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