blob: c47d432e04894dc9bf9e2eca91deb1a89b0a916e [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#ifdef HAVE_NETSNMP
29#include <net-snmp/net-snmp-config.h>
Joakim Tjernlundfb62a3c2008-05-13 20:03:32 +020030#include <net-snmp/net-snmp-includes.h>
31#else
paul718e3742002-12-13 20:15:29 +000032#include <asn1.h>
33#include <snmp.h>
34#include <snmp_impl.h>
Joakim Tjernlundfb62a3c2008-05-13 20:03:32 +020035#endif
paul718e3742002-12-13 20:15:29 +000036
37#include "if.h"
38#include "log.h"
39#include "prefix.h"
40#include "table.h"
41#include "command.h"
42#include "memory.h"
43#include "smux.h"
44
45#include "ospfd/ospfd.h"
46#include "ospfd/ospf_interface.h"
47#include "ospfd/ospf_asbr.h"
48#include "ospfd/ospf_lsa.h"
49#include "ospfd/ospf_lsdb.h"
50#include "ospfd/ospf_abr.h"
51#include "ospfd/ospf_neighbor.h"
52#include "ospfd/ospf_nsm.h"
53#include "ospfd/ospf_flood.h"
vincente6217872005-09-29 13:56:14 +000054#include "ospfd/ospf_ism.h"
Andrew J. Schorr9aecfae2006-06-24 20:05:02 +000055#include "ospfd/ospf_dump.h"
Chris Caputo0be8dfb2009-06-02 18:40:07 +010056#include "ospfd/ospf_snmp.h"
paul718e3742002-12-13 20:15:29 +000057
58/* OSPF2-MIB. */
59#define OSPF2MIB 1,3,6,1,2,1,14
60
paul718e3742002-12-13 20:15:29 +000061/* OSPF MIB General Group values. */
62#define OSPFROUTERID 1
63#define OSPFADMINSTAT 2
64#define OSPFVERSIONNUMBER 3
65#define OSPFAREABDRRTRSTATUS 4
66#define OSPFASBDRRTRSTATUS 5
67#define OSPFEXTERNLSACOUNT 6
68#define OSPFEXTERNLSACKSUMSUM 7
69#define OSPFTOSSUPPORT 8
70#define OSPFORIGINATENEWLSAS 9
71#define OSPFRXNEWLSAS 10
72#define OSPFEXTLSDBLIMIT 11
73#define OSPFMULTICASTEXTENSIONS 12
74#define OSPFEXITOVERFLOWINTERVAL 13
75#define OSPFDEMANDEXTENSIONS 14
76
77/* OSPF MIB ospfAreaTable. */
78#define OSPFAREAID 1
79#define OSPFAUTHTYPE 2
80#define OSPFIMPORTASEXTERN 3
81#define OSPFSPFRUNS 4
82#define OSPFAREABDRRTRCOUNT 5
83#define OSPFASBDRRTRCOUNT 6
84#define OSPFAREALSACOUNT 7
85#define OSPFAREALSACKSUMSUM 8
86#define OSPFAREASUMMARY 9
87#define OSPFAREASTATUS 10
88
89/* OSPF MIB ospfStubAreaTable. */
90#define OSPFSTUBAREAID 1
91#define OSPFSTUBTOS 2
92#define OSPFSTUBMETRIC 3
93#define OSPFSTUBSTATUS 4
94#define OSPFSTUBMETRICTYPE 5
95
96/* OSPF MIB ospfLsdbTable. */
97#define OSPFLSDBAREAID 1
98#define OSPFLSDBTYPE 2
99#define OSPFLSDBLSID 3
100#define OSPFLSDBROUTERID 4
101#define OSPFLSDBSEQUENCE 5
102#define OSPFLSDBAGE 6
103#define OSPFLSDBCHECKSUM 7
104#define OSPFLSDBADVERTISEMENT 8
105
106/* OSPF MIB ospfAreaRangeTable. */
107#define OSPFAREARANGEAREAID 1
108#define OSPFAREARANGENET 2
109#define OSPFAREARANGEMASK 3
110#define OSPFAREARANGESTATUS 4
111#define OSPFAREARANGEEFFECT 5
112
113/* OSPF MIB ospfHostTable. */
114#define OSPFHOSTIPADDRESS 1
115#define OSPFHOSTTOS 2
116#define OSPFHOSTMETRIC 3
117#define OSPFHOSTSTATUS 4
118#define OSPFHOSTAREAID 5
119
120/* OSPF MIB ospfIfTable. */
121#define OSPFIFIPADDRESS 1
122#define OSPFADDRESSLESSIF 2
123#define OSPFIFAREAID 3
124#define OSPFIFTYPE 4
125#define OSPFIFADMINSTAT 5
126#define OSPFIFRTRPRIORITY 6
127#define OSPFIFTRANSITDELAY 7
128#define OSPFIFRETRANSINTERVAL 8
129#define OSPFIFHELLOINTERVAL 9
130#define OSPFIFRTRDEADINTERVAL 10
131#define OSPFIFPOLLINTERVAL 11
132#define OSPFIFSTATE 12
133#define OSPFIFDESIGNATEDROUTER 13
134#define OSPFIFBACKUPDESIGNATEDROUTER 14
135#define OSPFIFEVENTS 15
136#define OSPFIFAUTHKEY 16
137#define OSPFIFSTATUS 17
138#define OSPFIFMULTICASTFORWARDING 18
139#define OSPFIFDEMAND 19
140#define OSPFIFAUTHTYPE 20
141
142/* OSPF MIB ospfIfMetricTable. */
143#define OSPFIFMETRICIPADDRESS 1
144#define OSPFIFMETRICADDRESSLESSIF 2
145#define OSPFIFMETRICTOS 3
146#define OSPFIFMETRICVALUE 4
147#define OSPFIFMETRICSTATUS 5
148
149/* OSPF MIB ospfVirtIfTable. */
150#define OSPFVIRTIFAREAID 1
151#define OSPFVIRTIFNEIGHBOR 2
152#define OSPFVIRTIFTRANSITDELAY 3
153#define OSPFVIRTIFRETRANSINTERVAL 4
154#define OSPFVIRTIFHELLOINTERVAL 5
155#define OSPFVIRTIFRTRDEADINTERVAL 6
156#define OSPFVIRTIFSTATE 7
157#define OSPFVIRTIFEVENTS 8
158#define OSPFVIRTIFAUTHKEY 9
159#define OSPFVIRTIFSTATUS 10
160#define OSPFVIRTIFAUTHTYPE 11
161
162/* OSPF MIB ospfNbrTable. */
163#define OSPFNBRIPADDR 1
164#define OSPFNBRADDRESSLESSINDEX 2
165#define OSPFNBRRTRID 3
166#define OSPFNBROPTIONS 4
167#define OSPFNBRPRIORITY 5
168#define OSPFNBRSTATE 6
169#define OSPFNBREVENTS 7
170#define OSPFNBRLSRETRANSQLEN 8
171#define OSPFNBMANBRSTATUS 9
172#define OSPFNBMANBRPERMANENCE 10
173#define OSPFNBRHELLOSUPPRESSED 11
174
175/* OSPF MIB ospfVirtNbrTable. */
176#define OSPFVIRTNBRAREA 1
177#define OSPFVIRTNBRRTRID 2
178#define OSPFVIRTNBRIPADDR 3
179#define OSPFVIRTNBROPTIONS 4
180#define OSPFVIRTNBRSTATE 5
181#define OSPFVIRTNBREVENTS 6
182#define OSPFVIRTNBRLSRETRANSQLEN 7
183#define OSPFVIRTNBRHELLOSUPPRESSED 8
184
185/* OSPF MIB ospfExtLsdbTable. */
186#define OSPFEXTLSDBTYPE 1
187#define OSPFEXTLSDBLSID 2
188#define OSPFEXTLSDBROUTERID 3
189#define OSPFEXTLSDBSEQUENCE 4
190#define OSPFEXTLSDBAGE 5
191#define OSPFEXTLSDBCHECKSUM 6
192#define OSPFEXTLSDBADVERTISEMENT 7
193
194/* OSPF MIB ospfAreaAggregateTable. */
195#define OSPFAREAAGGREGATEAREAID 1
196#define OSPFAREAAGGREGATELSDBTYPE 2
197#define OSPFAREAAGGREGATENET 3
198#define OSPFAREAAGGREGATEMASK 4
199#define OSPFAREAAGGREGATESTATUS 5
200#define OSPFAREAAGGREGATEEFFECT 6
201
202/* SYNTAX Status from OSPF-MIB. */
203#define OSPF_STATUS_ENABLED 1
204#define OSPF_STATUS_DISABLED 2
205
206/* SNMP value hack. */
207#define COUNTER ASN_COUNTER
208#define INTEGER ASN_INTEGER
209#define GAUGE ASN_GAUGE
210#define TIMETICKS ASN_TIMETICKS
211#define IPADDRESS ASN_IPADDRESS
212#define STRING ASN_OCTET_STR
213
214/* Declare static local variables for convenience. */
215SNMP_LOCAL_VARIABLES
216
217/* OSPF-MIB instances. */
218oid ospf_oid [] = { OSPF2MIB };
paul718e3742002-12-13 20:15:29 +0000219
220/* IP address 0.0.0.0. */
221static struct in_addr ospf_empty_addr = {0};
222
223/* Hook functions. */
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100224static u_char *ospfGeneralGroup (struct variable *, oid *, size_t *,
225 int, size_t *, WriteMethod **);
226static u_char *ospfAreaEntry (struct variable *, oid *, size_t *, int,
227 size_t *, WriteMethod **);
228static u_char *ospfStubAreaEntry (struct variable *, oid *, size_t *,
229 int, size_t *, WriteMethod **);
230static u_char *ospfLsdbEntry (struct variable *, oid *, size_t *, int,
231 size_t *, WriteMethod **);
232static u_char *ospfAreaRangeEntry (struct variable *, oid *, size_t *, int,
233 size_t *, WriteMethod **);
234static u_char *ospfHostEntry (struct variable *, oid *, size_t *, int,
235 size_t *, WriteMethod **);
236static u_char *ospfIfEntry (struct variable *, oid *, size_t *, int,
237 size_t *, WriteMethod **);
238static u_char *ospfIfMetricEntry (struct variable *, oid *, size_t *, int,
239 size_t *, WriteMethod **);
240static u_char *ospfVirtIfEntry (struct variable *, oid *, size_t *, int,
241 size_t *, WriteMethod **);
242static u_char *ospfNbrEntry (struct variable *, oid *, size_t *, int,
243 size_t *, WriteMethod **);
244static u_char *ospfVirtNbrEntry (struct variable *, oid *, size_t *, int,
245 size_t *, WriteMethod **);
246static u_char *ospfExtLsdbEntry (struct variable *, oid *, size_t *, int,
247 size_t *, WriteMethod **);
248static u_char *ospfAreaAggregateEntry (struct variable *, oid *, size_t *,
249 int, size_t *, WriteMethod **);
paul718e3742002-12-13 20:15:29 +0000250
251struct variable ospf_variables[] =
252{
253 /* OSPF general variables */
254 {OSPFROUTERID, IPADDRESS, RWRITE, ospfGeneralGroup,
255 2, {1, 1}},
256 {OSPFADMINSTAT, INTEGER, RWRITE, ospfGeneralGroup,
257 2, {1, 2}},
258 {OSPFVERSIONNUMBER, INTEGER, RONLY, ospfGeneralGroup,
259 2, {1, 3}},
260 {OSPFAREABDRRTRSTATUS, INTEGER, RONLY, ospfGeneralGroup,
261 2, {1, 4}},
262 {OSPFASBDRRTRSTATUS, INTEGER, RWRITE, ospfGeneralGroup,
263 2, {1, 5}},
264 {OSPFEXTERNLSACOUNT, GAUGE, RONLY, ospfGeneralGroup,
265 2, {1, 6}},
266 {OSPFEXTERNLSACKSUMSUM, INTEGER, RONLY, ospfGeneralGroup,
267 2, {1, 7}},
268 {OSPFTOSSUPPORT, INTEGER, RWRITE, ospfGeneralGroup,
269 2, {1, 8}},
270 {OSPFORIGINATENEWLSAS, COUNTER, RONLY, ospfGeneralGroup,
271 2, {1, 9}},
272 {OSPFRXNEWLSAS, COUNTER, RONLY, ospfGeneralGroup,
273 2, {1, 10}},
274 {OSPFEXTLSDBLIMIT, INTEGER, RWRITE, ospfGeneralGroup,
275 2, {1, 11}},
276 {OSPFMULTICASTEXTENSIONS, INTEGER, RWRITE, ospfGeneralGroup,
277 2, {1, 12}},
278 {OSPFEXITOVERFLOWINTERVAL, INTEGER, RWRITE, ospfGeneralGroup,
279 2, {1, 13}},
280 {OSPFDEMANDEXTENSIONS, INTEGER, RWRITE, ospfGeneralGroup,
281 2, {1, 14}},
282
283 /* OSPF area data structure. */
284 {OSPFAREAID, IPADDRESS, RONLY, ospfAreaEntry,
285 3, {2, 1, 1}},
286 {OSPFAUTHTYPE, INTEGER, RWRITE, ospfAreaEntry,
287 3, {2, 1, 2}},
288 {OSPFIMPORTASEXTERN, INTEGER, RWRITE, ospfAreaEntry,
289 3, {2, 1, 3}},
290 {OSPFSPFRUNS, COUNTER, RONLY, ospfAreaEntry,
291 3, {2, 1, 4}},
292 {OSPFAREABDRRTRCOUNT, GAUGE, RONLY, ospfAreaEntry,
293 3, {2, 1, 5}},
294 {OSPFASBDRRTRCOUNT, GAUGE, RONLY, ospfAreaEntry,
295 3, {2, 1, 6}},
296 {OSPFAREALSACOUNT, GAUGE, RONLY, ospfAreaEntry,
297 3, {2, 1, 7}},
298 {OSPFAREALSACKSUMSUM, INTEGER, RONLY, ospfAreaEntry,
299 3, {2, 1, 8}},
300 {OSPFAREASUMMARY, INTEGER, RWRITE, ospfAreaEntry,
301 3, {2, 1, 9}},
302 {OSPFAREASTATUS, INTEGER, RWRITE, ospfAreaEntry,
303 3, {2, 1, 10}},
304
305 /* OSPF stub area information. */
306 {OSPFSTUBAREAID, IPADDRESS, RONLY, ospfStubAreaEntry,
307 3, {3, 1, 1}},
308 {OSPFSTUBTOS, INTEGER, RONLY, ospfStubAreaEntry,
309 3, {3, 1, 2}},
310 {OSPFSTUBMETRIC, INTEGER, RWRITE, ospfStubAreaEntry,
311 3, {3, 1, 3}},
312 {OSPFSTUBSTATUS, INTEGER, RWRITE, ospfStubAreaEntry,
313 3, {3, 1, 4}},
314 {OSPFSTUBMETRICTYPE, INTEGER, RWRITE, ospfStubAreaEntry,
315 3, {3, 1, 5}},
316
317 /* OSPF link state database. */
318 {OSPFLSDBAREAID, IPADDRESS, RONLY, ospfLsdbEntry,
319 3, {4, 1, 1}},
320 {OSPFLSDBTYPE, INTEGER, RONLY, ospfLsdbEntry,
321 3, {4, 1, 2}},
322 {OSPFLSDBLSID, IPADDRESS, RONLY, ospfLsdbEntry,
323 3, {4, 1, 3}},
324 {OSPFLSDBROUTERID, IPADDRESS, RONLY, ospfLsdbEntry,
325 3, {4, 1, 4}},
326 {OSPFLSDBSEQUENCE, INTEGER, RONLY, ospfLsdbEntry,
327 3, {4, 1, 5}},
328 {OSPFLSDBAGE, INTEGER, RONLY, ospfLsdbEntry,
329 3, {4, 1, 6}},
330 {OSPFLSDBCHECKSUM, INTEGER, RONLY, ospfLsdbEntry,
331 3, {4, 1, 7}},
332 {OSPFLSDBADVERTISEMENT, STRING, RONLY, ospfLsdbEntry,
333 3, {4, 1, 8}},
334
335 /* Area range table. */
336 {OSPFAREARANGEAREAID, IPADDRESS, RONLY, ospfAreaRangeEntry,
337 3, {5, 1, 1}},
338 {OSPFAREARANGENET, IPADDRESS, RONLY, ospfAreaRangeEntry,
339 3, {5, 1, 2}},
340 {OSPFAREARANGEMASK, IPADDRESS, RWRITE, ospfAreaRangeEntry,
341 3, {5, 1, 3}},
342 {OSPFAREARANGESTATUS, INTEGER, RWRITE, ospfAreaRangeEntry,
343 3, {5, 1, 4}},
344 {OSPFAREARANGEEFFECT, INTEGER, RWRITE, ospfAreaRangeEntry,
345 3, {5, 1, 5}},
346
347 /* OSPF host table. */
348 {OSPFHOSTIPADDRESS, IPADDRESS, RONLY, ospfHostEntry,
349 3, {6, 1, 1}},
350 {OSPFHOSTTOS, INTEGER, RONLY, ospfHostEntry,
351 3, {6, 1, 2}},
352 {OSPFHOSTMETRIC, INTEGER, RWRITE, ospfHostEntry,
353 3, {6, 1, 3}},
354 {OSPFHOSTSTATUS, INTEGER, RWRITE, ospfHostEntry,
355 3, {6, 1, 4}},
356 {OSPFHOSTAREAID, IPADDRESS, RONLY, ospfHostEntry,
357 3, {6, 1, 5}},
358
359 /* OSPF interface table. */
360 {OSPFIFIPADDRESS, IPADDRESS, RONLY, ospfIfEntry,
361 3, {7, 1, 1}},
362 {OSPFADDRESSLESSIF, INTEGER, RONLY, ospfIfEntry,
363 3, {7, 1, 2}},
364 {OSPFIFAREAID, IPADDRESS, RWRITE, ospfIfEntry,
365 3, {7, 1, 3}},
366 {OSPFIFTYPE, INTEGER, RWRITE, ospfIfEntry,
367 3, {7, 1, 4}},
368 {OSPFIFADMINSTAT, INTEGER, RWRITE, ospfIfEntry,
369 3, {7, 1, 5}},
370 {OSPFIFRTRPRIORITY, INTEGER, RWRITE, ospfIfEntry,
371 3, {7, 1, 6}},
372 {OSPFIFTRANSITDELAY, INTEGER, RWRITE, ospfIfEntry,
373 3, {7, 1, 7}},
374 {OSPFIFRETRANSINTERVAL, INTEGER, RWRITE, ospfIfEntry,
375 3, {7, 1, 8}},
376 {OSPFIFHELLOINTERVAL, INTEGER, RWRITE, ospfIfEntry,
377 3, {7, 1, 9}},
378 {OSPFIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfIfEntry,
379 3, {7, 1, 10}},
380 {OSPFIFPOLLINTERVAL, INTEGER, RWRITE, ospfIfEntry,
381 3, {7, 1, 11}},
382 {OSPFIFSTATE, INTEGER, RONLY, ospfIfEntry,
383 3, {7, 1, 12}},
384 {OSPFIFDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry,
385 3, {7, 1, 13}},
386 {OSPFIFBACKUPDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry,
387 3, {7, 1, 14}},
388 {OSPFIFEVENTS, COUNTER, RONLY, ospfIfEntry,
389 3, {7, 1, 15}},
390 {OSPFIFAUTHKEY, STRING, RWRITE, ospfIfEntry,
391 3, {7, 1, 16}},
392 {OSPFIFSTATUS, INTEGER, RWRITE, ospfIfEntry,
393 3, {7, 1, 17}},
394 {OSPFIFMULTICASTFORWARDING, INTEGER, RWRITE, ospfIfEntry,
395 3, {7, 1, 18}},
396 {OSPFIFDEMAND, INTEGER, RWRITE, ospfIfEntry,
397 3, {7, 1, 19}},
398 {OSPFIFAUTHTYPE, INTEGER, RWRITE, ospfIfEntry,
399 3, {7, 1, 20}},
400
401 /* OSPF interface metric table. */
402 {OSPFIFMETRICIPADDRESS, IPADDRESS, RONLY, ospfIfMetricEntry,
403 3, {8, 1, 1}},
404 {OSPFIFMETRICADDRESSLESSIF, INTEGER, RONLY, ospfIfMetricEntry,
405 3, {8, 1, 2}},
406 {OSPFIFMETRICTOS, INTEGER, RONLY, ospfIfMetricEntry,
407 3, {8, 1, 3}},
408 {OSPFIFMETRICVALUE, INTEGER, RWRITE, ospfIfMetricEntry,
409 3, {8, 1, 4}},
410 {OSPFIFMETRICSTATUS, INTEGER, RWRITE, ospfIfMetricEntry,
411 3, {8, 1, 5}},
412
413 /* OSPF virtual interface table. */
414 {OSPFVIRTIFAREAID, IPADDRESS, RONLY, ospfVirtIfEntry,
415 3, {9, 1, 1}},
416 {OSPFVIRTIFNEIGHBOR, IPADDRESS, RONLY, ospfVirtIfEntry,
417 3, {9, 1, 2}},
418 {OSPFVIRTIFTRANSITDELAY, INTEGER, RWRITE, ospfVirtIfEntry,
419 3, {9, 1, 3}},
420 {OSPFVIRTIFRETRANSINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
421 3, {9, 1, 4}},
422 {OSPFVIRTIFHELLOINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
423 3, {9, 1, 5}},
424 {OSPFVIRTIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
425 3, {9, 1, 6}},
426 {OSPFVIRTIFSTATE, INTEGER, RONLY, ospfVirtIfEntry,
427 3, {9, 1, 7}},
428 {OSPFVIRTIFEVENTS, COUNTER, RONLY, ospfVirtIfEntry,
429 3, {9, 1, 8}},
430 {OSPFVIRTIFAUTHKEY, STRING, RWRITE, ospfVirtIfEntry,
431 3, {9, 1, 9}},
432 {OSPFVIRTIFSTATUS, INTEGER, RWRITE, ospfVirtIfEntry,
433 3, {9, 1, 10}},
434 {OSPFVIRTIFAUTHTYPE, INTEGER, RWRITE, ospfVirtIfEntry,
435 3, {9, 1, 11}},
436
437 /* OSPF neighbor table. */
438 {OSPFNBRIPADDR, IPADDRESS, RONLY, ospfNbrEntry,
439 3, {10, 1, 1}},
440 {OSPFNBRADDRESSLESSINDEX, INTEGER, RONLY, ospfNbrEntry,
441 3, {10, 1, 2}},
442 {OSPFNBRRTRID, IPADDRESS, RONLY, ospfNbrEntry,
443 3, {10, 1, 3}},
444 {OSPFNBROPTIONS, INTEGER, RONLY, ospfNbrEntry,
445 3, {10, 1, 4}},
446 {OSPFNBRPRIORITY, INTEGER, RWRITE, ospfNbrEntry,
447 3, {10, 1, 5}},
448 {OSPFNBRSTATE, INTEGER, RONLY, ospfNbrEntry,
449 3, {10, 1, 6}},
450 {OSPFNBREVENTS, COUNTER, RONLY, ospfNbrEntry,
451 3, {10, 1, 7}},
452 {OSPFNBRLSRETRANSQLEN, GAUGE, RONLY, ospfNbrEntry,
453 3, {10, 1, 8}},
454 {OSPFNBMANBRSTATUS, INTEGER, RWRITE, ospfNbrEntry,
455 3, {10, 1, 9}},
456 {OSPFNBMANBRPERMANENCE, INTEGER, RONLY, ospfNbrEntry,
457 3, {10, 1, 10}},
458 {OSPFNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfNbrEntry,
459 3, {10, 1, 11}},
460
461 /* OSPF virtual neighbor table. */
462 {OSPFVIRTNBRAREA, IPADDRESS, RONLY, ospfVirtNbrEntry,
463 3, {11, 1, 1}},
464 {OSPFVIRTNBRRTRID, IPADDRESS, RONLY, ospfVirtNbrEntry,
465 3, {11, 1, 2}},
466 {OSPFVIRTNBRIPADDR, IPADDRESS, RONLY, ospfVirtNbrEntry,
467 3, {11, 1, 3}},
468 {OSPFVIRTNBROPTIONS, INTEGER, RONLY, ospfVirtNbrEntry,
469 3, {11, 1, 4}},
470 {OSPFVIRTNBRSTATE, INTEGER, RONLY, ospfVirtNbrEntry,
471 3, {11, 1, 5}},
472 {OSPFVIRTNBREVENTS, COUNTER, RONLY, ospfVirtNbrEntry,
473 3, {11, 1, 6}},
474 {OSPFVIRTNBRLSRETRANSQLEN, INTEGER, RONLY, ospfVirtNbrEntry,
475 3, {11, 1, 7}},
476 {OSPFVIRTNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfVirtNbrEntry,
477 3, {11, 1, 8}},
478
479 /* OSPF link state database, external. */
480 {OSPFEXTLSDBTYPE, INTEGER, RONLY, ospfExtLsdbEntry,
481 3, {12, 1, 1}},
482 {OSPFEXTLSDBLSID, IPADDRESS, RONLY, ospfExtLsdbEntry,
483 3, {12, 1, 2}},
484 {OSPFEXTLSDBROUTERID, IPADDRESS, RONLY, ospfExtLsdbEntry,
485 3, {12, 1, 3}},
486 {OSPFEXTLSDBSEQUENCE, INTEGER, RONLY, ospfExtLsdbEntry,
487 3, {12, 1, 4}},
488 {OSPFEXTLSDBAGE, INTEGER, RONLY, ospfExtLsdbEntry,
489 3, {12, 1, 5}},
490 {OSPFEXTLSDBCHECKSUM, INTEGER, RONLY, ospfExtLsdbEntry,
491 3, {12, 1, 6}},
492 {OSPFEXTLSDBADVERTISEMENT, STRING, RONLY, ospfExtLsdbEntry,
493 3, {12, 1, 7}},
494
495 /* OSPF area aggregate table. */
496 {OSPFAREAAGGREGATEAREAID, IPADDRESS, RONLY, ospfAreaAggregateEntry,
497 3, {14, 1, 1}},
498 {OSPFAREAAGGREGATELSDBTYPE, INTEGER, RONLY, ospfAreaAggregateEntry,
499 3, {14, 1, 2}},
500 {OSPFAREAAGGREGATENET, IPADDRESS, RONLY, ospfAreaAggregateEntry,
501 3, {14, 1, 3}},
502 {OSPFAREAAGGREGATEMASK, IPADDRESS, RONLY, ospfAreaAggregateEntry,
503 3, {14, 1, 4}},
504 {OSPFAREAAGGREGATESTATUS, INTEGER, RWRITE, ospfAreaAggregateEntry,
505 3, {14, 1, 5}},
506 {OSPFAREAAGGREGATEEFFECT, INTEGER, RWRITE, ospfAreaAggregateEntry,
507 3, {14, 1, 6}}
508};
509
510/* The administrative status of OSPF. When OSPF is enbled on at least
511 one interface return 1. */
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100512static int
paul68980082003-03-25 05:07:42 +0000513ospf_admin_stat (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000514{
paulaa20c6f2004-10-07 14:19:36 +0000515 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000516 struct ospf_interface *oi;
517
paul68980082003-03-25 05:07:42 +0000518 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000519 return 0;
520
paul1eb8ef22005-04-07 07:30:20 +0000521 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
522 if (oi && oi->address)
523 return 1;
paul718e3742002-12-13 20:15:29 +0000524
paul718e3742002-12-13 20:15:29 +0000525 return 0;
526}
527
528static u_char *
529ospfGeneralGroup (struct variable *v, oid *name, size_t *length,
530 int exact, size_t *var_len, WriteMethod **write_method)
531{
paul020709f2003-04-04 02:44:16 +0000532 struct ospf *ospf;
533
534 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000535
paul718e3742002-12-13 20:15:29 +0000536 /* Check whether the instance identifier is valid */
537 if (smux_header_generic (v, name, length, exact, var_len, write_method)
538 == MATCH_FAILED)
539 return NULL;
540
541 /* Return the current value of the variable */
542 switch (v->magic)
543 {
544 case OSPFROUTERID: /* 1 */
545 /* Router-ID of this OSPF instance. */
paul68980082003-03-25 05:07:42 +0000546 if (ospf)
547 return SNMP_IPADDRESS (ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000548 else
549 return SNMP_IPADDRESS (ospf_empty_addr);
550 break;
551 case OSPFADMINSTAT: /* 2 */
552 /* The administrative status of OSPF in the router. */
paul68980082003-03-25 05:07:42 +0000553 if (ospf_admin_stat (ospf))
paul718e3742002-12-13 20:15:29 +0000554 return SNMP_INTEGER (OSPF_STATUS_ENABLED);
555 else
556 return SNMP_INTEGER (OSPF_STATUS_DISABLED);
557 break;
558 case OSPFVERSIONNUMBER: /* 3 */
559 /* OSPF version 2. */
560 return SNMP_INTEGER (OSPF_VERSION);
561 break;
562 case OSPFAREABDRRTRSTATUS: /* 4 */
563 /* Area Border router status. */
paul68980082003-03-25 05:07:42 +0000564 if (ospf && CHECK_FLAG (ospf->flags, OSPF_FLAG_ABR))
paul718e3742002-12-13 20:15:29 +0000565 return SNMP_INTEGER (SNMP_TRUE);
566 else
567 return SNMP_INTEGER (SNMP_FALSE);
568 break;
569 case OSPFASBDRRTRSTATUS: /* 5 */
570 /* AS Border router status. */
paul68980082003-03-25 05:07:42 +0000571 if (ospf && CHECK_FLAG (ospf->flags, OSPF_FLAG_ASBR))
paul718e3742002-12-13 20:15:29 +0000572 return SNMP_INTEGER (SNMP_TRUE);
573 else
574 return SNMP_INTEGER (SNMP_FALSE);
575 break;
576 case OSPFEXTERNLSACOUNT: /* 6 */
577 /* External LSA counts. */
paul68980082003-03-25 05:07:42 +0000578 if (ospf)
579 return SNMP_INTEGER (ospf_lsdb_count_all (ospf->lsdb));
paul718e3742002-12-13 20:15:29 +0000580 else
581 return SNMP_INTEGER (0);
582 break;
583 case OSPFEXTERNLSACKSUMSUM: /* 7 */
584 /* External LSA checksum. */
585 return SNMP_INTEGER (0);
586 break;
587 case OSPFTOSSUPPORT: /* 8 */
588 /* TOS is not supported. */
589 return SNMP_INTEGER (SNMP_FALSE);
590 break;
591 case OSPFORIGINATENEWLSAS: /* 9 */
592 /* The number of new link-state advertisements. */
paul68980082003-03-25 05:07:42 +0000593 if (ospf)
594 return SNMP_INTEGER (ospf->lsa_originate_count);
paul718e3742002-12-13 20:15:29 +0000595 else
596 return SNMP_INTEGER (0);
597 break;
598 case OSPFRXNEWLSAS: /* 10 */
599 /* The number of link-state advertisements received determined
600 to be new instantiations. */
paul68980082003-03-25 05:07:42 +0000601 if (ospf)
602 return SNMP_INTEGER (ospf->rx_lsa_count);
paul718e3742002-12-13 20:15:29 +0000603 else
604 return SNMP_INTEGER (0);
605 break;
606 case OSPFEXTLSDBLIMIT: /* 11 */
607 /* There is no limit for the number of non-default
608 AS-external-LSAs. */
609 return SNMP_INTEGER (-1);
610 break;
611 case OSPFMULTICASTEXTENSIONS: /* 12 */
612 /* Multicast Extensions to OSPF is not supported. */
613 return SNMP_INTEGER (0);
614 break;
615 case OSPFEXITOVERFLOWINTERVAL: /* 13 */
616 /* Overflow is not supported. */
617 return SNMP_INTEGER (0);
618 break;
619 case OSPFDEMANDEXTENSIONS: /* 14 */
620 /* Demand routing is not supported. */
621 return SNMP_INTEGER (SNMP_FALSE);
622 break;
623 default:
624 return NULL;
625 }
626 return NULL;
627}
628
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100629static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000630ospf_area_lookup_next (struct ospf *ospf, struct in_addr *area_id, int first)
paul718e3742002-12-13 20:15:29 +0000631{
632 struct ospf_area *area;
paulaa20c6f2004-10-07 14:19:36 +0000633 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000634
paul020709f2003-04-04 02:44:16 +0000635 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000636 return NULL;
637
638 if (first)
639 {
paul68980082003-03-25 05:07:42 +0000640 node = listhead (ospf->areas);
paul718e3742002-12-13 20:15:29 +0000641 if (node)
642 {
paul1eb8ef22005-04-07 07:30:20 +0000643 area = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000644 *area_id = area->area_id;
645 return area;
646 }
647 return NULL;
648 }
paul1eb8ef22005-04-07 07:30:20 +0000649 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
paul718e3742002-12-13 20:15:29 +0000650 {
paul718e3742002-12-13 20:15:29 +0000651 if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
652 {
653 *area_id = area->area_id;
654 return area;
655 }
656 }
657 return NULL;
658}
659
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100660static struct ospf_area *
paul718e3742002-12-13 20:15:29 +0000661ospfAreaLookup (struct variable *v, oid name[], size_t *length,
662 struct in_addr *addr, int exact)
663{
paul020709f2003-04-04 02:44:16 +0000664 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000665 struct ospf_area *area;
paul68980082003-03-25 05:07:42 +0000666 int len;
paul718e3742002-12-13 20:15:29 +0000667
paul020709f2003-04-04 02:44:16 +0000668 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +0000669 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000670 return NULL;
671
672 if (exact)
673 {
674 /* Length is insufficient to lookup OSPF area. */
675 if (*length - v->namelen != sizeof (struct in_addr))
676 return NULL;
677
678 oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
679
paul68980082003-03-25 05:07:42 +0000680 area = ospf_area_lookup_by_area_id (ospf, *addr);
paul718e3742002-12-13 20:15:29 +0000681
682 return area;
683 }
684 else
685 {
686 len = *length - v->namelen;
687 if (len > 4)
688 len = 4;
689
690 oid2in_addr (name + v->namelen, len, addr);
691
paul68980082003-03-25 05:07:42 +0000692 area = ospf_area_lookup_next (ospf, addr, len == 0 ? 1 : 0);
paul718e3742002-12-13 20:15:29 +0000693
694 if (area == NULL)
695 return NULL;
696
697 oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
698 *length = sizeof (struct in_addr) + v->namelen;
699
700 return area;
701 }
702 return NULL;
703}
704
705static u_char *
706ospfAreaEntry (struct variable *v, oid *name, size_t *length, int exact,
707 size_t *var_len, WriteMethod **write_method)
708{
709 struct ospf_area *area;
710 struct in_addr addr;
711
712 memset (&addr, 0, sizeof (struct in_addr));
713
714 area = ospfAreaLookup (v, name, length, &addr, exact);
715 if (! area)
716 return NULL;
717
718 /* Return the current value of the variable */
719 switch (v->magic)
720 {
721 case OSPFAREAID: /* 1 */
722 return SNMP_IPADDRESS (area->area_id);
723 break;
724 case OSPFAUTHTYPE: /* 2 */
725 return SNMP_INTEGER (area->auth_type);
726 break;
727 case OSPFIMPORTASEXTERN: /* 3 */
728 return SNMP_INTEGER (area->external_routing + 1);
729 break;
730 case OSPFSPFRUNS: /* 4 */
731 return SNMP_INTEGER (area->spf_calculation);
732 break;
733 case OSPFAREABDRRTRCOUNT: /* 5 */
734 return SNMP_INTEGER (area->abr_count);
735 break;
736 case OSPFASBDRRTRCOUNT: /* 6 */
737 return SNMP_INTEGER (area->asbr_count);
738 break;
739 case OSPFAREALSACOUNT: /* 7 */
740 return SNMP_INTEGER (area->lsdb->total);
741 break;
742 case OSPFAREALSACKSUMSUM: /* 8 */
743 return SNMP_INTEGER (0);
744 break;
745 case OSPFAREASUMMARY: /* 9 */
746#define OSPF_noAreaSummary 1
747#define OSPF_sendAreaSummary 2
748 if (area->no_summary)
749 return SNMP_INTEGER (OSPF_noAreaSummary);
750 else
751 return SNMP_INTEGER (OSPF_sendAreaSummary);
752 break;
753 case OSPFAREASTATUS: /* 10 */
754 return SNMP_INTEGER (SNMP_VALID);
755 break;
756 default:
757 return NULL;
758 break;
759 }
760 return NULL;
761}
762
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100763static struct ospf_area *
paul718e3742002-12-13 20:15:29 +0000764ospf_stub_area_lookup_next (struct in_addr *area_id, int first)
765{
766 struct ospf_area *area;
paulaa20c6f2004-10-07 14:19:36 +0000767 struct listnode *node;
paul020709f2003-04-04 02:44:16 +0000768 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000769
paul020709f2003-04-04 02:44:16 +0000770 ospf = ospf_lookup ();
771 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000772 return NULL;
773
paul1eb8ef22005-04-07 07:30:20 +0000774 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
paul718e3742002-12-13 20:15:29 +0000775 {
paul718e3742002-12-13 20:15:29 +0000776 if (area->external_routing == OSPF_AREA_STUB)
777 {
778 if (first)
779 {
780 *area_id = area->area_id;
781 return area;
782 }
783 else if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
784 {
785 *area_id = area->area_id;
786 return area;
787 }
788 }
789 }
790 return NULL;
791}
792
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100793static struct ospf_area *
paul718e3742002-12-13 20:15:29 +0000794ospfStubAreaLookup (struct variable *v, oid name[], size_t *length,
795 struct in_addr *addr, int exact)
796{
paul020709f2003-04-04 02:44:16 +0000797 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000798 struct ospf_area *area;
paul68980082003-03-25 05:07:42 +0000799 int len;
paul718e3742002-12-13 20:15:29 +0000800
paul020709f2003-04-04 02:44:16 +0000801 ospf = ospf_lookup ();
802 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000803 return NULL;
804
805 /* Exact lookup. */
806 if (exact)
807 {
808 /* ospfStubAreaID + ospfStubTOS. */
809 if (*length != v->namelen + sizeof (struct in_addr) + 1)
810 return NULL;
811
812 /* Check ospfStubTOS is zero. */
813 if (name[*length - 1] != 0)
814 return NULL;
815
816 oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
817
paul68980082003-03-25 05:07:42 +0000818 area = ospf_area_lookup_by_area_id (ospf, *addr);
paul718e3742002-12-13 20:15:29 +0000819
820 if (area->external_routing == OSPF_AREA_STUB)
821 return area;
822 else
823 return NULL;
824 }
825 else
826 {
827 len = *length - v->namelen;
828 if (len > 4)
829 len = 4;
830
831 oid2in_addr (name + v->namelen, len, addr);
832
833 area = ospf_stub_area_lookup_next (addr, len == 0 ? 1 : 0);
834
835 if (area == NULL)
836 return NULL;
837
838 oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
839 /* Set TOS 0. */
840 name[v->namelen + sizeof (struct in_addr)] = 0;
841 *length = v->namelen + sizeof (struct in_addr) + 1;
842
843 return area;
844 }
845 return NULL;
846}
847
848static u_char *
849ospfStubAreaEntry (struct variable *v, oid *name, size_t *length,
850 int exact, size_t *var_len, WriteMethod **write_method)
851{
852 struct ospf_area *area;
853 struct in_addr addr;
854
855 memset (&addr, 0, sizeof (struct in_addr));
856
857 area = ospfStubAreaLookup (v, name, length, &addr, exact);
858 if (! area)
859 return NULL;
860
861 /* Return the current value of the variable */
862 switch (v->magic)
863 {
864 case OSPFSTUBAREAID: /* 1 */
865 /* OSPF stub area id. */
866 return SNMP_IPADDRESS (area->area_id);
867 break;
868 case OSPFSTUBTOS: /* 2 */
869 /* TOS value is not supported. */
870 return SNMP_INTEGER (0);
871 break;
872 case OSPFSTUBMETRIC: /* 3 */
873 /* Default cost to stub area. */
874 return SNMP_INTEGER (area->default_cost);
875 break;
876 case OSPFSTUBSTATUS: /* 4 */
877 /* Status of the stub area. */
878 return SNMP_INTEGER (SNMP_VALID);
879 break;
880 case OSPFSTUBMETRICTYPE: /* 5 */
881 /* OSPF Metric type. */
882#define OSPF_ospfMetric 1
883#define OSPF_comparableCost 2
884#define OSPF_nonComparable 3
885 return SNMP_INTEGER (OSPF_ospfMetric);
886 break;
887 default:
888 return NULL;
889 break;
890 }
891 return NULL;
892}
893
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100894static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +0000895lsdb_lookup_next (struct ospf_area *area, u_char *type, int type_next,
896 struct in_addr *ls_id, int ls_id_next,
897 struct in_addr *router_id, int router_id_next)
898{
899 struct ospf_lsa *lsa;
900 int i;
901
902 if (type_next)
903 i = OSPF_MIN_LSA;
904 else
905 i = *type;
906
vincentba682532005-09-29 13:52:57 +0000907 /* Sanity check, if LSA type unknwon
908 merley skip any LSA */
909 if ((i < OSPF_MIN_LSA) || (i >= OSPF_MAX_LSA))
910 {
911 zlog_debug("Strange request with LSA type %d\n", i);
912 return NULL;
913 }
914
paul718e3742002-12-13 20:15:29 +0000915 for (; i < OSPF_MAX_LSA; i++)
916 {
917 *type = i;
918
919 lsa = ospf_lsdb_lookup_by_id_next (area->lsdb, *type, *ls_id, *router_id,
920 ls_id_next);
921 if (lsa)
922 return lsa;
923
924 ls_id_next = 1;
925 }
926 return NULL;
927}
928
Chris Caputo0be8dfb2009-06-02 18:40:07 +0100929static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +0000930ospfLsdbLookup (struct variable *v, oid *name, size_t *length,
931 struct in_addr *area_id, u_char *type,
932 struct in_addr *ls_id, struct in_addr *router_id, int exact)
933{
paul020709f2003-04-04 02:44:16 +0000934 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000935 struct ospf_area *area;
936 struct ospf_lsa *lsa;
paul6c835672004-10-11 11:00:30 +0000937 unsigned int len;
paul718e3742002-12-13 20:15:29 +0000938 int type_next;
939 int ls_id_next;
940 int router_id_next;
941 oid *offset;
942 int offsetlen;
943
paul020709f2003-04-04 02:44:16 +0000944 ospf = ospf_lookup ();
945
paul718e3742002-12-13 20:15:29 +0000946#define OSPF_LSDB_ENTRY_OFFSET \
947 (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
948
949 if (exact)
950 {
951 /* Area ID + Type + LS ID + Router ID. */
952 if (*length - v->namelen != OSPF_LSDB_ENTRY_OFFSET)
953 return NULL;
954
955 /* Set OID offset for Area ID. */
956 offset = name + v->namelen;
957
958 /* Lookup area first. */
959 oid2in_addr (offset, IN_ADDR_SIZE, area_id);
paul68980082003-03-25 05:07:42 +0000960 area = ospf_area_lookup_by_area_id (ospf, *area_id);
paul718e3742002-12-13 20:15:29 +0000961 if (! area)
962 return NULL;
963 offset += IN_ADDR_SIZE;
964
965 /* Type. */
966 *type = *offset;
967 offset++;
968
969 /* LS ID. */
970 oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
971 offset += IN_ADDR_SIZE;
972
973 /* Router ID. */
974 oid2in_addr (offset, IN_ADDR_SIZE, router_id);
975
976 /* Lookup LSDB. */
977 return ospf_lsdb_lookup_by_id (area->lsdb, *type, *ls_id, *router_id);
978 }
979 else
980 {
981 /* Get variable length. */
982 offset = name + v->namelen;
983 offsetlen = *length - v->namelen;
984 len = offsetlen;
985
986 if (len > IN_ADDR_SIZE)
987 len = IN_ADDR_SIZE;
988
989 oid2in_addr (offset, len, area_id);
990
991 /* First we search area. */
992 if (len == IN_ADDR_SIZE)
paul68980082003-03-25 05:07:42 +0000993 area = ospf_area_lookup_by_area_id (ospf, *area_id);
paul718e3742002-12-13 20:15:29 +0000994 else
paul68980082003-03-25 05:07:42 +0000995 area = ospf_area_lookup_next (ospf, area_id, len == 0 ? 1 : 0);
paul718e3742002-12-13 20:15:29 +0000996
997 if (area == NULL)
998 return NULL;
999
1000 do
1001 {
1002 /* Next we lookup type. */
1003 offset += IN_ADDR_SIZE;
1004 offsetlen -= IN_ADDR_SIZE;
1005 len = offsetlen;
1006
1007 if (len <= 0)
1008 type_next = 1;
1009 else
1010 {
1011 len = 1;
1012 type_next = 0;
1013 *type = *offset;
1014 }
1015
1016 /* LS ID. */
1017 offset++;
1018 offsetlen--;
1019 len = offsetlen;
1020
1021 if (len <= 0)
1022 ls_id_next = 1;
1023 else
1024 {
1025 ls_id_next = 0;
1026 if (len > IN_ADDR_SIZE)
1027 len = IN_ADDR_SIZE;
1028
1029 oid2in_addr (offset, len, ls_id);
1030 }
1031
1032 /* Router ID. */
1033 offset += IN_ADDR_SIZE;
1034 offsetlen -= IN_ADDR_SIZE;
1035 len = offsetlen;
1036
1037 if (len <= 0)
1038 router_id_next = 1;
1039 else
1040 {
1041 router_id_next = 0;
1042 if (len > IN_ADDR_SIZE)
1043 len = IN_ADDR_SIZE;
1044
1045 oid2in_addr (offset, len, router_id);
1046 }
1047
1048 lsa = lsdb_lookup_next (area, type, type_next, ls_id, ls_id_next,
1049 router_id, router_id_next);
1050
1051 if (lsa)
1052 {
1053 /* Fill in length. */
1054 *length = v->namelen + OSPF_LSDB_ENTRY_OFFSET;
1055
1056 /* Fill in value. */
1057 offset = name + v->namelen;
1058 oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
1059 offset += IN_ADDR_SIZE;
1060 *offset = lsa->data->type;
1061 offset++;
1062 oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
1063 offset += IN_ADDR_SIZE;
1064 oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
1065
1066 return lsa;
1067 }
1068 }
paul68980082003-03-25 05:07:42 +00001069 while ((area = ospf_area_lookup_next (ospf, area_id, 0)) != NULL);
paul718e3742002-12-13 20:15:29 +00001070 }
1071 return NULL;
1072}
1073
1074static u_char *
1075ospfLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
1076 size_t *var_len, WriteMethod **write_method)
1077{
1078 struct ospf_lsa *lsa;
1079 struct lsa_header *lsah;
1080 struct in_addr area_id;
1081 u_char type;
1082 struct in_addr ls_id;
1083 struct in_addr router_id;
paul020709f2003-04-04 02:44:16 +00001084 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001085
1086 /* INDEX { ospfLsdbAreaId, ospfLsdbType,
1087 ospfLsdbLsid, ospfLsdbRouterId } */
1088
1089 memset (&area_id, 0, sizeof (struct in_addr));
1090 type = 0;
1091 memset (&ls_id, 0, sizeof (struct in_addr));
1092 memset (&router_id, 0, sizeof (struct in_addr));
1093
1094 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001095 ospf = ospf_lookup ();
1096 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001097 return NULL;
1098
1099 lsa = ospfLsdbLookup (v, name, length, &area_id, &type, &ls_id, &router_id,
1100 exact);
1101 if (! lsa)
1102 return NULL;
1103
1104 lsah = lsa->data;
1105
1106 /* Return the current value of the variable */
1107 switch (v->magic)
1108 {
1109 case OSPFLSDBAREAID: /* 1 */
1110 return SNMP_IPADDRESS (lsa->area->area_id);
1111 break;
1112 case OSPFLSDBTYPE: /* 2 */
1113 return SNMP_INTEGER (lsah->type);
1114 break;
1115 case OSPFLSDBLSID: /* 3 */
1116 return SNMP_IPADDRESS (lsah->id);
1117 break;
1118 case OSPFLSDBROUTERID: /* 4 */
1119 return SNMP_IPADDRESS (lsah->adv_router);
1120 break;
1121 case OSPFLSDBSEQUENCE: /* 5 */
1122 return SNMP_INTEGER (lsah->ls_seqnum);
1123 break;
1124 case OSPFLSDBAGE: /* 6 */
1125 return SNMP_INTEGER (lsah->ls_age);
1126 break;
1127 case OSPFLSDBCHECKSUM: /* 7 */
1128 return SNMP_INTEGER (lsah->checksum);
1129 break;
1130 case OSPFLSDBADVERTISEMENT: /* 8 */
1131 *var_len = ntohs (lsah->length);
1132 return (u_char *) lsah;
1133 break;
1134 default:
1135 return NULL;
1136 break;
1137 }
1138 return NULL;
1139}
1140
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001141static struct ospf_area_range *
paul718e3742002-12-13 20:15:29 +00001142ospfAreaRangeLookup (struct variable *v, oid *name, size_t *length,
1143 struct in_addr *area_id, struct in_addr *range_net,
1144 int exact)
1145{
1146 oid *offset;
1147 int offsetlen;
paul6c835672004-10-11 11:00:30 +00001148 unsigned int len;
paul020709f2003-04-04 02:44:16 +00001149 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001150 struct ospf_area *area;
1151 struct ospf_area_range *range;
1152 struct prefix_ipv4 p;
1153 p.family = AF_INET;
1154 p.prefixlen = IPV4_MAX_BITLEN;
1155
paul020709f2003-04-04 02:44:16 +00001156 ospf = ospf_lookup ();
1157
paul718e3742002-12-13 20:15:29 +00001158 if (exact)
1159 {
1160 /* Area ID + Range Network. */
1161 if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length)
1162 return NULL;
1163
1164 /* Set OID offset for Area ID. */
1165 offset = name + v->namelen;
1166
1167 /* Lookup area first. */
1168 oid2in_addr (offset, IN_ADDR_SIZE, area_id);
1169
paul68980082003-03-25 05:07:42 +00001170 area = ospf_area_lookup_by_area_id (ospf, *area_id);
paul718e3742002-12-13 20:15:29 +00001171 if (! area)
1172 return NULL;
1173
1174 offset += IN_ADDR_SIZE;
1175
1176 /* Lookup area range. */
1177 oid2in_addr (offset, IN_ADDR_SIZE, range_net);
1178 p.prefix = *range_net;
1179
1180 return ospf_area_range_lookup (area, &p);
1181 }
1182 else
1183 {
1184 /* Set OID offset for Area ID. */
1185 offset = name + v->namelen;
1186 offsetlen = *length - v->namelen;
1187
1188 len = offsetlen;
1189 if (len > IN_ADDR_SIZE)
1190 len = IN_ADDR_SIZE;
1191
1192 oid2in_addr (offset, len, area_id);
1193
1194 /* First we search area. */
1195 if (len == IN_ADDR_SIZE)
paul68980082003-03-25 05:07:42 +00001196 area = ospf_area_lookup_by_area_id (ospf,*area_id);
paul718e3742002-12-13 20:15:29 +00001197 else
paul68980082003-03-25 05:07:42 +00001198 area = ospf_area_lookup_next (ospf, area_id, len == 0 ? 1 : 0);
paul718e3742002-12-13 20:15:29 +00001199
1200 if (area == NULL)
1201 return NULL;
1202
1203 do
1204 {
1205 offset += IN_ADDR_SIZE;
1206 offsetlen -= IN_ADDR_SIZE;
1207 len = offsetlen;
1208
1209 if (len < 0)
1210 len = 0;
1211 if (len > IN_ADDR_SIZE)
1212 len = IN_ADDR_SIZE;
1213
1214 oid2in_addr (offset, len, range_net);
1215
1216 range = ospf_area_range_lookup_next (area, range_net,
1217 len == 0 ? 1 : 0);
1218
1219 if (range)
1220 {
1221 /* Fill in length. */
1222 *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
1223
1224 /* Fill in value. */
1225 offset = name + v->namelen;
1226 oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
1227 offset += IN_ADDR_SIZE;
1228 oid_copy_addr (offset, range_net, IN_ADDR_SIZE);
1229
1230 return range;
1231 }
1232 }
paul68980082003-03-25 05:07:42 +00001233 while ((area = ospf_area_lookup_next (ospf, area_id, 0)) != NULL);
paul718e3742002-12-13 20:15:29 +00001234 }
1235 return NULL;
1236}
1237
1238static u_char *
1239ospfAreaRangeEntry (struct variable *v, oid *name, size_t *length, int exact,
1240 size_t *var_len, WriteMethod **write_method)
1241{
1242 struct ospf_area_range *range;
1243 struct in_addr area_id;
1244 struct in_addr range_net;
1245 struct in_addr mask;
paul020709f2003-04-04 02:44:16 +00001246 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001247
1248 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001249 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001250 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001251 return NULL;
1252
1253 memset (&area_id, 0, IN_ADDR_SIZE);
1254 memset (&range_net, 0, IN_ADDR_SIZE);
1255
1256 range = ospfAreaRangeLookup (v, name, length, &area_id, &range_net, exact);
1257 if (! range)
1258 return NULL;
1259
1260 /* Convert prefixlen to network mask format. */
1261 masklen2ip (range->subst_masklen, &mask);
1262
1263 /* Return the current value of the variable */
1264 switch (v->magic)
1265 {
1266 case OSPFAREARANGEAREAID: /* 1 */
1267 return SNMP_IPADDRESS (area_id);
1268 break;
1269 case OSPFAREARANGENET: /* 2 */
1270 return SNMP_IPADDRESS (range_net);
1271 break;
1272 case OSPFAREARANGEMASK: /* 3 */
1273 return SNMP_IPADDRESS (mask);
1274 break;
1275 case OSPFAREARANGESTATUS: /* 4 */
1276 return SNMP_INTEGER (SNMP_VALID);
1277 break;
1278 case OSPFAREARANGEEFFECT: /* 5 */
1279#define OSPF_advertiseMatching 1
1280#define OSPF_doNotAdvertiseMatching 2
1281 return SNMP_INTEGER (OSPF_advertiseMatching);
1282 break;
1283 default:
1284 return NULL;
1285 break;
1286 }
1287 return NULL;
1288}
1289
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001290static struct ospf_nbr_nbma *
paul718e3742002-12-13 20:15:29 +00001291ospfHostLookup (struct variable *v, oid *name, size_t *length,
1292 struct in_addr *addr, int exact)
1293{
1294 int len;
1295 struct ospf_nbr_nbma *nbr_nbma;
paul020709f2003-04-04 02:44:16 +00001296 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001297
paul020709f2003-04-04 02:44:16 +00001298 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001299 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001300 return NULL;
1301
1302 if (exact)
1303 {
1304 /* INDEX { ospfHostIpAddress, ospfHostTOS } */
1305 if (*length != v->namelen + IN_ADDR_SIZE + 1)
1306 return NULL;
1307
1308 /* Check ospfHostTOS. */
1309 if (name[*length - 1] != 0)
1310 return NULL;
1311
1312 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr);
1313
paul68980082003-03-25 05:07:42 +00001314 nbr_nbma = ospf_nbr_nbma_lookup (ospf, *addr);
paul718e3742002-12-13 20:15:29 +00001315
1316 return nbr_nbma;
1317 }
1318 else
1319 {
1320 len = *length - v->namelen;
1321 if (len > 4)
1322 len = 4;
1323
1324 oid2in_addr (name + v->namelen, len, addr);
1325
paul68980082003-03-25 05:07:42 +00001326 nbr_nbma = ospf_nbr_nbma_lookup_next (ospf, addr, len == 0 ? 1 : 0);
paul718e3742002-12-13 20:15:29 +00001327
1328 if (nbr_nbma == NULL)
1329 return NULL;
1330
1331 oid_copy_addr (name + v->namelen, addr, IN_ADDR_SIZE);
1332
1333 /* Set TOS 0. */
1334 name[v->namelen + IN_ADDR_SIZE] = 0;
1335
1336 *length = v->namelen + IN_ADDR_SIZE + 1;
1337
1338 return nbr_nbma;
1339 }
1340 return NULL;
1341}
1342
1343static u_char *
1344ospfHostEntry (struct variable *v, oid *name, size_t *length, int exact,
1345 size_t *var_len, WriteMethod **write_method)
1346{
1347 struct ospf_nbr_nbma *nbr_nbma;
1348 struct ospf_interface *oi;
1349 struct in_addr addr;
paul020709f2003-04-04 02:44:16 +00001350 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001351
1352 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001353 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001354 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001355 return NULL;
1356
1357 memset (&addr, 0, sizeof (struct in_addr));
1358
1359 nbr_nbma = ospfHostLookup (v, name, length, &addr, exact);
1360 if (nbr_nbma == NULL)
1361 return NULL;
1362
1363 oi = nbr_nbma->oi;
1364
1365 /* Return the current value of the variable */
1366 switch (v->magic)
1367 {
1368 case OSPFHOSTIPADDRESS: /* 1 */
1369 return SNMP_IPADDRESS (nbr_nbma->addr);
1370 break;
1371 case OSPFHOSTTOS: /* 2 */
1372 return SNMP_INTEGER (0);
1373 break;
1374 case OSPFHOSTMETRIC: /* 3 */
1375 if (oi)
1376 return SNMP_INTEGER (oi->output_cost);
1377 else
1378 return SNMP_INTEGER (1);
1379 break;
1380 case OSPFHOSTSTATUS: /* 4 */
1381 return SNMP_INTEGER (SNMP_VALID);
1382 break;
1383 case OSPFHOSTAREAID: /* 5 */
1384 if (oi && oi->area)
1385 return SNMP_IPADDRESS (oi->area->area_id);
1386 else
1387 return SNMP_IPADDRESS (ospf_empty_addr);
1388 break;
1389 default:
1390 return NULL;
1391 break;
1392 }
1393 return NULL;
1394}
1395
1396struct list *ospf_snmp_iflist;
1397
1398struct ospf_snmp_if
1399{
1400 struct in_addr addr;
1401 unsigned int ifindex;
1402 struct interface *ifp;
1403};
1404
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001405static struct ospf_snmp_if *
paul718e3742002-12-13 20:15:29 +00001406ospf_snmp_if_new ()
1407{
1408 struct ospf_snmp_if *osif;
1409
1410 osif = XMALLOC (0, sizeof (struct ospf_snmp_if));
1411 memset (osif, 0, sizeof (struct ospf_snmp_if));
1412 return osif;
1413}
1414
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001415static void
paul718e3742002-12-13 20:15:29 +00001416ospf_snmp_if_free (struct ospf_snmp_if *osif)
1417{
1418 XFREE (0, osif);
1419}
1420
1421void
1422ospf_snmp_if_delete (struct interface *ifp)
1423{
paul1eb8ef22005-04-07 07:30:20 +00001424 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001425 struct ospf_snmp_if *osif;
1426
paul1eb8ef22005-04-07 07:30:20 +00001427 for (ALL_LIST_ELEMENTS (ospf_snmp_iflist, node, nnode, osif))
paul718e3742002-12-13 20:15:29 +00001428 {
1429 if (osif->ifp == ifp)
1430 {
paul1eb8ef22005-04-07 07:30:20 +00001431 list_delete_node (ospf_snmp_iflist, node);
paul718e3742002-12-13 20:15:29 +00001432 ospf_snmp_if_free (osif);
1433 return;
1434 }
1435 }
1436}
1437
1438void
1439ospf_snmp_if_update (struct interface *ifp)
1440{
paul1eb8ef22005-04-07 07:30:20 +00001441 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001442 struct listnode *pn;
1443 struct connected *ifc;
1444 struct prefix *p;
1445 struct ospf_snmp_if *osif;
1446 struct in_addr *addr;
1447 unsigned int ifindex;
1448
1449 ospf_snmp_if_delete (ifp);
1450
1451 p = NULL;
1452 addr = NULL;
1453 ifindex = 0;
1454
1455 /* Lookup first IPv4 address entry. */
paul1eb8ef22005-04-07 07:30:20 +00001456 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
paul718e3742002-12-13 20:15:29 +00001457 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001458 p = CONNECTED_ID(ifc);
paul718e3742002-12-13 20:15:29 +00001459
1460 if (p->family == AF_INET)
1461 {
1462 addr = &p->u.prefix4;
1463 break;
1464 }
1465 }
1466 if (! addr)
1467 ifindex = ifp->ifindex;
1468
1469 /* Add interface to the list. */
1470 pn = NULL;
paul1eb8ef22005-04-07 07:30:20 +00001471 for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, node, osif))
paul718e3742002-12-13 20:15:29 +00001472 {
1473 if (addr)
1474 {
vincent77df1f72005-10-06 07:46:22 +00001475 /* Usual interfaces --> Sort them based on interface IPv4 addresses */
paul718e3742002-12-13 20:15:29 +00001476 if (ntohl (osif->addr.s_addr) > ntohl (addr->s_addr))
1477 break;
1478 }
1479 else
1480 {
vincent77df1f72005-10-06 07:46:22 +00001481 /* Unnumbered interfaces --> Sort them based on interface indexes */
paul718e3742002-12-13 20:15:29 +00001482 if (osif->addr.s_addr != 0 || osif->ifindex > ifindex)
1483 break;
1484 }
paul1eb8ef22005-04-07 07:30:20 +00001485 pn = node;
paul718e3742002-12-13 20:15:29 +00001486 }
1487
1488 osif = ospf_snmp_if_new ();
vincent77df1f72005-10-06 07:46:22 +00001489 if (addr) /* Usual interface */
1490 {
paul718e3742002-12-13 20:15:29 +00001491 osif->addr = *addr;
vincent77df1f72005-10-06 07:46:22 +00001492
1493 /* This field is used for storing ospfAddressLessIf OID value,
1494 * conform to RFC1850 OSPF-MIB specification, it must be 0 for
1495 * usual interface */
1496 osif->ifindex = 0;
1497 }
1498 else /* Unnumbered interface */
paul718e3742002-12-13 20:15:29 +00001499 osif->ifindex = ifindex;
1500 osif->ifp = ifp;
1501
1502 listnode_add_after (ospf_snmp_iflist, pn, osif);
1503}
1504
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001505static int
vincent77df1f72005-10-06 07:46:22 +00001506ospf_snmp_is_if_have_addr (struct interface *ifp)
1507{
vincent77df1f72005-10-06 07:46:22 +00001508 struct listnode *nn;
1509 struct connected *ifc;
1510
1511 /* Is this interface having any connected IPv4 address ? */
1512 for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, ifc))
1513 {
Andrew J. Schorre4529632006-12-12 19:18:21 +00001514 if (CONNECTED_PREFIX(ifc)->family == AF_INET)
vincent77df1f72005-10-06 07:46:22 +00001515 return 1;
1516 }
1517
1518 return 0;
1519}
1520
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001521static struct ospf_interface *
paul718e3742002-12-13 20:15:29 +00001522ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex)
1523{
paul1eb8ef22005-04-07 07:30:20 +00001524 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001525 struct ospf_snmp_if *osif;
vincent77df1f72005-10-06 07:46:22 +00001526 struct ospf_interface *oi = NULL;
1527 struct ospf *ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00001528
paul1eb8ef22005-04-07 07:30:20 +00001529 for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, node, osif))
paul718e3742002-12-13 20:15:29 +00001530 {
1531 if (ifaddr->s_addr)
vincent77df1f72005-10-06 07:46:22 +00001532 {
1533 if (IPV4_ADDR_SAME (&osif->addr, ifaddr))
1534 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1535 }
paul718e3742002-12-13 20:15:29 +00001536 else
vincent77df1f72005-10-06 07:46:22 +00001537 {
1538 if (osif->ifindex == *ifindex)
1539 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1540 }
paul718e3742002-12-13 20:15:29 +00001541 }
vincent77df1f72005-10-06 07:46:22 +00001542 return oi;
paul718e3742002-12-13 20:15:29 +00001543}
1544
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001545static struct ospf_interface *
paul718e3742002-12-13 20:15:29 +00001546ospf_snmp_if_lookup_next (struct in_addr *ifaddr, unsigned int *ifindex,
1547 int ifaddr_next, int ifindex_next)
1548{
1549 struct ospf_snmp_if *osif;
1550 struct listnode *nn;
vincent77df1f72005-10-06 07:46:22 +00001551 struct ospf *ospf = ospf_lookup ();
1552 struct ospf_interface *oi = NULL;
paul718e3742002-12-13 20:15:29 +00001553
vincent77df1f72005-10-06 07:46:22 +00001554 if (ospf == NULL)
1555 return NULL;
1556
1557 /* No instance is specified --> Return the first OSPF interface */
paul718e3742002-12-13 20:15:29 +00001558 if (ifaddr_next)
1559 {
vincent77df1f72005-10-06 07:46:22 +00001560 for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, nn, osif))
paul718e3742002-12-13 20:15:29 +00001561 {
paul1eb8ef22005-04-07 07:30:20 +00001562 osif = listgetdata (nn);
paul718e3742002-12-13 20:15:29 +00001563 *ifaddr = osif->addr;
1564 *ifindex = osif->ifindex;
vincent77df1f72005-10-06 07:46:22 +00001565 /* Because no instance is specified, we don't care about the kind of
1566 * interface (usual or unnumbered), just returning the first valid
1567 * OSPF interface */
1568 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1569 if (oi)
1570 return (oi);
paul718e3742002-12-13 20:15:29 +00001571 }
1572 return NULL;
1573 }
1574
vincent77df1f72005-10-06 07:46:22 +00001575 /* An instance is specified --> Return the next OSPF interface */
paul1eb8ef22005-04-07 07:30:20 +00001576 for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, nn, osif))
paul718e3742002-12-13 20:15:29 +00001577 {
vincent77df1f72005-10-06 07:46:22 +00001578 /* Usual interface */
1579 if (ifaddr->s_addr)
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001580 {
1581 /* The interface must have valid AF_INET connected address */
1582 /* it must have lager IPv4 address value than the lookup entry */
1583 if ((ospf_snmp_is_if_have_addr(osif->ifp)) &&
1584 (ntohl (osif->addr.s_addr) > ntohl (ifaddr->s_addr)))
1585 {
1586 *ifaddr = osif->addr;
1587 *ifindex = osif->ifindex;
vincent77df1f72005-10-06 07:46:22 +00001588
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001589 /* and it must be an OSPF interface */
1590 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1591 if (oi)
1592 return oi;
1593 }
1594 }
vincent77df1f72005-10-06 07:46:22 +00001595 /* Unnumbered interface */
1596 else
1597 /* The interface must NOT have valid AF_INET connected address */
1598 /* it must have lager interface index than the lookup entry */
1599 if ((!ospf_snmp_is_if_have_addr(osif->ifp)) &&
1600 (osif->ifindex > *ifindex))
1601 {
1602 *ifaddr = osif->addr;
1603 *ifindex = osif->ifindex;
1604
1605 /* and it must be an OSPF interface */
1606 oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr);
1607 if (oi)
1608 return oi;
1609 }
paul718e3742002-12-13 20:15:29 +00001610 }
1611 return NULL;
1612}
1613
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001614static int
paul718e3742002-12-13 20:15:29 +00001615ospf_snmp_iftype (struct interface *ifp)
1616{
1617#define ospf_snmp_iftype_broadcast 1
1618#define ospf_snmp_iftype_nbma 2
1619#define ospf_snmp_iftype_pointToPoint 3
1620#define ospf_snmp_iftype_pointToMultipoint 5
1621 if (if_is_broadcast (ifp))
1622 return ospf_snmp_iftype_broadcast;
1623 if (if_is_pointopoint (ifp))
1624 return ospf_snmp_iftype_pointToPoint;
1625 return ospf_snmp_iftype_broadcast;
1626}
1627
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001628static struct ospf_interface *
paul718e3742002-12-13 20:15:29 +00001629ospfIfLookup (struct variable *v, oid *name, size_t *length,
1630 struct in_addr *ifaddr, unsigned int *ifindex, int exact)
1631{
paul6c835672004-10-11 11:00:30 +00001632 unsigned int len;
paul718e3742002-12-13 20:15:29 +00001633 int ifaddr_next = 0;
1634 int ifindex_next = 0;
vincent77df1f72005-10-06 07:46:22 +00001635 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +00001636 oid *offset;
1637
1638 if (exact)
1639 {
1640 if (*length != v->namelen + IN_ADDR_SIZE + 1)
1641 return NULL;
1642
1643 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
1644 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1645
1646 return ospf_snmp_if_lookup (ifaddr, ifindex);
1647 }
1648 else
1649 {
1650 len = *length - v->namelen;
1651 if (len >= IN_ADDR_SIZE)
1652 len = IN_ADDR_SIZE;
1653 if (len <= 0)
1654 ifaddr_next = 1;
1655
1656 oid2in_addr (name + v->namelen, len, ifaddr);
1657
1658 len = *length - v->namelen - IN_ADDR_SIZE;
1659 if (len >= 1)
1660 len = 1;
1661 else
1662 ifindex_next = 1;
1663
1664 if (len == 1)
1665 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1666
vincent77df1f72005-10-06 07:46:22 +00001667 oi = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
paul718e3742002-12-13 20:15:29 +00001668 ifindex_next);
vincent77df1f72005-10-06 07:46:22 +00001669 if (oi)
paul718e3742002-12-13 20:15:29 +00001670 {
1671 *length = v->namelen + IN_ADDR_SIZE + 1;
1672 offset = name + v->namelen;
1673 oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
1674 offset += IN_ADDR_SIZE;
1675 *offset = *ifindex;
vincent77df1f72005-10-06 07:46:22 +00001676 return oi;
paul718e3742002-12-13 20:15:29 +00001677 }
1678 }
1679 return NULL;
1680}
1681
1682static u_char *
1683ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001684 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00001685{
paul718e3742002-12-13 20:15:29 +00001686 unsigned int ifindex;
1687 struct in_addr ifaddr;
1688 struct ospf_interface *oi;
paul020709f2003-04-04 02:44:16 +00001689 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001690
1691 ifindex = 0;
1692 memset (&ifaddr, 0, sizeof (struct in_addr));
1693
1694 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001695 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001696 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001697 return NULL;
1698
vincent77df1f72005-10-06 07:46:22 +00001699 oi = ospfIfLookup (v, name, length, &ifaddr, &ifindex, exact);
paul718e3742002-12-13 20:15:29 +00001700 if (oi == NULL)
1701 return NULL;
1702
1703 /* Return the current value of the variable */
1704 switch (v->magic)
1705 {
1706 case OSPFIFIPADDRESS: /* 1 */
1707 return SNMP_IPADDRESS (ifaddr);
1708 break;
1709 case OSPFADDRESSLESSIF: /* 2 */
1710 return SNMP_INTEGER (ifindex);
1711 break;
1712 case OSPFIFAREAID: /* 3 */
1713 if (oi->area)
1714 return SNMP_IPADDRESS (oi->area->area_id);
1715 else
1716 return SNMP_IPADDRESS (ospf_empty_addr);
1717 break;
1718 case OSPFIFTYPE: /* 4 */
vincent77df1f72005-10-06 07:46:22 +00001719 return SNMP_INTEGER (ospf_snmp_iftype (oi->ifp));
paul718e3742002-12-13 20:15:29 +00001720 break;
1721 case OSPFIFADMINSTAT: /* 5 */
1722 if (oi)
1723 return SNMP_INTEGER (OSPF_STATUS_ENABLED);
1724 else
1725 return SNMP_INTEGER (OSPF_STATUS_DISABLED);
1726 break;
1727 case OSPFIFRTRPRIORITY: /* 6 */
1728 return SNMP_INTEGER (PRIORITY (oi));
1729 break;
1730 case OSPFIFTRANSITDELAY: /* 7 */
1731 return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
1732 break;
1733 case OSPFIFRETRANSINTERVAL: /* 8 */
1734 return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
1735 break;
1736 case OSPFIFHELLOINTERVAL: /* 9 */
1737 return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
1738 break;
1739 case OSPFIFRTRDEADINTERVAL: /* 10 */
1740 return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
1741 break;
1742 case OSPFIFPOLLINTERVAL: /* 11 */
1743 return SNMP_INTEGER (OSPF_POLL_INTERVAL_DEFAULT);
1744 break;
1745 case OSPFIFSTATE: /* 12 */
vincentba682532005-09-29 13:52:57 +00001746 return SNMP_INTEGER (ISM_SNMP(oi->state));
paul718e3742002-12-13 20:15:29 +00001747 break;
1748 case OSPFIFDESIGNATEDROUTER: /* 13 */
1749 return SNMP_IPADDRESS (DR (oi));
1750 break;
1751 case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */
1752 return SNMP_IPADDRESS (BDR (oi));
1753 break;
1754 case OSPFIFEVENTS: /* 15 */
1755 return SNMP_INTEGER (oi->state_change);
1756 break;
1757 case OSPFIFAUTHKEY: /* 16 */
1758 *var_len = 0;
1759 return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
1760 break;
1761 case OSPFIFSTATUS: /* 17 */
1762 return SNMP_INTEGER (SNMP_VALID);
1763 break;
1764 case OSPFIFMULTICASTFORWARDING: /* 18 */
1765#define ospf_snmp_multiforward_blocked 1
1766#define ospf_snmp_multiforward_multicast 2
1767#define ospf_snmp_multiforward_unicast 3
1768 return SNMP_INTEGER (ospf_snmp_multiforward_blocked);
1769 break;
1770 case OSPFIFDEMAND: /* 19 */
1771 return SNMP_INTEGER (SNMP_FALSE);
1772 break;
1773 case OSPFIFAUTHTYPE: /* 20 */
1774 if (oi->area)
1775 return SNMP_INTEGER (oi->area->auth_type);
1776 else
1777 return SNMP_INTEGER (0);
1778 break;
1779 default:
1780 return NULL;
1781 break;
1782 }
1783 return NULL;
1784}
1785
1786#define OSPF_SNMP_METRIC_VALUE 1
1787
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001788static struct ospf_interface *
paul718e3742002-12-13 20:15:29 +00001789ospfIfMetricLookup (struct variable *v, oid *name, size_t *length,
1790 struct in_addr *ifaddr, unsigned int *ifindex, int exact)
1791{
paul6c835672004-10-11 11:00:30 +00001792 unsigned int len;
paul718e3742002-12-13 20:15:29 +00001793 int ifaddr_next = 0;
1794 int ifindex_next = 0;
vincent77df1f72005-10-06 07:46:22 +00001795 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +00001796 oid *offset;
1797 int metric;
1798
1799 if (exact)
1800 {
1801 if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1)
1802 return NULL;
1803
1804 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
1805 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1806 metric = name[v->namelen + IN_ADDR_SIZE + 1];
1807
1808 if (metric != OSPF_SNMP_METRIC_VALUE)
1809 return NULL;
1810
1811 return ospf_snmp_if_lookup (ifaddr, ifindex);
1812 }
1813 else
1814 {
1815 len = *length - v->namelen;
1816 if (len >= IN_ADDR_SIZE)
1817 len = IN_ADDR_SIZE;
1818 else
1819 ifaddr_next = 1;
1820
1821 oid2in_addr (name + v->namelen, len, ifaddr);
1822
1823 len = *length - v->namelen - IN_ADDR_SIZE;
1824 if (len >= 1)
1825 len = 1;
1826 else
1827 ifindex_next = 1;
1828
1829 if (len == 1)
1830 *ifindex = name[v->namelen + IN_ADDR_SIZE];
1831
vincent77df1f72005-10-06 07:46:22 +00001832 oi = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
paul718e3742002-12-13 20:15:29 +00001833 ifindex_next);
vincent77df1f72005-10-06 07:46:22 +00001834 if (oi)
paul718e3742002-12-13 20:15:29 +00001835 {
1836 *length = v->namelen + IN_ADDR_SIZE + 1 + 1;
1837 offset = name + v->namelen;
1838 oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
1839 offset += IN_ADDR_SIZE;
1840 *offset = *ifindex;
1841 offset++;
1842 *offset = OSPF_SNMP_METRIC_VALUE;
vincent77df1f72005-10-06 07:46:22 +00001843 return oi;
paul718e3742002-12-13 20:15:29 +00001844 }
1845 }
1846 return NULL;
1847}
1848
1849static u_char *
1850ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact,
1851 size_t *var_len, WriteMethod **write_method)
1852{
1853 /* Currently we support metric 1 only. */
paul718e3742002-12-13 20:15:29 +00001854 unsigned int ifindex;
1855 struct in_addr ifaddr;
1856 struct ospf_interface *oi;
paul020709f2003-04-04 02:44:16 +00001857 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001858
1859 ifindex = 0;
1860 memset (&ifaddr, 0, sizeof (struct in_addr));
1861
1862 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00001863 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00001864 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001865 return NULL;
1866
vincent77df1f72005-10-06 07:46:22 +00001867 oi = ospfIfMetricLookup (v, name, length, &ifaddr, &ifindex, exact);
paul718e3742002-12-13 20:15:29 +00001868 if (oi == NULL)
1869 return NULL;
1870
1871 /* Return the current value of the variable */
1872 switch (v->magic)
1873 {
1874 case OSPFIFMETRICIPADDRESS:
1875 return SNMP_IPADDRESS (ifaddr);
1876 break;
1877 case OSPFIFMETRICADDRESSLESSIF:
1878 return SNMP_INTEGER (ifindex);
1879 break;
1880 case OSPFIFMETRICTOS:
1881 return SNMP_INTEGER (0);
1882 break;
1883 case OSPFIFMETRICVALUE:
1884 return SNMP_INTEGER (OSPF_SNMP_METRIC_VALUE);
1885 break;
1886 case OSPFIFMETRICSTATUS:
1887 return SNMP_INTEGER (1);
1888 break;
1889 default:
1890 return NULL;
1891 break;
1892 }
1893 return NULL;
1894}
1895
1896struct route_table *ospf_snmp_vl_table;
1897
1898void
1899ospf_snmp_vl_add (struct ospf_vl_data *vl_data)
1900{
1901 struct prefix_ls lp;
1902 struct route_node *rn;
1903
1904 memset (&lp, 0, sizeof (struct prefix_ls));
1905 lp.family = 0;
1906 lp.prefixlen = 64;
1907 lp.id = vl_data->vl_area_id;
1908 lp.adv_router = vl_data->vl_peer;
1909
1910 rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
1911 rn->info = vl_data;
1912}
1913
1914void
1915ospf_snmp_vl_delete (struct ospf_vl_data *vl_data)
1916{
1917 struct prefix_ls lp;
1918 struct route_node *rn;
1919
1920 memset (&lp, 0, sizeof (struct prefix_ls));
1921 lp.family = 0;
1922 lp.prefixlen = 64;
1923 lp.id = vl_data->vl_area_id;
1924 lp.adv_router = vl_data->vl_peer;
1925
1926 rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
1927 if (! rn)
1928 return;
1929 rn->info = NULL;
1930 route_unlock_node (rn);
1931 route_unlock_node (rn);
1932}
1933
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001934static struct ospf_vl_data *
paul718e3742002-12-13 20:15:29 +00001935ospf_snmp_vl_lookup (struct in_addr *area_id, struct in_addr *neighbor)
1936{
1937 struct prefix_ls lp;
1938 struct route_node *rn;
1939 struct ospf_vl_data *vl_data;
1940
1941 memset (&lp, 0, sizeof (struct prefix_ls));
1942 lp.family = 0;
1943 lp.prefixlen = 64;
1944 lp.id = *area_id;
1945 lp.adv_router = *neighbor;
1946
1947 rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
1948 if (rn)
1949 {
1950 vl_data = rn->info;
1951 route_unlock_node (rn);
1952 return vl_data;
1953 }
1954 return NULL;
1955}
1956
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001957static struct ospf_vl_data *
paul718e3742002-12-13 20:15:29 +00001958ospf_snmp_vl_lookup_next (struct in_addr *area_id, struct in_addr *neighbor,
1959 int first)
1960{
1961 struct prefix_ls lp;
1962 struct route_node *rn;
1963 struct ospf_vl_data *vl_data;
1964
1965 memset (&lp, 0, sizeof (struct prefix_ls));
1966 lp.family = 0;
1967 lp.prefixlen = 64;
1968 lp.id = *area_id;
1969 lp.adv_router = *neighbor;
1970
1971 if (first)
1972 rn = route_top (ospf_snmp_vl_table);
1973 else
1974 {
1975 rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
1976 rn = route_next (rn);
1977 }
1978
1979 for (; rn; rn = route_next (rn))
1980 if (rn->info)
1981 break;
1982
1983 if (rn && rn->info)
1984 {
1985 vl_data = rn->info;
1986 *area_id = vl_data->vl_area_id;
1987 *neighbor = vl_data->vl_peer;
1988 route_unlock_node (rn);
1989 return vl_data;
1990 }
1991 return NULL;
1992}
1993
Chris Caputo0be8dfb2009-06-02 18:40:07 +01001994static struct ospf_vl_data *
paul718e3742002-12-13 20:15:29 +00001995ospfVirtIfLookup (struct variable *v, oid *name, size_t *length,
1996 struct in_addr *area_id, struct in_addr *neighbor, int exact)
1997{
1998 int first;
paul6c835672004-10-11 11:00:30 +00001999 unsigned int len;
paul718e3742002-12-13 20:15:29 +00002000 struct ospf_vl_data *vl_data;
2001
2002 if (exact)
2003 {
2004 if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE)
2005 return NULL;
2006
2007 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, area_id);
2008 oid2in_addr (name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE, neighbor);
2009
2010 return ospf_snmp_vl_lookup (area_id, neighbor);
2011 }
2012 else
2013 {
2014 first = 0;
2015
2016 len = *length - v->namelen;
2017 if (len <= 0)
2018 first = 1;
2019 if (len > IN_ADDR_SIZE)
2020 len = IN_ADDR_SIZE;
2021 oid2in_addr (name + v->namelen, len, area_id);
2022
2023 len = *length - v->namelen - IN_ADDR_SIZE;
2024 if (len > IN_ADDR_SIZE)
2025 len = IN_ADDR_SIZE;
2026 oid2in_addr (name + v->namelen + IN_ADDR_SIZE, len, neighbor);
2027
2028 vl_data = ospf_snmp_vl_lookup_next (area_id, neighbor, first);
2029
2030 if (vl_data)
2031 {
2032 *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
2033 oid_copy_addr (name + v->namelen, area_id, IN_ADDR_SIZE);
2034 oid_copy_addr (name + v->namelen + IN_ADDR_SIZE, neighbor,
2035 IN_ADDR_SIZE);
2036 return vl_data;
2037 }
2038 }
2039 return NULL;
2040}
2041
2042static u_char *
2043ospfVirtIfEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002044 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00002045{
2046 struct ospf_vl_data *vl_data;
2047 struct ospf_interface *oi;
2048 struct in_addr area_id;
2049 struct in_addr neighbor;
2050
2051 memset (&area_id, 0, sizeof (struct in_addr));
2052 memset (&neighbor, 0, sizeof (struct in_addr));
2053
2054 vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
2055 if (! vl_data)
2056 return NULL;
2057 oi = vl_data->vl_oi;
2058 if (! oi)
2059 return NULL;
2060
2061 /* Return the current value of the variable */
2062 switch (v->magic)
2063 {
2064 case OSPFVIRTIFAREAID:
2065 return SNMP_IPADDRESS (area_id);
2066 break;
2067 case OSPFVIRTIFNEIGHBOR:
2068 return SNMP_IPADDRESS (neighbor);
2069 break;
2070 case OSPFVIRTIFTRANSITDELAY:
2071 return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
2072 break;
2073 case OSPFVIRTIFRETRANSINTERVAL:
2074 return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
2075 break;
2076 case OSPFVIRTIFHELLOINTERVAL:
2077 return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
2078 break;
2079 case OSPFVIRTIFRTRDEADINTERVAL:
2080 return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
2081 break;
2082 case OSPFVIRTIFSTATE:
2083 return SNMP_INTEGER (oi->state);
2084 break;
2085 case OSPFVIRTIFEVENTS:
2086 return SNMP_INTEGER (oi->state_change);
2087 break;
2088 case OSPFVIRTIFAUTHKEY:
2089 *var_len = 0;
2090 return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
2091 break;
2092 case OSPFVIRTIFSTATUS:
2093 return SNMP_INTEGER (SNMP_VALID);
2094 break;
2095 case OSPFVIRTIFAUTHTYPE:
2096 if (oi->area)
2097 return SNMP_INTEGER (oi->area->auth_type);
2098 else
2099 return SNMP_INTEGER (0);
2100 break;
2101 default:
2102 return NULL;
2103 break;
2104 }
2105 return NULL;
2106}
2107
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002108static struct ospf_neighbor *
paul68980082003-03-25 05:07:42 +00002109ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr,
2110 unsigned int *ifindex)
paul718e3742002-12-13 20:15:29 +00002111{
paul1eb8ef22005-04-07 07:30:20 +00002112 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002113 struct ospf_interface *oi;
2114 struct ospf_neighbor *nbr;
2115 struct route_node *rn;
2116
paul1eb8ef22005-04-07 07:30:20 +00002117 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00002118 {
2119 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
2120 if ((nbr = rn->info) != NULL
2121 && nbr != oi->nbr_self
vincent5e4914c2005-09-29 16:34:30 +00002122/* If EXACT match is needed, provide ALL entry found
paul718e3742002-12-13 20:15:29 +00002123 && nbr->state != NSM_Down
vincent5e4914c2005-09-29 16:34:30 +00002124 */
paul718e3742002-12-13 20:15:29 +00002125 && nbr->src.s_addr != 0)
2126 {
2127 if (IPV4_ADDR_SAME (&nbr->src, nbr_addr))
2128 {
2129 route_unlock_node (rn);
2130 return nbr;
2131 }
2132 }
2133 }
2134 return NULL;
2135}
2136
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002137static struct ospf_neighbor *
paul718e3742002-12-13 20:15:29 +00002138ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex,
2139 int first)
2140{
2141 struct listnode *nn;
2142 struct ospf_interface *oi;
2143 struct ospf_neighbor *nbr;
2144 struct route_node *rn;
2145 struct ospf_neighbor *min = NULL;
paul020709f2003-04-04 02:44:16 +00002146 struct ospf *ospf = ospf;
paul718e3742002-12-13 20:15:29 +00002147
paul020709f2003-04-04 02:44:16 +00002148 ospf = ospf_lookup ();
paul1eb8ef22005-04-07 07:30:20 +00002149
2150 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, nn, oi))
paul718e3742002-12-13 20:15:29 +00002151 {
2152 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
2153 if ((nbr = rn->info) != NULL
2154 && nbr != oi->nbr_self
2155 && nbr->state != NSM_Down
2156 && nbr->src.s_addr != 0)
2157 {
2158 if (first)
2159 {
2160 if (! min)
2161 min = nbr;
2162 else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
2163 min = nbr;
2164 }
2165 else if (ntohl (nbr->src.s_addr) > ntohl (nbr_addr->s_addr))
2166 {
2167 if (! min)
2168 min = nbr;
2169 else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
2170 min = nbr;
2171 }
2172 }
2173 }
2174 if (min)
2175 {
2176 *nbr_addr = min->src;
2177 *ifindex = 0;
2178 return min;
2179 }
2180 return NULL;
2181}
2182
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002183static struct ospf_neighbor *
paul718e3742002-12-13 20:15:29 +00002184ospfNbrLookup (struct variable *v, oid *name, size_t *length,
2185 struct in_addr *nbr_addr, unsigned int *ifindex, int exact)
2186{
paul6c835672004-10-11 11:00:30 +00002187 unsigned int len;
paul718e3742002-12-13 20:15:29 +00002188 int first;
2189 struct ospf_neighbor *nbr;
paul020709f2003-04-04 02:44:16 +00002190 struct ospf *ospf;
2191
2192 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00002193
hasso1b639042005-03-27 13:32:25 +00002194 if (! ospf)
2195 return NULL;
2196
paul718e3742002-12-13 20:15:29 +00002197 if (exact)
2198 {
2199 if (*length != v->namelen + IN_ADDR_SIZE + 1)
2200 return NULL;
2201
2202 oid2in_addr (name + v->namelen, IN_ADDR_SIZE, nbr_addr);
2203 *ifindex = name[v->namelen + IN_ADDR_SIZE];
2204
paul68980082003-03-25 05:07:42 +00002205 return ospf_snmp_nbr_lookup (ospf, nbr_addr, ifindex);
paul718e3742002-12-13 20:15:29 +00002206 }
2207 else
2208 {
2209 first = 0;
2210 len = *length - v->namelen;
2211
2212 if (len <= 0)
2213 first = 1;
2214
2215 if (len > IN_ADDR_SIZE)
2216 len = IN_ADDR_SIZE;
2217
2218 oid2in_addr (name + v->namelen, len, nbr_addr);
2219
2220 len = *length - v->namelen - IN_ADDR_SIZE;
2221 if (len >= 1)
2222 *ifindex = name[v->namelen + IN_ADDR_SIZE];
2223
2224 nbr = ospf_snmp_nbr_lookup_next (nbr_addr, ifindex, first);
2225
2226 if (nbr)
2227 {
2228 *length = v->namelen + IN_ADDR_SIZE + 1;
2229 oid_copy_addr (name + v->namelen, nbr_addr, IN_ADDR_SIZE);
2230 name[v->namelen + IN_ADDR_SIZE] = *ifindex;
2231 return nbr;
2232 }
2233 }
2234 return NULL;
2235}
2236
Andrew J. Schorrad81f8c2007-03-14 22:05:18 +00002237/* map internal quagga neighbor states to official MIB values:
2238
2239ospfNbrState OBJECT-TYPE
2240 SYNTAX INTEGER {
2241 down (1),
2242 attempt (2),
2243 init (3),
2244 twoWay (4),
2245 exchangeStart (5),
2246 exchange (6),
2247 loading (7),
2248 full (8)
2249 }
2250*/
2251static int32_t
2252ospf_snmp_neighbor_state(u_char nst)
2253{
2254 switch (nst)
2255 {
2256 case NSM_Attempt:
2257 return 2;
2258 case NSM_Init:
2259 return 3;
2260 case NSM_TwoWay:
2261 return 4;
2262 case NSM_ExStart:
2263 return 5;
2264 case NSM_Exchange:
2265 return 6;
2266 case NSM_Loading:
2267 return 7;
2268 case NSM_Full:
2269 return 8;
2270 default:
2271 return 1; /* down */
2272 }
2273}
2274
paul718e3742002-12-13 20:15:29 +00002275static u_char *
2276ospfNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002277 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00002278{
2279 struct in_addr nbr_addr;
2280 unsigned int ifindex;
2281 struct ospf_neighbor *nbr;
2282 struct ospf_interface *oi;
2283
2284 memset (&nbr_addr, 0, sizeof (struct in_addr));
2285 ifindex = 0;
2286
2287 nbr = ospfNbrLookup (v, name, length, &nbr_addr, &ifindex, exact);
2288 if (! nbr)
2289 return NULL;
2290 oi = nbr->oi;
2291 if (! oi)
2292 return NULL;
2293
2294 /* Return the current value of the variable */
2295 switch (v->magic)
2296 {
2297 case OSPFNBRIPADDR:
2298 return SNMP_IPADDRESS (nbr_addr);
2299 break;
2300 case OSPFNBRADDRESSLESSINDEX:
2301 return SNMP_INTEGER (ifindex);
2302 break;
2303 case OSPFNBRRTRID:
2304 return SNMP_IPADDRESS (nbr->router_id);
2305 break;
2306 case OSPFNBROPTIONS:
2307 return SNMP_INTEGER (oi->nbr_self->options);
2308 break;
2309 case OSPFNBRPRIORITY:
2310 return SNMP_INTEGER (nbr->priority);
2311 break;
2312 case OSPFNBRSTATE:
Andrew J. Schorrad81f8c2007-03-14 22:05:18 +00002313 return SNMP_INTEGER (ospf_snmp_neighbor_state(nbr->state));
paul718e3742002-12-13 20:15:29 +00002314 break;
2315 case OSPFNBREVENTS:
2316 return SNMP_INTEGER (nbr->state_change);
2317 break;
2318 case OSPFNBRLSRETRANSQLEN:
2319 return SNMP_INTEGER (ospf_ls_retransmit_count (nbr));
2320 break;
2321 case OSPFNBMANBRSTATUS:
2322 return SNMP_INTEGER (SNMP_VALID);
2323 break;
2324 case OSPFNBMANBRPERMANENCE:
2325 return SNMP_INTEGER (2);
2326 break;
2327 case OSPFNBRHELLOSUPPRESSED:
2328 return SNMP_INTEGER (SNMP_FALSE);
2329 break;
2330 default:
2331 return NULL;
2332 break;
2333 }
2334 return NULL;
2335}
2336
2337static u_char *
2338ospfVirtNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002339 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00002340{
2341 struct ospf_vl_data *vl_data;
2342 struct in_addr area_id;
2343 struct in_addr neighbor;
paul020709f2003-04-04 02:44:16 +00002344 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002345
2346 memset (&area_id, 0, sizeof (struct in_addr));
2347 memset (&neighbor, 0, sizeof (struct in_addr));
2348
2349 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00002350 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00002351 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00002352 return NULL;
2353
2354 vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
2355 if (! vl_data)
2356 return NULL;
2357
2358 /* Return the current value of the variable */
2359 switch (v->magic)
2360 {
2361 case OSPFVIRTNBRAREA:
2362 return (u_char *) NULL;
2363 break;
2364 case OSPFVIRTNBRRTRID:
2365 return (u_char *) NULL;
2366 break;
2367 case OSPFVIRTNBRIPADDR:
2368 return (u_char *) NULL;
2369 break;
2370 case OSPFVIRTNBROPTIONS:
2371 return (u_char *) NULL;
2372 break;
2373 case OSPFVIRTNBRSTATE:
2374 return (u_char *) NULL;
2375 break;
2376 case OSPFVIRTNBREVENTS:
2377 return (u_char *) NULL;
2378 break;
2379 case OSPFVIRTNBRLSRETRANSQLEN:
2380 return (u_char *) NULL;
2381 break;
2382 case OSPFVIRTNBRHELLOSUPPRESSED:
2383 return (u_char *) NULL;
2384 break;
2385 default:
2386 return NULL;
2387 break;
2388 }
2389 return NULL;
2390}
2391
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002392static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00002393ospfExtLsdbLookup (struct variable *v, oid *name, size_t *length, u_char *type,
2394 struct in_addr *ls_id, struct in_addr *router_id, int exact)
2395{
2396 int first;
2397 oid *offset;
2398 int offsetlen;
2399 u_char lsa_type;
paul6c835672004-10-11 11:00:30 +00002400 unsigned int len;
paul718e3742002-12-13 20:15:29 +00002401 struct ospf_lsa *lsa;
paul020709f2003-04-04 02:44:16 +00002402 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002403
paul020709f2003-04-04 02:44:16 +00002404 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00002405 if (exact)
2406 {
2407 if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
2408 return NULL;
2409
2410 offset = name + v->namelen;
2411
2412 /* Make it sure given value match to type. */
2413 lsa_type = *offset;
2414 offset++;
2415
2416 if (lsa_type != *type)
2417 return NULL;
2418
2419 /* LS ID. */
2420 oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
2421 offset += IN_ADDR_SIZE;
2422
2423 /* Router ID. */
2424 oid2in_addr (offset, IN_ADDR_SIZE, router_id);
2425
paul68980082003-03-25 05:07:42 +00002426 return ospf_lsdb_lookup_by_id (ospf->lsdb, *type, *ls_id, *router_id);
paul718e3742002-12-13 20:15:29 +00002427 }
2428 else
2429 {
2430 /* Get variable length. */
2431 first = 0;
2432 offset = name + v->namelen;
2433 offsetlen = *length - v->namelen;
2434
2435 /* LSA type value. */
2436 lsa_type = *offset;
2437 offset++;
2438 offsetlen--;
2439
2440 if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA)
2441 first = 1;
2442
2443 /* LS ID. */
2444 len = offsetlen;
2445 if (len > IN_ADDR_SIZE)
2446 len = IN_ADDR_SIZE;
2447
2448 oid2in_addr (offset, len, ls_id);
2449
2450 offset += IN_ADDR_SIZE;
2451 offsetlen -= IN_ADDR_SIZE;
2452
2453 /* Router ID. */
2454 len = offsetlen;
2455 if (len > IN_ADDR_SIZE)
2456 len = IN_ADDR_SIZE;
2457
2458 oid2in_addr (offset, len, router_id);
2459
paul68980082003-03-25 05:07:42 +00002460 lsa = ospf_lsdb_lookup_by_id_next (ospf->lsdb, *type, *ls_id,
paul718e3742002-12-13 20:15:29 +00002461 *router_id, first);
2462
2463 if (lsa)
2464 {
2465 /* Fill in length. */
2466 *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE;
2467
2468 /* Fill in value. */
2469 offset = name + v->namelen;
2470
2471 *offset = OSPF_AS_EXTERNAL_LSA;
2472 offset++;
2473 oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
2474 offset += IN_ADDR_SIZE;
2475 oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
2476
2477 return lsa;
2478 }
2479 }
2480 return NULL;
2481}
2482
2483static u_char *
2484ospfExtLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
Chris Caputo0be8dfb2009-06-02 18:40:07 +01002485 size_t *var_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +00002486{
2487 struct ospf_lsa *lsa;
2488 struct lsa_header *lsah;
2489 u_char type;
2490 struct in_addr ls_id;
2491 struct in_addr router_id;
paul020709f2003-04-04 02:44:16 +00002492 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002493
2494 type = OSPF_AS_EXTERNAL_LSA;
2495 memset (&ls_id, 0, sizeof (struct in_addr));
2496 memset (&router_id, 0, sizeof (struct in_addr));
2497
2498 /* Check OSPF instance. */
paul020709f2003-04-04 02:44:16 +00002499 ospf = ospf_lookup ();
paul68980082003-03-25 05:07:42 +00002500 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00002501 return NULL;
2502
2503 lsa = ospfExtLsdbLookup (v, name, length, &type, &ls_id, &router_id, exact);
2504 if (! lsa)
2505 return NULL;
2506
2507 lsah = lsa->data;
2508
2509 /* Return the current value of the variable */
2510 switch (v->magic)
2511 {
2512 case OSPFEXTLSDBTYPE:
2513 return SNMP_INTEGER (OSPF_AS_EXTERNAL_LSA);
2514 break;
2515 case OSPFEXTLSDBLSID:
2516 return SNMP_IPADDRESS (lsah->id);
2517 break;
2518 case OSPFEXTLSDBROUTERID:
2519 return SNMP_IPADDRESS (lsah->adv_router);
2520 break;
2521 case OSPFEXTLSDBSEQUENCE:
2522 return SNMP_INTEGER (lsah->ls_seqnum);
2523 break;
2524 case OSPFEXTLSDBAGE:
2525 return SNMP_INTEGER (lsah->ls_age);
2526 break;
2527 case OSPFEXTLSDBCHECKSUM:
2528 return SNMP_INTEGER (lsah->checksum);
2529 break;
2530 case OSPFEXTLSDBADVERTISEMENT:
2531 *var_len = ntohs (lsah->length);
2532 return (u_char *) lsah;
2533 break;
2534 default:
2535 return NULL;
2536 break;
2537 }
2538 return NULL;
2539}
2540
2541static u_char *
2542ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length,
2543 int exact, size_t *var_len, WriteMethod **write_method)
2544{
2545 /* Return the current value of the variable */
2546 switch (v->magic)
2547 {
2548 case OSPFAREAAGGREGATEAREAID:
2549 return (u_char *) NULL;
2550 break;
2551 case OSPFAREAAGGREGATELSDBTYPE:
2552 return (u_char *) NULL;
2553 break;
2554 case OSPFAREAAGGREGATENET:
2555 return (u_char *) NULL;
2556 break;
2557 case OSPFAREAAGGREGATEMASK:
2558 return (u_char *) NULL;
2559 break;
2560 case OSPFAREAAGGREGATESTATUS:
2561 return (u_char *) NULL;
2562 break;
2563 case OSPFAREAAGGREGATEEFFECT:
2564 return (u_char *) NULL;
2565 break;
2566 default:
2567 return NULL;
2568 break;
2569 }
2570 return NULL;
2571}
2572
vincent5e4914c2005-09-29 16:34:30 +00002573/* OSPF Traps. */
2574#define IFSTATECHANGE 16
2575#define VIRTIFSTATECHANGE 1
2576#define NBRSTATECHANGE 2
2577#define VIRTNBRSTATECHANGE 3
2578
2579struct trap_object ospfNbrTrapList[] =
2580{
2581 {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
2582 {ospfNbrEntry, 3, {10, 1, OSPFNBRIPADDR}},
2583 {ospfNbrEntry, 3, {10, 1, OSPFNBRRTRID}},
2584 {ospfNbrEntry, 3, {10, 1, OSPFNBRSTATE}}
2585};
2586
2587
2588struct trap_object ospfVirtNbrTrapList[] =
2589{
2590 {ospfGeneralGroup, -2, {1, 1}},
2591 {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRAREA}},
2592 {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRRTRID}},
2593 {ospfVirtNbrEntry, 3, {11, 1, OSPFVIRTNBRSTATE}}
2594};
2595
2596struct trap_object ospfIfTrapList[] =
2597{
2598 {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
2599 {ospfIfEntry, 3, {7, 1, OSPFIFIPADDRESS}},
2600 {ospfIfEntry, 3, {7, 1, OSPFADDRESSLESSIF}},
2601 {ospfIfEntry, 3, {7, 1, OSPFIFSTATE}}
2602};
2603
2604struct trap_object ospfVirtIfTrapList[] =
2605{
2606 {ospfGeneralGroup, -2, {1, OSPFROUTERID}},
2607 {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFAREAID}},
2608 {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFNEIGHBOR}},
2609 {ospfVirtIfEntry, 3, {9, 1, OSPFVIRTIFSTATE}}
2610};
2611
2612void
2613ospfTrapNbrStateChange (struct ospf_neighbor *on)
2614{
2615 oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
Andrew J. Schorr9aecfae2006-06-24 20:05:02 +00002616 char msgbuf[16];
vincent5e4914c2005-09-29 16:34:30 +00002617
Andrew J. Schorr9aecfae2006-06-24 20:05:02 +00002618 ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf));
2619 zlog (NULL, LOG_INFO, "ospfTrapNbrStateChange trap sent: %s now %s",
2620 inet_ntoa(on->address.u.prefix4), msgbuf);
vincent5e4914c2005-09-29 16:34:30 +00002621
2622 oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE);
2623 index[IN_ADDR_SIZE] = 0;
2624
2625 smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
2626 index, IN_ADDR_SIZE + 1,
2627 ospfNbrTrapList,
2628 sizeof ospfNbrTrapList / sizeof (struct trap_object),
2629 time (NULL), NBRSTATECHANGE);
2630}
2631
2632void
2633ospfTrapVirtNbrStateChange (struct ospf_neighbor *on)
2634{
2635 oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
2636
2637 zlog (NULL, LOG_INFO, "ospfTrapVirtNbrStateChange trap sent");
2638
2639 oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE);
2640 index[IN_ADDR_SIZE] = 0;
2641
2642 smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
2643 index, IN_ADDR_SIZE + 1,
2644 ospfVirtNbrTrapList,
2645 sizeof ospfVirtNbrTrapList / sizeof (struct trap_object),
2646 time (NULL), VIRTNBRSTATECHANGE);
2647}
2648
2649void
2650ospfTrapIfStateChange (struct ospf_interface *oi)
2651{
2652 oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
2653
Andrew J. Schorr9aecfae2006-06-24 20:05:02 +00002654 zlog (NULL, LOG_INFO, "ospfTrapIfStateChange trap sent: %s now %s",
2655 inet_ntoa(oi->address->u.prefix4),
2656 LOOKUP(ospf_ism_state_msg, oi->state));
vincent5e4914c2005-09-29 16:34:30 +00002657
2658 oid_copy_addr (index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
2659 index[IN_ADDR_SIZE] = 0;
2660
2661 smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
2662 index, IN_ADDR_SIZE + 1,
2663 ospfIfTrapList,
2664 sizeof ospfIfTrapList / sizeof (struct trap_object),
2665 time (NULL), IFSTATECHANGE);
2666}
2667
2668void
2669ospfTrapVirtIfStateChange (struct ospf_interface *oi)
2670{
2671 oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
2672
2673 zlog (NULL, LOG_INFO, "ospfTrapVirtIfStateChange trap sent");
2674
2675 oid_copy_addr (index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
2676 index[IN_ADDR_SIZE] = 0;
2677
2678 smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid),
2679 index, IN_ADDR_SIZE + 1,
2680 ospfVirtIfTrapList,
2681 sizeof ospfVirtIfTrapList / sizeof (struct trap_object),
2682 time (NULL), VIRTIFSTATECHANGE);
2683}
paul718e3742002-12-13 20:15:29 +00002684/* Register OSPF2-MIB. */
2685void
2686ospf_snmp_init ()
2687{
2688 ospf_snmp_iflist = list_new ();
2689 ospf_snmp_vl_table = route_table_init ();
hassoc75105a2004-10-13 10:33:26 +00002690 smux_init (om->master);
paul718e3742002-12-13 20:15:29 +00002691 REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid);
paul718e3742002-12-13 20:15:29 +00002692}
2693#endif /* HAVE_SNMP */