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