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