mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
snoopy: add support for wireless monitor mode packets
This commit is contained in:
parent
7e36b43bba
commit
17b19538a4
9 changed files with 789 additions and 1 deletions
|
@ -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
|
||||
|
|
173
src/cmd/ip/snoopy/llc.c
Normal file
173
src/cmd/ip/snoopy/llc.c
Normal file
|
@ -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
|
||||
};
|
|
@ -27,6 +27,11 @@ PROTOS=\
|
|||
ppp_ipcp\
|
||||
pppoe_sess\
|
||||
pppoe_disc\
|
||||
dns\
|
||||
p80211\
|
||||
llc\
|
||||
radiotap\
|
||||
snap\
|
||||
|
||||
POBJS=${PROTOS:%=%.$O}
|
||||
|
||||
|
|
367
src/cmd/ip/snoopy/p80211.c
Normal file
367
src/cmd/ip/snoopy/p80211.c
Normal file
|
@ -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
|
||||
};
|
|
@ -29,5 +29,10 @@ Proto *protos[] =
|
|||
&ppp_ipcp,
|
||||
&pppoe_sess,
|
||||
&pppoe_disc,
|
||||
&dns,
|
||||
&p80211,
|
||||
&llc,
|
||||
&radiotap,
|
||||
&snap,
|
||||
0
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
117
src/cmd/ip/snoopy/radiotap.c
Normal file
117
src/cmd/ip/snoopy/radiotap.c
Normal file
|
@ -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
|
||||
};
|
112
src/cmd/ip/snoopy/snap.c
Normal file
112
src/cmd/ip/snoopy/snap.c
Normal file
|
@ -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
|
||||
};
|
|
@ -41,6 +41,7 @@ static Mux p_mux[] =
|
|||
{
|
||||
{"bootp", 67, },
|
||||
{"ninep", 6346, }, /* tvs */
|
||||
{"dns", 53 },
|
||||
{"rtp", ANYPORT, },
|
||||
{"rtcp", ANYPORT, },
|
||||
{0}
|
||||
|
|
Loading…
Reference in a new issue