netsniff-ng: Remove locally declared labels
[netsniff-ng.git] / proto_80211_mac_hdr.c
blob23f9c7a1afba0ecfd79d6d31286c6c73bfffeaf5
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012, 2013 Markus Amend <markus@netsniff-ng.org>
4 * Copyright 2012 Daniel Borkmann <daniel@netsniff-ng.org>
5 * Subject to the GPL, version 2.
6 */
8 /* TODO
9 * check all possible frame combinations for their behavior
10 * with respect to endianess (little / big)
13 #include <stdio.h>
14 #include <stdint.h>
15 #include <netinet/in.h> /* for ntohs() */
16 #include <asm/byteorder.h>
17 #include <arpa/inet.h> /* for inet_ntop() */
19 #include "proto.h"
20 #include "dissector_80211.h"
21 #include "built_in.h"
22 #include "pkt_buff.h"
23 #include "oui.h"
25 #define TU 0.001024
27 /* Note: Fields are encoded in little-endian! */
28 struct ieee80211_frm_ctrl {
29 union {
30 u16 frame_control;
31 struct {
32 #if defined(__LITTLE_ENDIAN_BITFIELD)
33 /* Correct order here ... */
34 __extension__ u16 proto_version:2,
35 type:2,
36 subtype:4,
37 to_ds:1,
38 from_ds:1,
39 more_frags:1,
40 retry:1,
41 power_mgmt:1,
42 more_data:1,
43 wep:1,
44 order:1;
45 #elif defined(__BIG_ENDIAN_BITFIELD)
46 __extension__ u16 subtype:4,
47 type:2,
48 proto_version:2,
49 order:1,
50 wep:1,
51 more_data:1,
52 power_mgmt:1,
53 retry:1,
54 more_frags:1,
55 from_ds:1,
56 to_ds:1;
57 #else
58 # error "Adjust your <asm/byteorder.h> defines"
59 #endif
62 } __packed;
64 /* Management Frame start */
65 /* Note: Fields are encoded in little-endian! */
66 struct ieee80211_mgmt {
67 u16 duration;
68 u8 da[6];
69 u8 sa[6];
70 u8 bssid[6];
71 u16 seq_ctrl;
72 } __packed;
74 struct ieee80211_mgmt_auth {
75 u16 auth_alg;
76 u16 auth_transaction;
77 u16 status_code;
78 /* possibly followed by Challenge text */
79 u8 variable[0];
80 } __packed;
82 struct ieee80211_mgmt_deauth {
83 u16 reason_code;
84 } __packed;
86 struct ieee80211_mgmt_assoc_req {
87 u16 capab_info;
88 u16 listen_interval;
89 /* followed by SSID and Supported rates */
90 u8 variable[0];
91 } __packed;
93 struct ieee80211_mgmt_assoc_resp {
94 u16 capab_info;
95 u16 status_code;
96 u16 aid;
97 /* followed by Supported rates */
98 u8 variable[0];
99 } __packed;
101 struct ieee80211_mgmt_reassoc_resp {
102 u16 capab_info;
103 u16 status_code;
104 u16 aid;
105 /* followed by Supported rates */
106 u8 variable[0];
107 } __packed;
109 struct ieee80211_mgmt_reassoc_req {
110 u16 capab_info;
111 u16 listen_interval;
112 u8 current_ap[6];
113 /* followed by SSID and Supported rates */
114 u8 variable[0];
115 } __packed;
117 struct ieee80211_mgmt_disassoc {
118 u16 reason_code;
119 } __packed;
121 struct ieee80211_mgmt_probe_req {
122 } __packed;
124 struct ieee80211_mgmt_beacon {
125 u64 timestamp;
126 u16 beacon_int;
127 u16 capab_info;
128 /* followed by some of SSID, Supported rates,
129 * FH Params, DS Params, CF Params, IBSS Params, TIM */
130 u8 variable[0];
131 } __packed;
133 struct ieee80211_mgmt_probe_resp {
134 u8 timestamp[8];
135 u16 beacon_int;
136 u16 capab_info;
137 /* followed by some of SSID, Supported rates,
138 * FH Params, DS Params, CF Params, IBSS Params, TIM */
139 u8 variable[0];
140 } __packed;
141 /* Management Frame end */
143 /* Control Frame start */
144 /* Note: Fields are encoded in little-endian! */
145 struct ieee80211_ctrl {
146 } __packed;
148 struct ieee80211_ctrl_rts {
149 u16 duration;
150 u8 da[6];
151 u8 sa[6];
152 } __packed;
154 struct ieee80211_ctrl_cts {
155 u16 duration;
156 u8 da[6];
157 } __packed;
159 struct ieee80211_ctrl_ack {
160 u16 duration;
161 u8 da[6];
162 } __packed;
164 struct ieee80211_ctrl_ps_poll {
165 u16 aid;
166 u8 bssid[6];
167 u8 sa[6];
168 } __packed;
170 struct ieee80211_ctrl_cf_end {
171 u16 duration;
172 u8 bssid[6];
173 u8 sa[6];
174 } __packed;
176 struct ieee80211_ctrl_cf_end_ack {
177 u16 duration;
178 u8 bssid[6];
179 u8 sa[6];
180 } __packed;
181 /* Control Frame end */
183 /* Data Frame start */
184 /* Note: Fields are encoded in little-endian! */
185 struct ieee80211_data {
186 } __packed;
188 /* TODO: Extend */
189 /* Data Frame end */
191 struct element_reserved {
192 u8 len;
193 } __packed;
195 struct element_ssid {
196 u8 len;
197 u8 SSID[0];
198 } __packed;
200 struct element_supp_rates {
201 u8 len;
202 u8 rates[0];
203 } __packed;
205 struct element_fh_ps {
206 u8 len;
207 u16 dwell_time;
208 u8 hop_set;
209 u8 hop_pattern;
210 u8 hop_index;
211 } __packed;
213 struct element_dsss_ps {
214 u8 len;
215 u8 curr_ch;
216 } __packed;
218 struct element_cf_ps {
219 u8 len;
220 u8 cfp_cnt;
221 u8 cfp_period;
222 u16 cfp_max_dur;
223 u16 cfp_dur_rem;
224 } __packed;
226 struct element_tim {
227 u8 len;
228 u8 dtim_cnt;
229 u8 dtim_period;
230 u8 bmp_cntrl;
231 u8 part_virt_bmp[0];
232 } __packed;
234 struct element_ibss_ps {
235 u8 len;
236 u16 atim_win;
237 } __packed;
239 struct element_country_tripled {
240 u8 frst_ch;
241 u8 nr_ch;
242 u8 max_trans;
243 } __packed;
245 struct element_country {
246 u8 len;
247 #if defined(__LITTLE_ENDIAN_BITFIELD)
248 /* Correct order here ... */
249 u8 country_first;
250 u8 country_sec;
251 u8 country_third;
252 #elif defined(__BIG_ENDIAN_BITFIELD)
253 u8 country_third;
254 u8 country_sec;
255 u8 country_first;
256 #else
257 # error "Adjust your <asm/byteorder.h> defines"
258 #endif
259 /* triplet may repeat */
260 struct element_country_tripled tripled [0];
261 /* end triplet */
262 u8 pad[0];
263 } __packed;
265 struct element_hop_pp {
266 u8 len;
267 u8 prime_radix;
268 u8 nr_ch;
269 } __packed;
271 struct element_hop_pt {
272 u8 len;
273 u8 flag;
274 u8 nr_sets;
275 u8 modules;
276 u8 offs;
277 u8 rand_tabl[0];
278 } __packed;
280 struct element_req {
281 u8 len;
282 u8 req_elem_idl[0];
283 } __packed;
285 struct element_bss_load {
286 u8 len;
287 u16 station_cnt;
288 u8 ch_util;
289 u16 avlb_adm_cap;
290 } __packed;
292 struct element_edca_ps {
293 u8 len;
294 u8 qos_inf;
295 u8 res;
296 u32 ac_be;
297 u32 ac_bk;
298 u32 ac_vi;
299 u32 ac_vo;
300 } __packed;
302 struct element_tspec {
303 union {
304 u32 len_ts_info;
305 struct {
306 #if defined(__LITTLE_ENDIAN_BITFIELD)
307 /* Correct order here ... */
308 __extension__ u32 len:8,
309 traffic_type:1,
310 tsid:4,
311 direction:2,
312 access_policy:2,
313 aggr:1,
314 apsd:1,
315 user_prior:3,
316 tsinfo_ack_pol:2,
317 schedule:1,
318 res:7;
319 #elif defined(__BIG_ENDIAN_BITFIELD)
320 __extension__ u32 len:8,
321 res:7,
322 schedule:1,
323 tsinfo_ack_pol:2,
324 user_prior:3,
325 apsd:1,
326 aggr:1,
327 access_policy:2,
328 direction:2,
329 tsid:4,
330 traffic_type:1;
331 #else
332 # error "Adjust your <asm/byteorder.h> defines"
333 #endif
336 u16 nom_msdu_size;
337 u16 max_msdu_size;
338 u32 min_srv_intv;
339 u32 max_srv_intv;
340 u32 inactive_intv;
341 u32 susp_intv;
342 u32 srv_start_time;
343 u32 min_data_rate;
344 u32 mean_data_rate;
345 u32 peak_data_rate;
346 u32 burst_size;
347 u32 delay_bound;
348 u32 min_phy_rate;
349 u16 surplus_bandw_allow;
350 u16 med_time;
351 } __packed;
353 struct element_tclas {
354 u8 len;
355 u8 user_priority;
356 u8 frm_class[0];
357 } __packed;
359 struct element_tclas_frm_class {
360 u8 type;
361 u8 mask;
362 u8 param[0];
363 } __packed;
365 struct element_tclas_type0 {
366 u8 sa[6];
367 u8 da[6];
368 u16 type;
369 } __packed;
371 struct element_tclas_type1 {
372 u8 version;
373 u8 subparam[0];
374 } __packed;
376 struct element_tclas_type1_ip4 {
377 u32 sa;
378 u32 da;
379 u16 sp;
380 u16 dp;
381 u8 dscp;
382 u8 proto;
383 u8 reserved;
384 } __packed;
386 struct element_tclas_type1_ip6 {
387 struct in6_addr sa;
388 struct in6_addr da;
389 u16 sp;
390 u16 dp;
391 union {
392 u8 flow_label[3];
393 struct {
394 #if defined(__LITTLE_ENDIAN_BITFIELD)
395 __extension__ u8 flow_label3:8;
396 __extension__ u8 flow_label2:8;
397 __extension__ u8 flow_label1:8;
398 #elif defined(__BIG_ENDIAN_BITFIELD)
399 __extension__ u8 flow_label1:8;
400 __extension__ u8 flow_label2:8;
401 __extension__ u8 flow_label3:8;
402 #else
403 # error "Adjust your <asm/byteorder.h> defines"
404 #endif
407 } __packed;
409 struct element_tclas_type2 {
410 u16 vlan_tci;
411 } __packed;
413 struct element_tclas_type3 {
414 u16 offs;
415 u8 value[0];
416 u8 mask[0];
417 } __packed;
419 struct element_tclas_type4 {
420 u8 version;
421 u8 subparam[0];
422 } __packed;
424 struct element_tclas_type4_ip4 {
425 u32 sa;
426 u32 da;
427 u16 sp;
428 u16 dp;
429 u8 dscp;
430 u8 proto;
431 u8 reserved;
432 } __packed;
434 struct element_tclas_type4_ip6 {
435 struct in6_addr sa;
436 struct in6_addr da;
437 u16 sp;
438 u16 dp;
439 u8 dscp;
440 u8 nxt_hdr;
441 union {
442 u8 flow_label[3];
443 struct {
444 #if defined(__LITTLE_ENDIAN_BITFIELD)
445 __extension__ u8 flow_label3:8;
446 __extension__ u8 flow_label2:8;
447 __extension__ u8 flow_label1:8;
448 #elif defined(__BIG_ENDIAN_BITFIELD)
449 __extension__ u8 flow_label1:8;
450 __extension__ u8 flow_label2:8;
451 __extension__ u8 flow_label3:8;
452 #else
453 # error "Adjust your <asm/byteorder.h> defines"
454 #endif
457 } __packed;
459 struct element_tclas_type5 {
460 u8 pcp;
461 u8 cfi;
462 u8 vid;
463 } __packed;
465 struct element_schedule {
466 u8 len;
467 u16 inf;
468 u32 start;
469 u32 serv_intv;
470 u16 spec_intv;
471 } __packed;
473 struct element_chall_txt {
474 u8 len;
475 u8 chall_txt[0];
476 } __packed;
478 struct element_pwr_constr {
479 u8 len;
480 u8 local_pwr_constr;
481 } __packed;
483 struct element_pwr_cap {
484 u8 len;
485 u8 min_pwr_cap;
486 u8 max_pwr_cap;
487 } __packed;
489 struct element_tpc_req {
490 u8 len;
491 } __packed;
493 struct element_tpc_rep {
494 u8 len;
495 u8 trans_pwr;
496 u8 link_marg;
497 } __packed;
499 struct element_supp_ch {
500 u8 len;
501 u8 first_ch_nr[0];
502 u8 nr_ch[0];
503 } __packed;
505 struct element_supp_ch_tuple {
506 u8 first_ch_nr;
507 u8 nr_ch;
508 } __packed;
510 struct element_ch_sw_ann {
511 u8 len;
512 u8 switch_mode;
513 u8 new_nr;
514 u8 switch_cnt;
515 } __packed;
517 struct element_meas_basic {
518 u8 ch_nr;
519 u64 start;
520 u16 dur;
521 } __packed;
523 struct element_meas_cca {
524 u8 ch_nr;
525 u64 start;
526 u16 dur;
527 } __packed;
529 struct element_meas_rpi {
530 u8 ch_nr;
531 u64 start;
532 u16 dur;
533 } __packed;
535 struct element_meas_ch_load {
536 u8 op_class;
537 u8 ch_nr;
538 u16 rand_intv;
539 u16 dur;
540 u8 sub[0];
541 } __packed;
543 struct element_meas_noise {
544 u8 op_class;
545 u8 ch_nr;
546 u16 rand_intv;
547 u16 dur;
548 u8 sub[0];
549 } __packed;
551 struct element_meas_beacon {
552 u8 op_class;
553 u8 ch_nr;
554 u16 rand_intv;
555 u16 dur;
556 u8 mode;
557 u8 bssid[6];
558 u8 sub[0];
559 } __packed;
561 struct element_meas_frame {
562 u8 op_class;
563 u8 ch_nr;
564 u16 rand_intv;
565 u16 dur;
566 u8 frame;
567 u8 mac[6];
568 u8 sub[0];
569 } __packed;
571 struct element_meas_sta {
572 u8 peer_mac[6];
573 u16 rand_intv;
574 u16 dur;
575 u8 group_id;
576 u8 sub[0];
577 } __packed;
579 struct element_meas_lci {
580 u8 loc_subj;
581 u8 latitude_req_res;
582 u8 longitude_req_res;
583 u8 altitude_req_res;
584 u8 sub[0];
585 } __packed;
587 struct element_meas_trans_str_cat {
588 u16 rand_intv;
589 u16 dur;
590 u8 peer_sta_addr[6];
591 u8 traffic_id;
592 u8 bin_0_range;
593 u8 sub[0];
594 } __packed;
596 struct element_meas_mcast_diag {
597 u16 rand_intv;
598 u16 dur;
599 u8 group_mac[6];
600 u8 mcast_triggered[0];
601 u8 sub[0];
602 } __packed;
604 struct element_meas_loc_civic {
605 u8 loc_subj;
606 u8 civic_loc;
607 u8 loc_srv_intv_unit;
608 u16 loc_srv_intv;
609 u8 sub[0];
610 } __packed;
612 struct element_meas_loc_id {
613 u8 loc_subj;
614 u8 loc_srv_intv_unit;
615 u16 loc_srv_intv;
616 u8 sub[0];
617 } __packed;
619 struct element_meas_pause {
620 u8 time;
621 u8 sub[0];
622 } __packed;
624 struct element_meas_req {
625 u8 len;
626 u8 token;
627 u8 req_mode;
628 u8 type;
629 u8 req[0];
630 } __packed;
632 struct element_meas_rep {
633 u8 len;
634 u8 token;
635 u8 rep_mode;
636 u8 type;
637 u8 rep[0];
638 } __packed;
640 struct element_quiet {
641 u8 len;
642 u8 cnt;
643 u8 period;
644 u16 dur;
645 u16 offs;
646 } __packed;
648 struct element_ibss_dfs {
649 u8 len;
650 u8 owner[6];
651 u8 rec_intv;
652 u8 ch_map[0];
653 } __packed;
655 struct element_ibss_dfs_tuple {
656 u8 ch_nr;
657 u8 map;
658 } __packed;
660 struct element_erp {
661 u8 len;
662 u8 param;
663 } __packed;
665 struct element_ts_del {
666 u8 len;
667 u32 delay;
668 } __packed;
670 struct element_tclas_proc {
671 u8 len;
672 u8 proc;
673 } __packed;
675 struct element_ht_cap {
676 u8 len;
677 union {
678 u16 info;
679 struct {
680 #if defined(__LITTLE_ENDIAN_BITFIELD)
681 /* Correct order here ... */
682 __extension__ u16 ldpc:1,
683 supp_width:1,
684 sm_pwr:2,
685 ht_green:1,
686 gi_20mhz:1,
687 gi_40mhz:1,
688 tx_stbc:1,
689 rx_stbc:2,
690 ht_ack:1,
691 max_msdu_length:1,
692 dsss_ck_mode:1,
693 res:1,
694 forty_int:1,
695 prot_supp:1;
696 #elif defined(__BIG_ENDIAN_BITFIELD)
697 __extension__ u16 rx_stbc:2,
698 ht_ack:1,
699 max_msdu_length:1,
700 dsss_ck_mode:1,
701 res:1,
702 forty_int:1,
703 prot_supp:1,
704 ldpc:1,
705 supp_width:1,
706 sm_pwr:2,
707 ht_green:1,
708 gi_20mhz:1,
709 gi_40mhz:1,
710 tx_stbc:1;
711 #else
712 # error "Adjust your <asm/byteorder.h> defines"
713 #endif
716 u8 param;
717 union {
718 u8 mcs_set[16];
719 struct {
720 #if defined(__LITTLE_ENDIAN_BITFIELD)
721 /* Correct order here ... */
722 __extension__ u8 bitmask1:8;
723 __extension__ u8 bitmask2:8;
724 __extension__ u8 bitmask3:8;
725 __extension__ u8 bitmask4:8;
726 __extension__ u8 bitmask5:8;
727 __extension__ u8 bitmask6:8;
728 __extension__ u8 bitmask7:8;
729 __extension__ u8 bitmask8:8;
730 __extension__ u8 bitmask9:8;
731 __extension__ u8 bitmask10_res:8;
732 __extension__ u16 supp_rate_res:16;
733 __extension__ u32 tx_param_res:32;
735 #elif defined(__BIG_ENDIAN_BITFIELD)
736 __extension__ u32 tx_param_res:32;
737 __extension__ u16 supp_rate_res:16;
738 __extension__ u8 bitmask10_res:8;
739 __extension__ u8 bitmask9:8;
740 __extension__ u8 bitmask8:8;
741 __extension__ u8 bitmask7:8;
742 __extension__ u8 bitmask6:8;
743 __extension__ u8 bitmask5:8;
744 __extension__ u8 bitmask4:8;
745 __extension__ u8 bitmask3:8;
746 __extension__ u8 bitmask2:8;
747 __extension__ u8 bitmask1:8;
748 #else
749 # error "Adjust your <asm/byteorder.h> defines"
750 #endif
753 u16 ext_cap;
754 u32 beam_cap;
755 u8 asel_cap;
756 } __packed;
758 struct element_qos_cap {
759 u8 len;
760 u8 info;
761 } __packed;
763 struct element_ext_supp_rates {
764 u8 len;
765 u8 rates[0];
766 } __packed;
768 struct element_vend_spec {
769 u8 len;
770 u8 oui[0];
771 u8 specific[0];
772 } __packed;
774 static int8_t len_neq_error(u8 len, u8 intended)
776 if(intended != len) {
777 tprintf("Length should be %u Bytes", intended);
778 return 1;
781 return 0;
784 static int8_t len_lt_error(u8 len, u8 intended)
786 if(len < intended) {
787 tprintf("Length should be greater %u Bytes", intended);
788 return 1;
791 return 0;
794 static float data_rates(u8 id)
796 /* XXX Why not (id / 2.f)? */
797 switch (id) {
798 case 2: return 1.0f;
799 case 3: return 1.5f;
800 case 4: return 2.0f;
801 case 5: return 2.5f;
802 case 6: return 3.0f;
803 case 9: return 4.5f;
804 case 11: return 5.5f;
805 case 12: return 6.0f;
806 case 18: return 9.0f;
807 case 22: return 11.0f;
808 case 24: return 12.0f;
809 case 27: return 13.5f;
810 case 36: return 18.0f;
811 case 44: return 22.0f;
812 case 48: return 24.0f;
813 case 54: return 27.0f;
814 case 66: return 33.0f;
815 case 72: return 36.0f;
816 case 96: return 48.0f;
817 case 108: return 54.0f;
820 return 0.f;
823 struct subelement {
824 u8 id;
825 u8 len;
826 u8 data[0];
827 } __packed;
830 static int8_t subelements(struct pkt_buff *pkt, u8 len)
832 u8 i, j;
833 u8 *data;
835 for (i=0; i<len;) {
836 struct subelement *sub;
838 sub = (struct subelement *) pkt_pull(pkt, sizeof(*sub));
839 if (sub == NULL)
840 return 0;
842 tprintf(", Subelement ID %u, ", sub->id);
843 tprintf("Length %u, ", sub->len);
845 data = pkt_pull(pkt, sub->len);
846 if (data == NULL)
847 return 0;
849 tprintf("Data: 0x");
850 for(j=0; j < sub->len; j++)
851 tprintf("%.2x ", data[j]);
853 i += sub->len + 1;
856 /* Not needed ?! Should break before*/
858 *if (i != len) {
859 * tprintf("Length error");
860 * return 0;
864 return 1;
867 static int8_t inf_reserved(struct pkt_buff *pkt, u8 *id)
869 u8 i;
870 u8 *data;
871 struct element_reserved *reserved;
873 reserved = (struct element_reserved *) pkt_pull(pkt, sizeof(*reserved));
874 if (reserved == NULL)
875 return 0;
877 tprintf("Reserved (%u, Len (%u)): ", *id, reserved->len);
879 data = pkt_pull(pkt, reserved->len);
880 if (data == NULL)
881 return 0;
883 tprintf("Data 0x");
884 for (i = 0; i < reserved->len; i++)
885 tprintf("%.2x", data[i]);
887 return 1;
890 static int8_t inf_ssid(struct pkt_buff *pkt, u8 *id)
892 u8 i;
893 struct element_ssid *ssid;
894 char *ssid_name;
896 ssid = (struct element_ssid *) pkt_pull(pkt, sizeof(*ssid));
897 if (ssid == NULL)
898 return 0;
900 tprintf(" SSID (%u, Len (%u)): ", *id, ssid->len);
902 if ((ssid->len - sizeof(*ssid) + 1) > 0) {
903 ssid_name = (char *) pkt_pull(pkt, ssid->len);
904 if (ssid_name == NULL)
905 return 0;
907 for (i = 0; i < ssid->len; i++)
908 tprintf("%c",ssid_name[i]);
909 } else {
910 tprintf("Wildcard SSID");
913 return 1;
916 static int8_t inf_supp_rates(struct pkt_buff *pkt, u8 *id)
918 u8 i;
919 u8 *rates;
920 struct element_supp_rates *supp_rates;
922 supp_rates = (struct element_supp_rates *)
923 pkt_pull(pkt, sizeof(*supp_rates));
924 if (supp_rates == NULL)
925 return 0;
927 tprintf(" Supp. Rates (%u, Len (%u)): ", *id, supp_rates->len);
928 if (len_lt_error(supp_rates->len, 1))
929 return 0;
931 if ((supp_rates->len - sizeof(*supp_rates) + 1) > 0) {
932 rates = pkt_pull(pkt, supp_rates->len);
933 if (rates == NULL)
934 return 0;
936 for (i = 0; i < supp_rates->len; i++)
937 tprintf("%g%s ", ((rates[i] & 0x80) >> 7) ?
938 data_rates(rates[i] & 0x3f) :
939 ((rates[i] & 0x3f) * 0.5),
940 ((rates[i] & 0x80) >> 7) ? "(B)" : "");
941 return 1;
944 return 0;
947 static int8_t inf_fh_ps(struct pkt_buff *pkt, u8 *id)
949 struct element_fh_ps *fh_ps;
951 fh_ps = (struct element_fh_ps *) pkt_pull(pkt, sizeof(*fh_ps));
952 if (fh_ps == NULL)
953 return 0;
955 tprintf(" FH Param Set (%u, Len(%u)): ", *id, fh_ps->len);
956 if (len_neq_error(fh_ps->len, 5))
957 return 0;
958 tprintf("Dwell Time: %fs, ", le16_to_cpu(fh_ps->dwell_time) * TU);
959 tprintf("HopSet: %u, ", fh_ps->hop_set);
960 tprintf("HopPattern: %u, ", fh_ps->hop_pattern);
961 tprintf("HopIndex: %u", fh_ps->hop_index);
963 return 1;
966 static int8_t inf_dsss_ps(struct pkt_buff *pkt, u8 *id)
968 struct element_dsss_ps *dsss_ps;
970 dsss_ps = (struct element_dsss_ps *) pkt_pull(pkt, sizeof(*dsss_ps));
971 if (dsss_ps == NULL)
972 return 0;
974 tprintf(" DSSS Param Set (%u, Len(%u)): ", *id, dsss_ps->len);
975 if (len_neq_error(dsss_ps->len, 1))
976 return 0;
977 tprintf("Current Channel: %u", dsss_ps->curr_ch);
979 return 1;
982 static int8_t inf_cf_ps(struct pkt_buff *pkt, u8 *id)
984 struct element_cf_ps *cf_ps;
986 cf_ps = (struct element_cf_ps *) pkt_pull(pkt, sizeof(*cf_ps));
987 if (cf_ps == NULL)
988 return 0;
990 tprintf(" CF Param Set (%u, Len(%u)): ", *id, cf_ps->len);
991 if (len_neq_error(cf_ps->len, 6))
992 return 0;
993 tprintf("CFP Count: %u, ", cf_ps->cfp_cnt);
994 tprintf("CFP Period: %u, ", cf_ps->cfp_period);
995 tprintf("CFP MaxDur: %fs, ", le16_to_cpu(cf_ps->cfp_max_dur) * TU);
996 tprintf("CFP DurRem: %fs", le16_to_cpu(cf_ps->cfp_dur_rem) * TU);
998 return 1;
1001 static int8_t inf_tim(struct pkt_buff *pkt, u8 *id)
1003 struct element_tim *tim;
1004 u8 i;
1006 tim = (struct element_tim *) pkt_pull(pkt, sizeof(*tim));
1007 if (tim == NULL)
1008 return 0;
1010 tprintf(" TIM (%u, Len(%u)): ", *id, tim->len);
1011 if (len_lt_error(tim->len, 3))
1012 return 0;
1013 tprintf("DTIM Count: %u, ", tim->dtim_cnt);
1014 tprintf("DTIM Period: %u, ", tim->dtim_period);
1015 tprintf("Bitmap Control: %u, ", tim->bmp_cntrl);
1016 if ((tim->len - sizeof(*tim) + 1) > 0) {
1017 u8 *bmp = pkt_pull(pkt, (tim->len - sizeof(*tim) + 1));
1018 if (bmp == NULL)
1019 return 0;
1021 tprintf("Partial Virtual Bitmap: 0x");
1022 for (i = 0; i < (tim->len - sizeof(*tim) + 1); i++)
1023 tprintf("%.2x", bmp[i]);
1026 return 1;
1029 static int8_t inf_ibss_ps(struct pkt_buff *pkt, u8 *id)
1031 struct element_ibss_ps *ibss_ps;
1033 ibss_ps = (struct element_ibss_ps *) pkt_pull(pkt, sizeof(*ibss_ps));
1034 if (ibss_ps == NULL)
1035 return 0;
1037 tprintf(" IBSS Param Set (%u, Len(%u)): ", *id, ibss_ps->len);
1038 if (len_neq_error(ibss_ps->len, 2))
1039 return 0;
1040 tprintf("ATIM Window: %fs", le16_to_cpu(ibss_ps->atim_win) * TU);
1042 return 1;
1045 static int8_t inf_country(struct pkt_buff *pkt, u8 *id)
1047 u8 i;
1048 u8 *pad;
1049 struct element_country *country;
1051 country = (struct element_country *) pkt_pull(pkt, sizeof(*country));
1052 if (country == NULL)
1053 return 0;
1055 tprintf(" Country (%u, Len(%u)): ", *id, country->len);
1056 if (len_lt_error(country->len, 6))
1057 return 0;
1058 tprintf("Country String: %c%c%c", country->country_first,
1059 country->country_sec, country->country_third);
1061 for (i = country->len % 3; i < (country->len - 3); i += 3) {
1062 struct element_country_tripled *country_tripled;
1064 country_tripled = (struct element_country_tripled *)
1065 pkt_pull(pkt, sizeof(*country_tripled));
1066 if (country_tripled == NULL)
1067 return 0;
1069 if(country_tripled->frst_ch >= 201) {
1070 tprintf("Oper Ext ID: %u, ", country_tripled->frst_ch);
1071 tprintf("Operating Class: %u, ", country_tripled->nr_ch);
1072 tprintf("Coverage Class: %u", country_tripled->max_trans);
1073 } else {
1074 tprintf("First Ch Nr: %u, ", country_tripled->frst_ch);
1075 tprintf("Nr of Ch: %u, ", country_tripled->nr_ch);
1076 tprintf("Max Transmit Pwr Lvl: %u", country_tripled->max_trans);
1080 if(country->len % 3) {
1081 pad = pkt_pull(pkt, 1);
1082 if (pad == NULL)
1083 return 0;
1085 tprintf(", Pad: 0x%x", *pad);
1088 return 1;
1091 static int8_t inf_hop_pp(struct pkt_buff *pkt, u8 *id)
1093 struct element_hop_pp *hop_pp;
1095 hop_pp = (struct element_hop_pp *) pkt_pull(pkt, sizeof(*hop_pp));
1096 if (hop_pp == NULL)
1097 return 0;
1099 tprintf(" Hopping Pattern Param (%u, Len(%u)): ", *id, hop_pp->len);
1100 if (len_neq_error(hop_pp->len, 2))
1101 return 0;
1102 tprintf("Prime Radix: %u, ", hop_pp->prime_radix);
1103 tprintf("Nr of Ch: %u", hop_pp->nr_ch);
1105 return 1;
1108 static int8_t inf_hop_pt(struct pkt_buff *pkt, u8 *id)
1110 size_t i;
1111 u8 *rand_tabl;
1112 struct element_hop_pt *hop_pt;
1114 hop_pt = (struct element_hop_pt *) pkt_pull(pkt, sizeof(*hop_pt));
1115 if (hop_pt == NULL)
1116 return 0;
1118 tprintf(" Hopping Pattern Table (%u, Len(%u)): ", *id, hop_pt->len);
1119 if (len_lt_error(hop_pt->len, 4))
1120 return 0;
1121 tprintf("Flag: %u, ", hop_pt->flag);
1122 tprintf("Nr of Sets: %u, ", hop_pt->nr_sets);
1123 tprintf("Modulus: %u, ", hop_pt->modules);
1124 tprintf("Offs: %u", hop_pt->offs);
1126 if ((hop_pt->len - sizeof(*hop_pt) + 1) > 0) {
1127 rand_tabl = pkt_pull(pkt, (hop_pt->len - sizeof(*hop_pt) + 1));
1128 if (rand_tabl == NULL)
1129 return 0;
1131 tprintf(", Rand table: 0x");
1132 for (i = 0; i < (hop_pt->len - sizeof(*hop_pt) + 1); i++)
1133 tprintf("%.2x", rand_tabl[i]);
1136 return 1;
1139 static int8_t inf_req(struct pkt_buff *pkt, u8 *id)
1141 size_t i;
1142 struct element_req *req;
1143 u8 *req_ids;
1145 req = (struct element_req *) pkt_pull(pkt, sizeof(*req));
1146 if (req == NULL)
1147 return 0;
1149 tprintf(" Request Element (%u, Len(%u)): ", *id, req->len);
1150 if ((req->len - sizeof(*req) + 1) > 0) {
1151 req_ids = pkt_pull(pkt, (req->len - sizeof(*req) + 1));
1152 if (req_ids == NULL)
1153 return 0;
1155 tprintf(", Requested Element IDs: ");
1156 for (i = 0; i < (req->len - sizeof(*req) + 1); i++)
1157 tprintf("%u ", req_ids[i]);
1160 return 1;
1163 static int8_t inf_bss_load(struct pkt_buff *pkt, u8 *id)
1165 struct element_bss_load *bss_load;
1167 bss_load = (struct element_bss_load *) pkt_pull(pkt, sizeof(*bss_load));
1168 if (bss_load == NULL)
1169 return 0;
1171 tprintf(" BSS Load element (%u, Len(%u)): ", *id, bss_load->len);
1172 if (len_neq_error(bss_load->len, 5))
1173 return 0;
1174 tprintf("Station Count: %u, ", le16_to_cpu(bss_load->station_cnt));
1175 tprintf("Channel Utilization: %u, ", bss_load->ch_util);
1176 tprintf("Available Admission Capacity: %uus",
1177 bss_load->avlb_adm_cap * 32);
1179 return 1;
1182 static int8_t inf_edca_ps(struct pkt_buff *pkt, u8 *id)
1184 u32 ac_be, ac_bk, ac_vi, ac_vo;
1185 struct element_edca_ps *edca_ps;
1187 edca_ps = (struct element_edca_ps *) pkt_pull(pkt, sizeof(*edca_ps));
1188 if (edca_ps == NULL)
1189 return 0;
1191 ac_be = le32_to_cpu(edca_ps->ac_be);
1192 ac_bk = le32_to_cpu(edca_ps->ac_bk);
1193 ac_vi = le32_to_cpu(edca_ps->ac_vi);
1194 ac_vo = le32_to_cpu(edca_ps->ac_vo);
1196 tprintf(" EDCA Param Set (%u, Len(%u)): ", *id, edca_ps->len);
1197 if (len_neq_error(edca_ps->len, 18))
1198 return 0;
1199 tprintf("QoS Info: 0x%x (-> EDCA Param Set Update Count (%u),"
1200 "Q-Ack (%u), Queue Re (%u), TXOP Req(%u), Res(%u)), ",
1201 edca_ps->qos_inf, edca_ps->qos_inf >> 4,
1202 (edca_ps->qos_inf >> 3) & 1, (edca_ps->qos_inf >> 2) & 1,
1203 (edca_ps->qos_inf >> 1) & 1, edca_ps->qos_inf & 1);
1204 tprintf("Reserved: 0x%x, ", edca_ps->res);
1205 tprintf("AC_BE Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1206 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_be,
1207 ac_be >> 28, (ac_be >> 27) & 1, (ac_be >> 25) & 3,
1208 (ac_be >> 24) & 1, (ac_be >> 20) & 15, (ac_be >> 16) & 15,
1209 bswap_16(ac_be & 0xFFFF) * 32);
1210 tprintf("AC_BK Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1211 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_bk,
1212 ac_bk >> 28, (ac_bk >> 27) & 1, (ac_bk >> 25) & 3,
1213 (ac_bk >> 24) & 1, (ac_bk >> 20) & 15, (ac_bk >> 16) & 15,
1214 bswap_16(ac_bk & 0xFFFF) * 32);
1215 tprintf("AC_VI Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1216 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_vi,
1217 ac_vi >> 28, (ac_vi >> 27) & 1, (ac_vi >> 25) & 3,
1218 (ac_vi >> 24) & 1, (ac_vi >> 20) & 15, (ac_vi >> 16) & 15,
1219 bswap_16(ac_vi & 0xFFFF) * 32);
1220 tprintf("AC_VO Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1221 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)", ac_vo,
1222 ac_vo >> 28, (ac_vo >> 27) & 1, (ac_vo >> 25) & 3,
1223 (ac_vo >> 24) & 1, (ac_vo >> 20) & 15, (ac_vo >> 16) & 15,
1224 bswap_16(ac_vo & 0xFFFF) * 32);
1226 return 1;
1229 static int8_t inf_tspec(struct pkt_buff *pkt, u8 *id)
1231 u16 nom_msdu_size, surplus_bandw_allow;
1232 struct element_tspec *tspec;
1234 tspec = (struct element_tspec *) pkt_pull(pkt, sizeof(*tspec));
1235 if (tspec == NULL)
1236 return 0;
1238 nom_msdu_size = le16_to_cpu(tspec->nom_msdu_size);
1239 surplus_bandw_allow = le16_to_cpu(tspec->surplus_bandw_allow);
1241 tprintf(" TSPEC (%u, Len(%u)): ", *id, tspec->len);
1242 if (len_neq_error(tspec->len, 55))
1243 return 0;
1244 tprintf("Traffic Type: %u, ", tspec->traffic_type);
1245 tprintf("TSID: %u, ", tspec->tsid);
1246 tprintf("Direction: %u, ", tspec->direction);
1247 tprintf("Access Policy: %u, ", tspec->access_policy);
1248 tprintf("Aggregation: %u, ", tspec->aggr);
1249 tprintf("APSD: %u, ", tspec->apsd);
1250 tprintf("User Priority: %u, ", tspec->user_prior);
1251 tprintf("TSinfo Ack Policy: %u, ", tspec->tsinfo_ack_pol);
1252 tprintf("Schedule: %u, ", tspec->schedule);
1253 tprintf("Reserved: 0x%x, ", tspec->res);
1254 tprintf("Nominal MSDU Size: %uB (Fixed (%u)), ",
1255 nom_msdu_size >> 1, nom_msdu_size & 1);
1256 tprintf("Maximum MSDU Size: %uB, ", le16_to_cpu(tspec->max_msdu_size));
1257 tprintf("Minimum Service Interval: %uus, ",
1258 le32_to_cpu(tspec->min_srv_intv));
1259 tprintf("Maximum Service Interval: %uus, ",
1260 le32_to_cpu(tspec->max_srv_intv));
1261 tprintf("Inactivity Interval: %uus, ",
1262 le32_to_cpu(tspec->inactive_intv));
1263 tprintf("Suspension Interval: %uus, ", le32_to_cpu(tspec->susp_intv));
1264 tprintf("Service Start Time: %uus, ",
1265 le32_to_cpu(tspec->srv_start_time));
1266 tprintf("Minimum Data Rate: %ub/s, ",le32_to_cpu(tspec->min_data_rate));
1267 tprintf("Mean Data Rate: %ub/s, ", le32_to_cpu(tspec->mean_data_rate));
1268 tprintf("Peak Data Rate: %ub/s, ",le32_to_cpu(tspec->peak_data_rate));
1269 tprintf("Burst Size: %uB, ", le32_to_cpu(tspec->burst_size));
1270 tprintf("Delay Bound: %uus, ", le32_to_cpu(tspec->delay_bound));
1271 tprintf("Minimum PHY Rate: %ub/s, ", le32_to_cpu(tspec->min_phy_rate));
1272 tprintf("Surplus Bandwidth: %u.%u, ", surplus_bandw_allow >> 13,
1273 surplus_bandw_allow & 0x1FFF);
1274 tprintf("Medium Time: %uus", le16_to_cpu(tspec->med_time) * 32);
1276 return 1;
1279 static const char *class_type(u8 type)
1281 switch (type) {
1282 case 0: return "Ethernet parameters";
1283 case 1: return "TCP/UDP IP parameters";
1284 case 2: return "IEEE 802.1Q parameters";
1285 case 3: return "Filter Offset parameters";
1286 case 4: return "IP and higher layer parameters";
1287 case 5: return "IEEE 802.1D/Q parameters";
1288 default: return "Reserved";
1292 static int8_t inf_tclas(struct pkt_buff *pkt, u8 *id)
1294 struct element_tclas *tclas;
1295 struct element_tclas_frm_class *frm_class;
1297 tclas = (struct element_tclas *) pkt_pull(pkt, sizeof(*tclas));
1298 if (tclas == NULL)
1299 return 0;
1301 frm_class = (struct element_tclas_frm_class *)
1302 pkt_pull(pkt, sizeof(*frm_class));
1303 if (frm_class == NULL)
1304 return 0;
1306 tprintf(" TCLAS (%u, Len(%u)): ", *id, tclas->len);
1307 if (len_lt_error(tclas->len, 3))
1308 return 0;
1309 tprintf("User Priority: %u, ", tclas->user_priority);
1310 tprintf("Classifier Type: %s (%u), ", class_type(frm_class->type),
1311 frm_class->type);
1312 tprintf("Classifier Mask: 0x%x, ", frm_class->mask);
1314 if(frm_class->type == 0) {
1315 struct element_tclas_type0 *type0;
1317 type0 = (struct element_tclas_type0 *)
1318 pkt_pull(pkt, sizeof(*type0));
1319 if (type0 == NULL)
1320 return 0;
1322 /* I think little endian, like the rest */
1323 tprintf("Src Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
1324 type0->sa[5], type0->sa[4], type0->sa[3],
1325 type0->sa[2], type0->sa[1], type0->sa[0]);
1326 tprintf("Dst Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
1327 type0->da[5], type0->da[4], type0->da[3],
1328 type0->da[2], type0->da[1], type0->da[0]);
1329 tprintf("Type: 0x%x", le16_to_cpu(type0->type));
1331 else if(frm_class->type == 1) {
1332 struct element_tclas_type1 *type1;
1334 type1 = (struct element_tclas_type1 *)
1335 pkt_pull(pkt, sizeof(*type1));
1336 if (type1 == NULL)
1337 return 0;
1339 tprintf("Version: %u, ", type1->version);
1340 /* big endian format follows */
1341 if(type1->version == 4) {
1342 struct element_tclas_type1_ip4 *type1_ip4;
1343 char src_ip[INET_ADDRSTRLEN];
1344 char dst_ip[INET_ADDRSTRLEN];
1346 type1_ip4 = (struct element_tclas_type1_ip4 *)
1347 pkt_pull(pkt, sizeof(*type1_ip4));
1348 if (type1_ip4 == NULL)
1349 return 0;
1351 inet_ntop(AF_INET, &type1_ip4->sa, src_ip, sizeof(src_ip));
1352 inet_ntop(AF_INET, &type1_ip4->da, dst_ip, sizeof(dst_ip));
1354 tprintf("Src IP: %s, ", src_ip);
1355 tprintf("Dst IP: %s, ", dst_ip);
1356 tprintf("Src Port: %u, ", ntohs(type1_ip4->sp));
1357 tprintf("Dst Port: %u, ", ntohs(type1_ip4->dp));
1358 tprintf("DSCP: 0x%x, ", type1_ip4->dscp);
1359 tprintf("Proto: %u, ", type1_ip4->proto);
1360 tprintf("Res: 0x%x", type1_ip4->reserved);
1362 else if(type1->version == 6) {
1363 struct element_tclas_type1_ip6 *type1_ip6;
1364 char src_ip[INET6_ADDRSTRLEN];
1365 char dst_ip[INET6_ADDRSTRLEN];
1367 type1_ip6 = (struct element_tclas_type1_ip6 *)
1368 pkt_pull(pkt, sizeof(*type1_ip6));
1369 if (type1_ip6 == NULL)
1370 return 0;
1372 inet_ntop(AF_INET6, &type1_ip6->sa,
1373 src_ip, sizeof(src_ip));
1374 inet_ntop(AF_INET6, &type1_ip6->da,
1375 dst_ip, sizeof(dst_ip));
1377 tprintf("Src IP: %s, ", src_ip);
1378 tprintf("Dst IP: %s, ", dst_ip);
1379 tprintf("Src Port: %u, ", ntohs(type1_ip6->sp));
1380 tprintf("Dst Port: %u, ", ntohs(type1_ip6->dp));
1381 tprintf("Flow Label: 0x%x%x%x", type1_ip6->flow_label1,
1382 type1_ip6->flow_label2, type1_ip6->flow_label3);
1384 else {
1385 tprintf("Version (%u) not supported", type1->version);
1386 return 0;
1390 else if(frm_class->type == 2) {
1391 struct element_tclas_type2 *type2;
1393 type2 = (struct element_tclas_type2 *)
1394 pkt_pull(pkt, sizeof(*type2));
1395 if (type2 == NULL)
1396 return 0;
1398 tprintf("802.1Q VLAN TCI: 0x%x", ntohs(type2->vlan_tci));
1400 else if(frm_class->type == 3) {
1401 struct element_tclas_type3 *type3;
1402 u8 len, i;
1403 u8 *val;
1405 type3 = (struct element_tclas_type3 *)
1406 pkt_pull(pkt, sizeof(*type3));
1407 if (type3 == NULL)
1408 return 0;
1410 len = (tclas->len - 5) / 2;
1412 tprintf("Filter Offset: %u, ", type3->offs);
1414 if((len & 1) || (len_lt_error(tclas->len, 5))) {
1415 tprintf("Length of TCLAS (%u) not correct", tclas->len);
1416 return 0;
1418 else {
1419 val = pkt_pull(pkt, len);
1420 if (val == NULL)
1421 return 0;
1423 tprintf("Filter Value: 0x");
1424 for (i = 0; i < len / 2; i++)
1425 tprintf("%x ", val[i]);
1426 tprintf(", ");
1427 tprintf("Filter Mask: 0x");
1428 for (i = len / 2; i < len; i++)
1429 tprintf("%x ", val[i]);
1433 else if(frm_class->type == 4) {
1434 struct element_tclas_type4 *type4;
1436 type4 = (struct element_tclas_type4 *)
1437 pkt_pull(pkt, sizeof(*type4));
1438 if (type4 == NULL)
1439 return 0;
1441 tprintf("Version: %u, ", type4->version);
1442 /* big endian format follows */
1443 if(type4->version == 4) {
1444 struct element_tclas_type4_ip4 *type4_ip4;
1445 char src_ip[INET_ADDRSTRLEN];
1446 char dst_ip[INET_ADDRSTRLEN];
1448 type4_ip4 = (struct element_tclas_type4_ip4 *)
1449 pkt_pull(pkt, sizeof(*type4_ip4));
1450 if (type4_ip4 == NULL)
1451 return 0;
1453 inet_ntop(AF_INET, &type4_ip4->sa, src_ip, sizeof(src_ip));
1454 inet_ntop(AF_INET, &type4_ip4->da, dst_ip, sizeof(dst_ip));
1456 tprintf("Src IP: %s, ", src_ip);
1457 tprintf("Dst IP: %s, ", dst_ip);
1458 tprintf("Src Port: %u, ", ntohs(type4_ip4->sp));
1459 tprintf("Dst Port: %u, ", ntohs(type4_ip4->dp));
1460 tprintf("DSCP: 0x%x, ", type4_ip4->dscp);
1461 tprintf("Proto: %u, ", type4_ip4->proto);
1462 tprintf("Res: 0x%x", type4_ip4->reserved);
1464 else if(type4->version == 6) {
1465 struct element_tclas_type4_ip6 *type4_ip6;
1466 char src_ip[INET6_ADDRSTRLEN];
1467 char dst_ip[INET6_ADDRSTRLEN];
1469 type4_ip6 = (struct element_tclas_type4_ip6 *)
1470 pkt_pull(pkt, sizeof(*type4_ip6));
1471 if (type4_ip6 == NULL)
1472 return 0;
1474 inet_ntop(AF_INET6, &type4_ip6->sa,
1475 src_ip, sizeof(src_ip));
1476 inet_ntop(AF_INET6, &type4_ip6->da,
1477 dst_ip, sizeof(dst_ip));
1479 tprintf("Src IP: %s, ", src_ip);
1480 tprintf("Dst IP: %s, ", dst_ip);
1481 tprintf("Src Port: %u, ", ntohs(type4_ip6->sp));
1482 tprintf("Dst Port: %u, ", ntohs(type4_ip6->dp));
1483 tprintf("DSCP: 0x%x, ", type4_ip6->dscp);
1484 tprintf("Nxt Hdr: %u, ", type4_ip6->nxt_hdr);
1485 tprintf("Flow Label: 0x%x%x%x", type4_ip6->flow_label1,
1486 type4_ip6->flow_label2, type4_ip6->flow_label3);
1488 else {
1489 tprintf("Version (%u) not supported", type4->version);
1490 return 0;
1493 else if(frm_class->type == 5) {
1494 struct element_tclas_type5 *type5;
1496 type5 = (struct element_tclas_type5 *)
1497 pkt_pull(pkt, sizeof(*type5));
1498 if (type5 == NULL)
1499 return 0;
1501 tprintf("802.1Q PCP: 0x%x, ", type5->pcp);
1502 tprintf("802.1Q CFI: 0x%x, ", type5->cfi);
1503 tprintf("802.1Q VID: 0x%x", type5->vid);
1505 else {
1506 tprintf("Classifier Type (%u) not supported", frm_class->type);
1507 return 0;
1510 return 1;
1513 static int8_t inf_sched(struct pkt_buff *pkt, u8 *id)
1515 struct element_schedule *schedule;
1516 u16 info;
1518 schedule = (struct element_schedule *) pkt_pull(pkt, sizeof(*schedule));
1519 if (schedule == NULL)
1520 return 0;
1522 info = le16_to_cpu(schedule->inf);
1524 tprintf(" Schedule (%u, Len(%u)): ", *id, schedule->len);
1525 if (len_neq_error(schedule->len, 12))
1526 return 0;
1528 tprintf("Aggregation: %u, ", info >> 15);
1529 tprintf("TSID: %u, ", (info >> 11) & 0xF);
1530 tprintf("Direction: %u, ", (info >> 9) & 0x3);
1531 tprintf("Res: %u, ", info & 0x1FF);
1532 tprintf("Serv Start Time: %uus, ", le32_to_cpu(schedule->start));
1533 tprintf("Serv Interval: %uus, ", le32_to_cpu(schedule->serv_intv));
1534 tprintf("Spec Interval: %fs", le32_to_cpu(schedule->spec_intv) * TU);
1536 return 1;
1539 static int8_t inf_chall_txt(struct pkt_buff *pkt, u8 *id)
1541 struct element_chall_txt *chall_txt;
1542 u8 i;
1543 u8 *txt;
1545 chall_txt = (struct element_chall_txt *)
1546 pkt_pull(pkt, sizeof(*chall_txt));
1547 if (chall_txt == NULL)
1548 return 0;
1550 tprintf(" Challenge Text (%u, Len(%u)): ", *id, chall_txt->len);
1551 if ((chall_txt->len - sizeof(*chall_txt) + 1) > 0) {
1552 txt = pkt_pull(pkt, (chall_txt->len - sizeof(*chall_txt) + 1));
1553 if (txt == NULL)
1554 return 0;
1556 tprintf("0x");
1557 for (i = 0; i < (chall_txt->len - sizeof(*chall_txt) + 1); i++)
1558 tprintf("%x", txt[i]);
1561 return 1;
1564 static int8_t inf_pwr_constr(struct pkt_buff *pkt, u8 *id)
1566 struct element_pwr_constr *pwr_constr;
1568 pwr_constr = (struct element_pwr_constr *) pkt_pull(pkt, sizeof(*pwr_constr));
1569 if (pwr_constr == NULL)
1570 return 0;
1572 tprintf(" Power Constraint (%u, Len(%u)): ", *id, pwr_constr->len);
1573 if (len_neq_error(pwr_constr->len, 1))
1574 return 0;
1576 tprintf("Local Power Constraint: %udB", pwr_constr->local_pwr_constr);
1578 return 1;
1581 static int8_t inf_pwr_cap(struct pkt_buff *pkt, u8 *id)
1583 struct element_pwr_cap *pwr_cap;
1585 pwr_cap = (struct element_pwr_cap *) pkt_pull(pkt, sizeof(*pwr_cap));
1586 if (pwr_cap == NULL)
1587 return 0;
1589 tprintf(" Power Capability (%u, Len(%u)): ", *id, pwr_cap->len);
1590 if (len_neq_error(pwr_cap->len, 2))
1591 return 0;
1593 tprintf("Min. Transm. Pwr Cap.: %ddBm, ", (int8_t)pwr_cap->min_pwr_cap);
1594 tprintf("Max. Transm. Pwr Cap.: %ddBm", (int8_t)pwr_cap->max_pwr_cap);
1596 return 1;
1599 static int8_t inf_tpc_req(struct pkt_buff *pkt, u8 *id)
1601 struct element_tpc_req *tpc_req;
1603 tpc_req = (struct element_tpc_req *) pkt_pull(pkt, sizeof(*tpc_req));
1604 if (tpc_req == NULL)
1605 return 0;
1607 tprintf(" TPC Request (%u, Len(%u))", *id, tpc_req->len);
1608 if (len_neq_error(tpc_req->len, 0))
1609 return 0;
1611 return 1;
1614 static int8_t inf_tpc_rep(struct pkt_buff *pkt, u8 *id)
1616 struct element_tpc_rep *tpc_rep;
1618 tpc_rep = (struct element_tpc_rep *) pkt_pull(pkt, sizeof(*tpc_rep));
1619 if (tpc_rep == NULL)
1620 return 0;
1622 tprintf(" TPC Report (%u, Len(%u)): ", *id, tpc_rep->len);
1623 if (len_neq_error(tpc_rep->len, 2))
1624 return 0;
1626 tprintf("Transmit Power: %udBm, ", (int8_t)tpc_rep->trans_pwr);
1627 tprintf("Link Margin: %udB", (int8_t)tpc_rep->trans_pwr);
1629 return 1;
1632 static int8_t inf_supp_ch(struct pkt_buff *pkt, u8 *id)
1634 struct element_supp_ch *supp_ch;
1635 u8 i;
1637 supp_ch = (struct element_supp_ch *) pkt_pull(pkt, sizeof(*supp_ch));
1638 if (supp_ch == NULL)
1639 return 0;
1641 tprintf(" Supp Channels (%u, Len(%u)): ", *id, supp_ch->len);
1642 if (len_lt_error(supp_ch->len, 2))
1643 return 0;
1645 if(supp_ch->len & 1) {
1646 tprintf("Length should be even");
1647 return 0;
1650 for (i = 0; i < supp_ch->len; i += 2) {
1651 struct element_supp_ch_tuple *supp_ch_tuple;
1653 supp_ch_tuple = (struct element_supp_ch_tuple *)
1654 pkt_pull(pkt, sizeof(*supp_ch_tuple));
1655 if (supp_ch_tuple == NULL)
1656 return 0;
1658 tprintf("First Channel Nr: %u, ", supp_ch_tuple->first_ch_nr);
1659 tprintf("Nr of Channels: %u, ", supp_ch_tuple->nr_ch);
1662 return 1;
1665 static int8_t inf_ch_sw_ann(struct pkt_buff *pkt, u8 *id)
1667 struct element_ch_sw_ann *ch_sw_ann;
1669 ch_sw_ann = (struct element_ch_sw_ann *)
1670 pkt_pull(pkt, sizeof(*ch_sw_ann));
1671 if (ch_sw_ann == NULL)
1672 return 0;
1674 tprintf(" Channel Switch Announc (%u, Len(%u)): ", *id, ch_sw_ann->len);
1675 if (len_neq_error(ch_sw_ann->len, 3))
1676 return 0;
1678 tprintf("Switch Mode: %u, ", ch_sw_ann->switch_mode);
1679 tprintf("New Nr: %u, ", ch_sw_ann->new_nr);
1680 tprintf("Switch Count: %u", ch_sw_ann->switch_cnt);
1682 return 1;
1685 static const char *meas_type(u8 type)
1687 switch (type) {
1688 case 0: return "Basic";
1689 case 1: return "Clear Channel assesment (CCA)";
1690 case 2: return "Receive power indication (RPI) histogram";
1691 case 3: return "Channel load";
1692 case 4: return "Noise histogram";
1693 case 5: return "Beacon";
1694 case 6: return "Frame";
1695 case 7: return "STA statistics";
1696 case 8: return "LCI";
1697 case 9: return "Transmit stream/category measurement";
1698 case 10: return "Multicast diagnostics";
1699 case 11: return "Location Civic";
1700 case 12: return "Location Identifier";
1701 case 13 ... 255: return "Reserved";
1705 static int8_t inf_meas_req(struct pkt_buff *pkt, u8 *id)
1707 struct element_meas_req *meas_req;
1709 meas_req = (struct element_meas_req *) pkt_pull(pkt, sizeof(*meas_req));
1710 if (meas_req == NULL)
1711 return 0;
1713 tprintf(" Measurement Req (%u, Len(%u)): ", *id, meas_req->len);
1714 if (len_lt_error(meas_req->len, 3))
1715 return 0;
1717 tprintf("Token: %u, ", meas_req->token);
1718 tprintf("Req Mode: 0x%x (Parallel (%u), Enable(%u), Request(%u), "
1719 "Report(%u), Dur Mand(%u), Res(0x%x)), ", meas_req->req_mode,
1720 meas_req->req_mode & 0x1,
1721 (meas_req->req_mode >> 1) & 0x1,
1722 (meas_req->req_mode >> 2) & 0x1,
1723 (meas_req->req_mode >> 3) & 0x1,
1724 (meas_req->req_mode >> 4) & 0x1,
1725 meas_req->req_mode >> 7);
1726 tprintf("Type: %s (%u), ", meas_type(meas_req->type), meas_req->type);
1728 if(meas_req->len > 3) {
1729 if(meas_req->type == 0) {
1730 struct element_meas_basic *basic;
1732 basic = (struct element_meas_basic *)
1733 pkt_pull(pkt, sizeof(*basic));
1734 if (basic == NULL)
1735 return 0;
1737 if ((meas_req->len - 3 - sizeof(*basic)) != 0) {
1738 tprintf("Length of Req matchs not Type %u",
1739 meas_req->type);
1740 return 0;
1743 tprintf("Ch Nr: %uus, ", basic->ch_nr);
1744 tprintf("Meas Start Time: %lu, ",
1745 le64_to_cpu(basic->start));
1746 tprintf("Meas Duration: %fs",
1747 le16_to_cpu(basic->dur) * TU);
1750 else if(meas_req->type == 1) {
1751 struct element_meas_cca *cca;
1753 cca = (struct element_meas_cca *)
1754 pkt_pull(pkt, sizeof(*cca));
1755 if (cca == NULL)
1756 return 0;
1758 if ((meas_req->len - 3 - sizeof(*cca)) != 0) {
1759 tprintf("Length of Req matchs not Type %u",
1760 meas_req->type);
1761 return 0;
1764 tprintf("Ch Nr: %uus, ", cca->ch_nr);
1765 tprintf("Meas Start Time: %lu, ",
1766 le64_to_cpu(cca->start));
1767 tprintf("Meas Duration: %fs",
1768 le16_to_cpu(cca->dur) * TU);
1770 else if(meas_req->type == 2) {
1771 struct element_meas_rpi *rpi;
1773 rpi = (struct element_meas_rpi *)
1774 pkt_pull(pkt, sizeof(*rpi));
1775 if (rpi == NULL)
1776 return 0;
1778 if ((meas_req->len - 3 - sizeof(*rpi)) != 0) {
1779 tprintf("Length of Req matchs not Type %u",
1780 meas_req->type);
1781 return 0;
1784 tprintf("Ch Nr: %uus, ", rpi->ch_nr);
1785 tprintf("Meas Start Time: %lu, ",
1786 le64_to_cpu(rpi->start));
1787 tprintf("Meas Duration: %fs",
1788 le16_to_cpu(rpi->dur) * TU);
1790 else if(meas_req->type == 3) {
1791 struct element_meas_ch_load *ch_load;
1793 ch_load = (struct element_meas_ch_load *)
1794 pkt_pull(pkt, sizeof(*ch_load));
1795 if (ch_load == NULL)
1796 return 0;
1798 if ((ssize_t)(meas_req->len - 3 - sizeof(*ch_load)) < 0) {
1799 tprintf("Length of Req matchs not Type %u",
1800 meas_req->type);
1801 return 0;
1804 tprintf("OP Class: %u, ", ch_load->op_class);
1805 tprintf("Ch Nr: %u, ", ch_load->ch_nr);
1806 tprintf("Rand Intv: %fs, ",
1807 le16_to_cpu(ch_load->rand_intv) * TU);
1808 tprintf("Meas Duration: %fs",
1809 le16_to_cpu(ch_load->dur) * TU);
1811 if(!subelements(pkt,
1812 meas_req->len - 3 - sizeof(*ch_load)))
1813 return 0;
1815 else if(meas_req->type == 4) {
1816 struct element_meas_noise *noise;
1818 noise = (struct element_meas_noise *)
1819 pkt_pull(pkt, sizeof(*noise));
1820 if (noise == NULL)
1821 return 0;
1823 if ((ssize_t)(meas_req->len - 3 - sizeof(*noise)) < 0) {
1824 tprintf("Length of Req matchs not Type %u",
1825 meas_req->type);
1826 return 0;
1829 tprintf("OP Class: %u, ", noise->op_class);
1830 tprintf("Ch Nr: %u, ", noise->ch_nr);
1831 tprintf("Rand Intv: %fs, ",
1832 le16_to_cpu(noise->rand_intv) * TU);
1833 tprintf("Meas Duration: %fs",
1834 le16_to_cpu(noise->dur) * TU);
1836 if(!subelements(pkt,
1837 meas_req->len - 3 - sizeof(*noise)))
1838 return 0;
1840 else if(meas_req->type == 5) {
1841 struct element_meas_beacon *beacon;
1843 beacon = (struct element_meas_beacon *)
1844 pkt_pull(pkt, sizeof(*beacon));
1845 if (beacon == NULL)
1846 return 0;
1848 if ((ssize_t)(meas_req->len - 3 - sizeof(*beacon)) < 0) {
1849 tprintf("Length of Req matchs not Type %u",
1850 meas_req->type);
1851 return 0;
1854 tprintf("OP Class: %u, ", beacon->op_class);
1855 tprintf("Ch Nr: %u, ", beacon->ch_nr);
1856 tprintf("Rand Intv: %fs, ",
1857 le16_to_cpu(beacon->rand_intv) * TU);
1858 tprintf("Meas Duration: %fs",
1859 le16_to_cpu(beacon->dur) * TU);
1860 tprintf("Mode: %u, ", beacon->mode);
1861 tprintf("BSSID: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1862 beacon->bssid[0], beacon->bssid[1],
1863 beacon->bssid[2], beacon->bssid[3],
1864 beacon->bssid[4], beacon->bssid[5]);
1866 if(!subelements(pkt,
1867 meas_req->len - 3 - sizeof(*beacon)))
1868 return 0;
1870 else if(meas_req->type == 6) {
1871 struct element_meas_frame *frame;
1873 frame = (struct element_meas_frame *)
1874 pkt_pull(pkt, sizeof(*frame));
1875 if (frame == NULL)
1876 return 0;
1878 if ((ssize_t)(meas_req->len - 3 - sizeof(*frame)) < 0) {
1879 tprintf("Length of Req matchs not Type %u",
1880 meas_req->type);
1881 return 0;
1884 tprintf("OP Class: %u, ", frame->op_class);
1885 tprintf("Ch Nr: %u, ", frame->ch_nr);
1886 tprintf("Rand Intv: %fs, ",
1887 le16_to_cpu(frame->rand_intv) * TU);
1888 tprintf("Meas Duration: %fs",
1889 le16_to_cpu(frame->dur) * TU);
1890 tprintf("Request Type: %u, ", frame->frame);
1891 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1892 frame->mac[0], frame->mac[1],
1893 frame->mac[2], frame->mac[3],
1894 frame->mac[4], frame->mac[5]);
1896 if(!subelements(pkt,
1897 meas_req->len - 3 - sizeof(*frame)))
1898 return 0;
1900 else if(meas_req->type == 7) {
1901 struct element_meas_sta *sta;
1903 sta = (struct element_meas_sta *)
1904 pkt_pull(pkt, sizeof(*sta));
1905 if (sta == NULL)
1906 return 0;
1908 if ((ssize_t)(meas_req->len - 3 - sizeof(*sta)) < 0) {
1909 tprintf("Length of Req matchs not Type %u",
1910 meas_req->type);
1911 return 0;
1914 tprintf("Peer MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1915 sta->peer_mac[0], sta->peer_mac[1],
1916 sta->peer_mac[2], sta->peer_mac[3],
1917 sta->peer_mac[4], sta->peer_mac[5]);
1918 tprintf("Rand Intv: %fs, ",
1919 le16_to_cpu(sta->rand_intv) * TU);
1920 tprintf("Meas Duration: %fs",
1921 le16_to_cpu(sta->dur) * TU);
1922 tprintf("Group ID: %u, ", sta->group_id);
1924 if(!subelements(pkt,
1925 meas_req->len - 3 - sizeof(*sta)))
1926 return 0;
1928 else if(meas_req->type == 8) {
1929 struct element_meas_lci *lci;
1931 lci = (struct element_meas_lci *)
1932 pkt_pull(pkt, sizeof(*lci));
1933 if (lci == NULL)
1934 return 0;
1936 if ((ssize_t)(meas_req->len - 3 - sizeof(*lci)) < 0) {
1937 tprintf("Length of Req matchs not Type %u",
1938 meas_req->type);
1939 return 0;
1942 tprintf("Location Subj: %u, ", lci->loc_subj);
1943 tprintf("Latitude Req Res: %udeg",
1944 lci->latitude_req_res);
1945 tprintf("Longitude Req Res: %udeg",
1946 lci->longitude_req_res);
1947 tprintf("Altitude Req Res: %udeg",
1948 lci->altitude_req_res);
1950 if(!subelements(pkt,
1951 meas_req->len - 3 - sizeof(*lci)))
1952 return 0;
1954 else if(meas_req->type == 9) {
1955 struct element_meas_trans_str_cat *trans;
1957 trans = (struct element_meas_trans_str_cat *)
1958 pkt_pull(pkt, sizeof(*trans));
1959 if (trans == NULL)
1960 return 0;
1962 if ((ssize_t)(meas_req->len - 3 - sizeof(*trans)) < 0) {
1963 tprintf("Length of Req matchs not Type %u",
1964 meas_req->type);
1965 return 0;
1968 tprintf("Rand Intv: %fs, ",
1969 le16_to_cpu(trans->rand_intv) * TU);
1970 tprintf("Meas Duration: %fs",
1971 le16_to_cpu(trans->dur) * TU);
1972 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1973 trans->peer_sta_addr[0], trans->peer_sta_addr[1],
1974 trans->peer_sta_addr[2], trans->peer_sta_addr[3],
1975 trans->peer_sta_addr[4], trans->peer_sta_addr[5]);
1976 tprintf("Traffic ID: %u, ", trans->traffic_id);
1977 tprintf("Bin 0 Range: %u, ", trans->bin_0_range);
1979 if(!subelements(pkt,
1980 meas_req->len - 3 - sizeof(*trans)))
1981 return 0;
1983 else if(meas_req->type == 10) {
1984 struct element_meas_mcast_diag *mcast;
1986 mcast = (struct element_meas_mcast_diag *)
1987 pkt_pull(pkt, sizeof(*mcast));
1988 if (mcast == NULL)
1989 return 0;
1991 if ((ssize_t)(meas_req->len - 3 - sizeof(*mcast)) < 0) {
1992 tprintf("Length of Req matchs not Type %u",
1993 meas_req->type);
1994 return 0;
1997 tprintf("Rand Intv: %fs, ",
1998 le16_to_cpu(mcast->rand_intv) * TU);
1999 tprintf("Meas Duration: %fs",
2000 le16_to_cpu(mcast->dur) * TU);
2001 tprintf("Group MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2002 mcast->group_mac[0], mcast->group_mac[1],
2003 mcast->group_mac[2], mcast->group_mac[3],
2004 mcast->group_mac[4], mcast->group_mac[5]);
2006 if(!subelements(pkt,
2007 meas_req->len - 3 - sizeof(*mcast)))
2008 return 0;
2010 else if(meas_req->type == 11) {
2011 struct element_meas_loc_civic *civic;
2013 civic = (struct element_meas_loc_civic *)
2014 pkt_pull(pkt, sizeof(*civic));
2015 if (civic == NULL)
2016 return 0;
2018 if ((ssize_t)(meas_req->len - 3 - sizeof(*civic)) < 0) {
2019 tprintf("Length of Req matchs not Type %u",
2020 meas_req->type);
2021 return 0;
2024 tprintf("Location Subj: %u, ", civic->loc_subj);
2025 tprintf("Type: %u, ", civic->civic_loc);
2026 tprintf("Srv Intv Units: %u, ",
2027 le16_to_cpu(civic->loc_srv_intv_unit));
2028 tprintf("Srv Intv: %u, ", civic->loc_srv_intv);
2030 if(!subelements(pkt,
2031 meas_req->len - 3 - sizeof(*civic)))
2032 return 0;
2034 else if(meas_req->type == 12) {
2035 struct element_meas_loc_id *id;
2037 id = (struct element_meas_loc_id *)
2038 pkt_pull(pkt, sizeof(*id));
2039 if (id == NULL)
2040 return 0;
2042 if ((ssize_t)(meas_req->len - 3 - sizeof(*id)) < 0) {
2043 tprintf("Length of Req matchs not Type %u",
2044 meas_req->type);
2045 return 0;
2048 tprintf("Location Subj: %u, ", id->loc_subj);
2049 tprintf("Srv Intv Units: %u, ",
2050 le16_to_cpu(id->loc_srv_intv_unit));
2051 tprintf("Srv Intv: %u", id->loc_srv_intv);
2053 if(!subelements(pkt,
2054 meas_req->len - 3 - sizeof(*id)))
2055 return 0;
2057 else if(meas_req->type == 255) {
2058 struct element_meas_pause *pause;
2060 pause = (struct element_meas_pause *)
2061 pkt_pull(pkt, sizeof(*pause));
2062 if (pause == NULL)
2063 return 0;
2065 if ((ssize_t)(meas_req->len - 3 - sizeof(*pause)) < 0) {
2066 tprintf("Length of Req matchs not Type %u",
2067 meas_req->type);
2068 return 0;
2071 tprintf("Pause Time: %fs, ", pause->time * 10 * TU);
2073 if(!subelements(pkt,
2074 meas_req->len - 3 - sizeof(*pause)))
2075 return 0;
2077 else {
2078 tprintf("Length field indicates data,"
2079 " but could not interpreted");
2080 return 0;
2084 return 1;
2087 static int8_t inf_meas_rep(struct pkt_buff *pkt, u8 *id)
2089 struct element_meas_rep *meas_rep;
2091 meas_rep = (struct element_meas_rep *) pkt_pull(pkt, sizeof(*meas_rep));
2092 if (meas_rep == NULL)
2093 return 0;
2095 tprintf(" Measurement Rep (%u, Len(%u)): ", *id, meas_rep->len);
2096 if (len_lt_error(meas_rep->len, 3))
2097 return 0;
2099 tprintf("Token: %u, ", meas_rep->token);
2100 tprintf("Rep Mode: 0x%x (Late (%u), Incapable(%u), Refused(%u), ",
2101 meas_rep->rep_mode, meas_rep->rep_mode >> 7,
2102 (meas_rep->rep_mode >> 6) & 0x1,
2103 (meas_rep->rep_mode >> 5) & 0x1);
2104 tprintf("Type: %s (%u), ", meas_type(meas_rep->type), meas_rep->type);
2106 if(meas_rep->len > 3) {
2107 if(meas_rep->type == 0) {
2108 struct element_meas_basic *basic;
2110 basic = (struct element_meas_basic *)
2111 pkt_pull(pkt, sizeof(*basic));
2112 if (basic == NULL)
2113 return 0;
2115 if ((meas_rep->len - 3 - sizeof(*basic)) != 0) {
2116 tprintf("Length of Req matchs not Type %u",
2117 meas_rep->type);
2118 return 0;
2121 tprintf("Ch Nr: %uus, ", basic->ch_nr);
2122 tprintf("Meas Start Time: %lu, ",
2123 le64_to_cpu(basic->start));
2124 tprintf("Meas Duration: %fs",
2125 le16_to_cpu(basic->dur) * TU);
2128 else if(meas_rep->type == 1) {
2129 struct element_meas_cca *cca;
2131 cca = (struct element_meas_cca *)
2132 pkt_pull(pkt, sizeof(*cca));
2133 if (cca == NULL)
2134 return 0;
2136 if ((meas_rep->len - 3 - sizeof(*cca)) != 0) {
2137 tprintf("Length of Req matchs not Type %u",
2138 meas_rep->type);
2139 return 0;
2142 tprintf("Ch Nr: %uus, ", cca->ch_nr);
2143 tprintf("Meas Start Time: %lu, ",
2144 le64_to_cpu(cca->start));
2145 tprintf("Meas Duration: %fs",
2146 le16_to_cpu(cca->dur) * TU);
2148 else if(meas_rep->type == 2) {
2149 struct element_meas_rpi *rpi;
2151 rpi = (struct element_meas_rpi *)
2152 pkt_pull(pkt, sizeof(*rpi));
2153 if (rpi == NULL)
2154 return 0;
2156 if ((meas_rep->len - 3 - sizeof(*rpi)) != 0) {
2157 tprintf("Length of Req matchs not Type %u",
2158 meas_rep->type);
2159 return 0;
2162 tprintf("Ch Nr: %uus, ", rpi->ch_nr);
2163 tprintf("Meas Start Time: %lu, ",
2164 le64_to_cpu(rpi->start));
2165 tprintf("Meas Duration: %fs",
2166 le16_to_cpu(rpi->dur) * TU);
2168 else if(meas_rep->type == 3) {
2169 struct element_meas_ch_load *ch_load;
2171 ch_load = (struct element_meas_ch_load *)
2172 pkt_pull(pkt, sizeof(*ch_load));
2173 if (ch_load == NULL)
2174 return 0;
2176 if ((ssize_t)(meas_rep->len - 3 - sizeof(*ch_load)) < 0) {
2177 tprintf("Length of Req matchs not Type %u",
2178 meas_rep->type);
2179 return 0;
2182 tprintf("OP Class: %u, ", ch_load->op_class);
2183 tprintf("Ch Nr: %u, ", ch_load->ch_nr);
2184 tprintf("Rand Intv: %fs, ",
2185 le16_to_cpu(ch_load->rand_intv) * TU);
2186 tprintf("Meas Duration: %fs",
2187 le16_to_cpu(ch_load->dur) * TU);
2189 if(!subelements(pkt,
2190 meas_rep->len - 3 - sizeof(*ch_load)))
2191 return 0;
2193 else if(meas_rep->type == 4) {
2194 struct element_meas_noise *noise;
2196 noise = (struct element_meas_noise *)
2197 pkt_pull(pkt, sizeof(*noise));
2198 if (noise == NULL)
2199 return 0;
2201 if ((ssize_t)(meas_rep->len - 3 - sizeof(*noise)) < 0) {
2202 tprintf("Length of Req matchs not Type %u",
2203 meas_rep->type);
2204 return 0;
2207 tprintf("OP Class: %u, ", noise->op_class);
2208 tprintf("Ch Nr: %u, ", noise->ch_nr);
2209 tprintf("Rand Intv: %fs, ",
2210 le16_to_cpu(noise->rand_intv) * TU);
2211 tprintf("Meas Duration: %fs",
2212 le16_to_cpu(noise->dur) * TU);
2214 if(!subelements(pkt,
2215 meas_rep->len - 3 - sizeof(*noise)))
2216 return 0;
2218 else if(meas_rep->type == 5) {
2219 struct element_meas_beacon *beacon;
2221 beacon = (struct element_meas_beacon *)
2222 pkt_pull(pkt, sizeof(*beacon));
2223 if (beacon == NULL)
2224 return 0;
2226 if ((ssize_t)(meas_rep->len - 3 - sizeof(*beacon)) < 0) {
2227 tprintf("Length of Req matchs not Type %u",
2228 meas_rep->type);
2229 return 0;
2232 tprintf("OP Class: %u, ", beacon->op_class);
2233 tprintf("Ch Nr: %u, ", beacon->ch_nr);
2234 tprintf("Rand Intv: %fs, ",
2235 le16_to_cpu(beacon->rand_intv) * TU);
2236 tprintf("Meas Duration: %fs",
2237 le16_to_cpu(beacon->dur) * TU);
2238 tprintf("Mode: %u, ", beacon->mode);
2239 tprintf("BSSID: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2240 beacon->bssid[0], beacon->bssid[1],
2241 beacon->bssid[2], beacon->bssid[3],
2242 beacon->bssid[4], beacon->bssid[5]);
2244 if(!subelements(pkt,
2245 meas_rep->len - 3 - sizeof(*beacon)))
2246 return 0;
2248 else if(meas_rep->type == 6) {
2249 struct element_meas_frame *frame;
2251 frame = (struct element_meas_frame *)
2252 pkt_pull(pkt, sizeof(*frame));
2253 if (frame == NULL)
2254 return 0;
2256 if ((ssize_t)(meas_rep->len - 3 - sizeof(*frame)) < 0) {
2257 tprintf("Length of Req matchs not Type %u",
2258 meas_rep->type);
2259 return 0;
2262 tprintf("OP Class: %u, ", frame->op_class);
2263 tprintf("Ch Nr: %u, ", frame->ch_nr);
2264 tprintf("Rand Intv: %fs, ",
2265 le16_to_cpu(frame->rand_intv) * TU);
2266 tprintf("Meas Duration: %fs",
2267 le16_to_cpu(frame->dur) * TU);
2268 tprintf("Request Type: %u, ", frame->frame);
2269 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2270 frame->mac[0], frame->mac[1],
2271 frame->mac[2], frame->mac[3],
2272 frame->mac[4], frame->mac[5]);
2274 if(!subelements(pkt,
2275 meas_rep->len - 3 - sizeof(*frame)))
2276 return 0;
2278 else if(meas_rep->type == 7) {
2279 struct element_meas_sta *sta;
2281 sta = (struct element_meas_sta *)
2282 pkt_pull(pkt, sizeof(*sta));
2283 if (sta == NULL)
2284 return 0;
2286 if ((ssize_t)(meas_rep->len - 3 - sizeof(*sta)) < 0) {
2287 tprintf("Length of Req matchs not Type %u",
2288 meas_rep->type);
2289 return 0;
2292 tprintf("Peer MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2293 sta->peer_mac[0], sta->peer_mac[1],
2294 sta->peer_mac[2], sta->peer_mac[3],
2295 sta->peer_mac[4], sta->peer_mac[5]);
2296 tprintf("Rand Intv: %fs, ",
2297 le16_to_cpu(sta->rand_intv) * TU);
2298 tprintf("Meas Duration: %fs",
2299 le16_to_cpu(sta->dur) * TU);
2300 tprintf("Group ID: %u, ", sta->group_id);
2302 if(!subelements(pkt,
2303 meas_rep->len - 3 - sizeof(*sta)))
2304 return 0;
2306 else if(meas_rep->type == 8) {
2307 struct element_meas_lci *lci;
2309 lci = (struct element_meas_lci *)
2310 pkt_pull(pkt, sizeof(*lci));
2311 if (lci == NULL)
2312 return 0;
2314 if ((ssize_t)(meas_rep->len - 3 - sizeof(*lci)) < 0) {
2315 tprintf("Length of Req matchs not Type %u",
2316 meas_rep->type);
2317 return 0;
2320 tprintf("Location Subj: %u, ", lci->loc_subj);
2321 tprintf("Latitude Req Res: %udeg",
2322 lci->latitude_req_res);
2323 tprintf("Longitude Req Res: %udeg",
2324 lci->longitude_req_res);
2325 tprintf("Altitude Req Res: %udeg",
2326 lci->altitude_req_res);
2328 if(!subelements(pkt,
2329 meas_rep->len - 3 - sizeof(*lci)))
2330 return 0;
2332 else if(meas_rep->type == 9) {
2333 struct element_meas_trans_str_cat *trans;
2335 trans = (struct element_meas_trans_str_cat *)
2336 pkt_pull(pkt, sizeof(*trans));
2337 if (trans == NULL)
2338 return 0;
2340 if ((ssize_t)(meas_rep->len - 3 - sizeof(*trans)) < 0) {
2341 tprintf("Length of Req matchs not Type %u",
2342 meas_rep->type);
2343 return 0;
2346 tprintf("Rand Intv: %fs, ",
2347 le16_to_cpu(trans->rand_intv) * TU);
2348 tprintf("Meas Duration: %fs",
2349 le16_to_cpu(trans->dur) * TU);
2350 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2351 trans->peer_sta_addr[0], trans->peer_sta_addr[1],
2352 trans->peer_sta_addr[2], trans->peer_sta_addr[3],
2353 trans->peer_sta_addr[4], trans->peer_sta_addr[5]);
2354 tprintf("Traffic ID: %u, ", trans->traffic_id);
2355 tprintf("Bin 0 Range: %u, ", trans->bin_0_range);
2357 if(!subelements(pkt,
2358 meas_rep->len - 3 - sizeof(*trans)))
2359 return 0;
2361 else if(meas_rep->type == 10) {
2362 struct element_meas_mcast_diag *mcast;
2364 mcast = (struct element_meas_mcast_diag *)
2365 pkt_pull(pkt, sizeof(*mcast));
2366 if (mcast == NULL)
2367 return 0;
2369 if ((ssize_t)(meas_rep->len - 3 - sizeof(*mcast)) < 0) {
2370 tprintf("Length of Req matchs not Type %u",
2371 meas_rep->type);
2372 return 0;
2375 tprintf("Rand Intv: %fs, ",
2376 le16_to_cpu(mcast->rand_intv) * TU);
2377 tprintf("Meas Duration: %fs",
2378 le16_to_cpu(mcast->dur) * TU);
2379 tprintf("Group MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2380 mcast->group_mac[0], mcast->group_mac[1],
2381 mcast->group_mac[2], mcast->group_mac[3],
2382 mcast->group_mac[4], mcast->group_mac[5]);
2384 if(!subelements(pkt,
2385 meas_rep->len - 3 - sizeof(*mcast)))
2386 return 0;
2388 else if(meas_rep->type == 11) {
2389 struct element_meas_loc_civic *civic;
2391 civic = (struct element_meas_loc_civic *)
2392 pkt_pull(pkt, sizeof(*civic));
2393 if (civic == NULL)
2394 return 0;
2396 if ((ssize_t)(meas_rep->len - 3 - sizeof(*civic)) < 0) {
2397 tprintf("Length of Req matchs not Type %u",
2398 meas_rep->type);
2399 return 0;
2402 tprintf("Location Subj: %u, ", civic->loc_subj);
2403 tprintf("Type: %u, ", civic->civic_loc);
2404 tprintf("Srv Intv Units: %u, ",
2405 le16_to_cpu(civic->loc_srv_intv_unit));
2406 tprintf("Srv Intv: %u, ", civic->loc_srv_intv);
2408 if(!subelements(pkt,
2409 meas_rep->len - 3 - sizeof(*civic)))
2410 return 0;
2412 else if(meas_rep->type == 12) {
2413 struct element_meas_loc_id *id;
2415 id = (struct element_meas_loc_id *)
2416 pkt_pull(pkt, sizeof(*id));
2417 if (id == NULL)
2418 return 0;
2420 if ((ssize_t)(meas_rep->len - 3 - sizeof(*id)) < 0) {
2421 tprintf("Length of Req matchs not Type %u",
2422 meas_rep->type);
2423 return 0;
2426 tprintf("Location Subj: %u, ", id->loc_subj);
2427 tprintf("Srv Intv Units: %u, ",
2428 le16_to_cpu(id->loc_srv_intv_unit));
2429 tprintf("Srv Intv: %u", id->loc_srv_intv);
2431 if(!subelements(pkt,
2432 meas_rep->len - 3 - sizeof(*id)))
2433 return 0;
2435 else {
2436 tprintf("Length field indicates data,"
2437 " but could not interpreted");
2438 return 0;
2442 return 1;
2445 static int8_t inf_quiet(struct pkt_buff *pkt, u8 *id)
2447 struct element_quiet *quiet;
2449 quiet = (struct element_quiet *) pkt_pull(pkt, sizeof(*quiet));
2450 if (quiet == NULL)
2451 return 0;
2453 tprintf(" Quit (%u, Len(%u)): ", *id, quiet->len);
2454 if (len_neq_error(quiet->len, 6))
2455 return 0;
2457 tprintf("Count: %ud, ", quiet->cnt);
2458 tprintf("Period: %u, ", quiet->period);
2459 tprintf("Duration: %fs, ", le16_to_cpu(quiet->dur) * TU);
2460 tprintf("Offs: %fs", le16_to_cpu(quiet->offs) * TU);
2463 return 1;
2466 static int8_t inf_ibss_dfs(struct pkt_buff *pkt, u8 *id)
2468 struct element_ibss_dfs *ibss_dfs;
2469 u8 i;
2471 ibss_dfs = (struct element_ibss_dfs *) pkt_pull(pkt, sizeof(*ibss_dfs));
2472 if (ibss_dfs == NULL)
2473 return 0;
2475 tprintf(" IBSS DFS (%u, Len(%u)): ", *id, ibss_dfs->len);
2476 if (len_lt_error(ibss_dfs->len, 7))
2477 return 0;
2479 tprintf("Owner: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2480 ibss_dfs->owner[0], ibss_dfs->owner[1],
2481 ibss_dfs->owner[2], ibss_dfs->owner[3],
2482 ibss_dfs->owner[4], ibss_dfs->owner[5]);
2483 tprintf("Recovery Intv: %u, ", ibss_dfs->rec_intv);
2485 if((ibss_dfs->len - sizeof(*ibss_dfs) + 1) & 1) {
2486 tprintf("Length of Channel Map should be modulo 2");
2487 return 0;
2490 for (i = 0; i < ibss_dfs->len; i += 2) {
2491 struct element_ibss_dfs_tuple *ibss_dfs_tuple;
2493 ibss_dfs_tuple = (struct element_ibss_dfs_tuple *)
2494 pkt_pull(pkt, sizeof(*ibss_dfs_tuple));
2495 if (ibss_dfs_tuple == NULL)
2496 return 0;
2498 tprintf("Channel Nr: %u, ", ibss_dfs_tuple->ch_nr);
2499 tprintf("Map: %u, ", ibss_dfs_tuple->map);
2502 return 1;
2505 static int8_t inf_erp(struct pkt_buff *pkt, u8 *id)
2507 struct element_erp *erp;
2509 erp = (struct element_erp *) pkt_pull(pkt, sizeof(*erp));
2510 if (erp == NULL)
2511 return 0;
2513 tprintf(" ERP (%u, Len(%u)): ", *id, erp->len);
2514 if (len_neq_error(erp->len, 1))
2515 return 0;
2516 tprintf("Non ERP Present (%u), ", erp->param & 0x1);
2517 tprintf("Use Protection (%u), ", (erp->param >> 1) & 0x1);
2518 tprintf("Barker Preamble Mode (%u), ", (erp->param >> 2) & 0x1);
2519 tprintf("Reserved (0x%.5x)", erp->param >> 3);
2521 return 1;
2524 static int8_t inf_ts_del(struct pkt_buff *pkt, u8 *id)
2526 struct element_ts_del *ts_del;
2528 ts_del = (struct element_ts_del *) pkt_pull(pkt, sizeof(*ts_del));
2529 if (ts_del == NULL)
2530 return 0;
2532 tprintf(" TS Delay (%u, Len(%u)): ", *id, ts_del->len);
2533 if (len_neq_error(ts_del->len, 4))
2534 return 0;
2535 tprintf("Delay (%fs)", le32_to_cpu(ts_del->delay) * TU);
2537 return 1;
2540 static int8_t inf_tclas_proc(struct pkt_buff *pkt, u8 *id)
2542 struct element_tclas_proc *tclas_proc;
2544 tclas_proc = (struct element_tclas_proc *)
2545 pkt_pull(pkt, sizeof(*tclas_proc));
2546 if (tclas_proc == NULL)
2547 return 0;
2549 tprintf(" TCLAS Procesing (%u, Len(%u)): ", *id, tclas_proc->len);
2550 if (len_neq_error(tclas_proc->len, 1))
2551 return 0;
2552 tprintf("Processing (%u)", tclas_proc->proc);
2554 return 1;
2557 static int8_t inf_ht_cap(struct pkt_buff *pkt, u8 *id)
2559 struct element_ht_cap *ht_cap;
2560 u32 tx_param_res, beam_cap;
2561 u16 ext_cap;
2563 ht_cap = (struct element_ht_cap *)
2564 pkt_pull(pkt, sizeof(*ht_cap));
2565 if (ht_cap == NULL)
2566 return 0;
2568 tx_param_res = le32_to_cpu(ht_cap->tx_param_res);
2569 beam_cap = le32_to_cpu(ht_cap->beam_cap);
2570 ext_cap = le16_to_cpu(ht_cap->ext_cap);
2572 tprintf(" HT Capabilities (%u, Len(%u)): ", *id, ht_cap->len);
2573 if (len_neq_error(ht_cap->len, 26))
2574 return 0;
2575 tprintf("Info (LDCP Cod Cap (%u), Supp Ch Width Set (%u),"
2576 " SM Pwr Save(%u), HT-Greenfield (%u), Short GI for 20/40 MHz"
2577 " (%u/%u), Tx/Rx STBC (%u/%u), HT-Delayed Block Ack (%u),"
2578 " Max A-MSDU Len (%u), DSSS/CCK Mode in 40 MHz (%u),"
2579 " Res (0x%x), Forty MHz Intol (%u), L-SIG TXOP Protection Supp"
2580 " (%u)), ", ht_cap->ldpc, ht_cap->supp_width,
2581 ht_cap->sm_pwr, ht_cap->ht_green, ht_cap->gi_20mhz,
2582 ht_cap->gi_40mhz, ht_cap->tx_stbc, ht_cap->rx_stbc,
2583 ht_cap->ht_ack, ht_cap->max_msdu_length, ht_cap->dsss_ck_mode,
2584 ht_cap->res, ht_cap->forty_int, ht_cap->prot_supp);
2585 tprintf("A-MPDU Params (Max Len Exp (%u), Min Start Spacing (%u),"
2586 " Res (0x%x)), ", ht_cap->param >> 6, (ht_cap->param >> 3) & 0x7,
2587 ht_cap->param & 0x07);
2588 tprintf("Supp MCS Set (Rx MCS Bitmask (0x%x%x%x%x%x%x%x%x%x%x),"
2589 " Res (0x%x), Rx High Supp Data Rate (%u), Res (0x%x),"
2590 " Tx MCS Set Def (%u), Tx Rx MCS Set Not Eq (%u),"
2591 " Tx Max Number Spat Str Supp (%u),"
2592 " Tx Uneq Mod Supp (%u), Res (0x%x)), ",
2593 ht_cap->bitmask1, ht_cap->bitmask2, ht_cap->bitmask3,
2594 ht_cap->bitmask4, ht_cap->bitmask5, ht_cap->bitmask6,
2595 ht_cap->bitmask7, ht_cap->bitmask8, ht_cap->bitmask9,
2596 ht_cap->bitmask10_res >> 3, ht_cap->bitmask10_res & 0x7,
2597 le16_to_cpu(ht_cap->supp_rate_res) >> 6,
2598 le16_to_cpu(ht_cap->supp_rate_res) & 0x3F,
2599 tx_param_res >> 31, (tx_param_res >> 30) & 1,
2600 (tx_param_res >> 28) & 3, (tx_param_res >> 27) & 1,
2601 tx_param_res & 0x7FFFFFF);
2602 tprintf("Ext Cap (PCO (%u), PCO Trans Time (%u), Res (0x%x),"
2603 " MCS Feedb (%u), +HTC Supp (%u), RD Resp (%u), Res (0x%x)), ",
2604 ext_cap >> 15, (ext_cap >> 13) & 3, (ext_cap >> 8) & 0x1F,
2605 (ext_cap >> 6) & 3, (ext_cap >> 5) & 1, (ext_cap >> 4) & 1,
2606 ext_cap & 0xF);
2607 tprintf("Transm Beamf (Impl Transm Beamf Rec Cap (%u),"
2608 " Rec/Transm Stagg Sound Cap (%u/%u),"
2609 " Rec/Trans NDP Cap (%u/%u), Impl Transm Beamf Cap (%u),"
2610 " Cal (%u), Expl CSI Transm Beamf Cap (%u),"
2611 " Expl Noncmpr/Compr Steering Cap (%u/%u),"
2612 " Expl Trans Beamf CSI Feedb (%u),"
2613 " Expl Noncmpr/Cmpr Feedb Cap (%u/%u),"
2614 " Min Grpg (%u), CSI Num Beamf Ant Supp (%u),"
2615 " Noncmpr/Cmpr Steering Nr Beamf Ant Supp (%u/%u),"
2616 " CSI Max Nr Rows Beamf Supp (%u),"
2617 " Ch Estim Cap (%u), Res (0x%x)), ",
2618 beam_cap >> 31, (beam_cap >> 30) & 1, (beam_cap >> 29) & 1,
2619 (beam_cap >> 28) & 1, (beam_cap >> 27) & 1, (beam_cap >> 26) & 1,
2620 (beam_cap >> 24) & 3, (beam_cap >> 23) & 1, (beam_cap >> 22) & 1,
2621 (beam_cap >> 21) & 1, (beam_cap >> 19) & 3, (beam_cap >> 17) & 3,
2622 (beam_cap >> 15) & 3, (beam_cap >> 13) & 3, (beam_cap >> 11) & 3,
2623 (beam_cap >> 9) & 3, (beam_cap >> 7) & 3, (beam_cap >> 5) & 3,
2624 (beam_cap >> 3) & 3, beam_cap & 7);
2625 tprintf("ASEL (Ant Select Cap (%u),"
2626 " Expl CSI Feedb Based Transm ASEL Cap (%u),"
2627 " Ant Indic Feedb Based Transm ASEL Cap (%u),"
2628 " Expl CSI Feedb Cap (%u), Ant Indic Feedb Cap (%u),"
2629 " Rec ASEL Cap (%u), Transm Sound PPDUs Cap (%u), Res (0x%x))",
2630 ht_cap->asel_cap >> 7, (ht_cap->asel_cap >> 6) & 1,
2631 (ht_cap->asel_cap >> 5) & 1, (ht_cap->asel_cap >> 4) & 1,
2632 (ht_cap->asel_cap >> 3) & 1, (ht_cap->asel_cap >> 2) & 1,
2633 (ht_cap->asel_cap >> 1) & 1, ht_cap->asel_cap & 1);
2635 return 1;
2638 static int8_t inf_qos_cap(struct pkt_buff *pkt, u8 *id)
2640 struct element_qos_cap *qos_cap;
2642 qos_cap = (struct element_qos_cap *)
2643 pkt_pull(pkt, sizeof(*qos_cap));
2644 if (qos_cap == NULL)
2645 return 0;
2647 tprintf(" QoS Capabilities (%u, Len(%u)): ", *id, qos_cap->len);
2648 if (len_neq_error(qos_cap->len, 1))
2649 return 0;
2651 tprintf("Info (0x%x)", qos_cap->info);
2653 return 1;
2656 static int8_t inf_ext_supp_rates(struct pkt_buff *pkt, u8 *id)
2658 u8 i;
2659 u8 *rates;
2660 struct element_ext_supp_rates *ext_supp_rates;
2662 ext_supp_rates = (struct element_ext_supp_rates *)
2663 pkt_pull(pkt, sizeof(*ext_supp_rates));
2664 if (ext_supp_rates == NULL)
2665 return 0;
2667 tprintf(" Ext Support Rates (%u, Len(%u)): ", *id, ext_supp_rates->len);
2669 if ((ext_supp_rates->len - sizeof(*ext_supp_rates) + 1) > 0) {
2670 rates = pkt_pull(pkt, ext_supp_rates->len);
2671 if (rates == NULL)
2672 return 0;
2674 for (i = 0; i < ext_supp_rates->len; i++)
2675 tprintf("%g ", (rates[i] & 0x80) ?
2676 ((rates[i] & 0x3f) * 0.5) :
2677 data_rates(rates[i]));
2678 return 1;
2681 return 0;
2684 static int8_t inf_vend_spec(struct pkt_buff *pkt, u8 *id)
2686 u8 i;
2687 u8 *data;
2688 struct element_vend_spec *vend_spec;
2690 vend_spec = (struct element_vend_spec *)
2691 pkt_pull(pkt, sizeof(*vend_spec));
2692 if (vend_spec == NULL)
2693 return 0;
2695 tprintf(" Vendor Specific (%u, Len (%u)): ", *id, vend_spec->len);
2697 data = pkt_pull(pkt, vend_spec->len);
2698 if (data == NULL)
2699 return 0;
2701 tprintf("Data 0x");
2702 for (i = 0; i < vend_spec->len; i++)
2703 tprintf("%.2x", data[i]);
2705 return 1;
2708 static int8_t inf_unimplemented(struct pkt_buff *pkt __maybe_unused,
2709 u8 *id __maybe_unused)
2711 return 0;
2714 static int8_t inf_elements(struct pkt_buff *pkt)
2716 u8 *id = pkt_pull(pkt, 1);
2717 if (id == NULL)
2718 return 0;
2720 switch (*id) {
2721 case 0: return inf_ssid(pkt, id);
2722 case 1: return inf_supp_rates(pkt, id);
2723 case 2: return inf_fh_ps(pkt, id);
2724 case 3: return inf_dsss_ps(pkt, id);
2725 case 4: return inf_cf_ps(pkt, id);
2726 case 5: return inf_tim(pkt, id);
2727 case 6: return inf_ibss_ps(pkt, id);
2728 case 7: return inf_country(pkt, id);
2729 case 8: return inf_hop_pp(pkt, id);
2730 case 9: return inf_hop_pt(pkt, id);
2731 case 10: return inf_req(pkt, id);
2732 case 11: return inf_bss_load(pkt, id);
2733 case 12: return inf_edca_ps(pkt, id);
2734 case 13: return inf_tspec(pkt, id);
2735 case 14: return inf_tclas(pkt, id);
2736 case 15: return inf_sched(pkt, id);
2737 case 16: return inf_chall_txt(pkt, id);
2738 case 17 ... 31: return inf_reserved(pkt, id);
2739 case 32: return inf_pwr_constr(pkt, id);
2740 case 33: return inf_pwr_cap(pkt, id);
2741 case 34: return inf_tpc_req(pkt, id);
2742 case 35: return inf_tpc_rep(pkt, id);
2743 case 36: return inf_supp_ch(pkt, id);
2744 case 37: return inf_ch_sw_ann(pkt, id);
2745 case 38: return inf_meas_req(pkt, id);
2746 case 39: return inf_meas_rep(pkt, id);
2747 case 40: return inf_quiet(pkt, id);
2748 case 41: return inf_ibss_dfs(pkt, id);
2749 case 42: return inf_erp(pkt, id);
2750 case 43: return inf_ts_del(pkt, id);
2751 case 44: return inf_tclas_proc(pkt, id);
2752 case 45: return inf_ht_cap(pkt, id);
2753 case 46: return inf_qos_cap(pkt, id);
2754 case 47: return inf_reserved(pkt, id);
2755 case 48: return inf_unimplemented(pkt, id);
2756 case 49: return inf_unimplemented(pkt, id);
2757 case 50: return inf_ext_supp_rates(pkt, id);
2758 case 51: return inf_unimplemented(pkt, id);
2759 case 52: return inf_unimplemented(pkt, id);
2760 case 53: return inf_unimplemented(pkt, id);
2761 case 54: return inf_unimplemented(pkt, id);
2762 case 55: return inf_unimplemented(pkt, id);
2763 case 56: return inf_unimplemented(pkt, id);
2764 case 57: return inf_unimplemented(pkt, id);
2765 case 58: return inf_unimplemented(pkt, id);
2766 case 59: return inf_unimplemented(pkt, id);
2767 case 60: return inf_unimplemented(pkt, id);
2768 case 61: return inf_unimplemented(pkt, id);
2769 case 62: return inf_unimplemented(pkt, id);
2770 case 63: return inf_unimplemented(pkt, id);
2771 case 64: return inf_unimplemented(pkt, id);
2772 case 65: return inf_unimplemented(pkt, id);
2773 case 66: return inf_unimplemented(pkt, id);
2774 case 67: return inf_unimplemented(pkt, id);
2775 case 68: return inf_unimplemented(pkt, id);
2776 case 69: return inf_unimplemented(pkt, id);
2777 case 70: return inf_unimplemented(pkt, id);
2778 case 71: return inf_unimplemented(pkt, id);
2779 case 72: return inf_unimplemented(pkt, id);
2780 case 73: return inf_unimplemented(pkt, id);
2781 case 74: return inf_unimplemented(pkt, id);
2782 case 75: return inf_unimplemented(pkt, id);
2783 case 76: return inf_unimplemented(pkt, id);
2784 case 78: return inf_unimplemented(pkt, id);
2785 case 79: return inf_unimplemented(pkt, id);
2786 case 80: return inf_unimplemented(pkt, id);
2787 case 81: return inf_unimplemented(pkt, id);
2788 case 82: return inf_unimplemented(pkt, id);
2789 case 83: return inf_unimplemented(pkt, id);
2790 case 84: return inf_unimplemented(pkt, id);
2791 case 85: return inf_unimplemented(pkt, id);
2792 case 86: return inf_unimplemented(pkt, id);
2793 case 87: return inf_unimplemented(pkt, id);
2794 case 88: return inf_unimplemented(pkt, id);
2795 case 89: return inf_unimplemented(pkt, id);
2796 case 90: return inf_unimplemented(pkt, id);
2797 case 91: return inf_unimplemented(pkt, id);
2798 case 92: return inf_unimplemented(pkt, id);
2799 case 93: return inf_unimplemented(pkt, id);
2800 case 94: return inf_unimplemented(pkt, id);
2801 case 95: return inf_unimplemented(pkt, id);
2802 case 96: return inf_unimplemented(pkt, id);
2803 case 97: return inf_unimplemented(pkt, id);
2804 case 98: return inf_unimplemented(pkt, id);
2805 case 99: return inf_unimplemented(pkt, id);
2806 case 100: return inf_unimplemented(pkt, id);
2807 case 101: return inf_unimplemented(pkt, id);
2808 case 102: return inf_unimplemented(pkt, id);
2809 case 104: return inf_unimplemented(pkt, id);
2810 case 105: return inf_unimplemented(pkt, id);
2811 case 106: return inf_unimplemented(pkt, id);
2812 case 107: return inf_unimplemented(pkt, id);
2813 case 108: return inf_unimplemented(pkt, id);
2814 case 109: return inf_unimplemented(pkt, id);
2815 case 110: return inf_unimplemented(pkt, id);
2816 case 111: return inf_unimplemented(pkt, id);
2817 case 112: return inf_unimplemented(pkt, id);
2818 case 113: return inf_unimplemented(pkt, id);
2819 case 114: return inf_unimplemented(pkt, id);
2820 case 115: return inf_unimplemented(pkt, id);
2821 case 116: return inf_unimplemented(pkt, id);
2822 case 117: return inf_unimplemented(pkt, id);
2823 case 118: return inf_unimplemented(pkt, id);
2824 case 119: return inf_unimplemented(pkt, id);
2825 case 120: return inf_unimplemented(pkt, id);
2826 case 121: return inf_unimplemented(pkt, id);
2827 case 122: return inf_unimplemented(pkt, id);
2828 case 123: return inf_unimplemented(pkt, id);
2829 case 124: return inf_unimplemented(pkt, id);
2830 case 125: return inf_unimplemented(pkt, id);
2831 case 126: return inf_unimplemented(pkt, id);
2832 case 127: return inf_unimplemented(pkt, id);
2833 case 128: return inf_reserved(pkt, id);
2834 case 129: return inf_reserved(pkt, id);
2835 case 130: return inf_unimplemented(pkt, id);
2836 case 131: return inf_unimplemented(pkt, id);
2837 case 132: return inf_unimplemented(pkt, id);
2838 case 133: return inf_reserved(pkt, id);
2839 case 134: return inf_reserved(pkt, id);
2840 case 135: return inf_reserved(pkt, id);
2841 case 136: return inf_reserved(pkt, id);
2842 case 137: return inf_unimplemented(pkt, id);
2843 case 138: return inf_unimplemented(pkt, id);
2844 case 139: return inf_unimplemented(pkt, id);
2845 case 140: return inf_unimplemented(pkt, id);
2846 case 141: return inf_unimplemented(pkt, id);
2847 case 142: return inf_unimplemented(pkt, id);
2848 case 143 ... 173: return inf_reserved(pkt, id);
2849 case 174: return inf_unimplemented(pkt, id);
2850 case 221: return inf_vend_spec(pkt, id);
2853 return 0;
2856 #define ESS 0b0000000000000001
2857 #define IBSS 0b0000000000000010
2858 #define CF_Pollable 0b0000000000000100
2859 #define CF_Poll_Req 0b0000000000001000
2860 #define Privacy 0b0000000000010000
2861 #define Short_Pre 0b0000000000100000
2862 #define PBCC 0b0000000001000000
2863 #define Ch_Agility 0b0000000010000000
2864 #define Spec_Mgmt 0b0000000100000000
2865 #define QoS 0b0000001000000000
2866 #define Short_Slot_t 0b0000010000000000
2867 #define APSD 0b0000100000000000
2868 #define Radio_Meas 0b0001000000000000
2869 #define DSSS_OFDM 0b0010000000000000
2870 #define Del_Block_ACK 0b0100000000000000
2871 #define Imm_Block_ACK 0b1000000000000000
2873 static int8_t cap_field(u16 cap_inf)
2875 if (ESS & cap_inf)
2876 tprintf(" ESS;");
2877 if (IBSS & cap_inf)
2878 tprintf(" IBSS;");
2879 if (CF_Pollable & cap_inf)
2880 tprintf(" CF Pollable;");
2881 if (CF_Poll_Req & cap_inf)
2882 tprintf(" CF-Poll Request;");
2883 if (Privacy & cap_inf)
2884 tprintf(" Privacy;");
2885 if (Short_Pre & cap_inf)
2886 tprintf(" Short Preamble;");
2887 if (PBCC & cap_inf)
2888 tprintf(" PBCC;");
2889 if (Ch_Agility & cap_inf)
2890 tprintf(" Channel Agility;");
2891 if (Spec_Mgmt & cap_inf)
2892 tprintf(" Spectrum Management;");
2893 if (QoS & cap_inf)
2894 tprintf(" QoS;");
2895 if (Short_Slot_t & cap_inf)
2896 tprintf(" Short Slot Time;");
2897 if (APSD & cap_inf)
2898 tprintf(" APSD;");
2899 if (Radio_Meas & cap_inf)
2900 tprintf(" Radio Measurement;");
2901 if (DSSS_OFDM & cap_inf)
2902 tprintf(" DSSS-OFDM;");
2903 if (Del_Block_ACK & cap_inf)
2904 tprintf(" Delayed Block Ack;");
2905 if (Imm_Block_ACK & cap_inf)
2906 tprintf(" Immediate Block Ack;");
2908 return 1;
2911 /* Management Dissectors */
2912 static int8_t beacon(struct pkt_buff *pkt)
2914 struct ieee80211_mgmt_beacon *beacon;
2916 beacon = (struct ieee80211_mgmt_beacon *)
2917 pkt_pull(pkt, sizeof(*beacon));
2918 if (beacon == NULL)
2919 return 0;
2921 tprintf("Timestamp 0x%.16lx, ", le64_to_cpu(beacon->timestamp));
2922 tprintf("Beacon Interval (%fs), ", le16_to_cpu(beacon->beacon_int)*TU);
2923 tprintf("Capabilities (0x%x <->", le16_to_cpu(beacon->capab_info));
2924 cap_field(le16_to_cpu(beacon->capab_info));
2925 tprintf(")");
2927 if(pkt_len(pkt)) {
2928 tprintf("\n\tParameters:");
2929 while (inf_elements(pkt)) {
2930 tprintf("\n\t");
2934 if(pkt_len(pkt))
2935 return 0;
2936 return 1;
2939 static int8_t mgmt_unimplemented(struct pkt_buff *pkt __maybe_unused)
2941 return 0;
2943 /* End Management Dissectors */
2945 /* Control Dissectors */
2946 static int8_t ctrl_unimplemented(struct pkt_buff *pkt __maybe_unused)
2948 return 0;
2950 /* End Control Dissectors */
2952 /* Data Dissectors */
2953 static int8_t data_unimplemented(struct pkt_buff *pkt __maybe_unused)
2955 return 0;
2957 /* End Data Dissectors */
2959 static const char *mgt_sub(u8 subtype, struct pkt_buff *pkt,
2960 int8_t (**get_content)(struct pkt_buff *pkt))
2962 u16 seq_ctrl;
2963 struct ieee80211_mgmt *mgmt;
2964 const char *dst, *src, *bssid;
2966 mgmt = (struct ieee80211_mgmt *) pkt_pull(pkt, sizeof(*mgmt));
2967 if (!mgmt)
2968 return NULL;
2970 dst = lookup_vendor((mgmt->da[0] << 16) |
2971 (mgmt->da[1] << 8) |
2972 mgmt->da[2]);
2973 src = lookup_vendor((mgmt->sa[0] << 16) |
2974 (mgmt->sa[1] << 8) |
2975 mgmt->sa[2]);
2977 bssid = lookup_vendor((mgmt->bssid[0] << 16) |
2978 (mgmt->bssid[1] << 8) |
2979 mgmt->bssid[2]);
2980 seq_ctrl = le16_to_cpu(mgmt->seq_ctrl);
2982 tprintf("Duration (%u),", le16_to_cpu(mgmt->duration));
2983 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
2984 mgmt->da[0], mgmt->da[1], mgmt->da[2],
2985 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
2986 if (dst) {
2987 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst,
2988 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
2991 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
2992 mgmt->sa[0], mgmt->sa[1], mgmt->sa[2],
2993 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
2994 if (src) {
2995 tprintf("=> (%s:%.2x:%.2x:%.2x)", src,
2996 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
2999 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
3000 mgmt->bssid[0], mgmt->bssid[1], mgmt->bssid[2],
3001 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
3002 if(bssid) {
3003 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid,
3004 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
3007 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ",
3008 seq_ctrl & 0xf, seq_ctrl >> 4);
3010 switch (subtype) {
3011 case 0b0000:
3012 *get_content = mgmt_unimplemented;
3013 return "Association Request";
3014 case 0b0001:
3015 *get_content = mgmt_unimplemented;
3016 return "Association Response";
3017 case 0b0010:
3018 *get_content = mgmt_unimplemented;
3019 return "Reassociation Request";
3020 case 0b0011:
3021 *get_content = mgmt_unimplemented;
3022 return "Reassociation Response";
3023 case 0b0100:
3024 *get_content = mgmt_unimplemented;
3025 return "Probe Request";
3026 case 0b0101:
3027 *get_content = mgmt_unimplemented;
3028 return "Probe Response";
3029 case 0b1000:
3030 *get_content = beacon;
3031 return "Beacon";
3032 case 0b1001:
3033 *get_content = mgmt_unimplemented;
3034 return "ATIM";
3035 case 0b1010:
3036 *get_content = mgmt_unimplemented;
3037 return "Disassociation";
3038 case 0b1011:
3039 *get_content = mgmt_unimplemented;
3040 return "Authentication";
3041 case 0b1100:
3042 *get_content = mgmt_unimplemented;
3043 return "Deauthentication";
3044 case 0b0110 ... 0b0111:
3045 case 0b1101 ... 0b1111:
3046 *get_content = NULL;
3047 return "Reserved";
3048 default:
3049 *get_content = NULL;
3050 return "Management SubType unknown";
3054 static const char *ctrl_sub(u8 subtype, struct pkt_buff *pkt __maybe_unused,
3055 int8_t (**get_content)(struct pkt_buff *pkt))
3057 switch (subtype) {
3058 case 0b1010:
3059 *get_content = ctrl_unimplemented;
3060 return "PS-Poll";
3061 case 0b1011:
3062 *get_content = ctrl_unimplemented;
3063 return "RTS";
3064 case 0b1100:
3065 *get_content = ctrl_unimplemented;
3066 return "CTS";
3067 case 0b1101:
3068 *get_content = ctrl_unimplemented;
3069 return "ACK";
3070 case 0b1110:
3071 *get_content = ctrl_unimplemented;
3072 return "CF End";
3073 case 0b1111:
3074 *get_content = ctrl_unimplemented;
3075 return "CF End + CF-ACK";
3076 case 0b0000 ... 0b1001:
3077 *get_content = NULL;
3078 return "Reserved";
3079 default:
3080 return "Control SubType unknown";
3084 static const char *data_sub(u8 subtype, struct pkt_buff *pkt __maybe_unused,
3085 int8_t (**get_content)(struct pkt_buff *pkt))
3087 switch (subtype) {
3088 case 0b0000:
3089 *get_content = data_unimplemented;
3090 return "Data";
3091 case 0b0001:
3092 *get_content = data_unimplemented;
3093 return "Data + CF-ACK";
3094 case 0b0010:
3095 *get_content = data_unimplemented;
3096 return "Data + CF-Poll";
3097 case 0b0011:
3098 *get_content = data_unimplemented;
3099 return "Data + CF-ACK + CF-Poll";
3100 case 0b0100:
3101 *get_content = data_unimplemented;
3102 return "Null";
3103 case 0b0101:
3104 *get_content = data_unimplemented;
3105 return "CF-ACK";
3106 case 0b0110:
3107 *get_content = data_unimplemented;
3108 return "CF-Poll";
3109 case 0b0111:
3110 *get_content = data_unimplemented;
3111 return "CF-ACK + CF-Poll";
3112 case 0b1000 ... 0b1111:
3113 *get_content = NULL;
3114 return "Reserved";
3115 default:
3116 *get_content = NULL;
3117 return "Data SubType unknown";
3121 static const char *
3122 frame_control_type(u8 type, const char *(**get_subtype)(u8 subtype,
3123 struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)))
3125 switch (type) {
3126 case 0b00:
3127 *get_subtype = mgt_sub;
3128 return "Management";
3129 case 0b01:
3130 *get_subtype = ctrl_sub;
3131 return "Control";
3132 case 0b10:
3133 *get_subtype = data_sub;
3134 return "Data";
3135 case 0b11:
3136 *get_subtype = NULL;
3137 return "Reserved";
3138 default:
3139 *get_subtype = NULL;
3140 return "Control Type unknown";
3144 static void ieee80211(struct pkt_buff *pkt)
3146 int8_t (*get_content)(struct pkt_buff *pkt) = NULL;
3147 const char *(*get_subtype)(u8 subtype, struct pkt_buff *pkt,
3148 int8_t (**get_content)(struct pkt_buff *pkt)) = NULL;
3149 const char *subtype = NULL;
3150 struct ieee80211_frm_ctrl *frm_ctrl;
3152 frm_ctrl = (struct ieee80211_frm_ctrl *)
3153 pkt_pull(pkt, sizeof(*frm_ctrl));
3154 if (frm_ctrl == NULL)
3155 return;
3157 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
3158 le16_to_cpu(frm_ctrl->frame_control));
3160 tprintf(" [ Proto Version (%u), ", frm_ctrl->proto_version);
3161 tprintf("Type (%u, %s), ", frm_ctrl->type,
3162 frame_control_type(frm_ctrl->type, &get_subtype));
3163 if (get_subtype) {
3164 subtype = (*get_subtype)(frm_ctrl->subtype, pkt, &get_content);
3165 tprintf("Subtype (%u, %s)", frm_ctrl->subtype, subtype);
3166 } else {
3167 tprintf("%s%s%s", colorize_start_full(black, red),
3168 "No SubType Data available", colorize_end());
3171 tprintf("%s%s", frm_ctrl->to_ds ? ", Frame goes to DS" : "",
3172 frm_ctrl->from_ds ? ", Frame comes from DS" : "");
3173 tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : "");
3174 tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : "");
3175 tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : "");
3176 tprintf("%s", frm_ctrl->more_data ? ", More Data" : "");
3177 tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : "");
3178 tprintf("%s", frm_ctrl->order ? ", Order" : "");
3179 tprintf(" ]\n");
3181 if (get_content) {
3182 tprintf(" [ Subtype %s: ", subtype);
3183 if (!((*get_content) (pkt)))
3184 tprintf("%s%s%s", colorize_start_full(black, red),
3185 "Failed to dissect Subtype", colorize_end());
3186 tprintf(" ]");
3187 } else {
3188 tprintf("%s%s%s", colorize_start_full(black, red),
3189 "No SubType Data available", colorize_end());
3192 tprintf("\n");
3194 // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
3197 static void ieee80211_less(struct pkt_buff *pkt __maybe_unused)
3199 tprintf("802.11 frame (more on todo)");
3202 struct protocol ieee80211_ops = {
3203 .key = 0,
3204 .print_full = ieee80211,
3205 .print_less = ieee80211_less,