aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ip
diff options
context:
space:
mode:
authorRuss Cox <rsc@swtch.com>2008-07-24 08:04:02 -0700
committerRuss Cox <rsc@swtch.com>2008-07-24 08:04:02 -0700
commit17b19538a48c036dbdc8817d233c0086f327485c (patch)
tree5c6260c0dda237cad964fb4fd809c89d09f2629d /src/cmd/ip
parent7e36b43bba16df64a08c13358ba2a70ae9001770 (diff)
downloadplan9port-17b19538a48c036dbdc8817d233c0086f327485c.tar.gz
plan9port-17b19538a48c036dbdc8817d233c0086f327485c.tar.bz2
plan9port-17b19538a48c036dbdc8817d233c0086f327485c.zip
snoopy: add support for wireless monitor mode packets
Diffstat (limited to 'src/cmd/ip')
-rwxr-xr-xsrc/cmd/ip/snoopy/dat.h5
-rw-r--r--src/cmd/ip/snoopy/llc.c173
-rwxr-xr-xsrc/cmd/ip/snoopy/mkfile5
-rw-r--r--src/cmd/ip/snoopy/p80211.c367
-rw-r--r--src/cmd/ip/snoopy/protos.c5
-rw-r--r--src/cmd/ip/snoopy/protos.h5
-rw-r--r--src/cmd/ip/snoopy/radiotap.c117
-rw-r--r--src/cmd/ip/snoopy/snap.c112
-rwxr-xr-xsrc/cmd/ip/snoopy/udp.c1
9 files changed, 789 insertions, 1 deletions
diff --git a/src/cmd/ip/snoopy/dat.h b/src/cmd/ip/snoopy/dat.h
index 49734a78..ba3e446d 100755
--- a/src/cmd/ip/snoopy/dat.h
+++ b/src/cmd/ip/snoopy/dat.h
@@ -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]<<8) | ((uchar*)x)[3])
+#define NetL(x) (((ulong)((((uchar*)x)[0]<<24) | (((uchar*)x)[1]<<16) | (((uchar*)x)[2]<<8) | ((uchar*)x)[3]))&0xFFFFFFFFU)
+
+#define LittleS(x) ((((uchar*)x)[1]<<8) | ((uchar*)x)[0])
+#define LittleL(x) (((ulong)((((uchar*)x)[3]<<24) | (((uchar*)x)[2]<<16) | (((uchar*)x)[1]<<8) | ((uchar*)x)[0]))&0xFFFFFFFFU)
/*
* one per protocol module
diff --git a/src/cmd/ip/snoopy/llc.c b/src/cmd/ip/snoopy/llc.c
new file mode 100644
index 00000000..bbc21986
--- /dev/null
+++ b/src/cmd/ip/snoopy/llc.c
@@ -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.dsap, h.ctl);
+ 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
index ddd66a7b..4797f12c 100755
--- a/src/cmd/ip/snoopy/mkfile
+++ b/src/cmd/ip/snoopy/mkfile
@@ -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
new file mode 100644
index 00000000..92ed8aba
--- /dev/null
+++ b/src/cmd/ip/snoopy/p80211.c
@@ -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=%d",
+ 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=%E",
+ 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 bssid=%E",
+ h.dur, h.ra, h.bssid);
+ break;
+ case CtlCfEndAck:
+ m->p = seprint(m->p, m->e, "ctl cf end ack dur=%d r=%E bssid=%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=%E",
+ h.da, h.bssid, h.sa);
+ break;
+ case FlagTods:
+ m->p = seprint(m->p, m->e, "data tds bssid=%E s=%E d=%E",
+ 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=%E s=%E",
+ 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
index 4503f7f0..69d6030b 100644
--- a/src/cmd/ip/snoopy/protos.c
+++ b/src/cmd/ip/snoopy/protos.c
@@ -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
index 501b59ec..c826736b 100644
--- a/src/cmd/ip/snoopy/protos.h
+++ b/src/cmd/ip/snoopy/protos.h
@@ -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
new file mode 100644
index 00000000..889dc8ab
--- /dev/null
+++ b/src/cmd/ip/snoopy/radiotap.c
@@ -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 chain.
+ 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
new file mode 100644
index 00000000..1854d1d6
--- /dev/null
+++ b/src/cmd/ip/snoopy/snap.c
@@ -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->et));
+ 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
index fc68d6f3..3d81f33d 100755
--- a/src/cmd/ip/snoopy/udp.c
+++ b/src/cmd/ip/snoopy/udp.c
@@ -41,6 +41,7 @@ static Mux p_mux[] =
{
{"bootp", 67, },
{"ninep", 6346, }, /* tvs */
+ {"dns", 53 },
{"rtp", ANYPORT, },
{"rtcp", ANYPORT, },
{0}