tp80211.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tp80211.c (6470B) | |
--- | |
1 /* | |
2 * IEEE 802.11. | |
3 */ | |
4 | |
5 #include <u.h> | |
6 #include <libc.h> | |
7 #include <ip.h> | |
8 #include "dat.h" | |
9 #include "protos.h" | |
10 | |
11 enum | |
12 { | |
13 Tmgmt = 0, | |
14 Tctl, | |
15 Tdata, | |
16 | |
17 CtlPoll = 0xA, | |
18 CtlRts, | |
19 CtlCts, | |
20 CtlAck, | |
21 CtlCfEnd, | |
22 CtlCfEndAck, | |
23 | |
24 Data = 0, | |
25 DataCfAck, | |
26 DataCfPoll, | |
27 DataCfAckPoll, | |
28 Nodata, | |
29 NodataCfAck, | |
30 NodataCfPoll, | |
31 NodataCfAckPoll, | |
32 | |
33 FlagTods = 0x1, | |
34 FlagFromds = 0x2, | |
35 FlagMoreflag = 0x4, | |
36 FlagRetry = 0x8, | |
37 FlagPowerMgmt = 0x10, | |
38 FlagMoreData = 0x20, | |
39 FlagWep = 0x40, | |
40 FlagOrder = 0x80, | |
41 | |
42 ProtoNone = 0, | |
43 ProtoLlc, | |
44 }; | |
45 | |
46 static Mux p_mux[] = | |
47 { | |
48 { "llc", ProtoLlc }, | |
49 { 0 } | |
50 }; | |
51 | |
52 typedef struct Hdr Hdr; | |
53 struct Hdr | |
54 { | |
55 uchar vers; | |
56 uchar type; | |
57 uchar subtype; | |
58 uchar flags; | |
59 ushort dur; | |
60 uchar aid; | |
61 uchar ra[6]; | |
62 uchar ta[6]; | |
63 uchar bssid[6]; | |
64 uchar sa[6]; | |
65 uchar da[6]; | |
66 ushort seq; | |
67 int proto; | |
68 int hdrlen; | |
69 }; | |
70 | |
71 static int | |
72 unpackhdr(uchar *p, uchar *ep, Hdr *h) | |
73 { | |
74 if(p+2 > ep) | |
75 return -1; | |
76 h->vers = p[0]&3; | |
77 if(h->vers != 0){ | |
78 h->hdrlen = 2; | |
79 return -1; | |
80 } | |
81 h->type = (p[0]>>2)&3; | |
82 h->subtype = (p[0]>>4)&15; | |
83 h->flags = p[1]; | |
84 h->hdrlen = 2; | |
85 | |
86 if(h->vers != 0) | |
87 return 0; | |
88 | |
89 switch(h->type){ | |
90 case Tmgmt: | |
91 // fc dur da sa bssid seq | |
92 if(p+2+2+6+6+6+2 > ep) | |
93 return -1; | |
94 h->hdrlen = 24; | |
95 h->dur = LittleS(p+2); | |
96 memmove(h->da, p+4, 6); | |
97 memmove(h->sa, p+10, 6); | |
98 memmove(h->bssid, p+16, 6); | |
99 h->seq = LittleS(p+22); | |
100 break; | |
101 | |
102 case Tctl: | |
103 switch(h->subtype){ | |
104 case CtlPoll: | |
105 // fc aid bssid ta | |
106 if(p+2+2+6+6 > ep) | |
107 return -1; | |
108 h->hdrlen = 16; | |
109 h->aid = LittleS(p+2); | |
110 memmove(h->bssid, p+4, 6); | |
111 memmove(h->ta, p+10, 6); | |
112 break; | |
113 | |
114 case CtlRts: | |
115 // fc dur ra ta | |
116 if(p+2+2+6+6 > ep) | |
117 return -1; | |
118 h->hdrlen = 16; | |
119 h->dur = LittleS(p+2); | |
120 memmove(h->ra, p+4, 6); | |
121 memmove(h->ta, p+10, 6); | |
122 break; | |
123 | |
124 case CtlCts: | |
125 case CtlAck: | |
126 // fc dur ra | |
127 if(p+2+2+6 > ep) | |
128 return -1; | |
129 h->hdrlen = 10; | |
130 h->dur = LittleS(p+2); | |
131 memmove(h->ra, p+4, 6); | |
132 break; | |
133 | |
134 case CtlCfEnd: | |
135 case CtlCfEndAck: | |
136 // fc dur ra bssid | |
137 if(p+2+2+6+6 > ep) | |
138 return -1; | |
139 h->hdrlen = 16; | |
140 h->dur = LittleS(p+2); | |
141 memmove(h->ra, p+4, 6); | |
142 memmove(h->bssid, p+10, 6); | |
143 break; | |
144 } | |
145 break; | |
146 | |
147 case Tdata: | |
148 if(p+24 > ep) | |
149 return -1; | |
150 h->hdrlen = 24; | |
151 h->dur = LittleS(p+2); // ??? maybe | |
152 // Also, what is at p+22? | |
153 | |
154 switch(h->flags&(FlagFromds|FlagTods)){ | |
155 case 0: | |
156 memmove(h->da, p+4, 6); | |
157 memmove(h->sa, p+10, 6); | |
158 memmove(h->bssid, p+16, 6); | |
159 break; | |
160 case FlagFromds: | |
161 memmove(h->da, p+4, 6); | |
162 memmove(h->bssid, p+10, 6); | |
163 memmove(h->sa, p+16, 6); | |
164 break; | |
165 case FlagTods: | |
166 memmove(h->bssid, p+4, 6); | |
167 memmove(h->sa, p+10, 6); | |
168 memmove(h->da, p+16, 6); | |
169 break; | |
170 case FlagFromds|FlagTods: | |
171 if(p+30 > ep) | |
172 return -1; | |
173 h->hdrlen = 30; | |
174 memmove(h->ra, p+4, 6); | |
175 memmove(h->ta, p+10, 6); | |
176 memmove(h->da, p+16, 6); | |
177 memmove(h->sa, p+24, 6); // 24 sic | |
178 break; | |
179 } | |
180 p += h->hdrlen; | |
181 h->proto = ProtoNone; | |
182 if(!(h->flags&FlagWep)) | |
183 h->proto = ProtoLlc; | |
184 break; | |
185 } | |
186 return 0; | |
187 } | |
188 | |
189 enum | |
190 { | |
191 Os, | |
192 Od, | |
193 Ot, | |
194 Or, | |
195 Obssid, | |
196 Oa, | |
197 Opr, | |
198 }; | |
199 | |
200 static Field p_fields[] = | |
201 { | |
202 { "s", Fether, Os, "source address" }, | |
203 { "d", Fether, Od, "destination address" }, | |
204 { "t", Fether, Ot, "transmit address" }, | |
205 { "r", Fether, Or, "receive address" }, | |
206 { "bssid", Fether, Obssid, "bssid address" }, | |
207 { "a", Fether, Oa, "any address" }, | |
208 { "sd", Fether, Oa, "source|destination add… | |
209 { 0 } | |
210 }; | |
211 | |
212 static void | |
213 p_compile(Filter *f) | |
214 { | |
215 Mux *m; | |
216 | |
217 if(f->op == '='){ | |
218 compile_cmp(p80211.name, f, p_fields); | |
219 return; | |
220 } | |
221 if(strcmp(f->s, "mgmt") == 0){ | |
222 f->pr = &p80211; | |
223 f->ulv = Tmgmt; | |
224 f->subop = Ot; | |
225 return; | |
226 } | |
227 if(strcmp(f->s, "ctl") == 0){ | |
228 f->pr = &p80211; | |
229 f->ulv = Tctl; | |
230 f->subop = Ot; | |
231 return; | |
232 } | |
233 if(strcmp(f->s, "data") == 0){ | |
234 f->pr = &p80211; | |
235 f->ulv = Tdata; | |
236 f->subop = Ot; | |
237 return; | |
238 } | |
239 for(m = p_mux; m->name != nil; m++){ | |
240 if(strcmp(f->s, m->name) == 0){ | |
241 f->pr = m->pr; | |
242 f->ulv = m->val; | |
243 f->subop = Opr; | |
244 return; | |
245 } | |
246 } | |
247 sysfatal("unknown 802.11 field or protocol: %s", f->s); | |
248 } | |
249 | |
250 static int | |
251 p_filter(Filter *f, Msg *m) | |
252 { | |
253 Hdr h; | |
254 | |
255 memset(&h, 0, sizeof h); | |
256 if(unpackhdr(m->ps, m->pe, &h) < 0) | |
257 return 0; | |
258 m->ps += h.hdrlen; | |
259 | |
260 switch(f->subop){ | |
261 case Os: | |
262 return memcmp(h.sa, f->a, 6) == 0; | |
263 case Od: | |
264 return memcmp(h.da, f->a, 6) == 0; | |
265 case Ot: | |
266 return memcmp(h.ta, f->a, 6) == 0; | |
267 case Or: | |
268 return memcmp(h.ra, f->a, 6) == 0; | |
269 case Obssid: | |
270 return memcmp(h.bssid, f->a, 6) == 0; | |
271 case Oa: | |
272 return memcmp(h.sa, f->a, 6) == 0 | |
273 || memcmp(h.da, f->a, 6) == 0 | |
274 || memcmp(h.ta, f->a, 6) == 0 | |
275 || memcmp(h.ra, f->a, 6) == 0 | |
276 || memcmp(h.bssid, f->a, 6) == 0; | |
277 case Opr: | |
278 return h.proto == f->ulv; | |
279 } | |
280 return 0; | |
281 } | |
282 | |
283 static int | |
284 p_seprint(Msg *m) | |
285 { | |
286 Hdr h; | |
287 | |
288 memset(&h, 0, sizeof h); | |
289 if(unpackhdr(m->ps, m->pe, &h) < 0) | |
290 return -1; | |
291 | |
292 m->pr = &dump; | |
293 m->p = seprint(m->p, m->e, "fc=%02x flags=%02x ", m->ps[0], m->p… | |
294 switch(h.type){ | |
295 case Tmgmt: | |
296 m->p = seprint(m->p, m->e, "mgmt dur=%d d=%E s=%E bssid=… | |
297 h.dur, h.da, h.sa, h.bssid, h.seq); | |
298 break; | |
299 case Tctl: | |
300 switch(h.subtype){ | |
301 case CtlPoll: | |
302 m->p = seprint(m->p, m->e, "ctl poll aid=%d bssi… | |
303 h.aid, h.bssid, h.ta); | |
304 break; | |
305 case CtlRts: | |
306 m->p = seprint(m->p, m->e, "ctl rts dur=%d r=%E … | |
307 h.dur, h.ra, h.ta); | |
308 break; | |
309 case CtlCts: | |
310 m->p = seprint(m->p, m->e, "ctl cts dur=%d r=%E", | |
311 h.dur, h.ra); | |
312 break; | |
313 case CtlAck: | |
314 m->p = seprint(m->p, m->e, "ctl ack dur=%d r=%E", | |
315 h.dur, h.ra); | |
316 break; | |
317 case CtlCfEnd: | |
318 m->p = seprint(m->p, m->e, "ctl cf end dur=%d r=… | |
319 h.dur, h.ra, h.bssid); | |
320 break; | |
321 case CtlCfEndAck: | |
322 m->p = seprint(m->p, m->e, "ctl cf end ack dur=%… | |
323 h.dur, h.ra, h.bssid); | |
324 break; | |
325 default: | |
326 m->p = seprint(m->p, m->e, "ctl %.*H", m->ps, h.… | |
327 break; | |
328 } | |
329 break; | |
330 case Tdata: | |
331 switch(h.flags&(FlagFromds|FlagTods)){ | |
332 case 0: | |
333 m->p = seprint(m->p, m->e, "data d=%E s=%E bssid… | |
334 h.da, h.sa, h.bssid); | |
335 break; | |
336 case FlagFromds: | |
337 m->p = seprint(m->p, m->e, "data fds d=%E bssid=… | |
338 h.da, h.bssid, h.sa); | |
339 break; | |
340 case FlagTods: | |
341 m->p = seprint(m->p, m->e, "data tds bssid=%E s=… | |
342 h.bssid, h.sa, h.da); | |
343 break; | |
344 case FlagFromds|FlagTods: | |
345 m->p = seprint(m->p, m->e, "data fds tds r=%E t=… | |
346 h.ra, h.ta, h.da, h.sa); | |
347 break; | |
348 } | |
349 if(!(h.flags&FlagWep)) | |
350 m->pr = &llc; | |
351 break; | |
352 } | |
353 m->ps += h.hdrlen; | |
354 return 0; | |
355 } | |
356 | |
357 Proto p80211 = | |
358 { | |
359 "802.11", | |
360 p_compile, | |
361 p_filter, | |
362 p_seprint, | |
363 p_mux, | |
364 nil, | |
365 nil, | |
366 defaultframer | |
367 }; |