3 * Copyright (C) 2020 Volta Networks, Inc.
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)
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
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
22 * This is minimal read-only implementations providing isisReadOnlyCompliance
27 #include <net-snmp/net-snmp-config.h>
28 #include <net-snmp/net-snmp-includes.h>
39 #include "lib/version.h"
41 #include "isisd/isis_constants.h"
42 #include "isisd/isis_common.h"
43 #include "isisd/isis_flags.h"
44 #include "isisd/isis_circuit.h"
45 #include "isisd/isis_lsp.h"
46 #include "isisd/isis_pdu.h"
47 #include "isisd/isis_network.h"
48 #include "isisd/isis_misc.h"
49 #include "isisd/isis_constants.h"
50 #include "isisd/isis_adjacency.h"
51 #include "isisd/isis_dynhn.h"
52 #include "isisd/isis_te.h"
53 #include "isisd/isis_dr.h"
54 #include "isisd/isis_nb.h"
55 #include "isisd/isisd.h"
58 #define ISIS_MIB 1, 3, 6, 1, 2, 1, 138
60 #define ISIS_OBJECTS 1
61 #define ISIS_SYSTEM 1, 1
62 #define ISIS_SYSLEVEL 1, 2
63 #define ISIS_CIRC 1, 3
64 #define ISIS_CIRC_LEVEL_VALUES 1, 4
65 #define ISIS_COUNTERS 1, 5
66 #define ISIS_ISADJ 1, 6
68 /************************ isisSystemGroup ************************/
71 #define ISIS_SYS_OBJECT 1, 1, 1
72 #define ISIS_SYS_VERSION 1
73 #define ISIS_SYS_LEVELTYPE 2
75 #define ISIS_SYS_MAXPATHSPLITS 4
76 #define ISIS_SYS_MAXLSPGENINT 5
77 #define ISIS_SYS_POLLESHELLORATE 6
78 #define ISIS_SYS_WAITTIME 7
79 #define ISIS_SYS_ADMINSTATE 8
80 #define ISIS_SYS_L2TOL1LEAKING 9
81 #define ISIS_SYS_MAXAGE 10
82 #define ISIS_SYS_RECEIVELSPBUFFERSIZE 11
83 #define ISIS_SYS_PROTSUPPORTED 12
84 #define ISIS_SYS_NOTIFICATIONENABLE 13
86 /* isisManAreaAddrEntry */
87 #define ISIS_MANAREA_ADDRENTRY 1, 1, 2, 1
88 #define ISIS_MANAREA_ADDREXISTSTATE 2
90 /* isisAreaAddrEntry */
91 #define ISIS_AREA_ADDRENTRY 1, 1, 3, 1
92 #define ISIS_AREA_ADDR 1
94 /* isisSummAddrEntry */
95 #define ISIS_SUMM_ADDRENTRY 1, 1, 4, 1
96 #define ISIS_SUMM_ADDREXISTSTATE 4
97 #define ISIS_SUMM_ADDRMETRIC 5
98 #define ISIS_SUMM_ADDRFULLMETRIC 6
100 /* isisRedistributeAddrEntry */
101 #define ISIS_REDISTRIBUTE_ADDRENTRY 1, 1, 5, 1
102 #define ISIS_REDISTRIBUTE_ADDREXISTSTATE 3
104 /* isisRouterEntry */
105 #define ISIS_ROUTER_ENTRY 1, 1, 6, 1
106 #define ISIS_ROUTER_HOSTNAME 3
107 #define ISIS_ROUTER_ID 4
109 /* isisSysLevelTable */
110 #define ISIS_SYSLEVEL_ENTRY 1, 2, 1, 1
111 #define ISIS_SYSLEVEL_ORIGLSPBUFFSIZE 2
112 #define ISIS_SYSLEVEL_MINLSPGENINT 3
113 #define ISIS_SYSLEVEL_STATE 4
114 #define ISIS_SYSLEVEL_SETOVERLOAD 5
115 #define ISIS_SYSLEVEL_SETOVERLOADUNTIL 6
116 #define ISIS_SYSLEVEL_METRICSTYLE 7
117 #define ISIS_SYSLEVEL_SPFCONSIDERS 8
118 #define ISIS_SYSLEVEL_TEENABLED 9
121 /* isisSystemCounterEntry */
122 #define ISIS_SYSTEM_COUNTER_ENTRY 1, 5, 1, 1
123 #define ISIS_SYSSTAT_CORRLSPS 2
124 #define ISIS_SYSSTAT_AUTHTYPEFAILS 3
125 #define ISIS_SYSSTAT_AUTHFAILS 4
126 #define ISIS_SYSSTAT_LSPDBASEOLOADS 5
127 #define ISIS_SYSSTAT_MANADDRDROPFROMAREAS 6
128 #define ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS 7
129 #define ISIS_SYSSTAT_SEQNUMSKIPS 8
130 #define ISIS_SYSSTAT_OWNLSPPURGES 9
131 #define ISIS_SYSSTAT_IDFIELDLENMISMATCHES 10
132 #define ISIS_SYSSTAT_PARTCHANGES 11
133 #define ISIS_SYSSTAT_SPFRUNS 12
134 #define ISIS_SYSSTAT_LSPERRORS 13
137 /************************ isisCircuitGroup ************************/
139 /* Scalar directly under isisCirc */
140 #define ISIS_NEXTCIRC_INDEX 1
143 #define ISIS_CIRC_ENTRY 1, 3, 2, 1
144 #define ISIS_CIRC_IFINDEX 2
145 #define ISIS_CIRC_ADMINSTATE 3
146 #define ISIS_CIRC_EXISTSTATE 4
147 #define ISIS_CIRC_TYPE 5
148 #define ISIS_CIRC_EXTDOMAIN 6
149 #define ISIS_CIRC_LEVELTYPE 7
150 #define ISIS_CIRC_PASSIVECIRCUIT 8
151 #define ISIS_CIRC_MESHGROUPENABLED 9
152 #define ISIS_CIRC_MESHGROUP 10
153 #define ISIS_CIRC_SMALLHELLOS 11
154 #define ISIS_CIRC_LASTUPTIME 12
155 #define ISIS_CIRC_3WAYENABLED 13
156 #define ISIS_CIRC_EXTENDEDCIRCID 14
158 /* isisCircLevelEntry */
159 #define ISIS_CIRCLEVEL_ENTRY 1, 4, 1, 1
160 #define ISIS_CIRCLEVEL_METRIC 2
161 #define ISIS_CIRCLEVEL_WIDEMETRIC 3
162 #define ISIS_CIRCLEVEL_ISPRIORITY 4
163 #define ISIS_CIRCLEVEL_IDOCTET 5
164 #define ISIS_CIRCLEVEL_ID 6
165 #define ISIS_CIRCLEVEL_DESIS 7
166 #define ISIS_CIRCLEVEL_HELLOMULTIPLIER 8
167 #define ISIS_CIRCLEVEL_HELLOTIMER 9
168 #define ISIS_CIRCLEVEL_DRHELLOTIMER 10
169 #define ISIS_CIRCLEVEL_LSPTHROTTLE 11
170 #define ISIS_CIRCLEVEL_MINLSPRETRANSINT 12
171 #define ISIS_CIRCLEVEL_CSNPINTERVAL 13
172 #define ISIS_CIRCLEVEL_PARTSNPINTERVAL 14
174 /* isisCircuitCounterEntry */
175 #define ISIS_CIRC_COUNTER_ENTRY 1, 5, 2, 1
176 #define ISIS_CIRC_ADJCHANGES 2
177 #define ISIS_CIRC_NUMADJ 3
178 #define ISIS_CIRC_INITFAILS 4
179 #define ISIS_CIRC_REJADJS 5
180 #define ISIS_CIRC_IDFIELDLENMISMATCHES 6
181 #define ISIS_CIRC_MAXAREAADDRMISMATCHES 7
182 #define ISIS_CIRC_AUTHTYPEFAILS 8
183 #define ISIS_CIRC_AUTHFAILS 9
184 #define ISIS_CIRC_LANDESISCHANGES 10
187 /************************ isisISAdjGroup ************************/
190 #define ISIS_ISADJ_ENTRY 1, 6, 1, 1
191 #define ISIS_ISADJ_STATE 2
192 #define ISIS_ISADJ_3WAYSTATE 3
193 #define ISIS_ISADJ_NEIGHSNPAADDRESS 4
194 #define ISIS_ISADJ_NEIGHSYSTYPE 5
195 #define ISIS_ISADJ_NEIGHSYSID 6
196 #define ISIS_ISADJ_NBREXTENDEDCIRCID 7
197 #define ISIS_ISADJ_USAGE 8
198 #define ISIS_ISADJ_HOLDTIMER 9
199 #define ISIS_ISADJ_NEIGHPRIORITY 10
200 #define ISIS_ISADJ_LASTUPTIME 11
202 /* isisISAdjAreadAddrEntry */
203 #define ISIS_ISADJAREA_ADDRENTRY 1, 6, 2, 1
204 #define ISIS_ISADJAREA_ADDRESS 2
206 /* isisISAdjIPAddrEntry*/
207 #define ISIS_ISADJIPADDR_ENTRY 1, 6, 3, 1
208 #define ISIS_ISADJIPADDR_TYPE 2
209 #define ISIS_ISADJIPADDR_ADDRESS 3
212 /* isisISAdjProtSuppEntty */
214 #define ISIS_ISADJPROTSUPP_ENTRY 1, 6, 4, 1
215 #define ISIS_ISADJPROTSUPP_PROTOCOL 1
218 /************************ Trap data variables ************************/
219 #define ISIS_NOTIFICATION_ENTRY 1, 10, 1
220 #define ISIS_NOTIF_SYLELVELINDEX 1
221 #define ISIS_NOTIF_CIRCIFINDEX 2
222 #define ISIS_PDU_LSPID 3
223 #define ISIS_PDU_FRAGMENT 4
224 #define ISIS_PDU_FIELDLEN 5
225 #define ISIS_PDU_MAXAREAADDR 6
226 #define ISIS_PDU_PROTOVER 7
227 #define ISIS_PDU_LSPSIZE 8
228 #define ISIS_PDU_ORIGBUFFERSIZE 9
229 #define ISIS_PDU_BUFFERSIZE 10
230 #define ISIS_PDU_PROTSUPP 11
231 #define ISIS_ADJ_STATE 12
232 #define ISIS_ERROR_OFFSET 13
233 #define ISIS_ERROR_TLVTYPE 14
234 #define ISIS_NOTIF_AREAADDR 15
236 /************************ Traps ************************/
237 #define ISIS_NOTIFICATIONS ISIS_MIB, 0
238 #define ISIS_TRAP_DB_OVERLOAD 1
239 #define ISIS_TRAP_MAN_ADDR_DROP 2
240 #define ISIS_TRAP_CORRUPTED_LSP 3
241 #define ISIS_TRAP_LSP_EXCEED_MAX 4
242 #define ISIS_TRAP_ID_LEN_MISMATCH 5
243 #define ISIS_TRAP_MAX_AREA_ADDR_MISMATCH 6
244 #define ISIS_TRAP_OWN_LSP_PURGE 7
245 #define ISIS_TRAP_SEQNO_SKIPPED 8
246 #define ISIS_TRAP_AUTHEN_TYPE_FAILURE 9
247 #define ISIS_TRAP_AUTHEN_FAILURE 10
248 #define ISIS_TRAP_VERSION_SKEW 11
249 #define ISIS_TRAP_AREA_MISMATCH 12
250 #define ISIS_TRAP_REJ_ADJACENCY 13
251 #define ISIS_TRAP_LSP_TOO_LARGE 14
252 #define ISIS_TRAP_LSP_BUFFSIZE_MISMATCH 15
253 #define ISIS_TRAP_PROTSUPP_MISMATCH 16
254 #define ISIS_TRAP_ADJ_STATE_CHANGE 17
255 #define ISIS_TRAP_LSP_ERROR 18
257 /* Change this definition if number of traps changes */
258 #define ISIS_TRAP_LAST_TRAP ISIS_TRAP_LSP_ERROR + 1
260 #define ISIS_SNMP_TRAP_VAR 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0
263 /* SNMP value hack. */
264 #define COUNTER32 ASN_COUNTER
265 #define INTEGER ASN_INTEGER
266 #define UNSIGNED32 ASN_GAUGE
267 #define TIMESTAMP ASN_TIMETICKS
268 #define TIMETICKS ASN_TIMETICKS
269 #define STRING ASN_OCTET_STR
271 /* Declare static local variables for convenience. */
274 /* If ARRAY_SIZE is not available use a primitive substitution */
276 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
280 * Define time function, it serves two purposes
281 * 1. Uses unint32_t for unix time and encapsulates
282 * sing extension issues in conversion from time_t
284 * 2. I could be replaced in unit test environment
286 #ifndef ISIS_SNMP_HAVE_TIME_FUNC
287 static uint32_t isis_snmp_time(void)
289 return (uint32_t)time(NULL
);
294 /* ISIS-MIB instances. */
295 static oid isis_oid
[] = {ISIS_MIB
};
297 /* SNMP trap variable */
298 static oid isis_snmp_trap_var
[] = {ISIS_SNMP_TRAP_VAR
};
300 /* SNMP trap values (others are calculated on the fly */
301 static oid isis_snmp_notifications
[] = {ISIS_NOTIFICATIONS
};
302 static oid isis_snmp_trap_val_db_overload
[] = {ISIS_NOTIFICATIONS
,
303 ISIS_TRAP_DB_OVERLOAD
};
304 static oid isis_snmp_trap_val_lsp_exceed_max
[] = {ISIS_NOTIFICATIONS
,
305 ISIS_TRAP_LSP_EXCEED_MAX
};
306 static oid isis_snmp_trap_val_area_mismatch
[] = {ISIS_NOTIFICATIONS
,
307 ISIS_TRAP_AREA_MISMATCH
};
308 static oid isis_snmp_trap_val_lsp_error
[] = {ISIS_NOTIFICATIONS
,
309 ISIS_TRAP_LSP_ERROR
};
312 * Trap vars under 'isisNotifications': note: we use full names of variables
315 static oid isis_snmp_trap_data_var_sys_level_index
[] = {
316 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_NOTIF_SYLELVELINDEX
, 0};
317 static oid isis_snmp_trap_data_var_circ_if_index
[] = {
318 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_NOTIF_CIRCIFINDEX
, 0};
319 static oid isis_snmp_trap_data_var_pdu_lsp_id
[] = {
320 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_LSPID
, 0};
321 static oid isis_snmp_trap_data_var_pdu_fragment
[] = {
322 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_FRAGMENT
, 0};
323 static oid isis_snmp_trap_data_var_pdu_field_len
[] = {
324 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_FIELDLEN
, 0};
325 static oid isis_snmp_trap_data_var_pdu_max_area_addr
[] = {
326 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_MAXAREAADDR
, 0};
327 static oid isis_snmp_trap_data_var_pdu_proto_ver
[] = {
328 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_PROTOVER
, 0};
329 static oid isis_snmp_trap_data_var_pdu_lsp_size
[] = {
330 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_PDU_LSPSIZE
, 0};
331 static oid isis_snmp_trap_data_var_adj_state
[] = {
332 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_ADJ_STATE
, 0};
333 static oid isis_snmp_trap_data_var_error_offset
[] = {
334 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_ERROR_OFFSET
, 0};
335 static oid isis_snmp_trap_data_var_error_tlv_type
[] = {
336 ISIS_MIB
, ISIS_NOTIFICATION_ENTRY
, ISIS_ERROR_TLVTYPE
, 0};
339 * Other variables used by traps: note we use full names of variables and
340 * reserve space for index
342 static oid isis_snmp_trap_data_var_sys_level_state
[] = {
343 ISIS_MIB
, ISIS_SYSLEVEL_ENTRY
, ISIS_SYSLEVEL_STATE
, 0};
345 /* Throttle time values for traps */
346 static time_t isis_snmp_trap_timestamp
[ISIS_TRAP_LAST_TRAP
]; /* ?? 1 */
348 /* Max len of raw-pdu in traps */
349 #define ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN (64)
352 * Just to save on typing we have a shortcut structure
353 * to specify mib layout as prefix/leaf combination
355 #define ISIS_SNMP_PREF_LEN_MAX 10
356 struct isis_var_prefix
{
357 FindVarMethod
*findVar
;
358 uint8_t ivd_pref_len
;
359 oid ivd_pref
[ISIS_SNMP_PREF_LEN_MAX
];
363 /* Find-val functions */
364 static uint8_t *isis_snmp_find_sys_object(struct variable
*, oid
*, size_t *,
365 int, size_t *, WriteMethod
**);
367 static uint8_t *isis_snmp_find_man_area(struct variable
*, oid
*, size_t *, int,
368 size_t *, WriteMethod
**);
370 static uint8_t *isis_snmp_find_area_addr(struct variable
*, oid
*, size_t *,
371 int, size_t *, WriteMethod
**);
373 static uint8_t *isis_snmp_find_summ_addr(struct variable
*, oid
*, size_t *,
374 int, size_t *, WriteMethod
**);
376 static uint8_t *isis_snmp_find_redistribute_addr(struct variable
*, oid
*,
377 size_t *, int, size_t *,
380 static uint8_t *isis_snmp_find_router(struct variable
*, oid
*, size_t *, int,
381 size_t *, WriteMethod
**);
383 static uint8_t *isis_snmp_find_sys_level(struct variable
*, oid
*, size_t *,
384 int, size_t *, WriteMethod
**);
386 static uint8_t *isis_snmp_find_system_counter(struct variable
*, oid
*,
387 size_t *, int, size_t *,
390 static uint8_t *isis_snmp_find_next_circ_index(struct variable
*, oid
*,
391 size_t *, int, size_t *,
394 static uint8_t *isis_snmp_find_circ(struct variable
*, oid
*, size_t *, int,
395 size_t *, WriteMethod
**);
397 static uint8_t *isis_snmp_find_circ_level(struct variable
*, oid
*, size_t *,
398 int, size_t *, WriteMethod
**);
400 static uint8_t *isis_snmp_find_circ_counter(struct variable
*, oid
*, size_t *,
401 int, size_t *, WriteMethod
**);
403 static uint8_t *isis_snmp_find_isadj(struct variable
*, oid
*, size_t *, int,
404 size_t *, WriteMethod
**);
406 static uint8_t *isis_snmp_find_isadj_area(struct variable
*, oid
*, size_t *,
407 int, size_t *, WriteMethod
**);
409 static uint8_t *isis_snmp_find_isadj_ipaddr(struct variable
*, oid
*, size_t *,
410 int, size_t *, WriteMethod
**);
412 static uint8_t *isis_snmp_find_isadj_prot_supp(struct variable
*, oid
*,
413 size_t *, int, size_t *,
417 * Just to save on typing we have a shortcut structure
418 * to specify mib layout, we populate the rest of the data
419 * during initialization
421 #define ISIS_PREF_LEN_MAX (6)
423 struct isis_func_to_prefix
{
424 FindVarMethod
*ihtp_func
;
425 oid ihtp_pref_oid
[ISIS_PREF_LEN_MAX
];
426 uint8_t ihtp_pref_len
;
429 static struct isis_func_to_prefix isis_func_to_prefix_arr
[] = {
430 {isis_snmp_find_sys_object
, {ISIS_SYS_OBJECT
}, 3},
431 {isis_snmp_find_man_area
, {ISIS_MANAREA_ADDRENTRY
}, 4},
432 {isis_snmp_find_area_addr
, {ISIS_AREA_ADDRENTRY
}, 4},
433 {isis_snmp_find_summ_addr
, {ISIS_SUMM_ADDRENTRY
}, 4},
434 {isis_snmp_find_redistribute_addr
, {ISIS_REDISTRIBUTE_ADDRENTRY
}, 4},
435 {isis_snmp_find_router
, {ISIS_ROUTER_ENTRY
}, 4},
436 {isis_snmp_find_sys_level
, {ISIS_SYSLEVEL_ENTRY
}, 4},
437 {isis_snmp_find_system_counter
, {ISIS_SYSTEM_COUNTER_ENTRY
}, 4},
438 {isis_snmp_find_next_circ_index
, {ISIS_CIRC
}, 2},
439 {isis_snmp_find_circ
, {ISIS_CIRC_ENTRY
}, 4},
440 {isis_snmp_find_circ_level
, {ISIS_CIRCLEVEL_ENTRY
}, 4},
441 {isis_snmp_find_circ_counter
, {ISIS_CIRC_COUNTER_ENTRY
}, 4},
442 {isis_snmp_find_isadj
, {ISIS_ISADJ_ENTRY
}, 4},
443 {isis_snmp_find_isadj_area
, {ISIS_ISADJAREA_ADDRENTRY
}, 4},
444 {isis_snmp_find_isadj_ipaddr
, {ISIS_ISADJIPADDR_ENTRY
}, 4},
445 {isis_snmp_find_isadj_prot_supp
, {ISIS_ISADJPROTSUPP_ENTRY
}, 4},
447 static size_t isis_func_to_prefix_count
= ARRAY_SIZE(isis_func_to_prefix_arr
);
449 static struct variable isis_var_arr
[] = {
450 {ISIS_SYS_VERSION
, INTEGER
, RONLY
, isis_snmp_find_sys_object
},
451 {ISIS_SYS_LEVELTYPE
, INTEGER
, RONLY
, isis_snmp_find_sys_object
},
452 {ISIS_SYS_ID
, STRING
, RONLY
, isis_snmp_find_sys_object
},
453 {ISIS_SYS_MAXPATHSPLITS
, UNSIGNED32
, RONLY
, isis_snmp_find_sys_object
},
454 {ISIS_SYS_MAXLSPGENINT
, UNSIGNED32
, RONLY
, isis_snmp_find_sys_object
},
455 {ISIS_SYS_POLLESHELLORATE
, UNSIGNED32
, RONLY
,
456 isis_snmp_find_sys_object
},
457 {ISIS_SYS_WAITTIME
, UNSIGNED32
, RONLY
, isis_snmp_find_sys_object
},
458 {ISIS_SYS_ADMINSTATE
, INTEGER
, RONLY
, isis_snmp_find_sys_object
},
459 {ISIS_SYS_L2TOL1LEAKING
, INTEGER
, RONLY
, isis_snmp_find_sys_object
},
460 {ISIS_SYS_MAXAGE
, UNSIGNED32
, RONLY
, isis_snmp_find_sys_object
},
461 {ISIS_SYS_RECEIVELSPBUFFERSIZE
, UNSIGNED32
, RONLY
,
462 isis_snmp_find_sys_object
},
463 {ISIS_SYS_PROTSUPPORTED
, STRING
, RONLY
, isis_snmp_find_sys_object
},
464 {ISIS_SYS_NOTIFICATIONENABLE
, INTEGER
, RONLY
,
465 isis_snmp_find_sys_object
},
466 {ISIS_MANAREA_ADDREXISTSTATE
, INTEGER
, RONLY
, isis_snmp_find_man_area
},
467 {ISIS_AREA_ADDR
, STRING
, RONLY
, isis_snmp_find_area_addr
},
468 {ISIS_SUMM_ADDREXISTSTATE
, INTEGER
, RONLY
, isis_snmp_find_summ_addr
},
469 {ISIS_SUMM_ADDRMETRIC
, UNSIGNED32
, RONLY
, isis_snmp_find_summ_addr
},
470 {ISIS_SUMM_ADDRFULLMETRIC
, UNSIGNED32
, RONLY
, isis_snmp_find_summ_addr
},
471 {ISIS_REDISTRIBUTE_ADDREXISTSTATE
, INTEGER
, RONLY
,
472 isis_snmp_find_redistribute_addr
},
473 {ISIS_ROUTER_HOSTNAME
, STRING
, RONLY
, isis_snmp_find_router
},
474 {ISIS_ROUTER_ID
, UNSIGNED32
, RONLY
, isis_snmp_find_router
},
475 {ISIS_SYSLEVEL_ORIGLSPBUFFSIZE
, UNSIGNED32
, RONLY
,
476 isis_snmp_find_sys_level
},
477 {ISIS_SYSLEVEL_MINLSPGENINT
, UNSIGNED32
, RONLY
,
478 isis_snmp_find_sys_level
},
479 {ISIS_SYSLEVEL_STATE
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
480 {ISIS_SYSLEVEL_SETOVERLOAD
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
481 {ISIS_SYSLEVEL_SETOVERLOADUNTIL
, UNSIGNED32
, RONLY
,
482 isis_snmp_find_sys_level
},
483 {ISIS_SYSLEVEL_METRICSTYLE
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
484 {ISIS_SYSLEVEL_SPFCONSIDERS
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
485 {ISIS_SYSLEVEL_TEENABLED
, INTEGER
, RONLY
, isis_snmp_find_sys_level
},
486 {ISIS_SYSSTAT_CORRLSPS
, COUNTER32
, RONLY
,
487 isis_snmp_find_system_counter
},
488 {ISIS_SYSSTAT_AUTHTYPEFAILS
, COUNTER32
, RONLY
,
489 isis_snmp_find_system_counter
},
490 {ISIS_SYSSTAT_AUTHFAILS
, COUNTER32
, RONLY
,
491 isis_snmp_find_system_counter
},
492 {ISIS_SYSSTAT_LSPDBASEOLOADS
, COUNTER32
, RONLY
,
493 isis_snmp_find_system_counter
},
494 {ISIS_SYSSTAT_MANADDRDROPFROMAREAS
, COUNTER32
, RONLY
,
495 isis_snmp_find_system_counter
},
496 {ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS
, COUNTER32
, RONLY
,
497 isis_snmp_find_system_counter
},
498 {ISIS_SYSSTAT_SEQNUMSKIPS
, COUNTER32
, RONLY
,
499 isis_snmp_find_system_counter
},
500 {ISIS_SYSSTAT_OWNLSPPURGES
, COUNTER32
, RONLY
,
501 isis_snmp_find_system_counter
},
502 {ISIS_SYSSTAT_IDFIELDLENMISMATCHES
, COUNTER32
, RONLY
,
503 isis_snmp_find_system_counter
},
504 {ISIS_SYSSTAT_PARTCHANGES
, COUNTER32
, RONLY
,
505 isis_snmp_find_system_counter
},
506 {ISIS_SYSSTAT_SPFRUNS
, COUNTER32
, RONLY
, isis_snmp_find_system_counter
},
507 {ISIS_SYSSTAT_LSPERRORS
, COUNTER32
, RONLY
,
508 isis_snmp_find_system_counter
},
509 {ISIS_NEXTCIRC_INDEX
, UNSIGNED32
, RONLY
,
510 isis_snmp_find_next_circ_index
},
511 {ISIS_CIRC_IFINDEX
, INTEGER
, RONLY
, isis_snmp_find_circ
},
512 {ISIS_CIRC_ADMINSTATE
, INTEGER
, RONLY
, isis_snmp_find_circ
},
513 {ISIS_CIRC_EXISTSTATE
, INTEGER
, RONLY
, isis_snmp_find_circ
},
514 {ISIS_CIRC_TYPE
, INTEGER
, RONLY
, isis_snmp_find_circ
},
515 {ISIS_CIRC_EXTDOMAIN
, INTEGER
, RONLY
, isis_snmp_find_circ
},
516 {ISIS_CIRC_LEVELTYPE
, INTEGER
, RONLY
, isis_snmp_find_circ
},
517 {ISIS_CIRC_PASSIVECIRCUIT
, INTEGER
, RONLY
, isis_snmp_find_circ
},
518 {ISIS_CIRC_MESHGROUPENABLED
, INTEGER
, RONLY
, isis_snmp_find_circ
},
519 {ISIS_CIRC_MESHGROUP
, UNSIGNED32
, RONLY
, isis_snmp_find_circ
},
520 {ISIS_CIRC_SMALLHELLOS
, INTEGER
, RONLY
, isis_snmp_find_circ
},
521 {ISIS_CIRC_LASTUPTIME
, TIMESTAMP
, RONLY
, isis_snmp_find_circ
},
522 {ISIS_CIRC_3WAYENABLED
, INTEGER
, RONLY
, isis_snmp_find_circ
},
523 {ISIS_CIRC_EXTENDEDCIRCID
, UNSIGNED32
, RONLY
, isis_snmp_find_circ
},
524 {ISIS_CIRCLEVEL_METRIC
, UNSIGNED32
, RONLY
, isis_snmp_find_circ_level
},
525 {ISIS_CIRCLEVEL_WIDEMETRIC
, UNSIGNED32
, RONLY
,
526 isis_snmp_find_circ_level
},
527 {ISIS_CIRCLEVEL_ISPRIORITY
, UNSIGNED32
, RONLY
,
528 isis_snmp_find_circ_level
},
529 {ISIS_CIRCLEVEL_IDOCTET
, UNSIGNED32
, RONLY
, isis_snmp_find_circ_level
},
530 {ISIS_CIRCLEVEL_ID
, STRING
, RONLY
, isis_snmp_find_circ_level
},
531 {ISIS_CIRCLEVEL_DESIS
, STRING
, RONLY
, isis_snmp_find_circ_level
},
532 {ISIS_CIRCLEVEL_HELLOMULTIPLIER
, UNSIGNED32
, RONLY
,
533 isis_snmp_find_circ_level
},
534 {ISIS_CIRCLEVEL_HELLOTIMER
, UNSIGNED32
, RONLY
,
535 isis_snmp_find_circ_level
},
536 {ISIS_CIRCLEVEL_DRHELLOTIMER
, UNSIGNED32
, RONLY
,
537 isis_snmp_find_circ_level
},
538 {ISIS_CIRCLEVEL_LSPTHROTTLE
, UNSIGNED32
, RONLY
,
539 isis_snmp_find_circ_level
},
540 {ISIS_CIRCLEVEL_MINLSPRETRANSINT
, UNSIGNED32
, RONLY
,
541 isis_snmp_find_circ_level
},
542 {ISIS_CIRCLEVEL_CSNPINTERVAL
, UNSIGNED32
, RONLY
,
543 isis_snmp_find_circ_level
},
544 {ISIS_CIRCLEVEL_PARTSNPINTERVAL
, UNSIGNED32
, RONLY
,
545 isis_snmp_find_circ_level
},
546 {ISIS_CIRC_ADJCHANGES
, COUNTER32
, RONLY
, isis_snmp_find_circ_counter
},
547 {ISIS_CIRC_NUMADJ
, UNSIGNED32
, RONLY
, isis_snmp_find_circ_counter
},
548 {ISIS_CIRC_INITFAILS
, COUNTER32
, RONLY
, isis_snmp_find_circ_counter
},
549 {ISIS_CIRC_REJADJS
, COUNTER32
, RONLY
, isis_snmp_find_circ_counter
},
550 {ISIS_CIRC_IDFIELDLENMISMATCHES
, COUNTER32
, RONLY
,
551 isis_snmp_find_circ_counter
},
552 {ISIS_CIRC_MAXAREAADDRMISMATCHES
, COUNTER32
, RONLY
,
553 isis_snmp_find_circ_counter
},
554 {ISIS_CIRC_AUTHTYPEFAILS
, COUNTER32
, RONLY
,
555 isis_snmp_find_circ_counter
},
556 {ISIS_CIRC_AUTHFAILS
, COUNTER32
, RONLY
, isis_snmp_find_circ_counter
},
557 {ISIS_CIRC_LANDESISCHANGES
, COUNTER32
, RONLY
,
558 isis_snmp_find_circ_counter
},
559 {ISIS_ISADJ_STATE
, INTEGER
, RONLY
, isis_snmp_find_isadj
},
560 {ISIS_ISADJ_3WAYSTATE
, INTEGER
, RONLY
, isis_snmp_find_isadj
},
561 {ISIS_ISADJ_NEIGHSNPAADDRESS
, STRING
, RONLY
, isis_snmp_find_isadj
},
562 {ISIS_ISADJ_NEIGHSYSTYPE
, INTEGER
, RONLY
, isis_snmp_find_isadj
},
563 {ISIS_ISADJ_NEIGHSYSID
, STRING
, RONLY
, isis_snmp_find_isadj
},
564 {ISIS_ISADJ_NBREXTENDEDCIRCID
, UNSIGNED32
, RONLY
, isis_snmp_find_isadj
},
565 {ISIS_ISADJ_USAGE
, INTEGER
, RONLY
, isis_snmp_find_isadj
},
566 {ISIS_ISADJ_HOLDTIMER
, UNSIGNED32
, RONLY
, isis_snmp_find_isadj
},
567 {ISIS_ISADJ_NEIGHPRIORITY
, UNSIGNED32
, RONLY
, isis_snmp_find_isadj
},
568 {ISIS_ISADJ_LASTUPTIME
, TIMESTAMP
, RONLY
, isis_snmp_find_isadj
},
569 {ISIS_ISADJAREA_ADDRESS
, STRING
, RONLY
, isis_snmp_find_isadj_area
},
570 {ISIS_ISADJIPADDR_TYPE
, INTEGER
, RONLY
, isis_snmp_find_isadj_ipaddr
},
571 {ISIS_ISADJIPADDR_ADDRESS
, STRING
, RONLY
, isis_snmp_find_isadj_ipaddr
},
572 {ISIS_ISADJPROTSUPP_PROTOCOL
, INTEGER
, RONLY
,
573 isis_snmp_find_isadj_prot_supp
},
576 static const size_t isis_var_count
= ARRAY_SIZE(isis_var_arr
);
578 /* Minimal set of hard-coded data */
579 #define ISIS_VERSION (1)
581 /* If sys-id is not set use this value */
582 static uint8_t isis_null_sysid
[ISIS_SYS_ID_LEN
];
585 #define ISIS_SNMP_OSI_ADDR_LEN_MAX (20)
588 * The implementation has a fixed max-path splits value
589 * of 64 (see ISIS_MAX_PATH_SPLITS), the max mib value
592 * FIXME(aromanov): should we return 32 or 64?
594 #define ISIS_SNMP_MAX_PATH_SPLITS (32)
596 #define ISIS_SNMP_ADMIN_STATE_ON (1)
598 #define ISIS_SNMP_ROW_STATUS_ACTIVE (1)
600 #define ISIS_SNMP_LEVEL_STATE_OFF (1)
601 #define ISIS_SNMP_LEVEL_STATE_ON (2)
602 #define ISIS_SNMP_LEVEL_STATE_WAITING (3)
603 #define ISIS_SNMP_LEVEL_STATE_OVERLOADED (4)
605 #define ISIS_SNMP_TRUTH_VALUE_TRUE (1)
606 #define ISIS_SNMP_TRUTH_VALUE_FALSE (2)
608 #define ISIS_SNMP_METRIC_STYLE_NARROW (1)
609 #define ISIS_SNMP_METRIC_STYLE_WIDE (2)
610 #define ISIS_SNMP_METRIC_STYLE_BOTH (3)
612 #define ISIS_SNMP_MESH_GROUP_INACTIVE (1)
614 #define ISIS_SNMP_ADJ_STATE_DOWN (1)
615 #define ISIS_SNMP_ADJ_STATE_INITIALIZING (2)
616 #define ISIS_SNMP_ADJ_STATE_UP (3)
617 #define ISIS_SNMP_ADJ_STATE_FAILED (4)
619 static inline uint32_t isis_snmp_adj_state(enum isis_adj_state state
)
622 case ISIS_ADJ_UNKNOWN
:
623 return ISIS_SNMP_ADJ_STATE_DOWN
;
624 case ISIS_ADJ_INITIALIZING
:
625 return ISIS_SNMP_ADJ_STATE_INITIALIZING
;
627 return ISIS_SNMP_ADJ_STATE_UP
;
629 return ISIS_SNMP_ADJ_STATE_FAILED
;
632 return 0; /* not reached */
635 #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1 (1)
636 #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2 (2)
637 #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2 (3)
638 #define ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN (4)
640 static inline uint32_t isis_snmp_adj_neightype(enum isis_system_type type
)
643 case ISIS_SYSTYPE_UNKNOWN
:
644 case ISIS_SYSTYPE_ES
:
645 return ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN
;
646 case ISIS_SYSTYPE_IS
:
647 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2
;
648 case ISIS_SYSTYPE_L1_IS
:
649 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1
;
650 case ISIS_SYSTYPE_L2_IS
:
651 return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2
;
654 return 0; /* not reached */
657 #define ISIS_SNMP_INET_TYPE_V4 (1)
658 #define ISIS_SNMP_INET_TYPE_V6 (2)
660 #define ISIS_SNMP_P2P_CIRCUIT (3)
662 /* Protocols supported value */
663 static uint8_t isis_snmp_protocols_supported
= 0x7; /* All: iso, ipv4, ipv6 */
665 #define SNMP_CIRCUITS_MAX (512)
667 static struct isis_circuit
*snmp_circuits
[SNMP_CIRCUITS_MAX
];
668 static uint32_t snmp_circuit_id_last
;
670 static int isis_circuit_snmp_id_gen(struct isis_circuit
*circuit
)
675 id
= snmp_circuit_id_last
;
678 /* find next unused entry */
679 for (i
= 0; i
< SNMP_CIRCUITS_MAX
; i
++) {
680 if (id
>= SNMP_CIRCUITS_MAX
) {
688 if (snmp_circuits
[id
] == NULL
)
694 if (i
== SNMP_CIRCUITS_MAX
) {
695 zlog_warn("Could not allocate a smmp-circuit-id");
699 snmp_circuits
[id
] = circuit
;
700 snmp_circuit_id_last
= id
;
701 circuit
->snmp_id
= id
;
706 static int isis_circuit_snmp_id_free(struct isis_circuit
*circuit
)
708 snmp_circuits
[circuit
->snmp_id
] = NULL
;
709 circuit
->snmp_id
= 0;
714 * Convenience function to move to the next circuit,
716 static struct isis_circuit
*isis_snmp_circuit_next(struct isis_circuit
*circuit
)
724 start
= circuit
->snmp_id
+ 1;
726 for (off
= start
; off
< SNMP_CIRCUITS_MAX
; off
++) {
727 circuit
= snmp_circuits
[off
];
737 * Convenience function to get the first matching level
739 static int isis_snmp_circuit_get_level_lo(struct isis_circuit
*circuit
)
741 if (circuit
->is_type
== IS_LEVEL_2
)
747 /* Check level match */
748 static int isis_snmp_get_level_match(int is_type
, int level
)
750 if (is_type
!= IS_LEVEL_1
&& is_type
!= IS_LEVEL_2
751 && is_type
!= IS_LEVEL_1_AND_2
)
754 if (level
!= IS_LEVEL_1
&& level
!= IS_LEVEL_2
)
758 if (is_type
== IS_LEVEL_1
) {
759 if (level
== IS_LEVEL_1
)
765 if (is_type
== IS_LEVEL_2
) {
766 if (level
== IS_LEVEL_2
)
775 * Helper function to convert oid index representing
776 * octet-string index (e.g. isis-sys-id) to byte string
777 * representing the same index.
779 * Also we do not fail if idx is longer than max_len,
780 * so we can use the same function to check compound
783 static int isis_snmp_conv_exact(uint8_t *buf
, size_t max_len
, size_t *out_len
,
784 const oid
*idx
, size_t idx_len
)
789 /* Oid representation: length followed by bytes */
790 if (idx
== NULL
|| idx_len
== 0)
798 if (idx_len
< len
+ 1)
801 for (off
= 0; off
< len
; off
++) {
802 if (idx
[off
+ 1] > 0xff)
805 buf
[off
] = (uint8_t)(idx
[off
+ 1] & 0xff);
813 static int isis_snmp_conv_next(uint8_t *buf
, size_t max_len
, size_t *out_len
,
814 int *try_exact
, const oid
*idx
, size_t idx_len
)
820 if (idx
== NULL
|| idx_len
== 0) {
833 if ((idx_len
- 1) < cmp_len
)
834 cmp_len
= idx_len
- 1;
836 for (off
= 0; off
< cmp_len
; off
++) {
837 if (idx
[off
+ 1] > 0xff) {
838 memset(buf
+ off
, 0xff, len
- off
);
844 buf
[off
] = (uint8_t)(idx
[off
+ 1] & 0xff);
848 memset(buf
+ cmp_len
, 0, len
- cmp_len
);
851 *try_exact
= cmp_len
< len
? 1 : 0;
856 * Helper functions to find area address from snmp index
858 static int isis_snmp_area_addr_lookup_exact(oid
*oid_idx
, size_t oid_idx_len
,
859 struct isis_area
**ret_area
,
860 struct area_addr
**ret_addr
)
862 uint8_t cmp_buf
[ISIS_SNMP_OSI_ADDR_LEN_MAX
];
864 struct isis_area
*area
= NULL
;
865 struct area_addr
*addr
= NULL
;
866 struct listnode
*addr_node
;
867 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
872 if (list_isempty(isis
->area_list
)) {
873 /* Area is not configured yet */
877 area
= listgetdata(listhead(isis
->area_list
));
879 int res
= isis_snmp_conv_exact(cmp_buf
, sizeof(cmp_buf
), &addr_len
,
880 oid_idx
, oid_idx_len
);
883 if (!res
|| addr_len
== 0 || oid_idx_len
!= (addr_len
+ 1)) {
884 /* Bad conversion, empty address or extra oids at the end */
888 for (ALL_LIST_ELEMENTS_RO(area
->area_addrs
, addr_node
, addr
)) {
889 if (addr
->addr_len
!= addr_len
)
892 if (memcmp(addr
->area_addr
, cmp_buf
, addr_len
) == 0) {
905 static int isis_snmp_area_addr_lookup_next(oid
*oid_idx
, size_t oid_idx_len
,
906 struct isis_area
**ret_area
,
907 struct area_addr
**ret_addr
)
909 uint8_t cmp_buf
[ISIS_SNMP_OSI_ADDR_LEN_MAX
];
912 struct isis_area
*found_area
= NULL
;
913 struct isis_area
*area
= NULL
;
914 struct area_addr
*found_addr
= NULL
;
915 struct area_addr
*addr
= NULL
;
916 struct listnode
*addr_node
;
917 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
922 if (list_isempty(isis
->area_list
)) {
923 /* Area is not configured yet */
927 area
= listgetdata(listhead(isis
->area_list
));
929 int res
= isis_snmp_conv_next(cmp_buf
, sizeof(cmp_buf
), &addr_len
,
930 &try_exact
, oid_idx
, oid_idx_len
);
935 for (ALL_LIST_ELEMENTS_RO(area
->area_addrs
, addr_node
, addr
)) {
936 if (addr
->addr_len
< addr_len
)
939 if (addr
->addr_len
== addr_len
) {
943 res
= memcmp(addr
->area_addr
, cmp_buf
, addr_len
);
948 if (res
== 0 && addr
->addr_len
== addr_len
) {
951 * This is the best match no point
962 if (found_addr
== NULL
|| addr
->addr_len
< found_addr
->addr_len
963 || (addr
->addr_len
== found_addr
->addr_len
964 && memcmp(addr
->area_addr
, found_addr
->area_addr
,
972 if (found_area
== NULL
)
976 *ret_area
= found_area
;
979 *ret_addr
= found_addr
;
985 * Helper functions to find circuit from
988 static int isis_snmp_circuit_lookup_exact(oid
*oid_idx
, size_t oid_idx_len
,
989 struct isis_circuit
**ret_circuit
)
991 struct isis_circuit
*circuit
;
993 if (oid_idx
== NULL
|| oid_idx_len
< 1
994 || oid_idx
[0] > SNMP_CIRCUITS_MAX
)
997 circuit
= snmp_circuits
[oid_idx
[0]];
1001 if (ret_circuit
!= NULL
)
1002 *ret_circuit
= circuit
;
1007 static int isis_snmp_circuit_lookup_next(oid
*oid_idx
, size_t oid_idx_len
,
1008 struct isis_circuit
**ret_circuit
)
1012 struct isis_circuit
*circuit
;
1016 if (oid_idx
!= NULL
&& oid_idx_len
!= 0) {
1017 if (oid_idx
[0] > SNMP_CIRCUITS_MAX
)
1023 for (off
= start
; off
< SNMP_CIRCUITS_MAX
; ++off
) {
1024 circuit
= snmp_circuits
[off
];
1026 if (circuit
!= NULL
&& off
> start
) {
1027 if (ret_circuit
!= NULL
)
1028 *ret_circuit
= circuit
;
1038 * Helper functions to find circuit level
1039 * combination from snmp index
1041 static int isis_snmp_circuit_level_lookup_exact(
1042 oid
*oid_idx
, size_t oid_idx_len
, int check_match
,
1043 struct isis_circuit
**ret_circuit
, int *ret_level
)
1047 struct isis_circuit
*circuit
;
1049 /* Minor optimization: check level first */
1050 if (oid_idx
== NULL
|| oid_idx_len
< 2)
1053 if (oid_idx
[1] < IS_LEVEL_1
|| oid_idx
[1] > IS_LEVEL_2
)
1056 level
= (int)oid_idx
[1];
1058 res
= isis_snmp_circuit_lookup_exact(oid_idx
, oid_idx_len
, &circuit
);
1063 if (check_match
&& !isis_snmp_get_level_match(circuit
->is_type
, level
))
1066 if (ret_circuit
!= NULL
)
1067 *ret_circuit
= circuit
;
1069 if (ret_level
!= NULL
)
1075 static int isis_snmp_circuit_level_lookup_next(
1076 oid
*oid_idx
, size_t oid_idx_len
, int check_match
,
1077 struct isis_circuit
**ret_circuit
, int *ret_level
)
1081 struct isis_circuit
*circuit
= NULL
;
1086 if (oid_idx
!= NULL
&& oid_idx_len
!= 0) {
1087 if (oid_idx
[0] > SNMP_CIRCUITS_MAX
)
1093 for (off
= start
; off
< SNMP_CIRCUITS_MAX
; off
++) {
1094 circuit
= snmp_circuits
[off
];
1096 if (circuit
== NULL
)
1099 if (off
> start
|| oid_idx_len
< 2) {
1100 /* Found and can use level 1 */
1105 assert(oid_idx
!= NULL
);
1107 /* We have to check level specified by index */
1108 if (oid_idx
[1] < IS_LEVEL_1
) {
1113 if (oid_idx
[1] < IS_LEVEL_2
) {
1122 if (circuit
== NULL
)
1126 && !isis_snmp_get_level_match(circuit
->is_type
, level
)) {
1127 if (level
== IS_LEVEL_1
) {
1129 * We can simply advance level because
1130 * at least one level should match
1134 /* We have to move to the next circuit */
1135 circuit
= isis_snmp_circuit_next(circuit
);
1136 if (circuit
== NULL
)
1139 level
= isis_snmp_circuit_get_level_lo(circuit
);
1143 if (ret_circuit
!= NULL
)
1144 *ret_circuit
= circuit
;
1146 if (ret_level
!= NULL
)
1153 * Helper functions to find adjacency
1156 * We have 4 tables related to adjacency
1157 * looking up adjacency is quite expensive
1158 * in case of bcast interfaces.
1160 * It is pain to have 4 very similar functions
1161 * hence we pass in and out additional data
1162 * we are looking for.
1164 * Note: we use data-len value to distinguish
1165 * between ipv4 and ipv6 addresses
1167 #define ISIS_SNMP_ADJ_DATA_NONE (1)
1168 #define ISIS_SNMP_ADJ_DATA_AREA_ADDR (2)
1169 #define ISIS_SNMP_ADJ_DATA_IP_ADDR (3)
1170 #define ISIS_SNMP_ADJ_DATA_PROTO (4)
1173 * Helper function to process data associated
1176 static int isis_snmp_adj_helper(struct isis_adjacency
*adj
, int data_id
,
1177 oid data_off
, uint8_t **ret_data
,
1178 size_t *ret_data_len
)
1180 uint8_t *data
= NULL
;
1181 size_t data_len
= 0;
1184 case ISIS_SNMP_ADJ_DATA_NONE
:
1187 case ISIS_SNMP_ADJ_DATA_AREA_ADDR
:
1188 if (data_off
>= adj
->area_address_count
)
1191 data
= adj
->area_addresses
[data_off
].area_addr
;
1192 data_len
= adj
->area_addresses
[data_off
].addr_len
;
1195 case ISIS_SNMP_ADJ_DATA_IP_ADDR
:
1197 >= (adj
->ipv4_address_count
+ adj
->ipv6_address_count
))
1200 if (data_off
>= adj
->ipv4_address_count
) {
1201 data
= (uint8_t *)&adj
->ipv6_addresses
1202 [data_off
- adj
->ipv4_address_count
];
1203 data_len
= sizeof(adj
->ipv6_addresses
[0]);
1205 data
= (uint8_t *)&adj
->ipv4_addresses
[data_off
];
1206 data_len
= sizeof(adj
->ipv4_addresses
[0]);
1212 case ISIS_SNMP_ADJ_DATA_PROTO
:
1213 if (data_off
>= adj
->nlpids
.count
)
1216 data
= &adj
->nlpids
.nlpids
[data_off
];
1217 data_len
= sizeof(adj
->nlpids
.nlpids
[0]);
1225 if (ret_data
!= NULL
)
1228 if (ret_data_len
!= NULL
)
1229 *ret_data_len
= data_len
;
1234 static int isis_snmp_adj_lookup_exact(oid
*oid_idx
, size_t oid_idx_len
,
1236 struct isis_adjacency
**ret_adj
,
1237 oid
*ret_data_idx
, uint8_t **ret_data
,
1238 size_t *ret_data_len
)
1241 struct listnode
*node
;
1242 struct isis_circuit
*circuit
;
1243 struct isis_adjacency
*adj
;
1244 struct isis_adjacency
*tmp_adj
;
1250 res
= isis_snmp_circuit_lookup_exact(oid_idx
, oid_idx_len
, &circuit
);
1255 if (oid_idx
== NULL
|| oid_idx_len
< 2
1256 || (data_id
!= ISIS_SNMP_ADJ_DATA_NONE
&& oid_idx_len
< 3))
1259 adj_idx
= oid_idx
[1];
1261 if (data_id
!= ISIS_SNMP_ADJ_DATA_NONE
) {
1262 if (oid_idx
[2] == 0)
1265 data_off
= oid_idx
[2] - 1;
1268 * Data-off is not used if data-id is none
1269 * but we set it just for consistency
1278 for (ALL_LIST_ELEMENTS_RO(circuit
->snmp_adj_list
, node
, tmp_adj
)) {
1279 if (tmp_adj
->snmp_idx
> adj_idx
) {
1281 * Adjacencies are ordered in the list
1282 * no point to look further
1287 if (tmp_adj
->snmp_idx
== adj_idx
) {
1288 res
= isis_snmp_adj_helper(tmp_adj
, data_id
, data_off
,
1300 if (ret_adj
!= NULL
)
1303 if (ret_data_idx
!= NULL
)
1304 *ret_data_idx
= data_off
+ 1;
1310 *ret_data_len
= data_len
;
1315 static int isis_snmp_adj_lookup_next(oid
*oid_idx
, size_t oid_idx_len
,
1317 struct isis_adjacency
**ret_adj
,
1318 oid
*ret_data_idx
, uint8_t **ret_data
,
1319 size_t *ret_data_len
)
1321 struct listnode
*node
;
1322 struct isis_circuit
*circuit
;
1323 struct isis_adjacency
*adj
;
1324 struct isis_adjacency
*tmp_adj
;
1336 * Note: we rely on the fact that data indexes are consequtive
1340 if (oid_idx
== 0 || oid_idx_len
== 0) {
1344 } else if (oid_idx_len
== 1) {
1345 circ_idx
= oid_idx
[0];
1348 } else if (oid_idx_len
== 2) {
1349 circ_idx
= oid_idx
[0];
1350 adj_idx
= oid_idx
[1];
1353 circ_idx
= oid_idx
[0];
1354 adj_idx
= oid_idx
[1];
1356 if (data_id
== ISIS_SNMP_ADJ_DATA_NONE
)
1359 data_idx
= oid_idx
[2];
1362 if (!isis_snmp_circuit_lookup_exact(&circ_idx
, 1, &circuit
)
1363 && !isis_snmp_circuit_lookup_next(&circ_idx
, 1, &circuit
))
1367 if (circuit
->snmp_id
!= circ_idx
) {
1368 /* Match is not exact */
1375 * Note: the simple loop below will work in all cases
1377 while (circuit
!= NULL
) {
1378 for (ALL_LIST_ELEMENTS_RO(circuit
->snmp_adj_list
, node
,
1380 if (tmp_adj
->snmp_idx
< adj_idx
)
1383 if (tmp_adj
->snmp_idx
== adj_idx
1384 && data_id
== ISIS_SNMP_ADJ_DATA_NONE
)
1387 if (adj_idx
!= 0 && tmp_adj
->snmp_idx
> adj_idx
)
1390 if (isis_snmp_adj_helper(tmp_adj
, data_id
, data_idx
,
1391 &data
, &data_len
)) {
1400 circuit
= isis_snmp_circuit_next(circuit
);
1409 if (ret_adj
!= NULL
)
1412 if (ret_data_idx
!= 0) {
1413 if (data_id
== ISIS_SNMP_ADJ_DATA_NONE
)
1415 * Value does not matter but let us set
1416 * it to zero for consistency
1420 *ret_data_idx
= data_idx
+ 1;
1426 if (ret_data_len
!= 0)
1427 *ret_data_len
= data_len
;
1432 static uint8_t *isis_snmp_find_sys_object(struct variable
*v
, oid
*name
,
1433 size_t *length
, int exact
,
1435 WriteMethod
**write_method
)
1437 struct isis_area
*area
= NULL
;
1438 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
1443 if (!list_isempty(isis
->area_list
))
1444 area
= listgetdata(listhead(isis
->area_list
));
1446 /* Check whether the instance identifier is valid */
1447 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
1452 case ISIS_SYS_VERSION
:
1453 return SNMP_INTEGER(ISIS_VERSION
);
1455 case ISIS_SYS_LEVELTYPE
:
1457 * If we do not have areas use 1&2 otherwise use settings
1458 * from the first area in the list
1461 return SNMP_INTEGER(IS_LEVEL_1_AND_2
);
1463 return SNMP_INTEGER(area
->is_type
);
1466 if (!isis
->sysid_set
) {
1467 *var_len
= ISIS_SYS_ID_LEN
;
1468 return isis_null_sysid
;
1471 *var_len
= ISIS_SYS_ID_LEN
;
1474 case ISIS_SYS_MAXPATHSPLITS
:
1475 return SNMP_INTEGER(ISIS_SNMP_MAX_PATH_SPLITS
);
1477 case ISIS_SYS_MAXLSPGENINT
:
1478 return SNMP_INTEGER(DEFAULT_MAX_LSP_GEN_INTERVAL
);
1480 case ISIS_SYS_POLLESHELLORATE
:
1481 return SNMP_INTEGER(DEFAULT_HELLO_INTERVAL
);
1483 case ISIS_SYS_WAITTIME
:
1484 /* Note: it seems that we have same fixed delay time */
1485 return SNMP_INTEGER(DEFAULT_MIN_LSP_GEN_INTERVAL
);
1487 case ISIS_SYS_ADMINSTATE
:
1488 /* If daemon is running it admin state is on */
1489 return SNMP_INTEGER(ISIS_SNMP_ADMIN_STATE_ON
);
1492 case ISIS_SYS_L2TOL1LEAKING
:
1493 /* We do not allow l2-to-l1 leaking */
1494 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
1496 case ISIS_SYS_MAXAGE
:
1497 return SNMP_INTEGER(MAX_AGE
);
1499 case ISIS_SYS_RECEIVELSPBUFFERSIZE
:
1501 return SNMP_INTEGER(DEFAULT_LSP_MTU
);
1503 return SNMP_INTEGER(area
->lsp_mtu
);
1505 case ISIS_SYS_PROTSUPPORTED
:
1507 return &isis_snmp_protocols_supported
;
1509 case ISIS_SYS_NOTIFICATIONENABLE
:
1510 if (isis
->snmp_notifications
)
1511 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
1513 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
1523 static uint8_t *isis_snmp_find_man_area(struct variable
*v
, oid
*name
,
1524 size_t *length
, int exact
,
1526 WriteMethod
**write_method
)
1529 struct area_addr
*area_addr
= NULL
;
1534 *write_method
= NULL
;
1536 if (*length
<= v
->namelen
) {
1539 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
1543 oid_idx
= name
+ v
->namelen
;
1544 oid_idx_len
= *length
- v
->namelen
;
1548 res
= isis_snmp_area_addr_lookup_exact(oid_idx
, oid_idx_len
,
1555 res
= isis_snmp_area_addr_lookup_next(oid_idx
, oid_idx_len
,
1561 /* Copy the name out */
1562 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
1565 name
[v
->namelen
] = area_addr
->addr_len
;
1567 for (off
= 0; off
< area_addr
->addr_len
; off
++)
1568 name
[v
->namelen
+ 1 + off
] = area_addr
->area_addr
[off
];
1570 *length
= v
->namelen
+ 1 + area_addr
->addr_len
;
1574 case ISIS_MANAREA_ADDREXISTSTATE
:
1575 return SNMP_INTEGER(ISIS_SNMP_ROW_STATUS_ACTIVE
);
1584 static uint8_t *isis_snmp_find_area_addr(struct variable
*v
, oid
*name
,
1585 size_t *length
, int exact
,
1587 WriteMethod
**write_method
)
1590 * Area addresses in sense of addresses reported by L1 lsps
1591 * are not supported yet.
1600 *write_method
= NULL
;
1605 static uint8_t *isis_snmp_find_summ_addr(struct variable
*v
, oid
*name
,
1606 size_t *length
, int exact
,
1608 WriteMethod
**write_method
)
1611 * So far there is no way to set summary table values through cli
1612 * and snmp operations are read-only, hence there are no entries
1619 *write_method
= NULL
;
1624 static uint8_t *isis_snmp_find_redistribute_addr(struct variable
*v
, oid
*name
,
1625 size_t *length
, int exact
,
1627 WriteMethod
**write_method
)
1630 * It is not clear at the point whether redist code in isis is actually
1631 * used for now we will consider that entries are not present
1638 *write_method
= NULL
;
1643 static uint8_t *isis_snmp_find_router(struct variable
*v
, oid
*name
,
1644 size_t *length
, int exact
,
1646 WriteMethod
**write_method
)
1648 uint8_t cmp_buf
[ISIS_SYS_ID_LEN
];
1653 struct isis_dynhn
*dyn
= NULL
;
1657 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
1662 *write_method
= NULL
;
1664 if (*length
<= v
->namelen
) {
1667 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
1671 oid_idx
= name
+ v
->namelen
;
1672 oid_idx_len
= *length
- v
->namelen
;
1676 res
= isis_snmp_conv_exact(cmp_buf
, sizeof(cmp_buf
), &cmp_len
,
1677 oid_idx
, oid_idx_len
);
1679 if (!res
|| cmp_len
!= ISIS_SYS_ID_LEN
1680 || oid_idx_len
!= (cmp_len
+ 2))
1682 * Bad conversion, or bad length,
1683 * or extra oids at the end
1687 if (oid_idx
[ISIS_SYS_ID_LEN
+ 1] < IS_LEVEL_1
1688 || oid_idx
[ISIS_SYS_ID_LEN
+ 1] > IS_LEVEL_2
)
1689 /* Level part of the index is out of range */
1692 cmp_level
= (int)oid_idx
[ISIS_SYS_ID_LEN
+ 1];
1694 dyn
= dynhn_find_by_id(isis
, cmp_buf
);
1696 if (dyn
== NULL
|| dyn
->level
!= cmp_level
)
1700 case ISIS_ROUTER_HOSTNAME
:
1701 *var_len
= strlen(dyn
->hostname
);
1702 return (uint8_t *)dyn
->hostname
;
1704 case ISIS_ROUTER_ID
:
1705 /* It seems that we do no know router-id in lsps */
1706 return SNMP_INTEGER(0);
1715 res
= isis_snmp_conv_next(cmp_buf
, sizeof(cmp_buf
), &cmp_len
,
1716 &try_exact
, oid_idx
, oid_idx_len
);
1720 /* Bad conversion */
1723 if (cmp_len
!= ISIS_SYS_ID_LEN
) {
1724 /* We do not have valid index oids */
1725 memset(cmp_buf
, 0, sizeof(cmp_buf
));
1727 } else if (try_exact
)
1729 * We have no valid level index.
1730 * Let start from non-existing level 0 and
1731 * hence not need to do exact match
1734 else if (oid_idx_len
< (ISIS_SYS_ID_LEN
+ 2))
1736 else if (oid_idx
[ISIS_SYS_ID_LEN
+ 1] <= IS_LEVEL_2
)
1737 cmp_level
= (int)oid_idx
[ISIS_SYS_ID_LEN
+ 1];
1740 * Any value greater than 2 will have the same result
1741 * but we can have integer overflows, hence 3 is a reasonable
1744 cmp_level
= (int)(IS_LEVEL_2
+ 1);
1746 dyn
= dynhn_snmp_next(isis
, cmp_buf
, cmp_level
);
1751 /* Copy the name out */
1752 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
1755 name
[v
->namelen
] = ISIS_SYS_ID_LEN
;
1757 for (off
= 0; off
< ISIS_SYS_ID_LEN
; off
++)
1758 name
[v
->namelen
+ 1 + off
] = dyn
->id
[off
];
1760 name
[v
->namelen
+ 1 + ISIS_SYS_ID_LEN
] = (oid
)dyn
->level
;
1763 *length
= v
->namelen
+ 1 + ISIS_SYS_ID_LEN
+ 1;
1766 case ISIS_ROUTER_HOSTNAME
:
1767 *var_len
= strlen(dyn
->hostname
);
1768 return (uint8_t *)dyn
->hostname
;
1770 case ISIS_ROUTER_ID
:
1771 /* It seems that we do no know router-id in lsps */
1772 return SNMP_INTEGER(0);
1781 static uint8_t *isis_snmp_find_sys_level(struct variable
*v
, oid
*name
,
1782 size_t *length
, int exact
,
1784 WriteMethod
**write_method
)
1790 struct isis_area
*area
= NULL
;
1791 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
1796 *write_method
= NULL
;
1798 if (*length
<= v
->namelen
) {
1801 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
1805 oid_idx
= name
+ v
->namelen
;
1806 oid_idx_len
= *length
- v
->namelen
;
1810 if (oid_idx
== NULL
|| oid_idx_len
!= 1)
1813 if (oid_idx
[0] == IS_LEVEL_1
)
1815 else if (oid_idx
[0] == IS_LEVEL_2
)
1821 if (oid_idx
== NULL
)
1823 else if (oid_idx_len
== 0)
1825 else if (oid_idx
[0] < IS_LEVEL_1
)
1827 else if (oid_idx
[0] < IS_LEVEL_2
)
1832 /* Copy the name out */
1833 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
1836 name
[v
->namelen
] = level
;
1839 *length
= v
->namelen
+ 1;
1844 if (!list_isempty(isis
->area_list
))
1845 area
= listgetdata(listhead(isis
->area_list
));
1850 level_match
= isis_snmp_get_level_match(area
->is_type
, level
);
1853 case ISIS_SYSLEVEL_ORIGLSPBUFFSIZE
:
1855 return SNMP_INTEGER(area
->lsp_mtu
);
1857 return SNMP_INTEGER(DEFAULT_LSP_MTU
);
1859 case ISIS_SYSLEVEL_MINLSPGENINT
:
1861 return SNMP_INTEGER(area
->lsp_gen_interval
[level
- 1]);
1863 return SNMP_INTEGER(DEFAULT_MIN_LSP_GEN_INTERVAL
);
1865 case ISIS_SYSLEVEL_STATE
:
1867 if (area
->overload_bit
)
1868 return SNMP_INTEGER(
1869 ISIS_SNMP_LEVEL_STATE_OVERLOADED
);
1871 return SNMP_INTEGER(ISIS_SNMP_LEVEL_STATE_ON
);
1873 return SNMP_INTEGER(ISIS_SNMP_LEVEL_STATE_OFF
);
1875 case ISIS_SYSLEVEL_SETOVERLOAD
:
1876 if (level_match
&& area
->overload_bit
)
1877 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
1879 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
1881 case ISIS_SYSLEVEL_SETOVERLOADUNTIL
:
1882 /* We do not have automatic cleanup of overload bit */
1883 return SNMP_INTEGER(0);
1885 case ISIS_SYSLEVEL_METRICSTYLE
:
1887 if (area
->newmetric
&& area
->oldmetric
)
1888 return SNMP_INTEGER(
1889 ISIS_SNMP_METRIC_STYLE_BOTH
);
1891 if (area
->newmetric
)
1892 return SNMP_INTEGER(
1893 ISIS_SNMP_METRIC_STYLE_WIDE
);
1895 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_NARROW
);
1897 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_NARROW
);
1899 case ISIS_SYSLEVEL_SPFCONSIDERS
:
1900 return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_BOTH
);
1902 case ISIS_SYSLEVEL_TEENABLED
:
1903 if (level_match
&& IS_MPLS_TE(area
->mta
))
1904 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
1906 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
1915 static uint8_t *isis_snmp_find_system_counter(struct variable
*v
, oid
*name
,
1916 size_t *length
, int exact
,
1918 WriteMethod
**write_method
)
1924 struct isis_area
*area
= NULL
;
1926 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
1931 *write_method
= NULL
;
1933 if (*length
<= v
->namelen
) {
1936 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
1940 oid_idx
= name
+ v
->namelen
;
1941 oid_idx_len
= *length
- v
->namelen
;
1945 if (oid_idx
== NULL
|| oid_idx_len
!= 1)
1948 if (oid_idx
[0] == IS_LEVEL_1
)
1950 else if (oid_idx
[0] == IS_LEVEL_2
)
1956 if (oid_idx
== NULL
)
1958 else if (oid_idx_len
== 0)
1960 else if (oid_idx
[0] < IS_LEVEL_1
)
1962 else if (oid_idx
[0] < IS_LEVEL_2
)
1967 /* Copy the name out */
1968 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
1971 name
[v
->namelen
] = level
;
1974 *length
= v
->namelen
+ 1;
1979 if (!list_isempty(isis
->area_list
))
1980 area
= listgetdata(listhead(isis
->area_list
));
1985 level_match
= isis_snmp_get_level_match(area
->is_type
, level
);
1988 /* If level does not match all counters are zeros */
1989 return SNMP_INTEGER(0);
1992 case ISIS_SYSSTAT_CORRLSPS
:
1996 case ISIS_SYSSTAT_AUTHTYPEFAILS
:
1997 val
= (uint32_t)area
->auth_type_failures
[level
- 1];
2000 case ISIS_SYSSTAT_AUTHFAILS
:
2001 val
= (uint32_t)area
->auth_failures
[level
- 1];
2004 case ISIS_SYSSTAT_LSPDBASEOLOADS
:
2005 val
= area
->overload_counter
;
2008 case ISIS_SYSSTAT_MANADDRDROPFROMAREAS
:
2009 /* We do not support manual addresses */
2013 case ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS
:
2014 val
= area
->lsp_exceeded_max_counter
;
2017 case ISIS_SYSSTAT_SEQNUMSKIPS
:
2018 val
= area
->lsp_seqno_skipped_counter
;
2021 case ISIS_SYSSTAT_OWNLSPPURGES
:
2022 if (!area
->purge_originator
)
2025 val
= area
->lsp_purge_count
[level
- 1];
2028 case ISIS_SYSSTAT_IDFIELDLENMISMATCHES
:
2029 val
= (uint32_t)area
->id_len_mismatches
[level
- 1];
2032 case ISIS_SYSSTAT_PARTCHANGES
:
2037 case ISIS_SYSSTAT_SPFRUNS
:
2038 val
= (uint32_t)area
->spf_run_count
[level
- 1];
2041 case ISIS_SYSSTAT_LSPERRORS
:
2042 val
= (uint32_t)area
->lsp_error_counter
[level
- 1];
2049 return SNMP_INTEGER(val
);
2052 static uint8_t *isis_snmp_find_next_circ_index(struct variable
*v
, oid
*name
,
2053 size_t *length
, int exact
,
2055 WriteMethod
**write_method
)
2057 /* Check whether the instance identifier is valid */
2058 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
2063 case ISIS_NEXTCIRC_INDEX
:
2065 * We do not support circuit creation through snmp
2067 return SNMP_INTEGER(0);
2076 static uint8_t *isis_snmp_find_circ(struct variable
*v
, oid
*name
,
2077 size_t *length
, int exact
, size_t *var_len
,
2078 WriteMethod
**write_method
)
2080 /* Index is circuit-id: 1-255 */
2083 struct isis_circuit
*circuit
;
2085 uint32_t delta_ticks
;
2089 *write_method
= NULL
;
2091 if (*length
<= v
->namelen
) {
2094 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2098 oid_idx
= name
+ v
->namelen
;
2099 oid_idx_len
= *length
- v
->namelen
;
2102 res
= isis_snmp_circuit_lookup_exact(oid_idx
, oid_idx_len
,
2105 if (!res
|| oid_idx_len
!= 1)
2109 res
= isis_snmp_circuit_lookup_next(oid_idx
, oid_idx_len
,
2115 /* Copy the name out */
2116 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2119 name
[v
->namelen
] = circuit
->snmp_id
;
2122 *length
= v
->namelen
+ 1;
2126 case ISIS_CIRC_IFINDEX
:
2127 if (circuit
->interface
== 0)
2128 return SNMP_INTEGER(0);
2130 return SNMP_INTEGER(circuit
->interface
->ifindex
);
2132 case ISIS_CIRC_ADMINSTATE
:
2133 return SNMP_INTEGER(ISIS_SNMP_ADMIN_STATE_ON
);
2135 case ISIS_CIRC_EXISTSTATE
:
2136 return SNMP_INTEGER(ISIS_SNMP_ROW_STATUS_ACTIVE
);
2138 case ISIS_CIRC_TYPE
:
2140 * Note: values do not match 100%:
2142 * 1. From isis_circuit.h:
2143 * CIRCUIT_T_UNKNOWN 0
2144 * CIRCUIT_T_BROADCAST 1
2146 * CIRCUIT_T_LOOPBACK 3
2155 return SNMP_INTEGER(circuit
->circ_type
);
2157 case ISIS_CIRC_EXTDOMAIN
:
2158 if (circuit
->ext_domain
)
2159 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
2161 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
2163 case ISIS_CIRC_LEVELTYPE
:
2164 return SNMP_INTEGER(circuit
->is_type
);
2166 case ISIS_CIRC_PASSIVECIRCUIT
:
2167 if (circuit
->is_passive
)
2168 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
2170 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
2172 case ISIS_CIRC_MESHGROUPENABLED
:
2174 return SNMP_INTEGER(ISIS_SNMP_MESH_GROUP_INACTIVE
);
2176 case ISIS_CIRC_MESHGROUP
:
2178 return SNMP_INTEGER(0);
2180 case ISIS_CIRC_SMALLHELLOS
:
2182 * return false if lan hellos must be padded
2184 if (circuit
->pad_hellos
)
2185 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
2187 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE
);
2189 case ISIS_CIRC_LASTUPTIME
:
2190 if (circuit
->last_uptime
== 0)
2191 return SNMP_INTEGER(0);
2193 up_ticks
= (uint32_t)netsnmp_get_agent_uptime();
2194 now_time
= isis_snmp_time();
2196 if (circuit
->last_uptime
>= now_time
)
2197 return SNMP_INTEGER(up_ticks
);
2199 delta_ticks
= (now_time
- circuit
->last_uptime
) * 10;
2201 if (up_ticks
< delta_ticks
)
2202 return SNMP_INTEGER(up_ticks
);
2204 return SNMP_INTEGER(up_ticks
- delta_ticks
);
2206 case ISIS_CIRC_3WAYENABLED
:
2208 return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE
);
2210 case ISIS_CIRC_EXTENDEDCIRCID
:
2211 /* Used for 3-way hand shake only */
2212 return SNMP_INTEGER(0);
2221 static uint8_t *isis_snmp_find_circ_level(struct variable
*v
, oid
*name
,
2222 size_t *length
, int exact
,
2224 WriteMethod
**write_method
)
2226 static uint8_t circuit_id_val
[ISIS_SYS_ID_LEN
+ 1];
2227 /* Index is circuit-id: 1-255 + level: 1-2 */
2231 struct isis_circuit
*circuit
;
2233 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
2238 *write_method
= NULL
;
2240 if (*length
<= v
->namelen
) {
2243 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2247 oid_idx
= name
+ v
->namelen
;
2248 oid_idx_len
= *length
- v
->namelen
;
2251 res
= isis_snmp_circuit_level_lookup_exact(oid_idx
, oid_idx_len
,
2252 1, &circuit
, &level
);
2254 if (!res
|| oid_idx_len
!= 2)
2258 res
= isis_snmp_circuit_level_lookup_next(oid_idx
, oid_idx_len
,
2259 1, &circuit
, &level
);
2264 /* Copy the name out */
2265 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2268 name
[v
->namelen
] = circuit
->snmp_id
;
2269 name
[v
->namelen
+ 1] = level
;
2272 *length
= v
->namelen
+ 2;
2276 case ISIS_CIRCLEVEL_METRIC
:
2277 return SNMP_INTEGER(circuit
->metric
[level
- 1]);
2279 case ISIS_CIRCLEVEL_WIDEMETRIC
:
2280 if (circuit
->area
== NULL
|| !circuit
->area
->newmetric
) {
2281 /* What should we do if wide metric is not supported? */
2282 return SNMP_INTEGER(0);
2284 return SNMP_INTEGER(circuit
->te_metric
[level
- 1]);
2286 case ISIS_CIRCLEVEL_ISPRIORITY
:
2287 return SNMP_INTEGER(circuit
->priority
[level
- 1]);
2289 case ISIS_CIRCLEVEL_IDOCTET
:
2290 return SNMP_INTEGER(circuit
->circuit_id
);
2292 case ISIS_CIRCLEVEL_ID
:
2293 if (circuit
->circ_type
!= CIRCUIT_T_P2P
) {
2295 * Unless it is point-to-point circuit, the value is and
2296 * empty octet string
2299 return circuit_id_val
;
2302 /* !!!!!! Circuit-id is zero for p2p links */
2303 if (circuit
->u
.p2p
.neighbor
== NULL
2304 || circuit
->u
.p2p
.neighbor
->adj_state
!= ISIS_ADJ_UP
) {
2305 /* No adjacency or adjacency not fully up yet */
2306 memcpy(circuit_id_val
, isis
->sysid
, ISIS_SYS_ID_LEN
);
2307 circuit_id_val
[ISIS_SYS_ID_LEN
] = circuit
->circuit_id
;
2308 *var_len
= ISIS_SYS_ID_LEN
+ 1;
2309 return circuit_id_val
;
2312 /* Adjacency fully-up */
2313 memcpy(circuit_id_val
, circuit
->u
.p2p
.neighbor
->sysid
,
2315 circuit_id_val
[ISIS_SYS_ID_LEN
] = 0;
2316 *var_len
= ISIS_SYS_ID_LEN
+ 1;
2317 return circuit_id_val
;
2319 case ISIS_CIRCLEVEL_DESIS
:
2320 if (circuit
->circ_type
!= CIRCUIT_T_BROADCAST
2321 || !circuit
->u
.bc
.is_dr
[level
- 1]) {
2323 * Unless it is lan circuit participating in dis process
2324 * the value is an empty octet string
2327 return circuit_id_val
;
2330 *var_len
= ISIS_SYS_ID_LEN
+ 1;
2332 if (level
== IS_LEVEL_1
)
2333 return circuit
->u
.bc
.l1_desig_is
;
2335 return circuit
->u
.bc
.l2_desig_is
;
2337 case ISIS_CIRCLEVEL_HELLOMULTIPLIER
:
2338 return SNMP_INTEGER(circuit
->hello_multiplier
[level
- 1]);
2340 case ISIS_CIRCLEVEL_HELLOTIMER
:
2341 return SNMP_INTEGER(circuit
->hello_interval
[level
- 1] * 1000);
2343 case ISIS_CIRCLEVEL_DRHELLOTIMER
:
2344 return SNMP_INTEGER(circuit
->hello_interval
[level
- 1] * 1000);
2346 case ISIS_CIRCLEVEL_LSPTHROTTLE
:
2348 return SNMP_INTEGER(
2349 circuit
->area
->min_spf_interval
[level
- 1]
2352 return SNMP_INTEGER(0);
2354 case ISIS_CIRCLEVEL_MINLSPRETRANSINT
:
2356 return SNMP_INTEGER(
2357 circuit
->area
->min_spf_interval
[level
- 1]);
2359 return SNMP_INTEGER(0);
2361 case ISIS_CIRCLEVEL_CSNPINTERVAL
:
2362 return SNMP_INTEGER(circuit
->csnp_interval
[level
- 1]);
2364 case ISIS_CIRCLEVEL_PARTSNPINTERVAL
:
2365 return SNMP_INTEGER(circuit
->psnp_interval
[level
- 1]);
2374 static uint8_t *isis_snmp_find_circ_counter(struct variable
*v
, oid
*name
,
2375 size_t *length
, int exact
,
2377 WriteMethod
**write_method
)
2379 /* Index circuit-id 1-255 + level */
2383 struct isis_circuit
*circuit
;
2387 *write_method
= NULL
;
2389 if (*length
<= v
->namelen
) {
2392 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2396 oid_idx
= name
+ v
->namelen
;
2397 oid_idx_len
= *length
- v
->namelen
;
2400 res
= isis_snmp_circuit_level_lookup_exact(oid_idx
, oid_idx_len
,
2401 1, &circuit
, &level
);
2403 if (!res
|| oid_idx_len
!= 2)
2407 res
= isis_snmp_circuit_level_lookup_next(oid_idx
, oid_idx_len
,
2408 1, &circuit
, &level
);
2413 /* Copy the name out */
2414 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2417 name
[v
->namelen
] = circuit
->snmp_id
;
2418 if (circuit
->circ_type
== CIRCUIT_T_P2P
)
2419 name
[v
->namelen
+ 1] = ISIS_SNMP_P2P_CIRCUIT
;
2421 name
[v
->namelen
+ 1] = level
;
2424 *length
= v
->namelen
+ 2;
2428 case ISIS_CIRC_ADJCHANGES
:
2429 val
= circuit
->adj_state_changes
;
2432 case ISIS_CIRC_NUMADJ
:
2433 if (circuit
->circ_type
== CIRCUIT_T_P2P
) {
2434 val
= circuit
->u
.p2p
.neighbor
== NULL
? 0 : 1;
2438 if (circuit
->circ_type
!= CIRCUIT_T_BROADCAST
) {
2443 if (level
== IS_LEVEL_1
) {
2444 if (circuit
->u
.bc
.adjdb
[0] == NULL
)
2447 val
= listcount(circuit
->u
.bc
.adjdb
[0]);
2451 if (circuit
->u
.bc
.adjdb
[1] == NULL
)
2454 val
= listcount(circuit
->u
.bc
.adjdb
[1]);
2458 case ISIS_CIRC_INITFAILS
:
2459 val
= circuit
->init_failures
; /* counter never incremented */
2462 case ISIS_CIRC_REJADJS
:
2463 val
= circuit
->rej_adjacencies
;
2466 case ISIS_CIRC_IDFIELDLENMISMATCHES
:
2467 val
= circuit
->id_len_mismatches
;
2470 case ISIS_CIRC_MAXAREAADDRMISMATCHES
:
2471 val
= circuit
->max_area_addr_mismatches
;
2474 case ISIS_CIRC_AUTHTYPEFAILS
:
2475 val
= circuit
->auth_type_failures
;
2478 case ISIS_CIRC_AUTHFAILS
:
2479 val
= circuit
->auth_failures
;
2482 case ISIS_CIRC_LANDESISCHANGES
:
2483 if (circuit
->circ_type
== CIRCUIT_T_P2P
)
2486 val
= circuit
->desig_changes
[level
- 1];
2493 return SNMP_INTEGER(val
);
2496 static uint8_t *isis_snmp_find_isadj(struct variable
*v
, oid
*name
,
2497 size_t *length
, int exact
, size_t *var_len
,
2498 WriteMethod
**write_method
)
2500 /* Index is circuit-id: 1-255 + adj-id: 1-... */
2505 struct isis_adjacency
*adj
;
2507 uint32_t delta_ticks
;
2510 *write_method
= NULL
;
2512 if (*length
<= v
->namelen
) {
2515 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2519 oid_idx
= name
+ v
->namelen
;
2520 oid_idx_len
= *length
- v
->namelen
;
2523 res
= isis_snmp_adj_lookup_exact(oid_idx
, oid_idx_len
,
2524 ISIS_SNMP_ADJ_DATA_NONE
, &adj
,
2527 if (!res
|| oid_idx_len
!= 2)
2531 res
= isis_snmp_adj_lookup_next(oid_idx
, oid_idx_len
,
2532 ISIS_SNMP_ADJ_DATA_NONE
, &adj
,
2537 /* Copy the name out */
2538 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2541 name
[v
->namelen
] = adj
->circuit
->snmp_id
;
2542 name
[v
->namelen
+ 1] = adj
->snmp_idx
;
2545 *length
= v
->namelen
+ 2;
2549 case ISIS_ISADJ_STATE
:
2550 return SNMP_INTEGER(isis_snmp_adj_state(adj
->adj_state
));
2552 case ISIS_ISADJ_3WAYSTATE
:
2553 return SNMP_INTEGER(adj
->threeway_state
);
2555 case ISIS_ISADJ_NEIGHSNPAADDRESS
: {
2556 const char *snpa
= (char *)snpa_print(adj
->snpa
);
2557 *var_len
= strlen(snpa
);
2558 return (uint8_t *)snpa
;
2561 case ISIS_ISADJ_NEIGHSYSTYPE
:
2562 return SNMP_INTEGER(isis_snmp_adj_neightype(adj
->sys_type
));
2564 case ISIS_ISADJ_NEIGHSYSID
:
2565 *var_len
= sizeof(adj
->sysid
);
2568 case ISIS_ISADJ_NBREXTENDEDCIRCID
:
2569 return SNMP_INTEGER(adj
->ext_circuit_id
!= 0 ? 1 : 0);
2571 case ISIS_ISADJ_USAGE
:
2572 /* It seems that no value conversion is required */
2573 return SNMP_INTEGER(adj
->adj_usage
);
2575 case ISIS_ISADJ_HOLDTIMER
:
2577 * It seems that we want remaining timer
2579 if (adj
->last_upd
!= 0) {
2580 val
= isis_snmp_time();
2581 if (val
< (adj
->last_upd
+ adj
->hold_time
))
2582 return SNMP_INTEGER(adj
->last_upd
2583 + adj
->hold_time
- val
);
2585 /* Not running or just expired */
2586 return SNMP_INTEGER(0);
2588 case ISIS_ISADJ_NEIGHPRIORITY
:
2589 return SNMP_INTEGER(adj
->prio
[adj
->level
- 1]);
2591 case ISIS_ISADJ_LASTUPTIME
:
2592 if (adj
->flaps
== 0)
2593 return SNMP_INTEGER(0);
2595 up_ticks
= (uint32_t)netsnmp_get_agent_uptime();
2597 now_time
= isis_snmp_time();
2599 if (adj
->last_flap
>= now_time
)
2600 return SNMP_INTEGER(up_ticks
);
2602 delta_ticks
= (now_time
- adj
->last_flap
) * 10;
2604 if (up_ticks
< delta_ticks
)
2605 return SNMP_INTEGER(up_ticks
);
2607 return SNMP_INTEGER(up_ticks
- delta_ticks
);
2616 static uint8_t *isis_snmp_find_isadj_area(struct variable
*v
, oid
*name
,
2617 size_t *length
, int exact
,
2619 WriteMethod
**write_method
)
2621 /* Index circuit-id: 1-255 + adj-id: 1-... */
2625 struct isis_adjacency
*adj
;
2630 *write_method
= NULL
;
2632 if (*length
<= v
->namelen
) {
2635 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2639 oid_idx
= name
+ v
->namelen
;
2640 oid_idx_len
= *length
- v
->namelen
;
2643 res
= isis_snmp_adj_lookup_exact(oid_idx
, oid_idx_len
,
2644 ISIS_SNMP_ADJ_DATA_AREA_ADDR
,
2645 &adj
, NULL
, &data
, &data_len
);
2647 if (!res
|| oid_idx_len
!= 3)
2651 res
= isis_snmp_adj_lookup_next(
2652 oid_idx
, oid_idx_len
, ISIS_SNMP_ADJ_DATA_AREA_ADDR
,
2653 &adj
, &data_idx
, &data
, &data_len
);
2657 /* Copy the name out */
2658 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2661 name
[v
->namelen
] = adj
->circuit
->snmp_id
;
2662 name
[v
->namelen
+ 1] = adj
->snmp_idx
;
2663 name
[v
->namelen
+ 2] = data_idx
;
2666 *length
= v
->namelen
+ 3;
2670 case ISIS_ISADJAREA_ADDRESS
:
2671 *var_len
= data_len
;
2681 static uint8_t *isis_snmp_find_isadj_ipaddr(struct variable
*v
, oid
*name
,
2682 size_t *length
, int exact
,
2684 WriteMethod
**write_method
)
2686 /* Index circuit-id 1-255 + adj-id 1-... */
2690 struct isis_adjacency
*adj
;
2695 *write_method
= NULL
;
2697 if (*length
<= v
->namelen
) {
2700 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2704 oid_idx
= name
+ v
->namelen
;
2705 oid_idx_len
= *length
- v
->namelen
;
2708 res
= isis_snmp_adj_lookup_exact(oid_idx
, oid_idx_len
,
2709 ISIS_SNMP_ADJ_DATA_IP_ADDR
,
2710 &adj
, NULL
, &data
, &data_len
);
2712 if (!res
|| oid_idx_len
!= 3)
2715 res
= isis_snmp_adj_lookup_next(
2716 oid_idx
, oid_idx_len
, ISIS_SNMP_ADJ_DATA_IP_ADDR
, &adj
,
2717 &data_idx
, &data
, &data_len
);
2721 /* Copy the name out */
2722 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2725 name
[v
->namelen
] = adj
->circuit
->snmp_id
;
2726 name
[v
->namelen
+ 1] = adj
->snmp_idx
;
2727 name
[v
->namelen
+ 2] = data_idx
;
2730 *length
= v
->namelen
+ 3;
2734 case ISIS_ISADJIPADDR_TYPE
:
2736 return SNMP_INTEGER(ISIS_SNMP_INET_TYPE_V4
);
2738 return SNMP_INTEGER(ISIS_SNMP_INET_TYPE_V6
);
2740 case ISIS_ISADJIPADDR_ADDRESS
:
2741 *var_len
= data_len
;
2751 static uint8_t *isis_snmp_find_isadj_prot_supp(struct variable
*v
, oid
*name
,
2752 size_t *length
, int exact
,
2754 WriteMethod
**write_method
)
2756 /* Index circuit-id 1-255 + adj-id 1-... */
2760 struct isis_adjacency
*adj
;
2765 *write_method
= NULL
;
2767 if (*length
<= v
->namelen
) {
2770 } else if (memcmp(name
, v
->name
, v
->namelen
* sizeof(oid
)) != 0) {
2774 oid_idx
= name
+ v
->namelen
;
2775 oid_idx_len
= *length
- v
->namelen
;
2778 res
= isis_snmp_adj_lookup_exact(oid_idx
, oid_idx_len
,
2779 ISIS_SNMP_ADJ_DATA_PROTO
, &adj
,
2780 NULL
, &data
, &data_len
);
2782 if (!res
|| oid_idx_len
!= 3)
2786 res
= isis_snmp_adj_lookup_next(oid_idx
, oid_idx_len
,
2787 ISIS_SNMP_ADJ_DATA_PROTO
, &adj
,
2788 &data_idx
, &data
, &data_len
);
2792 /* Copy the name out */
2793 memcpy(name
, v
->name
, v
->namelen
* sizeof(oid
));
2796 name
[v
->namelen
] = adj
->circuit
->snmp_id
;
2797 name
[v
->namelen
+ 1] = adj
->snmp_idx
;
2798 name
[v
->namelen
+ 2] = data_idx
;
2801 *length
= v
->namelen
+ 3;
2805 case ISIS_ISADJPROTSUPP_PROTOCOL
:
2806 return SNMP_INTEGER(*data
);
2816 /* Register ISIS-MIB. */
2817 static int isis_snmp_init(struct thread_master
*tm
)
2819 struct isis_func_to_prefix
*h2f
= isis_func_to_prefix_arr
;
2822 for (size_t off
= 0; off
< isis_var_count
; off
++) {
2823 v
= &isis_var_arr
[off
];
2825 if (v
->findVar
!= h2f
->ihtp_func
) {
2828 assert(h2f
< (isis_func_to_prefix_arr
2829 + isis_func_to_prefix_count
));
2830 assert(v
->findVar
== h2f
->ihtp_func
);
2833 v
->namelen
= h2f
->ihtp_pref_len
+ 1;
2834 memcpy(v
->name
, h2f
->ihtp_pref_oid
,
2835 h2f
->ihtp_pref_len
* sizeof(oid
));
2836 v
->name
[h2f
->ihtp_pref_len
] = v
->magic
;
2841 REGISTER_MIB("mibII/isis", isis_var_arr
, variable
, isis_oid
);
2846 * ISIS notification functions: we have one function per notification
2848 static int isis_snmp_trap_throttle(oid trap_id
)
2851 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
2853 if (isis
== NULL
|| !isis
->snmp_notifications
|| !smux_enabled())
2856 time_now
= isis_snmp_time();
2858 if ((isis_snmp_trap_timestamp
[trap_id
] + 5) > time_now
)
2859 /* Throttle trap rate at 1 in 5 secs */
2862 isis_snmp_trap_timestamp
[trap_id
] = time_now
;
2866 static int isis_snmp_db_overload_update(const struct isis_area
*area
)
2868 netsnmp_variable_list
*notification_vars
;
2872 if (!isis_snmp_trap_throttle(ISIS_TRAP_DB_OVERLOAD
))
2875 notification_vars
= NULL
;
2877 /* Put in trap value */
2878 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
2879 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
2880 (uint8_t *)&isis_snmp_trap_val_db_overload
,
2881 sizeof(isis_snmp_trap_val_db_overload
));
2884 val
= area
->is_type
;
2886 snmp_varlist_add_variable(
2887 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
2888 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
2889 (uint8_t *)&val
, sizeof(val
));
2891 /* Patch sys_level_state with proper index */
2892 off
= ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state
) - 1;
2893 isis_snmp_trap_data_var_sys_level_state
[off
] = val
;
2896 if (area
->overload_bit
)
2897 val
= ISIS_SNMP_LEVEL_STATE_OVERLOADED
;
2899 val
= ISIS_SNMP_LEVEL_STATE_ON
;
2901 snmp_varlist_add_variable(
2902 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_state
,
2903 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state
), INTEGER
,
2904 (uint8_t *)&val
, sizeof(val
));
2906 send_v2trap(notification_vars
);
2907 snmp_free_varbind(notification_vars
);
2908 smux_events_update();
2912 static int isis_snmp_lsp_exceed_max_update(const struct isis_area
*area
,
2913 const uint8_t *lsp_id
)
2915 netsnmp_variable_list
*notification_vars
;
2918 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_EXCEED_MAX
))
2921 notification_vars
= NULL
;
2923 /* Put in trap value */
2924 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
2925 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
2926 (uint8_t *)&isis_snmp_trap_val_lsp_exceed_max
,
2927 sizeof(isis_snmp_trap_val_lsp_exceed_max
));
2930 val
= area
->is_type
;
2932 snmp_varlist_add_variable(
2933 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
2934 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
2935 (uint8_t *)&val
, sizeof(val
));
2937 snmp_varlist_add_variable(
2938 ¬ification_vars
, isis_snmp_trap_data_var_pdu_lsp_id
,
2939 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
2940 ISIS_SYS_ID_LEN
+ 2);
2942 send_v2trap(notification_vars
);
2943 snmp_free_varbind(notification_vars
);
2944 smux_events_update();
2950 * A common function to handle popular combination of trap objects
2951 * isisNotificationSysLevelIndex,
2953 * isisNotificationCircIfIndex,
2956 static void isis_snmp_update_worker_a(const struct isis_circuit
*circuit
,
2957 oid trap_id
, const oid
*oid_a
,
2958 size_t oid_a_len
, uint8_t type_a
,
2959 const void *data_a
, size_t data_a_len
,
2960 const oid
*oid_b
, size_t oid_b_len
,
2961 uint8_t type_b
, const void *data_b
,
2964 netsnmp_variable_list
*notification_vars
= NULL
;
2965 oid var_name
[MAX_OID_LEN
];
2970 if (trap_id
!= ISIS_TRAP_ID_LEN_MISMATCH
2971 && trap_id
!= ISIS_TRAP_MAX_AREA_ADDR_MISMATCH
2972 && trap_id
!= ISIS_TRAP_OWN_LSP_PURGE
2973 && trap_id
!= ISIS_TRAP_SEQNO_SKIPPED
2974 && trap_id
!= ISIS_TRAP_AUTHEN_TYPE_FAILURE
2975 && trap_id
!= ISIS_TRAP_AUTHEN_FAILURE
2976 && trap_id
!= ISIS_TRAP_REJ_ADJACENCY
)
2979 /* Put in trap value */
2980 memcpy(var_name
, isis_snmp_notifications
,
2981 sizeof(isis_snmp_notifications
));
2982 var_count
= ARRAY_SIZE(isis_snmp_notifications
);
2983 var_name
[var_count
++] = trap_id
;
2985 /* Put in trap value */
2986 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
2987 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
2988 (uint8_t *)var_name
, var_count
* sizeof(oid
));
2990 val
= circuit
->is_type
;
2991 snmp_varlist_add_variable(
2992 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
2993 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
2994 (uint8_t *)&val
, sizeof(val
));
2996 if (oid_a_len
!= 0) {
2997 if (oid_a
== NULL
|| data_a
== NULL
|| data_a_len
== 0)
3000 snmp_varlist_add_variable(¬ification_vars
, oid_a
, oid_a_len
,
3001 type_a
, (uint8_t *)data_a
,
3005 if (circuit
->interface
== NULL
)
3008 val
= circuit
->interface
->ifindex
;
3010 snmp_varlist_add_variable(
3011 ¬ification_vars
, isis_snmp_trap_data_var_circ_if_index
,
3012 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index
), UNSIGNED32
,
3013 (uint8_t *)&val
, sizeof(val
));
3016 if (oid_b_len
!= 0) {
3017 if (oid_b
== NULL
|| data_b
== NULL
|| data_b_len
== 0)
3020 snmp_varlist_add_variable(¬ification_vars
, oid_b
, oid_b_len
,
3021 type_b
, (uint8_t *)data_b
,
3025 send_v2trap(notification_vars
);
3026 snmp_free_varbind(notification_vars
);
3027 smux_events_update();
3031 * A common function to handle popular combination of trap objects
3032 * isisNotificationSysLevelIndex,
3033 * isisNotificationCircIfIndex,
3037 * Note: the only difference with worker_a is order of circ-if-index vs
3040 static void isis_snmp_update_worker_b(const struct isis_circuit
*circuit
,
3041 oid trap_id
, const oid
*oid_a
,
3042 size_t oid_a_len
, uint8_t type_a
,
3043 const void *data_a
, size_t data_a_len
,
3044 const oid
*oid_b
, size_t oid_b_len
,
3045 uint8_t type_b
, const void *data_b
,
3048 netsnmp_variable_list
*notification_vars
= NULL
;
3049 oid var_name
[MAX_OID_LEN
];
3054 if (trap_id
!= ISIS_TRAP_VERSION_SKEW
3055 && trap_id
!= ISIS_TRAP_LSP_TOO_LARGE
3056 && trap_id
!= ISIS_TRAP_ADJ_STATE_CHANGE
)
3059 /* Put in trap value */
3060 memcpy(var_name
, isis_snmp_notifications
,
3061 sizeof(isis_snmp_notifications
));
3062 var_count
= ARRAY_SIZE(isis_snmp_notifications
);
3063 var_name
[var_count
++] = trap_id
;
3065 /* Put in trap value */
3066 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
3067 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
3068 (uint8_t *)var_name
, var_count
* sizeof(oid
));
3070 val
= circuit
->is_type
;
3071 snmp_varlist_add_variable(
3072 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
3073 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
3074 (uint8_t *)&val
, sizeof(val
));
3076 if (circuit
->interface
== NULL
)
3079 val
= circuit
->interface
->ifindex
;
3081 snmp_varlist_add_variable(
3082 ¬ification_vars
, isis_snmp_trap_data_var_circ_if_index
,
3083 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index
), UNSIGNED32
,
3084 (uint8_t *)&val
, sizeof(val
));
3087 if (oid_a_len
!= 0) {
3088 if (oid_a
== NULL
|| data_a
== NULL
|| data_a_len
== 0)
3091 snmp_varlist_add_variable(¬ification_vars
, oid_a
, oid_a_len
,
3092 type_a
, (uint8_t *)data_a
,
3096 if (oid_b_len
!= 0) {
3097 if (oid_b
== NULL
|| data_b
== NULL
|| data_b_len
== 0)
3100 snmp_varlist_add_variable(¬ification_vars
, oid_b
, oid_b_len
,
3101 type_b
, (uint8_t *)data_b
,
3105 send_v2trap(notification_vars
);
3106 snmp_free_varbind(notification_vars
);
3107 smux_events_update();
3111 static int isis_snmp_id_len_mismatch_update(const struct isis_circuit
*circuit
,
3112 uint8_t rcv_id
, const char *raw_pdu
,
3117 if (!isis_snmp_trap_throttle(ISIS_TRAP_ID_LEN_MISMATCH
))
3122 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3123 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3125 isis_snmp_update_worker_a(
3126 circuit
, ISIS_TRAP_ID_LEN_MISMATCH
,
3127 isis_snmp_trap_data_var_pdu_field_len
,
3128 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_field_len
), UNSIGNED32
,
3129 &val
, sizeof(val
), isis_snmp_trap_data_var_pdu_fragment
,
3130 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3131 raw_pdu
, raw_pdu_len
);
3136 isis_snmp_max_area_addr_mismatch_update(const struct isis_circuit
*circuit
,
3137 uint8_t max_addrs
, const char *raw_pdu
,
3142 if (!isis_snmp_trap_throttle(ISIS_TRAP_MAX_AREA_ADDR_MISMATCH
))
3147 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3148 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3150 isis_snmp_update_worker_a(
3151 circuit
, ISIS_TRAP_MAX_AREA_ADDR_MISMATCH
,
3152 isis_snmp_trap_data_var_pdu_max_area_addr
,
3153 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_max_area_addr
),
3154 UNSIGNED32
, &val
, sizeof(val
),
3155 isis_snmp_trap_data_var_pdu_fragment
,
3156 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3157 raw_pdu
, raw_pdu_len
);
3161 static int isis_snmp_own_lsp_purge_update(const struct isis_circuit
*circuit
,
3162 const uint8_t *lsp_id
)
3164 if (!isis_snmp_trap_throttle(ISIS_TRAP_OWN_LSP_PURGE
))
3167 isis_snmp_update_worker_a(
3168 circuit
, ISIS_TRAP_OWN_LSP_PURGE
, NULL
, 0, STRING
, NULL
, 0,
3169 isis_snmp_trap_data_var_pdu_lsp_id
,
3170 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3171 ISIS_SYS_ID_LEN
+ 2);
3175 static int isis_snmp_seqno_skipped_update(const struct isis_circuit
*circuit
,
3176 const uint8_t *lsp_id
)
3178 if (!isis_snmp_trap_throttle(ISIS_TRAP_SEQNO_SKIPPED
))
3181 isis_snmp_update_worker_a(
3182 circuit
, ISIS_TRAP_SEQNO_SKIPPED
, NULL
, 0, STRING
, NULL
, 0,
3183 isis_snmp_trap_data_var_pdu_lsp_id
,
3184 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3185 ISIS_SYS_ID_LEN
+ 2);
3190 isis_snmp_authentication_type_failure_update(const struct isis_circuit
*circuit
,
3191 const char *raw_pdu
,
3194 if (!isis_snmp_trap_throttle(ISIS_TRAP_AUTHEN_TYPE_FAILURE
))
3197 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3198 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3200 isis_snmp_update_worker_a(
3201 circuit
, ISIS_TRAP_AUTHEN_TYPE_FAILURE
, NULL
, 0, STRING
, NULL
,
3202 0, isis_snmp_trap_data_var_pdu_fragment
,
3203 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3204 raw_pdu
, raw_pdu_len
);
3209 isis_snmp_authentication_failure_update(const struct isis_circuit
*circuit
,
3210 char const *raw_pdu
, size_t raw_pdu_len
)
3212 if (!isis_snmp_trap_throttle(ISIS_TRAP_AUTHEN_FAILURE
))
3215 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3216 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3218 isis_snmp_update_worker_a(
3219 circuit
, ISIS_TRAP_AUTHEN_FAILURE
, NULL
, 0, STRING
, NULL
, 0,
3220 isis_snmp_trap_data_var_pdu_fragment
,
3221 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3222 raw_pdu
, raw_pdu_len
);
3226 static int isis_snmp_version_skew_update(const struct isis_circuit
*circuit
,
3227 uint8_t version
, const char *raw_pdu
,
3232 if (!isis_snmp_trap_throttle(ISIS_TRAP_VERSION_SKEW
))
3237 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3238 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3240 isis_snmp_update_worker_b(
3241 circuit
, ISIS_TRAP_VERSION_SKEW
,
3242 isis_snmp_trap_data_var_pdu_proto_ver
,
3243 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_proto_ver
), UNSIGNED32
,
3244 &val
, sizeof(val
), isis_snmp_trap_data_var_pdu_fragment
,
3245 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3246 raw_pdu
, raw_pdu_len
);
3250 static int isis_snmp_area_mismatch_update(const struct isis_circuit
*circuit
,
3251 const char *raw_pdu
,
3255 * This is a special case because
3256 * it does not include isisNotificationSysLevelIndex
3258 netsnmp_variable_list
*notification_vars
;
3261 if (!isis_snmp_trap_throttle(ISIS_TRAP_AREA_MISMATCH
))
3264 notification_vars
= NULL
;
3266 /* Put in trap value */
3267 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
3268 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
3269 (uint8_t *)&isis_snmp_trap_val_area_mismatch
,
3270 sizeof(isis_snmp_trap_val_area_mismatch
));
3273 if (circuit
->interface
== NULL
)
3276 val
= circuit
->interface
->ifindex
;
3278 snmp_varlist_add_variable(
3279 ¬ification_vars
, isis_snmp_trap_data_var_circ_if_index
,
3280 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index
), UNSIGNED32
,
3281 (uint8_t *)&val
, sizeof(val
));
3284 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3285 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3287 snmp_varlist_add_variable(
3288 ¬ification_vars
, isis_snmp_trap_data_var_pdu_fragment
,
3289 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3290 raw_pdu
, raw_pdu_len
);
3292 send_v2trap(notification_vars
);
3293 snmp_free_varbind(notification_vars
);
3294 smux_events_update();
3299 static int isis_snmp_reject_adjacency_update(const struct isis_circuit
*circuit
,
3300 const char *raw_pdu
,
3303 if (!isis_snmp_trap_throttle(ISIS_TRAP_REJ_ADJACENCY
))
3306 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3307 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3309 isis_snmp_update_worker_a(
3310 circuit
, ISIS_TRAP_REJ_ADJACENCY
, NULL
, 0, STRING
, NULL
, 0,
3311 isis_snmp_trap_data_var_pdu_fragment
,
3312 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3313 raw_pdu
, raw_pdu_len
);
3317 static int isis_snmp_lsp_too_large_update(const struct isis_circuit
*circuit
,
3319 const uint8_t *lsp_id
)
3321 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_TOO_LARGE
))
3324 isis_snmp_update_worker_b(
3325 circuit
, ISIS_TRAP_LSP_TOO_LARGE
,
3326 isis_snmp_trap_data_var_pdu_lsp_size
,
3327 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_size
), UNSIGNED32
,
3328 &pdu_size
, sizeof(pdu_size
), isis_snmp_trap_data_var_pdu_lsp_id
,
3329 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3330 ISIS_SYS_ID_LEN
+ 2);
3335 static int isis_snmp_adj_state_change_update(const struct isis_adjacency
*adj
)
3337 uint8_t lsp_id
[ISIS_SYS_ID_LEN
+ 2];
3339 struct isis
*isis
= isis_lookup_by_vrfid(VRF_DEFAULT
);
3341 if (isis
== NULL
|| !isis
->snmp_notifications
|| !smux_enabled())
3345 memcpy(lsp_id
, adj
->sysid
, ISIS_SYS_ID_LEN
);
3346 lsp_id
[ISIS_SYS_ID_LEN
] = 0;
3347 lsp_id
[ISIS_SYS_ID_LEN
+ 1] = 0;
3349 val
= isis_snmp_adj_state(adj
->adj_state
);
3351 isis_snmp_update_worker_b(
3352 adj
->circuit
, ISIS_TRAP_ADJ_STATE_CHANGE
,
3353 isis_snmp_trap_data_var_pdu_lsp_id
,
3354 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3355 ISIS_SYS_ID_LEN
+ 2, isis_snmp_trap_data_var_adj_state
,
3356 ARRAY_SIZE(isis_snmp_trap_data_var_adj_state
), INTEGER
, &val
,
3361 static int isis_snmp_lsp_error_update(const struct isis_circuit
*circuit
,
3362 const uint8_t *lsp_id
,
3363 char const *raw_pdu
, size_t raw_pdu_len
)
3366 * This is a special case because
3367 * it have more variables
3369 netsnmp_variable_list
*notification_vars
;
3372 if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_ERROR
))
3375 notification_vars
= NULL
;
3377 /* Put in trap value */
3378 snmp_varlist_add_variable(¬ification_vars
, isis_snmp_trap_var
,
3379 ARRAY_SIZE(isis_snmp_trap_var
), ASN_OBJECT_ID
,
3380 (uint8_t *)&isis_snmp_trap_val_lsp_error
,
3381 sizeof(isis_snmp_trap_val_lsp_error
));
3384 val
= circuit
->is_type
;
3386 snmp_varlist_add_variable(
3387 ¬ification_vars
, isis_snmp_trap_data_var_sys_level_index
,
3388 ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index
), INTEGER
,
3389 (uint8_t *)&val
, sizeof(val
));
3392 snmp_varlist_add_variable(
3393 ¬ification_vars
, isis_snmp_trap_data_var_pdu_lsp_id
,
3394 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id
), STRING
, lsp_id
,
3395 ISIS_SYS_ID_LEN
+ 2);
3398 if (circuit
->interface
== NULL
)
3401 val
= circuit
->interface
->ifindex
;
3403 snmp_varlist_add_variable(
3404 ¬ification_vars
, isis_snmp_trap_data_var_circ_if_index
,
3405 ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index
), UNSIGNED32
,
3406 (uint8_t *)&val
, sizeof(val
));
3409 if (raw_pdu_len
> ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
)
3410 raw_pdu_len
= ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN
;
3412 snmp_varlist_add_variable(
3413 ¬ification_vars
, isis_snmp_trap_data_var_pdu_fragment
,
3414 ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment
), STRING
,
3415 raw_pdu
, raw_pdu_len
);
3420 snmp_varlist_add_variable(
3421 ¬ification_vars
, isis_snmp_trap_data_var_error_offset
,
3422 ARRAY_SIZE(isis_snmp_trap_data_var_error_offset
), UNSIGNED32
,
3423 (uint8_t *)&val
, sizeof(val
));
3428 snmp_varlist_add_variable(
3429 ¬ification_vars
, isis_snmp_trap_data_var_error_tlv_type
,
3430 ARRAY_SIZE(isis_snmp_trap_data_var_error_tlv_type
), UNSIGNED32
,
3431 (uint8_t *)&val
, sizeof(val
));
3433 send_v2trap(notification_vars
);
3434 snmp_free_varbind(notification_vars
);
3435 smux_events_update();
3440 static int isis_snmp_module_init(void)
3442 hook_register(isis_hook_db_overload
, isis_snmp_db_overload_update
);
3443 hook_register(isis_hook_lsp_exceed_max
,
3444 isis_snmp_lsp_exceed_max_update
);
3445 hook_register(isis_hook_id_len_mismatch
,
3446 isis_snmp_id_len_mismatch_update
);
3447 hook_register(isis_hook_max_area_addr_mismatch
,
3448 isis_snmp_max_area_addr_mismatch_update
);
3449 hook_register(isis_hook_own_lsp_purge
, isis_snmp_own_lsp_purge_update
);
3450 hook_register(isis_hook_seqno_skipped
, isis_snmp_seqno_skipped_update
);
3451 hook_register(isis_hook_authentication_type_failure
,
3452 isis_snmp_authentication_type_failure_update
);
3453 hook_register(isis_hook_authentication_failure
,
3454 isis_snmp_authentication_failure_update
);
3455 hook_register(isis_hook_version_skew
, isis_snmp_version_skew_update
);
3456 hook_register(isis_hook_area_mismatch
, isis_snmp_area_mismatch_update
);
3457 hook_register(isis_hook_reject_adjacency
,
3458 isis_snmp_reject_adjacency_update
);
3459 hook_register(isis_hook_lsp_too_large
, isis_snmp_lsp_too_large_update
);
3460 hook_register(isis_hook_adj_state_change
,
3461 isis_snmp_adj_state_change_update
);
3462 hook_register(isis_hook_lsp_error
, isis_snmp_lsp_error_update
);
3463 hook_register(isis_circuit_new_hook
, isis_circuit_snmp_id_gen
);
3464 hook_register(isis_circuit_del_hook
, isis_circuit_snmp_id_free
);
3466 hook_register(frr_late_init
, isis_snmp_init
);
3471 .name
= "isis_snmp",
3472 .version
= FRR_VERSION
,
3473 .description
= "isis AgentX SNMP module",
3474 .init
= isis_snmp_module_init
,