]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_snmp.c
zebra: Allow ns delete to happen after under/over flow checks
[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 break;
552 case OSPFADMINSTAT: /* 2 */
553 /* The administrative status of OSPF in the router. */
554 if (ospf_admin_stat(ospf))
555 return SNMP_INTEGER(OSPF_STATUS_ENABLED);
556 else
557 return SNMP_INTEGER(OSPF_STATUS_DISABLED);
558 break;
559 case OSPFVERSIONNUMBER: /* 3 */
560 /* OSPF version 2. */
561 return SNMP_INTEGER(OSPF_VERSION);
562 break;
563 case OSPFAREABDRRTRSTATUS: /* 4 */
564 /* Area Border router status. */
565 if (ospf && CHECK_FLAG(ospf->flags, OSPF_FLAG_ABR))
566 return SNMP_INTEGER(SNMP_TRUE);
567 else
568 return SNMP_INTEGER(SNMP_FALSE);
569 break;
570 case OSPFASBDRRTRSTATUS: /* 5 */
571 /* AS Border router status. */
572 if (ospf && CHECK_FLAG(ospf->flags, OSPF_FLAG_ASBR))
573 return SNMP_INTEGER(SNMP_TRUE);
574 else
575 return SNMP_INTEGER(SNMP_FALSE);
576 break;
577 case OSPFEXTERNLSACOUNT: /* 6 */
578 /* External LSA counts. */
579 if (ospf)
580 return SNMP_INTEGER(ospf_lsdb_count_all(ospf->lsdb));
581 else
582 return SNMP_INTEGER(0);
583 break;
584 case OSPFEXTERNLSACKSUMSUM: /* 7 */
585 /* External LSA checksum. */
586 return SNMP_INTEGER(0);
587 break;
588 case OSPFTOSSUPPORT: /* 8 */
589 /* TOS is not supported. */
590 return SNMP_INTEGER(SNMP_FALSE);
591 break;
592 case OSPFORIGINATENEWLSAS: /* 9 */
593 /* The number of new link-state advertisements. */
594 if (ospf)
595 return SNMP_INTEGER(ospf->lsa_originate_count);
596 else
597 return SNMP_INTEGER(0);
598 break;
599 case OSPFRXNEWLSAS: /* 10 */
600 /* The number of link-state advertisements received determined
601 to be new instantiations. */
602 if (ospf)
603 return SNMP_INTEGER(ospf->rx_lsa_count);
604 else
605 return SNMP_INTEGER(0);
606 break;
607 case OSPFEXTLSDBLIMIT: /* 11 */
608 /* There is no limit for the number of non-default
609 AS-external-LSAs. */
610 return SNMP_INTEGER(-1);
611 break;
612 case OSPFMULTICASTEXTENSIONS: /* 12 */
613 /* Multicast Extensions to OSPF is not supported. */
614 return SNMP_INTEGER(0);
615 break;
616 case OSPFEXITOVERFLOWINTERVAL: /* 13 */
617 /* Overflow is not supported. */
618 return SNMP_INTEGER(0);
619 break;
620 case OSPFDEMANDEXTENSIONS: /* 14 */
621 /* Demand routing is not supported. */
622 return SNMP_INTEGER(SNMP_FALSE);
623 break;
624 default:
625 return NULL;
626 }
627 return NULL;
628 }
629
630 static struct ospf_area *
631 ospf_area_lookup_next(struct ospf *ospf, struct in_addr *area_id, int first)
632 {
633 struct ospf_area *area;
634 struct listnode *node;
635
636 if (ospf == NULL)
637 return NULL;
638
639 if (first) {
640 node = listhead(ospf->areas);
641 if (node) {
642 area = listgetdata(node);
643 *area_id = area->area_id;
644 return area;
645 }
646 return NULL;
647 }
648 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
649 if (ntohl(area->area_id.s_addr) > ntohl(area_id->s_addr)) {
650 *area_id = area->area_id;
651 return area;
652 }
653 }
654 return NULL;
655 }
656
657 static struct ospf_area *ospfAreaLookup(struct variable *v, oid name[],
658 size_t *length, struct in_addr *addr,
659 int exact)
660 {
661 struct ospf *ospf;
662 struct ospf_area *area;
663 int len;
664
665 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
666 if (ospf == NULL)
667 return NULL;
668
669 if (exact) {
670 /* Length is insufficient to lookup OSPF area. */
671 if (*length - v->namelen != sizeof(struct in_addr))
672 return NULL;
673
674 oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr);
675
676 area = ospf_area_lookup_by_area_id(ospf, *addr);
677
678 return area;
679 } else {
680 len = *length - v->namelen;
681 if (len > 4)
682 len = 4;
683
684 oid2in_addr(name + v->namelen, len, addr);
685
686 area = ospf_area_lookup_next(ospf, addr, len == 0 ? 1 : 0);
687
688 if (area == NULL)
689 return NULL;
690
691 oid_copy_addr(name + v->namelen, addr, sizeof(struct in_addr));
692 *length = sizeof(struct in_addr) + v->namelen;
693
694 return area;
695 }
696 return NULL;
697 }
698
699 static uint8_t *ospfAreaEntry(struct variable *v, oid *name, size_t *length,
700 int exact, size_t *var_len,
701 WriteMethod **write_method)
702 {
703 struct ospf_area *area;
704 struct in_addr addr;
705
706 if (smux_header_table(v, name, length, exact, var_len, write_method)
707 == MATCH_FAILED)
708 return NULL;
709
710 memset(&addr, 0, sizeof(struct in_addr));
711
712 area = ospfAreaLookup(v, name, length, &addr, exact);
713 if (!area)
714 return NULL;
715
716 /* Return the current value of the variable */
717 switch (v->magic) {
718 case OSPFAREAID: /* 1 */
719 return SNMP_IPADDRESS(area->area_id);
720 break;
721 case OSPFAUTHTYPE: /* 2 */
722 return SNMP_INTEGER(area->auth_type);
723 break;
724 case OSPFIMPORTASEXTERN: /* 3 */
725 return SNMP_INTEGER(area->external_routing + 1);
726 break;
727 case OSPFSPFRUNS: /* 4 */
728 return SNMP_INTEGER(area->spf_calculation);
729 break;
730 case OSPFAREABDRRTRCOUNT: /* 5 */
731 return SNMP_INTEGER(area->abr_count);
732 break;
733 case OSPFASBDRRTRCOUNT: /* 6 */
734 return SNMP_INTEGER(area->asbr_count);
735 break;
736 case OSPFAREALSACOUNT: /* 7 */
737 return SNMP_INTEGER(area->lsdb->total);
738 break;
739 case OSPFAREALSACKSUMSUM: /* 8 */
740 return SNMP_INTEGER(0);
741 break;
742 case OSPFAREASUMMARY: /* 9 */
743 #define OSPF_noAreaSummary 1
744 #define OSPF_sendAreaSummary 2
745 if (area->no_summary)
746 return SNMP_INTEGER(OSPF_noAreaSummary);
747 else
748 return SNMP_INTEGER(OSPF_sendAreaSummary);
749 break;
750 case OSPFAREASTATUS: /* 10 */
751 return SNMP_INTEGER(SNMP_VALID);
752 break;
753 default:
754 return NULL;
755 break;
756 }
757 return NULL;
758 }
759
760 static struct ospf_area *ospf_stub_area_lookup_next(struct in_addr *area_id,
761 int first)
762 {
763 struct ospf_area *area;
764 struct listnode *node;
765 struct ospf *ospf;
766
767 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
768 if (ospf == NULL)
769 return NULL;
770
771 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
772 if (area->external_routing == OSPF_AREA_STUB) {
773 if (first) {
774 *area_id = area->area_id;
775 return area;
776 } else if (ntohl(area->area_id.s_addr)
777 > ntohl(area_id->s_addr)) {
778 *area_id = area->area_id;
779 return area;
780 }
781 }
782 }
783 return NULL;
784 }
785
786 static struct ospf_area *ospfStubAreaLookup(struct variable *v, oid name[],
787 size_t *length,
788 struct in_addr *addr, int exact)
789 {
790 struct ospf *ospf;
791 struct ospf_area *area;
792 int len;
793
794 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
795 if (ospf == NULL)
796 return NULL;
797
798 /* Exact lookup. */
799 if (exact) {
800 /* ospfStubAreaID + ospfStubTOS. */
801 if (*length != v->namelen + sizeof(struct in_addr) + 1)
802 return NULL;
803
804 /* Check ospfStubTOS is zero. */
805 if (name[*length - 1] != 0)
806 return NULL;
807
808 oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr);
809
810 area = ospf_area_lookup_by_area_id(ospf, *addr);
811
812 if (area->external_routing == OSPF_AREA_STUB)
813 return area;
814 else
815 return NULL;
816 } else {
817 len = *length - v->namelen;
818 if (len > 4)
819 len = 4;
820
821 oid2in_addr(name + v->namelen, len, addr);
822
823 area = ospf_stub_area_lookup_next(addr, len == 0 ? 1 : 0);
824
825 if (area == NULL)
826 return NULL;
827
828 oid_copy_addr(name + v->namelen, addr, sizeof(struct in_addr));
829 /* Set TOS 0. */
830 name[v->namelen + sizeof(struct in_addr)] = 0;
831 *length = v->namelen + sizeof(struct in_addr) + 1;
832
833 return area;
834 }
835 return NULL;
836 }
837
838 static uint8_t *ospfStubAreaEntry(struct variable *v, oid *name, size_t *length,
839 int exact, size_t *var_len,
840 WriteMethod **write_method)
841 {
842 struct ospf_area *area;
843 struct in_addr addr;
844
845 if (smux_header_table(v, name, length, exact, var_len, write_method)
846 == MATCH_FAILED)
847 return NULL;
848
849 memset(&addr, 0, sizeof(struct in_addr));
850
851 area = ospfStubAreaLookup(v, name, length, &addr, exact);
852 if (!area)
853 return NULL;
854
855 /* Return the current value of the variable */
856 switch (v->magic) {
857 case OSPFSTUBAREAID: /* 1 */
858 /* OSPF stub area id. */
859 return SNMP_IPADDRESS(area->area_id);
860 break;
861 case OSPFSTUBTOS: /* 2 */
862 /* TOS value is not supported. */
863 return SNMP_INTEGER(0);
864 break;
865 case OSPFSTUBMETRIC: /* 3 */
866 /* Default cost to stub area. */
867 return SNMP_INTEGER(area->default_cost);
868 break;
869 case OSPFSTUBSTATUS: /* 4 */
870 /* Status of the stub area. */
871 return SNMP_INTEGER(SNMP_VALID);
872 break;
873 case OSPFSTUBMETRICTYPE: /* 5 */
874 /* OSPF Metric type. */
875 #define OSPF_ospfMetric 1
876 #define OSPF_comparableCost 2
877 #define OSPF_nonComparable 3
878 return SNMP_INTEGER(OSPF_ospfMetric);
879 break;
880 default:
881 return NULL;
882 break;
883 }
884 return NULL;
885 }
886
887 static struct ospf_lsa *lsdb_lookup_next(struct ospf_area *area, uint8_t *type,
888 int type_next, struct in_addr *ls_id,
889 int ls_id_next,
890 struct in_addr *router_id,
891 int router_id_next)
892 {
893 struct ospf_lsa *lsa;
894 int i;
895
896 if (type_next)
897 i = OSPF_MIN_LSA;
898 else
899 i = *type;
900
901 /* Sanity check, if LSA type unknwon
902 merley skip any LSA */
903 if ((i < OSPF_MIN_LSA) || (i >= OSPF_MAX_LSA)) {
904 zlog_debug("Strange request with LSA type %d\n", i);
905 return NULL;
906 }
907
908 for (; i < OSPF_MAX_LSA; i++) {
909 *type = i;
910
911 lsa = ospf_lsdb_lookup_by_id_next(area->lsdb, *type, *ls_id,
912 *router_id, ls_id_next);
913 if (lsa)
914 return lsa;
915
916 ls_id_next = 1;
917 }
918 return NULL;
919 }
920
921 static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name,
922 size_t *length, struct in_addr *area_id,
923 uint8_t *type, struct in_addr *ls_id,
924 struct in_addr *router_id, int exact)
925 {
926 struct ospf *ospf;
927 struct ospf_area *area;
928 struct ospf_lsa *lsa;
929 int len;
930 int type_next;
931 int ls_id_next;
932 int router_id_next;
933 oid *offset;
934 int offsetlen;
935
936 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
937
938 #define OSPF_LSDB_ENTRY_OFFSET (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
939
940 if (exact) {
941 /* Area ID + Type + LS ID + Router ID. */
942 if (*length - v->namelen != OSPF_LSDB_ENTRY_OFFSET)
943 return NULL;
944
945 /* Set OID offset for Area ID. */
946 offset = name + v->namelen;
947
948 /* Lookup area first. */
949 oid2in_addr(offset, IN_ADDR_SIZE, area_id);
950 area = ospf_area_lookup_by_area_id(ospf, *area_id);
951 if (!area)
952 return NULL;
953 offset += IN_ADDR_SIZE;
954
955 /* Type. */
956 *type = *offset;
957 offset++;
958
959 /* LS ID. */
960 oid2in_addr(offset, IN_ADDR_SIZE, ls_id);
961 offset += IN_ADDR_SIZE;
962
963 /* Router ID. */
964 oid2in_addr(offset, IN_ADDR_SIZE, router_id);
965
966 /* Lookup LSDB. */
967 return ospf_lsdb_lookup_by_id(area->lsdb, *type, *ls_id,
968 *router_id);
969 } else {
970 /* Get variable length. */
971 offset = name + v->namelen;
972 offsetlen = *length - v->namelen;
973 len = offsetlen;
974
975 if (len > (int)IN_ADDR_SIZE)
976 len = IN_ADDR_SIZE;
977
978 oid2in_addr(offset, len, area_id);
979
980 /* First we search area. */
981 if (len == IN_ADDR_SIZE)
982 area = ospf_area_lookup_by_area_id(ospf, *area_id);
983 else
984 area = ospf_area_lookup_next(ospf, area_id, 1);
985
986 if (area == NULL)
987 return NULL;
988
989 do {
990 /* Next we lookup type. */
991 offset += len;
992 offsetlen -= len;
993 len = offsetlen;
994
995 if (len <= 0)
996 type_next = 1;
997 else {
998 type_next = 0;
999 *type = *offset;
1000 }
1001
1002 /* LS ID. */
1003 offset++;
1004 offsetlen--;
1005 len = offsetlen;
1006
1007 if (len <= 0)
1008 ls_id_next = 1;
1009 else {
1010 ls_id_next = 0;
1011 if (len > (int)IN_ADDR_SIZE)
1012 len = IN_ADDR_SIZE;
1013
1014 oid2in_addr(offset, len, ls_id);
1015 }
1016
1017 /* Router ID. */
1018 offset += IN_ADDR_SIZE;
1019 offsetlen -= IN_ADDR_SIZE;
1020 len = offsetlen;
1021
1022 if (len <= 0)
1023 router_id_next = 1;
1024 else {
1025 router_id_next = 0;
1026 if (len > (int)IN_ADDR_SIZE)
1027 len = IN_ADDR_SIZE;
1028
1029 oid2in_addr(offset, len, router_id);
1030 }
1031
1032 lsa = lsdb_lookup_next(area, type, type_next, ls_id,
1033 ls_id_next, router_id,
1034 router_id_next);
1035
1036 if (lsa) {
1037 /* Fill in length. */
1038 *length = v->namelen + OSPF_LSDB_ENTRY_OFFSET;
1039
1040 /* Fill in value. */
1041 offset = name + v->namelen;
1042 oid_copy_addr(offset, area_id, IN_ADDR_SIZE);
1043 offset += IN_ADDR_SIZE;
1044 *offset = lsa->data->type;
1045 offset++;
1046 oid_copy_addr(offset, &lsa->data->id,
1047 IN_ADDR_SIZE);
1048 offset += IN_ADDR_SIZE;
1049 oid_copy_addr(offset, &lsa->data->adv_router,
1050 IN_ADDR_SIZE);
1051
1052 return lsa;
1053 }
1054 } while ((area = ospf_area_lookup_next(ospf, area_id, 0))
1055 != NULL);
1056 }
1057 return NULL;
1058 }
1059
1060 static uint8_t *ospfLsdbEntry(struct variable *v, oid *name, size_t *length,
1061 int exact, size_t *var_len,
1062 WriteMethod **write_method)
1063 {
1064 struct ospf_lsa *lsa;
1065 struct lsa_header *lsah;
1066 struct in_addr area_id;
1067 uint8_t type;
1068 struct in_addr ls_id;
1069 struct in_addr router_id;
1070 struct ospf *ospf;
1071
1072 if (smux_header_table(v, name, length, exact, var_len, write_method)
1073 == MATCH_FAILED)
1074 return NULL;
1075
1076 /* INDEX { ospfLsdbAreaId, ospfLsdbType,
1077 ospfLsdbLsid, ospfLsdbRouterId } */
1078
1079 memset(&area_id, 0, sizeof(struct in_addr));
1080 type = 0;
1081 memset(&ls_id, 0, sizeof(struct in_addr));
1082 memset(&router_id, 0, sizeof(struct in_addr));
1083
1084 /* Check OSPF instance. */
1085 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1086 if (ospf == NULL)
1087 return NULL;
1088
1089 lsa = ospfLsdbLookup(v, name, length, &area_id, &type, &ls_id,
1090 &router_id, exact);
1091 if (!lsa)
1092 return NULL;
1093
1094 lsah = lsa->data;
1095
1096 /* Return the current value of the variable */
1097 switch (v->magic) {
1098 case OSPFLSDBAREAID: /* 1 */
1099 return SNMP_IPADDRESS(lsa->area->area_id);
1100 break;
1101 case OSPFLSDBTYPE: /* 2 */
1102 return SNMP_INTEGER(lsah->type);
1103 break;
1104 case OSPFLSDBLSID: /* 3 */
1105 return SNMP_IPADDRESS(lsah->id);
1106 break;
1107 case OSPFLSDBROUTERID: /* 4 */
1108 return SNMP_IPADDRESS(lsah->adv_router);
1109 break;
1110 case OSPFLSDBSEQUENCE: /* 5 */
1111 return SNMP_INTEGER(lsah->ls_seqnum);
1112 break;
1113 case OSPFLSDBAGE: /* 6 */
1114 return SNMP_INTEGER(lsah->ls_age);
1115 break;
1116 case OSPFLSDBCHECKSUM: /* 7 */
1117 return SNMP_INTEGER(lsah->checksum);
1118 break;
1119 case OSPFLSDBADVERTISEMENT: /* 8 */
1120 *var_len = ntohs(lsah->length);
1121 return (uint8_t *)lsah;
1122 break;
1123 default:
1124 return NULL;
1125 break;
1126 }
1127 return NULL;
1128 }
1129
1130 static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v,
1131 oid *name, size_t *length,
1132 struct in_addr *area_id,
1133 struct in_addr *range_net,
1134 int exact)
1135 {
1136 oid *offset;
1137 int offsetlen;
1138 int len;
1139 struct ospf *ospf;
1140 struct ospf_area *area;
1141 struct ospf_area_range *range;
1142 struct prefix_ipv4 p;
1143 p.family = AF_INET;
1144 p.prefixlen = IPV4_MAX_BITLEN;
1145
1146 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1147
1148 if (exact) {
1149 /* Area ID + Range Network. */
1150 if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length)
1151 return NULL;
1152
1153 /* Set OID offset for Area ID. */
1154 offset = name + v->namelen;
1155
1156 /* Lookup area first. */
1157 oid2in_addr(offset, IN_ADDR_SIZE, area_id);
1158
1159 area = ospf_area_lookup_by_area_id(ospf, *area_id);
1160 if (!area)
1161 return NULL;
1162
1163 offset += IN_ADDR_SIZE;
1164
1165 /* Lookup area range. */
1166 oid2in_addr(offset, IN_ADDR_SIZE, range_net);
1167 p.prefix = *range_net;
1168
1169 return ospf_area_range_lookup(area, &p);
1170 } else {
1171 /* Set OID offset for Area ID. */
1172 offset = name + v->namelen;
1173 offsetlen = *length - v->namelen;
1174
1175 len = offsetlen;
1176 if (len > (int)IN_ADDR_SIZE)
1177 len = IN_ADDR_SIZE;
1178
1179 oid2in_addr(offset, len, area_id);
1180
1181 /* First we search area. */
1182 if (len == IN_ADDR_SIZE)
1183 area = ospf_area_lookup_by_area_id(ospf, *area_id);
1184 else
1185 area = ospf_area_lookup_next(ospf, area_id,
1186 len == 0 ? 1 : 0);
1187
1188 if (area == NULL)
1189 return NULL;
1190
1191 do {
1192 offset += IN_ADDR_SIZE;
1193 offsetlen -= IN_ADDR_SIZE;
1194 len = offsetlen;
1195
1196 if (len < 0)
1197 len = 0;
1198 if (len > (int)IN_ADDR_SIZE)
1199 len = IN_ADDR_SIZE;
1200
1201 oid2in_addr(offset, len, range_net);
1202
1203 range = ospf_area_range_lookup_next(area, range_net,
1204 len == 0 ? 1 : 0);
1205
1206 if (range) {
1207 /* Fill in length. */
1208 *length = v->namelen + IN_ADDR_SIZE
1209 + IN_ADDR_SIZE;
1210
1211 /* Fill in value. */
1212 offset = name + v->namelen;
1213 oid_copy_addr(offset, area_id, IN_ADDR_SIZE);
1214 offset += IN_ADDR_SIZE;
1215 oid_copy_addr(offset, range_net, IN_ADDR_SIZE);
1216
1217 return range;
1218 }
1219 } while ((area = ospf_area_lookup_next(ospf, area_id, 0))
1220 != NULL);
1221 }
1222 return NULL;
1223 }
1224
1225 static uint8_t *ospfAreaRangeEntry(struct variable *v, oid *name,
1226 size_t *length, int exact, size_t *var_len,
1227 WriteMethod **write_method)
1228 {
1229 struct ospf_area_range *range;
1230 struct in_addr area_id;
1231 struct in_addr range_net;
1232 struct in_addr mask;
1233 struct ospf *ospf;
1234
1235 if (smux_header_table(v, name, length, exact, var_len, write_method)
1236 == MATCH_FAILED)
1237 return NULL;
1238
1239 /* Check OSPF instance. */
1240 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1241 if (ospf == NULL)
1242 return NULL;
1243
1244 memset(&area_id, 0, IN_ADDR_SIZE);
1245 memset(&range_net, 0, IN_ADDR_SIZE);
1246
1247 range = ospfAreaRangeLookup(v, name, length, &area_id, &range_net,
1248 exact);
1249 if (!range)
1250 return NULL;
1251
1252 /* Convert prefixlen to network mask format. */
1253 masklen2ip(range->subst_masklen, &mask);
1254
1255 /* Return the current value of the variable */
1256 switch (v->magic) {
1257 case OSPFAREARANGEAREAID: /* 1 */
1258 return SNMP_IPADDRESS(area_id);
1259 break;
1260 case OSPFAREARANGENET: /* 2 */
1261 return SNMP_IPADDRESS(range_net);
1262 break;
1263 case OSPFAREARANGEMASK: /* 3 */
1264 return SNMP_IPADDRESS(mask);
1265 break;
1266 case OSPFAREARANGESTATUS: /* 4 */
1267 return SNMP_INTEGER(SNMP_VALID);
1268 break;
1269 case OSPFAREARANGEEFFECT: /* 5 */
1270 #define OSPF_advertiseMatching 1
1271 #define OSPF_doNotAdvertiseMatching 2
1272 return SNMP_INTEGER(OSPF_advertiseMatching);
1273 break;
1274 default:
1275 return NULL;
1276 break;
1277 }
1278 return NULL;
1279 }
1280
1281 static struct ospf_nbr_nbma *ospfHostLookup(struct variable *v, oid *name,
1282 size_t *length,
1283 struct in_addr *addr, int exact)
1284 {
1285 int len;
1286 struct ospf_nbr_nbma *nbr_nbma;
1287 struct ospf *ospf;
1288
1289 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1290 if (ospf == NULL)
1291 return NULL;
1292
1293 if (exact) {
1294 /* INDEX { ospfHostIpAddress, ospfHostTOS } */
1295 if (*length != v->namelen + IN_ADDR_SIZE + 1)
1296 return NULL;
1297
1298 /* Check ospfHostTOS. */
1299 if (name[*length - 1] != 0)
1300 return NULL;
1301
1302 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, addr);
1303
1304 nbr_nbma = ospf_nbr_nbma_lookup(ospf, *addr);
1305
1306 return nbr_nbma;
1307 } else {
1308 len = *length - v->namelen;
1309 if (len > 4)
1310 len = 4;
1311
1312 oid2in_addr(name + v->namelen, len, addr);
1313
1314 nbr_nbma =
1315 ospf_nbr_nbma_lookup_next(ospf, addr, len == 0 ? 1 : 0);
1316
1317 if (nbr_nbma == NULL)
1318 return NULL;
1319
1320 oid_copy_addr(name + v->namelen, addr, IN_ADDR_SIZE);
1321
1322 /* Set TOS 0. */
1323 name[v->namelen + IN_ADDR_SIZE] = 0;
1324
1325 *length = v->namelen + IN_ADDR_SIZE + 1;
1326
1327 return nbr_nbma;
1328 }
1329 return NULL;
1330 }
1331
1332 static uint8_t *ospfHostEntry(struct variable *v, oid *name, size_t *length,
1333 int exact, size_t *var_len,
1334 WriteMethod **write_method)
1335 {
1336 struct ospf_nbr_nbma *nbr_nbma;
1337 struct ospf_interface *oi;
1338 struct in_addr addr;
1339 struct ospf *ospf;
1340
1341 if (smux_header_table(v, name, length, exact, var_len, write_method)
1342 == MATCH_FAILED)
1343 return NULL;
1344
1345 /* Check OSPF instance. */
1346 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1347 if (ospf == NULL)
1348 return NULL;
1349
1350 memset(&addr, 0, sizeof(struct in_addr));
1351
1352 nbr_nbma = ospfHostLookup(v, name, length, &addr, exact);
1353 if (nbr_nbma == NULL)
1354 return NULL;
1355
1356 oi = nbr_nbma->oi;
1357
1358 /* Return the current value of the variable */
1359 switch (v->magic) {
1360 case OSPFHOSTIPADDRESS: /* 1 */
1361 return SNMP_IPADDRESS(nbr_nbma->addr);
1362 break;
1363 case OSPFHOSTTOS: /* 2 */
1364 return SNMP_INTEGER(0);
1365 break;
1366 case OSPFHOSTMETRIC: /* 3 */
1367 if (oi)
1368 return SNMP_INTEGER(oi->output_cost);
1369 else
1370 return SNMP_INTEGER(1);
1371 break;
1372 case OSPFHOSTSTATUS: /* 4 */
1373 return SNMP_INTEGER(SNMP_VALID);
1374 break;
1375 case OSPFHOSTAREAID: /* 5 */
1376 if (oi && oi->area)
1377 return SNMP_IPADDRESS(oi->area->area_id);
1378 else
1379 return SNMP_IPADDRESS(ospf_empty_addr);
1380 break;
1381 default:
1382 return NULL;
1383 break;
1384 }
1385 return NULL;
1386 }
1387
1388 static struct list *ospf_snmp_iflist;
1389
1390 struct ospf_snmp_if {
1391 struct in_addr addr;
1392 ifindex_t ifindex;
1393 struct interface *ifp;
1394 };
1395
1396 static struct ospf_snmp_if *ospf_snmp_if_new(void)
1397 {
1398 return XCALLOC(MTYPE_TMP, sizeof(struct ospf_snmp_if));
1399 }
1400
1401 static void ospf_snmp_if_free(struct ospf_snmp_if *osif)
1402 {
1403 XFREE(MTYPE_TMP, osif);
1404 }
1405
1406 static int ospf_snmp_if_delete(struct interface *ifp)
1407 {
1408 struct listnode *node, *nnode;
1409 struct ospf_snmp_if *osif;
1410
1411 for (ALL_LIST_ELEMENTS(ospf_snmp_iflist, node, nnode, osif)) {
1412 if (osif->ifp == ifp) {
1413 list_delete_node(ospf_snmp_iflist, node);
1414 ospf_snmp_if_free(osif);
1415 break;
1416 }
1417 }
1418 return 0;
1419 }
1420
1421 static int ospf_snmp_if_update(struct interface *ifp)
1422 {
1423 struct listnode *node;
1424 struct listnode *pn;
1425 struct connected *ifc;
1426 struct prefix *p;
1427 struct ospf_snmp_if *osif;
1428 struct in_addr *addr;
1429 ifindex_t ifindex;
1430
1431 ospf_snmp_if_delete(ifp);
1432
1433 p = NULL;
1434 addr = NULL;
1435 ifindex = 0;
1436
1437 /* Lookup first IPv4 address entry. */
1438 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
1439 p = CONNECTED_ID(ifc);
1440
1441 if (p->family == AF_INET) {
1442 addr = &p->u.prefix4;
1443 break;
1444 }
1445 }
1446 if (!addr)
1447 ifindex = ifp->ifindex;
1448
1449 /* Add interface to the list. */
1450 pn = NULL;
1451 for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, node, osif)) {
1452 if (addr) {
1453 /* Usual interfaces --> Sort them based on interface
1454 * IPv4 addresses */
1455 if (ntohl(osif->addr.s_addr) > ntohl(addr->s_addr))
1456 break;
1457 } else {
1458 /* Unnumbered interfaces --> Sort them based on
1459 * interface indexes */
1460 if (osif->addr.s_addr != 0 || osif->ifindex > ifindex)
1461 break;
1462 }
1463 pn = node;
1464 }
1465
1466 osif = ospf_snmp_if_new();
1467 if (addr) /* Usual interface */
1468 {
1469 osif->addr = *addr;
1470
1471 /* This field is used for storing ospfAddressLessIf OID value,
1472 * conform to RFC1850 OSPF-MIB specification, it must be 0 for
1473 * usual interface */
1474 osif->ifindex = 0;
1475 } else /* Unnumbered interface */
1476 osif->ifindex = ifindex;
1477 osif->ifp = ifp;
1478
1479 listnode_add_after(ospf_snmp_iflist, pn, osif);
1480 return 0;
1481 }
1482
1483 static int ospf_snmp_is_if_have_addr(struct interface *ifp)
1484 {
1485 struct listnode *nn;
1486 struct connected *ifc;
1487
1488 /* Is this interface having any connected IPv4 address ? */
1489 for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, ifc)) {
1490 if (CONNECTED_PREFIX(ifc)->family == AF_INET)
1491 return 1;
1492 }
1493
1494 return 0;
1495 }
1496
1497 static struct ospf_interface *ospf_snmp_if_lookup(struct in_addr *ifaddr,
1498 ifindex_t *ifindex)
1499 {
1500 struct listnode *node;
1501 struct ospf_snmp_if *osif;
1502 struct ospf_interface *oi = NULL;
1503 struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1504
1505 for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, node, osif)) {
1506 if (ifaddr->s_addr) {
1507 if (IPV4_ADDR_SAME(&osif->addr, ifaddr))
1508 oi = ospf_if_lookup_by_local_addr(
1509 ospf, osif->ifp, *ifaddr);
1510 } else {
1511 if (osif->ifindex == *ifindex)
1512 oi = ospf_if_lookup_by_local_addr(
1513 ospf, osif->ifp, *ifaddr);
1514 }
1515 }
1516 return oi;
1517 }
1518
1519 static struct ospf_interface *ospf_snmp_if_lookup_next(struct in_addr *ifaddr,
1520 ifindex_t *ifindex,
1521 int ifaddr_next,
1522 ifindex_t ifindex_next)
1523 {
1524 struct ospf_snmp_if *osif;
1525 struct listnode *nn;
1526 struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1527 struct ospf_interface *oi = NULL;
1528
1529 if (ospf == NULL)
1530 return NULL;
1531
1532 /* No instance is specified --> Return the first OSPF interface */
1533 if (ifaddr_next) {
1534 for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, nn, osif)) {
1535 osif = listgetdata(nn);
1536 *ifaddr = osif->addr;
1537 *ifindex = osif->ifindex;
1538 /* Because no instance is specified, we don't care about
1539 * the kind of
1540 * interface (usual or unnumbered), just returning the
1541 * first valid
1542 * OSPF interface */
1543 oi = ospf_if_lookup_by_local_addr(ospf, osif->ifp,
1544 *ifaddr);
1545 if (oi)
1546 return (oi);
1547 }
1548 return NULL;
1549 }
1550
1551 /* An instance is specified --> Return the next OSPF interface */
1552 for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, nn, osif)) {
1553 /* Usual interface */
1554 if (ifaddr->s_addr) {
1555 /* The interface must have valid AF_INET connected
1556 * address */
1557 /* it must have lager IPv4 address value than the lookup
1558 * entry */
1559 if ((ospf_snmp_is_if_have_addr(osif->ifp))
1560 && (ntohl(osif->addr.s_addr)
1561 > ntohl(ifaddr->s_addr))) {
1562 *ifaddr = osif->addr;
1563 *ifindex = osif->ifindex;
1564
1565 /* and it must be an OSPF interface */
1566 oi = ospf_if_lookup_by_local_addr(
1567 ospf, osif->ifp, *ifaddr);
1568 if (oi)
1569 return oi;
1570 }
1571 }
1572 /* Unnumbered interface */
1573 else
1574 /* The interface must NOT have valid AF_INET connected
1575 address */
1576 /* it must have lager interface index than the lookup
1577 entry */
1578 if ((!ospf_snmp_is_if_have_addr(osif->ifp))
1579 && (osif->ifindex > *ifindex)) {
1580 *ifaddr = osif->addr;
1581 *ifindex = osif->ifindex;
1582
1583 /* and it must be an OSPF interface */
1584 oi = ospf_if_lookup_by_local_addr(ospf, osif->ifp,
1585 *ifaddr);
1586 if (oi)
1587 return oi;
1588 }
1589 }
1590 return NULL;
1591 }
1592
1593 static int ospf_snmp_iftype(struct interface *ifp)
1594 {
1595 #define ospf_snmp_iftype_broadcast 1
1596 #define ospf_snmp_iftype_nbma 2
1597 #define ospf_snmp_iftype_pointToPoint 3
1598 #define ospf_snmp_iftype_pointToMultipoint 5
1599 if (if_is_broadcast(ifp))
1600 return ospf_snmp_iftype_broadcast;
1601 if (if_is_pointopoint(ifp))
1602 return ospf_snmp_iftype_pointToPoint;
1603 return ospf_snmp_iftype_broadcast;
1604 }
1605
1606 static struct ospf_interface *ospfIfLookup(struct variable *v, oid *name,
1607 size_t *length,
1608 struct in_addr *ifaddr,
1609 ifindex_t *ifindex, int exact)
1610 {
1611 unsigned int len;
1612 int ifaddr_next = 0;
1613 ifindex_t ifindex_next = 0;
1614 struct ospf_interface *oi;
1615 oid *offset;
1616
1617 if (exact) {
1618 if (*length != v->namelen + IN_ADDR_SIZE + 1)
1619 return NULL;
1620
1621 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, ifaddr);
1622 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1623
1624 return ospf_snmp_if_lookup(ifaddr, ifindex);
1625 } else {
1626 len = *length - v->namelen;
1627 if (len >= IN_ADDR_SIZE)
1628 len = IN_ADDR_SIZE;
1629 if (len == 0)
1630 ifaddr_next = 1;
1631
1632 oid2in_addr(name + v->namelen, len, ifaddr);
1633
1634 len = *length - v->namelen - IN_ADDR_SIZE;
1635 if (len >= 1)
1636 len = 1;
1637 else
1638 ifindex_next = 1;
1639
1640 if (len == 1)
1641 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1642
1643 oi = ospf_snmp_if_lookup_next(ifaddr, ifindex, ifaddr_next,
1644 ifindex_next);
1645 if (oi) {
1646 *length = v->namelen + IN_ADDR_SIZE + 1;
1647 offset = name + v->namelen;
1648 oid_copy_addr(offset, ifaddr, IN_ADDR_SIZE);
1649 offset += IN_ADDR_SIZE;
1650 *offset = *ifindex;
1651 return oi;
1652 }
1653 }
1654 return NULL;
1655 }
1656
1657 static uint8_t *ospfIfEntry(struct variable *v, oid *name, size_t *length,
1658 int exact, size_t *var_len,
1659 WriteMethod **write_method)
1660 {
1661 ifindex_t ifindex;
1662 struct in_addr ifaddr;
1663 struct ospf_interface *oi;
1664 struct ospf *ospf;
1665
1666 if (smux_header_table(v, name, length, exact, var_len, write_method)
1667 == MATCH_FAILED)
1668 return NULL;
1669
1670 ifindex = 0;
1671 memset(&ifaddr, 0, sizeof(struct in_addr));
1672
1673 /* Check OSPF instance. */
1674 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1675 if (ospf == NULL)
1676 return NULL;
1677
1678 oi = ospfIfLookup(v, name, length, &ifaddr, &ifindex, exact);
1679 if (oi == NULL)
1680 return NULL;
1681
1682 /* Return the current value of the variable */
1683 switch (v->magic) {
1684 case OSPFIFIPADDRESS: /* 1 */
1685 return SNMP_IPADDRESS(ifaddr);
1686 break;
1687 case OSPFADDRESSLESSIF: /* 2 */
1688 return SNMP_INTEGER(ifindex);
1689 break;
1690 case OSPFIFAREAID: /* 3 */
1691 if (oi->area)
1692 return SNMP_IPADDRESS(oi->area->area_id);
1693 else
1694 return SNMP_IPADDRESS(ospf_empty_addr);
1695 break;
1696 case OSPFIFTYPE: /* 4 */
1697 return SNMP_INTEGER(ospf_snmp_iftype(oi->ifp));
1698 break;
1699 case OSPFIFADMINSTAT: /* 5 */
1700 if (oi)
1701 return SNMP_INTEGER(OSPF_STATUS_ENABLED);
1702 else
1703 return SNMP_INTEGER(OSPF_STATUS_DISABLED);
1704 break;
1705 case OSPFIFRTRPRIORITY: /* 6 */
1706 return SNMP_INTEGER(PRIORITY(oi));
1707 break;
1708 case OSPFIFTRANSITDELAY: /* 7 */
1709 return SNMP_INTEGER(OSPF_IF_PARAM(oi, transmit_delay));
1710 break;
1711 case OSPFIFRETRANSINTERVAL: /* 8 */
1712 return SNMP_INTEGER(OSPF_IF_PARAM(oi, retransmit_interval));
1713 break;
1714 case OSPFIFHELLOINTERVAL: /* 9 */
1715 return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_hello));
1716 break;
1717 case OSPFIFRTRDEADINTERVAL: /* 10 */
1718 return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_wait));
1719 break;
1720 case OSPFIFPOLLINTERVAL: /* 11 */
1721 return SNMP_INTEGER(OSPF_POLL_INTERVAL_DEFAULT);
1722 break;
1723 case OSPFIFSTATE: /* 12 */
1724 return SNMP_INTEGER(ISM_SNMP(oi->state));
1725 break;
1726 case OSPFIFDESIGNATEDROUTER: /* 13 */
1727 return SNMP_IPADDRESS(DR(oi));
1728 break;
1729 case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */
1730 return SNMP_IPADDRESS(BDR(oi));
1731 break;
1732 case OSPFIFEVENTS: /* 15 */
1733 return SNMP_INTEGER(oi->state_change);
1734 break;
1735 case OSPFIFAUTHKEY: /* 16 */
1736 *var_len = 0;
1737 return (uint8_t *)OSPF_IF_PARAM(oi, auth_simple);
1738 break;
1739 case OSPFIFSTATUS: /* 17 */
1740 return SNMP_INTEGER(SNMP_VALID);
1741 break;
1742 case OSPFIFMULTICASTFORWARDING: /* 18 */
1743 #define ospf_snmp_multiforward_blocked 1
1744 #define ospf_snmp_multiforward_multicast 2
1745 #define ospf_snmp_multiforward_unicast 3
1746 return SNMP_INTEGER(ospf_snmp_multiforward_blocked);
1747 break;
1748 case OSPFIFDEMAND: /* 19 */
1749 return SNMP_INTEGER(SNMP_FALSE);
1750 break;
1751 case OSPFIFAUTHTYPE: /* 20 */
1752 if (oi->area)
1753 return SNMP_INTEGER(oi->area->auth_type);
1754 else
1755 return SNMP_INTEGER(0);
1756 break;
1757 default:
1758 return NULL;
1759 break;
1760 }
1761 return NULL;
1762 }
1763
1764 #define OSPF_SNMP_METRIC_VALUE 1
1765
1766 static struct ospf_interface *ospfIfMetricLookup(struct variable *v, oid *name,
1767 size_t *length,
1768 struct in_addr *ifaddr,
1769 ifindex_t *ifindex, int exact)
1770 {
1771 unsigned int len;
1772 int ifaddr_next = 0;
1773 ifindex_t ifindex_next = 0;
1774 struct ospf_interface *oi;
1775 oid *offset;
1776 int metric;
1777
1778 if (exact) {
1779 if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1)
1780 return NULL;
1781
1782 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, ifaddr);
1783 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1784 metric = name[v->namelen + IN_ADDR_SIZE + 1];
1785
1786 if (metric != OSPF_SNMP_METRIC_VALUE)
1787 return NULL;
1788
1789 return ospf_snmp_if_lookup(ifaddr, ifindex);
1790 } else {
1791 len = *length - v->namelen;
1792 if (len >= IN_ADDR_SIZE)
1793 len = IN_ADDR_SIZE;
1794 else
1795 ifaddr_next = 1;
1796
1797 oid2in_addr(name + v->namelen, len, ifaddr);
1798
1799 len = *length - v->namelen - IN_ADDR_SIZE;
1800 if (len >= 1)
1801 len = 1;
1802 else
1803 ifindex_next = 1;
1804
1805 if (len == 1)
1806 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1807
1808 oi = ospf_snmp_if_lookup_next(ifaddr, ifindex, ifaddr_next,
1809 ifindex_next);
1810 if (oi) {
1811 *length = v->namelen + IN_ADDR_SIZE + 1 + 1;
1812 offset = name + v->namelen;
1813 oid_copy_addr(offset, ifaddr, IN_ADDR_SIZE);
1814 offset += IN_ADDR_SIZE;
1815 *offset = *ifindex;
1816 offset++;
1817 *offset = OSPF_SNMP_METRIC_VALUE;
1818 return oi;
1819 }
1820 }
1821 return NULL;
1822 }
1823
1824 static uint8_t *ospfIfMetricEntry(struct variable *v, oid *name, size_t *length,
1825 int exact, size_t *var_len,
1826 WriteMethod **write_method)
1827 {
1828 /* Currently we support metric 1 only. */
1829 ifindex_t ifindex;
1830 struct in_addr ifaddr;
1831 struct ospf_interface *oi;
1832 struct ospf *ospf;
1833
1834 if (smux_header_table(v, name, length, exact, var_len, write_method)
1835 == MATCH_FAILED)
1836 return NULL;
1837
1838 ifindex = 0;
1839 memset(&ifaddr, 0, sizeof(struct in_addr));
1840
1841 /* Check OSPF instance. */
1842 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1843 if (ospf == NULL)
1844 return NULL;
1845
1846 oi = ospfIfMetricLookup(v, name, length, &ifaddr, &ifindex, exact);
1847 if (oi == NULL)
1848 return NULL;
1849
1850 /* Return the current value of the variable */
1851 switch (v->magic) {
1852 case OSPFIFMETRICIPADDRESS:
1853 return SNMP_IPADDRESS(ifaddr);
1854 break;
1855 case OSPFIFMETRICADDRESSLESSIF:
1856 return SNMP_INTEGER(ifindex);
1857 break;
1858 case OSPFIFMETRICTOS:
1859 return SNMP_INTEGER(0);
1860 break;
1861 case OSPFIFMETRICVALUE:
1862 return SNMP_INTEGER(OSPF_SNMP_METRIC_VALUE);
1863 break;
1864 case OSPFIFMETRICSTATUS:
1865 return SNMP_INTEGER(1);
1866 break;
1867 default:
1868 return NULL;
1869 break;
1870 }
1871 return NULL;
1872 }
1873
1874 static struct route_table *ospf_snmp_vl_table;
1875
1876 static int ospf_snmp_vl_add(struct ospf_vl_data *vl_data)
1877 {
1878 struct prefix_ls lp;
1879 struct route_node *rn;
1880
1881 memset(&lp, 0, sizeof(struct prefix_ls));
1882 lp.family = 0;
1883 lp.prefixlen = 64;
1884 lp.id = vl_data->vl_area_id;
1885 lp.adv_router = vl_data->vl_peer;
1886
1887 rn = route_node_get(ospf_snmp_vl_table, (struct prefix *)&lp);
1888 if (rn->info)
1889 route_unlock_node(rn);
1890
1891 rn->info = vl_data;
1892 return 0;
1893 }
1894
1895 static int ospf_snmp_vl_delete(struct ospf_vl_data *vl_data)
1896 {
1897 struct prefix_ls lp;
1898 struct route_node *rn;
1899
1900 memset(&lp, 0, sizeof(struct prefix_ls));
1901 lp.family = 0;
1902 lp.prefixlen = 64;
1903 lp.id = vl_data->vl_area_id;
1904 lp.adv_router = vl_data->vl_peer;
1905
1906 rn = route_node_lookup(ospf_snmp_vl_table, (struct prefix *)&lp);
1907 if (!rn)
1908 return 0;
1909 rn->info = NULL;
1910 route_unlock_node(rn);
1911 route_unlock_node(rn);
1912 return 0;
1913 }
1914
1915 static struct ospf_vl_data *ospf_snmp_vl_lookup(struct in_addr *area_id,
1916 struct in_addr *neighbor)
1917 {
1918 struct prefix_ls lp;
1919 struct route_node *rn;
1920 struct ospf_vl_data *vl_data;
1921
1922 memset(&lp, 0, sizeof(struct prefix_ls));
1923 lp.family = 0;
1924 lp.prefixlen = 64;
1925 lp.id = *area_id;
1926 lp.adv_router = *neighbor;
1927
1928 rn = route_node_lookup(ospf_snmp_vl_table, (struct prefix *)&lp);
1929 if (rn) {
1930 vl_data = rn->info;
1931 route_unlock_node(rn);
1932 return vl_data;
1933 }
1934 return NULL;
1935 }
1936
1937 static struct ospf_vl_data *ospf_snmp_vl_lookup_next(struct in_addr *area_id,
1938 struct in_addr *neighbor,
1939 int first)
1940 {
1941 struct prefix_ls lp;
1942 struct route_node *rn;
1943 struct ospf_vl_data *vl_data;
1944
1945 memset(&lp, 0, sizeof(struct prefix_ls));
1946 lp.family = 0;
1947 lp.prefixlen = 64;
1948 lp.id = *area_id;
1949 lp.adv_router = *neighbor;
1950
1951 if (first)
1952 rn = route_top(ospf_snmp_vl_table);
1953 else {
1954 rn = route_node_get(ospf_snmp_vl_table, (struct prefix *)&lp);
1955 rn = route_next(rn);
1956 }
1957
1958 for (; rn; rn = route_next(rn))
1959 if (rn->info)
1960 break;
1961
1962 if (rn && rn->info) {
1963 vl_data = rn->info;
1964 *area_id = vl_data->vl_area_id;
1965 *neighbor = vl_data->vl_peer;
1966 route_unlock_node(rn);
1967 return vl_data;
1968 }
1969 return NULL;
1970 }
1971
1972 static struct ospf_vl_data *
1973 ospfVirtIfLookup(struct variable *v, oid *name, size_t *length,
1974 struct in_addr *area_id, struct in_addr *neighbor, int exact)
1975 {
1976 int first;
1977 unsigned int len;
1978 struct ospf_vl_data *vl_data;
1979
1980 if (exact) {
1981 if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE)
1982 return NULL;
1983
1984 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, area_id);
1985 oid2in_addr(name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE,
1986 neighbor);
1987
1988 return ospf_snmp_vl_lookup(area_id, neighbor);
1989 } else {
1990 first = 0;
1991
1992 len = *length - v->namelen;
1993 if (len == 0)
1994 first = 1;
1995 if (len > IN_ADDR_SIZE)
1996 len = IN_ADDR_SIZE;
1997 oid2in_addr(name + v->namelen, len, area_id);
1998
1999 len = *length - v->namelen - IN_ADDR_SIZE;
2000 if (len > IN_ADDR_SIZE)
2001 len = IN_ADDR_SIZE;
2002 oid2in_addr(name + v->namelen + IN_ADDR_SIZE, len, neighbor);
2003
2004 vl_data = ospf_snmp_vl_lookup_next(area_id, neighbor, first);
2005
2006 if (vl_data) {
2007 *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
2008 oid_copy_addr(name + v->namelen, area_id, IN_ADDR_SIZE);
2009 oid_copy_addr(name + v->namelen + IN_ADDR_SIZE,
2010 neighbor, IN_ADDR_SIZE);
2011 return vl_data;
2012 }
2013 }
2014 return NULL;
2015 }
2016
2017 static uint8_t *ospfVirtIfEntry(struct variable *v, oid *name, size_t *length,
2018 int exact, size_t *var_len,
2019 WriteMethod **write_method)
2020 {
2021 struct ospf_vl_data *vl_data;
2022 struct ospf_interface *oi;
2023 struct in_addr area_id;
2024 struct in_addr neighbor;
2025
2026 if (smux_header_table(v, name, length, exact, var_len, write_method)
2027 == MATCH_FAILED)
2028 return NULL;
2029
2030 memset(&area_id, 0, sizeof(struct in_addr));
2031 memset(&neighbor, 0, sizeof(struct in_addr));
2032
2033 vl_data = ospfVirtIfLookup(v, name, length, &area_id, &neighbor, exact);
2034 if (!vl_data)
2035 return NULL;
2036 oi = vl_data->vl_oi;
2037 if (!oi)
2038 return NULL;
2039
2040 /* Return the current value of the variable */
2041 switch (v->magic) {
2042 case OSPFVIRTIFAREAID:
2043 return SNMP_IPADDRESS(area_id);
2044 break;
2045 case OSPFVIRTIFNEIGHBOR:
2046 return SNMP_IPADDRESS(neighbor);
2047 break;
2048 case OSPFVIRTIFTRANSITDELAY:
2049 return SNMP_INTEGER(OSPF_IF_PARAM(oi, transmit_delay));
2050 break;
2051 case OSPFVIRTIFRETRANSINTERVAL:
2052 return SNMP_INTEGER(OSPF_IF_PARAM(oi, retransmit_interval));
2053 break;
2054 case OSPFVIRTIFHELLOINTERVAL:
2055 return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_hello));
2056 break;
2057 case OSPFVIRTIFRTRDEADINTERVAL:
2058 return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_wait));
2059 break;
2060 case OSPFVIRTIFSTATE:
2061 return SNMP_INTEGER(oi->state);
2062 break;
2063 case OSPFVIRTIFEVENTS:
2064 return SNMP_INTEGER(oi->state_change);
2065 break;
2066 case OSPFVIRTIFAUTHKEY:
2067 *var_len = 0;
2068 return (uint8_t *)OSPF_IF_PARAM(oi, auth_simple);
2069 break;
2070 case OSPFVIRTIFSTATUS:
2071 return SNMP_INTEGER(SNMP_VALID);
2072 break;
2073 case OSPFVIRTIFAUTHTYPE:
2074 if (oi->area)
2075 return SNMP_INTEGER(oi->area->auth_type);
2076 else
2077 return SNMP_INTEGER(0);
2078 break;
2079 default:
2080 return NULL;
2081 break;
2082 }
2083 return NULL;
2084 }
2085
2086 static struct ospf_neighbor *ospf_snmp_nbr_lookup(struct ospf *ospf,
2087 struct in_addr *nbr_addr,
2088 ifindex_t *ifindex)
2089 {
2090 struct listnode *node, *nnode;
2091 struct ospf_interface *oi;
2092 struct ospf_neighbor *nbr;
2093 struct route_node *rn;
2094
2095 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
2096 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
2097 if ((nbr = rn->info) != NULL && nbr != oi->nbr_self
2098 /* If EXACT match is needed, provide ALL entry found
2099 && nbr->state != NSM_Down
2100 */
2101 && nbr->src.s_addr != 0) {
2102 if (IPV4_ADDR_SAME(&nbr->src, nbr_addr)) {
2103 route_unlock_node(rn);
2104 return nbr;
2105 }
2106 }
2107 }
2108 return NULL;
2109 }
2110
2111 static struct ospf_neighbor *ospf_snmp_nbr_lookup_next(struct in_addr *nbr_addr,
2112 ifindex_t *ifindex,
2113 int first)
2114 {
2115 struct listnode *nn;
2116 struct ospf_interface *oi;
2117 struct ospf_neighbor *nbr;
2118 struct route_node *rn;
2119 struct ospf_neighbor *min = NULL;
2120 struct ospf *ospf;
2121
2122 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2123
2124 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, nn, oi)) {
2125 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
2126 if ((nbr = rn->info) != NULL && nbr != oi->nbr_self
2127 && nbr->state != NSM_Down && nbr->src.s_addr != 0) {
2128 if (first) {
2129 if (!min)
2130 min = nbr;
2131 else if (ntohl(nbr->src.s_addr)
2132 < ntohl(min->src.s_addr))
2133 min = nbr;
2134 } else if (ntohl(nbr->src.s_addr)
2135 > ntohl(nbr_addr->s_addr)) {
2136 if (!min)
2137 min = nbr;
2138 else if (ntohl(nbr->src.s_addr)
2139 < ntohl(min->src.s_addr))
2140 min = nbr;
2141 }
2142 }
2143 }
2144 if (min) {
2145 *nbr_addr = min->src;
2146 *ifindex = 0;
2147 return min;
2148 }
2149 return NULL;
2150 }
2151
2152 static struct ospf_neighbor *ospfNbrLookup(struct variable *v, oid *name,
2153 size_t *length,
2154 struct in_addr *nbr_addr,
2155 ifindex_t *ifindex, int exact)
2156 {
2157 unsigned int len;
2158 int first;
2159 struct ospf_neighbor *nbr;
2160 struct ospf *ospf;
2161
2162 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2163
2164 if (!ospf)
2165 return NULL;
2166
2167 if (exact) {
2168 if (*length != v->namelen + IN_ADDR_SIZE + 1)
2169 return NULL;
2170
2171 oid2in_addr(name + v->namelen, IN_ADDR_SIZE, nbr_addr);
2172 *ifindex = name[v->namelen + IN_ADDR_SIZE];
2173
2174 return ospf_snmp_nbr_lookup(ospf, nbr_addr, ifindex);
2175 } else {
2176 first = 0;
2177 len = *length - v->namelen;
2178
2179 if (len == 0)
2180 first = 1;
2181
2182 if (len > IN_ADDR_SIZE)
2183 len = IN_ADDR_SIZE;
2184
2185 oid2in_addr(name + v->namelen, len, nbr_addr);
2186
2187 len = *length - v->namelen - IN_ADDR_SIZE;
2188 if (len >= 1)
2189 *ifindex = name[v->namelen + IN_ADDR_SIZE];
2190
2191 nbr = ospf_snmp_nbr_lookup_next(nbr_addr, ifindex, first);
2192
2193 if (nbr) {
2194 *length = v->namelen + IN_ADDR_SIZE + 1;
2195 oid_copy_addr(name + v->namelen, nbr_addr,
2196 IN_ADDR_SIZE);
2197 name[v->namelen + IN_ADDR_SIZE] = *ifindex;
2198 return nbr;
2199 }
2200 }
2201 return NULL;
2202 }
2203
2204 /* map internal quagga neighbor states to official MIB values:
2205
2206 ospfNbrState OBJECT-TYPE
2207 SYNTAX INTEGER {
2208 down (1),
2209 attempt (2),
2210 init (3),
2211 twoWay (4),
2212 exchangeStart (5),
2213 exchange (6),
2214 loading (7),
2215 full (8)
2216 }
2217 */
2218 static int32_t ospf_snmp_neighbor_state(uint8_t nst)
2219 {
2220 switch (nst) {
2221 case NSM_Attempt:
2222 return 2;
2223 case NSM_Init:
2224 return 3;
2225 case NSM_TwoWay:
2226 return 4;
2227 case NSM_ExStart:
2228 return 5;
2229 case NSM_Exchange:
2230 return 6;
2231 case NSM_Loading:
2232 return 7;
2233 case NSM_Full:
2234 return 8;
2235 default:
2236 return 1; /* down */
2237 }
2238 }
2239
2240 static uint8_t *ospfNbrEntry(struct variable *v, oid *name, size_t *length,
2241 int exact, size_t *var_len,
2242 WriteMethod **write_method)
2243 {
2244 struct in_addr nbr_addr;
2245 ifindex_t ifindex;
2246 struct ospf_neighbor *nbr;
2247 struct ospf_interface *oi;
2248
2249 if (smux_header_table(v, name, length, exact, var_len, write_method)
2250 == MATCH_FAILED)
2251 return NULL;
2252
2253 memset(&nbr_addr, 0, sizeof(struct in_addr));
2254 ifindex = 0;
2255
2256 nbr = ospfNbrLookup(v, name, length, &nbr_addr, &ifindex, exact);
2257 if (!nbr)
2258 return NULL;
2259 oi = nbr->oi;
2260 if (!oi)
2261 return NULL;
2262
2263 /* Return the current value of the variable */
2264 switch (v->magic) {
2265 case OSPFNBRIPADDR:
2266 return SNMP_IPADDRESS(nbr_addr);
2267 break;
2268 case OSPFNBRADDRESSLESSINDEX:
2269 return SNMP_INTEGER(ifindex);
2270 break;
2271 case OSPFNBRRTRID:
2272 return SNMP_IPADDRESS(nbr->router_id);
2273 break;
2274 case OSPFNBROPTIONS:
2275 return SNMP_INTEGER(oi->nbr_self->options);
2276 break;
2277 case OSPFNBRPRIORITY:
2278 return SNMP_INTEGER(nbr->priority);
2279 break;
2280 case OSPFNBRSTATE:
2281 return SNMP_INTEGER(ospf_snmp_neighbor_state(nbr->state));
2282 break;
2283 case OSPFNBREVENTS:
2284 return SNMP_INTEGER(nbr->state_change);
2285 break;
2286 case OSPFNBRLSRETRANSQLEN:
2287 return SNMP_INTEGER(ospf_ls_retransmit_count(nbr));
2288 break;
2289 case OSPFNBMANBRSTATUS:
2290 return SNMP_INTEGER(SNMP_VALID);
2291 break;
2292 case OSPFNBMANBRPERMANENCE:
2293 return SNMP_INTEGER(2);
2294 break;
2295 case OSPFNBRHELLOSUPPRESSED:
2296 return SNMP_INTEGER(SNMP_FALSE);
2297 break;
2298 default:
2299 return NULL;
2300 break;
2301 }
2302 return NULL;
2303 }
2304
2305 static uint8_t *ospfVirtNbrEntry(struct variable *v, oid *name, size_t *length,
2306 int exact, size_t *var_len,
2307 WriteMethod **write_method)
2308 {
2309 struct ospf_vl_data *vl_data;
2310 struct in_addr area_id;
2311 struct in_addr neighbor;
2312 struct ospf *ospf;
2313
2314 if (smux_header_table(v, name, length, exact, var_len, write_method)
2315 == MATCH_FAILED)
2316 return NULL;
2317
2318 memset(&area_id, 0, sizeof(struct in_addr));
2319 memset(&neighbor, 0, sizeof(struct in_addr));
2320
2321 /* Check OSPF instance. */
2322 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2323 if (ospf == NULL)
2324 return NULL;
2325
2326 vl_data = ospfVirtIfLookup(v, name, length, &area_id, &neighbor, exact);
2327 if (!vl_data)
2328 return NULL;
2329
2330 /* Return the current value of the variable */
2331 switch (v->magic) {
2332 case OSPFVIRTNBRAREA:
2333 return (uint8_t *)NULL;
2334 break;
2335 case OSPFVIRTNBRRTRID:
2336 return (uint8_t *)NULL;
2337 break;
2338 case OSPFVIRTNBRIPADDR:
2339 return (uint8_t *)NULL;
2340 break;
2341 case OSPFVIRTNBROPTIONS:
2342 return (uint8_t *)NULL;
2343 break;
2344 case OSPFVIRTNBRSTATE:
2345 return (uint8_t *)NULL;
2346 break;
2347 case OSPFVIRTNBREVENTS:
2348 return (uint8_t *)NULL;
2349 break;
2350 case OSPFVIRTNBRLSRETRANSQLEN:
2351 return (uint8_t *)NULL;
2352 break;
2353 case OSPFVIRTNBRHELLOSUPPRESSED:
2354 return (uint8_t *)NULL;
2355 break;
2356 default:
2357 return NULL;
2358 break;
2359 }
2360 return NULL;
2361 }
2362
2363 static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name,
2364 size_t *length, uint8_t *type,
2365 struct in_addr *ls_id,
2366 struct in_addr *router_id, int exact)
2367 {
2368 int first;
2369 oid *offset;
2370 int offsetlen;
2371 uint8_t lsa_type;
2372 unsigned int len;
2373 struct ospf_lsa *lsa;
2374 struct ospf *ospf;
2375
2376 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2377 if (exact) {
2378 if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
2379 return NULL;
2380
2381 offset = name + v->namelen;
2382
2383 /* Make it sure given value match to type. */
2384 lsa_type = *offset;
2385 offset++;
2386
2387 if (lsa_type != *type)
2388 return NULL;
2389
2390 /* LS ID. */
2391 oid2in_addr(offset, IN_ADDR_SIZE, ls_id);
2392 offset += IN_ADDR_SIZE;
2393
2394 /* Router ID. */
2395 oid2in_addr(offset, IN_ADDR_SIZE, router_id);
2396
2397 return ospf_lsdb_lookup_by_id(ospf->lsdb, *type, *ls_id,
2398 *router_id);
2399 } else {
2400 /* Get variable length. */
2401 first = 0;
2402 offset = name + v->namelen;
2403 offsetlen = *length - v->namelen;
2404
2405 /* LSA type value. */
2406 lsa_type = *offset;
2407 offset++;
2408 offsetlen--;
2409
2410 if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA)
2411 first = 1;
2412
2413 /* LS ID. */
2414 len = offsetlen;
2415 if (len > IN_ADDR_SIZE)
2416 len = IN_ADDR_SIZE;
2417
2418 oid2in_addr(offset, len, ls_id);
2419
2420 offset += IN_ADDR_SIZE;
2421 offsetlen -= IN_ADDR_SIZE;
2422
2423 /* Router ID. */
2424 len = offsetlen;
2425 if (len > IN_ADDR_SIZE)
2426 len = IN_ADDR_SIZE;
2427
2428 oid2in_addr(offset, len, router_id);
2429
2430 lsa = ospf_lsdb_lookup_by_id_next(ospf->lsdb, *type, *ls_id,
2431 *router_id, first);
2432
2433 if (lsa) {
2434 /* Fill in length. */
2435 *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE;
2436
2437 /* Fill in value. */
2438 offset = name + v->namelen;
2439
2440 *offset = OSPF_AS_EXTERNAL_LSA;
2441 offset++;
2442 oid_copy_addr(offset, &lsa->data->id, IN_ADDR_SIZE);
2443 offset += IN_ADDR_SIZE;
2444 oid_copy_addr(offset, &lsa->data->adv_router,
2445 IN_ADDR_SIZE);
2446
2447 return lsa;
2448 }
2449 }
2450 return NULL;
2451 }
2452
2453 static uint8_t *ospfExtLsdbEntry(struct variable *v, oid *name, size_t *length,
2454 int exact, size_t *var_len,
2455 WriteMethod **write_method)
2456 {
2457 struct ospf_lsa *lsa;
2458 struct lsa_header *lsah;
2459 uint8_t type;
2460 struct in_addr ls_id;
2461 struct in_addr router_id;
2462 struct ospf *ospf;
2463
2464 if (smux_header_table(v, name, length, exact, var_len, write_method)
2465 == MATCH_FAILED)
2466 return NULL;
2467
2468 type = OSPF_AS_EXTERNAL_LSA;
2469 memset(&ls_id, 0, sizeof(struct in_addr));
2470 memset(&router_id, 0, sizeof(struct in_addr));
2471
2472 /* Check OSPF instance. */
2473 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2474 if (ospf == NULL)
2475 return NULL;
2476
2477 lsa = ospfExtLsdbLookup(v, name, length, &type, &ls_id, &router_id,
2478 exact);
2479 if (!lsa)
2480 return NULL;
2481
2482 lsah = lsa->data;
2483
2484 /* Return the current value of the variable */
2485 switch (v->magic) {
2486 case OSPFEXTLSDBTYPE:
2487 return SNMP_INTEGER(OSPF_AS_EXTERNAL_LSA);
2488 break;
2489 case OSPFEXTLSDBLSID:
2490 return SNMP_IPADDRESS(lsah->id);
2491 break;
2492 case OSPFEXTLSDBROUTERID:
2493 return SNMP_IPADDRESS(lsah->adv_router);
2494 break;
2495 case OSPFEXTLSDBSEQUENCE:
2496 return SNMP_INTEGER(lsah->ls_seqnum);
2497 break;
2498 case OSPFEXTLSDBAGE:
2499 return SNMP_INTEGER(lsah->ls_age);
2500 break;
2501 case OSPFEXTLSDBCHECKSUM:
2502 return SNMP_INTEGER(lsah->checksum);
2503 break;
2504 case OSPFEXTLSDBADVERTISEMENT:
2505 *var_len = ntohs(lsah->length);
2506 return (uint8_t *)lsah;
2507 break;
2508 default:
2509 return NULL;
2510 break;
2511 }
2512 return NULL;
2513 }
2514
2515 static uint8_t *ospfAreaAggregateEntry(struct variable *v, oid *name,
2516 size_t *length, int exact,
2517 size_t *var_len,
2518 WriteMethod **write_method)
2519 {
2520 if (smux_header_table(v, name, length, exact, var_len, write_method)
2521 == MATCH_FAILED)
2522 return NULL;
2523
2524 /* Return the current value of the variable */
2525 switch (v->magic) {
2526 case OSPFAREAAGGREGATEAREAID:
2527 return (uint8_t *)NULL;
2528 break;
2529 case OSPFAREAAGGREGATELSDBTYPE:
2530 return (uint8_t *)NULL;
2531 break;
2532 case OSPFAREAAGGREGATENET:
2533 return (uint8_t *)NULL;
2534 break;
2535 case OSPFAREAAGGREGATEMASK:
2536 return (uint8_t *)NULL;
2537 break;
2538 case OSPFAREAAGGREGATESTATUS:
2539 return (uint8_t *)NULL;
2540 break;
2541 case OSPFAREAAGGREGATEEFFECT:
2542 return (uint8_t *)NULL;
2543 break;
2544 default:
2545 return NULL;
2546 break;
2547 }
2548 return NULL;
2549 }
2550
2551 /* OSPF Traps. */
2552 #define IFSTATECHANGE 16
2553 #define VIRTIFSTATECHANGE 1
2554 #define NBRSTATECHANGE 2
2555 #define VIRTNBRSTATECHANGE 3
2556
2557 static struct trap_object ospfNbrTrapList[] = {{-2, {1, OSPFROUTERID}},
2558 {3, {10, 1, OSPFNBRIPADDR}},
2559 {3, {10, 1, OSPFNBRRTRID}},
2560 {3, {10, 1, OSPFNBRSTATE}}};
2561
2562
2563 static struct trap_object ospfVirtNbrTrapList[] = {
2564 {-2, {1, 1}},
2565 {3, {11, 1, OSPFVIRTNBRAREA}},
2566 {3, {11, 1, OSPFVIRTNBRRTRID}},
2567 {3, {11, 1, OSPFVIRTNBRSTATE}}};
2568
2569 static struct trap_object ospfIfTrapList[] = {{-2, {1, OSPFROUTERID}},
2570 {3, {7, 1, OSPFIFIPADDRESS}},
2571 {3, {7, 1, OSPFADDRESSLESSIF}},
2572 {3, {7, 1, OSPFIFSTATE}}};
2573
2574 static struct trap_object ospfVirtIfTrapList[] = {
2575 {-2, {1, OSPFROUTERID}},
2576 {3, {9, 1, OSPFVIRTIFAREAID}},
2577 {3, {9, 1, OSPFVIRTIFNEIGHBOR}},
2578 {3, {9, 1, OSPFVIRTIFSTATE}}};
2579
2580 static void ospfTrapNbrStateChange(struct ospf_neighbor *on)
2581 {
2582 oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
2583 char msgbuf[16];
2584
2585 ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf));
2586 if (IS_DEBUG_OSPF_EVENT)
2587 zlog_info("%s: trap sent: %s now %s", __PRETTY_FUNCTION__,
2588 inet_ntoa(on->address.u.prefix4), msgbuf);
2589
2590 oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
2591 index[IN_ADDR_SIZE] = 0;
2592
2593 smux_trap(ospf_variables,
2594 sizeof ospf_variables / sizeof(struct variable),
2595 ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
2596 sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
2597 ospfNbrTrapList,
2598 sizeof ospfNbrTrapList / sizeof(struct trap_object),
2599 NBRSTATECHANGE);
2600 }
2601
2602 static void ospfTrapVirtNbrStateChange(struct ospf_neighbor *on)
2603 {
2604 oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
2605
2606 zlog_info("ospfTrapVirtNbrStateChange trap sent");
2607
2608 oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
2609 index[IN_ADDR_SIZE] = 0;
2610
2611 smux_trap(ospf_variables,
2612 sizeof ospf_variables / sizeof(struct variable),
2613 ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
2614 sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
2615 ospfVirtNbrTrapList,
2616 sizeof ospfVirtNbrTrapList / sizeof(struct trap_object),
2617 VIRTNBRSTATECHANGE);
2618 }
2619
2620 static int ospf_snmp_nsm_change(struct ospf_neighbor *nbr, int next_state,
2621 int old_state)
2622 {
2623 /* Terminal state or regression */
2624 if ((next_state == NSM_Full) || (next_state == NSM_TwoWay)
2625 || (next_state < old_state)) {
2626 /* ospfVirtNbrStateChange */
2627 if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK)
2628 ospfTrapVirtNbrStateChange(nbr);
2629 /* ospfNbrStateChange trap */
2630 else
2631 /* To/From FULL, only managed by DR */
2632 if (((next_state != NSM_Full)
2633 && (nbr->state != NSM_Full))
2634 || (nbr->oi->state == ISM_DR))
2635 ospfTrapNbrStateChange(nbr);
2636 }
2637 return 0;
2638 }
2639
2640 static void ospfTrapIfStateChange(struct ospf_interface *oi)
2641 {
2642 oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
2643
2644 if (IS_DEBUG_OSPF_EVENT)
2645 zlog_info("%s: trap sent: %s now %s", __PRETTY_FUNCTION__,
2646 inet_ntoa(oi->address->u.prefix4),
2647 lookup_msg(ospf_ism_state_msg, oi->state, NULL));
2648
2649 oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
2650 index[IN_ADDR_SIZE] = 0;
2651
2652 smux_trap(ospf_variables,
2653 sizeof ospf_variables / sizeof(struct variable),
2654 ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
2655 sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
2656 ospfIfTrapList,
2657 sizeof ospfIfTrapList / sizeof(struct trap_object),
2658 IFSTATECHANGE);
2659 }
2660
2661 static void ospfTrapVirtIfStateChange(struct ospf_interface *oi)
2662 {
2663 oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
2664
2665 zlog_info("ospfTrapVirtIfStateChange trap sent");
2666
2667 oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
2668 index[IN_ADDR_SIZE] = 0;
2669
2670 smux_trap(ospf_variables,
2671 sizeof ospf_variables / sizeof(struct variable),
2672 ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
2673 sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
2674 ospfVirtIfTrapList,
2675 sizeof ospfVirtIfTrapList / sizeof(struct trap_object),
2676 VIRTIFSTATECHANGE);
2677 }
2678
2679 static int ospf_snmp_ism_change(struct ospf_interface *oi, int state,
2680 int old_state)
2681 {
2682 /* Terminal state or regression */
2683 if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther)
2684 || (state == ISM_PointToPoint) || (state < old_state)) {
2685 /* ospfVirtIfStateChange */
2686 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
2687 ospfTrapVirtIfStateChange(oi);
2688 /* ospfIfStateChange */
2689 else
2690 ospfTrapIfStateChange(oi);
2691 }
2692 return 0;
2693 }
2694
2695 /* Register OSPF2-MIB. */
2696 static int ospf_snmp_init(struct thread_master *tm)
2697 {
2698 ospf_snmp_iflist = list_new();
2699 ospf_snmp_vl_table = route_table_init();
2700 smux_init(tm);
2701 REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid);
2702 return 0;
2703 }
2704
2705 static int ospf_snmp_module_init(void)
2706 {
2707 hook_register(ospf_if_update, ospf_snmp_if_update);
2708 hook_register(ospf_if_delete, ospf_snmp_if_delete);
2709 hook_register(ospf_vl_add, ospf_snmp_vl_add);
2710 hook_register(ospf_vl_delete, ospf_snmp_vl_delete);
2711 hook_register(ospf_ism_change, ospf_snmp_ism_change);
2712 hook_register(ospf_nsm_change, ospf_snmp_nsm_change);
2713
2714 hook_register(frr_late_init, ospf_snmp_init);
2715 return 0;
2716 }
2717
2718 FRR_MODULE_SETUP(.name = "ospfd_snmp", .version = FRR_VERSION,
2719 .description = "ospfd AgentX SNMP module",
2720 .init = ospf_snmp_module_init, )