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