diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2007-01-02 18:31:22 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2007-01-02 18:31:22 +0000 |
commit | 7355916064bc8f0d820e4d8adeaa4ad3181d5a8f (patch) | |
tree | ec4e245ea655beb0623ef7c46e92280ab25839ba /lib/libpcap | |
parent | e4dd67e23b287074f915425c4632e4bfbc4ae009 (diff) |
define bpf filters to match address and header fields in IEEE 802.11
wlan frames (DLT_IEEE802_11 and DLT_IEEE802_11_RADIO linktypes). see
tcpdump(8) for details.
"Works for me" claudio@
ok jmc@ deraadt@
Diffstat (limited to 'lib/libpcap')
-rw-r--r-- | lib/libpcap/gencode.c | 204 | ||||
-rw-r--r-- | lib/libpcap/gencode.h | 11 | ||||
-rw-r--r-- | lib/libpcap/grammar.y | 90 | ||||
-rw-r--r-- | lib/libpcap/scanner.l | 13 |
4 files changed, 300 insertions, 18 deletions
diff --git a/lib/libpcap/gencode.c b/lib/libpcap/gencode.c index ac3baa805c5..1921febca55 100644 --- a/lib/libpcap/gencode.c +++ b/lib/libpcap/gencode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gencode.c,v 1.26 2006/07/18 11:52:12 dlg Exp $ */ +/* $OpenBSD: gencode.c,v 1.27 2007/01/02 18:31:21 reyk Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 @@ -36,6 +36,9 @@ struct rtentry; #include <net/if_pflog.h> #include <net/pfvar.h> +#include <net80211/ieee80211.h> +#include <net80211/ieee80211_radiotap.h> + #include <stdlib.h> #include <stddef.h> #include <memory.h> @@ -133,6 +136,8 @@ static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, static struct block *gen_ehostop(const u_char *, int); static struct block *gen_fhostop(const u_char *, int); static struct block *gen_dnhostop(bpf_u_int32, int, u_int); +static struct block *gen_p80211_hostop(const u_char *, int); +static struct block *gen_p80211_addr(int, u_int, const u_char *); static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int); #ifdef INET6 static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int); @@ -624,9 +629,9 @@ init_linktype(type) off_nl = 32; return; - case DLT_IEEE802_11_RADIO: - off_linktype = 30 + 64; /* XXX variable */ - off_nl = 32 + 64; + case DLT_IEEE802_11_RADIO: /* XXX variable */ + off_linktype = 30 + IEEE80211_RADIOTAP_HDRLEN; + off_nl = 32 + IEEE80211_RADIOTAP_HDRLEN; return; case DLT_ATM_RFC1483: @@ -851,7 +856,8 @@ gen_hostop(addr, mask, dir, proto, src_off, dst_off) return b1; default: - abort(); + bpf_error("direction not supported on linktype 0x%x", + linktype); } b0 = gen_linktype(proto); b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask); @@ -895,7 +901,8 @@ gen_hostop6(addr, mask, dir, proto, src_off, dst_off) return b1; default: - abort(); + bpf_error("direction not supported on linktype 0x%x", + linktype); } /* this order is important */ a = (u_int32_t *)addr; @@ -939,8 +946,10 @@ gen_ehostop(eaddr, dir) b1 = gen_ehostop(eaddr, Q_DST); gen_or(b0, b1); return b1; + default: + bpf_error("direction not supported on linktype 0x%x", + linktype); } - abort(); /* NOTREACHED */ } @@ -981,8 +990,10 @@ gen_fhostop(eaddr, dir) b1 = gen_fhostop(eaddr, Q_DST); gen_or(b0, b1); return b1; + default: + bpf_error("direction not supported on linktype 0x%x", + linktype); } - abort(); /* NOTREACHED */ } @@ -1042,7 +1053,8 @@ gen_dnhostop(addr, dir, base_off) return b1; default: - abort(); + bpf_error("direction not supported on linktype 0x%x", + linktype); } b0 = gen_linktype(ETHERTYPE_DN); /* Check for pad = 1, long header case */ @@ -1159,7 +1171,8 @@ gen_host(addr, mask, proto, dir) bpf_error("'esp' modifier applied to host"); default: - abort(); + bpf_error("direction not supported on linktype 0x%x", + linktype); } /* NOTREACHED */ } @@ -2117,6 +2130,15 @@ gen_scode(name, q) "unknown FDDI host '%s'", name); return gen_fhostop(eaddr, dir); + case DLT_IEEE802_11: + case DLT_IEEE802_11_RADIO: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown 802.11 host '%s'", name); + + return gen_p80211_hostop(eaddr, dir); + default: bpf_error( "only ethernet/FDDI supports link-level host name"); @@ -2453,6 +2475,9 @@ gen_ecode(eaddr, q) return gen_ehostop(eaddr, (int)q.dir); if (linktype == DLT_FDDI) return gen_fhostop(eaddr, (int)q.dir); + if (linktype == DLT_IEEE802_11 || + linktype == DLT_IEEE802_11_RADIO) + return gen_p80211_hostop(eaddr, (int)q.dir); } bpf_error("ethernet address used in non-ether expression"); /* NOTREACHED */ @@ -2850,6 +2875,9 @@ gen_broadcast(proto) return gen_ehostop(ebroadcast, Q_DST); if (linktype == DLT_FDDI) return gen_fhostop(ebroadcast, Q_DST); + if (linktype == DLT_IEEE802_11 || + linktype == DLT_IEEE802_11_RADIO) + return gen_p80211_hostop(ebroadcast, Q_DST); bpf_error("not a broadcast link"); break; @@ -3086,3 +3114,159 @@ gen_pf_action(int action) return (b0); } + +/* IEEE 802.11 wireless header */ +struct block * +gen_p80211_type(int type, int mask) +{ + struct block *b0; + u_int offset; + + if (!(linktype == DLT_IEEE802_11 || + linktype == DLT_IEEE802_11_RADIO)) { + bpf_error("type not supported on linktype 0x%x", + linktype); + /* NOTREACHED */ + } + offset = (u_int)offsetof(struct ieee80211_frame, i_fc[0]); + if (linktype == DLT_IEEE802_11_RADIO) + offset += IEEE80211_RADIOTAP_HDRLEN; + + b0 = gen_mcmp(offset, BPF_B, (bpf_int32)type, (bpf_u_int32)mask); + + return (b0); +} + +struct block * +gen_p80211_fcdir(int fcdir) +{ + struct block *b0; + u_int offset; + + if (!(linktype == DLT_IEEE802_11 || + linktype == DLT_IEEE802_11_RADIO)) { + bpf_error("frame direction not supported on linktype 0x%x", + linktype); + /* NOTREACHED */ + } + offset = (u_int)offsetof(struct ieee80211_frame, i_fc[1]); + if (linktype == DLT_IEEE802_11_RADIO) + offset += IEEE80211_RADIOTAP_HDRLEN; + + b0 = gen_mcmp(offset, BPF_B, (bpf_int32)fcdir, + (bpf_u_int32)IEEE80211_FC1_DIR_MASK); + + return (b0); +} + +static struct block * +gen_p80211_hostop(const u_char *lladdr, int dir) +{ + struct block *b0, *b1, *b2, *b3, *b4; + u_int offset = 0; + + if (linktype == DLT_IEEE802_11_RADIO) + offset = IEEE80211_RADIOTAP_HDRLEN; + + switch (dir) { + case Q_SRC: + b0 = gen_p80211_addr(IEEE80211_FC1_DIR_NODS, offset + + (u_int)offsetof(struct ieee80211_frame, i_addr2), + lladdr); + b1 = gen_p80211_addr(IEEE80211_FC1_DIR_TODS, offset + + (u_int)offsetof(struct ieee80211_frame, i_addr2), + lladdr); + b2 = gen_p80211_addr(IEEE80211_FC1_DIR_FROMDS, offset + + (u_int)offsetof(struct ieee80211_frame, i_addr3), + lladdr); + b3 = gen_p80211_addr(IEEE80211_FC1_DIR_DSTODS, offset + + (u_int)offsetof(struct ieee80211_frame_addr4, i_addr4), + lladdr); + b4 = gen_p80211_addr(IEEE80211_FC1_DIR_DSTODS, offset + + (u_int)offsetof(struct ieee80211_frame_addr4, i_addr2), + lladdr); + + gen_or(b0, b1); + gen_or(b1, b2); + gen_or(b2, b3); + gen_or(b3, b4); + return (b4); + + case Q_DST: + b0 = gen_p80211_addr(IEEE80211_FC1_DIR_NODS, offset + + (u_int)offsetof(struct ieee80211_frame, i_addr1), + lladdr); + b1 = gen_p80211_addr(IEEE80211_FC1_DIR_TODS, offset + + (u_int)offsetof(struct ieee80211_frame, i_addr3), + lladdr); + b2 = gen_p80211_addr(IEEE80211_FC1_DIR_FROMDS, offset + + (u_int)offsetof(struct ieee80211_frame, i_addr1), + lladdr); + b3 = gen_p80211_addr(IEEE80211_FC1_DIR_DSTODS, offset + + (u_int)offsetof(struct ieee80211_frame_addr4, i_addr3), + lladdr); + b4 = gen_p80211_addr(IEEE80211_FC1_DIR_DSTODS, offset + + (u_int)offsetof(struct ieee80211_frame_addr4, i_addr1), + lladdr); + + gen_or(b0, b1); + gen_or(b1, b2); + gen_or(b2, b3); + gen_or(b3, b4); + return (b4); + + case Q_ADDR1: + return (gen_bcmp(offset + + (u_int)offsetof(struct ieee80211_frame, + i_addr1), IEEE80211_ADDR_LEN, lladdr)); + + case Q_ADDR2: + return (gen_bcmp(offset + + (u_int)offsetof(struct ieee80211_frame, + i_addr2), IEEE80211_ADDR_LEN, lladdr)); + + case Q_ADDR3: + return (gen_bcmp(offset + + (u_int)offsetof(struct ieee80211_frame, + i_addr3), IEEE80211_ADDR_LEN, lladdr)); + + case Q_ADDR4: + return (gen_p80211_addr(IEEE80211_FC1_DIR_DSTODS, offset + + (u_int)offsetof(struct ieee80211_frame_addr4, i_addr4), + lladdr)); + + case Q_AND: + b0 = gen_p80211_hostop(lladdr, Q_SRC); + b1 = gen_p80211_hostop(lladdr, Q_DST); + gen_and(b0, b1); + return (b1); + + case Q_DEFAULT: + case Q_OR: + b0 = gen_p80211_hostop(lladdr, Q_ADDR1); + b1 = gen_p80211_hostop(lladdr, Q_ADDR2); + b2 = gen_p80211_hostop(lladdr, Q_ADDR3); + b3 = gen_p80211_hostop(lladdr, Q_ADDR4); + gen_or(b0, b1); + gen_or(b1, b2); + gen_or(b2, b3); + return (b3); + + default: + bpf_error("direction not supported on linktype 0x%x", + linktype); + } + /* NOTREACHED */ +} + +static struct block * +gen_p80211_addr(int fcdir, u_int offset, const u_char *lladdr) +{ + struct block *b0, *b1; + + b0 = gen_mcmp(offset, BPF_B, (bpf_int32)fcdir, IEEE80211_FC1_DIR_MASK); + b1 = gen_bcmp(offset, IEEE80211_ADDR_LEN, lladdr); + gen_and(b0, b1); + + return (b1); +} diff --git a/lib/libpcap/gencode.h b/lib/libpcap/gencode.h index 452e55d9a9f..030e99c4e44 100644 --- a/lib/libpcap/gencode.h +++ b/lib/libpcap/gencode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: gencode.h,v 1.13 2006/07/18 11:52:12 dlg Exp $ */ +/* $OpenBSD: gencode.h,v 1.14 2007/01/02 18:31:21 reyk Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -20,7 +20,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/gencode.h,v 1.13 2006/07/18 11:52:12 dlg Exp $ (LBL) + * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/gencode.h,v 1.14 2007/01/02 18:31:21 reyk Exp $ (LBL) */ /* Address qualifiers. */ @@ -67,6 +67,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 @@ -184,6 +188,9 @@ struct block *gen_pf_reason(int); 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 **); __dead void bpf_error(const char *, ...) __attribute__((volatile, __format__ (printf, 1, 2))); diff --git a/lib/libpcap/grammar.y b/lib/libpcap/grammar.y index 1cdf27f8b49..2b167b7a649 100644 --- a/lib/libpcap/grammar.y +++ b/lib/libpcap/grammar.y @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: grammar.y,v 1.15 2006/03/26 19:15:13 camield Exp $ */ +/* $OpenBSD: grammar.y,v 1.16 2007/01/02 18:31:21 reyk Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -24,7 +24,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /cvs/OpenBSD/src/lib/libpcap/grammar.y,v 1.15 2006/03/26 19:15:13 camield Exp $ (LBL)"; + "@(#) $Header: /cvs/OpenBSD/src/lib/libpcap/grammar.y,v 1.16 2007/01/02 18:31:21 reyk Exp $ (LBL)"; #endif #include <sys/types.h> @@ -41,6 +41,8 @@ struct rtentry; #include <net/pfvar.h> +#include <net80211/ieee80211.h> + #include <stdio.h> #include <string.h> @@ -101,7 +103,7 @@ pcap_parse() %type <a> arth narth %type <i> byteop pname pnum relop irelop %type <blk> and or paren not null prog -%type <rblk> other pfvar +%type <rblk> other pfvar p80211 %token DST SRC HOST GATEWAY %token NET MASK PORT LESS GREATER PROTO PROTOCHAIN BYTE @@ -110,6 +112,7 @@ pcap_parse() %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 @@ -120,7 +123,7 @@ pcap_parse() %type <s> ID %type <e> EID %type <s> HID HID6 -%type <i> NUM action reason +%type <i> NUM action reason type subtype dir %left OR AND %nonassoc '!' @@ -234,7 +237,12 @@ 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; } | NET { $$ = Q_NET; } @@ -273,6 +281,7 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | INBOUND { $$ = gen_inbound(0); } | OUTBOUND { $$ = gen_inbound(1); } | pfvar { $$ = $1; } + | pqual p80211 { $$ = $2; } ; pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); } @@ -316,6 +325,79 @@ action: ID { if (strcasecmp($1, "pass") == 0 || } ; +p80211: TYPE type SUBTYPE subtype + { $$ = gen_p80211_type($2 | $4, + IEEE80211_FC0_TYPE_MASK | + IEEE80211_FC0_SUBTYPE_MASK); + } + | TYPE type { $$ = gen_p80211_type($2, + IEEE80211_FC0_TYPE_MASK); } + | SUBTYPE subtype { $$ = gen_p80211_type($2, + IEEE80211_FC0_SUBTYPE_MASK); } + | DIR dir { $$ = gen_p80211_fcdir($2); } + ; + +type: NUM + | ID { if (strcasecmp($1, "data") == 0) + $$ = IEEE80211_FC0_TYPE_DATA; + else if (strcasecmp($1, "mgt") == 0 || + strcasecmp($1, "management") == 0) + $$ = IEEE80211_FC0_TYPE_MGT; + else if (strcasecmp($1, "ctl") == 0 || + strcasecmp($1, "control") == 0) + $$ = IEEE80211_FC0_TYPE_CTL; + else + bpf_error("unknown 802.11 type"); + } + ; + +subtype: NUM + | ID { if (strcasecmp($1, "assocreq") == 0) + $$ = IEEE80211_FC0_SUBTYPE_ASSOC_REQ; + else if (strcasecmp($1, "assocresp") == 0) + $$ = IEEE80211_FC0_SUBTYPE_ASSOC_RESP; + else if (strcasecmp($1, "reassocreq") == 0) + $$ = IEEE80211_FC0_SUBTYPE_REASSOC_REQ; + else if (strcasecmp($1, "reassocresp") == 0) + $$ = IEEE80211_FC0_SUBTYPE_REASSOC_RESP; + else if (strcasecmp($1, "probereq") == 0) + $$ = IEEE80211_FC0_SUBTYPE_PROBE_REQ; + else if (strcasecmp($1, "proberesp") == 0) + $$ = IEEE80211_FC0_SUBTYPE_PROBE_RESP; + else if (strcasecmp($1, "beacon") == 0) + $$ = IEEE80211_FC0_SUBTYPE_BEACON; + else if (strcasecmp($1, "atim") == 0) + $$ = IEEE80211_FC0_SUBTYPE_ATIM; + else if (strcasecmp($1, "disassoc") == 0 || + strcasecmp($1, "disassociation") == 0) + $$ = IEEE80211_FC0_SUBTYPE_DISASSOC; + else if (strcasecmp($1, "auth") == 0 || + strcasecmp($1, "authentication") == 0) + $$ = IEEE80211_FC0_SUBTYPE_AUTH; + else if (strcasecmp($1, "deauth") == 0 || + strcasecmp($1, "deauthentication") == 0) + $$ = IEEE80211_FC0_SUBTYPE_DEAUTH; + else if (strcasecmp($1, "data") == 0) + $$ = IEEE80211_FC0_SUBTYPE_DATA; + else + bpf_error("unknown 802.11 subtype"); + } + ; + +dir: NUM + | ID { if (strcasecmp($1, "nods") == 0) + $$ = IEEE80211_FC1_DIR_NODS; + else if (strcasecmp($1, "tods") == 0) + $$ = IEEE80211_FC1_DIR_TODS; + else if (strcasecmp($1, "fromds") == 0) + $$ = IEEE80211_FC1_DIR_FROMDS; + else if (strcasecmp($1, "dstods") == 0) + $$ = IEEE80211_FC1_DIR_DSTODS; + else + bpf_error("unknown 802.11 direction"); + } + ; + relop: '>' { $$ = BPF_JGT; } | GEQ { $$ = BPF_JGE; } | '=' { $$ = BPF_JEQ; } diff --git a/lib/libpcap/scanner.l b/lib/libpcap/scanner.l index 6473b655f03..6aa93c19c0a 100644 --- a/lib/libpcap/scanner.l +++ b/lib/libpcap/scanner.l @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: scanner.l,v 1.18 2006/04/18 18:17:52 otto Exp $ */ +/* $OpenBSD: scanner.l,v 1.19 2007/01/02 18:31:21 reyk Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /cvs/OpenBSD/src/lib/libpcap/scanner.l,v 1.18 2006/04/18 18:17:52 otto Exp $ (LBL)"; + "@(#) $Header: /cvs/OpenBSD/src/lib/libpcap/scanner.l,v 1.19 2007/01/02 18:31:21 reyk Exp $ (LBL)"; #endif #include <sys/types.h> @@ -235,6 +235,15 @@ srnr|subrulenum return PF_SRNR; reason return PF_REASON; action return PF_ACTION; +wlan return LINK; +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; + [ \n\t] ; [+\-*/:\[\]!<>()&|=] return yytext[0]; ">=" return GEQ; |