]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-cdp.c
Add SunATM support, based on code from Yen Yen Lim at North Dakota State
[tcpdump] / print-cdp.c
index e0b86257fb7e0a2b1431fb47868f407a000cfea1..c291989db67b3f9d5d89fb79b5f07907d2c40693 100644 (file)
@@ -26,7 +26,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-cdp.c,v 1.8 2001-06-15 20:52:12 fenner Exp $";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-cdp.c,v 1.14 2002-06-11 17:08:44 itojun Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -49,12 +49,13 @@ static const char rcsid[] =
 
 static int cdp_print_addr(const u_char *, int);
 static int cdp_print_prefixes(const u_char *, int);
+static unsigned long cdp_get_number(const u_char *, int);
 
 void
 cdp_print(const u_char *p, u_int length, u_int caplen,
          const u_char *esrc, const u_char *edst)
 {
-       int i;
+       u_int i;
        int type, len;
 
        /* Cisco Discovery Protocol */
@@ -114,17 +115,56 @@ cdp_print(const u_char *p, u_int length, u_int caplen,
                        if (cdp_print_prefixes(p + i + 4, len - 4) < 0)
                                goto trunc;
                        break;
+               case 0x08:              /* guess - not documented */
+                       printf(" Protocol-Hello option" );
+                       break;
                case 0x09:              /* guess - not documented */
                        printf(" VTP Management Domain: '%.*s'", len - 4,
                            p + i + 4);
                        break;
                case 0x0a:              /* guess - not documented */
                        printf(" Native VLAN ID: %d",
-                           (p[i + 4] << 8) + p[i + 4 + 1] - 1);
+                           (p[i + 4] << 8) + p[i + 4 + 1] );
                        break;
                case 0x0b:              /* guess - not documented */
                        printf(" Duplex: %s", p[i + 4] ? "full": "half");
                        break;
+/* http://www.cisco.com/univercd/cc/td/doc/product/voice/ata/atarn/186rn21m.htm
+ * plus more details from other sources
+ */
+               case 0x0e:              /* incomplete doc. */
+                       printf(" ATA-186 VoIP VLAN request, app %d, vlan %d",
+                               p[i + 4], EXTRACT_16BITS(&p[i+4+1]));
+                       break;
+               case 0x0f:              /* incomplete doc. */
+                       printf(" ATA-186 VoIP VLAN assignment" );
+                       break;
+               case 0x10:              /* incomplete doc. */
+                       printf(" power consumption: %1.2fW",
+                               cdp_get_number(p+i+4, len-4)/1000.0 );
+                       break;
+               case 0x11:              /* guess - not documented */
+                       printf(" MTU %u bytes", EXTRACT_32BITS(&p[i+4]));
+                       break;
+               case 0x12:              /* guess - not documented */
+                       printf(" AVVID trust bitmap 0x%02x", p[i+4] );
+                       break;
+               case 0x13:              /* guess - not documented */
+                       printf(" AVVID untrusted ports CoS: 0x%02x", p[i+4]);
+                       break;
+               case 0x14:              /* guess - not documented */
+                       printf(" sysName='%.*s'", len - 4, p + i + 4 );
+                       break;
+               case 0x15:              /* guess - not documented */
+                       printf(" sysObjectID" );                /* TODO */
+                       break;
+               case 0x16:              /* guess - not documented */
+                       printf(" management address(es)" );
+                       break;
+               case 0x17:              /* guess - not documented */
+                       printf(" phys. location 0x%02x/%.*s",
+                               p[i+4], len - 5, p + i + 5 );
+                       break;
                default:
                        printf(" unknown field type %02x, len %d", type, len);
                        break;
@@ -142,13 +182,29 @@ trunc:
        printf("[|cdp]");
 }
 
+/*
+ * Protocol type values.
+ *
+ * PT_NLPID means that the protocol type field contains an OSI NLPID.
+ *
+ * PT_IEEE_802_2 means that the protocol type field contains an IEEE 802.2
+ * LLC header that specifies that the payload is for that protocol.
+ */
+#define PT_NLPID               1       /* OSI NLPID */
+#define PT_IEEE_802_2          2       /* IEEE 802.2 LLC header */
+
 static int
 cdp_print_addr(const u_char * p, int l)
 {
-       int pl, al, num;
+       int pt, pl, al, num;
        const u_char *endp = p + l;
+#ifdef INET6
+       static u_char prot_ipv6[] = {
+               0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd
+       };
+#endif
 
-       num = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
+       num = EXTRACT_32BITS(p);
        p += 4;
 
        printf(" (%d): ", num);
@@ -156,35 +212,66 @@ cdp_print_addr(const u_char * p, int l)
        while (p < endp && num >= 0) {
                if (p + 2 > endp)
                        goto trunc;
-               pl = p[1];
+               pt = p[0];              /* type of "protocol" field */
+               pl = p[1];              /* length of "protocol" field */
                p += 2;
 
-               /* special case: IPv4, protocol type=0xcc, addr. length=4 */
-               if (p + 3 > endp)
+               if (p + pl + 2 > endp)
                        goto trunc;
-               if (pl == 1 && *p == 0xcc && p[1] == 0 && p[2] == 4) {
+               al = EXTRACT_16BITS(&p[pl]);    /* address length */
+
+               if (pt == PT_NLPID && pl == 1 && *p == 0xcc && al == 4) {
+                       /*
+                        * IPv4: protocol type = NLPID, protocol length = 1
+                        * (1-byte NLPID), protocol = 0xcc (NLPID for IPv4),
+                        * address length = 4
+                        */
                        p += 3;
 
                        if (p + 4 > endp)
                                goto trunc;
-                       printf("IPv4 %u.%u.%u.%u ", p[0], p[1], p[2], p[3]);
+                       printf("IPv4 %u.%u.%u.%u", p[0], p[1], p[2], p[3]);
                        p += 4;
-               } else {        /* generic case: just print raw data */
+               }
+#ifdef INET6
+               else if (pt == PT_IEEE_802_2 && pl == 8 &&
+                   memcmp(p, prot_ipv6, 8) == 0 && al == 16) {
+                       /*
+                        * IPv6: protocol type = IEEE 802.2 header,
+                        * protocol length = 8 (size of LLC+SNAP header),
+                        * protocol = LLC+SNAP header with the IPv6
+                        * Ethertype, address length = 16
+                        */
+                       p += 10;
+                       if (p + al > endp)
+                               goto trunc;
+
+                       printf("IPv6 %s", ip6addr_string(p));
+                       p += al;
+               }
+#endif
+               else {
+                       /*
+                        * Generic case: just print raw data
+                        */
                        if (p + pl > endp)
                                goto trunc;
                        printf("pt=0x%02x, pl=%d, pb=", *(p - 2), pl);
                        while (pl-- > 0)
                                printf(" %02x", *p++);
-                       al = (*p << 8) + *(p + 1);
-                       if (p + 2 + al > endp)
+                       if (p + 2 > endp)
                                goto trunc;
+                       al = (*p << 8) + *(p + 1);
                        printf(", al=%d, a=", al);
                        p += 2;
+                       if (p + al > endp)
+                               goto trunc;
                        while (al-- > 0)
                                printf(" %02x", *p++);
                }
-               printf("  ");
                num--;
+               if (num)
+                       printf(" ");
        }
 
        return 0;
@@ -213,3 +300,17 @@ cdp_print_prefixes(const u_char * p, int l)
 trunc:
        return -1;
 }
+
+/* read in a <n>-byte number, MSB first
+ * (of course this can handle max sizeof(long))
+ */
+static unsigned long cdp_get_number(const u_char * p, int l)
+{
+    unsigned long res=0;
+    while( l>0 )
+    {
+       res = (res<<8) + *p;
+       p++; l--;
+    }
+    return res;
+}