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