Blob
1 /*2 * Radio tap as exported by BSD and Linux.3 * The wireless ethernet devices return this format on Linux4 * when running in monitor mode.5 *6 * TODO: Automatically determine whether the ethernet7 * device is radio or ether, so that -h is not needed.8 */10 #include <u.h>11 #include <libc.h>12 #include <ip.h>13 #include "dat.h"14 #include "protos.h"16 static Mux p_mux[] =17 {18 { "802.11", 0 },19 { 0 }20 };22 typedef struct Hdr Hdr;23 struct Hdr24 {25 uchar vers;26 uchar pad;27 ushort len;28 ulong present;29 };31 static int32 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 }46 enum47 {48 Ot,49 };51 static Field p_fields[] =52 {53 { 0 }54 };56 static void57 p_compile(Filter *f)58 {59 Mux *m;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 }76 static int77 p_filter(Filter *f, Msg *m)78 {79 Hdr h;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 }92 static int93 p_seprint(Msg *m)94 {95 Hdr h;97 memset(&h, 0, sizeof h);98 if(unpackhdr(m->ps, m->pe, &h) < 0)99 return -1;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 }107 Proto radiotap =108 {109 "radiotap",110 p_compile,111 p_filter,112 p_seprint,113 p_mux,114 nil,115 nil,116 defaultframer117 };