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