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