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
ospf_admin_stat(struct ospf * ospf)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 *
ospfGeneralGroup(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospf_area_lookup_next(struct ospf * ospf,struct in_addr * area_id,int first)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 *
ospfAreaLookup(struct variable * v,oid name[],size_t * length,struct in_addr * addr,int exact)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 *
ospfAreaEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospf_stub_area_lookup_next(struct in_addr * area_id,int first)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 *
ospfStubAreaLookup(struct variable * v,oid name[],size_t * length,struct in_addr * addr,int exact)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 *
ospfStubAreaEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
lsdb_lookup_next(struct ospf_area * area,u_char * type,int type_next,struct in_addr * ls_id,int ls_id_next,struct in_addr * router_id,int router_id_next)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 *
ospfLsdbLookup(struct variable * v,oid * name,size_t * length,struct in_addr * area_id,u_char * type,struct in_addr * ls_id,struct in_addr * router_id,int exact)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 *
ospfLsdbEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospfAreaRangeLookup(struct variable * v,oid * name,size_t * length,struct in_addr * area_id,struct in_addr * range_net,int exact)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 *
ospfAreaRangeEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospfHostLookup(struct variable * v,oid * name,size_t * length,struct in_addr * addr,int exact)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 *
ospfHostEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospf_snmp_if_new(void)1421 ospf_snmp_if_new (void)
1422 {
1423   return XCALLOC (MTYPE_TMP, sizeof (struct ospf_snmp_if));
1424 }
1425 
1426 static void
ospf_snmp_if_free(struct ospf_snmp_if * osif)1427 ospf_snmp_if_free (struct ospf_snmp_if *osif)
1428 {
1429   XFREE (MTYPE_TMP, osif);
1430 }
1431 
1432 void
ospf_snmp_if_delete(struct interface * ifp)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
ospf_snmp_if_update(struct interface * ifp)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
ospf_snmp_is_if_have_addr(struct interface * ifp)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 *
ospf_snmp_if_lookup(struct in_addr * ifaddr,ifindex_t * ifindex)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 *
ospf_snmp_if_lookup_next(struct in_addr * ifaddr,ifindex_t * ifindex,int ifaddr_next,ifindex_t ifindex_next)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
ospf_snmp_iftype(struct interface * ifp)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 *
ospfIfLookup(struct variable * v,oid * name,size_t * length,struct in_addr * ifaddr,ifindex_t * ifindex,int exact)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 *
ospfIfEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospfIfMetricLookup(struct variable * v,oid * name,size_t * length,struct in_addr * ifaddr,ifindex_t * ifindex,int exact)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 *
ospfIfMetricEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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
ospf_snmp_vl_add(struct ospf_vl_data * vl_data)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
ospf_snmp_vl_delete(struct ospf_vl_data * vl_data)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 *
ospf_snmp_vl_lookup(struct in_addr * area_id,struct in_addr * neighbor)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 *
ospf_snmp_vl_lookup_next(struct in_addr * area_id,struct in_addr * neighbor,int first)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 *
ospfVirtIfLookup(struct variable * v,oid * name,size_t * length,struct in_addr * area_id,struct in_addr * neighbor,int exact)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 *
ospfVirtIfEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospf_snmp_nbr_lookup(struct ospf * ospf,struct in_addr * nbr_addr,ifindex_t * ifindex)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 *
ospf_snmp_nbr_lookup_next(struct in_addr * nbr_addr,ifindex_t * ifindex,int first)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 *
ospfNbrLookup(struct variable * v,oid * name,size_t * length,struct in_addr * nbr_addr,ifindex_t * ifindex,int exact)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
ospf_snmp_neighbor_state(u_char nst)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 *
ospfNbrEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospfVirtNbrEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospfExtLsdbLookup(struct variable * v,oid * name,size_t * length,u_char * type,struct in_addr * ls_id,struct in_addr * router_id,int exact)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 *
ospfExtLsdbEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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 *
ospfAreaAggregateEntry(struct variable * v,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)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
ospfTrapNbrStateChange(struct ospf_neighbor * on)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
ospfTrapVirtNbrStateChange(struct ospf_neighbor * on)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
ospfTrapIfStateChange(struct ospf_interface * oi)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
ospfTrapVirtIfStateChange(struct ospf_interface * oi)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
ospf_snmp_init()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 */
2744