summaryrefslogtreecommitdiff
path: root/lib/libpcap/gencode.c
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/gencode.c
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/gencode.c')
-rw-r--r--lib/libpcap/gencode.c204
1 files changed, 194 insertions, 10 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);
+}