Initial revision
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
new file mode 100644
index 0000000..6187977
--- /dev/null
+++ b/ospfd/ospf_snmp.c
@@ -0,0 +1,2443 @@
+/* OSPFv2 SNMP support
+ * Copyright (C) 2000 IP Infusion Inc.
+ *
+ * Written by Kunihiro Ishiguro <kunihiro@zebra.org>
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include <zebra.h>
+
+#ifdef HAVE_SNMP
+#include <asn1.h>
+#include <snmp.h>
+#include <snmp_impl.h>
+
+#include "if.h"
+#include "log.h"
+#include "prefix.h"
+#include "table.h"
+#include "command.h"
+#include "memory.h"
+#include "smux.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_flood.h"
+
+/* OSPF2-MIB. */
+#define OSPF2MIB 1,3,6,1,2,1,14
+
+/* Zebra enterprise OSPF MIB.  This variable is used for register
+   OSPF MIB to SNMP agent under SMUX protocol.  */
+#define OSPFDOID 1,3,6,1,4,1,3317,1,2,5
+
+/* OSPF MIB General Group values. */
+#define OSPFROUTERID                     1
+#define OSPFADMINSTAT                    2
+#define OSPFVERSIONNUMBER                3
+#define OSPFAREABDRRTRSTATUS             4
+#define OSPFASBDRRTRSTATUS               5
+#define OSPFEXTERNLSACOUNT               6
+#define OSPFEXTERNLSACKSUMSUM            7
+#define OSPFTOSSUPPORT                   8
+#define OSPFORIGINATENEWLSAS             9
+#define OSPFRXNEWLSAS                    10
+#define OSPFEXTLSDBLIMIT                 11
+#define OSPFMULTICASTEXTENSIONS          12
+#define OSPFEXITOVERFLOWINTERVAL         13
+#define OSPFDEMANDEXTENSIONS             14
+
+/* OSPF MIB ospfAreaTable. */
+#define OSPFAREAID                       1
+#define OSPFAUTHTYPE                     2
+#define OSPFIMPORTASEXTERN               3
+#define OSPFSPFRUNS                      4
+#define OSPFAREABDRRTRCOUNT              5
+#define OSPFASBDRRTRCOUNT                6
+#define OSPFAREALSACOUNT                 7
+#define OSPFAREALSACKSUMSUM              8
+#define OSPFAREASUMMARY                  9
+#define OSPFAREASTATUS                   10
+
+/* OSPF MIB ospfStubAreaTable. */
+#define OSPFSTUBAREAID                   1
+#define OSPFSTUBTOS                      2
+#define OSPFSTUBMETRIC                   3
+#define OSPFSTUBSTATUS                   4
+#define OSPFSTUBMETRICTYPE               5
+
+/* OSPF MIB ospfLsdbTable. */
+#define OSPFLSDBAREAID                   1
+#define OSPFLSDBTYPE                     2
+#define OSPFLSDBLSID                     3
+#define OSPFLSDBROUTERID                 4
+#define OSPFLSDBSEQUENCE                 5
+#define OSPFLSDBAGE                      6
+#define OSPFLSDBCHECKSUM                 7
+#define OSPFLSDBADVERTISEMENT            8
+
+/* OSPF MIB ospfAreaRangeTable. */
+#define OSPFAREARANGEAREAID              1
+#define OSPFAREARANGENET                 2
+#define OSPFAREARANGEMASK                3
+#define OSPFAREARANGESTATUS              4
+#define OSPFAREARANGEEFFECT              5
+
+/* OSPF MIB ospfHostTable. */
+#define OSPFHOSTIPADDRESS                1
+#define OSPFHOSTTOS                      2
+#define OSPFHOSTMETRIC                   3
+#define OSPFHOSTSTATUS                   4
+#define OSPFHOSTAREAID                   5
+
+/* OSPF MIB ospfIfTable. */
+#define OSPFIFIPADDRESS                  1
+#define OSPFADDRESSLESSIF                2
+#define OSPFIFAREAID                     3
+#define OSPFIFTYPE                       4
+#define OSPFIFADMINSTAT                  5
+#define OSPFIFRTRPRIORITY                6
+#define OSPFIFTRANSITDELAY               7
+#define OSPFIFRETRANSINTERVAL            8
+#define OSPFIFHELLOINTERVAL              9
+#define OSPFIFRTRDEADINTERVAL            10
+#define OSPFIFPOLLINTERVAL               11
+#define OSPFIFSTATE                      12
+#define OSPFIFDESIGNATEDROUTER           13
+#define OSPFIFBACKUPDESIGNATEDROUTER     14
+#define OSPFIFEVENTS                     15
+#define OSPFIFAUTHKEY                    16
+#define OSPFIFSTATUS                     17
+#define OSPFIFMULTICASTFORWARDING        18
+#define OSPFIFDEMAND                     19
+#define OSPFIFAUTHTYPE                   20
+
+/* OSPF MIB ospfIfMetricTable. */
+#define OSPFIFMETRICIPADDRESS            1
+#define OSPFIFMETRICADDRESSLESSIF        2
+#define OSPFIFMETRICTOS                  3
+#define OSPFIFMETRICVALUE                4
+#define OSPFIFMETRICSTATUS               5
+
+/* OSPF MIB ospfVirtIfTable. */
+#define OSPFVIRTIFAREAID                 1
+#define OSPFVIRTIFNEIGHBOR               2
+#define OSPFVIRTIFTRANSITDELAY           3
+#define OSPFVIRTIFRETRANSINTERVAL        4
+#define OSPFVIRTIFHELLOINTERVAL          5
+#define OSPFVIRTIFRTRDEADINTERVAL        6
+#define OSPFVIRTIFSTATE                  7
+#define OSPFVIRTIFEVENTS                 8
+#define OSPFVIRTIFAUTHKEY                9
+#define OSPFVIRTIFSTATUS                 10
+#define OSPFVIRTIFAUTHTYPE               11
+
+/* OSPF MIB ospfNbrTable. */
+#define OSPFNBRIPADDR                    1
+#define OSPFNBRADDRESSLESSINDEX          2
+#define OSPFNBRRTRID                     3
+#define OSPFNBROPTIONS                   4
+#define OSPFNBRPRIORITY                  5
+#define OSPFNBRSTATE                     6
+#define OSPFNBREVENTS                    7
+#define OSPFNBRLSRETRANSQLEN             8
+#define OSPFNBMANBRSTATUS                9
+#define OSPFNBMANBRPERMANENCE            10
+#define OSPFNBRHELLOSUPPRESSED           11
+
+/* OSPF MIB ospfVirtNbrTable. */
+#define OSPFVIRTNBRAREA                  1
+#define OSPFVIRTNBRRTRID                 2
+#define OSPFVIRTNBRIPADDR                3
+#define OSPFVIRTNBROPTIONS               4
+#define OSPFVIRTNBRSTATE                 5
+#define OSPFVIRTNBREVENTS                6
+#define OSPFVIRTNBRLSRETRANSQLEN         7
+#define OSPFVIRTNBRHELLOSUPPRESSED       8
+
+/* OSPF MIB ospfExtLsdbTable. */
+#define OSPFEXTLSDBTYPE                  1
+#define OSPFEXTLSDBLSID                  2
+#define OSPFEXTLSDBROUTERID              3
+#define OSPFEXTLSDBSEQUENCE              4
+#define OSPFEXTLSDBAGE                   5
+#define OSPFEXTLSDBCHECKSUM              6
+#define OSPFEXTLSDBADVERTISEMENT         7
+
+/* OSPF MIB ospfAreaAggregateTable. */
+#define OSPFAREAAGGREGATEAREAID          1
+#define OSPFAREAAGGREGATELSDBTYPE        2
+#define OSPFAREAAGGREGATENET             3
+#define OSPFAREAAGGREGATEMASK            4
+#define OSPFAREAAGGREGATESTATUS          5
+#define OSPFAREAAGGREGATEEFFECT          6
+
+/* SYNTAX Status from OSPF-MIB. */
+#define OSPF_STATUS_ENABLED  1
+#define OSPF_STATUS_DISABLED 2
+
+/* SNMP value hack. */
+#define COUNTER     ASN_COUNTER
+#define INTEGER     ASN_INTEGER
+#define GAUGE       ASN_GAUGE
+#define TIMETICKS   ASN_TIMETICKS
+#define IPADDRESS   ASN_IPADDRESS
+#define STRING      ASN_OCTET_STR
+
+/* Declare static local variables for convenience. */
+SNMP_LOCAL_VARIABLES
+
+/* OSPF-MIB instances. */
+oid ospf_oid [] = { OSPF2MIB };
+oid ospfd_oid [] = { OSPFDOID };
+
+/* IP address 0.0.0.0. */
+static struct in_addr ospf_empty_addr = {0};
+
+/* Hook functions. */
+static u_char *ospfGeneralGroup ();
+static u_char *ospfAreaEntry ();
+static u_char *ospfStubAreaEntry ();
+static u_char *ospfLsdbEntry ();
+static u_char *ospfAreaRangeEntry ();
+static u_char *ospfHostEntry ();
+static u_char *ospfIfEntry ();
+static u_char *ospfIfMetricEntry ();
+static u_char *ospfVirtIfEntry ();
+static u_char *ospfNbrEntry ();
+static u_char *ospfVirtNbrEntry ();
+static u_char *ospfExtLsdbEntry ();
+static u_char *ospfAreaAggregateEntry ();
+
+struct variable ospf_variables[] = 
+{
+  /* OSPF general variables */
+  {OSPFROUTERID,              IPADDRESS, RWRITE, ospfGeneralGroup,
+   2, {1, 1}},
+  {OSPFADMINSTAT,             INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 2}},
+  {OSPFVERSIONNUMBER,         INTEGER, RONLY, ospfGeneralGroup,
+   2, {1, 3}},
+  {OSPFAREABDRRTRSTATUS,      INTEGER, RONLY, ospfGeneralGroup,
+   2, {1, 4}},
+  {OSPFASBDRRTRSTATUS,        INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 5}},
+  {OSPFEXTERNLSACOUNT,        GAUGE, RONLY, ospfGeneralGroup,
+   2, {1, 6}},
+  {OSPFEXTERNLSACKSUMSUM,     INTEGER, RONLY, ospfGeneralGroup,
+   2, {1, 7}},
+  {OSPFTOSSUPPORT,            INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 8}},
+  {OSPFORIGINATENEWLSAS,      COUNTER, RONLY, ospfGeneralGroup,
+   2, {1, 9}},
+  {OSPFRXNEWLSAS,             COUNTER, RONLY, ospfGeneralGroup,
+   2, {1, 10}},
+  {OSPFEXTLSDBLIMIT,          INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 11}},
+  {OSPFMULTICASTEXTENSIONS,   INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 12}},
+  {OSPFEXITOVERFLOWINTERVAL,  INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 13}},
+  {OSPFDEMANDEXTENSIONS,      INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 14}},
+
+  /* OSPF area data structure. */
+  {OSPFAREAID,                IPADDRESS, RONLY, ospfAreaEntry,
+   3, {2, 1, 1}},
+  {OSPFAUTHTYPE,              INTEGER, RWRITE, ospfAreaEntry,
+   3, {2, 1, 2}},
+  {OSPFIMPORTASEXTERN,        INTEGER, RWRITE, ospfAreaEntry,
+   3, {2, 1, 3}},
+  {OSPFSPFRUNS,               COUNTER, RONLY, ospfAreaEntry,
+   3, {2, 1, 4}},
+  {OSPFAREABDRRTRCOUNT,       GAUGE, RONLY, ospfAreaEntry,
+   3, {2, 1, 5}},
+  {OSPFASBDRRTRCOUNT,         GAUGE, RONLY, ospfAreaEntry,
+   3, {2, 1, 6}},
+  {OSPFAREALSACOUNT,          GAUGE, RONLY, ospfAreaEntry,
+   3, {2, 1, 7}},
+  {OSPFAREALSACKSUMSUM,       INTEGER, RONLY, ospfAreaEntry,
+   3, {2, 1, 8}},
+  {OSPFAREASUMMARY,           INTEGER, RWRITE, ospfAreaEntry,
+   3, {2, 1, 9}},
+  {OSPFAREASTATUS,            INTEGER, RWRITE, ospfAreaEntry,
+   3, {2, 1, 10}},
+
+  /* OSPF stub area information. */
+  {OSPFSTUBAREAID,            IPADDRESS, RONLY, ospfStubAreaEntry,
+   3, {3, 1, 1}},
+  {OSPFSTUBTOS,               INTEGER, RONLY, ospfStubAreaEntry,
+   3, {3, 1, 2}},
+  {OSPFSTUBMETRIC,            INTEGER, RWRITE, ospfStubAreaEntry,
+   3, {3, 1, 3}},
+  {OSPFSTUBSTATUS,            INTEGER, RWRITE, ospfStubAreaEntry,
+   3, {3, 1, 4}},
+  {OSPFSTUBMETRICTYPE,        INTEGER, RWRITE, ospfStubAreaEntry,
+   3, {3, 1, 5}},
+
+  /* OSPF link state database. */
+  {OSPFLSDBAREAID,            IPADDRESS, RONLY, ospfLsdbEntry,
+   3, {4, 1, 1}},
+  {OSPFLSDBTYPE,              INTEGER, RONLY, ospfLsdbEntry,
+   3, {4, 1, 2}},
+  {OSPFLSDBLSID,              IPADDRESS, RONLY, ospfLsdbEntry,
+   3, {4, 1, 3}},
+  {OSPFLSDBROUTERID,          IPADDRESS, RONLY, ospfLsdbEntry,
+   3, {4, 1, 4}},
+  {OSPFLSDBSEQUENCE,          INTEGER, RONLY, ospfLsdbEntry,
+   3, {4, 1, 5}},
+  {OSPFLSDBAGE,               INTEGER, RONLY, ospfLsdbEntry,
+   3, {4, 1, 6}},
+  {OSPFLSDBCHECKSUM,          INTEGER, RONLY, ospfLsdbEntry,
+   3, {4, 1, 7}},
+  {OSPFLSDBADVERTISEMENT,     STRING, RONLY, ospfLsdbEntry,
+   3, {4, 1, 8}},
+
+  /* Area range table. */
+  {OSPFAREARANGEAREAID,       IPADDRESS, RONLY, ospfAreaRangeEntry,
+   3, {5, 1, 1}},
+  {OSPFAREARANGENET,          IPADDRESS, RONLY, ospfAreaRangeEntry,
+   3, {5, 1, 2}},
+  {OSPFAREARANGEMASK,         IPADDRESS, RWRITE, ospfAreaRangeEntry,
+   3, {5, 1, 3}},
+  {OSPFAREARANGESTATUS,       INTEGER, RWRITE, ospfAreaRangeEntry,
+   3, {5, 1, 4}},
+  {OSPFAREARANGEEFFECT,       INTEGER, RWRITE, ospfAreaRangeEntry,
+   3, {5, 1, 5}},
+
+  /* OSPF host table. */
+  {OSPFHOSTIPADDRESS,         IPADDRESS, RONLY, ospfHostEntry,
+   3, {6, 1, 1}},
+  {OSPFHOSTTOS,               INTEGER, RONLY, ospfHostEntry,
+   3, {6, 1, 2}},
+  {OSPFHOSTMETRIC,            INTEGER, RWRITE, ospfHostEntry,
+   3, {6, 1, 3}},
+  {OSPFHOSTSTATUS,            INTEGER, RWRITE, ospfHostEntry,
+   3, {6, 1, 4}},
+  {OSPFHOSTAREAID,            IPADDRESS, RONLY, ospfHostEntry,
+   3, {6, 1, 5}},
+
+  /* OSPF interface table. */
+  {OSPFIFIPADDRESS,           IPADDRESS, RONLY, ospfIfEntry,
+   3, {7, 1, 1}},
+  {OSPFADDRESSLESSIF,         INTEGER, RONLY, ospfIfEntry,
+   3, {7, 1, 2}},
+  {OSPFIFAREAID,              IPADDRESS, RWRITE, ospfIfEntry,
+   3, {7, 1, 3}},
+  {OSPFIFTYPE,                INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 4}},
+  {OSPFIFADMINSTAT,           INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 5}},
+  {OSPFIFRTRPRIORITY,         INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 6}},
+  {OSPFIFTRANSITDELAY,        INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 7}},
+  {OSPFIFRETRANSINTERVAL,     INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 8}},
+  {OSPFIFHELLOINTERVAL,       INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 9}},
+  {OSPFIFRTRDEADINTERVAL,     INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 10}},
+  {OSPFIFPOLLINTERVAL,        INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 11}},
+  {OSPFIFSTATE,               INTEGER, RONLY, ospfIfEntry,
+   3, {7, 1, 12}},
+  {OSPFIFDESIGNATEDROUTER,    IPADDRESS, RONLY, ospfIfEntry,
+   3, {7, 1, 13}},
+  {OSPFIFBACKUPDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry,
+   3, {7, 1, 14}},
+  {OSPFIFEVENTS,              COUNTER, RONLY, ospfIfEntry,
+   3, {7, 1, 15}},
+  {OSPFIFAUTHKEY,             STRING,  RWRITE, ospfIfEntry,
+   3, {7, 1, 16}},
+  {OSPFIFSTATUS,              INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 17}},
+  {OSPFIFMULTICASTFORWARDING, INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 18}},
+  {OSPFIFDEMAND,              INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 19}},
+  {OSPFIFAUTHTYPE,            INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 20}},
+
+  /* OSPF interface metric table. */
+  {OSPFIFMETRICIPADDRESS,     IPADDRESS, RONLY, ospfIfMetricEntry,
+   3, {8, 1, 1}},
+  {OSPFIFMETRICADDRESSLESSIF, INTEGER, RONLY, ospfIfMetricEntry,
+   3, {8, 1, 2}},
+  {OSPFIFMETRICTOS,           INTEGER, RONLY, ospfIfMetricEntry,
+   3, {8, 1, 3}},
+  {OSPFIFMETRICVALUE,         INTEGER, RWRITE, ospfIfMetricEntry,
+   3, {8, 1, 4}},
+  {OSPFIFMETRICSTATUS,        INTEGER, RWRITE, ospfIfMetricEntry,
+   3, {8, 1, 5}},
+
+  /* OSPF virtual interface table. */
+  {OSPFVIRTIFAREAID,          IPADDRESS, RONLY, ospfVirtIfEntry,
+   3, {9, 1, 1}},
+  {OSPFVIRTIFNEIGHBOR,        IPADDRESS, RONLY, ospfVirtIfEntry,
+   3, {9, 1, 2}},
+  {OSPFVIRTIFTRANSITDELAY,    INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 3}},
+  {OSPFVIRTIFRETRANSINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 4}},
+  {OSPFVIRTIFHELLOINTERVAL,   INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 5}},
+  {OSPFVIRTIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 6}},
+  {OSPFVIRTIFSTATE,           INTEGER, RONLY, ospfVirtIfEntry,
+   3, {9, 1, 7}},
+  {OSPFVIRTIFEVENTS,          COUNTER, RONLY, ospfVirtIfEntry,
+   3, {9, 1, 8}},
+  {OSPFVIRTIFAUTHKEY,         STRING,  RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 9}},
+  {OSPFVIRTIFSTATUS,          INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 10}},
+  {OSPFVIRTIFAUTHTYPE,        INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 11}},
+
+  /* OSPF neighbor table. */
+  {OSPFNBRIPADDR,             IPADDRESS, RONLY, ospfNbrEntry,
+   3, {10, 1, 1}},
+  {OSPFNBRADDRESSLESSINDEX,   INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 2}},
+  {OSPFNBRRTRID,              IPADDRESS, RONLY, ospfNbrEntry,
+   3, {10, 1, 3}},
+  {OSPFNBROPTIONS,            INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 4}},
+  {OSPFNBRPRIORITY,           INTEGER, RWRITE, ospfNbrEntry,
+   3, {10, 1, 5}},
+  {OSPFNBRSTATE,              INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 6}},
+  {OSPFNBREVENTS,             COUNTER, RONLY, ospfNbrEntry,
+   3, {10, 1, 7}},
+  {OSPFNBRLSRETRANSQLEN,      GAUGE, RONLY, ospfNbrEntry,
+   3, {10, 1, 8}},
+  {OSPFNBMANBRSTATUS,         INTEGER, RWRITE, ospfNbrEntry,
+   3, {10, 1, 9}},
+  {OSPFNBMANBRPERMANENCE,     INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 10}},
+  {OSPFNBRHELLOSUPPRESSED,    INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 11}},
+
+  /* OSPF virtual neighbor table. */
+  {OSPFVIRTNBRAREA,           IPADDRESS, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 1}},
+  {OSPFVIRTNBRRTRID,          IPADDRESS, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 2}},
+  {OSPFVIRTNBRIPADDR,         IPADDRESS, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 3}},
+  {OSPFVIRTNBROPTIONS,        INTEGER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 4}},
+  {OSPFVIRTNBRSTATE,          INTEGER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 5}},
+  {OSPFVIRTNBREVENTS,         COUNTER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 6}},
+  {OSPFVIRTNBRLSRETRANSQLEN,  INTEGER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 7}},
+  {OSPFVIRTNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 8}},
+
+  /* OSPF link state database, external. */
+  {OSPFEXTLSDBTYPE,           INTEGER, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 1}},
+  {OSPFEXTLSDBLSID,           IPADDRESS, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 2}},
+  {OSPFEXTLSDBROUTERID,       IPADDRESS, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 3}},
+  {OSPFEXTLSDBSEQUENCE,       INTEGER, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 4}},
+  {OSPFEXTLSDBAGE,            INTEGER, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 5}},
+  {OSPFEXTLSDBCHECKSUM,       INTEGER, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 6}},
+  {OSPFEXTLSDBADVERTISEMENT,  STRING,  RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 7}},
+
+  /* OSPF area aggregate table. */
+  {OSPFAREAAGGREGATEAREAID,   IPADDRESS, RONLY, ospfAreaAggregateEntry, 
+   3, {14, 1, 1}},
+  {OSPFAREAAGGREGATELSDBTYPE, INTEGER, RONLY, ospfAreaAggregateEntry, 
+   3, {14, 1, 2}},
+  {OSPFAREAAGGREGATENET,      IPADDRESS, RONLY, ospfAreaAggregateEntry, 
+   3, {14, 1, 3}},
+  {OSPFAREAAGGREGATEMASK,     IPADDRESS, RONLY, ospfAreaAggregateEntry, 
+   3, {14, 1, 4}},
+  {OSPFAREAAGGREGATESTATUS,   INTEGER, RWRITE, ospfAreaAggregateEntry,
+   3, {14, 1, 5}},
+  {OSPFAREAAGGREGATEEFFECT,   INTEGER, RWRITE, ospfAreaAggregateEntry,
+   3, {14, 1, 6}}
+};
+
+/* The administrative status of OSPF.  When OSPF is enbled on at least
+   one interface return 1. */
+int
+ospf_admin_stat ()
+{
+  listnode node;
+  struct ospf_interface *oi;
+
+  if (! ospf_top)
+    return 0;
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      oi = getdata (node);
+
+      if (oi && oi->address)
+	return 1;
+    }
+  return 0;
+}
+
+static u_char *
+ospfGeneralGroup (struct variable *v, oid *name, size_t *length,
+		  int exact, size_t *var_len, WriteMethod **write_method)
+{
+  /* Check whether the instance identifier is valid */
+  if (smux_header_generic (v, name, length, exact, var_len, write_method)
+      == MATCH_FAILED)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFROUTERID:		/* 1 */
+      /* Router-ID of this OSPF instance. */
+      if (ospf_top)
+	return SNMP_IPADDRESS (ospf_top->router_id);
+      else
+	return SNMP_IPADDRESS (ospf_empty_addr);
+      break;
+    case OSPFADMINSTAT:		/* 2 */
+      /* The administrative status of OSPF in the router. */
+      if (ospf_admin_stat ())
+	return SNMP_INTEGER (OSPF_STATUS_ENABLED);
+      else
+	return SNMP_INTEGER (OSPF_STATUS_DISABLED);
+      break;
+    case OSPFVERSIONNUMBER:	/* 3 */
+      /* OSPF version 2. */
+      return SNMP_INTEGER (OSPF_VERSION);
+      break;
+    case OSPFAREABDRRTRSTATUS:	/* 4 */
+      /* Area Border router status. */
+      if (ospf_top && CHECK_FLAG (ospf_top->flags, OSPF_FLAG_ABR))
+	return SNMP_INTEGER (SNMP_TRUE);
+      else
+	return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    case OSPFASBDRRTRSTATUS:	/* 5 */
+      /* AS Border router status. */
+      if (ospf_top && CHECK_FLAG (ospf_top->flags, OSPF_FLAG_ASBR))
+	return SNMP_INTEGER (SNMP_TRUE);
+      else
+	return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    case OSPFEXTERNLSACOUNT:	/* 6 */
+      /* External LSA counts. */
+      if (ospf_top)
+	return SNMP_INTEGER (ospf_lsdb_count_all (ospf_top->lsdb));
+      else
+	return SNMP_INTEGER (0);
+      break;
+    case OSPFEXTERNLSACKSUMSUM:	/* 7 */
+      /* External LSA checksum. */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFTOSSUPPORT:	/* 8 */
+      /* TOS is not supported. */
+      return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    case OSPFORIGINATENEWLSAS:	/* 9 */
+      /* The number of new link-state advertisements. */
+      if (ospf_top)
+	return SNMP_INTEGER (ospf_top->lsa_originate_count);
+      else
+	return SNMP_INTEGER (0);
+      break;
+    case OSPFRXNEWLSAS:		/* 10 */
+      /* The number of link-state advertisements received determined
+         to be new instantiations. */
+      if (ospf_top)
+	return SNMP_INTEGER (ospf_top->rx_lsa_count);
+      else
+	return SNMP_INTEGER (0);
+      break;
+    case OSPFEXTLSDBLIMIT:	/* 11 */
+      /* There is no limit for the number of non-default
+         AS-external-LSAs. */
+      return SNMP_INTEGER (-1);
+      break;
+    case OSPFMULTICASTEXTENSIONS: /* 12 */
+      /* Multicast Extensions to OSPF is not supported. */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFEXITOVERFLOWINTERVAL: /* 13 */
+      /* Overflow is not supported. */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFDEMANDEXTENSIONS:	/* 14 */
+      /* Demand routing is not supported. */
+      return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    default:
+      return NULL;
+    }
+  return NULL;
+}
+
+struct ospf_area *
+ospf_area_lookup_next (struct in_addr *area_id, int first)
+{
+  struct ospf_area *area;
+  listnode node;
+
+  if (! ospf_top)
+    return NULL;
+
+  if (first)
+    {
+      node = listhead (ospf_top->areas);
+      if (node)
+	{
+	  area = getdata (node);
+	  *area_id = area->area_id;
+	  return area;
+	}
+      return NULL;
+    }
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
+	{
+	  *area_id = area->area_id;
+	  return area;
+	}
+    }
+  return NULL;
+}
+
+struct ospf_area *
+ospfAreaLookup (struct variable *v, oid name[], size_t *length,
+		struct in_addr *addr, int exact)
+{
+  int len;
+  struct ospf_area *area;
+
+  if (! ospf_top)
+    return NULL;
+
+  if (exact)
+    {
+      /* Length is insufficient to lookup OSPF area. */
+      if (*length - v->namelen != sizeof (struct in_addr))
+	return NULL;
+
+      oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
+
+      area = ospf_area_lookup_by_area_id (*addr);
+
+      return area;
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len > 4)
+	len = 4;
+      
+      oid2in_addr (name + v->namelen, len, addr);
+
+      area = ospf_area_lookup_next (addr, len == 0 ? 1 : 0);
+
+      if (area == NULL)
+	return NULL;
+
+      oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
+      *length = sizeof (struct in_addr) + v->namelen;
+
+      return area;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfAreaEntry (struct variable *v, oid *name, size_t *length, int exact,
+	       size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_area *area;
+  struct in_addr addr;
+
+  memset (&addr, 0, sizeof (struct in_addr));
+
+  area = ospfAreaLookup (v, name, length, &addr, exact);
+  if (! area)
+    return NULL;
+  
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFAREAID:		/* 1 */
+      return SNMP_IPADDRESS (area->area_id);
+      break;
+    case OSPFAUTHTYPE:		/* 2 */
+      return SNMP_INTEGER (area->auth_type);
+      break;
+    case OSPFIMPORTASEXTERN:	/* 3 */
+      return SNMP_INTEGER (area->external_routing + 1);
+      break;
+    case OSPFSPFRUNS:		/* 4 */
+      return SNMP_INTEGER (area->spf_calculation);
+      break;
+    case OSPFAREABDRRTRCOUNT:	/* 5 */
+      return SNMP_INTEGER (area->abr_count);
+      break;
+    case OSPFASBDRRTRCOUNT:	/* 6 */
+      return SNMP_INTEGER (area->asbr_count);
+      break;
+    case OSPFAREALSACOUNT:	/* 7 */
+      return SNMP_INTEGER (area->lsdb->total);
+      break;
+    case OSPFAREALSACKSUMSUM:	/* 8 */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFAREASUMMARY:	/* 9 */
+#define OSPF_noAreaSummary   1
+#define OSPF_sendAreaSummary 2
+      if (area->no_summary)
+	return SNMP_INTEGER (OSPF_noAreaSummary);
+      else
+	return SNMP_INTEGER (OSPF_sendAreaSummary);
+      break;
+    case OSPFAREASTATUS:	/* 10 */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_area *
+ospf_stub_area_lookup_next (struct in_addr *area_id, int first)
+{
+  struct ospf_area *area;
+  listnode node;
+
+  if (! ospf_top)
+    return NULL;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (area->external_routing == OSPF_AREA_STUB)
+	{
+	  if (first)
+	    {
+	      *area_id = area->area_id;
+	      return area;
+	    }
+	  else if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
+	    {
+	      *area_id = area->area_id;
+	      return area;
+	    }
+	}
+    }
+  return NULL;
+}
+
+struct ospf_area *
+ospfStubAreaLookup (struct variable *v, oid name[], size_t *length,
+		    struct in_addr *addr, int exact)
+{
+  int len;
+  struct ospf_area *area;
+
+  if (! ospf_top)
+    return NULL;
+
+  /* Exact lookup. */
+  if (exact)
+    {
+      /* ospfStubAreaID + ospfStubTOS. */
+      if (*length != v->namelen + sizeof (struct in_addr) + 1)
+	return NULL;
+
+      /* Check ospfStubTOS is zero. */
+      if (name[*length - 1] != 0)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
+
+      area = ospf_area_lookup_by_area_id (*addr);
+
+      if (area->external_routing == OSPF_AREA_STUB)
+	return area;
+      else
+	return NULL;
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len > 4)
+	len = 4;
+      
+      oid2in_addr (name + v->namelen, len, addr);
+
+      area = ospf_stub_area_lookup_next (addr, len == 0 ? 1 : 0);
+
+      if (area == NULL)
+	return NULL;
+
+      oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
+      /* Set TOS 0. */
+      name[v->namelen + sizeof (struct in_addr)] = 0;
+      *length = v->namelen + sizeof (struct in_addr) + 1;
+
+      return area;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfStubAreaEntry (struct variable *v, oid *name, size_t *length,
+		   int exact, size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_area *area;
+  struct in_addr addr;
+
+  memset (&addr, 0, sizeof (struct in_addr));
+
+  area = ospfStubAreaLookup (v, name, length, &addr, exact);
+  if (! area)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFSTUBAREAID:	/* 1 */
+      /* OSPF stub area id. */
+      return SNMP_IPADDRESS (area->area_id);
+      break;
+    case OSPFSTUBTOS:		/* 2 */
+      /* TOS value is not supported. */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFSTUBMETRIC:	/* 3 */
+      /* Default cost to stub area. */
+      return SNMP_INTEGER (area->default_cost);
+      break;
+    case OSPFSTUBSTATUS:	/* 4 */
+      /* Status of the stub area. */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFSTUBMETRICTYPE:	/* 5 */
+      /* OSPF Metric type. */
+#define OSPF_ospfMetric     1
+#define OSPF_comparableCost 2
+#define OSPF_nonComparable  3
+      return SNMP_INTEGER (OSPF_ospfMetric);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_lsa *
+lsdb_lookup_next (struct ospf_area *area, u_char *type, int type_next,
+		  struct in_addr *ls_id, int ls_id_next,
+		  struct in_addr *router_id, int router_id_next)
+{
+  struct ospf_lsa *lsa;
+  int i;
+
+  if (type_next)
+    i = OSPF_MIN_LSA;
+  else
+    i = *type;
+
+  for (; i < OSPF_MAX_LSA; i++)
+    {
+      *type = i;
+
+      lsa = ospf_lsdb_lookup_by_id_next (area->lsdb, *type, *ls_id, *router_id,
+					ls_id_next);
+      if (lsa)
+	return lsa;
+
+      ls_id_next = 1;
+    }
+  return NULL;
+}
+
+struct ospf_lsa *
+ospfLsdbLookup (struct variable *v, oid *name, size_t *length,
+		struct in_addr *area_id, u_char *type,
+		struct in_addr *ls_id, struct in_addr *router_id, int exact)
+{
+  struct ospf_area *area;
+  struct ospf_lsa *lsa;
+  int len;
+  int type_next;
+  int ls_id_next;
+  int router_id_next;
+  oid *offset;
+  int offsetlen;
+
+#define OSPF_LSDB_ENTRY_OFFSET \
+          (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
+
+  if (exact)
+    {
+      /* Area ID + Type + LS ID + Router ID. */
+      if (*length - v->namelen != OSPF_LSDB_ENTRY_OFFSET)
+	return NULL;
+      
+      /* Set OID offset for Area ID. */
+      offset = name + v->namelen;
+
+      /* Lookup area first. */
+      oid2in_addr (offset, IN_ADDR_SIZE, area_id);
+      area = ospf_area_lookup_by_area_id (*area_id);
+      if (! area)
+	return NULL;
+      offset += IN_ADDR_SIZE;
+
+      /* Type. */
+      *type = *offset;
+      offset++;
+
+      /* LS ID. */
+      oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
+      offset += IN_ADDR_SIZE;
+
+      /* Router ID. */
+      oid2in_addr (offset, IN_ADDR_SIZE, router_id);
+
+      /* Lookup LSDB. */
+      return ospf_lsdb_lookup_by_id (area->lsdb, *type, *ls_id, *router_id);
+    }
+  else
+    {
+      /* Get variable length. */
+      offset = name + v->namelen;
+      offsetlen = *length - v->namelen;
+      len = offsetlen;
+
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (offset, len, area_id);
+
+      /* First we search area. */
+      if (len == IN_ADDR_SIZE)
+	area = ospf_area_lookup_by_area_id (*area_id);
+      else
+	area = ospf_area_lookup_next (area_id, len == 0 ? 1 : 0);
+
+      if (area == NULL)
+	return NULL;
+
+      do 
+	{
+	  /* Next we lookup type. */
+	  offset += IN_ADDR_SIZE;
+	  offsetlen -= IN_ADDR_SIZE;
+	  len = offsetlen;
+
+	  if (len <= 0)
+	    type_next = 1;
+	  else
+	    {
+	      len = 1;
+	      type_next = 0;
+	      *type = *offset;
+	    }
+	
+	  /* LS ID. */
+	  offset++;
+	  offsetlen--;
+	  len = offsetlen;
+
+	  if (len <= 0)
+	    ls_id_next = 1;
+	  else
+	    {
+	      ls_id_next = 0;
+	      if (len > IN_ADDR_SIZE)
+		len = IN_ADDR_SIZE;
+
+	      oid2in_addr (offset, len, ls_id);
+	    }
+
+	  /* Router ID. */
+	  offset += IN_ADDR_SIZE;
+	  offsetlen -= IN_ADDR_SIZE;
+	  len = offsetlen;
+
+	  if (len <= 0)
+	    router_id_next = 1;
+	  else
+	    {
+	      router_id_next = 0;
+	      if (len > IN_ADDR_SIZE)
+		len = IN_ADDR_SIZE;
+
+	      oid2in_addr (offset, len, router_id);
+	    }
+
+	  lsa = lsdb_lookup_next (area, type, type_next, ls_id, ls_id_next,
+				  router_id, router_id_next);
+
+	  if (lsa)
+	    {
+	      /* Fill in length. */
+	      *length = v->namelen + OSPF_LSDB_ENTRY_OFFSET;
+
+	      /* Fill in value. */
+	      offset = name + v->namelen;
+	      oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
+	      offset += IN_ADDR_SIZE;
+	      *offset = lsa->data->type;
+	      offset++;
+	      oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
+	      offset += IN_ADDR_SIZE;
+	      oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
+	    
+	      return lsa;
+	    }
+	}
+      while ((area = ospf_area_lookup_next (area_id, 0)) != NULL);
+    }
+  return NULL;
+}
+
+static u_char *
+ospfLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
+	       size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_lsa *lsa;
+  struct lsa_header *lsah;
+  struct in_addr area_id;
+  u_char type;
+  struct in_addr ls_id;
+  struct in_addr router_id;
+
+  /* INDEX { ospfLsdbAreaId, ospfLsdbType,
+     ospfLsdbLsid, ospfLsdbRouterId } */
+
+  memset (&area_id, 0, sizeof (struct in_addr));
+  type = 0;
+  memset (&ls_id, 0, sizeof (struct in_addr));
+  memset (&router_id, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  lsa = ospfLsdbLookup (v, name, length, &area_id, &type, &ls_id, &router_id,
+			exact);
+  if (! lsa)
+    return NULL;
+
+  lsah = lsa->data;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFLSDBAREAID:	/* 1 */
+      return SNMP_IPADDRESS (lsa->area->area_id);
+      break;
+    case OSPFLSDBTYPE:		/* 2 */
+      return SNMP_INTEGER (lsah->type);
+      break;
+    case OSPFLSDBLSID:		/* 3 */
+      return SNMP_IPADDRESS (lsah->id);
+      break;
+    case OSPFLSDBROUTERID:	/* 4 */
+      return SNMP_IPADDRESS (lsah->adv_router);
+      break;
+    case OSPFLSDBSEQUENCE:	/* 5 */
+      return SNMP_INTEGER (lsah->ls_seqnum);
+      break;
+    case OSPFLSDBAGE:		/* 6 */
+      return SNMP_INTEGER (lsah->ls_age);
+      break;
+    case OSPFLSDBCHECKSUM:	/* 7 */
+      return SNMP_INTEGER (lsah->checksum);
+      break;
+    case OSPFLSDBADVERTISEMENT:	/* 8 */
+      *var_len = ntohs (lsah->length);
+      return (u_char *) lsah;
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_area_range *
+ospfAreaRangeLookup (struct variable *v, oid *name, size_t *length,
+		     struct in_addr *area_id, struct in_addr *range_net,
+		     int exact)
+{
+  oid *offset;
+  int offsetlen;
+  int len;
+  struct ospf_area *area;
+  struct ospf_area_range *range;
+  struct prefix_ipv4 p;
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_BITLEN;
+
+  if (exact) 
+    {
+      /* Area ID + Range Network. */
+      if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length)
+	return NULL;
+
+      /* Set OID offset for Area ID. */
+      offset = name + v->namelen;
+
+      /* Lookup area first. */
+      oid2in_addr (offset, IN_ADDR_SIZE, area_id);
+
+      area = ospf_area_lookup_by_area_id (*area_id);
+      if (! area)
+	return NULL;
+
+      offset += IN_ADDR_SIZE;
+
+      /* Lookup area range. */
+      oid2in_addr (offset, IN_ADDR_SIZE, range_net);
+      p.prefix = *range_net;
+
+      return ospf_area_range_lookup (area, &p);
+    }
+  else
+    {
+      /* Set OID offset for Area ID. */
+      offset = name + v->namelen;
+      offsetlen = *length - v->namelen;
+
+      len = offsetlen;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (offset, len, area_id);
+
+      /* First we search area. */
+      if (len == IN_ADDR_SIZE)
+	area = ospf_area_lookup_by_area_id (*area_id);
+      else
+	area = ospf_area_lookup_next (area_id, len == 0 ? 1 : 0);
+
+      if (area == NULL)
+	return NULL;
+
+      do 
+	{
+	  offset += IN_ADDR_SIZE;
+	  offsetlen -= IN_ADDR_SIZE;
+	  len = offsetlen;
+
+	  if (len < 0)
+	    len = 0;
+	  if (len > IN_ADDR_SIZE)
+	    len = IN_ADDR_SIZE;
+
+	  oid2in_addr (offset, len, range_net);
+
+	  range = ospf_area_range_lookup_next (area, range_net,
+					       len == 0 ? 1 : 0);
+
+	  if (range)
+	    {
+	      /* Fill in length. */
+	      *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
+
+	      /* Fill in value. */
+	      offset = name + v->namelen;
+	      oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
+	      offset += IN_ADDR_SIZE;
+	      oid_copy_addr (offset, range_net, IN_ADDR_SIZE);
+
+	      return range;
+	    }
+	}
+      while ((area = ospf_area_lookup_next (area_id, 0)) != NULL);
+    }
+  return NULL;
+}
+
+static u_char *
+ospfAreaRangeEntry (struct variable *v, oid *name, size_t *length, int exact,
+		    size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_area_range *range;
+  struct in_addr area_id;
+  struct in_addr range_net;
+  struct in_addr mask;
+  
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  memset (&area_id, 0, IN_ADDR_SIZE);
+  memset (&range_net, 0, IN_ADDR_SIZE);
+
+  range = ospfAreaRangeLookup (v, name, length, &area_id, &range_net, exact);
+  if (! range)
+    return NULL;
+
+  /* Convert prefixlen to network mask format. */
+  masklen2ip (range->subst_masklen, &mask);
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFAREARANGEAREAID:	/* 1 */
+      return SNMP_IPADDRESS (area_id);
+      break;
+    case OSPFAREARANGENET:	/* 2 */
+      return SNMP_IPADDRESS (range_net);
+      break;
+    case OSPFAREARANGEMASK:	/* 3 */
+      return SNMP_IPADDRESS (mask);
+      break;
+    case OSPFAREARANGESTATUS:	/* 4 */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFAREARANGEEFFECT:	/* 5 */
+#define OSPF_advertiseMatching      1
+#define OSPF_doNotAdvertiseMatching 2
+      return SNMP_INTEGER (OSPF_advertiseMatching);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_nbr_nbma *
+ospfHostLookup (struct variable *v, oid *name, size_t *length,
+		struct in_addr *addr, int exact)
+{
+  int len;
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  if (! ospf_top)
+    return NULL;
+
+  if (exact)
+    {
+      /* INDEX { ospfHostIpAddress, ospfHostTOS } */
+      if (*length != v->namelen + IN_ADDR_SIZE + 1)
+	return NULL;
+
+      /* Check ospfHostTOS. */
+      if (name[*length - 1] != 0)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr);
+
+      nbr_nbma = ospf_nbr_nbma_lookup (ospf_top, *addr);
+
+      return nbr_nbma;
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len > 4)
+	len = 4;
+      
+      oid2in_addr (name + v->namelen, len, addr);
+
+      nbr_nbma = ospf_nbr_nbma_lookup_next (addr, len == 0 ? 1 : 0);
+
+      if (nbr_nbma == NULL)
+	return NULL;
+
+      oid_copy_addr (name + v->namelen, addr, IN_ADDR_SIZE);
+
+      /* Set TOS 0. */
+      name[v->namelen + IN_ADDR_SIZE] = 0;
+
+      *length = v->namelen + IN_ADDR_SIZE + 1;
+
+      return nbr_nbma;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfHostEntry (struct variable *v, oid *name, size_t *length, int exact,
+	       size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+  struct ospf_interface *oi;
+  struct in_addr addr;
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  memset (&addr, 0, sizeof (struct in_addr));
+
+  nbr_nbma = ospfHostLookup (v, name, length, &addr, exact);
+  if (nbr_nbma == NULL)
+    return NULL;
+
+  oi = nbr_nbma->oi;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFHOSTIPADDRESS:	/* 1 */
+      return SNMP_IPADDRESS (nbr_nbma->addr);
+      break;
+    case OSPFHOSTTOS:		/* 2 */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFHOSTMETRIC:	/* 3 */
+      if (oi)
+	return SNMP_INTEGER (oi->output_cost);
+      else
+	return SNMP_INTEGER (1);
+      break;
+    case OSPFHOSTSTATUS:	/* 4 */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFHOSTAREAID:	/* 5 */
+      if (oi && oi->area)
+	return SNMP_IPADDRESS (oi->area->area_id);
+      else
+	return SNMP_IPADDRESS (ospf_empty_addr);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct list *ospf_snmp_iflist;
+
+struct ospf_snmp_if
+{
+  struct in_addr addr;
+  unsigned int ifindex;
+  struct interface *ifp;
+};
+
+struct ospf_snmp_if *
+ospf_snmp_if_new ()
+{
+  struct ospf_snmp_if *osif;
+
+  osif = XMALLOC (0, sizeof (struct ospf_snmp_if));
+  memset (osif, 0, sizeof (struct ospf_snmp_if));
+  return osif;
+}
+
+void
+ospf_snmp_if_free (struct ospf_snmp_if *osif)
+{
+  XFREE (0, osif);
+}
+
+void
+ospf_snmp_if_delete (struct interface *ifp)
+{
+  struct listnode *nn;
+  struct ospf_snmp_if *osif;
+
+  LIST_LOOP (ospf_snmp_iflist, osif, nn)
+    {
+      if (osif->ifp == ifp)
+	{
+	  list_delete_node (ospf_snmp_iflist, nn);
+	  ospf_snmp_if_free (osif);
+	  return;
+	}
+    }
+}
+
+void
+ospf_snmp_if_update (struct interface *ifp)
+{
+  struct listnode *nn;
+  struct listnode *pn;
+  struct connected *ifc;
+  struct prefix *p;
+  struct ospf_snmp_if *osif;
+  struct in_addr *addr;
+  unsigned int ifindex;
+
+  ospf_snmp_if_delete (ifp);
+
+  p = NULL;
+  addr = NULL;
+  ifindex = 0;
+
+  /* Lookup first IPv4 address entry. */
+  LIST_LOOP (ifp->connected, ifc, nn)
+    {
+      if (if_is_pointopoint (ifp))
+	p = ifc->destination;
+      else
+	p = ifc->address;
+
+      if (p->family == AF_INET)
+	{
+	  addr = &p->u.prefix4;
+	  break;
+	}
+    }
+  if (! addr)
+    ifindex = ifp->ifindex;
+
+  /* Add interface to the list. */
+  pn = NULL;
+  LIST_LOOP (ospf_snmp_iflist, osif, nn)
+    {
+      if (addr)
+	{
+	  if (ntohl (osif->addr.s_addr) > ntohl (addr->s_addr))
+	    break;
+	}
+      else
+	{
+	  /* Unnumbered interface. */
+	  if (osif->addr.s_addr != 0 || osif->ifindex > ifindex)
+	    break;
+	}
+      pn = nn;
+    }
+
+  osif = ospf_snmp_if_new ();
+  if (addr)
+    osif->addr = *addr;
+  else
+    osif->ifindex = ifindex;
+  osif->ifp = ifp;
+
+  listnode_add_after (ospf_snmp_iflist, pn, osif);
+}
+
+struct interface *
+ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex)
+{
+  struct listnode *nn;
+  struct ospf_snmp_if *osif;
+
+  LIST_LOOP (ospf_snmp_iflist, osif, nn)
+    {  
+      if (ifaddr->s_addr)
+	{
+	  if (IPV4_ADDR_SAME (&osif->addr, ifaddr))
+	    return osif->ifp;
+	}
+      else
+	{
+	  if (osif->ifindex == *ifindex)
+	    return osif->ifp;
+	}
+    }
+  return NULL;
+}
+
+struct interface *
+ospf_snmp_if_lookup_next (struct in_addr *ifaddr, unsigned int *ifindex,
+			  int ifaddr_next, int ifindex_next)
+{
+  struct ospf_snmp_if *osif;
+  struct listnode *nn;
+
+  if (ifaddr_next)
+    {
+      nn = listhead (ospf_snmp_iflist);
+      if (nn)
+	{
+	  osif = getdata (nn);
+	  *ifaddr = osif->addr;
+	  *ifindex = osif->ifindex;
+	  return osif->ifp;
+	}
+      return NULL;
+    }
+
+  LIST_LOOP (ospf_snmp_iflist, osif, nn)
+    {
+      if (ifaddr->s_addr)
+	{
+	  if (ntohl (osif->addr.s_addr) > ntohl (ifaddr->s_addr))
+	    {
+	      *ifaddr = osif->addr;
+	      *ifindex = osif->ifindex;
+	      return osif->ifp;
+	    }
+	}
+      else
+	{
+	  if (osif->ifindex > *ifindex || osif->addr.s_addr)
+	    {
+	      *ifaddr = osif->addr;
+	      *ifindex = osif->ifindex;
+	      return osif->ifp;
+	    }
+	}
+    }
+  return NULL;
+}
+
+int
+ospf_snmp_iftype (struct interface *ifp)
+{
+#define ospf_snmp_iftype_broadcast         1
+#define ospf_snmp_iftype_nbma              2
+#define ospf_snmp_iftype_pointToPoint      3
+#define ospf_snmp_iftype_pointToMultipoint 5
+  if (if_is_broadcast (ifp))
+    return ospf_snmp_iftype_broadcast;
+  if (if_is_pointopoint (ifp))
+    return ospf_snmp_iftype_pointToPoint;
+  return ospf_snmp_iftype_broadcast;
+}
+
+struct interface *
+ospfIfLookup (struct variable *v, oid *name, size_t *length,
+	      struct in_addr *ifaddr, unsigned int *ifindex, int exact)
+{
+  int len;
+  int ifaddr_next = 0;
+  int ifindex_next = 0;
+  struct interface *ifp;
+  oid *offset;
+
+  if (exact)
+    {
+      if (*length != v->namelen + IN_ADDR_SIZE + 1)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
+      *ifindex = name[v->namelen + IN_ADDR_SIZE];
+
+      return ospf_snmp_if_lookup (ifaddr, ifindex);
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len >= IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+      if (len <= 0)
+	ifaddr_next = 1;
+
+      oid2in_addr (name + v->namelen, len, ifaddr);
+
+      len = *length - v->namelen - IN_ADDR_SIZE;
+      if (len >= 1)
+	len = 1;
+      else
+	ifindex_next = 1;
+
+      if (len == 1)
+	*ifindex = name[v->namelen + IN_ADDR_SIZE];
+
+      ifp = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
+				      ifindex_next);
+      if (ifp)
+	{
+	  *length = v->namelen + IN_ADDR_SIZE + 1;
+	  offset = name + v->namelen;
+	  oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
+	  offset += IN_ADDR_SIZE;
+	  *offset = *ifindex;
+	  return ifp;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact,
+	     size_t  *var_len, WriteMethod **write_method)
+{
+  struct interface *ifp;
+  unsigned int ifindex;
+  struct in_addr ifaddr;
+  struct ospf_interface *oi;
+
+  ifindex = 0;
+  memset (&ifaddr, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  ifp = ospfIfLookup (v, name, length, &ifaddr, &ifindex, exact);
+  if (ifp == NULL)
+    return NULL;
+
+  oi = ospf_if_lookup_by_local_addr (ifp, ifaddr);
+  if (oi == NULL)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFIFIPADDRESS:	/* 1 */
+      return SNMP_IPADDRESS (ifaddr);
+      break;
+    case OSPFADDRESSLESSIF:	/* 2 */
+      return SNMP_INTEGER (ifindex);
+      break;
+    case OSPFIFAREAID:		/* 3 */
+      if (oi->area)
+	return SNMP_IPADDRESS (oi->area->area_id);
+      else
+	return SNMP_IPADDRESS (ospf_empty_addr);
+      break;
+    case OSPFIFTYPE:		/* 4 */
+      return SNMP_INTEGER (ospf_snmp_iftype (ifp));
+      break;
+    case OSPFIFADMINSTAT:	/* 5 */
+      if (oi)
+	return SNMP_INTEGER (OSPF_STATUS_ENABLED);
+      else
+	return SNMP_INTEGER (OSPF_STATUS_DISABLED);
+      break;
+    case OSPFIFRTRPRIORITY:	/* 6 */
+      return SNMP_INTEGER (PRIORITY (oi));
+      break;
+    case OSPFIFTRANSITDELAY:	/* 7 */
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
+      break;
+    case OSPFIFRETRANSINTERVAL:	/* 8 */
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
+      break;
+    case OSPFIFHELLOINTERVAL:	/* 9 */
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
+      break;
+    case OSPFIFRTRDEADINTERVAL:	/* 10 */
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
+      break;
+    case OSPFIFPOLLINTERVAL:	/* 11 */
+      return SNMP_INTEGER (OSPF_POLL_INTERVAL_DEFAULT);
+      break;
+    case OSPFIFSTATE:		/* 12 */
+      return SNMP_INTEGER (oi->state);
+      break;
+    case OSPFIFDESIGNATEDROUTER: /* 13 */
+      return SNMP_IPADDRESS (DR (oi));
+      break;
+    case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */
+      return SNMP_IPADDRESS (BDR (oi));
+      break;
+    case OSPFIFEVENTS:		/* 15 */
+      return SNMP_INTEGER (oi->state_change);
+      break;
+    case OSPFIFAUTHKEY:		/* 16 */
+      *var_len = 0;
+      return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
+      break;
+    case OSPFIFSTATUS:		/* 17 */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFIFMULTICASTFORWARDING: /* 18 */
+#define ospf_snmp_multiforward_blocked    1
+#define ospf_snmp_multiforward_multicast  2
+#define ospf_snmp_multiforward_unicast    3
+      return SNMP_INTEGER (ospf_snmp_multiforward_blocked);
+      break;
+    case OSPFIFDEMAND:		/* 19 */
+      return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    case OSPFIFAUTHTYPE:	/* 20 */
+      if (oi->area)
+	return SNMP_INTEGER (oi->area->auth_type);
+      else
+	return SNMP_INTEGER (0);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+#define OSPF_SNMP_METRIC_VALUE 1
+
+struct interface *
+ospfIfMetricLookup (struct variable *v, oid *name, size_t *length,
+		    struct in_addr *ifaddr, unsigned int *ifindex, int exact)
+{
+  int len;
+  int ifaddr_next = 0;
+  int ifindex_next = 0;
+  struct interface *ifp;
+  oid *offset;
+  int metric;
+
+  if (exact)
+    {
+      if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
+      *ifindex = name[v->namelen + IN_ADDR_SIZE];
+      metric = name[v->namelen + IN_ADDR_SIZE + 1];
+
+      if (metric != OSPF_SNMP_METRIC_VALUE)
+	return NULL;
+
+      return ospf_snmp_if_lookup (ifaddr, ifindex);
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len >= IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+      else
+	ifaddr_next = 1;
+
+      oid2in_addr (name + v->namelen, len, ifaddr);
+
+      len = *length - v->namelen - IN_ADDR_SIZE;
+      if (len >= 1)
+	len = 1;
+      else
+	ifindex_next = 1;
+
+      if (len == 1)
+	*ifindex = name[v->namelen + IN_ADDR_SIZE];
+
+      ifp = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
+				      ifindex_next);
+      if (ifp)
+	{
+	  *length = v->namelen + IN_ADDR_SIZE + 1 + 1;
+	  offset = name + v->namelen;
+	  oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
+	  offset += IN_ADDR_SIZE;
+	  *offset = *ifindex;
+	  offset++;
+	  *offset = OSPF_SNMP_METRIC_VALUE;
+	  return ifp;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact,
+		   size_t *var_len, WriteMethod **write_method)
+{
+  /* Currently we support metric 1 only. */
+  struct interface *ifp;
+  unsigned int ifindex;
+  struct in_addr ifaddr;
+  struct ospf_interface *oi;
+
+  ifindex = 0;
+  memset (&ifaddr, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  ifp = ospfIfMetricLookup (v, name, length, &ifaddr, &ifindex, exact);
+  if (ifp == NULL)
+    return NULL;
+
+  oi = ospf_if_lookup_by_local_addr (ifp, ifaddr);
+  if (oi == NULL)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFIFMETRICIPADDRESS:
+      return SNMP_IPADDRESS (ifaddr);
+      break;
+    case OSPFIFMETRICADDRESSLESSIF:
+      return SNMP_INTEGER (ifindex);
+      break;
+    case OSPFIFMETRICTOS:
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFIFMETRICVALUE:
+      return SNMP_INTEGER (OSPF_SNMP_METRIC_VALUE);
+      break;
+    case OSPFIFMETRICSTATUS:
+      return SNMP_INTEGER (1);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct route_table *ospf_snmp_vl_table;
+
+void
+ospf_snmp_vl_add (struct ospf_vl_data *vl_data)
+{
+  struct prefix_ls lp;
+  struct route_node *rn;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = vl_data->vl_area_id;
+  lp.adv_router = vl_data->vl_peer;
+
+  rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
+  rn->info = vl_data;
+}
+
+void
+ospf_snmp_vl_delete (struct ospf_vl_data *vl_data)
+{
+  struct prefix_ls lp;
+  struct route_node *rn;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = vl_data->vl_area_id;
+  lp.adv_router = vl_data->vl_peer;
+
+  rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
+  if (! rn)
+    return;
+  rn->info = NULL;
+  route_unlock_node (rn);
+  route_unlock_node (rn);
+}
+
+struct ospf_vl_data *
+ospf_snmp_vl_lookup (struct in_addr *area_id, struct in_addr *neighbor)
+{
+  struct prefix_ls lp;
+  struct route_node *rn;
+  struct ospf_vl_data *vl_data;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = *area_id;
+  lp.adv_router = *neighbor;
+
+  rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
+  if (rn)
+    {
+      vl_data = rn->info;
+      route_unlock_node (rn);
+      return vl_data;
+    }
+  return NULL;
+}
+
+struct ospf_vl_data *
+ospf_snmp_vl_lookup_next (struct in_addr *area_id, struct in_addr *neighbor,
+			  int first)
+{
+  struct prefix_ls lp;
+  struct route_node *rn;
+  struct ospf_vl_data *vl_data;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = *area_id;
+  lp.adv_router = *neighbor;
+
+  if (first)
+    rn = route_top (ospf_snmp_vl_table);
+  else
+    {
+      rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
+      rn = route_next (rn);
+    }
+
+  for (; rn; rn = route_next (rn))
+    if (rn->info)
+      break;
+
+  if (rn && rn->info)
+    {
+      vl_data = rn->info;
+      *area_id = vl_data->vl_area_id;
+      *neighbor = vl_data->vl_peer;
+      route_unlock_node (rn);
+      return vl_data;
+    }
+  return NULL;
+}
+
+struct ospf_vl_data *
+ospfVirtIfLookup (struct variable *v, oid *name, size_t *length,
+		  struct in_addr *area_id, struct in_addr *neighbor, int exact)
+{
+  int first;
+  int len;
+  struct ospf_vl_data *vl_data;
+
+  if (exact)
+    {
+      if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, area_id);
+      oid2in_addr (name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE, neighbor);
+
+      return ospf_snmp_vl_lookup (area_id, neighbor);
+    }
+  else
+    {
+      first = 0;
+
+      len = *length - v->namelen;
+      if (len <= 0)
+	first = 1;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+      oid2in_addr (name + v->namelen, len, area_id);
+
+      len = *length - v->namelen - IN_ADDR_SIZE;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+      oid2in_addr (name + v->namelen + IN_ADDR_SIZE, len, neighbor);
+
+      vl_data = ospf_snmp_vl_lookup_next (area_id, neighbor, first);
+
+      if (vl_data)
+	{
+	  *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
+	  oid_copy_addr (name + v->namelen, area_id, IN_ADDR_SIZE);
+	  oid_copy_addr (name + v->namelen + IN_ADDR_SIZE, neighbor,
+			 IN_ADDR_SIZE);
+	  return vl_data;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfVirtIfEntry (struct variable *v, oid *name, size_t *length, int exact,
+		 size_t  *var_len, WriteMethod **write_method)
+{
+  struct ospf_vl_data *vl_data;
+  struct ospf_interface *oi;
+  struct in_addr area_id;
+  struct in_addr neighbor;
+
+  memset (&area_id, 0, sizeof (struct in_addr));
+  memset (&neighbor, 0, sizeof (struct in_addr));
+
+  vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
+  if (! vl_data)
+    return NULL;
+  oi = vl_data->vl_oi;
+  if (! oi)
+    return NULL;
+  
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFVIRTIFAREAID:
+      return SNMP_IPADDRESS (area_id);
+      break;
+    case OSPFVIRTIFNEIGHBOR:
+      return SNMP_IPADDRESS (neighbor);
+      break;
+    case OSPFVIRTIFTRANSITDELAY:
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
+      break;
+    case OSPFVIRTIFRETRANSINTERVAL:
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
+      break;
+    case OSPFVIRTIFHELLOINTERVAL:
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
+      break;
+    case OSPFVIRTIFRTRDEADINTERVAL:
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
+      break;
+    case OSPFVIRTIFSTATE:
+      return SNMP_INTEGER (oi->state);
+      break;
+    case OSPFVIRTIFEVENTS:
+      return SNMP_INTEGER (oi->state_change);
+      break;
+    case OSPFVIRTIFAUTHKEY:
+      *var_len = 0;
+      return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
+      break;
+    case OSPFVIRTIFSTATUS:
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFVIRTIFAUTHTYPE:
+      if (oi->area)
+	return SNMP_INTEGER (oi->area->auth_type);
+      else
+	return SNMP_INTEGER (0);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_neighbor *
+ospf_snmp_nbr_lookup (struct in_addr *nbr_addr, unsigned int *ifindex)
+{
+  struct listnode *nn;
+  struct ospf_interface *oi;
+  struct ospf_neighbor *nbr;
+  struct route_node *rn;
+
+  LIST_LOOP (ospf_top->oiflist, oi, nn)
+    {
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info) != NULL
+	    && nbr != oi->nbr_self
+	    && nbr->state != NSM_Down
+	    && nbr->src.s_addr != 0)
+	  {
+	    if (IPV4_ADDR_SAME (&nbr->src, nbr_addr))
+	      {
+		route_unlock_node (rn);
+		return nbr;
+	      }
+	  }
+    }
+  return NULL;
+}
+
+struct ospf_neighbor *
+ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex,
+			   int first)
+{
+  struct listnode *nn;
+  struct ospf_interface *oi;
+  struct ospf_neighbor *nbr;
+  struct route_node *rn;
+  struct ospf_neighbor *min = NULL;
+
+  LIST_LOOP (ospf_top->oiflist, oi, nn)
+    {
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info) != NULL
+	    && nbr != oi->nbr_self
+	    && nbr->state != NSM_Down
+	    && nbr->src.s_addr != 0)
+	  {
+	    if (first)
+	      {
+		if (! min)
+		  min = nbr;
+		else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
+		  min = nbr;
+	      }
+	    else if (ntohl (nbr->src.s_addr) > ntohl (nbr_addr->s_addr))
+	      {
+		if (! min)
+		  min = nbr;
+		else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
+		  min = nbr;
+	      }
+	  }
+    }
+  if (min)
+    {
+      *nbr_addr = min->src;
+      *ifindex = 0;
+      return min;
+    }
+  return NULL;
+}
+
+struct ospf_neighbor *
+ospfNbrLookup (struct variable *v, oid *name, size_t *length,
+	       struct in_addr *nbr_addr, unsigned int *ifindex, int exact)
+{
+  int len;
+  int first;
+  struct ospf_neighbor *nbr;
+
+  if (exact)
+    {
+      if (*length != v->namelen + IN_ADDR_SIZE + 1)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, nbr_addr);
+      *ifindex = name[v->namelen + IN_ADDR_SIZE];
+
+      return ospf_snmp_nbr_lookup (nbr_addr, ifindex);
+    }
+  else
+    {
+      first = 0;
+      len = *length - v->namelen;
+
+      if (len <= 0)
+	first = 1;
+
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (name + v->namelen, len, nbr_addr);
+
+      len = *length - v->namelen - IN_ADDR_SIZE;
+      if (len >= 1)
+	*ifindex = name[v->namelen + IN_ADDR_SIZE];
+      
+      nbr = ospf_snmp_nbr_lookup_next (nbr_addr, ifindex, first);
+
+      if (nbr)
+	{
+	  *length = v->namelen + IN_ADDR_SIZE + 1;
+	  oid_copy_addr (name + v->namelen, nbr_addr, IN_ADDR_SIZE);
+	  name[v->namelen + IN_ADDR_SIZE] = *ifindex;
+	  return nbr;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
+	      size_t  *var_len, WriteMethod **write_method)
+{
+  struct in_addr nbr_addr;
+  unsigned int ifindex;
+  struct ospf_neighbor *nbr;
+  struct ospf_interface *oi;
+
+  memset (&nbr_addr, 0, sizeof (struct in_addr));
+  ifindex = 0;
+  
+  nbr = ospfNbrLookup (v, name, length, &nbr_addr, &ifindex, exact);
+  if (! nbr)
+    return NULL;
+  oi = nbr->oi;
+  if (! oi)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFNBRIPADDR:
+      return SNMP_IPADDRESS (nbr_addr);
+      break;
+    case OSPFNBRADDRESSLESSINDEX:
+      return SNMP_INTEGER (ifindex);
+      break;
+    case OSPFNBRRTRID:
+      return SNMP_IPADDRESS (nbr->router_id);
+      break;
+    case OSPFNBROPTIONS:
+      return SNMP_INTEGER (oi->nbr_self->options);
+      break;
+    case OSPFNBRPRIORITY:
+      return SNMP_INTEGER (nbr->priority);
+      break;
+    case OSPFNBRSTATE:
+      return SNMP_INTEGER (nbr->state);
+      break;
+    case OSPFNBREVENTS:
+      return SNMP_INTEGER (nbr->state_change);
+      break;
+    case OSPFNBRLSRETRANSQLEN:
+      return SNMP_INTEGER (ospf_ls_retransmit_count (nbr));
+      break;
+    case OSPFNBMANBRSTATUS:
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFNBMANBRPERMANENCE:
+      return SNMP_INTEGER (2);
+      break;
+    case OSPFNBRHELLOSUPPRESSED:
+      return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfVirtNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
+		  size_t  *var_len, WriteMethod **write_method)
+{
+  struct ospf_vl_data *vl_data;
+  struct in_addr area_id;
+  struct in_addr neighbor;
+
+  memset (&area_id, 0, sizeof (struct in_addr));
+  memset (&neighbor, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
+  if (! vl_data)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFVIRTNBRAREA:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRRTRID:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRIPADDR:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBROPTIONS:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRSTATE:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBREVENTS:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRLSRETRANSQLEN:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRHELLOSUPPRESSED:
+      return (u_char *) NULL;
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_lsa *
+ospfExtLsdbLookup (struct variable *v, oid *name, size_t *length, u_char *type,
+		   struct in_addr *ls_id, struct in_addr *router_id, int exact)
+{
+  int first;
+  oid *offset;
+  int offsetlen;
+  u_char lsa_type;
+  int len;
+  struct ospf_lsa *lsa;
+
+  if (exact)
+    {
+      if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
+	return NULL;
+      
+      offset = name + v->namelen;
+
+      /* Make it sure given value match to type. */
+      lsa_type = *offset;
+      offset++;
+
+      if (lsa_type != *type)
+	return NULL;
+      
+      /* LS ID. */
+      oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
+      offset += IN_ADDR_SIZE;
+
+      /* Router ID. */
+      oid2in_addr (offset, IN_ADDR_SIZE, router_id);
+
+      return ospf_lsdb_lookup_by_id (ospf_top->lsdb, *type, *ls_id, *router_id);
+    }
+  else
+    {
+      /* Get variable length. */
+      first = 0;
+      offset = name + v->namelen;
+      offsetlen = *length - v->namelen;
+
+      /* LSA type value. */
+      lsa_type = *offset;
+      offset++;
+      offsetlen--;
+
+      if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA)
+	first = 1;
+
+      /* LS ID. */
+      len = offsetlen;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (offset, len, ls_id);
+
+      offset += IN_ADDR_SIZE;
+      offsetlen -= IN_ADDR_SIZE;
+
+      /* Router ID. */
+      len = offsetlen;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (offset, len, router_id);
+
+      lsa = ospf_lsdb_lookup_by_id_next (ospf_top->lsdb, *type, *ls_id,
+					*router_id, first);
+
+      if (lsa)
+	{
+	  /* Fill in length. */
+	  *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE;
+
+	  /* Fill in value. */
+	  offset = name + v->namelen;
+
+	  *offset = OSPF_AS_EXTERNAL_LSA;
+	  offset++;
+	  oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
+	  offset += IN_ADDR_SIZE;
+	  oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
+	    
+	  return lsa;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfExtLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
+		  size_t  *var_len, WriteMethod **write_method)
+{
+  struct ospf_lsa *lsa;
+  struct lsa_header *lsah;
+  u_char type;
+  struct in_addr ls_id;
+  struct in_addr router_id;
+
+  type = OSPF_AS_EXTERNAL_LSA;
+  memset (&ls_id, 0, sizeof (struct in_addr));
+  memset (&router_id, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  lsa = ospfExtLsdbLookup (v, name, length, &type, &ls_id, &router_id, exact);
+  if (! lsa)
+    return NULL;
+
+  lsah = lsa->data;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFEXTLSDBTYPE:
+      return SNMP_INTEGER (OSPF_AS_EXTERNAL_LSA);
+      break;
+    case OSPFEXTLSDBLSID:
+      return SNMP_IPADDRESS (lsah->id);
+      break;
+    case OSPFEXTLSDBROUTERID:
+      return SNMP_IPADDRESS (lsah->adv_router);
+      break;
+    case OSPFEXTLSDBSEQUENCE:
+      return SNMP_INTEGER (lsah->ls_seqnum);
+      break;
+    case OSPFEXTLSDBAGE:
+      return SNMP_INTEGER (lsah->ls_age);
+      break;
+    case OSPFEXTLSDBCHECKSUM:
+      return SNMP_INTEGER (lsah->checksum);
+      break;
+    case OSPFEXTLSDBADVERTISEMENT:
+      *var_len = ntohs (lsah->length);
+      return (u_char *) lsah;
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length,
+			int exact, size_t *var_len, WriteMethod **write_method)
+{
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFAREAAGGREGATEAREAID:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATELSDBTYPE:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATENET:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATEMASK:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATESTATUS:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATEEFFECT:
+      return (u_char *) NULL;
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+/* Register OSPF2-MIB. */
+void
+ospf_snmp_init ()
+{
+  ospf_snmp_iflist = list_new ();
+  ospf_snmp_vl_table = route_table_init ();
+  smux_init (ospfd_oid, sizeof (ospfd_oid) / sizeof (oid));
+  REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid);
+  smux_start ();
+}
+#endif /* HAVE_SNMP */