]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Make "snap_print()" handle fetching and printing the OUI.
authorguy <guy>
Tue, 26 Apr 2005 07:26:33 +0000 (07:26 +0000)
committerguy <guy>
Tue, 26 Apr 2005 07:26:33 +0000 (07:26 +0000)
Don't copy the LLC header to a "struct llc", just construct the
individual fields.

Fetch the control field early in the dissection process, and check to
make sure we have at least 4 bytes of LLC header if it's not a U frame.
Fetch both bytes of the control field for I and S frames, and display
all 4 hex digits of it.

Only dissect UI frames as BPDUs, and pass the BPDU dissector a pointer
to the beginning of the BPDU, not the beginning of the LLC header - not
all BPDUs are encapsulated in LLC headers.

Only dissect UI frames as IP packets.

Do bounds checking in "snap_print()".

interface.h
llc.h
print-fr.c
print-llc.c
print-stp.c

index dafbf235ec2183222db1b5745e3437b6bed084a7..7b182a74a848bf1d52d2dc616cc159c631a815a8 100644 (file)
@@ -18,7 +18,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.247 2005-04-21 03:57:43 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.248 2005-04-26 07:26:33 guy Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -173,8 +173,7 @@ extern void hex_print(const char *, const u_char *, u_int);
 extern int ether_encap_print(u_short, const u_char *, u_int, u_int, u_short *);
 extern int llc_print(const u_char *, u_int, u_int, const u_char *,
        const u_char *, u_short *);
-extern int snap_print(const u_char *, u_int, u_int, u_short *, u_int32_t,
-       u_short, u_int);
+extern int snap_print(const u_char *, u_int, u_int, u_short *, u_int);
 extern void aarp_print(const u_char *, u_int);
 extern void aodv_print(const u_char *, u_int, int);
 extern void atalk_print(const u_char *, u_int);
diff --git a/llc.h b/llc.h
index 738a0d9db5c4a32f0ee7916ebc3e2bd26ee0ffb2..c97975501ff231de36d952cf52c0bbaded008eb6 100644 (file)
--- a/llc.h
+++ b/llc.h
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/llc.h,v 1.17 2005-04-06 20:09:07 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/llc.h,v 1.18 2005-04-26 07:26:33 guy Exp $ (LBL)
  */
 
 /*
- * This stuff should come from a system header file, but there's no
- * obviously portable way to do that and it's not really going
- * to change from system to system.
+ * Definitions for information in the LLC header.
  */
 
-/*
- * A somewhat abstracted view of the LLC header
- */
-
-struct llc {
-       u_int8_t dsap;
-       u_int8_t ssap;
-       union {
-               u_int8_t u_ctl;
-               u_int16_t is_ctl;
-               struct {
-                       u_int8_t snap_ui;
-                       u_int8_t snap_pi[5];
-               } snap;
-               struct {
-                       u_int8_t snap_ui;
-                       u_int8_t snap_orgcode[3];
-                       u_int8_t snap_ethertype[2];
-               } snap_ether;
-       } ctl;
-};
-
-#define        llcui           ctl.snap.snap_ui
-#define        llcpi           ctl.snap.snap_pi
-#define        llc_orgcode     ctl.snap_ether.snap_orgcode
-#define        llc_ethertype   ctl.snap_ether.snap_ethertype
-#define        llcis           ctl.is_ctl
-#define        llcu            ctl.u_ctl
-
 #define        LLC_U_FMT       3
 #define        LLC_GSAP        1
 #define LLC_S_FMT      1
@@ -144,4 +113,3 @@ struct llc {
 #define PID_RFC2684_802_6_FCS  0x0005  /* 802.6, with FCS */
 #define PID_RFC2684_802_6_NOFCS        0x000b  /* 802.6, without FCS */
 #define PID_RFC2684_BPDU       0x000e  /* BPDUs */
-
index 8536ce629b40c2fcdc386a960d776a848ff0c16f..02d6bdbe37680514e4c8773ac50350fe4ff6f9be 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-       "@(#)$Header: /tcpdump/master/tcpdump/print-fr.c,v 1.34 2005-04-25 19:17:25 guy Exp $ (LBL)";
+       "@(#)$Header: /tcpdump/master/tcpdump/print-fr.c,v 1.35 2005-04-26 07:26:34 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -191,8 +191,6 @@ fr_if_print(const struct pcap_pkthdr *h, register const u_char *p)
        register u_int length = h->len;
        register u_int caplen = h->caplen;
        u_int16_t extracted_ethertype;
-       u_int32_t orgcode;
-       register u_short et;
        u_int dlci;
         u_int sdlcore;
        u_int addr_len;
@@ -268,19 +266,7 @@ fr_if_print(const struct pcap_pkthdr *h, register const u_char *p)
                break;
 
        case NLPID_SNAP:
-               orgcode = EXTRACT_24BITS(p);
-               et = EXTRACT_16BITS(p + 3);
-
-                if (eflag)
-                    (void)printf("SNAP, oui %s (0x%06x), ethertype %s (0x%04x): ",
-                                 tok2str(oui_values,"Unknown",orgcode),
-                                 orgcode,
-                                 tok2str(ethertype_values,"Unknown", et),
-                                 et);
-
-               if (snap_print((const u_char *)(p + 5), length - 5,
-                          caplen - 5, &extracted_ethertype, orgcode, et,
-                          0) == 0) {
+               if (snap_print(p, length, caplen, &extracted_ethertype, 0) == 0) {
                        /* ether_type not known, print raw packet */
                         if (!eflag)
                             fr_hdr_print(length + hdr_len, hdr_len,
index 06d0d296d003de476ca7caee4b2236194ae93d65..17b511ea8346101b7fcf3727080985fca6e5830c 100644 (file)
@@ -24,7 +24,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.64 2005-04-26 03:51:38 guy Exp $";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.65 2005-04-26 07:26:34 guy Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -115,9 +115,9 @@ int
 llc_print(const u_char *p, u_int length, u_int caplen,
          const u_char *esrc, const u_char *edst, u_short *extracted_ethertype)
 {
-       struct llc llc;
-       register u_short et;
+       u_int8_t dsap, ssap;
        u_int16_t control;
+       int is_u;
        register int ret;
 
        if (caplen < 3) {
@@ -126,10 +126,40 @@ llc_print(const u_char *p, u_int length, u_int caplen,
                return(0);
        }
 
-       /* Watch out for possible alignment problems */
-       memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc)));
+       dsap = *p;
+       ssap = *(p + 1);
+
+       /*
+        * OK, what type of LLC frame is this?  The length
+        * of the control field depends on that - I frames
+        * have a two-byte control field, and U frames have
+        * a one-byte control field.
+        */
+       control = *(p + 2);
+       if ((control & LLC_U_FMT) == LLC_U_FMT) {
+               /*
+                * U frame.
+                */
+               is_u = 1;
+       } else {
+               /*
+                * The control field in I and S frames is
+                * 2 bytes...
+                */
+               if (caplen < 4) {
+                       (void)printf("[|llc]");
+                       default_print((u_char *)p, caplen);
+                       return(0);
+               }
+
+               /*
+                * ...and is little-endian.
+                */
+               control = EXTRACT_LE_16BITS(p + 2);
+               is_u = 0;
+       }
 
-       if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) {
+       if (ssap == LLCSAP_GLOBAL && dsap == LLCSAP_GLOBAL) {
                /*
                 * This is an Ethernet_802.3 IPX frame; it has an
                 * 802.3 header (i.e., an Ethernet header where the
@@ -152,26 +182,38 @@ llc_print(const u_char *p, u_int length, u_int caplen,
             return (1);
        }
 
-       if (eflag)
-         printf("LLC, dsap %s (0x%02x), ssap %s (0x%02x), cmd 0x%02x: ",
-                 tok2str(llc_values,"Unknown",llc.dsap),
-                llc.dsap,
-                 tok2str(llc_values,"Unknown",llc.ssap),
-                llc.ssap,
-                llc.llcu);
+       if (eflag) {
+               if (is_u) {
+                       printf("LLC, dsap %s (0x%02x), ssap %s (0x%02x), cmd 0x%02x: ",
+                           tok2str(llc_values, "Unknown", dsap),
+                           dsap,
+                           tok2str(llc_values, "Unknown", ssap),
+                           ssap,
+                           control);
+               } else {
+                       printf("LLC, dsap %s (0x%02x), ssap %s (0x%02x), cmd 0x%04x: ",
+                           tok2str(llc_values, "Unknown", dsap),
+                           dsap,
+                           tok2str(llc_values, "Unknown", ssap),
+                           ssap,
+                           control);
+               }
+       }
 
-       if (llc.ssap == LLCSAP_8021D && llc.dsap == LLCSAP_8021D) {
-               stp_print(p, length);
+       if (ssap == LLCSAP_8021D && dsap == LLCSAP_8021D &&
+           control == LLC_UI) {
+               stp_print(p+3, length-3);
                return (1);
        }
 
-       if (llc.ssap == LLCSAP_IP && llc.dsap == LLCSAP_IP) {
+       if (ssap == LLCSAP_IP && dsap == LLCSAP_IP &&
+           control == LLC_UI) {
                ip_print(gndo, p+4, length-4);
                return (1);
        }
 
-       if (llc.ssap == LLCSAP_IPX && llc.dsap == LLCSAP_IPX &&
-           llc.llcui == LLC_UI) {
+       if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX &&
+           control == LLC_UI) {
                /*
                 * This is an Ethernet_802.2 IPX frame, with an 802.3
                 * header and an 802.2 LLC header with the source and
@@ -180,16 +222,13 @@ llc_print(const u_char *p, u_int length, u_int caplen,
                 * Skip DSAP, LSAP, and control field.
                 */
                printf("(NOV-802.2) ");
-               p += 3;
-               length -= 3;
-               caplen -= 3;
-               ipx_print(p, length);
+               ipx_print(p+3, length-3);
                return (1);
        }
 
 #ifdef TCPDUMP_DO_SMB
-       if (llc.ssap == LLCSAP_NETBEUI && llc.dsap == LLCSAP_NETBEUI
-           && (!(llc.llcu & LLC_S_FMT) || llc.llcu == LLC_U_FMT)) {
+       if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI
+           && (!(control & LLC_S_FMT) || control == LLC_U_FMT)) {
                /*
                 * we don't actually have a full netbeui parser yet, but the
                 * smb parser can handle many smb-in-netbeui packets, which
@@ -202,120 +241,69 @@ llc_print(const u_char *p, u_int length, u_int caplen,
                 */
 
                /*
-                * Skip the DSAP and LSAP.
+                * Skip the LLC header.
                 */
-               p += 2;
-               length -= 2;
-               caplen -= 2;
-
-               /*
-                * OK, what type of LLC frame is this?  The length
-                * of the control field depends on that - I frames
-                * have a two-byte control field, and U frames have
-                * a one-byte control field.
-                */
-               if (llc.llcu == LLC_U_FMT) {
-                       control = llc.llcu;
-                       p += 1;
-                       length -= 1;
-                       caplen -= 1;
+               if (is_u) {
+                       p += 3;
+                       length -= 3;
+                       caplen -= 3;
                } else {
-                       /*
-                        * The control field in I and S frames is
-                        * little-endian.
-                        */
-                       control = EXTRACT_LE_16BITS(&llc.llcu);
-                       p += 2;
-                       length -= 2;
-                       caplen -= 2;
+                       p += 4;
+                       length -= 4;
+                       caplen -= 4;
                }
                netbeui_print(control, p, length);
                return (1);
        }
 #endif
-       if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS
-           && llc.llcui == LLC_UI) {
+       if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS
+           && control == LLC_UI) {
                isoclns_print(p + 3, length - 3, caplen - 3);
                return (1);
        }
 
-       if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP
-           && llc.llcui == LLC_UI) {
-               u_int32_t orgcode;
-
-               if (caplen < sizeof(llc)) {
-                       (void)printf("[|llc-snap]");
-                       default_print((u_char *)p, caplen);
-                       return (0);
-               }
-
-               caplen -= sizeof(llc);
-               length -= sizeof(llc);
-               p += sizeof(llc);
-
-               orgcode = EXTRACT_24BITS(&llc.llc_orgcode[0]);
-               et = EXTRACT_16BITS(&llc.llc_ethertype[0]);
-
-               if (eflag) {
-                       const struct tok *tok = NULL;
-                       const struct oui_tok *otp;
-
-                       for (otp = &oui_to_tok[0]; otp->tok != NULL; otp++) {
-                               if (otp->oui == orgcode) {
-                                       tok = otp->tok;
-                                       break;
-                               }
-                       }
-                       (void)printf("oui %s (0x%06x), %s %s (0x%04x): ",
-                            tok2str(oui_values, "Unknown", orgcode),
-                            orgcode,
-                            (orgcode == 0x000000 ? "ethertype" : "pid"),
-                            tok2str(tok, "Unknown", et),
-                            et);
-               }
-
+       if (ssap == LLCSAP_SNAP && dsap == LLCSAP_SNAP
+           && control == LLC_UI) {
                /*
                 * XXX - what *is* the right bridge pad value here?
                 * Does anybody ever bridge one form of LAN traffic
                 * over a networking type that uses 802.2 LLC?
                 */
-               ret = snap_print(p, length, caplen, extracted_ethertype,
-                   orgcode, et, 2);
+               ret = snap_print(p+3, length-3, caplen-3, extracted_ethertype,
+                   2);
                if (ret)
                        return (ret);
        }
 
        if (!eflag) {
-               if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
+               if ((ssap & ~LLC_GSAP) == dsap) {
                        if (esrc == NULL || edst == NULL)
-                               (void)printf("%s ", llcsap_string(llc.dsap));
+                               (void)printf("%s ", llcsap_string(dsap));
                        else
                                (void)printf("%s > %s %s ",
                                                etheraddr_string(esrc),
                                                etheraddr_string(edst),
-                                               llcsap_string(llc.dsap));
+                                               llcsap_string(dsap));
                } else {
                        if (esrc == NULL || edst == NULL)
                                (void)printf("%s > %s ",
-                                       llcsap_string(llc.ssap & ~LLC_GSAP),
-                                       llcsap_string(llc.dsap));
+                                       llcsap_string(ssap & ~LLC_GSAP),
+                                       llcsap_string(dsap));
                        else
                                (void)printf("%s %s > %s %s ",
                                        etheraddr_string(esrc),
-                                       llcsap_string(llc.ssap & ~LLC_GSAP),
+                                       llcsap_string(ssap & ~LLC_GSAP),
                                        etheraddr_string(edst),
-                                       llcsap_string(llc.dsap));
+                                       llcsap_string(dsap));
                }
        }
 
-       if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
-               u_int16_t cmd;
+       if (is_u) {
                const char *m;
                char f;
 
-               cmd = LLC_U_CMD(llc.llcu);
-               m = tok2str(cmd2str, "%02x", cmd);
-               switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
+               m = tok2str(cmd2str, "%02x", LLC_U_CMD(control));
+               switch ((ssap & LLC_GSAP) | (control & LLC_U_POLL)) {
                        case 0:                 f = 'C'; break;
                        case LLC_GSAP:          f = 'R'; break;
                        case LLC_U_POLL:        f = 'P'; break;
@@ -329,7 +317,7 @@ llc_print(const u_char *p, u_int length, u_int caplen,
                length -= 3;
                caplen -= 3;
 
-               if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) {
+               if ((control & ~LLC_U_POLL) == LLC_XID) {
                        if (*p == LLC_XID_FI) {
                                printf(": %02x %02x", p[1], p[2]);
                                p += 3;
@@ -340,11 +328,7 @@ llc_print(const u_char *p, u_int length, u_int caplen,
        } else {
                char f;
 
-               /*
-                * The control field in I and S frames is little-endian.
-                */
-               control = EXTRACT_LE_16BITS(&llc.llcu);
-               switch ((llc.ssap & LLC_GSAP) | (control & LLC_IS_POLL)) {
+               switch ((ssap & LLC_GSAP) | (control & LLC_IS_POLL)) {
                        case 0:                 f = 'C'; break;
                        case LLC_GSAP:          f = 'R'; break;
                        case LLC_IS_POLL:       f = 'P'; break;
@@ -373,11 +357,37 @@ llc_print(const u_char *p, u_int length, u_int caplen,
 
 int
 snap_print(const u_char *p, u_int length, u_int caplen,
-    u_short *extracted_ethertype, u_int32_t orgcode, u_short et,
-    u_int bridge_pad)
+    u_short *extracted_ethertype, u_int bridge_pad)
 {
+       u_int32_t orgcode;
+       register u_short et;
        register int ret;
 
+       TCHECK2(*p, 5);
+       orgcode = EXTRACT_24BITS(p);
+       et = EXTRACT_16BITS(p + 3);
+
+       if (eflag) {
+               const struct tok *tok = NULL;
+               const struct oui_tok *otp;
+
+               for (otp = &oui_to_tok[0]; otp->tok != NULL; otp++) {
+                       if (otp->oui == orgcode) {
+                               tok = otp->tok;
+                               break;
+                       }
+               }
+               (void)printf("oui %s (0x%06x), %s %s (0x%04x): ",
+                    tok2str(oui_values, "Unknown", orgcode),
+                    orgcode,
+                    (orgcode == 0x000000 ? "ethertype" : "pid"),
+                    tok2str(tok, "Unknown", et),
+                    et);
+       }
+       p += 5;
+       length -= 5;
+       caplen -= 5;
+
        switch (orgcode) {
        case OUI_ENCAP_ETHER:
        case OUI_CISCO_90:
@@ -429,6 +439,7 @@ snap_print(const u_char *p, u_int length, u_int caplen,
                        /*
                         * Skip the padding.
                         */
+                       TCHECK2(*p, bridge_pad);
                        caplen -= bridge_pad;
                        length -= bridge_pad;
                        p += bridge_pad;
@@ -449,6 +460,7 @@ snap_print(const u_char *p, u_int length, u_int caplen,
                         * Skip the padding, but not the Access
                         * Control field.
                         */
+                       TCHECK2(*p, bridge_pad);
                        caplen -= bridge_pad;
                        length -= bridge_pad;
                        p += bridge_pad;
@@ -469,6 +481,7 @@ snap_print(const u_char *p, u_int length, u_int caplen,
                        /*
                         * Skip the padding.
                         */
+                       TCHECK2(*p, bridge_pad + 1);
                        caplen -= bridge_pad + 1;
                        length -= bridge_pad + 1;
                        p += bridge_pad + 1;
@@ -485,6 +498,10 @@ snap_print(const u_char *p, u_int length, u_int caplen,
                }
        }
        return (0);
+
+trunc:
+       (void)printf("[|snap]");
+       return (1);
 }
 
 
index 11df16ca93991e9e43d69ceb9e7b6e7af0dde464..6ec2c097ce445a10c35564d03109593b782400f4 100644 (file)
@@ -11,7 +11,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-stp.c,v 1.13 2003-11-16 09:36:38 guy Exp $";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-stp.c,v 1.14 2005-04-26 07:26:34 guy Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -39,23 +39,23 @@ static void
 stp_print_config_bpdu(const u_char *p)
 {
        printf("config ");
-       if (p[7] & 1)
+       if (p[4] & 1)
                printf("TOP_CHANGE ");
-       if (p[7] & 0x80)
+       if (p[4] & 0x80)
                printf("TOP_CHANGE_ACK ");
 
-       stp_print_bridge_id(p+20);
-       printf(".%.2x%.2x ", p[28], p[29]);
+       stp_print_bridge_id(p+17);
+       printf(".%.2x%.2x ", p[25], p[26]);
 
        printf("root ");
-       stp_print_bridge_id(p+8);
+       stp_print_bridge_id(p+5);
 
-       printf(" pathcost %i ", (p[16] << 24) | (p[17] << 16) | (p[18] << 8) | p[19]);
+       printf(" pathcost %i ", (p[13] << 24) | (p[14] << 16) | (p[15] << 8) | p[16]);
 
-       printf("age %i ", p[30]);
-       printf("max %i ", p[32]);
-       printf("hello %i ", p[34]);
-       printf("fdelay %i ", p[36]);
+       printf("age %i ", p[27]);
+       printf("max %i ", p[29]);
+       printf("hello %i ", p[31]);
+       printf("fdelay %i ", p[33]);
 }
 
 static void
@@ -70,16 +70,16 @@ stp_print_tcn_bpdu(void)
 void
 stp_print(const u_char *p, u_int length)
 {
-       if (length < 7)
+       if (length < 4)
                goto trunc;
 
        printf("802.1d ");
-       if (p[2] != 0x03 || p[3] || p[4] || p[5]) {
+       if (p[0] || p[1] || p[2]) {
                printf("unknown version");
                return;
        }
 
-       switch (p[6])
+       switch (p[3])
        {
        case 0x00:
                if (length < 10)
@@ -92,7 +92,7 @@ stp_print(const u_char *p, u_int length)
                break;
 
        default:
-               printf("unknown type %i", p[6]);
+               printf("unknown type %i", p[3]);
                break;
        }