summaryrefslogtreecommitdiff
path: root/lib/libpcap
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2007-01-02 18:31:22 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2007-01-02 18:31:22 +0000
commit7355916064bc8f0d820e4d8adeaa4ad3181d5a8f (patch)
treeec4e245ea655beb0623ef7c46e92280ab25839ba /lib/libpcap
parente4dd67e23b287074f915425c4632e4bfbc4ae009 (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.c204
-rw-r--r--lib/libpcap/gencode.h11
-rw-r--r--lib/libpcap/grammar.y90
-rw-r--r--lib/libpcap/scanner.l13
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;