proto_80211_mac_hdr.c: add elements ts delay and tclas processing
[netsniff-ng.git] / src / proto_80211_mac_hdr.c
blob05eea878058172b66e0653b1f1e928847cffdd48
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Markus Amend <markus@netsniff-ng.org>
4 * Copyright 2012 Daniel Borkmann <daniel@netsniff-ng.org>
5 * Subject to the GPL, version 2.
6 */
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <netinet/in.h> /* for ntohs() */
11 #include <asm/byteorder.h>
12 #include <arpa/inet.h> /* for inet_ntop() */
14 #include "proto.h"
15 #include "protos.h"
16 #include "dissector_80211.h"
17 #include "built_in.h"
18 #include "pkt_buff.h"
19 #include "oui.h"
21 #define TU 0.001024
23 /* Note: Fields are encoded in little-endian! */
24 struct ieee80211_frm_ctrl {
25 union {
26 u16 frame_control;
27 struct {
28 #if defined(__LITTLE_ENDIAN_BITFIELD)
29 /* Correct order here ... */
30 __extension__ u16 proto_version:2,
31 type:2,
32 subtype:4,
33 to_ds:1,
34 from_ds:1,
35 more_frags:1,
36 retry:1,
37 power_mgmt:1,
38 more_data:1,
39 wep:1,
40 order:1;
41 #elif defined(__BIG_ENDIAN_BITFIELD)
42 __extension__ u16 subtype:4,
43 type:2,
44 proto_version:2,
45 order:1,
46 wep:1,
47 more_data:1,
48 power_mgmt:1,
49 retry:1,
50 more_frags:1,
51 from_ds:1,
52 to_ds:1;
53 #else
54 # error "Adjust your <asm/byteorder.h> defines"
55 #endif
58 } __packed;
60 /* Management Frame start */
61 /* Note: Fields are encoded in little-endian! */
62 struct ieee80211_mgmt {
63 u16 duration;
64 u8 da[6];
65 u8 sa[6];
66 u8 bssid[6];
67 u16 seq_ctrl;
68 } __packed;
70 struct ieee80211_mgmt_auth {
71 u16 auth_alg;
72 u16 auth_transaction;
73 u16 status_code;
74 /* possibly followed by Challenge text */
75 u8 variable[0];
76 } __packed;
78 struct ieee80211_mgmt_deauth {
79 u16 reason_code;
80 } __packed;
82 struct ieee80211_mgmt_assoc_req {
83 u16 capab_info;
84 u16 listen_interval;
85 /* followed by SSID and Supported rates */
86 u8 variable[0];
87 } __packed;
89 struct ieee80211_mgmt_assoc_resp {
90 u16 capab_info;
91 u16 status_code;
92 u16 aid;
93 /* followed by Supported rates */
94 u8 variable[0];
95 } __packed;
97 struct ieee80211_mgmt_reassoc_resp {
98 u16 capab_info;
99 u16 status_code;
100 u16 aid;
101 /* followed by Supported rates */
102 u8 variable[0];
103 } __packed;
105 struct ieee80211_mgmt_reassoc_req {
106 u16 capab_info;
107 u16 listen_interval;
108 u8 current_ap[6];
109 /* followed by SSID and Supported rates */
110 u8 variable[0];
111 } __packed;
113 struct ieee80211_mgmt_disassoc {
114 u16 reason_code;
115 } __packed;
117 struct ieee80211_mgmt_probe_req {
118 } __packed;
120 struct ieee80211_mgmt_beacon {
121 u64 timestamp;
122 u16 beacon_int;
123 u16 capab_info;
124 /* followed by some of SSID, Supported rates,
125 * FH Params, DS Params, CF Params, IBSS Params, TIM */
126 u8 variable[0];
127 } __packed;
129 struct ieee80211_mgmt_probe_resp {
130 u8 timestamp[8];
131 u16 beacon_int;
132 u16 capab_info;
133 /* followed by some of SSID, Supported rates,
134 * FH Params, DS Params, CF Params, IBSS Params, TIM */
135 u8 variable[0];
136 } __packed;
137 /* Management Frame end */
139 /* Control Frame start */
140 /* Note: Fields are encoded in little-endian! */
141 struct ieee80211_ctrl {
142 } __packed;
144 struct ieee80211_ctrl_rts {
145 u16 duration;
146 u8 da[6];
147 u8 sa[6];
148 } __packed;
150 struct ieee80211_ctrl_cts {
151 u16 duration;
152 u8 da[6];
153 } __packed;
155 struct ieee80211_ctrl_ack {
156 u16 duration;
157 u8 da[6];
158 } __packed;
160 struct ieee80211_ctrl_ps_poll {
161 u16 aid;
162 u8 bssid[6];
163 u8 sa[6];
164 } __packed;
166 struct ieee80211_ctrl_cf_end {
167 u16 duration;
168 u8 bssid[6];
169 u8 sa[6];
170 } __packed;
172 struct ieee80211_ctrl_cf_end_ack {
173 u16 duration;
174 u8 bssid[6];
175 u8 sa[6];
176 } __packed;
177 /* Control Frame end */
179 /* Data Frame start */
180 /* Note: Fields are encoded in little-endian! */
181 struct ieee80211_data {
182 } __packed;
184 /* TODO: Extend */
185 /* Data Frame end */
187 /* http://www.sss-mag.com/pdf/802_11tut.pdf
188 * http://www.scribd.com/doc/78443651/111/Management-Frames
189 * http://www.wildpackets.com/resources/compendium/wireless_lan/wlan_packets
190 * http://www.rhyshaden.com/wireless.htm
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 SSID[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 apsid: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 apsid: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;
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;
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_ext_supp_rates {
678 u8 len;
679 u8 rates[0];
680 } __packed;
682 struct element_vend_spec {
683 u8 len;
684 u8 oui[0];
685 u8 specific[0];
686 } __packed;
688 static int8_t len_neq_error(u8 len, u8 intended)
690 if(intended != len) {
691 tprintf("Length should be %u Bytes", intended);
692 return 1;
695 return 0;
698 static int8_t len_lt_error(u8 len, u8 intended)
700 if(len < intended) {
701 tprintf("Length should be greater %u Bytes", intended);
702 return 1;
705 return 0;
708 static float data_rates(u8 id)
710 /* XXX Why not (id / 2.f)? */
711 switch (id) {
712 case 2: return 1.0f;
713 case 3: return 1.5f;
714 case 4: return 2.0f;
715 case 5: return 2.5f;
716 case 6: return 3.0f;
717 case 9: return 4.5f;
718 case 11: return 5.5f;
719 case 12: return 6.0f;
720 case 18: return 9.0f;
721 case 22: return 11.0f;
722 case 24: return 12.0f;
723 case 27: return 13.5f;
724 case 36: return 18.0f;
725 case 44: return 22.0f;
726 case 48: return 24.0f;
727 case 54: return 27.0f;
728 case 66: return 33.0f;
729 case 72: return 36.0f;
730 case 96: return 48.0f;
731 case 108: return 54.0f;
734 return 0.f;
737 struct subelement {
738 u8 id;
739 u8 len;
740 u8 data[0];
741 } __packed;
744 static int8_t subelements(struct pkt_buff *pkt, u8 len)
746 u8 i, j;
747 u8 *data;
749 for (i=0; i<len;) {
750 struct subelement *sub;
752 sub = (struct subelement *) pkt_pull(pkt, sizeof(*sub));
753 if (sub == NULL)
754 return 0;
756 tprintf(", Subelement ID %u, ", sub->id);
757 tprintf("Length %u, ", sub->len);
759 data = pkt_pull(pkt, sub->len);
760 if (data == NULL)
761 return 0;
763 tprintf("Data: 0x");
764 for(j=0; j < sub->len; j++)
765 tprintf("%.2x ", data[j]);
767 i += sub->len + 1;
770 if (i != len) {
771 tprintf("Length error");
772 return 0;
775 return 1;
778 static int8_t inf_reserved(struct pkt_buff *pkt, u8 *id)
780 u8 i;
781 u8 *data;
782 struct element_reserved *reserved;
784 reserved = (struct element_reserved *) pkt_pull(pkt, sizeof(*reserved));
785 if (reserved == NULL)
786 return 0;
788 tprintf("Reserved (%u, Len (%u)): ", *id, reserved->len);
790 data = pkt_pull(pkt, reserved->len);
791 if (data == NULL)
792 return 0;
794 tprintf("Data 0x");
795 for (i = 0; i < reserved->len; i++)
796 tprintf("%.2x", data[i]);
798 return 1;
801 static int8_t inf_ssid(struct pkt_buff *pkt, u8 *id)
803 u8 i;
804 struct element_ssid *ssid;
805 char *ssid_name;
807 ssid = (struct element_ssid *) pkt_pull(pkt, sizeof(*ssid));
808 if (ssid == NULL)
809 return 0;
811 tprintf(" SSID (%u, Len (%u)): ", *id, ssid->len);
813 if ((ssid->len - sizeof(*ssid) + 1) > 0) {
814 ssid_name = (char *) pkt_pull(pkt, ssid->len);
815 if (ssid_name == NULL)
816 return 0;
818 for (i = 0; i < ssid->len; i++)
819 tprintf("%c",ssid_name[i]);
820 } else {
821 tprintf("Wildcard SSID");
824 return 1;
827 static int8_t inf_supp_rates(struct pkt_buff *pkt, u8 *id)
829 u8 i;
830 u8 *rates;
831 struct element_supp_rates *supp_rates;
833 supp_rates = (struct element_supp_rates *)
834 pkt_pull(pkt, sizeof(*supp_rates));
835 if (supp_rates == NULL)
836 return 0;
838 tprintf("Rates (%u, Len (%u)): ", *id, supp_rates->len);
839 if (len_lt_error(supp_rates->len, 1))
840 return 0;
842 if ((supp_rates->len - sizeof(*supp_rates) + 1) > 0) {
843 rates = pkt_pull(pkt, supp_rates->len);
844 if (rates == NULL)
845 return 0;
847 for (i = 0; i < supp_rates->len; i++)
848 tprintf("%g ", (rates[i] & 0x80) ?
849 ((rates[i] & 0x3f) * 0.5) :
850 data_rates(rates[i]));
851 return 1;
854 return 0;
857 static int8_t inf_fh_ps(struct pkt_buff *pkt, u8 *id)
859 struct element_fh_ps *fh_ps;
861 fh_ps = (struct element_fh_ps *) pkt_pull(pkt, sizeof(*fh_ps));
862 if (fh_ps == NULL)
863 return 0;
865 tprintf("FH Param Set (%u, Len(%u)): ", *id, fh_ps->len);
866 if (len_neq_error(fh_ps->len, 5))
867 return 0;
868 tprintf("Dwell Time: %fs, ", le16_to_cpu(fh_ps->dwell_time) * TU);
869 tprintf("HopSet: %u, ", fh_ps->hop_set);
870 tprintf("HopPattern: %u, ", fh_ps->hop_pattern);
871 tprintf("HopIndex: %u", fh_ps->hop_index);
873 return 1;
876 static int8_t inf_dsss_ps(struct pkt_buff *pkt, u8 *id)
878 struct element_dsss_ps *dsss_ps;
880 dsss_ps = (struct element_dsss_ps *) pkt_pull(pkt, sizeof(*dsss_ps));
881 if (dsss_ps == NULL)
882 return 0;
884 tprintf("DSSS Param Set (%u, Len(%u)): ", *id, dsss_ps->len);
885 if (len_neq_error(dsss_ps->len, 1))
886 return 0;
887 tprintf("Current Channel: %u", dsss_ps->curr_ch);
889 return 1;
892 static int8_t inf_cf_ps(struct pkt_buff *pkt, u8 *id)
894 struct element_cf_ps *cf_ps;
896 cf_ps = (struct element_cf_ps *) pkt_pull(pkt, sizeof(*cf_ps));
897 if (cf_ps == NULL)
898 return 0;
900 tprintf("CF Param Set (%u, Len(%u)): ", *id, cf_ps->len);
901 if (len_neq_error(cf_ps->len, 6))
902 return 0;
903 tprintf("CFP Count: %u, ", cf_ps->cfp_cnt);
904 tprintf("CFP Period: %u, ", cf_ps->cfp_period);
905 tprintf("CFP MaxDur: %fs, ", le16_to_cpu(cf_ps->cfp_max_dur) * TU);
906 tprintf("CFP DurRem: %fs", le16_to_cpu(cf_ps->cfp_dur_rem) * TU);
908 return 1;
911 static int8_t inf_tim(struct pkt_buff *pkt, u8 *id)
913 struct element_tim *tim;
915 tim = (struct element_tim *) pkt_pull(pkt, sizeof(*tim));
916 if (tim == NULL)
917 return 0;
919 tprintf("TIM (%u, Len(%u)): ", *id, tim->len);
920 if (len_lt_error(tim->len, 3))
921 return 0;
922 tprintf("DTIM Count: %u, ", tim->dtim_cnt);
923 tprintf("DTIM Period: %u, ", tim->dtim_period);
924 tprintf("Bitmap Control: %u, ", tim->bmp_cntrl);
925 if ((tim->len - sizeof(*tim) + 1) > 0) {
926 u8 *bmp = pkt_pull(pkt, (tim->len - sizeof(*tim) + 1));
927 if (bmp == NULL)
928 return 0;
930 tprintf("Partial Virtual Bitmap: 0x");
931 for(u8 i=0; i < (tim->len - sizeof(*tim) + 1); i++)
932 tprintf("%.2x ", bmp[i]);
935 return 1;
938 static int8_t inf_ibss_ps(struct pkt_buff *pkt, u8 *id)
940 struct element_ibss_ps *ibss_ps;
942 ibss_ps = (struct element_ibss_ps *) pkt_pull(pkt, sizeof(*ibss_ps));
943 if (ibss_ps == NULL)
944 return 0;
946 tprintf("IBSS Param Set (%u, Len(%u)): ", *id, ibss_ps->len);
947 if (len_neq_error(ibss_ps->len, 2))
948 return 0;
949 tprintf("ATIM Window: %fs", le16_to_cpu(ibss_ps->atim_win) * TU);
951 return 1;
954 static int8_t inf_country(struct pkt_buff *pkt, u8 *id)
956 u8 i;
957 u8 *pad;
958 struct element_country *country;
960 country = (struct element_country *) pkt_pull(pkt, sizeof(*country));
961 if (country == NULL)
962 return 0;
964 tprintf("Country (%u, Len(%u)): ", *id, country->len);
965 if (len_lt_error(country->len, 6))
966 return 0;
967 tprintf("Country String: %c%c%c", country->country_first,
968 country->country_sec, country->country_third);
970 for (i = 0; i < (country->len - 3); i += 3) {
971 struct element_country_tripled *country_tripled;
973 country_tripled = (struct element_country_tripled *)
974 pkt_pull(pkt, sizeof(*country_tripled));
975 if (country_tripled == NULL)
976 return 0;
978 if(country_tripled->frst_ch >= 201) {
979 tprintf("Oper Ext ID: %u, ", country_tripled->frst_ch);
980 tprintf("Operating Class: %u, ", country_tripled->nr_ch);
981 tprintf("Coverage Class: %u", country_tripled->max_trans);
982 } else {
983 tprintf("First Ch Nr: %u, ", country_tripled->frst_ch);
984 tprintf("Nr of Ch: %u, ", country_tripled->nr_ch);
985 tprintf("Max Transmit Pwr Lvl: %u", country_tripled->max_trans);
989 if(country->len % 2) {
990 pad = pkt_pull(pkt, 1);
991 if (pad == NULL)
992 return 0;
994 tprintf(", Pad: 0x%x", *pad);
997 return 1;
1000 static int8_t inf_hop_pp(struct pkt_buff *pkt, u8 *id)
1002 struct element_hop_pp *hop_pp;
1004 hop_pp = (struct element_hop_pp *) pkt_pull(pkt, sizeof(*hop_pp));
1005 if (hop_pp == NULL)
1006 return 0;
1008 tprintf("Hopping Pattern Param (%u, Len(%u)): ", *id, hop_pp->len);
1009 if (len_neq_error(hop_pp->len, 2))
1010 return 0;
1011 tprintf("Nr of Ch: %u", hop_pp->nr_ch);
1013 return 1;
1016 static int8_t inf_hop_pt(struct pkt_buff *pkt, u8 *id)
1018 int i;
1019 u8 *rand_tabl;
1020 struct element_hop_pt *hop_pt;
1022 hop_pt = (struct element_hop_pt *) pkt_pull(pkt, sizeof(*hop_pt));
1023 if (hop_pt == NULL)
1024 return 0;
1026 tprintf("Hopping Pattern Table (%u, Len(%u)): ", *id, hop_pt->len);
1027 if (len_lt_error(hop_pt->len, 4))
1028 return 0;
1029 tprintf("Flag: %u, ", hop_pt->flag);
1030 tprintf("Nr of Sets: %u, ", hop_pt->nr_sets);
1031 tprintf("Modules: %u, ", hop_pt->modules);
1032 tprintf("Offs: %u", hop_pt->offs);
1034 if ((hop_pt->len - sizeof(*hop_pt) + 1) > 0) {
1035 rand_tabl = pkt_pull(pkt, (hop_pt->len - sizeof(*hop_pt) + 1));
1036 if (rand_tabl == NULL)
1037 return 0;
1039 tprintf(", Rand table: 0x");
1040 for (i = 0; i < (hop_pt->len - sizeof(*hop_pt) + 1); i++)
1041 tprintf("%.2x ", rand_tabl[i]);
1044 return 1;
1047 static int8_t inf_req(struct pkt_buff *pkt, u8 *id)
1049 int i;
1050 struct element_req *req;
1051 u8 *req_ids;
1053 req = (struct element_req *) pkt_pull(pkt, sizeof(*req));
1054 if (req == NULL)
1055 return 0;
1057 tprintf("Request Element (%u, Len(%u)): ", *id, req->len);
1058 if ((req->len - sizeof(*req) + 1) > 0) {
1059 req_ids = pkt_pull(pkt, (req->len - sizeof(*req) + 1));
1060 if (req_ids == NULL)
1061 return 0;
1063 tprintf(", Requested Element IDs: ");
1064 for (i = 0; i < (req->len - sizeof(*req) + 1); i++)
1065 tprintf("%u ", req_ids[i]);
1068 return 1;
1071 static int8_t inf_bss_load(struct pkt_buff *pkt, u8 *id)
1073 struct element_bss_load *bss_load;
1075 bss_load = (struct element_bss_load *) pkt_pull(pkt, sizeof(*bss_load));
1076 if (bss_load == NULL)
1077 return 0;
1079 tprintf("BSS Load element (%u, Len(%u)): ", *id, bss_load->len);
1080 if (len_neq_error(bss_load->len, 5))
1081 return 0;
1082 tprintf("Station Count: %u, ", le16_to_cpu(bss_load->station_cnt));
1083 tprintf("Channel Utilization: %u, ", bss_load->ch_util);
1084 tprintf("Available Admission Capacity: %uus",
1085 bss_load->avlb_adm_cap * 32);
1087 return 1;
1090 static int8_t inf_edca_ps(struct pkt_buff *pkt, u8 *id)
1092 u32 ac_be, ac_bk, ac_vi, ac_vo;
1093 struct element_edca_ps *edca_ps;
1095 edca_ps = (struct element_edca_ps *) pkt_pull(pkt, sizeof(*edca_ps));
1096 if (edca_ps == NULL)
1097 return 0;
1099 ac_be = le32_to_cpu(edca_ps->ac_be);
1100 ac_bk = le32_to_cpu(edca_ps->ac_bk);
1101 ac_vi = le32_to_cpu(edca_ps->ac_vi);
1102 ac_vo = le32_to_cpu(edca_ps->ac_vo);
1104 tprintf("EDCA Param Set (%u, Len(%u)): ", *id, edca_ps->len);
1105 if (len_neq_error(edca_ps->len, 18))
1106 return 0;
1107 tprintf("QoS Info: 0x%x (-> EDCA Param Set Update Count (%u),"
1108 "Q-Ack (%u), Queue Re (%u), TXOP Req(%u), Res(%u)), ",
1109 edca_ps->qos_inf, edca_ps->qos_inf >> 4,
1110 (edca_ps->qos_inf >> 3) & 1, (edca_ps->qos_inf >> 2) & 1,
1111 (edca_ps->qos_inf >> 1) & 1, edca_ps->qos_inf & 1);
1112 tprintf("Reserved: 0x%x, ", edca_ps->res);
1113 tprintf("AC_BE Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1114 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_be,
1115 ac_be >> 28, (ac_be >> 27) & 1, (ac_be >> 25) & 3,
1116 (ac_be >> 24) & 1, (ac_be >> 20) & 15, (ac_be >> 16) & 15,
1117 bswap_16(ac_be & 0xFFFF) * 32);
1118 tprintf("AC_BK Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1119 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_bk,
1120 ac_bk >> 28, (ac_bk >> 27) & 1, (ac_bk >> 25) & 3,
1121 (ac_bk >> 24) & 1, (ac_bk >> 20) & 15, (ac_bk >> 16) & 15,
1122 bswap_16(ac_bk & 0xFFFF) * 32);
1123 tprintf("AC_VI Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1124 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_vi,
1125 ac_vi >> 28, (ac_vi >> 27) & 1, (ac_vi >> 25) & 3,
1126 (ac_vi >> 24) & 1, (ac_vi >> 20) & 15, (ac_vi >> 16) & 15,
1127 bswap_16(ac_vi & 0xFFFF) * 32);
1128 tprintf("AC_VO Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1129 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)", ac_vo,
1130 ac_vo >> 28, (ac_vo >> 27) & 1, (ac_vo >> 25) & 3,
1131 (ac_vo >> 24) & 1, (ac_vo >> 20) & 15, (ac_vo >> 16) & 15,
1132 bswap_16(ac_vo & 0xFFFF) * 32);
1134 return 1;
1137 static int8_t inf_tspec(struct pkt_buff *pkt, u8 *id)
1139 u16 nom_msdu_size, surplus_bandw_allow;
1140 struct element_tspec *tspec;
1142 tspec = (struct element_tspec *) pkt_pull(pkt, sizeof(*tspec));
1143 if (tspec == NULL)
1144 return 0;
1146 nom_msdu_size = le16_to_cpu(tspec->nom_msdu_size);
1147 surplus_bandw_allow = le16_to_cpu(tspec->surplus_bandw_allow);
1149 tprintf("TSPEC (%u, Len(%u)): ", *id, tspec->len);
1150 if (len_neq_error(tspec->len, 55))
1151 return 0;
1152 tprintf("Traffic Type: %u, ", tspec->traffic_type);
1153 tprintf("TSID: %u, ", tspec->tsid);
1154 tprintf("Direction: %u, ", tspec->direction);
1155 tprintf("Access Policy: %u, ", tspec->access_policy);
1156 tprintf("Aggregation: %u, ", tspec->aggr);
1157 tprintf("User Priority: %u, ", tspec->user_prior);
1158 tprintf("TSinfo Ack Policy: %u, ", tspec->tsinfo_ack_pol);
1159 tprintf("Schedule: %u, ", tspec->schedule);
1160 tprintf("Reserved: 0x%x, ", tspec->res);
1161 tprintf("Nominal MSDU Size: %uB (Fixed (%u)), ",
1162 nom_msdu_size >> 1, nom_msdu_size & 1);
1163 tprintf("Maximum MSDU Size: %uB, ", le16_to_cpu(tspec->max_msdu_size));
1164 tprintf("Minimum Service Interval: %uus, ",
1165 le32_to_cpu(tspec->min_srv_intv));
1166 tprintf("Maximum Service Interval: %uus, ",
1167 le32_to_cpu(tspec->max_srv_intv));
1168 tprintf("Inactivity Interval: %uus, ",
1169 le32_to_cpu(tspec->inactive_intv));
1170 tprintf("Suspension Interval: %uus, ", le32_to_cpu(tspec->susp_intv));
1171 tprintf("Service Start Time: %uus, ",
1172 le32_to_cpu(tspec->srv_start_time));
1173 tprintf("Minimum Data Rate: %ub/s, ",le32_to_cpu(tspec->min_data_rate));
1174 tprintf("Mean Data Rate: %ub/s, ", le32_to_cpu(tspec->mean_data_rate));
1175 tprintf("Peak Data Rate: %ub/s, ",le32_to_cpu(tspec->peak_data_rate));
1176 tprintf("Burst Size: %uB, ", le32_to_cpu(tspec->burst_size));
1177 tprintf("Delay Bound: %uus, ", le32_to_cpu(tspec->delay_bound));
1178 tprintf("Minimum PHY Rate: %ub/s, ", le32_to_cpu(tspec->min_phy_rate));
1179 tprintf("Surplus Bandwidth: %u.%u, ", surplus_bandw_allow >> 13,
1180 surplus_bandw_allow & 0x1FFF);
1181 tprintf("Medium Time: %uus", le16_to_cpu(tspec->med_time) * 32);
1183 return 1;
1186 static const char *class_type(u8 type)
1188 switch (type) {
1189 case 0: return "Ethernet parameters";
1190 case 1: return "TCP/UDP IP parameters";
1191 case 2: return "IEEE 802.1Q parameters";
1192 case 3: return "Filter Offset parameters";
1193 case 4: return "IP and higher layer parameters";
1194 case 5: return "IEEE 802.1D/Q parameters";
1195 default: return "Reserved";
1199 static int8_t inf_tclas(struct pkt_buff *pkt, u8 *id)
1201 struct element_tclas *tclas;
1202 struct element_tclas_frm_class *frm_class;
1204 tclas = (struct element_tclas *) pkt_pull(pkt, sizeof(*tclas));
1205 if (tclas == NULL)
1206 return 0;
1208 frm_class = (struct element_tclas_frm_class *)
1209 pkt_pull(pkt, sizeof(*frm_class));
1210 if (frm_class == NULL)
1211 return 0;
1213 tprintf("TCLAS (%u, Len(%u)): ", *id, tclas->len);
1214 if (len_lt_error(tclas->len, 3))
1215 return 0;
1216 tprintf("User Priority: %u, ", tclas->user_priority);
1217 tprintf("Classifier Type: %s (%u), ", class_type(frm_class->type),
1218 frm_class->type);
1219 tprintf("Classifier Mask: 0x%x, ", frm_class->mask);
1221 if(frm_class->type == 0) {
1222 struct element_tclas_type0 *type0;
1224 type0 = (struct element_tclas_type0 *)
1225 pkt_pull(pkt, sizeof(*type0));
1226 if (type0 == NULL)
1227 return 0;
1229 /* I think little endian, like the rest */
1230 tprintf("Src Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
1231 type0->sa[5], type0->sa[4], type0->sa[3],
1232 type0->sa[2], type0->sa[1], type0->sa[0]);
1233 tprintf("Dst Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
1234 type0->da[5], type0->da[4], type0->da[3],
1235 type0->da[2], type0->da[1], type0->da[0]);
1236 tprintf("Type: 0x%x", le16_to_cpu(type0->type));
1238 else if(frm_class->type == 1) {
1239 struct element_tclas_type1 *type1;
1241 type1 = (struct element_tclas_type1 *)
1242 pkt_pull(pkt, sizeof(*type1));
1243 if (type1 == NULL)
1244 return 0;
1246 tprintf("Version: %u, ", type1->version);
1247 /* big endian format follows */
1248 if(type1->version == 4) {
1249 struct element_tclas_type1_ip4 *type1_ip4;
1250 char src_ip[INET_ADDRSTRLEN];
1251 char dst_ip[INET_ADDRSTRLEN];
1253 type1_ip4 = (struct element_tclas_type1_ip4 *)
1254 pkt_pull(pkt, sizeof(*type1_ip4));
1255 if (type1_ip4 == NULL)
1256 return 0;
1258 inet_ntop(AF_INET, &type1_ip4->sa, src_ip, sizeof(src_ip));
1259 inet_ntop(AF_INET, &type1_ip4->da, dst_ip, sizeof(dst_ip));
1261 tprintf("Src IP: %s, ", src_ip);
1262 tprintf("Dst IP: %s, ", dst_ip);
1263 tprintf("Src Port: %u, ", ntohs(type1_ip4->sp));
1264 tprintf("Dst Port: %u, ", ntohs(type1_ip4->dp));
1265 tprintf("DSCP: 0x%x, ", type1_ip4->dscp);
1266 tprintf("Proto: %u, ", type1_ip4->proto);
1267 tprintf("Res: 0x%x", type1_ip4->reserved);
1269 else if(type1->version == 6) {
1270 struct element_tclas_type1_ip6 *type1_ip6;
1271 char src_ip[INET6_ADDRSTRLEN];
1272 char dst_ip[INET6_ADDRSTRLEN];
1274 type1_ip6 = (struct element_tclas_type1_ip6 *)
1275 pkt_pull(pkt, sizeof(*type1_ip6));
1276 if (type1_ip6 == NULL)
1277 return 0;
1279 inet_ntop(AF_INET6, &type1_ip6->sa,
1280 src_ip, sizeof(src_ip));
1281 inet_ntop(AF_INET6, &type1_ip6->da,
1282 dst_ip, sizeof(dst_ip));
1284 tprintf("Src IP: %s, ", src_ip);
1285 tprintf("Dst IP: %s, ", dst_ip);
1286 tprintf("Src Port: %u, ", ntohs(type1_ip6->sp));
1287 tprintf("Dst Port: %u, ", ntohs(type1_ip6->dp));
1288 tprintf("Flow Label: 0x%x%x%x", type1_ip6->flow_label1,
1289 type1_ip6->flow_label2, type1_ip6->flow_label3);
1291 else {
1292 tprintf("Version (%u) not supported", type1->version);
1293 return 0;
1297 else if(frm_class->type == 2) {
1298 struct element_tclas_type2 *type2;
1300 type2 = (struct element_tclas_type2 *)
1301 pkt_pull(pkt, sizeof(*type2));
1302 if (type2 == NULL)
1303 return 0;
1305 tprintf("802.1Q VLAN TCI: 0x%x", ntohs(type2->vlan_tci));
1307 else if(frm_class->type == 3) {
1308 struct element_tclas_type3 *type3;
1309 u8 len, i;
1310 u8 *val;
1312 type3 = (struct element_tclas_type3 *)
1313 pkt_pull(pkt, sizeof(*type3));
1314 if (type3 == NULL)
1315 return 0;
1317 len = (tclas->len - 5) / 2;
1319 tprintf("Filter Offset: %u, ", type3->offs);
1321 if((len & 1) || (len_lt_error(tclas->len, 5))) {
1322 tprintf("Length of TCLAS (%u) not correct", tclas->len);
1323 return 0;
1325 else {
1326 val = pkt_pull(pkt, len);
1327 if (val == NULL)
1328 return 0;
1330 tprintf("Filter Value: 0x");
1331 for (i = 0; i < len / 2; i++)
1332 tprintf("%x ", val[i]);
1333 tprintf(", ");
1334 tprintf("Filter Mask: 0x");
1335 for (i = len / 2; i < len; i++)
1336 tprintf("%x ", val[i]);
1340 else if(frm_class->type == 4) {
1341 struct element_tclas_type4 *type4;
1343 type4 = (struct element_tclas_type4 *)
1344 pkt_pull(pkt, sizeof(*type4));
1345 if (type4 == NULL)
1346 return 0;
1348 tprintf("Version: %u, ", type4->version);
1349 /* big endian format follows */
1350 if(type4->version == 4) {
1351 struct element_tclas_type4_ip4 *type4_ip4;
1352 char src_ip[INET_ADDRSTRLEN];
1353 char dst_ip[INET_ADDRSTRLEN];
1355 type4_ip4 = (struct element_tclas_type4_ip4 *)
1356 pkt_pull(pkt, sizeof(*type4_ip4));
1357 if (type4_ip4 == NULL)
1358 return 0;
1360 inet_ntop(AF_INET, &type4_ip4->sa, src_ip, sizeof(src_ip));
1361 inet_ntop(AF_INET, &type4_ip4->da, dst_ip, sizeof(dst_ip));
1363 tprintf("Src IP: %s, ", src_ip);
1364 tprintf("Dst IP: %s, ", dst_ip);
1365 tprintf("Src Port: %u, ", ntohs(type4_ip4->sp));
1366 tprintf("Dst Port: %u, ", ntohs(type4_ip4->dp));
1367 tprintf("DSCP: 0x%x, ", type4_ip4->dscp);
1368 tprintf("Proto: %u, ", type4_ip4->proto);
1369 tprintf("Res: 0x%x", type4_ip4->reserved);
1371 else if(type4->version == 6) {
1372 struct element_tclas_type4_ip6 *type4_ip6;
1373 char src_ip[INET6_ADDRSTRLEN];
1374 char dst_ip[INET6_ADDRSTRLEN];
1376 type4_ip6 = (struct element_tclas_type4_ip6 *)
1377 pkt_pull(pkt, sizeof(*type4_ip6));
1378 if (type4_ip6 == NULL)
1379 return 0;
1381 inet_ntop(AF_INET6, &type4_ip6->sa,
1382 src_ip, sizeof(src_ip));
1383 inet_ntop(AF_INET6, &type4_ip6->da,
1384 dst_ip, sizeof(dst_ip));
1386 tprintf("Src IP: %s, ", src_ip);
1387 tprintf("Dst IP: %s, ", dst_ip);
1388 tprintf("Src Port: %u, ", ntohs(type4_ip6->sp));
1389 tprintf("Dst Port: %u, ", ntohs(type4_ip6->dp));
1390 tprintf("DSCP: 0x%x, ", type4_ip6->dscp);
1391 tprintf("Nxt Hdr: %u, ", type4_ip6->nxt_hdr);
1392 tprintf("Flow Label: 0x%x%x%x", type4_ip6->flow_label1,
1393 type4_ip6->flow_label2, type4_ip6->flow_label3);
1395 else {
1396 tprintf("Version (%u) not supported", type4->version);
1397 return 0;
1400 else if(frm_class->type == 5) {
1401 struct element_tclas_type5 *type5;
1403 type5 = (struct element_tclas_type5 *)
1404 pkt_pull(pkt, sizeof(*type5));
1405 if (type5 == NULL)
1406 return 0;
1408 tprintf("802.1Q PCP: 0x%x, ", type5->pcp);
1409 tprintf("802.1Q CFI: 0x%x, ", type5->cfi);
1410 tprintf("802.1Q VID: 0x%x", type5->vid);
1412 else {
1413 tprintf("Classifier Type (%u) not supported", frm_class->type);
1414 return 0;
1417 return 1;
1420 static int8_t inf_sched(struct pkt_buff *pkt, u8 *id)
1422 struct element_schedule *schedule;
1423 u16 info;
1425 schedule = (struct element_schedule *) pkt_pull(pkt, sizeof(*schedule));
1426 if (schedule == NULL)
1427 return 0;
1429 info = le16_to_cpu(schedule->inf);
1431 tprintf("Schedule (%u, Len(%u)): ", *id, schedule->len);
1432 if (len_neq_error(schedule->len, 12))
1433 return 0;
1435 tprintf("Aggregation: %u, ", info >> 15);
1436 tprintf("TSID: %u, ", (info >> 11) & 0xF);
1437 tprintf("Direction: %u, ", (info >> 9) & 0x3);
1438 tprintf("Res: %u, ", info & 0x1FF);
1439 tprintf("Serv Start Time: %uus, ", le32_to_cpu(schedule->start));
1440 tprintf("Serv Interval: %uus, ", le32_to_cpu(schedule->serv_intv));
1441 tprintf("Spec Interval: %fs", le32_to_cpu(schedule->spec_intv) * TU);
1443 return 1;
1446 static int8_t inf_chall_txt(struct pkt_buff *pkt, u8 *id)
1448 struct element_chall_txt *chall_txt;
1449 u8 i;
1450 u8 *txt;
1452 chall_txt = (struct element_chall_txt *)
1453 pkt_pull(pkt, sizeof(*chall_txt));
1454 if (chall_txt == NULL)
1455 return 0;
1457 tprintf("Challenge Text (%u, Len(%u)): ", *id, chall_txt->len);
1458 if ((chall_txt->len - sizeof(*chall_txt) + 1) > 0) {
1459 txt = pkt_pull(pkt, (chall_txt->len - sizeof(*chall_txt) + 1));
1460 if (txt == NULL)
1461 return 0;
1463 tprintf("0x");
1464 for (i = 0; i < (chall_txt->len - sizeof(*chall_txt) + 1); i++)
1465 tprintf("%x ", txt[i]);
1468 return 1;
1471 static int8_t inf_pwr_constr(struct pkt_buff *pkt, u8 *id)
1473 struct element_pwr_constr *pwr_constr;
1475 pwr_constr = (struct element_pwr_constr *) pkt_pull(pkt, sizeof(*pwr_constr));
1476 if (pwr_constr == NULL)
1477 return 0;
1479 tprintf("Power Constraint (%u, Len(%u)): ", *id, pwr_constr->len);
1480 if (len_neq_error(pwr_constr->len, 1))
1481 return 0;
1483 tprintf("Local Power Constraint: %udB", pwr_constr->local_pwr_constr);
1485 return 1;
1488 static int8_t inf_pwr_cap(struct pkt_buff *pkt, u8 *id)
1490 struct element_pwr_cap *pwr_cap;
1492 pwr_cap = (struct element_pwr_cap *) pkt_pull(pkt, sizeof(*pwr_cap));
1493 if (pwr_cap == NULL)
1494 return 0;
1496 tprintf("Power Capability (%u, Len(%u)): ", *id, pwr_cap->len);
1497 if (len_neq_error(pwr_cap->len, 2))
1498 return 0;
1500 tprintf("Min. Transm. Pwr Cap.: %ddBm, ", (int8_t)pwr_cap->min_pwr_cap);
1501 tprintf("Max. Transm. Pwr Cap.: %ddBm", (int8_t)pwr_cap->max_pwr_cap);
1503 return 1;
1506 static int8_t inf_tpc_req(struct pkt_buff *pkt, u8 *id)
1508 struct element_tpc_req *tpc_req;
1510 tpc_req = (struct element_tpc_req *) pkt_pull(pkt, sizeof(*tpc_req));
1511 if (tpc_req == NULL)
1512 return 0;
1514 tprintf("TPC Request (%u, Len(%u))", *id, tpc_req->len);
1515 if (len_neq_error(tpc_req->len, 0))
1516 return 0;
1518 return 1;
1521 static int8_t inf_tpc_rep(struct pkt_buff *pkt, u8 *id)
1523 struct element_tpc_rep *tpc_rep;
1525 tpc_rep = (struct element_tpc_rep *) pkt_pull(pkt, sizeof(*tpc_rep));
1526 if (tpc_rep == NULL)
1527 return 0;
1529 tprintf("TPC Report (%u, Len(%u)): ", *id, tpc_rep->len);
1530 if (len_neq_error(tpc_rep->len, 2))
1531 return 0;
1533 tprintf("Transmit Power: %udBm, ", (int8_t)tpc_rep->trans_pwr);
1534 tprintf("Link Margin: %udB", (int8_t)tpc_rep->trans_pwr);
1536 return 1;
1539 static int8_t inf_supp_ch(struct pkt_buff *pkt, u8 *id)
1541 struct element_supp_ch *supp_ch;
1542 u8 i;
1544 supp_ch = (struct element_supp_ch *) pkt_pull(pkt, sizeof(*supp_ch));
1545 if (supp_ch == NULL)
1546 return 0;
1548 tprintf("Supp Channels (%u, Len(%u)): ", *id, supp_ch->len);
1549 if (len_lt_error(supp_ch->len, 2))
1550 return 0;
1552 if(supp_ch->len & 1) {
1553 tprintf("Length should be modulo 2");
1554 return 0;
1557 for (i = 0; i < supp_ch->len; i += 2) {
1558 struct element_supp_ch_tuple *supp_ch_tuple;
1560 supp_ch_tuple = (struct element_supp_ch_tuple *)
1561 pkt_pull(pkt, sizeof(*supp_ch_tuple));
1562 if (supp_ch_tuple == NULL)
1563 return 0;
1565 tprintf("First Channel Nr: %u, ", supp_ch_tuple->first_ch_nr);
1566 tprintf("Nr of Channels: %u, ", supp_ch_tuple->nr_ch);
1569 return 1;
1572 static int8_t inf_ch_sw_ann(struct pkt_buff *pkt, u8 *id)
1574 struct element_ch_sw_ann *ch_sw_ann;
1576 ch_sw_ann = (struct element_ch_sw_ann *)
1577 pkt_pull(pkt, sizeof(*ch_sw_ann));
1578 if (ch_sw_ann == NULL)
1579 return 0;
1581 tprintf("Channel Switch Announc (%u, Len(%u)): ", *id, ch_sw_ann->len);
1582 if (len_neq_error(ch_sw_ann->len, 3))
1583 return 0;
1585 tprintf("Switch Mode: %u, ", ch_sw_ann->switch_mode);
1586 tprintf("New Nr: %u, ", ch_sw_ann->new_nr);
1587 tprintf("Switch Count: %u", ch_sw_ann->switch_cnt);
1589 return 1;
1592 static const char *meas_type(u8 type)
1594 switch (type) {
1595 case 0: return "Basic";
1596 case 1: return "Clear Channel assesment (CCA)";
1597 case 2: return "Receive power indication (RPI) histogram";
1598 case 3: return "Channel load";
1599 case 4: return "Noise histogram";
1600 case 5: return "Beacon";
1601 case 6: return "Frame";
1602 case 7: return "STA statistics";
1603 case 8: return "LCI";
1604 case 9: return "Transmit stream/category measurement";
1605 case 10: return "Multicast diagnostics";
1606 case 11: return "Location Civic";
1607 case 12: return "Location Identifier";
1608 case 13 ... 255: return "Reserved";
1612 static int8_t inf_meas_req(struct pkt_buff *pkt, u8 *id)
1614 struct element_meas_req *meas_req;
1616 meas_req = (struct element_meas_req *) pkt_pull(pkt, sizeof(*meas_req));
1617 if (meas_req == NULL)
1618 return 0;
1620 tprintf("Measurement Req (%u, Len(%u)): ", *id, meas_req->len);
1621 if (len_lt_error(meas_req->len, 3))
1622 return 0;
1624 tprintf("Token: %u, ", meas_req->token);
1625 tprintf("Req Mode: 0x%x (Parallel (%u), Enable(%u), Request(%u), "
1626 "Report(%u), Dur Mand(%u)), ", meas_req->req_mode,
1627 meas_req->req_mode >> 7, (meas_req->req_mode >> 6) & 0x1,
1628 (meas_req->req_mode >> 5) & 0x1, (meas_req->req_mode >> 4) & 0x1,
1629 (meas_req->req_mode >> 3) & 0x1);
1630 tprintf("Type: %s (%u), ", meas_type(meas_req->type), meas_req->type);
1632 if(meas_req->len > 3) {
1633 if(meas_req->type == 0) {
1634 struct element_meas_basic *basic;
1636 basic = (struct element_meas_basic *)
1637 pkt_pull(pkt, sizeof(*basic));
1638 if (basic == NULL)
1639 return 0;
1641 if (!(meas_req->len - 3 - sizeof(*basic))) {
1642 tprintf("Length of Req matchs not Type %u",
1643 meas_req->type);
1644 return 0;
1647 tprintf("Ch Nr: %uus, ", basic->ch_nr);
1648 tprintf("Meas Start Time: %lu, ",
1649 le64_to_cpu(basic->start));
1650 tprintf("Meas Duration: %fs",
1651 le16_to_cpu(basic->dur) * TU);
1654 else if(meas_req->type == 1) {
1655 struct element_meas_cca *cca;
1657 cca = (struct element_meas_cca *)
1658 pkt_pull(pkt, sizeof(*cca));
1659 if (cca == NULL)
1660 return 0;
1662 if (!(meas_req->len - 3 - sizeof(*cca))) {
1663 tprintf("Length of Req matchs not Type %u",
1664 meas_req->type);
1665 return 0;
1668 tprintf("Ch Nr: %uus, ", cca->ch_nr);
1669 tprintf("Meas Start Time: %lu, ",
1670 le64_to_cpu(cca->start));
1671 tprintf("Meas Duration: %fs",
1672 le16_to_cpu(cca->dur) * TU);
1674 else if(meas_req->type == 2) {
1675 struct element_meas_rpi *rpi;
1677 rpi = (struct element_meas_rpi *)
1678 pkt_pull(pkt, sizeof(*rpi));
1679 if (rpi == NULL)
1680 return 0;
1682 if (!(meas_req->len - 3 - sizeof(*rpi))) {
1683 tprintf("Length of Req matchs not Type %u",
1684 meas_req->type);
1685 return 0;
1688 tprintf("Ch Nr: %uus, ", rpi->ch_nr);
1689 tprintf("Meas Start Time: %lu, ",
1690 le64_to_cpu(rpi->start));
1691 tprintf("Meas Duration: %fs",
1692 le16_to_cpu(rpi->dur) * TU);
1694 else if(meas_req->type == 3) {
1695 struct element_meas_ch_load *ch_load;
1697 ch_load = (struct element_meas_ch_load *)
1698 pkt_pull(pkt, sizeof(*ch_load));
1699 if (ch_load == NULL)
1700 return 0;
1702 if ((meas_req->len - 3 - sizeof(*ch_load)) >= 0) {
1703 tprintf("Length of Req matchs not Type %u",
1704 meas_req->type);
1705 return 0;
1708 tprintf("OP Class: %u, ", ch_load->op_class);
1709 tprintf("Ch Nr: %u, ", ch_load->ch_nr);
1710 tprintf("Rand Intv: %fs, ",
1711 le16_to_cpu(ch_load->rand_intv) * TU);
1712 tprintf("Meas Duration: %fs",
1713 le16_to_cpu(ch_load->dur) * TU);
1715 if(!subelements(pkt,
1716 meas_req->len - 3 - sizeof(*ch_load)))
1717 return 0;
1719 else if(meas_req->type == 4) {
1720 struct element_meas_noise *noise;
1722 noise = (struct element_meas_noise *)
1723 pkt_pull(pkt, sizeof(*noise));
1724 if (noise == NULL)
1725 return 0;
1727 if ((meas_req->len - 3 - sizeof(*noise)) >= 0) {
1728 tprintf("Length of Req matchs not Type %u",
1729 meas_req->type);
1730 return 0;
1733 tprintf("OP Class: %u, ", noise->op_class);
1734 tprintf("Ch Nr: %u, ", noise->ch_nr);
1735 tprintf("Rand Intv: %fs, ",
1736 le16_to_cpu(noise->rand_intv) * TU);
1737 tprintf("Meas Duration: %fs",
1738 le16_to_cpu(noise->dur) * TU);
1740 if(!subelements(pkt,
1741 meas_req->len - 3 - sizeof(*noise)))
1742 return 0;
1744 else if(meas_req->type == 5) {
1745 struct element_meas_beacon *beacon;
1747 beacon = (struct element_meas_beacon *)
1748 pkt_pull(pkt, sizeof(*beacon));
1749 if (beacon == NULL)
1750 return 0;
1752 if ((meas_req->len - 3 - sizeof(*beacon)) >= 0) {
1753 tprintf("Length of Req matchs not Type %u",
1754 meas_req->type);
1755 return 0;
1758 tprintf("OP Class: %u, ", beacon->op_class);
1759 tprintf("Ch Nr: %u, ", beacon->ch_nr);
1760 tprintf("Rand Intv: %fs, ",
1761 le16_to_cpu(beacon->rand_intv) * TU);
1762 tprintf("Meas Duration: %fs",
1763 le16_to_cpu(beacon->dur) * TU);
1764 tprintf("Mode: %u, ", beacon->mode);
1765 tprintf("BSSID: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1766 beacon->bssid[0], beacon->bssid[1],
1767 beacon->bssid[2], beacon->bssid[3],
1768 beacon->bssid[4], beacon->bssid[5]);
1770 if(!subelements(pkt,
1771 meas_req->len - 3 - sizeof(*beacon)))
1772 return 0;
1774 else if(meas_req->type == 6) {
1775 struct element_meas_frame *frame;
1777 frame = (struct element_meas_frame *)
1778 pkt_pull(pkt, sizeof(*frame));
1779 if (frame == NULL)
1780 return 0;
1782 if ((meas_req->len - 3 - sizeof(*frame)) >= 0) {
1783 tprintf("Length of Req matchs not Type %u",
1784 meas_req->type);
1785 return 0;
1788 tprintf("OP Class: %u, ", frame->op_class);
1789 tprintf("Ch Nr: %u, ", frame->ch_nr);
1790 tprintf("Rand Intv: %fs, ",
1791 le16_to_cpu(frame->rand_intv) * TU);
1792 tprintf("Meas Duration: %fs",
1793 le16_to_cpu(frame->dur) * TU);
1794 tprintf("Request Type: %u, ", frame->frame);
1795 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1796 frame->mac[0], frame->mac[1],
1797 frame->mac[2], frame->mac[3],
1798 frame->mac[4], frame->mac[5]);
1800 if(!subelements(pkt,
1801 meas_req->len - 3 - sizeof(*frame)))
1802 return 0;
1804 else if(meas_req->type == 7) {
1805 struct element_meas_sta *sta;
1807 sta = (struct element_meas_sta *)
1808 pkt_pull(pkt, sizeof(*sta));
1809 if (sta == NULL)
1810 return 0;
1812 if ((meas_req->len - 3 - sizeof(*sta)) >= 0) {
1813 tprintf("Length of Req matchs not Type %u",
1814 meas_req->type);
1815 return 0;
1818 tprintf("Peer MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1819 sta->peer_mac[0], sta->peer_mac[1],
1820 sta->peer_mac[2], sta->peer_mac[3],
1821 sta->peer_mac[4], sta->peer_mac[5]);
1822 tprintf("Rand Intv: %fs, ",
1823 le16_to_cpu(sta->rand_intv) * TU);
1824 tprintf("Meas Duration: %fs",
1825 le16_to_cpu(sta->dur) * TU);
1826 tprintf("Group ID: %u, ", sta->group_id);
1828 if(!subelements(pkt,
1829 meas_req->len - 3 - sizeof(*sta)))
1830 return 0;
1832 else if(meas_req->type == 8) {
1833 struct element_meas_lci *lci;
1835 lci = (struct element_meas_lci *)
1836 pkt_pull(pkt, sizeof(*lci));
1837 if (lci == NULL)
1838 return 0;
1840 if ((meas_req->len - 3 - sizeof(*lci)) >= 0) {
1841 tprintf("Length of Req matchs not Type %u",
1842 meas_req->type);
1843 return 0;
1846 tprintf("Location Subj: %u, ", lci->loc_subj);
1847 tprintf("Latitude Req Res: %udeg",
1848 lci->latitude_req_res);
1849 tprintf("Longitude Req Res: %udeg",
1850 lci->longitude_req_res);
1851 tprintf("Altitude Req Res: %udeg",
1852 lci->altitude_req_res);
1854 if(!subelements(pkt,
1855 meas_req->len - 3 - sizeof(*lci)))
1856 return 0;
1858 else if(meas_req->type == 9) {
1859 struct element_meas_trans_str_cat *trans;
1861 trans = (struct element_meas_trans_str_cat *)
1862 pkt_pull(pkt, sizeof(*trans));
1863 if (trans == NULL)
1864 return 0;
1866 if ((meas_req->len - 3 - sizeof(*trans)) >= 0) {
1867 tprintf("Length of Req matchs not Type %u",
1868 meas_req->type);
1869 return 0;
1872 tprintf("Rand Intv: %fs, ",
1873 le16_to_cpu(trans->rand_intv) * TU);
1874 tprintf("Meas Duration: %fs",
1875 le16_to_cpu(trans->dur) * TU);
1876 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1877 trans->peer_sta_addr[0], trans->peer_sta_addr[1],
1878 trans->peer_sta_addr[2], trans->peer_sta_addr[3],
1879 trans->peer_sta_addr[4], trans->peer_sta_addr[5]);
1880 tprintf("Traffic ID: %u, ", trans->traffic_id);
1881 tprintf("Bin 0 Range: %u, ", trans->bin_0_range);
1883 if(!subelements(pkt,
1884 meas_req->len - 3 - sizeof(*trans)))
1885 return 0;
1887 else if(meas_req->type == 10) {
1888 struct element_meas_mcast_diag *mcast;
1890 mcast = (struct element_meas_mcast_diag *)
1891 pkt_pull(pkt, sizeof(*mcast));
1892 if (mcast == NULL)
1893 return 0;
1895 if ((meas_req->len - 3 - sizeof(*mcast)) >= 0) {
1896 tprintf("Length of Req matchs not Type %u",
1897 meas_req->type);
1898 return 0;
1901 tprintf("Rand Intv: %fs, ",
1902 le16_to_cpu(mcast->rand_intv) * TU);
1903 tprintf("Meas Duration: %fs",
1904 le16_to_cpu(mcast->dur) * TU);
1905 tprintf("Group MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1906 mcast->group_mac[0], mcast->group_mac[1],
1907 mcast->group_mac[2], mcast->group_mac[3],
1908 mcast->group_mac[4], mcast->group_mac[5]);
1910 if(!subelements(pkt,
1911 meas_req->len - 3 - sizeof(*mcast)))
1912 return 0;
1914 else if(meas_req->type == 11) {
1915 struct element_meas_loc_civic *civic;
1917 civic = (struct element_meas_loc_civic *)
1918 pkt_pull(pkt, sizeof(*civic));
1919 if (civic == NULL)
1920 return 0;
1922 if ((meas_req->len - 3 - sizeof(*civic)) >= 0) {
1923 tprintf("Length of Req matchs not Type %u",
1924 meas_req->type);
1925 return 0;
1928 tprintf("Location Subj: %u, ", civic->loc_subj);
1929 tprintf("Type: %u, ", civic->civic_loc);
1930 tprintf("Srv Intv Units: %u, ",
1931 le16_to_cpu(civic->loc_srv_intv_unit));
1932 tprintf("Srv Intv: %u, ", civic->loc_srv_intv);
1934 if(!subelements(pkt,
1935 meas_req->len - 3 - sizeof(*civic)))
1936 return 0;
1938 else if(meas_req->type == 12) {
1939 struct element_meas_loc_id *id;
1941 id = (struct element_meas_loc_id *)
1942 pkt_pull(pkt, sizeof(*id));
1943 if (id == NULL)
1944 return 0;
1946 if ((meas_req->len - 3 - sizeof(*id)) >= 0) {
1947 tprintf("Length of Req matchs not Type %u",
1948 meas_req->type);
1949 return 0;
1952 tprintf("Location Subj: %u, ", id->loc_subj);
1953 tprintf("Srv Intv Units: %u, ",
1954 le16_to_cpu(id->loc_srv_intv_unit));
1955 tprintf("Srv Intv: %u", id->loc_srv_intv);
1957 if(!subelements(pkt,
1958 meas_req->len - 3 - sizeof(*id)))
1959 return 0;
1961 else if(meas_req->type == 255) {
1962 struct element_meas_pause *pause;
1964 pause = (struct element_meas_pause *)
1965 pkt_pull(pkt, sizeof(*pause));
1966 if (pause == NULL)
1967 return 0;
1969 if ((meas_req->len - 3 - sizeof(*pause)) >= 0) {
1970 tprintf("Length of Req matchs not Type %u",
1971 meas_req->type);
1972 return 0;
1975 tprintf("Pause Time: %fs, ", pause->time * 10 * TU);
1977 if(!subelements(pkt,
1978 meas_req->len - 3 - sizeof(*pause)))
1979 return 0;
1981 else {
1982 tprintf("Length field indicates data,"
1983 " but could not interpreted");
1984 return 0;
1988 return 1;
1991 static int8_t inf_meas_rep(struct pkt_buff *pkt, u8 *id)
1993 struct element_meas_rep *meas_rep;
1995 meas_rep = (struct element_meas_rep *) pkt_pull(pkt, sizeof(*meas_rep));
1996 if (meas_rep == NULL)
1997 return 0;
1999 tprintf("Measurement Rep (%u, Len(%u)): ", *id, meas_rep->len);
2000 if (len_lt_error(meas_rep->len, 3))
2001 return 0;
2003 tprintf("Token: %u, ", meas_rep->token);
2004 tprintf("Rep Mode: 0x%x (Late (%u), Incapable(%u), Refused(%u), ",
2005 meas_rep->rep_mode, meas_rep->rep_mode >> 7,
2006 (meas_rep->rep_mode >> 6) & 0x1,
2007 (meas_rep->rep_mode >> 5) & 0x1);
2008 tprintf("Type: %s (%u), ", meas_type(meas_rep->type), meas_rep->type);
2010 if(meas_rep->len > 3) {
2011 if(meas_rep->type == 0) {
2012 struct element_meas_basic *basic;
2014 basic = (struct element_meas_basic *)
2015 pkt_pull(pkt, sizeof(*basic));
2016 if (basic == NULL)
2017 return 0;
2019 if (!(meas_rep->len - 3 - sizeof(*basic))) {
2020 tprintf("Length of Req matchs not Type %u",
2021 meas_rep->type);
2022 return 0;
2025 tprintf("Ch Nr: %uus, ", basic->ch_nr);
2026 tprintf("Meas Start Time: %lu, ",
2027 le64_to_cpu(basic->start));
2028 tprintf("Meas Duration: %fs",
2029 le16_to_cpu(basic->dur) * TU);
2032 else if(meas_rep->type == 1) {
2033 struct element_meas_cca *cca;
2035 cca = (struct element_meas_cca *)
2036 pkt_pull(pkt, sizeof(*cca));
2037 if (cca == NULL)
2038 return 0;
2040 if (!(meas_rep->len - 3 - sizeof(*cca))) {
2041 tprintf("Length of Req matchs not Type %u",
2042 meas_rep->type);
2043 return 0;
2046 tprintf("Ch Nr: %uus, ", cca->ch_nr);
2047 tprintf("Meas Start Time: %lu, ",
2048 le64_to_cpu(cca->start));
2049 tprintf("Meas Duration: %fs",
2050 le16_to_cpu(cca->dur) * TU);
2052 else if(meas_rep->type == 2) {
2053 struct element_meas_rpi *rpi;
2055 rpi = (struct element_meas_rpi *)
2056 pkt_pull(pkt, sizeof(*rpi));
2057 if (rpi == NULL)
2058 return 0;
2060 if (!(meas_rep->len - 3 - sizeof(*rpi))) {
2061 tprintf("Length of Req matchs not Type %u",
2062 meas_rep->type);
2063 return 0;
2066 tprintf("Ch Nr: %uus, ", rpi->ch_nr);
2067 tprintf("Meas Start Time: %lu, ",
2068 le64_to_cpu(rpi->start));
2069 tprintf("Meas Duration: %fs",
2070 le16_to_cpu(rpi->dur) * TU);
2072 else if(meas_rep->type == 3) {
2073 struct element_meas_ch_load *ch_load;
2075 ch_load = (struct element_meas_ch_load *)
2076 pkt_pull(pkt, sizeof(*ch_load));
2077 if (ch_load == NULL)
2078 return 0;
2080 if ((meas_rep->len - 3 - sizeof(*ch_load)) >= 0) {
2081 tprintf("Length of Req matchs not Type %u",
2082 meas_rep->type);
2083 return 0;
2086 tprintf("OP Class: %u, ", ch_load->op_class);
2087 tprintf("Ch Nr: %u, ", ch_load->ch_nr);
2088 tprintf("Rand Intv: %fs, ",
2089 le16_to_cpu(ch_load->rand_intv) * TU);
2090 tprintf("Meas Duration: %fs",
2091 le16_to_cpu(ch_load->dur) * TU);
2093 if(!subelements(pkt,
2094 meas_rep->len - 3 - sizeof(*ch_load)))
2095 return 0;
2097 else if(meas_rep->type == 4) {
2098 struct element_meas_noise *noise;
2100 noise = (struct element_meas_noise *)
2101 pkt_pull(pkt, sizeof(*noise));
2102 if (noise == NULL)
2103 return 0;
2105 if ((meas_rep->len - 3 - sizeof(*noise)) >= 0) {
2106 tprintf("Length of Req matchs not Type %u",
2107 meas_rep->type);
2108 return 0;
2111 tprintf("OP Class: %u, ", noise->op_class);
2112 tprintf("Ch Nr: %u, ", noise->ch_nr);
2113 tprintf("Rand Intv: %fs, ",
2114 le16_to_cpu(noise->rand_intv) * TU);
2115 tprintf("Meas Duration: %fs",
2116 le16_to_cpu(noise->dur) * TU);
2118 if(!subelements(pkt,
2119 meas_rep->len - 3 - sizeof(*noise)))
2120 return 0;
2122 else if(meas_rep->type == 5) {
2123 struct element_meas_beacon *beacon;
2125 beacon = (struct element_meas_beacon *)
2126 pkt_pull(pkt, sizeof(*beacon));
2127 if (beacon == NULL)
2128 return 0;
2130 if ((meas_rep->len - 3 - sizeof(*beacon)) >= 0) {
2131 tprintf("Length of Req matchs not Type %u",
2132 meas_rep->type);
2133 return 0;
2136 tprintf("OP Class: %u, ", beacon->op_class);
2137 tprintf("Ch Nr: %u, ", beacon->ch_nr);
2138 tprintf("Rand Intv: %fs, ",
2139 le16_to_cpu(beacon->rand_intv) * TU);
2140 tprintf("Meas Duration: %fs",
2141 le16_to_cpu(beacon->dur) * TU);
2142 tprintf("Mode: %u, ", beacon->mode);
2143 tprintf("BSSID: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2144 beacon->bssid[0], beacon->bssid[1],
2145 beacon->bssid[2], beacon->bssid[3],
2146 beacon->bssid[4], beacon->bssid[5]);
2148 if(!subelements(pkt,
2149 meas_rep->len - 3 - sizeof(*beacon)))
2150 return 0;
2152 else if(meas_rep->type == 6) {
2153 struct element_meas_frame *frame;
2155 frame = (struct element_meas_frame *)
2156 pkt_pull(pkt, sizeof(*frame));
2157 if (frame == NULL)
2158 return 0;
2160 if ((meas_rep->len - 3 - sizeof(*frame)) >= 0) {
2161 tprintf("Length of Req matchs not Type %u",
2162 meas_rep->type);
2163 return 0;
2166 tprintf("OP Class: %u, ", frame->op_class);
2167 tprintf("Ch Nr: %u, ", frame->ch_nr);
2168 tprintf("Rand Intv: %fs, ",
2169 le16_to_cpu(frame->rand_intv) * TU);
2170 tprintf("Meas Duration: %fs",
2171 le16_to_cpu(frame->dur) * TU);
2172 tprintf("Request Type: %u, ", frame->frame);
2173 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2174 frame->mac[0], frame->mac[1],
2175 frame->mac[2], frame->mac[3],
2176 frame->mac[4], frame->mac[5]);
2178 if(!subelements(pkt,
2179 meas_rep->len - 3 - sizeof(*frame)))
2180 return 0;
2182 else if(meas_rep->type == 7) {
2183 struct element_meas_sta *sta;
2185 sta = (struct element_meas_sta *)
2186 pkt_pull(pkt, sizeof(*sta));
2187 if (sta == NULL)
2188 return 0;
2190 if ((meas_rep->len - 3 - sizeof(*sta)) >= 0) {
2191 tprintf("Length of Req matchs not Type %u",
2192 meas_rep->type);
2193 return 0;
2196 tprintf("Peer MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2197 sta->peer_mac[0], sta->peer_mac[1],
2198 sta->peer_mac[2], sta->peer_mac[3],
2199 sta->peer_mac[4], sta->peer_mac[5]);
2200 tprintf("Rand Intv: %fs, ",
2201 le16_to_cpu(sta->rand_intv) * TU);
2202 tprintf("Meas Duration: %fs",
2203 le16_to_cpu(sta->dur) * TU);
2204 tprintf("Group ID: %u, ", sta->group_id);
2206 if(!subelements(pkt,
2207 meas_rep->len - 3 - sizeof(*sta)))
2208 return 0;
2210 else if(meas_rep->type == 8) {
2211 struct element_meas_lci *lci;
2213 lci = (struct element_meas_lci *)
2214 pkt_pull(pkt, sizeof(*lci));
2215 if (lci == NULL)
2216 return 0;
2218 if ((meas_rep->len - 3 - sizeof(*lci)) >= 0) {
2219 tprintf("Length of Req matchs not Type %u",
2220 meas_rep->type);
2221 return 0;
2224 tprintf("Location Subj: %u, ", lci->loc_subj);
2225 tprintf("Latitude Req Res: %udeg",
2226 lci->latitude_req_res);
2227 tprintf("Longitude Req Res: %udeg",
2228 lci->longitude_req_res);
2229 tprintf("Altitude Req Res: %udeg",
2230 lci->altitude_req_res);
2232 if(!subelements(pkt,
2233 meas_rep->len - 3 - sizeof(*lci)))
2234 return 0;
2236 else if(meas_rep->type == 9) {
2237 struct element_meas_trans_str_cat *trans;
2239 trans = (struct element_meas_trans_str_cat *)
2240 pkt_pull(pkt, sizeof(*trans));
2241 if (trans == NULL)
2242 return 0;
2244 if ((meas_rep->len - 3 - sizeof(*trans)) >= 0) {
2245 tprintf("Length of Req matchs not Type %u",
2246 meas_rep->type);
2247 return 0;
2250 tprintf("Rand Intv: %fs, ",
2251 le16_to_cpu(trans->rand_intv) * TU);
2252 tprintf("Meas Duration: %fs",
2253 le16_to_cpu(trans->dur) * TU);
2254 tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2255 trans->peer_sta_addr[0], trans->peer_sta_addr[1],
2256 trans->peer_sta_addr[2], trans->peer_sta_addr[3],
2257 trans->peer_sta_addr[4], trans->peer_sta_addr[5]);
2258 tprintf("Traffic ID: %u, ", trans->traffic_id);
2259 tprintf("Bin 0 Range: %u, ", trans->bin_0_range);
2261 if(!subelements(pkt,
2262 meas_rep->len - 3 - sizeof(*trans)))
2263 return 0;
2265 else if(meas_rep->type == 10) {
2266 struct element_meas_mcast_diag *mcast;
2268 mcast = (struct element_meas_mcast_diag *)
2269 pkt_pull(pkt, sizeof(*mcast));
2270 if (mcast == NULL)
2271 return 0;
2273 if ((meas_rep->len - 3 - sizeof(*mcast)) >= 0) {
2274 tprintf("Length of Req matchs not Type %u",
2275 meas_rep->type);
2276 return 0;
2279 tprintf("Rand Intv: %fs, ",
2280 le16_to_cpu(mcast->rand_intv) * TU);
2281 tprintf("Meas Duration: %fs",
2282 le16_to_cpu(mcast->dur) * TU);
2283 tprintf("Group MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
2284 mcast->group_mac[0], mcast->group_mac[1],
2285 mcast->group_mac[2], mcast->group_mac[3],
2286 mcast->group_mac[4], mcast->group_mac[5]);
2288 if(!subelements(pkt,
2289 meas_rep->len - 3 - sizeof(*mcast)))
2290 return 0;
2292 else if(meas_rep->type == 11) {
2293 struct element_meas_loc_civic *civic;
2295 civic = (struct element_meas_loc_civic *)
2296 pkt_pull(pkt, sizeof(*civic));
2297 if (civic == NULL)
2298 return 0;
2300 if ((meas_rep->len - 3 - sizeof(*civic)) >= 0) {
2301 tprintf("Length of Req matchs not Type %u",
2302 meas_rep->type);
2303 return 0;
2306 tprintf("Location Subj: %u, ", civic->loc_subj);
2307 tprintf("Type: %u, ", civic->civic_loc);
2308 tprintf("Srv Intv Units: %u, ",
2309 le16_to_cpu(civic->loc_srv_intv_unit));
2310 tprintf("Srv Intv: %u, ", civic->loc_srv_intv);
2312 if(!subelements(pkt,
2313 meas_rep->len - 3 - sizeof(*civic)))
2314 return 0;
2316 else if(meas_rep->type == 12) {
2317 struct element_meas_loc_id *id;
2319 id = (struct element_meas_loc_id *)
2320 pkt_pull(pkt, sizeof(*id));
2321 if (id == NULL)
2322 return 0;
2324 if ((meas_rep->len - 3 - sizeof(*id)) >= 0) {
2325 tprintf("Length of Req matchs not Type %u",
2326 meas_rep->type);
2327 return 0;
2330 tprintf("Location Subj: %u, ", id->loc_subj);
2331 tprintf("Srv Intv Units: %u, ",
2332 le16_to_cpu(id->loc_srv_intv_unit));
2333 tprintf("Srv Intv: %u", id->loc_srv_intv);
2335 if(!subelements(pkt,
2336 meas_rep->len - 3 - sizeof(*id)))
2337 return 0;
2339 else {
2340 tprintf("Length field indicates data,"
2341 " but could not interpreted");
2342 return 0;
2346 return 1;
2349 static int8_t inf_quiet(struct pkt_buff *pkt, u8 *id)
2351 struct element_quiet *quiet;
2353 quiet = (struct element_quiet *) pkt_pull(pkt, sizeof(*quiet));
2354 if (quiet == NULL)
2355 return 0;
2357 tprintf("Quit (%u, Len(%u)): ", *id, quiet->len);
2358 if (len_neq_error(quiet->len, 6))
2359 return 0;
2361 tprintf("Count: %ud, ", quiet->cnt);
2362 tprintf("Period: %u, ", quiet->period);
2363 tprintf("Duration: %fs, ", le16_to_cpu(quiet->dur) * TU);
2364 tprintf("Offs: %fs", le16_to_cpu(quiet->offs) * TU);
2367 return 1;
2370 static int8_t inf_ibss_dfs(struct pkt_buff *pkt, u8 *id)
2372 struct element_ibss_dfs *ibss_dfs;
2373 u8 i;
2375 ibss_dfs = (struct element_ibss_dfs *) pkt_pull(pkt, sizeof(*ibss_dfs));
2376 if (ibss_dfs == NULL)
2377 return 0;
2379 tprintf("IBSS DFS (%u, Len(%u)): ", *id, ibss_dfs->len);
2380 if (len_lt_error(ibss_dfs->len, 7))
2381 return 0;
2383 tprintf("Owner: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
2384 ibss_dfs->owner[0], ibss_dfs->owner[1],
2385 ibss_dfs->owner[2], ibss_dfs->owner[3],
2386 ibss_dfs->owner[4], ibss_dfs->owner[5]);
2387 tprintf("Recovery Intv: %u, ", ibss_dfs->rec_intv);
2389 if((ibss_dfs->len - sizeof(*ibss_dfs) + 1) & 1) {
2390 tprintf("Length of Channel Map should be modulo 2");
2391 return 0;
2394 for (i = 0; i < ibss_dfs->len; i += 2) {
2395 struct element_ibss_dfs_tuple *ibss_dfs_tuple;
2397 ibss_dfs_tuple = (struct element_ibss_dfs_tuple *)
2398 pkt_pull(pkt, sizeof(*ibss_dfs_tuple));
2399 if (ibss_dfs_tuple == NULL)
2400 return 0;
2402 tprintf("Channel Nr: %u, ", ibss_dfs_tuple->ch_nr);
2403 tprintf("Map: %u, ", ibss_dfs_tuple->map);
2406 return 1;
2409 static int8_t inf_erp(struct pkt_buff *pkt, u8 *id)
2411 struct element_erp *erp;
2413 erp = (struct element_erp *) pkt_pull(pkt, sizeof(*erp));
2414 if (erp == NULL)
2415 return 0;
2417 tprintf("ERP (%u, Len(%u)): ", *id, erp->len);
2418 if (len_neq_error(erp->len, 1))
2419 return 0;
2420 tprintf("Non ERP Present (%u), ", erp->param & 0x1);
2421 tprintf("Use Protection (%u), ", (erp->param >> 1) & 0x1);
2422 tprintf("Barker Preamble Mode (%u), ", (erp->param >> 2) & 0x1);
2423 tprintf("Reserved (0x%.5x)", erp->param >> 3);
2425 return 1;
2428 static int8_t inf_ts_del(struct pkt_buff *pkt, u8 *id)
2430 struct element_ts_del *ts_del;
2432 ts_del = (struct element_ts_del *) pkt_pull(pkt, sizeof(*ts_del));
2433 if (ts_del == NULL)
2434 return 0;
2436 tprintf("TS Delay (%u, Len(%u)): ", *id, ts_del->len);
2437 if (len_neq_error(ts_del->len, 4))
2438 return 0;
2439 tprintf("Delay (%fs)", le32_to_cpu(ts_del->delay) * TU);
2441 return 1;
2444 static int8_t inf_tclas_proc(struct pkt_buff *pkt, u8 *id)
2446 struct element_tclas_proc *tclas_proc;
2448 tclas_proc = (struct element_tclas_proc *)
2449 pkt_pull(pkt, sizeof(*tclas_proc));
2450 if (tclas_proc == NULL)
2451 return 0;
2453 tprintf("TCLAS Procesing (%u, Len(%u)): ", *id, tclas_proc->len);
2454 if (len_neq_error(tclas_proc->len, 1))
2455 return 0;
2456 tprintf("Processing (%u)", tclas_proc->proc);
2458 return 1;
2461 static int8_t inf_ht_cap(struct pkt_buff *pkt, u8 *id)
2463 return 0;
2466 static int8_t inf_qos_cap(struct pkt_buff *pkt, u8 *id)
2468 return 0;
2471 static int8_t inf_rsn(struct pkt_buff *pkt, u8 *id)
2473 return 0;
2476 static int8_t inf_ext_supp_rates(struct pkt_buff *pkt, u8 *id)
2478 u8 i;
2479 u8 *rates;
2480 struct element_ext_supp_rates *ext_supp_rates;
2482 ext_supp_rates = (struct element_ext_supp_rates *)
2483 pkt_pull(pkt, sizeof(*ext_supp_rates));
2484 if (ext_supp_rates == NULL)
2485 return 0;
2487 tprintf("Ext Support Rates (%u, Len(%u)): ", *id, ext_supp_rates->len);
2489 if ((ext_supp_rates->len - sizeof(*ext_supp_rates) + 1) > 0) {
2490 rates = pkt_pull(pkt, ext_supp_rates->len);
2491 if (rates == NULL)
2492 return 0;
2494 for (i = 0; i < ext_supp_rates->len; i++)
2495 tprintf("%g ", (rates[i] & 0x80) ?
2496 ((rates[i] & 0x3f) * 0.5) :
2497 data_rates(rates[i]));
2498 return 1;
2501 return 0;
2504 static int8_t inf_ap_ch_exp(struct pkt_buff *pkt, u8 *id) {
2505 return 0;
2508 static int8_t inf_neighb_rep(struct pkt_buff *pkt, u8 *id) {
2509 return 0;
2512 static int8_t inf_rcpi(struct pkt_buff *pkt, u8 *id) {
2513 return 0;
2516 static int8_t inf_mde(struct pkt_buff *pkt, u8 *id) {
2517 return 0;
2520 static int8_t inf_fte(struct pkt_buff *pkt, u8 *id) {
2521 return 0;
2524 static int8_t inf_time_out_int(struct pkt_buff *pkt, u8 *id) {
2525 return 0;
2528 static int8_t inf_rde(struct pkt_buff *pkt, u8 *id) {
2529 return 0;
2532 static int8_t inf_dse_reg_loc(struct pkt_buff *pkt, u8 *id) {
2533 return 0;
2536 static int8_t inf_supp_op_class(struct pkt_buff *pkt, u8 *id) {
2537 return 0;
2540 static int8_t inf_ext_ch_sw_ann(struct pkt_buff *pkt, u8 *id) {
2541 return 0;
2544 static int8_t inf_ht_op(struct pkt_buff *pkt, u8 *id) {
2545 return 0;
2548 static int8_t inf_sec_ch_offs(struct pkt_buff *pkt, u8 *id) {
2549 return 0;
2552 static int8_t inf_bss_avg_acc_del(struct pkt_buff *pkt, u8 *id) {
2553 return 0;
2556 static int8_t inf_ant(struct pkt_buff *pkt, u8 *id) {
2557 return 0;
2560 static int8_t inf_rsni(struct pkt_buff *pkt, u8 *id) {
2561 return 0;
2564 static int8_t inf_meas_pilot_trans(struct pkt_buff *pkt, u8 *id) {
2565 return 0;
2568 static int8_t inf_bss_avl_adm_cap(struct pkt_buff *pkt, u8 *id) {
2569 return 0;
2572 static int8_t inf_bss_ac_acc_del(struct pkt_buff *pkt, u8 *id) {
2573 return 0;
2576 static int8_t inf_time_adv(struct pkt_buff *pkt, u8 *id) {
2577 return 0;
2580 static int8_t inf_rm_ena_cap(struct pkt_buff *pkt, u8 *id) {
2581 return 0;
2584 static int8_t inf_mult_bssid(struct pkt_buff *pkt, u8 *id) {
2585 return 0;
2588 static int8_t inf_20_40_bss_coex(struct pkt_buff *pkt, u8 *id) {
2589 return 0;
2592 static int8_t inf_20_40_bss_int_ch_rep(struct pkt_buff *pkt, u8 *id) {
2593 return 0;
2596 static int8_t inf_overl_bss_scan_para(struct pkt_buff *pkt, u8 *id) {
2597 return 0;
2600 static int8_t inf_ric_desc(struct pkt_buff *pkt, u8 *id) {
2601 return 0;
2604 static int8_t inf_mgmt_mic(struct pkt_buff *pkt, u8 *id) {
2605 return 0;
2608 static int8_t inf_ev_req(struct pkt_buff *pkt, u8 *id) {
2609 return 0;
2612 static int8_t inf_ev_rep(struct pkt_buff *pkt, u8 *id) {
2613 return 0;
2616 static int8_t inf_diagn_req(struct pkt_buff *pkt, u8 *id) {
2617 return 0;
2620 static int8_t inf_diagn_rep(struct pkt_buff *pkt, u8 *id) {
2621 return 0;
2624 static int8_t inf_loc_para(struct pkt_buff *pkt, u8 *id) {
2625 return 0;
2628 static int8_t inf_nontr_bssid_cap(struct pkt_buff *pkt, u8 *id) {
2629 return 0;
2632 static int8_t inf_ssid_list(struct pkt_buff *pkt, u8 *id) {
2633 return 0;
2636 static int8_t inf_mult_bssid_index(struct pkt_buff *pkt, u8 *id) {
2637 return 0;
2640 static int8_t inf_fms_desc(struct pkt_buff *pkt, u8 *id) {
2641 return 0;
2644 static int8_t inf_fms_req(struct pkt_buff *pkt, u8 *id) {
2645 return 0;
2648 static int8_t inf_fms_resp(struct pkt_buff *pkt, u8 *id) {
2649 return 0;
2652 static int8_t inf_qos_tfc_cap(struct pkt_buff *pkt, u8 *id) {
2653 return 0;
2656 static int8_t inf_bss_max_idle_per(struct pkt_buff *pkt, u8 *id) {
2657 return 0;
2660 static int8_t inf_tfs_req(struct pkt_buff *pkt, u8 *id) {
2661 return 0;
2664 static int8_t inf_tfs_resp(struct pkt_buff *pkt, u8 *id) {
2665 return 0;
2668 static int8_t inf_wnm_sleep_mod(struct pkt_buff *pkt, u8 *id) {
2669 return 0;
2672 static int8_t inf_tim_bcst_req(struct pkt_buff *pkt, u8 *id) {
2673 return 0;
2676 static int8_t inf_tim_bcst_resp(struct pkt_buff *pkt, u8 *id) {
2677 return 0;
2680 static int8_t inf_coll_interf_rep(struct pkt_buff *pkt, u8 *id) {
2681 return 0;
2684 static int8_t inf_ch_usage(struct pkt_buff *pkt, u8 *id) {
2685 return 0;
2688 static int8_t inf_time_zone(struct pkt_buff *pkt, u8 *id) {
2689 return 0;
2692 static int8_t inf_dms_req(struct pkt_buff *pkt, u8 *id) {
2693 return 0;
2696 static int8_t inf_dms_resp(struct pkt_buff *pkt, u8 *id) {
2697 return 0;
2700 static int8_t inf_link_id(struct pkt_buff *pkt, u8 *id) {
2701 return 0;
2704 static int8_t inf_wakeup_sched(struct pkt_buff *pkt, u8 *id) {
2705 return 0;
2708 static int8_t inf_ch_sw_timing(struct pkt_buff *pkt, u8 *id) {
2709 return 0;
2712 static int8_t inf_pti_ctrl(struct pkt_buff *pkt, u8 *id) {
2713 return 0;
2716 static int8_t inf_tpu_buff_status(struct pkt_buff *pkt, u8 *id) {
2717 return 0;
2720 static int8_t inf_interw(struct pkt_buff *pkt, u8 *id) {
2721 return 0;
2724 static int8_t inf_adv_proto(struct pkt_buff *pkt, u8 *id) {
2725 return 0;
2728 static int8_t inf_exp_bandw_req(struct pkt_buff *pkt, u8 *id) {
2729 return 0;
2732 static int8_t inf_qos_map_set(struct pkt_buff *pkt, u8 *id) {
2733 return 0;
2736 static int8_t inf_roam_cons(struct pkt_buff *pkt, u8 *id) {
2737 return 0;
2740 static int8_t inf_emer_alert_id(struct pkt_buff *pkt, u8 *id) {
2741 return 0;
2744 static int8_t inf_mesh_conf(struct pkt_buff *pkt, u8 *id) {
2745 return 0;
2748 static int8_t inf_mesh_id(struct pkt_buff *pkt, u8 *id) {
2749 return 0;
2752 static int8_t inf_mesh_link_metr_rep(struct pkt_buff *pkt, u8 *id) {
2753 return 0;
2756 static int8_t inf_cong_notif(struct pkt_buff *pkt, u8 *id) {
2757 return 0;
2760 static int8_t inf_mesh_peer_mgmt(struct pkt_buff *pkt, u8 *id) {
2761 return 0;
2764 static int8_t inf_mesh_ch_sw_para(struct pkt_buff *pkt, u8 *id) {
2765 return 0;
2768 static int8_t inf_mesh_awake_win(struct pkt_buff *pkt, u8 *id) {
2769 return 0;
2772 static int8_t inf_beacon_timing(struct pkt_buff *pkt, u8 *id) {
2773 return 0;
2776 static int8_t inf_mccaop_setup_req(struct pkt_buff *pkt, u8 *id) {
2777 return 0;
2780 static int8_t inf_mccaop_setup_rep(struct pkt_buff *pkt, u8 *id) {
2781 return 0;
2784 static int8_t inf_mccaop_adv(struct pkt_buff *pkt, u8 *id) {
2785 return 0;
2788 static int8_t inf_mccaop_teardwn(struct pkt_buff *pkt, u8 *id) {
2789 return 0;
2792 static int8_t inf_gann(struct pkt_buff *pkt, u8 *id) {
2793 return 0;
2796 static int8_t inf_rann(struct pkt_buff *pkt, u8 *id) {
2797 return 0;
2800 static int8_t inf_ext_cap(struct pkt_buff *pkt, u8 *id) {
2801 return 0;
2804 static int8_t inf_preq(struct pkt_buff *pkt, u8 *id) {
2805 return 0;
2808 static int8_t inf_prep(struct pkt_buff *pkt, u8 *id) {
2809 return 0;
2812 static int8_t inf_perr(struct pkt_buff *pkt, u8 *id) {
2813 return 0;
2816 static int8_t inf_pxu(struct pkt_buff *pkt, u8 *id) {
2817 return 0;
2820 static int8_t inf_pxuc(struct pkt_buff *pkt, u8 *id) {
2821 return 0;
2824 static int8_t inf_auth_mesh_peer_exch(struct pkt_buff *pkt, u8 *id) {
2825 return 0;
2828 static int8_t inf_mic(struct pkt_buff *pkt, u8 *id) {
2829 return 0;
2832 static int8_t inf_dest_uri(struct pkt_buff *pkt, u8 *id) {
2833 return 0;
2836 static int8_t inf_u_apsd_coex(struct pkt_buff *pkt, u8 *id) {
2837 return 0;
2840 static int8_t inf_mccaop_adv_overv(struct pkt_buff *pkt, u8 *id) {
2841 return 0;
2844 static int8_t inf_vend_spec(struct pkt_buff *pkt, u8 *id)
2846 u8 i;
2847 u8 *data;
2848 struct element_vend_spec *vend_spec;
2850 vend_spec = (struct element_vend_spec *)
2851 pkt_pull(pkt, sizeof(*vend_spec));
2852 if (vend_spec == NULL)
2853 return 0;
2855 tprintf("Vendor Specific (%u, Len (%u)): ", *id, vend_spec->len);
2857 data = pkt_pull(pkt, vend_spec->len);
2858 if (data == NULL)
2859 return 0;
2861 tprintf("Data 0x");
2862 for (i = 0; i < vend_spec->len; i++)
2863 tprintf("%.2x", data[i]);
2865 return 1;
2868 static int8_t inf_elements(struct pkt_buff *pkt)
2870 u8 *id = pkt_pull(pkt, 1);
2871 if (id == NULL)
2872 return 0;
2874 switch (*id) {
2875 case 0: return inf_ssid(pkt, id);
2876 case 1: return inf_supp_rates(pkt, id);
2877 case 2: return inf_fh_ps(pkt, id);
2878 case 3: return inf_dsss_ps(pkt, id);
2879 case 4: return inf_cf_ps(pkt, id);
2880 case 5: return inf_tim(pkt, id);
2881 case 6: return inf_ibss_ps(pkt, id);
2882 case 7: return inf_country(pkt, id);
2883 case 8: return inf_hop_pp(pkt, id);
2884 case 9: return inf_hop_pt(pkt, id);
2885 case 10: return inf_req(pkt, id);
2886 case 11: return inf_bss_load(pkt, id);
2887 case 12: return inf_edca_ps(pkt, id);
2888 case 13: return inf_tspec(pkt, id);
2889 case 14: return inf_tclas(pkt, id);
2890 case 15: return inf_sched(pkt, id);
2891 case 16: return inf_chall_txt(pkt, id);
2892 case 17 ... 31: return inf_reserved(pkt, id);
2893 case 32: return inf_pwr_constr(pkt, id);
2894 case 33: return inf_pwr_cap(pkt, id);
2895 case 34: return inf_tpc_req(pkt, id);
2896 case 35: return inf_tpc_rep(pkt, id);
2897 case 36: return inf_supp_ch(pkt, id);
2898 case 37: return inf_ch_sw_ann(pkt, id);
2899 case 38: return inf_meas_req(pkt, id);
2900 case 39: return inf_meas_rep(pkt, id);
2901 case 40: return inf_quiet(pkt, id);
2902 case 41: return inf_ibss_dfs(pkt, id);
2903 case 42: return inf_erp(pkt, id);
2904 case 43: return inf_ts_del(pkt, id);
2905 case 44: return inf_tclas_proc(pkt, id);
2906 case 45: return inf_ht_cap(pkt, id);
2907 case 46: return inf_qos_cap(pkt, id);
2908 case 47: return inf_reserved(pkt, id);
2909 case 48: return inf_rsn(pkt, id);
2910 case 49: return inf_rsn(pkt, id);
2911 case 50: return inf_ext_supp_rates(pkt, id);
2912 case 51: return inf_ap_ch_exp(pkt, id);
2913 case 52: return inf_neighb_rep(pkt, id);
2914 case 53: return inf_rcpi(pkt, id);
2915 case 54: return inf_mde(pkt, id);
2916 case 55: return inf_fte(pkt, id);
2917 case 56: return inf_time_out_int(pkt, id);
2918 case 57: return inf_rde(pkt, id);
2919 case 58: return inf_dse_reg_loc(pkt, id);
2920 case 59: return inf_supp_op_class(pkt, id);
2921 case 60: return inf_ext_ch_sw_ann(pkt, id);
2922 case 61: return inf_ht_op(pkt, id);
2923 case 62: return inf_sec_ch_offs(pkt, id);
2924 case 63: return inf_bss_avg_acc_del(pkt, id);
2925 case 64: return inf_ant(pkt, id);
2926 case 65: return inf_rsni(pkt, id);
2927 case 66: return inf_meas_pilot_trans(pkt, id);
2928 case 67: return inf_bss_avl_adm_cap(pkt, id);
2929 case 68: return inf_bss_ac_acc_del(pkt, id);
2930 case 69: return inf_time_adv(pkt, id);
2931 case 70: return inf_rm_ena_cap(pkt, id);
2932 case 71: return inf_mult_bssid(pkt, id);
2933 case 72: return inf_20_40_bss_coex(pkt, id);
2934 case 73: return inf_20_40_bss_int_ch_rep(pkt, id);
2935 case 74: return inf_overl_bss_scan_para(pkt, id);
2936 case 75: return inf_ric_desc(pkt, id);
2937 case 76: return inf_mgmt_mic(pkt, id);
2938 case 78: return inf_ev_req(pkt, id);
2939 case 79: return inf_ev_rep(pkt, id);
2940 case 80: return inf_diagn_req(pkt, id);
2941 case 81: return inf_diagn_rep(pkt, id);
2942 case 82: return inf_loc_para(pkt, id);
2943 case 83: return inf_nontr_bssid_cap(pkt, id);
2944 case 84: return inf_ssid_list(pkt, id);
2945 case 85: return inf_mult_bssid_index(pkt, id);
2946 case 86: return inf_fms_desc(pkt, id);
2947 case 87: return inf_fms_req(pkt, id);
2948 case 88: return inf_fms_resp(pkt, id);
2949 case 89: return inf_qos_tfc_cap(pkt, id);
2950 case 90: return inf_bss_max_idle_per(pkt, id);
2951 case 91: return inf_tfs_req(pkt, id);
2952 case 92: return inf_tfs_resp(pkt, id);
2953 case 93: return inf_wnm_sleep_mod(pkt, id);
2954 case 94: return inf_tim_bcst_req(pkt, id);
2955 case 95: return inf_tim_bcst_resp(pkt, id);
2956 case 96: return inf_coll_interf_rep(pkt, id);
2957 case 97: return inf_ch_usage(pkt, id);
2958 case 98: return inf_time_zone(pkt, id);
2959 case 99: return inf_dms_req(pkt, id);
2960 case 100: return inf_dms_resp(pkt, id);
2961 case 101: return inf_link_id(pkt, id);
2962 case 102: return inf_wakeup_sched(pkt, id);
2963 case 104: return inf_ch_sw_timing(pkt, id);
2964 case 105: return inf_pti_ctrl(pkt, id);
2965 case 106: return inf_tpu_buff_status(pkt, id);
2966 case 107: return inf_interw(pkt, id);
2967 case 108: return inf_adv_proto(pkt, id);
2968 case 109: return inf_exp_bandw_req(pkt, id);
2969 case 110: return inf_qos_map_set(pkt, id);
2970 case 111: return inf_roam_cons(pkt, id);
2971 case 112: return inf_emer_alert_id(pkt, id);
2972 case 113: return inf_mesh_conf(pkt, id);
2973 case 114: return inf_mesh_id(pkt, id);
2974 case 115: return inf_mesh_link_metr_rep(pkt, id);
2975 case 116: return inf_cong_notif(pkt, id);
2976 case 117: return inf_mesh_peer_mgmt(pkt, id);
2977 case 118: return inf_mesh_ch_sw_para(pkt, id);
2978 case 119: return inf_mesh_awake_win(pkt, id);
2979 case 120: return inf_beacon_timing(pkt, id);
2980 case 121: return inf_mccaop_setup_req(pkt, id);
2981 case 122: return inf_mccaop_setup_rep(pkt, id);
2982 case 123: return inf_mccaop_adv(pkt, id);
2983 case 124: return inf_mccaop_teardwn(pkt, id);
2984 case 125: return inf_gann(pkt, id);
2985 case 126: return inf_rann(pkt, id);
2986 case 127: return inf_ext_cap(pkt, id);
2987 case 128: return inf_reserved(pkt, id);
2988 case 129: return inf_reserved(pkt, id);
2989 case 130: return inf_preq(pkt, id);
2990 case 131: return inf_prep(pkt, id);
2991 case 132: return inf_perr(pkt, id);
2992 case 133: return inf_reserved(pkt, id);
2993 case 134: return inf_reserved(pkt, id);
2994 case 135: return inf_reserved(pkt, id);
2995 case 136: return inf_reserved(pkt, id);
2996 case 137: return inf_pxu(pkt, id);
2997 case 138: return inf_pxuc(pkt, id);
2998 case 139: return inf_auth_mesh_peer_exch(pkt, id);
2999 case 140: return inf_mic(pkt, id);
3000 case 141: return inf_dest_uri(pkt, id);
3001 case 142: return inf_u_apsd_coex(pkt, id);
3002 case 143 ... 173: return inf_reserved(pkt, id);
3003 case 174: return inf_mccaop_adv_overv(pkt, id);
3004 case 221: return inf_vend_spec(pkt, id);
3007 return 0;
3010 #define ESS 0b0000000000000001
3011 #define IBSS 0b0000000000000010
3012 #define CF_Pollable 0b0000000000000100
3013 #define CF_Poll_Req 0b0000000000001000
3014 #define Privacy 0b0000000000010000
3015 #define Short_Pre 0b0000000000100000
3016 #define PBCC 0b0000000001000000
3017 #define Ch_Agility 0b0000000010000000
3018 #define Spec_Mgmt 0b0000000100000000
3019 #define QoS 0b0000001000000000
3020 #define Short_Slot_t 0b0000010000000000
3021 #define APSD 0b0000100000000000
3022 #define Radio_Meas 0b0001000000000000
3023 #define DSSS_OFDM 0b0010000000000000
3024 #define Del_Block_ACK 0b0100000000000000
3025 #define Imm_Block_ACK 0b1000000000000000
3027 static int8_t cap_field(u16 cap_inf)
3029 if (ESS & cap_inf)
3030 tprintf(" ESS;");
3031 if (IBSS & cap_inf)
3032 tprintf(" IBSS;");
3033 if (CF_Pollable & cap_inf)
3034 tprintf(" CF Pollable;");
3035 if (CF_Poll_Req & cap_inf)
3036 tprintf(" CF-Poll Request;");
3037 if (Privacy & cap_inf)
3038 tprintf(" Privacy;");
3039 if (Short_Pre & cap_inf)
3040 tprintf(" Short Preamble;");
3041 if (PBCC & cap_inf)
3042 tprintf(" PBCC;");
3043 if (Ch_Agility & cap_inf)
3044 tprintf(" Channel Agility;");
3045 if (Spec_Mgmt & cap_inf)
3046 tprintf(" Spectrum Management;");
3047 if (QoS & cap_inf)
3048 tprintf(" QoS;");
3049 if (Short_Slot_t & cap_inf)
3050 tprintf(" Short Slot Time;");
3051 if (APSD & cap_inf)
3052 tprintf(" APSD;");
3053 if (Radio_Meas & cap_inf)
3054 tprintf(" Radio Measurement;");
3055 if (DSSS_OFDM & cap_inf)
3056 tprintf(" DSSS-OFDM;");
3057 if (Del_Block_ACK & cap_inf)
3058 tprintf(" Delayed Block Ack;");
3059 if (Imm_Block_ACK & cap_inf)
3060 tprintf(" Immediate Block Ack;");
3062 return 1;
3065 /* Management Dissectors */
3066 static int8_t assoc_req(struct pkt_buff *pkt) {
3067 return 0;
3070 static int8_t assoc_resp(struct pkt_buff *pkt) {
3071 return 0;
3074 static int8_t reassoc_req(struct pkt_buff *pkt) {
3075 return 0;
3078 static int8_t reassoc_resp(struct pkt_buff *pkt) {
3079 return 0;
3082 static int8_t probe_req(struct pkt_buff *pkt) {
3083 return 0;
3086 static int8_t probe_resp(struct pkt_buff *pkt) {
3087 return 0;
3090 static int8_t beacon(struct pkt_buff *pkt)
3092 struct ieee80211_mgmt_beacon *beacon;
3094 beacon = (struct ieee80211_mgmt_beacon *)
3095 pkt_pull(pkt, sizeof(*beacon));
3096 if (beacon == NULL)
3097 return 0;
3099 tprintf("Timestamp 0x%.16lx, ", le64_to_cpu(beacon->timestamp));
3100 tprintf("Beacon Interval (%fs), ", le16_to_cpu(beacon->beacon_int)*TU);
3101 tprintf("Capabilities (0x%x <->", le16_to_cpu(beacon->capab_info));
3102 cap_field(le16_to_cpu(beacon->capab_info));
3103 tprintf(")");
3105 if(pkt_len(pkt)) {
3106 tprintf("\n\tParameters:");
3107 while (inf_elements(pkt)) {
3108 tprintf("\n\t");
3112 if(pkt_len(pkt))
3113 return 0;
3114 return 1;
3117 static int8_t atim(struct pkt_buff *pkt) {
3118 return 0;
3121 static int8_t disassoc(struct pkt_buff *pkt) {
3122 return 0;
3125 static int8_t auth(struct pkt_buff *pkt) {
3126 return 0;
3129 static int8_t deauth(struct pkt_buff *pkt) {
3130 return 0;
3132 /* End Management Dissectors */
3134 /* Control Dissectors */
3135 static int8_t ps_poll(struct pkt_buff *pkt) {
3136 return 0;
3139 static int8_t rts(struct pkt_buff *pkt) {
3140 return 0;
3143 static int8_t cts(struct pkt_buff *pkt) {
3144 return 0;
3147 static int8_t ack(struct pkt_buff *pkt) {
3148 return 0;
3151 static int8_t cf_end(struct pkt_buff *pkt) {
3152 return 0;
3155 static int8_t cf_end_ack(struct pkt_buff *pkt) {
3156 return 0;
3158 /* End Control Dissectors */
3160 /* Data Dissectors */
3161 static int8_t data(struct pkt_buff *pkt) {
3162 return 0;
3165 static int8_t data_cf_ack(struct pkt_buff *pkt) {
3166 return 0;
3169 static int8_t data_cf_poll(struct pkt_buff *pkt) {
3170 return 0;
3173 static int8_t data_cf_ack_poll(struct pkt_buff *pkt) {
3174 return 0;
3177 static int8_t null(struct pkt_buff *pkt) {
3178 return 0;
3181 static int8_t cf_ack(struct pkt_buff *pkt) {
3182 return 0;
3185 static int8_t cf_poll(struct pkt_buff *pkt) {
3186 return 0;
3189 static int8_t cf_ack_poll(struct pkt_buff *pkt) {
3190 return 0;
3192 /* End Data Dissectors */
3194 static const char *mgt_sub(u8 subtype, struct pkt_buff *pkt,
3195 int8_t (**get_content)(struct pkt_buff *pkt))
3197 u16 seq_ctrl;
3198 struct ieee80211_mgmt *mgmt;
3199 const char *dst, *src, *bssid;
3201 mgmt = (struct ieee80211_mgmt *) pkt_pull(pkt, sizeof(*mgmt));
3202 if (mgmt == NULL)
3203 return 0;
3205 dst = lookup_vendor((mgmt->da[0] << 16) |
3206 (mgmt->da[1] << 8) |
3207 mgmt->da[2]);
3208 src = lookup_vendor((mgmt->sa[0] << 16) |
3209 (mgmt->sa[1] << 8) |
3210 mgmt->sa[2]);
3212 bssid = lookup_vendor((mgmt->bssid[0] << 16) |
3213 (mgmt->bssid[1] << 8) |
3214 mgmt->bssid[2]);
3215 seq_ctrl = le16_to_cpu(mgmt->seq_ctrl);
3217 tprintf("Duration (%u),", le16_to_cpu(mgmt->duration));
3218 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
3219 mgmt->da[0], mgmt->da[1], mgmt->da[2],
3220 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
3221 if (dst) {
3222 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst,
3223 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
3226 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
3227 mgmt->sa[0], mgmt->sa[1], mgmt->sa[2],
3228 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
3229 if (src) {
3230 tprintf("=> (%s:%.2x:%.2x:%.2x)", src,
3231 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
3234 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
3235 mgmt->bssid[0], mgmt->bssid[1], mgmt->bssid[2],
3236 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
3237 if(bssid) {
3238 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid,
3239 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
3242 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ",
3243 seq_ctrl & 0xf, seq_ctrl >> 4);
3245 switch (subtype) {
3246 case 0b0000:
3247 *get_content = assoc_req;
3248 return "Association Request";
3249 case 0b0001:
3250 *get_content = assoc_resp;
3251 return "Association Response";
3252 case 0b0010:
3253 *get_content = reassoc_req;
3254 return "Reassociation Request";
3255 case 0b0011:
3256 *get_content = reassoc_resp;
3257 return "Reassociation Response";
3258 case 0b0100:
3259 *get_content = probe_req;
3260 return "Probe Request";
3261 case 0b0101:
3262 *get_content = probe_resp;
3263 return "Probe Response";
3264 case 0b1000:
3265 *get_content = beacon;
3266 return "Beacon";
3267 case 0b1001:
3268 *get_content = atim;
3269 return "ATIM";
3270 case 0b1010:
3271 *get_content = disassoc;
3272 return "Disassociation";
3273 case 0b1011:
3274 *get_content = auth;
3275 return "Authentication";
3276 case 0b1100:
3277 *get_content = deauth;
3278 return "Deauthentication";
3279 case 0b0110 ... 0b0111:
3280 case 0b1101 ... 0b1111:
3281 *get_content = NULL;
3282 return "Reserved";
3283 default:
3284 *get_content = NULL;
3285 return "Management SubType unknown";
3289 static const char *ctrl_sub(u8 subtype, struct pkt_buff *pkt,
3290 int8_t (**get_content)(struct pkt_buff *pkt))
3292 switch (subtype) {
3293 case 0b1010:
3294 *get_content = ps_poll;
3295 return "PS-Poll";
3296 case 0b1011:
3297 *get_content = rts;
3298 return "RTS";
3299 case 0b1100:
3300 *get_content = cts;
3301 return "CTS";
3302 case 0b1101:
3303 *get_content = ack;
3304 return "ACK";
3305 case 0b1110:
3306 *get_content = cf_end;
3307 return "CF End";
3308 case 0b1111:
3309 *get_content = cf_end_ack;
3310 return "CF End + CF-ACK";
3311 case 0b0000 ... 0b1001:
3312 *get_content = NULL;
3313 return "Reserved";
3314 default:
3315 return "Control SubType unkown";
3319 static const char *data_sub(u8 subtype, struct pkt_buff *pkt,
3320 int8_t (**get_content)(struct pkt_buff *pkt))
3322 switch (subtype) {
3323 case 0b0000:
3324 *get_content = data;
3325 return "Data";
3326 case 0b0001:
3327 *get_content = data_cf_ack;
3328 return "Data + CF-ACK";
3329 case 0b0010:
3330 *get_content = data_cf_poll;
3331 return "Data + CF-Poll";
3332 case 0b0011:
3333 *get_content = data_cf_ack_poll;
3334 return "Data + CF-ACK + CF-Poll";
3335 case 0b0100:
3336 *get_content = null;
3337 return "Null";
3338 case 0b0101:
3339 *get_content = cf_ack;
3340 return "CF-ACK";
3341 case 0b0110:
3342 *get_content = cf_poll;
3343 return "CF-Poll";
3344 case 0b0111:
3345 *get_content = cf_ack_poll;
3346 return "CF-ACK + CF-Poll";
3347 case 0b1000 ... 0b1111:
3348 *get_content = NULL;
3349 return "Reserved";
3350 default:
3351 *get_content = NULL;
3352 return "Data SubType unkown";
3356 static const char *
3357 frame_control_type(u8 type, const char *(**get_subtype)(u8 subtype,
3358 struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)))
3360 switch (type) {
3361 case 0b00:
3362 *get_subtype = mgt_sub;
3363 return "Management";
3364 case 0b01:
3365 *get_subtype = ctrl_sub;
3366 return "Control";
3367 case 0b10:
3368 *get_subtype = data_sub;
3369 return "Data";
3370 case 0b11:
3371 *get_subtype = NULL;
3372 return "Reserved";
3373 default:
3374 *get_subtype = NULL;
3375 return "Control Type unkown";
3379 static void ieee80211(struct pkt_buff *pkt)
3381 int8_t (*get_content)(struct pkt_buff *pkt) = NULL;
3382 const char *(*get_subtype)(u8 subtype, struct pkt_buff *pkt,
3383 int8_t (**get_content)(struct pkt_buff *pkt)) = NULL;
3384 const char *subtype = NULL;
3385 struct ieee80211_frm_ctrl *frm_ctrl;
3387 frm_ctrl = (struct ieee80211_frm_ctrl *)
3388 pkt_pull(pkt, sizeof(*frm_ctrl));
3389 if (frm_ctrl == NULL)
3390 return;
3392 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
3393 le16_to_cpu(frm_ctrl->frame_control));
3395 tprintf(" [ Proto Version (%u), ", frm_ctrl->proto_version);
3396 tprintf("Type (%u, %s), ", frm_ctrl->type,
3397 frame_control_type(frm_ctrl->type, &get_subtype));
3398 if (get_subtype) {
3399 subtype = (*get_subtype)(frm_ctrl->subtype, pkt, &get_content);
3400 tprintf("Subtype (%u, %s)", frm_ctrl->subtype, subtype);
3401 } else {
3402 tprintf("%s%s%s", colorize_start_full(black, red),
3403 "No SubType Data available", colorize_end());
3406 tprintf("%s%s", frm_ctrl->to_ds ? ", Frame goes to DS" : "",
3407 frm_ctrl->from_ds ? ", Frame comes from DS" : "");
3408 tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : "");
3409 tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : "");
3410 tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : "");
3411 tprintf("%s", frm_ctrl->more_data ? ", More Data" : "");
3412 tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : "");
3413 tprintf("%s", frm_ctrl->order ? ", Order" : "");
3414 tprintf(" ]\n");
3416 if (get_content) {
3417 tprintf(" [ Subtype %s: ", subtype);
3418 if (!((*get_content) (pkt)))
3419 tprintf("%s%s%s", colorize_start_full(black, red),
3420 "Failed to dissect Subtype", colorize_end());
3421 tprintf(" ]");
3422 } else {
3423 tprintf("%s%s%s", colorize_start_full(black, red),
3424 "No SubType Data available", colorize_end());
3427 tprintf("\n");
3429 // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
3432 static void ieee80211_less(struct pkt_buff *pkt)
3434 tprintf("802.11 frame (more on todo)");
3437 struct protocol ieee80211_ops = {
3438 .key = 0,
3439 .print_full = ieee80211,
3440 .print_less = ieee80211_less,
3443 EXPORT_SYMBOL(ieee80211_ops);