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/gencode.c | |
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/gencode.c')
-rw-r--r-- | lib/libpcap/gencode.c | 204 |
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); +} |