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