File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospfd / ospf_snmp.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:29 2012 UTC (11 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_21, HEAD
quagga

    1: /* OSPFv2 SNMP support
    2:  * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
    3:  * Copyright (C) 2000 IP Infusion Inc.
    4:  *
    5:  * Written by Kunihiro Ishiguro <kunihiro@zebra.org>
    6:  *
    7:  * This file is part of GNU Zebra.
    8:  *
    9:  * GNU Zebra is free software; you can redistribute it and/or modify it
   10:  * under the terms of the GNU General Public License as published by the
   11:  * Free Software Foundation; either version 2, or (at your option) any
   12:  * later version.
   13:  *
   14:  * GNU Zebra is distributed in the hope that it will be useful, but
   15:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   17:  * General Public License for more details.
   18:  *
   19:  * You should have received a copy of the GNU General Public License
   20:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
   21:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   22:  * 02111-1307, USA.  
   23:  */
   24: 
   25: #include <zebra.h>
   26: 
   27: #ifdef HAVE_SNMP
   28: #ifdef HAVE_NETSNMP
   29: #include <net-snmp/net-snmp-config.h>
   30: #include <net-snmp/net-snmp-includes.h>
   31: #else
   32: #include <asn1.h>
   33: #include <snmp.h>
   34: #include <snmp_impl.h>
   35: #endif
   36: 
   37: #include "if.h"
   38: #include "log.h"
   39: #include "prefix.h"
   40: #include "table.h"
   41: #include "command.h"
   42: #include "memory.h"
   43: #include "smux.h"
   44: 
   45: #include "ospfd/ospfd.h"
   46: #include "ospfd/ospf_interface.h"
   47: #include "ospfd/ospf_asbr.h"
   48: #include "ospfd/ospf_lsa.h"
   49: #include "ospfd/ospf_lsdb.h"
   50: #include "ospfd/ospf_abr.h"
   51: #include "ospfd/ospf_neighbor.h"
   52: #include "ospfd/ospf_nsm.h"
   53: #include "ospfd/ospf_flood.h"
   54: #include "ospfd/ospf_ism.h"
   55: #include "ospfd/ospf_dump.h"
   56: #include "ospfd/ospf_snmp.h"
   57: 
   58: /* OSPF2-MIB. */
   59: #define OSPF2MIB 1,3,6,1,2,1,14
   60: 
   61: /* OSPF MIB General Group values. */
   62: #define OSPFROUTERID                     1
   63: #define OSPFADMINSTAT                    2
   64: #define OSPFVERSIONNUMBER                3
   65: #define OSPFAREABDRRTRSTATUS             4
   66: #define OSPFASBDRRTRSTATUS               5
   67: #define OSPFEXTERNLSACOUNT               6
   68: #define OSPFEXTERNLSACKSUMSUM            7
   69: #define OSPFTOSSUPPORT                   8
   70: #define OSPFORIGINATENEWLSAS             9
   71: #define OSPFRXNEWLSAS                    10
   72: #define OSPFEXTLSDBLIMIT                 11
   73: #define OSPFMULTICASTEXTENSIONS          12
   74: #define OSPFEXITOVERFLOWINTERVAL         13
   75: #define OSPFDEMANDEXTENSIONS             14
   76: 
   77: /* OSPF MIB ospfAreaTable. */
   78: #define OSPFAREAID                       1
   79: #define OSPFAUTHTYPE                     2
   80: #define OSPFIMPORTASEXTERN               3
   81: #define OSPFSPFRUNS                      4
   82: #define OSPFAREABDRRTRCOUNT              5
   83: #define OSPFASBDRRTRCOUNT                6
   84: #define OSPFAREALSACOUNT                 7
   85: #define OSPFAREALSACKSUMSUM              8
   86: #define OSPFAREASUMMARY                  9
   87: #define OSPFAREASTATUS                   10
   88: 
   89: /* OSPF MIB ospfStubAreaTable. */
   90: #define OSPFSTUBAREAID                   1
   91: #define OSPFSTUBTOS                      2
   92: #define OSPFSTUBMETRIC                   3
   93: #define OSPFSTUBSTATUS                   4
   94: #define OSPFSTUBMETRICTYPE               5
   95: 
   96: /* OSPF MIB ospfLsdbTable. */
   97: #define OSPFLSDBAREAID                   1
   98: #define OSPFLSDBTYPE                     2
   99: #define OSPFLSDBLSID                     3
  100: #define OSPFLSDBROUTERID                 4
  101: #define OSPFLSDBSEQUENCE                 5
  102: #define OSPFLSDBAGE                      6
  103: #define OSPFLSDBCHECKSUM                 7
  104: #define OSPFLSDBADVERTISEMENT            8
  105: 
  106: /* OSPF MIB ospfAreaRangeTable. */
  107: #define OSPFAREARANGEAREAID              1
  108: #define OSPFAREARANGENET                 2
  109: #define OSPFAREARANGEMASK                3
  110: #define OSPFAREARANGESTATUS              4
  111: #define OSPFAREARANGEEFFECT              5
  112: 
  113: /* OSPF MIB ospfHostTable. */
  114: #define OSPFHOSTIPADDRESS                1
  115: #define OSPFHOSTTOS                      2
  116: #define OSPFHOSTMETRIC                   3
  117: #define OSPFHOSTSTATUS                   4
  118: #define OSPFHOSTAREAID                   5
  119: 
  120: /* OSPF MIB ospfIfTable. */
  121: #define OSPFIFIPADDRESS                  1
  122: #define OSPFADDRESSLESSIF                2
  123: #define OSPFIFAREAID                     3
  124: #define OSPFIFTYPE                       4
  125: #define OSPFIFADMINSTAT                  5
  126: #define OSPFIFRTRPRIORITY                6
  127: #define OSPFIFTRANSITDELAY               7
  128: #define OSPFIFRETRANSINTERVAL            8
  129: #define OSPFIFHELLOINTERVAL              9
  130: #define OSPFIFRTRDEADINTERVAL            10
  131: #define OSPFIFPOLLINTERVAL               11
  132: #define OSPFIFSTATE                      12
  133: #define OSPFIFDESIGNATEDROUTER           13
  134: #define OSPFIFBACKUPDESIGNATEDROUTER     14
  135: #define OSPFIFEVENTS                     15
  136: #define OSPFIFAUTHKEY                    16
  137: #define OSPFIFSTATUS                     17
  138: #define OSPFIFMULTICASTFORWARDING        18
  139: #define OSPFIFDEMAND                     19
  140: #define OSPFIFAUTHTYPE                   20
  141: 
  142: /* OSPF MIB ospfIfMetricTable. */
  143: #define OSPFIFMETRICIPADDRESS            1
  144: #define OSPFIFMETRICADDRESSLESSIF        2
  145: #define OSPFIFMETRICTOS                  3
  146: #define OSPFIFMETRICVALUE                4
  147: #define OSPFIFMETRICSTATUS               5
  148: 
  149: /* OSPF MIB ospfVirtIfTable. */
  150: #define OSPFVIRTIFAREAID                 1
  151: #define OSPFVIRTIFNEIGHBOR               2
  152: #define OSPFVIRTIFTRANSITDELAY           3
  153: #define OSPFVIRTIFRETRANSINTERVAL        4
  154: #define OSPFVIRTIFHELLOINTERVAL          5
  155: #define OSPFVIRTIFRTRDEADINTERVAL        6
  156: #define OSPFVIRTIFSTATE                  7
  157: #define OSPFVIRTIFEVENTS                 8
  158: #define OSPFVIRTIFAUTHKEY                9
  159: #define OSPFVIRTIFSTATUS                 10
  160: #define OSPFVIRTIFAUTHTYPE               11
  161: 
  162: /* OSPF MIB ospfNbrTable. */
  163: #define OSPFNBRIPADDR                    1
  164: #define OSPFNBRADDRESSLESSINDEX          2
  165: #define OSPFNBRRTRID                     3
  166: #define OSPFNBROPTIONS                   4
  167: #define OSPFNBRPRIORITY                  5
  168: #define OSPFNBRSTATE                     6
  169: #define OSPFNBREVENTS                    7
  170: #define OSPFNBRLSRETRANSQLEN             8
  171: #define OSPFNBMANBRSTATUS                9
  172: #define OSPFNBMANBRPERMANENCE            10
  173: #define OSPFNBRHELLOSUPPRESSED           11
  174: 
  175: /* OSPF MIB ospfVirtNbrTable. */
  176: #define OSPFVIRTNBRAREA                  1
  177: #define OSPFVIRTNBRRTRID                 2
  178: #define OSPFVIRTNBRIPADDR                3
  179: #define OSPFVIRTNBROPTIONS               4
  180: #define OSPFVIRTNBRSTATE                 5
  181: #define OSPFVIRTNBREVENTS                6
  182: #define OSPFVIRTNBRLSRETRANSQLEN         7
  183: #define OSPFVIRTNBRHELLOSUPPRESSED       8
  184: 
  185: /* OSPF MIB ospfExtLsdbTable. */
  186: #define OSPFEXTLSDBTYPE                  1
  187: #define OSPFEXTLSDBLSID                  2
  188: #define OSPFEXTLSDBROUTERID              3
  189: #define OSPFEXTLSDBSEQUENCE              4
  190: #define OSPFEXTLSDBAGE                   5
  191: #define OSPFEXTLSDBCHECKSUM              6
  192: #define OSPFEXTLSDBADVERTISEMENT         7
  193: 
  194: /* OSPF MIB ospfAreaAggregateTable. */
  195: #define OSPFAREAAGGREGATEAREAID          1
  196: #define OSPFAREAAGGREGATELSDBTYPE        2
  197: #define OSPFAREAAGGREGATENET             3
  198: #define OSPFAREAAGGREGATEMASK            4
  199: #define OSPFAREAAGGREGATESTATUS          5
  200: #define OSPFAREAAGGREGATEEFFECT          6
  201: 
  202: /* SYNTAX Status from OSPF-MIB. */
  203: #define OSPF_STATUS_ENABLED  1
  204: #define OSPF_STATUS_DISABLED 2
  205: 
  206: /* SNMP value hack. */
  207: #define COUNTER     ASN_COUNTER
  208: #define INTEGER     ASN_INTEGER
  209: #define GAUGE       ASN_GAUGE
  210: #define TIMETICKS   ASN_TIMETICKS
  211: #define IPADDRESS   ASN_IPADDRESS
  212: #define STRING      ASN_OCTET_STR
  213: 
  214: /* Declare static local variables for convenience. */
  215: SNMP_LOCAL_VARIABLES
  216: 
  217: /* OSPF-MIB instances. */
  218: oid ospf_oid [] = { OSPF2MIB };
  219: 
  220: /* IP address 0.0.0.0. */
  221: static struct in_addr ospf_empty_addr = {0};
  222: 
  223: /* Hook functions. */
  224: static u_char *ospfGeneralGroup (struct variable *, oid *, size_t *,
  225: 				 int, size_t *, WriteMethod **);
  226: static u_char *ospfAreaEntry (struct variable *, oid *, size_t *, int,
  227: 			      size_t *, WriteMethod **);
  228: static u_char *ospfStubAreaEntry (struct variable *, oid *, size_t *,
  229: 				  int, size_t *, WriteMethod **);
  230: static u_char *ospfLsdbEntry (struct variable *, oid *, size_t *, int,
  231: 			      size_t *, WriteMethod **);
  232: static u_char *ospfAreaRangeEntry (struct variable *, oid *, size_t *, int,
  233: 				   size_t *, WriteMethod **);
  234: static u_char *ospfHostEntry (struct variable *, oid *, size_t *, int,
  235: 			      size_t *, WriteMethod **);
  236: static u_char *ospfIfEntry (struct variable *, oid *, size_t *, int,
  237: 			    size_t *, WriteMethod **);
  238: static u_char *ospfIfMetricEntry (struct variable *, oid *, size_t *, int,
  239: 				  size_t *, WriteMethod **);
  240: static u_char *ospfVirtIfEntry (struct variable *, oid *, size_t *, int,
  241: 				size_t *, WriteMethod **);
  242: static u_char *ospfNbrEntry (struct variable *, oid *, size_t *, int,
  243: 			     size_t *, WriteMethod **);
  244: static u_char *ospfVirtNbrEntry (struct variable *, oid *, size_t *, int,
  245: 				 size_t *, WriteMethod **);
  246: static u_char *ospfExtLsdbEntry (struct variable *, oid *, size_t *, int,
  247: 				 size_t *, WriteMethod **);
  248: static u_char *ospfAreaAggregateEntry (struct variable *, oid *, size_t *,
  249: 				       int, size_t *, WriteMethod **);
  250: 
  251: struct variable ospf_variables[] = 
  252: {
  253:   /* OSPF general variables */
  254:   {OSPFROUTERID,              IPADDRESS, RWRITE, ospfGeneralGroup,
  255:    2, {1, 1}},
  256:   {OSPFADMINSTAT,             INTEGER, RWRITE, ospfGeneralGroup,
  257:    2, {1, 2}},
  258:   {OSPFVERSIONNUMBER,         INTEGER, RONLY, ospfGeneralGroup,
  259:    2, {1, 3}},
  260:   {OSPFAREABDRRTRSTATUS,      INTEGER, RONLY, ospfGeneralGroup,
  261:    2, {1, 4}},
  262:   {OSPFASBDRRTRSTATUS,        INTEGER, RWRITE, ospfGeneralGroup,
  263:    2, {1, 5}},
  264:   {OSPFEXTERNLSACOUNT,        GAUGE, RONLY, ospfGeneralGroup,
  265:    2, {1, 6}},
  266:   {OSPFEXTERNLSACKSUMSUM,     INTEGER, RONLY, ospfGeneralGroup,
  267:    2, {1, 7}},
  268:   {OSPFTOSSUPPORT,            INTEGER, RWRITE, ospfGeneralGroup,
  269:    2, {1, 8}},
  270:   {OSPFORIGINATENEWLSAS,      COUNTER, RONLY, ospfGeneralGroup,
  271:    2, {1, 9}},
  272:   {OSPFRXNEWLSAS,             COUNTER, RONLY, ospfGeneralGroup,
  273:    2, {1, 10}},
  274:   {OSPFEXTLSDBLIMIT,          INTEGER, RWRITE, ospfGeneralGroup,
  275:    2, {1, 11}},
  276:   {OSPFMULTICASTEXTENSIONS,   INTEGER, RWRITE, ospfGeneralGroup,
  277:    2, {1, 12}},
  278:   {OSPFEXITOVERFLOWINTERVAL,  INTEGER, RWRITE, ospfGeneralGroup,
  279:    2, {1, 13}},
  280:   {OSPFDEMANDEXTENSIONS,      INTEGER, RWRITE, ospfGeneralGroup,
  281:    2, {1, 14}},
  282: 
  283:   /* OSPF area data structure. */
  284:   {OSPFAREAID,                IPADDRESS, RONLY, ospfAreaEntry,
  285:    3, {2, 1, 1}},
  286:   {OSPFAUTHTYPE,              INTEGER, RWRITE, ospfAreaEntry,
  287:    3, {2, 1, 2}},
  288:   {OSPFIMPORTASEXTERN,        INTEGER, RWRITE, ospfAreaEntry,
  289:    3, {2, 1, 3}},
  290:   {OSPFSPFRUNS,               COUNTER, RONLY, ospfAreaEntry,
  291:    3, {2, 1, 4}},
  292:   {OSPFAREABDRRTRCOUNT,       GAUGE, RONLY, ospfAreaEntry,
  293:    3, {2, 1, 5}},
  294:   {OSPFASBDRRTRCOUNT,         GAUGE, RONLY, ospfAreaEntry,
  295:    3, {2, 1, 6}},
  296:   {OSPFAREALSACOUNT,          GAUGE, RONLY, ospfAreaEntry,
  297:    3, {2, 1, 7}},
  298:   {OSPFAREALSACKSUMSUM,       INTEGER, RONLY, ospfAreaEntry,
  299:    3, {2, 1, 8}},
  300:   {OSPFAREASUMMARY,           INTEGER, RWRITE, ospfAreaEntry,
  301:    3, {2, 1, 9}},
  302:   {OSPFAREASTATUS,            INTEGER, RWRITE, ospfAreaEntry,
  303:    3, {2, 1, 10}},
  304: 
  305:   /* OSPF stub area information. */
  306:   {OSPFSTUBAREAID,            IPADDRESS, RONLY, ospfStubAreaEntry,
  307:    3, {3, 1, 1}},
  308:   {OSPFSTUBTOS,               INTEGER, RONLY, ospfStubAreaEntry,
  309:    3, {3, 1, 2}},
  310:   {OSPFSTUBMETRIC,            INTEGER, RWRITE, ospfStubAreaEntry,
  311:    3, {3, 1, 3}},
  312:   {OSPFSTUBSTATUS,            INTEGER, RWRITE, ospfStubAreaEntry,
  313:    3, {3, 1, 4}},
  314:   {OSPFSTUBMETRICTYPE,        INTEGER, RWRITE, ospfStubAreaEntry,
  315:    3, {3, 1, 5}},
  316: 
  317:   /* OSPF link state database. */
  318:   {OSPFLSDBAREAID,            IPADDRESS, RONLY, ospfLsdbEntry,
  319:    3, {4, 1, 1}},
  320:   {OSPFLSDBTYPE,              INTEGER, RONLY, ospfLsdbEntry,
  321:    3, {4, 1, 2}},
  322:   {OSPFLSDBLSID,              IPADDRESS, RONLY, ospfLsdbEntry,
  323:    3, {4, 1, 3}},
  324:   {OSPFLSDBROUTERID,          IPADDRESS, RONLY, ospfLsdbEntry,
  325:    3, {4, 1, 4}},
  326:   {OSPFLSDBSEQUENCE,          INTEGER, RONLY, ospfLsdbEntry,
  327:    3, {4, 1, 5}},
  328:   {OSPFLSDBAGE,               INTEGER, RONLY, ospfLsdbEntry,
  329:    3, {4, 1, 6}},
  330:   {OSPFLSDBCHECKSUM,          INTEGER, RONLY, ospfLsdbEntry,
  331:    3, {4, 1, 7}},
  332:   {OSPFLSDBADVERTISEMENT,     STRING, RONLY, ospfLsdbEntry,
  333:    3, {4, 1, 8}},
  334: 
  335:   /* Area range table. */
  336:   {OSPFAREARANGEAREAID,       IPADDRESS, RONLY, ospfAreaRangeEntry,
  337:    3, {5, 1, 1}},
  338:   {OSPFAREARANGENET,          IPADDRESS, RONLY, ospfAreaRangeEntry,
  339:    3, {5, 1, 2}},
  340:   {OSPFAREARANGEMASK,         IPADDRESS, RWRITE, ospfAreaRangeEntry,
  341:    3, {5, 1, 3}},
  342:   {OSPFAREARANGESTATUS,       INTEGER, RWRITE, ospfAreaRangeEntry,
  343:    3, {5, 1, 4}},
  344:   {OSPFAREARANGEEFFECT,       INTEGER, RWRITE, ospfAreaRangeEntry,
  345:    3, {5, 1, 5}},
  346: 
  347:   /* OSPF host table. */
  348:   {OSPFHOSTIPADDRESS,         IPADDRESS, RONLY, ospfHostEntry,
  349:    3, {6, 1, 1}},
  350:   {OSPFHOSTTOS,               INTEGER, RONLY, ospfHostEntry,
  351:    3, {6, 1, 2}},
  352:   {OSPFHOSTMETRIC,            INTEGER, RWRITE, ospfHostEntry,
  353:    3, {6, 1, 3}},
  354:   {OSPFHOSTSTATUS,            INTEGER, RWRITE, ospfHostEntry,
  355:    3, {6, 1, 4}},
  356:   {OSPFHOSTAREAID,            IPADDRESS, RONLY, ospfHostEntry,
  357:    3, {6, 1, 5}},
  358: 
  359:   /* OSPF interface table. */
  360:   {OSPFIFIPADDRESS,           IPADDRESS, RONLY, ospfIfEntry,
  361:    3, {7, 1, 1}},
  362:   {OSPFADDRESSLESSIF,         INTEGER, RONLY, ospfIfEntry,
  363:    3, {7, 1, 2}},
  364:   {OSPFIFAREAID,              IPADDRESS, RWRITE, ospfIfEntry,
  365:    3, {7, 1, 3}},
  366:   {OSPFIFTYPE,                INTEGER, RWRITE, ospfIfEntry,
  367:    3, {7, 1, 4}},
  368:   {OSPFIFADMINSTAT,           INTEGER, RWRITE, ospfIfEntry,
  369:    3, {7, 1, 5}},
  370:   {OSPFIFRTRPRIORITY,         INTEGER, RWRITE, ospfIfEntry,
  371:    3, {7, 1, 6}},
  372:   {OSPFIFTRANSITDELAY,        INTEGER, RWRITE, ospfIfEntry,
  373:    3, {7, 1, 7}},
  374:   {OSPFIFRETRANSINTERVAL,     INTEGER, RWRITE, ospfIfEntry,
  375:    3, {7, 1, 8}},
  376:   {OSPFIFHELLOINTERVAL,       INTEGER, RWRITE, ospfIfEntry,
  377:    3, {7, 1, 9}},
  378:   {OSPFIFRTRDEADINTERVAL,     INTEGER, RWRITE, ospfIfEntry,
  379:    3, {7, 1, 10}},
  380:   {OSPFIFPOLLINTERVAL,        INTEGER, RWRITE, ospfIfEntry,
  381:    3, {7, 1, 11}},
  382:   {OSPFIFSTATE,               INTEGER, RONLY, ospfIfEntry,
  383:    3, {7, 1, 12}},
  384:   {OSPFIFDESIGNATEDROUTER,    IPADDRESS, RONLY, ospfIfEntry,
  385:    3, {7, 1, 13}},
  386:   {OSPFIFBACKUPDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry,
  387:    3, {7, 1, 14}},
  388:   {OSPFIFEVENTS,              COUNTER, RONLY, ospfIfEntry,
  389:    3, {7, 1, 15}},
  390:   {OSPFIFAUTHKEY,             STRING,  RWRITE, ospfIfEntry,
  391:    3, {7, 1, 16}},
  392:   {OSPFIFSTATUS,              INTEGER, RWRITE, ospfIfEntry,
  393:    3, {7, 1, 17}},
  394:   {OSPFIFMULTICASTFORWARDING, INTEGER, RWRITE, ospfIfEntry,
  395:    3, {7, 1, 18}},
  396:   {OSPFIFDEMAND,              INTEGER, RWRITE, ospfIfEntry,
  397:    3, {7, 1, 19}},
  398:   {OSPFIFAUTHTYPE,            INTEGER, RWRITE, ospfIfEntry,
  399:    3, {7, 1, 20}},
  400: 
  401:   /* OSPF interface metric table. */
  402:   {OSPFIFMETRICIPADDRESS,     IPADDRESS, RONLY, ospfIfMetricEntry,
  403:    3, {8, 1, 1}},
  404:   {OSPFIFMETRICADDRESSLESSIF, INTEGER, RONLY, ospfIfMetricEntry,
  405:    3, {8, 1, 2}},
  406:   {OSPFIFMETRICTOS,           INTEGER, RONLY, ospfIfMetricEntry,
  407:    3, {8, 1, 3}},
  408:   {OSPFIFMETRICVALUE,         INTEGER, RWRITE, ospfIfMetricEntry,
  409:    3, {8, 1, 4}},
  410:   {OSPFIFMETRICSTATUS,        INTEGER, RWRITE, ospfIfMetricEntry,
  411:    3, {8, 1, 5}},
  412: 
  413:   /* OSPF virtual interface table. */
  414:   {OSPFVIRTIFAREAID,          IPADDRESS, RONLY, ospfVirtIfEntry,
  415:    3, {9, 1, 1}},
  416:   {OSPFVIRTIFNEIGHBOR,        IPADDRESS, RONLY, ospfVirtIfEntry,
  417:    3, {9, 1, 2}},
  418:   {OSPFVIRTIFTRANSITDELAY,    INTEGER, RWRITE, ospfVirtIfEntry,
  419:    3, {9, 1, 3}},
  420:   {OSPFVIRTIFRETRANSINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
  421:    3, {9, 1, 4}},
  422:   {OSPFVIRTIFHELLOINTERVAL,   INTEGER, RWRITE, ospfVirtIfEntry,
  423:    3, {9, 1, 5}},
  424:   {OSPFVIRTIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
  425:    3, {9, 1, 6}},
  426:   {OSPFVIRTIFSTATE,           INTEGER, RONLY, ospfVirtIfEntry,
  427:    3, {9, 1, 7}},
  428:   {OSPFVIRTIFEVENTS,          COUNTER, RONLY, ospfVirtIfEntry,
  429:    3, {9, 1, 8}},
  430:   {OSPFVIRTIFAUTHKEY,         STRING,  RWRITE, ospfVirtIfEntry,
  431:    3, {9, 1, 9}},
  432:   {OSPFVIRTIFSTATUS,          INTEGER, RWRITE, ospfVirtIfEntry,
  433:    3, {9, 1, 10}},
  434:   {OSPFVIRTIFAUTHTYPE,        INTEGER, RWRITE, ospfVirtIfEntry,
  435:    3, {9, 1, 11}},
  436: 
  437:   /* OSPF neighbor table. */
  438:   {OSPFNBRIPADDR,             IPADDRESS, RONLY, ospfNbrEntry,
  439:    3, {10, 1, 1}},
  440:   {OSPFNBRADDRESSLESSINDEX,   INTEGER, RONLY, ospfNbrEntry,
  441:    3, {10, 1, 2}},
  442:   {OSPFNBRRTRID,              IPADDRESS, RONLY, ospfNbrEntry,
  443:    3, {10, 1, 3}},
  444:   {OSPFNBROPTIONS,            INTEGER, RONLY, ospfNbrEntry,
  445:    3, {10, 1, 4}},
  446:   {OSPFNBRPRIORITY,           INTEGER, RWRITE, ospfNbrEntry,
  447:    3, {10, 1, 5}},
  448:   {OSPFNBRSTATE,              INTEGER, RONLY, ospfNbrEntry,
  449:    3, {10, 1, 6}},
  450:   {OSPFNBREVENTS,             COUNTER, RONLY, ospfNbrEntry,
  451:    3, {10, 1, 7}},
  452:   {OSPFNBRLSRETRANSQLEN,      GAUGE, RONLY, ospfNbrEntry,
  453:    3, {10, 1, 8}},
  454:   {OSPFNBMANBRSTATUS,         INTEGER, RWRITE, ospfNbrEntry,
  455:    3, {10, 1, 9}},
  456:   {OSPFNBMANBRPERMANENCE,     INTEGER, RONLY, ospfNbrEntry,
  457:    3, {10, 1, 10}},
  458:   {OSPFNBRHELLOSUPPRESSED,    INTEGER, RONLY, ospfNbrEntry,
  459:    3, {10, 1, 11}},
  460: 
  461:   /* OSPF virtual neighbor table. */
  462:   {OSPFVIRTNBRAREA,           IPADDRESS, RONLY, ospfVirtNbrEntry,
  463:    3, {11, 1, 1}},
  464:   {OSPFVIRTNBRRTRID,          IPADDRESS, RONLY, ospfVirtNbrEntry,
  465:    3, {11, 1, 2}},
  466:   {OSPFVIRTNBRIPADDR,         IPADDRESS, RONLY, ospfVirtNbrEntry,
  467:    3, {11, 1, 3}},
  468:   {OSPFVIRTNBROPTIONS,        INTEGER, RONLY, ospfVirtNbrEntry,
  469:    3, {11, 1, 4}},
  470:   {OSPFVIRTNBRSTATE,          INTEGER, RONLY, ospfVirtNbrEntry,
  471:    3, {11, 1, 5}},
  472:   {OSPFVIRTNBREVENTS,         COUNTER, RONLY, ospfVirtNbrEntry,
  473:    3, {11, 1, 6}},
  474:   {OSPFVIRTNBRLSRETRANSQLEN,  INTEGER, RONLY, ospfVirtNbrEntry,
  475:    3, {11, 1, 7}},
  476:   {OSPFVIRTNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfVirtNbrEntry,
  477:    3, {11, 1, 8}},
  478: 
  479:   /* OSPF link state database, external. */
  480:   {OSPFEXTLSDBTYPE,           INTEGER, RONLY, ospfExtLsdbEntry,
  481:    3, {12, 1, 1}},
  482:   {OSPFEXTLSDBLSID,           IPADDRESS, RONLY, ospfExtLsdbEntry,
  483:    3, {12, 1, 2}},
  484:   {OSPFEXTLSDBROUTERID,       IPADDRESS, RONLY, ospfExtLsdbEntry,
  485:    3, {12, 1, 3}},
  486:   {OSPFEXTLSDBSEQUENCE,       INTEGER, RONLY, ospfExtLsdbEntry,
  487:    3, {12, 1, 4}},
  488:   {OSPFEXTLSDBAGE,            INTEGER, RONLY, ospfExtLsdbEntry,
  489:    3, {12, 1, 5}},
  490:   {OSPFEXTLSDBCHECKSUM,       INTEGER, RONLY, ospfExtLsdbEntry,
  491:    3, {12, 1, 6}},
  492:   {OSPFEXTLSDBADVERTISEMENT,  STRING,  RONLY, ospfExtLsdbEntry,
  493:    3, {12, 1, 7}},
  494: 
  495:   /* OSPF area aggregate table. */
  496:   {OSPFAREAAGGREGATEAREAID,   IPADDRESS, RONLY, ospfAreaAggregateEntry, 
  497:    3, {14, 1, 1}},
  498:   {OSPFAREAAGGREGATELSDBTYPE, INTEGER, RONLY, ospfAreaAggregateEntry, 
  499:    3, {14, 1, 2}},
  500:   {OSPFAREAAGGREGATENET,      IPADDRESS, RONLY, ospfAreaAggregateEntry, 
  501:    3, {14, 1, 3}},
  502:   {OSPFAREAAGGREGATEMASK,     IPADDRESS, RONLY, ospfAreaAggregateEntry, 
  503:    3, {14, 1, 4}},
  504:   {OSPFAREAAGGREGATESTATUS,   INTEGER, RWRITE, ospfAreaAggregateEntry,
  505:    3, {14, 1, 5}},
  506:   {OSPFAREAAGGREGATEEFFECT,   INTEGER, RWRITE, ospfAreaAggregateEntry,
  507:    3, {14, 1, 6}}
  508: };
  509: 
  510: /* The administrative status of OSPF.  When OSPF is enbled on at least
  511:    one interface return 1. */
  512: static int
  513: ospf_admin_stat (struct ospf *ospf)
  514: {
  515:   struct listnode *node;
  516:   struct ospf_interface *oi;
  517: 
  518:   if (ospf == NULL)
  519:     return 0;
  520: 
  521:   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
  522:     if (oi && oi->address)
  523:       return 1;
  524: 
  525:   return 0;
  526: }
  527: 
  528: static u_char *
  529: ospfGeneralGroup (struct variable *v, oid *name, size_t *length,
  530: 		  int exact, size_t *var_len, WriteMethod **write_method)
  531: {
  532:   struct ospf *ospf;
  533: 
  534:   ospf = ospf_lookup ();
  535: 
  536:   /* Check whether the instance identifier is valid */
  537:   if (smux_header_generic (v, name, length, exact, var_len, write_method)
  538:       == MATCH_FAILED)
  539:     return NULL;
  540: 
  541:   /* Return the current value of the variable */
  542:   switch (v->magic) 
  543:     {
  544:     case OSPFROUTERID:		/* 1 */
  545:       /* Router-ID of this OSPF instance. */
  546:       if (ospf)
  547: 	return SNMP_IPADDRESS (ospf->router_id);
  548:       else
  549: 	return SNMP_IPADDRESS (ospf_empty_addr);
  550:       break;
  551:     case OSPFADMINSTAT:		/* 2 */
  552:       /* The administrative status of OSPF in the router. */
  553:       if (ospf_admin_stat (ospf))
  554: 	return SNMP_INTEGER (OSPF_STATUS_ENABLED);
  555:       else
  556: 	return SNMP_INTEGER (OSPF_STATUS_DISABLED);
  557:       break;
  558:     case OSPFVERSIONNUMBER:	/* 3 */
  559:       /* OSPF version 2. */
  560:       return SNMP_INTEGER (OSPF_VERSION);
  561:       break;
  562:     case OSPFAREABDRRTRSTATUS:	/* 4 */
  563:       /* Area Border router status. */
  564:       if (ospf && CHECK_FLAG (ospf->flags, OSPF_FLAG_ABR))
  565: 	return SNMP_INTEGER (SNMP_TRUE);
  566:       else
  567: 	return SNMP_INTEGER (SNMP_FALSE);
  568:       break;
  569:     case OSPFASBDRRTRSTATUS:	/* 5 */
  570:       /* AS Border router status. */
  571:       if (ospf && CHECK_FLAG (ospf->flags, OSPF_FLAG_ASBR))
  572: 	return SNMP_INTEGER (SNMP_TRUE);
  573:       else
  574: 	return SNMP_INTEGER (SNMP_FALSE);
  575:       break;
  576:     case OSPFEXTERNLSACOUNT:	/* 6 */
  577:       /* External LSA counts. */
  578:       if (ospf)
  579: 	return SNMP_INTEGER (ospf_lsdb_count_all (ospf->lsdb));
  580:       else
  581: 	return SNMP_INTEGER (0);
  582:       break;
  583:     case OSPFEXTERNLSACKSUMSUM:	/* 7 */
  584:       /* External LSA checksum. */
  585:       return SNMP_INTEGER (0);
  586:       break;
  587:     case OSPFTOSSUPPORT:	/* 8 */
  588:       /* TOS is not supported. */
  589:       return SNMP_INTEGER (SNMP_FALSE);
  590:       break;
  591:     case OSPFORIGINATENEWLSAS:	/* 9 */
  592:       /* The number of new link-state advertisements. */
  593:       if (ospf)
  594: 	return SNMP_INTEGER (ospf->lsa_originate_count);
  595:       else
  596: 	return SNMP_INTEGER (0);
  597:       break;
  598:     case OSPFRXNEWLSAS:		/* 10 */
  599:       /* The number of link-state advertisements received determined
  600:          to be new instantiations. */
  601:       if (ospf)
  602: 	return SNMP_INTEGER (ospf->rx_lsa_count);
  603:       else
  604: 	return SNMP_INTEGER (0);
  605:       break;
  606:     case OSPFEXTLSDBLIMIT:	/* 11 */
  607:       /* There is no limit for the number of non-default
  608:          AS-external-LSAs. */
  609:       return SNMP_INTEGER (-1);
  610:       break;
  611:     case OSPFMULTICASTEXTENSIONS: /* 12 */
  612:       /* Multicast Extensions to OSPF is not supported. */
  613:       return SNMP_INTEGER (0);
  614:       break;
  615:     case OSPFEXITOVERFLOWINTERVAL: /* 13 */
  616:       /* Overflow is not supported. */
  617:       return SNMP_INTEGER (0);
  618:       break;
  619:     case OSPFDEMANDEXTENSIONS:	/* 14 */
  620:       /* Demand routing is not supported. */
  621:       return SNMP_INTEGER (SNMP_FALSE);
  622:       break;
  623:     default:
  624:       return NULL;
  625:     }
  626:   return NULL;
  627: }
  628: 
  629: static struct ospf_area *
  630: ospf_area_lookup_next (struct ospf *ospf, struct in_addr *area_id, int first)
  631: {
  632:   struct ospf_area *area;
  633:   struct listnode *node;
  634: 
  635:   if (ospf == NULL)
  636:     return NULL;
  637: 
  638:   if (first)
  639:     {
  640:       node = listhead (ospf->areas);
  641:       if (node)
  642: 	{
  643: 	  area = listgetdata (node);
  644: 	  *area_id = area->area_id;
  645: 	  return area;
  646: 	}
  647:       return NULL;
  648:     }
  649:   for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
  650:     {
  651:       if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
  652: 	{
  653: 	  *area_id = area->area_id;
  654: 	  return area;
  655: 	}
  656:     }
  657:   return NULL;
  658: }
  659: 
  660: static struct ospf_area *
  661: ospfAreaLookup (struct variable *v, oid name[], size_t *length,
  662: 		struct in_addr *addr, int exact)
  663: {
  664:   struct ospf *ospf;
  665:   struct ospf_area *area;
  666:   int len;
  667: 
  668:   ospf = ospf_lookup ();
  669:   if (ospf == NULL)
  670:     return NULL;
  671: 
  672:   if (exact)
  673:     {
  674:       /* Length is insufficient to lookup OSPF area. */
  675:       if (*length - v->namelen != sizeof (struct in_addr))
  676: 	return NULL;
  677: 
  678:       oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
  679: 
  680:       area = ospf_area_lookup_by_area_id (ospf, *addr);
  681: 
  682:       return area;
  683:     }
  684:   else
  685:     {
  686:       len = *length - v->namelen;
  687:       if (len > 4)
  688: 	len = 4;
  689:       
  690:       oid2in_addr (name + v->namelen, len, addr);
  691: 
  692:       area = ospf_area_lookup_next (ospf, addr, len == 0 ? 1 : 0);
  693: 
  694:       if (area == NULL)
  695: 	return NULL;
  696: 
  697:       oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
  698:       *length = sizeof (struct in_addr) + v->namelen;
  699: 
  700:       return area;
  701:     }
  702:   return NULL;
  703: }
  704: 
  705: static u_char *
  706: ospfAreaEntry (struct variable *v, oid *name, size_t *length, int exact,
  707: 	       size_t *var_len, WriteMethod **write_method)
  708: {
  709:   struct ospf_area *area;
  710:   struct in_addr addr;
  711: 
  712:   memset (&addr, 0, sizeof (struct in_addr));
  713: 
  714:   area = ospfAreaLookup (v, name, length, &addr, exact);
  715:   if (! area)
  716:     return NULL;
  717:   
  718:   /* Return the current value of the variable */
  719:   switch (v->magic) 
  720:     {
  721:     case OSPFAREAID:		/* 1 */
  722:       return SNMP_IPADDRESS (area->area_id);
  723:       break;
  724:     case OSPFAUTHTYPE:		/* 2 */
  725:       return SNMP_INTEGER (area->auth_type);
  726:       break;
  727:     case OSPFIMPORTASEXTERN:	/* 3 */
  728:       return SNMP_INTEGER (area->external_routing + 1);
  729:       break;
  730:     case OSPFSPFRUNS:		/* 4 */
  731:       return SNMP_INTEGER (area->spf_calculation);
  732:       break;
  733:     case OSPFAREABDRRTRCOUNT:	/* 5 */
  734:       return SNMP_INTEGER (area->abr_count);
  735:       break;
  736:     case OSPFASBDRRTRCOUNT:	/* 6 */
  737:       return SNMP_INTEGER (area->asbr_count);
  738:       break;
  739:     case OSPFAREALSACOUNT:	/* 7 */
  740:       return SNMP_INTEGER (area->lsdb->total);
  741:       break;
  742:     case OSPFAREALSACKSUMSUM:	/* 8 */
  743:       return SNMP_INTEGER (0);
  744:       break;
  745:     case OSPFAREASUMMARY:	/* 9 */
  746: #define OSPF_noAreaSummary   1
  747: #define OSPF_sendAreaSummary 2
  748:       if (area->no_summary)
  749: 	return SNMP_INTEGER (OSPF_noAreaSummary);
  750:       else
  751: 	return SNMP_INTEGER (OSPF_sendAreaSummary);
  752:       break;
  753:     case OSPFAREASTATUS:	/* 10 */
  754:       return SNMP_INTEGER (SNMP_VALID);
  755:       break;
  756:     default:
  757:       return NULL;
  758:       break;
  759:     }
  760:   return NULL;
  761: }
  762: 
  763: static struct ospf_area *
  764: ospf_stub_area_lookup_next (struct in_addr *area_id, int first)
  765: {
  766:   struct ospf_area *area;
  767:   struct listnode *node;
  768:   struct ospf *ospf;
  769: 
  770:   ospf = ospf_lookup ();
  771:   if (ospf == NULL)
  772:     return NULL;
  773: 
  774:   for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
  775:     {
  776:       if (area->external_routing == OSPF_AREA_STUB)
  777: 	{
  778: 	  if (first)
  779: 	    {
  780: 	      *area_id = area->area_id;
  781: 	      return area;
  782: 	    }
  783: 	  else if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
  784: 	    {
  785: 	      *area_id = area->area_id;
  786: 	      return area;
  787: 	    }
  788: 	}
  789:     }
  790:   return NULL;
  791: }
  792: 
  793: static struct ospf_area *
  794: ospfStubAreaLookup (struct variable *v, oid name[], size_t *length,
  795: 		    struct in_addr *addr, int exact)
  796: {
  797:   struct ospf *ospf;
  798:   struct ospf_area *area;
  799:   int len;
  800: 
  801:   ospf = ospf_lookup ();
  802:   if (ospf == NULL)
  803:     return NULL;
  804: 
  805:   /* Exact lookup. */
  806:   if (exact)
  807:     {
  808:       /* ospfStubAreaID + ospfStubTOS. */
  809:       if (*length != v->namelen + sizeof (struct in_addr) + 1)
  810: 	return NULL;
  811: 
  812:       /* Check ospfStubTOS is zero. */
  813:       if (name[*length - 1] != 0)
  814: 	return NULL;
  815: 
  816:       oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
  817: 
  818:       area = ospf_area_lookup_by_area_id (ospf, *addr);
  819: 
  820:       if (area->external_routing == OSPF_AREA_STUB)
  821: 	return area;
  822:       else
  823: 	return NULL;
  824:     }
  825:   else
  826:     {
  827:       len = *length - v->namelen;
  828:       if (len > 4)
  829: 	len = 4;
  830:       
  831:       oid2in_addr (name + v->namelen, len, addr);
  832: 
  833:       area = ospf_stub_area_lookup_next (addr, len == 0 ? 1 : 0);
  834: 
  835:       if (area == NULL)
  836: 	return NULL;
  837: 
  838:       oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
  839:       /* Set TOS 0. */
  840:       name[v->namelen + sizeof (struct in_addr)] = 0;
  841:       *length = v->namelen + sizeof (struct in_addr) + 1;
  842: 
  843:       return area;
  844:     }
  845:   return NULL;
  846: }
  847: 
  848: static u_char *
  849: ospfStubAreaEntry (struct variable *v, oid *name, size_t *length,
  850: 		   int exact, size_t *var_len, WriteMethod **write_method)
  851: {
  852:   struct ospf_area *area;
  853:   struct in_addr addr;
  854: 
  855:   memset (&addr, 0, sizeof (struct in_addr));
  856: 
  857:   area = ospfStubAreaLookup (v, name, length, &addr, exact);
  858:   if (! area)
  859:     return NULL;
  860: 
  861:   /* Return the current value of the variable */
  862:   switch (v->magic) 
  863:     {
  864:     case OSPFSTUBAREAID:	/* 1 */
  865:       /* OSPF stub area id. */
  866:       return SNMP_IPADDRESS (area->area_id);
  867:       break;
  868:     case OSPFSTUBTOS:		/* 2 */
  869:       /* TOS value is not supported. */
  870:       return SNMP_INTEGER (0);
  871:       break;
  872:     case OSPFSTUBMETRIC:	/* 3 */
  873:       /* Default cost to stub area. */
  874:       return SNMP_INTEGER (area->default_cost);
  875:       break;
  876:     case OSPFSTUBSTATUS:	/* 4 */
  877:       /* Status of the stub area. */
  878:       return SNMP_INTEGER (SNMP_VALID);
  879:       break;
  880:     case OSPFSTUBMETRICTYPE:	/* 5 */
  881:       /* OSPF Metric type. */
  882: #define OSPF_ospfMetric     1
  883: #define OSPF_comparableCost 2
  884: #define OSPF_nonComparable  3
  885:       return SNMP_INTEGER (OSPF_ospfMetric);
  886:       break;
  887:     default:
  888:       return NULL;
  889:       break;
  890:     }
  891:   return NULL;
  892: }
  893: 
  894: static struct ospf_lsa *
  895: lsdb_lookup_next (struct ospf_area *area, u_char *type, int type_next,
  896: 		  struct in_addr *ls_id, int ls_id_next,
  897: 		  struct in_addr *router_id, int router_id_next)
  898: {
  899:   struct ospf_lsa *lsa;
  900:   int i;
  901: 
  902:   if (type_next)
  903:     i = OSPF_MIN_LSA;
  904:   else
  905:     i = *type;
  906: 
  907:   /* Sanity check, if LSA type unknwon
  908:      merley skip any LSA */
  909:   if ((i < OSPF_MIN_LSA) || (i >= OSPF_MAX_LSA))
  910:     {
  911:       zlog_debug("Strange request with LSA type %d\n", i);
  912:       return NULL;
  913:     }
  914: 
  915:   for (; i < OSPF_MAX_LSA; i++)
  916:     {
  917:       *type = i;
  918: 
  919:       lsa = ospf_lsdb_lookup_by_id_next (area->lsdb, *type, *ls_id, *router_id,
  920: 					ls_id_next);
  921:       if (lsa)
  922: 	return lsa;
  923: 
  924:       ls_id_next = 1;
  925:     }
  926:   return NULL;
  927: }
  928: 
  929: static struct ospf_lsa *
  930: ospfLsdbLookup (struct variable *v, oid *name, size_t *length,
  931: 		struct in_addr *area_id, u_char *type,
  932: 		struct in_addr *ls_id, struct in_addr *router_id, int exact)
  933: {
  934:   struct ospf *ospf;
  935:   struct ospf_area *area;
  936:   struct ospf_lsa *lsa;
  937:   int len;
  938:   int type_next;
  939:   int ls_id_next;
  940:   int router_id_next;
  941:   oid *offset;
  942:   int offsetlen;
  943: 
  944:   ospf = ospf_lookup ();
  945: 
  946: #define OSPF_LSDB_ENTRY_OFFSET \
  947:           (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
  948: 
  949:   if (exact)
  950:     {
  951:       /* Area ID + Type + LS ID + Router ID. */
  952:       if (*length - v->namelen != OSPF_LSDB_ENTRY_OFFSET)
  953: 	return NULL;
  954:       
  955:       /* Set OID offset for Area ID. */
  956:       offset = name + v->namelen;
  957: 
  958:       /* Lookup area first. */
  959:       oid2in_addr (offset, IN_ADDR_SIZE, area_id);
  960:       area = ospf_area_lookup_by_area_id (ospf, *area_id);
  961:       if (! area)
  962: 	return NULL;
  963:       offset += IN_ADDR_SIZE;
  964: 
  965:       /* Type. */
  966:       *type = *offset;
  967:       offset++;
  968: 
  969:       /* LS ID. */
  970:       oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
  971:       offset += IN_ADDR_SIZE;
  972: 
  973:       /* Router ID. */
  974:       oid2in_addr (offset, IN_ADDR_SIZE, router_id);
  975: 
  976:       /* Lookup LSDB. */
  977:       return ospf_lsdb_lookup_by_id (area->lsdb, *type, *ls_id, *router_id);
  978:     }
  979:   else
  980:     {
  981:       /* Get variable length. */
  982:       offset = name + v->namelen;
  983:       offsetlen = *length - v->namelen;
  984:       len = offsetlen;
  985: 
  986:       if (len > IN_ADDR_SIZE)
  987: 	len = IN_ADDR_SIZE;
  988: 
  989:       oid2in_addr (offset, len, area_id);
  990: 
  991:       /* First we search area. */
  992:       if (len == IN_ADDR_SIZE)
  993: 	area = ospf_area_lookup_by_area_id (ospf, *area_id);
  994:       else
  995: 	area = ospf_area_lookup_next (ospf, area_id, 1);
  996: 
  997:       if (area == NULL)
  998: 	return NULL;
  999: 
 1000:       do 
 1001: 	{
 1002: 	  /* Next we lookup type. */
 1003: 	  offset += len;
 1004: 	  offsetlen -= len;
 1005: 	  len = offsetlen;
 1006: 
 1007: 	  if (len <= 0)
 1008: 	    type_next = 1;
 1009: 	  else
 1010: 	    {
 1011: 	      len = 1;
 1012: 	      type_next = 0;
 1013: 	      *type = *offset;
 1014: 	    }
 1015: 	
 1016: 	  /* LS ID. */
 1017: 	  offset++;
 1018: 	  offsetlen--;
 1019: 	  len = offsetlen;
 1020: 
 1021: 	  if (len <= 0)
 1022: 	    ls_id_next = 1;
 1023: 	  else
 1024: 	    {
 1025: 	      ls_id_next = 0;
 1026: 	      if (len > IN_ADDR_SIZE)
 1027: 		len = IN_ADDR_SIZE;
 1028: 
 1029: 	      oid2in_addr (offset, len, ls_id);
 1030: 	    }
 1031: 
 1032: 	  /* Router ID. */
 1033: 	  offset += IN_ADDR_SIZE;
 1034: 	  offsetlen -= IN_ADDR_SIZE;
 1035: 	  len = offsetlen;
 1036: 
 1037: 	  if (len <= 0)
 1038: 	    router_id_next = 1;
 1039: 	  else
 1040: 	    {
 1041: 	      router_id_next = 0;
 1042: 	      if (len > IN_ADDR_SIZE)
 1043: 		len = IN_ADDR_SIZE;
 1044: 
 1045: 	      oid2in_addr (offset, len, router_id);
 1046: 	    }
 1047: 
 1048: 	  lsa = lsdb_lookup_next (area, type, type_next, ls_id, ls_id_next,
 1049: 				  router_id, router_id_next);
 1050: 
 1051: 	  if (lsa)
 1052: 	    {
 1053: 	      /* Fill in length. */
 1054: 	      *length = v->namelen + OSPF_LSDB_ENTRY_OFFSET;
 1055: 
 1056: 	      /* Fill in value. */
 1057: 	      offset = name + v->namelen;
 1058: 	      oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
 1059: 	      offset += IN_ADDR_SIZE;
 1060: 	      *offset = lsa->data->type;
 1061: 	      offset++;
 1062: 	      oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
 1063: 	      offset += IN_ADDR_SIZE;
 1064: 	      oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
 1065: 	    
 1066: 	      return lsa;
 1067: 	    }
 1068: 	}
 1069:       while ((area = ospf_area_lookup_next (ospf, area_id, 0)) != NULL);
 1070:     }
 1071:   return NULL;
 1072: }
 1073: 
 1074: static u_char *
 1075: ospfLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
 1076: 	       size_t *var_len, WriteMethod **write_method)
 1077: {
 1078:   struct ospf_lsa *lsa;
 1079:   struct lsa_header *lsah;
 1080:   struct in_addr area_id;
 1081:   u_char type;
 1082:   struct in_addr ls_id;
 1083:   struct in_addr router_id;
 1084:   struct ospf *ospf;
 1085: 
 1086:   /* INDEX { ospfLsdbAreaId, ospfLsdbType,
 1087:      ospfLsdbLsid, ospfLsdbRouterId } */
 1088: 
 1089:   memset (&area_id, 0, sizeof (struct in_addr));
 1090:   type = 0;
 1091:   memset (&ls_id, 0, sizeof (struct in_addr));
 1092:   memset (&router_id, 0, sizeof (struct in_addr));
 1093: 
 1094:   /* Check OSPF instance. */
 1095:   ospf = ospf_lookup ();
 1096:   if (ospf == NULL)
 1097:     return NULL;
 1098: 
 1099:   lsa = ospfLsdbLookup (v, name, length, &area_id, &type, &ls_id, &router_id,
 1100: 			exact);
 1101:   if (! lsa)
 1102:     return NULL;
 1103: 
 1104:   lsah = lsa->data;
 1105: 
 1106:   /* Return the current value of the variable */
 1107:   switch (v->magic) 
 1108:     {
 1109:     case OSPFLSDBAREAID:	/* 1 */
 1110:       return SNMP_IPADDRESS (lsa->area->area_id);
 1111:       break;
 1112:     case OSPFLSDBTYPE:		/* 2 */
 1113:       return SNMP_INTEGER (lsah->type);
 1114:       break;
 1115:     case OSPFLSDBLSID:		/* 3 */
 1116:       return SNMP_IPADDRESS (lsah->id);
 1117:       break;
 1118:     case OSPFLSDBROUTERID:	/* 4 */
 1119:       return SNMP_IPADDRESS (lsah->adv_router);
 1120:       break;
 1121:     case OSPFLSDBSEQUENCE:	/* 5 */
 1122:       return SNMP_INTEGER (lsah->ls_seqnum);
 1123:       break;
 1124:     case OSPFLSDBAGE:		/* 6 */
 1125:       return SNMP_INTEGER (lsah->ls_age);
 1126:       break;
 1127:     case OSPFLSDBCHECKSUM:	/* 7 */
 1128:       return SNMP_INTEGER (lsah->checksum);
 1129:       break;
 1130:     case OSPFLSDBADVERTISEMENT:	/* 8 */
 1131:       *var_len = ntohs (lsah->length);
 1132:       return (u_char *) lsah;
 1133:       break;
 1134:     default:
 1135:       return NULL;
 1136:       break;
 1137:     }
 1138:   return NULL;
 1139: }
 1140: 
 1141: static struct ospf_area_range *
 1142: ospfAreaRangeLookup (struct variable *v, oid *name, size_t *length,
 1143: 		     struct in_addr *area_id, struct in_addr *range_net,
 1144: 		     int exact)
 1145: {
 1146:   oid *offset;
 1147:   int offsetlen;
 1148:   unsigned int len;
 1149:   struct ospf *ospf;
 1150:   struct ospf_area *area;
 1151:   struct ospf_area_range *range;
 1152:   struct prefix_ipv4 p;
 1153:   p.family = AF_INET;
 1154:   p.prefixlen = IPV4_MAX_BITLEN;
 1155: 
 1156:   ospf = ospf_lookup ();
 1157: 
 1158:   if (exact) 
 1159:     {
 1160:       /* Area ID + Range Network. */
 1161:       if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length)
 1162: 	return NULL;
 1163: 
 1164:       /* Set OID offset for Area ID. */
 1165:       offset = name + v->namelen;
 1166: 
 1167:       /* Lookup area first. */
 1168:       oid2in_addr (offset, IN_ADDR_SIZE, area_id);
 1169: 
 1170:       area = ospf_area_lookup_by_area_id (ospf, *area_id);
 1171:       if (! area)
 1172: 	return NULL;
 1173: 
 1174:       offset += IN_ADDR_SIZE;
 1175: 
 1176:       /* Lookup area range. */
 1177:       oid2in_addr (offset, IN_ADDR_SIZE, range_net);
 1178:       p.prefix = *range_net;
 1179: 
 1180:       return ospf_area_range_lookup (area, &p);
 1181:     }
 1182:   else
 1183:     {
 1184:       /* Set OID offset for Area ID. */
 1185:       offset = name + v->namelen;
 1186:       offsetlen = *length - v->namelen;
 1187: 
 1188:       len = offsetlen;
 1189:       if (len > IN_ADDR_SIZE)
 1190: 	len = IN_ADDR_SIZE;
 1191: 
 1192:       oid2in_addr (offset, len, area_id);
 1193: 
 1194:       /* First we search area. */
 1195:       if (len == IN_ADDR_SIZE)
 1196: 	area = ospf_area_lookup_by_area_id (ospf,*area_id);
 1197:       else
 1198: 	area = ospf_area_lookup_next (ospf, area_id, len == 0 ? 1 : 0);
 1199: 
 1200:       if (area == NULL)
 1201: 	return NULL;
 1202: 
 1203:       do 
 1204: 	{
 1205: 	  offset += IN_ADDR_SIZE;
 1206: 	  offsetlen -= IN_ADDR_SIZE;
 1207: 	  len = offsetlen;
 1208: 
 1209: 	  if (len < 0)
 1210: 	    len = 0;
 1211: 	  if (len > IN_ADDR_SIZE)
 1212: 	    len = IN_ADDR_SIZE;
 1213: 
 1214: 	  oid2in_addr (offset, len, range_net);
 1215: 
 1216: 	  range = ospf_area_range_lookup_next (area, range_net,
 1217: 					       len == 0 ? 1 : 0);
 1218: 
 1219: 	  if (range)
 1220: 	    {
 1221: 	      /* Fill in length. */
 1222: 	      *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
 1223: 
 1224: 	      /* Fill in value. */
 1225: 	      offset = name + v->namelen;
 1226: 	      oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
 1227: 	      offset += IN_ADDR_SIZE;
 1228: 	      oid_copy_addr (offset, range_net, IN_ADDR_SIZE);
 1229: 
 1230: 	      return range;
 1231: 	    }
 1232: 	}
 1233:       while ((area = ospf_area_lookup_next (ospf, area_id, 0)) != NULL);
 1234:     }
 1235:   return NULL;
 1236: }
 1237: 
 1238: static u_char *
 1239: ospfAreaRangeEntry (struct variable *v, oid *name, size_t *length, int exact,
 1240: 		    size_t *var_len, WriteMethod **write_method)
 1241: {
 1242:   struct ospf_area_range *range;
 1243:   struct in_addr area_id;
 1244:   struct in_addr range_net;
 1245:   struct in_addr mask;
 1246:   struct ospf *ospf;
 1247:   
 1248:   /* Check OSPF instance. */
 1249:   ospf = ospf_lookup ();
 1250:   if (ospf == NULL)
 1251:     return NULL;
 1252: 
 1253:   memset (&area_id, 0, IN_ADDR_SIZE);
 1254:   memset (&range_net, 0, IN_ADDR_SIZE);
 1255: 
 1256:   range = ospfAreaRangeLookup (v, name, length, &area_id, &range_net, exact);
 1257:   if (! range)
 1258:     return NULL;
 1259: 
 1260:   /* Convert prefixlen to network mask format. */
 1261:   masklen2ip (range->subst_masklen, &mask);
 1262: 
 1263:   /* Return the current value of the variable */
 1264:   switch (v->magic) 
 1265:     {
 1266:     case OSPFAREARANGEAREAID:	/* 1 */
 1267:       return SNMP_IPADDRESS (area_id);
 1268:       break;
 1269:     case OSPFAREARANGENET:	/* 2 */
 1270:       return SNMP_IPADDRESS (range_net);
 1271:       break;
 1272:     case OSPFAREARANGEMASK:	/* 3 */
 1273:       return SNMP_IPADDRESS (mask);
 1274:       break;
 1275:     case OSPFAREARANGESTATUS:	/* 4 */
 1276:       return SNMP_INTEGER (SNMP_VALID);
 1277:       break;
 1278:     case OSPFAREARANGEEFFECT:	/* 5 */
 1279: #define OSPF_advertiseMatching      1
 1280: #define OSPF_doNotAdvertiseMatching 2
 1281:       return SNMP_INTEGER (OSPF_advertiseMatching);
 1282:       break;
 1283:     default:
 1284:       return NULL;
 1285:       break;
 1286:     }
 1287:   return NULL;
 1288: }
 1289: 
 1290: static struct ospf_nbr_nbma *
 1291: ospfHostLookup (struct variable *v, oid *name, size_t *length,
 1292: 		struct in_addr *addr, int exact)
 1293: {
 1294:   int len;
 1295:   struct ospf_nbr_nbma *nbr_nbma;
 1296:   struct ospf *ospf;
 1297: 
 1298:   ospf = ospf_lookup ();
 1299:   if (ospf == NULL)
 1300:     return NULL;
 1301: 
 1302:   if (exact)
 1303:     {
 1304:       /* INDEX { ospfHostIpAddress, ospfHostTOS } */
 1305:       if (*length != v->namelen + IN_ADDR_SIZE + 1)
 1306: 	return NULL;
 1307: 
 1308:       /* Check ospfHostTOS. */
 1309:       if (name[*length - 1] != 0)
 1310: 	return NULL;
 1311: 
 1312:       oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr);
 1313: 
 1314:       nbr_nbma = ospf_nbr_nbma_lookup (ospf, *addr);
 1315: 
 1316:       return nbr_nbma;
 1317:     }
 1318:   else
 1319:     {
 1320:       len = *length - v->namelen;
 1321:       if (len > 4)
 1322: 	len = 4;
 1323:       
 1324:       oid2in_addr (name + v->namelen, len, addr);
 1325: 
 1326:       nbr_nbma = ospf_nbr_nbma_lookup_next (ospf, addr, len == 0 ? 1 : 0);
 1327: 
 1328:       if (nbr_nbma == NULL)
 1329: 	return NULL;
 1330: 
 1331:       oid_copy_addr (name + v->namelen, addr, IN_ADDR_SIZE);
 1332: 
 1333:       /* Set TOS 0. */
 1334:       name[v->namelen + IN_ADDR_SIZE] = 0;
 1335: 
 1336:       *length = v->namelen + IN_ADDR_SIZE + 1;
 1337: 
 1338:       return nbr_nbma;
 1339:     }
 1340:   return NULL;
 1341: }
 1342: 
 1343: static u_char *
 1344: ospfHostEntry (struct variable *v, oid *name, size_t *length, int exact,
 1345: 	       size_t *var_len, WriteMethod **write_method)
 1346: {
 1347:   struct ospf_nbr_nbma *nbr_nbma;
 1348:   struct ospf_interface *oi;
 1349:   struct in_addr addr;
 1350:   struct ospf *ospf;
 1351: 
 1352:   /* Check OSPF instance. */
 1353:   ospf = ospf_lookup ();
 1354:   if (ospf == NULL)
 1355:     return NULL;
 1356: 
 1357:   memset (&addr, 0, sizeof (struct in_addr));
 1358: 
 1359:   nbr_nbma = ospfHostLookup (v, name, length, &addr, exact);
 1360:   if (nbr_nbma == NULL)
 1361:     return NULL;
 1362: 
 1363:   oi = nbr_nbma->oi;
 1364: 
 1365:   /* Return the current value of the variable */
 1366:   switch (v->magic) 
 1367:     {
 1368:     case OSPFHOSTIPADDRESS:	/* 1 */
 1369:       return SNMP_IPADDRESS (nbr_nbma->addr);
 1370:       break;
 1371:     case OSPFHOSTTOS:		/* 2 */
 1372:       return SNMP_INTEGER (0);
 1373:       break;
 1374:     case OSPFHOSTMETRIC:	/* 3 */
 1375:       if (oi)
 1376: 	return SNMP_INTEGER (oi->output_cost);
 1377:       else
 1378: 	return SNMP_INTEGER (1);
 1379:       break;
 1380:     case OSPFHOSTSTATUS:	/* 4 */
 1381:       return SNMP_INTEGER (SNMP_VALID);
 1382:       break;
 1383:     case OSPFHOSTAREAID:	/* 5 */
 1384:       if (oi && oi->area)
 1385: 	return SNMP_IPADDRESS (oi->area->area_id);
 1386:       else
 1387: 	return SNMP_IPADDRESS (ospf_empty_addr);
 1388:       break;
 1389:     default:
 1390:       return NULL;
 1391:       break;
 1392:     }
 1393:   return NULL;
 1394: }
 1395: 
 1396: struct list *ospf_snmp_iflist;
 1397: 
 1398: struct ospf_snmp_if
 1399: {
 1400:   struct in_addr addr;
 1401:   unsigned int ifindex;
 1402:   struct interface *ifp;
 1403: };
 1404: 
 1405: static struct ospf_snmp_if *
 1406: ospf_snmp_if_new (void)
 1407: {
 1408:   return XCALLOC (0, sizeof (struct ospf_snmp_if));
 1409: }
 1410: 
 1411: static void
 1412: ospf_snmp_if_free (struct ospf_snmp_if *osif)
 1413: {
 1414:   XFREE (0, osif);
 1415: }
 1416: 
 1417: void
 1418: ospf_snmp_if_delete (struct interface *ifp)
 1419: {
 1420:   struct listnode *node, *nnode;
 1421:   struct ospf_snmp_if *osif;
 1422: 
 1423:   for (ALL_LIST_ELEMENTS (ospf_snmp_iflist, node, nnode, osif))
 1424:     {
 1425:       if (osif->ifp == ifp)
 1426: 	{
 1427: 	  list_delete_node (ospf_snmp_iflist, node);
 1428: 	  ospf_snmp_if_free (osif);
 1429: 	  return;
 1430: 	}
 1431:     }
 1432: }
 1433: 
 1434: void
 1435: ospf_snmp_if_update (struct interface *ifp)
 1436: {
 1437:   struct listnode *node;
 1438:   struct listnode *pn;
 1439:   struct connected *ifc;
 1440:   struct prefix *p;
 1441:   struct ospf_snmp_if *osif;
 1442:   struct in_addr *addr;
 1443:   unsigned int ifindex;
 1444: 
 1445:   ospf_snmp_if_delete (ifp);
 1446: 
 1447:   p = NULL;
 1448:   addr = NULL;
 1449:   ifindex = 0;
 1450: 
 1451:   /* Lookup first IPv4 address entry. */
 1452:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
 1453:     {
 1454:       p = CONNECTED_ID(ifc);
 1455: 
 1456:       if (p->family == AF_INET)
 1457: 	{
 1458: 	  addr = &p->u.prefix4;
 1459: 	  break;
 1460: 	}
 1461:     }
 1462:   if (! addr)
 1463:     ifindex = ifp->ifindex;
 1464: 
 1465:   /* Add interface to the list. */
 1466:   pn = NULL;
 1467:   for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, node, osif))
 1468:     {
 1469:       if (addr)
 1470: 	{
 1471: 	  /* Usual interfaces --> Sort them based on interface IPv4 addresses */
 1472: 	  if (ntohl (osif->addr.s_addr) > ntohl (addr->s_addr))
 1473: 	    break;
 1474: 	}
 1475:       else
 1476: 	{
 1477: 	  /* Unnumbered interfaces --> Sort them based on interface indexes */
 1478: 	  if (osif->addr.s_addr != 0 || osif->ifindex > ifindex)
 1479: 	    break;
 1480: 	}
 1481:       pn = node;
 1482:     }
 1483: 
 1484:   osif = ospf_snmp_if_new ();
 1485:   if (addr) /* Usual interface */
 1486:   {
 1487:     osif->addr = *addr;
 1488:     
 1489:     /* This field is used for storing ospfAddressLessIf OID value,
 1490:      * conform to RFC1850 OSPF-MIB specification, it must be 0 for
 1491:      * usual interface */
 1492:     osif->ifindex = 0;
 1493:   }
 1494:   else  /* Unnumbered interface */
 1495:     osif->ifindex = ifindex;
 1496:   osif->ifp = ifp;
 1497: 
 1498:   listnode_add_after (ospf_snmp_iflist, pn, osif);
 1499: }
 1500: 
 1501: static int
 1502: ospf_snmp_is_if_have_addr (struct interface *ifp)
 1503: {
 1504:   struct listnode *nn;
 1505:   struct connected *ifc;
 1506: 
 1507:   /* Is this interface having any connected IPv4 address ? */
 1508:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, ifc))
 1509:   {
 1510:     if (CONNECTED_PREFIX(ifc)->family == AF_INET)
 1511:       return 1;
 1512:   }
 1513:   
 1514:   return 0;
 1515: }
 1516: 
 1517: static struct ospf_interface *
 1518: ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex)
 1519: {
 1520:   struct listnode *node;
 1521:   struct ospf_snmp_if *osif;
 1522:   struct ospf_interface *oi = NULL;
 1523:   struct ospf *ospf = ospf_lookup ();
 1524: 
 1525:   for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, node, osif))
 1526:     {  
 1527:       if (ifaddr->s_addr)
 1528:         {
 1529: 	      if (IPV4_ADDR_SAME (&osif->addr, ifaddr))
 1530:             oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
 1531:         }
 1532:       else
 1533:         {
 1534: 	      if (osif->ifindex == *ifindex)
 1535:             oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
 1536:         }
 1537:     }
 1538:   return oi;
 1539: }
 1540: 
 1541: static struct ospf_interface *
 1542: ospf_snmp_if_lookup_next (struct in_addr *ifaddr, unsigned int *ifindex,
 1543: 			  int ifaddr_next, int ifindex_next)
 1544: {
 1545:   struct ospf_snmp_if *osif;
 1546:   struct listnode *nn;
 1547:   struct ospf *ospf = ospf_lookup ();
 1548:   struct ospf_interface *oi = NULL;
 1549: 
 1550:   if (ospf == NULL)
 1551:     return NULL;
 1552: 
 1553:   /* No instance is specified --> Return the first OSPF interface */
 1554:   if (ifaddr_next)
 1555:     {
 1556:       for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, nn, osif))
 1557: 	{
 1558: 	  osif = listgetdata (nn);
 1559: 	  *ifaddr = osif->addr;
 1560: 	  *ifindex = osif->ifindex;
 1561:           /* Because no instance is specified, we don't care about the kind of 
 1562:            * interface (usual or unnumbered), just returning the first valid 
 1563:            * OSPF interface */
 1564:           oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
 1565:           if (oi)
 1566:             return (oi);
 1567: 	}
 1568:       return NULL;
 1569:     }
 1570: 
 1571:   /* An instance is specified --> Return the next OSPF interface */
 1572:   for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, nn, osif))
 1573:     {
 1574:       /* Usual interface */
 1575:       if (ifaddr->s_addr) 
 1576: 	{
 1577: 	  /* The interface must have valid AF_INET connected address */
 1578: 	  /* it must have lager IPv4 address value than the lookup entry */
 1579: 	  if ((ospf_snmp_is_if_have_addr(osif->ifp)) &&
 1580: 	      (ntohl (osif->addr.s_addr) > ntohl (ifaddr->s_addr)))
 1581: 	    {
 1582: 	      *ifaddr = osif->addr;
 1583: 	      *ifindex = osif->ifindex;
 1584:         
 1585: 	      /* and it must be an OSPF interface */
 1586: 	      oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
 1587: 	      if (oi)
 1588: 		return oi;
 1589: 	    }
 1590: 	}
 1591:       /* Unnumbered interface */
 1592:       else  
 1593:         /* The interface must NOT have valid AF_INET connected address */
 1594:         /* it must have lager interface index than the lookup entry */
 1595:         if ((!ospf_snmp_is_if_have_addr(osif->ifp)) &&
 1596:             (osif->ifindex > *ifindex))
 1597:           {
 1598:             *ifaddr = osif->addr;
 1599:             *ifindex = osif->ifindex;
 1600:         
 1601:             /* and it must be an OSPF interface */
 1602:             oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
 1603:             if (oi)
 1604:               return oi;
 1605:           }
 1606:     }
 1607:   return NULL;
 1608: }
 1609: 
 1610: static int
 1611: ospf_snmp_iftype (struct interface *ifp)
 1612: {
 1613: #define ospf_snmp_iftype_broadcast         1
 1614: #define ospf_snmp_iftype_nbma              2
 1615: #define ospf_snmp_iftype_pointToPoint      3
 1616: #define ospf_snmp_iftype_pointToMultipoint 5
 1617:   if (if_is_broadcast (ifp))
 1618:     return ospf_snmp_iftype_broadcast;
 1619:   if (if_is_pointopoint (ifp))
 1620:     return ospf_snmp_iftype_pointToPoint;
 1621:   return ospf_snmp_iftype_broadcast;
 1622: }
 1623: 
 1624: static struct ospf_interface *
 1625: ospfIfLookup (struct variable *v, oid *name, size_t *length,
 1626: 	      struct in_addr *ifaddr, unsigned int *ifindex, int exact)
 1627: {
 1628:   unsigned int len;
 1629:   int ifaddr_next = 0;
 1630:   int ifindex_next = 0;
 1631:   struct ospf_interface *oi;
 1632:   oid *offset;
 1633: 
 1634:   if (exact)
 1635:     {
 1636:       if (*length != v->namelen + IN_ADDR_SIZE + 1)
 1637: 	return NULL;
 1638: 
 1639:       oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
 1640:       *ifindex = name[v->namelen + IN_ADDR_SIZE];
 1641: 
 1642:       return ospf_snmp_if_lookup (ifaddr, ifindex);
 1643:     }
 1644:   else
 1645:     {
 1646:       len = *length - v->namelen;
 1647:       if (len >= IN_ADDR_SIZE)
 1648: 	len = IN_ADDR_SIZE;
 1649:       if (len <= 0)
 1650: 	ifaddr_next = 1;
 1651: 
 1652:       oid2in_addr (name + v->namelen, len, ifaddr);
 1653: 
 1654:       len = *length - v->namelen - IN_ADDR_SIZE;
 1655:       if (len >= 1)
 1656: 	len = 1;
 1657:       else
 1658: 	ifindex_next = 1;
 1659: 
 1660:       if (len == 1)
 1661: 	*ifindex = name[v->namelen + IN_ADDR_SIZE];
 1662: 
 1663:       oi = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
 1664: 				      ifindex_next);
 1665:       if (oi)
 1666: 	{
 1667: 	  *length = v->namelen + IN_ADDR_SIZE + 1;
 1668: 	  offset = name + v->namelen;
 1669: 	  oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
 1670: 	  offset += IN_ADDR_SIZE;
 1671: 	  *offset = *ifindex;
 1672: 	  return oi;
 1673: 	}
 1674:     }
 1675:   return NULL;
 1676: }
 1677: 
 1678: static u_char *
 1679: ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact,
 1680: 	     size_t *var_len, WriteMethod **write_method)
 1681: {
 1682:   unsigned int ifindex;
 1683:   struct in_addr ifaddr;
 1684:   struct ospf_interface *oi;
 1685:   struct ospf *ospf;
 1686: 
 1687:   ifindex = 0;
 1688:   memset (&ifaddr, 0, sizeof (struct in_addr));
 1689: 
 1690:   /* Check OSPF instance. */
 1691:   ospf = ospf_lookup ();
 1692:   if (ospf == NULL)
 1693:     return NULL;
 1694: 
 1695:   oi = ospfIfLookup (v, name, length, &ifaddr, &ifindex, exact);
 1696:   if (oi == NULL)
 1697:     return NULL;
 1698: 
 1699:   /* Return the current value of the variable */
 1700:   switch (v->magic) 
 1701:     {
 1702:     case OSPFIFIPADDRESS:	/* 1 */
 1703:       return SNMP_IPADDRESS (ifaddr);
 1704:       break;
 1705:     case OSPFADDRESSLESSIF:	/* 2 */
 1706:       return SNMP_INTEGER (ifindex);
 1707:       break;
 1708:     case OSPFIFAREAID:		/* 3 */
 1709:       if (oi->area)
 1710: 	return SNMP_IPADDRESS (oi->area->area_id);
 1711:       else
 1712: 	return SNMP_IPADDRESS (ospf_empty_addr);
 1713:       break;
 1714:     case OSPFIFTYPE:		/* 4 */
 1715:       return SNMP_INTEGER (ospf_snmp_iftype (oi->ifp));
 1716:       break;
 1717:     case OSPFIFADMINSTAT:	/* 5 */
 1718:       if (oi)
 1719: 	return SNMP_INTEGER (OSPF_STATUS_ENABLED);
 1720:       else
 1721: 	return SNMP_INTEGER (OSPF_STATUS_DISABLED);
 1722:       break;
 1723:     case OSPFIFRTRPRIORITY:	/* 6 */
 1724:       return SNMP_INTEGER (PRIORITY (oi));
 1725:       break;
 1726:     case OSPFIFTRANSITDELAY:	/* 7 */
 1727:       return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
 1728:       break;
 1729:     case OSPFIFRETRANSINTERVAL:	/* 8 */
 1730:       return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
 1731:       break;
 1732:     case OSPFIFHELLOINTERVAL:	/* 9 */
 1733:       return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
 1734:       break;
 1735:     case OSPFIFRTRDEADINTERVAL:	/* 10 */
 1736:       return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
 1737:       break;
 1738:     case OSPFIFPOLLINTERVAL:	/* 11 */
 1739:       return SNMP_INTEGER (OSPF_POLL_INTERVAL_DEFAULT);
 1740:       break;
 1741:     case OSPFIFSTATE:		/* 12 */
 1742:       return SNMP_INTEGER (ISM_SNMP(oi->state));
 1743:       break;
 1744:     case OSPFIFDESIGNATEDROUTER: /* 13 */
 1745:       return SNMP_IPADDRESS (DR (oi));
 1746:       break;
 1747:     case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */
 1748:       return SNMP_IPADDRESS (BDR (oi));
 1749:       break;
 1750:     case OSPFIFEVENTS:		/* 15 */
 1751:       return SNMP_INTEGER (oi->state_change);
 1752:       break;
 1753:     case OSPFIFAUTHKEY:		/* 16 */
 1754:       *var_len = 0;
 1755:       return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
 1756:       break;
 1757:     case OSPFIFSTATUS:		/* 17 */
 1758:       return SNMP_INTEGER (SNMP_VALID);
 1759:       break;
 1760:     case OSPFIFMULTICASTFORWARDING: /* 18 */
 1761: #define ospf_snmp_multiforward_blocked    1
 1762: #define ospf_snmp_multiforward_multicast  2
 1763: #define ospf_snmp_multiforward_unicast    3
 1764:       return SNMP_INTEGER (ospf_snmp_multiforward_blocked);
 1765:       break;
 1766:     case OSPFIFDEMAND:		/* 19 */
 1767:       return SNMP_INTEGER (SNMP_FALSE);
 1768:       break;
 1769:     case OSPFIFAUTHTYPE:	/* 20 */
 1770:       if (oi->area)
 1771: 	return SNMP_INTEGER (oi->area->auth_type);
 1772:       else
 1773: 	return SNMP_INTEGER (0);
 1774:       break;
 1775:     default:
 1776:       return NULL;
 1777:       break;
 1778:     }
 1779:   return NULL;
 1780: }
 1781: 
 1782: #define OSPF_SNMP_METRIC_VALUE 1
 1783: 
 1784: static struct ospf_interface *
 1785: ospfIfMetricLookup (struct variable *v, oid *name, size_t *length,
 1786: 		    struct in_addr *ifaddr, unsigned int *ifindex, int exact)
 1787: {
 1788:   unsigned int len;
 1789:   int ifaddr_next = 0;
 1790:   int ifindex_next = 0;
 1791:   struct ospf_interface *oi;
 1792:   oid *offset;
 1793:   int metric;
 1794: 
 1795:   if (exact)
 1796:     {
 1797:       if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1)
 1798: 	return NULL;
 1799: 
 1800:       oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
 1801:       *ifindex = name[v->namelen + IN_ADDR_SIZE];
 1802:       metric = name[v->namelen + IN_ADDR_SIZE + 1];
 1803: 
 1804:       if (metric != OSPF_SNMP_METRIC_VALUE)
 1805: 	return NULL;
 1806: 
 1807:       return ospf_snmp_if_lookup (ifaddr, ifindex);
 1808:     }
 1809:   else
 1810:     {
 1811:       len = *length - v->namelen;
 1812:       if (len >= IN_ADDR_SIZE)
 1813: 	len = IN_ADDR_SIZE;
 1814:       else
 1815: 	ifaddr_next = 1;
 1816: 
 1817:       oid2in_addr (name + v->namelen, len, ifaddr);
 1818: 
 1819:       len = *length - v->namelen - IN_ADDR_SIZE;
 1820:       if (len >= 1)
 1821: 	len = 1;
 1822:       else
 1823: 	ifindex_next = 1;
 1824: 
 1825:       if (len == 1)
 1826: 	*ifindex = name[v->namelen + IN_ADDR_SIZE];
 1827: 
 1828:       oi = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
 1829: 				      ifindex_next);
 1830:       if (oi)
 1831: 	{
 1832: 	  *length = v->namelen + IN_ADDR_SIZE + 1 + 1;
 1833: 	  offset = name + v->namelen;
 1834: 	  oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
 1835: 	  offset += IN_ADDR_SIZE;
 1836: 	  *offset = *ifindex;
 1837: 	  offset++;
 1838: 	  *offset = OSPF_SNMP_METRIC_VALUE;
 1839: 	  return oi;
 1840: 	}
 1841:     }
 1842:   return NULL;
 1843: }
 1844: 
 1845: static u_char *
 1846: ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact,
 1847: 		   size_t *var_len, WriteMethod **write_method)
 1848: {
 1849:   /* Currently we support metric 1 only. */
 1850:   unsigned int ifindex;
 1851:   struct in_addr ifaddr;
 1852:   struct ospf_interface *oi;
 1853:   struct ospf *ospf;
 1854: 
 1855:   ifindex = 0;
 1856:   memset (&ifaddr, 0, sizeof (struct in_addr));
 1857: 
 1858:   /* Check OSPF instance. */
 1859:   ospf = ospf_lookup ();
 1860:   if (ospf == NULL)
 1861:     return NULL;
 1862: 
 1863:   oi = ospfIfMetricLookup (v, name, length, &ifaddr, &ifindex, exact);
 1864:   if (oi == NULL)
 1865:     return NULL;
 1866: 
 1867:   /* Return the current value of the variable */
 1868:   switch (v->magic) 
 1869:     {
 1870:     case OSPFIFMETRICIPADDRESS:
 1871:       return SNMP_IPADDRESS (ifaddr);
 1872:       break;
 1873:     case OSPFIFMETRICADDRESSLESSIF:
 1874:       return SNMP_INTEGER (ifindex);
 1875:       break;
 1876:     case OSPFIFMETRICTOS:
 1877:       return SNMP_INTEGER (0);
 1878:       break;
 1879:     case OSPFIFMETRICVALUE:
 1880:       return SNMP_INTEGER (OSPF_SNMP_METRIC_VALUE);
 1881:       break;
 1882:     case OSPFIFMETRICSTATUS:
 1883:       return SNMP_INTEGER (1);
 1884:       break;
 1885:     default:
 1886:       return NULL;
 1887:       break;
 1888:     }
 1889:   return NULL;
 1890: }
 1891: 
 1892: struct route_table *ospf_snmp_vl_table;
 1893: 
 1894: void
 1895: ospf_snmp_vl_add (struct ospf_vl_data *vl_data)
 1896: {
 1897:   struct prefix_ls lp;
 1898:   struct route_node *rn;
 1899: 
 1900:   memset (&lp, 0, sizeof (struct prefix_ls));
 1901:   lp.family = 0;
 1902:   lp.prefixlen = 64;
 1903:   lp.id = vl_data->vl_area_id;
 1904:   lp.adv_router = vl_data->vl_peer;
 1905: 
 1906:   rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
 1907:   rn->info = vl_data;
 1908: }
 1909: 
 1910: void
 1911: ospf_snmp_vl_delete (struct ospf_vl_data *vl_data)
 1912: {
 1913:   struct prefix_ls lp;
 1914:   struct route_node *rn;
 1915: 
 1916:   memset (&lp, 0, sizeof (struct prefix_ls));
 1917:   lp.family = 0;
 1918:   lp.prefixlen = 64;
 1919:   lp.id = vl_data->vl_area_id;
 1920:   lp.adv_router = vl_data->vl_peer;
 1921: 
 1922:   rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
 1923:   if (! rn)
 1924:     return;
 1925:   rn->info = NULL;
 1926:   route_unlock_node (rn);
 1927:   route_unlock_node (rn);
 1928: }
 1929: 
 1930: static struct ospf_vl_data *
 1931: ospf_snmp_vl_lookup (struct in_addr *area_id, struct in_addr *neighbor)
 1932: {
 1933:   struct prefix_ls lp;
 1934:   struct route_node *rn;
 1935:   struct ospf_vl_data *vl_data;
 1936: 
 1937:   memset (&lp, 0, sizeof (struct prefix_ls));
 1938:   lp.family = 0;
 1939:   lp.prefixlen = 64;
 1940:   lp.id = *area_id;
 1941:   lp.adv_router = *neighbor;
 1942: 
 1943:   rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
 1944:   if (rn)
 1945:     {
 1946:       vl_data = rn->info;
 1947:       route_unlock_node (rn);
 1948:       return vl_data;
 1949:     }
 1950:   return NULL;
 1951: }
 1952: 
 1953: static struct ospf_vl_data *
 1954: ospf_snmp_vl_lookup_next (struct in_addr *area_id, struct in_addr *neighbor,
 1955: 			  int first)
 1956: {
 1957:   struct prefix_ls lp;
 1958:   struct route_node *rn;
 1959:   struct ospf_vl_data *vl_data;
 1960: 
 1961:   memset (&lp, 0, sizeof (struct prefix_ls));
 1962:   lp.family = 0;
 1963:   lp.prefixlen = 64;
 1964:   lp.id = *area_id;
 1965:   lp.adv_router = *neighbor;
 1966: 
 1967:   if (first)
 1968:     rn = route_top (ospf_snmp_vl_table);
 1969:   else
 1970:     {
 1971:       rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
 1972:       rn = route_next (rn);
 1973:     }
 1974: 
 1975:   for (; rn; rn = route_next (rn))
 1976:     if (rn->info)
 1977:       break;
 1978: 
 1979:   if (rn && rn->info)
 1980:     {
 1981:       vl_data = rn->info;
 1982:       *area_id = vl_data->vl_area_id;
 1983:       *neighbor = vl_data->vl_peer;
 1984:       route_unlock_node (rn);
 1985:       return vl_data;
 1986:     }
 1987:   return NULL;
 1988: }
 1989: 
 1990: static struct ospf_vl_data *
 1991: ospfVirtIfLookup (struct variable *v, oid *name, size_t *length,
 1992: 		  struct in_addr *area_id, struct in_addr *neighbor, int exact)
 1993: {
 1994:   int first;
 1995:   unsigned int len;
 1996:   struct ospf_vl_data *vl_data;
 1997: 
 1998:   if (exact)
 1999:     {
 2000:       if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE)
 2001: 	return NULL;
 2002: 
 2003:       oid2in_addr (name + v->namelen, IN_ADDR_SIZE, area_id);
 2004:       oid2in_addr (name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE, neighbor);
 2005: 
 2006:       return ospf_snmp_vl_lookup (area_id, neighbor);
 2007:     }
 2008:   else
 2009:     {
 2010:       first = 0;
 2011: 
 2012:       len = *length - v->namelen;
 2013:       if (len <= 0)
 2014: 	first = 1;
 2015:       if (len > IN_ADDR_SIZE)
 2016: 	len = IN_ADDR_SIZE;
 2017:       oid2in_addr (name + v->namelen, len, area_id);
 2018: 
 2019:       len = *length - v->namelen - IN_ADDR_SIZE;
 2020:       if (len > IN_ADDR_SIZE)
 2021: 	len = IN_ADDR_SIZE;
 2022:       oid2in_addr (name + v->namelen + IN_ADDR_SIZE, len, neighbor);
 2023: 
 2024:       vl_data = ospf_snmp_vl_lookup_next (area_id, neighbor, first);
 2025: 
 2026:       if (vl_data)
 2027: 	{
 2028: 	  *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
 2029: 	  oid_copy_addr (name + v->namelen, area_id, IN_ADDR_SIZE);
 2030: 	  oid_copy_addr (name + v->namelen + IN_ADDR_SIZE, neighbor,
 2031: 			 IN_ADDR_SIZE);
 2032: 	  return vl_data;
 2033: 	}
 2034:     }
 2035:   return NULL;
 2036: }
 2037: 
 2038: static u_char *
 2039: ospfVirtIfEntry (struct variable *v, oid *name, size_t *length, int exact,
 2040: 		 size_t *var_len, WriteMethod **write_method)
 2041: {
 2042:   struct ospf_vl_data *vl_data;
 2043:   struct ospf_interface *oi;
 2044:   struct in_addr area_id;
 2045:   struct in_addr neighbor;
 2046: 
 2047:   memset (&area_id, 0, sizeof (struct in_addr));
 2048:   memset (&neighbor, 0, sizeof (struct in_addr));
 2049: 
 2050:   vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
 2051:   if (! vl_data)
 2052:     return NULL;
 2053:   oi = vl_data->vl_oi;
 2054:   if (! oi)
 2055:     return NULL;
 2056:   
 2057:   /* Return the current value of the variable */
 2058:   switch (v->magic) 
 2059:     {
 2060:     case OSPFVIRTIFAREAID:
 2061:       return SNMP_IPADDRESS (area_id);
 2062:       break;
 2063:     case OSPFVIRTIFNEIGHBOR:
 2064:       return SNMP_IPADDRESS (neighbor);
 2065:       break;
 2066:     case OSPFVIRTIFTRANSITDELAY:
 2067:       return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
 2068:       break;
 2069:     case OSPFVIRTIFRETRANSINTERVAL:
 2070:       return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
 2071:       break;
 2072:     case OSPFVIRTIFHELLOINTERVAL:
 2073:       return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
 2074:       break;
 2075:     case OSPFVIRTIFRTRDEADINTERVAL:
 2076:       return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
 2077:       break;
 2078:     case OSPFVIRTIFSTATE:
 2079:       return SNMP_INTEGER (oi->state);
 2080:       break;
 2081:     case OSPFVIRTIFEVENTS:
 2082:       return SNMP_INTEGER (oi->state_change);
 2083:       break;
 2084:     case OSPFVIRTIFAUTHKEY:
 2085:       *var_len = 0;
 2086:       return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
 2087:       break;
 2088:     case OSPFVIRTIFSTATUS:
 2089:       return SNMP_INTEGER (SNMP_VALID);
 2090:       break;
 2091:     case OSPFVIRTIFAUTHTYPE:
 2092:       if (oi->area)
 2093: 	return SNMP_INTEGER (oi->area->auth_type);
 2094:       else
 2095: 	return SNMP_INTEGER (0);
 2096:       break;
 2097:     default:
 2098:       return NULL;
 2099:       break;
 2100:     }
 2101:   return NULL;
 2102: }
 2103: 
 2104: static struct ospf_neighbor *
 2105: ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr,
 2106: 		      unsigned int *ifindex)
 2107: {
 2108:   struct listnode *node, *nnode;
 2109:   struct ospf_interface *oi;
 2110:   struct ospf_neighbor *nbr;
 2111:   struct route_node *rn;
 2112: 
 2113:   for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
 2114:     {
 2115:       for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
 2116: 	if ((nbr = rn->info) != NULL
 2117: 	    && nbr != oi->nbr_self
 2118: /* If EXACT match is needed, provide ALL entry found
 2119: 	    && nbr->state != NSM_Down
 2120:  */
 2121: 	    && nbr->src.s_addr != 0)
 2122: 	  {
 2123: 	    if (IPV4_ADDR_SAME (&nbr->src, nbr_addr))
 2124: 	      {
 2125: 		route_unlock_node (rn);
 2126: 		return nbr;
 2127: 	      }
 2128: 	  }
 2129:     }
 2130:   return NULL;
 2131: }
 2132: 
 2133: static struct ospf_neighbor *
 2134: ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex,
 2135: 			   int first)
 2136: {
 2137:   struct listnode *nn;
 2138:   struct ospf_interface *oi;
 2139:   struct ospf_neighbor *nbr;
 2140:   struct route_node *rn;
 2141:   struct ospf_neighbor *min = NULL;
 2142:   struct ospf *ospf = ospf;
 2143: 
 2144:   ospf = ospf_lookup ();
 2145: 
 2146:   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, nn, oi))
 2147:     {
 2148:       for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
 2149: 	if ((nbr = rn->info) != NULL
 2150: 	    && nbr != oi->nbr_self
 2151: 	    && nbr->state != NSM_Down
 2152: 	    && nbr->src.s_addr != 0)
 2153: 	  {
 2154: 	    if (first)
 2155: 	      {
 2156: 		if (! min)
 2157: 		  min = nbr;
 2158: 		else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
 2159: 		  min = nbr;
 2160: 	      }
 2161: 	    else if (ntohl (nbr->src.s_addr) > ntohl (nbr_addr->s_addr))
 2162: 	      {
 2163: 		if (! min)
 2164: 		  min = nbr;
 2165: 		else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
 2166: 		  min = nbr;
 2167: 	      }
 2168: 	  }
 2169:     }
 2170:   if (min)
 2171:     {
 2172:       *nbr_addr = min->src;
 2173:       *ifindex = 0;
 2174:       return min;
 2175:     }
 2176:   return NULL;
 2177: }
 2178: 
 2179: static struct ospf_neighbor *
 2180: ospfNbrLookup (struct variable *v, oid *name, size_t *length,
 2181: 	       struct in_addr *nbr_addr, unsigned int *ifindex, int exact)
 2182: {
 2183:   unsigned int len;
 2184:   int first;
 2185:   struct ospf_neighbor *nbr;
 2186:   struct ospf *ospf;
 2187: 
 2188:   ospf = ospf_lookup ();
 2189: 
 2190:   if (! ospf)
 2191:     return NULL;
 2192: 
 2193:   if (exact)
 2194:     {
 2195:       if (*length != v->namelen + IN_ADDR_SIZE + 1)
 2196: 	return NULL;
 2197: 
 2198:       oid2in_addr (name + v->namelen, IN_ADDR_SIZE, nbr_addr);
 2199:       *ifindex = name[v->namelen + IN_ADDR_SIZE];
 2200: 
 2201:       return ospf_snmp_nbr_lookup (ospf, nbr_addr, ifindex);
 2202:     }
 2203:   else
 2204:     {
 2205:       first = 0;
 2206:       len = *length - v->namelen;
 2207: 
 2208:       if (len <= 0)
 2209: 	first = 1;
 2210: 
 2211:       if (len > IN_ADDR_SIZE)
 2212: 	len = IN_ADDR_SIZE;
 2213: 
 2214:       oid2in_addr (name + v->namelen, len, nbr_addr);
 2215: 
 2216:       len = *length - v->namelen - IN_ADDR_SIZE;
 2217:       if (len >= 1)
 2218: 	*ifindex = name[v->namelen + IN_ADDR_SIZE];
 2219:       
 2220:       nbr = ospf_snmp_nbr_lookup_next (nbr_addr, ifindex, first);
 2221: 
 2222:       if (nbr)
 2223: 	{
 2224: 	  *length = v->namelen + IN_ADDR_SIZE + 1;
 2225: 	  oid_copy_addr (name + v->namelen, nbr_addr, IN_ADDR_SIZE);
 2226: 	  name[v->namelen + IN_ADDR_SIZE] = *ifindex;
 2227: 	  return nbr;
 2228: 	}
 2229:     }
 2230:   return NULL;
 2231: }
 2232: 
 2233: /* map internal quagga neighbor states to official MIB values:
 2234: 
 2235: ospfNbrState OBJECT-TYPE
 2236:         SYNTAX   INTEGER    {
 2237:                     down (1),
 2238:                     attempt (2),
 2239:                     init (3),
 2240:                     twoWay (4),
 2241:                     exchangeStart (5),
 2242:                     exchange (6),
 2243:                     loading (7),
 2244:                     full (8)
 2245:                   }
 2246: */
 2247: static int32_t
 2248: ospf_snmp_neighbor_state(u_char nst)
 2249: {
 2250:   switch (nst)
 2251:     {
 2252:     case NSM_Attempt:
 2253:       return 2;
 2254:     case NSM_Init:
 2255:       return 3;
 2256:     case NSM_TwoWay:
 2257:       return 4;
 2258:     case NSM_ExStart:
 2259:       return 5;
 2260:     case NSM_Exchange:
 2261:       return 6;
 2262:     case NSM_Loading:
 2263:       return 7;
 2264:     case NSM_Full:
 2265:       return 8;
 2266:     default:
 2267:       return 1; /* down */
 2268:     }
 2269: }
 2270: 
 2271: static u_char *
 2272: ospfNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
 2273: 	      size_t *var_len, WriteMethod **write_method)
 2274: {
 2275:   struct in_addr nbr_addr;
 2276:   unsigned int ifindex;
 2277:   struct ospf_neighbor *nbr;
 2278:   struct ospf_interface *oi;
 2279: 
 2280:   memset (&nbr_addr, 0, sizeof (struct in_addr));
 2281:   ifindex = 0;
 2282:   
 2283:   nbr = ospfNbrLookup (v, name, length, &nbr_addr, &ifindex, exact);
 2284:   if (! nbr)
 2285:     return NULL;
 2286:   oi = nbr->oi;
 2287:   if (! oi)
 2288:     return NULL;
 2289: 
 2290:   /* Return the current value of the variable */
 2291:   switch (v->magic) 
 2292:     {
 2293:     case OSPFNBRIPADDR:
 2294:       return SNMP_IPADDRESS (nbr_addr);
 2295:       break;
 2296:     case OSPFNBRADDRESSLESSINDEX:
 2297:       return SNMP_INTEGER (ifindex);
 2298:       break;
 2299:     case OSPFNBRRTRID:
 2300:       return SNMP_IPADDRESS (nbr->router_id);
 2301:       break;
 2302:     case OSPFNBROPTIONS:
 2303:       return SNMP_INTEGER (oi->nbr_self->options);
 2304:       break;
 2305:     case OSPFNBRPRIORITY:
 2306:       return SNMP_INTEGER (nbr->priority);
 2307:       break;
 2308:     case OSPFNBRSTATE:
 2309:       return SNMP_INTEGER (ospf_snmp_neighbor_state(nbr->state));
 2310:       break;
 2311:     case OSPFNBREVENTS:
 2312:       return SNMP_INTEGER (nbr->state_change);
 2313:       break;
 2314:     case OSPFNBRLSRETRANSQLEN:
 2315:       return SNMP_INTEGER (ospf_ls_retransmit_count (nbr));
 2316:       break;
 2317:     case OSPFNBMANBRSTATUS:
 2318:       return SNMP_INTEGER (SNMP_VALID);
 2319:       break;
 2320:     case OSPFNBMANBRPERMANENCE:
 2321:       return SNMP_INTEGER (2);
 2322:       break;
 2323:     case OSPFNBRHELLOSUPPRESSED:
 2324:       return SNMP_INTEGER (SNMP_FALSE);
 2325:       break;
 2326:     default:
 2327:       return NULL;
 2328:       break;
 2329:     }
 2330:   return NULL;
 2331: }
 2332: 
 2333: static u_char *
 2334: ospfVirtNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
 2335: 		  size_t *var_len, WriteMethod **write_method)
 2336: {
 2337:   struct ospf_vl_data *vl_data;
 2338:   struct in_addr area_id;
 2339:   struct in_addr neighbor;
 2340:   struct ospf *ospf;
 2341: 
 2342:   memset (&area_id, 0, sizeof (struct in_addr));
 2343:   memset (&neighbor, 0, sizeof (struct in_addr));
 2344: 
 2345:   /* Check OSPF instance. */
 2346:   ospf = ospf_lookup ();
 2347:   if (ospf == NULL)
 2348:     return NULL;
 2349: 
 2350:   vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
 2351:   if (! vl_data)
 2352:     return NULL;
 2353: 
 2354:   /* Return the current value of the variable */
 2355:   switch (v->magic) 
 2356:     {
 2357:     case OSPFVIRTNBRAREA:
 2358:       return (u_char *) NULL;
 2359:       break;
 2360:     case OSPFVIRTNBRRTRID:
 2361:       return (u_char *) NULL;
 2362:       break;
 2363:     case OSPFVIRTNBRIPADDR:
 2364:       return (u_char *) NULL;
 2365:       break;
 2366:     case OSPFVIRTNBROPTIONS:
 2367:       return (u_char *) NULL;
 2368:       break;
 2369:     case OSPFVIRTNBRSTATE:
 2370:       return (u_char *) NULL;
 2371:       break;
 2372:     case OSPFVIRTNBREVENTS:
 2373:       return (u_char *) NULL;
 2374:       break;
 2375:     case OSPFVIRTNBRLSRETRANSQLEN:
 2376:       return (u_char *) NULL;
 2377:       break;
 2378:     case OSPFVIRTNBRHELLOSUPPRESSED:
 2379:       return (u_char *) NULL;
 2380:       break;
 2381:     default:
 2382:       return NULL;
 2383:       break;
 2384:     }
 2385:   return NULL;
 2386: }
 2387: 
 2388: static struct ospf_lsa *
 2389: ospfExtLsdbLookup (struct variable *v, oid *name, size_t *length, u_char *type,
 2390: 		   struct in_addr *ls_id, struct in_addr *router_id, int exact)
 2391: {
 2392:   int first;
 2393:   oid *offset;
 2394:   int offsetlen;
 2395:   u_char lsa_type;
 2396:   unsigned int len;
 2397:   struct ospf_lsa *lsa;
 2398:   struct ospf *ospf;
 2399: 
 2400:   ospf = ospf_lookup ();
 2401:   if (exact)
 2402:     {
 2403:       if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
 2404: 	return NULL;
 2405:       
 2406:       offset = name + v->namelen;
 2407: 
 2408:       /* Make it sure given value match to type. */
 2409:       lsa_type = *offset;
 2410:       offset++;
 2411: 
 2412:       if (lsa_type != *type)
 2413: 	return NULL;
 2414:       
 2415:       /* LS ID. */
 2416:       oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
 2417:       offset += IN_ADDR_SIZE;
 2418: 
 2419:       /* Router ID. */
 2420:       oid2in_addr (offset, IN_ADDR_SIZE, router_id);
 2421: 
 2422:       return ospf_lsdb_lookup_by_id (ospf->lsdb, *type, *ls_id, *router_id);
 2423:     }
 2424:   else
 2425:     {
 2426:       /* Get variable length. */
 2427:       first = 0;
 2428:       offset = name + v->namelen;
 2429:       offsetlen = *length - v->namelen;
 2430: 
 2431:       /* LSA type value. */
 2432:       lsa_type = *offset;
 2433:       offset++;
 2434:       offsetlen--;
 2435: 
 2436:       if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA)
 2437: 	first = 1;
 2438: 
 2439:       /* LS ID. */
 2440:       len = offsetlen;
 2441:       if (len > IN_ADDR_SIZE)
 2442: 	len = IN_ADDR_SIZE;
 2443: 
 2444:       oid2in_addr (offset, len, ls_id);
 2445: 
 2446:       offset += IN_ADDR_SIZE;
 2447:       offsetlen -= IN_ADDR_SIZE;
 2448: 
 2449:       /* Router ID. */
 2450:       len = offsetlen;
 2451:       if (len > IN_ADDR_SIZE)
 2452: 	len = IN_ADDR_SIZE;
 2453: 
 2454:       oid2in_addr (offset, len, router_id);
 2455: 
 2456:       lsa = ospf_lsdb_lookup_by_id_next (ospf->lsdb, *type, *ls_id,
 2457: 					*router_id, first);
 2458: 
 2459:       if (lsa)
 2460: 	{
 2461: 	  /* Fill in length. */
 2462: 	  *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE;
 2463: 
 2464: 	  /* Fill in value. */
 2465: 	  offset = name + v->namelen;
 2466: 
 2467: 	  *offset = OSPF_AS_EXTERNAL_LSA;
 2468: 	  offset++;
 2469: 	  oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
 2470: 	  offset += IN_ADDR_SIZE;
 2471: 	  oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
 2472: 	    
 2473: 	  return lsa;
 2474: 	}
 2475:     }
 2476:   return NULL;
 2477: }
 2478: 
 2479: static u_char *
 2480: ospfExtLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
 2481: 		  size_t *var_len, WriteMethod **write_method)
 2482: {
 2483:   struct ospf_lsa *lsa;
 2484:   struct lsa_header *lsah;
 2485:   u_char type;
 2486:   struct in_addr ls_id;
 2487:   struct in_addr router_id;
 2488:   struct ospf *ospf;
 2489: 
 2490:   type = OSPF_AS_EXTERNAL_LSA;
 2491:   memset (&ls_id, 0, sizeof (struct in_addr));
 2492:   memset (&router_id, 0, sizeof (struct in_addr));
 2493: 
 2494:   /* Check OSPF instance. */
 2495:   ospf = ospf_lookup ();
 2496:   if (ospf == NULL)
 2497:     return NULL;
 2498: 
 2499:   lsa = ospfExtLsdbLookup (v, name, length, &type, &ls_id, &router_id, exact);
 2500:   if (! lsa)
 2501:     return NULL;
 2502: 
 2503:   lsah = lsa->data;
 2504: 
 2505:   /* Return the current value of the variable */
 2506:   switch (v->magic) 
 2507:     {
 2508:     case OSPFEXTLSDBTYPE:
 2509:       return SNMP_INTEGER (OSPF_AS_EXTERNAL_LSA);
 2510:       break;
 2511:     case OSPFEXTLSDBLSID:
 2512:       return SNMP_IPADDRESS (lsah->id);
 2513:       break;
 2514:     case OSPFEXTLSDBROUTERID:
 2515:       return SNMP_IPADDRESS (lsah->adv_router);
 2516:       break;
 2517:     case OSPFEXTLSDBSEQUENCE:
 2518:       return SNMP_INTEGER (lsah->ls_seqnum);
 2519:       break;
 2520:     case OSPFEXTLSDBAGE:
 2521:       return SNMP_INTEGER (lsah->ls_age);
 2522:       break;
 2523:     case OSPFEXTLSDBCHECKSUM:
 2524:       return SNMP_INTEGER (lsah->checksum);
 2525:       break;
 2526:     case OSPFEXTLSDBADVERTISEMENT:
 2527:       *var_len = ntohs (lsah->length);
 2528:       return (u_char *) lsah;
 2529:       break;
 2530:     default:
 2531:       return NULL;
 2532:       break;
 2533:     }
 2534:   return NULL;
 2535: }
 2536: 
 2537: static u_char *
 2538: ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length,
 2539: 			int exact, size_t *var_len, WriteMethod **write_method)
 2540: {
 2541:   /* Return the current value of the variable */
 2542:   switch (v->magic) 
 2543:     {
 2544:     case OSPFAREAAGGREGATEAREAID:
 2545:       return (u_char *) NULL;
 2546:       break;
 2547:     case OSPFAREAAGGREGATELSDBTYPE:
 2548:       return (u_char *) NULL;
 2549:       break;
 2550:     case OSPFAREAAGGREGATENET:
 2551:       return (u_char *) NULL;
 2552:       break;
 2553:     case OSPFAREAAGGREGATEMASK:
 2554:       return (u_char *) NULL;
 2555:       break;
 2556:     case OSPFAREAAGGREGATESTATUS:
 2557:       return (u_char *) NULL;
 2558:       break;
 2559:     case OSPFAREAAGGREGATEEFFECT:
 2560:       return (u_char *) NULL;
 2561:       break;
 2562:     default:
 2563:       return NULL;
 2564:       break;
 2565:     }
 2566:   return NULL;
 2567: }
 2568: 
 2569: /* OSPF Traps. */
 2570: #define IFSTATECHANGE      16
 2571: #define VIRTIFSTATECHANGE   1
 2572: #define NBRSTATECHANGE      2
 2573: #define VIRTNBRSTATECHANGE  3
 2574: 
 2575: struct trap_object ospfNbrTrapList[] =
 2576: {
 2577:   {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
 2578:   {ospfNbrEntry, 3, {10, 1, OSPFNBRIPADDR}},
 2579:   {ospfNbrEntry, 3, {10, 1, OSPFNBRRTRID}},
 2580:   {ospfNbrEntry, 3, {10, 1, OSPFNBRSTATE}}
 2581: };
 2582: 
 2583: 
 2584: struct trap_object ospfVirtNbrTrapList[] =
 2585: {
 2586:   {ospfGeneralGroup, -2, {1, 1}},
 2587:   {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRAREA}},
 2588:   {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRRTRID}},
 2589:   {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRSTATE}}
 2590: };
 2591: 
 2592: struct trap_object ospfIfTrapList[] =
 2593: {
 2594:   {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
 2595:   {ospfIfEntry, 3, {7, 1, OSPFIFIPADDRESS}},
 2596:   {ospfIfEntry, 3, {7, 1, OSPFADDRESSLESSIF}},
 2597:   {ospfIfEntry, 3, {7, 1, OSPFIFSTATE}}
 2598: };
 2599: 
 2600: struct trap_object ospfVirtIfTrapList[] =
 2601: {
 2602:   {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
 2603:   {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFAREAID}},
 2604:   {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFNEIGHBOR}},
 2605:   {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFSTATE}}
 2606: };
 2607: 
 2608: void
 2609: ospfTrapNbrStateChange (struct ospf_neighbor *on)
 2610: {
 2611:   oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
 2612:   char msgbuf[16];
 2613:   
 2614:   ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf));
 2615:   zlog (NULL, LOG_INFO, "ospfTrapNbrStateChange trap sent: %s now %s",
 2616: 	inet_ntoa(on->address.u.prefix4), msgbuf);
 2617: 
 2618:   oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE);
 2619:   index[IN_ADDR_SIZE] = 0;
 2620: 
 2621:   smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
 2622:              index,  IN_ADDR_SIZE + 1,
 2623:              ospfNbrTrapList, 
 2624:              sizeof ospfNbrTrapList / sizeof (struct trap_object),
 2625:              time (NULL), NBRSTATECHANGE);
 2626: }
 2627: 
 2628: void
 2629: ospfTrapVirtNbrStateChange (struct ospf_neighbor *on)
 2630: {
 2631:   oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
 2632:   
 2633:   zlog (NULL, LOG_INFO, "ospfTrapVirtNbrStateChange trap sent");
 2634: 
 2635:   oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE);
 2636:   index[IN_ADDR_SIZE] = 0;
 2637: 
 2638:   smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
 2639:              index,  IN_ADDR_SIZE + 1,
 2640:              ospfVirtNbrTrapList, 
 2641:              sizeof ospfVirtNbrTrapList / sizeof (struct trap_object),
 2642:              time (NULL), VIRTNBRSTATECHANGE);
 2643: }
 2644: 
 2645: void
 2646: ospfTrapIfStateChange (struct ospf_interface *oi)
 2647: {
 2648:   oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
 2649: 
 2650:   zlog (NULL, LOG_INFO, "ospfTrapIfStateChange trap sent: %s now %s",
 2651:   	inet_ntoa(oi->address->u.prefix4),
 2652: 	LOOKUP(ospf_ism_state_msg, oi->state));
 2653:   
 2654:   oid_copy_addr (index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
 2655:   index[IN_ADDR_SIZE] = 0;
 2656: 
 2657:   smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
 2658:              index, IN_ADDR_SIZE + 1,
 2659:              ospfIfTrapList, 
 2660:              sizeof ospfIfTrapList / sizeof (struct trap_object),
 2661:              time (NULL), IFSTATECHANGE);
 2662: }
 2663: 
 2664: void
 2665: ospfTrapVirtIfStateChange (struct ospf_interface *oi)
 2666: {
 2667:   oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
 2668: 
 2669:   zlog (NULL, LOG_INFO, "ospfTrapVirtIfStateChange trap sent");
 2670:   
 2671:   oid_copy_addr (index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
 2672:   index[IN_ADDR_SIZE] = 0;
 2673: 
 2674:   smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
 2675:              index, IN_ADDR_SIZE + 1,
 2676:              ospfVirtIfTrapList,
 2677:              sizeof ospfVirtIfTrapList / sizeof (struct trap_object),
 2678:              time (NULL), VIRTIFSTATECHANGE);
 2679: }
 2680: /* Register OSPF2-MIB. */
 2681: void
 2682: ospf_snmp_init ()
 2683: {
 2684:   ospf_snmp_iflist = list_new ();
 2685:   ospf_snmp_vl_table = route_table_init ();
 2686:   smux_init (om->master);
 2687:   REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid);
 2688: }
 2689: #endif /* HAVE_SNMP */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>