]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_snmp.c
isisd: gracefully handle spf error
[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_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_addr(name + v->namelen, addr, sizeof(struct in_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_addr(name + v->namelen, addr, sizeof(struct in_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_addr(offset, area_id, IN_ADDR_SIZE);
1012 offset += IN_ADDR_SIZE;
1013 *offset = lsa->data->type;
1014 offset++;
1015 oid_copy_addr(offset, &lsa->data->id,
1016 IN_ADDR_SIZE);
1017 offset += IN_ADDR_SIZE;
1018 oid_copy_addr(offset, &lsa->data->adv_router,
1019 IN_ADDR_SIZE);
1020
1021 return lsa;
1022 }
1023 } while ((area = ospf_area_lookup_next(ospf, area_id, 0))
1024 != NULL);
1025 }
1026 return NULL;
1027 }
1028
1029 static uint8_t *ospfLsdbEntry(struct variable *v, oid *name, size_t *length,
1030 int exact, size_t *var_len,
1031 WriteMethod **write_method)
1032 {
1033 struct ospf_lsa *lsa;
1034 struct lsa_header *lsah;
1035 struct in_addr area_id;
1036 uint8_t type;
1037 struct in_addr ls_id;
1038 struct in_addr router_id;
1039 struct ospf *ospf;
1040
1041 if (smux_header_table(v, name, length, exact, var_len, write_method)
1042 == MATCH_FAILED)
1043 return NULL;
1044
1045 /* INDEX { ospfLsdbAreaId, ospfLsdbType,
1046 ospfLsdbLsid, ospfLsdbRouterId } */
1047
1048 memset(&area_id, 0, sizeof(struct in_addr));
1049 type = 0;
1050 memset(&ls_id, 0, sizeof(struct in_addr));
1051 memset(&router_id, 0, sizeof(struct in_addr));
1052
1053 /* Check OSPF instance. */
1054 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1055 if (ospf == NULL)
1056 return NULL;
1057
1058 lsa = ospfLsdbLookup(v, name, length, &area_id, &type, &ls_id,
1059 &router_id, exact);
1060 if (!lsa)
1061 return NULL;
1062
1063 lsah = lsa->data;
1064
1065 /* Return the current value of the variable */
1066 switch (v->magic) {
1067 case OSPFLSDBAREAID: /* 1 */
1068 return SNMP_IPADDRESS(lsa->area->area_id);
1069 case OSPFLSDBTYPE: /* 2 */
1070 return SNMP_INTEGER(lsah->type);
1071 case OSPFLSDBLSID: /* 3 */
1072 return SNMP_IPADDRESS(lsah->id);
1073 case OSPFLSDBROUTERID: /* 4 */
1074 return SNMP_IPADDRESS(lsah->adv_router);
1075 case OSPFLSDBSEQUENCE: /* 5 */
1076 return SNMP_INTEGER(lsah->ls_seqnum);
1077 case OSPFLSDBAGE: /* 6 */
1078 return SNMP_INTEGER(lsah->ls_age);
1079 case OSPFLSDBCHECKSUM: /* 7 */
1080 return SNMP_INTEGER(lsah->checksum);
1081 case OSPFLSDBADVERTISEMENT: /* 8 */
1082 *var_len = ntohs(lsah->length);
1083 return (uint8_t *)lsah;
1084 default:
1085 return NULL;
1086 }
1087 return NULL;
1088 }
1089
1090 static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v,
1091 oid *name, size_t *length,
1092 struct in_addr *area_id,
1093 struct in_addr *range_net,
1094 int exact)
1095 {
1096 oid *offset;
1097 int offsetlen;
1098 int len;
1099 struct ospf *ospf;
1100 struct ospf_area *area;
1101 struct ospf_area_range *range;
1102 struct prefix_ipv4 p;
1103 p.family = AF_INET;
1104 p.prefixlen = IPV4_MAX_BITLEN;
1105
1106 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1107
1108 if (exact) {
1109 /* Area ID + Range Network. */
1110 if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length)
1111 return NULL;
1112
1113 /* Set OID offset for Area ID. */
1114 offset = name + v->namelen;
1115
1116 /* Lookup area first. */
1117 oid2in_addr(offset, IN_ADDR_SIZE, area_id);
1118
1119 area = ospf_area_lookup_by_area_id(ospf, *area_id);
1120 if (!area)
1121 return NULL;
1122
1123 offset += IN_ADDR_SIZE;
1124
1125 /* Lookup area range. */
1126 oid2in_addr(offset, IN_ADDR_SIZE, range_net);
1127 p.prefix = *range_net;
1128
1129 return ospf_area_range_lookup(area, &p);
1130 } else {
1131 /* Set OID offset for Area ID. */
1132 offset = name + v->namelen;
1133 offsetlen = *length - v->namelen;
1134
1135 len = offsetlen;
1136 if (len > (int)IN_ADDR_SIZE)
1137 len = IN_ADDR_SIZE;
1138
1139 oid2in_addr(offset, len, area_id);
1140
1141 /* First we search area. */
1142 if (len == IN_ADDR_SIZE)
1143 area = ospf_area_lookup_by_area_id(ospf, *area_id);
1144 else
1145 area = ospf_area_lookup_next(ospf, area_id,
1146 len == 0 ? 1 : 0);
1147
1148 if (area == NULL)
1149 return NULL;
1150
1151 do {
1152 offset += IN_ADDR_SIZE;
1153 offsetlen -= IN_ADDR_SIZE;
1154 len = offsetlen;
1155
1156 if (len < 0)
1157 len = 0;
1158 if (len > (int)IN_ADDR_SIZE)
1159 len = IN_ADDR_SIZE;
1160
1161 oid2in_addr(offset, len, range_net);
1162
1163 range = ospf_area_range_lookup_next(area, range_net,
1164 len == 0 ? 1 : 0);
1165
1166 if (range) {
1167 /* Fill in length. */
1168 *length = v->namelen + IN_ADDR_SIZE
1169 + IN_ADDR_SIZE;
1170
1171 /* Fill in value. */
1172 offset = name + v->namelen;
1173 oid_copy_addr(offset, area_id, IN_ADDR_SIZE);
1174 offset += IN_ADDR_SIZE;
1175 oid_copy_addr(offset, range_net, IN_ADDR_SIZE);
1176
1177 return range;
1178 }
1179 } while ((area = ospf_area_lookup_next(ospf, area_id, 0))
1180 != NULL);
1181 }
1182 return NULL;
1183 }
1184
1185 static uint8_t *ospfAreaRangeEntry(struct variable *v, oid *name,
1186 size_t *length, int exact, size_t *var_len,
1187 WriteMethod **write_method)
1188 {
1189 struct ospf_area_range *range;
1190 struct in_addr area_id;
1191 struct in_addr range_net;
1192 struct in_addr mask;
1193 struct ospf *ospf;
1194
1195 if (smux_header_table(v, name, length, exact, var_len, write_method)
1196 == MATCH_FAILED)
1197 return NULL;
1198
1199 /* Check OSPF instance. */
1200 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1201 if (ospf == NULL)
1202 return NULL;
1203
1204 memset(&area_id, 0, IN_ADDR_SIZE);
1205 memset(&range_net, 0, IN_ADDR_SIZE);
1206
1207 range = ospfAreaRangeLookup(v, name, length, &area_id, &range_net,
1208 exact);
1209 if (!range)
1210 return NULL;
1211
1212 /* Convert prefixlen to network mask format. */
1213 masklen2ip(range->subst_masklen, &mask);
1214
1215 /* Return the current value of the variable */
1216 switch (v->magic) {
1217 case OSPFAREARANGEAREAID: /* 1 */
1218 return SNMP_IPADDRESS(area_id);
1219 case OSPFAREARANGENET: /* 2 */
1220 return SNMP_IPADDRESS(range_net);
1221 case OSPFAREARANGEMASK: /* 3 */
1222 return SNMP_IPADDRESS(mask);
1223 case OSPFAREARANGESTATUS: /* 4 */
1224 return SNMP_INTEGER(SNMP_VALID);
1225 case OSPFAREARANGEEFFECT: /* 5 */
1226 #define OSPF_advertiseMatching 1
1227 #define OSPF_doNotAdvertiseMatching 2
1228 return SNMP_INTEGER(OSPF_advertiseMatching);
1229 default:
1230 return NULL;
1231 }
1232 return NULL;
1233 }
1234
1235 static struct ospf_nbr_nbma *ospfHostLookup(struct variable *v, oid *name,
1236 size_t *length,
1237 struct in_addr *addr, int exact)
1238 {
1239 int len;
1240 struct ospf_nbr_nbma *nbr_nbma;
1241 struct ospf *ospf;
1242
1243 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1244 if (ospf == NULL)
1245 return NULL;
1246
1247 if (exact) {
1248 /* INDEX { ospfHostIpAddress, ospfHostTOS } */
1249 if (*length != v->namelen + IN_ADDR_SIZE + 1)
1250 return NULL;
1251
1252 /* Check ospfHostTOS. */
1253 if (name[*length - 1] != 0)
1254 return NULL;
1255
1256 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, addr);
1257
1258 nbr_nbma = ospf_nbr_nbma_lookup(ospf, *addr);
1259
1260 return nbr_nbma;
1261 } else {
1262 len = *length - v->namelen;
1263 if (len > 4)
1264 len = 4;
1265
1266 oid2in_addr(name + v->namelen, len, addr);
1267
1268 nbr_nbma =
1269 ospf_nbr_nbma_lookup_next(ospf, addr, len == 0 ? 1 : 0);
1270
1271 if (nbr_nbma == NULL)
1272 return NULL;
1273
1274 oid_copy_addr(name + v->namelen, addr, IN_ADDR_SIZE);
1275
1276 /* Set TOS 0. */
1277 name[v->namelen + IN_ADDR_SIZE] = 0;
1278
1279 *length = v->namelen + IN_ADDR_SIZE + 1;
1280
1281 return nbr_nbma;
1282 }
1283 return NULL;
1284 }
1285
1286 static uint8_t *ospfHostEntry(struct variable *v, oid *name, size_t *length,
1287 int exact, size_t *var_len,
1288 WriteMethod **write_method)
1289 {
1290 struct ospf_nbr_nbma *nbr_nbma;
1291 struct ospf_interface *oi;
1292 struct in_addr addr;
1293 struct ospf *ospf;
1294
1295 if (smux_header_table(v, name, length, exact, var_len, write_method)
1296 == MATCH_FAILED)
1297 return NULL;
1298
1299 /* Check OSPF instance. */
1300 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1301 if (ospf == NULL)
1302 return NULL;
1303
1304 memset(&addr, 0, sizeof(struct in_addr));
1305
1306 nbr_nbma = ospfHostLookup(v, name, length, &addr, exact);
1307 if (nbr_nbma == NULL)
1308 return NULL;
1309
1310 oi = nbr_nbma->oi;
1311
1312 /* Return the current value of the variable */
1313 switch (v->magic) {
1314 case OSPFHOSTIPADDRESS: /* 1 */
1315 return SNMP_IPADDRESS(nbr_nbma->addr);
1316 case OSPFHOSTTOS: /* 2 */
1317 return SNMP_INTEGER(0);
1318 case OSPFHOSTMETRIC: /* 3 */
1319 if (oi)
1320 return SNMP_INTEGER(oi->output_cost);
1321 else
1322 return SNMP_INTEGER(1);
1323 case OSPFHOSTSTATUS: /* 4 */
1324 return SNMP_INTEGER(SNMP_VALID);
1325 case OSPFHOSTAREAID: /* 5 */
1326 if (oi && oi->area)
1327 return SNMP_IPADDRESS(oi->area->area_id);
1328 else
1329 return SNMP_IPADDRESS(ospf_empty_addr);
1330 default:
1331 return NULL;
1332 }
1333 return NULL;
1334 }
1335
1336 static struct list *ospf_snmp_iflist;
1337
1338 struct ospf_snmp_if {
1339 struct in_addr addr;
1340 ifindex_t ifindex;
1341 struct interface *ifp;
1342 };
1343
1344 static struct ospf_snmp_if *ospf_snmp_if_new(void)
1345 {
1346 return XCALLOC(MTYPE_TMP, sizeof(struct ospf_snmp_if));
1347 }
1348
1349 static void ospf_snmp_if_free(struct ospf_snmp_if *osif)
1350 {
1351 XFREE(MTYPE_TMP, osif);
1352 }
1353
1354 static int ospf_snmp_if_delete(struct interface *ifp)
1355 {
1356 struct listnode *node, *nnode;
1357 struct ospf_snmp_if *osif;
1358
1359 for (ALL_LIST_ELEMENTS(ospf_snmp_iflist, node, nnode, osif)) {
1360 if (osif->ifp == ifp) {
1361 list_delete_node(ospf_snmp_iflist, node);
1362 ospf_snmp_if_free(osif);
1363 break;
1364 }
1365 }
1366 return 0;
1367 }
1368
1369 static int ospf_snmp_if_update(struct interface *ifp)
1370 {
1371 struct listnode *node;
1372 struct listnode *pn;
1373 struct connected *ifc;
1374 struct prefix *p;
1375 struct ospf_snmp_if *osif;
1376 struct in_addr *addr;
1377 ifindex_t ifindex;
1378
1379 ospf_snmp_if_delete(ifp);
1380
1381 p = NULL;
1382 addr = NULL;
1383 ifindex = 0;
1384
1385 /* Lookup first IPv4 address entry. */
1386 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
1387 p = CONNECTED_ID(ifc);
1388
1389 if (p->family == AF_INET) {
1390 addr = &p->u.prefix4;
1391 break;
1392 }
1393 }
1394 if (!addr)
1395 ifindex = ifp->ifindex;
1396
1397 /* Add interface to the list. */
1398 pn = NULL;
1399 for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, node, osif)) {
1400 if (addr) {
1401 /* Usual interfaces --> Sort them based on interface
1402 * IPv4 addresses */
1403 if (ntohl(osif->addr.s_addr) > ntohl(addr->s_addr))
1404 break;
1405 } else {
1406 /* Unnumbered interfaces --> Sort them based on
1407 * interface indexes */
1408 if (osif->addr.s_addr != 0 || osif->ifindex > ifindex)
1409 break;
1410 }
1411 pn = node;
1412 }
1413
1414 osif = ospf_snmp_if_new();
1415 if (addr) /* Usual interface */
1416 {
1417 osif->addr = *addr;
1418
1419 /* This field is used for storing ospfAddressLessIf OID value,
1420 * conform to RFC1850 OSPF-MIB specification, it must be 0 for
1421 * usual interface */
1422 osif->ifindex = 0;
1423 } else /* Unnumbered interface */
1424 osif->ifindex = ifindex;
1425 osif->ifp = ifp;
1426
1427 listnode_add_after(ospf_snmp_iflist, pn, osif);
1428 return 0;
1429 }
1430
1431 static int ospf_snmp_is_if_have_addr(struct interface *ifp)
1432 {
1433 struct listnode *nn;
1434 struct connected *ifc;
1435
1436 /* Is this interface having any connected IPv4 address ? */
1437 for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, ifc)) {
1438 if (CONNECTED_PREFIX(ifc)->family == AF_INET)
1439 return 1;
1440 }
1441
1442 return 0;
1443 }
1444
1445 static struct ospf_interface *ospf_snmp_if_lookup(struct in_addr *ifaddr,
1446 ifindex_t *ifindex)
1447 {
1448 struct listnode *node;
1449 struct ospf_snmp_if *osif;
1450 struct ospf_interface *oi = NULL;
1451 struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1452
1453 for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, node, osif)) {
1454 if (ifaddr->s_addr) {
1455 if (IPV4_ADDR_SAME(&osif->addr, ifaddr))
1456 oi = ospf_if_lookup_by_local_addr(
1457 ospf, osif->ifp, *ifaddr);
1458 } else {
1459 if (osif->ifindex == *ifindex)
1460 oi = ospf_if_lookup_by_local_addr(
1461 ospf, osif->ifp, *ifaddr);
1462 }
1463 }
1464 return oi;
1465 }
1466
1467 static struct ospf_interface *ospf_snmp_if_lookup_next(struct in_addr *ifaddr,
1468 ifindex_t *ifindex,
1469 int ifaddr_next,
1470 ifindex_t ifindex_next)
1471 {
1472 struct ospf_snmp_if *osif;
1473 struct listnode *nn;
1474 struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1475 struct ospf_interface *oi = NULL;
1476
1477 if (ospf == NULL)
1478 return NULL;
1479
1480 /* No instance is specified --> Return the first OSPF interface */
1481 if (ifaddr_next) {
1482 for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, nn, osif)) {
1483 osif = listgetdata(nn);
1484 *ifaddr = osif->addr;
1485 *ifindex = osif->ifindex;
1486 /* Because no instance is specified, we don't care about
1487 * the kind of
1488 * interface (usual or unnumbered), just returning the
1489 * first valid
1490 * OSPF interface */
1491 oi = ospf_if_lookup_by_local_addr(ospf, osif->ifp,
1492 *ifaddr);
1493 if (oi)
1494 return (oi);
1495 }
1496 return NULL;
1497 }
1498
1499 /* An instance is specified --> Return the next OSPF interface */
1500 for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, nn, osif)) {
1501 /* Usual interface */
1502 if (ifaddr->s_addr) {
1503 /* The interface must have valid AF_INET connected
1504 * address */
1505 /* it must have lager IPv4 address value than the lookup
1506 * entry */
1507 if ((ospf_snmp_is_if_have_addr(osif->ifp))
1508 && (ntohl(osif->addr.s_addr)
1509 > ntohl(ifaddr->s_addr))) {
1510 *ifaddr = osif->addr;
1511 *ifindex = osif->ifindex;
1512
1513 /* and it must be an OSPF interface */
1514 oi = ospf_if_lookup_by_local_addr(
1515 ospf, osif->ifp, *ifaddr);
1516 if (oi)
1517 return oi;
1518 }
1519 }
1520 /* Unnumbered interface */
1521 else
1522 /* The interface must NOT have valid AF_INET connected
1523 address */
1524 /* it must have lager interface index than the lookup
1525 entry */
1526 if ((!ospf_snmp_is_if_have_addr(osif->ifp))
1527 && (osif->ifindex > *ifindex)) {
1528 *ifaddr = osif->addr;
1529 *ifindex = osif->ifindex;
1530
1531 /* and it must be an OSPF interface */
1532 oi = ospf_if_lookup_by_local_addr(ospf, osif->ifp,
1533 *ifaddr);
1534 if (oi)
1535 return oi;
1536 }
1537 }
1538 return NULL;
1539 }
1540
1541 static int ospf_snmp_iftype(struct interface *ifp)
1542 {
1543 #define ospf_snmp_iftype_broadcast 1
1544 #define ospf_snmp_iftype_nbma 2
1545 #define ospf_snmp_iftype_pointToPoint 3
1546 #define ospf_snmp_iftype_pointToMultipoint 5
1547 if (if_is_broadcast(ifp))
1548 return ospf_snmp_iftype_broadcast;
1549 if (if_is_pointopoint(ifp))
1550 return ospf_snmp_iftype_pointToPoint;
1551 return ospf_snmp_iftype_broadcast;
1552 }
1553
1554 static struct ospf_interface *ospfIfLookup(struct variable *v, oid *name,
1555 size_t *length,
1556 struct in_addr *ifaddr,
1557 ifindex_t *ifindex, int exact)
1558 {
1559 unsigned int len;
1560 int ifaddr_next = 0;
1561 ifindex_t ifindex_next = 0;
1562 struct ospf_interface *oi;
1563 oid *offset;
1564
1565 if (exact) {
1566 if (*length != v->namelen + IN_ADDR_SIZE + 1)
1567 return NULL;
1568
1569 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, ifaddr);
1570 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1571
1572 return ospf_snmp_if_lookup(ifaddr, ifindex);
1573 } else {
1574 len = *length - v->namelen;
1575 if (len >= IN_ADDR_SIZE)
1576 len = IN_ADDR_SIZE;
1577 if (len == 0)
1578 ifaddr_next = 1;
1579
1580 oid2in_addr(name + v->namelen, len, ifaddr);
1581
1582 len = *length - v->namelen - IN_ADDR_SIZE;
1583 if (len >= 1)
1584 len = 1;
1585 else
1586 ifindex_next = 1;
1587
1588 if (len == 1)
1589 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1590
1591 oi = ospf_snmp_if_lookup_next(ifaddr, ifindex, ifaddr_next,
1592 ifindex_next);
1593 if (oi) {
1594 *length = v->namelen + IN_ADDR_SIZE + 1;
1595 offset = name + v->namelen;
1596 oid_copy_addr(offset, ifaddr, IN_ADDR_SIZE);
1597 offset += IN_ADDR_SIZE;
1598 *offset = *ifindex;
1599 return oi;
1600 }
1601 }
1602 return NULL;
1603 }
1604
1605 static uint8_t *ospfIfEntry(struct variable *v, oid *name, size_t *length,
1606 int exact, size_t *var_len,
1607 WriteMethod **write_method)
1608 {
1609 ifindex_t ifindex;
1610 struct in_addr ifaddr;
1611 struct ospf_interface *oi;
1612 struct ospf *ospf;
1613
1614 if (smux_header_table(v, name, length, exact, var_len, write_method)
1615 == MATCH_FAILED)
1616 return NULL;
1617
1618 ifindex = 0;
1619 memset(&ifaddr, 0, sizeof(struct in_addr));
1620
1621 /* Check OSPF instance. */
1622 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1623 if (ospf == NULL)
1624 return NULL;
1625
1626 oi = ospfIfLookup(v, name, length, &ifaddr, &ifindex, exact);
1627 if (oi == NULL)
1628 return NULL;
1629
1630 /* Return the current value of the variable */
1631 switch (v->magic) {
1632 case OSPFIFIPADDRESS: /* 1 */
1633 return SNMP_IPADDRESS(ifaddr);
1634 case OSPFADDRESSLESSIF: /* 2 */
1635 return SNMP_INTEGER(ifindex);
1636 case OSPFIFAREAID: /* 3 */
1637 if (oi->area)
1638 return SNMP_IPADDRESS(oi->area->area_id);
1639 else
1640 return SNMP_IPADDRESS(ospf_empty_addr);
1641 case OSPFIFTYPE: /* 4 */
1642 return SNMP_INTEGER(ospf_snmp_iftype(oi->ifp));
1643 case OSPFIFADMINSTAT: /* 5 */
1644 if (oi)
1645 return SNMP_INTEGER(OSPF_STATUS_ENABLED);
1646 else
1647 return SNMP_INTEGER(OSPF_STATUS_DISABLED);
1648 case OSPFIFRTRPRIORITY: /* 6 */
1649 return SNMP_INTEGER(PRIORITY(oi));
1650 case OSPFIFTRANSITDELAY: /* 7 */
1651 return SNMP_INTEGER(OSPF_IF_PARAM(oi, transmit_delay));
1652 case OSPFIFRETRANSINTERVAL: /* 8 */
1653 return SNMP_INTEGER(OSPF_IF_PARAM(oi, retransmit_interval));
1654 case OSPFIFHELLOINTERVAL: /* 9 */
1655 return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_hello));
1656 case OSPFIFRTRDEADINTERVAL: /* 10 */
1657 return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_wait));
1658 case OSPFIFPOLLINTERVAL: /* 11 */
1659 return SNMP_INTEGER(OSPF_POLL_INTERVAL_DEFAULT);
1660 case OSPFIFSTATE: /* 12 */
1661 return SNMP_INTEGER(ISM_SNMP(oi->state));
1662 case OSPFIFDESIGNATEDROUTER: /* 13 */
1663 return SNMP_IPADDRESS(DR(oi));
1664 case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */
1665 return SNMP_IPADDRESS(BDR(oi));
1666 case OSPFIFEVENTS: /* 15 */
1667 return SNMP_INTEGER(oi->state_change);
1668 case OSPFIFAUTHKEY: /* 16 */
1669 *var_len = 0;
1670 return (uint8_t *)OSPF_IF_PARAM(oi, auth_simple);
1671 case OSPFIFSTATUS: /* 17 */
1672 return SNMP_INTEGER(SNMP_VALID);
1673 case OSPFIFMULTICASTFORWARDING: /* 18 */
1674 #define ospf_snmp_multiforward_blocked 1
1675 #define ospf_snmp_multiforward_multicast 2
1676 #define ospf_snmp_multiforward_unicast 3
1677 return SNMP_INTEGER(ospf_snmp_multiforward_blocked);
1678 case OSPFIFDEMAND: /* 19 */
1679 return SNMP_INTEGER(SNMP_FALSE);
1680 case OSPFIFAUTHTYPE: /* 20 */
1681 if (oi->area)
1682 return SNMP_INTEGER(oi->area->auth_type);
1683 else
1684 return SNMP_INTEGER(0);
1685 default:
1686 return NULL;
1687 }
1688 return NULL;
1689 }
1690
1691 #define OSPF_SNMP_METRIC_VALUE 1
1692
1693 static struct ospf_interface *ospfIfMetricLookup(struct variable *v, oid *name,
1694 size_t *length,
1695 struct in_addr *ifaddr,
1696 ifindex_t *ifindex, int exact)
1697 {
1698 unsigned int len;
1699 int ifaddr_next = 0;
1700 ifindex_t ifindex_next = 0;
1701 struct ospf_interface *oi;
1702 oid *offset;
1703 int metric;
1704
1705 if (exact) {
1706 if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1)
1707 return NULL;
1708
1709 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, ifaddr);
1710 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1711 metric = name[v->namelen + IN_ADDR_SIZE + 1];
1712
1713 if (metric != OSPF_SNMP_METRIC_VALUE)
1714 return NULL;
1715
1716 return ospf_snmp_if_lookup(ifaddr, ifindex);
1717 } else {
1718 len = *length - v->namelen;
1719 if (len >= IN_ADDR_SIZE)
1720 len = IN_ADDR_SIZE;
1721 else
1722 ifaddr_next = 1;
1723
1724 oid2in_addr(name + v->namelen, len, ifaddr);
1725
1726 len = *length - v->namelen - IN_ADDR_SIZE;
1727 if (len >= 1)
1728 len = 1;
1729 else
1730 ifindex_next = 1;
1731
1732 if (len == 1)
1733 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1734
1735 oi = ospf_snmp_if_lookup_next(ifaddr, ifindex, ifaddr_next,
1736 ifindex_next);
1737 if (oi) {
1738 *length = v->namelen + IN_ADDR_SIZE + 1 + 1;
1739 offset = name + v->namelen;
1740 oid_copy_addr(offset, ifaddr, IN_ADDR_SIZE);
1741 offset += IN_ADDR_SIZE;
1742 *offset = *ifindex;
1743 offset++;
1744 *offset = OSPF_SNMP_METRIC_VALUE;
1745 return oi;
1746 }
1747 }
1748 return NULL;
1749 }
1750
1751 static uint8_t *ospfIfMetricEntry(struct variable *v, oid *name, size_t *length,
1752 int exact, size_t *var_len,
1753 WriteMethod **write_method)
1754 {
1755 /* Currently we support metric 1 only. */
1756 ifindex_t ifindex;
1757 struct in_addr ifaddr;
1758 struct ospf_interface *oi;
1759 struct ospf *ospf;
1760
1761 if (smux_header_table(v, name, length, exact, var_len, write_method)
1762 == MATCH_FAILED)
1763 return NULL;
1764
1765 ifindex = 0;
1766 memset(&ifaddr, 0, sizeof(struct in_addr));
1767
1768 /* Check OSPF instance. */
1769 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1770 if (ospf == NULL)
1771 return NULL;
1772
1773 oi = ospfIfMetricLookup(v, name, length, &ifaddr, &ifindex, exact);
1774 if (oi == NULL)
1775 return NULL;
1776
1777 /* Return the current value of the variable */
1778 switch (v->magic) {
1779 case OSPFIFMETRICIPADDRESS:
1780 return SNMP_IPADDRESS(ifaddr);
1781 case OSPFIFMETRICADDRESSLESSIF:
1782 return SNMP_INTEGER(ifindex);
1783 case OSPFIFMETRICTOS:
1784 return SNMP_INTEGER(0);
1785 case OSPFIFMETRICVALUE:
1786 return SNMP_INTEGER(OSPF_SNMP_METRIC_VALUE);
1787 case OSPFIFMETRICSTATUS:
1788 return SNMP_INTEGER(1);
1789 default:
1790 return NULL;
1791 }
1792 return NULL;
1793 }
1794
1795 static struct route_table *ospf_snmp_vl_table;
1796
1797 static int ospf_snmp_vl_add(struct ospf_vl_data *vl_data)
1798 {
1799 struct prefix_ls lp;
1800 struct route_node *rn;
1801
1802 memset(&lp, 0, sizeof(struct prefix_ls));
1803 lp.family = 0;
1804 lp.prefixlen = 64;
1805 lp.id = vl_data->vl_area_id;
1806 lp.adv_router = vl_data->vl_peer;
1807
1808 rn = route_node_get(ospf_snmp_vl_table, (struct prefix *)&lp);
1809 if (rn->info)
1810 route_unlock_node(rn);
1811
1812 rn->info = vl_data;
1813 return 0;
1814 }
1815
1816 static int ospf_snmp_vl_delete(struct ospf_vl_data *vl_data)
1817 {
1818 struct prefix_ls lp;
1819 struct route_node *rn;
1820
1821 memset(&lp, 0, sizeof(struct prefix_ls));
1822 lp.family = 0;
1823 lp.prefixlen = 64;
1824 lp.id = vl_data->vl_area_id;
1825 lp.adv_router = vl_data->vl_peer;
1826
1827 rn = route_node_lookup(ospf_snmp_vl_table, (struct prefix *)&lp);
1828 if (!rn)
1829 return 0;
1830 rn->info = NULL;
1831 route_unlock_node(rn);
1832 route_unlock_node(rn);
1833 return 0;
1834 }
1835
1836 static struct ospf_vl_data *ospf_snmp_vl_lookup(struct in_addr *area_id,
1837 struct in_addr *neighbor)
1838 {
1839 struct prefix_ls lp;
1840 struct route_node *rn;
1841 struct ospf_vl_data *vl_data;
1842
1843 memset(&lp, 0, sizeof(struct prefix_ls));
1844 lp.family = 0;
1845 lp.prefixlen = 64;
1846 lp.id = *area_id;
1847 lp.adv_router = *neighbor;
1848
1849 rn = route_node_lookup(ospf_snmp_vl_table, (struct prefix *)&lp);
1850 if (rn) {
1851 vl_data = rn->info;
1852 route_unlock_node(rn);
1853 return vl_data;
1854 }
1855 return NULL;
1856 }
1857
1858 static struct ospf_vl_data *ospf_snmp_vl_lookup_next(struct in_addr *area_id,
1859 struct in_addr *neighbor,
1860 int first)
1861 {
1862 struct prefix_ls lp;
1863 struct route_node *rn;
1864 struct ospf_vl_data *vl_data;
1865
1866 memset(&lp, 0, sizeof(struct prefix_ls));
1867 lp.family = 0;
1868 lp.prefixlen = 64;
1869 lp.id = *area_id;
1870 lp.adv_router = *neighbor;
1871
1872 if (first)
1873 rn = route_top(ospf_snmp_vl_table);
1874 else {
1875 rn = route_node_get(ospf_snmp_vl_table, (struct prefix *)&lp);
1876 rn = route_next(rn);
1877 }
1878
1879 for (; rn; rn = route_next(rn))
1880 if (rn->info)
1881 break;
1882
1883 if (rn && rn->info) {
1884 vl_data = rn->info;
1885 *area_id = vl_data->vl_area_id;
1886 *neighbor = vl_data->vl_peer;
1887 route_unlock_node(rn);
1888 return vl_data;
1889 }
1890 return NULL;
1891 }
1892
1893 static struct ospf_vl_data *
1894 ospfVirtIfLookup(struct variable *v, oid *name, size_t *length,
1895 struct in_addr *area_id, struct in_addr *neighbor, int exact)
1896 {
1897 int first;
1898 unsigned int len;
1899 struct ospf_vl_data *vl_data;
1900
1901 if (exact) {
1902 if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE)
1903 return NULL;
1904
1905 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, area_id);
1906 oid2in_addr(name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE,
1907 neighbor);
1908
1909 return ospf_snmp_vl_lookup(area_id, neighbor);
1910 } else {
1911 first = 0;
1912
1913 len = *length - v->namelen;
1914 if (len == 0)
1915 first = 1;
1916 if (len > IN_ADDR_SIZE)
1917 len = IN_ADDR_SIZE;
1918 oid2in_addr(name + v->namelen, len, area_id);
1919
1920 len = *length - v->namelen - IN_ADDR_SIZE;
1921 if (len > IN_ADDR_SIZE)
1922 len = IN_ADDR_SIZE;
1923 oid2in_addr(name + v->namelen + IN_ADDR_SIZE, len, neighbor);
1924
1925 vl_data = ospf_snmp_vl_lookup_next(area_id, neighbor, first);
1926
1927 if (vl_data) {
1928 *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
1929 oid_copy_addr(name + v->namelen, area_id, IN_ADDR_SIZE);
1930 oid_copy_addr(name + v->namelen + IN_ADDR_SIZE,
1931 neighbor, IN_ADDR_SIZE);
1932 return vl_data;
1933 }
1934 }
1935 return NULL;
1936 }
1937
1938 static uint8_t *ospfVirtIfEntry(struct variable *v, oid *name, size_t *length,
1939 int exact, size_t *var_len,
1940 WriteMethod **write_method)
1941 {
1942 struct ospf_vl_data *vl_data;
1943 struct ospf_interface *oi;
1944 struct in_addr area_id;
1945 struct in_addr neighbor;
1946
1947 if (smux_header_table(v, name, length, exact, var_len, write_method)
1948 == MATCH_FAILED)
1949 return NULL;
1950
1951 memset(&area_id, 0, sizeof(struct in_addr));
1952 memset(&neighbor, 0, sizeof(struct in_addr));
1953
1954 vl_data = ospfVirtIfLookup(v, name, length, &area_id, &neighbor, exact);
1955 if (!vl_data)
1956 return NULL;
1957 oi = vl_data->vl_oi;
1958 if (!oi)
1959 return NULL;
1960
1961 /* Return the current value of the variable */
1962 switch (v->magic) {
1963 case OSPFVIRTIFAREAID:
1964 return SNMP_IPADDRESS(area_id);
1965 case OSPFVIRTIFNEIGHBOR:
1966 return SNMP_IPADDRESS(neighbor);
1967 case OSPFVIRTIFTRANSITDELAY:
1968 return SNMP_INTEGER(OSPF_IF_PARAM(oi, transmit_delay));
1969 case OSPFVIRTIFRETRANSINTERVAL:
1970 return SNMP_INTEGER(OSPF_IF_PARAM(oi, retransmit_interval));
1971 case OSPFVIRTIFHELLOINTERVAL:
1972 return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_hello));
1973 case OSPFVIRTIFRTRDEADINTERVAL:
1974 return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_wait));
1975 case OSPFVIRTIFSTATE:
1976 return SNMP_INTEGER(oi->state);
1977 case OSPFVIRTIFEVENTS:
1978 return SNMP_INTEGER(oi->state_change);
1979 case OSPFVIRTIFAUTHKEY:
1980 *var_len = 0;
1981 return (uint8_t *)OSPF_IF_PARAM(oi, auth_simple);
1982 case OSPFVIRTIFSTATUS:
1983 return SNMP_INTEGER(SNMP_VALID);
1984 case OSPFVIRTIFAUTHTYPE:
1985 if (oi->area)
1986 return SNMP_INTEGER(oi->area->auth_type);
1987 else
1988 return SNMP_INTEGER(0);
1989 default:
1990 return NULL;
1991 }
1992 return NULL;
1993 }
1994
1995 static struct ospf_neighbor *ospf_snmp_nbr_lookup(struct ospf *ospf,
1996 struct in_addr *nbr_addr,
1997 ifindex_t *ifindex)
1998 {
1999 struct listnode *node, *nnode;
2000 struct ospf_interface *oi;
2001 struct ospf_neighbor *nbr;
2002 struct route_node *rn;
2003
2004 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
2005 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
2006 if ((nbr = rn->info) != NULL && nbr != oi->nbr_self
2007 /* If EXACT match is needed, provide ALL entry found
2008 && nbr->state != NSM_Down
2009 */
2010 && nbr->src.s_addr != 0) {
2011 if (IPV4_ADDR_SAME(&nbr->src, nbr_addr)) {
2012 route_unlock_node(rn);
2013 return nbr;
2014 }
2015 }
2016 }
2017 return NULL;
2018 }
2019
2020 static struct ospf_neighbor *ospf_snmp_nbr_lookup_next(struct in_addr *nbr_addr,
2021 ifindex_t *ifindex,
2022 int first)
2023 {
2024 struct listnode *nn;
2025 struct ospf_interface *oi;
2026 struct ospf_neighbor *nbr;
2027 struct route_node *rn;
2028 struct ospf_neighbor *min = NULL;
2029 struct ospf *ospf;
2030
2031 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2032
2033 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, nn, oi)) {
2034 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
2035 if ((nbr = rn->info) != NULL && nbr != oi->nbr_self
2036 && nbr->state != NSM_Down && nbr->src.s_addr != 0) {
2037 if (first) {
2038 if (!min)
2039 min = nbr;
2040 else if (ntohl(nbr->src.s_addr)
2041 < ntohl(min->src.s_addr))
2042 min = nbr;
2043 } else if (ntohl(nbr->src.s_addr)
2044 > ntohl(nbr_addr->s_addr)) {
2045 if (!min)
2046 min = nbr;
2047 else if (ntohl(nbr->src.s_addr)
2048 < ntohl(min->src.s_addr))
2049 min = nbr;
2050 }
2051 }
2052 }
2053 if (min) {
2054 *nbr_addr = min->src;
2055 *ifindex = 0;
2056 return min;
2057 }
2058 return NULL;
2059 }
2060
2061 static struct ospf_neighbor *ospfNbrLookup(struct variable *v, oid *name,
2062 size_t *length,
2063 struct in_addr *nbr_addr,
2064 ifindex_t *ifindex, int exact)
2065 {
2066 unsigned int len;
2067 int first;
2068 struct ospf_neighbor *nbr;
2069 struct ospf *ospf;
2070
2071 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2072
2073 if (!ospf)
2074 return NULL;
2075
2076 if (exact) {
2077 if (*length != v->namelen + IN_ADDR_SIZE + 1)
2078 return NULL;
2079
2080 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, nbr_addr);
2081 *ifindex = name[v->namelen + IN_ADDR_SIZE];
2082
2083 return ospf_snmp_nbr_lookup(ospf, nbr_addr, ifindex);
2084 } else {
2085 first = 0;
2086 len = *length - v->namelen;
2087
2088 if (len == 0)
2089 first = 1;
2090
2091 if (len > IN_ADDR_SIZE)
2092 len = IN_ADDR_SIZE;
2093
2094 oid2in_addr(name + v->namelen, len, nbr_addr);
2095
2096 len = *length - v->namelen - IN_ADDR_SIZE;
2097 if (len >= 1)
2098 *ifindex = name[v->namelen + IN_ADDR_SIZE];
2099
2100 nbr = ospf_snmp_nbr_lookup_next(nbr_addr, ifindex, first);
2101
2102 if (nbr) {
2103 *length = v->namelen + IN_ADDR_SIZE + 1;
2104 oid_copy_addr(name + v->namelen, nbr_addr,
2105 IN_ADDR_SIZE);
2106 name[v->namelen + IN_ADDR_SIZE] = *ifindex;
2107 return nbr;
2108 }
2109 }
2110 return NULL;
2111 }
2112
2113 /* map internal quagga neighbor states to official MIB values:
2114
2115 ospfNbrState OBJECT-TYPE
2116 SYNTAX INTEGER {
2117 down (1),
2118 attempt (2),
2119 init (3),
2120 twoWay (4),
2121 exchangeStart (5),
2122 exchange (6),
2123 loading (7),
2124 full (8)
2125 }
2126 */
2127 static int32_t ospf_snmp_neighbor_state(uint8_t nst)
2128 {
2129 switch (nst) {
2130 case NSM_Attempt:
2131 return 2;
2132 case NSM_Init:
2133 return 3;
2134 case NSM_TwoWay:
2135 return 4;
2136 case NSM_ExStart:
2137 return 5;
2138 case NSM_Exchange:
2139 return 6;
2140 case NSM_Loading:
2141 return 7;
2142 case NSM_Full:
2143 return 8;
2144 default:
2145 return 1; /* down */
2146 }
2147 }
2148
2149 static uint8_t *ospfNbrEntry(struct variable *v, oid *name, size_t *length,
2150 int exact, size_t *var_len,
2151 WriteMethod **write_method)
2152 {
2153 struct in_addr nbr_addr;
2154 ifindex_t ifindex;
2155 struct ospf_neighbor *nbr;
2156 struct ospf_interface *oi;
2157
2158 if (smux_header_table(v, name, length, exact, var_len, write_method)
2159 == MATCH_FAILED)
2160 return NULL;
2161
2162 memset(&nbr_addr, 0, sizeof(struct in_addr));
2163 ifindex = 0;
2164
2165 nbr = ospfNbrLookup(v, name, length, &nbr_addr, &ifindex, exact);
2166 if (!nbr)
2167 return NULL;
2168 oi = nbr->oi;
2169
2170 /* Return the current value of the variable */
2171 switch (v->magic) {
2172 case OSPFNBRIPADDR:
2173 return SNMP_IPADDRESS(nbr_addr);
2174 case OSPFNBRADDRESSLESSINDEX:
2175 return SNMP_INTEGER(ifindex);
2176 case OSPFNBRRTRID:
2177 return SNMP_IPADDRESS(nbr->router_id);
2178 case OSPFNBROPTIONS:
2179 return SNMP_INTEGER(oi->nbr_self->options);
2180 case OSPFNBRPRIORITY:
2181 return SNMP_INTEGER(nbr->priority);
2182 case OSPFNBRSTATE:
2183 return SNMP_INTEGER(ospf_snmp_neighbor_state(nbr->state));
2184 case OSPFNBREVENTS:
2185 return SNMP_INTEGER(nbr->state_change);
2186 case OSPFNBRLSRETRANSQLEN:
2187 return SNMP_INTEGER(ospf_ls_retransmit_count(nbr));
2188 case OSPFNBMANBRSTATUS:
2189 return SNMP_INTEGER(SNMP_VALID);
2190 case OSPFNBMANBRPERMANENCE:
2191 return SNMP_INTEGER(2);
2192 case OSPFNBRHELLOSUPPRESSED:
2193 return SNMP_INTEGER(SNMP_FALSE);
2194 default:
2195 return NULL;
2196 }
2197 return NULL;
2198 }
2199
2200 static uint8_t *ospfVirtNbrEntry(struct variable *v, oid *name, size_t *length,
2201 int exact, size_t *var_len,
2202 WriteMethod **write_method)
2203 {
2204 struct ospf_vl_data *vl_data;
2205 struct in_addr area_id;
2206 struct in_addr neighbor;
2207 struct ospf *ospf;
2208
2209 if (smux_header_table(v, name, length, exact, var_len, write_method)
2210 == MATCH_FAILED)
2211 return NULL;
2212
2213 memset(&area_id, 0, sizeof(struct in_addr));
2214 memset(&neighbor, 0, sizeof(struct in_addr));
2215
2216 /* Check OSPF instance. */
2217 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2218 if (ospf == NULL)
2219 return NULL;
2220
2221 vl_data = ospfVirtIfLookup(v, name, length, &area_id, &neighbor, exact);
2222 if (!vl_data)
2223 return NULL;
2224
2225 /* Return the current value of the variable */
2226 switch (v->magic) {
2227 case OSPFVIRTNBRAREA:
2228 return (uint8_t *)NULL;
2229 case OSPFVIRTNBRRTRID:
2230 return (uint8_t *)NULL;
2231 case OSPFVIRTNBRIPADDR:
2232 return (uint8_t *)NULL;
2233 case OSPFVIRTNBROPTIONS:
2234 return (uint8_t *)NULL;
2235 case OSPFVIRTNBRSTATE:
2236 return (uint8_t *)NULL;
2237 case OSPFVIRTNBREVENTS:
2238 return (uint8_t *)NULL;
2239 case OSPFVIRTNBRLSRETRANSQLEN:
2240 return (uint8_t *)NULL;
2241 case OSPFVIRTNBRHELLOSUPPRESSED:
2242 return (uint8_t *)NULL;
2243 default:
2244 return NULL;
2245 }
2246 return NULL;
2247 }
2248
2249 static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name,
2250 size_t *length, uint8_t *type,
2251 struct in_addr *ls_id,
2252 struct in_addr *router_id, int exact)
2253 {
2254 int first;
2255 oid *offset;
2256 int offsetlen;
2257 uint8_t lsa_type;
2258 unsigned int len;
2259 struct ospf_lsa *lsa;
2260 struct ospf *ospf;
2261
2262 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2263 if (exact) {
2264 if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
2265 return NULL;
2266
2267 offset = name + v->namelen;
2268
2269 /* Make it sure given value match to type. */
2270 lsa_type = *offset;
2271 offset++;
2272
2273 if (lsa_type != *type)
2274 return NULL;
2275
2276 /* LS ID. */
2277 oid2in_addr(offset, IN_ADDR_SIZE, ls_id);
2278 offset += IN_ADDR_SIZE;
2279
2280 /* Router ID. */
2281 oid2in_addr(offset, IN_ADDR_SIZE, router_id);
2282
2283 return ospf_lsdb_lookup_by_id(ospf->lsdb, *type, *ls_id,
2284 *router_id);
2285 } else {
2286 /* Get variable length. */
2287 first = 0;
2288 offset = name + v->namelen;
2289 offsetlen = *length - v->namelen;
2290
2291 /* LSA type value. */
2292 lsa_type = *offset;
2293 offset++;
2294 offsetlen--;
2295
2296 if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA)
2297 first = 1;
2298
2299 /* LS ID. */
2300 len = offsetlen;
2301 if (len > IN_ADDR_SIZE)
2302 len = IN_ADDR_SIZE;
2303
2304 oid2in_addr(offset, len, ls_id);
2305
2306 offset += IN_ADDR_SIZE;
2307 offsetlen -= IN_ADDR_SIZE;
2308
2309 /* Router ID. */
2310 len = offsetlen;
2311 if (len > IN_ADDR_SIZE)
2312 len = IN_ADDR_SIZE;
2313
2314 oid2in_addr(offset, len, router_id);
2315
2316 lsa = ospf_lsdb_lookup_by_id_next(ospf->lsdb, *type, *ls_id,
2317 *router_id, first);
2318
2319 if (lsa) {
2320 /* Fill in length. */
2321 *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE;
2322
2323 /* Fill in value. */
2324 offset = name + v->namelen;
2325
2326 *offset = OSPF_AS_EXTERNAL_LSA;
2327 offset++;
2328 oid_copy_addr(offset, &lsa->data->id, IN_ADDR_SIZE);
2329 offset += IN_ADDR_SIZE;
2330 oid_copy_addr(offset, &lsa->data->adv_router,
2331 IN_ADDR_SIZE);
2332
2333 return lsa;
2334 }
2335 }
2336 return NULL;
2337 }
2338
2339 static uint8_t *ospfExtLsdbEntry(struct variable *v, oid *name, size_t *length,
2340 int exact, size_t *var_len,
2341 WriteMethod **write_method)
2342 {
2343 struct ospf_lsa *lsa;
2344 struct lsa_header *lsah;
2345 uint8_t type;
2346 struct in_addr ls_id;
2347 struct in_addr router_id;
2348 struct ospf *ospf;
2349
2350 if (smux_header_table(v, name, length, exact, var_len, write_method)
2351 == MATCH_FAILED)
2352 return NULL;
2353
2354 type = OSPF_AS_EXTERNAL_LSA;
2355 memset(&ls_id, 0, sizeof(struct in_addr));
2356 memset(&router_id, 0, sizeof(struct in_addr));
2357
2358 /* Check OSPF instance. */
2359 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2360 if (ospf == NULL)
2361 return NULL;
2362
2363 lsa = ospfExtLsdbLookup(v, name, length, &type, &ls_id, &router_id,
2364 exact);
2365 if (!lsa)
2366 return NULL;
2367
2368 lsah = lsa->data;
2369
2370 /* Return the current value of the variable */
2371 switch (v->magic) {
2372 case OSPFEXTLSDBTYPE:
2373 return SNMP_INTEGER(OSPF_AS_EXTERNAL_LSA);
2374 case OSPFEXTLSDBLSID:
2375 return SNMP_IPADDRESS(lsah->id);
2376 case OSPFEXTLSDBROUTERID:
2377 return SNMP_IPADDRESS(lsah->adv_router);
2378 case OSPFEXTLSDBSEQUENCE:
2379 return SNMP_INTEGER(lsah->ls_seqnum);
2380 case OSPFEXTLSDBAGE:
2381 return SNMP_INTEGER(lsah->ls_age);
2382 case OSPFEXTLSDBCHECKSUM:
2383 return SNMP_INTEGER(lsah->checksum);
2384 case OSPFEXTLSDBADVERTISEMENT:
2385 *var_len = ntohs(lsah->length);
2386 return (uint8_t *)lsah;
2387 default:
2388 return NULL;
2389 }
2390 return NULL;
2391 }
2392
2393 static uint8_t *ospfAreaAggregateEntry(struct variable *v, oid *name,
2394 size_t *length, int exact,
2395 size_t *var_len,
2396 WriteMethod **write_method)
2397 {
2398 if (smux_header_table(v, name, length, exact, var_len, write_method)
2399 == MATCH_FAILED)
2400 return NULL;
2401
2402 /* Return the current value of the variable */
2403 switch (v->magic) {
2404 case OSPFAREAAGGREGATEAREAID:
2405 return (uint8_t *)NULL;
2406 case OSPFAREAAGGREGATELSDBTYPE:
2407 return (uint8_t *)NULL;
2408 case OSPFAREAAGGREGATENET:
2409 return (uint8_t *)NULL;
2410 case OSPFAREAAGGREGATEMASK:
2411 return (uint8_t *)NULL;
2412 case OSPFAREAAGGREGATESTATUS:
2413 return (uint8_t *)NULL;
2414 case OSPFAREAAGGREGATEEFFECT:
2415 return (uint8_t *)NULL;
2416 default:
2417 return NULL;
2418 }
2419 return NULL;
2420 }
2421
2422 /* OSPF Traps. */
2423 #define IFSTATECHANGE 16
2424 #define VIRTIFSTATECHANGE 1
2425 #define NBRSTATECHANGE 2
2426 #define VIRTNBRSTATECHANGE 3
2427
2428 static struct trap_object ospfNbrTrapList[] = {{-2, {1, OSPFROUTERID}},
2429 {3, {10, 1, OSPFNBRIPADDR}},
2430 {3, {10, 1, OSPFNBRRTRID}},
2431 {3, {10, 1, OSPFNBRSTATE}}};
2432
2433
2434 static struct trap_object ospfVirtNbrTrapList[] = {
2435 {-2, {1, 1}},
2436 {3, {11, 1, OSPFVIRTNBRAREA}},
2437 {3, {11, 1, OSPFVIRTNBRRTRID}},
2438 {3, {11, 1, OSPFVIRTNBRSTATE}}};
2439
2440 static struct trap_object ospfIfTrapList[] = {{-2, {1, OSPFROUTERID}},
2441 {3, {7, 1, OSPFIFIPADDRESS}},
2442 {3, {7, 1, OSPFADDRESSLESSIF}},
2443 {3, {7, 1, OSPFIFSTATE}}};
2444
2445 static struct trap_object ospfVirtIfTrapList[] = {
2446 {-2, {1, OSPFROUTERID}},
2447 {3, {9, 1, OSPFVIRTIFAREAID}},
2448 {3, {9, 1, OSPFVIRTIFNEIGHBOR}},
2449 {3, {9, 1, OSPFVIRTIFSTATE}}};
2450
2451 static void ospfTrapNbrStateChange(struct ospf_neighbor *on)
2452 {
2453 oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
2454 char msgbuf[16];
2455
2456 ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf));
2457 if (IS_DEBUG_OSPF_EVENT)
2458 zlog_info("%s: trap sent: %s now %s", __func__,
2459 inet_ntoa(on->address.u.prefix4), msgbuf);
2460
2461 oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
2462 index[IN_ADDR_SIZE] = 0;
2463
2464 smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
2465 array_size(ospf_trap_oid), ospf_oid,
2466 sizeof(ospf_oid) / sizeof(oid), index, IN_ADDR_SIZE + 1,
2467 ospfNbrTrapList, array_size(ospfNbrTrapList), NBRSTATECHANGE);
2468 }
2469
2470 static void ospfTrapVirtNbrStateChange(struct ospf_neighbor *on)
2471 {
2472 oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
2473
2474 zlog_info("ospfTrapVirtNbrStateChange trap sent");
2475
2476 oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
2477 index[IN_ADDR_SIZE] = 0;
2478
2479 smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
2480 array_size(ospf_trap_oid), ospf_oid,
2481 sizeof(ospf_oid) / sizeof(oid), index, IN_ADDR_SIZE + 1,
2482 ospfVirtNbrTrapList, array_size(ospfVirtNbrTrapList),
2483 VIRTNBRSTATECHANGE);
2484 }
2485
2486 static int ospf_snmp_nsm_change(struct ospf_neighbor *nbr, int next_state,
2487 int old_state)
2488 {
2489 /* Terminal state or regression */
2490 if ((next_state == NSM_Full) || (next_state == NSM_TwoWay)
2491 || (next_state < old_state)) {
2492 /* ospfVirtNbrStateChange */
2493 if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK)
2494 ospfTrapVirtNbrStateChange(nbr);
2495 /* ospfNbrStateChange trap */
2496 else
2497 /* To/From FULL, only managed by DR */
2498 if (((next_state != NSM_Full)
2499 && (nbr->state != NSM_Full))
2500 || (nbr->oi->state == ISM_DR))
2501 ospfTrapNbrStateChange(nbr);
2502 }
2503 return 0;
2504 }
2505
2506 static void ospfTrapIfStateChange(struct ospf_interface *oi)
2507 {
2508 oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
2509
2510 if (IS_DEBUG_OSPF_EVENT)
2511 zlog_info("%s: trap sent: %s now %s", __func__,
2512 inet_ntoa(oi->address->u.prefix4),
2513 lookup_msg(ospf_ism_state_msg, oi->state, NULL));
2514
2515 oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
2516 index[IN_ADDR_SIZE] = 0;
2517
2518 smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
2519 array_size(ospf_trap_oid), ospf_oid,
2520 sizeof(ospf_oid) / sizeof(oid), index, IN_ADDR_SIZE + 1,
2521 ospfIfTrapList, array_size(ospfIfTrapList), IFSTATECHANGE);
2522 }
2523
2524 static void ospfTrapVirtIfStateChange(struct ospf_interface *oi)
2525 {
2526 oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
2527
2528 zlog_info("ospfTrapVirtIfStateChange trap sent");
2529
2530 oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
2531 index[IN_ADDR_SIZE] = 0;
2532
2533 smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
2534 array_size(ospf_trap_oid), ospf_oid,
2535 sizeof(ospf_oid) / sizeof(oid), index, IN_ADDR_SIZE + 1,
2536 ospfVirtIfTrapList, array_size(ospfVirtIfTrapList),
2537 VIRTIFSTATECHANGE);
2538 }
2539
2540 static int ospf_snmp_ism_change(struct ospf_interface *oi, int state,
2541 int old_state)
2542 {
2543 /* Terminal state or regression */
2544 if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther)
2545 || (state == ISM_PointToPoint) || (state < old_state)) {
2546 /* ospfVirtIfStateChange */
2547 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
2548 ospfTrapVirtIfStateChange(oi);
2549 /* ospfIfStateChange */
2550 else
2551 ospfTrapIfStateChange(oi);
2552 }
2553 return 0;
2554 }
2555
2556 /* Register OSPF2-MIB. */
2557 static int ospf_snmp_init(struct thread_master *tm)
2558 {
2559 ospf_snmp_iflist = list_new();
2560 ospf_snmp_vl_table = route_table_init();
2561 smux_init(tm);
2562 REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid);
2563 return 0;
2564 }
2565
2566 static int ospf_snmp_module_init(void)
2567 {
2568 hook_register(ospf_if_update, ospf_snmp_if_update);
2569 hook_register(ospf_if_delete, ospf_snmp_if_delete);
2570 hook_register(ospf_vl_add, ospf_snmp_vl_add);
2571 hook_register(ospf_vl_delete, ospf_snmp_vl_delete);
2572 hook_register(ospf_ism_change, ospf_snmp_ism_change);
2573 hook_register(ospf_nsm_change, ospf_snmp_nsm_change);
2574
2575 hook_register(frr_late_init, ospf_snmp_init);
2576 return 0;
2577 }
2578
2579 FRR_MODULE_SETUP(.name = "ospfd_snmp", .version = FRR_VERSION,
2580 .description = "ospfd AgentX SNMP module",
2581 .init = ospf_snmp_module_init, )