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. */
209SNMP_LOCAL_VARIABLES
210
211/* OSPF-MIB instances. */
212oid ospf_oid [] = { OSPF2MIB };
213oid ospf_trap_oid [] = { OSPF2MIB, 16, 2 }; /* Not reverse mappable! */
214
215/* IP address 0.0.0.0. */
216static struct in_addr ospf_empty_addr = {0};
217
218/* Hook functions. */
219static u_char *ospfGeneralGroup (struct variable *, oid *, size_t *,
220				 int, size_t *, WriteMethod **);
221static u_char *ospfAreaEntry (struct variable *, oid *, size_t *, int,
222			      size_t *, WriteMethod **);
223static u_char *ospfStubAreaEntry (struct variable *, oid *, size_t *,
224				  int, size_t *, WriteMethod **);
225static u_char *ospfLsdbEntry (struct variable *, oid *, size_t *, int,
226			      size_t *, WriteMethod **);
227static u_char *ospfAreaRangeEntry (struct variable *, oid *, size_t *, int,
228				   size_t *, WriteMethod **);
229static u_char *ospfHostEntry (struct variable *, oid *, size_t *, int,
230			      size_t *, WriteMethod **);
231static u_char *ospfIfEntry (struct variable *, oid *, size_t *, int,
232			    size_t *, WriteMethod **);
233static u_char *ospfIfMetricEntry (struct variable *, oid *, size_t *, int,
234				  size_t *, WriteMethod **);
235static u_char *ospfVirtIfEntry (struct variable *, oid *, size_t *, int,
236				size_t *, WriteMethod **);
237static u_char *ospfNbrEntry (struct variable *, oid *, size_t *, int,
238			     size_t *, WriteMethod **);
239static u_char *ospfVirtNbrEntry (struct variable *, oid *, size_t *, int,
240				 size_t *, WriteMethod **);
241static u_char *ospfExtLsdbEntry (struct variable *, oid *, size_t *, int,
242				 size_t *, WriteMethod **);
243static u_char *ospfAreaAggregateEntry (struct variable *, oid *, size_t *,
244				       int, size_t *, WriteMethod **);
245
246struct 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. */
507static int
508ospf_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
523static u_char *
524ospfGeneralGroup (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
624static struct ospf_area *
625ospf_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
655static struct ospf_area *
656ospfAreaLookup (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
700static u_char *
701ospfAreaEntry (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
762static struct ospf_area *
763ospf_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
792static struct ospf_area *
793ospfStubAreaLookup (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
847static u_char *
848ospfStubAreaEntry (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
897static struct ospf_lsa *
898lsdb_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
932static struct ospf_lsa *
933ospfLsdbLookup (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
1077static u_char *
1078ospfLsdbEntry (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
1148static struct ospf_area_range *
1149ospfAreaRangeLookup (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
1245static u_char *
1246ospfAreaRangeEntry (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
1301static struct ospf_nbr_nbma *
1302ospfHostLookup (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
1354static u_char *
1355ospfHostEntry (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
1411struct list *ospf_snmp_iflist;
1412
1413struct ospf_snmp_if
1414{
1415  struct in_addr addr;
1416  unsigned int ifindex;
1417  struct interface *ifp;
1418};
1419
1420static struct ospf_snmp_if *
1421ospf_snmp_if_new (void)
1422{
1423  return XCALLOC (0, sizeof (struct ospf_snmp_if));
1424}
1425
1426static void
1427ospf_snmp_if_free (struct ospf_snmp_if *osif)
1428{
1429  XFREE (0, osif);
1430}
1431
1432void
1433ospf_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
1449void
1450ospf_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
1516static int
1517ospf_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
1532static struct ospf_interface *
1533ospf_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
1556static struct ospf_interface *
1557ospf_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
1625static int
1626ospf_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
1639static struct ospf_interface *
1640ospfIfLookup (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
1693static u_char *
1694ospfIfEntry (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
1803static struct ospf_interface *
1804ospfIfMetricLookup (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
1864static u_char *
1865ospfIfMetricEntry (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
1915struct route_table *ospf_snmp_vl_table;
1916
1917void
1918ospf_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
1933void
1934ospf_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
1953static struct ospf_vl_data *
1954ospf_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
1976static struct ospf_vl_data *
1977ospf_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
2013static struct ospf_vl_data *
2014ospfVirtIfLookup (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
2061static u_char *
2062ospfVirtIfEntry (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
2131static struct ospf_neighbor *
2132ospf_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
2160static struct ospf_neighbor *
2161ospf_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
2206static struct ospf_neighbor *
2207ospfNbrLookup (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
2262ospfNbrState 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*/
2274static int32_t
2275ospf_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
2298static u_char *
2299ospfNbrEntry (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
2364static u_char *
2365ospfVirtNbrEntry (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
2423static struct ospf_lsa *
2424ospfExtLsdbLookup (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
2514static u_char *
2515ospfExtLsdbEntry (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
2576static u_char *
2577ospfAreaAggregateEntry (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
2618struct 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
2627struct 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
2635struct 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
2643struct 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
2651void
2652ospfTrapNbrStateChange (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
2673void
2674ospfTrapVirtNbrStateChange (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
2692void
2693ospfTrapIfStateChange (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
2713void
2714ospfTrapVirtIfStateChange (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. */
2732void
2733ospf_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 */
2741