diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:16:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:16:35 +0000 |
commit | e2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch) | |
tree | f0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /ldpd/ldp_snmp.c | |
parent | Initial commit. (diff) | |
download | frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.tar.xz frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.zip |
Adding upstream version 9.1.upstream/9.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ldpd/ldp_snmp.c')
-rw-r--r-- | ldpd/ldp_snmp.c | 1224 |
1 files changed, 1224 insertions, 0 deletions
diff --git a/ldpd/ldp_snmp.c b/ldpd/ldp_snmp.c new file mode 100644 index 0000000..ed391ac --- /dev/null +++ b/ldpd/ldp_snmp.c @@ -0,0 +1,1224 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * LDP SNMP support + * Copyright (C) 2020 Volta Networks, Inc. + */ + +/* + * This is minimal read-only implementations providing + * mplsLdpModuleReadOnlyCompliance as described in RFC 3815. + */ + +#include <zebra.h> + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> + +#include "vrf.h" +#include "if.h" +#include "log.h" +#include "prefix.h" +#include "table.h" +#include "command.h" +#include "memory.h" +#include "smux.h" +#include "libfrr.h" +#include "lib/version.h" +#include "ldpd.h" +#include "ldpe.h" + +/* SNMP value hack. */ +#define COUNTER32 ASN_COUNTER +#define INTEGER ASN_INTEGER +#define UNSIGNED32 ASN_GAUGE +#define TIMESTAMP ASN_TIMETICKS +#define TIMETICKS ASN_TIMETICKS +#define STRING ASN_OCTET_STR +#define IPADDRESS ASN_IPADDRESS + +#define LDP_LSRID_IDX_LEN 6 +#define LDP_ENTITY_IDX_LEN 1 +#define LDP_ADJACENCY_IDX_LEN 1 + +/* MPLS-LDP-STD-MIB. */ +#define MPLS_LDP_STD_MIB 1, 3, 6, 1, 2, 1, 10, 166, 4 + +#define MPLS_LDP_LSR_ID 0 +#define MPLS_LDP_LSR_LOOP_DETECTION_CAPABLE 0 +#define MPLS_LDP_ENTITY_LAST_CHANGE 0 +#define MPLS_LDP_ENTITY_INDEX_NEXT 0 + +/* Declare static local variables for convenience. */ +SNMP_LOCAL_VARIABLES + +/* LDP-MIB instances. */ +static oid ldp_oid[] = {MPLS_LDP_STD_MIB}; +static oid ldp_trap_oid[] = {MPLS_LDP_STD_MIB, 0}; + +static uint8_t snmp_ldp_rtrid[6] = {0, 0, 0, 0, 0}; + +#define LDP_DEFAULT_ENTITY_INDEX 1 + +#define MPLSLDPLSRLOOPDETECTIONCAPABLE_NONE 1 +#define MPLSLDPLSRLOOPDETECTIONCAPABLE_OTHER 2 +#define MPLSLDPLSRLOOPDETECTIONCAPABLE_HOPCOUNT 3 +#define MPLSLDPLSRLOOPDETECTIONCAPABLE_PATHVECTOR 4 +#define MPLSLDPLSRLOOPDETECTIONCAPABLE_HOPCOUNTANDPATHVECTOR 5 + +/* MPLS LDP mplsLdpHelloAdjacencyTable. */ +#define MPLSLDPHELLOADJACENCYINDEX 1 +#define MPLSLDPHELLOADJACENCYHOLDTIMEREM 2 +#define MPLSLDPHELLOADJACENCYHOLDTIME 3 +#define MPLSLDPHELLOADJACENCYTYPE 4 + +/* enums for column mplsLdpHelloAdjacencyType */ +#define MPLSLDPHELLOADJACENCYTYPE_LINK 1 +#define MPLSLDPHELLOADJACENCYTYPE_TARGETED 2 + +#define MPLSLDPPEERTRANSPORTADDRTYPE_UNKNOWN 0 +#define MPLSLDPPEERTRANSPORTADDRTYPE_IPV4 1 +#define MPLSLDPPEERTRANSPORTADDRTYPE_IPV6 2 +#define MPLSLDPPEERTRANSPORTADDRTYPE_IPV4Z 3 +#define MPLSLDPPEERTRANSPORTADDRTYPE_IPV6Z 4 +#define MPLSLDPPEERTRANSPORTADDRTYPE_DNS 16 + +#define DOWNSTREAMONDEMAND 1 +#define DOWNSTREAMUNSOLICITED 2 + +#define CONSERVATIVERETENTION 1 +#define LIBERALRETENTION 2 + +#define TRANSPORTADDRINTERFACE 1 +#define TRANSPORTADDRLOOPBACK 2 + +#define LABELTYPEGENERIC 1 + +#define STORAGETYPENONVOLATILE 3 + +#define ROWSTATUSACTIVE 4 + +#define ADMINSTATUSENABLED 1 + +#define OPERSTATUSENABLED 2 + +/* MPLS LDP mplsLdpPeerTable */ +#define MPLSLDPPEERLDPID 1 +#define MPLSLDPPEERLABELDISTMETHOD 2 +#define MPLSLDPPEERPATHVECTORLIMIT 3 +#define MPLSLDPPEERTRANSPORTADDRTYPE 4 +#define MPLSLDPPEERTRANSPORTADDR 5 + +#define MPLSLDPSESSIONROLE_UNKNOWN 1 +#define MPLSLDPSESSIONROLE_ACTIVE 2 +#define MPLSLDPSESSIONROLE_PASSIVE 3 + +#define MPLSLDPSESSIONSTATE_NONEXISTENT 1 +#define MPLSLDPSESSIONSTATE_INITIALIZED 2 +#define MPLSLDPSESSIONSTATE_OPENREC 3 +#define MPLSLDPSESSIONSTATE_OPENSENT 4 +#define MPLSLDPSESSIONSTATE_OPERATIONAL 5 + +/* MPLS LDP mplsLdpSessionTable */ +#define MPLSLDPSESSIONSTATELASTCHANGE 1 +#define MPLSLDPSESSIONSTATE 2 +#define MPLSLDPSESSIONROLE 3 +#define MPLSLDPSESSIONPROTOCOLVERSION 4 +#define MPLSLDPSESSIONKEEPALIVEHOLDTIMEREM 5 +#define MPLSLDPSESSIONKEEPALIVETIME 6 +#define MPLSLDPSESSIONMAXPDULENGTH 7 +#define MPLSLDPSESSIONDISCONTINUITYTIME 8 + +/* MPLS LDP mplsLdpEntityTable */ +#define MPLSLDPENTITYLDPID 1 +#define MPLSLDPENTITYINDEX 2 +#define MPLSLDPENTITYPROTOCOLVERSION 3 +#define MPLSLDPENTITYADMINSTATUS 4 +#define MPLSLDPENTITYOPERSTATUS 5 +#define MPLSLDPENTITYTCPPORT 6 +#define MPLSLDPENTITYUDPDSCPORT 7 +#define MPLSLDPENTITYMAXPDULENGTH 8 +#define MPLSLDPENTITYKEEPALIVEHOLDTIMER 9 +#define MPLSLDPENTITYHELLOHOLDTIMER 10 +#define MPLSLDPENTITYINITSESSIONTHRESHOLD 11 +#define MPLSLDPENTITYLABELDISTMETHOD 12 +#define MPLSLDPENTITYLABELRETENTIONMODE 13 +#define MPLSLDPENTITYPATHVECTORLIMIT 14 +#define MPLSLDPENTITYHOPCOUNTLIMIT 15 +#define MPLSLDPENTITYTRANSPORTADDRKIND 16 +#define MPLSLDPENTITYTARGETPEER 17 +#define MPLSLDPENTITYTARGETPEERADDRTYPE 18 +#define MPLSLDPENTITYTARGETPEERADDR 19 +#define MPLSLDPENTITYLABELTYPE 20 +#define MPLSLDPENTITYDISCONTINUITYTIME 21 +#define MPLSLDPENTITYSTORAGETYPE 22 +#define MPLSLDPENTITYROWSTATUS 23 + +/* MPLS LDP mplsLdpEntityStatsTable */ +#define MPLSLDPENTITYSTATSSESSIONATTEMPTS 1 +#define MPLSLDPENTITYSTATSSESSIONREJHELLO 2 +#define MPLSLDPENTITYSTATSSESSIONREJAD 3 +#define MPLSLDPENTITYSTATSSESSIONREJMAXPDU 4 +#define MPLSLDPENTITYSTATSSESSIONREJLR 5 +#define MPLSLDPENTITYSTATSBADLDPID 6 +#define MPLSLDPENTITYSTATSBADPDULENGTH 7 +#define MPLSLDPENTITYSTATSBADMSGLENGTH 8 +#define MPLSLDPENTITYSTATSBADTLVLENGTH 9 +#define MPLSLDPENTITYSTATSMALFORMEDTLV 10 +#define MPLSLDPENTITYSTATSKEEPALIVEEXP 11 +#define MPLSLDPENTITYSTATSSHUTDOWNRCVNOTIFY 12 +#define MPLSLDPENTITYSTATSSHUTDOWNSENTNOTIFY 13 + +#define MPLSLDPSESSIONSTATSUNKNOWNMESTYPEERRORS 1 +#define MPLSLDPSESSIONSTATSUNKNOWNTLVERRORS 2 + +static uint8_t *ldpLsrId(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + *var_len = 4; + return (uint8_t *)&leconf->rtr_id.s_addr; +} + +static uint8_t *ldpLoopDetectCap(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + return SNMP_INTEGER(MPLSLDPLSRLOOPDETECTIONCAPABLE_NONE); +} + +extern uint32_t ldp_start_time; +static uint8_t *ldpEntityLastChange(struct variable *v, oid name[], + size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + *var_len = sizeof(time_t); + return (uint8_t *) &(leconf->config_change_time); + +} + +static uint8_t *ldpEntityIndexNext(struct variable *v, oid name[], + size_t *length,int exact, size_t *var_len, + WriteMethod **write_method) +{ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + return SNMP_INTEGER(0); +} + +#define LDP_ENTITY_TOTAL_LEN 21 +#define LDP_ENTITY_MAX_IDX_LEN 6 + +static struct ldpd_af_conf *ldpEntityTable_lookup(struct variable *v, oid *name, + size_t *length, int exact, + uint32_t *index) +{ + int len; + struct ldpd_af_conf *af_v4, *af_v6; + + af_v4 = &leconf->ipv4; + af_v6 = &leconf->ipv6; + + if (exact) { + if (*length != LDP_ENTITY_TOTAL_LEN) + return NULL; + + if (leconf->trans_pref == DUAL_STACK_LDPOV6 && + af_v6->flags & F_LDPD_AF_ENABLED) { + *index = 2; + return af_v6; + } else { + *index = 1; + return af_v4; + } + } else { + /* only support one router id so can just skip */ + len = *length - v->namelen - LDP_ENTITY_MAX_IDX_LEN; + if (len <= 0) { + if (leconf->trans_pref == DUAL_STACK_LDPOV6 && + af_v6->flags & F_LDPD_AF_ENABLED) { + *index = 2; + return af_v6; + } else { + *index = 1; + return af_v4; + } + } + } + return NULL; +} + +static uint8_t *ldpEntityTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct ldpd_af_conf *af; + struct in_addr entityLdpId = {.s_addr = 0}; + uint32_t index = 0; + + *write_method = NULL; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + af = ldpEntityTable_lookup(v, name, length, exact, &index); + if (af == NULL) + return NULL; + + if (!exact) { + entityLdpId.s_addr = ldp_rtr_id_get(leconf); + + /* Copy the name out */ + memcpy(name, v->name, v->namelen * sizeof(oid)); + + /* Append index */ + *length = LDP_ENTITY_TOTAL_LEN; + oid_copy_in_addr(name + v->namelen, &entityLdpId); + name[v->namelen + 4] = 0; + name[v->namelen + 5] = 0; + name[v->namelen + 6] = LDP_DEFAULT_ENTITY_INDEX; + } + + /* Return the current value of the variable */ + switch (v->magic) { + case MPLSLDPENTITYLDPID: + *var_len = 6; + memcpy (snmp_ldp_rtrid, &entityLdpId, IN_ADDR_SIZE); + return (uint8_t *)snmp_ldp_rtrid; + case MPLSLDPENTITYINDEX: + return SNMP_INTEGER(LDP_DEFAULT_ENTITY_INDEX); + case MPLSLDPENTITYPROTOCOLVERSION: + return SNMP_INTEGER(LDP_VERSION); + case MPLSLDPENTITYADMINSTATUS: + return SNMP_INTEGER(ADMINSTATUSENABLED); + case MPLSLDPENTITYOPERSTATUS: + return SNMP_INTEGER(OPERSTATUSENABLED); + case MPLSLDPENTITYTCPPORT: + return SNMP_INTEGER(LDP_PORT); + case MPLSLDPENTITYUDPDSCPORT: + return SNMP_INTEGER(LDP_PORT); + case MPLSLDPENTITYMAXPDULENGTH: + return SNMP_INTEGER(LDP_MAX_LEN); + case MPLSLDPENTITYKEEPALIVEHOLDTIMER: + return SNMP_INTEGER(af->keepalive); + case MPLSLDPENTITYHELLOHOLDTIMER: + return SNMP_INTEGER(af->lhello_holdtime); + case MPLSLDPENTITYINITSESSIONTHRESHOLD: + return SNMP_INTEGER(0); /* not supported */ + case MPLSLDPENTITYLABELDISTMETHOD: + return SNMP_INTEGER(DOWNSTREAMUNSOLICITED); + case MPLSLDPENTITYLABELRETENTIONMODE: + return SNMP_INTEGER(LIBERALRETENTION); + case MPLSLDPENTITYPATHVECTORLIMIT: + return SNMP_INTEGER(0); /* not supported */ + case MPLSLDPENTITYHOPCOUNTLIMIT: + return SNMP_INTEGER(0); + case MPLSLDPENTITYTRANSPORTADDRKIND: + return SNMP_INTEGER(TRANSPORTADDRLOOPBACK); + case MPLSLDPENTITYTARGETPEER: + return SNMP_INTEGER(1); + case MPLSLDPENTITYTARGETPEERADDRTYPE: + if (index == 1) + return SNMP_INTEGER(MPLSLDPPEERTRANSPORTADDRTYPE_IPV4); + else + return SNMP_INTEGER(MPLSLDPPEERTRANSPORTADDRTYPE_IPV6); + case MPLSLDPENTITYTARGETPEERADDR: + if (index == 1) { + *var_len = sizeof(af->trans_addr.v4); + return ((uint8_t *)&af->trans_addr.v4); + }else { + *var_len = sizeof(af->trans_addr.v6); + return ((uint8_t *)&af->trans_addr.v6); + } + case MPLSLDPENTITYLABELTYPE: + return SNMP_INTEGER(LABELTYPEGENERIC); + case MPLSLDPENTITYDISCONTINUITYTIME: + return SNMP_INTEGER(0); + case MPLSLDPENTITYSTORAGETYPE: + return SNMP_INTEGER(STORAGETYPENONVOLATILE); + case MPLSLDPENTITYROWSTATUS: + return SNMP_INTEGER(ROWSTATUSACTIVE); + default: + return NULL; + } + + return NULL; +} + +static uint8_t *ldpEntityStatsTable(struct variable *v, oid name[], + size_t *length, int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct in_addr entityLdpId = {.s_addr = 0}; + int len; + + *write_method = NULL; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + if (exact) { + if (*length != LDP_ENTITY_TOTAL_LEN) + return NULL; + } else { + len = *length - v->namelen - LDP_ENTITY_MAX_IDX_LEN; + if (len > 0) + return NULL; + + entityLdpId.s_addr = ldp_rtr_id_get(leconf); + + /* Copy the name out */ + memcpy(name, v->name, v->namelen * sizeof(oid)); + + /* Append index */ + *length = LDP_ENTITY_TOTAL_LEN; + oid_copy_in_addr(name + v->namelen, &entityLdpId); + name[v->namelen + 4] = 0; + name[v->namelen + 5] = 0; + name[v->namelen + 6] = LDP_DEFAULT_ENTITY_INDEX; + } + + /* Return the current value of the variable */ + switch (v->magic) { + case MPLSLDPENTITYSTATSSESSIONATTEMPTS: + return SNMP_INTEGER(leconf->stats.session_attempts); + case MPLSLDPENTITYSTATSSESSIONREJHELLO: + return SNMP_INTEGER(leconf->stats.session_rejects_hello); + case MPLSLDPENTITYSTATSSESSIONREJAD: + return SNMP_INTEGER(leconf->stats.session_rejects_ad); + case MPLSLDPENTITYSTATSSESSIONREJMAXPDU: + return SNMP_INTEGER(leconf->stats.session_rejects_max_pdu); + case MPLSLDPENTITYSTATSSESSIONREJLR: + return SNMP_INTEGER(leconf->stats.session_rejects_lr); + case MPLSLDPENTITYSTATSBADLDPID: + return SNMP_INTEGER(leconf->stats.bad_ldp_id); + case MPLSLDPENTITYSTATSBADPDULENGTH: + return SNMP_INTEGER(leconf->stats.bad_pdu_len); + case MPLSLDPENTITYSTATSBADMSGLENGTH: + return SNMP_INTEGER(leconf->stats.bad_msg_len); + case MPLSLDPENTITYSTATSBADTLVLENGTH: + return SNMP_INTEGER(leconf->stats.bad_tlv_len); + case MPLSLDPENTITYSTATSMALFORMEDTLV: + return SNMP_INTEGER(leconf->stats.malformed_tlv); + case MPLSLDPENTITYSTATSKEEPALIVEEXP: + return SNMP_INTEGER(leconf->stats.keepalive_timer_exp); + case MPLSLDPENTITYSTATSSHUTDOWNRCVNOTIFY: + return SNMP_INTEGER(leconf->stats.shutdown_rcv_notify); + case MPLSLDPENTITYSTATSSHUTDOWNSENTNOTIFY: + return SNMP_INTEGER(leconf->stats.shutdown_send_notify); + default: + return NULL; + } + + return NULL; +} + +#define LDP_ADJACENCY_ENTRY_MAX_IDX_LEN 14 + +static void ldpHelloAdjacencyTable_oid_to_index( + struct variable *v, oid name[], + size_t *length, + struct in_addr *entityLdpId, + uint32_t *entityIndex, + struct in_addr *peerLdpId, + uint32_t *adjacencyIndex) +{ + oid *offset = name + v->namelen; + int offsetlen = *length - v->namelen; + int len = offsetlen; + + if (len > LDP_ADJACENCY_ENTRY_MAX_IDX_LEN) + len = LDP_ADJACENCY_ENTRY_MAX_IDX_LEN; + + if (len >= LDP_LSRID_IDX_LEN) + oid2in_addr(offset, sizeof(struct in_addr), entityLdpId); + + offset += LDP_LSRID_IDX_LEN; + offsetlen -= LDP_LSRID_IDX_LEN; + len = offsetlen; + + if (len > LDP_ENTITY_IDX_LEN) + len = LDP_ENTITY_IDX_LEN; + + if (len >= LDP_ENTITY_IDX_LEN) + *entityIndex = offset[0]; + + offset += LDP_ENTITY_IDX_LEN; + offsetlen -= LDP_ENTITY_IDX_LEN; + len = offsetlen; + + if (len > LDP_LSRID_IDX_LEN) + len = LDP_LSRID_IDX_LEN; + + if (len >= LDP_LSRID_IDX_LEN) + oid2in_addr(offset, sizeof(struct in_addr), peerLdpId); + + offset += LDP_LSRID_IDX_LEN; + offsetlen -= LDP_LSRID_IDX_LEN; + len = offsetlen; + + if (len > LDP_ADJACENCY_IDX_LEN) + len = LDP_ADJACENCY_IDX_LEN; + + if (len >= LDP_ADJACENCY_IDX_LEN) + *adjacencyIndex = offset[0]; +} + +static struct adj * +nbr_get_adj_by_index(struct nbr *nbr, uint32_t adjacencyIndex) +{ + struct adj *adj; + uint32_t i = 0; + + RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) + if (++i == adjacencyIndex) + return adj; + + return NULL; +} + +static struct ctl_adj * +ldpHelloAdjacencyTable_lookup_helper( + struct in_addr *entityLdpId, + uint32_t *entityIndex, + struct in_addr *peerLdpId, + uint32_t *adjacencyIndex) +{ + struct ctl_adj *ctl_adj = NULL; + struct adj *adj = NULL; + struct nbr *cur_nbr = nbr_find_ldpid(peerLdpId->s_addr); + + if (cur_nbr) + /* If found nbr, then look to see if the + * adjacency exists + */ + adj = nbr_get_adj_by_index(cur_nbr, *adjacencyIndex); + + if (adj) + ctl_adj = adj_to_ctl(adj); + + return ctl_adj; +} + +static struct ctl_adj * +ldpHelloAdjacencyTable_next_helper( + int first, + struct in_addr *entityLdpId, + uint32_t *entityIndex, + struct in_addr *peerLdpId, + uint32_t *adjacencyIndex) +{ + struct ctl_adj *ctl_adj = NULL; + struct nbr *nbr = NULL; + struct adj *adj = NULL; + + if (first) + nbr = nbr_get_first_ldpid(); + else { + struct nbr *cur_nbr = nbr_find_ldpid(peerLdpId->s_addr); + if (cur_nbr) + /* If found nbr, then look to see if the + * adjacency exists + */ + adj = nbr_get_adj_by_index(cur_nbr, *adjacencyIndex + 1); + if (adj) + *adjacencyIndex += 1; + else + nbr = nbr_get_next_ldpid(peerLdpId->s_addr); + } + + if (!adj && nbr) { + adj = RB_MIN(nbr_adj_head, &nbr->adj_tree); + *adjacencyIndex = 1; + } + + if (adj) + ctl_adj = adj_to_ctl(adj); + + return ctl_adj; +} + +#define HELLO_ADJ_MAX_IDX_LEN 14 + +static struct ctl_adj * +ldpHelloAdjacencyTable_lookup(struct variable *v, oid name[], + size_t *length, int exact, + struct in_addr *entityLdpId, + uint32_t *entityIndex, + struct in_addr *peerLdpId, + uint32_t *adjacencyIndex) +{ + struct ctl_adj *hello_adj = NULL; + + if (exact) { + if (*length < HELLO_ADJ_MAX_IDX_LEN) + return NULL; + + ldpHelloAdjacencyTable_oid_to_index( + v, name, length, + entityLdpId, entityIndex, peerLdpId, adjacencyIndex); + + hello_adj = ldpHelloAdjacencyTable_lookup_helper( + entityLdpId, entityIndex, peerLdpId, adjacencyIndex); + } else { + int first = 0; + int offsetlen = *length - v->namelen; + + if (offsetlen < HELLO_ADJ_MAX_IDX_LEN) + first = 1; + + ldpHelloAdjacencyTable_oid_to_index( + v, name, length, + entityLdpId, entityIndex, peerLdpId, adjacencyIndex); + + hello_adj = ldpHelloAdjacencyTable_next_helper(first, + entityLdpId, entityIndex, peerLdpId, adjacencyIndex); + + } + return hello_adj; +} + +static uint8_t *ldpHelloAdjacencyTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct in_addr entityLdpId = {.s_addr = 0}; + uint32_t entityIndex = 0; + struct in_addr peerLdpId = {.s_addr = 0}; + uint32_t adjacencyIndex = 0; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + struct ctl_adj *ctl_adj = ldpHelloAdjacencyTable_lookup(v, name, + length, exact, + &entityLdpId, &entityIndex, &peerLdpId, &adjacencyIndex); + + if (!ctl_adj) + return NULL; + + if (!exact) { + + /* Copy the name out */ + memcpy(name, v->name, v->namelen * sizeof(oid)); + + /* Append index */ + struct in_addr entityLdpId = {.s_addr = 0}; + entityLdpId.s_addr = ldp_rtr_id_get(leconf); + + struct in_addr peerLdpId = ctl_adj->id; + + oid_copy_in_addr(name + v->namelen, &entityLdpId); + name[v->namelen + 4] = 0; + name[v->namelen + 5] = 0; + name[v->namelen + 6] = LDP_DEFAULT_ENTITY_INDEX; + oid_copy_in_addr(name + v->namelen + 7, &peerLdpId); + name[v->namelen + 11] = 0; + name[v->namelen + 12] = 0; + name[v->namelen + 13] = adjacencyIndex; + + /* Set length */ + *length = v->namelen + HELLO_ADJ_MAX_IDX_LEN; + } + + switch (v->magic) { + case MPLSLDPHELLOADJACENCYINDEX: + return SNMP_INTEGER(adjacencyIndex); + case MPLSLDPHELLOADJACENCYHOLDTIMEREM: + return SNMP_INTEGER(ctl_adj->holdtime_remaining); + case MPLSLDPHELLOADJACENCYHOLDTIME: + return SNMP_INTEGER(ctl_adj->holdtime); + case MPLSLDPHELLOADJACENCYTYPE: + if (ctl_adj->type == HELLO_LINK) + return SNMP_INTEGER(MPLSLDPHELLOADJACENCYTYPE_LINK); + return SNMP_INTEGER(MPLSLDPHELLOADJACENCYTYPE_TARGETED); + default: + return NULL; + } + + return NULL; +} + +#define LDP_LSRID_IDX_LEN 6 +#define LDP_ENTITY_IDX_LEN 1 +#define LDP_PEER_ENTRY_MAX_IDX_LEN 13 + +static void ldpPeerTable_oid_to_index( + struct variable *v, oid name[], + size_t *length, + struct in_addr *entityLdpId, + uint32_t *entityIndex, + struct in_addr *peerLdpId) +{ + oid *offset = name + v->namelen; + int offsetlen = *length - v->namelen; + int len = offsetlen; + + if (len > LDP_PEER_ENTRY_MAX_IDX_LEN) + len = LDP_PEER_ENTRY_MAX_IDX_LEN; + + if (len >= LDP_LSRID_IDX_LEN) + oid2in_addr(offset, sizeof(struct in_addr), entityLdpId); + + offset += LDP_LSRID_IDX_LEN; + offsetlen -= LDP_LSRID_IDX_LEN; + len = offsetlen; + + if (len > LDP_ENTITY_IDX_LEN) + len = LDP_ENTITY_IDX_LEN; + + if (len >= LDP_ENTITY_IDX_LEN) + *entityIndex = offset[0]; + + offset += LDP_ENTITY_IDX_LEN; + offsetlen -= LDP_ENTITY_IDX_LEN; + len = offsetlen; + + if (len > LDP_LSRID_IDX_LEN) + len = LDP_LSRID_IDX_LEN; + + if (len >= LDP_LSRID_IDX_LEN) + oid2in_addr(offset, sizeof(struct in_addr), peerLdpId); +} + +static struct ctl_nbr * +ldpPeerTable_lookup_next(int first, + struct in_addr peerLdpId) +{ + struct nbr *nbr = NULL; + struct ctl_nbr *ctl_nbr = NULL;; + + if (first) + nbr = nbr_get_first_ldpid(); + else + nbr = nbr_get_next_ldpid(peerLdpId.s_addr); + + if (nbr) + ctl_nbr = nbr_to_ctl(nbr); + + return ctl_nbr; +} + +static struct ctl_nbr * +ldpPeerTable_lookup(struct variable *v, oid name[], + size_t *length, int exact, + struct in_addr *entityLdpId, + uint32_t *entityIndex, + struct in_addr *peerLdpId) +{ + struct ctl_nbr *ctl_nbr = NULL; + struct nbr *nbr = NULL; + int first = 0; + + if (exact) { + if (*length < (long unsigned int)v->namelen + + LDP_PEER_ENTRY_MAX_IDX_LEN) + return NULL; + + ldpPeerTable_oid_to_index( + v, name, length, + entityLdpId, entityIndex, peerLdpId); + + nbr = nbr_find_ldpid(peerLdpId->s_addr); + if (nbr) + ctl_nbr = nbr_to_ctl(nbr); + + return ctl_nbr; + } else { + + int offsetlen = *length - v->namelen; + if (offsetlen < LDP_LSRID_IDX_LEN) + first = 1; + + ldpPeerTable_oid_to_index( + v, name, length, + entityLdpId, entityIndex, peerLdpId); + + ctl_nbr = ldpPeerTable_lookup_next(first, *peerLdpId); + return ctl_nbr; + } + return NULL; +} + +static uint8_t *ldpPeerTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct in_addr entityLdpId = {.s_addr = 0}; + uint32_t entityIndex = 0; + struct in_addr peerLdpId = {.s_addr = 0}; + struct ctl_nbr *ctl_nbr; + + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + ctl_nbr = ldpPeerTable_lookup(v, name, length, exact, &entityLdpId, + &entityIndex, &peerLdpId); + + if (!ctl_nbr) + return NULL; + + if (!exact) { + + entityLdpId.s_addr = ldp_rtr_id_get(leconf); + entityIndex = LDP_DEFAULT_ENTITY_INDEX; + peerLdpId = ctl_nbr->id; + + /* Copy the name out */ + memcpy(name, v->name, v->namelen * sizeof(oid)); + + /* Append index */ + oid_copy_in_addr(name + v->namelen, &entityLdpId); + + name[v->namelen + 4] = 0; + name[v->namelen + 5] = 0; + name[v->namelen + 6] = entityIndex; + oid_copy_in_addr(name + v->namelen + 7, &peerLdpId); + name[v->namelen + 11] = 0; + name[v->namelen + 12] = 0; + + /* Set length */ + *length = v->namelen + LDP_PEER_ENTRY_MAX_IDX_LEN; + } + + switch (v->magic) { + case MPLSLDPPEERLDPID: + *var_len = 6; + memcpy(snmp_ldp_rtrid, &ctl_nbr->id, IN_ADDR_SIZE); + return snmp_ldp_rtrid; + case MPLSLDPPEERLABELDISTMETHOD: + return SNMP_INTEGER(DOWNSTREAMUNSOLICITED); + case MPLSLDPPEERPATHVECTORLIMIT: + return SNMP_INTEGER(0); + case MPLSLDPPEERTRANSPORTADDRTYPE: + if (ctl_nbr->af == AF_INET) + return SNMP_INTEGER(MPLSLDPPEERTRANSPORTADDRTYPE_IPV4); + else + return SNMP_INTEGER(MPLSLDPPEERTRANSPORTADDRTYPE_IPV6); + case MPLSLDPPEERTRANSPORTADDR: + if (ctl_nbr->af == AF_INET) { + *var_len = sizeof(ctl_nbr->raddr.v4); + return ((uint8_t *)&ctl_nbr->raddr.v4); + } else { + *var_len = sizeof(ctl_nbr->raddr.v6); + return ((uint8_t *)&ctl_nbr->raddr.v6); + } + default: + return NULL; + } + + return NULL; +} +static uint8_t *ldpSessionTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct in_addr entityLdpId = {.s_addr = 0}; + uint32_t entityIndex = 0; + struct in_addr peerLdpId = {.s_addr = 0}; + struct ctl_nbr *ctl_nbr; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + ctl_nbr = ldpPeerTable_lookup(v, name, length, exact, &entityLdpId, + &entityIndex, &peerLdpId); + + if (!ctl_nbr) + return NULL; + + if (!exact) { + entityLdpId.s_addr = ldp_rtr_id_get(leconf); + entityIndex = LDP_DEFAULT_ENTITY_INDEX; + peerLdpId = ctl_nbr->id; + + /* Copy the name out */ + memcpy(name, v->name, v->namelen * sizeof(oid)); + + /* Append index */ + oid_copy_in_addr(name + v->namelen, &entityLdpId); + + name[v->namelen + 4] = 0; + name[v->namelen + 5] = 0; + name[v->namelen + 6] = entityIndex; + oid_copy_in_addr(name + v->namelen + 7, &peerLdpId); + name[v->namelen + 11] = 0; + name[v->namelen + 12] = 0; + + /* Set length */ + *length = v->namelen + LDP_PEER_ENTRY_MAX_IDX_LEN; + } + + switch (v->magic) { + case MPLSLDPSESSIONSTATELASTCHANGE: + *var_len = sizeof(time_t); + return (uint8_t *) &(ctl_nbr->uptime); + case MPLSLDPSESSIONSTATE: + switch (ctl_nbr->nbr_state) { + case NBR_STA_INITIAL: + return SNMP_INTEGER(MPLSLDPSESSIONSTATE_INITIALIZED); + case NBR_STA_OPENREC: + return SNMP_INTEGER(MPLSLDPSESSIONSTATE_OPENREC); + case NBR_STA_OPENSENT: + return SNMP_INTEGER(MPLSLDPSESSIONSTATE_OPENSENT); + case NBR_STA_OPER: + return SNMP_INTEGER(MPLSLDPSESSIONSTATE_OPERATIONAL); + default: + return SNMP_INTEGER(MPLSLDPSESSIONSTATE_NONEXISTENT); + } + case MPLSLDPSESSIONROLE: + if (ldp_addrcmp(ctl_nbr->af, &ctl_nbr->laddr, &ctl_nbr->raddr) + > 0) + return SNMP_INTEGER(MPLSLDPSESSIONROLE_ACTIVE); + else + return SNMP_INTEGER(MPLSLDPSESSIONROLE_PASSIVE); + case MPLSLDPSESSIONPROTOCOLVERSION: + return SNMP_INTEGER(LDP_VERSION); + case MPLSLDPSESSIONKEEPALIVEHOLDTIMEREM: + return SNMP_INTEGER(ctl_nbr->hold_time_remaining); + case MPLSLDPSESSIONKEEPALIVETIME: + return SNMP_INTEGER(ctl_nbr->holdtime); + case MPLSLDPSESSIONMAXPDULENGTH: + if (ctl_nbr->nbr_state == NBR_STA_OPER) + return SNMP_INTEGER(ctl_nbr->max_pdu_len); + else + return SNMP_INTEGER(LDP_MAX_LEN); + case MPLSLDPSESSIONDISCONTINUITYTIME: + return SNMP_INTEGER(0); /* not supported */ + default: + return NULL; + } + + return NULL; +} + +static uint8_t *ldpSessionStatsTable(struct variable *v, oid name[], + size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct in_addr entityLdpId = {.s_addr = 0}; + uint32_t entityIndex = 0; + struct in_addr peerLdpId = {.s_addr = 0}; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + struct ctl_nbr *ctl_nbr = ldpPeerTable_lookup(v, name, length, exact, + &entityLdpId, &entityIndex, &peerLdpId); + + if (!ctl_nbr) + return NULL; + + if (!exact) { + entityLdpId.s_addr = ldp_rtr_id_get(leconf); + entityIndex = LDP_DEFAULT_ENTITY_INDEX; + peerLdpId = ctl_nbr->id; + + /* Copy the name out */ + memcpy(name, v->name, v->namelen * sizeof(oid)); + + /* Append index */ + oid_copy_in_addr(name + v->namelen, &entityLdpId); + name[v->namelen + 4] = 0; + name[v->namelen + 5] = 0; + name[v->namelen + 6] = entityIndex; + oid_copy_in_addr(name + v->namelen + 7, &peerLdpId); + name[v->namelen + 11] = 0; + name[v->namelen + 12] = 0; + + *length = v->namelen + LDP_PEER_ENTRY_MAX_IDX_LEN; + } + + switch (v->magic) { + case MPLSLDPSESSIONSTATSUNKNOWNMESTYPEERRORS: + return SNMP_INTEGER(ctl_nbr->stats.unknown_msg); + case MPLSLDPSESSIONSTATSUNKNOWNTLVERRORS: + return SNMP_INTEGER(ctl_nbr->stats.unknown_tlv); + default: + return NULL; + } + + return NULL; +} + +static struct variable ldpe_variables[] = { + {MPLS_LDP_LSR_ID, STRING, RONLY, ldpLsrId, 3, {1, 1, 1}}, + {MPLS_LDP_LSR_LOOP_DETECTION_CAPABLE, INTEGER, RONLY, + ldpLoopDetectCap, 3, {1, 1, 2}}, + {MPLS_LDP_ENTITY_LAST_CHANGE, TIMESTAMP, RONLY, ldpEntityLastChange, + 3, {1, 2, 1}}, + {MPLS_LDP_ENTITY_INDEX_NEXT, UNSIGNED32, RONLY, ldpEntityIndexNext, + 3, {1, 2, 2}}, + + /* MPLS LDP mplsLdpEntityTable. */ + {MPLSLDPENTITYLDPID, STRING, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 1}}, + {MPLSLDPENTITYINDEX, UNSIGNED32, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 2}}, + {MPLSLDPENTITYPROTOCOLVERSION, UNSIGNED32, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 3}}, + {MPLSLDPENTITYADMINSTATUS, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 4}}, + {MPLSLDPENTITYOPERSTATUS, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 5}}, + {MPLSLDPENTITYTCPPORT, UNSIGNED32, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 6}}, + {MPLSLDPENTITYUDPDSCPORT, UNSIGNED32, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 7}}, + {MPLSLDPENTITYMAXPDULENGTH, UNSIGNED32, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 8}}, + {MPLSLDPENTITYKEEPALIVEHOLDTIMER, UNSIGNED32, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 9}}, + {MPLSLDPENTITYHELLOHOLDTIMER, UNSIGNED32, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 10}}, + {MPLSLDPENTITYINITSESSIONTHRESHOLD, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 11}}, + {MPLSLDPENTITYLABELDISTMETHOD, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 12}}, + {MPLSLDPENTITYLABELRETENTIONMODE, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 13}}, + {MPLSLDPENTITYPATHVECTORLIMIT, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 14}}, + {MPLSLDPENTITYHOPCOUNTLIMIT, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 15}}, + {MPLSLDPENTITYTRANSPORTADDRKIND, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 16}}, + {MPLSLDPENTITYTARGETPEER, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 17}}, + {MPLSLDPENTITYTARGETPEERADDRTYPE, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 18}}, + {MPLSLDPENTITYTARGETPEERADDR, STRING, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 19}}, + {MPLSLDPENTITYLABELTYPE, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 20}}, + {MPLSLDPENTITYDISCONTINUITYTIME, TIMESTAMP, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 21}}, + {MPLSLDPENTITYSTORAGETYPE, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 22}}, + {MPLSLDPENTITYROWSTATUS, INTEGER, RONLY, ldpEntityTable, + 5, {1, 2, 3, 1, 23}}, + + /* MPLS LDP mplsLdpEntityStatsTable. */ + { MPLSLDPENTITYSTATSSESSIONATTEMPTS, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 1}}, + { MPLSLDPENTITYSTATSSESSIONREJHELLO, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 2}}, + { MPLSLDPENTITYSTATSSESSIONREJAD, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 3}}, + { MPLSLDPENTITYSTATSSESSIONREJMAXPDU, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 4}}, + { MPLSLDPENTITYSTATSSESSIONREJLR, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 5}}, + { MPLSLDPENTITYSTATSBADLDPID, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 6}}, + { MPLSLDPENTITYSTATSBADPDULENGTH, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 7}}, + { MPLSLDPENTITYSTATSBADMSGLENGTH, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 8}}, + { MPLSLDPENTITYSTATSBADTLVLENGTH, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 9}}, + { MPLSLDPENTITYSTATSMALFORMEDTLV, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 10}}, + { MPLSLDPENTITYSTATSKEEPALIVEEXP, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 11}}, + { MPLSLDPENTITYSTATSSHUTDOWNRCVNOTIFY, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 12}}, + { MPLSLDPENTITYSTATSSHUTDOWNSENTNOTIFY, COUNTER32, RONLY, + ldpEntityStatsTable, 5, {1, 2, 4, 1, 13}}, + + /* MPLS LDP mplsLdpPeerTable */ + {MPLSLDPPEERLDPID, STRING, RONLY, ldpPeerTable, 5, {1, 3, 2, 1, 1}}, + {MPLSLDPPEERLABELDISTMETHOD, INTEGER, RONLY, ldpPeerTable, + 5, {1, 3, 2, 1, 2}}, + {MPLSLDPPEERPATHVECTORLIMIT, INTEGER, RONLY, ldpPeerTable, + 5, {1, 3, 2, 1, 3}}, + {MPLSLDPPEERTRANSPORTADDRTYPE, INTEGER, RONLY, ldpPeerTable, + 5, {1, 3, 2, 1, 4}}, + {MPLSLDPPEERTRANSPORTADDR, STRING, RONLY, ldpPeerTable, + 5, {1, 3, 2, 1, 5}}, + + /* MPLS LDP mplsLdpSessionTable */ + {MPLSLDPSESSIONSTATELASTCHANGE, TIMESTAMP, RONLY, ldpSessionTable, + 5, {1, 3, 3, 1, 1}}, + {MPLSLDPSESSIONSTATE, INTEGER, RONLY, ldpSessionTable, + 5, {1, 3, 3, 1, 2}}, + {MPLSLDPSESSIONROLE, INTEGER, RONLY, ldpSessionTable, + 5, {1, 3, 3, 1, 3}}, + {MPLSLDPSESSIONPROTOCOLVERSION, UNSIGNED32, RONLY, ldpSessionTable, + 5, {1, 3, 3, 1, 4}}, + {MPLSLDPSESSIONKEEPALIVEHOLDTIMEREM, INTEGER, RONLY, ldpSessionTable, + 5, {1, 3, 3, 1, 5}}, + {MPLSLDPSESSIONKEEPALIVETIME, UNSIGNED32, RONLY, ldpSessionTable, + 5, {1, 3, 3, 1, 6}}, + {MPLSLDPSESSIONMAXPDULENGTH, UNSIGNED32, RONLY, ldpSessionTable, + 5, {1, 3, 3, 1, 7}}, + {MPLSLDPSESSIONDISCONTINUITYTIME, TIMESTAMP, RONLY, ldpSessionTable, + 5, {1, 3, 3, 1, 8}}, + + /* MPLS LDP mplsLdpSessionStatsTable */ + {MPLSLDPSESSIONSTATSUNKNOWNMESTYPEERRORS, COUNTER32, RONLY, + ldpSessionStatsTable, 5, {1, 3, 4, 1, 1}}, + {MPLSLDPSESSIONSTATSUNKNOWNTLVERRORS, COUNTER32, RONLY, + ldpSessionStatsTable, 5, {1, 3, 4, 1, 2}}, + + /* MPLS LDP mplsLdpHelloAdjacencyTable. */ + {MPLSLDPHELLOADJACENCYINDEX, UNSIGNED32, RONLY, + ldpHelloAdjacencyTable, 6, {1, 3, 5, 1, 1, 1}}, + {MPLSLDPHELLOADJACENCYHOLDTIMEREM, INTEGER, RONLY, + ldpHelloAdjacencyTable, 6, {1, 3, 5, 1, 1, 2}}, + {MPLSLDPHELLOADJACENCYHOLDTIME, UNSIGNED32, RONLY, + ldpHelloAdjacencyTable, 6, {1, 3, 5, 1, 1, 3}}, + {MPLSLDPHELLOADJACENCYTYPE, INTEGER, RONLY, + ldpHelloAdjacencyTable, 6, {1, 3, 5, 1, 1, 4}}, +}; + +static struct variable lde_variables[] = { +}; + +static struct trap_object ldpSessionTrapList[] = { + {5, {1, 3, 3, 1, MPLSLDPSESSIONSTATE}}, + {5, {1, 3, 3, 1, MPLSLDPSESSIONDISCONTINUITYTIME}}, + {5, {1, 3, 4, 1, MPLSLDPSESSIONSTATSUNKNOWNMESTYPEERRORS}}, + {5, {1, 3, 4, 1, MPLSLDPSESSIONSTATSUNKNOWNTLVERRORS}}}; + +/* LDP TRAP. */ +#define LDPINITSESSIONTHRESHOLDEXCEEDED 1 +#define LDPPATHVECTORLIMITMISMATCH 2 +#define LDPSESSIONUP 3 +#define LDPSESSIONDOWN 4 + +static void +ldpTrapSession(struct nbr * nbr, unsigned int sptrap) +{ + oid index[sizeof(oid) * (LDP_PEER_ENTRY_MAX_IDX_LEN + 1)]; + + struct in_addr entityLdpId = {.s_addr = 0}; + uint32_t entityIndex = 0; + struct in_addr peerLdpId = {.s_addr = 0}; + + struct ctl_nbr *ctl_nbr = nbr_to_ctl(nbr); + + entityLdpId.s_addr = ldp_rtr_id_get(leconf); + entityIndex = LDP_DEFAULT_ENTITY_INDEX; + peerLdpId = ctl_nbr->id; + + oid_copy_in_addr(index, &entityLdpId); + index[4] = 0; + index[5] = 0; + index[6] = entityIndex; + oid_copy_in_addr(&index[7], &peerLdpId); + index[11] = 0; + index[12] = 0; + + index[LDP_PEER_ENTRY_MAX_IDX_LEN] = 0; + + smux_trap(ldpe_variables, array_size(ldpe_variables), ldp_trap_oid, + array_size(ldp_trap_oid), ldp_oid, + sizeof(ldp_oid) / sizeof(oid), index, + LDP_PEER_ENTRY_MAX_IDX_LEN + 1, + ldpSessionTrapList, array_size(ldpSessionTrapList), sptrap); +} + +static void +ldpTrapSessionUp(struct nbr * nbr) +{ + ldpTrapSession(nbr, LDPSESSIONUP); +} + +static void +ldpTrapSessionDown(struct nbr * nbr) +{ + ldpTrapSession(nbr, LDPSESSIONDOWN); +} + +static int ldp_snmp_agentx_enabled(void) +{ + main_imsg_compose_both(IMSG_AGENTX_ENABLED, NULL, 0); + + return 0; +} + +static int ldp_snmp_nbr_state_change(struct nbr * nbr, int old_state) +{ + if (old_state == nbr->state) + return 0; + + if (nbr->state == NBR_STA_OPER) + ldpTrapSessionUp(nbr); + else if (old_state == NBR_STA_OPER) + ldpTrapSessionDown(nbr); + + return 0; +} + +static int ldp_snmp_init(struct event_loop *tm) +{ + hook_register(agentx_enabled, ldp_snmp_agentx_enabled); + + smux_init(tm); + + return 0; +} + +static int ldp_snmp_register_mib(struct event_loop *tm) +{ + static int registered = 0; + + if (registered) + return 0; + + registered = 1; + + smux_init(tm); + + smux_agentx_enable(); + + if (ldpd_process == PROC_LDE_ENGINE) + REGISTER_MIB("mibII/ldp", lde_variables, variable, ldp_oid); + else if (ldpd_process == PROC_LDP_ENGINE) { + REGISTER_MIB("mibII/ldp", ldpe_variables, variable, ldp_oid); + + hook_register(ldp_nbr_state_change, ldp_snmp_nbr_state_change); + } + + return 0; +} + +static int ldp_snmp_module_init(void) +{ + if (ldpd_process == PROC_MAIN) + hook_register(frr_late_init, ldp_snmp_init); + else + hook_register(ldp_register_mib, ldp_snmp_register_mib); + + return 0; +} + +FRR_MODULE_SETUP( + .name = "ldp_snmp", + .version = FRR_VERSION, + .description = "ldp AgentX SNMP module", + .init = ldp_snmp_module_init, +); |