File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospfd / ospf_snmp.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:40 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

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

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