plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

radiotap.c (1693B)


      1 /*
      2  * Radio tap as exported by BSD and Linux.
      3  * The wireless ethernet devices return this format on Linux
      4  * when running in monitor mode.
      5  *
      6  * TODO: Automatically determine whether the ethernet
      7  * device is radio or ether, so that -h is not needed.
      8  */
      9 
     10 #include <u.h>
     11 #include <libc.h>
     12 #include <ip.h>
     13 #include "dat.h"
     14 #include "protos.h"
     15 
     16 static Mux p_mux[] =
     17 {
     18 	{ "802.11", 0 },
     19 	{ 0 }
     20 };
     21 
     22 typedef struct Hdr Hdr;
     23 struct Hdr
     24 {
     25 	uchar vers;
     26 	uchar pad;
     27 	ushort	len;
     28 	ulong	present;
     29 };
     30 
     31 static int
     32 unpackhdr(uchar *p, uchar *ep, Hdr *h)
     33 {
     34 	if(p+sizeof(Hdr) > ep)
     35 		return -1;
     36 	h->vers = p[0];
     37 	h->pad = p[1];
     38 	h->len = LittleS(p+2);
     39 	h->present = LittleL(p+4);
     40 	// can be more present fields if 0x80000000 is set in each along the chain.
     41 	if(p+h->len > ep)
     42 		return -1;
     43 	return 0;
     44 }
     45 
     46 enum
     47 {
     48 	Ot,
     49 };
     50 
     51 static Field p_fields[] =
     52 {
     53 	{ 0 }
     54 };
     55 
     56 static void
     57 p_compile(Filter *f)
     58 {
     59 	Mux *m;
     60 
     61 	if(f->op == '='){
     62 		compile_cmp(radiotap.name, f, p_fields);
     63 		return;
     64 	}
     65 	for(m = p_mux; m->name != nil; m++){
     66 		if(strcmp(f->s, m->name) == 0){
     67 			f->pr = m->pr;
     68 			f->ulv = m->val;
     69 			f->subop = Ot;
     70 			return;
     71 		}
     72 	}
     73 	sysfatal("unknown radiotap field or protocol: %s", f->s);
     74 }
     75 
     76 static int
     77 p_filter(Filter *f, Msg *m)
     78 {
     79 	Hdr h;
     80 
     81 	memset(&h, 0, sizeof h);
     82 	if(unpackhdr(m->ps, m->pe, &h) < 0)
     83 		return 0;
     84 	m->ps += h.len;
     85 	switch(f->subop){
     86 	case Ot:
     87 		return 1;
     88 	}
     89 	return 0;
     90 }
     91 
     92 static int
     93 p_seprint(Msg *m)
     94 {
     95 	Hdr h;
     96 
     97 	memset(&h, 0, sizeof h);
     98 	if(unpackhdr(m->ps, m->pe, &h) < 0)
     99 		return -1;
    100 
    101 	m->p = seprint(m->p, m->e, "%.*H", h.len, m->ps);
    102 	m->ps += h.len;
    103 	m->pr = &p80211;
    104 	return 0;
    105 }
    106 
    107 Proto radiotap =
    108 {
    109 	"radiotap",
    110 	p_compile,
    111 	p_filter,
    112 	p_seprint,
    113 	p_mux,
    114 	nil,
    115 	nil,
    116 	defaultframer
    117 };