diff options
| -rw-r--r-- | ldpd/lde.c | 12 | ||||
| -rw-r--r-- | ldpd/ldp_snmp.c | 1087 | ||||
| -rw-r--r-- | ldpd/ldpd.c | 29 | ||||
| -rw-r--r-- | ldpd/ldpd.h | 9 | ||||
| -rw-r--r-- | ldpd/ldpe.c | 20 | ||||
| -rw-r--r-- | ldpd/ldpe.h | 5 | ||||
| -rw-r--r-- | ldpd/neighbor.c | 31 | ||||
| -rw-r--r-- | ldpd/subdir.am | 9 | 
8 files changed, 1190 insertions, 12 deletions
diff --git a/ldpd/lde.c b/ldpd/lde.c index 69338b8bad..8fa74d1c3d 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -127,15 +127,13 @@ static struct quagga_signal_t lde_signals[] =  void  lde(void)  { -	struct thread		 thread; -  #ifdef HAVE_SETPROCTITLE  	setproctitle("label decision engine");  #endif  	ldpd_process = PROC_LDE_ENGINE;  	log_procname = log_procnames[PROC_LDE_ENGINE]; -	master = thread_master_create(NULL); +	master = frr_init();  	/* setup signal handler */  	signal_init(master, array_size(lde_signals), lde_signals); @@ -157,9 +155,12 @@ lde(void)  	/* create base configuration */  	ldeconf = config_new_empty(); -	/* Fetch next active thread. */ +	struct thread thread;  	while (thread_fetch(master, &thread))  		thread_call(&thread); + +	/* NOTREACHED */ +	return;  }  void @@ -566,6 +567,9 @@ lde_dispatch_parent(struct thread *thread)  			memcpy(&init, imsg.data, sizeof(init));  			lde_init(&init);  			break; +		case IMSG_AGENTX_ENABLED: +			ldp_agentx_enabled(); +			break;  		case IMSG_RECONF_CONF:  			if ((nconf = malloc(sizeof(struct ldpd_conf))) ==  			    NULL) diff --git a/ldpd/ldp_snmp.c b/ldpd/ldp_snmp.c new file mode 100644 index 0000000000..c9b37c0d27 --- /dev/null +++ b/ldpd/ldp_snmp.c @@ -0,0 +1,1087 @@ +/* + * LDP SNMP support + * Copyright (C) 2020 Volta Networks, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * 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 "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_addr(name + v->namelen, &entityLdpId, +			      IN_ADDR_SIZE); +		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; +} + +#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_addr(name + v->namelen, &entityLdpId, +			sizeof(struct in_addr)); +		name[v->namelen + 4] = 0; +		name[v->namelen + 5] = 0; +		name[v->namelen + 6] = LDP_DEFAULT_ENTITY_INDEX; +		oid_copy_addr(name + v->namelen + 7, &peerLdpId, +			sizeof(struct in_addr)); +		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_addr(name + v->namelen, &entityLdpId, +			sizeof(struct in_addr)); + +		name[v->namelen + 4] = 0; +		name[v->namelen + 5] = 0; +		name[v->namelen + 6] = entityIndex; +		oid_copy_addr(name + v->namelen + 7, &peerLdpId, +			sizeof(struct in_addr)); +		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_addr(name + v->namelen, &entityLdpId, +			sizeof(struct in_addr)); + +		name[v->namelen + 4] = 0; +		name[v->namelen + 5] = 0; +		name[v->namelen + 6] = entityIndex; +		oid_copy_addr(name + v->namelen + 7, &peerLdpId, +			sizeof(struct in_addr)); +		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 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 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 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_addr(index, &entityLdpId, sizeof(struct in_addr)); +        index[4] = 0; +        index[5] = 0; +        index[6] = entityIndex; +        oid_copy_addr(&index[7], &peerLdpId, sizeof(struct in_addr)); +        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() +{ +	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 thread_master *tm) +{ +	hook_register(agentx_enabled, ldp_snmp_agentx_enabled); + +	smux_init(tm); + +	return 0; +} + +static int ldp_snmp_register_mib(struct thread_master *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, ) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 83e93ebbbc..14235a0f1f 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -86,6 +86,30 @@ static struct imsgev	*iev_lde, *iev_lde_sync;  static pid_t		 ldpe_pid;  static pid_t		 lde_pid; +static struct frr_daemon_info ldpd_di; + +DEFINE_HOOK(ldp_register_mib, (struct thread_master * tm), (tm)) + +static void ldp_load_module(const char *name) +{ +	const char *dir; +	dir = ldpd_di.module_path ? ldpd_di.module_path : frr_moduledir; +	char moderr[256]; +	struct frrmod_runtime *module; + +	module = frrmod_load(name, dir, moderr, sizeof(moderr)); +	if (!module) { +		fprintf(stderr, "%s: failed to load %s", __func__, name); +		log_warnx("%s: failed to load %s", __func__, name); +	} +} + +void ldp_agentx_enabled(void) +{ +	ldp_load_module("snmp"); +	hook_call(ldp_register_mib, master); +} +  enum ldpd_process ldpd_process;  #define LDP_DEFAULT_CONFIG	"ldpd.conf" @@ -94,8 +118,6 @@ enum ldpd_process ldpd_process;  /* Master of threads. */  struct thread_master *master; -static struct frr_daemon_info ldpd_di; -  /* ldpd privileges */  static zebra_capabilities_t _caps_p [] =  { @@ -1343,6 +1365,9 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)  			ldpe_reset_ds_nbrs();  	} +	if (ldpd_process == PROC_LDP_ENGINE) +		ldpe_set_config_change_time(); +  	conf->flags = xconf->flags;  } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index beb625d8a2..103f4f228d 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -161,6 +161,7 @@ enum imsg_type {  	IMSG_RLFA_REG,  	IMSG_RLFA_UNREG_ALL,  	IMSG_RLFA_LABELS, +	IMSG_AGENTX_ENABLED,  };  struct ldpd_init { @@ -434,6 +435,7 @@ struct ldp_stats {  	uint32_t		 labelrel_rcvd;  	uint32_t		 labelabreq_sent;  	uint32_t		 labelabreq_rcvd; +  };  struct l2vpn_if { @@ -562,6 +564,7 @@ struct ldpd_conf {  	uint16_t		 trans_pref;  	uint16_t		 wait_for_sync_interval;  	int			 flags; +	time_t			 config_change_time;  	QOBJ_FIELDS  };  DECLARE_QOBJ_TYPE(ldpd_conf) @@ -683,6 +686,8 @@ struct ctl_nbr {  	int			 nbr_state;  	struct ldp_stats	 stats;  	int			 flags; +	uint16_t		 max_pdu_len; +	uint16_t		 hold_time_remaining;  };  struct ctl_rt { @@ -891,4 +896,8 @@ int		 ldp_zebra_send_rlfa_labels(struct zapi_rlfa_response *  	(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_INTFACELOCAL))  #endif +DECLARE_HOOK(ldp_register_mib, (struct thread_master * tm), (tm)) + +extern void ldp_agentx_enabled(void); +  #endif	/* _LDPD_H_ */ diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 6a5a0750bd..d09eb2fa33 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -33,6 +33,7 @@  #include "memory.h"  #include "privs.h"  #include "sigevent.h" +#include "libfrr.h"  static void	 ldpe_shutdown(void);  static int	 ldpe_dispatch_main(struct thread *); @@ -103,15 +104,13 @@ char *pkt_ptr; /* packet buffer */  void  ldpe(void)  { -	struct thread		 thread; -  #ifdef HAVE_SETPROCTITLE  	setproctitle("ldp engine");  #endif  	ldpd_process = PROC_LDP_ENGINE;  	log_procname = log_procnames[ldpd_process]; -	master = thread_master_create(NULL); +	master = frr_init();  	/* setup signal handler */  	signal_init(master, array_size(ldpe_signals), ldpe_signals); @@ -133,9 +132,12 @@ ldpe(void)  	/* create base configuration */  	leconf = config_new_empty(); -	/* Fetch next active thread. */ +	struct thread thread;  	while (thread_fetch(master, &thread))  		thread_call(&thread); + +	/* NOTREACHED */ +	return;  }  void @@ -387,6 +389,9 @@ ldpe_dispatch_main(struct thread *thread)  			memcpy(&init, imsg.data, sizeof(init));  			ldpe_init(&init);  			break; +		case IMSG_AGENTX_ENABLED: +			ldp_agentx_enabled(); +			break;  		case IMSG_CLOSE_SOCKETS:  			af = imsg.hdr.peerid; @@ -1073,3 +1078,10 @@ ldpe_check_filter_af(int af, struct ldpd_af_conf *af_conf,  	if (strcmp(af_conf->acl_thello_accept_from, filter_name) == 0)  		ldpe_remove_dynamic_tnbrs(af);  } + +void +ldpe_set_config_change_time(void) +{ +	/* SNMP update time when ever there is a config change */ +	leconf->config_change_time = time(NULL); +} diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index ef4702341b..9572f1ac12 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -216,6 +216,7 @@ void		 ldpe_nbr_ctl(struct ctl_conn *);  void		 ldpe_ldp_sync_ctl(struct ctl_conn *);  void		 mapping_list_add(struct mapping_head *, struct map *);  void		 mapping_list_clr(struct mapping_head *); +void		 ldpe_set_config_change_time(void);  /* interface.c */  struct iface	*if_new(const char *); @@ -266,6 +267,8 @@ struct nbr		*nbr_new(struct in_addr, int, int, union ldpd_addr *,  			    uint32_t);  void			 nbr_del(struct nbr *);  struct nbr		*nbr_find_ldpid(uint32_t); +struct nbr		*nbr_get_first_ldpid(void); +struct nbr		*nbr_get_next_ldpid(uint32_t);  struct nbr		*nbr_find_addr(int, union ldpd_addr *);  struct nbr		*nbr_find_peerid(uint32_t);  int			 nbr_adj_count(struct nbr *, int); @@ -318,4 +321,6 @@ void	ldpe_l2vpn_exit(struct l2vpn *);  void	ldpe_l2vpn_pw_init(struct l2vpn_pw *);  void	ldpe_l2vpn_pw_exit(struct l2vpn_pw *); +DECLARE_HOOK(ldp_nbr_state_change, (struct nbr * nbr, int old_state), (nbr, old_state)) +  #endif	/* _LDPE_H_ */ diff --git a/ldpd/neighbor.c b/ldpd/neighbor.c index 75deaad2c0..23c67ec1ca 100644 --- a/ldpd/neighbor.c +++ b/ldpd/neighbor.c @@ -26,6 +26,8 @@  #include "lde.h"  #include "log.h" +DEFINE_HOOK(ldp_nbr_state_change, (struct nbr * nbr, int old_state), (nbr, old_state)) +  static __inline int	 nbr_id_compare(const struct nbr *, const struct nbr *);  static __inline int	 nbr_addr_compare(const struct nbr *,  			    const struct nbr *); @@ -158,6 +160,8 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event)  		    &nbr->id, nbr_state_name(old_state),  		    nbr_state_name(nbr->state)); +		hook_call(ldp_nbr_state_change, nbr, old_state); +  		if (nbr->state == NBR_STA_OPER) {  			gettimeofday(&now, NULL);  			nbr->uptime = now.tv_sec; @@ -355,6 +359,23 @@ nbr_find_ldpid(uint32_t lsr_id)  }  struct nbr * +nbr_get_first_ldpid() +{ +	return (RB_MIN(nbr_id_head, &nbrs_by_id)); +} + +struct nbr * +nbr_get_next_ldpid(uint32_t lsr_id) +{ +	struct nbr		*nbr; +	nbr = nbr_find_ldpid(lsr_id); +	if (nbr) +		return (RB_NEXT(nbr_id_head, nbr)); +	return NULL; +} + + +struct nbr *  nbr_find_addr(int af, union ldpd_addr *addr)  {  	struct nbr	n; @@ -831,14 +852,20 @@ nbr_to_ctl(struct nbr *nbr)  	nctl.af = nbr->af;  	nctl.id = nbr->id;  	nctl.laddr = nbr->laddr; -	nctl.lport = nbr->tcp->lport; +	nctl.lport = nbr->tcp ? nbr->tcp->lport : 0;  	nctl.raddr = nbr->raddr; -	nctl.rport = nbr->tcp->rport; +	nctl.rport = nbr->tcp ? nbr->tcp->rport : 0;  	nctl.auth_method = nbr->auth.method;  	nctl.holdtime = nbr->keepalive;  	nctl.nbr_state = nbr->state;  	nctl.stats = nbr->stats;  	nctl.flags = nbr->flags; +	nctl.max_pdu_len = nbr->max_pdu_len; +	if (nbr->keepalive_timer) +		nctl.hold_time_remaining = +		    thread_timer_remain_second(nbr->keepalive_timer); +	else +		nctl.hold_time_remaining = 0;  	gettimeofday(&now, NULL);  	if (nbr->state == NBR_STA_OPER) { diff --git a/ldpd/subdir.am b/ldpd/subdir.am index d89d18341d..b01d414de8 100644 --- a/ldpd/subdir.am +++ b/ldpd/subdir.am @@ -41,6 +41,10 @@ ldpd_libldp_a_SOURCES = \  	ldpd/util.c \  	# end +if SNMP +module_LTLIBRARIES += ldpd/ldpd_snmp.la +endif +  clippy_scan += \  	ldpd/ldp_vty_cmds.c \  	# end @@ -59,3 +63,8 @@ noinst_HEADERS += \  ldpd_ldpd_SOURCES = ldpd/ldpd.c  ldpd_ldpd_LDADD = ldpd/libldp.a lib/libfrr.la $(LIBCAP) + +ldpd_ldpd_snmp_la_SOURCES = ldpd/ldp_snmp.c +ldpd_ldpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99 +ldpd_ldpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +ldpd_ldpd_snmp_la_LIBADD = lib/libfrrsnmp.la  | 
