Blob


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 */
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 Hdr
24 {
25 uchar vers;
26 uchar pad;
27 ushort len;
28 ulong present;
29 };
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 }
46 enum
47 {
48 Ot,
49 };
51 static Field p_fields[] =
52 {
53 { 0 }
54 };
56 static void
57 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 int
77 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 int
93 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;
107 Proto radiotap =
109 "radiotap",
110 p_compile,
111 p_filter,
112 p_seprint,
113 p_mux,
114 nil,
115 nil,
116 defaultframer
117 };