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