]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
Implement LLDP-MED reception and display
authorVincent Bernat <vbernat@wanadooportails.com>
Wed, 26 Nov 2008 14:23:00 +0000 (15:23 +0100)
committerVincent Bernat <vbernat@wanadooportails.com>
Wed, 26 Nov 2008 14:23:00 +0000 (15:23 +0100)
src/ctl.c
src/lldp.c
src/lldpctl.c
src/lldpd.h

index 6c2be325fd0a56cfcbd2948a72ad3e0c4528836c..d4d076dc4cfd11a965c5ef24ebbf997a7a4815e5 100644 (file)
--- 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*);
 }
index d705a2f0ff173b494e6348f1367f0626e7425cb3..4d9600323e2df21b42a4775d44a595f07e83c1a0 100644 (file)
@@ -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);
index 4279df797810ad37bc80b2518bf08d736264e2b0..a1e0203397acfad72657727a96ded58c2396e2b1 100644 (file)
@@ -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);
                }
        }
index c811f315725cf8218974c114ff97e23f5c8bb934..42ce3eddb895e09c28b248c39f6146b0649f75cf 100644 (file)
@@ -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"