]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_snmp.c
*: manual SPDX License ID conversions
[mirror_frr.git] / isisd / isis_snmp.c
CommitLineData
1ee746d9 1/*
2 * ISIS SNMP support
3 * Copyright (C) 2020 Volta Networks, Inc.
4 * Aleksey Romanov
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/*
22 * This is minimal read-only implementations providing isisReadOnlyCompliance
23 */
24
25#include <zebra.h>
26
27#include <net-snmp/net-snmp-config.h>
28#include <net-snmp/net-snmp-includes.h>
29
30#include "vrf.h"
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#include "libfrr.h"
09781197 39#include "lib/version.h"
05855c53 40#include "lib/zclient.h"
1ee746d9 41
42#include "isisd/isis_constants.h"
43#include "isisd/isis_common.h"
44#include "isisd/isis_flags.h"
45#include "isisd/isis_circuit.h"
46#include "isisd/isis_lsp.h"
47#include "isisd/isis_pdu.h"
48#include "isisd/isis_network.h"
49#include "isisd/isis_misc.h"
50#include "isisd/isis_constants.h"
51#include "isisd/isis_adjacency.h"
52#include "isisd/isis_dynhn.h"
53#include "isisd/isis_te.h"
54#include "isisd/isis_dr.h"
55#include "isisd/isis_nb.h"
56#include "isisd/isisd.h"
57
58/* ISIS-MIB. */
59#define ISIS_MIB 1, 3, 6, 1, 2, 1, 138
60
61#define ISIS_OBJECTS 1
62#define ISIS_SYSTEM 1, 1
63#define ISIS_SYSLEVEL 1, 2
64#define ISIS_CIRC 1, 3
65#define ISIS_CIRC_LEVEL_VALUES 1, 4
66#define ISIS_COUNTERS 1, 5
67#define ISIS_ISADJ 1, 6
68
69/************************ isisSystemGroup ************************/
70
71/* isisSysObject */
72#define ISIS_SYS_OBJECT 1, 1, 1
73#define ISIS_SYS_VERSION 1
74#define ISIS_SYS_LEVELTYPE 2
75#define ISIS_SYS_ID 3
76#define ISIS_SYS_MAXPATHSPLITS 4
77#define ISIS_SYS_MAXLSPGENINT 5
78#define ISIS_SYS_POLLESHELLORATE 6
79#define ISIS_SYS_WAITTIME 7
80#define ISIS_SYS_ADMINSTATE 8
81#define ISIS_SYS_L2TOL1LEAKING 9
82#define ISIS_SYS_MAXAGE 10
83#define ISIS_SYS_RECEIVELSPBUFFERSIZE 11
84#define ISIS_SYS_PROTSUPPORTED 12
85#define ISIS_SYS_NOTIFICATIONENABLE 13
86
87/* isisManAreaAddrEntry */
88#define ISIS_MANAREA_ADDRENTRY 1, 1, 2, 1
89#define ISIS_MANAREA_ADDREXISTSTATE 2
90
91/* isisAreaAddrEntry */
92#define ISIS_AREA_ADDRENTRY 1, 1, 3, 1
93#define ISIS_AREA_ADDR 1
94
95/* isisSummAddrEntry */
96#define ISIS_SUMM_ADDRENTRY 1, 1, 4, 1
97#define ISIS_SUMM_ADDREXISTSTATE 4
98#define ISIS_SUMM_ADDRMETRIC 5
99#define ISIS_SUMM_ADDRFULLMETRIC 6
100
101/* isisRedistributeAddrEntry */
102#define ISIS_REDISTRIBUTE_ADDRENTRY 1, 1, 5, 1
103#define ISIS_REDISTRIBUTE_ADDREXISTSTATE 3
104
105/* isisRouterEntry */
106#define ISIS_ROUTER_ENTRY 1, 1, 6, 1
107#define ISIS_ROUTER_HOSTNAME 3
108#define ISIS_ROUTER_ID 4
109
110/* isisSysLevelTable */
111#define ISIS_SYSLEVEL_ENTRY 1, 2, 1, 1
112#define ISIS_SYSLEVEL_ORIGLSPBUFFSIZE 2
113#define ISIS_SYSLEVEL_MINLSPGENINT 3
114#define ISIS_SYSLEVEL_STATE 4
115#define ISIS_SYSLEVEL_SETOVERLOAD 5
116#define ISIS_SYSLEVEL_SETOVERLOADUNTIL 6
117#define ISIS_SYSLEVEL_METRICSTYLE 7
118#define ISIS_SYSLEVEL_SPFCONSIDERS 8
119#define ISIS_SYSLEVEL_TEENABLED 9
120
121
122/* isisSystemCounterEntry */
123#define ISIS_SYSTEM_COUNTER_ENTRY 1, 5, 1, 1
124#define ISIS_SYSSTAT_CORRLSPS 2
125#define ISIS_SYSSTAT_AUTHTYPEFAILS 3
126#define ISIS_SYSSTAT_AUTHFAILS 4
127#define ISIS_SYSSTAT_LSPDBASEOLOADS 5
128#define ISIS_SYSSTAT_MANADDRDROPFROMAREAS 6
129#define ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS 7
130#define ISIS_SYSSTAT_SEQNUMSKIPS 8
131#define ISIS_SYSSTAT_OWNLSPPURGES 9
132#define ISIS_SYSSTAT_IDFIELDLENMISMATCHES 10
133#define ISIS_SYSSTAT_PARTCHANGES 11
134#define ISIS_SYSSTAT_SPFRUNS 12
135#define ISIS_SYSSTAT_LSPERRORS 13
136
137
138/************************ isisCircuitGroup ************************/
139
140/* Scalar directly under isisCirc */
141#define ISIS_NEXTCIRC_INDEX 1
142
143/* isisCircEntry */
144#define ISIS_CIRC_ENTRY 1, 3, 2, 1
145#define ISIS_CIRC_IFINDEX 2
146#define ISIS_CIRC_ADMINSTATE 3
147#define ISIS_CIRC_EXISTSTATE 4
148#define ISIS_CIRC_TYPE 5
149#define ISIS_CIRC_EXTDOMAIN 6
150#define ISIS_CIRC_LEVELTYPE 7
151#define ISIS_CIRC_PASSIVECIRCUIT 8
152#define ISIS_CIRC_MESHGROUPENABLED 9
153#define ISIS_CIRC_MESHGROUP 10
154#define ISIS_CIRC_SMALLHELLOS 11
155#define ISIS_CIRC_LASTUPTIME 12
156#define ISIS_CIRC_3WAYENABLED 13
157#define ISIS_CIRC_EXTENDEDCIRCID 14
158
159/* isisCircLevelEntry */
160#define ISIS_CIRCLEVEL_ENTRY 1, 4, 1, 1
161#define ISIS_CIRCLEVEL_METRIC 2
162#define ISIS_CIRCLEVEL_WIDEMETRIC 3
163#define ISIS_CIRCLEVEL_ISPRIORITY 4
164#define ISIS_CIRCLEVEL_IDOCTET 5
165#define ISIS_CIRCLEVEL_ID 6
166#define ISIS_CIRCLEVEL_DESIS 7
167#define ISIS_CIRCLEVEL_HELLOMULTIPLIER 8
168#define ISIS_CIRCLEVEL_HELLOTIMER 9
169#define ISIS_CIRCLEVEL_DRHELLOTIMER 10
170#define ISIS_CIRCLEVEL_LSPTHROTTLE 11
171#define ISIS_CIRCLEVEL_MINLSPRETRANSINT 12
172#define ISIS_CIRCLEVEL_CSNPINTERVAL 13
173#define ISIS_CIRCLEVEL_PARTSNPINTERVAL 14
174
175/* isisCircuitCounterEntry */
176#define ISIS_CIRC_COUNTER_ENTRY 1, 5, 2, 1
177#define ISIS_CIRC_ADJCHANGES 2
178#define ISIS_CIRC_NUMADJ 3
179#define ISIS_CIRC_INITFAILS 4
180#define ISIS_CIRC_REJADJS 5
181#define ISIS_CIRC_IDFIELDLENMISMATCHES 6
182#define ISIS_CIRC_MAXAREAADDRMISMATCHES 7
183#define ISIS_CIRC_AUTHTYPEFAILS 8
184#define ISIS_CIRC_AUTHFAILS 9
185#define ISIS_CIRC_LANDESISCHANGES 10
186
187
188/************************ isisISAdjGroup ************************/
189
190/* isisISAdjEntry */
191#define ISIS_ISADJ_ENTRY 1, 6, 1, 1
192#define ISIS_ISADJ_STATE 2
193#define ISIS_ISADJ_3WAYSTATE 3
194#define ISIS_ISADJ_NEIGHSNPAADDRESS 4
195#define ISIS_ISADJ_NEIGHSYSTYPE 5
196#define ISIS_ISADJ_NEIGHSYSID 6
197#define ISIS_ISADJ_NBREXTENDEDCIRCID 7
198#define ISIS_ISADJ_USAGE 8
199#define ISIS_ISADJ_HOLDTIMER 9
200#define ISIS_ISADJ_NEIGHPRIORITY 10
201#define ISIS_ISADJ_LASTUPTIME 11
202
203/* isisISAdjAreadAddrEntry */
204#define ISIS_ISADJAREA_ADDRENTRY 1, 6, 2, 1
205#define ISIS_ISADJAREA_ADDRESS 2
206
207/* isisISAdjIPAddrEntry*/
208#define ISIS_ISADJIPADDR_ENTRY 1, 6, 3, 1
209#define ISIS_ISADJIPADDR_TYPE 2
210#define ISIS_ISADJIPADDR_ADDRESS 3
211
212
213/* isisISAdjProtSuppEntty */
214
215#define ISIS_ISADJPROTSUPP_ENTRY 1, 6, 4, 1
216#define ISIS_ISADJPROTSUPP_PROTOCOL 1
217
218
219/************************ Trap data variables ************************/
220#define ISIS_NOTIFICATION_ENTRY 1, 10, 1
221#define ISIS_NOTIF_SYLELVELINDEX 1
222#define ISIS_NOTIF_CIRCIFINDEX 2
223#define ISIS_PDU_LSPID 3
224#define ISIS_PDU_FRAGMENT 4
225#define ISIS_PDU_FIELDLEN 5
226#define ISIS_PDU_MAXAREAADDR 6
227#define ISIS_PDU_PROTOVER 7
228#define ISIS_PDU_LSPSIZE 8
229#define ISIS_PDU_ORIGBUFFERSIZE 9
230#define ISIS_PDU_BUFFERSIZE 10
231#define ISIS_PDU_PROTSUPP 11
232#define ISIS_ADJ_STATE 12
233#define ISIS_ERROR_OFFSET 13
234#define ISIS_ERROR_TLVTYPE 14
235#define ISIS_NOTIF_AREAADDR 15
236
237/************************ Traps ************************/
238#define ISIS_NOTIFICATIONS ISIS_MIB, 0
239#define ISIS_TRAP_DB_OVERLOAD 1
240#define ISIS_TRAP_MAN_ADDR_DROP 2
241#define ISIS_TRAP_CORRUPTED_LSP 3
242#define ISIS_TRAP_LSP_EXCEED_MAX 4
243#define ISIS_TRAP_ID_LEN_MISMATCH 5
244#define ISIS_TRAP_MAX_AREA_ADDR_MISMATCH 6
245#define ISIS_TRAP_OWN_LSP_PURGE 7
246#define ISIS_TRAP_SEQNO_SKIPPED 8
247#define ISIS_TRAP_AUTHEN_TYPE_FAILURE 9
248#define ISIS_TRAP_AUTHEN_FAILURE 10
249#define ISIS_TRAP_VERSION_SKEW 11
250#define ISIS_TRAP_AREA_MISMATCH 12
251#define ISIS_TRAP_REJ_ADJACENCY 13
252#define ISIS_TRAP_LSP_TOO_LARGE 14
253#define ISIS_TRAP_LSP_BUFFSIZE_MISMATCH 15
254#define ISIS_TRAP_PROTSUPP_MISMATCH 16
255#define ISIS_TRAP_ADJ_STATE_CHANGE 17
256#define ISIS_TRAP_LSP_ERROR 18
257
258/* Change this definition if number of traps changes */
e91a589b 259#define ISIS_TRAP_LAST_TRAP ISIS_TRAP_LSP_ERROR + 1
1ee746d9 260
261#define ISIS_SNMP_TRAP_VAR 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0
262
263
264/* SNMP value hack. */
265#define COUNTER32 ASN_COUNTER
266#define INTEGER ASN_INTEGER
267#define UNSIGNED32 ASN_GAUGE
268#define TIMESTAMP ASN_TIMETICKS
269#define TIMETICKS ASN_TIMETICKS
270#define STRING ASN_OCTET_STR
271
272/* Declare static local variables for convenience. */
273SNMP_LOCAL_VARIABLES
274
275/* If ARRAY_SIZE is not available use a primitive substitution */
276#ifndef ARRAY_SIZE
277#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
278#endif
279
280/*
281 * Define time function, it serves two purposes
282 * 1. Uses unint32_t for unix time and encapsulates
283 * sing extension issues in conversion from time_t
284 *
285 * 2. I could be replaced in unit test environment
286 */
1ee746d9 287
288/* ISIS-MIB instances. */
289static oid isis_oid[] = {ISIS_MIB};
290
291/* SNMP trap variable */
292static oid isis_snmp_trap_var[] = {ISIS_SNMP_TRAP_VAR};
293
294/* SNMP trap values (others are calculated on the fly */
295static oid isis_snmp_notifications[] = {ISIS_NOTIFICATIONS};
296static oid isis_snmp_trap_val_db_overload[] = {ISIS_NOTIFICATIONS,
297 ISIS_TRAP_DB_OVERLOAD};
298static oid isis_snmp_trap_val_lsp_exceed_max[] = {ISIS_NOTIFICATIONS,
299 ISIS_TRAP_LSP_EXCEED_MAX};
300static oid isis_snmp_trap_val_area_mismatch[] = {ISIS_NOTIFICATIONS,
301 ISIS_TRAP_AREA_MISMATCH};
302static oid isis_snmp_trap_val_lsp_error[] = {ISIS_NOTIFICATIONS,
303 ISIS_TRAP_LSP_ERROR};
304
305/*
306 * Trap vars under 'isisNotifications': note: we use full names of variables
307 * scalar index
308 */
309static oid isis_snmp_trap_data_var_sys_level_index[] = {
310 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_NOTIF_SYLELVELINDEX, 0};
311static oid isis_snmp_trap_data_var_circ_if_index[] = {
312 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_NOTIF_CIRCIFINDEX, 0};
313static oid isis_snmp_trap_data_var_pdu_lsp_id[] = {
314 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_LSPID, 0};
315static oid isis_snmp_trap_data_var_pdu_fragment[] = {
316 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_FRAGMENT, 0};
317static oid isis_snmp_trap_data_var_pdu_field_len[] = {
318 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_FIELDLEN, 0};
319static oid isis_snmp_trap_data_var_pdu_max_area_addr[] = {
320 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_MAXAREAADDR, 0};
321static oid isis_snmp_trap_data_var_pdu_proto_ver[] = {
322 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_PROTOVER, 0};
323static oid isis_snmp_trap_data_var_pdu_lsp_size[] = {
324 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_LSPSIZE, 0};
325static oid isis_snmp_trap_data_var_adj_state[] = {
326 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_ADJ_STATE, 0};
327static oid isis_snmp_trap_data_var_error_offset[] = {
328 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_ERROR_OFFSET, 0};
329static oid isis_snmp_trap_data_var_error_tlv_type[] = {
330 ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_ERROR_TLVTYPE, 0};
331
332/*
333 * Other variables used by traps: note we use full names of variables and
334 * reserve space for index
335 */
336static oid isis_snmp_trap_data_var_sys_level_state[] = {
337 ISIS_MIB, ISIS_SYSLEVEL_ENTRY, ISIS_SYSLEVEL_STATE, 0};
338
339/* Throttle time values for traps */
340static time_t isis_snmp_trap_timestamp[ISIS_TRAP_LAST_TRAP]; /* ?? 1 */
341
342/* Max len of raw-pdu in traps */
343#define ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN (64)
344
345/*
346 * Just to save on typing we have a shortcut structure
347 * to specify mib layout as prefix/leaf combination
348 */
349#define ISIS_SNMP_PREF_LEN_MAX 10
350struct isis_var_prefix {
351 FindVarMethod *findVar;
352 uint8_t ivd_pref_len;
353 oid ivd_pref[ISIS_SNMP_PREF_LEN_MAX];
354};
355
356
357/* Find-val functions */
358static uint8_t *isis_snmp_find_sys_object(struct variable *, oid *, size_t *,
359 int, size_t *, WriteMethod **);
360
361static uint8_t *isis_snmp_find_man_area(struct variable *, oid *, size_t *, int,
362 size_t *, WriteMethod **);
363
364static uint8_t *isis_snmp_find_area_addr(struct variable *, oid *, size_t *,
365 int, size_t *, WriteMethod **);
366
367static uint8_t *isis_snmp_find_summ_addr(struct variable *, oid *, size_t *,
368 int, size_t *, WriteMethod **);
369
370static uint8_t *isis_snmp_find_redistribute_addr(struct variable *, oid *,
371 size_t *, int, size_t *,
372 WriteMethod **);
373
374static uint8_t *isis_snmp_find_router(struct variable *, oid *, size_t *, int,
375 size_t *, WriteMethod **);
376
377static uint8_t *isis_snmp_find_sys_level(struct variable *, oid *, size_t *,
378 int, size_t *, WriteMethod **);
379
380static uint8_t *isis_snmp_find_system_counter(struct variable *, oid *,
381 size_t *, int, size_t *,
382 WriteMethod **);
383
384static uint8_t *isis_snmp_find_next_circ_index(struct variable *, oid *,
385 size_t *, int, size_t *,
386 WriteMethod **);
387
388static uint8_t *isis_snmp_find_circ(struct variable *, oid *, size_t *, int,
389 size_t *, WriteMethod **);
390
391static uint8_t *isis_snmp_find_circ_level(struct variable *, oid *, size_t *,
392 int, size_t *, WriteMethod **);
393
394static uint8_t *isis_snmp_find_circ_counter(struct variable *, oid *, size_t *,
395 int, size_t *, WriteMethod **);
396
397static uint8_t *isis_snmp_find_isadj(struct variable *, oid *, size_t *, int,
398 size_t *, WriteMethod **);
399
400static uint8_t *isis_snmp_find_isadj_area(struct variable *, oid *, size_t *,
401 int, size_t *, WriteMethod **);
402
403static uint8_t *isis_snmp_find_isadj_ipaddr(struct variable *, oid *, size_t *,
404 int, size_t *, WriteMethod **);
405
406static uint8_t *isis_snmp_find_isadj_prot_supp(struct variable *, oid *,
407 size_t *, int, size_t *,
408 WriteMethod **);
409
410/*
411 * Just to save on typing we have a shortcut structure
412 * to specify mib layout, we populate the rest of the data
413 * during initialization
414 */
415#define ISIS_PREF_LEN_MAX (6)
416
417struct isis_func_to_prefix {
418 FindVarMethod *ihtp_func;
419 oid ihtp_pref_oid[ISIS_PREF_LEN_MAX];
420 uint8_t ihtp_pref_len;
421};
422
423static struct isis_func_to_prefix isis_func_to_prefix_arr[] = {
424 {isis_snmp_find_sys_object, {ISIS_SYS_OBJECT}, 3},
425 {isis_snmp_find_man_area, {ISIS_MANAREA_ADDRENTRY}, 4},
426 {isis_snmp_find_area_addr, {ISIS_AREA_ADDRENTRY}, 4},
427 {isis_snmp_find_summ_addr, {ISIS_SUMM_ADDRENTRY}, 4},
428 {isis_snmp_find_redistribute_addr, {ISIS_REDISTRIBUTE_ADDRENTRY}, 4},
429 {isis_snmp_find_router, {ISIS_ROUTER_ENTRY}, 4},
430 {isis_snmp_find_sys_level, {ISIS_SYSLEVEL_ENTRY}, 4},
431 {isis_snmp_find_system_counter, {ISIS_SYSTEM_COUNTER_ENTRY}, 4},
432 {isis_snmp_find_next_circ_index, {ISIS_CIRC}, 2},
433 {isis_snmp_find_circ, {ISIS_CIRC_ENTRY}, 4},
434 {isis_snmp_find_circ_level, {ISIS_CIRCLEVEL_ENTRY}, 4},
435 {isis_snmp_find_circ_counter, {ISIS_CIRC_COUNTER_ENTRY}, 4},
436 {isis_snmp_find_isadj, {ISIS_ISADJ_ENTRY}, 4},
437 {isis_snmp_find_isadj_area, {ISIS_ISADJAREA_ADDRENTRY}, 4},
438 {isis_snmp_find_isadj_ipaddr, {ISIS_ISADJIPADDR_ENTRY}, 4},
439 {isis_snmp_find_isadj_prot_supp, {ISIS_ISADJPROTSUPP_ENTRY}, 4},
440};
441static size_t isis_func_to_prefix_count = ARRAY_SIZE(isis_func_to_prefix_arr);
442
443static struct variable isis_var_arr[] = {
444 {ISIS_SYS_VERSION, INTEGER, RONLY, isis_snmp_find_sys_object},
445 {ISIS_SYS_LEVELTYPE, INTEGER, RONLY, isis_snmp_find_sys_object},
446 {ISIS_SYS_ID, STRING, RONLY, isis_snmp_find_sys_object},
447 {ISIS_SYS_MAXPATHSPLITS, UNSIGNED32, RONLY, isis_snmp_find_sys_object},
448 {ISIS_SYS_MAXLSPGENINT, UNSIGNED32, RONLY, isis_snmp_find_sys_object},
449 {ISIS_SYS_POLLESHELLORATE, UNSIGNED32, RONLY,
450 isis_snmp_find_sys_object},
451 {ISIS_SYS_WAITTIME, UNSIGNED32, RONLY, isis_snmp_find_sys_object},
452 {ISIS_SYS_ADMINSTATE, INTEGER, RONLY, isis_snmp_find_sys_object},
453 {ISIS_SYS_L2TOL1LEAKING, INTEGER, RONLY, isis_snmp_find_sys_object},
454 {ISIS_SYS_MAXAGE, UNSIGNED32, RONLY, isis_snmp_find_sys_object},
455 {ISIS_SYS_RECEIVELSPBUFFERSIZE, UNSIGNED32, RONLY,
456 isis_snmp_find_sys_object},
457 {ISIS_SYS_PROTSUPPORTED, STRING, RONLY, isis_snmp_find_sys_object},
458 {ISIS_SYS_NOTIFICATIONENABLE, INTEGER, RONLY,
459 isis_snmp_find_sys_object},
460 {ISIS_MANAREA_ADDREXISTSTATE, INTEGER, RONLY, isis_snmp_find_man_area},
461 {ISIS_AREA_ADDR, STRING, RONLY, isis_snmp_find_area_addr},
462 {ISIS_SUMM_ADDREXISTSTATE, INTEGER, RONLY, isis_snmp_find_summ_addr},
463 {ISIS_SUMM_ADDRMETRIC, UNSIGNED32, RONLY, isis_snmp_find_summ_addr},
464 {ISIS_SUMM_ADDRFULLMETRIC, UNSIGNED32, RONLY, isis_snmp_find_summ_addr},
465 {ISIS_REDISTRIBUTE_ADDREXISTSTATE, INTEGER, RONLY,
466 isis_snmp_find_redistribute_addr},
467 {ISIS_ROUTER_HOSTNAME, STRING, RONLY, isis_snmp_find_router},
468 {ISIS_ROUTER_ID, UNSIGNED32, RONLY, isis_snmp_find_router},
469 {ISIS_SYSLEVEL_ORIGLSPBUFFSIZE, UNSIGNED32, RONLY,
470 isis_snmp_find_sys_level},
471 {ISIS_SYSLEVEL_MINLSPGENINT, UNSIGNED32, RONLY,
472 isis_snmp_find_sys_level},
473 {ISIS_SYSLEVEL_STATE, INTEGER, RONLY, isis_snmp_find_sys_level},
474 {ISIS_SYSLEVEL_SETOVERLOAD, INTEGER, RONLY, isis_snmp_find_sys_level},
475 {ISIS_SYSLEVEL_SETOVERLOADUNTIL, UNSIGNED32, RONLY,
476 isis_snmp_find_sys_level},
477 {ISIS_SYSLEVEL_METRICSTYLE, INTEGER, RONLY, isis_snmp_find_sys_level},
478 {ISIS_SYSLEVEL_SPFCONSIDERS, INTEGER, RONLY, isis_snmp_find_sys_level},
479 {ISIS_SYSLEVEL_TEENABLED, INTEGER, RONLY, isis_snmp_find_sys_level},
480 {ISIS_SYSSTAT_CORRLSPS, COUNTER32, RONLY,
481 isis_snmp_find_system_counter},
482 {ISIS_SYSSTAT_AUTHTYPEFAILS, COUNTER32, RONLY,
483 isis_snmp_find_system_counter},
484 {ISIS_SYSSTAT_AUTHFAILS, COUNTER32, RONLY,
485 isis_snmp_find_system_counter},
486 {ISIS_SYSSTAT_LSPDBASEOLOADS, COUNTER32, RONLY,
487 isis_snmp_find_system_counter},
488 {ISIS_SYSSTAT_MANADDRDROPFROMAREAS, COUNTER32, RONLY,
489 isis_snmp_find_system_counter},
490 {ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS, COUNTER32, RONLY,
491 isis_snmp_find_system_counter},
492 {ISIS_SYSSTAT_SEQNUMSKIPS, COUNTER32, RONLY,
493 isis_snmp_find_system_counter},
494 {ISIS_SYSSTAT_OWNLSPPURGES, COUNTER32, RONLY,
495 isis_snmp_find_system_counter},
496 {ISIS_SYSSTAT_IDFIELDLENMISMATCHES, COUNTER32, RONLY,
497 isis_snmp_find_system_counter},
498 {ISIS_SYSSTAT_PARTCHANGES, COUNTER32, RONLY,
499 isis_snmp_find_system_counter},
500 {ISIS_SYSSTAT_SPFRUNS, COUNTER32, RONLY, isis_snmp_find_system_counter},
501 {ISIS_SYSSTAT_LSPERRORS, COUNTER32, RONLY,
502 isis_snmp_find_system_counter},
503 {ISIS_NEXTCIRC_INDEX, UNSIGNED32, RONLY,
504 isis_snmp_find_next_circ_index},
505 {ISIS_CIRC_IFINDEX, INTEGER, RONLY, isis_snmp_find_circ},
506 {ISIS_CIRC_ADMINSTATE, INTEGER, RONLY, isis_snmp_find_circ},
507 {ISIS_CIRC_EXISTSTATE, INTEGER, RONLY, isis_snmp_find_circ},
508 {ISIS_CIRC_TYPE, INTEGER, RONLY, isis_snmp_find_circ},
509 {ISIS_CIRC_EXTDOMAIN, INTEGER, RONLY, isis_snmp_find_circ},
510 {ISIS_CIRC_LEVELTYPE, INTEGER, RONLY, isis_snmp_find_circ},
511 {ISIS_CIRC_PASSIVECIRCUIT, INTEGER, RONLY, isis_snmp_find_circ},
512 {ISIS_CIRC_MESHGROUPENABLED, INTEGER, RONLY, isis_snmp_find_circ},
513 {ISIS_CIRC_MESHGROUP, UNSIGNED32, RONLY, isis_snmp_find_circ},
514 {ISIS_CIRC_SMALLHELLOS, INTEGER, RONLY, isis_snmp_find_circ},
515 {ISIS_CIRC_LASTUPTIME, TIMESTAMP, RONLY, isis_snmp_find_circ},
516 {ISIS_CIRC_3WAYENABLED, INTEGER, RONLY, isis_snmp_find_circ},
517 {ISIS_CIRC_EXTENDEDCIRCID, UNSIGNED32, RONLY, isis_snmp_find_circ},
518 {ISIS_CIRCLEVEL_METRIC, UNSIGNED32, RONLY, isis_snmp_find_circ_level},
519 {ISIS_CIRCLEVEL_WIDEMETRIC, UNSIGNED32, RONLY,
520 isis_snmp_find_circ_level},
521 {ISIS_CIRCLEVEL_ISPRIORITY, UNSIGNED32, RONLY,
522 isis_snmp_find_circ_level},
523 {ISIS_CIRCLEVEL_IDOCTET, UNSIGNED32, RONLY, isis_snmp_find_circ_level},
524 {ISIS_CIRCLEVEL_ID, STRING, RONLY, isis_snmp_find_circ_level},
525 {ISIS_CIRCLEVEL_DESIS, STRING, RONLY, isis_snmp_find_circ_level},
526 {ISIS_CIRCLEVEL_HELLOMULTIPLIER, UNSIGNED32, RONLY,
527 isis_snmp_find_circ_level},
528 {ISIS_CIRCLEVEL_HELLOTIMER, UNSIGNED32, RONLY,
529 isis_snmp_find_circ_level},
530 {ISIS_CIRCLEVEL_DRHELLOTIMER, UNSIGNED32, RONLY,
531 isis_snmp_find_circ_level},
532 {ISIS_CIRCLEVEL_LSPTHROTTLE, UNSIGNED32, RONLY,
533 isis_snmp_find_circ_level},
534 {ISIS_CIRCLEVEL_MINLSPRETRANSINT, UNSIGNED32, RONLY,
535 isis_snmp_find_circ_level},
536 {ISIS_CIRCLEVEL_CSNPINTERVAL, UNSIGNED32, RONLY,
537 isis_snmp_find_circ_level},
538 {ISIS_CIRCLEVEL_PARTSNPINTERVAL, UNSIGNED32, RONLY,
539 isis_snmp_find_circ_level},
540 {ISIS_CIRC_ADJCHANGES, COUNTER32, RONLY, isis_snmp_find_circ_counter},
541 {ISIS_CIRC_NUMADJ, UNSIGNED32, RONLY, isis_snmp_find_circ_counter},
542 {ISIS_CIRC_INITFAILS, COUNTER32, RONLY, isis_snmp_find_circ_counter},
543 {ISIS_CIRC_REJADJS, COUNTER32, RONLY, isis_snmp_find_circ_counter},
544 {ISIS_CIRC_IDFIELDLENMISMATCHES, COUNTER32, RONLY,
545 isis_snmp_find_circ_counter},
546 {ISIS_CIRC_MAXAREAADDRMISMATCHES, COUNTER32, RONLY,
547 isis_snmp_find_circ_counter},
548 {ISIS_CIRC_AUTHTYPEFAILS, COUNTER32, RONLY,
549 isis_snmp_find_circ_counter},
550 {ISIS_CIRC_AUTHFAILS, COUNTER32, RONLY, isis_snmp_find_circ_counter},
551 {ISIS_CIRC_LANDESISCHANGES, COUNTER32, RONLY,
552 isis_snmp_find_circ_counter},
553 {ISIS_ISADJ_STATE, INTEGER, RONLY, isis_snmp_find_isadj},
554 {ISIS_ISADJ_3WAYSTATE, INTEGER, RONLY, isis_snmp_find_isadj},
555 {ISIS_ISADJ_NEIGHSNPAADDRESS, STRING, RONLY, isis_snmp_find_isadj},
556 {ISIS_ISADJ_NEIGHSYSTYPE, INTEGER, RONLY, isis_snmp_find_isadj},
557 {ISIS_ISADJ_NEIGHSYSID, STRING, RONLY, isis_snmp_find_isadj},
558 {ISIS_ISADJ_NBREXTENDEDCIRCID, UNSIGNED32, RONLY, isis_snmp_find_isadj},
559 {ISIS_ISADJ_USAGE, INTEGER, RONLY, isis_snmp_find_isadj},
560 {ISIS_ISADJ_HOLDTIMER, UNSIGNED32, RONLY, isis_snmp_find_isadj},
561 {ISIS_ISADJ_NEIGHPRIORITY, UNSIGNED32, RONLY, isis_snmp_find_isadj},
562 {ISIS_ISADJ_LASTUPTIME, TIMESTAMP, RONLY, isis_snmp_find_isadj},
563 {ISIS_ISADJAREA_ADDRESS, STRING, RONLY, isis_snmp_find_isadj_area},
564 {ISIS_ISADJIPADDR_TYPE, INTEGER, RONLY, isis_snmp_find_isadj_ipaddr},
565 {ISIS_ISADJIPADDR_ADDRESS, STRING, RONLY, isis_snmp_find_isadj_ipaddr},
566 {ISIS_ISADJPROTSUPP_PROTOCOL, INTEGER, RONLY,
567 isis_snmp_find_isadj_prot_supp},
568};
569
570static const size_t isis_var_count = ARRAY_SIZE(isis_var_arr);
571
572/* Minimal set of hard-coded data */
573#define ISIS_VERSION (1)
574
575/* If sys-id is not set use this value */
576static uint8_t isis_null_sysid[ISIS_SYS_ID_LEN];
577
578/* OSI addr-len */
579#define ISIS_SNMP_OSI_ADDR_LEN_MAX (20)
580
581/*
582 * The implementation has a fixed max-path splits value
583 * of 64 (see ISIS_MAX_PATH_SPLITS), the max mib value
584 * is 32.
585 *
586 * FIXME(aromanov): should we return 32 or 64?
587 */
588#define ISIS_SNMP_MAX_PATH_SPLITS (32)
589
590#define ISIS_SNMP_ADMIN_STATE_ON (1)
591
592#define ISIS_SNMP_ROW_STATUS_ACTIVE (1)
593
594#define ISIS_SNMP_LEVEL_STATE_OFF (1)
595#define ISIS_SNMP_LEVEL_STATE_ON (2)
596#define ISIS_SNMP_LEVEL_STATE_WAITING (3)
597#define ISIS_SNMP_LEVEL_STATE_OVERLOADED (4)
598
599#define ISIS_SNMP_TRUTH_VALUE_TRUE (1)
600#define ISIS_SNMP_TRUTH_VALUE_FALSE (2)
601
602#define ISIS_SNMP_METRIC_STYLE_NARROW (1)
603#define ISIS_SNMP_METRIC_STYLE_WIDE (2)
604#define ISIS_SNMP_METRIC_STYLE_BOTH (3)
605
606#define ISIS_SNMP_MESH_GROUP_INACTIVE (1)
607
608#define ISIS_SNMP_ADJ_STATE_DOWN (1)
609#define ISIS_SNMP_ADJ_STATE_INITIALIZING (2)
610#define ISIS_SNMP_ADJ_STATE_UP (3)
611#define ISIS_SNMP_ADJ_STATE_FAILED (4)
612
5ff4ad8e
IR
613static inline uint32_t isis_snmp_adj_state(enum isis_adj_state state)
614{
615 switch (state) {
616 case ISIS_ADJ_UNKNOWN:
617 return ISIS_SNMP_ADJ_STATE_DOWN;
618 case ISIS_ADJ_INITIALIZING:
619 return ISIS_SNMP_ADJ_STATE_INITIALIZING;
620 case ISIS_ADJ_UP:
621 return ISIS_SNMP_ADJ_STATE_UP;
622 case ISIS_ADJ_DOWN:
623 return ISIS_SNMP_ADJ_STATE_FAILED;
624 }
625
626 return 0; /* not reached */
627}
628
1ee746d9 629#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1 (1)
630#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2 (2)
631#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2 (3)
632#define ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN (4)
633
5ff4ad8e
IR
634static inline uint32_t isis_snmp_adj_neightype(enum isis_system_type type)
635{
636 switch (type) {
637 case ISIS_SYSTYPE_UNKNOWN:
638 case ISIS_SYSTYPE_ES:
639 return ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN;
640 case ISIS_SYSTYPE_IS:
641 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2;
642 case ISIS_SYSTYPE_L1_IS:
643 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1;
644 case ISIS_SYSTYPE_L2_IS:
645 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2;
646 }
647
648 return 0; /* not reached */
649}
650
1ee746d9 651#define ISIS_SNMP_INET_TYPE_V4 (1)
652#define ISIS_SNMP_INET_TYPE_V6 (2)
653
654#define ISIS_SNMP_P2P_CIRCUIT (3)
655
656/* Protocols supported value */
657static uint8_t isis_snmp_protocols_supported = 0x7; /* All: iso, ipv4, ipv6 */
658
e2b5b7d6
IR
659#define SNMP_CIRCUITS_MAX (512)
660
661static struct isis_circuit *snmp_circuits[SNMP_CIRCUITS_MAX];
662static uint32_t snmp_circuit_id_last;
663
664static int isis_circuit_snmp_id_gen(struct isis_circuit *circuit)
665{
666 uint32_t id;
667 uint32_t i;
668
669 id = snmp_circuit_id_last;
670 id++;
671
672 /* find next unused entry */
673 for (i = 0; i < SNMP_CIRCUITS_MAX; i++) {
674 if (id >= SNMP_CIRCUITS_MAX) {
675 id = 0;
676 continue;
677 }
678
679 if (id == 0)
680 continue;
681
682 if (snmp_circuits[id] == NULL)
683 break;
684
685 id++;
686 }
687
688 if (i == SNMP_CIRCUITS_MAX) {
689 zlog_warn("Could not allocate a smmp-circuit-id");
690 return 0;
691 }
692
693 snmp_circuits[id] = circuit;
694 snmp_circuit_id_last = id;
695 circuit->snmp_id = id;
696
697 return 0;
698}
699
700static int isis_circuit_snmp_id_free(struct isis_circuit *circuit)
701{
702 snmp_circuits[circuit->snmp_id] = NULL;
703 circuit->snmp_id = 0;
704 return 0;
705}
706
1ee746d9 707/*
708 * Convenience function to move to the next circuit,
709 */
710static struct isis_circuit *isis_snmp_circuit_next(struct isis_circuit *circuit)
711{
712 uint32_t start;
713 uint32_t off;
1ee746d9 714
715 start = 1;
716
717 if (circuit != NULL)
718 start = circuit->snmp_id + 1;
719
720 for (off = start; off < SNMP_CIRCUITS_MAX; off++) {
e2b5b7d6 721 circuit = snmp_circuits[off];
1ee746d9 722
723 if (circuit != NULL)
724 return circuit;
725 }
726
727 return NULL;
728}
729
730/*
731 * Convenience function to get the first matching level
732 */
733static int isis_snmp_circuit_get_level_lo(struct isis_circuit *circuit)
734{
735 if (circuit->is_type == IS_LEVEL_2)
736 return IS_LEVEL_2;
737
738 return IS_LEVEL_1;
739}
740
741/* Check level match */
742static int isis_snmp_get_level_match(int is_type, int level)
743{
744 if (is_type != IS_LEVEL_1 && is_type != IS_LEVEL_2
745 && is_type != IS_LEVEL_1_AND_2)
746 return 0;
747
748 if (level != IS_LEVEL_1 && level != IS_LEVEL_2)
749 return 0;
750
751
752 if (is_type == IS_LEVEL_1) {
753 if (level == IS_LEVEL_1)
754 return 1;
755
756 return 0;
757 }
758
759 if (is_type == IS_LEVEL_2) {
760 if (level == IS_LEVEL_2)
761 return 1;
762
763 return 0;
764 }
765
766 return 1;
767}
768/*
769 * Helper function to convert oid index representing
770 * octet-string index (e.g. isis-sys-id) to byte string
771 * representing the same index.
772 *
773 * Also we do not fail if idx is longer than max_len,
774 * so we can use the same function to check compound
775 * indexes.
776 */
777static int isis_snmp_conv_exact(uint8_t *buf, size_t max_len, size_t *out_len,
778 const oid *idx, size_t idx_len)
779{
780 size_t off;
781 size_t len;
782
783 /* Oid representation: length followed by bytes */
784 if (idx == NULL || idx_len == 0)
785 return 0;
786
787 len = idx[0];
788
789 if (len > max_len)
790 return 0;
791
792 if (idx_len < len + 1)
793 return 0;
794
795 for (off = 0; off < len; off++) {
796 if (idx[off + 1] > 0xff)
797 return 0;
798
799 buf[off] = (uint8_t)(idx[off + 1] & 0xff);
800 }
801
802 *out_len = len;
803
804 return 1;
805}
806
807static int isis_snmp_conv_next(uint8_t *buf, size_t max_len, size_t *out_len,
808 int *try_exact, const oid *idx, size_t idx_len)
809{
810 size_t off;
811 size_t len;
812 size_t cmp_len;
813
814 if (idx == NULL || idx_len == 0) {
815 *out_len = 0;
816 *try_exact = 1;
817 return 1;
818 }
819
820 len = idx[0];
821
822 if (len > max_len)
823 return 0;
824
825 cmp_len = len;
826
827 if ((idx_len - 1) < cmp_len)
828 cmp_len = idx_len - 1;
829
830 for (off = 0; off < cmp_len; off++) {
831 if (idx[off + 1] > 0xff) {
832 memset(buf + off, 0xff, len - off);
833 *out_len = len;
834 *try_exact = 1;
835 return 1;
836 }
837
838 buf[off] = (uint8_t)(idx[off + 1] & 0xff);
839 }
840
841 if (cmp_len < len)
842 memset(buf + cmp_len, 0, len - cmp_len);
843
844 *out_len = len;
845 *try_exact = cmp_len < len ? 1 : 0;
846 return 1;
847}
848
849/*
850 * Helper functions to find area address from snmp index
851 */
852static int isis_snmp_area_addr_lookup_exact(oid *oid_idx, size_t oid_idx_len,
853 struct isis_area **ret_area,
854 struct area_addr **ret_addr)
855{
856 uint8_t cmp_buf[ISIS_SNMP_OSI_ADDR_LEN_MAX];
857 size_t addr_len;
858 struct isis_area *area = NULL;
859 struct area_addr *addr = NULL;
860 struct listnode *addr_node;
861 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
862
863 if (isis == NULL)
864 return 0;
865
866 if (list_isempty(isis->area_list)) {
867 /* Area is not configured yet */
868 return 0;
869 }
870
871 area = listgetdata(listhead(isis->area_list));
872
873 int res = isis_snmp_conv_exact(cmp_buf, sizeof(cmp_buf), &addr_len,
874 oid_idx, oid_idx_len);
875
876
877 if (!res || addr_len == 0 || oid_idx_len != (addr_len + 1)) {
878 /* Bad conversion, empty address or extra oids at the end */
879 return 0;
880 }
881
882 for (ALL_LIST_ELEMENTS_RO(area->area_addrs, addr_node, addr)) {
883 if (addr->addr_len != addr_len)
884 continue;
885
886 if (memcmp(addr->area_addr, cmp_buf, addr_len) == 0) {
887 if (ret_area != 0)
888 *ret_area = area;
889
890 if (ret_addr != 0)
891 *ret_addr = addr;
892
893 return 1;
894 }
895 }
896 return 0;
897}
898
899static int isis_snmp_area_addr_lookup_next(oid *oid_idx, size_t oid_idx_len,
900 struct isis_area **ret_area,
901 struct area_addr **ret_addr)
902{
903 uint8_t cmp_buf[ISIS_SNMP_OSI_ADDR_LEN_MAX];
904 size_t addr_len;
905 int try_exact = 0;
906 struct isis_area *found_area = NULL;
907 struct isis_area *area = NULL;
908 struct area_addr *found_addr = NULL;
909 struct area_addr *addr = NULL;
910 struct listnode *addr_node;
911 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
912
913 if (isis == NULL)
914 return 0;
915
916 if (list_isempty(isis->area_list)) {
917 /* Area is not configured yet */
918 return 0;
919 }
920
921 area = listgetdata(listhead(isis->area_list));
922
923 int res = isis_snmp_conv_next(cmp_buf, sizeof(cmp_buf), &addr_len,
924 &try_exact, oid_idx, oid_idx_len);
925
926 if (!res)
927 return 0;
928
929 for (ALL_LIST_ELEMENTS_RO(area->area_addrs, addr_node, addr)) {
930 if (addr->addr_len < addr_len)
931 continue;
932
933 if (addr->addr_len == addr_len) {
934 if (addr_len == 0)
935 continue;
936
937 res = memcmp(addr->area_addr, cmp_buf, addr_len);
938
939 if (res < 0)
940 continue;
941
942 if (res == 0 && addr->addr_len == addr_len) {
943 if (try_exact) {
944 /*
945 * This is the best match no point
946 * to look further
947 */
948 found_area = area;
949 found_addr = addr;
950 break;
951 }
952 continue;
953 }
954 }
955
956 if (found_addr == NULL || addr->addr_len < found_addr->addr_len
957 || (addr->addr_len == found_addr->addr_len
958 && memcmp(addr->area_addr, found_addr->area_addr,
959 addr->addr_len)
960 < 0)) {
961 found_area = area;
962 found_addr = addr;
963 }
964 }
965
966 if (found_area == NULL)
967 return 0;
968
969 if (ret_area != 0)
970 *ret_area = found_area;
971
972 if (ret_addr != 0)
973 *ret_addr = found_addr;
974
975 return 1;
976}
977
978/*
979 * Helper functions to find circuit from
980 * snmp index
981 */
982static int isis_snmp_circuit_lookup_exact(oid *oid_idx, size_t oid_idx_len,
983 struct isis_circuit **ret_circuit)
984{
985 struct isis_circuit *circuit;
1ee746d9 986
987 if (oid_idx == NULL || oid_idx_len < 1
988 || oid_idx[0] > SNMP_CIRCUITS_MAX)
989 return 0;
990
e2b5b7d6 991 circuit = snmp_circuits[oid_idx[0]];
1ee746d9 992 if (circuit == NULL)
993 return 0;
994
995 if (ret_circuit != NULL)
996 *ret_circuit = circuit;
997
998 return 1;
999}
1000
1001static int isis_snmp_circuit_lookup_next(oid *oid_idx, size_t oid_idx_len,
1002 struct isis_circuit **ret_circuit)
1003{
1004 oid off;
1005 oid start;
1006 struct isis_circuit *circuit;
1ee746d9 1007
1008 start = 0;
1009
e91a589b 1010 if (oid_idx != NULL && oid_idx_len != 0) {
1ee746d9 1011 if (oid_idx[0] > SNMP_CIRCUITS_MAX)
1012 return 0;
1013
1014 start = oid_idx[0];
1015 }
1016
1017 for (off = start; off < SNMP_CIRCUITS_MAX; ++off) {
e2b5b7d6 1018 circuit = snmp_circuits[off];
1ee746d9 1019
1020 if (circuit != NULL && off > start) {
1021 if (ret_circuit != NULL)
1022 *ret_circuit = circuit;
1023
1024 return 1;
1025 }
1026 }
1027
1028 return 0;
1029}
1030
1031/*
1032 * Helper functions to find circuit level
1033 * combination from snmp index
1034 */
1035static int isis_snmp_circuit_level_lookup_exact(
1036 oid *oid_idx, size_t oid_idx_len, int check_match,
1037 struct isis_circuit **ret_circuit, int *ret_level)
1038{
1039 int level;
1040 int res;
1041 struct isis_circuit *circuit;
1042
1043 /* Minor optimization: check level first */
1044 if (oid_idx == NULL || oid_idx_len < 2)
1045 return 0;
1046
1047 if (oid_idx[1] < IS_LEVEL_1 || oid_idx[1] > IS_LEVEL_2)
1048 return 0;
1049
1050 level = (int)oid_idx[1];
1051
1052 res = isis_snmp_circuit_lookup_exact(oid_idx, oid_idx_len, &circuit);
1053
1054 if (!res)
1055 return 0;
1056
1057 if (check_match && !isis_snmp_get_level_match(circuit->is_type, level))
1058 return 0;
1059
1060 if (ret_circuit != NULL)
1061 *ret_circuit = circuit;
1062
1063 if (ret_level != NULL)
1064 *ret_level = level;
1065
1066 return 1;
1067}
1068
1069static int isis_snmp_circuit_level_lookup_next(
1070 oid *oid_idx, size_t oid_idx_len, int check_match,
1071 struct isis_circuit **ret_circuit, int *ret_level)
1072{
1073 oid off;
1074 oid start;
4397d967 1075 struct isis_circuit *circuit = NULL;
1ee746d9 1076 int level;
1ee746d9 1077
1078 start = 0;
1079
e91a589b 1080 if (oid_idx != NULL && oid_idx_len != 0) {
1ee746d9 1081 if (oid_idx[0] > SNMP_CIRCUITS_MAX)
1082 return 0;
1083
1084 start = oid_idx[0];
1085 }
1086
1087 for (off = start; off < SNMP_CIRCUITS_MAX; off++) {
e2b5b7d6 1088 circuit = snmp_circuits[off];
1ee746d9 1089
1090 if (circuit == NULL)
1091 continue;
1092
1093 if (off > start || oid_idx_len < 2) {
1094 /* Found and can use level 1 */
1095 level = IS_LEVEL_1;
1096 break;
1097 }
1098
c33cb9fb
MS
1099 assert(oid_idx != NULL);
1100
1ee746d9 1101 /* We have to check level specified by index */
1102 if (oid_idx[1] < IS_LEVEL_1) {
1103 level = IS_LEVEL_1;
1104 break;
1105 }
1106
1107 if (oid_idx[1] < IS_LEVEL_2) {
1108 level = IS_LEVEL_2;
1109 break;
1110 }
1111
1112 /* Try next */
1113 circuit = NULL;
1114 }
1115
1116 if (circuit == NULL)
1117 return 0;
1118
1119 if (check_match
1120 && !isis_snmp_get_level_match(circuit->is_type, level)) {
1121 if (level == IS_LEVEL_1) {
1122 /*
1123 * We can simply advance level because
1124 * at least one level should match
1125 */
1126 level = IS_LEVEL_2;
1127 } else {
1128 /* We have to move to the next circuit */
1129 circuit = isis_snmp_circuit_next(circuit);
1130 if (circuit == NULL)
1131 return 0;
1132
1133 level = isis_snmp_circuit_get_level_lo(circuit);
1134 }
1135 }
1136
1137 if (ret_circuit != NULL)
1138 *ret_circuit = circuit;
1139
1140 if (ret_level != NULL)
1141 *ret_level = level;
1142
1143 return 1;
1144}
1145
1146/*
1147 * Helper functions to find adjacency
1148 * from snmp index.
1149 *
1150 * We have 4 tables related to adjacency
1151 * looking up adjacency is quite expensive
1152 * in case of bcast interfaces.
1153 *
1154 * It is pain to have 4 very similar functions
1155 * hence we pass in and out additional data
1156 * we are looking for.
1157 *
1158 * Note: we use data-len value to distinguish
1159 * between ipv4 and ipv6 addresses
1160 */
1161#define ISIS_SNMP_ADJ_DATA_NONE (1)
1162#define ISIS_SNMP_ADJ_DATA_AREA_ADDR (2)
1163#define ISIS_SNMP_ADJ_DATA_IP_ADDR (3)
1164#define ISIS_SNMP_ADJ_DATA_PROTO (4)
1165
1166/*
1167 * Helper function to process data associated
1168 * with adjacency
1169 */
1170static int isis_snmp_adj_helper(struct isis_adjacency *adj, int data_id,
1171 oid data_off, uint8_t **ret_data,
1172 size_t *ret_data_len)
1173{
1174 uint8_t *data = NULL;
1175 size_t data_len = 0;
1176
1177 switch (data_id) {
1178 case ISIS_SNMP_ADJ_DATA_NONE:
1179 break;
1180
1181 case ISIS_SNMP_ADJ_DATA_AREA_ADDR:
1182 if (data_off >= adj->area_address_count)
1183 return 0;
1184
1185 data = adj->area_addresses[data_off].area_addr;
1186 data_len = adj->area_addresses[data_off].addr_len;
1187 break;
1188
1189 case ISIS_SNMP_ADJ_DATA_IP_ADDR:
173f8887 1190 if (data_off >= (adj->ipv4_address_count + adj->ll_ipv6_count))
1ee746d9 1191 return 0;
1192
1193 if (data_off >= adj->ipv4_address_count) {
173f8887 1194 data = (uint8_t *)&adj->ll_ipv6_addrs
1ee746d9 1195 [data_off - adj->ipv4_address_count];
173f8887 1196 data_len = sizeof(adj->ll_ipv6_addrs[0]);
1ee746d9 1197 } else {
1198 data = (uint8_t *)&adj->ipv4_addresses[data_off];
1199 data_len = sizeof(adj->ipv4_addresses[0]);
1200 }
1201
1202 break;
1203
1204
1205 case ISIS_SNMP_ADJ_DATA_PROTO:
1206 if (data_off >= adj->nlpids.count)
1207 return 0;
1208
1209 data = &adj->nlpids.nlpids[data_off];
1210 data_len = sizeof(adj->nlpids.nlpids[0]);
1211 break;
1212
1213 default:
1214 assert(0);
1215 return 0;
1216 }
1217
1218 if (ret_data != NULL)
1219 *ret_data = data;
1220
1221 if (ret_data_len != NULL)
1222 *ret_data_len = data_len;
1223
1224 return 1;
1225}
1226
1227static int isis_snmp_adj_lookup_exact(oid *oid_idx, size_t oid_idx_len,
1228 int data_id,
1229 struct isis_adjacency **ret_adj,
1230 oid *ret_data_idx, uint8_t **ret_data,
1231 size_t *ret_data_len)
1232{
1233 int res;
1234 struct listnode *node;
1235 struct isis_circuit *circuit;
1236 struct isis_adjacency *adj;
1237 struct isis_adjacency *tmp_adj;
1238 oid adj_idx;
1239 oid data_off;
1240 uint8_t *data;
1241 size_t data_len;
1242
1243 res = isis_snmp_circuit_lookup_exact(oid_idx, oid_idx_len, &circuit);
1244
1245 if (!res)
1246 return 0;
1247
1248 if (oid_idx == NULL || oid_idx_len < 2
1249 || (data_id != ISIS_SNMP_ADJ_DATA_NONE && oid_idx_len < 3))
1250 return 0;
1251
1252 adj_idx = oid_idx[1];
1253
1254 if (data_id != ISIS_SNMP_ADJ_DATA_NONE) {
1255 if (oid_idx[2] == 0)
1256 return 0;
1257
1258 data_off = oid_idx[2] - 1;
1259 } else {
1260 /*
1261 * Data-off is not used if data-id is none
1262 * but we set it just for consistency
1263 */
1264 data_off = 0;
1265 }
1266
1267 adj = NULL;
1268 data = NULL;
1269 data_len = 0;
1270
1271 for (ALL_LIST_ELEMENTS_RO(circuit->snmp_adj_list, node, tmp_adj)) {
1272 if (tmp_adj->snmp_idx > adj_idx) {
1273 /*
1274 * Adjacencies are ordered in the list
1275 * no point to look further
1276 */
1277 break;
1278 }
1279
1280 if (tmp_adj->snmp_idx == adj_idx) {
1281 res = isis_snmp_adj_helper(tmp_adj, data_id, data_off,
1282 &data, &data_len);
1283 if (res)
1284 adj = tmp_adj;
1285
1286 break;
1287 }
1288 }
1289
1290 if (adj == NULL)
1291 return 0;
1292
1293 if (ret_adj != NULL)
1294 *ret_adj = adj;
1295
1296 if (ret_data_idx != NULL)
1297 *ret_data_idx = data_off + 1;
1298
1299 if (ret_data)
1300 *ret_data = data;
1301
1302 if (ret_data_len)
1303 *ret_data_len = data_len;
1304
1305 return 1;
1306}
1307
1308static int isis_snmp_adj_lookup_next(oid *oid_idx, size_t oid_idx_len,
1309 int data_id,
1310 struct isis_adjacency **ret_adj,
1311 oid *ret_data_idx, uint8_t **ret_data,
1312 size_t *ret_data_len)
1313{
1314 struct listnode *node;
1315 struct isis_circuit *circuit;
1316 struct isis_adjacency *adj;
1317 struct isis_adjacency *tmp_adj;
1318 oid circ_idx;
1319 oid adj_idx;
1320 oid data_idx;
1321 uint8_t *data;
1322 size_t data_len;
1323
1324 adj = NULL;
1325 data = NULL;
1326 data_len = 0;
1327
1328 /*
1329 * Note: we rely on the fact that data indexes are consequtive
1330 * starting from 1
1331 */
1332
1333 if (oid_idx == 0 || oid_idx_len == 0) {
1334 circ_idx = 0;
1335 adj_idx = 0;
1336 data_idx = 0;
1337 } else if (oid_idx_len == 1) {
1338 circ_idx = oid_idx[0];
1339 adj_idx = 0;
1340 data_idx = 0;
1341 } else if (oid_idx_len == 2) {
1342 circ_idx = oid_idx[0];
1343 adj_idx = oid_idx[1];
1344 data_idx = 0;
1345 } else {
1346 circ_idx = oid_idx[0];
1347 adj_idx = oid_idx[1];
1348
1349 if (data_id == ISIS_SNMP_ADJ_DATA_NONE)
1350 data_idx = 0;
1351 else
1352 data_idx = oid_idx[2];
1353 }
1354
1355 if (!isis_snmp_circuit_lookup_exact(&circ_idx, 1, &circuit)
1356 && !isis_snmp_circuit_lookup_next(&circ_idx, 1, &circuit))
1357 /* No circuit */
1358 return 0;
1359
1360 if (circuit->snmp_id != circ_idx) {
1361 /* Match is not exact */
1362 circ_idx = 0;
1363 adj_idx = 0;
1364 data_idx = 0;
1365 }
1366
1367 /*
1368 * Note: the simple loop below will work in all cases
1369 */
1370 while (circuit != NULL) {
1371 for (ALL_LIST_ELEMENTS_RO(circuit->snmp_adj_list, node,
1372 tmp_adj)) {
1373 if (tmp_adj->snmp_idx < adj_idx)
1374 continue;
1375
1376 if (tmp_adj->snmp_idx == adj_idx
1377 && data_id == ISIS_SNMP_ADJ_DATA_NONE)
1378 continue;
1379
1380 if (adj_idx != 0 && tmp_adj->snmp_idx > adj_idx)
1381 data_idx = 0;
1382
1383 if (isis_snmp_adj_helper(tmp_adj, data_id, data_idx,
1384 &data, &data_len)) {
1385 adj = tmp_adj;
1386 break;
1387 }
1388 }
1389
1390 if (adj != NULL)
1391 break;
1392
1393 circuit = isis_snmp_circuit_next(circuit);
1394 circ_idx = 0;
1395 adj_idx = 0;
1396 data_idx = 0;
1397 }
1398
1399 if (adj == NULL)
1400 return 0;
1401
1402 if (ret_adj != NULL)
1403 *ret_adj = adj;
1404
1405 if (ret_data_idx != 0) {
1406 if (data_id == ISIS_SNMP_ADJ_DATA_NONE)
1407 /*
1408 * Value does not matter but let us set
1409 * it to zero for consistency
1410 */
1411 *ret_data_idx = 0;
1412 else
1413 *ret_data_idx = data_idx + 1;
1414 }
1415
1416 if (ret_data != 0)
1417 *ret_data = data;
1418
1419 if (ret_data_len != 0)
1420 *ret_data_len = data_len;
1421
1422 return 1;
1423}
1424
1425static uint8_t *isis_snmp_find_sys_object(struct variable *v, oid *name,
1426 size_t *length, int exact,
1427 size_t *var_len,
1428 WriteMethod **write_method)
1429{
1430 struct isis_area *area = NULL;
1431 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
1432
1433 if (isis == NULL)
1434 return NULL;
1435
1436 if (!list_isempty(isis->area_list))
1437 area = listgetdata(listhead(isis->area_list));
1438
1439 /* Check whether the instance identifier is valid */
1440 if (smux_header_generic(v, name, length, exact, var_len, write_method)
1441 == MATCH_FAILED)
1442 return NULL;
1443
1444 switch (v->magic) {
1445 case ISIS_SYS_VERSION:
1446 return SNMP_INTEGER(ISIS_VERSION);
1447
1448 case ISIS_SYS_LEVELTYPE:
1449 /*
1450 * If we do not have areas use 1&2 otherwise use settings
1451 * from the first area in the list
1452 */
1453 if (area == NULL)
1454 return SNMP_INTEGER(IS_LEVEL_1_AND_2);
1455
1456 return SNMP_INTEGER(area->is_type);
1457
1458 case ISIS_SYS_ID:
1459 if (!isis->sysid_set) {
1460 *var_len = ISIS_SYS_ID_LEN;
1461 return isis_null_sysid;
1462 }
1463
1464 *var_len = ISIS_SYS_ID_LEN;
1465 return isis->sysid;
1466
1467 case ISIS_SYS_MAXPATHSPLITS:
1468 return SNMP_INTEGER(ISIS_SNMP_MAX_PATH_SPLITS);
1469
1470 case ISIS_SYS_MAXLSPGENINT:
1471 return SNMP_INTEGER(DEFAULT_MAX_LSP_GEN_INTERVAL);
1472
1473 case ISIS_SYS_POLLESHELLORATE:
1474 return SNMP_INTEGER(DEFAULT_HELLO_INTERVAL);
1475
1476 case ISIS_SYS_WAITTIME:
1477 /* Note: it seems that we have same fixed delay time */
1478 return SNMP_INTEGER(DEFAULT_MIN_LSP_GEN_INTERVAL);
1479
1480 case ISIS_SYS_ADMINSTATE:
1481 /* If daemon is running it admin state is on */
1482 return SNMP_INTEGER(ISIS_SNMP_ADMIN_STATE_ON);
1483
1484
1485 case ISIS_SYS_L2TOL1LEAKING:
1486 /* We do not allow l2-to-l1 leaking */
1487 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
1488
1489 case ISIS_SYS_MAXAGE:
1490 return SNMP_INTEGER(MAX_AGE);
1491
1492 case ISIS_SYS_RECEIVELSPBUFFERSIZE:
1493 if (area == NULL)
1494 return SNMP_INTEGER(DEFAULT_LSP_MTU);
1495
1496 return SNMP_INTEGER(area->lsp_mtu);
1497
1498 case ISIS_SYS_PROTSUPPORTED:
1499 *var_len = 1;
1500 return &isis_snmp_protocols_supported;
1501
1502 case ISIS_SYS_NOTIFICATIONENABLE:
1503 if (isis->snmp_notifications)
1504 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
1505
1506 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
1507
1508 default:
1509 break;
1510 }
1511
1512 return NULL;
1513}
1514
1515
1516static uint8_t *isis_snmp_find_man_area(struct variable *v, oid *name,
1517 size_t *length, int exact,
1518 size_t *var_len,
1519 WriteMethod **write_method)
1520{
1521 int res;
1522 struct area_addr *area_addr = NULL;
1523 oid *oid_idx;
1524 size_t oid_idx_len;
1525 size_t off = 0;
1526
1527 *write_method = NULL;
1528
1529 if (*length <= v->namelen) {
1530 oid_idx = NULL;
1531 oid_idx_len = 0;
1532 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
1533 oid_idx = NULL;
1534 oid_idx_len = 0;
1535 } else {
1536 oid_idx = name + v->namelen;
1537 oid_idx_len = *length - v->namelen;
1538 }
1539
1540 if (exact) {
1541 res = isis_snmp_area_addr_lookup_exact(oid_idx, oid_idx_len,
1542 NULL, &area_addr);
1543
1544 if (!res)
1545 return NULL;
1546
1547 } else {
1548 res = isis_snmp_area_addr_lookup_next(oid_idx, oid_idx_len,
1549 NULL, &area_addr);
1550
1551 if (!res)
1552 return NULL;
1553
1554 /* Copy the name out */
1555 memcpy(name, v->name, v->namelen * sizeof(oid));
1556
1557 /* Append index */
1558 name[v->namelen] = area_addr->addr_len;
1559
1560 for (off = 0; off < area_addr->addr_len; off++)
1561 name[v->namelen + 1 + off] = area_addr->area_addr[off];
1562
1563 *length = v->namelen + 1 + area_addr->addr_len;
1564 }
1565
1566 switch (v->magic) {
1567 case ISIS_MANAREA_ADDREXISTSTATE:
1568 return SNMP_INTEGER(ISIS_SNMP_ROW_STATUS_ACTIVE);
1569
1570 default:
1571 break;
1572 }
1573
1574 return NULL;
1575}
1576
1577static uint8_t *isis_snmp_find_area_addr(struct variable *v, oid *name,
1578 size_t *length, int exact,
1579 size_t *var_len,
1580 WriteMethod **write_method)
1581{
1582 /*
1583 * Area addresses in sense of addresses reported by L1 lsps
1584 * are not supported yet.
1585 */
1586 (void)v;
1587 (void)name;
1588 (void)length;
1589 (void)exact;
1590 (void)var_len;
1591
1592
1593 *write_method = NULL;
1594
1595 return NULL;
1596}
1597
1598static uint8_t *isis_snmp_find_summ_addr(struct variable *v, oid *name,
1599 size_t *length, int exact,
1600 size_t *var_len,
1601 WriteMethod **write_method)
1602{
1603 /*
1604 * So far there is no way to set summary table values through cli
1605 * and snmp operations are read-only, hence there are no entries
1606 */
1607 (void)v;
1608 (void)name;
1609 (void)length;
1610 (void)exact;
1611 (void)var_len;
1612 *write_method = NULL;
1613
1614 return NULL;
1615}
1616
1617static uint8_t *isis_snmp_find_redistribute_addr(struct variable *v, oid *name,
1618 size_t *length, int exact,
1619 size_t *var_len,
1620 WriteMethod **write_method)
1621{
1622 /*
1623 * It is not clear at the point whether redist code in isis is actually
1624 * used for now we will consider that entries are not present
1625 */
1626 (void)v;
1627 (void)name;
1628 (void)length;
1629 (void)exact;
1630 (void)var_len;
1631 *write_method = NULL;
1632
1633 return NULL;
1634}
1635
1636static uint8_t *isis_snmp_find_router(struct variable *v, oid *name,
1637 size_t *length, int exact,
1638 size_t *var_len,
1639 WriteMethod **write_method)
1640{
1641 uint8_t cmp_buf[ISIS_SYS_ID_LEN];
1642 size_t cmp_len;
1643 int try_exact;
1644 int cmp_level;
1645 int res;
1646 struct isis_dynhn *dyn = NULL;
1647 oid *oid_idx;
1648 size_t oid_idx_len;
1649 size_t off = 0;
240f48b3
IR
1650 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
1651
1652 if (isis == NULL)
1653 return NULL;
1ee746d9 1654
1655 *write_method = NULL;
1656
1657 if (*length <= v->namelen) {
1658 oid_idx = NULL;
1659 oid_idx_len = 0;
1660 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
1661 oid_idx = NULL;
1662 oid_idx_len = 0;
1663 } else {
1664 oid_idx = name + v->namelen;
1665 oid_idx_len = *length - v->namelen;
1666 }
1667
1668 if (exact) {
1669 res = isis_snmp_conv_exact(cmp_buf, sizeof(cmp_buf), &cmp_len,
1670 oid_idx, oid_idx_len);
1671
1672 if (!res || cmp_len != ISIS_SYS_ID_LEN
1673 || oid_idx_len != (cmp_len + 2))
1674 /*
1675 * Bad conversion, or bad length,
1676 * or extra oids at the end
1677 */
1678 return NULL;
1679
1680 if (oid_idx[ISIS_SYS_ID_LEN + 1] < IS_LEVEL_1
1681 || oid_idx[ISIS_SYS_ID_LEN + 1] > IS_LEVEL_2)
1682 /* Level part of the index is out of range */
1683 return NULL;
1684
1685 cmp_level = (int)oid_idx[ISIS_SYS_ID_LEN + 1];
1686
240f48b3 1687 dyn = dynhn_find_by_id(isis, cmp_buf);
1ee746d9 1688
1689 if (dyn == NULL || dyn->level != cmp_level)
1690 return NULL;
1691
1692 switch (v->magic) {
1693 case ISIS_ROUTER_HOSTNAME:
1694 *var_len = strlen(dyn->hostname);
1695 return (uint8_t *)dyn->hostname;
1696
1697 case ISIS_ROUTER_ID:
1698 /* It seems that we do no know router-id in lsps */
1699 return SNMP_INTEGER(0);
1700
1701 default:
1702 break;
1703 }
1704
1705 return NULL;
1706 }
1707
1708 res = isis_snmp_conv_next(cmp_buf, sizeof(cmp_buf), &cmp_len,
1709 &try_exact, oid_idx, oid_idx_len);
1710
1711
1712 if (!res)
1713 /* Bad conversion */
1714 return NULL;
1715
1716 if (cmp_len != ISIS_SYS_ID_LEN) {
1717 /* We do not have valid index oids */
1718 memset(cmp_buf, 0, sizeof(cmp_buf));
1719 cmp_level = 0;
1720 } else if (try_exact)
1721 /*
1722 * We have no valid level index.
1723 * Let start from non-existing level 0 and
1724 * hence not need to do exact match
1725 */
1726 cmp_level = 0;
1727 else if (oid_idx_len < (ISIS_SYS_ID_LEN + 2))
1728 cmp_level = 0;
1729 else if (oid_idx[ISIS_SYS_ID_LEN + 1] <= IS_LEVEL_2)
1730 cmp_level = (int)oid_idx[ISIS_SYS_ID_LEN + 1];
1731 else
1732 /*
1733 * Any value greater than 2 will have the same result
1734 * but we can have integer overflows, hence 3 is a reasonable
1735 * choice
1736 */
1737 cmp_level = (int)(IS_LEVEL_2 + 1);
1738
240f48b3 1739 dyn = dynhn_snmp_next(isis, cmp_buf, cmp_level);
1ee746d9 1740
1741 if (dyn == NULL)
1742 return NULL;
1743
1744 /* Copy the name out */
1745 memcpy(name, v->name, v->namelen * sizeof(oid));
1746
1747 /* Append index */
1748 name[v->namelen] = ISIS_SYS_ID_LEN;
1749
1750 for (off = 0; off < ISIS_SYS_ID_LEN; off++)
1751 name[v->namelen + 1 + off] = dyn->id[off];
1752
1753 name[v->namelen + 1 + ISIS_SYS_ID_LEN] = (oid)dyn->level;
1754
1755 /* Set length */
1756 *length = v->namelen + 1 + ISIS_SYS_ID_LEN + 1;
1757
1758 switch (v->magic) {
1759 case ISIS_ROUTER_HOSTNAME:
1760 *var_len = strlen(dyn->hostname);
1761 return (uint8_t *)dyn->hostname;
1762
1763 case ISIS_ROUTER_ID:
1764 /* It seems that we do no know router-id in lsps */
1765 return SNMP_INTEGER(0);
1766
1767 default:
1768 break;
1769 }
1770
1771 return NULL;
1772}
1773
1774static uint8_t *isis_snmp_find_sys_level(struct variable *v, oid *name,
1775 size_t *length, int exact,
1776 size_t *var_len,
1777 WriteMethod **write_method)
1778{
1779 oid *oid_idx;
1780 size_t oid_idx_len;
1781 int level;
1782 int level_match;
1783 struct isis_area *area = NULL;
1784 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
1785
1786 if (isis == NULL)
1787 return NULL;
1788
1789 *write_method = NULL;
1790
1791 if (*length <= v->namelen) {
1792 oid_idx = NULL;
1793 oid_idx_len = 0;
1794 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
1795 oid_idx = NULL;
1796 oid_idx_len = 0;
1797 } else {
1798 oid_idx = name + v->namelen;
1799 oid_idx_len = *length - v->namelen;
1800 }
1801
1802 if (exact) {
1803 if (oid_idx == NULL || oid_idx_len != 1)
1804 return NULL;
1805
1806 if (oid_idx[0] == IS_LEVEL_1)
1807 level = IS_LEVEL_1;
1808 else if (oid_idx[0] == IS_LEVEL_2)
1809 level = IS_LEVEL_2;
1810 else
1811 return NULL;
1812
1813 } else {
1814 if (oid_idx == NULL)
1815 level = IS_LEVEL_1;
1816 else if (oid_idx_len == 0)
1817 level = IS_LEVEL_1;
1818 else if (oid_idx[0] < IS_LEVEL_1)
1819 level = IS_LEVEL_1;
1820 else if (oid_idx[0] < IS_LEVEL_2)
1821 level = IS_LEVEL_2;
1822 else
1823 return NULL;
1824
1825 /* Copy the name out */
1826 memcpy(name, v->name, v->namelen * sizeof(oid));
1827
1828 /* Append index */
1829 name[v->namelen] = level;
1830
1831 /* Set length */
1832 *length = v->namelen + 1;
1833 }
1834
1835 area = NULL;
1836
1837 if (!list_isempty(isis->area_list))
1838 area = listgetdata(listhead(isis->area_list));
1839
1840 level_match = 0;
1841
1842 if (area != NULL)
1843 level_match = isis_snmp_get_level_match(area->is_type, level);
1844
1845 switch (v->magic) {
1846 case ISIS_SYSLEVEL_ORIGLSPBUFFSIZE:
1847 if (level_match)
1848 return SNMP_INTEGER(area->lsp_mtu);
1849
1850 return SNMP_INTEGER(DEFAULT_LSP_MTU);
1851
1852 case ISIS_SYSLEVEL_MINLSPGENINT:
1853 if (level_match)
1854 return SNMP_INTEGER(area->lsp_gen_interval[level - 1]);
1855 else
1856 return SNMP_INTEGER(DEFAULT_MIN_LSP_GEN_INTERVAL);
1857
1858 case ISIS_SYSLEVEL_STATE:
1859 if (level_match) {
1860 if (area->overload_bit)
1861 return SNMP_INTEGER(
1862 ISIS_SNMP_LEVEL_STATE_OVERLOADED);
1863
1864 return SNMP_INTEGER(ISIS_SNMP_LEVEL_STATE_ON);
1865 }
1866 return SNMP_INTEGER(ISIS_SNMP_LEVEL_STATE_OFF);
1867
1868 case ISIS_SYSLEVEL_SETOVERLOAD:
1869 if (level_match && area->overload_bit)
1870 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
1871
1872 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
1873
1874 case ISIS_SYSLEVEL_SETOVERLOADUNTIL:
1875 /* We do not have automatic cleanup of overload bit */
1876 return SNMP_INTEGER(0);
1877
1878 case ISIS_SYSLEVEL_METRICSTYLE:
1879 if (level_match) {
1880 if (area->newmetric && area->oldmetric)
1881 return SNMP_INTEGER(
1882 ISIS_SNMP_METRIC_STYLE_BOTH);
1883
1884 if (area->newmetric)
1885 return SNMP_INTEGER(
1886 ISIS_SNMP_METRIC_STYLE_WIDE);
1887
1888 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_NARROW);
1889 }
1890 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_NARROW);
1891
1892 case ISIS_SYSLEVEL_SPFCONSIDERS:
1893 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_BOTH);
1894
1895 case ISIS_SYSLEVEL_TEENABLED:
1896 if (level_match && IS_MPLS_TE(area->mta))
1897 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
1898
1899 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
1900
1901 default:
1902 break;
1903 }
1904
1905 return NULL;
1906}
1907
1908static uint8_t *isis_snmp_find_system_counter(struct variable *v, oid *name,
1909 size_t *length, int exact,
1910 size_t *var_len,
1911 WriteMethod **write_method)
1912{
1913 oid *oid_idx;
1914 size_t oid_idx_len;
1915 int level;
1916 int level_match;
1917 struct isis_area *area = NULL;
1918 uint32_t val;
1919 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
1920
1921 if (isis == NULL)
1922 return NULL;
1923
1924 *write_method = NULL;
1925
1926 if (*length <= v->namelen) {
1927 oid_idx = NULL;
1928 oid_idx_len = 0;
1929 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
1930 oid_idx = NULL;
1931 oid_idx_len = 0;
1932 } else {
1933 oid_idx = name + v->namelen;
1934 oid_idx_len = *length - v->namelen;
1935 }
1936
1937 if (exact) {
1938 if (oid_idx == NULL || oid_idx_len != 1)
1939 return 0;
1940
1941 if (oid_idx[0] == IS_LEVEL_1)
1942 level = IS_LEVEL_1;
1943 else if (oid_idx[0] == IS_LEVEL_2)
1944 level = IS_LEVEL_2;
1945 else
1946 return NULL;
1947
1948 } else {
1949 if (oid_idx == NULL)
1950 level = IS_LEVEL_1;
1951 else if (oid_idx_len == 0)
1952 level = IS_LEVEL_1;
1953 else if (oid_idx[0] < IS_LEVEL_1)
1954 level = IS_LEVEL_1;
1955 else if (oid_idx[0] < IS_LEVEL_2)
1956 level = IS_LEVEL_2;
1957 else
1958 return NULL;
1959
1960 /* Copy the name out */
1961 memcpy(name, v->name, v->namelen * sizeof(oid));
1962
1963 /* Append index */
1964 name[v->namelen] = level;
1965
1966 /* Set length */
1967 *length = v->namelen + 1;
1968 }
1969
1970 area = NULL;
1971
1972 if (!list_isempty(isis->area_list))
1973 area = listgetdata(listhead(isis->area_list));
1974
1975 level_match = 0;
1976
1977 if (area != NULL)
1978 level_match = isis_snmp_get_level_match(area->is_type, level);
1979
1980 if (!level_match)
1981 /* If level does not match all counters are zeros */
1982 return SNMP_INTEGER(0);
1983
1ee746d9 1984 switch (v->magic) {
1985 case ISIS_SYSSTAT_CORRLSPS:
1986 val = 0;
1987 break;
1988
1989 case ISIS_SYSSTAT_AUTHTYPEFAILS:
1990 val = (uint32_t)area->auth_type_failures[level - 1];
1991 break;
1992
1993 case ISIS_SYSSTAT_AUTHFAILS:
1994 val = (uint32_t)area->auth_failures[level - 1];
1995 break;
1996
1997 case ISIS_SYSSTAT_LSPDBASEOLOADS:
1998 val = area->overload_counter;
1999 break;
2000
2001 case ISIS_SYSSTAT_MANADDRDROPFROMAREAS:
2002 /* We do not support manual addresses */
2003 val = 0;
2004 break;
2005
2006 case ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS:
2007 val = area->lsp_exceeded_max_counter;
2008 break;
2009
2010 case ISIS_SYSSTAT_SEQNUMSKIPS:
2011 val = area->lsp_seqno_skipped_counter;
2012 break;
2013
2014 case ISIS_SYSSTAT_OWNLSPPURGES:
2015 if (!area->purge_originator)
2016 val = 0;
2017 else
2018 val = area->lsp_purge_count[level - 1];
2019 break;
2020
2021 case ISIS_SYSSTAT_IDFIELDLENMISMATCHES:
2022 val = (uint32_t)area->id_len_mismatches[level - 1];
2023 break;
2024
2025 case ISIS_SYSSTAT_PARTCHANGES:
2026 /* Not supported */
2027 val = 0;
2028 break;
2029
2030 case ISIS_SYSSTAT_SPFRUNS:
2031 val = (uint32_t)area->spf_run_count[level - 1];
2032 break;
2033
2034 case ISIS_SYSSTAT_LSPERRORS:
2035 val = (uint32_t)area->lsp_error_counter[level - 1];
2036 break;
2037
2038 default:
2039 return NULL;
2040 }
2041
2042 return SNMP_INTEGER(val);
2043}
2044
2045static uint8_t *isis_snmp_find_next_circ_index(struct variable *v, oid *name,
2046 size_t *length, int exact,
2047 size_t *var_len,
2048 WriteMethod **write_method)
2049{
2050 /* Check whether the instance identifier is valid */
2051 if (smux_header_generic(v, name, length, exact, var_len, write_method)
2052 == MATCH_FAILED)
2053 return NULL;
2054
2055 switch (v->magic) {
2056 case ISIS_NEXTCIRC_INDEX:
2057 /*
2058 * We do not support circuit creation through snmp
2059 */
2060 return SNMP_INTEGER(0);
2061
2062 default:
2063 break;
2064 }
2065
2066 return 0;
2067}
2068
2069static uint8_t *isis_snmp_find_circ(struct variable *v, oid *name,
2070 size_t *length, int exact, size_t *var_len,
2071 WriteMethod **write_method)
2072{
2073 /* Index is circuit-id: 1-255 */
2074 oid *oid_idx;
2075 size_t oid_idx_len;
2076 struct isis_circuit *circuit;
e91a589b 2077 uint32_t up_ticks;
2078 uint32_t delta_ticks;
75fef2a4 2079 time_t now_time;
1ee746d9 2080 int res;
2081
2082 *write_method = NULL;
2083
2084 if (*length <= v->namelen) {
2085 oid_idx = NULL;
2086 oid_idx_len = 0;
2087 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
2088 oid_idx = NULL;
2089 oid_idx_len = 0;
2090 } else {
2091 oid_idx = name + v->namelen;
2092 oid_idx_len = *length - v->namelen;
2093 }
2094 if (exact) {
2095 res = isis_snmp_circuit_lookup_exact(oid_idx, oid_idx_len,
2096 &circuit);
2097
2098 if (!res || oid_idx_len != 1)
2099 return NULL;
2100
2101 } else {
2102 res = isis_snmp_circuit_lookup_next(oid_idx, oid_idx_len,
2103 &circuit);
2104
2105 if (!res)
2106 return NULL;
2107
2108 /* Copy the name out */
2109 memcpy(name, v->name, v->namelen * sizeof(oid));
2110
2111 /* Append index */
2112 name[v->namelen] = circuit->snmp_id;
2113
2114 /* Set length */
2115 *length = v->namelen + 1;
2116 }
2117
2118 switch (v->magic) {
2119 case ISIS_CIRC_IFINDEX:
9d3de36d 2120 if (circuit->interface == NULL)
1ee746d9 2121 return SNMP_INTEGER(0);
2122
2123 return SNMP_INTEGER(circuit->interface->ifindex);
2124
2125 case ISIS_CIRC_ADMINSTATE:
2126 return SNMP_INTEGER(ISIS_SNMP_ADMIN_STATE_ON);
2127
2128 case ISIS_CIRC_EXISTSTATE:
2129 return SNMP_INTEGER(ISIS_SNMP_ROW_STATUS_ACTIVE);
2130
2131 case ISIS_CIRC_TYPE:
2132 /*
2133 * Note: values do not match 100%:
2134 *
2135 * 1. From isis_circuit.h:
2136 * CIRCUIT_T_UNKNOWN 0
2137 * CIRCUIT_T_BROADCAST 1
2138 * CIRCUIT_T_P2P 2
2139 * CIRCUIT_T_LOOPBACK 3
2140 *
2141 * 2. From rfc:
2142 * broadcast(1),
2143 * ptToPt(2),
2144 * staticIn(3),
2145 * staticOut(4),
2146 */
2147
2148 return SNMP_INTEGER(circuit->circ_type);
2149
2150 case ISIS_CIRC_EXTDOMAIN:
2151 if (circuit->ext_domain)
2152 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
2153
2154 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
2155
2156 case ISIS_CIRC_LEVELTYPE:
2157 return SNMP_INTEGER(circuit->is_type);
2158
2159 case ISIS_CIRC_PASSIVECIRCUIT:
2160 if (circuit->is_passive)
2161 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
2162
2163 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
2164
2165 case ISIS_CIRC_MESHGROUPENABLED:
2166 /* Not supported */
2167 return SNMP_INTEGER(ISIS_SNMP_MESH_GROUP_INACTIVE);
2168
2169 case ISIS_CIRC_MESHGROUP:
2170 /* Not supported */
2171 return SNMP_INTEGER(0);
2172
2173 case ISIS_CIRC_SMALLHELLOS:
2174 /*
2175 * return false if lan hellos must be padded
2176 */
2177 if (circuit->pad_hellos)
2178 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
2179
2180 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
2181
2182 case ISIS_CIRC_LASTUPTIME:
2183 if (circuit->last_uptime == 0)
2184 return SNMP_INTEGER(0);
2185
e91a589b 2186 up_ticks = (uint32_t)netsnmp_get_agent_uptime();
75fef2a4 2187 now_time = time(NULL);
1ee746d9 2188
2189 if (circuit->last_uptime >= now_time)
2190 return SNMP_INTEGER(up_ticks);
2191
2192 delta_ticks = (now_time - circuit->last_uptime) * 10;
2193
2194 if (up_ticks < delta_ticks)
2195 return SNMP_INTEGER(up_ticks);
2196
e91a589b 2197 return SNMP_INTEGER(up_ticks - delta_ticks);
1ee746d9 2198
2199 case ISIS_CIRC_3WAYENABLED:
2200 /* Not supported */
2201 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
2202
2203 case ISIS_CIRC_EXTENDEDCIRCID:
2204 /* Used for 3-way hand shake only */
2205 return SNMP_INTEGER(0);
2206
2207 default:
2208 break;
2209 }
2210
2211 return NULL;
2212}
2213
2214static uint8_t *isis_snmp_find_circ_level(struct variable *v, oid *name,
2215 size_t *length, int exact,
2216 size_t *var_len,
2217 WriteMethod **write_method)
2218{
2219 static uint8_t circuit_id_val[ISIS_SYS_ID_LEN + 1];
2220 /* Index is circuit-id: 1-255 + level: 1-2 */
2221 oid *oid_idx;
2222 size_t oid_idx_len;
2223 int res;
2224 struct isis_circuit *circuit;
2225 int level;
2226 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
2227
2228 if (isis == NULL)
2229 return NULL;
2230
2231 *write_method = NULL;
2232
2233 if (*length <= v->namelen) {
2234 oid_idx = NULL;
2235 oid_idx_len = 0;
2236 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
2237 oid_idx = NULL;
2238 oid_idx_len = 0;
2239 } else {
2240 oid_idx = name + v->namelen;
2241 oid_idx_len = *length - v->namelen;
2242 }
2243 if (exact) {
2244 res = isis_snmp_circuit_level_lookup_exact(oid_idx, oid_idx_len,
2245 1, &circuit, &level);
2246
2247 if (!res || oid_idx_len != 2)
2248 return NULL;
2249
2250 } else {
2251 res = isis_snmp_circuit_level_lookup_next(oid_idx, oid_idx_len,
2252 1, &circuit, &level);
2253
2254 if (!res)
2255 return NULL;
2256
2257 /* Copy the name out */
2258 memcpy(name, v->name, v->namelen * sizeof(oid));
2259
2260 /* Append index */
2261 name[v->namelen] = circuit->snmp_id;
2262 name[v->namelen + 1] = level;
2263
2264 /* Set length */
2265 *length = v->namelen + 2;
2266 }
2267
2268 switch (v->magic) {
2269 case ISIS_CIRCLEVEL_METRIC:
2270 return SNMP_INTEGER(circuit->metric[level - 1]);
2271
2272 case ISIS_CIRCLEVEL_WIDEMETRIC:
2273 if (circuit->area == NULL || !circuit->area->newmetric) {
2274 /* What should we do if wide metric is not supported? */
2275 return SNMP_INTEGER(0);
2276 }
2277 return SNMP_INTEGER(circuit->te_metric[level - 1]);
2278
2279 case ISIS_CIRCLEVEL_ISPRIORITY:
2280 return SNMP_INTEGER(circuit->priority[level - 1]);
2281
2282 case ISIS_CIRCLEVEL_IDOCTET:
2283 return SNMP_INTEGER(circuit->circuit_id);
2284
2285 case ISIS_CIRCLEVEL_ID:
2286 if (circuit->circ_type != CIRCUIT_T_P2P) {
2287 /*
2288 * Unless it is point-to-point circuit, the value is and
2289 * empty octet string
2290 */
2291 *var_len = 0;
2292 return circuit_id_val;
2293 }
2294
2295 /* !!!!!! Circuit-id is zero for p2p links */
2296 if (circuit->u.p2p.neighbor == NULL
2297 || circuit->u.p2p.neighbor->adj_state != ISIS_ADJ_UP) {
2298 /* No adjacency or adjacency not fully up yet */
2299 memcpy(circuit_id_val, isis->sysid, ISIS_SYS_ID_LEN);
2300 circuit_id_val[ISIS_SYS_ID_LEN] = circuit->circuit_id;
2301 *var_len = ISIS_SYS_ID_LEN + 1;
2302 return circuit_id_val;
2303 }
2304
2305 /* Adjacency fully-up */
2306 memcpy(circuit_id_val, circuit->u.p2p.neighbor->sysid,
2307 ISIS_SYS_ID_LEN);
2308 circuit_id_val[ISIS_SYS_ID_LEN] = 0;
2309 *var_len = ISIS_SYS_ID_LEN + 1;
2310 return circuit_id_val;
2311
2312 case ISIS_CIRCLEVEL_DESIS:
2313 if (circuit->circ_type != CIRCUIT_T_BROADCAST
2314 || !circuit->u.bc.is_dr[level - 1]) {
2315 /*
2316 * Unless it is lan circuit participating in dis process
2317 * the value is an empty octet string
2318 */
2319 *var_len = 0;
2320 return circuit_id_val;
2321 }
2322
2323 *var_len = ISIS_SYS_ID_LEN + 1;
2324
2325 if (level == IS_LEVEL_1)
2326 return circuit->u.bc.l1_desig_is;
2327
2328 return circuit->u.bc.l2_desig_is;
2329
2330 case ISIS_CIRCLEVEL_HELLOMULTIPLIER:
2331 return SNMP_INTEGER(circuit->hello_multiplier[level - 1]);
2332
2333 case ISIS_CIRCLEVEL_HELLOTIMER:
2334 return SNMP_INTEGER(circuit->hello_interval[level - 1] * 1000);
2335
2336 case ISIS_CIRCLEVEL_DRHELLOTIMER:
2337 return SNMP_INTEGER(circuit->hello_interval[level - 1] * 1000);
2338
2339 case ISIS_CIRCLEVEL_LSPTHROTTLE:
2340 if (circuit->area)
2341 return SNMP_INTEGER(
2342 circuit->area->min_spf_interval[level - 1]
2343 * 1000);
2344 else
2345 return SNMP_INTEGER(0);
2346
2347 case ISIS_CIRCLEVEL_MINLSPRETRANSINT:
2348 if (circuit->area)
2349 return SNMP_INTEGER(
2350 circuit->area->min_spf_interval[level - 1]);
2351 else
2352 return SNMP_INTEGER(0);
2353
2354 case ISIS_CIRCLEVEL_CSNPINTERVAL:
2355 return SNMP_INTEGER(circuit->csnp_interval[level - 1]);
2356
2357 case ISIS_CIRCLEVEL_PARTSNPINTERVAL:
2358 return SNMP_INTEGER(circuit->psnp_interval[level - 1]);
2359
2360 default:
2361 break;
2362 }
2363
2364 return NULL;
2365}
2366
2367static uint8_t *isis_snmp_find_circ_counter(struct variable *v, oid *name,
2368 size_t *length, int exact,
2369 size_t *var_len,
2370 WriteMethod **write_method)
2371{
2372 /* Index circuit-id 1-255 + level */
2373 oid *oid_idx;
2374 size_t oid_idx_len;
2375 int res;
2376 struct isis_circuit *circuit;
2377 int level;
2378 uint32_t val = 0;
2379
2380 *write_method = NULL;
2381
2382 if (*length <= v->namelen) {
2383 oid_idx = NULL;
2384 oid_idx_len = 0;
2385 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
2386 oid_idx = NULL;
2387 oid_idx_len = 0;
2388 } else {
2389 oid_idx = name + v->namelen;
2390 oid_idx_len = *length - v->namelen;
2391 }
2392 if (exact) {
2393 res = isis_snmp_circuit_level_lookup_exact(oid_idx, oid_idx_len,
2394 1, &circuit, &level);
2395
2396 if (!res || oid_idx_len != 2)
2397 return NULL;
2398
2399 } else {
2400 res = isis_snmp_circuit_level_lookup_next(oid_idx, oid_idx_len,
2401 1, &circuit, &level);
2402
2403 if (!res)
2404 return NULL;
2405
2406 /* Copy the name out */
2407 memcpy(name, v->name, v->namelen * sizeof(oid));
2408
2409 /* Append index */
2410 name[v->namelen] = circuit->snmp_id;
2411 if (circuit->circ_type == CIRCUIT_T_P2P)
2412 name[v->namelen + 1] = ISIS_SNMP_P2P_CIRCUIT;
2413 else
2414 name[v->namelen + 1] = level;
2415
2416 /* Set length */
2417 *length = v->namelen + 2;
2418 }
2419
2420 switch (v->magic) {
2421 case ISIS_CIRC_ADJCHANGES:
2422 val = circuit->adj_state_changes;
2423 break;
2424
2425 case ISIS_CIRC_NUMADJ:
2426 if (circuit->circ_type == CIRCUIT_T_P2P) {
2427 val = circuit->u.p2p.neighbor == NULL ? 0 : 1;
2428 break;
2429 }
2430
2431 if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
2432 val = 0;
2433 break;
2434 }
2435
2436 if (level == IS_LEVEL_1) {
2437 if (circuit->u.bc.adjdb[0] == NULL)
2438 val = 0;
2439 else
2440 val = listcount(circuit->u.bc.adjdb[0]);
2441 break;
2442 }
2443
2444 if (circuit->u.bc.adjdb[1] == NULL)
2445 val = 0;
2446 else
2447 val = listcount(circuit->u.bc.adjdb[1]);
2448
2449 break;
2450
2451 case ISIS_CIRC_INITFAILS:
2452 val = circuit->init_failures; /* counter never incremented */
2453 break;
2454
2455 case ISIS_CIRC_REJADJS:
2456 val = circuit->rej_adjacencies;
2457 break;
2458
2459 case ISIS_CIRC_IDFIELDLENMISMATCHES:
2460 val = circuit->id_len_mismatches;
2461 break;
2462
2463 case ISIS_CIRC_MAXAREAADDRMISMATCHES:
2464 val = circuit->max_area_addr_mismatches;
2465 break;
2466
2467 case ISIS_CIRC_AUTHTYPEFAILS:
2468 val = circuit->auth_type_failures;
2469 break;
2470
2471 case ISIS_CIRC_AUTHFAILS:
2472 val = circuit->auth_failures;
2473 break;
2474
2475 case ISIS_CIRC_LANDESISCHANGES:
2476 if (circuit->circ_type == CIRCUIT_T_P2P)
2477 val = 0;
2478 else
2479 val = circuit->desig_changes[level - 1];
2480 break;
2481
2482 default:
2483 return NULL;
2484 }
2485
2486 return SNMP_INTEGER(val);
2487}
2488
2489static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
2490 size_t *length, int exact, size_t *var_len,
2491 WriteMethod **write_method)
2492{
2493 /* Index is circuit-id: 1-255 + adj-id: 1-... */
2494 oid *oid_idx;
2495 size_t oid_idx_len;
2496 int res;
75fef2a4 2497 time_t val;
1ee746d9 2498 struct isis_adjacency *adj;
e91a589b 2499 uint32_t up_ticks;
2500 uint32_t delta_ticks;
75fef2a4 2501 time_t now_time;
1ee746d9 2502
2503 *write_method = NULL;
2504
2505 if (*length <= v->namelen) {
2506 oid_idx = NULL;
2507 oid_idx_len = 0;
2508 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
2509 oid_idx = NULL;
2510 oid_idx_len = 0;
2511 } else {
2512 oid_idx = name + v->namelen;
2513 oid_idx_len = *length - v->namelen;
2514 }
2515 if (exact) {
2516 res = isis_snmp_adj_lookup_exact(oid_idx, oid_idx_len,
2517 ISIS_SNMP_ADJ_DATA_NONE, &adj,
2518 NULL, NULL, NULL);
2519
2520 if (!res || oid_idx_len != 2)
2521 return NULL;
2522
2523 } else {
2524 res = isis_snmp_adj_lookup_next(oid_idx, oid_idx_len,
2525 ISIS_SNMP_ADJ_DATA_NONE, &adj,
2526 NULL, NULL, NULL);
2527 if (!res)
2528 return NULL;
2529
2530 /* Copy the name out */
2531 memcpy(name, v->name, v->namelen * sizeof(oid));
2532
2533 /* Append index */
2534 name[v->namelen] = adj->circuit->snmp_id;
2535 name[v->namelen + 1] = adj->snmp_idx;
2536
2537 /* Set length */
2538 *length = v->namelen + 2;
2539 }
2540
2541 switch (v->magic) {
2542 case ISIS_ISADJ_STATE:
5ff4ad8e 2543 return SNMP_INTEGER(isis_snmp_adj_state(adj->adj_state));
1ee746d9 2544
2545 case ISIS_ISADJ_3WAYSTATE:
2546 return SNMP_INTEGER(adj->threeway_state);
2547
2548 case ISIS_ISADJ_NEIGHSNPAADDRESS: {
2549 const char *snpa = (char *)snpa_print(adj->snpa);
2550 *var_len = strlen(snpa);
2551 return (uint8_t *)snpa;
2552 }
2553
2554 case ISIS_ISADJ_NEIGHSYSTYPE:
5ff4ad8e 2555 return SNMP_INTEGER(isis_snmp_adj_neightype(adj->sys_type));
1ee746d9 2556
2557 case ISIS_ISADJ_NEIGHSYSID:
2558 *var_len = sizeof(adj->sysid);
2559 return adj->sysid;
2560
2561 case ISIS_ISADJ_NBREXTENDEDCIRCID:
2562 return SNMP_INTEGER(adj->ext_circuit_id != 0 ? 1 : 0);
2563
2564 case ISIS_ISADJ_USAGE:
2565 /* It seems that no value conversion is required */
2566 return SNMP_INTEGER(adj->adj_usage);
2567
2568 case ISIS_ISADJ_HOLDTIMER:
2569 /*
2570 * It seems that we want remaining timer
2571 */
2572 if (adj->last_upd != 0) {
75fef2a4 2573 val = time(NULL);
ac716cdf 2574 if (val < (adj->last_upd + adj->hold_time))
1ee746d9 2575 return SNMP_INTEGER(adj->last_upd
2576 + adj->hold_time - val);
2577 }
2578 /* Not running or just expired */
2579 return SNMP_INTEGER(0);
2580
2581 case ISIS_ISADJ_NEIGHPRIORITY:
2582 return SNMP_INTEGER(adj->prio[adj->level - 1]);
2583
2584 case ISIS_ISADJ_LASTUPTIME:
2585 if (adj->flaps == 0)
2586 return SNMP_INTEGER(0);
2587
e91a589b 2588 up_ticks = (uint32_t)netsnmp_get_agent_uptime();
1ee746d9 2589
75fef2a4 2590 now_time = time(NULL);
1ee746d9 2591
2592 if (adj->last_flap >= now_time)
2593 return SNMP_INTEGER(up_ticks);
2594
2595 delta_ticks = (now_time - adj->last_flap) * 10;
2596
2597 if (up_ticks < delta_ticks)
2598 return SNMP_INTEGER(up_ticks);
2599
e91a589b 2600 return SNMP_INTEGER(up_ticks - delta_ticks);
1ee746d9 2601
2602 default:
2603 break;
2604 }
2605
2606 return NULL;
2607}
2608
2609static uint8_t *isis_snmp_find_isadj_area(struct variable *v, oid *name,
2610 size_t *length, int exact,
2611 size_t *var_len,
2612 WriteMethod **write_method)
2613{
2614 /* Index circuit-id: 1-255 + adj-id: 1-... */
2615 oid *oid_idx;
2616 size_t oid_idx_len;
2617 int res;
2618 struct isis_adjacency *adj;
2619 oid data_idx;
2620 uint8_t *data;
2621 size_t data_len;
2622
2623 *write_method = NULL;
2624
2625 if (*length <= v->namelen) {
2626 oid_idx = NULL;
2627 oid_idx_len = 0;
2628 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
2629 oid_idx = NULL;
2630 oid_idx_len = 0;
2631 } else {
2632 oid_idx = name + v->namelen;
2633 oid_idx_len = *length - v->namelen;
2634 }
2635 if (exact) {
2636 res = isis_snmp_adj_lookup_exact(oid_idx, oid_idx_len,
2637 ISIS_SNMP_ADJ_DATA_AREA_ADDR,
2638 &adj, NULL, &data, &data_len);
2639
2640 if (!res || oid_idx_len != 3)
2641 return NULL;
2642
2643 } else {
2644 res = isis_snmp_adj_lookup_next(
2645 oid_idx, oid_idx_len, ISIS_SNMP_ADJ_DATA_AREA_ADDR,
2646 &adj, &data_idx, &data, &data_len);
2647 if (!res)
2648 return NULL;
2649
2650 /* Copy the name out */
2651 memcpy(name, v->name, v->namelen * sizeof(oid));
2652
2653 /* Append index */
2654 name[v->namelen] = adj->circuit->snmp_id;
2655 name[v->namelen + 1] = adj->snmp_idx;
2656 name[v->namelen + 2] = data_idx;
2657
2658 /* Set length */
2659 *length = v->namelen + 3;
2660 }
2661
2662 switch (v->magic) {
2663 case ISIS_ISADJAREA_ADDRESS:
2664 *var_len = data_len;
2665 return data;
2666
2667 default:
2668 break;
2669 }
2670
2671 return NULL;
2672}
2673
2674static uint8_t *isis_snmp_find_isadj_ipaddr(struct variable *v, oid *name,
2675 size_t *length, int exact,
2676 size_t *var_len,
2677 WriteMethod **write_method)
2678{
2679 /* Index circuit-id 1-255 + adj-id 1-... */
2680 oid *oid_idx;
2681 size_t oid_idx_len;
2682 int res;
2683 struct isis_adjacency *adj;
2684 oid data_idx;
2685 uint8_t *data;
2686 size_t data_len;
2687
2688 *write_method = NULL;
2689
2690 if (*length <= v->namelen) {
2691 oid_idx = NULL;
2692 oid_idx_len = 0;
2693 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
2694 oid_idx = NULL;
2695 oid_idx_len = 0;
2696 } else {
2697 oid_idx = name + v->namelen;
2698 oid_idx_len = *length - v->namelen;
2699 }
2700 if (exact) {
2701 res = isis_snmp_adj_lookup_exact(oid_idx, oid_idx_len,
2702 ISIS_SNMP_ADJ_DATA_IP_ADDR,
2703 &adj, NULL, &data, &data_len);
2704
2705 if (!res || oid_idx_len != 3)
2706 return NULL;
2707 } else {
2708 res = isis_snmp_adj_lookup_next(
2709 oid_idx, oid_idx_len, ISIS_SNMP_ADJ_DATA_IP_ADDR, &adj,
2710 &data_idx, &data, &data_len);
2711 if (!res)
2712 return NULL;
2713
2714 /* Copy the name out */
2715 memcpy(name, v->name, v->namelen * sizeof(oid));
2716
2717 /* Append index */
2718 name[v->namelen] = adj->circuit->snmp_id;
2719 name[v->namelen + 1] = adj->snmp_idx;
2720 name[v->namelen + 2] = data_idx;
2721
2722 /* Set length */
2723 *length = v->namelen + 3;
2724 }
2725
2726 switch (v->magic) {
2727 case ISIS_ISADJIPADDR_TYPE:
2728 if (data_len == 4)
2729 return SNMP_INTEGER(ISIS_SNMP_INET_TYPE_V4);
2730
2731 return SNMP_INTEGER(ISIS_SNMP_INET_TYPE_V6);
2732
2733 case ISIS_ISADJIPADDR_ADDRESS:
2734 *var_len = data_len;
2735 return data;
2736
2737 default:
2738 break;
2739 }
2740
2741 return NULL;
2742}
2743
2744static uint8_t *isis_snmp_find_isadj_prot_supp(struct variable *v, oid *name,
2745 size_t *length, int exact,
2746 size_t *var_len,
2747 WriteMethod **write_method)
2748{
2749 /* Index circuit-id 1-255 + adj-id 1-... */
2750 oid *oid_idx;
2751 size_t oid_idx_len;
2752 int res;
2753 struct isis_adjacency *adj;
2754 oid data_idx;
2755 uint8_t *data;
2756 size_t data_len;
2757
2758 *write_method = NULL;
2759
2760 if (*length <= v->namelen) {
2761 oid_idx = NULL;
2762 oid_idx_len = 0;
2763 } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
2764 oid_idx = NULL;
2765 oid_idx_len = 0;
2766 } else {
2767 oid_idx = name + v->namelen;
2768 oid_idx_len = *length - v->namelen;
2769 }
2770 if (exact) {
2771 res = isis_snmp_adj_lookup_exact(oid_idx, oid_idx_len,
2772 ISIS_SNMP_ADJ_DATA_PROTO, &adj,
2773 NULL, &data, &data_len);
2774
2775 if (!res || oid_idx_len != 3)
2776 return NULL;
2777
2778 } else {
2779 res = isis_snmp_adj_lookup_next(oid_idx, oid_idx_len,
2780 ISIS_SNMP_ADJ_DATA_PROTO, &adj,
2781 &data_idx, &data, &data_len);
2782 if (!res)
2783 return NULL;
2784
2785 /* Copy the name out */
2786 memcpy(name, v->name, v->namelen * sizeof(oid));
2787
2788 /* Append index */
2789 name[v->namelen] = adj->circuit->snmp_id;
2790 name[v->namelen + 1] = adj->snmp_idx;
2791 name[v->namelen + 2] = data_idx;
2792
2793 /* Set length */
2794 *length = v->namelen + 3;
2795 }
2796
2797 switch (v->magic) {
2798 case ISIS_ISADJPROTSUPP_PROTOCOL:
2799 return SNMP_INTEGER(*data);
2800
2801 default:
2802 break;
2803 }
2804
2805 return NULL;
2806}
2807
2808
2809/* Register ISIS-MIB. */
2810static int isis_snmp_init(struct thread_master *tm)
2811{
2812 struct isis_func_to_prefix *h2f = isis_func_to_prefix_arr;
2813 struct variable *v;
2814
2815 for (size_t off = 0; off < isis_var_count; off++) {
2816 v = &isis_var_arr[off];
2817
2818 if (v->findVar != h2f->ihtp_func) {
2819 /* Next table */
2820 h2f++;
2821 assert(h2f < (isis_func_to_prefix_arr
2822 + isis_func_to_prefix_count));
2823 assert(v->findVar == h2f->ihtp_func);
2824 }
2825
2826 v->namelen = h2f->ihtp_pref_len + 1;
2827 memcpy(v->name, h2f->ihtp_pref_oid,
2828 h2f->ihtp_pref_len * sizeof(oid));
2829 v->name[h2f->ihtp_pref_len] = v->magic;
2830 }
2831
2832
2833 smux_init(tm);
2834 REGISTER_MIB("mibII/isis", isis_var_arr, variable, isis_oid);
2835 return 0;
2836}
2837
2838/*
2839 * ISIS notification functions: we have one function per notification
2840 */
2841static int isis_snmp_trap_throttle(oid trap_id)
2842{
2843 time_t time_now;
2844 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
2845
2846 if (isis == NULL || !isis->snmp_notifications || !smux_enabled())
2847 return 0;
2848
75fef2a4 2849 time_now = time(NULL);
1ee746d9 2850
2851 if ((isis_snmp_trap_timestamp[trap_id] + 5) > time_now)
2852 /* Throttle trap rate at 1 in 5 secs */
2853 return 0;
2854
2855 isis_snmp_trap_timestamp[trap_id] = time_now;
2856 return 1;
2857}
2858
2859static int isis_snmp_db_overload_update(const struct isis_area *area)
2860{
2861 netsnmp_variable_list *notification_vars;
2862 long val;
2863 uint32_t off;
2864
2865 if (!isis_snmp_trap_throttle(ISIS_TRAP_DB_OVERLOAD))
2866 return 0;
2867
2868 notification_vars = NULL;
2869
2870 /* Put in trap value */
2871 snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
2872 ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
2873 (uint8_t *)&isis_snmp_trap_val_db_overload,
2874 sizeof(isis_snmp_trap_val_db_overload));
2875
2876 /* Prepare data */
2877 val = area->is_type;
2878
2879 snmp_varlist_add_variable(
2880 &notification_vars, isis_snmp_trap_data_var_sys_level_index,
2881 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
2882 (uint8_t *)&val, sizeof(val));
2883
2884 /* Patch sys_level_state with proper index */
2885 off = ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state) - 1;
2886 isis_snmp_trap_data_var_sys_level_state[off] = val;
2887
2888 /* Prepare data */
2889 if (area->overload_bit)
2890 val = ISIS_SNMP_LEVEL_STATE_OVERLOADED;
2891 else
2892 val = ISIS_SNMP_LEVEL_STATE_ON;
2893
2894 snmp_varlist_add_variable(
2895 &notification_vars, isis_snmp_trap_data_var_sys_level_state,
2896 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state), INTEGER,
2897 (uint8_t *)&val, sizeof(val));
2898
2899 send_v2trap(notification_vars);
2900 snmp_free_varbind(notification_vars);
2901 smux_events_update();
2902 return 0;
2903}
2904
2905static int isis_snmp_lsp_exceed_max_update(const struct isis_area *area,
2906 const uint8_t *lsp_id)
2907{
2908 netsnmp_variable_list *notification_vars;
2909 long val;
2910
2911 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_EXCEED_MAX))
2912 return 0;
2913
2914 notification_vars = NULL;
2915
2916 /* Put in trap value */
2917 snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
2918 ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
2919 (uint8_t *)&isis_snmp_trap_val_lsp_exceed_max,
2920 sizeof(isis_snmp_trap_val_lsp_exceed_max));
2921
2922 /* Prepare data */
2923 val = area->is_type;
2924
2925 snmp_varlist_add_variable(
2926 &notification_vars, isis_snmp_trap_data_var_sys_level_index,
2927 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
2928 (uint8_t *)&val, sizeof(val));
2929
2930 snmp_varlist_add_variable(
2931 &notification_vars, isis_snmp_trap_data_var_pdu_lsp_id,
2932 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
2933 ISIS_SYS_ID_LEN + 2);
2934
2935 send_v2trap(notification_vars);
2936 snmp_free_varbind(notification_vars);
2937 smux_events_update();
2938 return 0;
2939}
2940
2941
2942/*
2943 * A common function to handle popular combination of trap objects
2944 * isisNotificationSysLevelIndex,
2945 * optional-object-a
2946 * isisNotificationCircIfIndex,
2947 * optional-object-b
2948 */
2949static void isis_snmp_update_worker_a(const struct isis_circuit *circuit,
2950 oid trap_id, const oid *oid_a,
2951 size_t oid_a_len, uint8_t type_a,
2952 const void *data_a, size_t data_a_len,
2953 const oid *oid_b, size_t oid_b_len,
2954 uint8_t type_b, const void *data_b,
2955 size_t data_b_len)
2956{
2957 netsnmp_variable_list *notification_vars = NULL;
2958 oid var_name[MAX_OID_LEN];
2959 size_t var_count;
2960 long val;
2961
2962 /* Sanity */
2963 if (trap_id != ISIS_TRAP_ID_LEN_MISMATCH
2964 && trap_id != ISIS_TRAP_MAX_AREA_ADDR_MISMATCH
2965 && trap_id != ISIS_TRAP_OWN_LSP_PURGE
2966 && trap_id != ISIS_TRAP_SEQNO_SKIPPED
2967 && trap_id != ISIS_TRAP_AUTHEN_TYPE_FAILURE
2968 && trap_id != ISIS_TRAP_AUTHEN_FAILURE
2969 && trap_id != ISIS_TRAP_REJ_ADJACENCY)
2970 return;
2971
2972 /* Put in trap value */
2973 memcpy(var_name, isis_snmp_notifications,
2974 sizeof(isis_snmp_notifications));
2975 var_count = ARRAY_SIZE(isis_snmp_notifications);
2976 var_name[var_count++] = trap_id;
2977
2978 /* Put in trap value */
2979 snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
2980 ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
2981 (uint8_t *)var_name, var_count * sizeof(oid));
2982
2983 val = circuit->is_type;
2984 snmp_varlist_add_variable(
2985 &notification_vars, isis_snmp_trap_data_var_sys_level_index,
2986 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
2987 (uint8_t *)&val, sizeof(val));
2988
2989 if (oid_a_len != 0) {
2990 if (oid_a == NULL || data_a == NULL || data_a_len == 0)
2991 return;
2992
2993 snmp_varlist_add_variable(&notification_vars, oid_a, oid_a_len,
2994 type_a, (uint8_t *)data_a,
2995 data_a_len);
2996 }
2997
2998 if (circuit->interface == NULL)
2999 val = 0;
3000 else
3001 val = circuit->interface->ifindex;
3002
3003 snmp_varlist_add_variable(
3004 &notification_vars, isis_snmp_trap_data_var_circ_if_index,
3005 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
3006 (uint8_t *)&val, sizeof(val));
3007
3008
3009 if (oid_b_len != 0) {
3010 if (oid_b == NULL || data_b == NULL || data_b_len == 0)
3011 return;
3012
3013 snmp_varlist_add_variable(&notification_vars, oid_b, oid_b_len,
3014 type_b, (uint8_t *)data_b,
3015 data_b_len);
3016 }
3017
3018 send_v2trap(notification_vars);
3019 snmp_free_varbind(notification_vars);
3020 smux_events_update();
3021}
3022
3023/*
3024 * A common function to handle popular combination of trap objects
3025 * isisNotificationSysLevelIndex,
3026 * isisNotificationCircIfIndex,
3027 * optional-var-a
3028 * optional-var-b
3029 *
3030 * Note: the only difference with worker_a is order of circ-if-index vs
3031 * optional-var-a
3032 */
3033static void isis_snmp_update_worker_b(const struct isis_circuit *circuit,
3034 oid trap_id, const oid *oid_a,
3035 size_t oid_a_len, uint8_t type_a,
3036 const void *data_a, size_t data_a_len,
3037 const oid *oid_b, size_t oid_b_len,
3038 uint8_t type_b, const void *data_b,
3039 size_t data_b_len)
3040{
3041 netsnmp_variable_list *notification_vars = NULL;
3042 oid var_name[MAX_OID_LEN];
3043 size_t var_count;
3044 long val;
3045
3046 /* Sanity */
3047 if (trap_id != ISIS_TRAP_VERSION_SKEW
3048 && trap_id != ISIS_TRAP_LSP_TOO_LARGE
3049 && trap_id != ISIS_TRAP_ADJ_STATE_CHANGE)
3050 return;
3051
3052 /* Put in trap value */
3053 memcpy(var_name, isis_snmp_notifications,
3054 sizeof(isis_snmp_notifications));
3055 var_count = ARRAY_SIZE(isis_snmp_notifications);
3056 var_name[var_count++] = trap_id;
3057
3058 /* Put in trap value */
3059 snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
3060 ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
3061 (uint8_t *)var_name, var_count * sizeof(oid));
3062
3063 val = circuit->is_type;
3064 snmp_varlist_add_variable(
3065 &notification_vars, isis_snmp_trap_data_var_sys_level_index,
3066 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
3067 (uint8_t *)&val, sizeof(val));
3068
3069 if (circuit->interface == NULL)
3070 val = 0;
3071 else
3072 val = circuit->interface->ifindex;
3073
3074 snmp_varlist_add_variable(
3075 &notification_vars, isis_snmp_trap_data_var_circ_if_index,
3076 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
3077 (uint8_t *)&val, sizeof(val));
3078
3079
3080 if (oid_a_len != 0) {
3081 if (oid_a == NULL || data_a == NULL || data_a_len == 0)
3082 return;
3083
3084 snmp_varlist_add_variable(&notification_vars, oid_a, oid_a_len,
3085 type_a, (uint8_t *)data_a,
3086 data_a_len);
3087 }
3088
3089 if (oid_b_len != 0) {
3090 if (oid_b == NULL || data_b == NULL || data_b_len == 0)
3091 return;
3092
3093 snmp_varlist_add_variable(&notification_vars, oid_b, oid_b_len,
3094 type_b, (uint8_t *)data_b,
3095 data_b_len);
3096 }
3097
3098 send_v2trap(notification_vars);
3099 snmp_free_varbind(notification_vars);
3100 smux_events_update();
3101}
3102
3103
3104static int isis_snmp_id_len_mismatch_update(const struct isis_circuit *circuit,
3105 uint8_t rcv_id, const char *raw_pdu,
3106 size_t raw_pdu_len)
3107{
3108 long val;
3109
3110 if (!isis_snmp_trap_throttle(ISIS_TRAP_ID_LEN_MISMATCH))
3111 return 0;
3112
3113 val = rcv_id;
3114
3115 if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
3116 raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
3117
3118 isis_snmp_update_worker_a(
3119 circuit, ISIS_TRAP_ID_LEN_MISMATCH,
3120 isis_snmp_trap_data_var_pdu_field_len,
3121 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_field_len), UNSIGNED32,
3122 &val, sizeof(val), isis_snmp_trap_data_var_pdu_fragment,
3123 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
3124 raw_pdu, raw_pdu_len);
3125 return 0;
3126}
3127
3128static int
3129isis_snmp_max_area_addr_mismatch_update(const struct isis_circuit *circuit,
3130 uint8_t max_addrs, const char *raw_pdu,
3131 size_t raw_pdu_len)
3132{
3133 long val;
3134
3135 if (!isis_snmp_trap_throttle(ISIS_TRAP_MAX_AREA_ADDR_MISMATCH))
3136 return 0;
3137
3138 val = max_addrs;
3139
3140 if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
3141 raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
3142
3143 isis_snmp_update_worker_a(
3144 circuit, ISIS_TRAP_MAX_AREA_ADDR_MISMATCH,
3145 isis_snmp_trap_data_var_pdu_max_area_addr,
3146 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_max_area_addr),
3147 UNSIGNED32, &val, sizeof(val),
3148 isis_snmp_trap_data_var_pdu_fragment,
3149 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
3150 raw_pdu, raw_pdu_len);
3151 return 0;
3152}
3153
3154static int isis_snmp_own_lsp_purge_update(const struct isis_circuit *circuit,
3155 const uint8_t *lsp_id)
3156{
3157 if (!isis_snmp_trap_throttle(ISIS_TRAP_OWN_LSP_PURGE))
3158 return 0;
3159
3160 isis_snmp_update_worker_a(
3161 circuit, ISIS_TRAP_OWN_LSP_PURGE, NULL, 0, STRING, NULL, 0,
3162 isis_snmp_trap_data_var_pdu_lsp_id,
3163 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
3164 ISIS_SYS_ID_LEN + 2);
3165 return 0;
3166}
3167
3168static int isis_snmp_seqno_skipped_update(const struct isis_circuit *circuit,
3169 const uint8_t *lsp_id)
3170{
3171 if (!isis_snmp_trap_throttle(ISIS_TRAP_SEQNO_SKIPPED))
3172 return 0;
3173
3174 isis_snmp_update_worker_a(
3175 circuit, ISIS_TRAP_SEQNO_SKIPPED, NULL, 0, STRING, NULL, 0,
3176 isis_snmp_trap_data_var_pdu_lsp_id,
3177 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
3178 ISIS_SYS_ID_LEN + 2);
3179 return 0;
3180}
3181
3182static int
3183isis_snmp_authentication_type_failure_update(const struct isis_circuit *circuit,
3184 const char *raw_pdu,
3185 size_t raw_pdu_len)
3186{
3187 if (!isis_snmp_trap_throttle(ISIS_TRAP_AUTHEN_TYPE_FAILURE))
3188 return 0;
3189
3190 if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
3191 raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
3192
3193 isis_snmp_update_worker_a(
3194 circuit, ISIS_TRAP_AUTHEN_TYPE_FAILURE, NULL, 0, STRING, NULL,
3195 0, isis_snmp_trap_data_var_pdu_fragment,
3196 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
3197 raw_pdu, raw_pdu_len);
3198 return 0;
3199}
3200
3201static int
3202isis_snmp_authentication_failure_update(const struct isis_circuit *circuit,
3203 char const *raw_pdu, size_t raw_pdu_len)
3204{
3205 if (!isis_snmp_trap_throttle(ISIS_TRAP_AUTHEN_FAILURE))
3206 return 0;
3207
3208 if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
3209 raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
3210
3211 isis_snmp_update_worker_a(
3212 circuit, ISIS_TRAP_AUTHEN_FAILURE, NULL, 0, STRING, NULL, 0,
3213 isis_snmp_trap_data_var_pdu_fragment,
3214 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
3215 raw_pdu, raw_pdu_len);
3216 return 0;
3217}
3218
3219static int isis_snmp_version_skew_update(const struct isis_circuit *circuit,
3220 uint8_t version, const char *raw_pdu,
3221 size_t raw_pdu_len)
3222{
3223 long val;
3224
3225 if (!isis_snmp_trap_throttle(ISIS_TRAP_VERSION_SKEW))
3226 return 0;
3227
3228 val = version;
3229
3230 if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
3231 raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
3232
3233 isis_snmp_update_worker_b(
3234 circuit, ISIS_TRAP_VERSION_SKEW,
3235 isis_snmp_trap_data_var_pdu_proto_ver,
3236 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_proto_ver), UNSIGNED32,
3237 &val, sizeof(val), isis_snmp_trap_data_var_pdu_fragment,
3238 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
3239 raw_pdu, raw_pdu_len);
3240 return 0;
3241}
3242
3243static int isis_snmp_area_mismatch_update(const struct isis_circuit *circuit,
3244 const char *raw_pdu,
3245 size_t raw_pdu_len)
3246{
3247 /*
3248 * This is a special case because
3249 * it does not include isisNotificationSysLevelIndex
3250 */
3251 netsnmp_variable_list *notification_vars;
3252 long val;
3253
3254 if (!isis_snmp_trap_throttle(ISIS_TRAP_AREA_MISMATCH))
3255 return 0;
3256
3257 notification_vars = NULL;
3258
3259 /* Put in trap value */
3260 snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
3261 ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
3262 (uint8_t *)&isis_snmp_trap_val_area_mismatch,
3263 sizeof(isis_snmp_trap_val_area_mismatch));
3264
3265
3266 if (circuit->interface == NULL)
3267 val = 0;
3268 else
3269 val = circuit->interface->ifindex;
3270
3271 snmp_varlist_add_variable(
3272 &notification_vars, isis_snmp_trap_data_var_circ_if_index,
3273 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
3274 (uint8_t *)&val, sizeof(val));
3275
3276
3277 if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
3278 raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
3279
3280 snmp_varlist_add_variable(
3281 &notification_vars, isis_snmp_trap_data_var_pdu_fragment,
3282 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
3283 raw_pdu, raw_pdu_len);
3284
3285 send_v2trap(notification_vars);
3286 snmp_free_varbind(notification_vars);
3287 smux_events_update();
3288
3289 return 0;
3290}
3291
3292static int isis_snmp_reject_adjacency_update(const struct isis_circuit *circuit,
3293 const char *raw_pdu,
3294 size_t raw_pdu_len)
3295{
3296 if (!isis_snmp_trap_throttle(ISIS_TRAP_REJ_ADJACENCY))
3297 return 0;
3298
3299 if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
3300 raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
3301
3302 isis_snmp_update_worker_a(
3303 circuit, ISIS_TRAP_REJ_ADJACENCY, NULL, 0, STRING, NULL, 0,
3304 isis_snmp_trap_data_var_pdu_fragment,
3305 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
3306 raw_pdu, raw_pdu_len);
3307 return 0;
3308}
3309
3310static int isis_snmp_lsp_too_large_update(const struct isis_circuit *circuit,
3311 uint32_t pdu_size,
3312 const uint8_t *lsp_id)
3313{
3314 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_TOO_LARGE))
3315 return 0;
3316
3317 isis_snmp_update_worker_b(
3318 circuit, ISIS_TRAP_LSP_TOO_LARGE,
3319 isis_snmp_trap_data_var_pdu_lsp_size,
3320 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_size), UNSIGNED32,
3321 &pdu_size, sizeof(pdu_size), isis_snmp_trap_data_var_pdu_lsp_id,
3322 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
3323 ISIS_SYS_ID_LEN + 2);
3324 return 0;
3325}
3326
3327
3328static int isis_snmp_adj_state_change_update(const struct isis_adjacency *adj)
3329{
3330 uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
3331 long val;
3332 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
3333
3334 if (isis == NULL || !isis->snmp_notifications || !smux_enabled())
3335 return 0;
3336
3337 /* Prepare data */
3338 memcpy(lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
3339 lsp_id[ISIS_SYS_ID_LEN] = 0;
3340 lsp_id[ISIS_SYS_ID_LEN + 1] = 0;
3341
5ff4ad8e 3342 val = isis_snmp_adj_state(adj->adj_state);
1ee746d9 3343
3344 isis_snmp_update_worker_b(
3345 adj->circuit, ISIS_TRAP_ADJ_STATE_CHANGE,
3346 isis_snmp_trap_data_var_pdu_lsp_id,
3347 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
3348 ISIS_SYS_ID_LEN + 2, isis_snmp_trap_data_var_adj_state,
3349 ARRAY_SIZE(isis_snmp_trap_data_var_adj_state), INTEGER, &val,
3350 sizeof(val));
3351 return 0;
3352}
3353
3354static int isis_snmp_lsp_error_update(const struct isis_circuit *circuit,
3355 const uint8_t *lsp_id,
3356 char const *raw_pdu, size_t raw_pdu_len)
3357{
3358 /*
3359 * This is a special case because
3360 * it have more variables
3361 */
3362 netsnmp_variable_list *notification_vars;
3363 long val;
3364
3365 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_ERROR))
3366 return 0;
3367
3368 notification_vars = NULL;
3369
3370 /* Put in trap value */
3371 snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
3372 ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
3373 (uint8_t *)&isis_snmp_trap_val_lsp_error,
3374 sizeof(isis_snmp_trap_val_lsp_error));
3375
3376 /* Prepare data */
3377 val = circuit->is_type;
3378
3379 snmp_varlist_add_variable(
3380 &notification_vars, isis_snmp_trap_data_var_sys_level_index,
3381 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
3382 (uint8_t *)&val, sizeof(val));
3383
3384
3385 snmp_varlist_add_variable(
3386 &notification_vars, isis_snmp_trap_data_var_pdu_lsp_id,
3387 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
3388 ISIS_SYS_ID_LEN + 2);
3389
3390 /* Prepare data */
3391 if (circuit->interface == NULL)
3392 val = 0;
3393 else
3394 val = circuit->interface->ifindex;
3395
3396 snmp_varlist_add_variable(
3397 &notification_vars, isis_snmp_trap_data_var_circ_if_index,
3398 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
3399 (uint8_t *)&val, sizeof(val));
3400
3401 /* Prepare data */
3402 if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
3403 raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
3404
3405 snmp_varlist_add_variable(
3406 &notification_vars, isis_snmp_trap_data_var_pdu_fragment,
3407 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
3408 raw_pdu, raw_pdu_len);
3409
3410 /* Prepare data */
3411 val = 0;
3412
3413 snmp_varlist_add_variable(
3414 &notification_vars, isis_snmp_trap_data_var_error_offset,
3415 ARRAY_SIZE(isis_snmp_trap_data_var_error_offset), UNSIGNED32,
3416 (uint8_t *)&val, sizeof(val));
3417
3418 /* Prepare data */
3419 val = 0;
3420
3421 snmp_varlist_add_variable(
3422 &notification_vars, isis_snmp_trap_data_var_error_tlv_type,
3423 ARRAY_SIZE(isis_snmp_trap_data_var_error_tlv_type), UNSIGNED32,
3424 (uint8_t *)&val, sizeof(val));
3425
3426 send_v2trap(notification_vars);
3427 snmp_free_varbind(notification_vars);
3428 smux_events_update();
3429 return 0;
3430}
3431
3432
3433static int isis_snmp_module_init(void)
3434{
3435 hook_register(isis_hook_db_overload, isis_snmp_db_overload_update);
3436 hook_register(isis_hook_lsp_exceed_max,
3437 isis_snmp_lsp_exceed_max_update);
3438 hook_register(isis_hook_id_len_mismatch,
3439 isis_snmp_id_len_mismatch_update);
3440 hook_register(isis_hook_max_area_addr_mismatch,
3441 isis_snmp_max_area_addr_mismatch_update);
3442 hook_register(isis_hook_own_lsp_purge, isis_snmp_own_lsp_purge_update);
3443 hook_register(isis_hook_seqno_skipped, isis_snmp_seqno_skipped_update);
3444 hook_register(isis_hook_authentication_type_failure,
3445 isis_snmp_authentication_type_failure_update);
3446 hook_register(isis_hook_authentication_failure,
3447 isis_snmp_authentication_failure_update);
3448 hook_register(isis_hook_version_skew, isis_snmp_version_skew_update);
3449 hook_register(isis_hook_area_mismatch, isis_snmp_area_mismatch_update);
3450 hook_register(isis_hook_reject_adjacency,
3451 isis_snmp_reject_adjacency_update);
3452 hook_register(isis_hook_lsp_too_large, isis_snmp_lsp_too_large_update);
3453 hook_register(isis_hook_adj_state_change,
3454 isis_snmp_adj_state_change_update);
3455 hook_register(isis_hook_lsp_error, isis_snmp_lsp_error_update);
e2b5b7d6
IR
3456 hook_register(isis_circuit_new_hook, isis_circuit_snmp_id_gen);
3457 hook_register(isis_circuit_del_hook, isis_circuit_snmp_id_free);
1ee746d9 3458
3459 hook_register(frr_late_init, isis_snmp_init);
3460 return 0;
3461}
3462
80413c20
DL
3463FRR_MODULE_SETUP(
3464 .name = "isis_snmp",
3465 .version = FRR_VERSION,
3466 .description = "isis AgentX SNMP module",
3467 .init = isis_snmp_module_init,
3468);