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