diff --git a/gencode.c b/gencode.c index 908f226..fa68122 100644 --- a/gencode.c +++ b/gencode.c @@ -3801,6 +3801,14 @@ gen_ehostop(eaddr, dir) case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11 with 802.11 headers"); break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11 with 802.11 headers"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11 with 802.11 headers"); + break; } abort(); /* NOTREACHED */ @@ -3859,6 +3867,14 @@ gen_fhostop(eaddr, dir) case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11"); break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11"); + break; } abort(); /* NOTREACHED */ @@ -3909,6 +3925,14 @@ gen_thostop(eaddr, dir) case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11"); break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11"); + break; } abort(); /* NOTREACHED */ @@ -4202,8 +4226,79 @@ gen_wlanhostop(eaddr, dir) gen_and(b1, b0); return b0; + case Q_RA: + /* + * Not present in management frames; addr1 in other + * frames. + */ + + /* + * If the high-order bit of the type value is 0, this + * is a management frame. + * I.e, check "(link[0] & 0x08)". + */ + s = gen_load_a(OR_LINK, 0, BPF_B); + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x08; + b1->stmts = s; + + /* + * Check addr1. + */ + b0 = gen_bcmp(OR_LINK, 4, 6, eaddr); + + /* + * AND that with the check of addr1. + */ + gen_and(b1, b0); + return (b0); + + case Q_TA: + /* + * Not present in management frames; addr2, if present, + * in other frames. + */ + + /* + * 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); + + /* + * If the high-order bit of the type value is 0, this + * is a management frame. + * I.e, check "(link[0] & 0x08)". + */ + s = gen_load_a(OR_LINK, 0, BPF_B); + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x08; + b1->stmts = s; + + /* + * AND that with the check for frames other than + * CTS and ACK frames. + */ + gen_and(b1, b2); + + /* + * Check addr2. + */ + b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); + gen_and(b2, b1); + return b1; + /* - * XXX - add RA, TA, and BSSID keywords? + * XXX - add BSSID keyword? */ case Q_ADDR1: return (gen_bcmp(OR_LINK, 4, 6, eaddr)); @@ -4315,6 +4410,14 @@ gen_ipfchostop(eaddr, dir) case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11"); break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11"); + break; } abort(); /* NOTREACHED */ @@ -7856,6 +7959,14 @@ gen_ahostop(eaddr, dir) case Q_ADDR4: bpf_error("'addr4' is only supported on 802.11"); break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11"); + break; } abort(); /* NOTREACHED */ diff --git a/gencode.h b/gencode.h index e2388b7..4f71003 100644 --- a/gencode.h +++ b/gencode.h @@ -136,6 +136,8 @@ #define Q_ADDR2 6 #define Q_ADDR3 7 #define Q_ADDR4 8 +#define Q_RA 9 +#define Q_TA 10 #define Q_DEFAULT 0 #define Q_UNDEF 255 diff --git a/grammar.y b/grammar.y index 4c52579..cbb9363 100644 --- a/grammar.y +++ b/grammar.y @@ -277,7 +277,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 TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 RA TA %token LINK %token GEQ LEQ NEQ %token ID EID HID HID6 AID @@ -442,6 +442,8 @@ dqual: SRC { $$ = Q_SRC; } | ADDR2 { $$ = Q_ADDR2; } | ADDR3 { $$ = Q_ADDR3; } | ADDR4 { $$ = Q_ADDR4; } + | RA { $$ = Q_RA; } + | TA { $$ = Q_TA; } ; /* address type qualifiers */ aqual: HOST { $$ = Q_HOST; } diff --git a/pcap-filter.manmisc.in b/pcap-filter.manmisc.in index 6b826e3..d7b4b0a 100644 --- a/pcap-filter.manmisc.in +++ b/pcap-filter.manmisc.in @@ -65,6 +65,8 @@ Possible directions are .BR dst , .BR "src or dst" , .BR "src and dst" , +.BR ra , +.BR ta , .BR addr1 , .BR addr2 , .BR addr3 , @@ -76,6 +78,8 @@ there is no dir qualifier, .B "src or dst" is assumed. The +.BR ra , +.BR ta , .BR addr1 , .BR addr2 , .BR addr3 , @@ -472,6 +476,15 @@ and .B scrub (applies only to packets logged by OpenBSD's or FreeBSD's .BR pf (4)). +.IP "\fBwlan ra \fIehost\fR" +True if the IEEE 802.11 RA is +.IR ehost . +The RA field is used in all frames except for management frames. +.IP "\fBwlan ta \fIehost\fR" +True if the IEEE 802.11 TA is +.IR ehost . +The TA field is used in all frames except for management frames and +CTS (Clear To Send) and ACK (Acknowledgment) control frames. .IP "\fBwlan addr1 \fIehost\fR" True if the first IEEE 802.11 address is .IR ehost . @@ -490,7 +503,7 @@ True if the fourth IEEE 802.11 address, if present, is .IR ehost . The fourth address field is only used for WDS (Wireless Distribution System) frames. -.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fInetbeui\fP" +.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP" Abbreviations for: .in +.5i .nf diff --git a/scanner.l b/scanner.l index 9b3e139..a061a7e 100644 --- a/scanner.l +++ b/scanner.l @@ -273,6 +273,8 @@ address1|addr1 return ADDR1; address2|addr2 return ADDR2; address3|addr3 return ADDR3; address4|addr4 return ADDR4; +ra return RA; +ta return TA; less return LESS; greater return GREATER;