]> The Tcpdump Group git mirrors - libpcap/commitdiff
Support OpenBSD's "addr1", "addr2", "addr3", and "addr4" link-layer
authorguy <guy>
Sun, 18 Nov 2007 02:03:52 +0000 (02:03 +0000)
committerguy <guy>
Sun, 18 Nov 2007 02:03:52 +0000 (02:03 +0000)
address types for 802.11.

Support the OpenBSD names for some of the 802.11 frame types.

Support OpenBSD's "dir" keyword for 802.11 frame directions.

gencode.c
gencode.h
grammar.y
ieee80211.h
scanner.l

index 7523e11be06dcb3a9defd5dd6e16c1113d48ced8..c483e8701dd4c7a592d4c8247391876be70b159d 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -21,7 +21,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.301 2007-11-10 21:53:05 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.302 2007-11-18 02:03:52 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -68,6 +68,7 @@ static const char rcsid[] _U_ =
 #include "nlpid.h"
 #include "llc.h"
 #include "gencode.h"
+#include "ieee80211.h"
 #include "atmuni31.h"
 #include "sunatmpos.h"
 #include "ppp.h"
@@ -3840,6 +3841,55 @@ gen_wlanhostop(eaddr, dir)
                gen_and(b1, b0);
                return b0;
 
+       /*
+        * XXX - add RA, TA, and BSSID keywords?
+        */
+       case Q_ADDR1:
+               return (gen_bcmp(OR_LINK, 4, 6, eaddr));
+
+       case Q_ADDR2:
+               /*
+                * Not present in CTS or ACK control frames.
+                */
+               b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b1);
+               b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b2);
+               gen_and(b1, b2);
+               gen_or(b0, b2);
+               b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+               gen_and(b2, b1);
+               return b1;
+
+       case Q_ADDR3:
+               /*
+                * Not present in control frames.
+                */
+               b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ADDR4:
+               /*
+                * Present only if the direction mask has both "From DS"
+                * and "To DS" set.  Neither control frames nor management
+                * frames should have both of those set, so we don't
+                * check the frame type.
+                */
+               b0 = gen_mcmp(OR_LINK, 1, BPF_B,
+                       IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
+               b1 = gen_bcmp(OR_LINK, 24, 6, eaddr);
+               gen_and(b0, b1);
+               return b1;
+
        case Q_AND:
                b0 = gen_wlanhostop(eaddr, Q_SRC);
                b1 = gen_wlanhostop(eaddr, Q_DST);
@@ -7290,6 +7340,31 @@ gen_p80211_type(int type, int mask)
                bpf_error("802.11 link-layer types supported only on 802.11");
                /* NOTREACHED */
        }
+
+       return (b0);
+}
+
+struct block *
+gen_p80211_fcdir(int fcdir)
+{
+       struct block *b0;
+
+       switch (linktype) {
+
+       case DLT_IEEE802_11:
+       case DLT_IEEE802_11_RADIO_AVS:
+       case DLT_IEEE802_11_RADIO:
+       case DLT_PRISM_HEADER:
+               break;
+
+       default:
+               bpf_error("frame direction supported only with 802.11 headers");
+               /* NOTREACHED */
+       }
+
+       b0 = gen_mcmp(OR_LINK, 1, BPF_B, (bpf_int32)fcdir,
+               (bpf_u_int32)IEEE80211_FC1_DIR_MASK);
+
        return (b0);
 }
 
index 71fc1237fe2f307c31af26c19381ee68f5f0ae0d..e2388b78c42410938721d4ced83d2d00ae9be6f0 100644 (file)
--- a/gencode.h
+++ b/gencode.h
@@ -18,7 +18,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.70 2007-06-11 10:04:25 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.71 2007-11-18 02:03:52 guy Exp $ (LBL)
  */
 
 /*
 #define Q_DST          2
 #define Q_OR           3
 #define Q_AND          4
+#define Q_ADDR1                5
+#define Q_ADDR2                6
+#define Q_ADDR3                7
+#define Q_ADDR4                8
 
 #define Q_DEFAULT      0
 #define Q_UNDEF                255
@@ -313,6 +317,7 @@ struct block *gen_pf_action(int);
 struct block *gen_pf_dir(int);
 
 struct block *gen_p80211_type(int, int);
+struct block *gen_p80211_fcdir(int);
 
 void bpf_optimize(struct block **);
 void bpf_error(const char *, ...)
index bc0f529116d1c3dac0d299e7b57e4a777c0e45ad..8a272b4d0a35de17c60a247dc241f6b86c30da9f 100644 (file)
--- a/grammar.y
+++ b/grammar.y
@@ -22,7 +22,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.100 2007-11-14 00:54:35 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.101 2007-11-18 02:03:52 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -68,9 +68,91 @@ struct rtentry;
                         (q).dir = (d),\
                         (q).addr = (a)
 
-static const char *ieee80211_mgt_names[] = IEEE80211_MGT_SUBTYPE_NAMES;
-static const char *ieee80211_ctl_names[] = IEEE80211_CTL_SUBTYPE_NAMES;
-static const char *ieee80211_data_names[] = IEEE80211_DATA_SUBTYPE_NAMES;
+struct tok {
+       int v;                  /* value */
+       const char *s;          /* string */
+};
+
+static const struct tok ieee80211_types[] = {
+       { IEEE80211_FC0_TYPE_DATA, "data" },
+       { IEEE80211_FC0_TYPE_MGT, "mgt" },
+       { IEEE80211_FC0_TYPE_MGT, "management" },
+       { IEEE80211_FC0_TYPE_CTL, "ctl" },
+       { IEEE80211_FC0_TYPE_CTL, "control" },
+       { 0, NULL }
+};
+static const struct tok ieee80211_mgt_subtypes[] = {
+       { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assocreq" },
+       { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assoc-req" },
+       { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assocresp" },
+       { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assoc-resp" },
+       { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassocreq" },
+       { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassoc-req" },
+       { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassocresp" },
+       { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassoc-resp" },
+       { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probereq" },
+       { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probe-req" },
+       { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "proberesp" },
+       { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "probe-resp" },
+       { IEEE80211_FC0_SUBTYPE_BEACON, "beacon" },
+       { IEEE80211_FC0_SUBTYPE_ATIM, "atim" },
+       { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassoc" },
+       { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassociation" },
+       { IEEE80211_FC0_SUBTYPE_AUTH, "auth" },
+       { IEEE80211_FC0_SUBTYPE_AUTH, "authentication" },
+       { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauth" },
+       { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauthentication" },
+       { 0, NULL }
+};
+static const struct tok ieee80211_ctl_subtypes[] = {
+       { IEEE80211_FC0_SUBTYPE_PS_POLL, "ps-poll" },
+       { IEEE80211_FC0_SUBTYPE_RTS, "rts" },
+       { IEEE80211_FC0_SUBTYPE_CTS, "cts" },
+       { IEEE80211_FC0_SUBTYPE_ACK, "ack" },
+       { IEEE80211_FC0_SUBTYPE_CF_END, "cf-end" },
+       { IEEE80211_FC0_SUBTYPE_CF_END_ACK, "cf-end-ack" },
+       { 0, NULL }
+};
+static const struct tok ieee80211_data_subtypes[] = {
+       { IEEE80211_FC0_SUBTYPE_DATA, "data" },
+       { IEEE80211_FC0_SUBTYPE_CF_ACK, "data-cf-ack" },
+       { IEEE80211_FC0_SUBTYPE_CF_POLL, "data-cf-poll" },
+       { IEEE80211_FC0_SUBTYPE_CF_ACPL, "data-cf-ack-poll" },
+       { IEEE80211_FC0_SUBTYPE_NODATA, "null" },
+       { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK, "cf-ack" },
+       { IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "cf-poll"  },
+       { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "cf-ack-poll" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_DATA, "qos-data" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACK, "qos-data-cf-ack" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_POLL, "qos-data-cf-poll" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACPL, "qos-data-cf-ack-poll" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA, "qos" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "qos-cf-poll" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" },
+       { 0, NULL }
+};
+struct type2tok {
+       int type;
+       const struct tok *tok;
+};
+static const struct type2tok ieee80211_type_subtypes[] = {
+       { IEEE80211_FC0_TYPE_MGT, ieee80211_mgt_subtypes },
+       { IEEE80211_FC0_TYPE_CTL, ieee80211_ctl_subtypes },
+       { IEEE80211_FC0_TYPE_DATA, ieee80211_data_subtypes },
+       { 0, NULL }
+};
+
+static int
+str2tok(const char *str, const struct tok *toks)
+{
+       int i;
+
+       for (i = 0; toks[i].s != NULL; i++) {
+               if (pcap_strcasecmp(toks[i].s, str) == 0)
+                       return (toks[i].v);
+       }
+       return (-1);
+}
 
 int n_errors = 0;
 
@@ -194,6 +276,7 @@ pfaction_to_num(const char *action)
 %token  TK_BROADCAST TK_MULTICAST
 %token  NUM INBOUND OUTBOUND
 %token  PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
+%token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4
 %token  LINK
 %token GEQ LEQ NEQ
 %token ID EID HID HID6 AID
@@ -212,13 +295,12 @@ pfaction_to_num(const char *action)
 %token RADIO
 %token FISU LSSU MSU
 %token SIO OPC DPC SLS
-%token TYPE SUBTYPE
 
 %type  <s> ID
 %type  <e> EID
 %type  <e> AID
 %type  <s> HID HID6
-%type  <i> NUM action reason type subtype type_subtype
+%type  <i> NUM action reason type subtype type_subtype dir
 
 %left OR AND
 %nonassoc  '!'
@@ -355,6 +437,10 @@ dqual:       SRC                   { $$ = Q_SRC; }
        | DST OR SRC            { $$ = Q_OR; }
        | SRC AND DST           { $$ = Q_AND; }
        | DST AND SRC           { $$ = Q_AND; }
+       | ADDR1                 { $$ = Q_ADDR1; }
+       | ADDR2                 { $$ = Q_ADDR2; }
+       | ADDR3                 { $$ = Q_ADDR3; }
+       | ADDR4                 { $$ = Q_ADDR4; }
        ;
 /* address type qualifiers */
 aqual:   HOST                  { $$ = Q_HOST; }
@@ -441,71 +527,67 @@ p80211:   TYPE type SUBTYPE subtype
                                        IEEE80211_FC0_TYPE_MASK |
                                        IEEE80211_FC0_SUBTYPE_MASK);
                                }
+       | DIR dir               { $$ = gen_p80211_fcdir($2); }
        ;
 
 type:    NUM
-       | ID                    { const char *names[] = IEEE80211_TYPE_NAMES;
-                                 int i, lim;
-                                 lim = (IEEE80211_FC0_TYPE_MASK >> IEEE80211_FC0_TYPE_SHIFT) + 1;
-                                 for (i = 0; i < lim; ++i) {
-                                       if (pcap_strcasecmp($1, names[i]) == 0) {
-                                               $$ = i << IEEE80211_FC0_TYPE_SHIFT;
-                                               break;
-                                       }
-                                 }
-                                 if (i == lim)
+       | ID                    { $$ = str2tok($1, ieee80211_types);
+                                 if ($$ == -1)
                                        bpf_error("unknown 802.11 type name");
                                }
        ;
 
 subtype:  NUM
-       | ID                    { const char **names;
-                                 int i, lim;
-                                 if ($<i>-1 == IEEE80211_FC0_TYPE_MGT)
-                                       names = ieee80211_mgt_names;
-                                 else if ($<i>-1 == IEEE80211_FC0_TYPE_CTL)
-                                       names = ieee80211_ctl_names;
-                                 else if ($<i>-1 == IEEE80211_FC0_TYPE_DATA)
-                                       names = ieee80211_data_names;
-                                 else
-                                       bpf_error("unknown 802.11 type");
-                                 lim = (IEEE80211_FC0_SUBTYPE_MASK >> IEEE80211_FC0_SUBTYPE_SHIFT) + 1;
-                                 for (i = 0; i < lim; ++i) {
-                                       if (pcap_strcasecmp($1, names[i]) == 0) {
-                                               $$ = i << IEEE80211_FC0_SUBTYPE_SHIFT;
+       | ID                    { const struct tok *types = NULL;
+                                 int i;
+                                 for (i = 0;; i++) {
+                                       if (ieee80211_type_subtypes[i].tok == NULL) {
+                                               /* Ran out of types */
+                                               bpf_error("unknown 802.11 type");
+                                               break;
+                                       }
+                                       if ($<i>-1 == ieee80211_type_subtypes[i].type) {
+                                               types = ieee80211_type_subtypes[i].tok;
                                                break;
                                        }
                                  }
-                                 if (i == lim)
-                                       bpf_error("unknown 802.11 subtype name");
+
+                                 $$ = str2tok($1, types);
+                                 if ($$ == -1)
+                                       bpf_error("unknown 802.11 subtype name");
                                }
        ;
 
-type_subtype:  ID              { const char **sub_names[] = {
-                                       ieee80211_mgt_names,
-                                       ieee80211_ctl_names,
-                                       ieee80211_data_names
-                                 };
-                                 int i, j, lim, sub_lim;
-                                 sub_lim = sizeof(sub_names) / sizeof(sub_names[0]);
-                                 lim = (IEEE80211_FC0_SUBTYPE_MASK >> IEEE80211_FC0_SUBTYPE_SHIFT) + 1;
-                                 for (i = 0; i < sub_lim; ++i) {
-                                       const char **names = sub_names[i];
-                                       for (j = 0; j < lim; ++j) {
-                                               if (pcap_strcasecmp($1, names[j]) == 0)
-                                                       break;
+type_subtype:  ID              { int i;
+                                 for (i = 0;; i++) {
+                                       if (ieee80211_type_subtypes[i].tok == NULL) {
+                                               /* Ran out of types */
+                                               bpf_error("unknown 802.11 type name");
+                                               break;
                                        }
-                                       if (j != lim) {
-                                               $$ = (i << IEEE80211_FC0_TYPE_SHIFT) |
-                                                    (j << IEEE80211_FC0_SUBTYPE_SHIFT);
+                                       $$ = str2tok($1, ieee80211_type_subtypes[i].tok);
+                                       if ($$ != -1) {
+                                               $$ |= ieee80211_type_subtypes[i].type;
                                                break;
                                        }
                                  }
-                                 if (i == sub_lim)
-                                       bpf_error("unknown 802.11 subtype name");
                                }
                ;
 
+dir:     NUM
+       | ID                    { if (pcap_strcasecmp($1, "nods") == 0)
+                                       $$ = IEEE80211_FC1_DIR_NODS;
+                                 else if (pcap_strcasecmp($1, "tods") == 0)
+                                       $$ = IEEE80211_FC1_DIR_TODS;
+                                 else if (pcap_strcasecmp($1, "fromds") == 0)
+                                       $$ = IEEE80211_FC1_DIR_FROMDS;
+                                 else if (pcap_strcasecmp($1, "dstods") == 0)
+                                       $$ = IEEE80211_FC1_DIR_DSTODS;
+                                 else
+                                       bpf_error("unknown 802.11 direction");
+                               }
+       ;
+
 reason:          NUM                   { $$ = $1; }
        | ID                    { $$ = pfreason_to_num($1); }
        ;
index 12cd383cbc9a8247c0d970f97cac9d9c9f2a7850..473803d8a242760be6bba87c1090c7548db3b5ed 100644 (file)
@@ -74,9 +74,9 @@
 #define        IEEE80211_FC0_SUBTYPE_CF_POLL           0x20
 #define        IEEE80211_FC0_SUBTYPE_CF_ACPL           0x30
 #define        IEEE80211_FC0_SUBTYPE_NODATA            0x40
-#define        IEEE80211_FC0_SUBTYPE_CFACK             0x50
-#define        IEEE80211_FC0_SUBTYPE_CFPOLL            0x60
-#define        IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK     0x70
+#define        IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK     0x50
+#define        IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL    0x60
+#define        IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL    0x70
 #define        IEEE80211_FC0_SUBTYPE_QOS               0x80
 #define        IEEE80211_FC0_SUBTYPE_QOS_NULL          0xc0
 
index fb9fb06b4aed6190fb7ed9e0ff3704a530d5e0b7..f10b0a3d31b7ecf9133329eb0dd2c497dfabcaca 100644 (file)
--- a/scanner.l
+++ b/scanner.l
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.110 2007-06-11 10:04:25 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.111 2007-11-18 02:03:52 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -249,6 +249,11 @@ gateway            return GATEWAY;
 
 type           return TYPE;
 subtype                return SUBTYPE;
+direction|dir  return DIR;
+address1|addr1 return ADDR1;
+address2|addr2 return ADDR2;
+address3|addr3 return ADDR3;
+address4|addr4 return ADDR4;
 
 less           return LESS;
 greater                return GREATER;