flowtop: man: Add notice about rate info
[netsniff-ng.git] / proto_80211_mac_hdr.c
blobc7b5b15cadb3f4c887dbf3a28e05a4b177d6af33
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 endianness (little / big)
13 #include <inttypes.h>
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <netinet/in.h> /* for ntohs() */
17 #include <asm/byteorder.h>
18 #include <arpa/inet.h> /* for inet_ntop() */
20 #include "proto.h"
21 #include "dissector_80211.h"
22 #include "built_in.h"
23 #include "pkt_buff.h"
24 #include "oui.h"
25 #include "linktype.h"
27 #define TU 0.001024
29 /* Note: Fields are encoded in little-endian! */
30 struct ieee80211_frm_ctrl {
31 union {
32 u16 frame_control;
33 struct {
34 #if defined(__LITTLE_ENDIAN_BITFIELD)
35 /* Correct order here ... */
36 __extension__ u16 proto_version:2,
37 type:2,
38 subtype:4,
39 to_ds:1,
40 from_ds:1,
41 more_frags:1,
42 retry:1,
43 power_mgmt:1,
44 more_data:1,
45 wep:1,
46 order:1;
47 #elif defined(__BIG_ENDIAN_BITFIELD)
48 __extension__ u16 subtype:4,
49 type:2,
50 proto_version:2,
51 order:1,
52 wep:1,
53 more_data:1,
54 power_mgmt:1,
55 retry:1,
56 more_frags:1,
57 from_ds:1,
58 to_ds:1;
59 #else
60 # error "Adjust your <asm/byteorder.h> defines"
61 #endif
64 } __packed;
66 /* Management Frame start */
67 /* Note: Fields are encoded in little-endian! */
68 struct ieee80211_mgmt {
69 u16 duration;
70 u8 da[6];
71 u8 sa[6];
72 u8 bssid[6];
73 u16 seq_ctrl;
74 } __packed;
76 struct ieee80211_mgmt_auth {
77 u16 auth_alg;
78 u16 auth_transaction;
79 u16 status_code;
80 /* possibly followed by Challenge text */
81 u8 variable[0];
82 } __packed;
84 struct ieee80211_mgmt_deauth {
85 u16 reason_code;
86 } __packed;
88 struct ieee80211_mgmt_assoc_req {
89 u16 capab_info;
90 u16 listen_interval;
91 /* followed by SSID and Supported rates */
92 u8 variable[0];
93 } __packed;
95 struct ieee80211_mgmt_assoc_resp {
96 u16 capab_info;
97 u16 status_code;
98 u16 aid;
99 /* followed by Supported rates */
100 u8 variable[0];
101 } __packed;
103 struct ieee80211_mgmt_reassoc_resp {
104 u16 capab_info;
105 u16 status_code;
106 u16 aid;
107 /* followed by Supported rates */
108 u8 variable[0];
109 } __packed;
111 struct ieee80211_mgmt_reassoc_req {
112 u16 capab_info;
113 u16 listen_interval;
114 u8 current_ap[6];
115 /* followed by SSID and Supported rates */
116 u8 variable[0];
117 } __packed;
119 struct ieee80211_mgmt_disassoc {
120 u16 reason_code;
121 } __packed;
123 struct ieee80211_mgmt_probe_req {
124 } __packed;
126 struct ieee80211_mgmt_beacon {
127 u64 timestamp;
128 u16 beacon_int;
129 u16 capab_info;
130 /* followed by some of SSID, Supported rates,
131 * FH Params, DS Params, CF Params, IBSS Params, TIM */
132 u8 variable[0];
133 } __packed;
135 struct ieee80211_mgmt_probe_resp {
136 u8 timestamp[8];
137 u16 beacon_int;
138 u16 capab_info;
139 /* followed by some of SSID, Supported rates,
140 * FH Params, DS Params, CF Params, IBSS Params, TIM */
141 u8 variable[0];
142 } __packed;
143 /* Management Frame end */
145 /* Control Frame start */
146 /* Note: Fields are encoded in little-endian! */
147 struct ieee80211_ctrl {
148 } __packed;
150 struct ieee80211_ctrl_rts {
151 u16 duration;
152 u8 da[6];
153 u8 sa[6];
154 } __packed;
156 struct ieee80211_ctrl_cts {
157 u16 duration;
158 u8 da[6];
159 } __packed;
161 struct ieee80211_ctrl_ack {
162 u16 duration;
163 u8 da[6];
164 } __packed;
166 struct ieee80211_ctrl_ps_poll {
167 u16 aid;
168 u8 bssid[6];
169 u8 sa[6];
170 } __packed;
172 struct ieee80211_ctrl_cf_end {
173 u16 duration;
174 u8 bssid[6];
175 u8 sa[6];
176 } __packed;
178 struct ieee80211_ctrl_cf_end_ack {
179 u16 duration;
180 u8 bssid[6];
181 u8 sa[6];
182 } __packed;
183 /* Control Frame end */
185 /* Data Frame start */
186 /* Note: Fields are encoded in little-endian! */
187 struct ieee80211_data {
188 } __packed;
190 /* TODO: Extend */
191 /* Data Frame end */
193 struct element_reserved {
194 u8 len;
195 } __packed;
197 struct element_ssid {
198 u8 len;
199 u8 SSID[0];
200 } __packed;
202 struct element_supp_rates {
203 u8 len;
204 u8 rates[0];
205 } __packed;
207 struct element_fh_ps {
208 u8 len;
209 u16 dwell_time;
210 u8 hop_set;
211 u8 hop_pattern;
212 u8 hop_index;
213 } __packed;
215 struct element_dsss_ps {
216 u8 len;
217 u8 curr_ch;
218 } __packed;
220 struct element_cf_ps {
221 u8 len;
222 u8 cfp_cnt;
223 u8 cfp_period;
224 u16 cfp_max_dur;
225 u16 cfp_dur_rem;
226 } __packed;
228 struct element_tim {
229 u8 len;
230 u8 dtim_cnt;
231 u8 dtim_period;
232 u8 bmp_cntrl;
233 u8 part_virt_bmp[0];
234 } __packed;
236 struct element_ibss_ps {
237 u8 len;
238 u16 atim_win;
239 } __packed;
241 struct element_country_tripled {
242 u8 frst_ch;
243 u8 nr_ch;
244 u8 max_trans;
245 } __packed;
247 struct element_country {
248 u8 len;
249 #if defined(__LITTLE_ENDIAN_BITFIELD)
250 /* Correct order here ... */
251 u8 country_first;
252 u8 country_sec;
253 u8 country_third;
254 #elif defined(__BIG_ENDIAN_BITFIELD)
255 u8 country_third;
256 u8 country_sec;
257 u8 country_first;
258 #else
259 # error "Adjust your <asm/byteorder.h> defines"
260 #endif
261 /* triplet may repeat */
262 struct element_country_tripled tripled [0];
263 /* end triplet */
264 u8 pad[0];
265 } __packed;
267 struct element_hop_pp {
268 u8 len;
269 u8 prime_radix;
270 u8 nr_ch;
271 } __packed;
273 struct element_hop_pt {
274 u8 len;
275 u8 flag;
276 u8 nr_sets;
277 u8 modules;
278 u8 offs;
279 u8 rand_tabl[0];
280 } __packed;
282 struct element_req {
283 u8 len;
284 u8 req_elem_idl[0];
285 } __packed;
287 struct element_bss_load {
288 u8 len;
289 u16 station_cnt;
290 u8 ch_util;
291 u16 avlb_adm_cap;
292 } __packed;
294 struct element_edca_ps {
295 u8 len;
296 u8 qos_inf;
297 u8 res;
298 u32 ac_be;
299 u32 ac_bk;
300 u32 ac_vi;
301 u32 ac_vo;
302 } __packed;
304 struct element_tspec {
305 union {
306 u32 len_ts_info;
307 struct {
308 #if defined(__LITTLE_ENDIAN_BITFIELD)
309 /* Correct order here ... */
310 __extension__ u32 len:8,
311 traffic_type:1,
312 tsid:4,
313 direction:2,
314 access_policy:2,
315 aggr:1,
316 apsd:1,
317 user_prior:3,
318 tsinfo_ack_pol:2,
319 schedule:1,
320 res:7;
321 #elif defined(__BIG_ENDIAN_BITFIELD)
322 __extension__ u32 len:8,
323 res:7,
324 schedule:1,
325 tsinfo_ack_pol:2,
326 user_prior:3,
327 apsd:1,
328 aggr:1,
329 access_policy:2,
330 direction:2,
331 tsid:4,
332 traffic_type:1;
333 #else
334 # error "Adjust your <asm/byteorder.h> defines"
335 #endif
338 u16 nom_msdu_size;
339 u16 max_msdu_size;
340 u32 min_srv_intv;
341 u32 max_srv_intv;
342 u32 inactive_intv;
343 u32 susp_intv;
344 u32 srv_start_time;
345 u32 min_data_rate;
346 u32 mean_data_rate;
347 u32 peak_data_rate;
348 u32 burst_size;
349 u32 delay_bound;
350 u32 min_phy_rate;
351 u16 surplus_bandw_allow;
352 u16 med_time;
353 } __packed;
355 struct element_tclas {
356 u8 len;
357 u8 user_priority;
358 u8 frm_class[0];
359 } __packed;
361 struct element_tclas_frm_class {
362 u8 type;
363 u8 mask;
364 u8 param[0];
365 } __packed;
367 struct element_tclas_type0 {
368 u8 sa[6];
369 u8 da[6];
370 u16 type;
371 } __packed;
373 struct element_tclas_type1 {
374 u8 version;
375 u8 subparam[0];
376 } __packed;
378 struct element_tclas_type1_ip4 {
379 u32 sa;
380 u32 da;
381 u16 sp;
382 u16 dp;
383 u8 dscp;
384 u8 proto;
385 u8 reserved;
386 } __packed;
388 struct element_tclas_type1_ip6 {
389 struct in6_addr sa;
390 struct in6_addr da;
391 u16 sp;
392 u16 dp;
393 union {
394 u8 flow_label[3];
395 struct {
396 #if defined(__LITTLE_ENDIAN_BITFIELD)
397 __extension__ u8 flow_label3:8;
398 __extension__ u8 flow_label2:8;
399 __extension__ u8 flow_label1:8;
400 #elif defined(__BIG_ENDIAN_BITFIELD)
401 __extension__ u8 flow_label1:8;
402 __extension__ u8 flow_label2:8;
403 __extension__ u8 flow_label3:8;
404 #else
405 # error "Adjust your <asm/byteorder.h> defines"
406 #endif
409 } __packed;
411 struct element_tclas_type2 {
412 u16 vlan_tci;
413 } __packed;
415 struct element_tclas_type3 {
416 u16 offs;
417 u8 value[0];
418 u8 mask[0];
419 } __packed;
421 struct element_tclas_type4 {
422 u8 version;
423 u8 subparam[0];
424 } __packed;
426 struct element_tclas_type4_ip4 {
427 u32 sa;
428 u32 da;
429 u16 sp;
430 u16 dp;
431 u8 dscp;
432 u8 proto;
433 u8 reserved;
434 } __packed;
436 struct element_tclas_type4_ip6 {
437 struct in6_addr sa;
438 struct in6_addr da;
439 u16 sp;
440 u16 dp;
441 u8 dscp;
442 u8 nxt_hdr;
443 union {
444 u8 flow_label[3];
445 struct {
446 #if defined(__LITTLE_ENDIAN_BITFIELD)
447 __extension__ u8 flow_label3:8;
448 __extension__ u8 flow_label2:8;
449 __extension__ u8 flow_label1:8;
450 #elif defined(__BIG_ENDIAN_BITFIELD)
451 __extension__ u8 flow_label1:8;
452 __extension__ u8 flow_label2:8;
453 __extension__ u8 flow_label3:8;
454 #else
455 # error "Adjust your <asm/byteorder.h> defines"
456 #endif
459 } __packed;
461 struct element_tclas_type5 {
462 u8 pcp;
463 u8 cfi;
464 u8 vid;
465 } __packed;
467 struct element_schedule {
468 u8 len;
469 u16 inf;
470 u32 start;
471 u32 serv_intv;
472 u16 spec_intv;
473 } __packed;
475 struct element_chall_txt {
476 u8 len;
477 u8 chall_txt[0];
478 } __packed;
480 struct element_pwr_constr {
481 u8 len;
482 u8 local_pwr_constr;
483 } __packed;
485 struct element_pwr_cap {
486 u8 len;
487 u8 min_pwr_cap;
488 u8 max_pwr_cap;
489 } __packed;
491 struct element_tpc_req {
492 u8 len;
493 } __packed;
495 struct element_tpc_rep {
496 u8 len;
497 u8 trans_pwr;
498 u8 link_marg;
499 } __packed;
501 struct element_supp_ch {
502 u8 len;
503 u8 first_ch_nr[0];
504 u8 nr_ch[0];
505 } __packed;
507 struct element_supp_ch_tuple {
508 u8 first_ch_nr;
509 u8 nr_ch;
510 } __packed;
512 struct element_ch_sw_ann {
513 u8 len;
514 u8 switch_mode;
515 u8 new_nr;
516 u8 switch_cnt;
517 } __packed;
519 struct element_meas_basic {
520 u8 ch_nr;
521 u64 start;
522 u16 dur;
523 } __packed;
525 struct element_meas_cca {
526 u8 ch_nr;
527 u64 start;
528 u16 dur;
529 } __packed;
531 struct element_meas_rpi {
532 u8 ch_nr;
533 u64 start;
534 u16 dur;
535 } __packed;
537 struct element_meas_ch_load {
538 u8 op_class;
539 u8 ch_nr;
540 u16 rand_intv;
541 u16 dur;
542 u8 sub[0];
543 } __packed;
545 struct element_meas_noise {
546 u8 op_class;
547 u8 ch_nr;
548 u16 rand_intv;
549 u16 dur;
550 u8 sub[0];
551 } __packed;
553 struct element_meas_beacon {
554 u8 op_class;
555 u8 ch_nr;
556 u16 rand_intv;
557 u16 dur;
558 u8 mode;
559 u8 bssid[6];
560 u8 sub[0];
561 } __packed;
563 struct element_meas_frame {
564 u8 op_class;
565 u8 ch_nr;
566 u16 rand_intv;
567 u16 dur;
568 u8 frame;
569 u8 mac[6];
570 u8 sub[0];
571 } __packed;
573 struct element_meas_sta {
574 u8 peer_mac[6];
575 u16 rand_intv;
576 u16 dur;
577 u8 group_id;
578 u8 sub[0];
579 } __packed;
581 struct element_meas_lci {
582 u8 loc_subj;
583 u8 latitude_req_res;
584 u8 longitude_req_res;
585 u8 altitude_req_res;
586 u8 sub[0];
587 } __packed;
589 struct element_meas_trans_str_cat {
590 u16 rand_intv;
591 u16 dur;
592 u8 peer_sta_addr[6];
593 u8 traffic_id;
594 u8 bin_0_range;
595 u8 sub[0];
596 } __packed;
598 struct element_meas_mcast_diag {
599 u16 rand_intv;
600 u16 dur;
601 u8 group_mac[6];
602 u8 mcast_triggered[0];
603 u8 sub[0];
604 } __packed;
606 struct element_meas_loc_civic {
607 u8 loc_subj;
608 u8 civic_loc;
609 u8 loc_srv_intv_unit;
610 u16 loc_srv_intv;
611 u8 sub[0];
612 } __packed;
614 struct element_meas_loc_id {
615 u8 loc_subj;
616 u8 loc_srv_intv_unit;
617 u16 loc_srv_intv;
618 u8 sub[0];
619 } __packed;
621 struct element_meas_pause {
622 u8 time;
623 u8 sub[0];
624 } __packed;
626 struct element_meas_req {
627 u8 len;
628 u8 token;
629 u8 req_mode;
630 u8 type;
631 u8 req[0];
632 } __packed;
634 struct element_meas_rep {
635 u8 len;
636 u8 token;
637 u8 rep_mode;
638 u8 type;
639 u8 rep[0];
640 } __packed;
642 struct element_quiet {
643 u8 len;
644 u8 cnt;
645 u8 period;
646 u16 dur;
647 u16 offs;
648 } __packed;
650 struct element_ibss_dfs {
651 u8 len;
652 u8 owner[6];
653 u8 rec_intv;
654 u8 ch_map[0];
655 } __packed;
657 struct element_ibss_dfs_tuple {
658 u8 ch_nr;
659 u8 map;
660 } __packed;
662 struct element_erp {
663 u8 len;
664 u8 param;
665 } __packed;
667 struct element_ts_del {
668 u8 len;
669 u32 delay;
670 } __packed;
672 struct element_tclas_proc {
673 u8 len;
674 u8 proc;
675 } __packed;
677 struct element_ht_cap {
678 u8 len;
679 union {
680 u16 info;
681 struct {
682 #if defined(__LITTLE_ENDIAN_BITFIELD)
683 /* Correct order here ... */
684 __extension__ u16 ldpc:1,
685 supp_width:1,
686 sm_pwr:2,
687 ht_green:1,
688 gi_20mhz:1,
689 gi_40mhz:1,
690 tx_stbc:1,
691 rx_stbc:2,
692 ht_ack:1,
693 max_msdu_length:1,
694 dsss_ck_mode:1,
695 res:1,
696 forty_int:1,
697 prot_supp:1;
698 #elif defined(__BIG_ENDIAN_BITFIELD)
699 __extension__ u16 rx_stbc:2,
700 ht_ack:1,
701 max_msdu_length:1,
702 dsss_ck_mode:1,
703 res:1,
704 forty_int:1,
705 prot_supp:1,
706 ldpc:1,
707 supp_width:1,
708 sm_pwr:2,
709 ht_green:1,
710 gi_20mhz:1,
711 gi_40mhz:1,
712 tx_stbc:1;
713 #else
714 # error "Adjust your <asm/byteorder.h> defines"
715 #endif
718 u8 param;
719 union {
720 u8 mcs_set[16];
721 struct {
722 #if defined(__LITTLE_ENDIAN_BITFIELD)
723 /* Correct order here ... */
724 __extension__ u8 bitmask1:8;
725 __extension__ u8 bitmask2:8;
726 __extension__ u8 bitmask3:8;
727 __extension__ u8 bitmask4:8;
728 __extension__ u8 bitmask5:8;
729 __extension__ u8 bitmask6:8;
730 __extension__ u8 bitmask7:8;
731 __extension__ u8 bitmask8:8;
732 __extension__ u8 bitmask9:8;
733 __extension__ u8 bitmask10_res:8;
734 __extension__ u16 supp_rate_res:16;
735 __extension__ u32 tx_param_res:32;
737 #elif defined(__BIG_ENDIAN_BITFIELD)
738 __extension__ u32 tx_param_res:32;
739 __extension__ u16 supp_rate_res:16;
740 __extension__ u8 bitmask10_res:8;
741 __extension__ u8 bitmask9:8;
742 __extension__ u8 bitmask8:8;
743 __extension__ u8 bitmask7:8;
744 __extension__ u8 bitmask6:8;
745 __extension__ u8 bitmask5:8;
746 __extension__ u8 bitmask4:8;
747 __extension__ u8 bitmask3:8;
748 __extension__ u8 bitmask2:8;
749 __extension__ u8 bitmask1:8;
750 #else
751 # error "Adjust your <asm/byteorder.h> defines"
752 #endif
755 u16 ext_cap;
756 u32 beam_cap;
757 u8 asel_cap;
758 } __packed;
760 struct element_qos_cap {
761 u8 len;
762 u8 info;
763 } __packed;
765 struct element_ext_supp_rates {
766 u8 len;
767 u8 rates[0];
768 } __packed;
770 struct element_vend_spec {
771 u8 len;
772 u8 oui[0];
773 u8 specific[0];
774 } __packed;
776 struct ieee80211_radiotap_header {
777 u8 version; /* set to 0 */
778 u8 pad;
779 u16 len; /* entire length */
780 u32 present; /* fields present */
781 } __packed;
783 static int8_t len_neq_error(u8 len, u8 intended)
785 if(intended != len) {
786 tprintf("Length should be %u Bytes", intended);
787 return 1;
790 return 0;
793 static int8_t len_lt_error(u8 len, u8 intended)
795 if(len < intended) {
796 tprintf("Length should be greater %u Bytes", intended);
797 return 1;
800 return 0;
803 static float data_rates(u8 id)
805 /* XXX Why not (id / 2.f)? */
806 switch (id) {
807 case 2: return 1.0f;
808 case 3: return 1.5f;
809 case 4: return 2.0f;
810 case 5: return 2.5f;
811 case 6: return 3.0f;
812 case 9: return 4.5f;
813 case 11: return 5.5f;
814 case 12: return 6.0f;
815 case 18: return 9.0f;
816 case 22: return 11.0f;
817 case 24: return 12.0f;
818 case 27: return 13.5f;
819 case 36: return 18.0f;
820 case 44: return 22.0f;
821 case 48: return 24.0f;
822 case 54: return 27.0f;
823 case 66: return 33.0f;
824 case 72: return 36.0f;
825 case 96: return 48.0f;
826 case 108: return 54.0f;
829 return 0.f;
832 struct subelement {
833 u8 id;
834 u8 len;
835 u8 data[0];
836 } __packed;
839 static int8_t subelements(struct pkt_buff *pkt, u8 len)
841 u8 i, j;
842 u8 *data;
844 for (i=0; i<len;) {
845 struct subelement *sub;
847 sub = (struct subelement *) pkt_pull(pkt, sizeof(*sub));
848 if (sub == NULL)
849 return 0;
851 tprintf(", Subelement ID %u, ", sub->id);
852 tprintf("Length %u, ", sub->len);
854 data = pkt_pull(pkt, sub->len);
855 if (data == NULL)
856 return 0;
858 tprintf("Data: 0x");
859 for(j=0; j < sub->len; j++)
860 tprintf("%.2x ", data[j]);
862 i += sub->len + 1;
865 /* Not needed ?! Should break before*/
867 *if (i != len) {
868 * tprintf("Length error");
869 * return 0;
873 return 1;
876 static int8_t inf_reserved(struct pkt_buff *pkt, u8 *id)
878 u8 i;
879 u8 *data;
880 struct element_reserved *reserved;
882 reserved = (struct element_reserved *) pkt_pull(pkt, sizeof(*reserved));
883 if (reserved == NULL)
884 return 0;
886 tprintf(" Reserved (%u, Len (%u)): ", *id, reserved->len);
888 data = pkt_pull(pkt, reserved->len);
889 if (data == NULL)
890 return 0;
892 tprintf("Data 0x");
893 for (i = 0; i < reserved->len; i++)
894 tprintf("%.2x", data[i]);
896 return 1;
899 static int8_t inf_ssid(struct pkt_buff *pkt, u8 *id)
901 u8 i;
902 struct element_ssid *ssid;
903 char *ssid_name;
905 ssid = (struct element_ssid *) pkt_pull(pkt, sizeof(*ssid));
906 if (ssid == NULL)
907 return 0;
909 tprintf(" SSID (%u, Len (%u)): ", *id, ssid->len);
911 if ((ssid->len - sizeof(*ssid) + 1) > 0) {
912 ssid_name = (char *) pkt_pull(pkt, ssid->len);
913 if (ssid_name == NULL)
914 return 0;
916 for (i = 0; i < ssid->len; i++)
917 tprintf("%c",ssid_name[i]);
918 } else {
919 tprintf("Wildcard SSID");
922 return 1;
925 static int8_t inf_supp_rates(struct pkt_buff *pkt, u8 *id)
927 u8 i;
928 u8 *rates;
929 struct element_supp_rates *supp_rates;
931 supp_rates = (struct element_supp_rates *)
932 pkt_pull(pkt, sizeof(*supp_rates));
933 if (supp_rates == NULL)
934 return 0;
936 tprintf(" Supp. Rates (%u, Len (%u)): ", *id, supp_rates->len);
937 if (len_lt_error(supp_rates->len, 1))
938 return 0;
940 if ((supp_rates->len - sizeof(*supp_rates) + 1) > 0) {
941 rates = pkt_pull(pkt, supp_rates->len);
942 if (rates == NULL)
943 return 0;
945 for (i = 0; i < supp_rates->len; i++)
946 tprintf("%g%s ", ((rates[i] & 0x80) >> 7) ?
947 data_rates(rates[i] & 0x3f) :
948 ((rates[i] & 0x3f) * 0.5),
949 ((rates[i] & 0x80) >> 7) ? "(B)" : "");
950 return 1;
953 return 0;
956 static int8_t inf_fh_ps(struct pkt_buff *pkt, u8 *id)
958 struct element_fh_ps *fh_ps;
960 fh_ps = (struct element_fh_ps *) pkt_pull(pkt, sizeof(*fh_ps));
961 if (fh_ps == NULL)
962 return 0;
964 tprintf(" FH Param Set (%u, Len(%u)): ", *id, fh_ps->len);
965 if (len_neq_error(fh_ps->len, 5))
966 return 0;
967 tprintf("Dwell Time: %fs, ", le16_to_cpu(fh_ps->dwell_time) * TU);
968 tprintf("HopSet: %u, ", fh_ps->hop_set);
969 tprintf("HopPattern: %u, ", fh_ps->hop_pattern);
970 tprintf("HopIndex: %u", fh_ps->hop_index);
972 return 1;
975 static int8_t inf_dsss_ps(struct pkt_buff *pkt, u8 *id)
977 struct element_dsss_ps *dsss_ps;
979 dsss_ps = (struct element_dsss_ps *) pkt_pull(pkt, sizeof(*dsss_ps));
980 if (dsss_ps == NULL)
981 return 0;
983 tprintf(" DSSS Param Set (%u, Len(%u)): ", *id, dsss_ps->len);
984 if (len_neq_error(dsss_ps->len, 1))
985 return 0;
986 tprintf("Current Channel: %u", dsss_ps->curr_ch);
988 return 1;
991 static int8_t inf_cf_ps(struct pkt_buff *pkt, u8 *id)
993 struct element_cf_ps *cf_ps;
995 cf_ps = (struct element_cf_ps *) pkt_pull(pkt, sizeof(*cf_ps));
996 if (cf_ps == NULL)
997 return 0;
999 tprintf(" CF Param Set (%u, Len(%u)): ", *id, cf_ps->len);
1000 if (len_neq_error(cf_ps->len, 6))
1001 return 0;
1002 tprintf("CFP Count: %u, ", cf_ps->cfp_cnt);
1003 tprintf("CFP Period: %u, ", cf_ps->cfp_period);
1004 tprintf("CFP MaxDur: %fs, ", le16_to_cpu(cf_ps->cfp_max_dur) * TU);
1005 tprintf("CFP DurRem: %fs", le16_to_cpu(cf_ps->cfp_dur_rem) * TU);
1007 return 1;
1010 static int8_t inf_tim(struct pkt_buff *pkt, u8 *id)
1012 struct element_tim *tim;
1013 u8 i;
1015 tim = (struct element_tim *) pkt_pull(pkt, sizeof(*tim));
1016 if (tim == NULL)
1017 return 0;
1019 tprintf(" TIM (%u, Len(%u)): ", *id, tim->len);
1020 if (len_lt_error(tim->len, 3))
1021 return 0;
1022 tprintf("DTIM Count: %u, ", tim->dtim_cnt);
1023 tprintf("DTIM Period: %u, ", tim->dtim_period);
1024 tprintf("Bitmap Control: %u, ", tim->bmp_cntrl);
1025 if ((tim->len - sizeof(*tim) + 1) > 0) {
1026 u8 *bmp = pkt_pull(pkt, (tim->len - sizeof(*tim) + 1));
1027 if (bmp == NULL)
1028 return 0;
1030 tprintf("Partial Virtual Bitmap: 0x");
1031 for (i = 0; i < (tim->len - sizeof(*tim) + 1); i++)
1032 tprintf("%.2x", bmp[i]);
1035 return 1;
1038 static int8_t inf_ibss_ps(struct pkt_buff *pkt, u8 *id)
1040 struct element_ibss_ps *ibss_ps;
1042 ibss_ps = (struct element_ibss_ps *) pkt_pull(pkt, sizeof(*ibss_ps));
1043 if (ibss_ps == NULL)
1044 return 0;
1046 tprintf(" IBSS Param Set (%u, Len(%u)): ", *id, ibss_ps->len);
1047 if (len_neq_error(ibss_ps->len, 2))
1048 return 0;
1049 tprintf("ATIM Window: %fs", le16_to_cpu(ibss_ps->atim_win) * TU);
1051 return 1;
1054 static int8_t inf_country(struct pkt_buff *pkt, u8 *id)
1056 u8 i;
1057 u8 *pad;
1058 struct element_country *country;
1060 country = (struct element_country *) pkt_pull(pkt, sizeof(*country));
1061 if (country == NULL)
1062 return 0;
1064 tprintf(" Country (%u, Len(%u)): ", *id, country->len);
1065 if (len_lt_error(country->len, 6))
1066 return 0;
1067 tprintf("Country String: %c%c%c", country->country_first,
1068 country->country_sec, country->country_third);
1070 for (i = country->len % 3; i < (country->len - 3); i += 3) {
1071 struct element_country_tripled *country_tripled;
1073 country_tripled = (struct element_country_tripled *)
1074 pkt_pull(pkt, sizeof(*country_tripled));
1075 if (country_tripled == NULL)
1076 return 0;
1078 tprintf("\n\t\t");
1079 if(country_tripled->frst_ch >= 201) {
1080 tprintf("Oper Ext ID: %u, ", country_tripled->frst_ch);
1081 tprintf("Operating Class: %u, ", country_tripled->nr_ch);
1082 tprintf("Coverage Class: %u", country_tripled->max_trans);
1083 } else {
1084 tprintf("First Ch Nr: %u, ", country_tripled->frst_ch);
1085 tprintf("Nr of Ch: %u, ", country_tripled->nr_ch);
1086 tprintf("Max Transmit Pwr Lvl: %u", country_tripled->max_trans);
1090 if(country->len % 3) {
1091 pad = pkt_pull(pkt, 1);
1092 if (pad == NULL)
1093 return 0;
1095 tprintf(", Pad: 0x%x", *pad);
1098 return 1;
1101 static int8_t inf_hop_pp(struct pkt_buff *pkt, u8 *id)
1103 struct element_hop_pp *hop_pp;
1105 hop_pp = (struct element_hop_pp *) pkt_pull(pkt, sizeof(*hop_pp));
1106 if (hop_pp == NULL)
1107 return 0;
1109 tprintf(" Hopping Pattern Param (%u, Len(%u)): ", *id, hop_pp->len);
1110 if (len_neq_error(hop_pp->len, 2))
1111 return 0;
1112 tprintf("Prime Radix: %u, ", hop_pp->prime_radix);
1113 tprintf("Nr of Ch: %u", hop_pp->nr_ch);
1115 return 1;
1118 static int8_t inf_hop_pt(struct pkt_buff *pkt, u8 *id)
1120 size_t i;
1121 u8 *rand_tabl;
1122 struct element_hop_pt *hop_pt;
1124 hop_pt = (struct element_hop_pt *) pkt_pull(pkt, sizeof(*hop_pt));
1125 if (hop_pt == NULL)
1126 return 0;
1128 tprintf(" Hopping Pattern Table (%u, Len(%u)): ", *id, hop_pt->len);
1129 if (len_lt_error(hop_pt->len, 4))
1130 return 0;
1131 tprintf("Flag: %u, ", hop_pt->flag);
1132 tprintf("Nr of Sets: %u, ", hop_pt->nr_sets);
1133 tprintf("Modulus: %u, ", hop_pt->modules);
1134 tprintf("Offs: %u", hop_pt->offs);
1136 if ((hop_pt->len - sizeof(*hop_pt) + 1) > 0) {
1137 rand_tabl = pkt_pull(pkt, (hop_pt->len - sizeof(*hop_pt) + 1));
1138 if (rand_tabl == NULL)
1139 return 0;
1141 tprintf(", Rand table: 0x");
1142 for (i = 0; i < (hop_pt->len - sizeof(*hop_pt) + 1); i++)
1143 tprintf("%.2x", rand_tabl[i]);
1146 return 1;
1149 static int8_t inf_req(struct pkt_buff *pkt, u8 *id)
1151 size_t i;
1152 struct element_req *req;
1153 u8 *req_ids;
1155 req = (struct element_req *) pkt_pull(pkt, sizeof(*req));
1156 if (req == NULL)
1157 return 0;
1159 tprintf(" Request Element (%u, Len(%u)): ", *id, req->len);
1160 if ((req->len - sizeof(*req) + 1) > 0) {
1161 req_ids = pkt_pull(pkt, (req->len - sizeof(*req) + 1));
1162 if (req_ids == NULL)
1163 return 0;
1165 tprintf(", Requested Element IDs: ");
1166 for (i = 0; i < (req->len - sizeof(*req) + 1); i++)
1167 tprintf("%u ", req_ids[i]);
1170 return 1;
1173 static int8_t inf_bss_load(struct pkt_buff *pkt, u8 *id)
1175 struct element_bss_load *bss_load;
1177 bss_load = (struct element_bss_load *) pkt_pull(pkt, sizeof(*bss_load));
1178 if (bss_load == NULL)
1179 return 0;
1181 tprintf(" BSS Load element (%u, Len(%u)): ", *id, bss_load->len);
1182 if (len_neq_error(bss_load->len, 5))
1183 return 0;
1184 tprintf("Station Count: %u, ", le16_to_cpu(bss_load->station_cnt));
1185 tprintf("Channel Utilization: %u, ", bss_load->ch_util);
1186 tprintf("Available Admission Capacity: %uus",
1187 bss_load->avlb_adm_cap * 32);
1189 return 1;
1192 static int8_t inf_edca_ps(struct pkt_buff *pkt, u8 *id)
1194 u32 ac_be, ac_bk, ac_vi, ac_vo;
1195 struct element_edca_ps *edca_ps;
1197 edca_ps = (struct element_edca_ps *) pkt_pull(pkt, sizeof(*edca_ps));
1198 if (edca_ps == NULL)
1199 return 0;
1201 ac_be = le32_to_cpu(edca_ps->ac_be);
1202 ac_bk = le32_to_cpu(edca_ps->ac_bk);
1203 ac_vi = le32_to_cpu(edca_ps->ac_vi);
1204 ac_vo = le32_to_cpu(edca_ps->ac_vo);
1206 tprintf(" EDCA Param Set (%u, Len(%u)): ", *id, edca_ps->len);
1207 if (len_neq_error(edca_ps->len, 18))
1208 return 0;
1209 tprintf("QoS Info: 0x%x (-> EDCA Param Set Update Count (%u),"
1210 "Q-Ack (%u), Queue Re (%u), TXOP Req(%u), Res(%u)), ",
1211 edca_ps->qos_inf, edca_ps->qos_inf >> 4,
1212 (edca_ps->qos_inf >> 3) & 1, (edca_ps->qos_inf >> 2) & 1,
1213 (edca_ps->qos_inf >> 1) & 1, edca_ps->qos_inf & 1);
1214 tprintf("Reserved: 0x%x, ", edca_ps->res);
1215 tprintf("AC_BE Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1216 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_be,
1217 ac_be >> 28, (ac_be >> 27) & 1, (ac_be >> 25) & 3,
1218 (ac_be >> 24) & 1, (ac_be >> 20) & 15, (ac_be >> 16) & 15,
1219 bswap_16(ac_be & 0xFFFF) * 32);
1220 tprintf("AC_BK Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1221 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_bk,
1222 ac_bk >> 28, (ac_bk >> 27) & 1, (ac_bk >> 25) & 3,
1223 (ac_bk >> 24) & 1, (ac_bk >> 20) & 15, (ac_bk >> 16) & 15,
1224 bswap_16(ac_bk & 0xFFFF) * 32);
1225 tprintf("AC_VI Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1226 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_vi,
1227 ac_vi >> 28, (ac_vi >> 27) & 1, (ac_vi >> 25) & 3,
1228 (ac_vi >> 24) & 1, (ac_vi >> 20) & 15, (ac_vi >> 16) & 15,
1229 bswap_16(ac_vi & 0xFFFF) * 32);
1230 tprintf("AC_VO Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1231 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)", ac_vo,
1232 ac_vo >> 28, (ac_vo >> 27) & 1, (ac_vo >> 25) & 3,
1233 (ac_vo >> 24) & 1, (ac_vo >> 20) & 15, (ac_vo >> 16) & 15,
1234 bswap_16(ac_vo & 0xFFFF) * 32);
1236 return 1;
1239 static int8_t inf_tspec(struct pkt_buff *pkt, u8 *id)
1241 u16 nom_msdu_size, surplus_bandw_allow;
1242 struct element_tspec *tspec;
1244 tspec = (struct element_tspec *) pkt_pull(pkt, sizeof(*tspec));
1245 if (tspec == NULL)
1246 return 0;
1248 nom_msdu_size = le16_to_cpu(tspec->nom_msdu_size);
1249 surplus_bandw_allow = le16_to_cpu(tspec->surplus_bandw_allow);
1251 tprintf(" TSPEC (%u, Len(%u)): ", *id, tspec->len);
1252 if (len_neq_error(tspec->len, 55))
1253 return 0;
1254 tprintf("Traffic Type: %u, ", tspec->traffic_type);
1255 tprintf("TSID: %u, ", tspec->tsid);
1256 tprintf("Direction: %u, ", tspec->direction);
1257 tprintf("Access Policy: %u, ", tspec->access_policy);
1258 tprintf("Aggregation: %u, ", tspec->aggr);
1259 tprintf("APSD: %u, ", tspec->apsd);
1260 tprintf("User Priority: %u, ", tspec->user_prior);
1261 tprintf("TSinfo Ack Policy: %u, ", tspec->tsinfo_ack_pol);
1262 tprintf("Schedule: %u, ", tspec->schedule);
1263 tprintf("Reserved: 0x%x, ", tspec->res);
1264 tprintf("Nominal MSDU Size: %uB (Fixed (%u)), ",
1265 nom_msdu_size >> 1, nom_msdu_size & 1);
1266 tprintf("Maximum MSDU Size: %uB, ", le16_to_cpu(tspec->max_msdu_size));
1267 tprintf("Minimum Service Interval: %uus, ",
1268 le32_to_cpu(tspec->min_srv_intv));
1269 tprintf("Maximum Service Interval: %uus, ",
1270 le32_to_cpu(tspec->max_srv_intv));
1271 tprintf("Inactivity Interval: %uus, ",
1272 le32_to_cpu(tspec->inactive_intv));
1273 tprintf("Suspension Interval: %uus, ", le32_to_cpu(tspec->susp_intv));
1274 tprintf("Service Start Time: %uus, ",
1275 le32_to_cpu(tspec->srv_start_time));
1276 tprintf("Minimum Data Rate: %ub/s, ",le32_to_cpu(tspec->min_data_rate));
1277 tprintf("Mean Data Rate: %ub/s, ", le32_to_cpu(tspec->mean_data_rate));
1278 tprintf("Peak Data Rate: %ub/s, ",le32_to_cpu(tspec->peak_data_rate));
1279 tprintf("Burst Size: %uB, ", le32_to_cpu(tspec->burst_size));
1280 tprintf("Delay Bound: %uus, ", le32_to_cpu(tspec->delay_bound));
1281 tprintf("Minimum PHY Rate: %ub/s, ", le32_to_cpu(tspec->min_phy_rate));
1282 tprintf("Surplus Bandwidth: %u.%u, ", surplus_bandw_allow >> 13,
1283 surplus_bandw_allow & 0x1FFF);
1284 tprintf("Medium Time: %uus", le16_to_cpu(tspec->med_time) * 32);
1286 return 1;
1289 static const char *class_type(u8 type)
1291 switch (type) {
1292 case 0: return "Ethernet parameters";
1293 case 1: return "TCP/UDP IP parameters";
1294 case 2: return "IEEE 802.1Q parameters";
1295 case 3: return "Filter Offset parameters";
1296 case 4: return "IP and higher layer parameters";
1297 case 5: return "IEEE 802.1D/Q parameters";
1298 default: return "Reserved";
1302 static int8_t inf_tclas(struct pkt_buff *pkt, u8 *id)
1304 struct element_tclas *tclas;
1305 struct element_tclas_frm_class *frm_class;
1307 tclas = (struct element_tclas *) pkt_pull(pkt, sizeof(*tclas));
1308 if (tclas == NULL)
1309 return 0;
1311 frm_class = (struct element_tclas_frm_class *)
1312 pkt_pull(pkt, sizeof(*frm_class));
1313 if (frm_class == NULL)
1314 return 0;
1316 tprintf(" TCLAS (%u, Len(%u)): ", *id, tclas->len);
1317 if (len_lt_error(tclas->len, 3))
1318 return 0;
1319 tprintf("User Priority: %u, ", tclas->user_priority);
1320 tprintf("Classifier Type: %s (%u), ", class_type(frm_class->type),
1321 frm_class->type);
1322 tprintf("Classifier Mask: 0x%x, ", frm_class->mask);
1324 if(frm_class->type == 0) {
1325 struct element_tclas_type0 *type0;
1327 type0 = (struct element_tclas_type0 *)
1328 pkt_pull(pkt, sizeof(*type0));
1329 if (type0 == NULL)
1330 return 0;
1332 /* I think little endian, like the rest */
1333 tprintf("Src Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
1334 type0->sa[5], type0->sa[4], type0->sa[3],
1335 type0->sa[2], type0->sa[1], type0->sa[0]);
1336 tprintf("Dst Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
1337 type0->da[5], type0->da[4], type0->da[3],
1338 type0->da[2], type0->da[1], type0->da[0]);
1339 tprintf("Type: 0x%x", le16_to_cpu(type0->type));
1341 else if(frm_class->type == 1) {
1342 struct element_tclas_type1 *type1;
1344 type1 = (struct element_tclas_type1 *)
1345 pkt_pull(pkt, sizeof(*type1));
1346 if (type1 == NULL)
1347 return 0;
1349 tprintf("Version: %u, ", type1->version);
1350 /* big endian format follows */
1351 if(type1->version == 4) {
1352 struct element_tclas_type1_ip4 *type1_ip4;
1353 char src_ip[INET_ADDRSTRLEN];
1354 char dst_ip[INET_ADDRSTRLEN];
1356 type1_ip4 = (struct element_tclas_type1_ip4 *)
1357 pkt_pull(pkt, sizeof(*type1_ip4));
1358 if (type1_ip4 == NULL)
1359 return 0;
1361 inet_ntop(AF_INET, &type1_ip4->sa, src_ip, sizeof(src_ip));
1362 inet_ntop(AF_INET, &type1_ip4->da, dst_ip, sizeof(dst_ip));
1364 tprintf("Src IP: %s, ", src_ip);
1365 tprintf("Dst IP: %s, ", dst_ip);
1366 tprintf("Src Port: %u, ", ntohs(type1_ip4->sp));
1367 tprintf("Dst Port: %u, ", ntohs(type1_ip4->dp));
1368 tprintf("DSCP: 0x%x, ", type1_ip4->dscp);
1369 tprintf("Proto: %u, ", type1_ip4->proto);
1370 tprintf("Res: 0x%x", type1_ip4->reserved);
1372 else if(type1->version == 6) {
1373 struct element_tclas_type1_ip6 *type1_ip6;
1374 char src_ip[INET6_ADDRSTRLEN];
1375 char dst_ip[INET6_ADDRSTRLEN];
1377 type1_ip6 = (struct element_tclas_type1_ip6 *)
1378 pkt_pull(pkt, sizeof(*type1_ip6));
1379 if (type1_ip6 == NULL)
1380 return 0;
1382 inet_ntop(AF_INET6, &type1_ip6->sa,
1383 src_ip, sizeof(src_ip));
1384 inet_ntop(AF_INET6, &type1_ip6->da,
1385 dst_ip, sizeof(dst_ip));
1387 tprintf("Src IP: %s, ", src_ip);
1388 tprintf("Dst IP: %s, ", dst_ip);
1389 tprintf("Src Port: %u, ", ntohs(type1_ip6->sp));
1390 tprintf("Dst Port: %u, ", ntohs(type1_ip6->dp));
1391 tprintf("Flow Label: 0x%x%x%x", type1_ip6->flow_label1,
1392 type1_ip6->flow_label2, type1_ip6->flow_label3);
1394 else {
1395 tprintf("Version (%u) not supported", type1->version);
1396 return 0;
1400 else if(frm_class->type == 2) {
1401 struct element_tclas_type2 *type2;
1403 type2 = (struct element_tclas_type2 *)
1404 pkt_pull(pkt, sizeof(*type2));
1405 if (type2 == NULL)
1406 return 0;
1408 tprintf("802.1Q VLAN TCI: 0x%x", ntohs(type2->vlan_tci));
1410 else if(frm_class->type == 3) {
1411 struct element_tclas_type3 *type3;
1412 u8 len, i;
1413 u8 *val;
1415 type3 = (struct element_tclas_type3 *)
1416 pkt_pull(pkt, sizeof(*type3));
1417 if (type3 == NULL)
1418 return 0;
1420 len = (tclas->len - 5) / 2;
1422 tprintf("Filter Offset: %u, ", type3->offs);
1424 if((len & 1) || (len_lt_error(tclas->len, 5))) {
1425 tprintf("Length of TCLAS (%u) not correct", tclas->len);
1426 return 0;
1428 else {
1429 val = pkt_pull(pkt, len);
1430 if (val == NULL)
1431 return 0;
1433 tprintf("Filter Value: 0x");
1434 for (i = 0; i < len / 2; i++)
1435 tprintf("%x ", val[i]);
1436 tprintf(", ");
1437 tprintf("Filter Mask: 0x");
1438 for (i = len / 2; i < len; i++)
1439 tprintf("%x ", val[i]);
1443 else if(frm_class->type == 4) {
1444 struct element_tclas_type4 *type4;
1446 type4 = (struct element_tclas_type4 *)
1447 pkt_pull(pkt, sizeof(*type4));
1448 if (type4 == NULL)
1449 return 0;
1451 tprintf("Version: %u, ", type4->version);
1452 /* big endian format follows */
1453 if(type4->version == 4) {
1454 struct element_tclas_type4_ip4 *type4_ip4;
1455 char src_ip[INET_ADDRSTRLEN];
1456 char dst_ip[INET_ADDRSTRLEN];
1458 type4_ip4 = (struct element_tclas_type4_ip4 *)
1459 pkt_pull(pkt, sizeof(*type4_ip4));
1460 if (type4_ip4 == NULL)
1461 return 0;
1463 inet_ntop(AF_INET, &type4_ip4->sa, src_ip, sizeof(src_ip));
1464 inet_ntop(AF_INET, &type4_ip4->da, dst_ip, sizeof(dst_ip));
1466 tprintf("Src IP: %s, ", src_ip);
1467 tprintf("Dst IP: %s, ", dst_ip);
1468 tprintf("Src Port: %u, ", ntohs(type4_ip4->sp));
1469 tprintf("Dst Port: %u, ", ntohs(type4_ip4->dp));
1470 tprintf("DSCP: 0x%x, ", type4_ip4->dscp);
1471 tprintf("Proto: %u, ", type4_ip4->proto);
1472 tprintf("Res: 0x%x", type4_ip4->reserved);
1474 else if(type4->version == 6) {
1475 struct element_tclas_type4_ip6 *type4_ip6;
1476 char src_ip[INET6_ADDRSTRLEN];
1477 char dst_ip[INET6_ADDRSTRLEN];
1479 type4_ip6 = (struct element_tclas_type4_ip6 *)
1480 pkt_pull(pkt, sizeof(*type4_ip6));
1481 if (type4_ip6 == NULL)
1482 return 0;
1484 inet_ntop(AF_INET6, &type4_ip6->sa,
1485 src_ip, sizeof(src_ip));
1486 inet_ntop(AF_INET6, &type4_ip6->da,
1487 dst_ip, sizeof(dst_ip));
1489 tprintf("Src IP: %s, ", src_ip);
1490 tprintf("Dst IP: %s, ", dst_ip);
1491 tprintf("Src Port: %u, ", ntohs(type4_ip6->sp));
1492 tprintf("Dst Port: %u, ", ntohs(type4_ip6->dp));
1493 tprintf("DSCP: 0x%x, ", type4_ip6->dscp);
1494 tprintf("Nxt Hdr: %u, ", type4_ip6->nxt_hdr);
1495 tprintf("Flow Label: 0x%x%x%x", type4_ip6->flow_label1,
1496 type4_ip6->flow_label2, type4_ip6->flow_label3);
1498 else {
1499 tprintf("Version (%u) not supported", type4->version);
1500 return 0;
1503 else if(frm_class->type == 5) {
1504 struct element_tclas_type5 *type5;
1506 type5 = (struct element_tclas_type5 *)
1507 pkt_pull(pkt, sizeof(*type5));
1508 if (type5 == NULL)
1509 return 0;
1511 tprintf("802.1Q PCP: 0x%x, ", type5->pcp);
1512 tprintf("802.1Q CFI: 0x%x, ", type5->cfi);
1513 tprintf("802.1Q VID: 0x%x", type5->vid);
1515 else {
1516 tprintf("Classifier Type (%u) not supported", frm_class->type);
1517 return 0;
1520 return 1;
1523 static int8_t inf_sched(struct pkt_buff *pkt, u8 *id)
1525 struct element_schedule *schedule;
1526 u16 info;
1528 schedule = (struct element_schedule *) pkt_pull(pkt, sizeof(*schedule));
1529 if (schedule == NULL)
1530 return 0;
1532 info = le16_to_cpu(schedule->inf);
1534 tprintf(" Schedule (%u, Len(%u)): ", *id, schedule->len);
1535 if (len_neq_error(schedule->len, 12))
1536 return 0;
1538 tprintf("Aggregation: %u, ", info >> 15);
1539 tprintf("TSID: %u, ", (info >> 11) & 0xF);
1540 tprintf("Direction: %u, ", (info >> 9) & 0x3);
1541 tprintf("Res: %u, ", info & 0x1FF);
1542 tprintf("Serv Start Time: %uus, ", le32_to_cpu(schedule->start));
1543 tprintf("Serv Interval: %uus, ", le32_to_cpu(schedule->serv_intv));
1544 tprintf("Spec Interval: %fs", le32_to_cpu(schedule->spec_intv) * TU);
1546 return 1;
1549 static int8_t inf_chall_txt(struct pkt_buff *pkt, u8 *id)
1551 struct element_chall_txt *chall_txt;
1552 u8 i;
1553 u8 *txt;
1555 chall_txt = (struct element_chall_txt *)
1556 pkt_pull(pkt, sizeof(*chall_txt));
1557 if (chall_txt == NULL)
1558 return 0;
1560 tprintf(" Challenge Text (%u, Len(%u)): ", *id, chall_txt->len);
1561 if ((chall_txt->len - sizeof(*chall_txt) + 1) > 0) {
1562 txt = pkt_pull(pkt, (chall_txt->len - sizeof(*chall_txt) + 1));
1563 if (txt == NULL)
1564 return 0;
1566 tprintf("0x");
1567 for (i = 0; i < (chall_txt->len - sizeof(*chall_txt) + 1); i++)
1568 tprintf("%x", txt[i]);
1571 return 1;
1574 static int8_t inf_pwr_constr(struct pkt_buff *pkt, u8 *id)
1576 struct element_pwr_constr *pwr_constr;
1578 pwr_constr = (struct element_pwr_constr *) pkt_pull(pkt, sizeof(*pwr_constr));
1579 if (pwr_constr == NULL)
1580 return 0;
1582 tprintf(" Power Constraint (%u, Len(%u)): ", *id, pwr_constr->len);
1583 if (len_neq_error(pwr_constr->len, 1))
1584 return 0;
1586 tprintf("Local Power Constraint: %udB", pwr_constr->local_pwr_constr);
1588 return 1;
1591 static int8_t inf_pwr_cap(struct pkt_buff *pkt, u8 *id)
1593 struct element_pwr_cap *pwr_cap;
1595 pwr_cap = (struct element_pwr_cap *) pkt_pull(pkt, sizeof(*pwr_cap));
1596 if (pwr_cap == NULL)
1597 return 0;
1599 tprintf(" Power Capability (%u, Len(%u)): ", *id, pwr_cap->len);
1600 if (len_neq_error(pwr_cap->len, 2))
1601 return 0;
1603 tprintf("Min. Transm. Pwr Cap.: %ddBm, ", (int8_t)pwr_cap->min_pwr_cap);
1604 tprintf("Max. Transm. Pwr Cap.: %ddBm", (int8_t)pwr_cap->max_pwr_cap);
1606 return 1;
1609 static int8_t inf_tpc_req(struct pkt_buff *pkt, u8 *id)
1611 struct element_tpc_req *tpc_req;
1613 tpc_req = (struct element_tpc_req *) pkt_pull(pkt, sizeof(*tpc_req));
1614 if (tpc_req == NULL)
1615 return 0;
1617 tprintf(" TPC Request (%u, Len(%u))", *id, tpc_req->len);
1618 if (len_neq_error(tpc_req->len, 0))
1619 return 0;
1621 return 1;
1624 static int8_t inf_tpc_rep(struct pkt_buff *pkt, u8 *id)
1626 struct element_tpc_rep *tpc_rep;
1628 tpc_rep = (struct element_tpc_rep *) pkt_pull(pkt, sizeof(*tpc_rep));
1629 if (tpc_rep == NULL)
1630 return 0;
1632 tprintf(" TPC Report (%u, Len(%u)): ", *id, tpc_rep->len);
1633 if (len_neq_error(tpc_rep->len, 2))
1634 return 0;
1636 tprintf("Transmit Power: %udBm, ", (int8_t)tpc_rep->trans_pwr);
1637 tprintf("Link Margin: %udB", (int8_t)tpc_rep->trans_pwr);
1639 return 1;
1642 static int8_t inf_supp_ch(struct pkt_buff *pkt, u8 *id)
1644 struct element_supp_ch *supp_ch;
1645 u8 i;
1647 supp_ch = (struct element_supp_ch *) pkt_pull(pkt, sizeof(*supp_ch));
1648 if (supp_ch == NULL)
1649 return 0;
1651 tprintf(" Supp Channels (%u, Len(%u)): ", *id, supp_ch->len);
1652 if (len_lt_error(supp_ch->len, 2))
1653 return 0;
1655 if(supp_ch->len & 1) {
1656 tprintf("Length should be even");
1657 return 0;
1660 for (i = 0; i < supp_ch->len; i += 2) {
1661 struct element_supp_ch_tuple *supp_ch_tuple;
1663 supp_ch_tuple = (struct element_supp_ch_tuple *)
1664 pkt_pull(pkt, sizeof(*supp_ch_tuple));
1665 if (supp_ch_tuple == NULL)
1666 return 0;
1668 tprintf("First Channel Nr: %u, ", supp_ch_tuple->first_ch_nr);
1669 tprintf("Nr of Channels: %u, ", supp_ch_tuple->nr_ch);
1672 return 1;
1675 static int8_t inf_ch_sw_ann(struct pkt_buff *pkt, u8 *id)
1677 struct element_ch_sw_ann *ch_sw_ann;
1679 ch_sw_ann = (struct element_ch_sw_ann *)
1680 pkt_pull(pkt, sizeof(*ch_sw_ann));
1681 if (ch_sw_ann == NULL)
1682 return 0;
1684 tprintf(" Channel Switch Announc (%u, Len(%u)): ", *id, ch_sw_ann->len);
1685 if (len_neq_error(ch_sw_ann->len, 3))
1686 return 0;
1688 tprintf("Switch Mode: %u, ", ch_sw_ann->switch_mode);
1689 tprintf("New Nr: %u, ", ch_sw_ann->new_nr);
1690 tprintf("Switch Count: %u", ch_sw_ann->switch_cnt);
1692 return 1;
1695 static const char *meas_type(u8 type)
1697 switch (type) {
1698 case 0: return "Basic";
1699 case 1: return "Clear Channel assesment (CCA)";
1700 case 2: return "Receive power indication (RPI) histogram";
1701 case 3: return "Channel load";
1702 case 4: return "Noise histogram";
1703 case 5: return "Beacon";
1704 case 6: return "Frame";
1705 case 7: return "STA statistics";
1706 case 8: return "LCI";
1707 case 9: return "Transmit stream/category measurement";
1708 case 10: return "Multicast diagnostics";
1709 case 11: return "Location Civic";
1710 case 12: return "Location Identifier";
1711 default: return "Reserved";
1715 static int8_t inf_meas_req(struct pkt_buff *pkt, u8 *id)
1717 struct element_meas_req *meas_req;
1719 meas_req = (struct element_meas_req *) pkt_pull(pkt, sizeof(*meas_req));
1720 if (meas_req == NULL)
1721 return 0;
1723 tprintf(" Measurement Req (%u, Len(%u)): ", *id, meas_req->len);
1724 if (len_lt_error(meas_req->len, 3))
1725 return 0;
1727 tprintf("Token: %u, ", meas_req->token);
1728 tprintf("Req Mode: 0x%x (Parallel (%u), Enable(%u), Request(%u), "
1729 "Report(%u), Dur Mand(%u), Res(0x%x)), ", meas_req->req_mode,
1730 meas_req->req_mode & 0x1,
1731 (meas_req->req_mode >> 1) & 0x1,
1732 (meas_req->req_mode >> 2) & 0x1,
1733 (meas_req->req_mode >> 3) & 0x1,
1734 (meas_req->req_mode >> 4) & 0x1,
1735 meas_req->req_mode >> 7);
1736 tprintf("Type: %s (%u), ", meas_type(meas_req->type), meas_req->type);
1738 if(meas_req->len > 3) {
1739 if(meas_req->type == 0) {
1740 struct element_meas_basic *basic;
1742 basic = (struct element_meas_basic *)
1743 pkt_pull(pkt, sizeof(*basic));
1744 if (basic == NULL)
1745 return 0;
1747 if ((meas_req->len - 3 - sizeof(*basic)) != 0) {
1748 tprintf("Length of Req matchs not Type %u",
1749 meas_req->type);
1750 return 0;
1753 tprintf("Ch Nr: %uus, ", basic->ch_nr);
1754 tprintf("Meas Start Time: %"PRIu64", ",
1755 le64_to_cpu(basic->start));
1756 tprintf("Meas Duration: %fs",
1757 le16_to_cpu(basic->dur) * TU);
1760 else if(meas_req->type == 1) {
1761 struct element_meas_cca *cca;
1763 cca = (struct element_meas_cca *)
1764 pkt_pull(pkt, sizeof(*cca));
1765 if (cca == NULL)
1766 return 0;
1768 if ((meas_req->len - 3 - sizeof(*cca)) != 0) {
1769 tprintf("Length of Req matchs not Type %u",
1770 meas_req->type);
1771 return 0;
1774 tprintf("Ch Nr: %uus, ", cca->ch_nr);
1775 tprintf("Meas Start Time: %"PRIu64", ",
1776 le64_to_cpu(cca->start));
1777 tprintf("Meas Duration: %fs",
1778 le16_to_cpu(cca->dur) * TU);
1780 else if(meas_req->type == 2) {
1781 struct element_meas_rpi *rpi;
1783 rpi = (struct element_meas_rpi *)
1784 pkt_pull(pkt, sizeof(*rpi));
1785 if (rpi == NULL)
1786 return 0;
1788 if ((meas_req->len - 3 - sizeof(*rpi)) != 0) {
1789 tprintf("Length of Req matchs not Type %u",
1790 meas_req->type);
1791 return 0;
1794 tprintf("Ch Nr: %uus, ", rpi->ch_nr);
1795 tprintf("Meas Start Time: %"PRIu64", ",
1796 le64_to_cpu(rpi->start));
1797 tprintf("Meas Duration: %fs",
1798 le16_to_cpu(rpi->dur) * TU);
1800 else if(meas_req->type == 3) {
1801 struct element_meas_ch_load *ch_load;
1803 ch_load = (struct element_meas_ch_load *)
1804 pkt_pull(pkt, sizeof(*ch_load));
1805 if (ch_load == NULL)
1806 return 0;
1808 if ((ssize_t)(meas_req->len - 3 - sizeof(*ch_load)) < 0) {
1809 tprintf("Length of Req matchs not Type %u",
1810 meas_req->type);
1811 return 0;
1814 tprintf("OP Class: %u, ", ch_load->op_class);
1815 tprintf("Ch Nr: %u, ", ch_load->ch_nr);
1816 tprintf("Rand Intv: %fs, ",
1817 le16_to_cpu(ch_load->rand_intv) * TU);
1818 tprintf("Meas Duration: %fs",
1819 le16_to_cpu(ch_load->dur) * TU);
1821 if(!subelements(pkt,
1822 meas_req->len - 3 - sizeof(*ch_load)))
1823 return 0;
1825 else if(meas_req->type == 4) {
1826 struct element_meas_noise *noise;
1828 noise = (struct element_meas_noise *)
1829 pkt_pull(pkt, sizeof(*noise));
1830 if (noise == NULL)
1831 return 0;
1833 if ((ssize_t)(meas_req->len - 3 - sizeof(*noise)) < 0) {
1834 tprintf("Length of Req matchs not Type %u",
1835 meas_req->type);
1836 return 0;
1839 tprintf("OP Class: %u, ", noise->op_class);
1840 tprintf("Ch Nr: %u, ", noise->ch_nr);
1841 tprintf("Rand Intv: %fs, ",
1842 le16_to_cpu(noise->rand_intv) * TU);
1843 tprintf("Meas Duration: %fs",
1844 le16_to_cpu(noise->dur) * TU);
1846 if(!subelements(pkt,
1847 meas_req->len - 3 - sizeof(*noise)))
1848 return 0;
1850 else if(meas_req->type == 5) {
1851 struct element_meas_beacon *beacon;
1853 beacon = (struct element_meas_beacon *)
1854 pkt_pull(pkt, sizeof(*beacon));
1855 if (beacon == NULL)
1856 return 0;
1858 if ((ssize_t)(meas_req->len - 3 - sizeof(*beacon)) < 0) {
1859 tprintf("Length of Req matchs not Type %u",
1860 meas_req->type);
1861 return 0;
1864 tprintf("OP Class: %u, ", beacon->op_class);
1865 tprintf("Ch Nr: %u, ", beacon->ch_nr);
1866 tprintf("Rand Intv: %fs, ",
1867 le16_to_cpu(beacon->rand_intv) * TU);
1868 tprintf("Meas Duration: %fs",
1869 le16_to_cpu(beacon->dur) * TU);
1870 tprintf("Mode: %u, ", beacon->mode);
1871 tprintf("BSSID: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1872 beacon->bssid[0], beacon->bssid[1],
1873 beacon->bssid[2], beacon->bssid[3],
1874 beacon->bssid[4], beacon->bssid[5]);
1876 if(!subelements(pkt,
1877 meas_req->len - 3 - sizeof(*beacon)))
1878 return 0;
1880 else if(meas_req->type == 6) {
1881 struct element_meas_frame *frame;
1883 frame = (struct element_meas_frame *)
1884 pkt_pull(pkt, sizeof(*frame));
1885 if (frame == NULL)
1886 return 0;
1888 if ((ssize_t)(meas_req->len - 3 - sizeof(*frame)) < 0) {
1889 tprintf("Length of Req matchs not Type %u",
1890 meas_req->type);
1891 return 0;
1894 tprintf("OP Class: %u, ", frame->op_class);
1895 tprintf("Ch Nr: %u, ", frame->ch_nr);
1896 tprintf("Rand Intv: %fs, ",
1897 le16_to_cpu(frame->rand_intv) * TU);
1898 tprintf("Meas Duration: %fs",
1899 le16_to_cpu(frame->dur) * TU);
1900 tprintf("Request Type: %u, ", frame->frame);
1901 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1902 frame->mac[0], frame->mac[1],
1903 frame->mac[2], frame->mac[3],
1904 frame->mac[4], frame->mac[5]);
1906 if(!subelements(pkt,
1907 meas_req->len - 3 - sizeof(*frame)))
1908 return 0;
1910 else if(meas_req->type == 7) {
1911 struct element_meas_sta *sta;
1913 sta = (struct element_meas_sta *)
1914 pkt_pull(pkt, sizeof(*sta));
1915 if (sta == NULL)
1916 return 0;
1918 if ((ssize_t)(meas_req->len - 3 - sizeof(*sta)) < 0) {
1919 tprintf("Length of Req matchs not Type %u",
1920 meas_req->type);
1921 return 0;
1924 tprintf("Peer MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1925 sta->peer_mac[0], sta->peer_mac[1],
1926 sta->peer_mac[2], sta->peer_mac[3],
1927 sta->peer_mac[4], sta->peer_mac[5]);
1928 tprintf("Rand Intv: %fs, ",
1929 le16_to_cpu(sta->rand_intv) * TU);
1930 tprintf("Meas Duration: %fs",
1931 le16_to_cpu(sta->dur) * TU);
1932 tprintf("Group ID: %u, ", sta->group_id);
1934 if(!subelements(pkt,
1935 meas_req->len - 3 - sizeof(*sta)))
1936 return 0;
1938 else if(meas_req->type == 8) {
1939 struct element_meas_lci *lci;
1941 lci = (struct element_meas_lci *)
1942 pkt_pull(pkt, sizeof(*lci));
1943 if (lci == NULL)
1944 return 0;
1946 if ((ssize_t)(meas_req->len - 3 - sizeof(*lci)) < 0) {
1947 tprintf("Length of Req matchs not Type %u",
1948 meas_req->type);
1949 return 0;
1952 tprintf("Location Subj: %u, ", lci->loc_subj);
1953 tprintf("Latitude Req Res: %udeg",
1954 lci->latitude_req_res);
1955 tprintf("Longitude Req Res: %udeg",
1956 lci->longitude_req_res);
1957 tprintf("Altitude Req Res: %udeg",
1958 lci->altitude_req_res);
1960 if(!subelements(pkt,
1961 meas_req->len - 3 - sizeof(*lci)))
1962 return 0;
1964 else if(meas_req->type == 9) {
1965 struct element_meas_trans_str_cat *trans;
1967 trans = (struct element_meas_trans_str_cat *)
1968 pkt_pull(pkt, sizeof(*trans));
1969 if (trans == NULL)
1970 return 0;
1972 if ((ssize_t)(meas_req->len - 3 - sizeof(*trans)) < 0) {
1973 tprintf("Length of Req matchs not Type %u",
1974 meas_req->type);
1975 return 0;
1978 tprintf("Rand Intv: %fs, ",
1979 le16_to_cpu(trans->rand_intv) * TU);
1980 tprintf("Meas Duration: %fs",
1981 le16_to_cpu(trans->dur) * TU);
1982 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1983 trans->peer_sta_addr[0], trans->peer_sta_addr[1],
1984 trans->peer_sta_addr[2], trans->peer_sta_addr[3],
1985 trans->peer_sta_addr[4], trans->peer_sta_addr[5]);
1986 tprintf("Traffic ID: %u, ", trans->traffic_id);
1987 tprintf("Bin 0 Range: %u, ", trans->bin_0_range);
1989 if(!subelements(pkt,
1990 meas_req->len - 3 - sizeof(*trans)))
1991 return 0;
1993 else if(meas_req->type == 10) {
1994 struct element_meas_mcast_diag *mcast;
1996 mcast = (struct element_meas_mcast_diag *)
1997 pkt_pull(pkt, sizeof(*mcast));
1998 if (mcast == NULL)
1999 return 0;
2001 if ((ssize_t)(meas_req->len - 3 - sizeof(*mcast)) < 0) {
2002 tprintf("Length of Req matchs not Type %u",
2003 meas_req->type);
2004 return 0;
2007 tprintf("Rand Intv: %fs, ",
2008 le16_to_cpu(mcast->rand_intv) * TU);
2009 tprintf("Meas Duration: %fs",
2010 le16_to_cpu(mcast->dur) * TU);
2011 tprintf("Group MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2012 mcast->group_mac[0], mcast->group_mac[1],
2013 mcast->group_mac[2], mcast->group_mac[3],
2014 mcast->group_mac[4], mcast->group_mac[5]);
2016 if(!subelements(pkt,
2017 meas_req->len - 3 - sizeof(*mcast)))
2018 return 0;
2020 else if(meas_req->type == 11) {
2021 struct element_meas_loc_civic *civic;
2023 civic = (struct element_meas_loc_civic *)
2024 pkt_pull(pkt, sizeof(*civic));
2025 if (civic == NULL)
2026 return 0;
2028 if ((ssize_t)(meas_req->len - 3 - sizeof(*civic)) < 0) {
2029 tprintf("Length of Req matchs not Type %u",
2030 meas_req->type);
2031 return 0;
2034 tprintf("Location Subj: %u, ", civic->loc_subj);
2035 tprintf("Type: %u, ", civic->civic_loc);
2036 tprintf("Srv Intv Units: %u, ",
2037 le16_to_cpu(civic->loc_srv_intv_unit));
2038 tprintf("Srv Intv: %u, ", civic->loc_srv_intv);
2040 if(!subelements(pkt,
2041 meas_req->len - 3 - sizeof(*civic)))
2042 return 0;
2044 else if(meas_req->type == 12) {
2045 struct element_meas_loc_id *id;
2047 id = (struct element_meas_loc_id *)
2048 pkt_pull(pkt, sizeof(*id));
2049 if (id == NULL)
2050 return 0;
2052 if ((ssize_t)(meas_req->len - 3 - sizeof(*id)) < 0) {
2053 tprintf("Length of Req matchs not Type %u",
2054 meas_req->type);
2055 return 0;
2058 tprintf("Location Subj: %u, ", id->loc_subj);
2059 tprintf("Srv Intv Units: %u, ",
2060 le16_to_cpu(id->loc_srv_intv_unit));
2061 tprintf("Srv Intv: %u", id->loc_srv_intv);
2063 if(!subelements(pkt,
2064 meas_req->len - 3 - sizeof(*id)))
2065 return 0;
2067 else if(meas_req->type == 255) {
2068 struct element_meas_pause *pause;
2070 pause = (struct element_meas_pause *)
2071 pkt_pull(pkt, sizeof(*pause));
2072 if (pause == NULL)
2073 return 0;
2075 if ((ssize_t)(meas_req->len - 3 - sizeof(*pause)) < 0) {
2076 tprintf("Length of Req matchs not Type %u",
2077 meas_req->type);
2078 return 0;
2081 tprintf("Pause Time: %fs, ", pause->time * 10 * TU);
2083 if(!subelements(pkt,
2084 meas_req->len - 3 - sizeof(*pause)))
2085 return 0;
2087 else {
2088 tprintf("Length field indicates data,"
2089 " but could not interpreted");
2090 return 0;
2094 return 1;
2097 static int8_t inf_meas_rep(struct pkt_buff *pkt, u8 *id)
2099 struct element_meas_rep *meas_rep;
2101 meas_rep = (struct element_meas_rep *) pkt_pull(pkt, sizeof(*meas_rep));
2102 if (meas_rep == NULL)
2103 return 0;
2105 tprintf(" Measurement Rep (%u, Len(%u)): ", *id, meas_rep->len);
2106 if (len_lt_error(meas_rep->len, 3))
2107 return 0;
2109 tprintf("Token: %u, ", meas_rep->token);
2110 tprintf("Rep Mode: 0x%x (Late (%u), Incapable(%u), Refused(%u), ",
2111 meas_rep->rep_mode, meas_rep->rep_mode >> 7,
2112 (meas_rep->rep_mode >> 6) & 0x1,
2113 (meas_rep->rep_mode >> 5) & 0x1);
2114 tprintf("Type: %s (%u), ", meas_type(meas_rep->type), meas_rep->type);
2116 if(meas_rep->len > 3) {
2117 if(meas_rep->type == 0) {
2118 struct element_meas_basic *basic;
2120 basic = (struct element_meas_basic *)
2121 pkt_pull(pkt, sizeof(*basic));
2122 if (basic == NULL)
2123 return 0;
2125 if ((meas_rep->len - 3 - sizeof(*basic)) != 0) {
2126 tprintf("Length of Req matchs not Type %u",
2127 meas_rep->type);
2128 return 0;
2131 tprintf("Ch Nr: %uus, ", basic->ch_nr);
2132 tprintf("Meas Start Time: %"PRIu64", ",
2133 le64_to_cpu(basic->start));
2134 tprintf("Meas Duration: %fs",
2135 le16_to_cpu(basic->dur) * TU);
2138 else if(meas_rep->type == 1) {
2139 struct element_meas_cca *cca;
2141 cca = (struct element_meas_cca *)
2142 pkt_pull(pkt, sizeof(*cca));
2143 if (cca == NULL)
2144 return 0;
2146 if ((meas_rep->len - 3 - sizeof(*cca)) != 0) {
2147 tprintf("Length of Req matchs not Type %u",
2148 meas_rep->type);
2149 return 0;
2152 tprintf("Ch Nr: %uus, ", cca->ch_nr);
2153 tprintf("Meas Start Time: %"PRIu64", ",
2154 le64_to_cpu(cca->start));
2155 tprintf("Meas Duration: %fs",
2156 le16_to_cpu(cca->dur) * TU);
2158 else if(meas_rep->type == 2) {
2159 struct element_meas_rpi *rpi;
2161 rpi = (struct element_meas_rpi *)
2162 pkt_pull(pkt, sizeof(*rpi));
2163 if (rpi == NULL)
2164 return 0;
2166 if ((meas_rep->len - 3 - sizeof(*rpi)) != 0) {
2167 tprintf("Length of Req matchs not Type %u",
2168 meas_rep->type);
2169 return 0;
2172 tprintf("Ch Nr: %uus, ", rpi->ch_nr);
2173 tprintf("Meas Start Time: %"PRIu64", ",
2174 le64_to_cpu(rpi->start));
2175 tprintf("Meas Duration: %fs",
2176 le16_to_cpu(rpi->dur) * TU);
2178 else if(meas_rep->type == 3) {
2179 struct element_meas_ch_load *ch_load;
2181 ch_load = (struct element_meas_ch_load *)
2182 pkt_pull(pkt, sizeof(*ch_load));
2183 if (ch_load == NULL)
2184 return 0;
2186 if ((ssize_t)(meas_rep->len - 3 - sizeof(*ch_load)) < 0) {
2187 tprintf("Length of Req matchs not Type %u",
2188 meas_rep->type);
2189 return 0;
2192 tprintf("OP Class: %u, ", ch_load->op_class);
2193 tprintf("Ch Nr: %u, ", ch_load->ch_nr);
2194 tprintf("Rand Intv: %fs, ",
2195 le16_to_cpu(ch_load->rand_intv) * TU);
2196 tprintf("Meas Duration: %fs",
2197 le16_to_cpu(ch_load->dur) * TU);
2199 if(!subelements(pkt,
2200 meas_rep->len - 3 - sizeof(*ch_load)))
2201 return 0;
2203 else if(meas_rep->type == 4) {
2204 struct element_meas_noise *noise;
2206 noise = (struct element_meas_noise *)
2207 pkt_pull(pkt, sizeof(*noise));
2208 if (noise == NULL)
2209 return 0;
2211 if ((ssize_t)(meas_rep->len - 3 - sizeof(*noise)) < 0) {
2212 tprintf("Length of Req matchs not Type %u",
2213 meas_rep->type);
2214 return 0;
2217 tprintf("OP Class: %u, ", noise->op_class);
2218 tprintf("Ch Nr: %u, ", noise->ch_nr);
2219 tprintf("Rand Intv: %fs, ",
2220 le16_to_cpu(noise->rand_intv) * TU);
2221 tprintf("Meas Duration: %fs",
2222 le16_to_cpu(noise->dur) * TU);
2224 if(!subelements(pkt,
2225 meas_rep->len - 3 - sizeof(*noise)))
2226 return 0;
2228 else if(meas_rep->type == 5) {
2229 struct element_meas_beacon *beacon;
2231 beacon = (struct element_meas_beacon *)
2232 pkt_pull(pkt, sizeof(*beacon));
2233 if (beacon == NULL)
2234 return 0;
2236 if ((ssize_t)(meas_rep->len - 3 - sizeof(*beacon)) < 0) {
2237 tprintf("Length of Req matchs not Type %u",
2238 meas_rep->type);
2239 return 0;
2242 tprintf("OP Class: %u, ", beacon->op_class);
2243 tprintf("Ch Nr: %u, ", beacon->ch_nr);
2244 tprintf("Rand Intv: %fs, ",
2245 le16_to_cpu(beacon->rand_intv) * TU);
2246 tprintf("Meas Duration: %fs",
2247 le16_to_cpu(beacon->dur) * TU);
2248 tprintf("Mode: %u, ", beacon->mode);
2249 tprintf("BSSID: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2250 beacon->bssid[0], beacon->bssid[1],
2251 beacon->bssid[2], beacon->bssid[3],
2252 beacon->bssid[4], beacon->bssid[5]);
2254 if(!subelements(pkt,
2255 meas_rep->len - 3 - sizeof(*beacon)))
2256 return 0;
2258 else if(meas_rep->type == 6) {
2259 struct element_meas_frame *frame;
2261 frame = (struct element_meas_frame *)
2262 pkt_pull(pkt, sizeof(*frame));
2263 if (frame == NULL)
2264 return 0;
2266 if ((ssize_t)(meas_rep->len - 3 - sizeof(*frame)) < 0) {
2267 tprintf("Length of Req matchs not Type %u",
2268 meas_rep->type);
2269 return 0;
2272 tprintf("OP Class: %u, ", frame->op_class);
2273 tprintf("Ch Nr: %u, ", frame->ch_nr);
2274 tprintf("Rand Intv: %fs, ",
2275 le16_to_cpu(frame->rand_intv) * TU);
2276 tprintf("Meas Duration: %fs",
2277 le16_to_cpu(frame->dur) * TU);
2278 tprintf("Request Type: %u, ", frame->frame);
2279 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2280 frame->mac[0], frame->mac[1],
2281 frame->mac[2], frame->mac[3],
2282 frame->mac[4], frame->mac[5]);
2284 if(!subelements(pkt,
2285 meas_rep->len - 3 - sizeof(*frame)))
2286 return 0;
2288 else if(meas_rep->type == 7) {
2289 struct element_meas_sta *sta;
2291 sta = (struct element_meas_sta *)
2292 pkt_pull(pkt, sizeof(*sta));
2293 if (sta == NULL)
2294 return 0;
2296 if ((ssize_t)(meas_rep->len - 3 - sizeof(*sta)) < 0) {
2297 tprintf("Length of Req matchs not Type %u",
2298 meas_rep->type);
2299 return 0;
2302 tprintf("Peer MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2303 sta->peer_mac[0], sta->peer_mac[1],
2304 sta->peer_mac[2], sta->peer_mac[3],
2305 sta->peer_mac[4], sta->peer_mac[5]);
2306 tprintf("Rand Intv: %fs, ",
2307 le16_to_cpu(sta->rand_intv) * TU);
2308 tprintf("Meas Duration: %fs",
2309 le16_to_cpu(sta->dur) * TU);
2310 tprintf("Group ID: %u, ", sta->group_id);
2312 if(!subelements(pkt,
2313 meas_rep->len - 3 - sizeof(*sta)))
2314 return 0;
2316 else if(meas_rep->type == 8) {
2317 struct element_meas_lci *lci;
2319 lci = (struct element_meas_lci *)
2320 pkt_pull(pkt, sizeof(*lci));
2321 if (lci == NULL)
2322 return 0;
2324 if ((ssize_t)(meas_rep->len - 3 - sizeof(*lci)) < 0) {
2325 tprintf("Length of Req matchs not Type %u",
2326 meas_rep->type);
2327 return 0;
2330 tprintf("Location Subj: %u, ", lci->loc_subj);
2331 tprintf("Latitude Req Res: %udeg",
2332 lci->latitude_req_res);
2333 tprintf("Longitude Req Res: %udeg",
2334 lci->longitude_req_res);
2335 tprintf("Altitude Req Res: %udeg",
2336 lci->altitude_req_res);
2338 if(!subelements(pkt,
2339 meas_rep->len - 3 - sizeof(*lci)))
2340 return 0;
2342 else if(meas_rep->type == 9) {
2343 struct element_meas_trans_str_cat *trans;
2345 trans = (struct element_meas_trans_str_cat *)
2346 pkt_pull(pkt, sizeof(*trans));
2347 if (trans == NULL)
2348 return 0;
2350 if ((ssize_t)(meas_rep->len - 3 - sizeof(*trans)) < 0) {
2351 tprintf("Length of Req matchs not Type %u",
2352 meas_rep->type);
2353 return 0;
2356 tprintf("Rand Intv: %fs, ",
2357 le16_to_cpu(trans->rand_intv) * TU);
2358 tprintf("Meas Duration: %fs",
2359 le16_to_cpu(trans->dur) * TU);
2360 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2361 trans->peer_sta_addr[0], trans->peer_sta_addr[1],
2362 trans->peer_sta_addr[2], trans->peer_sta_addr[3],
2363 trans->peer_sta_addr[4], trans->peer_sta_addr[5]);
2364 tprintf("Traffic ID: %u, ", trans->traffic_id);
2365 tprintf("Bin 0 Range: %u, ", trans->bin_0_range);
2367 if(!subelements(pkt,
2368 meas_rep->len - 3 - sizeof(*trans)))
2369 return 0;
2371 else if(meas_rep->type == 10) {
2372 struct element_meas_mcast_diag *mcast;
2374 mcast = (struct element_meas_mcast_diag *)
2375 pkt_pull(pkt, sizeof(*mcast));
2376 if (mcast == NULL)
2377 return 0;
2379 if ((ssize_t)(meas_rep->len - 3 - sizeof(*mcast)) < 0) {
2380 tprintf("Length of Req matchs not Type %u",
2381 meas_rep->type);
2382 return 0;
2385 tprintf("Rand Intv: %fs, ",
2386 le16_to_cpu(mcast->rand_intv) * TU);
2387 tprintf("Meas Duration: %fs",
2388 le16_to_cpu(mcast->dur) * TU);
2389 tprintf("Group MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2390 mcast->group_mac[0], mcast->group_mac[1],
2391 mcast->group_mac[2], mcast->group_mac[3],
2392 mcast->group_mac[4], mcast->group_mac[5]);
2394 if(!subelements(pkt,
2395 meas_rep->len - 3 - sizeof(*mcast)))
2396 return 0;
2398 else if(meas_rep->type == 11) {
2399 struct element_meas_loc_civic *civic;
2401 civic = (struct element_meas_loc_civic *)
2402 pkt_pull(pkt, sizeof(*civic));
2403 if (civic == NULL)
2404 return 0;
2406 if ((ssize_t)(meas_rep->len - 3 - sizeof(*civic)) < 0) {
2407 tprintf("Length of Req matchs not Type %u",
2408 meas_rep->type);
2409 return 0;
2412 tprintf("Location Subj: %u, ", civic->loc_subj);
2413 tprintf("Type: %u, ", civic->civic_loc);
2414 tprintf("Srv Intv Units: %u, ",
2415 le16_to_cpu(civic->loc_srv_intv_unit));
2416 tprintf("Srv Intv: %u, ", civic->loc_srv_intv);
2418 if(!subelements(pkt,
2419 meas_rep->len - 3 - sizeof(*civic)))
2420 return 0;
2422 else if(meas_rep->type == 12) {
2423 struct element_meas_loc_id *id;
2425 id = (struct element_meas_loc_id *)
2426 pkt_pull(pkt, sizeof(*id));
2427 if (id == NULL)
2428 return 0;
2430 if ((ssize_t)(meas_rep->len - 3 - sizeof(*id)) < 0) {
2431 tprintf("Length of Req matchs not Type %u",
2432 meas_rep->type);
2433 return 0;
2436 tprintf("Location Subj: %u, ", id->loc_subj);
2437 tprintf("Srv Intv Units: %u, ",
2438 le16_to_cpu(id->loc_srv_intv_unit));
2439 tprintf("Srv Intv: %u", id->loc_srv_intv);
2441 if(!subelements(pkt,
2442 meas_rep->len - 3 - sizeof(*id)))
2443 return 0;
2445 else {
2446 tprintf("Length field indicates data,"
2447 " but could not interpreted");
2448 return 0;
2452 return 1;
2455 static int8_t inf_quiet(struct pkt_buff *pkt, u8 *id)
2457 struct element_quiet *quiet;
2459 quiet = (struct element_quiet *) pkt_pull(pkt, sizeof(*quiet));
2460 if (quiet == NULL)
2461 return 0;
2463 tprintf(" Quit (%u, Len(%u)): ", *id, quiet->len);
2464 if (len_neq_error(quiet->len, 6))
2465 return 0;
2467 tprintf("Count: %ud, ", quiet->cnt);
2468 tprintf("Period: %u, ", quiet->period);
2469 tprintf("Duration: %fs, ", le16_to_cpu(quiet->dur) * TU);
2470 tprintf("Offs: %fs", le16_to_cpu(quiet->offs) * TU);
2473 return 1;
2476 static int8_t inf_ibss_dfs(struct pkt_buff *pkt, u8 *id)
2478 struct element_ibss_dfs *ibss_dfs;
2479 u8 i;
2481 ibss_dfs = (struct element_ibss_dfs *) pkt_pull(pkt, sizeof(*ibss_dfs));
2482 if (ibss_dfs == NULL)
2483 return 0;
2485 tprintf(" IBSS DFS (%u, Len(%u)): ", *id, ibss_dfs->len);
2486 if (len_lt_error(ibss_dfs->len, 7))
2487 return 0;
2489 tprintf("Owner: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2490 ibss_dfs->owner[0], ibss_dfs->owner[1],
2491 ibss_dfs->owner[2], ibss_dfs->owner[3],
2492 ibss_dfs->owner[4], ibss_dfs->owner[5]);
2493 tprintf("Recovery Intv: %u, ", ibss_dfs->rec_intv);
2495 if((ibss_dfs->len - sizeof(*ibss_dfs) + 1) & 1) {
2496 tprintf("Length of Channel Map should be modulo 2");
2497 return 0;
2500 for (i = 0; i < ibss_dfs->len; i += 2) {
2501 struct element_ibss_dfs_tuple *ibss_dfs_tuple;
2503 ibss_dfs_tuple = (struct element_ibss_dfs_tuple *)
2504 pkt_pull(pkt, sizeof(*ibss_dfs_tuple));
2505 if (ibss_dfs_tuple == NULL)
2506 return 0;
2508 tprintf("Channel Nr: %u, ", ibss_dfs_tuple->ch_nr);
2509 tprintf("Map: %u, ", ibss_dfs_tuple->map);
2512 return 1;
2515 static int8_t inf_erp(struct pkt_buff *pkt, u8 *id)
2517 struct element_erp *erp;
2519 erp = (struct element_erp *) pkt_pull(pkt, sizeof(*erp));
2520 if (erp == NULL)
2521 return 0;
2523 tprintf(" ERP (%u, Len(%u)): ", *id, erp->len);
2524 if (len_neq_error(erp->len, 1))
2525 return 0;
2526 tprintf("Non ERP Present (%u), ", erp->param & 0x1);
2527 tprintf("Use Protection (%u), ", (erp->param >> 1) & 0x1);
2528 tprintf("Barker Preamble Mode (%u), ", (erp->param >> 2) & 0x1);
2529 tprintf("Reserved (0x%.5x)", erp->param >> 3);
2531 return 1;
2534 static int8_t inf_ts_del(struct pkt_buff *pkt, u8 *id)
2536 struct element_ts_del *ts_del;
2538 ts_del = (struct element_ts_del *) pkt_pull(pkt, sizeof(*ts_del));
2539 if (ts_del == NULL)
2540 return 0;
2542 tprintf(" TS Delay (%u, Len(%u)): ", *id, ts_del->len);
2543 if (len_neq_error(ts_del->len, 4))
2544 return 0;
2545 tprintf("Delay (%fs)", le32_to_cpu(ts_del->delay) * TU);
2547 return 1;
2550 static int8_t inf_tclas_proc(struct pkt_buff *pkt, u8 *id)
2552 struct element_tclas_proc *tclas_proc;
2554 tclas_proc = (struct element_tclas_proc *)
2555 pkt_pull(pkt, sizeof(*tclas_proc));
2556 if (tclas_proc == NULL)
2557 return 0;
2559 tprintf(" TCLAS Procesing (%u, Len(%u)): ", *id, tclas_proc->len);
2560 if (len_neq_error(tclas_proc->len, 1))
2561 return 0;
2562 tprintf("Processing (%u)", tclas_proc->proc);
2564 return 1;
2567 static int8_t inf_ht_cap(struct pkt_buff *pkt, u8 *id)
2569 struct element_ht_cap *ht_cap;
2570 u32 tx_param_res, beam_cap;
2571 u16 ext_cap;
2573 ht_cap = (struct element_ht_cap *)
2574 pkt_pull(pkt, sizeof(*ht_cap));
2575 if (ht_cap == NULL)
2576 return 0;
2578 tx_param_res = le32_to_cpu(ht_cap->tx_param_res);
2579 beam_cap = le32_to_cpu(ht_cap->beam_cap);
2580 ext_cap = le16_to_cpu(ht_cap->ext_cap);
2582 tprintf(" HT Capabilities (%u, Len(%u)):\n", *id, ht_cap->len);
2583 if (len_neq_error(ht_cap->len, 26))
2584 return 0;
2586 tprintf("\t\t Info:\n");
2587 tprintf("\t\t\t LDCP Cod Cap (%u)\n", ht_cap->ldpc);
2588 tprintf("\t\t\t Supp Ch Width Set (%u)\n", ht_cap->supp_width);
2589 tprintf("\t\t\t SM Pwr Save(%u)\n", ht_cap->sm_pwr);
2590 tprintf("\t\t\t HT-Greenfield (%u)\n", ht_cap->ht_green);
2591 tprintf("\t\t\t Short GI for 20/40 MHz (%u/%u)\n", ht_cap->gi_20mhz,
2592 ht_cap->gi_40mhz);
2593 tprintf("\t\t\t Tx/Rx STBC (%u/%u)\n", ht_cap->tx_stbc,
2594 ht_cap->rx_stbc);
2595 tprintf("\t\t\t HT-Delayed Block Ack (%u)\n", ht_cap->ht_ack);
2596 tprintf("\t\t\t Max A-MSDU Len (%u)\n", ht_cap->max_msdu_length);
2597 tprintf("\t\t\t DSSS/CCK Mode in 40 MHz (%u)\n",
2598 ht_cap->dsss_ck_mode);
2599 tprintf("\t\t\t Res (0x%x)\n", ht_cap->res);
2600 tprintf("\t\t\t Forty MHz Intol (%u)\n", ht_cap->forty_int);
2601 tprintf("\t\t\t L-SIG TXOP Protection Supp (%u)\n",
2602 ht_cap->prot_supp);
2604 tprintf("\t\t A-MPDU Params:\n");
2605 tprintf("\t\t\t Max Len Exp (%u)\n", ht_cap->param >> 6);
2606 tprintf("\t\t\t Min Start Spacing (%u)\n",
2607 (ht_cap->param >> 3) & 0x7);
2608 tprintf("\t\t\t Res (0x%x)\n", ht_cap->param & 0x07);
2610 tprintf("\t\t Supp MCS Set:\n");
2611 tprintf("\t\t\t Rx MCS Bitmask (0x%x%x%x%x%x%x%x%x%x%x)\n",
2612 ht_cap->bitmask1, ht_cap->bitmask2, ht_cap->bitmask3,
2613 ht_cap->bitmask4, ht_cap->bitmask5, ht_cap->bitmask6,
2614 ht_cap->bitmask7, ht_cap->bitmask8, ht_cap->bitmask9,
2615 ht_cap->bitmask10_res >> 3);
2616 tprintf("\t\t\t Res (0x%x)\n", ht_cap->bitmask10_res & 0x7);
2617 tprintf("\t\t\t Rx High Supp Data Rate (%u)\n",
2618 le16_to_cpu(ht_cap->supp_rate_res) >> 6);
2619 tprintf("\t\t\t Res (0x%x)\n",
2620 le16_to_cpu(ht_cap->supp_rate_res) & 0x3F);
2621 tprintf("\t\t\t Tx MCS Set Def (%u)\n", tx_param_res >> 31);
2622 tprintf("\t\t\t Tx Rx MCS Set Not Eq (%u)\n",
2623 (tx_param_res >> 30) & 1);
2624 tprintf("\t\t\t Tx Max Number Spat Str Supp (%u)\n",
2625 (tx_param_res >> 28) & 3);
2626 tprintf("\t\t\t Tx Uneq Mod Supp (%u)\n", (tx_param_res >> 27) & 1);
2627 tprintf("\t\t\t Res (0x%x)\n", tx_param_res & 0x7FFFFFF);
2629 tprintf("\t\t Ext Cap:\n");
2630 tprintf("\t\t\t PCO (%u)\n", ext_cap >> 15);
2631 tprintf("\t\t\t PCO Trans Time (%u)\n", (ext_cap >> 13) & 3);
2632 tprintf("\t\t\t Res (0x%x)\n", (ext_cap >> 8) & 0x1F);
2633 tprintf("\t\t\t MCS Feedb (%u)\n", (ext_cap >> 6) & 3);
2634 tprintf("\t\t\t +HTC Supp (%u)\n", (ext_cap >> 5) & 1);
2635 tprintf("\t\t\t RD Resp (%u)\n", (ext_cap >> 4) & 1);
2636 tprintf("\t\t\t Res (0x%x)\n", ext_cap & 0xF);
2638 tprintf("\t\t Transm Beamf:\n");
2639 tprintf("\t\t\t Impl Transm Beamf Rec Cap (%u)\n", beam_cap >> 31);
2640 tprintf("\t\t\t Rec/Transm Stagg Sound Cap (%u/%u)\n",
2641 (beam_cap >> 30) & 1, (beam_cap >> 29) & 1);
2642 tprintf("\t\t\t Rec/Trans NDP Cap (%u/%u)\n",
2643 (beam_cap >> 28) & 1, (beam_cap >> 27) & 1);
2644 tprintf("\t\t\t Impl Transm Beamf Cap (%u)\n", (beam_cap >> 26) & 1);
2645 tprintf("\t\t\t Cal (%u)\n", (beam_cap >> 24) & 3);
2646 tprintf("\t\t\t Expl CSI Transm Beamf Cap (%u)\n",
2647 (beam_cap >> 23) & 1);
2648 tprintf("\t\t\t Expl Noncmpr/Compr Steering Cap (%u/%u)\n",
2649 (beam_cap >> 22) & 1, (beam_cap >> 21) & 1);
2650 tprintf("\t\t\t Expl Trans Beamf CSI Feedb (%u)\n",
2651 (beam_cap >> 19) & 3);
2652 tprintf("\t\t\t Expl Noncmpr/Cmpr Feedb Cap (%u/%u)\n",
2653 (beam_cap >> 17) & 3, (beam_cap >> 15) & 3);
2654 tprintf("\t\t\t Min Grpg (%u)\n", (beam_cap >> 13) & 3);
2655 tprintf("\t\t\t CSI Num Beamf Ant Supp (%u)\n", (beam_cap >> 11) & 3);
2656 tprintf("\t\t\t Noncmpr/Cmpr Steering Nr Beamf Ant Supp (%u/%u)\n",
2657 (beam_cap >> 9) & 3, (beam_cap >> 7) & 3);
2658 tprintf("\t\t\t CSI Max Nr Rows Beamf Supp (%u)\n",
2659 (beam_cap >> 5) & 3);
2660 tprintf("\t\t\t Ch Estim Cap (%u)\n", (beam_cap >> 3) & 3);
2661 tprintf("\t\t\t Res (0x%x)\n", beam_cap & 7);
2663 tprintf("\t\t ASEL:\n");
2664 tprintf("\t\t\t Ant Select Cap (%u)\n", ht_cap->asel_cap >> 7);
2665 tprintf("\t\t\t Expl CSI Feedb Based Transm ASEL Cap (%u)\n",
2666 (ht_cap->asel_cap >> 6) & 1);
2667 tprintf("\t\t\t Ant Indic Feedb Based Transm ASEL Cap (%u)\n",
2668 (ht_cap->asel_cap >> 5) & 1);
2669 tprintf("\t\t\t Expl CSI Feedb Cap (%u)\n",
2670 (ht_cap->asel_cap >> 4) & 1);
2671 tprintf("\t\t\t Ant Indic Feedb Cap (%u)\n",
2672 (ht_cap->asel_cap >> 3) & 1);
2673 tprintf("\t\t\t Rec ASEL Cap (%u)\n", (ht_cap->asel_cap >> 2) & 1);
2674 tprintf("\t\t\t Transm Sound PPDUs Cap (%u)\n",
2675 (ht_cap->asel_cap >> 1) & 1);
2676 tprintf("\t\t\t Res (0x%x)", ht_cap->asel_cap & 1);
2678 return 1;
2681 static int8_t inf_qos_cap(struct pkt_buff *pkt, u8 *id)
2683 struct element_qos_cap *qos_cap;
2685 qos_cap = (struct element_qos_cap *)
2686 pkt_pull(pkt, sizeof(*qos_cap));
2687 if (qos_cap == NULL)
2688 return 0;
2690 tprintf(" QoS Capabilities (%u, Len(%u)): ", *id, qos_cap->len);
2691 if (len_neq_error(qos_cap->len, 1))
2692 return 0;
2694 tprintf("Info (0x%x)", qos_cap->info);
2696 return 1;
2699 static int8_t inf_ext_supp_rates(struct pkt_buff *pkt, u8 *id)
2701 u8 i;
2702 u8 *rates;
2703 struct element_ext_supp_rates *ext_supp_rates;
2705 ext_supp_rates = (struct element_ext_supp_rates *)
2706 pkt_pull(pkt, sizeof(*ext_supp_rates));
2707 if (ext_supp_rates == NULL)
2708 return 0;
2710 tprintf(" Ext Support Rates (%u, Len(%u)): ", *id, ext_supp_rates->len);
2712 if ((ext_supp_rates->len - sizeof(*ext_supp_rates) + 1) > 0) {
2713 rates = pkt_pull(pkt, ext_supp_rates->len);
2714 if (rates == NULL)
2715 return 0;
2717 for (i = 0; i < ext_supp_rates->len; i++)
2718 tprintf("%g ", (rates[i] & 0x80) ?
2719 ((rates[i] & 0x3f) * 0.5) :
2720 data_rates(rates[i]));
2721 return 1;
2724 return 0;
2727 static int8_t inf_vend_spec(struct pkt_buff *pkt, u8 *id)
2729 u8 i;
2730 u8 *data;
2731 struct element_vend_spec *vend_spec;
2733 vend_spec = (struct element_vend_spec *)
2734 pkt_pull(pkt, sizeof(*vend_spec));
2735 if (vend_spec == NULL)
2736 return 0;
2738 tprintf(" Vendor Specific (%u, Len (%u)): ", *id, vend_spec->len);
2740 data = pkt_pull(pkt, vend_spec->len);
2741 if (data == NULL)
2742 return 0;
2744 tprintf("Data 0x");
2745 for (i = 0; i < vend_spec->len; i++)
2746 tprintf("%.2x", data[i]);
2748 return 1;
2751 static int8_t inf_unimplemented(struct pkt_buff *pkt __maybe_unused,
2752 u8 *id __maybe_unused)
2754 return 0;
2757 static int8_t inf_elements(struct pkt_buff *pkt)
2759 u8 *id = pkt_pull(pkt, 1);
2760 if (id == NULL)
2761 return 0;
2763 switch (*id) {
2764 case 0: return inf_ssid(pkt, id);
2765 case 1: return inf_supp_rates(pkt, id);
2766 case 2: return inf_fh_ps(pkt, id);
2767 case 3: return inf_dsss_ps(pkt, id);
2768 case 4: return inf_cf_ps(pkt, id);
2769 case 5: return inf_tim(pkt, id);
2770 case 6: return inf_ibss_ps(pkt, id);
2771 case 7: return inf_country(pkt, id);
2772 case 8: return inf_hop_pp(pkt, id);
2773 case 9: return inf_hop_pt(pkt, id);
2774 case 10: return inf_req(pkt, id);
2775 case 11: return inf_bss_load(pkt, id);
2776 case 12: return inf_edca_ps(pkt, id);
2777 case 13: return inf_tspec(pkt, id);
2778 case 14: return inf_tclas(pkt, id);
2779 case 15: return inf_sched(pkt, id);
2780 case 16: return inf_chall_txt(pkt, id);
2781 case 17 ... 31: return inf_reserved(pkt, id);
2782 case 32: return inf_pwr_constr(pkt, id);
2783 case 33: return inf_pwr_cap(pkt, id);
2784 case 34: return inf_tpc_req(pkt, id);
2785 case 35: return inf_tpc_rep(pkt, id);
2786 case 36: return inf_supp_ch(pkt, id);
2787 case 37: return inf_ch_sw_ann(pkt, id);
2788 case 38: return inf_meas_req(pkt, id);
2789 case 39: return inf_meas_rep(pkt, id);
2790 case 40: return inf_quiet(pkt, id);
2791 case 41: return inf_ibss_dfs(pkt, id);
2792 case 42: return inf_erp(pkt, id);
2793 case 43: return inf_ts_del(pkt, id);
2794 case 44: return inf_tclas_proc(pkt, id);
2795 case 45: return inf_ht_cap(pkt, id);
2796 case 46: return inf_qos_cap(pkt, id);
2797 case 47: return inf_reserved(pkt, id);
2798 case 48: return inf_unimplemented(pkt, id);
2799 case 49: return inf_unimplemented(pkt, id);
2800 case 50: return inf_ext_supp_rates(pkt, id);
2801 case 51: return inf_unimplemented(pkt, id);
2802 case 52: return inf_unimplemented(pkt, id);
2803 case 53: return inf_unimplemented(pkt, id);
2804 case 54: return inf_unimplemented(pkt, id);
2805 case 55: return inf_unimplemented(pkt, id);
2806 case 56: return inf_unimplemented(pkt, id);
2807 case 57: return inf_unimplemented(pkt, id);
2808 case 58: return inf_unimplemented(pkt, id);
2809 case 59: return inf_unimplemented(pkt, id);
2810 case 60: return inf_unimplemented(pkt, id);
2811 case 61: return inf_unimplemented(pkt, id);
2812 case 62: return inf_unimplemented(pkt, id);
2813 case 63: return inf_unimplemented(pkt, id);
2814 case 64: return inf_unimplemented(pkt, id);
2815 case 65: return inf_unimplemented(pkt, id);
2816 case 66: return inf_unimplemented(pkt, id);
2817 case 67: return inf_unimplemented(pkt, id);
2818 case 68: return inf_unimplemented(pkt, id);
2819 case 69: return inf_unimplemented(pkt, id);
2820 case 70: return inf_unimplemented(pkt, id);
2821 case 71: return inf_unimplemented(pkt, id);
2822 case 72: return inf_unimplemented(pkt, id);
2823 case 73: return inf_unimplemented(pkt, id);
2824 case 74: return inf_unimplemented(pkt, id);
2825 case 75: return inf_unimplemented(pkt, id);
2826 case 76: return inf_unimplemented(pkt, id);
2827 case 78: return inf_unimplemented(pkt, id);
2828 case 79: return inf_unimplemented(pkt, id);
2829 case 80: return inf_unimplemented(pkt, id);
2830 case 81: return inf_unimplemented(pkt, id);
2831 case 82: return inf_unimplemented(pkt, id);
2832 case 83: return inf_unimplemented(pkt, id);
2833 case 84: return inf_unimplemented(pkt, id);
2834 case 85: return inf_unimplemented(pkt, id);
2835 case 86: return inf_unimplemented(pkt, id);
2836 case 87: return inf_unimplemented(pkt, id);
2837 case 88: return inf_unimplemented(pkt, id);
2838 case 89: return inf_unimplemented(pkt, id);
2839 case 90: return inf_unimplemented(pkt, id);
2840 case 91: return inf_unimplemented(pkt, id);
2841 case 92: return inf_unimplemented(pkt, id);
2842 case 93: return inf_unimplemented(pkt, id);
2843 case 94: return inf_unimplemented(pkt, id);
2844 case 95: return inf_unimplemented(pkt, id);
2845 case 96: return inf_unimplemented(pkt, id);
2846 case 97: return inf_unimplemented(pkt, id);
2847 case 98: return inf_unimplemented(pkt, id);
2848 case 99: return inf_unimplemented(pkt, id);
2849 case 100: return inf_unimplemented(pkt, id);
2850 case 101: return inf_unimplemented(pkt, id);
2851 case 102: return inf_unimplemented(pkt, id);
2852 case 104: return inf_unimplemented(pkt, id);
2853 case 105: return inf_unimplemented(pkt, id);
2854 case 106: return inf_unimplemented(pkt, id);
2855 case 107: return inf_unimplemented(pkt, id);
2856 case 108: return inf_unimplemented(pkt, id);
2857 case 109: return inf_unimplemented(pkt, id);
2858 case 110: return inf_unimplemented(pkt, id);
2859 case 111: return inf_unimplemented(pkt, id);
2860 case 112: return inf_unimplemented(pkt, id);
2861 case 113: return inf_unimplemented(pkt, id);
2862 case 114: return inf_unimplemented(pkt, id);
2863 case 115: return inf_unimplemented(pkt, id);
2864 case 116: return inf_unimplemented(pkt, id);
2865 case 117: return inf_unimplemented(pkt, id);
2866 case 118: return inf_unimplemented(pkt, id);
2867 case 119: return inf_unimplemented(pkt, id);
2868 case 120: return inf_unimplemented(pkt, id);
2869 case 121: return inf_unimplemented(pkt, id);
2870 case 122: return inf_unimplemented(pkt, id);
2871 case 123: return inf_unimplemented(pkt, id);
2872 case 124: return inf_unimplemented(pkt, id);
2873 case 125: return inf_unimplemented(pkt, id);
2874 case 126: return inf_unimplemented(pkt, id);
2875 case 127: return inf_unimplemented(pkt, id);
2876 case 128: return inf_reserved(pkt, id);
2877 case 129: return inf_reserved(pkt, id);
2878 case 130: return inf_unimplemented(pkt, id);
2879 case 131: return inf_unimplemented(pkt, id);
2880 case 132: return inf_unimplemented(pkt, id);
2881 case 133: return inf_reserved(pkt, id);
2882 case 134: return inf_reserved(pkt, id);
2883 case 135: return inf_reserved(pkt, id);
2884 case 136: return inf_reserved(pkt, id);
2885 case 137: return inf_unimplemented(pkt, id);
2886 case 138: return inf_unimplemented(pkt, id);
2887 case 139: return inf_unimplemented(pkt, id);
2888 case 140: return inf_unimplemented(pkt, id);
2889 case 141: return inf_unimplemented(pkt, id);
2890 case 142: return inf_unimplemented(pkt, id);
2891 case 143 ... 173: return inf_reserved(pkt, id);
2892 case 174: return inf_unimplemented(pkt, id);
2893 case 221: return inf_vend_spec(pkt, id);
2896 return 0;
2899 #define ESS 0x0001
2900 #define IBSS 0x0002
2901 #define CF_Pollable 0x0004
2902 #define CF_Poll_Req 0x0008
2903 #define Privacy 0x0010
2904 #define Short_Pre 0x0020
2905 #define PBCC 0x0040
2906 #define Ch_Agility 0x0080
2907 #define Spec_Mgmt 0x0100
2908 #define QoS 0x0200
2909 #define Short_Slot_t 0x0400
2910 #define APSD 0x0800
2911 #define Radio_Meas 0x1000
2912 #define DSSS_OFDM 0x2000
2913 #define Del_Block_ACK 0x4000
2914 #define Imm_Block_ACK 0x8000
2916 static int8_t cap_field(u16 cap_inf)
2918 if (ESS & cap_inf)
2919 tprintf(" ESS;");
2920 if (IBSS & cap_inf)
2921 tprintf(" IBSS;");
2922 if (CF_Pollable & cap_inf)
2923 tprintf(" CF Pollable;");
2924 if (CF_Poll_Req & cap_inf)
2925 tprintf(" CF-Poll Request;");
2926 if (Privacy & cap_inf)
2927 tprintf(" Privacy;");
2928 if (Short_Pre & cap_inf)
2929 tprintf(" Short Preamble;");
2930 if (PBCC & cap_inf)
2931 tprintf(" PBCC;");
2932 if (Ch_Agility & cap_inf)
2933 tprintf(" Channel Agility;");
2934 if (Spec_Mgmt & cap_inf)
2935 tprintf(" Spectrum Management;");
2936 if (QoS & cap_inf)
2937 tprintf(" QoS;");
2938 if (Short_Slot_t & cap_inf)
2939 tprintf(" Short Slot Time;");
2940 if (APSD & cap_inf)
2941 tprintf(" APSD;");
2942 if (Radio_Meas & cap_inf)
2943 tprintf(" Radio Measurement;");
2944 if (DSSS_OFDM & cap_inf)
2945 tprintf(" DSSS-OFDM;");
2946 if (Del_Block_ACK & cap_inf)
2947 tprintf(" Delayed Block Ack;");
2948 if (Imm_Block_ACK & cap_inf)
2949 tprintf(" Immediate Block Ack;");
2951 return 1;
2954 static void print_inf_elements(struct pkt_buff *pkt)
2956 if (pkt_len(pkt)) {
2957 do {
2958 if (pkt_len(pkt))
2959 tprintf("\n\tIE:");
2961 } while (inf_elements(pkt));
2965 /* Management Dissectors */
2966 static int8_t mgmt_beacon_dissect(struct pkt_buff *pkt)
2968 struct ieee80211_mgmt_beacon *beacon;
2970 beacon = (struct ieee80211_mgmt_beacon *)
2971 pkt_pull(pkt, sizeof(*beacon));
2972 if (beacon == NULL)
2973 return 0;
2975 tprintf("Timestamp 0x%.16"PRIx64", ", le64_to_cpu(beacon->timestamp));
2976 tprintf("Beacon Interval (%fs), ", le16_to_cpu(beacon->beacon_int)*TU);
2977 tprintf("Capabilities (0x%x <->", le16_to_cpu(beacon->capab_info));
2978 cap_field(le16_to_cpu(beacon->capab_info));
2979 tprintf(")");
2981 print_inf_elements(pkt);
2983 if (pkt_len(pkt))
2984 return 0;
2986 return 1;
2989 static int8_t mgmt_probe_request_dissect(struct pkt_buff *pkt)
2991 print_inf_elements(pkt);
2993 if (pkt_len(pkt))
2994 return 0;
2996 return 1;
2999 static int8_t mgmt_unimplemented(struct pkt_buff *pkt __maybe_unused)
3001 return 0;
3003 /* End Management Dissectors */
3005 /* Control Dissectors */
3006 static int8_t ctrl_unimplemented(struct pkt_buff *pkt __maybe_unused)
3008 return 0;
3010 /* End Control Dissectors */
3012 /* Data Dissectors */
3013 static int8_t data_unimplemented(struct pkt_buff *pkt __maybe_unused)
3015 return 0;
3017 /* End Data Dissectors */
3019 static const char *mgt_sub(u8 subtype, struct pkt_buff *pkt,
3020 int8_t (**get_content)(struct pkt_buff *pkt))
3022 u16 seq_ctrl;
3023 struct ieee80211_mgmt *mgmt;
3024 const char *dst, *src, *bssid;
3026 mgmt = (struct ieee80211_mgmt *) pkt_pull(pkt, sizeof(*mgmt));
3027 if (!mgmt)
3028 return NULL;
3030 dst = lookup_vendor((mgmt->da[0] << 16) |
3031 (mgmt->da[1] << 8) |
3032 mgmt->da[2]);
3033 src = lookup_vendor((mgmt->sa[0] << 16) |
3034 (mgmt->sa[1] << 8) |
3035 mgmt->sa[2]);
3037 bssid = lookup_vendor((mgmt->bssid[0] << 16) |
3038 (mgmt->bssid[1] << 8) |
3039 mgmt->bssid[2]);
3040 seq_ctrl = le16_to_cpu(mgmt->seq_ctrl);
3042 tprintf("Duration (%u),", le16_to_cpu(mgmt->duration));
3043 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
3044 mgmt->da[0], mgmt->da[1], mgmt->da[2],
3045 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
3046 if (dst) {
3047 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst,
3048 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
3051 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
3052 mgmt->sa[0], mgmt->sa[1], mgmt->sa[2],
3053 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
3054 if (src) {
3055 tprintf("=> (%s:%.2x:%.2x:%.2x)", src,
3056 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
3059 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
3060 mgmt->bssid[0], mgmt->bssid[1], mgmt->bssid[2],
3061 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
3062 if(bssid) {
3063 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid,
3064 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
3067 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ",
3068 seq_ctrl & 0xf, seq_ctrl >> 4);
3070 switch (subtype) {
3071 case 0x0:
3072 *get_content = mgmt_unimplemented;
3073 return "Association Request";
3074 case 0x1:
3075 *get_content = mgmt_unimplemented;
3076 return "Association Response";
3077 case 0x2:
3078 *get_content = mgmt_unimplemented;
3079 return "Reassociation Request";
3080 case 0x3:
3081 *get_content = mgmt_unimplemented;
3082 return "Reassociation Response";
3083 case 0x4:
3084 *get_content = mgmt_probe_request_dissect;
3085 return "Probe Request";
3086 case 0x5:
3087 /* Probe Response is very similar to Beacon except some IEs */
3088 *get_content = mgmt_beacon_dissect;
3089 return "Probe Response";
3090 case 0x8:
3091 *get_content = mgmt_beacon_dissect;
3092 return "Beacon";
3093 case 0x9:
3094 *get_content = mgmt_unimplemented;
3095 return "ATIM";
3096 case 0xA:
3097 *get_content = mgmt_unimplemented;
3098 return "Disassociation";
3099 case 0xB:
3100 *get_content = mgmt_unimplemented;
3101 return "Authentication";
3102 case 0xC:
3103 *get_content = mgmt_unimplemented;
3104 return "Deauthentication";
3105 default:
3106 *get_content = NULL;
3107 return "Reserved";
3111 static const char *ctrl_sub(u8 subtype, struct pkt_buff *pkt __maybe_unused,
3112 int8_t (**get_content)(struct pkt_buff *pkt))
3114 switch (subtype) {
3115 case 0xA:
3116 *get_content = ctrl_unimplemented;
3117 return "PS-Poll";
3118 case 0xB:
3119 *get_content = ctrl_unimplemented;
3120 return "RTS";
3121 case 0xC:
3122 *get_content = ctrl_unimplemented;
3123 return "CTS";
3124 case 0xD:
3125 *get_content = ctrl_unimplemented;
3126 return "ACK";
3127 case 0xE:
3128 *get_content = ctrl_unimplemented;
3129 return "CF End";
3130 case 0xF:
3131 *get_content = ctrl_unimplemented;
3132 return "CF End + CF-ACK";
3133 default:
3134 *get_content = NULL;
3135 return "Reserved";
3139 static const char *data_sub(u8 subtype, struct pkt_buff *pkt __maybe_unused,
3140 int8_t (**get_content)(struct pkt_buff *pkt))
3142 switch (subtype) {
3143 case 0x0:
3144 *get_content = data_unimplemented;
3145 return "Data";
3146 case 0x1:
3147 *get_content = data_unimplemented;
3148 return "Data + CF-ACK";
3149 case 0x2:
3150 *get_content = data_unimplemented;
3151 return "Data + CF-Poll";
3152 case 0x3:
3153 *get_content = data_unimplemented;
3154 return "Data + CF-ACK + CF-Poll";
3155 case 0x4:
3156 *get_content = data_unimplemented;
3157 return "Null";
3158 case 0x5:
3159 *get_content = data_unimplemented;
3160 return "CF-ACK";
3161 case 0x6:
3162 *get_content = data_unimplemented;
3163 return "CF-Poll";
3164 case 0x7:
3165 *get_content = data_unimplemented;
3166 return "CF-ACK + CF-Poll";
3167 default:
3168 *get_content = NULL;
3169 return "Reserved";
3173 static const char *
3174 frame_control_type(u8 type, const char *(**get_subtype)(u8 subtype,
3175 struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)))
3177 switch (type) {
3178 case 0x0:
3179 *get_subtype = mgt_sub;
3180 return "Management";
3181 case 0x1:
3182 *get_subtype = ctrl_sub;
3183 return "Control";
3184 case 0x2:
3185 *get_subtype = data_sub;
3186 return "Data";
3187 case 0x3:
3188 *get_subtype = NULL;
3189 return "Reserved";
3190 default:
3191 *get_subtype = NULL;
3192 return "Control Type unknown";
3196 static void ieee80211(struct pkt_buff *pkt)
3198 int8_t (*get_content)(struct pkt_buff *pkt) = NULL;
3199 const char *(*get_subtype)(u8 subtype, struct pkt_buff *pkt,
3200 int8_t (**get_content)(struct pkt_buff *pkt)) = NULL;
3201 const char *subtype = NULL;
3202 struct ieee80211_frm_ctrl *frm_ctrl;
3204 if (pkt->link_type == LINKTYPE_IEEE802_11_RADIOTAP) {
3205 struct ieee80211_radiotap_header *rtap;
3207 rtap = (struct ieee80211_radiotap_header *)pkt_pull(pkt,
3208 sizeof(*rtap));
3209 if (rtap == NULL)
3210 return;
3212 tprintf(" [ Radiotap ");
3213 tprintf("Version (%u), ", rtap->version);
3214 tprintf("Length (%u), ", le16_to_cpu(rtap->len));
3215 tprintf("Flags (0x%08x) ]\n", le32_to_cpu(rtap->present));
3217 pkt_pull(pkt, le16_to_cpu(rtap->len) - sizeof(*rtap));
3220 frm_ctrl = (struct ieee80211_frm_ctrl *)pkt_pull(pkt, sizeof(*frm_ctrl));
3221 if (frm_ctrl == NULL)
3222 return;
3224 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
3225 le16_to_cpu(frm_ctrl->frame_control));
3227 tprintf(" [ Proto Version (%u), ", frm_ctrl->proto_version);
3228 tprintf("Type (%u, %s), ", frm_ctrl->type,
3229 frame_control_type(frm_ctrl->type, &get_subtype));
3230 if (get_subtype) {
3231 subtype = (*get_subtype)(frm_ctrl->subtype, pkt, &get_content);
3232 tprintf("Subtype (%u, %s)", frm_ctrl->subtype, subtype);
3233 } else {
3234 tprintf("%s%s%s", colorize_start_full(black, red),
3235 "No SubType Data available", colorize_end());
3238 tprintf("%s%s", frm_ctrl->to_ds ? ", Frame goes to DS" : "",
3239 frm_ctrl->from_ds ? ", Frame comes from DS" : "");
3240 tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : "");
3241 tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : "");
3242 tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : "");
3243 tprintf("%s", frm_ctrl->more_data ? ", More Data" : "");
3244 tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : "");
3245 tprintf("%s", frm_ctrl->order ? ", Order" : "");
3246 tprintf(" ]\n");
3248 if (get_content) {
3249 tprintf(" [ Subtype %s: ", subtype);
3250 if (!((*get_content) (pkt)))
3251 tprintf("%s%s%s", colorize_start_full(black, red),
3252 "Failed to dissect Subtype", colorize_end());
3253 tprintf(" ]");
3254 } else {
3255 tprintf("%s%s%s", colorize_start_full(black, red),
3256 "No SubType Data available", colorize_end());
3259 tprintf("\n");
3261 // pkt_set_dissector(pkt, &ieee802_lay2, ntohs(eth->h_proto));
3264 static void ieee80211_less(struct pkt_buff *pkt __maybe_unused)
3266 tprintf("802.11 frame (more on todo)");
3269 struct protocol ieee80211_ops = {
3270 .key = 0,
3271 .print_full = ieee80211,
3272 .print_less = ieee80211_less,