1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2020 Volta Networks, Inc.
9 * This is minimal read-only implementations providing isisReadOnlyCompliance
14 #include <net-snmp/net-snmp-config.h>
15 #include <net-snmp/net-snmp-includes.h>
26 #include "lib/version.h"
27 #include "lib/zclient.h"
29 #include "isisd/isis_constants.h"
30 #include "isisd/isis_common.h"
31 #include "isisd/isis_flags.h"
32 #include "isisd/isis_circuit.h"
33 #include "isisd/isis_lsp.h"
34 #include "isisd/isis_pdu.h"
35 #include "isisd/isis_network.h"
36 #include "isisd/isis_misc.h"
37 #include "isisd/isis_constants.h"
38 #include "isisd/isis_adjacency.h"
39 #include "isisd/isis_dynhn.h"
40 #include "isisd/isis_te.h"
41 #include "isisd/isis_dr.h"
42 #include "isisd/isis_nb.h"
43 #include "isisd/isisd.h"
46 #define ISIS_MIB 1, 3, 6, 1, 2, 1, 138
48 #define ISIS_OBJECTS 1
49 #define ISIS_SYSTEM 1, 1
50 #define ISIS_SYSLEVEL 1, 2
51 #define ISIS_CIRC 1, 3
52 #define ISIS_CIRC_LEVEL_VALUES 1, 4
53 #define ISIS_COUNTERS 1, 5
54 #define ISIS_ISADJ 1, 6
56 /************************ isisSystemGroup ************************/
59 #define ISIS_SYS_OBJECT 1, 1, 1
60 #define ISIS_SYS_VERSION 1
61 #define ISIS_SYS_LEVELTYPE 2
63 #define ISIS_SYS_MAXPATHSPLITS 4
64 #define ISIS_SYS_MAXLSPGENINT 5
65 #define ISIS_SYS_POLLESHELLORATE 6
66 #define ISIS_SYS_WAITTIME 7
67 #define ISIS_SYS_ADMINSTATE 8
68 #define ISIS_SYS_L2TOL1LEAKING 9
69 #define ISIS_SYS_MAXAGE 10
70 #define ISIS_SYS_RECEIVELSPBUFFERSIZE 11
71 #define ISIS_SYS_PROTSUPPORTED 12
72 #define ISIS_SYS_NOTIFICATIONENABLE 13
74 /* isisManAreaAddrEntry */
75 #define ISIS_MANAREA_ADDRENTRY 1, 1, 2, 1
76 #define ISIS_MANAREA_ADDREXISTSTATE 2
78 /* isisAreaAddrEntry */
79 #define ISIS_AREA_ADDRENTRY 1, 1, 3, 1
80 #define ISIS_AREA_ADDR 1
82 /* isisSummAddrEntry */
83 #define ISIS_SUMM_ADDRENTRY 1, 1, 4, 1
84 #define ISIS_SUMM_ADDREXISTSTATE 4
85 #define ISIS_SUMM_ADDRMETRIC 5
86 #define ISIS_SUMM_ADDRFULLMETRIC 6
88 /* isisRedistributeAddrEntry */
89 #define ISIS_REDISTRIBUTE_ADDRENTRY 1, 1, 5, 1
90 #define ISIS_REDISTRIBUTE_ADDREXISTSTATE 3
93 #define ISIS_ROUTER_ENTRY 1, 1, 6, 1
94 #define ISIS_ROUTER_HOSTNAME 3
95 #define ISIS_ROUTER_ID 4
97 /* isisSysLevelTable */
98 #define ISIS_SYSLEVEL_ENTRY 1, 2, 1, 1
99 #define ISIS_SYSLEVEL_ORIGLSPBUFFSIZE 2
100 #define ISIS_SYSLEVEL_MINLSPGENINT 3
101 #define ISIS_SYSLEVEL_STATE 4
102 #define ISIS_SYSLEVEL_SETOVERLOAD 5
103 #define ISIS_SYSLEVEL_SETOVERLOADUNTIL 6
104 #define ISIS_SYSLEVEL_METRICSTYLE 7
105 #define ISIS_SYSLEVEL_SPFCONSIDERS 8
106 #define ISIS_SYSLEVEL_TEENABLED 9
109 /* isisSystemCounterEntry */
110 #define ISIS_SYSTEM_COUNTER_ENTRY 1, 5, 1, 1
111 #define ISIS_SYSSTAT_CORRLSPS 2
112 #define ISIS_SYSSTAT_AUTHTYPEFAILS 3
113 #define ISIS_SYSSTAT_AUTHFAILS 4
114 #define ISIS_SYSSTAT_LSPDBASEOLOADS 5
115 #define ISIS_SYSSTAT_MANADDRDROPFROMAREAS 6
116 #define ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS 7
117 #define ISIS_SYSSTAT_SEQNUMSKIPS 8
118 #define ISIS_SYSSTAT_OWNLSPPURGES 9
119 #define ISIS_SYSSTAT_IDFIELDLENMISMATCHES 10
120 #define ISIS_SYSSTAT_PARTCHANGES 11
121 #define ISIS_SYSSTAT_SPFRUNS 12
122 #define ISIS_SYSSTAT_LSPERRORS 13
125 /************************ isisCircuitGroup ************************/
127 /* Scalar directly under isisCirc */
128 #define ISIS_NEXTCIRC_INDEX 1
131 #define ISIS_CIRC_ENTRY 1, 3, 2, 1
132 #define ISIS_CIRC_IFINDEX 2
133 #define ISIS_CIRC_ADMINSTATE 3
134 #define ISIS_CIRC_EXISTSTATE 4
135 #define ISIS_CIRC_TYPE 5
136 #define ISIS_CIRC_EXTDOMAIN 6
137 #define ISIS_CIRC_LEVELTYPE 7
138 #define ISIS_CIRC_PASSIVECIRCUIT 8
139 #define ISIS_CIRC_MESHGROUPENABLED 9
140 #define ISIS_CIRC_MESHGROUP 10
141 #define ISIS_CIRC_SMALLHELLOS 11
142 #define ISIS_CIRC_LASTUPTIME 12
143 #define ISIS_CIRC_3WAYENABLED 13
144 #define ISIS_CIRC_EXTENDEDCIRCID 14
146 /* isisCircLevelEntry */
147 #define ISIS_CIRCLEVEL_ENTRY 1, 4, 1, 1
148 #define ISIS_CIRCLEVEL_METRIC 2
149 #define ISIS_CIRCLEVEL_WIDEMETRIC 3
150 #define ISIS_CIRCLEVEL_ISPRIORITY 4
151 #define ISIS_CIRCLEVEL_IDOCTET 5
152 #define ISIS_CIRCLEVEL_ID 6
153 #define ISIS_CIRCLEVEL_DESIS 7
154 #define ISIS_CIRCLEVEL_HELLOMULTIPLIER 8
155 #define ISIS_CIRCLEVEL_HELLOTIMER 9
156 #define ISIS_CIRCLEVEL_DRHELLOTIMER 10
157 #define ISIS_CIRCLEVEL_LSPTHROTTLE 11
158 #define ISIS_CIRCLEVEL_MINLSPRETRANSINT 12
159 #define ISIS_CIRCLEVEL_CSNPINTERVAL 13
160 #define ISIS_CIRCLEVEL_PARTSNPINTERVAL 14
162 /* isisCircuitCounterEntry */
163 #define ISIS_CIRC_COUNTER_ENTRY 1, 5, 2, 1
164 #define ISIS_CIRC_ADJCHANGES 2
165 #define ISIS_CIRC_NUMADJ 3
166 #define ISIS_CIRC_INITFAILS 4
167 #define ISIS_CIRC_REJADJS 5
168 #define ISIS_CIRC_IDFIELDLENMISMATCHES 6
169 #define ISIS_CIRC_MAXAREAADDRMISMATCHES 7
170 #define ISIS_CIRC_AUTHTYPEFAILS 8
171 #define ISIS_CIRC_AUTHFAILS 9
172 #define ISIS_CIRC_LANDESISCHANGES 10
175 /************************ isisISAdjGroup ************************/
178 #define ISIS_ISADJ_ENTRY 1, 6, 1, 1
179 #define ISIS_ISADJ_STATE 2
180 #define ISIS_ISADJ_3WAYSTATE 3
181 #define ISIS_ISADJ_NEIGHSNPAADDRESS 4
182 #define ISIS_ISADJ_NEIGHSYSTYPE 5
183 #define ISIS_ISADJ_NEIGHSYSID 6
184 #define ISIS_ISADJ_NBREXTENDEDCIRCID 7
185 #define ISIS_ISADJ_USAGE 8
186 #define ISIS_ISADJ_HOLDTIMER 9
187 #define ISIS_ISADJ_NEIGHPRIORITY 10
188 #define ISIS_ISADJ_LASTUPTIME 11
190 /* isisISAdjAreadAddrEntry */
191 #define ISIS_ISADJAREA_ADDRENTRY 1, 6, 2, 1
192 #define ISIS_ISADJAREA_ADDRESS 2
194 /* isisISAdjIPAddrEntry*/
195 #define ISIS_ISADJIPADDR_ENTRY 1, 6, 3, 1
196 #define ISIS_ISADJIPADDR_TYPE 2
197 #define ISIS_ISADJIPADDR_ADDRESS 3
200 /* isisISAdjProtSuppEntty */
202 #define ISIS_ISADJPROTSUPP_ENTRY 1, 6, 4, 1
203 #define ISIS_ISADJPROTSUPP_PROTOCOL 1
206 /************************ Trap data variables ************************/
207 #define ISIS_NOTIFICATION_ENTRY 1, 10, 1
208 #define ISIS_NOTIF_SYLELVELINDEX 1
209 #define ISIS_NOTIF_CIRCIFINDEX 2
210 #define ISIS_PDU_LSPID 3
211 #define ISIS_PDU_FRAGMENT 4
212 #define ISIS_PDU_FIELDLEN 5
213 #define ISIS_PDU_MAXAREAADDR 6
214 #define ISIS_PDU_PROTOVER 7
215 #define ISIS_PDU_LSPSIZE 8
216 #define ISIS_PDU_ORIGBUFFERSIZE 9
217 #define ISIS_PDU_BUFFERSIZE 10
218 #define ISIS_PDU_PROTSUPP 11
219 #define ISIS_ADJ_STATE 12
220 #define ISIS_ERROR_OFFSET 13
221 #define ISIS_ERROR_TLVTYPE 14
222 #define ISIS_NOTIF_AREAADDR 15
224 /************************ Traps ************************/
225 #define ISIS_NOTIFICATIONS ISIS_MIB, 0
226 #define ISIS_TRAP_DB_OVERLOAD 1
227 #define ISIS_TRAP_MAN_ADDR_DROP 2
228 #define ISIS_TRAP_CORRUPTED_LSP 3
229 #define ISIS_TRAP_LSP_EXCEED_MAX 4
230 #define ISIS_TRAP_ID_LEN_MISMATCH 5
231 #define ISIS_TRAP_MAX_AREA_ADDR_MISMATCH 6
232 #define ISIS_TRAP_OWN_LSP_PURGE 7
233 #define ISIS_TRAP_SEQNO_SKIPPED 8
234 #define ISIS_TRAP_AUTHEN_TYPE_FAILURE 9
235 #define ISIS_TRAP_AUTHEN_FAILURE 10
236 #define ISIS_TRAP_VERSION_SKEW 11
237 #define ISIS_TRAP_AREA_MISMATCH 12
238 #define ISIS_TRAP_REJ_ADJACENCY 13
239 #define ISIS_TRAP_LSP_TOO_LARGE 14
240 #define ISIS_TRAP_LSP_BUFFSIZE_MISMATCH 15
241 #define ISIS_TRAP_PROTSUPP_MISMATCH 16
242 #define ISIS_TRAP_ADJ_STATE_CHANGE 17
243 #define ISIS_TRAP_LSP_ERROR 18
245 /* Change this definition if number of traps changes */
246 #define ISIS_TRAP_LAST_TRAP ISIS_TRAP_LSP_ERROR + 1
248 #define ISIS_SNMP_TRAP_VAR 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0
251 /* SNMP value hack. */
252 #define COUNTER32 ASN_COUNTER
253 #define INTEGER ASN_INTEGER
254 #define UNSIGNED32 ASN_GAUGE
255 #define TIMESTAMP ASN_TIMETICKS
256 #define TIMETICKS ASN_TIMETICKS
257 #define STRING ASN_OCTET_STR
259 /* Declare static local variables for convenience. */
262 /* If ARRAY_SIZE is not available use a primitive substitution */
264 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
268 * Define time function, it serves two purposes
269 * 1. Uses unint32_t for unix time and encapsulates
270 * sing extension issues in conversion from time_t
272 * 2. I could be replaced in unit test environment
275 /* ISIS-MIB instances. */
276 static oid isis_oid
[] = {ISIS_MIB
};
278 /* SNMP trap variable */
279 static oid isis_snmp_trap_var
[] = {ISIS_SNMP_TRAP_VAR
};
281 /* SNMP trap values (others are calculated on the fly */
282 static oid isis_snmp_notifications
[] = {ISIS_NOTIFICATIONS
};
283 static oid isis_snmp_trap_val_db_overload
[] = {ISIS_NOTIFICATIONS
,
284 ISIS_TRAP_DB_OVERLOAD
};
285 static oid isis_snmp_trap_val_lsp_exceed_max
[] = {ISIS_NOTIFICATIONS
,
286 ISIS_TRAP_LSP_EXCEED_MAX
};
287 static oid isis_snmp_trap_val_area_mismatch
[] = {ISIS_NOTIFICATIONS
,
288 ISIS_TRAP_AREA_MISMATCH
};
289 static oid isis_snmp_trap_val_lsp_error
[] = {ISIS_NOTIFICATIONS
,
290 ISIS_TRAP_LSP_ERROR
};
293 * Trap vars under 'isisNotifications': note: we use full names of variables
296 static oid isis_snmp_trap_data_var_sys_level_index
[] = {
297 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_NOTIF_SYLELVELINDEX
, 0};
298 static oid isis_snmp_trap_data_var_circ_if_index
[] = {
299 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_NOTIF_CIRCIFINDEX
, 0};
300 static oid isis_snmp_trap_data_var_pdu_lsp_id
[] = {
301 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_LSPID
, 0};
302 static oid isis_snmp_trap_data_var_pdu_fragment
[] = {
303 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_FRAGMENT
, 0};
304 static oid isis_snmp_trap_data_var_pdu_field_len
[] = {
305 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_FIELDLEN
, 0};
306 static oid isis_snmp_trap_data_var_pdu_max_area_addr
[] = {
307 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_MAXAREAADDR
, 0};
308 static oid isis_snmp_trap_data_var_pdu_proto_ver
[] = {
309 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_PROTOVER
, 0};
310 static oid isis_snmp_trap_data_var_pdu_lsp_size
[] = {
311 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_LSPSIZE
, 0};
312 static oid isis_snmp_trap_data_var_adj_state
[] = {
313 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_ADJ_STATE
, 0};
314 static oid isis_snmp_trap_data_var_error_offset
[] = {
315 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_ERROR_OFFSET
, 0};
316 static oid isis_snmp_trap_data_var_error_tlv_type
[] = {
317 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_ERROR_TLVTYPE
, 0};
320 * Other variables used by traps: note we use full names of variables and
321 * reserve space for index
323 static oid isis_snmp_trap_data_var_sys_level_state
[] = {
324 ISIS_MIB
, ISIS_SYSLEVEL_ENTRY
, ISIS_SYSLEVEL_STATE
, 0};
326 /* Throttle time values for traps */
327 static time_t isis_snmp_trap_timestamp
[ISIS_TRAP_LAST_TRAP
]; /* ?? 1 */
329 /* Max len of raw-pdu in traps */
330 #define ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN (64)
333 * Just to save on typing we have a shortcut structure
334 * to specify mib layout as prefix/leaf combination
336 #define ISIS_SNMP_PREF_LEN_MAX 10
337 struct isis_var_prefix
{
338 FindVarMethod
*findVar
;
339 uint8_t ivd_pref_len
;
340 oid ivd_pref
[ISIS_SNMP_PREF_LEN_MAX
];
344 /* Find-val functions */
345 static uint8_t *isis_snmp_find_sys_object(struct variable
*, oid
*, size_t *,
346 int, size_t *, WriteMethod
**);
348 static uint8_t *isis_snmp_find_man_area(struct variable
*, oid
*, size_t *, int,
349 size_t *, WriteMethod
**);
351 static uint8_t *isis_snmp_find_area_addr(struct variable
*, oid
*, size_t *,
352 int, size_t *, WriteMethod
**);
354 static uint8_t *isis_snmp_find_summ_addr(struct variable
*, oid
*, size_t *,
355 int, size_t *, WriteMethod
**);
357 static uint8_t *isis_snmp_find_redistribute_addr(struct variable
*, oid
*,
358 size_t *, int, size_t *,
361 static uint8_t *isis_snmp_find_router(struct variable
*, oid
*, size_t *, int,
362 size_t *, WriteMethod
**);
364 static uint8_t *isis_snmp_find_sys_level(struct variable
*, oid
*, size_t *,
365 int, size_t *, WriteMethod
**);
367 static uint8_t *isis_snmp_find_system_counter(struct variable
*, oid
*,
368 size_t *, int, size_t *,
371 static uint8_t *isis_snmp_find_next_circ_index(struct variable
*, oid
*,
372 size_t *, int, size_t *,
375 static uint8_t *isis_snmp_find_circ(struct variable
*, oid
*, size_t *, int,
376 size_t *, WriteMethod
**);
378 static uint8_t *isis_snmp_find_circ_level(struct variable
*, oid
*, size_t *,
379 int, size_t *, WriteMethod
**);
381 static uint8_t *isis_snmp_find_circ_counter(struct variable
*, oid
*, size_t *,
382 int, size_t *, WriteMethod
**);
384 static uint8_t *isis_snmp_find_isadj(struct variable
*, oid
*, size_t *, int,
385 size_t *, WriteMethod
**);
387 static uint8_t *isis_snmp_find_isadj_area(struct variable
*, oid
*, size_t *,
388 int, size_t *, WriteMethod
**);
390 static uint8_t *isis_snmp_find_isadj_ipaddr(struct variable
*, oid
*, size_t *,
391 int, size_t *, WriteMethod
**);
393 static uint8_t *isis_snmp_find_isadj_prot_supp(struct variable
*, oid
*,
394 size_t *, int, size_t *,
398 * Just to save on typing we have a shortcut structure
399 * to specify mib layout, we populate the rest of the data
400 * during initialization
402 #define ISIS_PREF_LEN_MAX (6)
404 struct isis_func_to_prefix
{
405 FindVarMethod
*ihtp_func
;
406 oid ihtp_pref_oid
[ISIS_PREF_LEN_MAX
];
407 uint8_t ihtp_pref_len
;
410 static struct isis_func_to_prefix isis_func_to_prefix_arr
[] = {
411 {isis_snmp_find_sys_object
, {ISIS_SYS_OBJECT
}, 3},
412 {isis_snmp_find_man_area
, {ISIS_MANAREA_ADDRENTRY
}, 4},
413 {isis_snmp_find_area_addr
, {ISIS_AREA_ADDRENTRY
}, 4},
414 {isis_snmp_find_summ_addr
, {ISIS_SUMM_ADDRENTRY
}, 4},
415 {isis_snmp_find_redistribute_addr
, {ISIS_REDISTRIBUTE_ADDRENTRY
}, 4},
416 {isis_snmp_find_router
, {ISIS_ROUTER_ENTRY
}, 4},
417 {isis_snmp_find_sys_level
, {ISIS_SYSLEVEL_ENTRY
}, 4},
418 {isis_snmp_find_system_counter
, {ISIS_SYSTEM_COUNTER_ENTRY
}, 4},
419 {isis_snmp_find_next_circ_index
, {ISIS_CIRC
}, 2},
420 {isis_snmp_find_circ
, {ISIS_CIRC_ENTRY
}, 4},
421 {isis_snmp_find_circ_level
, {ISIS_CIRCLEVEL_ENTRY
}, 4},
422 {isis_snmp_find_circ_counter
, {ISIS_CIRC_COUNTER_ENTRY
}, 4},
423 {isis_snmp_find_isadj
, {ISIS_ISADJ_ENTRY
}, 4},
424 {isis_snmp_find_isadj_area
, {ISIS_ISADJAREA_ADDRENTRY
}, 4},
425 {isis_snmp_find_isadj_ipaddr
, {ISIS_ISADJIPADDR_ENTRY
}, 4},
426 {isis_snmp_find_isadj_prot_supp
, {ISIS_ISADJPROTSUPP_ENTRY
}, 4},
428 static size_t isis_func_to_prefix_count
= ARRAY_SIZE(isis_func_to_prefix_arr
);
430 static struct variable isis_var_arr
[] = {
431 {ISIS_SYS_VERSION
, INTEGER
, RONLY
, isis_snmp_find_sys_object
},
432 {ISIS_SYS_LEVELTYPE
, INTEGER
, RONLY
, isis_snmp_find_sys_object
},
433 {ISIS_SYS_ID
, STRING
, RONLY
, isis_snmp_find_sys_object
},
434 {ISIS_SYS_MAXPATHSPLITS
, UNSIGNED32
, RONLY
, isis_snmp_find_sys_object
},
435 {ISIS_SYS_MAXLSPGENINT
, UNSIGNED32
, RONLY
, isis_snmp_find_sys_object
},
436 {ISIS_SYS_POLLESHELLORATE
, UNSIGNED32
, RONLY
,
437 isis_snmp_find_sys_object
},
438 {ISIS_SYS_WAITTIME
, UNSIGNED32
, RONLY
, isis_snmp_find_sys_object
},
439 {ISIS_SYS_ADMINSTATE
, INTEGER
, RONLY
, isis_snmp_find_sys_object
},
440 {ISIS_SYS_L2TOL1LEAKING
, INTEGER
, RONLY
, isis_snmp_find_sys_object
},
441 {ISIS_SYS_MAXAGE
, UNSIGNED32
, RONLY
, isis_snmp_find_sys_object
},
442 {ISIS_SYS_RECEIVELSPBUFFERSIZE
, UNSIGNED32
, RONLY
,
443 isis_snmp_find_sys_object
},
444 {ISIS_SYS_PROTSUPPORTED
, STRING
, RONLY
, isis_snmp_find_sys_object
},
445 {ISIS_SYS_NOTIFICATIONENABLE
, INTEGER
, RONLY
,
446 isis_snmp_find_sys_object
},
447 {ISIS_MANAREA_ADDREXISTSTATE
, INTEGER
, RONLY
, isis_snmp_find_man_area
},
448 {ISIS_AREA_ADDR
, STRING
, RONLY
, isis_snmp_find_area_addr
},
449 {ISIS_SUMM_ADDREXISTSTATE
, INTEGER
, RONLY
, isis_snmp_find_summ_addr
},
450 {ISIS_SUMM_ADDRMETRIC
, UNSIGNED32
, RONLY
, isis_snmp_find_summ_addr
},
451 {ISIS_SUMM_ADDRFULLMETRIC
, UNSIGNED32
, RONLY
, isis_snmp_find_summ_addr
},
452 {ISIS_REDISTRIBUTE_ADDREXISTSTATE
, INTEGER
, RONLY
,
453 isis_snmp_find_redistribute_addr
},
454 {ISIS_ROUTER_HOSTNAME
, STRING
, RONLY
, isis_snmp_find_router
},
455 {ISIS_ROUTER_ID
, UNSIGNED32
, RONLY
, isis_snmp_find_router
},
456 {ISIS_SYSLEVEL_ORIGLSPBUFFSIZE
, UNSIGNED32
, RONLY
,
457 isis_snmp_find_sys_level
},
458 {ISIS_SYSLEVEL_MINLSPGENINT
, UNSIGNED32
, RONLY
,
459 isis_snmp_find_sys_level
},
460 {ISIS_SYSLEVEL_STATE
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
461 {ISIS_SYSLEVEL_SETOVERLOAD
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
462 {ISIS_SYSLEVEL_SETOVERLOADUNTIL
, UNSIGNED32
, RONLY
,
463 isis_snmp_find_sys_level
},
464 {ISIS_SYSLEVEL_METRICSTYLE
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
465 {ISIS_SYSLEVEL_SPFCONSIDERS
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
466 {ISIS_SYSLEVEL_TEENABLED
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
467 {ISIS_SYSSTAT_CORRLSPS
, COUNTER32
, RONLY
,
468 isis_snmp_find_system_counter
},
469 {ISIS_SYSSTAT_AUTHTYPEFAILS
, COUNTER32
, RONLY
,
470 isis_snmp_find_system_counter
},
471 {ISIS_SYSSTAT_AUTHFAILS
, COUNTER32
, RONLY
,
472 isis_snmp_find_system_counter
},
473 {ISIS_SYSSTAT_LSPDBASEOLOADS
, COUNTER32
, RONLY
,
474 isis_snmp_find_system_counter
},
475 {ISIS_SYSSTAT_MANADDRDROPFROMAREAS
, COUNTER32
, RONLY
,
476 isis_snmp_find_system_counter
},
477 {ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS
, COUNTER32
, RONLY
,
478 isis_snmp_find_system_counter
},
479 {ISIS_SYSSTAT_SEQNUMSKIPS
, COUNTER32
, RONLY
,
480 isis_snmp_find_system_counter
},
481 {ISIS_SYSSTAT_OWNLSPPURGES
, COUNTER32
, RONLY
,
482 isis_snmp_find_system_counter
},
483 {ISIS_SYSSTAT_IDFIELDLENMISMATCHES
, COUNTER32
, RONLY
,
484 isis_snmp_find_system_counter
},
485 {ISIS_SYSSTAT_PARTCHANGES
, COUNTER32
, RONLY
,
486 isis_snmp_find_system_counter
},
487 {ISIS_SYSSTAT_SPFRUNS
, COUNTER32
, RONLY
, isis_snmp_find_system_counter
},
488 {ISIS_SYSSTAT_LSPERRORS
, COUNTER32
, RONLY
,
489 isis_snmp_find_system_counter
},
490 {ISIS_NEXTCIRC_INDEX
, UNSIGNED32
, RONLY
,
491 isis_snmp_find_next_circ_index
},
492 {ISIS_CIRC_IFINDEX
, INTEGER
, RONLY
, isis_snmp_find_circ
},
493 {ISIS_CIRC_ADMINSTATE
, INTEGER
, RONLY
, isis_snmp_find_circ
},
494 {ISIS_CIRC_EXISTSTATE
, INTEGER
, RONLY
, isis_snmp_find_circ
},
495 {ISIS_CIRC_TYPE
, INTEGER
, RONLY
, isis_snmp_find_circ
},
496 {ISIS_CIRC_EXTDOMAIN
, INTEGER
, RONLY
, isis_snmp_find_circ
},
497 {ISIS_CIRC_LEVELTYPE
, INTEGER
, RONLY
, isis_snmp_find_circ
},
498 {ISIS_CIRC_PASSIVECIRCUIT
, INTEGER
, RONLY
, isis_snmp_find_circ
},
499 {ISIS_CIRC_MESHGROUPENABLED
, INTEGER
, RONLY
, isis_snmp_find_circ
},
500 {ISIS_CIRC_MESHGROUP
, UNSIGNED32
, RONLY
, isis_snmp_find_circ
},
501 {ISIS_CIRC_SMALLHELLOS
, INTEGER
, RONLY
, isis_snmp_find_circ
},
502 {ISIS_CIRC_LASTUPTIME
, TIMESTAMP
, RONLY
, isis_snmp_find_circ
},
503 {ISIS_CIRC_3WAYENABLED
, INTEGER
, RONLY
, isis_snmp_find_circ
},
504 {ISIS_CIRC_EXTENDEDCIRCID
, UNSIGNED32
, RONLY
, isis_snmp_find_circ
},
505 {ISIS_CIRCLEVEL_METRIC
, UNSIGNED32
, RONLY
, isis_snmp_find_circ_level
},
506 {ISIS_CIRCLEVEL_WIDEMETRIC
, UNSIGNED32
, RONLY
,
507 isis_snmp_find_circ_level
},
508 {ISIS_CIRCLEVEL_ISPRIORITY
, UNSIGNED32
, RONLY
,
509 isis_snmp_find_circ_level
},
510 {ISIS_CIRCLEVEL_IDOCTET
, UNSIGNED32
, RONLY
, isis_snmp_find_circ_level
},
511 {ISIS_CIRCLEVEL_ID
, STRING
, RONLY
, isis_snmp_find_circ_level
},
512 {ISIS_CIRCLEVEL_DESIS
, STRING
, RONLY
, isis_snmp_find_circ_level
},
513 {ISIS_CIRCLEVEL_HELLOMULTIPLIER
, UNSIGNED32
, RONLY
,
514 isis_snmp_find_circ_level
},
515 {ISIS_CIRCLEVEL_HELLOTIMER
, UNSIGNED32
, RONLY
,
516 isis_snmp_find_circ_level
},
517 {ISIS_CIRCLEVEL_DRHELLOTIMER
, UNSIGNED32
, RONLY
,
518 isis_snmp_find_circ_level
},
519 {ISIS_CIRCLEVEL_LSPTHROTTLE
, UNSIGNED32
, RONLY
,
520 isis_snmp_find_circ_level
},
521 {ISIS_CIRCLEVEL_MINLSPRETRANSINT
, UNSIGNED32
, RONLY
,
522 isis_snmp_find_circ_level
},
523 {ISIS_CIRCLEVEL_CSNPINTERVAL
, UNSIGNED32
, RONLY
,
524 isis_snmp_find_circ_level
},
525 {ISIS_CIRCLEVEL_PARTSNPINTERVAL
, UNSIGNED32
, RONLY
,
526 isis_snmp_find_circ_level
},
527 {ISIS_CIRC_ADJCHANGES
, COUNTER32
, RONLY
, isis_snmp_find_circ_counter
},
528 {ISIS_CIRC_NUMADJ
, UNSIGNED32
, RONLY
, isis_snmp_find_circ_counter
},
529 {ISIS_CIRC_INITFAILS
, COUNTER32
, RONLY
, isis_snmp_find_circ_counter
},
530 {ISIS_CIRC_REJADJS
, COUNTER32
, RONLY
, isis_snmp_find_circ_counter
},
531 {ISIS_CIRC_IDFIELDLENMISMATCHES
, COUNTER32
, RONLY
,
532 isis_snmp_find_circ_counter
},
533 {ISIS_CIRC_MAXAREAADDRMISMATCHES
, COUNTER32
, RONLY
,
534 isis_snmp_find_circ_counter
},
535 {ISIS_CIRC_AUTHTYPEFAILS
, COUNTER32
, RONLY
,
536 isis_snmp_find_circ_counter
},
537 {ISIS_CIRC_AUTHFAILS
, COUNTER32
, RONLY
, isis_snmp_find_circ_counter
},
538 {ISIS_CIRC_LANDESISCHANGES
, COUNTER32
, RONLY
,
539 isis_snmp_find_circ_counter
},
540 {ISIS_ISADJ_STATE
, INTEGER
, RONLY
, isis_snmp_find_isadj
},
541 {ISIS_ISADJ_3WAYSTATE
, INTEGER
, RONLY
, isis_snmp_find_isadj
},
542 {ISIS_ISADJ_NEIGHSNPAADDRESS
, STRING
, RONLY
, isis_snmp_find_isadj
},
543 {ISIS_ISADJ_NEIGHSYSTYPE
, INTEGER
, RONLY
, isis_snmp_find_isadj
},
544 {ISIS_ISADJ_NEIGHSYSID
, STRING
, RONLY
, isis_snmp_find_isadj
},
545 {ISIS_ISADJ_NBREXTENDEDCIRCID
, UNSIGNED32
, RONLY
, isis_snmp_find_isadj
},
546 {ISIS_ISADJ_USAGE
, INTEGER
, RONLY
, isis_snmp_find_isadj
},
547 {ISIS_ISADJ_HOLDTIMER
, UNSIGNED32
, RONLY
, isis_snmp_find_isadj
},
548 {ISIS_ISADJ_NEIGHPRIORITY
, UNSIGNED32
, RONLY
, isis_snmp_find_isadj
},
549 {ISIS_ISADJ_LASTUPTIME
, TIMESTAMP
, RONLY
, isis_snmp_find_isadj
},
550 {ISIS_ISADJAREA_ADDRESS
, STRING
, RONLY
, isis_snmp_find_isadj_area
},
551 {ISIS_ISADJIPADDR_TYPE
, INTEGER
, RONLY
, isis_snmp_find_isadj_ipaddr
},
552 {ISIS_ISADJIPADDR_ADDRESS
, STRING
, RONLY
, isis_snmp_find_isadj_ipaddr
},
553 {ISIS_ISADJPROTSUPP_PROTOCOL
, INTEGER
, RONLY
,
554 isis_snmp_find_isadj_prot_supp
},
557 static const size_t isis_var_count
= ARRAY_SIZE(isis_var_arr
);
559 /* Minimal set of hard-coded data */
560 #define ISIS_VERSION (1)
562 /* If sys-id is not set use this value */
563 static uint8_t isis_null_sysid
[ISIS_SYS_ID_LEN
];
566 #define ISIS_SNMP_OSI_ADDR_LEN_MAX (20)
569 * The implementation has a fixed max-path splits value
570 * of 64 (see ISIS_MAX_PATH_SPLITS), the max mib value
573 * FIXME(aromanov): should we return 32 or 64?
575 #define ISIS_SNMP_MAX_PATH_SPLITS (32)
577 #define ISIS_SNMP_ADMIN_STATE_ON (1)
579 #define ISIS_SNMP_ROW_STATUS_ACTIVE (1)
581 #define ISIS_SNMP_LEVEL_STATE_OFF (1)
582 #define ISIS_SNMP_LEVEL_STATE_ON (2)
583 #define ISIS_SNMP_LEVEL_STATE_WAITING (3)
584 #define ISIS_SNMP_LEVEL_STATE_OVERLOADED (4)
586 #define ISIS_SNMP_TRUTH_VALUE_TRUE (1)
587 #define ISIS_SNMP_TRUTH_VALUE_FALSE (2)
589 #define ISIS_SNMP_METRIC_STYLE_NARROW (1)
590 #define ISIS_SNMP_METRIC_STYLE_WIDE (2)
591 #define ISIS_SNMP_METRIC_STYLE_BOTH (3)
593 #define ISIS_SNMP_MESH_GROUP_INACTIVE (1)
595 #define ISIS_SNMP_ADJ_STATE_DOWN (1)
596 #define ISIS_SNMP_ADJ_STATE_INITIALIZING (2)
597 #define ISIS_SNMP_ADJ_STATE_UP (3)
598 #define ISIS_SNMP_ADJ_STATE_FAILED (4)
600 static inline uint32_t isis_snmp_adj_state(enum isis_adj_state state
)
603 case ISIS_ADJ_UNKNOWN
:
604 return ISIS_SNMP_ADJ_STATE_DOWN
;
605 case ISIS_ADJ_INITIALIZING
:
606 return ISIS_SNMP_ADJ_STATE_INITIALIZING
;
608 return ISIS_SNMP_ADJ_STATE_UP
;
610 return ISIS_SNMP_ADJ_STATE_FAILED
;
613 return 0; /* not reached */
616 #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1 (1)
617 #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2 (2)
618 #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2 (3)
619 #define ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN (4)
621 static inline uint32_t isis_snmp_adj_neightype(enum isis_system_type type
)
624 case ISIS_SYSTYPE_UNKNOWN
:
625 case ISIS_SYSTYPE_ES
:
626 return ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN
;
627 case ISIS_SYSTYPE_IS
:
628 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2
;
629 case ISIS_SYSTYPE_L1_IS
:
630 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1
;
631 case ISIS_SYSTYPE_L2_IS
:
632 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2
;
635 return 0; /* not reached */
638 #define ISIS_SNMP_INET_TYPE_V4 (1)
639 #define ISIS_SNMP_INET_TYPE_V6 (2)
641 #define ISIS_SNMP_P2P_CIRCUIT (3)
643 /* Protocols supported value */
644 static uint8_t isis_snmp_protocols_supported
= 0x7; /* All: iso, ipv4, ipv6 */
646 #define SNMP_CIRCUITS_MAX (512)
648 static struct isis_circuit
*snmp_circuits
[SNMP_CIRCUITS_MAX
];
649 static uint32_t snmp_circuit_id_last
;
651 static int isis_circuit_snmp_id_gen(struct isis_circuit
*circuit
)
656 id
= snmp_circuit_id_last
;
659 /* find next unused entry */
660 for (i
= 0; i
< SNMP_CIRCUITS_MAX
; i
++) {
661 if (id
>= SNMP_CIRCUITS_MAX
) {
669 if (snmp_circuits
[id
] == NULL
)
675 if (i
== SNMP_CIRCUITS_MAX
) {
676 zlog_warn("Could not allocate a smmp-circuit-id");
680 snmp_circuits
[id
] = circuit
;
681 snmp_circuit_id_last
= id
;
682 circuit
->snmp_id
= id
;
687 static int isis_circuit_snmp_id_free(struct isis_circuit
*circuit
)
689 snmp_circuits
[circuit
->snmp_id
] = NULL
;
690 circuit
->snmp_id
= 0;
695 * Convenience function to move to the next circuit,
697 static struct isis_circuit
*isis_snmp_circuit_next(struct isis_circuit
*circuit
)
705 start
= circuit
->snmp_id
+ 1;
707 for (off
= start
; off
< SNMP_CIRCUITS_MAX
; off
++) {
708 circuit
= snmp_circuits
[off
];
718 * Convenience function to get the first matching level
720 static int isis_snmp_circuit_get_level_lo(struct isis_circuit
*circuit
)
722 if (circuit
->is_type
== IS_LEVEL_2
)
728 /* Check level match */
729 static int isis_snmp_get_level_match(int is_type
, int level
)
731 if (is_type
!= IS_LEVEL_1
&& is_type
!= IS_LEVEL_2
732 && is_type
!= IS_LEVEL_1_AND_2
)
735 if (level
!= IS_LEVEL_1
&& level
!= IS_LEVEL_2
)
739 if (is_type
== IS_LEVEL_1
) {
740 if (level
== IS_LEVEL_1
)
746 if (is_type
== IS_LEVEL_2
) {
747 if (level
== IS_LEVEL_2
)
756 * Helper function to convert oid index representing
757 * octet-string index (e.g. isis-sys-id) to byte string
758 * representing the same index.
760 * Also we do not fail if idx is longer than max_len,
761 * so we can use the same function to check compound
764 static int isis_snmp_conv_exact(uint8_t *buf
, size_t max_len
, size_t *out_len
,
765 const oid
*idx
, size_t idx_len
)
770 /* Oid representation: length followed by bytes */
771 if (idx
== NULL
|| idx_len
== 0)
779 if (idx_len
< len
+ 1)
782 for (off
= 0; off
< len
; off
++) {
783 if (idx
[off
+ 1] > 0xff)
786 buf
[off
] = (uint8_t)(idx
[off
+ 1] & 0xff);
794 static int isis_snmp_conv_next(uint8_t *buf
, size_t max_len
, size_t *out_len
,
795 int *try_exact
, const oid
*idx
, size_t idx_len
)
801 if (idx
== NULL
|| idx_len
== 0) {
814 if ((idx_len
- 1) < cmp_len
)
815 cmp_len
= idx_len
- 1;
817 for (off
= 0; off
< cmp_len
; off
++) {
818 if (idx
[off
+ 1] > 0xff) {
819 memset(buf
+ off
, 0xff, len
- off
);
825 buf
[off
] = (uint8_t)(idx
[off
+ 1] & 0xff);
829 memset(buf
+ cmp_len
, 0, len
- cmp_len
);
832 *try_exact
= cmp_len
< len
? 1 : 0;
837 * Helper functions to find area address from snmp index
839 static int isis_snmp_area_addr_lookup_exact(oid
*oid_idx
, size_t oid_idx_len
,
840 struct isis_area
**ret_area
,
841 struct area_addr
**ret_addr
)
843 uint8_t cmp_buf
[ISIS_SNMP_OSI_ADDR_LEN_MAX
];
845 struct isis_area
*area
= NULL
;
846 struct area_addr
*addr
= NULL
;
847 struct listnode
*addr_node
;
848 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
853 if (list_isempty(isis
->area_list
)) {
854 /* Area is not configured yet */
858 area
= listgetdata(listhead(isis
->area_list
));
860 int res
= isis_snmp_conv_exact(cmp_buf
, sizeof(cmp_buf
), &addr_len
,
861 oid_idx
, oid_idx_len
);
864 if (!res
|| addr_len
== 0 || oid_idx_len
!= (addr_len
+ 1)) {
865 /* Bad conversion, empty address or extra oids at the end */
869 for (ALL_LIST_ELEMENTS_RO(area
->area_addrs
, addr_node
, addr
)) {
870 if (addr
->addr_len
!= addr_len
)
873 if (memcmp(addr
->area_addr
, cmp_buf
, addr_len
) == 0) {
886 static int isis_snmp_area_addr_lookup_next(oid
*oid_idx
, size_t oid_idx_len
,
887 struct isis_area
**ret_area
,
888 struct area_addr
**ret_addr
)
890 uint8_t cmp_buf
[ISIS_SNMP_OSI_ADDR_LEN_MAX
];
893 struct isis_area
*found_area
= NULL
;
894 struct isis_area
*area
= NULL
;
895 struct area_addr
*found_addr
= NULL
;
896 struct area_addr
*addr
= NULL
;
897 struct listnode
*addr_node
;
898 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
903 if (list_isempty(isis
->area_list
)) {
904 /* Area is not configured yet */
908 area
= listgetdata(listhead(isis
->area_list
));
910 int res
= isis_snmp_conv_next(cmp_buf
, sizeof(cmp_buf
), &addr_len
,
911 &try_exact
, oid_idx
, oid_idx_len
);
916 for (ALL_LIST_ELEMENTS_RO(area
->area_addrs
, addr_node
, addr
)) {
917 if (addr
->addr_len
< addr_len
)
920 if (addr
->addr_len
== addr_len
) {
924 res
= memcmp(addr
->area_addr
, cmp_buf
, addr_len
);
929 if (res
== 0 && addr
->addr_len
== addr_len
) {
932 * This is the best match no point
943 if (found_addr
== NULL
|| addr
->addr_len
< found_addr
->addr_len
944 || (addr
->addr_len
== found_addr
->addr_len
945 && memcmp(addr
->area_addr
, found_addr
->area_addr
,
953 if (found_area
== NULL
)
957 *ret_area
= found_area
;
960 *ret_addr
= found_addr
;
966 * Helper functions to find circuit from
969 static int isis_snmp_circuit_lookup_exact(oid
*oid_idx
, size_t oid_idx_len
,
970 struct isis_circuit
**ret_circuit
)
972 struct isis_circuit
*circuit
;
974 if (oid_idx
== NULL
|| oid_idx_len
< 1
975 || oid_idx
[0] > SNMP_CIRCUITS_MAX
)
978 circuit
= snmp_circuits
[oid_idx
[0]];
982 if (ret_circuit
!= NULL
)
983 *ret_circuit
= circuit
;
988 static int isis_snmp_circuit_lookup_next(oid
*oid_idx
, size_t oid_idx_len
,
989 struct isis_circuit
**ret_circuit
)
993 struct isis_circuit
*circuit
;
997 if (oid_idx
!= NULL
&& oid_idx_len
!= 0) {
998 if (oid_idx
[0] > SNMP_CIRCUITS_MAX
)
1004 for (off
= start
; off
< SNMP_CIRCUITS_MAX
; ++off
) {
1005 circuit
= snmp_circuits
[off
];
1007 if (circuit
!= NULL
&& off
> start
) {
1008 if (ret_circuit
!= NULL
)
1009 *ret_circuit
= circuit
;
1019 * Helper functions to find circuit level
1020 * combination from snmp index
1022 static int isis_snmp_circuit_level_lookup_exact(
1023 oid
*oid_idx
, size_t oid_idx_len
, int check_match
,
1024 struct isis_circuit
**ret_circuit
, int *ret_level
)
1028 struct isis_circuit
*circuit
;
1030 /* Minor optimization: check level first */
1031 if (oid_idx
== NULL
|| oid_idx_len
< 2)
1034 if (oid_idx
[1] < IS_LEVEL_1
|| oid_idx
[1] > IS_LEVEL_2
)
1037 level
= (int)oid_idx
[1];
1039 res
= isis_snmp_circuit_lookup_exact(oid_idx
, oid_idx_len
, &circuit
);
1044 if (check_match
&& !isis_snmp_get_level_match(circuit
->is_type
, level
))
1047 if (ret_circuit
!= NULL
)
1048 *ret_circuit
= circuit
;
1050 if (ret_level
!= NULL
)
1056 static int isis_snmp_circuit_level_lookup_next(
1057 oid
*oid_idx
, size_t oid_idx_len
, int check_match
,
1058 struct isis_circuit
**ret_circuit
, int *ret_level
)
1062 struct isis_circuit
*circuit
= NULL
;
1067 if (oid_idx
!= NULL
&& oid_idx_len
!= 0) {
1068 if (oid_idx
[0] > SNMP_CIRCUITS_MAX
)
1074 for (off
= start
; off
< SNMP_CIRCUITS_MAX
; off
++) {
1075 circuit
= snmp_circuits
[off
];
1077 if (circuit
== NULL
)
1080 if (off
> start
|| oid_idx_len
< 2) {
1081 /* Found and can use level 1 */
1086 assert(oid_idx
!= NULL
);
1088 /* We have to check level specified by index */
1089 if (oid_idx
[1] < IS_LEVEL_1
) {
1094 if (oid_idx
[1] < IS_LEVEL_2
) {
1103 if (circuit
== NULL
)
1107 && !isis_snmp_get_level_match(circuit
->is_type
, level
)) {
1108 if (level
== IS_LEVEL_1
) {
1110 * We can simply advance level because
1111 * at least one level should match
1115 /* We have to move to the next circuit */
1116 circuit
= isis_snmp_circuit_next(circuit
);
1117 if (circuit
== NULL
)
1120 level
= isis_snmp_circuit_get_level_lo(circuit
);
1124 if (ret_circuit
!= NULL
)
1125 *ret_circuit
= circuit
;
1127 if (ret_level
!= NULL
)
1134 * Helper functions to find adjacency
1137 * We have 4 tables related to adjacency
1138 * looking up adjacency is quite expensive
1139 * in case of bcast interfaces.
1141 * It is pain to have 4 very similar functions
1142 * hence we pass in and out additional data
1143 * we are looking for.
1145 * Note: we use data-len value to distinguish
1146 * between ipv4 and ipv6 addresses
1148 #define ISIS_SNMP_ADJ_DATA_NONE (1)
1149 #define ISIS_SNMP_ADJ_DATA_AREA_ADDR (2)
1150 #define ISIS_SNMP_ADJ_DATA_IP_ADDR (3)
1151 #define ISIS_SNMP_ADJ_DATA_PROTO (4)
1154 * Helper function to process data associated
1157 static int isis_snmp_adj_helper(struct isis_adjacency
*adj
, int data_id
,
1158 oid data_off
, uint8_t **ret_data
,
1159 size_t *ret_data_len
)
1161 uint8_t *data
= NULL
;
1162 size_t data_len
= 0;
1165 case ISIS_SNMP_ADJ_DATA_NONE
:
1168 case ISIS_SNMP_ADJ_DATA_AREA_ADDR
:
1169 if (data_off
>= adj
->area_address_count
)
1172 data
= adj
->area_addresses
[data_off
].area_addr
;
1173 data_len
= adj
->area_addresses
[data_off
].addr_len
;
1176 case ISIS_SNMP_ADJ_DATA_IP_ADDR
:
1177 if (data_off
>= (adj
->ipv4_address_count
+ adj
->ll_ipv6_count
))
1180 if (data_off
>= adj
->ipv4_address_count
) {
1181 data
= (uint8_t *)&adj
->ll_ipv6_addrs
1182 [data_off
- adj
->ipv4_address_count
];
1183 data_len
= sizeof(adj
->ll_ipv6_addrs
[0]);
1185 data
= (uint8_t *)&adj
->ipv4_addresses
[data_off
];
1186 data_len
= sizeof(adj
->ipv4_addresses
[0]);
1192 case ISIS_SNMP_ADJ_DATA_PROTO
:
1193 if (data_off
>= adj
->nlpids
.count
)
1196 data
= &adj
->nlpids
.nlpids
[data_off
];
1197 data_len
= sizeof(adj
->nlpids
.nlpids
[0]);
1205 if (ret_data
!= NULL
)
1208 if (ret_data_len
!= NULL
)
1209 *ret_data_len
= data_len
;
1214 static int isis_snmp_adj_lookup_exact(oid
*oid_idx
, size_t oid_idx_len
,
1216 struct isis_adjacency
**ret_adj
,
1217 oid
*ret_data_idx
, uint8_t **ret_data
,
1218 size_t *ret_data_len
)
1221 struct listnode
*node
;
1222 struct isis_circuit
*circuit
;
1223 struct isis_adjacency
*adj
;
1224 struct isis_adjacency
*tmp_adj
;
1230 res
= isis_snmp_circuit_lookup_exact(oid_idx
, oid_idx_len
, &circuit
);
1235 if (oid_idx
== NULL
|| oid_idx_len
< 2
1236 || (data_id
!= ISIS_SNMP_ADJ_DATA_NONE
&& oid_idx_len
< 3))
1239 adj_idx
= oid_idx
[1];
1241 if (data_id
!= ISIS_SNMP_ADJ_DATA_NONE
) {
1242 if (oid_idx
[2] == 0)
1245 data_off
= oid_idx
[2] - 1;
1248 * Data-off is not used if data-id is none
1249 * but we set it just for consistency
1258 for (ALL_LIST_ELEMENTS_RO(circuit
->snmp_adj_list
, node
, tmp_adj
)) {
1259 if (tmp_adj
->snmp_idx
> adj_idx
) {
1261 * Adjacencies are ordered in the list
1262 * no point to look further
1267 if (tmp_adj
->snmp_idx
== adj_idx
) {
1268 res
= isis_snmp_adj_helper(tmp_adj
, data_id
, data_off
,
1280 if (ret_adj
!= NULL
)
1283 if (ret_data_idx
!= NULL
)
1284 *ret_data_idx
= data_off
+ 1;
1290 *ret_data_len
= data_len
;
1295 static int isis_snmp_adj_lookup_next(oid
*oid_idx
, size_t oid_idx_len
,
1297 struct isis_adjacency
**ret_adj
,
1298 oid
*ret_data_idx
, uint8_t **ret_data
,
1299 size_t *ret_data_len
)
1301 struct listnode
*node
;
1302 struct isis_circuit
*circuit
;
1303 struct isis_adjacency
*adj
;
1304 struct isis_adjacency
*tmp_adj
;
1316 * Note: we rely on the fact that data indexes are consequtive
1320 if (oid_idx
== 0 || oid_idx_len
== 0) {
1324 } else if (oid_idx_len
== 1) {
1325 circ_idx
= oid_idx
[0];
1328 } else if (oid_idx_len
== 2) {
1329 circ_idx
= oid_idx
[0];
1330 adj_idx
= oid_idx
[1];
1333 circ_idx
= oid_idx
[0];
1334 adj_idx
= oid_idx
[1];
1336 if (data_id
== ISIS_SNMP_ADJ_DATA_NONE
)
1339 data_idx
= oid_idx
[2];
1342 if (!isis_snmp_circuit_lookup_exact(&circ_idx
, 1, &circuit
)
1343 && !isis_snmp_circuit_lookup_next(&circ_idx
, 1, &circuit
))
1347 if (circuit
->snmp_id
!= circ_idx
) {
1348 /* Match is not exact */
1355 * Note: the simple loop below will work in all cases
1357 while (circuit
!= NULL
) {
1358 for (ALL_LIST_ELEMENTS_RO(circuit
->snmp_adj_list
, node
,
1360 if (tmp_adj
->snmp_idx
< adj_idx
)
1363 if (tmp_adj
->snmp_idx
== adj_idx
1364 && data_id
== ISIS_SNMP_ADJ_DATA_NONE
)
1367 if (adj_idx
!= 0 && tmp_adj
->snmp_idx
> adj_idx
)
1370 if (isis_snmp_adj_helper(tmp_adj
, data_id
, data_idx
,
1371 &data
, &data_len
)) {
1380 circuit
= isis_snmp_circuit_next(circuit
);
1389 if (ret_adj
!= NULL
)
1392 if (ret_data_idx
!= 0) {
1393 if (data_id
== ISIS_SNMP_ADJ_DATA_NONE
)
1395 * Value does not matter but let us set
1396 * it to zero for consistency
1400 *ret_data_idx
= data_idx
+ 1;
1406 if (ret_data_len
!= 0)
1407 *ret_data_len
= data_len
;
1412 static uint8_t *isis_snmp_find_sys_object(struct variable
*v
, oid
*name
,
1413 size_t *length
, int exact
,
1415 WriteMethod
**write_method
)
1417 struct isis_area
*area
= NULL
;
1418 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
1423 if (!list_isempty(isis
->area_list
))
1424 area
= listgetdata(listhead(isis
->area_list
));
1426 /* Check whether the instance identifier is valid */
1427 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
1432 case ISIS_SYS_VERSION
:
1433 return SNMP_INTEGER(ISIS_VERSION
);
1435 case ISIS_SYS_LEVELTYPE
:
1437 * If we do not have areas use 1&2 otherwise use settings
1438 * from the first area in the list
1441 return SNMP_INTEGER(IS_LEVEL_1_AND_2
);
1443 return SNMP_INTEGER(area
->is_type
);
1446 if (!isis
->sysid_set
) {
1447 *var_len
= ISIS_SYS_ID_LEN
;
1448 return isis_null_sysid
;
1451 *var_len
= ISIS_SYS_ID_LEN
;
1454 case ISIS_SYS_MAXPATHSPLITS
:
1455 return SNMP_INTEGER(ISIS_SNMP_MAX_PATH_SPLITS
);
1457 case ISIS_SYS_MAXLSPGENINT
:
1458 return SNMP_INTEGER(DEFAULT_MAX_LSP_GEN_INTERVAL
);
1460 case ISIS_SYS_POLLESHELLORATE
:
1461 return SNMP_INTEGER(DEFAULT_HELLO_INTERVAL
);
1463 case ISIS_SYS_WAITTIME
:
1464 /* Note: it seems that we have same fixed delay time */
1465 return SNMP_INTEGER(DEFAULT_MIN_LSP_GEN_INTERVAL
);
1467 case ISIS_SYS_ADMINSTATE
:
1468 /* If daemon is running it admin state is on */
1469 return SNMP_INTEGER(ISIS_SNMP_ADMIN_STATE_ON
);
1472 case ISIS_SYS_L2TOL1LEAKING
:
1473 /* We do not allow l2-to-l1 leaking */
1474 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
1476 case ISIS_SYS_MAXAGE
:
1477 return SNMP_INTEGER(MAX_AGE
);
1479 case ISIS_SYS_RECEIVELSPBUFFERSIZE
:
1481 return SNMP_INTEGER(DEFAULT_LSP_MTU
);
1483 return SNMP_INTEGER(area
->lsp_mtu
);
1485 case ISIS_SYS_PROTSUPPORTED
:
1487 return &isis_snmp_protocols_supported
;
1489 case ISIS_SYS_NOTIFICATIONENABLE
:
1490 if (isis
->snmp_notifications
)
1491 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
1493 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
1503 static uint8_t *isis_snmp_find_man_area(struct variable
*v
, oid
*name
,
1504 size_t *length
, int exact
,
1506 WriteMethod
**write_method
)
1509 struct area_addr
*area_addr
= NULL
;
1514 *write_method
= NULL
;
1516 if (*length
<= v
->namelen
) {
1519 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
1523 oid_idx
= name
+ v
->namelen
;
1524 oid_idx_len
= *length
- v
->namelen
;
1528 res
= isis_snmp_area_addr_lookup_exact(oid_idx
, oid_idx_len
,
1535 res
= isis_snmp_area_addr_lookup_next(oid_idx
, oid_idx_len
,
1541 /* Copy the name out */
1542 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
1545 name
[v
->namelen
] = area_addr
->addr_len
;
1547 for (off
= 0; off
< area_addr
->addr_len
; off
++)
1548 name
[v
->namelen
+ 1 + off
] = area_addr
->area_addr
[off
];
1550 *length
= v
->namelen
+ 1 + area_addr
->addr_len
;
1554 case ISIS_MANAREA_ADDREXISTSTATE
:
1555 return SNMP_INTEGER(ISIS_SNMP_ROW_STATUS_ACTIVE
);
1564 static uint8_t *isis_snmp_find_area_addr(struct variable
*v
, oid
*name
,
1565 size_t *length
, int exact
,
1567 WriteMethod
**write_method
)
1570 * Area addresses in sense of addresses reported by L1 lsps
1571 * are not supported yet.
1580 *write_method
= NULL
;
1585 static uint8_t *isis_snmp_find_summ_addr(struct variable
*v
, oid
*name
,
1586 size_t *length
, int exact
,
1588 WriteMethod
**write_method
)
1591 * So far there is no way to set summary table values through cli
1592 * and snmp operations are read-only, hence there are no entries
1599 *write_method
= NULL
;
1604 static uint8_t *isis_snmp_find_redistribute_addr(struct variable
*v
, oid
*name
,
1605 size_t *length
, int exact
,
1607 WriteMethod
**write_method
)
1610 * It is not clear at the point whether redist code in isis is actually
1611 * used for now we will consider that entries are not present
1618 *write_method
= NULL
;
1623 static uint8_t *isis_snmp_find_router(struct variable
*v
, oid
*name
,
1624 size_t *length
, int exact
,
1626 WriteMethod
**write_method
)
1628 uint8_t cmp_buf
[ISIS_SYS_ID_LEN
];
1633 struct isis_dynhn
*dyn
= NULL
;
1637 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
1642 *write_method
= NULL
;
1644 if (*length
<= v
->namelen
) {
1647 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
1651 oid_idx
= name
+ v
->namelen
;
1652 oid_idx_len
= *length
- v
->namelen
;
1656 res
= isis_snmp_conv_exact(cmp_buf
, sizeof(cmp_buf
), &cmp_len
,
1657 oid_idx
, oid_idx_len
);
1659 if (!res
|| cmp_len
!= ISIS_SYS_ID_LEN
1660 || oid_idx_len
!= (cmp_len
+ 2))
1662 * Bad conversion, or bad length,
1663 * or extra oids at the end
1667 if (oid_idx
[ISIS_SYS_ID_LEN
+ 1] < IS_LEVEL_1
1668 || oid_idx
[ISIS_SYS_ID_LEN
+ 1] > IS_LEVEL_2
)
1669 /* Level part of the index is out of range */
1672 cmp_level
= (int)oid_idx
[ISIS_SYS_ID_LEN
+ 1];
1674 dyn
= dynhn_find_by_id(isis
, cmp_buf
);
1676 if (dyn
== NULL
|| dyn
->level
!= cmp_level
)
1680 case ISIS_ROUTER_HOSTNAME
:
1681 *var_len
= strlen(dyn
->hostname
);
1682 return (uint8_t *)dyn
->hostname
;
1684 case ISIS_ROUTER_ID
:
1685 /* It seems that we do no know router-id in lsps */
1686 return SNMP_INTEGER(0);
1695 res
= isis_snmp_conv_next(cmp_buf
, sizeof(cmp_buf
), &cmp_len
,
1696 &try_exact
, oid_idx
, oid_idx_len
);
1700 /* Bad conversion */
1703 if (cmp_len
!= ISIS_SYS_ID_LEN
) {
1704 /* We do not have valid index oids */
1705 memset(cmp_buf
, 0, sizeof(cmp_buf
));
1707 } else if (try_exact
)
1709 * We have no valid level index.
1710 * Let start from non-existing level 0 and
1711 * hence not need to do exact match
1714 else if (oid_idx_len
< (ISIS_SYS_ID_LEN
+ 2))
1716 else if (oid_idx
[ISIS_SYS_ID_LEN
+ 1] <= IS_LEVEL_2
)
1717 cmp_level
= (int)oid_idx
[ISIS_SYS_ID_LEN
+ 1];
1720 * Any value greater than 2 will have the same result
1721 * but we can have integer overflows, hence 3 is a reasonable
1724 cmp_level
= (int)(IS_LEVEL_2
+ 1);
1726 dyn
= dynhn_snmp_next(isis
, cmp_buf
, cmp_level
);
1731 /* Copy the name out */
1732 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
1735 name
[v
->namelen
] = ISIS_SYS_ID_LEN
;
1737 for (off
= 0; off
< ISIS_SYS_ID_LEN
; off
++)
1738 name
[v
->namelen
+ 1 + off
] = dyn
->id
[off
];
1740 name
[v
->namelen
+ 1 + ISIS_SYS_ID_LEN
] = (oid
)dyn
->level
;
1743 *length
= v
->namelen
+ 1 + ISIS_SYS_ID_LEN
+ 1;
1746 case ISIS_ROUTER_HOSTNAME
:
1747 *var_len
= strlen(dyn
->hostname
);
1748 return (uint8_t *)dyn
->hostname
;
1750 case ISIS_ROUTER_ID
:
1751 /* It seems that we do no know router-id in lsps */
1752 return SNMP_INTEGER(0);
1761 static uint8_t *isis_snmp_find_sys_level(struct variable
*v
, oid
*name
,
1762 size_t *length
, int exact
,
1764 WriteMethod
**write_method
)
1770 struct isis_area
*area
= NULL
;
1771 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
1776 *write_method
= NULL
;
1778 if (*length
<= v
->namelen
) {
1781 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
1785 oid_idx
= name
+ v
->namelen
;
1786 oid_idx_len
= *length
- v
->namelen
;
1790 if (oid_idx
== NULL
|| oid_idx_len
!= 1)
1793 if (oid_idx
[0] == IS_LEVEL_1
)
1795 else if (oid_idx
[0] == IS_LEVEL_2
)
1801 if (oid_idx
== NULL
)
1803 else if (oid_idx_len
== 0)
1805 else if (oid_idx
[0] < IS_LEVEL_1
)
1807 else if (oid_idx
[0] < IS_LEVEL_2
)
1812 /* Copy the name out */
1813 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
1816 name
[v
->namelen
] = level
;
1819 *length
= v
->namelen
+ 1;
1824 if (!list_isempty(isis
->area_list
))
1825 area
= listgetdata(listhead(isis
->area_list
));
1830 level_match
= isis_snmp_get_level_match(area
->is_type
, level
);
1833 case ISIS_SYSLEVEL_ORIGLSPBUFFSIZE
:
1835 return SNMP_INTEGER(area
->lsp_mtu
);
1837 return SNMP_INTEGER(DEFAULT_LSP_MTU
);
1839 case ISIS_SYSLEVEL_MINLSPGENINT
:
1841 return SNMP_INTEGER(area
->lsp_gen_interval
[level
- 1]);
1843 return SNMP_INTEGER(DEFAULT_MIN_LSP_GEN_INTERVAL
);
1845 case ISIS_SYSLEVEL_STATE
:
1847 if (area
->overload_bit
)
1848 return SNMP_INTEGER(
1849 ISIS_SNMP_LEVEL_STATE_OVERLOADED
);
1851 return SNMP_INTEGER(ISIS_SNMP_LEVEL_STATE_ON
);
1853 return SNMP_INTEGER(ISIS_SNMP_LEVEL_STATE_OFF
);
1855 case ISIS_SYSLEVEL_SETOVERLOAD
:
1856 if (level_match
&& area
->overload_bit
)
1857 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
1859 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
1861 case ISIS_SYSLEVEL_SETOVERLOADUNTIL
:
1862 /* We do not have automatic cleanup of overload bit */
1863 return SNMP_INTEGER(0);
1865 case ISIS_SYSLEVEL_METRICSTYLE
:
1867 if (area
->newmetric
&& area
->oldmetric
)
1868 return SNMP_INTEGER(
1869 ISIS_SNMP_METRIC_STYLE_BOTH
);
1871 if (area
->newmetric
)
1872 return SNMP_INTEGER(
1873 ISIS_SNMP_METRIC_STYLE_WIDE
);
1875 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_NARROW
);
1877 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_NARROW
);
1879 case ISIS_SYSLEVEL_SPFCONSIDERS
:
1880 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_BOTH
);
1882 case ISIS_SYSLEVEL_TEENABLED
:
1883 if (level_match
&& IS_MPLS_TE(area
->mta
))
1884 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
1886 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
1895 static uint8_t *isis_snmp_find_system_counter(struct variable
*v
, oid
*name
,
1896 size_t *length
, int exact
,
1898 WriteMethod
**write_method
)
1904 struct isis_area
*area
= NULL
;
1906 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
1911 *write_method
= NULL
;
1913 if (*length
<= v
->namelen
) {
1916 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
1920 oid_idx
= name
+ v
->namelen
;
1921 oid_idx_len
= *length
- v
->namelen
;
1925 if (oid_idx
== NULL
|| oid_idx_len
!= 1)
1928 if (oid_idx
[0] == IS_LEVEL_1
)
1930 else if (oid_idx
[0] == IS_LEVEL_2
)
1936 if (oid_idx
== NULL
)
1938 else if (oid_idx_len
== 0)
1940 else if (oid_idx
[0] < IS_LEVEL_1
)
1942 else if (oid_idx
[0] < IS_LEVEL_2
)
1947 /* Copy the name out */
1948 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
1951 name
[v
->namelen
] = level
;
1954 *length
= v
->namelen
+ 1;
1959 if (!list_isempty(isis
->area_list
))
1960 area
= listgetdata(listhead(isis
->area_list
));
1965 level_match
= isis_snmp_get_level_match(area
->is_type
, level
);
1968 /* If level does not match all counters are zeros */
1969 return SNMP_INTEGER(0);
1972 case ISIS_SYSSTAT_CORRLSPS
:
1976 case ISIS_SYSSTAT_AUTHTYPEFAILS
:
1977 val
= (uint32_t)area
->auth_type_failures
[level
- 1];
1980 case ISIS_SYSSTAT_AUTHFAILS
:
1981 val
= (uint32_t)area
->auth_failures
[level
- 1];
1984 case ISIS_SYSSTAT_LSPDBASEOLOADS
:
1985 val
= area
->overload_counter
;
1988 case ISIS_SYSSTAT_MANADDRDROPFROMAREAS
:
1989 /* We do not support manual addresses */
1993 case ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS
:
1994 val
= area
->lsp_exceeded_max_counter
;
1997 case ISIS_SYSSTAT_SEQNUMSKIPS
:
1998 val
= area
->lsp_seqno_skipped_counter
;
2001 case ISIS_SYSSTAT_OWNLSPPURGES
:
2002 if (!area
->purge_originator
)
2005 val
= area
->lsp_purge_count
[level
- 1];
2008 case ISIS_SYSSTAT_IDFIELDLENMISMATCHES
:
2009 val
= (uint32_t)area
->id_len_mismatches
[level
- 1];
2012 case ISIS_SYSSTAT_PARTCHANGES
:
2017 case ISIS_SYSSTAT_SPFRUNS
:
2018 val
= (uint32_t)area
->spf_run_count
[level
- 1];
2021 case ISIS_SYSSTAT_LSPERRORS
:
2022 val
= (uint32_t)area
->lsp_error_counter
[level
- 1];
2029 return SNMP_INTEGER(val
);
2032 static uint8_t *isis_snmp_find_next_circ_index(struct variable
*v
, oid
*name
,
2033 size_t *length
, int exact
,
2035 WriteMethod
**write_method
)
2037 /* Check whether the instance identifier is valid */
2038 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
2043 case ISIS_NEXTCIRC_INDEX
:
2045 * We do not support circuit creation through snmp
2047 return SNMP_INTEGER(0);
2056 static uint8_t *isis_snmp_find_circ(struct variable
*v
, oid
*name
,
2057 size_t *length
, int exact
, size_t *var_len
,
2058 WriteMethod
**write_method
)
2060 /* Index is circuit-id: 1-255 */
2063 struct isis_circuit
*circuit
;
2065 uint32_t delta_ticks
;
2069 *write_method
= NULL
;
2071 if (*length
<= v
->namelen
) {
2074 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2078 oid_idx
= name
+ v
->namelen
;
2079 oid_idx_len
= *length
- v
->namelen
;
2082 res
= isis_snmp_circuit_lookup_exact(oid_idx
, oid_idx_len
,
2085 if (!res
|| oid_idx_len
!= 1)
2089 res
= isis_snmp_circuit_lookup_next(oid_idx
, oid_idx_len
,
2095 /* Copy the name out */
2096 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2099 name
[v
->namelen
] = circuit
->snmp_id
;
2102 *length
= v
->namelen
+ 1;
2106 case ISIS_CIRC_IFINDEX
:
2107 if (circuit
->interface
== NULL
)
2108 return SNMP_INTEGER(0);
2110 return SNMP_INTEGER(circuit
->interface
->ifindex
);
2112 case ISIS_CIRC_ADMINSTATE
:
2113 return SNMP_INTEGER(ISIS_SNMP_ADMIN_STATE_ON
);
2115 case ISIS_CIRC_EXISTSTATE
:
2116 return SNMP_INTEGER(ISIS_SNMP_ROW_STATUS_ACTIVE
);
2118 case ISIS_CIRC_TYPE
:
2120 * Note: values do not match 100%:
2122 * 1. From isis_circuit.h:
2123 * CIRCUIT_T_UNKNOWN 0
2124 * CIRCUIT_T_BROADCAST 1
2126 * CIRCUIT_T_LOOPBACK 3
2135 return SNMP_INTEGER(circuit
->circ_type
);
2137 case ISIS_CIRC_EXTDOMAIN
:
2138 if (circuit
->ext_domain
)
2139 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
2141 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
2143 case ISIS_CIRC_LEVELTYPE
:
2144 return SNMP_INTEGER(circuit
->is_type
);
2146 case ISIS_CIRC_PASSIVECIRCUIT
:
2147 if (circuit
->is_passive
)
2148 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
2150 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
2152 case ISIS_CIRC_MESHGROUPENABLED
:
2154 return SNMP_INTEGER(ISIS_SNMP_MESH_GROUP_INACTIVE
);
2156 case ISIS_CIRC_MESHGROUP
:
2158 return SNMP_INTEGER(0);
2160 case ISIS_CIRC_SMALLHELLOS
:
2162 * return false if lan hellos must be padded
2164 if (circuit
->pad_hellos
)
2165 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
2167 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
2169 case ISIS_CIRC_LASTUPTIME
:
2170 if (circuit
->last_uptime
== 0)
2171 return SNMP_INTEGER(0);
2173 up_ticks
= (uint32_t)netsnmp_get_agent_uptime();
2174 now_time
= time(NULL
);
2176 if (circuit
->last_uptime
>= now_time
)
2177 return SNMP_INTEGER(up_ticks
);
2179 delta_ticks
= (now_time
- circuit
->last_uptime
) * 10;
2181 if (up_ticks
< delta_ticks
)
2182 return SNMP_INTEGER(up_ticks
);
2184 return SNMP_INTEGER(up_ticks
- delta_ticks
);
2186 case ISIS_CIRC_3WAYENABLED
:
2188 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
2190 case ISIS_CIRC_EXTENDEDCIRCID
:
2191 /* Used for 3-way hand shake only */
2192 return SNMP_INTEGER(0);
2201 static uint8_t *isis_snmp_find_circ_level(struct variable
*v
, oid
*name
,
2202 size_t *length
, int exact
,
2204 WriteMethod
**write_method
)
2206 static uint8_t circuit_id_val
[ISIS_SYS_ID_LEN
+ 1];
2207 /* Index is circuit-id: 1-255 + level: 1-2 */
2211 struct isis_circuit
*circuit
;
2213 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
2218 *write_method
= NULL
;
2220 if (*length
<= v
->namelen
) {
2223 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2227 oid_idx
= name
+ v
->namelen
;
2228 oid_idx_len
= *length
- v
->namelen
;
2231 res
= isis_snmp_circuit_level_lookup_exact(oid_idx
, oid_idx_len
,
2232 1, &circuit
, &level
);
2234 if (!res
|| oid_idx_len
!= 2)
2238 res
= isis_snmp_circuit_level_lookup_next(oid_idx
, oid_idx_len
,
2239 1, &circuit
, &level
);
2244 /* Copy the name out */
2245 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2248 name
[v
->namelen
] = circuit
->snmp_id
;
2249 name
[v
->namelen
+ 1] = level
;
2252 *length
= v
->namelen
+ 2;
2256 case ISIS_CIRCLEVEL_METRIC
:
2257 return SNMP_INTEGER(circuit
->metric
[level
- 1]);
2259 case ISIS_CIRCLEVEL_WIDEMETRIC
:
2260 if (circuit
->area
== NULL
|| !circuit
->area
->newmetric
) {
2261 /* What should we do if wide metric is not supported? */
2262 return SNMP_INTEGER(0);
2264 return SNMP_INTEGER(circuit
->te_metric
[level
- 1]);
2266 case ISIS_CIRCLEVEL_ISPRIORITY
:
2267 return SNMP_INTEGER(circuit
->priority
[level
- 1]);
2269 case ISIS_CIRCLEVEL_IDOCTET
:
2270 return SNMP_INTEGER(circuit
->circuit_id
);
2272 case ISIS_CIRCLEVEL_ID
:
2273 if (circuit
->circ_type
!= CIRCUIT_T_P2P
) {
2275 * Unless it is point-to-point circuit, the value is and
2276 * empty octet string
2279 return circuit_id_val
;
2282 /* !!!!!! Circuit-id is zero for p2p links */
2283 if (circuit
->u
.p2p
.neighbor
== NULL
2284 || circuit
->u
.p2p
.neighbor
->adj_state
!= ISIS_ADJ_UP
) {
2285 /* No adjacency or adjacency not fully up yet */
2286 memcpy(circuit_id_val
, isis
->sysid
, ISIS_SYS_ID_LEN
);
2287 circuit_id_val
[ISIS_SYS_ID_LEN
] = circuit
->circuit_id
;
2288 *var_len
= ISIS_SYS_ID_LEN
+ 1;
2289 return circuit_id_val
;
2292 /* Adjacency fully-up */
2293 memcpy(circuit_id_val
, circuit
->u
.p2p
.neighbor
->sysid
,
2295 circuit_id_val
[ISIS_SYS_ID_LEN
] = 0;
2296 *var_len
= ISIS_SYS_ID_LEN
+ 1;
2297 return circuit_id_val
;
2299 case ISIS_CIRCLEVEL_DESIS
:
2300 if (circuit
->circ_type
!= CIRCUIT_T_BROADCAST
2301 || !circuit
->u
.bc
.is_dr
[level
- 1]) {
2303 * Unless it is lan circuit participating in dis process
2304 * the value is an empty octet string
2307 return circuit_id_val
;
2310 *var_len
= ISIS_SYS_ID_LEN
+ 1;
2312 if (level
== IS_LEVEL_1
)
2313 return circuit
->u
.bc
.l1_desig_is
;
2315 return circuit
->u
.bc
.l2_desig_is
;
2317 case ISIS_CIRCLEVEL_HELLOMULTIPLIER
:
2318 return SNMP_INTEGER(circuit
->hello_multiplier
[level
- 1]);
2320 case ISIS_CIRCLEVEL_HELLOTIMER
:
2321 return SNMP_INTEGER(circuit
->hello_interval
[level
- 1] * 1000);
2323 case ISIS_CIRCLEVEL_DRHELLOTIMER
:
2324 return SNMP_INTEGER(circuit
->hello_interval
[level
- 1] * 1000);
2326 case ISIS_CIRCLEVEL_LSPTHROTTLE
:
2328 return SNMP_INTEGER(
2329 circuit
->area
->min_spf_interval
[level
- 1]
2332 return SNMP_INTEGER(0);
2334 case ISIS_CIRCLEVEL_MINLSPRETRANSINT
:
2336 return SNMP_INTEGER(
2337 circuit
->area
->min_spf_interval
[level
- 1]);
2339 return SNMP_INTEGER(0);
2341 case ISIS_CIRCLEVEL_CSNPINTERVAL
:
2342 return SNMP_INTEGER(circuit
->csnp_interval
[level
- 1]);
2344 case ISIS_CIRCLEVEL_PARTSNPINTERVAL
:
2345 return SNMP_INTEGER(circuit
->psnp_interval
[level
- 1]);
2354 static uint8_t *isis_snmp_find_circ_counter(struct variable
*v
, oid
*name
,
2355 size_t *length
, int exact
,
2357 WriteMethod
**write_method
)
2359 /* Index circuit-id 1-255 + level */
2363 struct isis_circuit
*circuit
;
2367 *write_method
= NULL
;
2369 if (*length
<= v
->namelen
) {
2372 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2376 oid_idx
= name
+ v
->namelen
;
2377 oid_idx_len
= *length
- v
->namelen
;
2380 res
= isis_snmp_circuit_level_lookup_exact(oid_idx
, oid_idx_len
,
2381 1, &circuit
, &level
);
2383 if (!res
|| oid_idx_len
!= 2)
2387 res
= isis_snmp_circuit_level_lookup_next(oid_idx
, oid_idx_len
,
2388 1, &circuit
, &level
);
2393 /* Copy the name out */
2394 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2397 name
[v
->namelen
] = circuit
->snmp_id
;
2398 if (circuit
->circ_type
== CIRCUIT_T_P2P
)
2399 name
[v
->namelen
+ 1] = ISIS_SNMP_P2P_CIRCUIT
;
2401 name
[v
->namelen
+ 1] = level
;
2404 *length
= v
->namelen
+ 2;
2408 case ISIS_CIRC_ADJCHANGES
:
2409 val
= circuit
->adj_state_changes
;
2412 case ISIS_CIRC_NUMADJ
:
2413 if (circuit
->circ_type
== CIRCUIT_T_P2P
) {
2414 val
= circuit
->u
.p2p
.neighbor
== NULL
? 0 : 1;
2418 if (circuit
->circ_type
!= CIRCUIT_T_BROADCAST
) {
2423 if (level
== IS_LEVEL_1
) {
2424 if (circuit
->u
.bc
.adjdb
[0] == NULL
)
2427 val
= listcount(circuit
->u
.bc
.adjdb
[0]);
2431 if (circuit
->u
.bc
.adjdb
[1] == NULL
)
2434 val
= listcount(circuit
->u
.bc
.adjdb
[1]);
2438 case ISIS_CIRC_INITFAILS
:
2439 val
= circuit
->init_failures
; /* counter never incremented */
2442 case ISIS_CIRC_REJADJS
:
2443 val
= circuit
->rej_adjacencies
;
2446 case ISIS_CIRC_IDFIELDLENMISMATCHES
:
2447 val
= circuit
->id_len_mismatches
;
2450 case ISIS_CIRC_MAXAREAADDRMISMATCHES
:
2451 val
= circuit
->max_area_addr_mismatches
;
2454 case ISIS_CIRC_AUTHTYPEFAILS
:
2455 val
= circuit
->auth_type_failures
;
2458 case ISIS_CIRC_AUTHFAILS
:
2459 val
= circuit
->auth_failures
;
2462 case ISIS_CIRC_LANDESISCHANGES
:
2463 if (circuit
->circ_type
== CIRCUIT_T_P2P
)
2466 val
= circuit
->desig_changes
[level
- 1];
2473 return SNMP_INTEGER(val
);
2476 static uint8_t *isis_snmp_find_isadj(struct variable
*v
, oid
*name
,
2477 size_t *length
, int exact
, size_t *var_len
,
2478 WriteMethod
**write_method
)
2480 /* Index is circuit-id: 1-255 + adj-id: 1-... */
2485 struct isis_adjacency
*adj
;
2487 uint32_t delta_ticks
;
2490 *write_method
= NULL
;
2492 if (*length
<= v
->namelen
) {
2495 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2499 oid_idx
= name
+ v
->namelen
;
2500 oid_idx_len
= *length
- v
->namelen
;
2503 res
= isis_snmp_adj_lookup_exact(oid_idx
, oid_idx_len
,
2504 ISIS_SNMP_ADJ_DATA_NONE
, &adj
,
2507 if (!res
|| oid_idx_len
!= 2)
2511 res
= isis_snmp_adj_lookup_next(oid_idx
, oid_idx_len
,
2512 ISIS_SNMP_ADJ_DATA_NONE
, &adj
,
2517 /* Copy the name out */
2518 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2521 name
[v
->namelen
] = adj
->circuit
->snmp_id
;
2522 name
[v
->namelen
+ 1] = adj
->snmp_idx
;
2525 *length
= v
->namelen
+ 2;
2529 case ISIS_ISADJ_STATE
:
2530 return SNMP_INTEGER(isis_snmp_adj_state(adj
->adj_state
));
2532 case ISIS_ISADJ_3WAYSTATE
:
2533 return SNMP_INTEGER(adj
->threeway_state
);
2535 case ISIS_ISADJ_NEIGHSNPAADDRESS
: {
2536 const char *snpa
= (char *)snpa_print(adj
->snpa
);
2537 *var_len
= strlen(snpa
);
2538 return (uint8_t *)snpa
;
2541 case ISIS_ISADJ_NEIGHSYSTYPE
:
2542 return SNMP_INTEGER(isis_snmp_adj_neightype(adj
->sys_type
));
2544 case ISIS_ISADJ_NEIGHSYSID
:
2545 *var_len
= sizeof(adj
->sysid
);
2548 case ISIS_ISADJ_NBREXTENDEDCIRCID
:
2549 return SNMP_INTEGER(adj
->ext_circuit_id
!= 0 ? 1 : 0);
2551 case ISIS_ISADJ_USAGE
:
2552 /* It seems that no value conversion is required */
2553 return SNMP_INTEGER(adj
->adj_usage
);
2555 case ISIS_ISADJ_HOLDTIMER
:
2557 * It seems that we want remaining timer
2559 if (adj
->last_upd
!= 0) {
2561 if (val
< (adj
->last_upd
+ adj
->hold_time
))
2562 return SNMP_INTEGER(adj
->last_upd
2563 + adj
->hold_time
- val
);
2565 /* Not running or just expired */
2566 return SNMP_INTEGER(0);
2568 case ISIS_ISADJ_NEIGHPRIORITY
:
2569 return SNMP_INTEGER(adj
->prio
[adj
->level
- 1]);
2571 case ISIS_ISADJ_LASTUPTIME
:
2572 if (adj
->flaps
== 0)
2573 return SNMP_INTEGER(0);
2575 up_ticks
= (uint32_t)netsnmp_get_agent_uptime();
2577 now_time
= time(NULL
);
2579 if (adj
->last_flap
>= now_time
)
2580 return SNMP_INTEGER(up_ticks
);
2582 delta_ticks
= (now_time
- adj
->last_flap
) * 10;
2584 if (up_ticks
< delta_ticks
)
2585 return SNMP_INTEGER(up_ticks
);
2587 return SNMP_INTEGER(up_ticks
- delta_ticks
);
2596 static uint8_t *isis_snmp_find_isadj_area(struct variable
*v
, oid
*name
,
2597 size_t *length
, int exact
,
2599 WriteMethod
**write_method
)
2601 /* Index circuit-id: 1-255 + adj-id: 1-... */
2605 struct isis_adjacency
*adj
;
2610 *write_method
= NULL
;
2612 if (*length
<= v
->namelen
) {
2615 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2619 oid_idx
= name
+ v
->namelen
;
2620 oid_idx_len
= *length
- v
->namelen
;
2623 res
= isis_snmp_adj_lookup_exact(oid_idx
, oid_idx_len
,
2624 ISIS_SNMP_ADJ_DATA_AREA_ADDR
,
2625 &adj
, NULL
, &data
, &data_len
);
2627 if (!res
|| oid_idx_len
!= 3)
2631 res
= isis_snmp_adj_lookup_next(
2632 oid_idx
, oid_idx_len
, ISIS_SNMP_ADJ_DATA_AREA_ADDR
,
2633 &adj
, &data_idx
, &data
, &data_len
);
2637 /* Copy the name out */
2638 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2641 name
[v
->namelen
] = adj
->circuit
->snmp_id
;
2642 name
[v
->namelen
+ 1] = adj
->snmp_idx
;
2643 name
[v
->namelen
+ 2] = data_idx
;
2646 *length
= v
->namelen
+ 3;
2650 case ISIS_ISADJAREA_ADDRESS
:
2651 *var_len
= data_len
;
2661 static uint8_t *isis_snmp_find_isadj_ipaddr(struct variable
*v
, oid
*name
,
2662 size_t *length
, int exact
,
2664 WriteMethod
**write_method
)
2666 /* Index circuit-id 1-255 + adj-id 1-... */
2670 struct isis_adjacency
*adj
;
2675 *write_method
= NULL
;
2677 if (*length
<= v
->namelen
) {
2680 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2684 oid_idx
= name
+ v
->namelen
;
2685 oid_idx_len
= *length
- v
->namelen
;
2688 res
= isis_snmp_adj_lookup_exact(oid_idx
, oid_idx_len
,
2689 ISIS_SNMP_ADJ_DATA_IP_ADDR
,
2690 &adj
, NULL
, &data
, &data_len
);
2692 if (!res
|| oid_idx_len
!= 3)
2695 res
= isis_snmp_adj_lookup_next(
2696 oid_idx
, oid_idx_len
, ISIS_SNMP_ADJ_DATA_IP_ADDR
, &adj
,
2697 &data_idx
, &data
, &data_len
);
2701 /* Copy the name out */
2702 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2705 name
[v
->namelen
] = adj
->circuit
->snmp_id
;
2706 name
[v
->namelen
+ 1] = adj
->snmp_idx
;
2707 name
[v
->namelen
+ 2] = data_idx
;
2710 *length
= v
->namelen
+ 3;
2714 case ISIS_ISADJIPADDR_TYPE
:
2716 return SNMP_INTEGER(ISIS_SNMP_INET_TYPE_V4
);
2718 return SNMP_INTEGER(ISIS_SNMP_INET_TYPE_V6
);
2720 case ISIS_ISADJIPADDR_ADDRESS
:
2721 *var_len
= data_len
;
2731 static uint8_t *isis_snmp_find_isadj_prot_supp(struct variable
*v
, oid
*name
,
2732 size_t *length
, int exact
,
2734 WriteMethod
**write_method
)
2736 /* Index circuit-id 1-255 + adj-id 1-... */
2740 struct isis_adjacency
*adj
;
2745 *write_method
= NULL
;
2747 if (*length
<= v
->namelen
) {
2750 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2754 oid_idx
= name
+ v
->namelen
;
2755 oid_idx_len
= *length
- v
->namelen
;
2758 res
= isis_snmp_adj_lookup_exact(oid_idx
, oid_idx_len
,
2759 ISIS_SNMP_ADJ_DATA_PROTO
, &adj
,
2760 NULL
, &data
, &data_len
);
2762 if (!res
|| oid_idx_len
!= 3)
2766 res
= isis_snmp_adj_lookup_next(oid_idx
, oid_idx_len
,
2767 ISIS_SNMP_ADJ_DATA_PROTO
, &adj
,
2768 &data_idx
, &data
, &data_len
);
2772 /* Copy the name out */
2773 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2776 name
[v
->namelen
] = adj
->circuit
->snmp_id
;
2777 name
[v
->namelen
+ 1] = adj
->snmp_idx
;
2778 name
[v
->namelen
+ 2] = data_idx
;
2781 *length
= v
->namelen
+ 3;
2785 case ISIS_ISADJPROTSUPP_PROTOCOL
:
2786 return SNMP_INTEGER(*data
);
2796 /* Register ISIS-MIB. */
2797 static int isis_snmp_init(struct thread_master
*tm
)
2799 struct isis_func_to_prefix
*h2f
= isis_func_to_prefix_arr
;
2802 for (size_t off
= 0; off
< isis_var_count
; off
++) {
2803 v
= &isis_var_arr
[off
];
2805 if (v
->findVar
!= h2f
->ihtp_func
) {
2808 assert(h2f
< (isis_func_to_prefix_arr
2809 + isis_func_to_prefix_count
));
2810 assert(v
->findVar
== h2f
->ihtp_func
);
2813 v
->namelen
= h2f
->ihtp_pref_len
+ 1;
2814 memcpy(v
->name
, h2f
->ihtp_pref_oid
,
2815 h2f
->ihtp_pref_len
* sizeof(oid
));
2816 v
->name
[h2f
->ihtp_pref_len
] = v
->magic
;
2821 REGISTER_MIB("mibII/isis", isis_var_arr
, variable
, isis_oid
);
2826 * ISIS notification functions: we have one function per notification
2828 static int isis_snmp_trap_throttle(oid trap_id
)
2831 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
2833 if (isis
== NULL
|| !isis
->snmp_notifications
|| !smux_enabled())
2836 time_now
= time(NULL
);
2838 if ((isis_snmp_trap_timestamp
[trap_id
] + 5) > time_now
)
2839 /* Throttle trap rate at 1 in 5 secs */
2842 isis_snmp_trap_timestamp
[trap_id
] = time_now
;
2846 static int isis_snmp_db_overload_update(const struct isis_area
*area
)
2848 netsnmp_variable_list
*notification_vars
;
2852 if (!isis_snmp_trap_throttle(ISIS_TRAP_DB_OVERLOAD
))
2855 notification_vars
= NULL
;
2857 /* Put in trap value */
2858 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
2859 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
2860 (uint8_t *)&isis_snmp_trap_val_db_overload
,
2861 sizeof(isis_snmp_trap_val_db_overload
));
2864 val
= area
->is_type
;
2866 snmp_varlist_add_variable(
2867 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
2868 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
2869 (uint8_t *)&val
, sizeof(val
));
2871 /* Patch sys_level_state with proper index */
2872 off
= ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state
) - 1;
2873 isis_snmp_trap_data_var_sys_level_state
[off
] = val
;
2876 if (area
->overload_bit
)
2877 val
= ISIS_SNMP_LEVEL_STATE_OVERLOADED
;
2879 val
= ISIS_SNMP_LEVEL_STATE_ON
;
2881 snmp_varlist_add_variable(
2882 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_state
,
2883 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state
), INTEGER
,
2884 (uint8_t *)&val
, sizeof(val
));
2886 send_v2trap(notification_vars
);
2887 snmp_free_varbind(notification_vars
);
2888 smux_events_update();
2892 static int isis_snmp_lsp_exceed_max_update(const struct isis_area
*area
,
2893 const uint8_t *lsp_id
)
2895 netsnmp_variable_list
*notification_vars
;
2898 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_EXCEED_MAX
))
2901 notification_vars
= NULL
;
2903 /* Put in trap value */
2904 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
2905 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
2906 (uint8_t *)&isis_snmp_trap_val_lsp_exceed_max
,
2907 sizeof(isis_snmp_trap_val_lsp_exceed_max
));
2910 val
= area
->is_type
;
2912 snmp_varlist_add_variable(
2913 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
2914 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
2915 (uint8_t *)&val
, sizeof(val
));
2917 snmp_varlist_add_variable(
2918 ¬ification_vars
, isis_snmp_trap_data_var_pdu_lsp_id
,
2919 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
2920 ISIS_SYS_ID_LEN
+ 2);
2922 send_v2trap(notification_vars
);
2923 snmp_free_varbind(notification_vars
);
2924 smux_events_update();
2930 * A common function to handle popular combination of trap objects
2931 * isisNotificationSysLevelIndex,
2933 * isisNotificationCircIfIndex,
2936 static void isis_snmp_update_worker_a(const struct isis_circuit
*circuit
,
2937 oid trap_id
, const oid
*oid_a
,
2938 size_t oid_a_len
, uint8_t type_a
,
2939 const void *data_a
, size_t data_a_len
,
2940 const oid
*oid_b
, size_t oid_b_len
,
2941 uint8_t type_b
, const void *data_b
,
2944 netsnmp_variable_list
*notification_vars
= NULL
;
2945 oid var_name
[MAX_OID_LEN
];
2950 if (trap_id
!= ISIS_TRAP_ID_LEN_MISMATCH
2951 && trap_id
!= ISIS_TRAP_MAX_AREA_ADDR_MISMATCH
2952 && trap_id
!= ISIS_TRAP_OWN_LSP_PURGE
2953 && trap_id
!= ISIS_TRAP_SEQNO_SKIPPED
2954 && trap_id
!= ISIS_TRAP_AUTHEN_TYPE_FAILURE
2955 && trap_id
!= ISIS_TRAP_AUTHEN_FAILURE
2956 && trap_id
!= ISIS_TRAP_REJ_ADJACENCY
)
2959 /* Put in trap value */
2960 memcpy(var_name
, isis_snmp_notifications
,
2961 sizeof(isis_snmp_notifications
));
2962 var_count
= ARRAY_SIZE(isis_snmp_notifications
);
2963 var_name
[var_count
++] = trap_id
;
2965 /* Put in trap value */
2966 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
2967 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
2968 (uint8_t *)var_name
, var_count
* sizeof(oid
));
2970 val
= circuit
->is_type
;
2971 snmp_varlist_add_variable(
2972 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
2973 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
2974 (uint8_t *)&val
, sizeof(val
));
2976 if (oid_a_len
!= 0) {
2977 if (oid_a
== NULL
|| data_a
== NULL
|| data_a_len
== 0)
2980 snmp_varlist_add_variable(¬ification_vars
, oid_a
, oid_a_len
,
2981 type_a
, (uint8_t *)data_a
,
2985 if (circuit
->interface
== NULL
)
2988 val
= circuit
->interface
->ifindex
;
2990 snmp_varlist_add_variable(
2991 ¬ification_vars
, isis_snmp_trap_data_var_circ_if_index
,
2992 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index
), UNSIGNED32
,
2993 (uint8_t *)&val
, sizeof(val
));
2996 if (oid_b_len
!= 0) {
2997 if (oid_b
== NULL
|| data_b
== NULL
|| data_b_len
== 0)
3000 snmp_varlist_add_variable(¬ification_vars
, oid_b
, oid_b_len
,
3001 type_b
, (uint8_t *)data_b
,
3005 send_v2trap(notification_vars
);
3006 snmp_free_varbind(notification_vars
);
3007 smux_events_update();
3011 * A common function to handle popular combination of trap objects
3012 * isisNotificationSysLevelIndex,
3013 * isisNotificationCircIfIndex,
3017 * Note: the only difference with worker_a is order of circ-if-index vs
3020 static void isis_snmp_update_worker_b(const struct isis_circuit
*circuit
,
3021 oid trap_id
, const oid
*oid_a
,
3022 size_t oid_a_len
, uint8_t type_a
,
3023 const void *data_a
, size_t data_a_len
,
3024 const oid
*oid_b
, size_t oid_b_len
,
3025 uint8_t type_b
, const void *data_b
,
3028 netsnmp_variable_list
*notification_vars
= NULL
;
3029 oid var_name
[MAX_OID_LEN
];
3034 if (trap_id
!= ISIS_TRAP_VERSION_SKEW
3035 && trap_id
!= ISIS_TRAP_LSP_TOO_LARGE
3036 && trap_id
!= ISIS_TRAP_ADJ_STATE_CHANGE
)
3039 /* Put in trap value */
3040 memcpy(var_name
, isis_snmp_notifications
,
3041 sizeof(isis_snmp_notifications
));
3042 var_count
= ARRAY_SIZE(isis_snmp_notifications
);
3043 var_name
[var_count
++] = trap_id
;
3045 /* Put in trap value */
3046 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
3047 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
3048 (uint8_t *)var_name
, var_count
* sizeof(oid
));
3050 val
= circuit
->is_type
;
3051 snmp_varlist_add_variable(
3052 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
3053 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
3054 (uint8_t *)&val
, sizeof(val
));
3056 if (circuit
->interface
== NULL
)
3059 val
= circuit
->interface
->ifindex
;
3061 snmp_varlist_add_variable(
3062 ¬ification_vars
, isis_snmp_trap_data_var_circ_if_index
,
3063 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index
), UNSIGNED32
,
3064 (uint8_t *)&val
, sizeof(val
));
3067 if (oid_a_len
!= 0) {
3068 if (oid_a
== NULL
|| data_a
== NULL
|| data_a_len
== 0)
3071 snmp_varlist_add_variable(¬ification_vars
, oid_a
, oid_a_len
,
3072 type_a
, (uint8_t *)data_a
,
3076 if (oid_b_len
!= 0) {
3077 if (oid_b
== NULL
|| data_b
== NULL
|| data_b_len
== 0)
3080 snmp_varlist_add_variable(¬ification_vars
, oid_b
, oid_b_len
,
3081 type_b
, (uint8_t *)data_b
,
3085 send_v2trap(notification_vars
);
3086 snmp_free_varbind(notification_vars
);
3087 smux_events_update();
3091 static int isis_snmp_id_len_mismatch_update(const struct isis_circuit
*circuit
,
3092 uint8_t rcv_id
, const char *raw_pdu
,
3097 if (!isis_snmp_trap_throttle(ISIS_TRAP_ID_LEN_MISMATCH
))
3102 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3103 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3105 isis_snmp_update_worker_a(
3106 circuit
, ISIS_TRAP_ID_LEN_MISMATCH
,
3107 isis_snmp_trap_data_var_pdu_field_len
,
3108 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_field_len
), UNSIGNED32
,
3109 &val
, sizeof(val
), isis_snmp_trap_data_var_pdu_fragment
,
3110 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3111 raw_pdu
, raw_pdu_len
);
3116 isis_snmp_max_area_addr_mismatch_update(const struct isis_circuit
*circuit
,
3117 uint8_t max_addrs
, const char *raw_pdu
,
3122 if (!isis_snmp_trap_throttle(ISIS_TRAP_MAX_AREA_ADDR_MISMATCH
))
3127 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3128 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3130 isis_snmp_update_worker_a(
3131 circuit
, ISIS_TRAP_MAX_AREA_ADDR_MISMATCH
,
3132 isis_snmp_trap_data_var_pdu_max_area_addr
,
3133 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_max_area_addr
),
3134 UNSIGNED32
, &val
, sizeof(val
),
3135 isis_snmp_trap_data_var_pdu_fragment
,
3136 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3137 raw_pdu
, raw_pdu_len
);
3141 static int isis_snmp_own_lsp_purge_update(const struct isis_circuit
*circuit
,
3142 const uint8_t *lsp_id
)
3144 if (!isis_snmp_trap_throttle(ISIS_TRAP_OWN_LSP_PURGE
))
3147 isis_snmp_update_worker_a(
3148 circuit
, ISIS_TRAP_OWN_LSP_PURGE
, NULL
, 0, STRING
, NULL
, 0,
3149 isis_snmp_trap_data_var_pdu_lsp_id
,
3150 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3151 ISIS_SYS_ID_LEN
+ 2);
3155 static int isis_snmp_seqno_skipped_update(const struct isis_circuit
*circuit
,
3156 const uint8_t *lsp_id
)
3158 if (!isis_snmp_trap_throttle(ISIS_TRAP_SEQNO_SKIPPED
))
3161 isis_snmp_update_worker_a(
3162 circuit
, ISIS_TRAP_SEQNO_SKIPPED
, NULL
, 0, STRING
, NULL
, 0,
3163 isis_snmp_trap_data_var_pdu_lsp_id
,
3164 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3165 ISIS_SYS_ID_LEN
+ 2);
3170 isis_snmp_authentication_type_failure_update(const struct isis_circuit
*circuit
,
3171 const char *raw_pdu
,
3174 if (!isis_snmp_trap_throttle(ISIS_TRAP_AUTHEN_TYPE_FAILURE
))
3177 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3178 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3180 isis_snmp_update_worker_a(
3181 circuit
, ISIS_TRAP_AUTHEN_TYPE_FAILURE
, NULL
, 0, STRING
, NULL
,
3182 0, isis_snmp_trap_data_var_pdu_fragment
,
3183 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3184 raw_pdu
, raw_pdu_len
);
3189 isis_snmp_authentication_failure_update(const struct isis_circuit
*circuit
,
3190 char const *raw_pdu
, size_t raw_pdu_len
)
3192 if (!isis_snmp_trap_throttle(ISIS_TRAP_AUTHEN_FAILURE
))
3195 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3196 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3198 isis_snmp_update_worker_a(
3199 circuit
, ISIS_TRAP_AUTHEN_FAILURE
, NULL
, 0, STRING
, NULL
, 0,
3200 isis_snmp_trap_data_var_pdu_fragment
,
3201 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3202 raw_pdu
, raw_pdu_len
);
3206 static int isis_snmp_version_skew_update(const struct isis_circuit
*circuit
,
3207 uint8_t version
, const char *raw_pdu
,
3212 if (!isis_snmp_trap_throttle(ISIS_TRAP_VERSION_SKEW
))
3217 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3218 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3220 isis_snmp_update_worker_b(
3221 circuit
, ISIS_TRAP_VERSION_SKEW
,
3222 isis_snmp_trap_data_var_pdu_proto_ver
,
3223 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_proto_ver
), UNSIGNED32
,
3224 &val
, sizeof(val
), isis_snmp_trap_data_var_pdu_fragment
,
3225 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3226 raw_pdu
, raw_pdu_len
);
3230 static int isis_snmp_area_mismatch_update(const struct isis_circuit
*circuit
,
3231 const char *raw_pdu
,
3235 * This is a special case because
3236 * it does not include isisNotificationSysLevelIndex
3238 netsnmp_variable_list
*notification_vars
;
3241 if (!isis_snmp_trap_throttle(ISIS_TRAP_AREA_MISMATCH
))
3244 notification_vars
= NULL
;
3246 /* Put in trap value */
3247 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
3248 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
3249 (uint8_t *)&isis_snmp_trap_val_area_mismatch
,
3250 sizeof(isis_snmp_trap_val_area_mismatch
));
3253 if (circuit
->interface
== NULL
)
3256 val
= circuit
->interface
->ifindex
;
3258 snmp_varlist_add_variable(
3259 ¬ification_vars
, isis_snmp_trap_data_var_circ_if_index
,
3260 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index
), UNSIGNED32
,
3261 (uint8_t *)&val
, sizeof(val
));
3264 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3265 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3267 snmp_varlist_add_variable(
3268 ¬ification_vars
, isis_snmp_trap_data_var_pdu_fragment
,
3269 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3270 raw_pdu
, raw_pdu_len
);
3272 send_v2trap(notification_vars
);
3273 snmp_free_varbind(notification_vars
);
3274 smux_events_update();
3279 static int isis_snmp_reject_adjacency_update(const struct isis_circuit
*circuit
,
3280 const char *raw_pdu
,
3283 if (!isis_snmp_trap_throttle(ISIS_TRAP_REJ_ADJACENCY
))
3286 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3287 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3289 isis_snmp_update_worker_a(
3290 circuit
, ISIS_TRAP_REJ_ADJACENCY
, NULL
, 0, STRING
, NULL
, 0,
3291 isis_snmp_trap_data_var_pdu_fragment
,
3292 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3293 raw_pdu
, raw_pdu_len
);
3297 static int isis_snmp_lsp_too_large_update(const struct isis_circuit
*circuit
,
3299 const uint8_t *lsp_id
)
3301 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_TOO_LARGE
))
3304 isis_snmp_update_worker_b(
3305 circuit
, ISIS_TRAP_LSP_TOO_LARGE
,
3306 isis_snmp_trap_data_var_pdu_lsp_size
,
3307 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_size
), UNSIGNED32
,
3308 &pdu_size
, sizeof(pdu_size
), isis_snmp_trap_data_var_pdu_lsp_id
,
3309 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3310 ISIS_SYS_ID_LEN
+ 2);
3315 static int isis_snmp_adj_state_change_update(const struct isis_adjacency
*adj
)
3317 uint8_t lsp_id
[ISIS_SYS_ID_LEN
+ 2];
3319 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
3321 if (isis
== NULL
|| !isis
->snmp_notifications
|| !smux_enabled())
3325 memcpy(lsp_id
, adj
->sysid
, ISIS_SYS_ID_LEN
);
3326 lsp_id
[ISIS_SYS_ID_LEN
] = 0;
3327 lsp_id
[ISIS_SYS_ID_LEN
+ 1] = 0;
3329 val
= isis_snmp_adj_state(adj
->adj_state
);
3331 isis_snmp_update_worker_b(
3332 adj
->circuit
, ISIS_TRAP_ADJ_STATE_CHANGE
,
3333 isis_snmp_trap_data_var_pdu_lsp_id
,
3334 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3335 ISIS_SYS_ID_LEN
+ 2, isis_snmp_trap_data_var_adj_state
,
3336 ARRAY_SIZE(isis_snmp_trap_data_var_adj_state
), INTEGER
, &val
,
3341 static int isis_snmp_lsp_error_update(const struct isis_circuit
*circuit
,
3342 const uint8_t *lsp_id
,
3343 char const *raw_pdu
, size_t raw_pdu_len
)
3346 * This is a special case because
3347 * it have more variables
3349 netsnmp_variable_list
*notification_vars
;
3352 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_ERROR
))
3355 notification_vars
= NULL
;
3357 /* Put in trap value */
3358 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
3359 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
3360 (uint8_t *)&isis_snmp_trap_val_lsp_error
,
3361 sizeof(isis_snmp_trap_val_lsp_error
));
3364 val
= circuit
->is_type
;
3366 snmp_varlist_add_variable(
3367 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
3368 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
3369 (uint8_t *)&val
, sizeof(val
));
3372 snmp_varlist_add_variable(
3373 ¬ification_vars
, isis_snmp_trap_data_var_pdu_lsp_id
,
3374 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3375 ISIS_SYS_ID_LEN
+ 2);
3378 if (circuit
->interface
== NULL
)
3381 val
= circuit
->interface
->ifindex
;
3383 snmp_varlist_add_variable(
3384 ¬ification_vars
, isis_snmp_trap_data_var_circ_if_index
,
3385 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index
), UNSIGNED32
,
3386 (uint8_t *)&val
, sizeof(val
));
3389 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3390 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3392 snmp_varlist_add_variable(
3393 ¬ification_vars
, isis_snmp_trap_data_var_pdu_fragment
,
3394 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3395 raw_pdu
, raw_pdu_len
);
3400 snmp_varlist_add_variable(
3401 ¬ification_vars
, isis_snmp_trap_data_var_error_offset
,
3402 ARRAY_SIZE(isis_snmp_trap_data_var_error_offset
), UNSIGNED32
,
3403 (uint8_t *)&val
, sizeof(val
));
3408 snmp_varlist_add_variable(
3409 ¬ification_vars
, isis_snmp_trap_data_var_error_tlv_type
,
3410 ARRAY_SIZE(isis_snmp_trap_data_var_error_tlv_type
), UNSIGNED32
,
3411 (uint8_t *)&val
, sizeof(val
));
3413 send_v2trap(notification_vars
);
3414 snmp_free_varbind(notification_vars
);
3415 smux_events_update();
3420 static int isis_snmp_module_init(void)
3422 hook_register(isis_hook_db_overload
, isis_snmp_db_overload_update
);
3423 hook_register(isis_hook_lsp_exceed_max
,
3424 isis_snmp_lsp_exceed_max_update
);
3425 hook_register(isis_hook_id_len_mismatch
,
3426 isis_snmp_id_len_mismatch_update
);
3427 hook_register(isis_hook_max_area_addr_mismatch
,
3428 isis_snmp_max_area_addr_mismatch_update
);
3429 hook_register(isis_hook_own_lsp_purge
, isis_snmp_own_lsp_purge_update
);
3430 hook_register(isis_hook_seqno_skipped
, isis_snmp_seqno_skipped_update
);
3431 hook_register(isis_hook_authentication_type_failure
,
3432 isis_snmp_authentication_type_failure_update
);
3433 hook_register(isis_hook_authentication_failure
,
3434 isis_snmp_authentication_failure_update
);
3435 hook_register(isis_hook_version_skew
, isis_snmp_version_skew_update
);
3436 hook_register(isis_hook_area_mismatch
, isis_snmp_area_mismatch_update
);
3437 hook_register(isis_hook_reject_adjacency
,
3438 isis_snmp_reject_adjacency_update
);
3439 hook_register(isis_hook_lsp_too_large
, isis_snmp_lsp_too_large_update
);
3440 hook_register(isis_hook_adj_state_change
,
3441 isis_snmp_adj_state_change_update
);
3442 hook_register(isis_hook_lsp_error
, isis_snmp_lsp_error_update
);
3443 hook_register(isis_circuit_new_hook
, isis_circuit_snmp_id_gen
);
3444 hook_register(isis_circuit_del_hook
, isis_circuit_snmp_id_free
);
3446 hook_register(frr_late_init
, isis_snmp_init
);
3451 .name
= "isis_snmp",
3452 .version
= FRR_VERSION
,
3453 .description
= "isis AgentX SNMP module",
3454 .init
= isis_snmp_module_init
,