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