From 6772b2377970dcd4ff829d9f64ef19e1fdd5db59 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Wed, 26 Nov 2008 15:23:00 +0100 Subject: [PATCH] Implement LLDP-MED reception and display --- src/ctl.c | 40 ++++++++++++++++--------- src/lldp.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lldpctl.c | 69 ++++++++++++++++++++++++++++++++++++++++++ src/lldpd.h | 2 +- 4 files changed, 179 insertions(+), 15 deletions(-) diff --git a/src/ctl.c b/src/ctl.c index 6c2be325..d4d076dc 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -232,7 +232,11 @@ int pack_string(struct hmsg *h, void **p, void *s, const struct formatdef *ct) { - int len = strlen(*(char**)s); + int len, ss; + if ((*(char**)s) == NULL) + len = -1; + else + len = strlen(*(char**)s); if (h->hdr.len + len + sizeof(int) > MAX_HMSGSIZE - sizeof(struct hmsg_hdr)) { LLOG_WARNX("message became too large"); @@ -240,10 +244,14 @@ pack_string(struct hmsg *h, void **p, void *s, } memcpy(*p, &len, sizeof(int)); *p += sizeof(int); - memcpy(*p, *(char **)s, len); - *p += len; - h->hdr.len += sizeof(int) + len; - return sizeof(int) + len; + ss = sizeof(int); + if (len != -1) { + memcpy(*p, *(char **)s, len); + *p += len; + ss += len; + } + h->hdr.len += ss; + return ss; } int @@ -253,16 +261,20 @@ unpack_string(struct hmsg *h, void **p, void *s, char *string; int len = *(int*)*p; *p += sizeof(int); - if ((string = (char *)calloc(1, len + 1)) == NULL) { - LLOG_WARNX("unable to allocate new string"); - return -1; - } - if (_ctl_alloc_pointer(pointers, string) == -1) { - free(string); - return -1; + if (len == -1) { + string = NULL; + } else { + if ((string = (char *)calloc(1, len + 1)) == NULL) { + LLOG_WARNX("unable to allocate new string"); + return -1; + } + if (_ctl_alloc_pointer(pointers, string) == -1) { + free(string); + return -1; + } + memcpy(string, *p, len); + *p += len; } - memcpy(string, *p, len); - *p += len; memcpy(s, &string, sizeof(char *)); return sizeof(char*); } diff --git a/src/lldp.c b/src/lldp.c index d705a2f0..4d960032 100644 --- a/src/lldp.c +++ b/src/lldp.c @@ -347,6 +347,7 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, const char lldpaddr[] = LLDP_MULTICAST_ADDR; const char dot1[] = LLDP_TLV_ORG_DOT1; const char dot3[] = LLDP_TLV_ORG_DOT3; + const char med[] = LLDP_TLV_ORG_MED; int f; /* Current position in frame */ int size, type, subtype; /* TLV header */ char *b; @@ -584,6 +585,80 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, f += size; hardware->h_rx_unrecognized_cnt++; } + } else if (memcmp(med, frame + f, 3) == 0) { + /* LLDP-MED */ +#ifndef ENABLE_LLDPMED + f += size; + hardware->h_rx_unrecognized_cnt++; +#else + subtype = *(u_int8_t*)(frame + f + 3); + switch (subtype) { + case LLDP_TLV_MED_CAP: + f += 4; + if (size != 7) { + LLOG_WARN("too short LLDP-MED cap " + "tlv received on %s", + hardware->h_ifname); + goto malformed; + } + chassis->c_med_cap = + ntohs(*(u_int16_t*)(frame + f)); + f += 2; + chassis->c_med_type = + *(u_int8_t*)(frame + f); + f += 1; + break; + case LLDP_TLV_MED_IV_HW: + case LLDP_TLV_MED_IV_SW: + case LLDP_TLV_MED_IV_FW: + case LLDP_TLV_MED_IV_SN: + case LLDP_TLV_MED_IV_MANUF: + case LLDP_TLV_MED_IV_MODEL: + case LLDP_TLV_MED_IV_ASSET: + f += 4; + if (size <= 4) + b = NULL; + else { + b = (char*)malloc(size - 4); + strlcpy(b, + (char*)(frame + f), + size - 4); + } + switch (subtype) { + case LLDP_TLV_MED_IV_HW: + chassis->c_med_hw = b; + break; + case LLDP_TLV_MED_IV_FW: + chassis->c_med_fw = b; + break; + case LLDP_TLV_MED_IV_SW: + chassis->c_med_sw = b; + break; + case LLDP_TLV_MED_IV_SN: + chassis->c_med_sn = b; + break; + case LLDP_TLV_MED_IV_MANUF: + chassis->c_med_manuf = b; + break; + case LLDP_TLV_MED_IV_MODEL: + chassis->c_med_fw = b; + break; + case LLDP_TLV_MED_IV_ASSET: + chassis->c_med_fw = b; + break; + default: + LLOG_WARNX("should not be there!"); + free(b); + break; + } + f += size - 4; + break; + default: + /* Unknown LLDP MED, ignore it */ + f += size; + hardware->h_rx_unrecognized_cnt++; + } +#endif /* ENABLE_LLDPMED */ } else { LLOG_INFO("unknown org tlv received on %s", hardware->h_ifname); @@ -633,6 +708,14 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, *newport = port; return 1; malformed: +#ifdef ENABLE_LLDPMED + free(chassis->c_med_hw); + free(chassis->c_med_fw); + free(chassis->c_med_sn); + free(chassis->c_med_manuf); + free(chassis->c_med_model); + free(chassis->c_med_asset); +#endif free(chassis->c_id); free(chassis->c_name); free(chassis->c_descr); diff --git a/src/lldpctl.c b/src/lldpctl.c index 4279df79..a1e02033 100644 --- a/src/lldpctl.c +++ b/src/lldpctl.c @@ -241,6 +241,69 @@ pretty_print(char *string) printf(" %s\n", string); } +#ifdef ENABLE_LLDPMED +void +display_med(struct lldpd_chassis *chassis) +{ + printf(" LLDP-MED device type: "); + switch (chassis->c_med_type) { + case LLDPMED_CLASS_I: + printf("Generic Endpoint (Class I)"); + break; + case LLDPMED_CLASS_II: + printf("Media Endpoint (Class II)"); + break; + case LLDPMED_CLASS_III: + printf("Communication Device Endpoint (Class III)"); + break; + case LLDPMED_NETWORK_DEVICE: + printf("Network Connectivity Device"); + break; + default: + printf("Unknown (%d)", chassis->c_med_type); + break; + } + printf("\n LLDP-MED capabilities:"); + if (chassis->c_med_cap & LLDPMED_CAP_CAP) + printf(" Capabilities"); + if (chassis->c_med_cap & LLDPMED_CAP_POLICY) + printf(" Policy"); + if (chassis->c_med_cap & LLDPMED_CAP_LOCATION) + printf(" Location"); + if (chassis->c_med_cap & (LLDPMED_CAP_MDI1 | LLDPMED_CAP_MDI2)) + printf(" MDI"); + if (chassis->c_med_cap & LLDPMED_CAP_IV) + printf(" Inventory"); + printf("\n"); + if (chassis->c_med_hw || + chassis->c_med_sw || + chassis->c_med_fw || + chassis->c_med_sn || + chassis->c_med_manuf || + chassis->c_med_model || + chassis->c_med_asset) { + printf(" LLDP-MED Inventory:\n"); + if (chassis->c_med_hw) + printf(" Hardware Revision: %s\n", chassis->c_med_hw); + if (chassis->c_med_sw) + printf(" Software Revision: %s\n", chassis->c_med_sw); + if (chassis->c_med_fw) + printf(" Firmware Revision: %s\n", chassis->c_med_fw); + if (chassis->c_med_sn) + printf(" Serial Number: %s\n", chassis->c_med_sn); + if (chassis->c_med_manuf) + printf(" Manufacturer: %s\n", + chassis->c_med_manuf); + if (chassis->c_med_model) + printf(" Model: %s\n", + chassis->c_med_model); + if (chassis->c_med_asset) + printf(" Asset ID: %s\n", + chassis->c_med_asset); + } +} +#endif + void display_chassis(struct lldpd_chassis *chassis) { @@ -447,6 +510,12 @@ main(int argc, char *argv[]) display_vlans(&port); } } +#ifdef ENABLE_LLDPMED + if (chassis.c_med_cap) { + printf("\n"); + display_med(&chassis); + } +#endif printf("%s\n", sep); } } diff --git a/src/lldpd.h b/src/lldpd.h index c811f315..42ce3edd 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -94,7 +94,7 @@ struct lldpd_chassis { #endif }; -#ifndef ENABLE_LLDP_MED +#ifndef ENABLE_LLDPMED #define STRUCT_LLDPD_CHASSIS "bCsswwwll" #else #define STRUCT_LLDPD_CHASSIS "bCsswwwllwbsssssss" -- 2.39.5