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