proto: 802.11: minor: Markus as lead author
[netsniff-ng.git] / src / proto_80211_mac_hdr.c
blob698d92a72e09419147e990028b7bcf6911dac399
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Markus Amend <markus@netsniff-ng.org>
4 * Copyright 2012 Daniel Borkmann <daniel@netsniff-ng.org>
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 #define TU 0.001024
22 /* Note: Fields are encoded in little-endian! */
23 struct ieee80211_frm_ctrl {
24 union {
25 u16 frame_control;
26 struct {
27 #if defined(__LITTLE_ENDIAN_BITFIELD)
28 /* Correct order here ... */
29 __extension__ u16 proto_version:2,
30 type:2,
31 subtype:4,
32 to_ds:1,
33 from_ds:1,
34 more_frags:1,
35 retry:1,
36 power_mgmt:1,
37 more_data:1,
38 wep:1,
39 order:1;
40 #elif defined(__BIG_ENDIAN_BITFIELD)
41 __extension__ u16 subtype:4,
42 type:2,
43 proto_version:2,
44 order:1,
45 wep:1,
46 more_data:1,
47 power_mgmt:1,
48 retry:1,
49 more_frags:1,
50 from_ds:1,
51 to_ds:1;
52 #else
53 # error "Adjust your <asm/byteorder.h> defines"
54 #endif
57 } __packed;
59 /* Management Frame start */
60 /* Note: Fields are encoded in little-endian! */
61 struct ieee80211_mgmt {
62 u16 duration;
63 u8 da[6];
64 u8 sa[6];
65 u8 bssid[6];
66 u16 seq_ctrl;
67 } __packed;
69 struct ieee80211_mgmt_auth {
70 u16 auth_alg;
71 u16 auth_transaction;
72 u16 status_code;
73 /* possibly followed by Challenge text */
74 u8 variable[0];
75 } __packed;
77 struct ieee80211_mgmt_deauth {
78 u16 reason_code;
79 } __packed;
81 struct ieee80211_mgmt_assoc_req {
82 u16 capab_info;
83 u16 listen_interval;
84 /* followed by SSID and Supported rates */
85 u8 variable[0];
86 } __packed;
88 struct ieee80211_mgmt_assoc_resp {
89 u16 capab_info;
90 u16 status_code;
91 u16 aid;
92 /* followed by Supported rates */
93 u8 variable[0];
94 } __packed;
96 struct ieee80211_mgmt_reassoc_resp {
97 u16 capab_info;
98 u16 status_code;
99 u16 aid;
100 /* followed by Supported rates */
101 u8 variable[0];
102 } __packed;
104 struct ieee80211_mgmt_reassoc_req {
105 u16 capab_info;
106 u16 listen_interval;
107 u8 current_ap[6];
108 /* followed by SSID and Supported rates */
109 u8 variable[0];
110 } __packed;
112 struct ieee80211_mgmt_disassoc {
113 u16 reason_code;
114 } __packed;
116 struct ieee80211_mgmt_probe_req {
117 } __packed;
119 struct ieee80211_mgmt_beacon {
120 u64 timestamp;
121 u16 beacon_int;
122 u16 capab_info;
123 /* followed by some of SSID, Supported rates,
124 * FH Params, DS Params, CF Params, IBSS Params, TIM */
125 u8 variable[0];
126 } __packed;
128 struct ieee80211_mgmt_probe_resp {
129 u8 timestamp[8];
130 u16 beacon_int;
131 u16 capab_info;
132 /* followed by some of SSID, Supported rates,
133 * FH Params, DS Params, CF Params, IBSS Params, TIM */
134 u8 variable[0];
135 } __packed;
136 /* Management Frame end */
138 /* Control Frame start */
139 /* Note: Fields are encoded in little-endian! */
140 struct ieee80211_ctrl {
141 } __packed;
143 struct ieee80211_ctrl_rts {
144 u16 duration;
145 u8 da[6];
146 u8 sa[6];
147 } __packed;
149 struct ieee80211_ctrl_cts {
150 u16 duration;
151 u8 da[6];
152 } __packed;
154 struct ieee80211_ctrl_ack {
155 u16 duration;
156 u8 da[6];
157 } __packed;
159 struct ieee80211_ctrl_ps_poll {
160 u16 aid;
161 u8 bssid[6];
162 u8 sa[6];
163 } __packed;
165 struct ieee80211_ctrl_cf_end {
166 u16 duration;
167 u8 bssid[6];
168 u8 sa[6];
169 } __packed;
171 struct ieee80211_ctrl_cf_end_ack {
172 u16 duration;
173 u8 bssid[6];
174 u8 sa[6];
175 } __packed;
176 /* Control Frame end */
178 /* Data Frame start */
179 /* Note: Fields are encoded in little-endian! */
180 struct ieee80211_data {
181 } __packed;
183 /* TODO: Extend */
184 /* Data Frame end */
186 /* http://www.sss-mag.com/pdf/802_11tut.pdf
187 * http://www.scribd.com/doc/78443651/111/Management-Frames
188 * http://www.wildpackets.com/resources/compendium/wireless_lan/wlan_packets
189 * http://www.rhyshaden.com/wireless.htm
192 struct element_reserved {
193 u8 len;
194 } __packed;
196 struct element_ssid {
197 u8 len;
198 u8 SSID[0];
199 } __packed;
201 struct element_supp_rates {
202 u8 len;
203 u8 SSID[0];
204 } __packed;
206 struct element_fh_ps {
207 u8 len;
208 u16 dwell_time;
209 u8 hop_set;
210 u8 hop_pattern;
211 u8 hop_index;
212 } __packed;
214 struct element_dsss_ps {
215 u8 len;
216 u8 curr_ch;
217 } __packed;
219 struct element_cf_ps {
220 u8 len;
221 u8 cfp_cnt;
222 u8 cfp_period;
223 u16 cfp_max_dur;
224 u16 cfp_dur_rem;
225 } __packed;
227 struct element_tim {
228 u8 len;
229 u8 dtim_cnt;
230 u8 dtim_period;
231 u8 bmp_cntrl;
232 u8 part_virt_bmp[0];
233 } __packed;
235 struct element_ibss_ps {
236 u8 len;
237 u16 atim_win;
238 } __packed;
240 struct element_country_tripled {
241 u8 frst_ch;
242 u8 nr_ch;
243 u8 max_trans;
244 } __packed;
246 struct element_country {
247 u8 len;
248 #if defined(__LITTLE_ENDIAN_BITFIELD)
249 /* Correct order here ... */
250 u8 country_first;
251 u8 country_sec;
252 u8 country_third;
253 #elif defined(__BIG_ENDIAN_BITFIELD)
254 u8 country_third;
255 u8 country_sec;
256 u8 country_first;
257 #else
258 # error "Adjust your <asm/byteorder.h> defines"
259 #endif
260 /* triplet may repeat */
261 struct element_country_tripled tripled [0];
262 /* end triplet */
263 u8 pad[0];
264 } __packed;
266 struct element_hop_pp {
267 u8 len;
268 u8 prime_radix;
269 u8 nr_ch;
270 } __packed;
272 struct element_hop_pt {
273 u8 len;
274 u8 flag;
275 u8 nr_sets;
276 u8 modules;
277 u8 offs;
278 u8 rand_tabl[0];
279 } __packed;
281 struct element_erp {
282 u8 len;
283 u8 param;
284 } __packed;
286 struct element_ext_supp_rates {
287 u8 len;
288 u8 rates[0];
289 } __packed;
291 struct element_vend_spec {
292 u8 len;
293 u8 oui[0];
294 u8 specific[0];
295 } __packed;
297 static float data_rates(u8 id)
299 /* XXX Why not (id / 2.f)? */
300 switch (id) {
301 case 2: return 1.0f;
302 case 3: return 1.5f;
303 case 4: return 2.0f;
304 case 5: return 2.5f;
305 case 6: return 3.0f;
306 case 9: return 4.5f;
307 case 11: return 5.5f;
308 case 12: return 6.0f;
309 case 18: return 9.0f;
310 case 22: return 11.0f;
311 case 24: return 12.0f;
312 case 27: return 13.5f;
313 case 36: return 18.0f;
314 case 44: return 22.0f;
315 case 48: return 24.0f;
316 case 54: return 27.0f;
317 case 66: return 33.0f;
318 case 72: return 36.0f;
319 case 96: return 48.0f;
320 case 108: return 54.0f;
323 return 0.f;
326 static int8_t inf_reserved(struct pkt_buff *pkt, u8 *id)
328 int i;
329 u8 *data;
330 struct element_reserved *reserved;
332 reserved = (struct element_reserved *) pkt_pull(pkt, sizeof(*reserved));
333 if (reserved == NULL)
334 return 0;
336 tprintf("Reserved (%u, Len (%u)): ", *id, reserved->len);
338 data = pkt_pull(pkt, reserved->len);
339 if (data == NULL)
340 return 0;
342 tprintf("Data 0x");
343 for (i = 0; i < reserved->len; i++)
344 tprintf("%.2x", data[i]);
346 return 1;
349 static int8_t inf_ssid(struct pkt_buff *pkt, u8 *id)
351 int i;
352 struct element_ssid *ssid;
353 char *ssid_name;
355 ssid = (struct element_ssid *) pkt_pull(pkt, sizeof(*ssid));
356 if (ssid == NULL)
357 return 0;
359 tprintf(" SSID (%u, Len (%u)): ", *id, ssid->len);
361 if (ssid->len) {
362 ssid_name = (char *) pkt_pull(pkt, ssid->len);
363 if (ssid_name == NULL)
364 return 0;
366 for (i = 0; i < ssid->len; i++)
367 tprintf("%c",ssid_name[i]);
368 } else {
369 tprintf("Wildcard SSID");
372 return 1;
375 static int8_t inf_supp_rates(struct pkt_buff *pkt, u8 *id)
377 int i;
378 u8 *rates;
379 struct element_supp_rates *supp_rates;
381 supp_rates = (struct element_supp_rates *)
382 pkt_pull(pkt, sizeof(*supp_rates));
383 if (supp_rates == NULL)
384 return 0;
386 tprintf("Rates (%u, Len (%u)): ", *id, supp_rates->len);
388 if (supp_rates->len) {
389 rates = pkt_pull(pkt, supp_rates->len);
390 if (rates == NULL)
391 return 0;
393 for (i = 0; i < supp_rates->len; i++)
394 tprintf("%g ", (rates[i] & 0x80) ?
395 ((rates[i] & 0x3f) * 0.5) :
396 data_rates(rates[i]));
397 return 1;
400 return 0;
403 static int8_t inf_fh_ps(struct pkt_buff *pkt, u8 *id)
405 struct element_fh_ps *fh_ps;
407 fh_ps = (struct element_fh_ps *) pkt_pull(pkt, sizeof(*fh_ps));
408 if (fh_ps == NULL)
409 return 0;
411 tprintf("FH Param Set (%u, Len(%u)): ", *id, fh_ps->len);
412 tprintf("Dwell Time: %fs, ", le16_to_cpu(fh_ps->dwell_time) * TU);
413 tprintf("HopSet: %u, ", fh_ps->hop_set);
414 tprintf("HopPattern: %u, ", fh_ps->hop_pattern);
415 tprintf("HopIndex: %u", fh_ps->hop_index);
417 return 1;
420 static int8_t inf_dsss_ps(struct pkt_buff *pkt, u8 *id)
422 struct element_dsss_ps *dsss_ps;
424 dsss_ps = (struct element_dsss_ps *) pkt_pull(pkt, sizeof(*dsss_ps));
425 if (dsss_ps == NULL)
426 return 0;
428 tprintf("DSSS Param Set (%u, Len(%u)): ", *id, dsss_ps->len);
429 tprintf("Current Channel: %u", dsss_ps->curr_ch);
431 return 1;
434 static int8_t inf_cf_ps(struct pkt_buff *pkt, u8 *id)
436 struct element_cf_ps *cf_ps;
438 cf_ps = (struct element_cf_ps *) pkt_pull(pkt, sizeof(*cf_ps));
439 if (cf_ps == NULL)
440 return 0;
442 tprintf("CF Param Set (%u, Len(%u)): ", *id, cf_ps->len);
443 tprintf("CFP Count: %u, ", cf_ps->cfp_cnt);
444 tprintf("CFP Period: %u, ", cf_ps->cfp_period);
445 tprintf("CFP MaxDur: %fs, ", le16_to_cpu(cf_ps->cfp_max_dur) * TU);
446 tprintf("CFP DurRem: %fs", le16_to_cpu(cf_ps->cfp_dur_rem) * TU);
448 return 1;
451 static int8_t inf_tim(struct pkt_buff *pkt, u8 *id)
453 struct element_tim *tim;
455 tim = (struct element_tim *) pkt_pull(pkt, sizeof(*tim));
456 if (tim == NULL)
457 return 0;
459 tprintf("TIM (%u, Len(%u)): ", *id, tim->len);
460 tprintf("DTIM Count: %u, ", tim->dtim_cnt);
461 tprintf("DTIM Period: %u, ", tim->dtim_period);
462 tprintf("Bitmap Control: %u, ", tim->bmp_cntrl);
463 if ((tim->len - sizeof(*tim) + 1) > 0) {
464 u8 *bmp = pkt_pull(pkt, (tim->len - sizeof(*tim) + 1));
465 if (bmp == NULL)
466 return 0;
468 tprintf("Partial Virtual Bitmap: 0x");
469 for(u8 i=0; i < (tim->len - sizeof(*tim) + 1); i++)
470 tprintf("%.2x ", bmp[i]);
473 return 1;
476 static int8_t inf_ibss_ps(struct pkt_buff *pkt, u8 *id)
478 struct element_ibss_ps *ibss_ps;
480 ibss_ps = (struct element_ibss_ps *) pkt_pull(pkt, sizeof(*ibss_ps));
481 if (ibss_ps == NULL)
482 return 0;
484 tprintf("IBSS Param Set (%u, Len(%u)): ", *id, ibss_ps->len);
485 tprintf("ATIM Window: %fs", le16_to_cpu(ibss_ps->atim_win) * TU);
487 return 1;
490 static int8_t inf_country(struct pkt_buff *pkt, u8 *id)
492 int i;
493 u8 *pad;
494 struct element_country *country;
496 country = (struct element_country *) pkt_pull(pkt, sizeof(*country));
497 if (country == NULL)
498 return 0;
500 tprintf("Country (%u, Len(%u)): ", *id, country->len);
501 tprintf("Country String: %c%c%c", country->country_first,
502 country->country_sec, country->country_third);
504 for (i = 0; i < (country->len - 3); i += 3) {
505 struct element_country_tripled *country_tripled;
507 country_tripled = (struct element_country_tripled *)
508 pkt_pull(pkt, sizeof(*country_tripled));
509 if (country_tripled == NULL)
510 return 0;
512 if(country_tripled->frst_ch >= 201) {
513 tprintf("Oper Ext ID: %u, ", country_tripled->frst_ch);
514 tprintf("Operating Class: %u, ", country_tripled->nr_ch);
515 tprintf("Coverage Class: %u", country_tripled->max_trans);
516 } else {
517 tprintf("First Ch Nr: %u, ", country_tripled->frst_ch);
518 tprintf("Nr of Ch: %u, ", country_tripled->nr_ch);
519 tprintf("Max Transmit Pwr Lvl: %u", country_tripled->max_trans);
523 if(country->len % 2) {
524 pad = pkt_pull(pkt, 1);
525 if (pad == NULL)
526 return 0;
528 tprintf(", Pad: 0x%x", *pad);
531 return 1;
534 static int8_t inf_hop_pp(struct pkt_buff *pkt, u8 *id)
536 struct element_hop_pp *hop_pp;
538 hop_pp = (struct element_hop_pp *) pkt_pull(pkt, sizeof(*hop_pp));
539 if (hop_pp == NULL)
540 return 0;
542 tprintf("Hopping Pattern Param (%u, Len(%u)): ", *id, hop_pp->len);
543 tprintf("Nr of Ch: %u", hop_pp->nr_ch);
545 return 1;
548 static int8_t inf_hop_pt(struct pkt_buff *pkt, u8 *id)
550 int i;
551 u8 *rand_tabl;
552 struct element_hop_pt *hop_pt;
554 hop_pt = (struct element_hop_pt *) pkt_pull(pkt, sizeof(*hop_pt));
555 if (hop_pt == NULL)
556 return 0;
558 tprintf("Hopping Pattern Table (%u, Len(%u)): ", *id, hop_pt->len);
559 tprintf("Flag: %u, ", hop_pt->flag);
560 tprintf("Nr of Sets: %u, ", hop_pt->nr_sets);
561 tprintf("Modules: %u, ", hop_pt->modules);
562 tprintf("Offs: %u", hop_pt->offs);
564 if ((hop_pt->len - sizeof(*hop_pt) + 1) > 0) {
565 rand_tabl = pkt_pull(pkt, (hop_pt->len - sizeof(*hop_pt) + 1));
566 if (rand_tabl == NULL)
567 return 0;
569 tprintf(", Rand table: 0x");
570 for (i = 0; i < (hop_pt->len - sizeof(*hop_pt) + 1); i++)
571 tprintf("%.2x ", rand_tabl[i]);
574 return 1;
577 static int8_t inf_req(struct pkt_buff *pkt, u8 *id)
579 return 1;
582 static int8_t inf_bss_load(struct pkt_buff *pkt, u8 *id)
584 return 1;
587 static int8_t inf_edca_ps(struct pkt_buff *pkt, u8 *id)
589 return 1;
592 static int8_t inf_tspec(struct pkt_buff *pkt, u8 *id)
594 return 1;
597 static int8_t inf_tclas(struct pkt_buff *pkt, u8 *id)
599 return 1;
602 static int8_t inf_sched(struct pkt_buff *pkt, u8 *id)
604 return 1;
607 static int8_t inf_chall_txt(struct pkt_buff *pkt, u8 *id)
609 return 1;
612 static int8_t inf_pwr_constr(struct pkt_buff *pkt, u8 *id)
614 return 1;
617 static int8_t inf_pwr_cap(struct pkt_buff *pkt, u8 *id)
619 return 1;
622 static int8_t inf_tpc_req(struct pkt_buff *pkt, u8 *id)
624 return 1;
627 static int8_t inf_tpc_rep(struct pkt_buff *pkt, u8 *id)
629 return 1;
632 static int8_t inf_supp_ch(struct pkt_buff *pkt, u8 *id)
634 return 1;
637 static int8_t inf_ch_sw_ann(struct pkt_buff *pkt, u8 *id)
639 return 1;
642 static int8_t inf_meas_req(struct pkt_buff *pkt, u8 *id)
644 return 1;
647 static int8_t inf_meas_rep(struct pkt_buff *pkt, u8 *id)
649 return 1;
652 static int8_t inf_quiet(struct pkt_buff *pkt, u8 *id)
654 return 1;
657 static int8_t inf_ibss_dfs(struct pkt_buff *pkt, u8 *id)
659 return 1;
662 static int8_t inf_erp(struct pkt_buff *pkt, u8 *id)
664 struct element_erp *erp;
666 erp = (struct element_erp *) pkt_pull(pkt, sizeof(*erp));
667 if (erp == NULL)
668 return 0;
670 tprintf("ERP (%u, Len(%u)): ", *id, erp->len);
671 tprintf("Non ERP Present (%u), ", erp->param & 0x1);
672 tprintf("Use Protection (%u), ", (erp->param >> 1) & 0x1);
673 tprintf("Barker Preamble Mode (%u), ", (erp->param >> 2) & 0x1);
674 tprintf("Reserved (0x%.5x)", erp->param >> 3);
676 return 1;
679 static int8_t inf_ts_del(struct pkt_buff *pkt, u8 *id)
681 return 1;
684 static int8_t inf_tclas_proc(struct pkt_buff *pkt, u8 *id)
686 return 1;
689 static int8_t inf_ht_cap(struct pkt_buff *pkt, u8 *id)
691 return 1;
694 static int8_t inf_qos_cap(struct pkt_buff *pkt, u8 *id)
696 return 1;
699 static int8_t inf_rsn(struct pkt_buff *pkt, u8 *id)
701 return 1;
704 static int8_t inf_ext_supp_rates(struct pkt_buff *pkt, u8 *id)
706 int i;
707 u8 *rates;
708 struct element_ext_supp_rates *ext_supp_rates;
710 ext_supp_rates = (struct element_ext_supp_rates *)
711 pkt_pull(pkt, sizeof(*ext_supp_rates));
712 if (ext_supp_rates == NULL)
713 return 0;
715 tprintf("Ext Support Rates (%u, Len(%u)): ", *id, ext_supp_rates->len);
717 if (ext_supp_rates->len) {
718 rates = pkt_pull(pkt, ext_supp_rates->len);
719 if (rates == NULL)
720 return 0;
722 for (i = 0; i < ext_supp_rates->len; i++)
723 tprintf("%g ", (rates[i] & 0x80) ?
724 ((rates[i] & 0x3f) * 0.5) :
725 data_rates(rates[i]));
726 return 1;
729 return 0;
732 static int8_t inf_ap_ch_exp(struct pkt_buff *pkt, u8 *id) {
733 return 1;
736 static int8_t inf_neighb_rep(struct pkt_buff *pkt, u8 *id) {
737 return 1;
740 static int8_t inf_rcpi(struct pkt_buff *pkt, u8 *id) {
741 return 1;
744 static int8_t inf_mde(struct pkt_buff *pkt, u8 *id) {
745 return 1;
748 static int8_t inf_fte(struct pkt_buff *pkt, u8 *id) {
749 return 1;
752 static int8_t inf_time_out_int(struct pkt_buff *pkt, u8 *id) {
753 return 1;
756 static int8_t inf_rde(struct pkt_buff *pkt, u8 *id) {
757 return 1;
760 static int8_t inf_dse_reg_loc(struct pkt_buff *pkt, u8 *id) {
761 return 1;
764 static int8_t inf_supp_op_class(struct pkt_buff *pkt, u8 *id) {
765 return 1;
768 static int8_t inf_ext_ch_sw_ann(struct pkt_buff *pkt, u8 *id) {
769 return 1;
772 static int8_t inf_ht_op(struct pkt_buff *pkt, u8 *id) {
773 return 1;
776 static int8_t inf_sec_ch_offs(struct pkt_buff *pkt, u8 *id) {
777 return 1;
780 static int8_t inf_bss_avg_acc_del(struct pkt_buff *pkt, u8 *id) {
781 return 1;
784 static int8_t inf_ant(struct pkt_buff *pkt, u8 *id) {
785 return 1;
788 static int8_t inf_rsni(struct pkt_buff *pkt, u8 *id) {
789 return 1;
792 static int8_t inf_meas_pilot_trans(struct pkt_buff *pkt, u8 *id) {
793 return 1;
796 static int8_t inf_bss_avl_adm_cap(struct pkt_buff *pkt, u8 *id) {
797 return 1;
800 static int8_t inf_bss_ac_acc_del(struct pkt_buff *pkt, u8 *id) {
801 return 1;
804 static int8_t inf_time_adv(struct pkt_buff *pkt, u8 *id) {
805 return 1;
808 static int8_t inf_rm_ena_cap(struct pkt_buff *pkt, u8 *id) {
809 return 1;
812 static int8_t inf_mult_bssid(struct pkt_buff *pkt, u8 *id) {
813 return 1;
816 static int8_t inf_20_40_bss_coex(struct pkt_buff *pkt, u8 *id) {
817 return 1;
820 static int8_t inf_20_40_bss_int_ch_rep(struct pkt_buff *pkt, u8 *id) {
821 return 1;
824 static int8_t inf_overl_bss_scan_para(struct pkt_buff *pkt, u8 *id) {
825 return 1;
828 static int8_t inf_ric_desc(struct pkt_buff *pkt, u8 *id) {
829 return 1;
832 static int8_t inf_mgmt_mic(struct pkt_buff *pkt, u8 *id) {
833 return 1;
836 static int8_t inf_ev_req(struct pkt_buff *pkt, u8 *id) {
837 return 1;
840 static int8_t inf_ev_rep(struct pkt_buff *pkt, u8 *id) {
841 return 1;
844 static int8_t inf_diagn_req(struct pkt_buff *pkt, u8 *id) {
845 return 1;
848 static int8_t inf_diagn_rep(struct pkt_buff *pkt, u8 *id) {
849 return 1;
852 static int8_t inf_loc_para(struct pkt_buff *pkt, u8 *id) {
853 return 1;
856 static int8_t inf_nontr_bssid_cap(struct pkt_buff *pkt, u8 *id) {
857 return 1;
860 static int8_t inf_ssid_list(struct pkt_buff *pkt, u8 *id) {
861 return 1;
864 static int8_t inf_mult_bssid_index(struct pkt_buff *pkt, u8 *id) {
865 return 1;
868 static int8_t inf_fms_desc(struct pkt_buff *pkt, u8 *id) {
869 return 1;
872 static int8_t inf_fms_req(struct pkt_buff *pkt, u8 *id) {
873 return 1;
876 static int8_t inf_fms_resp(struct pkt_buff *pkt, u8 *id) {
877 return 1;
880 static int8_t inf_qos_tfc_cap(struct pkt_buff *pkt, u8 *id) {
881 return 1;
884 static int8_t inf_bss_max_idle_per(struct pkt_buff *pkt, u8 *id) {
885 return 1;
888 static int8_t inf_tfs_req(struct pkt_buff *pkt, u8 *id) {
889 return 1;
892 static int8_t inf_tfs_resp(struct pkt_buff *pkt, u8 *id) {
893 return 1;
896 static int8_t inf_wnm_sleep_mod(struct pkt_buff *pkt, u8 *id) {
897 return 1;
900 static int8_t inf_tim_bcst_req(struct pkt_buff *pkt, u8 *id) {
901 return 1;
904 static int8_t inf_tim_bcst_resp(struct pkt_buff *pkt, u8 *id) {
905 return 1;
908 static int8_t inf_coll_interf_rep(struct pkt_buff *pkt, u8 *id) {
909 return 1;
912 static int8_t inf_ch_usage(struct pkt_buff *pkt, u8 *id) {
913 return 1;
916 static int8_t inf_time_zone(struct pkt_buff *pkt, u8 *id) {
917 return 1;
920 static int8_t inf_dms_req(struct pkt_buff *pkt, u8 *id) {
921 return 1;
924 static int8_t inf_dms_resp(struct pkt_buff *pkt, u8 *id) {
925 return 1;
928 static int8_t inf_link_id(struct pkt_buff *pkt, u8 *id) {
929 return 1;
932 static int8_t inf_wakeup_sched(struct pkt_buff *pkt, u8 *id) {
933 return 1;
936 static int8_t inf_ch_sw_timing(struct pkt_buff *pkt, u8 *id) {
937 return 1;
940 static int8_t inf_pti_ctrl(struct pkt_buff *pkt, u8 *id) {
941 return 1;
944 static int8_t inf_tpu_buff_status(struct pkt_buff *pkt, u8 *id) {
945 return 1;
948 static int8_t inf_interw(struct pkt_buff *pkt, u8 *id) {
949 return 1;
952 static int8_t inf_adv_proto(struct pkt_buff *pkt, u8 *id) {
953 return 1;
956 static int8_t inf_exp_bandw_req(struct pkt_buff *pkt, u8 *id) {
957 return 1;
960 static int8_t inf_qos_map_set(struct pkt_buff *pkt, u8 *id) {
961 return 1;
964 static int8_t inf_roam_cons(struct pkt_buff *pkt, u8 *id) {
965 return 1;
968 static int8_t inf_emer_alert_id(struct pkt_buff *pkt, u8 *id) {
969 return 1;
972 static int8_t inf_mesh_conf(struct pkt_buff *pkt, u8 *id) {
973 return 1;
976 static int8_t inf_mesh_id(struct pkt_buff *pkt, u8 *id) {
977 return 1;
980 static int8_t inf_mesh_link_metr_rep(struct pkt_buff *pkt, u8 *id) {
981 return 1;
984 static int8_t inf_cong_notif(struct pkt_buff *pkt, u8 *id) {
985 return 1;
988 static int8_t inf_mesh_peer_mgmt(struct pkt_buff *pkt, u8 *id) {
989 return 1;
992 static int8_t inf_mesh_ch_sw_para(struct pkt_buff *pkt, u8 *id) {
993 return 1;
996 static int8_t inf_mesh_awake_win(struct pkt_buff *pkt, u8 *id) {
997 return 1;
1000 static int8_t inf_beacon_timing(struct pkt_buff *pkt, u8 *id) {
1001 return 1;
1004 static int8_t inf_mccaop_setup_req(struct pkt_buff *pkt, u8 *id) {
1005 return 1;
1008 static int8_t inf_mccaop_setup_rep(struct pkt_buff *pkt, u8 *id) {
1009 return 1;
1012 static int8_t inf_mccaop_adv(struct pkt_buff *pkt, u8 *id) {
1013 return 1;
1016 static int8_t inf_mccaop_teardwn(struct pkt_buff *pkt, u8 *id) {
1017 return 1;
1020 static int8_t inf_gann(struct pkt_buff *pkt, u8 *id) {
1021 return 1;
1024 static int8_t inf_rann(struct pkt_buff *pkt, u8 *id) {
1025 return 1;
1028 static int8_t inf_ext_cap(struct pkt_buff *pkt, u8 *id) {
1029 return 1;
1032 static int8_t inf_preq(struct pkt_buff *pkt, u8 *id) {
1033 return 1;
1036 static int8_t inf_prep(struct pkt_buff *pkt, u8 *id) {
1037 return 1;
1040 static int8_t inf_perr(struct pkt_buff *pkt, u8 *id) {
1041 return 1;
1044 static int8_t inf_pxu(struct pkt_buff *pkt, u8 *id) {
1045 return 1;
1048 static int8_t inf_pxuc(struct pkt_buff *pkt, u8 *id) {
1049 return 1;
1052 static int8_t inf_auth_mesh_peer_exch(struct pkt_buff *pkt, u8 *id) {
1053 return 1;
1056 static int8_t inf_mic(struct pkt_buff *pkt, u8 *id) {
1057 return 1;
1060 static int8_t inf_dest_uri(struct pkt_buff *pkt, u8 *id) {
1061 return 1;
1064 static int8_t inf_u_apsd_coex(struct pkt_buff *pkt, u8 *id) {
1065 return 1;
1068 static int8_t inf_mccaop_adv_overv(struct pkt_buff *pkt, u8 *id) {
1069 return 1;
1072 static int8_t inf_vend_spec(struct pkt_buff *pkt, u8 *id)
1074 int i;
1075 u8 *data;
1076 struct element_vend_spec *vend_spec;
1078 vend_spec = (struct element_vend_spec *)
1079 pkt_pull(pkt, sizeof(*vend_spec));
1080 if (vend_spec == NULL)
1081 return 0;
1083 tprintf("Vendor Specific (%u, Len (%u)): ", *id, vend_spec->len);
1085 data = pkt_pull(pkt, vend_spec->len);
1086 if (data == NULL)
1087 return 0;
1089 tprintf("Data 0x");
1090 for (i = 0; i < vend_spec->len; i++)
1091 tprintf("%.2x", data[i]);
1093 return 1;
1096 static int8_t inf_elements(struct pkt_buff *pkt)
1098 u8 *id = pkt_pull(pkt, 1);
1099 if (id == NULL)
1100 return 0;
1102 switch (*id) {
1103 case 0: return inf_ssid(pkt, id);
1104 case 1: return inf_supp_rates(pkt, id);
1105 case 2: return inf_fh_ps(pkt, id);
1106 case 3: return inf_dsss_ps(pkt, id);
1107 case 4: return inf_cf_ps(pkt, id);
1108 case 5: return inf_tim(pkt, id);
1109 case 6: return inf_ibss_ps(pkt, id);
1110 case 7: return inf_country(pkt, id);
1111 case 8: return inf_hop_pp(pkt, id);
1112 case 9: return inf_hop_pt(pkt, id);
1113 case 10: return inf_req(pkt, id);
1114 case 11: return inf_bss_load(pkt, id);
1115 case 12: return inf_edca_ps(pkt, id);
1116 case 13: return inf_tspec(pkt, id);
1117 case 14: return inf_tclas(pkt, id);
1118 case 15: return inf_sched(pkt, id);
1119 case 16: return inf_chall_txt(pkt, id);
1120 case 17 ... 31: return inf_reserved(pkt, id);
1121 case 32: return inf_pwr_constr(pkt, id);
1122 case 33: return inf_pwr_cap(pkt, id);
1123 case 34: return inf_tpc_req(pkt, id);
1124 case 35: return inf_tpc_rep(pkt, id);
1125 case 36: return inf_supp_ch(pkt, id);
1126 case 37: return inf_ch_sw_ann(pkt, id);
1127 case 38: return inf_meas_req(pkt, id);
1128 case 39: return inf_meas_rep(pkt, id);
1129 case 40: return inf_quiet(pkt, id);
1130 case 41: return inf_ibss_dfs(pkt, id);
1131 case 42: return inf_erp(pkt, id);
1132 case 43: return inf_ts_del(pkt, id);
1133 case 44: return inf_tclas_proc(pkt, id);
1134 case 45: return inf_ht_cap(pkt, id);
1135 case 46: return inf_qos_cap(pkt, id);
1136 case 47: return inf_reserved(pkt, id);
1137 case 48: return inf_rsn(pkt, id);
1138 case 49: return inf_rsn(pkt, id);
1139 case 50: return inf_ext_supp_rates(pkt, id);
1140 case 51: return inf_ap_ch_exp(pkt, id);
1141 case 52: return inf_neighb_rep(pkt, id);
1142 case 53: return inf_rcpi(pkt, id);
1143 case 54: return inf_mde(pkt, id);
1144 case 55: return inf_fte(pkt, id);
1145 case 56: return inf_time_out_int(pkt, id);
1146 case 57: return inf_rde(pkt, id);
1147 case 58: return inf_dse_reg_loc(pkt, id);
1148 case 59: return inf_supp_op_class(pkt, id);
1149 case 60: return inf_ext_ch_sw_ann(pkt, id);
1150 case 61: return inf_ht_op(pkt, id);
1151 case 62: return inf_sec_ch_offs(pkt, id);
1152 case 63: return inf_bss_avg_acc_del(pkt, id);
1153 case 64: return inf_ant(pkt, id);
1154 case 65: return inf_rsni(pkt, id);
1155 case 66: return inf_meas_pilot_trans(pkt, id);
1156 case 67: return inf_bss_avl_adm_cap(pkt, id);
1157 case 68: return inf_bss_ac_acc_del(pkt, id);
1158 case 69: return inf_time_adv(pkt, id);
1159 case 70: return inf_rm_ena_cap(pkt, id);
1160 case 71: return inf_mult_bssid(pkt, id);
1161 case 72: return inf_20_40_bss_coex(pkt, id);
1162 case 73: return inf_20_40_bss_int_ch_rep(pkt, id);
1163 case 74: return inf_overl_bss_scan_para(pkt, id);
1164 case 75: return inf_ric_desc(pkt, id);
1165 case 76: return inf_mgmt_mic(pkt, id);
1166 case 78: return inf_ev_req(pkt, id);
1167 case 79: return inf_ev_rep(pkt, id);
1168 case 80: return inf_diagn_req(pkt, id);
1169 case 81: return inf_diagn_rep(pkt, id);
1170 case 82: return inf_loc_para(pkt, id);
1171 case 83: return inf_nontr_bssid_cap(pkt, id);
1172 case 84: return inf_ssid_list(pkt, id);
1173 case 85: return inf_mult_bssid_index(pkt, id);
1174 case 86: return inf_fms_desc(pkt, id);
1175 case 87: return inf_fms_req(pkt, id);
1176 case 88: return inf_fms_resp(pkt, id);
1177 case 89: return inf_qos_tfc_cap(pkt, id);
1178 case 90: return inf_bss_max_idle_per(pkt, id);
1179 case 91: return inf_tfs_req(pkt, id);
1180 case 92: return inf_tfs_resp(pkt, id);
1181 case 93: return inf_wnm_sleep_mod(pkt, id);
1182 case 94: return inf_tim_bcst_req(pkt, id);
1183 case 95: return inf_tim_bcst_resp(pkt, id);
1184 case 96: return inf_coll_interf_rep(pkt, id);
1185 case 97: return inf_ch_usage(pkt, id);
1186 case 98: return inf_time_zone(pkt, id);
1187 case 99: return inf_dms_req(pkt, id);
1188 case 100: return inf_dms_resp(pkt, id);
1189 case 101: return inf_link_id(pkt, id);
1190 case 102: return inf_wakeup_sched(pkt, id);
1191 case 104: return inf_ch_sw_timing(pkt, id);
1192 case 105: return inf_pti_ctrl(pkt, id);
1193 case 106: return inf_tpu_buff_status(pkt, id);
1194 case 107: return inf_interw(pkt, id);
1195 case 108: return inf_adv_proto(pkt, id);
1196 case 109: return inf_exp_bandw_req(pkt, id);
1197 case 110: return inf_qos_map_set(pkt, id);
1198 case 111: return inf_roam_cons(pkt, id);
1199 case 112: return inf_emer_alert_id(pkt, id);
1200 case 113: return inf_mesh_conf(pkt, id);
1201 case 114: return inf_mesh_id(pkt, id);
1202 case 115: return inf_mesh_link_metr_rep(pkt, id);
1203 case 116: return inf_cong_notif(pkt, id);
1204 case 117: return inf_mesh_peer_mgmt(pkt, id);
1205 case 118: return inf_mesh_ch_sw_para(pkt, id);
1206 case 119: return inf_mesh_awake_win(pkt, id);
1207 case 120: return inf_beacon_timing(pkt, id);
1208 case 121: return inf_mccaop_setup_req(pkt, id);
1209 case 122: return inf_mccaop_setup_rep(pkt, id);
1210 case 123: return inf_mccaop_adv(pkt, id);
1211 case 124: return inf_mccaop_teardwn(pkt, id);
1212 case 125: return inf_gann(pkt, id);
1213 case 126: return inf_rann(pkt, id);
1214 case 127: return inf_ext_cap(pkt, id);
1215 case 128: return inf_reserved(pkt, id);
1216 case 129: return inf_reserved(pkt, id);
1217 case 130: return inf_preq(pkt, id);
1218 case 131: return inf_prep(pkt, id);
1219 case 132: return inf_perr(pkt, id);
1220 case 133: return inf_reserved(pkt, id);
1221 case 134: return inf_reserved(pkt, id);
1222 case 135: return inf_reserved(pkt, id);
1223 case 136: return inf_reserved(pkt, id);
1224 case 137: return inf_pxu(pkt, id);
1225 case 138: return inf_pxuc(pkt, id);
1226 case 139: return inf_auth_mesh_peer_exch(pkt, id);
1227 case 140: return inf_mic(pkt, id);
1228 case 141: return inf_dest_uri(pkt, id);
1229 case 142: return inf_u_apsd_coex(pkt, id);
1230 case 143 ... 173: return inf_reserved(pkt, id);
1231 case 174: return inf_mccaop_adv_overv(pkt, id);
1232 case 221: return inf_vend_spec(pkt, id);
1235 return 0;
1238 #define ESS 0b0000000000000001
1239 #define IBSS 0b0000000000000010
1240 #define CF_Pollable 0b0000000000000100
1241 #define CF_Poll_Req 0b0000000000001000
1242 #define Privacy 0b0000000000010000
1243 #define Short_Pre 0b0000000000100000
1244 #define PBCC 0b0000000001000000
1245 #define Ch_Agility 0b0000000010000000
1246 #define Spec_Mgmt 0b0000000100000000
1247 #define QoS 0b0000001000000000
1248 #define Short_Slot_t 0b0000010000000000
1249 #define APSD 0b0000100000000000
1250 #define Radio_Meas 0b0001000000000000
1251 #define DSSS_OFDM 0b0010000000000000
1252 #define Del_Block_ACK 0b0100000000000000
1253 #define Imm_Block_ACK 0b1000000000000000
1255 static int8_t cap_field(u16 cap_inf)
1257 if (ESS & cap_inf)
1258 tprintf(" ESS;");
1259 if (IBSS & cap_inf)
1260 tprintf(" IBSS;");
1261 if (CF_Pollable & cap_inf)
1262 tprintf(" CF Pollable;");
1263 if (CF_Poll_Req & cap_inf)
1264 tprintf(" CF-Poll Request;");
1265 if (Privacy & cap_inf)
1266 tprintf(" Privacy;");
1267 if (Short_Pre & cap_inf)
1268 tprintf(" Short Preamble;");
1269 if (PBCC & cap_inf)
1270 tprintf(" PBCC;");
1271 if (Ch_Agility & cap_inf)
1272 tprintf(" Channel Agility;");
1273 if (Spec_Mgmt & cap_inf)
1274 tprintf(" Spectrum Management;");
1275 if (QoS & cap_inf)
1276 tprintf(" QoS;");
1277 if (Short_Slot_t & cap_inf)
1278 tprintf(" Short Slot Time;");
1279 if (APSD & cap_inf)
1280 tprintf(" APSD;");
1281 if (Radio_Meas & cap_inf)
1282 tprintf(" Radio Measurement;");
1283 if (DSSS_OFDM & cap_inf)
1284 tprintf(" DSSS-OFDM;");
1285 if (Del_Block_ACK & cap_inf)
1286 tprintf(" Delayed Block Ack;");
1287 if (Imm_Block_ACK & cap_inf)
1288 tprintf(" Immediate Block Ack;");
1290 return 1;
1293 /* Management Dissectors */
1294 static int8_t assoc_req(struct pkt_buff *pkt) {
1295 return 0;
1298 static int8_t assoc_resp(struct pkt_buff *pkt) {
1299 return 0;
1302 static int8_t reassoc_req(struct pkt_buff *pkt) {
1303 return 0;
1306 static int8_t reassoc_resp(struct pkt_buff *pkt) {
1307 return 0;
1310 static int8_t probe_req(struct pkt_buff *pkt) {
1311 return 0;
1314 static int8_t probe_resp(struct pkt_buff *pkt) {
1315 return 0;
1318 static int8_t beacon(struct pkt_buff *pkt)
1320 struct ieee80211_mgmt_beacon *beacon;
1322 beacon = (struct ieee80211_mgmt_beacon *)
1323 pkt_pull(pkt, sizeof(*beacon));
1324 if (beacon == NULL)
1325 return 0;
1327 tprintf("Timestamp 0x%.16lx, ", le64_to_cpu(beacon->timestamp));
1328 tprintf("Beacon Interval (%fs), ", le16_to_cpu(beacon->beacon_int)*TU);
1329 tprintf("Capabilities (0x%x <->", le16_to_cpu(beacon->capab_info));
1330 cap_field(le16_to_cpu(beacon->capab_info));
1331 tprintf(")");
1333 if(pkt_len(pkt)) {
1334 tprintf("\n\tParameters:");
1335 while (inf_elements(pkt)) {
1336 tprintf("\n\t");
1340 if(pkt_len(pkt))
1341 return 0;
1342 return 1;
1345 static int8_t atim(struct pkt_buff *pkt) {
1346 return 0;
1349 static int8_t disassoc(struct pkt_buff *pkt) {
1350 return 0;
1353 static int8_t auth(struct pkt_buff *pkt) {
1354 return 0;
1357 static int8_t deauth(struct pkt_buff *pkt) {
1358 return 0;
1360 /* End Management Dissectors */
1362 /* Control Dissectors */
1363 static int8_t ps_poll(struct pkt_buff *pkt) {
1364 return 0;
1367 static int8_t rts(struct pkt_buff *pkt) {
1368 return 0;
1371 static int8_t cts(struct pkt_buff *pkt) {
1372 return 0;
1375 static int8_t ack(struct pkt_buff *pkt) {
1376 return 0;
1379 static int8_t cf_end(struct pkt_buff *pkt) {
1380 return 0;
1383 static int8_t cf_end_ack(struct pkt_buff *pkt) {
1384 return 0;
1386 /* End Control Dissectors */
1388 /* Data Dissectors */
1389 static int8_t data(struct pkt_buff *pkt) {
1390 return 0;
1393 static int8_t data_cf_ack(struct pkt_buff *pkt) {
1394 return 0;
1397 static int8_t data_cf_poll(struct pkt_buff *pkt) {
1398 return 0;
1401 static int8_t data_cf_ack_poll(struct pkt_buff *pkt) {
1402 return 0;
1405 static int8_t null(struct pkt_buff *pkt) {
1406 return 0;
1409 static int8_t cf_ack(struct pkt_buff *pkt) {
1410 return 0;
1413 static int8_t cf_poll(struct pkt_buff *pkt) {
1414 return 0;
1417 static int8_t cf_ack_poll(struct pkt_buff *pkt) {
1418 return 0;
1420 /* End Data Dissectors */
1422 static const char *mgt_sub(u8 subtype, struct pkt_buff *pkt,
1423 int8_t (**get_content)(struct pkt_buff *pkt))
1425 u16 seq_ctrl;
1426 struct ieee80211_mgmt *mgmt;
1427 const char *dst, *src, *bssid;
1429 mgmt = (struct ieee80211_mgmt *) pkt_pull(pkt, sizeof(*mgmt));
1430 if (mgmt == NULL)
1431 return 0;
1433 dst = lookup_vendor((mgmt->da[0] << 16) |
1434 (mgmt->da[1] << 8) |
1435 mgmt->da[2]);
1436 src = lookup_vendor((mgmt->sa[0] << 16) |
1437 (mgmt->sa[1] << 8) |
1438 mgmt->sa[2]);
1440 bssid = lookup_vendor((mgmt->bssid[0] << 16) |
1441 (mgmt->bssid[1] << 8) |
1442 mgmt->bssid[2]);
1443 seq_ctrl = le16_to_cpu(mgmt->seq_ctrl);
1445 tprintf("Duration (%u),", le16_to_cpu(mgmt->duration));
1446 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
1447 mgmt->da[0], mgmt->da[1], mgmt->da[2],
1448 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
1449 if (dst) {
1450 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst,
1451 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
1454 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
1455 mgmt->sa[0], mgmt->sa[1], mgmt->sa[2],
1456 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
1457 if (src) {
1458 tprintf("=> (%s:%.2x:%.2x:%.2x)", src,
1459 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
1462 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
1463 mgmt->bssid[0], mgmt->bssid[1], mgmt->bssid[2],
1464 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
1465 if(bssid) {
1466 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid,
1467 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
1470 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ",
1471 seq_ctrl & 0xf, seq_ctrl >> 4);
1473 switch (subtype) {
1474 case 0b0000:
1475 *get_content = assoc_req;
1476 return "Association Request";
1477 case 0b0001:
1478 *get_content = assoc_resp;
1479 return "Association Response";
1480 case 0b0010:
1481 *get_content = reassoc_req;
1482 return "Reassociation Request";
1483 case 0b0011:
1484 *get_content = reassoc_resp;
1485 return "Reassociation Response";
1486 case 0b0100:
1487 *get_content = probe_req;
1488 return "Probe Request";
1489 case 0b0101:
1490 *get_content = probe_resp;
1491 return "Probe Response";
1492 case 0b1000:
1493 *get_content = beacon;
1494 return "Beacon";
1495 case 0b1001:
1496 *get_content = atim;
1497 return "ATIM";
1498 case 0b1010:
1499 *get_content = disassoc;
1500 return "Disassociation";
1501 case 0b1011:
1502 *get_content = auth;
1503 return "Authentication";
1504 case 0b1100:
1505 *get_content = deauth;
1506 return "Deauthentication";
1507 case 0b0110 ... 0b0111:
1508 case 0b1101 ... 0b1111:
1509 *get_content = NULL;
1510 return "Reserved";
1511 default:
1512 *get_content = NULL;
1513 return "Management SubType unknown";
1517 static const char *ctrl_sub(u8 subtype, struct pkt_buff *pkt,
1518 int8_t (**get_content)(struct pkt_buff *pkt))
1520 switch (subtype) {
1521 case 0b1010:
1522 *get_content = ps_poll;
1523 return "PS-Poll";
1524 case 0b1011:
1525 *get_content = rts;
1526 return "RTS";
1527 case 0b1100:
1528 *get_content = cts;
1529 return "CTS";
1530 case 0b1101:
1531 *get_content = ack;
1532 return "ACK";
1533 case 0b1110:
1534 *get_content = cf_end;
1535 return "CF End";
1536 case 0b1111:
1537 *get_content = cf_end_ack;
1538 return "CF End + CF-ACK";
1539 case 0b0000 ... 0b1001:
1540 *get_content = NULL;
1541 return "Reserved";
1542 default:
1543 return "Control SubType unkown";
1547 static const char *data_sub(u8 subtype, struct pkt_buff *pkt,
1548 int8_t (**get_content)(struct pkt_buff *pkt))
1550 switch (subtype) {
1551 case 0b0000:
1552 *get_content = data;
1553 return "Data";
1554 case 0b0001:
1555 *get_content = data_cf_ack;
1556 return "Data + CF-ACK";
1557 case 0b0010:
1558 *get_content = data_cf_poll;
1559 return "Data + CF-Poll";
1560 case 0b0011:
1561 *get_content = data_cf_ack_poll;
1562 return "Data + CF-ACK + CF-Poll";
1563 case 0b0100:
1564 *get_content = null;
1565 return "Null";
1566 case 0b0101:
1567 *get_content = cf_ack;
1568 return "CF-ACK";
1569 case 0b0110:
1570 *get_content = cf_poll;
1571 return "CF-Poll";
1572 case 0b0111:
1573 *get_content = cf_ack_poll;
1574 return "CF-ACK + CF-Poll";
1575 case 0b1000 ... 0b1111:
1576 *get_content = NULL;
1577 return "Reserved";
1578 default:
1579 *get_content = NULL;
1580 return "Data SubType unkown";
1584 static const char *
1585 frame_control_type(u8 type, const char *(**get_subtype)(u8 subtype,
1586 struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)))
1588 switch (type) {
1589 case 0b00:
1590 *get_subtype = mgt_sub;
1591 return "Management";
1592 case 0b01:
1593 *get_subtype = ctrl_sub;
1594 return "Control";
1595 case 0b10:
1596 *get_subtype = data_sub;
1597 return "Data";
1598 case 0b11:
1599 *get_subtype = NULL;
1600 return "Reserved";
1601 default:
1602 *get_subtype = NULL;
1603 return "Control Type unkown";
1607 static void ieee80211(struct pkt_buff *pkt)
1609 int8_t (*get_content)(struct pkt_buff *pkt) = NULL;
1610 const char *(*get_subtype)(u8 subtype, struct pkt_buff *pkt,
1611 int8_t (**get_content)(struct pkt_buff *pkt)) = NULL;
1612 const char *subtype = NULL;
1613 struct ieee80211_frm_ctrl *frm_ctrl;
1615 frm_ctrl = (struct ieee80211_frm_ctrl *)
1616 pkt_pull(pkt, sizeof(*frm_ctrl));
1617 if (frm_ctrl == NULL)
1618 return;
1620 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
1621 le16_to_cpu(frm_ctrl->frame_control));
1623 tprintf(" [ Proto Version (%u), ", frm_ctrl->proto_version);
1624 tprintf("Type (%u, %s), ", frm_ctrl->type,
1625 frame_control_type(frm_ctrl->type, &get_subtype));
1626 if (get_subtype) {
1627 subtype = (*get_subtype)(frm_ctrl->subtype, pkt, &get_content);
1628 tprintf("Subtype (%u, %s)", frm_ctrl->subtype, subtype);
1629 } else {
1630 tprintf("\n%s%s%s", colorize_start_full(black, red),
1631 "No SubType Data available", colorize_end());
1634 tprintf("%s%s", frm_ctrl->to_ds ? ", Frame goes to DS" : "",
1635 frm_ctrl->from_ds ? ", Frame comes from DS" : "");
1636 tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : "");
1637 tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : "");
1638 tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : "");
1639 tprintf("%s", frm_ctrl->more_data ? ", More Data" : "");
1640 tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : "");
1641 tprintf("%s", frm_ctrl->order ? ", Order" : "");
1642 tprintf(" ]\n");
1644 if (get_content) {
1645 tprintf(" [ Subtype %s: ", subtype);
1646 if (!((*get_content) (pkt)))
1647 tprintf("\n%s%s%s", colorize_start_full(black, red),
1648 "Failed to dissect Subtype", colorize_end());
1649 tprintf(" ]");
1650 } else {
1651 tprintf("\n%s%s%s", colorize_start_full(black, red),
1652 "No SubType Data available", colorize_end());
1655 // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
1658 static void ieee80211_less(struct pkt_buff *pkt)
1660 tprintf("802.11 frame (more on todo)");
1663 struct protocol ieee80211_ops = {
1664 .key = 0,
1665 .print_full = ieee80211,
1666 .print_less = ieee80211_less,
1669 EXPORT_SYMBOL(ieee80211_ops);