minor: fix c90 warnings
[netsniff-ng.git] / src / proto_80211_mac_hdr.c
blob7505baf695787633958ed9ca213beb55f26571ed
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 const char *dst, *src, *bssid;
310 u16 seq_ctrl;
312 mgmt = (struct ieee80211_mgmt *) pkt_pull(pkt, sizeof(*mgmt));
313 if (mgmt == NULL)
314 return 0;
316 dst = lookup_vendor((mgmt->da[0] << 16) | (mgmt->da[1] << 8) | mgmt->da[2]);
317 src = lookup_vendor((mgmt->sa[0] << 16) | (mgmt->sa[1] << 8) | mgmt->sa[2]);
318 bssid = lookup_vendor((mgmt->bssid[0] << 16) | (mgmt->bssid[1] << 8) | mgmt->bssid[2]);
320 seq_ctrl = le16_to_cpu(mgmt->seq_ctrl);
322 tprintf("Duration (%u),", le16_to_cpu(mgmt->duration));
323 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
324 mgmt->da[0], mgmt->da[1], mgmt->da[2], mgmt->da[3], mgmt->da[4], mgmt->da[5]);
325 if(dst)
326 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst, mgmt->da[3], mgmt->da[4], mgmt->da[5]);
327 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
328 mgmt->sa[0], mgmt->sa[1], mgmt->sa[2], mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
329 if(src)
330 tprintf("=> (%s:%.2x:%.2x:%.2x)", src, mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
331 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
332 mgmt->bssid[0], mgmt->bssid[1], mgmt->bssid[2], mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
333 if(bssid)
334 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid, mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
335 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ", seq_ctrl & 0xf, seq_ctrl >> 4);
337 switch (subtype) {
338 case 0b0000:
339 *get_content = assoc_req;
340 return "Association Request";
341 case 0b0001:
342 *get_content = assoc_resp;
343 return "Association Response";
344 case 0b0010:
345 *get_content = reassoc_req;
346 return "Reassociation Request";
347 case 0b0011:
348 *get_content = reassoc_resp;
349 return "Reassociation Response";
350 case 0b0100:
351 *get_content = probe_req;
352 return "Probe Request";
353 case 0b0101:
354 *get_content = probe_resp;
355 return "Probe Response";
356 case 0b1000:
357 *get_content = beacon;
358 return "Beacon";
359 case 0b1001:
360 *get_content = atim;
361 return "ATIM";
362 case 0b1010:
363 *get_content = disassoc;
364 return "Disassociation";
365 case 0b1011:
366 *get_content = auth;
367 return "Authentication";
368 case 0b1100:
369 *get_content = deauth;
370 return "Deauthentication";
373 if ((subtype >= 0b0110 && subtype <= 0b0111) || (subtype >= 0b1101 && subtype <= 0b1111))
374 return "Reserved";
376 return "Management SubType not supported";
379 static char *ctrl_sub(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)) {
381 switch (subtype) {
382 case 0b1010:
383 *get_content = ps_poll;
384 return "PS-Poll";
385 case 0b1011:
386 *get_content = rts;
387 return "RTS";
388 case 0b1100:
389 *get_content = cts;
390 return "CTS";
391 case 0b1101:
392 *get_content = ack;
393 return "ACK";
394 case 0b1110:
395 *get_content = cf_end;
396 return "CF End";
397 case 0b1111:
398 *get_content = cf_end_ack;
399 return "CF End + CF-ACK";
402 if (subtype <= 0b1001)
403 return "Reserved";
405 return "Control SubType not supported";
408 static char *data_sub(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)) {
410 switch (subtype) {
411 case 0b0000:
412 *get_content = data;
413 return "Data";
414 case 0b0001:
415 *get_content = data_cf_ack;
416 return "Data + CF-ACK";
417 case 0b0010:
418 *get_content = data_cf_poll;
419 return "Data + CF-Poll";
420 case 0b0011:
421 *get_content = data_cf_ack_poll;
422 return "Data + CF-ACK + CF-Poll";
423 case 0b0100:
424 *get_content = null;
425 return "Null";
426 case 0b0101:
427 *get_content = cf_ack;
428 return "CF-ACK";
429 case 0b0110:
430 *get_content = cf_poll;
431 return "CF-Poll";
432 case 0b0111:
433 *get_content = cf_ack_poll;
434 return "CF-ACK + CF-Poll";
437 if (subtype >= 0b1000 && subtype <= 0b1111)
438 return "Reserved";
440 return "Data SubType not supported";
443 static char *frame_control_type(u8 type, char *(**get_subtype)(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt))) {
444 switch (type) {
445 case 0b00:
446 *get_subtype = mgt_sub;
447 return "Management";
448 case 0b01:
449 *get_subtype = ctrl_sub;
450 return "Control";
451 case 0b10:
452 *get_subtype = data_sub;
453 return "Data";
454 case 0b11: return "Reserved";
457 return "Control Type not supported";
461 static void ieee80211(struct pkt_buff *pkt)
463 int8_t (*get_content)(struct pkt_buff *pkt) = NULL;
464 char *(*get_subtype)(u8 subtype, struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)) = NULL;
466 struct ieee80211_frm_ctrl *frm_ctrl =
467 (struct ieee80211_frm_ctrl *) pkt_pull(pkt, sizeof(*frm_ctrl));
468 if (frm_ctrl == NULL)
469 return;
471 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
472 le16_to_cpu(frm_ctrl->frame_control));
473 tprintf("\t [ Proto Version (%u), ", frm_ctrl->proto_version);
474 tprintf("Type (%u, %s), ", frm_ctrl->type, frame_control_type(frm_ctrl->type, &get_subtype));
475 if (get_subtype)
476 tprintf("Subtype (%u, %s)", frm_ctrl->subtype, (*get_subtype)(frm_ctrl->subtype, pkt, &get_content));
477 else
478 tprintf("\n%s%s%s", colorize_start_full(black, red),
479 "No SubType Data available", colorize_end());
480 tprintf("%s%s",
481 frm_ctrl->to_ds ? ", Frame goes to DS" : "",
482 frm_ctrl->from_ds ? ", Frame comes from DS" : "");
483 tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : "");
484 tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : "");
485 tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : "");
486 tprintf("%s", frm_ctrl->more_data ? ", More Data" : "");
487 tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : "");
488 tprintf("%s", frm_ctrl->order ? ", Order" : "");
489 tprintf(" ]\n");
491 if (get_content) {
492 if (!((*get_content) (pkt)))
493 tprintf("\n%s%s%s", colorize_start_full(black, red),
494 "Failed to dissect Subtype", colorize_end());
496 else
497 tprintf("\n%s%s%s", colorize_start_full(black, red),
498 "No SubType Data available", colorize_end());
500 // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
503 static void ieee80211_less(struct pkt_buff *pkt)
505 tprintf("802.11 frame (more on todo)");
508 struct protocol ieee80211_ops = {
509 .key = 0,
510 .print_full = ieee80211,
511 .print_less = ieee80211_less,
514 EXPORT_SYMBOL(ieee80211_ops);