| t@@ -0,0 +1,173 @@
+/*
+ * LLC. Only enough to dispatch to SNAP and IP.
+ */
+
+#include
+#include
+#include
+#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
+}; |
| t@@ -0,0 +1,367 @@
+/*
+ * IEEE 802.11.
+ */
+
+#include
+#include
+#include
+#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
+}; |
| t@@ -0,0 +1,112 @@
+/*
+ * SNAP.
+ */
+
+#include
+#include
+#include
+#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
+}; |