rollback
[netsniff-ng.git] / src / proto_80211_mac_hdr.c
blob269706b664caf61fe686cb6091e292432ed4b1b7
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Daniel Borkmann <borkmann@iogearbox.net>
4 * Copyright 2012 Markus Amend <markus@netsniff-ng.org>, Deutsche Flugsicherung GmbH
5 * Subject to the GPL, version 2.
6 */
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <netinet/in.h> /* for ntohs() */
11 #include <asm/byteorder.h>
13 #include "proto.h"
14 #include "protos.h"
15 #include "dissector_80211.h"
16 #include "built_in.h"
17 #include "pkt_buff.h"
18 #include "oui.h"
20 /* Note: Fields are encoded in little-endian! */
21 struct ieee80211_frm_ctrl {
22 union {
23 u16 frame_control;
24 struct {
25 #if defined(__LITTLE_ENDIAN_BITFIELD)
26 /* Correct order here ... */
27 __extension__ u16 proto_version:2,
28 type:2,
29 subtype:4,
30 to_ds:1,
31 from_ds:1,
32 more_frags:1,
33 retry:1,
34 power_mgmt:1,
35 more_data:1,
36 wep:1,
37 order:1;
38 #elif defined(__BIG_ENDIAN_BITFIELD)
39 __extension__ u16 subtype:4,
40 type:2,
41 proto_version:2,
42 order:1,
43 wep:1,
44 more_data:1,
45 power_mgmt:1,
46 retry:1,
47 more_frags:1,
48 from_ds:1,
49 to_ds:1;
50 #else
51 # error "Adjust your <asm/byteorder.h> defines"
52 #endif
55 } __packed;
57 /* Management Frame start */
58 /* Note: Fields are encoded in little-endian! */
59 struct ieee80211_mgmt {
60 u16 duration;
61 u8 da[6];
62 u8 sa[6];
63 u8 bssid[6];
64 u16 seq_ctrl;
65 } __packed;
67 struct ieee80211_mgmt_auth {
68 u16 auth_alg;
69 u16 auth_transaction;
70 u16 status_code;
71 /* possibly followed by Challenge text */
72 u8 variable[0];
73 } __packed;
75 struct ieee80211_mgmt_deauth {
76 u16 reason_code;
77 } __packed;
79 struct ieee80211_mgmt_assoc_req {
80 u16 capab_info;
81 u16 listen_interval;
82 /* followed by SSID and Supported rates */
83 u8 variable[0];
84 } __packed;
86 struct ieee80211_mgmt_assoc_resp {
87 u16 capab_info;
88 u16 status_code;
89 u16 aid;
90 /* followed by Supported rates */
91 u8 variable[0];
92 } __packed;
94 struct ieee80211_mgmt_reassoc_resp {
95 u16 capab_info;
96 u16 status_code;
97 u16 aid;
98 /* followed by Supported rates */
99 u8 variable[0];
100 } __packed;
102 struct ieee80211_mgmt_reassoc_req {
103 u16 capab_info;
104 u16 listen_interval;
105 u8 current_ap[6];
106 /* followed by SSID and Supported rates */
107 u8 variable[0];
108 } __packed;
110 struct ieee80211_mgmt_disassoc {
111 u16 reason_code;
112 } __packed;
114 struct ieee80211_mgmt_probe_req {
115 } __packed;
117 struct ieee80211_mgmt_beacon {
118 u64 timestamp;
119 u16 beacon_int;
120 u16 capab_info;
121 /* followed by some of SSID, Supported rates,
122 * FH Params, DS Params, CF Params, IBSS Params, TIM */
123 u8 variable[0];
124 } __packed;
126 struct ieee80211_mgmt_probe_resp {
127 u8 timestamp[8];
128 u16 beacon_int;
129 u16 capab_info;
130 /* followed by some of SSID, Supported rates,
131 * FH Params, DS Params, CF Params, IBSS Params, TIM */
132 u8 variable[0];
133 } __packed;
134 /* Management Frame end */
136 /* Control Frame start */
137 /* Note: Fields are encoded in little-endian! */
138 struct ieee80211_ctrl {
139 } __packed;
141 struct ieee80211_ctrl_rts {
142 u16 duration;
143 u8 da[6];
144 u8 sa[6];
145 } __packed;
147 struct ieee80211_ctrl_cts {
148 u16 duration;
149 u8 da[6];
150 } __packed;
152 struct ieee80211_ctrl_ack {
153 u16 duration;
154 u8 da[6];
155 } __packed;
157 struct ieee80211_ctrl_ps_poll {
158 u16 aid;
159 u8 bssid[6];
160 u8 sa[6];
161 } __packed;
163 struct ieee80211_ctrl_cf_end {
164 u16 duration;
165 u8 bssid[6];
166 u8 sa[6];
167 } __packed;
169 struct ieee80211_ctrl_cf_end_ack {
170 u16 duration;
171 u8 bssid[6];
172 u8 sa[6];
173 } __packed;
174 /* Control Frame end */
176 /* Data Frame start */
177 /* Note: Fields are encoded in little-endian! */
178 struct ieee80211_data {
179 } __packed;
181 /* TODO: Extend */
182 /* Data Frame end */
185 /* http://www.sss-mag.com/pdf/802_11tut.pdf
186 * http://www.scribd.com/doc/78443651/111/Management-Frames
187 * http://www.wildpackets.com/resources/compendium/wireless_lan/wlan_packets
188 * http://www.rhyshaden.com/wireless.htm
191 /* Management Dissectors */
192 static int8_t assoc_req(struct pkt_buff *pkt) {
193 return 0;
196 static int8_t assoc_resp(struct pkt_buff *pkt) {
197 return 0;
200 static int8_t reassoc_req(struct pkt_buff *pkt) {
201 return 0;
204 static int8_t reassoc_resp(struct pkt_buff *pkt) {
205 return 0;
208 static int8_t probe_req(struct pkt_buff *pkt) {
209 return 0;
212 static int8_t probe_resp(struct pkt_buff *pkt) {
213 return 0;
216 static int8_t beacon(struct pkt_buff *pkt) {
217 struct ieee80211_mgmt_beacon *beacon =
218 (struct ieee80211_mgmt_beacon *) pkt_pull(pkt, sizeof(*beacon));
219 if (beacon == NULL)
220 return 0;
221 tprintf("Timestamp 0x%.16lx, ", le64_to_cpu(beacon->timestamp));
222 tprintf("Beacon Interval (%fs), ",
223 le16_to_cpu(beacon->beacon_int) * 0.001024);
224 tprintf("Capabilites (0x%.8x)",
225 le16_to_cpu(beacon->capab_info));
226 return 1;
229 static int8_t atim(struct pkt_buff *pkt) {
230 return 0;
233 static int8_t disassoc(struct pkt_buff *pkt) {
234 return 0;
237 static int8_t auth(struct pkt_buff *pkt) {
238 return 0;
241 static int8_t deauth(struct pkt_buff *pkt) {
242 return 0;
244 /* End Management Dissectors */
246 /* Control Dissectors */
247 static int8_t ps_poll(struct pkt_buff *pkt) {
248 return 0;
251 static int8_t rts(struct pkt_buff *pkt) {
252 return 0;
255 static int8_t cts(struct pkt_buff *pkt) {
256 return 0;
259 static int8_t ack(struct pkt_buff *pkt) {
260 return 0;
263 static int8_t cf_end(struct pkt_buff *pkt) {
264 return 0;
267 static int8_t cf_end_ack(struct pkt_buff *pkt) {
268 return 0;
270 /* End Control Dissectors */
272 /* Data Dissectors */
273 static int8_t data(struct pkt_buff *pkt) {
274 return 0;
277 static int8_t data_cf_ack(struct pkt_buff *pkt) {
278 return 0;
281 static int8_t data_cf_poll(struct pkt_buff *pkt) {
282 return 0;
285 static int8_t data_cf_ack_poll(struct pkt_buff *pkt) {
286 return 0;
289 static int8_t null(struct pkt_buff *pkt) {
290 return 0;
293 static int8_t cf_ack(struct pkt_buff *pkt) {
294 return 0;
297 static int8_t cf_poll(struct pkt_buff *pkt) {
298 return 0;
301 static int8_t cf_ack_poll(struct pkt_buff *pkt) {
302 return 0;
304 /* End Data Dissectors */
306 static char *mgt_sub(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)) {
308 struct ieee80211_mgmt *mgmt =
309 (struct ieee80211_mgmt *) pkt_pull(pkt, sizeof(*mgmt));
310 if (mgmt == NULL)
311 return 0;
313 const char *dst = lookup_vendor((mgmt->da[0] << 16) | (mgmt->da[1] << 8) | mgmt->da[2]);
314 const char *src = lookup_vendor((mgmt->sa[0] << 16) | (mgmt->sa[1] << 8) | mgmt->sa[2]);
315 const char *bssid = lookup_vendor((mgmt->bssid[0] << 16) | (mgmt->bssid[1] << 8) | mgmt->bssid[2]);
316 u16 seq_ctrl = le16_to_cpu(mgmt->seq_ctrl);
318 tprintf("Duration (%u),", le16_to_cpu(mgmt->duration));
319 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
320 mgmt->da[0], mgmt->da[1], mgmt->da[2], mgmt->da[3], mgmt->da[4], mgmt->da[5]);
321 if(dst)
322 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst, mgmt->da[3], mgmt->da[4], mgmt->da[5]);
323 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
324 mgmt->sa[0], mgmt->sa[1], mgmt->sa[2], mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
325 if(src)
326 tprintf("=> (%s:%.2x:%.2x:%.2x)", src, mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
327 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
328 mgmt->bssid[0], mgmt->bssid[1], mgmt->bssid[2], mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
329 if(bssid)
330 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid, mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
331 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ", seq_ctrl & 0xf, seq_ctrl >> 4);
333 switch (subtype) {
334 case 0b0000:
335 *get_content = assoc_req;
336 return "Association Request";
337 case 0b0001:
338 *get_content = assoc_resp;
339 return "Association Response";
340 case 0b0010:
341 *get_content = reassoc_req;
342 return "Reassociation Request";
343 case 0b0011:
344 *get_content = reassoc_resp;
345 return "Reassociation Response";
346 case 0b0100:
347 *get_content = probe_req;
348 return "Probe Request";
349 case 0b0101:
350 *get_content = probe_resp;
351 return "Probe Response";
352 case 0b1000:
353 *get_content = beacon;
354 return "Beacon";
355 case 0b1001:
356 *get_content = atim;
357 return "ATIM";
358 case 0b1010:
359 *get_content = disassoc;
360 return "Disassociation";
361 case 0b1011:
362 *get_content = auth;
363 return "Authentication";
364 case 0b1100:
365 *get_content = deauth;
366 return "Deauthentication";
369 if ((subtype >= 0b0110 && subtype <= 0b0111) || (subtype >= 0b1101 && subtype <= 0b1111))
370 return "Reserved";
372 return "Management SubType not supported";
375 static char *ctrl_sub(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)) {
377 switch (subtype) {
378 case 0b1010:
379 *get_content = ps_poll;
380 return "PS-Poll";
381 case 0b1011:
382 *get_content = rts;
383 return "RTS";
384 case 0b1100:
385 *get_content = cts;
386 return "CTS";
387 case 0b1101:
388 *get_content = ack;
389 return "ACK";
390 case 0b1110:
391 *get_content = cf_end;
392 return "CF End";
393 case 0b1111:
394 *get_content = cf_end_ack;
395 return "CF End + CF-ACK";
398 if (subtype <= 0b1001)
399 return "Reserved";
401 return "Control SubType not supported";
404 static char *data_sub(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)) {
406 switch (subtype) {
407 case 0b0000:
408 *get_content = data;
409 return "Data";
410 case 0b0001:
411 *get_content = data_cf_ack;
412 return "Data + CF-ACK";
413 case 0b0010:
414 *get_content = data_cf_poll;
415 return "Data + CF-Poll";
416 case 0b0011:
417 *get_content = data_cf_ack_poll;
418 return "Data + CF-ACK + CF-Poll";
419 case 0b0100:
420 *get_content = null;
421 return "Null";
422 case 0b0101:
423 *get_content = cf_ack;
424 return "CF-ACK";
425 case 0b0110:
426 *get_content = cf_poll;
427 return "CF-Poll";
428 case 0b0111:
429 *get_content = cf_ack_poll;
430 return "CF-ACK + CF-Poll";
433 if (subtype >= 0b1000 && subtype <= 0b1111)
434 return "Reserved";
436 return "Data SubType not supported";
439 static char *frame_control_type(u8 type, char *(**get_subtype)(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt))) {
440 switch (type) {
441 case 0b00:
442 *get_subtype = mgt_sub;
443 return "Management";
444 case 0b01:
445 *get_subtype = ctrl_sub;
446 return "Control";
447 case 0b10:
448 *get_subtype = data_sub;
449 return "Data";
450 case 0b11: return "Reserved";
453 return "Control Type not supported";
457 static void ieee80211(struct pkt_buff *pkt)
459 int8_t (*get_content)(struct pkt_buff *pkt) = NULL;
460 char *(*get_subtype)(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)) = NULL;
462 struct ieee80211_frm_ctrl *frm_ctrl =
463 (struct ieee80211_frm_ctrl *) pkt_pull(pkt, sizeof(*frm_ctrl));
464 if (frm_ctrl == NULL)
465 return;
467 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
468 le16_to_cpu(frm_ctrl->frame_control));
469 tprintf("\t [ Proto Version (%u), ", frm_ctrl->proto_version);
470 tprintf("Type (%u, %s), ", frm_ctrl->type, frame_control_type(frm_ctrl->type, &get_subtype));
471 if (get_subtype)
472 tprintf("Subtype (%u, %s)", frm_ctrl->subtype, (*get_subtype)(frm_ctrl->subtype, pkt, &get_content));
473 else
474 tprintf("\n%s%s%s", colorize_start_full(black, red),
475 "No SubType Data available", colorize_end());
476 tprintf("%s%s",
477 frm_ctrl->to_ds ? ", Frame goes to DS" : "",
478 frm_ctrl->from_ds ? ", Frame comes from DS" : "");
479 tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : "");
480 tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : "");
481 tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : "");
482 tprintf("%s", frm_ctrl->more_data ? ", More Data" : "");
483 tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : "");
484 tprintf("%s", frm_ctrl->order ? ", Order" : "");
485 tprintf(" ]\n");
487 if (get_content) {
488 if (!((*get_content) (pkt)))
489 tprintf("\n%s%s%s", colorize_start_full(black, red),
490 "Failed to dissect Subtype", colorize_end());
492 else
493 tprintf("\n%s%s%s", colorize_start_full(black, red),
494 "No SubType Data available", colorize_end());
496 // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
499 static void ieee80211_less(struct pkt_buff *pkt)
501 tprintf("802.11 frame (more on todo)");
504 struct protocol ieee80211_ops = {
505 .key = 0,
506 .print_full = ieee80211,
507 .print_less = ieee80211_less,
510 EXPORT_SYMBOL(ieee80211_ops);