From 8ca3da075bfc6d6b1b0592d24b6e5376b041f34e Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Wed, 29 May 2019 18:58:09 +0200 Subject: [PATCH] snmp: implement lldpRemOrgDefInfoTable for remote custom TLVs As a simplification, lldpRemOrgDefInfoIndex is 1 for the first custom TLV of a given port and is increased by 1 for each new TLV. This is not what is encouraged in the MIB: > An agent is encouraged to assign monotonically increasing index > values to new entries, starting with one, after each reboot. It is > considered unlikely that the lldpRemOrgDefInfoIndex will wrap > between reboots. However, it is simpler to implement it this way as we don't need to record the index inside the `lldpd_custom` structure. Also, the index will increase even for a different OUI or subtype as we do not want to sort the custom TLVs. Fix #330. --- NEWS | 1 + src/daemon/agent.c | 70 +++++++++++++++++++++++++++++++++++++++++++++- tests/check_snmp.c | 59 +++++++++++++++++++++++++++++++++++++- 3 files changed, 128 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index bf8f0aa6..608188e8 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ lldpd (1.0.4) * Changes: + Add "configure system max-neighbors XX" command to modify maximum of neighbors accepted per port. + + Implement lldpRemOrgDefInfoTable table for custom TLVs. * Fix: + Better compliance for statsTLVsUnrecognizedTotal and statsAgeoutsTotal counters. diff --git a/src/daemon/agent.c b/src/daemon/agent.c index dd36d943..cd33c78e 100644 --- a/src/daemon/agent.c +++ b/src/daemon/agent.c @@ -295,6 +295,40 @@ header_tpripindexed_table(struct variable *vp, oid *name, size_t *length, return header_index_best(); } +#ifdef ENABLE_CUSTOM +static struct lldpd_custom* +header_tprcustomindexed_table(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + struct lldpd_hardware *hardware; + struct lldpd_port *port; + struct lldpd_custom *custom; + oid index[8]; + oid idx; + + if (!header_index_init(vp, name, length, exact, var_len, write_method)) return NULL; + TAILQ_FOREACH(hardware, &scfg->g_hardware, h_entries) { + TAILQ_FOREACH(port, &hardware->h_rports, p_entries) { + if (SMART_HIDDEN(port)) continue; + idx = 1; + TAILQ_FOREACH(custom, &port->p_custom_list, next) { + index[0] = lastchange(port); + index[1] = hardware->h_ifindex; + index[2] = port->p_chassis->c_index; + index[3] = custom->oui[0]; + index[4] = custom->oui[1]; + index[5] = custom->oui[2]; + index[6] = custom->subtype; + index[7] = idx++; + if (header_index_add(index, 8, custom)) + return custom; + } + } + } + return header_index_best(); +} +#endif + #ifdef ENABLE_LLDPMED #define TPR_VARIANT_MED_POLICY 2 #define TPR_VARIANT_MED_LOCATION 3 @@ -552,6 +586,8 @@ header_tprpiindexed_table(struct variable *vp, oid *name, size_t *length, #define LLDP_SNMP_ADDR_IFSUBTYPE 2 #define LLDP_SNMP_ADDR_IFID 3 #define LLDP_SNMP_ADDR_OID 4 +/* Custom TLVs */ +#define LLDP_SNMP_ORG_DEF_INFO 1 /* LLDP-MED */ #define LLDP_SNMP_MED_CAP_AVAILABLE 1 #define LLDP_SNMP_MED_CAP_ENABLED 2 @@ -1407,6 +1443,33 @@ agent_h_remote_management(struct variable *vp, oid *name, size_t *length, return agent_v_management(vp, var_len, mgmt); } +#ifdef ENABLE_CUSTOM +static u_char* +agent_v_custom(struct variable *vp, size_t *var_len, struct lldpd_custom *custom) +{ + switch (vp->magic) { + case LLDP_SNMP_ORG_DEF_INFO: + *var_len = custom->oui_info_len; + return (u_char *)custom->oui_info; + default: + break; + } + return NULL; +} +static u_char* +agent_h_remote_custom(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + struct lldpd_custom *custom; + + if ((custom = header_tprcustomindexed_table(vp, name, length, + exact, var_len, write_method)) == NULL) + return NULL; + + return agent_v_custom(vp, var_len, custom); +} +#endif + /* Here is how it works: a agent_h_*() function will handle incoming requests. It will use an appropriate header_*indexed_table() @@ -1477,8 +1540,13 @@ struct variable8 agent_lldp_vars[] = { {1, 4, 2, 1, 4}}, {LLDP_SNMP_ADDR_OID, ASN_OBJECT_ID, RONLY, agent_h_remote_management, 5, {1, 4, 2, 1, 5}}, - /* Dot3, local ports */ +#ifdef ENABLE_CUSTOM + /* Custom TLVs */ + {LLDP_SNMP_ORG_DEF_INFO, ASN_OCTET_STR, RONLY, agent_h_remote_custom, 5, + {1, 4, 4, 1, 4}}, +#endif #ifdef ENABLE_DOT3 + /* Dot3, local ports */ {LLDP_SNMP_DOT3_AUTONEG_SUPPORT, ASN_INTEGER, RONLY, agent_h_local_port, 8, {1, 5, 4623, 1, 2, 1, 1, 1}}, {LLDP_SNMP_DOT3_AUTONEG_ENABLED, ASN_INTEGER, RONLY, agent_h_local_port, 8, diff --git a/tests/check_snmp.c b/tests/check_snmp.c index 742c5bf8..24b3077a 100644 --- a/tests/check_snmp.c +++ b/tests/check_snmp.c @@ -246,10 +246,38 @@ struct lldpd_hardware hardware2 = { .data_len = 15, }, { .format = 0 }, { .format = 0 }, }, -#endif +#endif } }; +#ifdef ENABLE_CUSTOM +struct lldpd_custom custom1 = { + .oui = { 33, 44, 55 }, + .subtype = 44, + .oui_info = (u_int8_t*)"OUI content", +}; +struct lldpd_custom custom2 = { + .oui = { 33, 44, 55 }, + .subtype = 44, + .oui_info = (u_int8_t*)"More content", +}; +struct lldpd_custom custom3 = { + .oui = { 33, 44, 55 }, + .subtype = 45, + .oui_info = (u_int8_t*)"More more content", +}; +struct lldpd_custom custom4 = { + .oui = { 33, 44, 56 }, + .subtype = 44, + .oui_info = (u_int8_t*)"Even more content", +}; +struct lldpd_custom custom5 = { + .oui = { 33, 44, 55 }, + .subtype = 44, + .oui_info = (u_int8_t*)"Still more content", +}; +#endif + #ifdef ENABLE_DOT1 struct lldpd_vlan vlan47 = { .v_name = "VLAN #47", @@ -308,6 +336,21 @@ snmp_config() TAILQ_INIT(&test_cfg.g_hardware); TAILQ_INSERT_TAIL(&test_cfg.g_hardware, &hardware1, h_entries); TAILQ_INSERT_TAIL(&test_cfg.g_hardware, &hardware2, h_entries); +#ifdef ENABLE_CUSTOM + custom1.oui_info_len = strlen((char*)custom1.oui_info); + custom2.oui_info_len = strlen((char*)custom2.oui_info); + custom3.oui_info_len = strlen((char*)custom3.oui_info); + custom4.oui_info_len = strlen((char*)custom4.oui_info); + custom5.oui_info_len = strlen((char*)custom5.oui_info); + TAILQ_INIT(&hardware1.h_lport.p_custom_list); + TAILQ_INIT(&hardware2.h_lport.p_custom_list); + TAILQ_INIT(&port2.p_custom_list); + TAILQ_INSERT_TAIL(&hardware2.h_lport.p_custom_list, &custom1, next); + TAILQ_INSERT_TAIL(&hardware2.h_lport.p_custom_list, &custom2, next); + TAILQ_INSERT_TAIL(&hardware2.h_lport.p_custom_list, &custom3, next); + TAILQ_INSERT_TAIL(&hardware2.h_lport.p_custom_list, &custom4, next); + TAILQ_INSERT_TAIL(&hardware1.h_lport.p_custom_list, &custom5, next); +#endif #ifdef ENABLE_DOT1 TAILQ_INIT(&hardware1.h_lport.p_vlans); TAILQ_INSERT_TAIL(&hardware1.h_lport.p_vlans, &vlan47, v_entries); @@ -525,6 +568,20 @@ struct tree_node snmp_tree[] = { { .string = { .octet = (char *)zeroDotZero, .len = sizeof(zeroDotZero) }} }, +#ifdef ENABLE_CUSTOM + /* lldpRemOrgDefInfo */ + { {1, 4, 4, 1, 4, 0, 3, 1, 33, 44, 55, 44, 1 }, 13, ASN_OCTET_STR, + { .string = { .octet = "OUI content", .len = 11 }} }, + { {1, 4, 4, 1, 4, 0, 3, 1, 33, 44, 55, 44, 2 }, 13, ASN_OCTET_STR, + { .string = { .octet = "More content", .len = 12 }} }, + { {1, 4, 4, 1, 4, 0, 3, 1, 33, 44, 55, 45, 3 }, 13, ASN_OCTET_STR, + { .string = { .octet = "More more content", .len = 17 }} }, + { {1, 4, 4, 1, 4, 0, 3, 1, 33, 44, 56, 44, 4 }, 13, ASN_OCTET_STR, + { .string = { .octet = "Even more content", .len = 17 }} }, + { {1, 4, 4, 1, 4, 10000, 4, 1, 33, 44, 55, 44, 1 }, 13, ASN_OCTET_STR, + { .string = { .octet = "Still more content", .len = 18 }} }, +#endif + #ifdef ENABLE_DOT3 /* lldpXdot3LocPortAutoNegSupported */ { {1, 5, 4623, 1, 2, 1, 1, 1, 3 }, 9, ASN_INTEGER, { .integer = 1 }}, -- 2.39.5