tsnoopy: add support for wireless monitor mode packets - plan9port - [fork] Pla… | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 17b19538a48c036dbdc8817d233c0086f327485c | |
parent 7e36b43bba16df64a08c13358ba2a70ae9001770 | |
Author: Russ Cox <[email protected]> | |
Date: Thu, 24 Jul 2008 08:04:02 -0700 | |
snoopy: add support for wireless monitor mode packets | |
Diffstat: | |
M src/cmd/ip/snoopy/dat.h | 5 ++++- | |
A src/cmd/ip/snoopy/llc.c | 173 +++++++++++++++++++++++++++++… | |
M src/cmd/ip/snoopy/mkfile | 5 +++++ | |
A src/cmd/ip/snoopy/p80211.c | 367 ++++++++++++++++++++++++++++++ | |
M src/cmd/ip/snoopy/protos.c | 5 +++++ | |
M src/cmd/ip/snoopy/protos.h | 5 +++++ | |
A src/cmd/ip/snoopy/radiotap.c | 117 +++++++++++++++++++++++++++++… | |
A src/cmd/ip/snoopy/snap.c | 112 +++++++++++++++++++++++++++++… | |
M src/cmd/ip/snoopy/udp.c | 1 + | |
9 files changed, 789 insertions(+), 1 deletion(-) | |
--- | |
diff --git a/src/cmd/ip/snoopy/dat.h b/src/cmd/ip/snoopy/dat.h | |
t@@ -6,7 +6,10 @@ typedef struct Proto Proto; | |
#define NetS(x) ((((uchar*)x)[0]<<8) | ((uchar*)x)[1]) | |
#define Net3(x) ((((uchar*)x)[0]<<16) | (((uchar*)x)[1]<<8) | ((uchar*)x)[2]) | |
-#define NetL(x) ((((uchar*)x)[0]<<24) | (((uchar*)x)[1]<<16) | (((uchar*)x)[2]… | |
+#define NetL(x) (((ulong)((((uchar*)x)[0]<<24) | (((uchar*)x)[1]<<16) | (((uch… | |
+ | |
+#define LittleS(x) ((((uchar*)x)[1]<<8) | ((uchar*)x)[0]) | |
+#define LittleL(x) (((ulong)((((uchar*)x)[3]<<24) | (((uchar*)x)[2]<<16) | (((… | |
/* | |
* one per protocol module | |
diff --git a/src/cmd/ip/snoopy/llc.c b/src/cmd/ip/snoopy/llc.c | |
t@@ -0,0 +1,173 @@ | |
+/* | |
+ * LLC. Only enough to dispatch to SNAP and IP. | |
+ */ | |
+ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <ip.h> | |
+#include "dat.h" | |
+#include "protos.h" | |
+ | |
+enum | |
+{ | |
+ UFmt = 3, | |
+ Gsap = 1, | |
+ IG = 1, | |
+ SFmt = 1, | |
+ UPoll = 0x10, | |
+ IsPoll = 0x100, | |
+ XidFi = 0x81, | |
+ | |
+ SapNull = 0, | |
+ SapGlobal = 0xff, | |
+ Sap8021BI = 0x02, | |
+ Sap8021BG = 0x03, | |
+ SapSNA = 0x04, | |
+ SapIP = 0x06, | |
+ SapProwayNM = 0x0e, | |
+ Sap8021D = 0x42, | |
+ SapRS511 = 0x4e, | |
+ SapISO8208 = 0x7e, | |
+ SapProway = 0x8e, | |
+ SapSnap = 0xaa, | |
+ SapIpx = 0xe0, | |
+ SapNetbeui = 0xf0, | |
+ SapIsons = 0xfe, | |
+}; | |
+ | |
+static Mux p_mux[] = | |
+{ | |
+// Linux gives llc -> snap not llc -> ip. | |
+// If we don't tell snoopy about llc -> ip, then the default patterns | |
+// like snoopy -h radiotap -f dns work better. | |
+// { "ip", SapIP }, | |
+ { "snap", SapSnap }, | |
+ { 0 } | |
+}; | |
+ | |
+typedef struct Hdr Hdr; | |
+struct Hdr | |
+{ | |
+ uchar dsap; | |
+ uchar ssap; | |
+ uchar dsapf; | |
+ uchar ssapf; | |
+ ushort ctl; | |
+ uchar isu; | |
+ int hdrlen; | |
+}; | |
+ | |
+static int | |
+unpackhdr(uchar *p, uchar *ep, Hdr *h) | |
+{ | |
+ if(p+3 > ep) | |
+ return -1; | |
+ h->dsapf = p[0]; | |
+ h->dsap = h->dsapf & ~IG; | |
+ h->ssapf = p[1]; | |
+ h->ssap = h->ssapf & ~Gsap; | |
+ h->ctl = p[2]; | |
+ h->hdrlen = 3; | |
+ if((h->ctl&UFmt) == UFmt) | |
+ h->isu = 1; | |
+ else{ | |
+ if(p+4 > ep) | |
+ return -1; | |
+ h->hdrlen = 4; | |
+ h->ctl = LittleS(p+2); | |
+ } | |
+ return 0; | |
+} | |
+ | |
+enum | |
+{ | |
+ Ossap, | |
+ Odsap, | |
+ Ot, | |
+}; | |
+ | |
+static Field p_fields[] = | |
+{ | |
+ { "ssap", Fnum, Ossap, "ssap" }, | |
+ { "dsap", Fnum, Odsap, "dsap" }, | |
+ { 0 } | |
+}; | |
+ | |
+static void | |
+p_compile(Filter *f) | |
+{ | |
+ Mux *m; | |
+ | |
+ if(f->op == '='){ | |
+ compile_cmp(llc.name, f, p_fields); | |
+ return; | |
+ } | |
+ for(m = p_mux; m->name != nil; m++){ | |
+ if(strcmp(f->s, m->name) == 0){ | |
+ f->pr = m->pr; | |
+ f->ulv = m->val; | |
+ f->subop = Ot; | |
+ return; | |
+ } | |
+ } | |
+ sysfatal("unknown llc field or protocol: %s", f->s); | |
+} | |
+ | |
+static int | |
+p_filter(Filter *f, Msg *m) | |
+{ | |
+ Hdr h; | |
+ | |
+ memset(&h, 0, sizeof h); | |
+ if(unpackhdr(m->ps, m->pe, &h) < 0) | |
+ return 0; | |
+ m->ps += h.hdrlen; | |
+ | |
+ switch(f->subop){ | |
+ case Ossap: | |
+ return f->ulv == h.ssap; | |
+ case Odsap: | |
+ return f->ulv == h.dsap; | |
+ case Ot: | |
+ return f->ulv == h.ssap && f->ulv == h.dsap; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+static int | |
+p_seprint(Msg *m) | |
+{ | |
+ Hdr h; | |
+ | |
+ memset(&h, 0, sizeof h); | |
+ if(unpackhdr(m->ps, m->pe, &h) < 0) | |
+ return -1; | |
+ | |
+ m->pr = &dump; | |
+ m->p = seprint(m->p, m->e, "ssap=%02x dsap=%02x ctl=%04x", h.ssap, h.d… | |
+ m->ps += h.hdrlen; | |
+ m->pr = &dump; | |
+ if(h.ssap == h.dsap){ | |
+ switch(h.ssap){ | |
+ case SapIP: | |
+ m->pr = &ip; | |
+ break; | |
+ case SapSnap: | |
+ m->pr = &snap; | |
+ break; | |
+ } | |
+ } | |
+ return 0; | |
+} | |
+ | |
+Proto llc = | |
+{ | |
+ "llc", | |
+ p_compile, | |
+ p_filter, | |
+ p_seprint, | |
+ p_mux, | |
+ nil, | |
+ nil, | |
+ defaultframer | |
+}; | |
diff --git a/src/cmd/ip/snoopy/mkfile b/src/cmd/ip/snoopy/mkfile | |
t@@ -27,6 +27,11 @@ PROTOS=\ | |
ppp_ipcp\ | |
pppoe_sess\ | |
pppoe_disc\ | |
+ dns\ | |
+ p80211\ | |
+ llc\ | |
+ radiotap\ | |
+ snap\ | |
POBJS=${PROTOS:%=%.$O} | |
diff --git a/src/cmd/ip/snoopy/p80211.c b/src/cmd/ip/snoopy/p80211.c | |
t@@ -0,0 +1,367 @@ | |
+/* | |
+ * IEEE 802.11. | |
+ */ | |
+ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <ip.h> | |
+#include "dat.h" | |
+#include "protos.h" | |
+ | |
+enum | |
+{ | |
+ Tmgmt = 0, | |
+ Tctl, | |
+ Tdata, | |
+ | |
+ CtlPoll = 0xA, | |
+ CtlRts, | |
+ CtlCts, | |
+ CtlAck, | |
+ CtlCfEnd, | |
+ CtlCfEndAck, | |
+ | |
+ Data = 0, | |
+ DataCfAck, | |
+ DataCfPoll, | |
+ DataCfAckPoll, | |
+ Nodata, | |
+ NodataCfAck, | |
+ NodataCfPoll, | |
+ NodataCfAckPoll, | |
+ | |
+ FlagTods = 0x1, | |
+ FlagFromds = 0x2, | |
+ FlagMoreflag = 0x4, | |
+ FlagRetry = 0x8, | |
+ FlagPowerMgmt = 0x10, | |
+ FlagMoreData = 0x20, | |
+ FlagWep = 0x40, | |
+ FlagOrder = 0x80, | |
+ | |
+ ProtoNone = 0, | |
+ ProtoLlc, | |
+}; | |
+ | |
+static Mux p_mux[] = | |
+{ | |
+ { "llc", ProtoLlc }, | |
+ { 0 } | |
+}; | |
+ | |
+typedef struct Hdr Hdr; | |
+struct Hdr | |
+{ | |
+ uchar vers; | |
+ uchar type; | |
+ uchar subtype; | |
+ uchar flags; | |
+ ushort dur; | |
+ uchar aid; | |
+ uchar ra[6]; | |
+ uchar ta[6]; | |
+ uchar bssid[6]; | |
+ uchar sa[6]; | |
+ uchar da[6]; | |
+ ushort seq; | |
+ int proto; | |
+ int hdrlen; | |
+}; | |
+ | |
+static int | |
+unpackhdr(uchar *p, uchar *ep, Hdr *h) | |
+{ | |
+ if(p+2 > ep) | |
+ return -1; | |
+ h->vers = p[0]&3; | |
+ if(h->vers != 0){ | |
+ h->hdrlen = 2; | |
+ return -1; | |
+ } | |
+ h->type = (p[0]>>2)&3; | |
+ h->subtype = (p[0]>>4)&15; | |
+ h->flags = p[1]; | |
+ h->hdrlen = 2; | |
+ | |
+ if(h->vers != 0) | |
+ return 0; | |
+ | |
+ switch(h->type){ | |
+ case Tmgmt: | |
+ // fc dur da sa bssid seq | |
+ if(p+2+2+6+6+6+2 > ep) | |
+ return -1; | |
+ h->hdrlen = 24; | |
+ h->dur = LittleS(p+2); | |
+ memmove(h->da, p+4, 6); | |
+ memmove(h->sa, p+10, 6); | |
+ memmove(h->bssid, p+16, 6); | |
+ h->seq = LittleS(p+22); | |
+ break; | |
+ | |
+ case Tctl: | |
+ switch(h->subtype){ | |
+ case CtlPoll: | |
+ // fc aid bssid ta | |
+ if(p+2+2+6+6 > ep) | |
+ return -1; | |
+ h->hdrlen = 16; | |
+ h->aid = LittleS(p+2); | |
+ memmove(h->bssid, p+4, 6); | |
+ memmove(h->ta, p+10, 6); | |
+ break; | |
+ | |
+ case CtlRts: | |
+ // fc dur ra ta | |
+ if(p+2+2+6+6 > ep) | |
+ return -1; | |
+ h->hdrlen = 16; | |
+ h->dur = LittleS(p+2); | |
+ memmove(h->ra, p+4, 6); | |
+ memmove(h->ta, p+10, 6); | |
+ break; | |
+ | |
+ case CtlCts: | |
+ case CtlAck: | |
+ // fc dur ra | |
+ if(p+2+2+6 > ep) | |
+ return -1; | |
+ h->hdrlen = 10; | |
+ h->dur = LittleS(p+2); | |
+ memmove(h->ra, p+4, 6); | |
+ break; | |
+ | |
+ case CtlCfEnd: | |
+ case CtlCfEndAck: | |
+ // fc dur ra bssid | |
+ if(p+2+2+6+6 > ep) | |
+ return -1; | |
+ h->hdrlen = 16; | |
+ h->dur = LittleS(p+2); | |
+ memmove(h->ra, p+4, 6); | |
+ memmove(h->bssid, p+10, 6); | |
+ break; | |
+ } | |
+ break; | |
+ | |
+ case Tdata: | |
+ if(p+24 > ep) | |
+ return -1; | |
+ h->hdrlen = 24; | |
+ h->dur = LittleS(p+2); // ??? maybe | |
+ // Also, what is at p+22? | |
+ | |
+ switch(h->flags&(FlagFromds|FlagTods)){ | |
+ case 0: | |
+ memmove(h->da, p+4, 6); | |
+ memmove(h->sa, p+10, 6); | |
+ memmove(h->bssid, p+16, 6); | |
+ break; | |
+ case FlagFromds: | |
+ memmove(h->da, p+4, 6); | |
+ memmove(h->bssid, p+10, 6); | |
+ memmove(h->sa, p+16, 6); | |
+ break; | |
+ case FlagTods: | |
+ memmove(h->bssid, p+4, 6); | |
+ memmove(h->sa, p+10, 6); | |
+ memmove(h->da, p+16, 6); | |
+ break; | |
+ case FlagFromds|FlagTods: | |
+ if(p+30 > ep) | |
+ return -1; | |
+ h->hdrlen = 30; | |
+ memmove(h->ra, p+4, 6); | |
+ memmove(h->ta, p+10, 6); | |
+ memmove(h->da, p+16, 6); | |
+ memmove(h->sa, p+24, 6); // 24 sic | |
+ break; | |
+ } | |
+ p += h->hdrlen; | |
+ h->proto = ProtoNone; | |
+ if(!(h->flags&FlagWep)) | |
+ h->proto = ProtoLlc; | |
+ break; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+enum | |
+{ | |
+ Os, | |
+ Od, | |
+ Ot, | |
+ Or, | |
+ Obssid, | |
+ Oa, | |
+ Opr, | |
+}; | |
+ | |
+static Field p_fields[] = | |
+{ | |
+ { "s", Fether, Os, "source address" }, | |
+ { "d", Fether, Od, "destination address" }, | |
+ { "t", Fether, Ot, "transmit address" }, | |
+ { "r", Fether, Or, "receive address" }, | |
+ { "bssid", Fether, Obssid, "bssid address" }, | |
+ { "a", Fether, Oa, "any address" }, | |
+ { "sd", Fether, Oa, "source|destination address" … | |
+ { 0 } | |
+}; | |
+ | |
+static void | |
+p_compile(Filter *f) | |
+{ | |
+ Mux *m; | |
+ | |
+ if(f->op == '='){ | |
+ compile_cmp(p80211.name, f, p_fields); | |
+ return; | |
+ } | |
+ if(strcmp(f->s, "mgmt") == 0){ | |
+ f->pr = &p80211; | |
+ f->ulv = Tmgmt; | |
+ f->subop = Ot; | |
+ return; | |
+ } | |
+ if(strcmp(f->s, "ctl") == 0){ | |
+ f->pr = &p80211; | |
+ f->ulv = Tctl; | |
+ f->subop = Ot; | |
+ return; | |
+ } | |
+ if(strcmp(f->s, "data") == 0){ | |
+ f->pr = &p80211; | |
+ f->ulv = Tdata; | |
+ f->subop = Ot; | |
+ return; | |
+ } | |
+ for(m = p_mux; m->name != nil; m++){ | |
+ if(strcmp(f->s, m->name) == 0){ | |
+ f->pr = m->pr; | |
+ f->ulv = m->val; | |
+ f->subop = Opr; | |
+ return; | |
+ } | |
+ } | |
+ sysfatal("unknown 802.11 field or protocol: %s", f->s); | |
+} | |
+ | |
+static int | |
+p_filter(Filter *f, Msg *m) | |
+{ | |
+ Hdr h; | |
+ | |
+ memset(&h, 0, sizeof h); | |
+ if(unpackhdr(m->ps, m->pe, &h) < 0) | |
+ return 0; | |
+ m->ps += h.hdrlen; | |
+ | |
+ switch(f->subop){ | |
+ case Os: | |
+ return memcmp(h.sa, f->a, 6) == 0; | |
+ case Od: | |
+ return memcmp(h.da, f->a, 6) == 0; | |
+ case Ot: | |
+ return memcmp(h.ta, f->a, 6) == 0; | |
+ case Or: | |
+ return memcmp(h.ra, f->a, 6) == 0; | |
+ case Obssid: | |
+ return memcmp(h.bssid, f->a, 6) == 0; | |
+ case Oa: | |
+ return memcmp(h.sa, f->a, 6) == 0 | |
+ || memcmp(h.da, f->a, 6) == 0 | |
+ || memcmp(h.ta, f->a, 6) == 0 | |
+ || memcmp(h.ra, f->a, 6) == 0 | |
+ || memcmp(h.bssid, f->a, 6) == 0; | |
+ case Opr: | |
+ return h.proto == f->ulv; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+static int | |
+p_seprint(Msg *m) | |
+{ | |
+ Hdr h; | |
+ | |
+ memset(&h, 0, sizeof h); | |
+ if(unpackhdr(m->ps, m->pe, &h) < 0) | |
+ return -1; | |
+ | |
+ m->pr = &dump; | |
+ m->p = seprint(m->p, m->e, "fc=%02x flags=%02x ", m->ps[0], m->ps[1]); | |
+ switch(h.type){ | |
+ case Tmgmt: | |
+ m->p = seprint(m->p, m->e, "mgmt dur=%d d=%E s=%E bssid=%E seq… | |
+ h.dur, h.da, h.sa, h.bssid, h.seq); | |
+ break; | |
+ case Tctl: | |
+ switch(h.subtype){ | |
+ case CtlPoll: | |
+ m->p = seprint(m->p, m->e, "ctl poll aid=%d bssid=%E t… | |
+ h.aid, h.bssid, h.ta); | |
+ break; | |
+ case CtlRts: | |
+ m->p = seprint(m->p, m->e, "ctl rts dur=%d r=%E t=%E", | |
+ h.dur, h.ra, h.ta); | |
+ break; | |
+ case CtlCts: | |
+ m->p = seprint(m->p, m->e, "ctl cts dur=%d r=%E", | |
+ h.dur, h.ra); | |
+ break; | |
+ case CtlAck: | |
+ m->p = seprint(m->p, m->e, "ctl ack dur=%d r=%E", | |
+ h.dur, h.ra); | |
+ break; | |
+ case CtlCfEnd: | |
+ m->p = seprint(m->p, m->e, "ctl cf end dur=%d r=%E bss… | |
+ h.dur, h.ra, h.bssid); | |
+ break; | |
+ case CtlCfEndAck: | |
+ m->p = seprint(m->p, m->e, "ctl cf end ack dur=%d r=%E… | |
+ h.dur, h.ra, h.bssid); | |
+ break; | |
+ default: | |
+ m->p = seprint(m->p, m->e, "ctl %.*H", m->ps, h.hdrlen… | |
+ break; | |
+ } | |
+ break; | |
+ case Tdata: | |
+ switch(h.flags&(FlagFromds|FlagTods)){ | |
+ case 0: | |
+ m->p = seprint(m->p, m->e, "data d=%E s=%E bssid=%E", | |
+ h.da, h.sa, h.bssid); | |
+ break; | |
+ case FlagFromds: | |
+ m->p = seprint(m->p, m->e, "data fds d=%E bssid=%E s=%… | |
+ h.da, h.bssid, h.sa); | |
+ break; | |
+ case FlagTods: | |
+ m->p = seprint(m->p, m->e, "data tds bssid=%E s=%E d=%… | |
+ h.bssid, h.sa, h.da); | |
+ break; | |
+ case FlagFromds|FlagTods: | |
+ m->p = seprint(m->p, m->e, "data fds tds r=%E t=%E d=%… | |
+ h.ra, h.ta, h.da, h.sa); | |
+ break; | |
+ } | |
+ if(!(h.flags&FlagWep)) | |
+ m->pr = &llc; | |
+ break; | |
+ } | |
+ m->ps += h.hdrlen; | |
+ return 0; | |
+} | |
+ | |
+Proto p80211 = | |
+{ | |
+ "802.11", | |
+ p_compile, | |
+ p_filter, | |
+ p_seprint, | |
+ p_mux, | |
+ nil, | |
+ nil, | |
+ defaultframer | |
+}; | |
diff --git a/src/cmd/ip/snoopy/protos.c b/src/cmd/ip/snoopy/protos.c | |
t@@ -29,5 +29,10 @@ Proto *protos[] = | |
&ppp_ipcp, | |
&pppoe_sess, | |
&pppoe_disc, | |
+ &dns, | |
+ &p80211, | |
+ &llc, | |
+ &radiotap, | |
+ &snap, | |
0 | |
}; | |
diff --git a/src/cmd/ip/snoopy/protos.h b/src/cmd/ip/snoopy/protos.h | |
t@@ -23,3 +23,8 @@ extern Proto ppp_chap; | |
extern Proto ppp_ipcp; | |
extern Proto pppoe_sess; | |
extern Proto pppoe_disc; | |
+extern Proto dns; | |
+extern Proto p80211; | |
+extern Proto llc; | |
+extern Proto radiotap; | |
+extern Proto snap; | |
diff --git a/src/cmd/ip/snoopy/radiotap.c b/src/cmd/ip/snoopy/radiotap.c | |
t@@ -0,0 +1,117 @@ | |
+/* | |
+ * Radio tap as exported by BSD and Linux. | |
+ * The wireless ethernet devices return this format on Linux | |
+ * when running in monitor mode. | |
+ * | |
+ * TODO: Automatically determine whether the ethernet | |
+ * device is radio or ether, so that -h is not needed. | |
+ */ | |
+ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <ip.h> | |
+#include "dat.h" | |
+#include "protos.h" | |
+ | |
+static Mux p_mux[] = | |
+{ | |
+ { "802.11", 0 }, | |
+ { 0 } | |
+}; | |
+ | |
+typedef struct Hdr Hdr; | |
+struct Hdr | |
+{ | |
+ uchar vers; | |
+ uchar pad; | |
+ ushort len; | |
+ ulong present; | |
+}; | |
+ | |
+static int | |
+unpackhdr(uchar *p, uchar *ep, Hdr *h) | |
+{ | |
+ if(p+sizeof(Hdr) > ep) | |
+ return -1; | |
+ h->vers = p[0]; | |
+ h->pad = p[1]; | |
+ h->len = LittleS(p+2); | |
+ h->present = LittleL(p+4); | |
+ // can be more present fields if 0x80000000 is set in each along the c… | |
+ if(p+h->len > ep) | |
+ return -1; | |
+ return 0; | |
+} | |
+ | |
+enum | |
+{ | |
+ Ot, | |
+}; | |
+ | |
+static Field p_fields[] = | |
+{ | |
+ { 0 } | |
+}; | |
+ | |
+static void | |
+p_compile(Filter *f) | |
+{ | |
+ Mux *m; | |
+ | |
+ if(f->op == '='){ | |
+ compile_cmp(radiotap.name, f, p_fields); | |
+ return; | |
+ } | |
+ for(m = p_mux; m->name != nil; m++){ | |
+ if(strcmp(f->s, m->name) == 0){ | |
+ f->pr = m->pr; | |
+ f->ulv = m->val; | |
+ f->subop = Ot; | |
+ return; | |
+ } | |
+ } | |
+ sysfatal("unknown radiotap field or protocol: %s", f->s); | |
+} | |
+ | |
+static int | |
+p_filter(Filter *f, Msg *m) | |
+{ | |
+ Hdr h; | |
+ | |
+ memset(&h, 0, sizeof h); | |
+ if(unpackhdr(m->ps, m->pe, &h) < 0) | |
+ return 0; | |
+ m->ps += h.len; | |
+ switch(f->subop){ | |
+ case Ot: | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+static int | |
+p_seprint(Msg *m) | |
+{ | |
+ Hdr h; | |
+ | |
+ memset(&h, 0, sizeof h); | |
+ if(unpackhdr(m->ps, m->pe, &h) < 0) | |
+ return -1; | |
+ | |
+ m->p = seprint(m->p, m->e, "%.*H", h.len, m->ps); | |
+ m->ps += h.len; | |
+ m->pr = &p80211; | |
+ return 0; | |
+} | |
+ | |
+Proto radiotap = | |
+{ | |
+ "radiotap", | |
+ p_compile, | |
+ p_filter, | |
+ p_seprint, | |
+ p_mux, | |
+ nil, | |
+ nil, | |
+ defaultframer | |
+}; | |
diff --git a/src/cmd/ip/snoopy/snap.c b/src/cmd/ip/snoopy/snap.c | |
t@@ -0,0 +1,112 @@ | |
+/* | |
+ * SNAP. | |
+ */ | |
+ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <ip.h> | |
+#include "dat.h" | |
+#include "protos.h" | |
+ | |
+enum | |
+{ | |
+ Oorg, | |
+ Oet, | |
+ | |
+ OuiEther = 0, | |
+ OuiCisco = 0xc, | |
+ OuiCisco90 = 0xf8, | |
+ OuiRfc2684 = 0x80c2, | |
+ OuiAppletalk = 0x80007, | |
+}; | |
+ | |
+static Mux p_mux[] = | |
+{ | |
+ {"ip", 0x0800, } , | |
+ {"arp", 0x0806, } , | |
+ {"rarp", 0x0806, } , | |
+ {"ip6", 0x86dd, } , | |
+ {"pppoe_disc", 0x8863, }, | |
+ {"pppoe_sess", 0x8864, }, | |
+ {"eapol", 0x888e, }, | |
+ { 0 } | |
+}; | |
+ | |
+typedef struct Hdr Hdr; | |
+struct Hdr | |
+{ | |
+ uchar org[3]; | |
+ uchar et[2]; | |
+}; | |
+ | |
+static Field p_fields[] = | |
+{ | |
+ { "org", Fnum, Oorg, "org" }, | |
+ { "et", Fnum, Oet, "et" }, | |
+ { 0 } | |
+}; | |
+ | |
+static void | |
+p_compile(Filter *f) | |
+{ | |
+ Mux *m; | |
+ | |
+ if(f->op == '='){ | |
+ compile_cmp(snap.name, f, p_fields); | |
+ return; | |
+ } | |
+ for(m = p_mux; m->name != nil; m++){ | |
+ if(strcmp(f->s, m->name) == 0){ | |
+ f->pr = m->pr; | |
+ f->ulv = m->val; | |
+ f->subop = Oet; | |
+ return; | |
+ } | |
+ } | |
+ sysfatal("unknown snap field or protocol: %s", f->s); | |
+} | |
+ | |
+static int | |
+p_filter(Filter *f, Msg *m) | |
+{ | |
+ Hdr *h; | |
+ | |
+ if(m->pe - m->ps < sizeof(Hdr)) | |
+ return 0; | |
+ h = (Hdr*)m->ps; | |
+ m->ps += 5; | |
+ switch(f->subop){ | |
+ case Oorg: | |
+ return f->ulv == Net3(h->org); | |
+ case Oet: | |
+ return f->ulv == NetS(h->et); | |
+ } | |
+ return 0; | |
+} | |
+ | |
+static int | |
+p_seprint(Msg *m) | |
+{ | |
+ Hdr *h; | |
+ | |
+ if(m->pe - m->ps < sizeof(Hdr)) | |
+ return 0; | |
+ h = (Hdr*)m->ps; | |
+ m->ps += 5; | |
+ demux(p_mux, NetS(h->et), NetS(h->et), m, &dump); | |
+ | |
+ m->p = seprint(m->p, m->e, "org=%06x et=%04x", Net3(h->org), NetS(h->e… | |
+ return 0; | |
+} | |
+ | |
+Proto snap = | |
+{ | |
+ "snap", | |
+ p_compile, | |
+ p_filter, | |
+ p_seprint, | |
+ p_mux, | |
+ nil, | |
+ nil, | |
+ defaultframer | |
+}; | |
diff --git a/src/cmd/ip/snoopy/udp.c b/src/cmd/ip/snoopy/udp.c | |
t@@ -41,6 +41,7 @@ static Mux p_mux[] = | |
{ | |
{"bootp", 67, }, | |
{"ninep", 6346, }, /* tvs */ | |
+ {"dns", 53 }, | |
{"rtp", ANYPORT, }, | |
{"rtcp", ANYPORT, }, | |
{0} |