mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-03 23:47:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1225 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1225 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// 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,
 | 
						|
);
 |