blob: 739dcae1cdeacffb0f80a7929ff0f72d4df85177 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* OSPFv2 SNMP support
vincentba682532005-09-29 13:52:57 +00002 * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
paul718e3742002-12-13 20:15:29 +00003 * Copyright (C) 2000 IP Infusion Inc.
4 *
5 * Written by Kunihiro Ishiguro <kunihiro@zebra.org>
6 *
7 * This file is part of GNU Zebra.
8 *
9 * GNU Zebra is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
13 *
14 * GNU Zebra is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with GNU Zebra; see the file COPYING. If not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 * 02111-1307, USA.
23 */
24
25#include <zebra.h>
26
27#ifdef HAVE_SNMP
paul07661cb2003-03-18 00:03:05 +000028#include <net-snmp/net-snmp-config.h>
Joakim Tjernlundfb62a3c2008-05-13 20:03:32 +020029#include <net-snmp/net-snmp-includes.h>
paul718e3742002-12-13 20:15:29 +000030
31#include "if.h"
32#include "log.h"
33#include "prefix.h"
34#include "table.h"
35#include "command.h"
36#include "memory.h"
37#include "smux.h"
38
39#include "ospfd/ospfd.h"
40#include "ospfd/ospf_interface.h"
41#include "ospfd/ospf_asbr.h"
42#include "ospfd/ospf_lsa.h"
43#include "ospfd/ospf_lsdb.h"
44#include "ospfd/ospf_abr.h"
45#include "ospfd/ospf_neighbor.h"
46#include "ospfd/ospf_nsm.h"
47#include "ospfd/ospf_flood.h"
vincente6217872005-09-29 13:56:14 +000048#include "ospfd/ospf_ism.h"
Andrew J. Schorr9aecfae2006-06-24 20:05:02 +000049#include "ospfd/ospf_dump.h"
Chris Caputo0be8dfb2009-06-02 18:40:07 +010050#include "ospfd/ospf_snmp.h"
paul718e3742002-12-13 20:15:29 +000051
52/* OSPF2-MIB. */
53#define OSPF2MIB 1,3,6,1,2,1,14
54
paul718e3742002-12-13 20:15:29 +000055/* OSPF MIB General Group values. */
56#define OSPFROUTERID 1
57#define OSPFADMINSTAT 2
58#define OSPFVERSIONNUMBER 3
59#define OSPFAREABDRRTRSTATUS 4
60#define OSPFASBDRRTRSTATUS 5
61#define OSPFEXTERNLSACOUNT 6
62#define OSPFEXTERNLSACKSUMSUM 7
63#define OSPFTOSSUPPORT 8
64#define OSPFORIGINATENEWLSAS 9
65#define OSPFRXNEWLSAS 10
66#define OSPFEXTLSDBLIMIT 11
67#define OSPFMULTICASTEXTENSIONS 12
68#define OSPFEXITOVERFLOWINTERVAL 13
69#define OSPFDEMANDEXTENSIONS 14
70
71/* OSPF MIB ospfAreaTable. */
72#define OSPFAREAID 1
73#define OSPFAUTHTYPE 2
74#define OSPFIMPORTASEXTERN 3
75#define OSPFSPFRUNS 4
76#define OSPFAREABDRRTRCOUNT 5
77#define OSPFASBDRRTRCOUNT 6
78#define OSPFAREALSACOUNT 7
79#define OSPFAREALSACKSUMSUM 8
80#define OSPFAREASUMMARY 9
81#define OSPFAREASTATUS 10
82
83/* OSPF MIB ospfStubAreaTable. */
84#define OSPFSTUBAREAID 1
85#define OSPFSTUBTOS 2
86#define OSPFSTUBMETRIC 3
87#define OSPFSTUBSTATUS 4
88#define OSPFSTUBMETRICTYPE 5
89
90/* OSPF MIB ospfLsdbTable. */
91#define OSPFLSDBAREAID 1
92#define OSPFLSDBTYPE 2
93#define OSPFLSDBLSID 3
94#define OSPFLSDBROUTERID 4
95#define OSPFLSDBSEQUENCE 5
96#define OSPFLSDBAGE 6
97#define OSPFLSDBCHECKSUM 7
98#define OSPFLSDBADVERTISEMENT 8
99
100/* OSPF MIB ospfAreaRangeTable. */
101#define OSPFAREARANGEAREAID 1
102#define OSPFAREARANGENET 2
103#define OSPFAREARANGEMASK 3
104#define OSPFAREARANGESTATUS 4
105#define OSPFAREARANGEEFFECT 5
106
107/* OSPF MIB ospfHostTable. */
108#define OSPFHOSTIPADDRESS 1
109#define OSPFHOSTTOS 2
110#define OSPFHOSTMETRIC 3
111#define OSPFHOSTSTATUS 4
112#define OSPFHOSTAREAID 5
113
114/* OSPF MIB ospfIfTable. */
115#define OSPFIFIPADDRESS 1
116#define OSPFADDRESSLESSIF 2
117#define OSPFIFAREAID 3
118#define OSPFIFTYPE 4
119#define OSPFIFADMINSTAT 5
120#define OSPFIFRTRPRIORITY 6
121#define OSPFIFTRANSITDELAY 7
122#define OSPFIFRETRANSINTERVAL 8
123#define OSPFIFHELLOINTERVAL 9
124#define OSPFIFRTRDEADINTERVAL 10
125#define OSPFIFPOLLINTERVAL 11
126#define OSPFIFSTATE 12
127#define OSPFIFDESIGNATEDROUTER 13
128#define OSPFIFBACKUPDESIGNATEDROUTER 14
129#define OSPFIFEVENTS 15
130#define OSPFIFAUTHKEY 16
131#define OSPFIFSTATUS 17
132#define OSPFIFMULTICASTFORWARDING 18
133#define OSPFIFDEMAND 19
134#define OSPFIFAUTHTYPE 20
135
136/* OSPF MIB ospfIfMetricTable. */
137#define OSPFIFMETRICIPADDRESS 1
138#define OSPFIFMETRICADDRESSLESSIF 2
139#define OSPFIFMETRICTOS 3
140#define OSPFIFMETRICVALUE 4
141#define OSPFIFMETRICSTATUS 5
142
143/* OSPF MIB ospfVirtIfTable. */
144#define OSPFVIRTIFAREAID 1
145#define OSPFVIRTIFNEIGHBOR 2
146#define OSPFVIRTIFTRANSITDELAY 3
147#define OSPFVIRTIFRETRANSINTERVAL 4
148#define OSPFVIRTIFHELLOINTERVAL 5
149#define OSPFVIRTIFRTRDEADINTERVAL 6
150#define OSPFVIRTIFSTATE 7
151#define OSPFVIRTIFEVENTS 8
152#define OSPFVIRTIFAUTHKEY 9
153#define OSPFVIRTIFSTATUS 10
154#define OSPFVIRTIFAUTHTYPE 11
155
156/* OSPF MIB ospfNbrTable. */
157#define OSPFNBRIPADDR 1
158#define OSPFNBRADDRESSLESSINDEX 2
159#define OSPFNBRRTRID 3
160#define OSPFNBROPTIONS 4
161#define OSPFNBRPRIORITY 5
162#define OSPFNBRSTATE 6
163#define OSPFNBREVENTS 7
164#define OSPFNBRLSRETRANSQLEN 8
165#define OSPFNBMANBRSTATUS 9
166#define OSPFNBMANBRPERMANENCE 10
167#define OSPFNBRHELLOSUPPRESSED 11
168
169/* OSPF MIB ospfVirtNbrTable. */
170#define OSPFVIRTNBRAREA 1
171#define OSPFVIRTNBRRTRID 2
172#define OSPFVIRTNBRIPADDR 3
173#define OSPFVIRTNBROPTIONS 4
174#define OSPFVIRTNBRSTATE 5
175#define OSPFVIRTNBREVENTS 6
176#define OSPFVIRTNBRLSRETRANSQLEN 7
177#define OSPFVIRTNBRHELLOSUPPRESSED 8
178
179/* OSPF MIB ospfExtLsdbTable. */
180#define OSPFEXTLSDBTYPE 1
181#define OSPFEXTLSDBLSID 2
182#define OSPFEXTLSDBROUTERID 3
183#define OSPFEXTLSDBSEQUENCE 4
184#define OSPFEXTLSDBAGE 5
185#define OSPFEXTLSDBCHECKSUM 6
186#define OSPFEXTLSDBADVERTISEMENT 7
187
188/* OSPF MIB ospfAreaAggregateTable. */
189#define OSPFAREAAGGREGATEAREAID 1
190#define OSPFAREAAGGREGATELSDBTYPE 2
191#define OSPFAREAAGGREGATENET 3
192#define OSPFAREAAGGREGATEMASK 4
193#define OSPFAREAAGGREGATESTATUS 5
194#define OSPFAREAAGGREGATEEFFECT 6
195
196/* SYNTAX Status from OSPF-MIB. */
197#define OSPF_STATUS_ENABLED 1
198#define OSPF_STATUS_DISABLED 2
199
200/* SNMP value hack. */
201#define COUNTER ASN_COUNTER
202#define INTEGER ASN_INTEGER
203#define GAUGE ASN_GAUGE
204#define TIMETICKS ASN_TIMETICKS
205#define IPADDRESS ASN_IPADDRESS
206#define STRING ASN_OCTET_STR
207
208/* Declare static local variables for convenience. */
209SNMP_LOCAL_VARIABLES
210
211/* OSPF-MIB instances. */
212oid ospf_oid [] = { OSPF2MIB };
paul718e3742002-12-13 20:15:29 +0000213
214/* IP address 0.0.0.0. */
215static struct in_addr ospf_empty_addr = {0};
216
217/* Hook functions. */
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100218static u_char *ospfGeneralGroup (struct variable *, oid *, size_t *,
219 int, size_t *, WriteMethod **);
220static u_char *ospfAreaEntry (struct variable *, oid *, size_t *, int,
221 size_t *, WriteMethod **);
222static u_char *ospfStubAreaEntry (struct variable *, oid *, size_t *,
223 int, size_t *, WriteMethod **);
224static u_char *ospfLsdbEntry (struct variable *, oid *, size_t *, int,
225 size_t *, WriteMethod **);
226static u_char *ospfAreaRangeEntry (struct variable *, oid *, size_t *, int,
227 size_t *, WriteMethod **);
228static u_char *ospfHostEntry (struct variable *, oid *, size_t *, int,
229 size_t *, WriteMethod **);
230static u_char *ospfIfEntry (struct variable *, oid *, size_t *, int,
231 size_t *, WriteMethod **);
232static u_char *ospfIfMetricEntry (struct variable *, oid *, size_t *, int,
233 size_t *, WriteMethod **);
234static u_char *ospfVirtIfEntry (struct variable *, oid *, size_t *, int,
235 size_t *, WriteMethod **);
236static u_char *ospfNbrEntry (struct variable *, oid *, size_t *, int,
237 size_t *, WriteMethod **);
238static u_char *ospfVirtNbrEntry (struct variable *, oid *, size_t *, int,
239 size_t *, WriteMethod **);
240static u_char *ospfExtLsdbEntry (struct variable *, oid *, size_t *, int,
241 size_t *, WriteMethod **);
242static u_char *ospfAreaAggregateEntry (struct variable *, oid *, size_t *,
243 int, size_t *, WriteMethod **);
paul718e3742002-12-13 20:15:29 +0000244
245struct variable ospf_variables[] =
246{
247 /* OSPF general variables */
248 {OSPFROUTERID, IPADDRESS, RWRITE, ospfGeneralGroup,
249 2, {1, 1}},
250 {OSPFADMINSTAT, INTEGER, RWRITE, ospfGeneralGroup,
251 2, {1, 2}},
252 {OSPFVERSIONNUMBER, INTEGER, RONLY, ospfGeneralGroup,
253 2, {1, 3}},
254 {OSPFAREABDRRTRSTATUS, INTEGER, RONLY, ospfGeneralGroup,
255 2, {1, 4}},
256 {OSPFASBDRRTRSTATUS, INTEGER, RWRITE, ospfGeneralGroup,
257 2, {1, 5}},
258 {OSPFEXTERNLSACOUNT, GAUGE, RONLY, ospfGeneralGroup,
259 2, {1, 6}},
260 {OSPFEXTERNLSACKSUMSUM, INTEGER, RONLY, ospfGeneralGroup,
261 2, {1, 7}},
262 {OSPFTOSSUPPORT, INTEGER, RWRITE, ospfGeneralGroup,
263 2, {1, 8}},
264 {OSPFORIGINATENEWLSAS, COUNTER, RONLY, ospfGeneralGroup,
265 2, {1, 9}},
266 {OSPFRXNEWLSAS, COUNTER, RONLY, ospfGeneralGroup,
267 2, {1, 10}},
268 {OSPFEXTLSDBLIMIT, INTEGER, RWRITE, ospfGeneralGroup,
269 2, {1, 11}},
270 {OSPFMULTICASTEXTENSIONS, INTEGER, RWRITE, ospfGeneralGroup,
271 2, {1, 12}},
272 {OSPFEXITOVERFLOWINTERVAL, INTEGER, RWRITE, ospfGeneralGroup,
273 2, {1, 13}},
274 {OSPFDEMANDEXTENSIONS, INTEGER, RWRITE, ospfGeneralGroup,
275 2, {1, 14}},
276
277 /* OSPF area data structure. */
278 {OSPFAREAID, IPADDRESS, RONLY, ospfAreaEntry,
279 3, {2, 1, 1}},
280 {OSPFAUTHTYPE, INTEGER, RWRITE, ospfAreaEntry,
281 3, {2, 1, 2}},
282 {OSPFIMPORTASEXTERN, INTEGER, RWRITE, ospfAreaEntry,
283 3, {2, 1, 3}},
284 {OSPFSPFRUNS, COUNTER, RONLY, ospfAreaEntry,
285 3, {2, 1, 4}},
286 {OSPFAREABDRRTRCOUNT, GAUGE, RONLY, ospfAreaEntry,
287 3, {2, 1, 5}},
288 {OSPFASBDRRTRCOUNT, GAUGE, RONLY, ospfAreaEntry,
289 3, {2, 1, 6}},
290 {OSPFAREALSACOUNT, GAUGE, RONLY, ospfAreaEntry,
291 3, {2, 1, 7}},
292 {OSPFAREALSACKSUMSUM, INTEGER, RONLY, ospfAreaEntry,
293 3, {2, 1, 8}},
294 {OSPFAREASUMMARY, INTEGER, RWRITE, ospfAreaEntry,
295 3, {2, 1, 9}},
296 {OSPFAREASTATUS, INTEGER, RWRITE, ospfAreaEntry,
297 3, {2, 1, 10}},
298
299 /* OSPF stub area information. */
300 {OSPFSTUBAREAID, IPADDRESS, RONLY, ospfStubAreaEntry,
301 3, {3, 1, 1}},
302 {OSPFSTUBTOS, INTEGER, RONLY, ospfStubAreaEntry,
303 3, {3, 1, 2}},
304 {OSPFSTUBMETRIC, INTEGER, RWRITE, ospfStubAreaEntry,
305 3, {3, 1, 3}},
306 {OSPFSTUBSTATUS, INTEGER, RWRITE, ospfStubAreaEntry,
307 3, {3, 1, 4}},
308 {OSPFSTUBMETRICTYPE, INTEGER, RWRITE, ospfStubAreaEntry,
309 3, {3, 1, 5}},
310
311 /* OSPF link state database. */
312 {OSPFLSDBAREAID, IPADDRESS, RONLY, ospfLsdbEntry,
313 3, {4, 1, 1}},
314 {OSPFLSDBTYPE, INTEGER, RONLY, ospfLsdbEntry,
315 3, {4, 1, 2}},
316 {OSPFLSDBLSID, IPADDRESS, RONLY, ospfLsdbEntry,
317 3, {4, 1, 3}},
318 {OSPFLSDBROUTERID, IPADDRESS, RONLY, ospfLsdbEntry,
319 3, {4, 1, 4}},
320 {OSPFLSDBSEQUENCE, INTEGER, RONLY, ospfLsdbEntry,
321 3, {4, 1, 5}},
322 {OSPFLSDBAGE, INTEGER, RONLY, ospfLsdbEntry,
323 3, {4, 1, 6}},
324 {OSPFLSDBCHECKSUM, INTEGER, RONLY, ospfLsdbEntry,
325 3, {4, 1, 7}},
326 {OSPFLSDBADVERTISEMENT, STRING, RONLY, ospfLsdbEntry,
327 3, {4, 1, 8}},
328
329 /* Area range table. */
330 {OSPFAREARANGEAREAID, IPADDRESS, RONLY, ospfAreaRangeEntry,
331 3, {5, 1, 1}},
332 {OSPFAREARANGENET, IPADDRESS, RONLY, ospfAreaRangeEntry,
333 3, {5, 1, 2}},
334 {OSPFAREARANGEMASK, IPADDRESS, RWRITE, ospfAreaRangeEntry,
335 3, {5, 1, 3}},
336 {OSPFAREARANGESTATUS, INTEGER, RWRITE, ospfAreaRangeEntry,
337 3, {5, 1, 4}},
338 {OSPFAREARANGEEFFECT, INTEGER, RWRITE, ospfAreaRangeEntry,
339 3, {5, 1, 5}},
340
341 /* OSPF host table. */
342 {OSPFHOSTIPADDRESS, IPADDRESS, RONLY, ospfHostEntry,
343 3, {6, 1, 1}},
344 {OSPFHOSTTOS, INTEGER, RONLY, ospfHostEntry,
345 3, {6, 1, 2}},
346 {OSPFHOSTMETRIC, INTEGER, RWRITE, ospfHostEntry,
347 3, {6, 1, 3}},
348 {OSPFHOSTSTATUS, INTEGER, RWRITE, ospfHostEntry,
349 3, {6, 1, 4}},
350 {OSPFHOSTAREAID, IPADDRESS, RONLY, ospfHostEntry,
351 3, {6, 1, 5}},
352
353 /* OSPF interface table. */
354 {OSPFIFIPADDRESS, IPADDRESS, RONLY, ospfIfEntry,
355 3, {7, 1, 1}},
356 {OSPFADDRESSLESSIF, INTEGER, RONLY, ospfIfEntry,
357 3, {7, 1, 2}},
358 {OSPFIFAREAID, IPADDRESS, RWRITE, ospfIfEntry,
359 3, {7, 1, 3}},
360 {OSPFIFTYPE, INTEGER, RWRITE, ospfIfEntry,
361 3, {7, 1, 4}},
362 {OSPFIFADMINSTAT, INTEGER, RWRITE, ospfIfEntry,
363 3, {7, 1, 5}},
364 {OSPFIFRTRPRIORITY, INTEGER, RWRITE, ospfIfEntry,
365 3, {7, 1, 6}},
366 {OSPFIFTRANSITDELAY, INTEGER, RWRITE, ospfIfEntry,
367 3, {7, 1, 7}},
368 {OSPFIFRETRANSINTERVAL, INTEGER, RWRITE, ospfIfEntry,
369 3, {7, 1, 8}},
370 {OSPFIFHELLOINTERVAL, INTEGER, RWRITE, ospfIfEntry,
371 3, {7, 1, 9}},
372 {OSPFIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfIfEntry,
373 3, {7, 1, 10}},
374 {OSPFIFPOLLINTERVAL, INTEGER, RWRITE, ospfIfEntry,
375 3, {7, 1, 11}},
376 {OSPFIFSTATE, INTEGER, RONLY, ospfIfEntry,
377 3, {7, 1, 12}},
378 {OSPFIFDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry,
379 3, {7, 1, 13}},
380 {OSPFIFBACKUPDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry,
381 3, {7, 1, 14}},
382 {OSPFIFEVENTS, COUNTER, RONLY, ospfIfEntry,
383 3, {7, 1, 15}},
384 {OSPFIFAUTHKEY, STRING, RWRITE, ospfIfEntry,
385 3, {7, 1, 16}},
386 {OSPFIFSTATUS, INTEGER, RWRITE, ospfIfEntry,
387 3, {7, 1, 17}},
388 {OSPFIFMULTICASTFORWARDING, INTEGER, RWRITE, ospfIfEntry,
389 3, {7, 1, 18}},
390 {OSPFIFDEMAND, INTEGER, RWRITE, ospfIfEntry,
391 3, {7, 1, 19}},
392 {OSPFIFAUTHTYPE, INTEGER, RWRITE, ospfIfEntry,
393 3, {7, 1, 20}},
394
395 /* OSPF interface metric table. */
396 {OSPFIFMETRICIPADDRESS, IPADDRESS, RONLY, ospfIfMetricEntry,
397 3, {8, 1, 1}},
398 {OSPFIFMETRICADDRESSLESSIF, INTEGER, RONLY, ospfIfMetricEntry,
399 3, {8, 1, 2}},
400 {OSPFIFMETRICTOS, INTEGER, RONLY, ospfIfMetricEntry,
401 3, {8, 1, 3}},
402 {OSPFIFMETRICVALUE, INTEGER, RWRITE, ospfIfMetricEntry,
403 3, {8, 1, 4}},
404 {OSPFIFMETRICSTATUS, INTEGER, RWRITE, ospfIfMetricEntry,
405 3, {8, 1, 5}},
406
407 /* OSPF virtual interface table. */
408 {OSPFVIRTIFAREAID, IPADDRESS, RONLY, ospfVirtIfEntry,
409 3, {9, 1, 1}},
410 {OSPFVIRTIFNEIGHBOR, IPADDRESS, RONLY, ospfVirtIfEntry,
411 3, {9, 1, 2}},
412 {OSPFVIRTIFTRANSITDELAY, INTEGER, RWRITE, ospfVirtIfEntry,
413 3, {9, 1, 3}},
414 {OSPFVIRTIFRETRANSINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
415 3, {9, 1, 4}},
416 {OSPFVIRTIFHELLOINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
417 3, {9, 1, 5}},
418 {OSPFVIRTIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
419 3, {9, 1, 6}},
420 {OSPFVIRTIFSTATE, INTEGER, RONLY, ospfVirtIfEntry,
421 3, {9, 1, 7}},
422 {OSPFVIRTIFEVENTS, COUNTER, RONLY, ospfVirtIfEntry,
423 3, {9, 1, 8}},
424 {OSPFVIRTIFAUTHKEY, STRING, RWRITE, ospfVirtIfEntry,
425 3, {9, 1, 9}},
426 {OSPFVIRTIFSTATUS, INTEGER, RWRITE, ospfVirtIfEntry,
427 3, {9, 1, 10}},
428 {OSPFVIRTIFAUTHTYPE, INTEGER, RWRITE, ospfVirtIfEntry,
429 3, {9, 1, 11}},
430
431 /* OSPF neighbor table. */
432 {OSPFNBRIPADDR, IPADDRESS, RONLY, ospfNbrEntry,
433 3, {10, 1, 1}},
434 {OSPFNBRADDRESSLESSINDEX, INTEGER, RONLY, ospfNbrEntry,
435 3, {10, 1, 2}},
436 {OSPFNBRRTRID, IPADDRESS, RONLY, ospfNbrEntry,
437 3, {10, 1, 3}},
438 {OSPFNBROPTIONS, INTEGER, RONLY, ospfNbrEntry,
439 3, {10, 1, 4}},
440 {OSPFNBRPRIORITY, INTEGER, RWRITE, ospfNbrEntry,
441 3, {10, 1, 5}},
442 {OSPFNBRSTATE, INTEGER, RONLY, ospfNbrEntry,
443 3, {10, 1, 6}},
444 {OSPFNBREVENTS, COUNTER, RONLY, ospfNbrEntry,
445 3, {10, 1, 7}},
446 {OSPFNBRLSRETRANSQLEN, GAUGE, RONLY, ospfNbrEntry,
447 3, {10, 1, 8}},
448 {OSPFNBMANBRSTATUS, INTEGER, RWRITE, ospfNbrEntry,
449 3, {10, 1, 9}},
450 {OSPFNBMANBRPERMANENCE, INTEGER, RONLY, ospfNbrEntry,
451 3, {10, 1, 10}},
452 {OSPFNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfNbrEntry,
453 3, {10, 1, 11}},
454
455 /* OSPF virtual neighbor table. */
456 {OSPFVIRTNBRAREA, IPADDRESS, RONLY, ospfVirtNbrEntry,
457 3, {11, 1, 1}},
458 {OSPFVIRTNBRRTRID, IPADDRESS, RONLY, ospfVirtNbrEntry,
459 3, {11, 1, 2}},
460 {OSPFVIRTNBRIPADDR, IPADDRESS, RONLY, ospfVirtNbrEntry,
461 3, {11, 1, 3}},
462 {OSPFVIRTNBROPTIONS, INTEGER, RONLY, ospfVirtNbrEntry,
463 3, {11, 1, 4}},
464 {OSPFVIRTNBRSTATE, INTEGER, RONLY, ospfVirtNbrEntry,
465 3, {11, 1, 5}},
466 {OSPFVIRTNBREVENTS, COUNTER, RONLY, ospfVirtNbrEntry,
467 3, {11, 1, 6}},
468 {OSPFVIRTNBRLSRETRANSQLEN, INTEGER, RONLY, ospfVirtNbrEntry,
469 3, {11, 1, 7}},
470 {OSPFVIRTNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfVirtNbrEntry,
471 3, {11, 1, 8}},
472
473 /* OSPF link state database, external. */
474 {OSPFEXTLSDBTYPE, INTEGER, RONLY, ospfExtLsdbEntry,
475 3, {12, 1, 1}},
476 {OSPFEXTLSDBLSID, IPADDRESS, RONLY, ospfExtLsdbEntry,
477 3, {12, 1, 2}},
478 {OSPFEXTLSDBROUTERID, IPADDRESS, RONLY, ospfExtLsdbEntry,
479 3, {12, 1, 3}},
480 {OSPFEXTLSDBSEQUENCE, INTEGER, RONLY, ospfExtLsdbEntry,
481 3, {12, 1, 4}},
482 {OSPFEXTLSDBAGE, INTEGER, RONLY, ospfExtLsdbEntry,
483 3, {12, 1, 5}},
484 {OSPFEXTLSDBCHECKSUM, INTEGER, RONLY, ospfExtLsdbEntry,
485 3, {12, 1, 6}},
486 {OSPFEXTLSDBADVERTISEMENT, STRING, RONLY, ospfExtLsdbEntry,
487 3, {12, 1, 7}},
488
489 /* OSPF area aggregate table. */
490 {OSPFAREAAGGREGATEAREAID, IPADDRESS, RONLY, ospfAreaAggregateEntry,
491 3, {14, 1, 1}},
492 {OSPFAREAAGGREGATELSDBTYPE, INTEGER, RONLY, ospfAreaAggregateEntry,
493 3, {14, 1, 2}},
494 {OSPFAREAAGGREGATENET, IPADDRESS, RONLY, ospfAreaAggregateEntry,
495 3, {14, 1, 3}},
496 {OSPFAREAAGGREGATEMASK, IPADDRESS, RONLY, ospfAreaAggregateEntry,
497 3, {14, 1, 4}},
498 {OSPFAREAAGGREGATESTATUS, INTEGER, RWRITE, ospfAreaAggregateEntry,
499 3, {14, 1, 5}},
500 {OSPFAREAAGGREGATEEFFECT, INTEGER, RWRITE, ospfAreaAggregateEntry,
501 3, {14, 1, 6}}
502};
503
504/* The administrative status of OSPF. When OSPF is enbled on at least
505 one interface return 1. */
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100506static int
paul68980082003-03-25 05:07:42 +0000507ospf_admin_stat (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000508{
paulaa20c6f2004-10-07 14:19:36 +0000509 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000510 struct ospf_interface *oi;
511
paul68980082003-03-25 05:07:42 +0000512 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000513 return 0;
514
paul1eb8ef22005-04-07 07:30:20 +0000515 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
516 if (oi && oi->address)
517 return 1;
paul718e3742002-12-13 20:15:29 +0000518
paul718e3742002-12-13 20:15:29 +0000519 return 0;
520}
521
522static u_char *
523ospfGeneralGroup (struct variable *v, oid *name, size_t *length,
524 int exact, size_t *var_len, WriteMethod **write_method)
525{
paul020709f2003-04-04 02:44:16 +0000526 struct ospf *ospf;
527
528 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000529
paul718e3742002-12-13 20:15:29 +0000530 /* Check whether the instance identifier is valid */
531 if (smux_header_generic (v, name, length, exact, var_len, write_method)
532 == MATCH_FAILED)
533 return NULL;
534
535 /* Return the current value of the variable */
536 switch (v->magic)
537 {
538 case OSPFROUTERID: /* 1 */
539 /* Router-ID of this OSPF instance. */
paul68980082003-03-25 05:07:42 +0000540 if (ospf)
541 return SNMP_IPADDRESS (ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000542 else
543 return SNMP_IPADDRESS (ospf_empty_addr);
544 break;
545 case OSPFADMINSTAT: /* 2 */
546 /* The administrative status of OSPF in the router. */
paul68980082003-03-25 05:07:42 +0000547 if (ospf_admin_stat (ospf))
paul718e3742002-12-13 20:15:29 +0000548 return SNMP_INTEGER (OSPF_STATUS_ENABLED);
549 else
550 return SNMP_INTEGER (OSPF_STATUS_DISABLED);
551 break;
552 case OSPFVERSIONNUMBER: /* 3 */
553 /* OSPF version 2. */
554 return SNMP_INTEGER (OSPF_VERSION);
555 break;
556 case OSPFAREABDRRTRSTATUS: /* 4 */
557 /* Area Border router status. */
paul68980082003-03-25 05:07:42 +0000558 if (ospf && CHECK_FLAG (ospf->flags, OSPF_FLAG_ABR))
paul718e3742002-12-13 20:15:29 +0000559 return SNMP_INTEGER (SNMP_TRUE);
560 else
561 return SNMP_INTEGER (SNMP_FALSE);
562 break;
563 case OSPFASBDRRTRSTATUS: /* 5 */
564 /* AS Border router status. */
paul68980082003-03-25 05:07:42 +0000565 if (ospf && CHECK_FLAG (ospf->flags, OSPF_FLAG_ASBR))
paul718e3742002-12-13 20:15:29 +0000566 return SNMP_INTEGER (SNMP_TRUE);
567 else
568 return SNMP_INTEGER (SNMP_FALSE);
569 break;
570 case OSPFEXTERNLSACOUNT: /* 6 */
571 /* External LSA counts. */
paul68980082003-03-25 05:07:42 +0000572 if (ospf)
573 return SNMP_INTEGER (ospf_lsdb_count_all (ospf->lsdb));
paul718e3742002-12-13 20:15:29 +0000574 else
575 return SNMP_INTEGER (0);
576 break;
577 case OSPFEXTERNLSACKSUMSUM: /* 7 */
578 /* External LSA checksum. */
579 return SNMP_INTEGER (0);
580 break;
581 case OSPFTOSSUPPORT: /* 8 */
582 /* TOS is not supported. */
583 return SNMP_INTEGER (SNMP_FALSE);
584 break;
585 case OSPFORIGINATENEWLSAS: /* 9 */
586 /* The number of new link-state advertisements. */
paul68980082003-03-25 05:07:42 +0000587 if (ospf)
588 return SNMP_INTEGER (ospf->lsa_originate_count);
paul718e3742002-12-13 20:15:29 +0000589 else
590 return SNMP_INTEGER (0);
591 break;
592 case OSPFRXNEWLSAS: /* 10 */
593 /* The number of link-state advertisements received determined
594 to be new instantiations. */
paul68980082003-03-25 05:07:42 +0000595 if (ospf)
596 return SNMP_INTEGER (ospf->rx_lsa_count);
paul718e3742002-12-13 20:15:29 +0000597 else
598 return SNMP_INTEGER (0);
599 break;
600 case OSPFEXTLSDBLIMIT: /* 11 */
601 /* There is no limit for the number of non-default
602 AS-external-LSAs. */
603 return SNMP_INTEGER (-1);
604 break;
605 case OSPFMULTICASTEXTENSIONS: /* 12 */
606 /* Multicast Extensions to OSPF is not supported. */
607 return SNMP_INTEGER (0);
608 break;
609 case OSPFEXITOVERFLOWINTERVAL: /* 13 */
610 /* Overflow is not supported. */
611 return SNMP_INTEGER (0);
612 break;
613 case OSPFDEMANDEXTENSIONS: /* 14 */
614 /* Demand routing is not supported. */
615 return SNMP_INTEGER (SNMP_FALSE);
616 break;
617 default:
618 return NULL;
619 }
620 return NULL;
621}
622
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100623static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000624ospf_area_lookup_next (struct ospf *ospf, struct in_addr *area_id, int first)
paul718e3742002-12-13 20:15:29 +0000625{
626 struct ospf_area *area;
paulaa20c6f2004-10-07 14:19:36 +0000627 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000628
paul020709f2003-04-04 02:44:16 +0000629 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000630 return NULL;
631
632 if (first)
633 {
paul68980082003-03-25 05:07:42 +0000634 node = listhead (ospf->areas);
paul718e3742002-12-13 20:15:29 +0000635 if (node)
636 {
paul1eb8ef22005-04-07 07:30:20 +0000637 area = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000638 *area_id = area->area_id;
639 return area;
640 }
641 return NULL;
642 }
paul1eb8ef22005-04-07 07:30:20 +0000643 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
paul718e3742002-12-13 20:15:29 +0000644 {
paul718e3742002-12-13 20:15:29 +0000645 if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
646 {
647 *area_id = area->area_id;
648 return area;
649 }
650 }
651 return NULL;
652}
653
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100654static struct ospf_area *
paul718e3742002-12-13 20:15:29 +0000655ospfAreaLookup (struct variable *v, oid name[], size_t *length,
656 struct in_addr *addr, int exact)
657{
paul020709f2003-04-04 02:44:16 +0000658 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000659 struct ospf_area *area;
paul68980082003-03-25 05:07:42 +0000660 int len;
paul718e3742002-12-13 20:15:29 +0000661
paul020709f2003-04-04 02:44:16 +0000662 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000663 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000664 return NULL;
665
666 if (exact)
667 {
668 /* Length is insufficient to lookup OSPF area. */
669 if (*length - v->namelen != sizeof (struct in_addr))
670 return NULL;
671
672 oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
673
paul68980082003-03-25 05:07:42 +0000674 area = ospf_area_lookup_by_area_id (ospf, *addr);
paul718e3742002-12-13 20:15:29 +0000675
676 return area;
677 }
678 else
679 {
680 len = *length - v->namelen;
681 if (len > 4)
682 len = 4;
683
684 oid2in_addr (name + v->namelen, len, addr);
685
paul68980082003-03-25 05:07:42 +0000686 area = ospf_area_lookup_next (ospf, addr, len == 0 ? 1 : 0);
paul718e3742002-12-13 20:15:29 +0000687
688 if (area == NULL)
689 return NULL;
690
691 oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
692 *length = sizeof (struct in_addr) + v->namelen;
693
694 return area;
695 }
696 return NULL;
697}
698
699static u_char *
700ospfAreaEntry (struct variable *v, oid *name, size_t *length, int exact,
701 size_t *var_len, WriteMethod **write_method)
702{
703 struct ospf_area *area;
704 struct in_addr addr;
705
706 memset (&addr, 0, sizeof (struct in_addr));
707
708 area = ospfAreaLookup (v, name, length, &addr, exact);
709 if (! area)
710 return NULL;
711
712 /* Return the current value of the variable */
713 switch (v->magic)
714 {
715 case OSPFAREAID: /* 1 */
716 return SNMP_IPADDRESS (area->area_id);
717 break;
718 case OSPFAUTHTYPE: /* 2 */
719 return SNMP_INTEGER (area->auth_type);
720 break;
721 case OSPFIMPORTASEXTERN: /* 3 */
722 return SNMP_INTEGER (area->external_routing + 1);
723 break;
724 case OSPFSPFRUNS: /* 4 */
725 return SNMP_INTEGER (area->spf_calculation);
726 break;
727 case OSPFAREABDRRTRCOUNT: /* 5 */
728 return SNMP_INTEGER (area->abr_count);
729 break;
730 case OSPFASBDRRTRCOUNT: /* 6 */
731 return SNMP_INTEGER (area->asbr_count);
732 break;
733 case OSPFAREALSACOUNT: /* 7 */
734 return SNMP_INTEGER (area->lsdb->total);
735 break;
736 case OSPFAREALSACKSUMSUM: /* 8 */
737 return SNMP_INTEGER (0);
738 break;
739 case OSPFAREASUMMARY: /* 9 */
740#define OSPF_noAreaSummary 1
741#define OSPF_sendAreaSummary 2
742 if (area->no_summary)
743 return SNMP_INTEGER (OSPF_noAreaSummary);
744 else
745 return SNMP_INTEGER (OSPF_sendAreaSummary);
746 break;
747 case OSPFAREASTATUS: /* 10 */
748 return SNMP_INTEGER (SNMP_VALID);
749 break;
750 default:
751 return NULL;
752 break;
753 }
754 return NULL;
755}
756
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100757static struct ospf_area *
paul718e3742002-12-13 20:15:29 +0000758ospf_stub_area_lookup_next (struct in_addr *area_id, int first)
759{
760 struct ospf_area *area;
paulaa20c6f2004-10-07 14:19:36 +0000761 struct listnode *node;
paul020709f2003-04-04 02:44:16 +0000762 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000763
paul020709f2003-04-04 02:44:16 +0000764 ospf = ospf_lookup ();
765 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000766 return NULL;
767
paul1eb8ef22005-04-07 07:30:20 +0000768 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
paul718e3742002-12-13 20:15:29 +0000769 {
paul718e3742002-12-13 20:15:29 +0000770 if (area->external_routing == OSPF_AREA_STUB)
771 {
772 if (first)
773 {
774 *area_id = area->area_id;
775 return area;
776 }
777 else if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
778 {
779 *area_id = area->area_id;
780 return area;
781 }
782 }
783 }
784 return NULL;
785}
786
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100787static struct ospf_area *
paul718e3742002-12-13 20:15:29 +0000788ospfStubAreaLookup (struct variable *v, oid name[], size_t *length,
789 struct in_addr *addr, int exact)
790{
paul020709f2003-04-04 02:44:16 +0000791 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000792 struct ospf_area *area;
paul68980082003-03-25 05:07:42 +0000793 int len;
paul718e3742002-12-13 20:15:29 +0000794
paul020709f2003-04-04 02:44:16 +0000795 ospf = ospf_lookup ();
796 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000797 return NULL;
798
799 /* Exact lookup. */
800 if (exact)
801 {
802 /* ospfStubAreaID + ospfStubTOS. */
803 if (*length != v->namelen + sizeof (struct in_addr) + 1)
804 return NULL;
805
806 /* Check ospfStubTOS is zero. */
807 if (name[*length - 1] != 0)
808 return NULL;
809
810 oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
811
paul68980082003-03-25 05:07:42 +0000812 area = ospf_area_lookup_by_area_id (ospf, *addr);
paul718e3742002-12-13 20:15:29 +0000813
814 if (area->external_routing == OSPF_AREA_STUB)
815 return area;
816 else
817 return NULL;
818 }
819 else
820 {
821 len = *length - v->namelen;
822 if (len > 4)
823 len = 4;
824
825 oid2in_addr (name + v->namelen, len, addr);
826
827 area = ospf_stub_area_lookup_next (addr, len == 0 ? 1 : 0);
828
829 if (area == NULL)
830 return NULL;
831
832 oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
833 /* Set TOS 0. */
834 name[v->namelen + sizeof (struct in_addr)] = 0;
835 *length = v->namelen + sizeof (struct in_addr) + 1;
836
837 return area;
838 }
839 return NULL;
840}
841
842static u_char *
843ospfStubAreaEntry (struct variable *v, oid *name, size_t *length,
844 int exact, size_t *var_len, WriteMethod **write_method)
845{
846 struct ospf_area *area;
847 struct in_addr addr;
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 {
858 case OSPFSTUBAREAID: /* 1 */
859 /* OSPF stub area id. */
860 return SNMP_IPADDRESS (area->area_id);
861 break;
862 case OSPFSTUBTOS: /* 2 */
863 /* TOS value is not supported. */
864 return SNMP_INTEGER (0);
865 break;
866 case OSPFSTUBMETRIC: /* 3 */
867 /* Default cost to stub area. */
868 return SNMP_INTEGER (area->default_cost);
869 break;
870 case OSPFSTUBSTATUS: /* 4 */
871 /* Status of the stub area. */
872 return SNMP_INTEGER (SNMP_VALID);
873 break;
874 case OSPFSTUBMETRICTYPE: /* 5 */
875 /* OSPF Metric type. */
876#define OSPF_ospfMetric 1
877#define OSPF_comparableCost 2
878#define OSPF_nonComparable 3
879 return SNMP_INTEGER (OSPF_ospfMetric);
880 break;
881 default:
882 return NULL;
883 break;
884 }
885 return NULL;
886}
887
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100888static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +0000889lsdb_lookup_next (struct ospf_area *area, u_char *type, int type_next,
890 struct in_addr *ls_id, int ls_id_next,
891 struct in_addr *router_id, int router_id_next)
892{
893 struct ospf_lsa *lsa;
894 int i;
895
896 if (type_next)
897 i = OSPF_MIN_LSA;
898 else
899 i = *type;
900
vincentba682532005-09-29 13:52:57 +0000901 /* Sanity check, if LSA type unknwon
902 merley skip any LSA */
903 if ((i < OSPF_MIN_LSA) || (i >= OSPF_MAX_LSA))
904 {
905 zlog_debug("Strange request with LSA type %d\n", i);
906 return NULL;
907 }
908
paul718e3742002-12-13 20:15:29 +0000909 for (; i < OSPF_MAX_LSA; i++)
910 {
911 *type = i;
912
913 lsa = ospf_lsdb_lookup_by_id_next (area->lsdb, *type, *ls_id, *router_id,
914 ls_id_next);
915 if (lsa)
916 return lsa;
917
918 ls_id_next = 1;
919 }
920 return NULL;
921}
922
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100923static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +0000924ospfLsdbLookup (struct variable *v, oid *name, size_t *length,
925 struct in_addr *area_id, u_char *type,
926 struct in_addr *ls_id, struct in_addr *router_id, int exact)
927{
paul020709f2003-04-04 02:44:16 +0000928 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000929 struct ospf_area *area;
930 struct ospf_lsa *lsa;
Jorge Boncompte [DTI2]7939e012012-04-09 18:03:57 +0200931 int len;
paul718e3742002-12-13 20:15:29 +0000932 int type_next;
933 int ls_id_next;
934 int router_id_next;
935 oid *offset;
936 int offsetlen;
937
paul020709f2003-04-04 02:44:16 +0000938 ospf = ospf_lookup ();
939
paul718e3742002-12-13 20:15:29 +0000940#define OSPF_LSDB_ENTRY_OFFSET \
941 (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
942
943 if (exact)
944 {
945 /* Area ID + Type + LS ID + Router ID. */
946 if (*length - v->namelen != OSPF_LSDB_ENTRY_OFFSET)
947 return NULL;
948
949 /* Set OID offset for Area ID. */
950 offset = name + v->namelen;
951
952 /* Lookup area first. */
953 oid2in_addr (offset, IN_ADDR_SIZE, area_id);
paul68980082003-03-25 05:07:42 +0000954 area = ospf_area_lookup_by_area_id (ospf, *area_id);
paul718e3742002-12-13 20:15:29 +0000955 if (! area)
956 return NULL;
957 offset += IN_ADDR_SIZE;
958
959 /* Type. */
960 *type = *offset;
961 offset++;
962
963 /* LS ID. */
964 oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
965 offset += IN_ADDR_SIZE;
966
967 /* Router ID. */
968 oid2in_addr (offset, IN_ADDR_SIZE, router_id);
969
970 /* Lookup LSDB. */
971 return ospf_lsdb_lookup_by_id (area->lsdb, *type, *ls_id, *router_id);
972 }
973 else
974 {
975 /* Get variable length. */
976 offset = name + v->namelen;
977 offsetlen = *length - v->namelen;
978 len = offsetlen;
979
980 if (len > IN_ADDR_SIZE)
981 len = IN_ADDR_SIZE;
982
983 oid2in_addr (offset, len, area_id);
984
985 /* First we search area. */
986 if (len == IN_ADDR_SIZE)
paul68980082003-03-25 05:07:42 +0000987 area = ospf_area_lookup_by_area_id (ospf, *area_id);
paul718e3742002-12-13 20:15:29 +0000988 else
Jorge Boncompte [DTI2]7939e012012-04-09 18:03:57 +0200989 area = ospf_area_lookup_next (ospf, area_id, 1);
paul718e3742002-12-13 20:15:29 +0000990
991 if (area == NULL)
992 return NULL;
993
994 do
995 {
996 /* Next we lookup type. */
Jorge Boncompte [DTI2]7939e012012-04-09 18:03:57 +0200997 offset += len;
998 offsetlen -= len;
paul718e3742002-12-13 20:15:29 +0000999 len = offsetlen;
1000
1001 if (len <= 0)
1002 type_next = 1;
1003 else
1004 {
1005 len = 1;
1006 type_next = 0;
1007 *type = *offset;
1008 }
1009
1010 /* LS ID. */
1011 offset++;
1012 offsetlen--;
1013 len = offsetlen;
1014
1015 if (len <= 0)
1016 ls_id_next = 1;
1017 else
1018 {
1019 ls_id_next = 0;
1020 if (len > IN_ADDR_SIZE)
1021 len = IN_ADDR_SIZE;
1022
1023 oid2in_addr (offset, len, ls_id);
1024 }
1025
1026 /* Router ID. */
1027 offset += IN_ADDR_SIZE;
1028 offsetlen -= IN_ADDR_SIZE;
1029 len = offsetlen;
1030
1031 if (len <= 0)
1032 router_id_next = 1;
1033 else
1034 {
1035 router_id_next = 0;
1036 if (len > IN_ADDR_SIZE)
1037 len = IN_ADDR_SIZE;
1038
1039 oid2in_addr (offset, len, router_id);
1040 }
1041
1042 lsa = lsdb_lookup_next (area, type, type_next, ls_id, ls_id_next,
1043 router_id, router_id_next);
1044
1045 if (lsa)
1046 {
1047 /* Fill in length. */
1048 *length = v->namelen + OSPF_LSDB_ENTRY_OFFSET;
1049
1050 /* Fill in value. */
1051 offset = name + v->namelen;
1052 oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
1053 offset += IN_ADDR_SIZE;
1054 *offset = lsa->data->type;
1055 offset++;
1056 oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
1057 offset += IN_ADDR_SIZE;
1058 oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
1059
1060 return lsa;
1061 }
1062 }
paul68980082003-03-25 05:07:42 +00001063 while ((area = ospf_area_lookup_next (ospf, area_id, 0)) != NULL);
paul718e3742002-12-13 20:15:29 +00001064 }
1065 return NULL;
1066}
1067
1068static u_char *
1069ospfLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
1070 size_t *var_len, WriteMethod **write_method)
1071{
1072 struct ospf_lsa *lsa;
1073 struct lsa_header *lsah;
1074 struct in_addr area_id;
1075 u_char type;
1076 struct in_addr ls_id;
1077 struct in_addr router_id;
paul020709f2003-04-04 02:44:16 +00001078 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001079
1080 /* INDEX { ospfLsdbAreaId, ospfLsdbType,
1081 ospfLsdbLsid, ospfLsdbRouterId } */
1082
1083 memset (&area_id, 0, sizeof (struct in_addr));
1084 type = 0;
1085 memset (&ls_id, 0, sizeof (struct in_addr));
1086 memset (&router_id, 0, sizeof (struct in_addr));
1087
1088 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001089 ospf = ospf_lookup ();
1090 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001091 return NULL;
1092
1093 lsa = ospfLsdbLookup (v, name, length, &area_id, &type, &ls_id, &router_id,
1094 exact);
1095 if (! lsa)
1096 return NULL;
1097
1098 lsah = lsa->data;
1099
1100 /* Return the current value of the variable */
1101 switch (v->magic)
1102 {
1103 case OSPFLSDBAREAID: /* 1 */
1104 return SNMP_IPADDRESS (lsa->area->area_id);
1105 break;
1106 case OSPFLSDBTYPE: /* 2 */
1107 return SNMP_INTEGER (lsah->type);
1108 break;
1109 case OSPFLSDBLSID: /* 3 */
1110 return SNMP_IPADDRESS (lsah->id);
1111 break;
1112 case OSPFLSDBROUTERID: /* 4 */
1113 return SNMP_IPADDRESS (lsah->adv_router);
1114 break;
1115 case OSPFLSDBSEQUENCE: /* 5 */
1116 return SNMP_INTEGER (lsah->ls_seqnum);
1117 break;
1118 case OSPFLSDBAGE: /* 6 */
1119 return SNMP_INTEGER (lsah->ls_age);
1120 break;
1121 case OSPFLSDBCHECKSUM: /* 7 */
1122 return SNMP_INTEGER (lsah->checksum);
1123 break;
1124 case OSPFLSDBADVERTISEMENT: /* 8 */
1125 *var_len = ntohs (lsah->length);
1126 return (u_char *) lsah;
1127 break;
1128 default:
1129 return NULL;
1130 break;
1131 }
1132 return NULL;
1133}
1134
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001135static struct ospf_area_range *
paul718e3742002-12-13 20:15:29 +00001136ospfAreaRangeLookup (struct variable *v, oid *name, size_t *length,
1137 struct in_addr *area_id, struct in_addr *range_net,
1138 int exact)
1139{
1140 oid *offset;
1141 int offsetlen;
paul6c835672004-10-11 11:00:30 +00001142 unsigned int len;
paul020709f2003-04-04 02:44:16 +00001143 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001144 struct ospf_area *area;
1145 struct ospf_area_range *range;
1146 struct prefix_ipv4 p;
1147 p.family = AF_INET;
1148 p.prefixlen = IPV4_MAX_BITLEN;
1149
paul020709f2003-04-04 02:44:16 +00001150 ospf = ospf_lookup ();
1151
paul718e3742002-12-13 20:15:29 +00001152 if (exact)
1153 {
1154 /* Area ID + Range Network. */
1155 if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length)
1156 return NULL;
1157
1158 /* Set OID offset for Area ID. */
1159 offset = name + v->namelen;
1160
1161 /* Lookup area first. */
1162 oid2in_addr (offset, IN_ADDR_SIZE, area_id);
1163
paul68980082003-03-25 05:07:42 +00001164 area = ospf_area_lookup_by_area_id (ospf, *area_id);
paul718e3742002-12-13 20:15:29 +00001165 if (! area)
1166 return NULL;
1167
1168 offset += IN_ADDR_SIZE;
1169
1170 /* Lookup area range. */
1171 oid2in_addr (offset, IN_ADDR_SIZE, range_net);
1172 p.prefix = *range_net;
1173
1174 return ospf_area_range_lookup (area, &p);
1175 }
1176 else
1177 {
1178 /* Set OID offset for Area ID. */
1179 offset = name + v->namelen;
1180 offsetlen = *length - v->namelen;
1181
1182 len = offsetlen;
1183 if (len > IN_ADDR_SIZE)
1184 len = IN_ADDR_SIZE;
1185
1186 oid2in_addr (offset, len, area_id);
1187
1188 /* First we search area. */
1189 if (len == IN_ADDR_SIZE)
paul68980082003-03-25 05:07:42 +00001190 area = ospf_area_lookup_by_area_id (ospf,*area_id);
paul718e3742002-12-13 20:15:29 +00001191 else
paul68980082003-03-25 05:07:42 +00001192 area = ospf_area_lookup_next (ospf, area_id, len == 0 ? 1 : 0);
paul718e3742002-12-13 20:15:29 +00001193
1194 if (area == NULL)
1195 return NULL;
1196
1197 do
1198 {
1199 offset += IN_ADDR_SIZE;
1200 offsetlen -= IN_ADDR_SIZE;
1201 len = offsetlen;
1202
1203 if (len < 0)
1204 len = 0;
1205 if (len > IN_ADDR_SIZE)
1206 len = IN_ADDR_SIZE;
1207
1208 oid2in_addr (offset, len, range_net);
1209
1210 range = ospf_area_range_lookup_next (area, range_net,
1211 len == 0 ? 1 : 0);
1212
1213 if (range)
1214 {
1215 /* Fill in length. */
1216 *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
1217
1218 /* Fill in value. */
1219 offset = name + v->namelen;
1220 oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
1221 offset += IN_ADDR_SIZE;
1222 oid_copy_addr (offset, range_net, IN_ADDR_SIZE);
1223
1224 return range;
1225 }
1226 }
paul68980082003-03-25 05:07:42 +00001227 while ((area = ospf_area_lookup_next (ospf, area_id, 0)) != NULL);
paul718e3742002-12-13 20:15:29 +00001228 }
1229 return NULL;
1230}
1231
1232static u_char *
1233ospfAreaRangeEntry (struct variable *v, oid *name, size_t *length, int exact,
1234 size_t *var_len, WriteMethod **write_method)
1235{
1236 struct ospf_area_range *range;
1237 struct in_addr area_id;
1238 struct in_addr range_net;
1239 struct in_addr mask;
paul020709f2003-04-04 02:44:16 +00001240 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001241
1242 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001243 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001244 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001245 return NULL;
1246
1247 memset (&area_id, 0, IN_ADDR_SIZE);
1248 memset (&range_net, 0, IN_ADDR_SIZE);
1249
1250 range = ospfAreaRangeLookup (v, name, length, &area_id, &range_net, exact);
1251 if (! range)
1252 return NULL;
1253
1254 /* Convert prefixlen to network mask format. */
1255 masklen2ip (range->subst_masklen, &mask);
1256
1257 /* Return the current value of the variable */
1258 switch (v->magic)
1259 {
1260 case OSPFAREARANGEAREAID: /* 1 */
1261 return SNMP_IPADDRESS (area_id);
1262 break;
1263 case OSPFAREARANGENET: /* 2 */
1264 return SNMP_IPADDRESS (range_net);
1265 break;
1266 case OSPFAREARANGEMASK: /* 3 */
1267 return SNMP_IPADDRESS (mask);
1268 break;
1269 case OSPFAREARANGESTATUS: /* 4 */
1270 return SNMP_INTEGER (SNMP_VALID);
1271 break;
1272 case OSPFAREARANGEEFFECT: /* 5 */
1273#define OSPF_advertiseMatching 1
1274#define OSPF_doNotAdvertiseMatching 2
1275 return SNMP_INTEGER (OSPF_advertiseMatching);
1276 break;
1277 default:
1278 return NULL;
1279 break;
1280 }
1281 return NULL;
1282}
1283
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001284static struct ospf_nbr_nbma *
paul718e3742002-12-13 20:15:29 +00001285ospfHostLookup (struct variable *v, oid *name, size_t *length,
1286 struct in_addr *addr, int exact)
1287{
1288 int len;
1289 struct ospf_nbr_nbma *nbr_nbma;
paul020709f2003-04-04 02:44:16 +00001290 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001291
paul020709f2003-04-04 02:44:16 +00001292 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001293 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001294 return NULL;
1295
1296 if (exact)
1297 {
1298 /* INDEX { ospfHostIpAddress, ospfHostTOS } */
1299 if (*length != v->namelen + IN_ADDR_SIZE + 1)
1300 return NULL;
1301
1302 /* Check ospfHostTOS. */
1303 if (name[*length - 1] != 0)
1304 return NULL;
1305
1306 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr);
1307
paul68980082003-03-25 05:07:42 +00001308 nbr_nbma = ospf_nbr_nbma_lookup (ospf, *addr);
paul718e3742002-12-13 20:15:29 +00001309
1310 return nbr_nbma;
1311 }
1312 else
1313 {
1314 len = *length - v->namelen;
1315 if (len > 4)
1316 len = 4;
1317
1318 oid2in_addr (name + v->namelen, len, addr);
1319
paul68980082003-03-25 05:07:42 +00001320 nbr_nbma = ospf_nbr_nbma_lookup_next (ospf, addr, len == 0 ? 1 : 0);
paul718e3742002-12-13 20:15:29 +00001321
1322 if (nbr_nbma == NULL)
1323 return NULL;
1324
1325 oid_copy_addr (name + v->namelen, addr, IN_ADDR_SIZE);
1326
1327 /* Set TOS 0. */
1328 name[v->namelen + IN_ADDR_SIZE] = 0;
1329
1330 *length = v->namelen + IN_ADDR_SIZE + 1;
1331
1332 return nbr_nbma;
1333 }
1334 return NULL;
1335}
1336
1337static u_char *
1338ospfHostEntry (struct variable *v, oid *name, size_t *length, int exact,
1339 size_t *var_len, WriteMethod **write_method)
1340{
1341 struct ospf_nbr_nbma *nbr_nbma;
1342 struct ospf_interface *oi;
1343 struct in_addr addr;
paul020709f2003-04-04 02:44:16 +00001344 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001345
1346 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001347 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001348 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001349 return NULL;
1350
1351 memset (&addr, 0, sizeof (struct in_addr));
1352
1353 nbr_nbma = ospfHostLookup (v, name, length, &addr, exact);
1354 if (nbr_nbma == NULL)
1355 return NULL;
1356
1357 oi = nbr_nbma->oi;
1358
1359 /* Return the current value of the variable */
1360 switch (v->magic)
1361 {
1362 case OSPFHOSTIPADDRESS: /* 1 */
1363 return SNMP_IPADDRESS (nbr_nbma->addr);
1364 break;
1365 case OSPFHOSTTOS: /* 2 */
1366 return SNMP_INTEGER (0);
1367 break;
1368 case OSPFHOSTMETRIC: /* 3 */
1369 if (oi)
1370 return SNMP_INTEGER (oi->output_cost);
1371 else
1372 return SNMP_INTEGER (1);
1373 break;
1374 case OSPFHOSTSTATUS: /* 4 */
1375 return SNMP_INTEGER (SNMP_VALID);
1376 break;
1377 case OSPFHOSTAREAID: /* 5 */
1378 if (oi && oi->area)
1379 return SNMP_IPADDRESS (oi->area->area_id);
1380 else
1381 return SNMP_IPADDRESS (ospf_empty_addr);
1382 break;
1383 default:
1384 return NULL;
1385 break;
1386 }
1387 return NULL;
1388}
1389
1390struct list *ospf_snmp_iflist;
1391
1392struct ospf_snmp_if
1393{
1394 struct in_addr addr;
1395 unsigned int ifindex;
1396 struct interface *ifp;
1397};
1398
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001399static struct ospf_snmp_if *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001400ospf_snmp_if_new (void)
paul718e3742002-12-13 20:15:29 +00001401{
Stephen Hemminger393deb92008-08-18 14:13:29 -07001402 return XCALLOC (0, sizeof (struct ospf_snmp_if));
paul718e3742002-12-13 20:15:29 +00001403}
1404
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001405static void
paul718e3742002-12-13 20:15:29 +00001406ospf_snmp_if_free (struct ospf_snmp_if *osif)
1407{
1408 XFREE (0, osif);
1409}
1410
1411void
1412ospf_snmp_if_delete (struct interface *ifp)
1413{
paul1eb8ef22005-04-07 07:30:20 +00001414 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001415 struct ospf_snmp_if *osif;
1416
paul1eb8ef22005-04-07 07:30:20 +00001417 for (ALL_LIST_ELEMENTS (ospf_snmp_iflist, node, nnode, osif))
paul718e3742002-12-13 20:15:29 +00001418 {
1419 if (osif->ifp == ifp)
1420 {
paul1eb8ef22005-04-07 07:30:20 +00001421 list_delete_node (ospf_snmp_iflist, node);
paul718e3742002-12-13 20:15:29 +00001422 ospf_snmp_if_free (osif);
1423 return;
1424 }
1425 }
1426}
1427
1428void
1429ospf_snmp_if_update (struct interface *ifp)
1430{
paul1eb8ef22005-04-07 07:30:20 +00001431 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001432 struct listnode *pn;
1433 struct connected *ifc;
1434 struct prefix *p;
1435 struct ospf_snmp_if *osif;
1436 struct in_addr *addr;
1437 unsigned int ifindex;
1438
1439 ospf_snmp_if_delete (ifp);
1440
1441 p = NULL;
1442 addr = NULL;
1443 ifindex = 0;
1444
1445 /* Lookup first IPv4 address entry. */
paul1eb8ef22005-04-07 07:30:20 +00001446 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
paul718e3742002-12-13 20:15:29 +00001447 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001448 p = CONNECTED_ID(ifc);
paul718e3742002-12-13 20:15:29 +00001449
1450 if (p->family == AF_INET)
1451 {
1452 addr = &p->u.prefix4;
1453 break;
1454 }
1455 }
1456 if (! addr)
1457 ifindex = ifp->ifindex;
1458
1459 /* Add interface to the list. */
1460 pn = NULL;
paul1eb8ef22005-04-07 07:30:20 +00001461 for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, node, osif))
paul718e3742002-12-13 20:15:29 +00001462 {
1463 if (addr)
1464 {
vincent77df1f72005-10-06 07:46:22 +00001465 /* Usual interfaces --> Sort them based on interface IPv4 addresses */
paul718e3742002-12-13 20:15:29 +00001466 if (ntohl (osif->addr.s_addr) > ntohl (addr->s_addr))
1467 break;
1468 }
1469 else
1470 {
vincent77df1f72005-10-06 07:46:22 +00001471 /* Unnumbered interfaces --> Sort them based on interface indexes */
paul718e3742002-12-13 20:15:29 +00001472 if (osif->addr.s_addr != 0 || osif->ifindex > ifindex)
1473 break;
1474 }
paul1eb8ef22005-04-07 07:30:20 +00001475 pn = node;
paul718e3742002-12-13 20:15:29 +00001476 }
1477
1478 osif = ospf_snmp_if_new ();
vincent77df1f72005-10-06 07:46:22 +00001479 if (addr) /* Usual interface */
1480 {
paul718e3742002-12-13 20:15:29 +00001481 osif->addr = *addr;
vincent77df1f72005-10-06 07:46:22 +00001482
1483 /* This field is used for storing ospfAddressLessIf OID value,
1484 * conform to RFC1850 OSPF-MIB specification, it must be 0 for
1485 * usual interface */
1486 osif->ifindex = 0;
1487 }
1488 else /* Unnumbered interface */
paul718e3742002-12-13 20:15:29 +00001489 osif->ifindex = ifindex;
1490 osif->ifp = ifp;
1491
1492 listnode_add_after (ospf_snmp_iflist, pn, osif);
1493}
1494
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001495static int
vincent77df1f72005-10-06 07:46:22 +00001496ospf_snmp_is_if_have_addr (struct interface *ifp)
1497{
vincent77df1f72005-10-06 07:46:22 +00001498 struct listnode *nn;
1499 struct connected *ifc;
1500
1501 /* Is this interface having any connected IPv4 address ? */
1502 for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, ifc))
1503 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001504 if (CONNECTED_PREFIX(ifc)->family == AF_INET)
vincent77df1f72005-10-06 07:46:22 +00001505 return 1;
1506 }
1507
1508 return 0;
1509}
1510
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001511static struct ospf_interface *
paul718e3742002-12-13 20:15:29 +00001512ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex)
1513{
paul1eb8ef22005-04-07 07:30:20 +00001514 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001515 struct ospf_snmp_if *osif;
vincent77df1f72005-10-06 07:46:22 +00001516 struct ospf_interface *oi = NULL;
1517 struct ospf *ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00001518
paul1eb8ef22005-04-07 07:30:20 +00001519 for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, node, osif))
paul718e3742002-12-13 20:15:29 +00001520 {
1521 if (ifaddr->s_addr)
vincent77df1f72005-10-06 07:46:22 +00001522 {
1523 if (IPV4_ADDR_SAME (&osif->addr, ifaddr))
1524 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1525 }
paul718e3742002-12-13 20:15:29 +00001526 else
vincent77df1f72005-10-06 07:46:22 +00001527 {
1528 if (osif->ifindex == *ifindex)
1529 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1530 }
paul718e3742002-12-13 20:15:29 +00001531 }
vincent77df1f72005-10-06 07:46:22 +00001532 return oi;
paul718e3742002-12-13 20:15:29 +00001533}
1534
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001535static struct ospf_interface *
paul718e3742002-12-13 20:15:29 +00001536ospf_snmp_if_lookup_next (struct in_addr *ifaddr, unsigned int *ifindex,
1537 int ifaddr_next, int ifindex_next)
1538{
1539 struct ospf_snmp_if *osif;
1540 struct listnode *nn;
vincent77df1f72005-10-06 07:46:22 +00001541 struct ospf *ospf = ospf_lookup ();
1542 struct ospf_interface *oi = NULL;
paul718e3742002-12-13 20:15:29 +00001543
vincent77df1f72005-10-06 07:46:22 +00001544 if (ospf == NULL)
1545 return NULL;
1546
1547 /* No instance is specified --> Return the first OSPF interface */
paul718e3742002-12-13 20:15:29 +00001548 if (ifaddr_next)
1549 {
vincent77df1f72005-10-06 07:46:22 +00001550 for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, nn, osif))
paul718e3742002-12-13 20:15:29 +00001551 {
paul1eb8ef22005-04-07 07:30:20 +00001552 osif = listgetdata (nn);
paul718e3742002-12-13 20:15:29 +00001553 *ifaddr = osif->addr;
1554 *ifindex = osif->ifindex;
vincent77df1f72005-10-06 07:46:22 +00001555 /* Because no instance is specified, we don't care about the kind of
1556 * interface (usual or unnumbered), just returning the first valid
1557 * OSPF interface */
1558 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1559 if (oi)
1560 return (oi);
paul718e3742002-12-13 20:15:29 +00001561 }
1562 return NULL;
1563 }
1564
vincent77df1f72005-10-06 07:46:22 +00001565 /* An instance is specified --> Return the next OSPF interface */
paul1eb8ef22005-04-07 07:30:20 +00001566 for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, nn, osif))
paul718e3742002-12-13 20:15:29 +00001567 {
vincent77df1f72005-10-06 07:46:22 +00001568 /* Usual interface */
1569 if (ifaddr->s_addr)
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001570 {
1571 /* The interface must have valid AF_INET connected address */
1572 /* it must have lager IPv4 address value than the lookup entry */
1573 if ((ospf_snmp_is_if_have_addr(osif->ifp)) &&
1574 (ntohl (osif->addr.s_addr) > ntohl (ifaddr->s_addr)))
1575 {
1576 *ifaddr = osif->addr;
1577 *ifindex = osif->ifindex;
vincent77df1f72005-10-06 07:46:22 +00001578
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001579 /* and it must be an OSPF interface */
1580 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1581 if (oi)
1582 return oi;
1583 }
1584 }
vincent77df1f72005-10-06 07:46:22 +00001585 /* Unnumbered interface */
1586 else
1587 /* The interface must NOT have valid AF_INET connected address */
1588 /* it must have lager interface index than the lookup entry */
1589 if ((!ospf_snmp_is_if_have_addr(osif->ifp)) &&
1590 (osif->ifindex > *ifindex))
1591 {
1592 *ifaddr = osif->addr;
1593 *ifindex = osif->ifindex;
1594
1595 /* and it must be an OSPF interface */
1596 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1597 if (oi)
1598 return oi;
1599 }
paul718e3742002-12-13 20:15:29 +00001600 }
1601 return NULL;
1602}
1603
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001604static int
paul718e3742002-12-13 20:15:29 +00001605ospf_snmp_iftype (struct interface *ifp)
1606{
1607#define ospf_snmp_iftype_broadcast 1
1608#define ospf_snmp_iftype_nbma 2
1609#define ospf_snmp_iftype_pointToPoint 3
1610#define ospf_snmp_iftype_pointToMultipoint 5
1611 if (if_is_broadcast (ifp))
1612 return ospf_snmp_iftype_broadcast;
1613 if (if_is_pointopoint (ifp))
1614 return ospf_snmp_iftype_pointToPoint;
1615 return ospf_snmp_iftype_broadcast;
1616}
1617
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001618static struct ospf_interface *
paul718e3742002-12-13 20:15:29 +00001619ospfIfLookup (struct variable *v, oid *name, size_t *length,
1620 struct in_addr *ifaddr, unsigned int *ifindex, int exact)
1621{
paul6c835672004-10-11 11:00:30 +00001622 unsigned int len;
paul718e3742002-12-13 20:15:29 +00001623 int ifaddr_next = 0;
1624 int ifindex_next = 0;
vincent77df1f72005-10-06 07:46:22 +00001625 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +00001626 oid *offset;
1627
1628 if (exact)
1629 {
1630 if (*length != v->namelen + IN_ADDR_SIZE + 1)
1631 return NULL;
1632
1633 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
1634 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1635
1636 return ospf_snmp_if_lookup (ifaddr, ifindex);
1637 }
1638 else
1639 {
1640 len = *length - v->namelen;
1641 if (len >= IN_ADDR_SIZE)
1642 len = IN_ADDR_SIZE;
1643 if (len <= 0)
1644 ifaddr_next = 1;
1645
1646 oid2in_addr (name + v->namelen, len, ifaddr);
1647
1648 len = *length - v->namelen - IN_ADDR_SIZE;
1649 if (len >= 1)
1650 len = 1;
1651 else
1652 ifindex_next = 1;
1653
1654 if (len == 1)
1655 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1656
vincent77df1f72005-10-06 07:46:22 +00001657 oi = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
paul718e3742002-12-13 20:15:29 +00001658 ifindex_next);
vincent77df1f72005-10-06 07:46:22 +00001659 if (oi)
paul718e3742002-12-13 20:15:29 +00001660 {
1661 *length = v->namelen + IN_ADDR_SIZE + 1;
1662 offset = name + v->namelen;
1663 oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
1664 offset += IN_ADDR_SIZE;
1665 *offset = *ifindex;
vincent77df1f72005-10-06 07:46:22 +00001666 return oi;
paul718e3742002-12-13 20:15:29 +00001667 }
1668 }
1669 return NULL;
1670}
1671
1672static u_char *
1673ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001674 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00001675{
paul718e3742002-12-13 20:15:29 +00001676 unsigned int ifindex;
1677 struct in_addr ifaddr;
1678 struct ospf_interface *oi;
paul020709f2003-04-04 02:44:16 +00001679 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001680
1681 ifindex = 0;
1682 memset (&ifaddr, 0, sizeof (struct in_addr));
1683
1684 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001685 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001686 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001687 return NULL;
1688
vincent77df1f72005-10-06 07:46:22 +00001689 oi = ospfIfLookup (v, name, length, &ifaddr, &ifindex, exact);
paul718e3742002-12-13 20:15:29 +00001690 if (oi == NULL)
1691 return NULL;
1692
1693 /* Return the current value of the variable */
1694 switch (v->magic)
1695 {
1696 case OSPFIFIPADDRESS: /* 1 */
1697 return SNMP_IPADDRESS (ifaddr);
1698 break;
1699 case OSPFADDRESSLESSIF: /* 2 */
1700 return SNMP_INTEGER (ifindex);
1701 break;
1702 case OSPFIFAREAID: /* 3 */
1703 if (oi->area)
1704 return SNMP_IPADDRESS (oi->area->area_id);
1705 else
1706 return SNMP_IPADDRESS (ospf_empty_addr);
1707 break;
1708 case OSPFIFTYPE: /* 4 */
vincent77df1f72005-10-06 07:46:22 +00001709 return SNMP_INTEGER (ospf_snmp_iftype (oi->ifp));
paul718e3742002-12-13 20:15:29 +00001710 break;
1711 case OSPFIFADMINSTAT: /* 5 */
1712 if (oi)
1713 return SNMP_INTEGER (OSPF_STATUS_ENABLED);
1714 else
1715 return SNMP_INTEGER (OSPF_STATUS_DISABLED);
1716 break;
1717 case OSPFIFRTRPRIORITY: /* 6 */
1718 return SNMP_INTEGER (PRIORITY (oi));
1719 break;
1720 case OSPFIFTRANSITDELAY: /* 7 */
1721 return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
1722 break;
1723 case OSPFIFRETRANSINTERVAL: /* 8 */
1724 return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
1725 break;
1726 case OSPFIFHELLOINTERVAL: /* 9 */
1727 return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
1728 break;
1729 case OSPFIFRTRDEADINTERVAL: /* 10 */
1730 return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
1731 break;
1732 case OSPFIFPOLLINTERVAL: /* 11 */
1733 return SNMP_INTEGER (OSPF_POLL_INTERVAL_DEFAULT);
1734 break;
1735 case OSPFIFSTATE: /* 12 */
vincentba682532005-09-29 13:52:57 +00001736 return SNMP_INTEGER (ISM_SNMP(oi->state));
paul718e3742002-12-13 20:15:29 +00001737 break;
1738 case OSPFIFDESIGNATEDROUTER: /* 13 */
1739 return SNMP_IPADDRESS (DR (oi));
1740 break;
1741 case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */
1742 return SNMP_IPADDRESS (BDR (oi));
1743 break;
1744 case OSPFIFEVENTS: /* 15 */
1745 return SNMP_INTEGER (oi->state_change);
1746 break;
1747 case OSPFIFAUTHKEY: /* 16 */
1748 *var_len = 0;
1749 return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
1750 break;
1751 case OSPFIFSTATUS: /* 17 */
1752 return SNMP_INTEGER (SNMP_VALID);
1753 break;
1754 case OSPFIFMULTICASTFORWARDING: /* 18 */
1755#define ospf_snmp_multiforward_blocked 1
1756#define ospf_snmp_multiforward_multicast 2
1757#define ospf_snmp_multiforward_unicast 3
1758 return SNMP_INTEGER (ospf_snmp_multiforward_blocked);
1759 break;
1760 case OSPFIFDEMAND: /* 19 */
1761 return SNMP_INTEGER (SNMP_FALSE);
1762 break;
1763 case OSPFIFAUTHTYPE: /* 20 */
1764 if (oi->area)
1765 return SNMP_INTEGER (oi->area->auth_type);
1766 else
1767 return SNMP_INTEGER (0);
1768 break;
1769 default:
1770 return NULL;
1771 break;
1772 }
1773 return NULL;
1774}
1775
1776#define OSPF_SNMP_METRIC_VALUE 1
1777
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001778static struct ospf_interface *
paul718e3742002-12-13 20:15:29 +00001779ospfIfMetricLookup (struct variable *v, oid *name, size_t *length,
1780 struct in_addr *ifaddr, unsigned int *ifindex, int exact)
1781{
paul6c835672004-10-11 11:00:30 +00001782 unsigned int len;
paul718e3742002-12-13 20:15:29 +00001783 int ifaddr_next = 0;
1784 int ifindex_next = 0;
vincent77df1f72005-10-06 07:46:22 +00001785 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +00001786 oid *offset;
1787 int metric;
1788
1789 if (exact)
1790 {
1791 if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1)
1792 return NULL;
1793
1794 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
1795 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1796 metric = name[v->namelen + IN_ADDR_SIZE + 1];
1797
1798 if (metric != OSPF_SNMP_METRIC_VALUE)
1799 return NULL;
1800
1801 return ospf_snmp_if_lookup (ifaddr, ifindex);
1802 }
1803 else
1804 {
1805 len = *length - v->namelen;
1806 if (len >= IN_ADDR_SIZE)
1807 len = IN_ADDR_SIZE;
1808 else
1809 ifaddr_next = 1;
1810
1811 oid2in_addr (name + v->namelen, len, ifaddr);
1812
1813 len = *length - v->namelen - IN_ADDR_SIZE;
1814 if (len >= 1)
1815 len = 1;
1816 else
1817 ifindex_next = 1;
1818
1819 if (len == 1)
1820 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1821
vincent77df1f72005-10-06 07:46:22 +00001822 oi = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
paul718e3742002-12-13 20:15:29 +00001823 ifindex_next);
vincent77df1f72005-10-06 07:46:22 +00001824 if (oi)
paul718e3742002-12-13 20:15:29 +00001825 {
1826 *length = v->namelen + IN_ADDR_SIZE + 1 + 1;
1827 offset = name + v->namelen;
1828 oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
1829 offset += IN_ADDR_SIZE;
1830 *offset = *ifindex;
1831 offset++;
1832 *offset = OSPF_SNMP_METRIC_VALUE;
vincent77df1f72005-10-06 07:46:22 +00001833 return oi;
paul718e3742002-12-13 20:15:29 +00001834 }
1835 }
1836 return NULL;
1837}
1838
1839static u_char *
1840ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact,
1841 size_t *var_len, WriteMethod **write_method)
1842{
1843 /* Currently we support metric 1 only. */
paul718e3742002-12-13 20:15:29 +00001844 unsigned int ifindex;
1845 struct in_addr ifaddr;
1846 struct ospf_interface *oi;
paul020709f2003-04-04 02:44:16 +00001847 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001848
1849 ifindex = 0;
1850 memset (&ifaddr, 0, sizeof (struct in_addr));
1851
1852 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001853 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001854 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001855 return NULL;
1856
vincent77df1f72005-10-06 07:46:22 +00001857 oi = ospfIfMetricLookup (v, name, length, &ifaddr, &ifindex, exact);
paul718e3742002-12-13 20:15:29 +00001858 if (oi == NULL)
1859 return NULL;
1860
1861 /* Return the current value of the variable */
1862 switch (v->magic)
1863 {
1864 case OSPFIFMETRICIPADDRESS:
1865 return SNMP_IPADDRESS (ifaddr);
1866 break;
1867 case OSPFIFMETRICADDRESSLESSIF:
1868 return SNMP_INTEGER (ifindex);
1869 break;
1870 case OSPFIFMETRICTOS:
1871 return SNMP_INTEGER (0);
1872 break;
1873 case OSPFIFMETRICVALUE:
1874 return SNMP_INTEGER (OSPF_SNMP_METRIC_VALUE);
1875 break;
1876 case OSPFIFMETRICSTATUS:
1877 return SNMP_INTEGER (1);
1878 break;
1879 default:
1880 return NULL;
1881 break;
1882 }
1883 return NULL;
1884}
1885
1886struct route_table *ospf_snmp_vl_table;
1887
1888void
1889ospf_snmp_vl_add (struct ospf_vl_data *vl_data)
1890{
1891 struct prefix_ls lp;
1892 struct route_node *rn;
1893
1894 memset (&lp, 0, sizeof (struct prefix_ls));
1895 lp.family = 0;
1896 lp.prefixlen = 64;
1897 lp.id = vl_data->vl_area_id;
1898 lp.adv_router = vl_data->vl_peer;
1899
1900 rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
1901 rn->info = vl_data;
1902}
1903
1904void
1905ospf_snmp_vl_delete (struct ospf_vl_data *vl_data)
1906{
1907 struct prefix_ls lp;
1908 struct route_node *rn;
1909
1910 memset (&lp, 0, sizeof (struct prefix_ls));
1911 lp.family = 0;
1912 lp.prefixlen = 64;
1913 lp.id = vl_data->vl_area_id;
1914 lp.adv_router = vl_data->vl_peer;
1915
1916 rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
1917 if (! rn)
1918 return;
1919 rn->info = NULL;
1920 route_unlock_node (rn);
1921 route_unlock_node (rn);
1922}
1923
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001924static struct ospf_vl_data *
paul718e3742002-12-13 20:15:29 +00001925ospf_snmp_vl_lookup (struct in_addr *area_id, struct in_addr *neighbor)
1926{
1927 struct prefix_ls lp;
1928 struct route_node *rn;
1929 struct ospf_vl_data *vl_data;
1930
1931 memset (&lp, 0, sizeof (struct prefix_ls));
1932 lp.family = 0;
1933 lp.prefixlen = 64;
1934 lp.id = *area_id;
1935 lp.adv_router = *neighbor;
1936
1937 rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
1938 if (rn)
1939 {
1940 vl_data = rn->info;
1941 route_unlock_node (rn);
1942 return vl_data;
1943 }
1944 return NULL;
1945}
1946
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001947static struct ospf_vl_data *
paul718e3742002-12-13 20:15:29 +00001948ospf_snmp_vl_lookup_next (struct in_addr *area_id, struct in_addr *neighbor,
1949 int first)
1950{
1951 struct prefix_ls lp;
1952 struct route_node *rn;
1953 struct ospf_vl_data *vl_data;
1954
1955 memset (&lp, 0, sizeof (struct prefix_ls));
1956 lp.family = 0;
1957 lp.prefixlen = 64;
1958 lp.id = *area_id;
1959 lp.adv_router = *neighbor;
1960
1961 if (first)
1962 rn = route_top (ospf_snmp_vl_table);
1963 else
1964 {
1965 rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
1966 rn = route_next (rn);
1967 }
1968
1969 for (; rn; rn = route_next (rn))
1970 if (rn->info)
1971 break;
1972
1973 if (rn && rn->info)
1974 {
1975 vl_data = rn->info;
1976 *area_id = vl_data->vl_area_id;
1977 *neighbor = vl_data->vl_peer;
1978 route_unlock_node (rn);
1979 return vl_data;
1980 }
1981 return NULL;
1982}
1983
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001984static struct ospf_vl_data *
paul718e3742002-12-13 20:15:29 +00001985ospfVirtIfLookup (struct variable *v, oid *name, size_t *length,
1986 struct in_addr *area_id, struct in_addr *neighbor, int exact)
1987{
1988 int first;
paul6c835672004-10-11 11:00:30 +00001989 unsigned int len;
paul718e3742002-12-13 20:15:29 +00001990 struct ospf_vl_data *vl_data;
1991
1992 if (exact)
1993 {
1994 if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE)
1995 return NULL;
1996
1997 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, area_id);
1998 oid2in_addr (name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE, neighbor);
1999
2000 return ospf_snmp_vl_lookup (area_id, neighbor);
2001 }
2002 else
2003 {
2004 first = 0;
2005
2006 len = *length - v->namelen;
2007 if (len <= 0)
2008 first = 1;
2009 if (len > IN_ADDR_SIZE)
2010 len = IN_ADDR_SIZE;
2011 oid2in_addr (name + v->namelen, len, area_id);
2012
2013 len = *length - v->namelen - IN_ADDR_SIZE;
2014 if (len > IN_ADDR_SIZE)
2015 len = IN_ADDR_SIZE;
2016 oid2in_addr (name + v->namelen + IN_ADDR_SIZE, len, neighbor);
2017
2018 vl_data = ospf_snmp_vl_lookup_next (area_id, neighbor, first);
2019
2020 if (vl_data)
2021 {
2022 *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
2023 oid_copy_addr (name + v->namelen, area_id, IN_ADDR_SIZE);
2024 oid_copy_addr (name + v->namelen + IN_ADDR_SIZE, neighbor,
2025 IN_ADDR_SIZE);
2026 return vl_data;
2027 }
2028 }
2029 return NULL;
2030}
2031
2032static u_char *
2033ospfVirtIfEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002034 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00002035{
2036 struct ospf_vl_data *vl_data;
2037 struct ospf_interface *oi;
2038 struct in_addr area_id;
2039 struct in_addr neighbor;
2040
2041 memset (&area_id, 0, sizeof (struct in_addr));
2042 memset (&neighbor, 0, sizeof (struct in_addr));
2043
2044 vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
2045 if (! vl_data)
2046 return NULL;
2047 oi = vl_data->vl_oi;
2048 if (! oi)
2049 return NULL;
2050
2051 /* Return the current value of the variable */
2052 switch (v->magic)
2053 {
2054 case OSPFVIRTIFAREAID:
2055 return SNMP_IPADDRESS (area_id);
2056 break;
2057 case OSPFVIRTIFNEIGHBOR:
2058 return SNMP_IPADDRESS (neighbor);
2059 break;
2060 case OSPFVIRTIFTRANSITDELAY:
2061 return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
2062 break;
2063 case OSPFVIRTIFRETRANSINTERVAL:
2064 return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
2065 break;
2066 case OSPFVIRTIFHELLOINTERVAL:
2067 return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
2068 break;
2069 case OSPFVIRTIFRTRDEADINTERVAL:
2070 return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
2071 break;
2072 case OSPFVIRTIFSTATE:
2073 return SNMP_INTEGER (oi->state);
2074 break;
2075 case OSPFVIRTIFEVENTS:
2076 return SNMP_INTEGER (oi->state_change);
2077 break;
2078 case OSPFVIRTIFAUTHKEY:
2079 *var_len = 0;
2080 return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
2081 break;
2082 case OSPFVIRTIFSTATUS:
2083 return SNMP_INTEGER (SNMP_VALID);
2084 break;
2085 case OSPFVIRTIFAUTHTYPE:
2086 if (oi->area)
2087 return SNMP_INTEGER (oi->area->auth_type);
2088 else
2089 return SNMP_INTEGER (0);
2090 break;
2091 default:
2092 return NULL;
2093 break;
2094 }
2095 return NULL;
2096}
2097
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002098static struct ospf_neighbor *
paul68980082003-03-25 05:07:42 +00002099ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr,
2100 unsigned int *ifindex)
paul718e3742002-12-13 20:15:29 +00002101{
paul1eb8ef22005-04-07 07:30:20 +00002102 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002103 struct ospf_interface *oi;
2104 struct ospf_neighbor *nbr;
2105 struct route_node *rn;
2106
paul1eb8ef22005-04-07 07:30:20 +00002107 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00002108 {
2109 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
2110 if ((nbr = rn->info) != NULL
2111 && nbr != oi->nbr_self
vincent5e4914c2005-09-29 16:34:30 +00002112/* If EXACT match is needed, provide ALL entry found
paul718e3742002-12-13 20:15:29 +00002113 && nbr->state != NSM_Down
vincent5e4914c2005-09-29 16:34:30 +00002114 */
paul718e3742002-12-13 20:15:29 +00002115 && nbr->src.s_addr != 0)
2116 {
2117 if (IPV4_ADDR_SAME (&nbr->src, nbr_addr))
2118 {
2119 route_unlock_node (rn);
2120 return nbr;
2121 }
2122 }
2123 }
2124 return NULL;
2125}
2126
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002127static struct ospf_neighbor *
paul718e3742002-12-13 20:15:29 +00002128ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex,
2129 int first)
2130{
2131 struct listnode *nn;
2132 struct ospf_interface *oi;
2133 struct ospf_neighbor *nbr;
2134 struct route_node *rn;
2135 struct ospf_neighbor *min = NULL;
paul020709f2003-04-04 02:44:16 +00002136 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00002137
paul020709f2003-04-04 02:44:16 +00002138 ospf = ospf_lookup ();
paul1eb8ef22005-04-07 07:30:20 +00002139
2140 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, nn, oi))
paul718e3742002-12-13 20:15:29 +00002141 {
2142 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
2143 if ((nbr = rn->info) != NULL
2144 && nbr != oi->nbr_self
2145 && nbr->state != NSM_Down
2146 && nbr->src.s_addr != 0)
2147 {
2148 if (first)
2149 {
2150 if (! min)
2151 min = nbr;
2152 else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
2153 min = nbr;
2154 }
2155 else if (ntohl (nbr->src.s_addr) > ntohl (nbr_addr->s_addr))
2156 {
2157 if (! min)
2158 min = nbr;
2159 else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
2160 min = nbr;
2161 }
2162 }
2163 }
2164 if (min)
2165 {
2166 *nbr_addr = min->src;
2167 *ifindex = 0;
2168 return min;
2169 }
2170 return NULL;
2171}
2172
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002173static struct ospf_neighbor *
paul718e3742002-12-13 20:15:29 +00002174ospfNbrLookup (struct variable *v, oid *name, size_t *length,
2175 struct in_addr *nbr_addr, unsigned int *ifindex, int exact)
2176{
paul6c835672004-10-11 11:00:30 +00002177 unsigned int len;
paul718e3742002-12-13 20:15:29 +00002178 int first;
2179 struct ospf_neighbor *nbr;
paul020709f2003-04-04 02:44:16 +00002180 struct ospf *ospf;
2181
2182 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00002183
hasso1b639042005-03-27 13:32:25 +00002184 if (! ospf)
2185 return NULL;
2186
paul718e3742002-12-13 20:15:29 +00002187 if (exact)
2188 {
2189 if (*length != v->namelen + IN_ADDR_SIZE + 1)
2190 return NULL;
2191
2192 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, nbr_addr);
2193 *ifindex = name[v->namelen + IN_ADDR_SIZE];
2194
paul68980082003-03-25 05:07:42 +00002195 return ospf_snmp_nbr_lookup (ospf, nbr_addr, ifindex);
paul718e3742002-12-13 20:15:29 +00002196 }
2197 else
2198 {
2199 first = 0;
2200 len = *length - v->namelen;
2201
2202 if (len <= 0)
2203 first = 1;
2204
2205 if (len > IN_ADDR_SIZE)
2206 len = IN_ADDR_SIZE;
2207
2208 oid2in_addr (name + v->namelen, len, nbr_addr);
2209
2210 len = *length - v->namelen - IN_ADDR_SIZE;
2211 if (len >= 1)
2212 *ifindex = name[v->namelen + IN_ADDR_SIZE];
2213
2214 nbr = ospf_snmp_nbr_lookup_next (nbr_addr, ifindex, first);
2215
2216 if (nbr)
2217 {
2218 *length = v->namelen + IN_ADDR_SIZE + 1;
2219 oid_copy_addr (name + v->namelen, nbr_addr, IN_ADDR_SIZE);
2220 name[v->namelen + IN_ADDR_SIZE] = *ifindex;
2221 return nbr;
2222 }
2223 }
2224 return NULL;
2225}
2226
Andrew J. Schorrad81f8c2007-03-14 22:05:18 +00002227/* map internal quagga neighbor states to official MIB values:
2228
2229ospfNbrState OBJECT-TYPE
2230 SYNTAX INTEGER {
2231 down (1),
2232 attempt (2),
2233 init (3),
2234 twoWay (4),
2235 exchangeStart (5),
2236 exchange (6),
2237 loading (7),
2238 full (8)
2239 }
2240*/
2241static int32_t
2242ospf_snmp_neighbor_state(u_char nst)
2243{
2244 switch (nst)
2245 {
2246 case NSM_Attempt:
2247 return 2;
2248 case NSM_Init:
2249 return 3;
2250 case NSM_TwoWay:
2251 return 4;
2252 case NSM_ExStart:
2253 return 5;
2254 case NSM_Exchange:
2255 return 6;
2256 case NSM_Loading:
2257 return 7;
2258 case NSM_Full:
2259 return 8;
2260 default:
2261 return 1; /* down */
2262 }
2263}
2264
paul718e3742002-12-13 20:15:29 +00002265static u_char *
2266ospfNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002267 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00002268{
2269 struct in_addr nbr_addr;
2270 unsigned int ifindex;
2271 struct ospf_neighbor *nbr;
2272 struct ospf_interface *oi;
2273
2274 memset (&nbr_addr, 0, sizeof (struct in_addr));
2275 ifindex = 0;
2276
2277 nbr = ospfNbrLookup (v, name, length, &nbr_addr, &ifindex, exact);
2278 if (! nbr)
2279 return NULL;
2280 oi = nbr->oi;
2281 if (! oi)
2282 return NULL;
2283
2284 /* Return the current value of the variable */
2285 switch (v->magic)
2286 {
2287 case OSPFNBRIPADDR:
2288 return SNMP_IPADDRESS (nbr_addr);
2289 break;
2290 case OSPFNBRADDRESSLESSINDEX:
2291 return SNMP_INTEGER (ifindex);
2292 break;
2293 case OSPFNBRRTRID:
2294 return SNMP_IPADDRESS (nbr->router_id);
2295 break;
2296 case OSPFNBROPTIONS:
2297 return SNMP_INTEGER (oi->nbr_self->options);
2298 break;
2299 case OSPFNBRPRIORITY:
2300 return SNMP_INTEGER (nbr->priority);
2301 break;
2302 case OSPFNBRSTATE:
Andrew J. Schorrad81f8c2007-03-14 22:05:18 +00002303 return SNMP_INTEGER (ospf_snmp_neighbor_state(nbr->state));
paul718e3742002-12-13 20:15:29 +00002304 break;
2305 case OSPFNBREVENTS:
2306 return SNMP_INTEGER (nbr->state_change);
2307 break;
2308 case OSPFNBRLSRETRANSQLEN:
2309 return SNMP_INTEGER (ospf_ls_retransmit_count (nbr));
2310 break;
2311 case OSPFNBMANBRSTATUS:
2312 return SNMP_INTEGER (SNMP_VALID);
2313 break;
2314 case OSPFNBMANBRPERMANENCE:
2315 return SNMP_INTEGER (2);
2316 break;
2317 case OSPFNBRHELLOSUPPRESSED:
2318 return SNMP_INTEGER (SNMP_FALSE);
2319 break;
2320 default:
2321 return NULL;
2322 break;
2323 }
2324 return NULL;
2325}
2326
2327static u_char *
2328ospfVirtNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002329 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00002330{
2331 struct ospf_vl_data *vl_data;
2332 struct in_addr area_id;
2333 struct in_addr neighbor;
paul020709f2003-04-04 02:44:16 +00002334 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002335
2336 memset (&area_id, 0, sizeof (struct in_addr));
2337 memset (&neighbor, 0, sizeof (struct in_addr));
2338
2339 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00002340 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00002341 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00002342 return NULL;
2343
2344 vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
2345 if (! vl_data)
2346 return NULL;
2347
2348 /* Return the current value of the variable */
2349 switch (v->magic)
2350 {
2351 case OSPFVIRTNBRAREA:
2352 return (u_char *) NULL;
2353 break;
2354 case OSPFVIRTNBRRTRID:
2355 return (u_char *) NULL;
2356 break;
2357 case OSPFVIRTNBRIPADDR:
2358 return (u_char *) NULL;
2359 break;
2360 case OSPFVIRTNBROPTIONS:
2361 return (u_char *) NULL;
2362 break;
2363 case OSPFVIRTNBRSTATE:
2364 return (u_char *) NULL;
2365 break;
2366 case OSPFVIRTNBREVENTS:
2367 return (u_char *) NULL;
2368 break;
2369 case OSPFVIRTNBRLSRETRANSQLEN:
2370 return (u_char *) NULL;
2371 break;
2372 case OSPFVIRTNBRHELLOSUPPRESSED:
2373 return (u_char *) NULL;
2374 break;
2375 default:
2376 return NULL;
2377 break;
2378 }
2379 return NULL;
2380}
2381
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002382static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00002383ospfExtLsdbLookup (struct variable *v, oid *name, size_t *length, u_char *type,
2384 struct in_addr *ls_id, struct in_addr *router_id, int exact)
2385{
2386 int first;
2387 oid *offset;
2388 int offsetlen;
2389 u_char lsa_type;
paul6c835672004-10-11 11:00:30 +00002390 unsigned int len;
paul718e3742002-12-13 20:15:29 +00002391 struct ospf_lsa *lsa;
paul020709f2003-04-04 02:44:16 +00002392 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002393
paul020709f2003-04-04 02:44:16 +00002394 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00002395 if (exact)
2396 {
2397 if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
2398 return NULL;
2399
2400 offset = name + v->namelen;
2401
2402 /* Make it sure given value match to type. */
2403 lsa_type = *offset;
2404 offset++;
2405
2406 if (lsa_type != *type)
2407 return NULL;
2408
2409 /* LS ID. */
2410 oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
2411 offset += IN_ADDR_SIZE;
2412
2413 /* Router ID. */
2414 oid2in_addr (offset, IN_ADDR_SIZE, router_id);
2415
paul68980082003-03-25 05:07:42 +00002416 return ospf_lsdb_lookup_by_id (ospf->lsdb, *type, *ls_id, *router_id);
paul718e3742002-12-13 20:15:29 +00002417 }
2418 else
2419 {
2420 /* Get variable length. */
2421 first = 0;
2422 offset = name + v->namelen;
2423 offsetlen = *length - v->namelen;
2424
2425 /* LSA type value. */
2426 lsa_type = *offset;
2427 offset++;
2428 offsetlen--;
2429
2430 if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA)
2431 first = 1;
2432
2433 /* LS ID. */
2434 len = offsetlen;
2435 if (len > IN_ADDR_SIZE)
2436 len = IN_ADDR_SIZE;
2437
2438 oid2in_addr (offset, len, ls_id);
2439
2440 offset += IN_ADDR_SIZE;
2441 offsetlen -= IN_ADDR_SIZE;
2442
2443 /* Router ID. */
2444 len = offsetlen;
2445 if (len > IN_ADDR_SIZE)
2446 len = IN_ADDR_SIZE;
2447
2448 oid2in_addr (offset, len, router_id);
2449
paul68980082003-03-25 05:07:42 +00002450 lsa = ospf_lsdb_lookup_by_id_next (ospf->lsdb, *type, *ls_id,
paul718e3742002-12-13 20:15:29 +00002451 *router_id, first);
2452
2453 if (lsa)
2454 {
2455 /* Fill in length. */
2456 *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE;
2457
2458 /* Fill in value. */
2459 offset = name + v->namelen;
2460
2461 *offset = OSPF_AS_EXTERNAL_LSA;
2462 offset++;
2463 oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
2464 offset += IN_ADDR_SIZE;
2465 oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
2466
2467 return lsa;
2468 }
2469 }
2470 return NULL;
2471}
2472
2473static u_char *
2474ospfExtLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002475 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00002476{
2477 struct ospf_lsa *lsa;
2478 struct lsa_header *lsah;
2479 u_char type;
2480 struct in_addr ls_id;
2481 struct in_addr router_id;
paul020709f2003-04-04 02:44:16 +00002482 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002483
2484 type = OSPF_AS_EXTERNAL_LSA;
2485 memset (&ls_id, 0, sizeof (struct in_addr));
2486 memset (&router_id, 0, sizeof (struct in_addr));
2487
2488 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00002489 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00002490 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00002491 return NULL;
2492
2493 lsa = ospfExtLsdbLookup (v, name, length, &type, &ls_id, &router_id, exact);
2494 if (! lsa)
2495 return NULL;
2496
2497 lsah = lsa->data;
2498
2499 /* Return the current value of the variable */
2500 switch (v->magic)
2501 {
2502 case OSPFEXTLSDBTYPE:
2503 return SNMP_INTEGER (OSPF_AS_EXTERNAL_LSA);
2504 break;
2505 case OSPFEXTLSDBLSID:
2506 return SNMP_IPADDRESS (lsah->id);
2507 break;
2508 case OSPFEXTLSDBROUTERID:
2509 return SNMP_IPADDRESS (lsah->adv_router);
2510 break;
2511 case OSPFEXTLSDBSEQUENCE:
2512 return SNMP_INTEGER (lsah->ls_seqnum);
2513 break;
2514 case OSPFEXTLSDBAGE:
2515 return SNMP_INTEGER (lsah->ls_age);
2516 break;
2517 case OSPFEXTLSDBCHECKSUM:
2518 return SNMP_INTEGER (lsah->checksum);
2519 break;
2520 case OSPFEXTLSDBADVERTISEMENT:
2521 *var_len = ntohs (lsah->length);
2522 return (u_char *) lsah;
2523 break;
2524 default:
2525 return NULL;
2526 break;
2527 }
2528 return NULL;
2529}
2530
2531static u_char *
2532ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length,
2533 int exact, size_t *var_len, WriteMethod **write_method)
2534{
2535 /* Return the current value of the variable */
2536 switch (v->magic)
2537 {
2538 case OSPFAREAAGGREGATEAREAID:
2539 return (u_char *) NULL;
2540 break;
2541 case OSPFAREAAGGREGATELSDBTYPE:
2542 return (u_char *) NULL;
2543 break;
2544 case OSPFAREAAGGREGATENET:
2545 return (u_char *) NULL;
2546 break;
2547 case OSPFAREAAGGREGATEMASK:
2548 return (u_char *) NULL;
2549 break;
2550 case OSPFAREAAGGREGATESTATUS:
2551 return (u_char *) NULL;
2552 break;
2553 case OSPFAREAAGGREGATEEFFECT:
2554 return (u_char *) NULL;
2555 break;
2556 default:
2557 return NULL;
2558 break;
2559 }
2560 return NULL;
2561}
2562
vincent5e4914c2005-09-29 16:34:30 +00002563/* OSPF Traps. */
2564#define IFSTATECHANGE 16
2565#define VIRTIFSTATECHANGE 1
2566#define NBRSTATECHANGE 2
2567#define VIRTNBRSTATECHANGE 3
2568
2569struct trap_object ospfNbrTrapList[] =
2570{
2571 {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
2572 {ospfNbrEntry, 3, {10, 1, OSPFNBRIPADDR}},
2573 {ospfNbrEntry, 3, {10, 1, OSPFNBRRTRID}},
2574 {ospfNbrEntry, 3, {10, 1, OSPFNBRSTATE}}
2575};
2576
2577
2578struct trap_object ospfVirtNbrTrapList[] =
2579{
2580 {ospfGeneralGroup, -2, {1, 1}},
2581 {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRAREA}},
2582 {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRRTRID}},
2583 {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRSTATE}}
2584};
2585
2586struct trap_object ospfIfTrapList[] =
2587{
2588 {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
2589 {ospfIfEntry, 3, {7, 1, OSPFIFIPADDRESS}},
2590 {ospfIfEntry, 3, {7, 1, OSPFADDRESSLESSIF}},
2591 {ospfIfEntry, 3, {7, 1, OSPFIFSTATE}}
2592};
2593
2594struct trap_object ospfVirtIfTrapList[] =
2595{
2596 {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
2597 {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFAREAID}},
2598 {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFNEIGHBOR}},
2599 {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFSTATE}}
2600};
2601
2602void
2603ospfTrapNbrStateChange (struct ospf_neighbor *on)
2604{
2605 oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
Andrew J. Schorr9aecfae2006-06-24 20:05:02 +00002606 char msgbuf[16];
vincent5e4914c2005-09-29 16:34:30 +00002607
Andrew J. Schorr9aecfae2006-06-24 20:05:02 +00002608 ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf));
2609 zlog (NULL, LOG_INFO, "ospfTrapNbrStateChange trap sent: %s now %s",
2610 inet_ntoa(on->address.u.prefix4), msgbuf);
vincent5e4914c2005-09-29 16:34:30 +00002611
2612 oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE);
2613 index[IN_ADDR_SIZE] = 0;
2614
2615 smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
2616 index, IN_ADDR_SIZE + 1,
2617 ospfNbrTrapList,
2618 sizeof ospfNbrTrapList / sizeof (struct trap_object),
2619 time (NULL), NBRSTATECHANGE);
2620}
2621
2622void
2623ospfTrapVirtNbrStateChange (struct ospf_neighbor *on)
2624{
2625 oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
2626
2627 zlog (NULL, LOG_INFO, "ospfTrapVirtNbrStateChange trap sent");
2628
2629 oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE);
2630 index[IN_ADDR_SIZE] = 0;
2631
2632 smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
2633 index, IN_ADDR_SIZE + 1,
2634 ospfVirtNbrTrapList,
2635 sizeof ospfVirtNbrTrapList / sizeof (struct trap_object),
2636 time (NULL), VIRTNBRSTATECHANGE);
2637}
2638
2639void
2640ospfTrapIfStateChange (struct ospf_interface *oi)
2641{
2642 oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
2643
Andrew J. Schorr9aecfae2006-06-24 20:05:02 +00002644 zlog (NULL, LOG_INFO, "ospfTrapIfStateChange trap sent: %s now %s",
2645 inet_ntoa(oi->address->u.prefix4),
2646 LOOKUP(ospf_ism_state_msg, oi->state));
vincent5e4914c2005-09-29 16:34:30 +00002647
2648 oid_copy_addr (index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
2649 index[IN_ADDR_SIZE] = 0;
2650
2651 smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
2652 index, IN_ADDR_SIZE + 1,
2653 ospfIfTrapList,
2654 sizeof ospfIfTrapList / sizeof (struct trap_object),
2655 time (NULL), IFSTATECHANGE);
2656}
2657
2658void
2659ospfTrapVirtIfStateChange (struct ospf_interface *oi)
2660{
2661 oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
2662
2663 zlog (NULL, LOG_INFO, "ospfTrapVirtIfStateChange trap sent");
2664
2665 oid_copy_addr (index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
2666 index[IN_ADDR_SIZE] = 0;
2667
2668 smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
2669 index, IN_ADDR_SIZE + 1,
2670 ospfVirtIfTrapList,
2671 sizeof ospfVirtIfTrapList / sizeof (struct trap_object),
2672 time (NULL), VIRTIFSTATECHANGE);
2673}
paul718e3742002-12-13 20:15:29 +00002674/* Register OSPF2-MIB. */
2675void
2676ospf_snmp_init ()
2677{
2678 ospf_snmp_iflist = list_new ();
2679 ospf_snmp_vl_table = route_table_init ();
hassoc75105a2004-10-13 10:33:26 +00002680 smux_init (om->master);
paul718e3742002-12-13 20:15:29 +00002681 REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid);
paul718e3742002-12-13 20:15:29 +00002682}
2683#endif /* HAVE_SNMP */