]> The Tcpdump Group git mirrors - libpcap/commitdiff
Add support for filters testing for 802.2 LLC frame types.
authorGuy Harris <[email protected]>
Tue, 20 May 2014 03:53:58 +0000 (20:53 -0700)
committerGuy Harris <[email protected]>
Tue, 20 May 2014 03:53:58 +0000 (20:53 -0700)
"llc" can now be used to check for frames with 802.2 headers on
linktypes other than Sun ATM, and can now be given an argument to check
for I, S, and U frames and for particular types of S and U frames.

gencode.c
gencode.h
grammar.y
llc.h
pcap-filter.manmisc.in

index 8d79a8e051d06f6650727bfa177e7bb628a54809..7be05df230a033da839536e7b407ea4e37066807 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -2986,7 +2986,7 @@ gen_linktype(proto)
 
        case DLT_FDDI:
                /*
-                * XXX - check for asynchronous frames, as per RFC 1103.
+                * XXX - check for LLC frames.
                 */
                return gen_llc_linktype(proto);
                /*NOTREACHED*/
@@ -3465,6 +3465,178 @@ gen_snap(orgcode, ptype)
        return gen_bcmp(OR_MACPL, 0, 8, snapblock);
 }
 
+/*
+ * Generate code to match frames with an LLC header.
+ */
+struct block *
+gen_llc(void)
+{
+       struct block *b0, *b1;
+
+       switch (linktype) {
+
+       case DLT_EN10MB:
+               /*
+                * We check for an Ethernet type field less than
+                * 1500, which means it's an 802.3 length field.
+                */
+               b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+               gen_not(b0);
+
+               /*
+                * Now check for the purported DSAP and SSAP not being
+                * 0xFF, to rule out NetWare-over-802.3.
+                */
+               b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF);
+               gen_not(b1);
+               gen_and(b0, b1);
+               return b1;
+
+       case DLT_SUNATM:
+               /*
+                * We check for LLC traffic.
+                */
+               b0 = gen_atmtype_abbrev(A_LLC);
+               return b0;
+
+       case DLT_IEEE802:       /* Token Ring */
+               /*
+                * XXX - check for LLC frames.
+                */
+               return gen_true();
+
+       case DLT_FDDI:
+               /*
+                * XXX - check for LLC frames.
+                */
+               return gen_true();
+
+       case DLT_ATM_RFC1483:
+               /*
+                * For LLC encapsulation, these are defined to have an
+                * 802.2 LLC header.
+                *
+                * For VC encapsulation, they don't, but there's no
+                * way to check for that; the protocol used on the VC
+                * is negotiated out of band.
+                */
+               return gen_true();
+
+       case DLT_IEEE802_11:
+       case DLT_PRISM_HEADER:
+       case DLT_IEEE802_11_RADIO:
+       case DLT_IEEE802_11_RADIO_AVS:
+       case DLT_PPI:
+               /*
+                * Check that we have a data frame.
+                */
+               b0 = gen_check_802_11_data_frame();
+               return b0;
+
+       default:
+               bpf_error("'llc' not supported for linktype %d", linktype);
+               /* NOTREACHED */
+       }
+}
+
+struct block *
+gen_llc_i(void)
+{
+       struct block *b0, *b1;
+       struct slist *s;
+
+       /*
+        * Check whether this is an LLC frame.
+        */
+       b0 = gen_llc();
+
+       /*
+        * Load the control byte and test the low-order bit; it must
+        * be clear for I frames.
+        */
+       s = gen_load_a(OR_MACPL, 2, BPF_B);
+       b1 = new_block(JMP(BPF_JSET));
+       b1->s.k = 0x01;
+       b1->stmts = s;
+       gen_not(b1);
+       gen_and(b0, b1);
+       return b1;
+}
+
+struct block *
+gen_llc_s(void)
+{
+       struct block *b0, *b1;
+
+       /*
+        * Check whether this is an LLC frame.
+        */
+       b0 = gen_llc();
+
+       /*
+        * Now compare the low-order 2 bit of the control byte against
+        * the appropriate value for S frames.
+        */
+       b1 = gen_mcmp(OR_MACPL, 2, BPF_B, LLC_S_FMT, 0x03);
+       gen_and(b0, b1);
+       return b1;
+}
+
+struct block *
+gen_llc_u(void)
+{
+       struct block *b0, *b1;
+
+       /*
+        * Check whether this is an LLC frame.
+        */
+       b0 = gen_llc();
+
+       /*
+        * Now compare the low-order 2 bit of the control byte against
+        * the appropriate value for U frames.
+        */
+       b1 = gen_mcmp(OR_MACPL, 2, BPF_B, LLC_U_FMT, 0x03);
+       gen_and(b0, b1);
+       return b1;
+}
+
+struct block *
+gen_llc_s_subtype(bpf_u_int32 subtype)
+{
+       struct block *b0, *b1;
+
+       /*
+        * Check whether this is an LLC frame.
+        */
+       b0 = gen_llc();
+
+       /*
+        * Now check for an S frame with the appropriate type.
+        */
+       b1 = gen_mcmp(OR_MACPL, 2, BPF_B, subtype, LLC_S_CMD_MASK);
+       gen_and(b0, b1);
+       return b1;
+}
+
+struct block *
+gen_llc_u_subtype(bpf_u_int32 subtype)
+{
+       struct block *b0, *b1;
+
+       /*
+        * Check whether this is an LLC frame.
+        */
+       b0 = gen_llc();
+
+       /*
+        * Now check for a U frame with the appropriate type.
+        */
+       b1 = gen_mcmp(OR_MACPL, 2, BPF_B, subtype, LLC_U_CMD_MASK);
+       gen_and(b0, b1);
+       return b1;
+}
+
 /*
  * Generate code to match a particular packet type, for link-layer types
  * using 802.2 LLC headers.
index ee0f9eea9fb337548ad17279584cd4d574c16b3d..e6b3a71ea0dbbd347fdb293efae50894da640a3a 100644 (file)
--- a/gencode.h
+++ b/gencode.h
@@ -308,6 +308,13 @@ struct block *gen_broadcast(int);
 struct block *gen_multicast(int);
 struct block *gen_inbound(int);
 
+struct block *gen_llc(void);
+struct block *gen_llc_i(void);
+struct block *gen_llc_s(void);
+struct block *gen_llc_u(void);
+struct block *gen_llc_s_subtype(bpf_u_int32);
+struct block *gen_llc_u_subtype(bpf_u_int32);
+
 struct block *gen_vlan(int);
 struct block *gen_mpls(int);
 
index b73201530ccf7d89a50f820b61f6611adfb9d010..b269d27173e9c59d6a6fb45545f98e63ab01fe91 100644 (file)
--- a/grammar.y
+++ b/grammar.y
@@ -54,6 +54,7 @@ struct rtentry;
 #include <net/pfvar.h>
 #include <net/if_pflog.h>
 #endif
+#include "llc.h"
 #include "ieee80211.h"
 #include <pcap/namedb.h>
 
@@ -128,6 +129,23 @@ static const struct tok ieee80211_data_subtypes[] = {
        { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" },
        { 0, NULL }
 };
+static const struct tok llc_s_subtypes[] = {
+       { LLC_RR, "rr" },
+       { LLC_RNR, "rnr" },
+       { LLC_REJ, "rej" },
+       { 0, NULL }
+};
+static const struct tok llc_u_subtypes[] = {
+       { LLC_UI, "ui" },
+       { LLC_UA, "ua" },
+       { LLC_DISC, "disc" },
+       { LLC_DM, "dm" },
+       { LLC_SABME, "sabme" },
+       { LLC_TEST, "test" },
+       { LLC_XID, "xid" },
+       { LLC_FRMR, "frmr" },
+       { 0, NULL }
+};
 struct type2tok {
        int type;
        const struct tok *tok;
@@ -257,7 +275,7 @@ pfaction_to_num(const char *action)
 %type  <a>     arth narth
 %type  <i>     byteop pname pnum relop irelop
 %type  <blk>   and or paren not null prog
-%type  <rblk>  other pfvar p80211
+%type  <rblk>  other pfvar p80211 pllc
 %type  <i>     atmtype atmmultitype
 %type  <blk>   atmfield
 %type  <blk>   atmfieldvalue atmvalue atmlistvalue
@@ -507,6 +525,7 @@ other:        pqual TK_BROADCAST    { $$ = gen_broadcast($1); }
        | PPPOES                { $$ = gen_pppoes(-1); }
        | pfvar                 { $$ = $1; }
        | pqual p80211          { $$ = $2; }
+       | pllc                  { $$ = $1; }
        ;
 
 pfvar:   PF_IFNAME ID          { $$ = gen_pf_ifname($2); }
@@ -576,6 +595,31 @@ type_subtype:      ID              { int i;
                                }
                ;
 
+pllc:  LLC                     { $$ = gen_llc(); }
+       | LLC ID                { if (pcap_strcasecmp($2, "i") == 0)
+                                       $$ = gen_llc_i();
+                                 else if (pcap_strcasecmp($2, "s") == 0)
+                                       $$ = gen_llc_s();
+                                 else if (pcap_strcasecmp($2, "u") == 0)
+                                       $$ = gen_llc_u();
+                                 else {
+                                       u_int subtype;
+
+                                       subtype = str2tok($2, llc_s_subtypes);
+                                       if (subtype != -1)
+                                               $$ = gen_llc_s_subtype(subtype);
+                                       else {
+                                               subtype = str2tok($2, llc_u_subtypes);
+                                               if (subtype == -1)
+                                                       bpf_error("unknown LLC type name \"%s\"", $2);
+                                               $$ = gen_llc_u_subtype(subtype);
+                                       }
+                                 }
+                               }
+                               /* sigh, "rnr" is already a keyword for PF */
+       | LLC PF_RNR            { $$ = gen_llc_s_subtype(LLC_RNR); }
+       ;
+
 dir:     NUM
        | ID                    { if (pcap_strcasecmp($1, "nods") == 0)
                                        $$ = IEEE80211_FC1_DIR_NODS;
@@ -634,7 +678,6 @@ pnum:         NUM
        | paren pnum ')'        { $$ = $2; }
        ;
 atmtype: LANE                  { $$ = A_LANE; }
-       | LLC                   { $$ = A_LLC; }
        | METAC                 { $$ = A_METAC; }
        | BCC                   { $$ = A_BCC; }
        | OAMF4EC               { $$ = A_OAMF4EC; }
diff --git a/llc.h b/llc.h
index a02d1587de108e2e613dfe4c1d2345694743a433..b0cf881ca1dde908b06c50e460ebe9a712c463db 100644 (file)
--- a/llc.h
+++ b/llc.h
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/*
+ * Definitions for information in the LLC header.
+ */
+
+#define        LLC_U_FMT       3
+#define        LLC_GSAP        1
+#define        LLC_IG          1 /* Individual / Group */
+#define LLC_S_FMT      1
+
+#define        LLC_U_POLL      0x10
+#define        LLC_IS_POLL     0x0100
+#define        LLC_XID_FI      0x81
+
+#define LLC_U_CMD_MASK 0xef
+#define        LLC_UI          0x03
+#define        LLC_UA          0x63
+#define        LLC_DISC        0x43
+#define        LLC_DM          0x0f
+#define        LLC_SABME       0x6f
+#define        LLC_TEST        0xe3
+#define        LLC_XID         0xaf
+#define        LLC_FRMR        0x87
+
+#define LLC_S_CMD_MASK 0x0f
+#define        LLC_RR          0x0001
+#define        LLC_RNR         0x0005
+#define        LLC_REJ         0x0009
+
+#define LLC_IS_NR(is)  (((is) >> 9) & 0x7f)
+#define LLC_I_NS(is)   (((is) >> 1) & 0x7f)
+
 /*
  * 802.2 LLC SAP values.
  */
 #ifndef LLCSAP_GLOBAL
 #define        LLCSAP_GLOBAL           0xff
 #endif
-#ifndef LLCSAP_8021B
+#ifndef LLCSAP_8021B_I
 #define        LLCSAP_8021B_I          0x02
 #endif
-#ifndef LLCSAP_8021B
+#ifndef LLCSAP_8021B_G
 #define        LLCSAP_8021B_G          0x03
 #endif
 #ifndef LLCSAP_IP
index a71e5dc22deb0596848a286e52b9815f3038e5d9..f65a6a95f75fedb7581870454b65d3945163d349 100644 (file)
@@ -452,6 +452,67 @@ True if the DECNET destination address is
 .IP "\fBdecnet host \fIhost\fR"
 True if either the DECNET source or destination address is
 .IR host .
+.IP \fBllc\fP
+True if the packet has an 802.2 LLC header.  This includes:
+.IP
+Ethernet packets with a length field rather than a type field that
+aren't raw NetWare-over-802.3 packets;
+.IP
+IEEE 802.11 data packets;
+.IP
+Token Ring packets (no check is done for LLC frames);
+.IP
+FDDI packets (no check is done for LLC frames);
+.IP
+LLC-encapsulated ATM packets, for SunATM on Solaris.
+.IP
+
+.IP "\fBllc\fP \Fitype\fR"
+True if the packet has an 802.2 LLC header and has the specified
+.IR type .
+.I type
+can be one of:
+.RS
+.TP
+\fBi\fR
+Information (I) PDUs
+.TP
+\fBs\fR
+Supervisory (S) PDUs
+.TP
+\fBu\fR
+Unnumbered (U) PDUs
+.TP
+\fBrr\fR
+Receiver Ready (RR) S PDUs
+.TP
+\fBrnr\fR
+Receiver Not Ready (RNR) S PDUs
+.TP
+\fBrej\fR
+Reject (REJ) S PDUs
+.TP
+\fBui\fR
+Unnumbered Information (UI) U PDUs
+.TP
+\fBua\fR
+Unnumbered Acknowledgment (UA) U PDUs
+.TP
+\fBdisc\fR
+Disconnect (DISC) U PDUs
+.TP
+\fBsabme\fR
+Set Asynchronous Balanced Mode Extended (SABME) U PDUs
+.TP
+\fBtest\fR
+Test (TEST) U PDUs
+.TP
+\fBxid\fR
+Exchange Identification (XID) U PDUs
+.TP
+\fBfrmr\fR
+Frame Reject (FRMR) U PDUs
+.RE
 .IP "\fBifname \fIinterface\fR"
 True if the packet was logged as coming from the specified interface (applies
 only to packets logged by OpenBSD's or FreeBSD's
@@ -703,9 +764,6 @@ on the assumption that the packet is either a LANE emulated Ethernet
 packet or a LANE LE Control packet.  If \fBlane\fR isn't specified, the
 tests are done under the assumption that the packet is an
 LLC-encapsulated packet.
-.IP \fBllc\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-an LLC-encapsulated packet.
 .IP \fBoamf4s\fP
 True if the packet is an ATM packet, for SunATM on Solaris, and is
 a segment OAM F4 flow cell (VPI=0 & VCI=3).