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