From 740fb4355de3babe5856302f84463cb4c0f7c7ac Mon Sep 17 00:00:00 2001 From: guy Date: Sun, 18 Nov 2007 02:03:52 +0000 Subject: [PATCH] Support OpenBSD's "addr1", "addr2", "addr3", and "addr4" link-layer 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 | 77 +++++++++++++++++++++- gencode.h | 7 +- grammar.y | 182 +++++++++++++++++++++++++++++++++++++--------------- ieee80211.h | 6 +- scanner.l | 7 +- 5 files changed, 223 insertions(+), 56 deletions(-) diff --git a/gencode.c b/gencode.c index 7523e11..c483e87 100644 --- 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); } diff --git a/gencode.h b/gencode.h index 71fc123..e2388b7 100644 --- 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) */ /* @@ -132,6 +132,10 @@ #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 *, ...) diff --git a/grammar.y b/grammar.y index bc0f529..8a272b4 100644 --- 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 ID %type EID %type AID %type HID HID6 -%type NUM action reason type subtype type_subtype +%type 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 ($-1 == IEEE80211_FC0_TYPE_MGT) - names = ieee80211_mgt_names; - else if ($-1 == IEEE80211_FC0_TYPE_CTL) - names = ieee80211_ctl_names; - else if ($-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 ($-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); } ; diff --git a/ieee80211.h b/ieee80211.h index 12cd383..473803d 100644 --- a/ieee80211.h +++ b/ieee80211.h @@ -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 diff --git a/scanner.l b/scanner.l index fb9fb06..f10b0a3 100644 --- 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;