proto_80211_mac_hdr.c: partly implement "measurement request" element
[netsniff-ng.git] / src / proto_80211_mac_hdr.c
blob95d9e496360e01b27c7c07ad627b26e75eea8af0
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_req {
520 u8 len;
521 u8 token;
522 u8 req_mode;
523 u8 type;
524 u8 req[0];
525 } __packed;
527 struct element_meas_req_basic {
528 u8 ch_nr;
529 u64 start;
530 u16 dur;
531 } __packed;
533 struct element_meas_req_cca {
534 u8 ch_nr;
535 u64 start;
536 u16 dur;
537 } __packed;
539 struct element_meas_req_rpi {
540 u8 ch_nr;
541 u64 start;
542 u16 dur;
543 } __packed;
545 struct element_meas_req_ch_load {
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_req_noise {
554 u8 op_class;
555 u8 ch_nr;
556 u16 rand_intv;
557 u16 dur;
558 u8 sub[0];
559 } __packed;
561 struct element_meas_req_beacon {
562 u8 op_class;
563 u8 ch_nr;
564 u16 rand_intv;
565 u16 dur;
566 u8 mode;
567 u8 bssid[6];
568 u8 sub[0];
569 } __packed;
571 struct element_meas_req_frame {
572 u8 op_class;
573 u8 ch_nr;
574 u16 rand_intv;
575 u16 dur;
576 u8 frame;
577 u8 mac[6];
578 u8 sub[0];
579 } __packed;
581 struct element_meas_req_sta {
582 u8 peer_mac[6];
583 u16 rand_intv;
584 u16 dur;
585 u8 group_id;
586 u8 sub[0];
587 } __packed;
589 struct element_meas_req_lci {
590 u8 loc_subj;
591 u8 latitude_req_res;
592 u8 longitude_req_res;
593 u8 altitude_req_res;
594 u8 sub[0];
595 } __packed;
597 struct element_meas_req_trans_str_cat {
598 u16 rand_intv;
599 u16 meas_dur;
600 u8 peer_sta_addr[6];
601 u8 traffic_id;
602 u8 bin_0_range;
603 u8 sub[0];
604 } __packed;
606 struct element_meas_req_mcast_diag {
607 u16 rand_intv;
608 u16 dur;
609 u8 group_mac_addr[6];
610 u8 mcast_triggered[0];
611 u8 sub[0];
612 } __packed;
614 struct element_meas_req_loc_civic {
615 u8 loc_subj;
616 u8 civic_loc;
617 u8 loc_srv_intv_unit;
618 u16 loc_srv_intv;
619 u8 sub[0];
620 } __packed;
622 struct element_meas_req_loc_id {
623 u8 loc_subj;
624 u8 loc_srv_intv_unit;
625 u16 loc_srv_intv;
626 u8 sub[0];
627 } __packed;
629 struct element_meas_req_pause {
630 u8 time;
631 u8 sub[0];
632 } __packed;
634 struct element_erp {
635 u8 len;
636 u8 param;
637 } __packed;
639 struct element_ext_supp_rates {
640 u8 len;
641 u8 rates[0];
642 } __packed;
644 struct element_vend_spec {
645 u8 len;
646 u8 oui[0];
647 u8 specific[0];
648 } __packed;
650 static int8_t len_neq_error(u8 len, u8 intended)
652 if(intended != len) {
653 tprintf("Length should be %u Bytes", intended);
654 return 1;
657 return 0;
660 static int8_t len_lt_error(u8 len, u8 intended)
662 if(len < intended) {
663 tprintf("Length should be greater %u Bytes", intended);
664 return 1;
667 return 0;
670 static float data_rates(u8 id)
672 /* XXX Why not (id / 2.f)? */
673 switch (id) {
674 case 2: return 1.0f;
675 case 3: return 1.5f;
676 case 4: return 2.0f;
677 case 5: return 2.5f;
678 case 6: return 3.0f;
679 case 9: return 4.5f;
680 case 11: return 5.5f;
681 case 12: return 6.0f;
682 case 18: return 9.0f;
683 case 22: return 11.0f;
684 case 24: return 12.0f;
685 case 27: return 13.5f;
686 case 36: return 18.0f;
687 case 44: return 22.0f;
688 case 48: return 24.0f;
689 case 54: return 27.0f;
690 case 66: return 33.0f;
691 case 72: return 36.0f;
692 case 96: return 48.0f;
693 case 108: return 54.0f;
696 return 0.f;
699 static int8_t inf_reserved(struct pkt_buff *pkt, u8 *id)
701 u8 i;
702 u8 *data;
703 struct element_reserved *reserved;
705 reserved = (struct element_reserved *) pkt_pull(pkt, sizeof(*reserved));
706 if (reserved == NULL)
707 return 0;
709 tprintf("Reserved (%u, Len (%u)): ", *id, reserved->len);
711 data = pkt_pull(pkt, reserved->len);
712 if (data == NULL)
713 return 0;
715 tprintf("Data 0x");
716 for (i = 0; i < reserved->len; i++)
717 tprintf("%.2x", data[i]);
719 return 1;
722 static int8_t inf_ssid(struct pkt_buff *pkt, u8 *id)
724 u8 i;
725 struct element_ssid *ssid;
726 char *ssid_name;
728 ssid = (struct element_ssid *) pkt_pull(pkt, sizeof(*ssid));
729 if (ssid == NULL)
730 return 0;
732 tprintf(" SSID (%u, Len (%u)): ", *id, ssid->len);
734 if ((ssid->len - sizeof(*ssid) + 1) > 0) {
735 ssid_name = (char *) pkt_pull(pkt, ssid->len);
736 if (ssid_name == NULL)
737 return 0;
739 for (i = 0; i < ssid->len; i++)
740 tprintf("%c",ssid_name[i]);
741 } else {
742 tprintf("Wildcard SSID");
745 return 1;
748 static int8_t inf_supp_rates(struct pkt_buff *pkt, u8 *id)
750 u8 i;
751 u8 *rates;
752 struct element_supp_rates *supp_rates;
754 supp_rates = (struct element_supp_rates *)
755 pkt_pull(pkt, sizeof(*supp_rates));
756 if (supp_rates == NULL)
757 return 0;
759 tprintf("Rates (%u, Len (%u)): ", *id, supp_rates->len);
760 if (len_lt_error(supp_rates->len, 1))
761 return 0;
763 if ((supp_rates->len - sizeof(*supp_rates) + 1) > 0) {
764 rates = pkt_pull(pkt, supp_rates->len);
765 if (rates == NULL)
766 return 0;
768 for (i = 0; i < supp_rates->len; i++)
769 tprintf("%g ", (rates[i] & 0x80) ?
770 ((rates[i] & 0x3f) * 0.5) :
771 data_rates(rates[i]));
772 return 1;
775 return 0;
778 static int8_t inf_fh_ps(struct pkt_buff *pkt, u8 *id)
780 struct element_fh_ps *fh_ps;
782 fh_ps = (struct element_fh_ps *) pkt_pull(pkt, sizeof(*fh_ps));
783 if (fh_ps == NULL)
784 return 0;
786 tprintf("FH Param Set (%u, Len(%u)): ", *id, fh_ps->len);
787 if (len_neq_error(fh_ps->len, 5))
788 return 0;
789 tprintf("Dwell Time: %fs, ", le16_to_cpu(fh_ps->dwell_time) * TU);
790 tprintf("HopSet: %u, ", fh_ps->hop_set);
791 tprintf("HopPattern: %u, ", fh_ps->hop_pattern);
792 tprintf("HopIndex: %u", fh_ps->hop_index);
794 return 1;
797 static int8_t inf_dsss_ps(struct pkt_buff *pkt, u8 *id)
799 struct element_dsss_ps *dsss_ps;
801 dsss_ps = (struct element_dsss_ps *) pkt_pull(pkt, sizeof(*dsss_ps));
802 if (dsss_ps == NULL)
803 return 0;
805 tprintf("DSSS Param Set (%u, Len(%u)): ", *id, dsss_ps->len);
806 if (len_neq_error(dsss_ps->len, 1))
807 return 0;
808 tprintf("Current Channel: %u", dsss_ps->curr_ch);
810 return 1;
813 static int8_t inf_cf_ps(struct pkt_buff *pkt, u8 *id)
815 struct element_cf_ps *cf_ps;
817 cf_ps = (struct element_cf_ps *) pkt_pull(pkt, sizeof(*cf_ps));
818 if (cf_ps == NULL)
819 return 0;
821 tprintf("CF Param Set (%u, Len(%u)): ", *id, cf_ps->len);
822 if (len_neq_error(cf_ps->len, 6))
823 return 0;
824 tprintf("CFP Count: %u, ", cf_ps->cfp_cnt);
825 tprintf("CFP Period: %u, ", cf_ps->cfp_period);
826 tprintf("CFP MaxDur: %fs, ", le16_to_cpu(cf_ps->cfp_max_dur) * TU);
827 tprintf("CFP DurRem: %fs", le16_to_cpu(cf_ps->cfp_dur_rem) * TU);
829 return 1;
832 static int8_t inf_tim(struct pkt_buff *pkt, u8 *id)
834 struct element_tim *tim;
836 tim = (struct element_tim *) pkt_pull(pkt, sizeof(*tim));
837 if (tim == NULL)
838 return 0;
840 tprintf("TIM (%u, Len(%u)): ", *id, tim->len);
841 if (len_lt_error(tim->len, 3))
842 return 0;
843 tprintf("DTIM Count: %u, ", tim->dtim_cnt);
844 tprintf("DTIM Period: %u, ", tim->dtim_period);
845 tprintf("Bitmap Control: %u, ", tim->bmp_cntrl);
846 if ((tim->len - sizeof(*tim) + 1) > 0) {
847 u8 *bmp = pkt_pull(pkt, (tim->len - sizeof(*tim) + 1));
848 if (bmp == NULL)
849 return 0;
851 tprintf("Partial Virtual Bitmap: 0x");
852 for(u8 i=0; i < (tim->len - sizeof(*tim) + 1); i++)
853 tprintf("%.2x ", bmp[i]);
856 return 1;
859 static int8_t inf_ibss_ps(struct pkt_buff *pkt, u8 *id)
861 struct element_ibss_ps *ibss_ps;
863 ibss_ps = (struct element_ibss_ps *) pkt_pull(pkt, sizeof(*ibss_ps));
864 if (ibss_ps == NULL)
865 return 0;
867 tprintf("IBSS Param Set (%u, Len(%u)): ", *id, ibss_ps->len);
868 if (len_neq_error(ibss_ps->len, 2))
869 return 0;
870 tprintf("ATIM Window: %fs", le16_to_cpu(ibss_ps->atim_win) * TU);
872 return 1;
875 static int8_t inf_country(struct pkt_buff *pkt, u8 *id)
877 u8 i;
878 u8 *pad;
879 struct element_country *country;
881 country = (struct element_country *) pkt_pull(pkt, sizeof(*country));
882 if (country == NULL)
883 return 0;
885 tprintf("Country (%u, Len(%u)): ", *id, country->len);
886 if (len_lt_error(country->len, 6))
887 return 0;
888 tprintf("Country String: %c%c%c", country->country_first,
889 country->country_sec, country->country_third);
891 for (i = 0; i < (country->len - 3); i += 3) {
892 struct element_country_tripled *country_tripled;
894 country_tripled = (struct element_country_tripled *)
895 pkt_pull(pkt, sizeof(*country_tripled));
896 if (country_tripled == NULL)
897 return 0;
899 if(country_tripled->frst_ch >= 201) {
900 tprintf("Oper Ext ID: %u, ", country_tripled->frst_ch);
901 tprintf("Operating Class: %u, ", country_tripled->nr_ch);
902 tprintf("Coverage Class: %u", country_tripled->max_trans);
903 } else {
904 tprintf("First Ch Nr: %u, ", country_tripled->frst_ch);
905 tprintf("Nr of Ch: %u, ", country_tripled->nr_ch);
906 tprintf("Max Transmit Pwr Lvl: %u", country_tripled->max_trans);
910 if(country->len % 2) {
911 pad = pkt_pull(pkt, 1);
912 if (pad == NULL)
913 return 0;
915 tprintf(", Pad: 0x%x", *pad);
918 return 1;
921 static int8_t inf_hop_pp(struct pkt_buff *pkt, u8 *id)
923 struct element_hop_pp *hop_pp;
925 hop_pp = (struct element_hop_pp *) pkt_pull(pkt, sizeof(*hop_pp));
926 if (hop_pp == NULL)
927 return 0;
929 tprintf("Hopping Pattern Param (%u, Len(%u)): ", *id, hop_pp->len);
930 if (len_neq_error(hop_pp->len, 2))
931 return 0;
932 tprintf("Nr of Ch: %u", hop_pp->nr_ch);
934 return 1;
937 static int8_t inf_hop_pt(struct pkt_buff *pkt, u8 *id)
939 int i;
940 u8 *rand_tabl;
941 struct element_hop_pt *hop_pt;
943 hop_pt = (struct element_hop_pt *) pkt_pull(pkt, sizeof(*hop_pt));
944 if (hop_pt == NULL)
945 return 0;
947 tprintf("Hopping Pattern Table (%u, Len(%u)): ", *id, hop_pt->len);
948 if (len_lt_error(hop_pt->len, 4))
949 return 0;
950 tprintf("Flag: %u, ", hop_pt->flag);
951 tprintf("Nr of Sets: %u, ", hop_pt->nr_sets);
952 tprintf("Modules: %u, ", hop_pt->modules);
953 tprintf("Offs: %u", hop_pt->offs);
955 if ((hop_pt->len - sizeof(*hop_pt) + 1) > 0) {
956 rand_tabl = pkt_pull(pkt, (hop_pt->len - sizeof(*hop_pt) + 1));
957 if (rand_tabl == NULL)
958 return 0;
960 tprintf(", Rand table: 0x");
961 for (i = 0; i < (hop_pt->len - sizeof(*hop_pt) + 1); i++)
962 tprintf("%.2x ", rand_tabl[i]);
965 return 1;
968 static int8_t inf_req(struct pkt_buff *pkt, u8 *id)
970 int i;
971 struct element_req *req;
972 u8 *req_ids;
974 req = (struct element_req *) pkt_pull(pkt, sizeof(*req));
975 if (req == NULL)
976 return 0;
978 tprintf("Request Element (%u, Len(%u)): ", *id, req->len);
979 if ((req->len - sizeof(*req) + 1) > 0) {
980 req_ids = pkt_pull(pkt, (req->len - sizeof(*req) + 1));
981 if (req_ids == NULL)
982 return 0;
984 tprintf(", Requested Element IDs: ");
985 for (i = 0; i < (req->len - sizeof(*req) + 1); i++)
986 tprintf("%u ", req_ids[i]);
989 return 1;
992 static int8_t inf_bss_load(struct pkt_buff *pkt, u8 *id)
994 struct element_bss_load *bss_load;
996 bss_load = (struct element_bss_load *) pkt_pull(pkt, sizeof(*bss_load));
997 if (bss_load == NULL)
998 return 0;
1000 tprintf("BSS Load element (%u, Len(%u)): ", *id, bss_load->len);
1001 if (len_neq_error(bss_load->len, 5))
1002 return 0;
1003 tprintf("Station Count: %u, ", le16_to_cpu(bss_load->station_cnt));
1004 tprintf("Channel Utilization: %u, ", bss_load->ch_util);
1005 tprintf("Available Admission Capacity: %uus",
1006 bss_load->avlb_adm_cap * 32);
1008 return 1;
1011 static int8_t inf_edca_ps(struct pkt_buff *pkt, u8 *id)
1013 u32 ac_be, ac_bk, ac_vi, ac_vo;
1014 struct element_edca_ps *edca_ps;
1016 edca_ps = (struct element_edca_ps *) pkt_pull(pkt, sizeof(*edca_ps));
1017 if (edca_ps == NULL)
1018 return 0;
1020 ac_be = le32_to_cpu(edca_ps->ac_be);
1021 ac_bk = le32_to_cpu(edca_ps->ac_bk);
1022 ac_vi = le32_to_cpu(edca_ps->ac_vi);
1023 ac_vo = le32_to_cpu(edca_ps->ac_vo);
1025 tprintf("EDCA Param Set (%u, Len(%u)): ", *id, edca_ps->len);
1026 if (len_neq_error(edca_ps->len, 18))
1027 return 0;
1028 tprintf("QoS Info: 0x%x (-> EDCA Param Set Update Count (%u),"
1029 "Q-Ack (%u), Queue Re (%u), TXOP Req(%u), Res(%u)), ",
1030 edca_ps->qos_inf, edca_ps->qos_inf >> 4,
1031 (edca_ps->qos_inf >> 3) & 1, (edca_ps->qos_inf >> 2) & 1,
1032 (edca_ps->qos_inf >> 1) & 1, edca_ps->qos_inf & 1);
1033 tprintf("Reserved: 0x%x, ", edca_ps->res);
1034 tprintf("AC_BE Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1035 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_be,
1036 ac_be >> 28, (ac_be >> 27) & 1, (ac_be >> 25) & 3,
1037 (ac_be >> 24) & 1, (ac_be >> 20) & 15, (ac_be >> 16) & 15,
1038 bswap_16(ac_be & 0xFFFF) * 32);
1039 tprintf("AC_BK Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1040 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_bk,
1041 ac_bk >> 28, (ac_bk >> 27) & 1, (ac_bk >> 25) & 3,
1042 (ac_bk >> 24) & 1, (ac_bk >> 20) & 15, (ac_bk >> 16) & 15,
1043 bswap_16(ac_bk & 0xFFFF) * 32);
1044 tprintf("AC_VI Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1045 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_vi,
1046 ac_vi >> 28, (ac_vi >> 27) & 1, (ac_vi >> 25) & 3,
1047 (ac_vi >> 24) & 1, (ac_vi >> 20) & 15, (ac_vi >> 16) & 15,
1048 bswap_16(ac_vi & 0xFFFF) * 32);
1049 tprintf("AC_VO Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
1050 "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)", ac_vo,
1051 ac_vo >> 28, (ac_vo >> 27) & 1, (ac_vo >> 25) & 3,
1052 (ac_vo >> 24) & 1, (ac_vo >> 20) & 15, (ac_vo >> 16) & 15,
1053 bswap_16(ac_vo & 0xFFFF) * 32);
1055 return 1;
1058 static int8_t inf_tspec(struct pkt_buff *pkt, u8 *id)
1060 u16 nom_msdu_size, surplus_bandw_allow;
1061 struct element_tspec *tspec;
1063 tspec = (struct element_tspec *) pkt_pull(pkt, sizeof(*tspec));
1064 if (tspec == NULL)
1065 return 0;
1067 nom_msdu_size = le16_to_cpu(tspec->nom_msdu_size);
1068 surplus_bandw_allow = le16_to_cpu(tspec->surplus_bandw_allow);
1070 tprintf("TSPEC (%u, Len(%u)): ", *id, tspec->len);
1071 if (len_neq_error(tspec->len, 55))
1072 return 0;
1073 tprintf("Traffic Type: %u, ", tspec->traffic_type);
1074 tprintf("TSID: %u, ", tspec->tsid);
1075 tprintf("Direction: %u, ", tspec->direction);
1076 tprintf("Access Policy: %u, ", tspec->access_policy);
1077 tprintf("Aggregation: %u, ", tspec->aggr);
1078 tprintf("User Priority: %u, ", tspec->user_prior);
1079 tprintf("TSinfo Ack Policy: %u, ", tspec->tsinfo_ack_pol);
1080 tprintf("Schedule: %u, ", tspec->schedule);
1081 tprintf("Reserved: 0x%x, ", tspec->res);
1082 tprintf("Nominal MSDU Size: %uB (Fixed (%u)), ",
1083 nom_msdu_size >> 1, nom_msdu_size & 1);
1084 tprintf("Maximum MSDU Size: %uB, ", le16_to_cpu(tspec->max_msdu_size));
1085 tprintf("Minimum Service Interval: %uus, ",
1086 le32_to_cpu(tspec->min_srv_intv));
1087 tprintf("Maximum Service Interval: %uus, ",
1088 le32_to_cpu(tspec->max_srv_intv));
1089 tprintf("Inactivity Interval: %uus, ",
1090 le32_to_cpu(tspec->inactive_intv));
1091 tprintf("Suspension Interval: %uus, ", le32_to_cpu(tspec->susp_intv));
1092 tprintf("Service Start Time: %uus, ",
1093 le32_to_cpu(tspec->srv_start_time));
1094 tprintf("Minimum Data Rate: %ub/s, ",le32_to_cpu(tspec->min_data_rate));
1095 tprintf("Mean Data Rate: %ub/s, ", le32_to_cpu(tspec->mean_data_rate));
1096 tprintf("Peak Data Rate: %ub/s, ",le32_to_cpu(tspec->peak_data_rate));
1097 tprintf("Burst Size: %uB, ", le32_to_cpu(tspec->burst_size));
1098 tprintf("Delay Bound: %uus, ", le32_to_cpu(tspec->delay_bound));
1099 tprintf("Minimum PHY Rate: %ub/s, ", le32_to_cpu(tspec->min_phy_rate));
1100 tprintf("Surplus Bandwidth: %u.%u, ", surplus_bandw_allow >> 13,
1101 surplus_bandw_allow & 0x1FFF);
1102 tprintf("Medium Time: %uus", le16_to_cpu(tspec->med_time) * 32);
1104 return 1;
1107 static const char *class_type(u8 type)
1109 switch (type) {
1110 case 0: return "Ethernet parameters";
1111 case 1: return "TCP/UDP IP parameters";
1112 case 2: return "IEEE 802.1Q parameters";
1113 case 3: return "Filter Offset parameters";
1114 case 4: return "IP and higher layer parameters";
1115 case 5: return "IEEE 802.1D/Q parameters";
1116 default: return "Reserved";
1120 static int8_t inf_tclas(struct pkt_buff *pkt, u8 *id)
1122 struct element_tclas *tclas;
1123 struct element_tclas_frm_class *frm_class;
1125 tclas = (struct element_tclas *) pkt_pull(pkt, sizeof(*tclas));
1126 if (tclas == NULL)
1127 return 0;
1129 frm_class = (struct element_tclas_frm_class *)
1130 pkt_pull(pkt, sizeof(*frm_class));
1131 if (frm_class == NULL)
1132 return 0;
1134 tprintf("TCLAS (%u, Len(%u)): ", *id, tclas->len);
1135 if (len_lt_error(tclas->len, 3))
1136 return 0;
1137 tprintf("User Priority: %u, ", tclas->user_priority);
1138 tprintf("Classifier Type: %s (%u), ", class_type(frm_class->type),
1139 frm_class->type);
1140 tprintf("Classifier Mask: 0x%x, ", frm_class->mask);
1142 if(frm_class->type == 0) {
1143 struct element_tclas_type0 *type0;
1145 type0 = (struct element_tclas_type0 *)
1146 pkt_pull(pkt, sizeof(*type0));
1147 if (type0 == NULL)
1148 return 0;
1150 /* I think little endian, like the rest */
1151 tprintf("Src Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
1152 type0->sa[5], type0->sa[4], type0->sa[3],
1153 type0->sa[2], type0->sa[1], type0->sa[0]);
1154 tprintf("Dst Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
1155 type0->da[5], type0->da[4], type0->da[3],
1156 type0->da[2], type0->da[1], type0->da[0]);
1157 tprintf("Type: 0x%x", le16_to_cpu(type0->type));
1159 else if(frm_class->type == 1) {
1160 struct element_tclas_type1 *type1;
1162 type1 = (struct element_tclas_type1 *)
1163 pkt_pull(pkt, sizeof(*type1));
1164 if (type1 == NULL)
1165 return 0;
1167 tprintf("Version: %u, ", type1->version);
1168 /* big endian format follows */
1169 if(type1->version == 4) {
1170 struct element_tclas_type1_ip4 *type1_ip4;
1171 char src_ip[INET_ADDRSTRLEN];
1172 char dst_ip[INET_ADDRSTRLEN];
1174 type1_ip4 = (struct element_tclas_type1_ip4 *)
1175 pkt_pull(pkt, sizeof(*type1_ip4));
1176 if (type1_ip4 == NULL)
1177 return 0;
1179 inet_ntop(AF_INET, &type1_ip4->sa, src_ip, sizeof(src_ip));
1180 inet_ntop(AF_INET, &type1_ip4->da, dst_ip, sizeof(dst_ip));
1182 tprintf("Src IP: %s, ", src_ip);
1183 tprintf("Dst IP: %s, ", dst_ip);
1184 tprintf("Src Port: %u, ", ntohs(type1_ip4->sp));
1185 tprintf("Dst Port: %u, ", ntohs(type1_ip4->dp));
1186 tprintf("DSCP: 0x%x, ", type1_ip4->dscp);
1187 tprintf("Proto: %u, ", type1_ip4->proto);
1188 tprintf("Res: 0x%x", type1_ip4->reserved);
1190 else if(type1->version == 6) {
1191 struct element_tclas_type1_ip6 *type1_ip6;
1192 char src_ip[INET6_ADDRSTRLEN];
1193 char dst_ip[INET6_ADDRSTRLEN];
1195 type1_ip6 = (struct element_tclas_type1_ip6 *)
1196 pkt_pull(pkt, sizeof(*type1_ip6));
1197 if (type1_ip6 == NULL)
1198 return 0;
1200 inet_ntop(AF_INET6, &type1_ip6->sa,
1201 src_ip, sizeof(src_ip));
1202 inet_ntop(AF_INET6, &type1_ip6->da,
1203 dst_ip, sizeof(dst_ip));
1205 tprintf("Src IP: %s, ", src_ip);
1206 tprintf("Dst IP: %s, ", dst_ip);
1207 tprintf("Src Port: %u, ", ntohs(type1_ip6->sp));
1208 tprintf("Dst Port: %u, ", ntohs(type1_ip6->dp));
1209 tprintf("Flow Label: 0x%x%x%x", type1_ip6->flow_label1,
1210 type1_ip6->flow_label2, type1_ip6->flow_label3);
1212 else {
1213 tprintf("Version (%u) not supported", type1->version);
1214 return 0;
1218 else if(frm_class->type == 2) {
1219 struct element_tclas_type2 *type2;
1221 type2 = (struct element_tclas_type2 *)
1222 pkt_pull(pkt, sizeof(*type2));
1223 if (type2 == NULL)
1224 return 0;
1226 tprintf("802.1Q VLAN TCI: 0x%x", ntohs(type2->vlan_tci));
1228 else if(frm_class->type == 3) {
1229 struct element_tclas_type3 *type3;
1230 u8 len, i;
1231 u8 *val;
1233 type3 = (struct element_tclas_type3 *)
1234 pkt_pull(pkt, sizeof(*type3));
1235 if (type3 == NULL)
1236 return 0;
1238 len = (tclas->len - 5) / 2;
1240 tprintf("Filter Offset: %u, ", type3->offs);
1242 if((len & 1) || (len_lt_error(tclas->len, 5))) {
1243 tprintf("Length of TCLAS (%u) not correct", tclas->len);
1244 return 0;
1246 else {
1247 val = pkt_pull(pkt, len);
1248 if (val == NULL)
1249 return 0;
1251 tprintf("Filter Value: 0x");
1252 for (i = 0; i < len / 2; i++)
1253 tprintf("%x ", val[i]);
1254 tprintf(", ");
1255 tprintf("Filter Mask: 0x");
1256 for (i = len / 2; i < len; i++)
1257 tprintf("%x ", val[i]);
1261 else if(frm_class->type == 4) {
1262 struct element_tclas_type4 *type4;
1264 type4 = (struct element_tclas_type4 *)
1265 pkt_pull(pkt, sizeof(*type4));
1266 if (type4 == NULL)
1267 return 0;
1269 tprintf("Version: %u, ", type4->version);
1270 /* big endian format follows */
1271 if(type4->version == 4) {
1272 struct element_tclas_type4_ip4 *type4_ip4;
1273 char src_ip[INET_ADDRSTRLEN];
1274 char dst_ip[INET_ADDRSTRLEN];
1276 type4_ip4 = (struct element_tclas_type4_ip4 *)
1277 pkt_pull(pkt, sizeof(*type4_ip4));
1278 if (type4_ip4 == NULL)
1279 return 0;
1281 inet_ntop(AF_INET, &type4_ip4->sa, src_ip, sizeof(src_ip));
1282 inet_ntop(AF_INET, &type4_ip4->da, 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(type4_ip4->sp));
1287 tprintf("Dst Port: %u, ", ntohs(type4_ip4->dp));
1288 tprintf("DSCP: 0x%x, ", type4_ip4->dscp);
1289 tprintf("Proto: %u, ", type4_ip4->proto);
1290 tprintf("Res: 0x%x", type4_ip4->reserved);
1292 else if(type4->version == 6) {
1293 struct element_tclas_type4_ip6 *type4_ip6;
1294 char src_ip[INET6_ADDRSTRLEN];
1295 char dst_ip[INET6_ADDRSTRLEN];
1297 type4_ip6 = (struct element_tclas_type4_ip6 *)
1298 pkt_pull(pkt, sizeof(*type4_ip6));
1299 if (type4_ip6 == NULL)
1300 return 0;
1302 inet_ntop(AF_INET6, &type4_ip6->sa,
1303 src_ip, sizeof(src_ip));
1304 inet_ntop(AF_INET6, &type4_ip6->da,
1305 dst_ip, sizeof(dst_ip));
1307 tprintf("Src IP: %s, ", src_ip);
1308 tprintf("Dst IP: %s, ", dst_ip);
1309 tprintf("Src Port: %u, ", ntohs(type4_ip6->sp));
1310 tprintf("Dst Port: %u, ", ntohs(type4_ip6->dp));
1311 tprintf("DSCP: 0x%x, ", type4_ip6->dscp);
1312 tprintf("Nxt Hdr: %u, ", type4_ip6->nxt_hdr);
1313 tprintf("Flow Label: 0x%x%x%x", type4_ip6->flow_label1,
1314 type4_ip6->flow_label2, type4_ip6->flow_label3);
1316 else {
1317 tprintf("Version (%u) not supported", type4->version);
1318 return 0;
1321 else if(frm_class->type == 5) {
1322 struct element_tclas_type5 *type5;
1324 type5 = (struct element_tclas_type5 *)
1325 pkt_pull(pkt, sizeof(*type5));
1326 if (type5 == NULL)
1327 return 0;
1329 tprintf("802.1Q PCP: 0x%x, ", type5->pcp);
1330 tprintf("802.1Q CFI: 0x%x, ", type5->cfi);
1331 tprintf("802.1Q VID: 0x%x", type5->vid);
1333 else {
1334 tprintf("Classifier Type (%u) not supported", frm_class->type);
1335 return 0;
1338 return 1;
1341 static int8_t inf_sched(struct pkt_buff *pkt, u8 *id)
1343 struct element_schedule *schedule;
1344 u16 info;
1346 schedule = (struct element_schedule *) pkt_pull(pkt, sizeof(*schedule));
1347 if (schedule == NULL)
1348 return 0;
1350 info = le16_to_cpu(schedule->inf);
1352 tprintf("Schedule (%u, Len(%u)): ", *id, schedule->len);
1353 if (len_neq_error(schedule->len, 12))
1354 return 0;
1356 tprintf("Aggregation: %u, ", info >> 15);
1357 tprintf("TSID: %u, ", (info >> 11) & 0xF);
1358 tprintf("Direction: %u, ", (info >> 9) & 0x3);
1359 tprintf("Res: %u, ", info & 0x1FF);
1360 tprintf("Serv Start Time: %uus, ", le32_to_cpu(schedule->start));
1361 tprintf("Serv Interval: %uus, ", le32_to_cpu(schedule->serv_intv));
1362 tprintf("Spec Interval: %fs", le32_to_cpu(schedule->spec_intv) * TU);
1364 return 1;
1367 static int8_t inf_chall_txt(struct pkt_buff *pkt, u8 *id)
1369 struct element_chall_txt *chall_txt;
1370 u8 i;
1371 u8 *txt;
1373 chall_txt = (struct element_chall_txt *)
1374 pkt_pull(pkt, sizeof(*chall_txt));
1375 if (chall_txt == NULL)
1376 return 0;
1378 tprintf("Challenge Text (%u, Len(%u)): ", *id, chall_txt->len);
1379 if ((chall_txt->len - sizeof(*chall_txt) + 1) > 0) {
1380 txt = pkt_pull(pkt, (chall_txt->len - sizeof(*chall_txt) + 1));
1381 if (txt == NULL)
1382 return 0;
1384 tprintf("0x");
1385 for (i = 0; i < (chall_txt->len - sizeof(*chall_txt) + 1); i++)
1386 tprintf("%x ", txt[i]);
1389 return 1;
1392 static int8_t inf_pwr_constr(struct pkt_buff *pkt, u8 *id)
1394 struct element_pwr_constr *pwr_constr;
1396 pwr_constr = (struct element_pwr_constr *) pkt_pull(pkt, sizeof(*pwr_constr));
1397 if (pwr_constr == NULL)
1398 return 0;
1400 tprintf("Power Constraint (%u, Len(%u)): ", *id, pwr_constr->len);
1401 if (len_neq_error(pwr_constr->len, 1))
1402 return 0;
1404 tprintf("Local Power Constraint: %udB", pwr_constr->local_pwr_constr);
1406 return 1;
1409 static int8_t inf_pwr_cap(struct pkt_buff *pkt, u8 *id)
1411 struct element_pwr_cap *pwr_cap;
1413 pwr_cap = (struct element_pwr_cap *) pkt_pull(pkt, sizeof(*pwr_cap));
1414 if (pwr_cap == NULL)
1415 return 0;
1417 tprintf("Power Capability (%u, Len(%u)): ", *id, pwr_cap->len);
1418 if (len_neq_error(pwr_cap->len, 2))
1419 return 0;
1421 tprintf("Min. Transm. Pwr Cap.: %ddBm, ", (int8_t)pwr_cap->min_pwr_cap);
1422 tprintf("Max. Transm. Pwr Cap.: %ddBm", (int8_t)pwr_cap->max_pwr_cap);
1424 return 1;
1427 static int8_t inf_tpc_req(struct pkt_buff *pkt, u8 *id)
1429 struct element_tpc_req *tpc_req;
1431 tpc_req = (struct element_tpc_req *) pkt_pull(pkt, sizeof(*tpc_req));
1432 if (tpc_req == NULL)
1433 return 0;
1435 tprintf("TPC Request (%u, Len(%u))", *id, tpc_req->len);
1436 if (len_neq_error(tpc_req->len, 0))
1437 return 0;
1439 return 1;
1442 static int8_t inf_tpc_rep(struct pkt_buff *pkt, u8 *id)
1444 struct element_tpc_rep *tpc_rep;
1446 tpc_rep = (struct element_tpc_rep *) pkt_pull(pkt, sizeof(*tpc_rep));
1447 if (tpc_rep == NULL)
1448 return 0;
1450 tprintf("TPC Report (%u, Len(%u)): ", *id, tpc_rep->len);
1451 if (len_neq_error(tpc_rep->len, 2))
1452 return 0;
1454 tprintf("Transmit Power: %udBm, ", (int8_t)tpc_rep->trans_pwr);
1455 tprintf("Link Margin: %udB", (int8_t)tpc_rep->trans_pwr);
1457 return 1;
1460 static int8_t inf_supp_ch(struct pkt_buff *pkt, u8 *id)
1462 struct element_supp_ch *supp_ch;
1463 u8 i;
1465 supp_ch = (struct element_supp_ch *) pkt_pull(pkt, sizeof(*supp_ch));
1466 if (supp_ch == NULL)
1467 return 0;
1469 tprintf("Supp Channels (%u, Len(%u)): ", *id, supp_ch->len);
1470 if (len_lt_error(supp_ch->len, 2))
1471 return 0;
1473 if(supp_ch->len & 1) {
1474 tprintf("Length should be modulo 2");
1475 return 0;
1478 for (i = 0; i < supp_ch->len; i += 2) {
1479 struct element_supp_ch_tuple *supp_ch_tuple;
1481 supp_ch_tuple = (struct element_supp_ch_tuple *)
1482 pkt_pull(pkt, sizeof(*supp_ch_tuple));
1483 if (supp_ch_tuple == NULL)
1484 return 0;
1486 tprintf("First Channel Nr: %u, ", supp_ch_tuple->first_ch_nr);
1487 tprintf("Nr of Channels: %u, ", supp_ch_tuple->nr_ch);
1490 return 1;
1493 static int8_t inf_ch_sw_ann(struct pkt_buff *pkt, u8 *id)
1495 struct element_ch_sw_ann *ch_sw_ann;
1497 ch_sw_ann = (struct element_ch_sw_ann *)
1498 pkt_pull(pkt, sizeof(*ch_sw_ann));
1499 if (ch_sw_ann == NULL)
1500 return 0;
1502 tprintf("Channel Switch Announc (%u, Len(%u)): ", *id, ch_sw_ann->len);
1503 if (len_neq_error(ch_sw_ann->len, 3))
1504 return 0;
1506 tprintf("Switch Mode: %u, ", ch_sw_ann->switch_mode);
1507 tprintf("New Nr: %u, ", ch_sw_ann->new_nr);
1508 tprintf("Switch Count: %u", ch_sw_ann->switch_cnt);
1510 return 1;
1513 static const char *meas_type(u8 type)
1515 switch (type) {
1516 case 0: return "Basic";
1517 case 1: return "Clear Channel assesment (CCA)";
1518 case 2: return "Receive power indication (RPI) histogram";
1519 case 3: return "Channel load";
1520 case 4: return "Noise histogram";
1521 case 5: return "Beacon";
1522 case 6: return "Frame";
1523 case 7: return "STA statistics";
1524 case 8: return "LCI";
1525 case 9: return "Transmit stream/category measurement";
1526 case 10: return "Multicast diagnostics";
1527 case 11: return "Location Civic";
1528 case 12: return "Location Identifier";
1529 case 13 ... 255: return "Reserved";
1533 static int8_t inf_meas_req(struct pkt_buff *pkt, u8 *id)
1535 struct element_meas_req *meas_req;
1537 meas_req = (struct element_meas_req *) pkt_pull(pkt, sizeof(*meas_req));
1538 if (meas_req == NULL)
1539 return 0;
1541 tprintf("Measurement Req (%u, Len(%u)): ", *id, meas_req->len);
1542 if (len_lt_error(meas_req->len, 3))
1543 return 0;
1545 tprintf("Token: %u, ", meas_req->token);
1546 tprintf("Req Mode: 0x%x (Parallel (%u), Enable(%u), Request(%u), "
1547 "Report(%u), Dur Mand(%u)), ", meas_req->req_mode,
1548 meas_req->req_mode >> 7, (meas_req->req_mode >> 6) & 0x1,
1549 (meas_req->req_mode >> 5) & 0x1, (meas_req->req_mode >> 4) & 0x1,
1550 (meas_req->req_mode >> 3) & 0x1);
1551 tprintf("Type: %s (%u), ", meas_type(meas_req->type), meas_req->type);
1553 if(meas_req->len > 3) {
1554 if(meas_req->type == 0) {
1555 struct element_meas_req_basic *basic;
1557 basic = (struct element_meas_req_basic *)
1558 pkt_pull(pkt, sizeof(*basic));
1559 if (basic == NULL)
1560 return 0;
1562 else if(meas_req->type == 1) {
1563 struct element_meas_req_cca *cca;
1565 cca = (struct element_meas_req_cca *)
1566 pkt_pull(pkt, sizeof(*cca));
1567 if (cca == NULL)
1568 return 0;
1570 else if(meas_req->type == 2) {
1571 struct element_meas_req_rpi *rpi;
1573 rpi = (struct element_meas_req_rpi *)
1574 pkt_pull(pkt, sizeof(*rpi));
1575 if (rpi == NULL)
1576 return 0;
1578 else if(meas_req->type == 3) {
1579 struct element_meas_req_ch_load *ch_load;
1581 ch_load = (struct element_meas_req_ch_load *)
1582 pkt_pull(pkt, sizeof(*ch_load));
1583 if (ch_load == NULL)
1584 return 0;
1586 else if(meas_req->type == 4) {
1587 struct element_meas_req_noise *noise;
1589 noise = (struct element_meas_req_noise *)
1590 pkt_pull(pkt, sizeof(*noise));
1591 if (noise == NULL)
1592 return 0;
1594 else if(meas_req->type == 5) {
1595 struct element_meas_req_beacon *beacon;
1597 beacon = (struct element_meas_req_beacon *)
1598 pkt_pull(pkt, sizeof(*beacon));
1599 if (beacon == NULL)
1600 return 0;
1602 else if(meas_req->type == 6) {
1603 struct element_meas_req_frame *frame;
1605 frame = (struct element_meas_req_frame *)
1606 pkt_pull(pkt, sizeof(*frame));
1607 if (frame == NULL)
1608 return 0;
1610 else if(meas_req->type == 7) {
1611 struct element_meas_req_sta *sta;
1613 sta = (struct element_meas_req_sta *)
1614 pkt_pull(pkt, sizeof(*sta));
1615 if (sta == NULL)
1616 return 0;
1618 else if(meas_req->type == 8) {
1619 struct element_meas_req_lci *lci;
1621 lci = (struct element_meas_req_lci *)
1622 pkt_pull(pkt, sizeof(*lci));
1623 if (lci == NULL)
1624 return 0;
1626 else if(meas_req->type == 9) {
1627 struct element_meas_req_trans_str_cat *trans;
1629 trans = (struct element_meas_req_trans_str_cat *)
1630 pkt_pull(pkt, sizeof(*trans));
1631 if (trans == NULL)
1632 return 0;
1634 else if(meas_req->type == 10) {
1635 struct element_meas_req_mcast_diag *mcast;
1637 mcast = (struct element_meas_req_mcast_diag *)
1638 pkt_pull(pkt, sizeof(*mcast));
1639 if (mcast == NULL)
1640 return 0;
1642 else if(meas_req->type == 11) {
1643 struct element_meas_req_loc_civic *civic;
1645 civic = (struct element_meas_req_loc_civic *)
1646 pkt_pull(pkt, sizeof(*civic));
1647 if (civic == NULL)
1648 return 0;
1650 else if(meas_req->type == 12) {
1651 struct element_meas_req_loc_id *id;
1653 id = (struct element_meas_req_loc_id *)
1654 pkt_pull(pkt, sizeof(*id));
1655 if (id == NULL)
1656 return 0;
1658 else if(meas_req->type == 255) {
1659 struct element_meas_req_pause *pause;
1661 pause = (struct element_meas_req_pause *)
1662 pkt_pull(pkt, sizeof(*pause));
1663 if (pause == NULL)
1664 return 0;
1666 else {
1667 tprintf("Length field indicates data,"
1668 " but could not interpreted");
1669 return 0;
1673 return 0;
1676 static int8_t inf_meas_rep(struct pkt_buff *pkt, u8 *id)
1678 return 0;
1681 static int8_t inf_quiet(struct pkt_buff *pkt, u8 *id)
1683 return 0;
1686 static int8_t inf_ibss_dfs(struct pkt_buff *pkt, u8 *id)
1688 return 0;
1691 static int8_t inf_erp(struct pkt_buff *pkt, u8 *id)
1693 struct element_erp *erp;
1695 erp = (struct element_erp *) pkt_pull(pkt, sizeof(*erp));
1696 if (erp == NULL)
1697 return 0;
1699 tprintf("ERP (%u, Len(%u)): ", *id, erp->len);
1700 if (len_neq_error(erp->len, 1))
1701 return 0;
1702 tprintf("Non ERP Present (%u), ", erp->param & 0x1);
1703 tprintf("Use Protection (%u), ", (erp->param >> 1) & 0x1);
1704 tprintf("Barker Preamble Mode (%u), ", (erp->param >> 2) & 0x1);
1705 tprintf("Reserved (0x%.5x)", erp->param >> 3);
1707 return 1;
1710 static int8_t inf_ts_del(struct pkt_buff *pkt, u8 *id)
1712 return 0;
1715 static int8_t inf_tclas_proc(struct pkt_buff *pkt, u8 *id)
1717 return 0;
1720 static int8_t inf_ht_cap(struct pkt_buff *pkt, u8 *id)
1722 return 0;
1725 static int8_t inf_qos_cap(struct pkt_buff *pkt, u8 *id)
1727 return 0;
1730 static int8_t inf_rsn(struct pkt_buff *pkt, u8 *id)
1732 return 0;
1735 static int8_t inf_ext_supp_rates(struct pkt_buff *pkt, u8 *id)
1737 u8 i;
1738 u8 *rates;
1739 struct element_ext_supp_rates *ext_supp_rates;
1741 ext_supp_rates = (struct element_ext_supp_rates *)
1742 pkt_pull(pkt, sizeof(*ext_supp_rates));
1743 if (ext_supp_rates == NULL)
1744 return 0;
1746 tprintf("Ext Support Rates (%u, Len(%u)): ", *id, ext_supp_rates->len);
1748 if ((ext_supp_rates->len - sizeof(*ext_supp_rates) + 1) > 0) {
1749 rates = pkt_pull(pkt, ext_supp_rates->len);
1750 if (rates == NULL)
1751 return 0;
1753 for (i = 0; i < ext_supp_rates->len; i++)
1754 tprintf("%g ", (rates[i] & 0x80) ?
1755 ((rates[i] & 0x3f) * 0.5) :
1756 data_rates(rates[i]));
1757 return 1;
1760 return 0;
1763 static int8_t inf_ap_ch_exp(struct pkt_buff *pkt, u8 *id) {
1764 return 0;
1767 static int8_t inf_neighb_rep(struct pkt_buff *pkt, u8 *id) {
1768 return 0;
1771 static int8_t inf_rcpi(struct pkt_buff *pkt, u8 *id) {
1772 return 0;
1775 static int8_t inf_mde(struct pkt_buff *pkt, u8 *id) {
1776 return 0;
1779 static int8_t inf_fte(struct pkt_buff *pkt, u8 *id) {
1780 return 0;
1783 static int8_t inf_time_out_int(struct pkt_buff *pkt, u8 *id) {
1784 return 0;
1787 static int8_t inf_rde(struct pkt_buff *pkt, u8 *id) {
1788 return 0;
1791 static int8_t inf_dse_reg_loc(struct pkt_buff *pkt, u8 *id) {
1792 return 0;
1795 static int8_t inf_supp_op_class(struct pkt_buff *pkt, u8 *id) {
1796 return 0;
1799 static int8_t inf_ext_ch_sw_ann(struct pkt_buff *pkt, u8 *id) {
1800 return 0;
1803 static int8_t inf_ht_op(struct pkt_buff *pkt, u8 *id) {
1804 return 0;
1807 static int8_t inf_sec_ch_offs(struct pkt_buff *pkt, u8 *id) {
1808 return 0;
1811 static int8_t inf_bss_avg_acc_del(struct pkt_buff *pkt, u8 *id) {
1812 return 0;
1815 static int8_t inf_ant(struct pkt_buff *pkt, u8 *id) {
1816 return 0;
1819 static int8_t inf_rsni(struct pkt_buff *pkt, u8 *id) {
1820 return 0;
1823 static int8_t inf_meas_pilot_trans(struct pkt_buff *pkt, u8 *id) {
1824 return 0;
1827 static int8_t inf_bss_avl_adm_cap(struct pkt_buff *pkt, u8 *id) {
1828 return 0;
1831 static int8_t inf_bss_ac_acc_del(struct pkt_buff *pkt, u8 *id) {
1832 return 0;
1835 static int8_t inf_time_adv(struct pkt_buff *pkt, u8 *id) {
1836 return 0;
1839 static int8_t inf_rm_ena_cap(struct pkt_buff *pkt, u8 *id) {
1840 return 0;
1843 static int8_t inf_mult_bssid(struct pkt_buff *pkt, u8 *id) {
1844 return 0;
1847 static int8_t inf_20_40_bss_coex(struct pkt_buff *pkt, u8 *id) {
1848 return 0;
1851 static int8_t inf_20_40_bss_int_ch_rep(struct pkt_buff *pkt, u8 *id) {
1852 return 0;
1855 static int8_t inf_overl_bss_scan_para(struct pkt_buff *pkt, u8 *id) {
1856 return 0;
1859 static int8_t inf_ric_desc(struct pkt_buff *pkt, u8 *id) {
1860 return 0;
1863 static int8_t inf_mgmt_mic(struct pkt_buff *pkt, u8 *id) {
1864 return 0;
1867 static int8_t inf_ev_req(struct pkt_buff *pkt, u8 *id) {
1868 return 0;
1871 static int8_t inf_ev_rep(struct pkt_buff *pkt, u8 *id) {
1872 return 0;
1875 static int8_t inf_diagn_req(struct pkt_buff *pkt, u8 *id) {
1876 return 0;
1879 static int8_t inf_diagn_rep(struct pkt_buff *pkt, u8 *id) {
1880 return 0;
1883 static int8_t inf_loc_para(struct pkt_buff *pkt, u8 *id) {
1884 return 0;
1887 static int8_t inf_nontr_bssid_cap(struct pkt_buff *pkt, u8 *id) {
1888 return 0;
1891 static int8_t inf_ssid_list(struct pkt_buff *pkt, u8 *id) {
1892 return 0;
1895 static int8_t inf_mult_bssid_index(struct pkt_buff *pkt, u8 *id) {
1896 return 0;
1899 static int8_t inf_fms_desc(struct pkt_buff *pkt, u8 *id) {
1900 return 0;
1903 static int8_t inf_fms_req(struct pkt_buff *pkt, u8 *id) {
1904 return 0;
1907 static int8_t inf_fms_resp(struct pkt_buff *pkt, u8 *id) {
1908 return 0;
1911 static int8_t inf_qos_tfc_cap(struct pkt_buff *pkt, u8 *id) {
1912 return 0;
1915 static int8_t inf_bss_max_idle_per(struct pkt_buff *pkt, u8 *id) {
1916 return 0;
1919 static int8_t inf_tfs_req(struct pkt_buff *pkt, u8 *id) {
1920 return 0;
1923 static int8_t inf_tfs_resp(struct pkt_buff *pkt, u8 *id) {
1924 return 0;
1927 static int8_t inf_wnm_sleep_mod(struct pkt_buff *pkt, u8 *id) {
1928 return 0;
1931 static int8_t inf_tim_bcst_req(struct pkt_buff *pkt, u8 *id) {
1932 return 0;
1935 static int8_t inf_tim_bcst_resp(struct pkt_buff *pkt, u8 *id) {
1936 return 0;
1939 static int8_t inf_coll_interf_rep(struct pkt_buff *pkt, u8 *id) {
1940 return 0;
1943 static int8_t inf_ch_usage(struct pkt_buff *pkt, u8 *id) {
1944 return 0;
1947 static int8_t inf_time_zone(struct pkt_buff *pkt, u8 *id) {
1948 return 0;
1951 static int8_t inf_dms_req(struct pkt_buff *pkt, u8 *id) {
1952 return 0;
1955 static int8_t inf_dms_resp(struct pkt_buff *pkt, u8 *id) {
1956 return 0;
1959 static int8_t inf_link_id(struct pkt_buff *pkt, u8 *id) {
1960 return 0;
1963 static int8_t inf_wakeup_sched(struct pkt_buff *pkt, u8 *id) {
1964 return 0;
1967 static int8_t inf_ch_sw_timing(struct pkt_buff *pkt, u8 *id) {
1968 return 0;
1971 static int8_t inf_pti_ctrl(struct pkt_buff *pkt, u8 *id) {
1972 return 0;
1975 static int8_t inf_tpu_buff_status(struct pkt_buff *pkt, u8 *id) {
1976 return 0;
1979 static int8_t inf_interw(struct pkt_buff *pkt, u8 *id) {
1980 return 0;
1983 static int8_t inf_adv_proto(struct pkt_buff *pkt, u8 *id) {
1984 return 0;
1987 static int8_t inf_exp_bandw_req(struct pkt_buff *pkt, u8 *id) {
1988 return 0;
1991 static int8_t inf_qos_map_set(struct pkt_buff *pkt, u8 *id) {
1992 return 0;
1995 static int8_t inf_roam_cons(struct pkt_buff *pkt, u8 *id) {
1996 return 0;
1999 static int8_t inf_emer_alert_id(struct pkt_buff *pkt, u8 *id) {
2000 return 0;
2003 static int8_t inf_mesh_conf(struct pkt_buff *pkt, u8 *id) {
2004 return 0;
2007 static int8_t inf_mesh_id(struct pkt_buff *pkt, u8 *id) {
2008 return 0;
2011 static int8_t inf_mesh_link_metr_rep(struct pkt_buff *pkt, u8 *id) {
2012 return 0;
2015 static int8_t inf_cong_notif(struct pkt_buff *pkt, u8 *id) {
2016 return 0;
2019 static int8_t inf_mesh_peer_mgmt(struct pkt_buff *pkt, u8 *id) {
2020 return 0;
2023 static int8_t inf_mesh_ch_sw_para(struct pkt_buff *pkt, u8 *id) {
2024 return 0;
2027 static int8_t inf_mesh_awake_win(struct pkt_buff *pkt, u8 *id) {
2028 return 0;
2031 static int8_t inf_beacon_timing(struct pkt_buff *pkt, u8 *id) {
2032 return 0;
2035 static int8_t inf_mccaop_setup_req(struct pkt_buff *pkt, u8 *id) {
2036 return 0;
2039 static int8_t inf_mccaop_setup_rep(struct pkt_buff *pkt, u8 *id) {
2040 return 0;
2043 static int8_t inf_mccaop_adv(struct pkt_buff *pkt, u8 *id) {
2044 return 0;
2047 static int8_t inf_mccaop_teardwn(struct pkt_buff *pkt, u8 *id) {
2048 return 0;
2051 static int8_t inf_gann(struct pkt_buff *pkt, u8 *id) {
2052 return 0;
2055 static int8_t inf_rann(struct pkt_buff *pkt, u8 *id) {
2056 return 0;
2059 static int8_t inf_ext_cap(struct pkt_buff *pkt, u8 *id) {
2060 return 0;
2063 static int8_t inf_preq(struct pkt_buff *pkt, u8 *id) {
2064 return 0;
2067 static int8_t inf_prep(struct pkt_buff *pkt, u8 *id) {
2068 return 0;
2071 static int8_t inf_perr(struct pkt_buff *pkt, u8 *id) {
2072 return 0;
2075 static int8_t inf_pxu(struct pkt_buff *pkt, u8 *id) {
2076 return 0;
2079 static int8_t inf_pxuc(struct pkt_buff *pkt, u8 *id) {
2080 return 0;
2083 static int8_t inf_auth_mesh_peer_exch(struct pkt_buff *pkt, u8 *id) {
2084 return 0;
2087 static int8_t inf_mic(struct pkt_buff *pkt, u8 *id) {
2088 return 0;
2091 static int8_t inf_dest_uri(struct pkt_buff *pkt, u8 *id) {
2092 return 0;
2095 static int8_t inf_u_apsd_coex(struct pkt_buff *pkt, u8 *id) {
2096 return 0;
2099 static int8_t inf_mccaop_adv_overv(struct pkt_buff *pkt, u8 *id) {
2100 return 0;
2103 static int8_t inf_vend_spec(struct pkt_buff *pkt, u8 *id)
2105 u8 i;
2106 u8 *data;
2107 struct element_vend_spec *vend_spec;
2109 vend_spec = (struct element_vend_spec *)
2110 pkt_pull(pkt, sizeof(*vend_spec));
2111 if (vend_spec == NULL)
2112 return 0;
2114 tprintf("Vendor Specific (%u, Len (%u)): ", *id, vend_spec->len);
2116 data = pkt_pull(pkt, vend_spec->len);
2117 if (data == NULL)
2118 return 0;
2120 tprintf("Data 0x");
2121 for (i = 0; i < vend_spec->len; i++)
2122 tprintf("%.2x", data[i]);
2124 return 1;
2127 static int8_t inf_elements(struct pkt_buff *pkt)
2129 u8 *id = pkt_pull(pkt, 1);
2130 if (id == NULL)
2131 return 0;
2133 switch (*id) {
2134 case 0: return inf_ssid(pkt, id);
2135 case 1: return inf_supp_rates(pkt, id);
2136 case 2: return inf_fh_ps(pkt, id);
2137 case 3: return inf_dsss_ps(pkt, id);
2138 case 4: return inf_cf_ps(pkt, id);
2139 case 5: return inf_tim(pkt, id);
2140 case 6: return inf_ibss_ps(pkt, id);
2141 case 7: return inf_country(pkt, id);
2142 case 8: return inf_hop_pp(pkt, id);
2143 case 9: return inf_hop_pt(pkt, id);
2144 case 10: return inf_req(pkt, id);
2145 case 11: return inf_bss_load(pkt, id);
2146 case 12: return inf_edca_ps(pkt, id);
2147 case 13: return inf_tspec(pkt, id);
2148 case 14: return inf_tclas(pkt, id);
2149 case 15: return inf_sched(pkt, id);
2150 case 16: return inf_chall_txt(pkt, id);
2151 case 17 ... 31: return inf_reserved(pkt, id);
2152 case 32: return inf_pwr_constr(pkt, id);
2153 case 33: return inf_pwr_cap(pkt, id);
2154 case 34: return inf_tpc_req(pkt, id);
2155 case 35: return inf_tpc_rep(pkt, id);
2156 case 36: return inf_supp_ch(pkt, id);
2157 case 37: return inf_ch_sw_ann(pkt, id);
2158 case 38: return inf_meas_req(pkt, id);
2159 case 39: return inf_meas_rep(pkt, id);
2160 case 40: return inf_quiet(pkt, id);
2161 case 41: return inf_ibss_dfs(pkt, id);
2162 case 42: return inf_erp(pkt, id);
2163 case 43: return inf_ts_del(pkt, id);
2164 case 44: return inf_tclas_proc(pkt, id);
2165 case 45: return inf_ht_cap(pkt, id);
2166 case 46: return inf_qos_cap(pkt, id);
2167 case 47: return inf_reserved(pkt, id);
2168 case 48: return inf_rsn(pkt, id);
2169 case 49: return inf_rsn(pkt, id);
2170 case 50: return inf_ext_supp_rates(pkt, id);
2171 case 51: return inf_ap_ch_exp(pkt, id);
2172 case 52: return inf_neighb_rep(pkt, id);
2173 case 53: return inf_rcpi(pkt, id);
2174 case 54: return inf_mde(pkt, id);
2175 case 55: return inf_fte(pkt, id);
2176 case 56: return inf_time_out_int(pkt, id);
2177 case 57: return inf_rde(pkt, id);
2178 case 58: return inf_dse_reg_loc(pkt, id);
2179 case 59: return inf_supp_op_class(pkt, id);
2180 case 60: return inf_ext_ch_sw_ann(pkt, id);
2181 case 61: return inf_ht_op(pkt, id);
2182 case 62: return inf_sec_ch_offs(pkt, id);
2183 case 63: return inf_bss_avg_acc_del(pkt, id);
2184 case 64: return inf_ant(pkt, id);
2185 case 65: return inf_rsni(pkt, id);
2186 case 66: return inf_meas_pilot_trans(pkt, id);
2187 case 67: return inf_bss_avl_adm_cap(pkt, id);
2188 case 68: return inf_bss_ac_acc_del(pkt, id);
2189 case 69: return inf_time_adv(pkt, id);
2190 case 70: return inf_rm_ena_cap(pkt, id);
2191 case 71: return inf_mult_bssid(pkt, id);
2192 case 72: return inf_20_40_bss_coex(pkt, id);
2193 case 73: return inf_20_40_bss_int_ch_rep(pkt, id);
2194 case 74: return inf_overl_bss_scan_para(pkt, id);
2195 case 75: return inf_ric_desc(pkt, id);
2196 case 76: return inf_mgmt_mic(pkt, id);
2197 case 78: return inf_ev_req(pkt, id);
2198 case 79: return inf_ev_rep(pkt, id);
2199 case 80: return inf_diagn_req(pkt, id);
2200 case 81: return inf_diagn_rep(pkt, id);
2201 case 82: return inf_loc_para(pkt, id);
2202 case 83: return inf_nontr_bssid_cap(pkt, id);
2203 case 84: return inf_ssid_list(pkt, id);
2204 case 85: return inf_mult_bssid_index(pkt, id);
2205 case 86: return inf_fms_desc(pkt, id);
2206 case 87: return inf_fms_req(pkt, id);
2207 case 88: return inf_fms_resp(pkt, id);
2208 case 89: return inf_qos_tfc_cap(pkt, id);
2209 case 90: return inf_bss_max_idle_per(pkt, id);
2210 case 91: return inf_tfs_req(pkt, id);
2211 case 92: return inf_tfs_resp(pkt, id);
2212 case 93: return inf_wnm_sleep_mod(pkt, id);
2213 case 94: return inf_tim_bcst_req(pkt, id);
2214 case 95: return inf_tim_bcst_resp(pkt, id);
2215 case 96: return inf_coll_interf_rep(pkt, id);
2216 case 97: return inf_ch_usage(pkt, id);
2217 case 98: return inf_time_zone(pkt, id);
2218 case 99: return inf_dms_req(pkt, id);
2219 case 100: return inf_dms_resp(pkt, id);
2220 case 101: return inf_link_id(pkt, id);
2221 case 102: return inf_wakeup_sched(pkt, id);
2222 case 104: return inf_ch_sw_timing(pkt, id);
2223 case 105: return inf_pti_ctrl(pkt, id);
2224 case 106: return inf_tpu_buff_status(pkt, id);
2225 case 107: return inf_interw(pkt, id);
2226 case 108: return inf_adv_proto(pkt, id);
2227 case 109: return inf_exp_bandw_req(pkt, id);
2228 case 110: return inf_qos_map_set(pkt, id);
2229 case 111: return inf_roam_cons(pkt, id);
2230 case 112: return inf_emer_alert_id(pkt, id);
2231 case 113: return inf_mesh_conf(pkt, id);
2232 case 114: return inf_mesh_id(pkt, id);
2233 case 115: return inf_mesh_link_metr_rep(pkt, id);
2234 case 116: return inf_cong_notif(pkt, id);
2235 case 117: return inf_mesh_peer_mgmt(pkt, id);
2236 case 118: return inf_mesh_ch_sw_para(pkt, id);
2237 case 119: return inf_mesh_awake_win(pkt, id);
2238 case 120: return inf_beacon_timing(pkt, id);
2239 case 121: return inf_mccaop_setup_req(pkt, id);
2240 case 122: return inf_mccaop_setup_rep(pkt, id);
2241 case 123: return inf_mccaop_adv(pkt, id);
2242 case 124: return inf_mccaop_teardwn(pkt, id);
2243 case 125: return inf_gann(pkt, id);
2244 case 126: return inf_rann(pkt, id);
2245 case 127: return inf_ext_cap(pkt, id);
2246 case 128: return inf_reserved(pkt, id);
2247 case 129: return inf_reserved(pkt, id);
2248 case 130: return inf_preq(pkt, id);
2249 case 131: return inf_prep(pkt, id);
2250 case 132: return inf_perr(pkt, id);
2251 case 133: return inf_reserved(pkt, id);
2252 case 134: return inf_reserved(pkt, id);
2253 case 135: return inf_reserved(pkt, id);
2254 case 136: return inf_reserved(pkt, id);
2255 case 137: return inf_pxu(pkt, id);
2256 case 138: return inf_pxuc(pkt, id);
2257 case 139: return inf_auth_mesh_peer_exch(pkt, id);
2258 case 140: return inf_mic(pkt, id);
2259 case 141: return inf_dest_uri(pkt, id);
2260 case 142: return inf_u_apsd_coex(pkt, id);
2261 case 143 ... 173: return inf_reserved(pkt, id);
2262 case 174: return inf_mccaop_adv_overv(pkt, id);
2263 case 221: return inf_vend_spec(pkt, id);
2266 return 0;
2269 #define ESS 0b0000000000000001
2270 #define IBSS 0b0000000000000010
2271 #define CF_Pollable 0b0000000000000100
2272 #define CF_Poll_Req 0b0000000000001000
2273 #define Privacy 0b0000000000010000
2274 #define Short_Pre 0b0000000000100000
2275 #define PBCC 0b0000000001000000
2276 #define Ch_Agility 0b0000000010000000
2277 #define Spec_Mgmt 0b0000000100000000
2278 #define QoS 0b0000001000000000
2279 #define Short_Slot_t 0b0000010000000000
2280 #define APSD 0b0000100000000000
2281 #define Radio_Meas 0b0001000000000000
2282 #define DSSS_OFDM 0b0010000000000000
2283 #define Del_Block_ACK 0b0100000000000000
2284 #define Imm_Block_ACK 0b1000000000000000
2286 static int8_t cap_field(u16 cap_inf)
2288 if (ESS & cap_inf)
2289 tprintf(" ESS;");
2290 if (IBSS & cap_inf)
2291 tprintf(" IBSS;");
2292 if (CF_Pollable & cap_inf)
2293 tprintf(" CF Pollable;");
2294 if (CF_Poll_Req & cap_inf)
2295 tprintf(" CF-Poll Request;");
2296 if (Privacy & cap_inf)
2297 tprintf(" Privacy;");
2298 if (Short_Pre & cap_inf)
2299 tprintf(" Short Preamble;");
2300 if (PBCC & cap_inf)
2301 tprintf(" PBCC;");
2302 if (Ch_Agility & cap_inf)
2303 tprintf(" Channel Agility;");
2304 if (Spec_Mgmt & cap_inf)
2305 tprintf(" Spectrum Management;");
2306 if (QoS & cap_inf)
2307 tprintf(" QoS;");
2308 if (Short_Slot_t & cap_inf)
2309 tprintf(" Short Slot Time;");
2310 if (APSD & cap_inf)
2311 tprintf(" APSD;");
2312 if (Radio_Meas & cap_inf)
2313 tprintf(" Radio Measurement;");
2314 if (DSSS_OFDM & cap_inf)
2315 tprintf(" DSSS-OFDM;");
2316 if (Del_Block_ACK & cap_inf)
2317 tprintf(" Delayed Block Ack;");
2318 if (Imm_Block_ACK & cap_inf)
2319 tprintf(" Immediate Block Ack;");
2321 return 1;
2324 /* Management Dissectors */
2325 static int8_t assoc_req(struct pkt_buff *pkt) {
2326 return 0;
2329 static int8_t assoc_resp(struct pkt_buff *pkt) {
2330 return 0;
2333 static int8_t reassoc_req(struct pkt_buff *pkt) {
2334 return 0;
2337 static int8_t reassoc_resp(struct pkt_buff *pkt) {
2338 return 0;
2341 static int8_t probe_req(struct pkt_buff *pkt) {
2342 return 0;
2345 static int8_t probe_resp(struct pkt_buff *pkt) {
2346 return 0;
2349 static int8_t beacon(struct pkt_buff *pkt)
2351 struct ieee80211_mgmt_beacon *beacon;
2353 beacon = (struct ieee80211_mgmt_beacon *)
2354 pkt_pull(pkt, sizeof(*beacon));
2355 if (beacon == NULL)
2356 return 0;
2358 tprintf("Timestamp 0x%.16lx, ", le64_to_cpu(beacon->timestamp));
2359 tprintf("Beacon Interval (%fs), ", le16_to_cpu(beacon->beacon_int)*TU);
2360 tprintf("Capabilities (0x%x <->", le16_to_cpu(beacon->capab_info));
2361 cap_field(le16_to_cpu(beacon->capab_info));
2362 tprintf(")");
2364 if(pkt_len(pkt)) {
2365 tprintf("\n\tParameters:");
2366 while (inf_elements(pkt)) {
2367 tprintf("\n\t");
2371 if(pkt_len(pkt))
2372 return 0;
2373 return 1;
2376 static int8_t atim(struct pkt_buff *pkt) {
2377 return 0;
2380 static int8_t disassoc(struct pkt_buff *pkt) {
2381 return 0;
2384 static int8_t auth(struct pkt_buff *pkt) {
2385 return 0;
2388 static int8_t deauth(struct pkt_buff *pkt) {
2389 return 0;
2391 /* End Management Dissectors */
2393 /* Control Dissectors */
2394 static int8_t ps_poll(struct pkt_buff *pkt) {
2395 return 0;
2398 static int8_t rts(struct pkt_buff *pkt) {
2399 return 0;
2402 static int8_t cts(struct pkt_buff *pkt) {
2403 return 0;
2406 static int8_t ack(struct pkt_buff *pkt) {
2407 return 0;
2410 static int8_t cf_end(struct pkt_buff *pkt) {
2411 return 0;
2414 static int8_t cf_end_ack(struct pkt_buff *pkt) {
2415 return 0;
2417 /* End Control Dissectors */
2419 /* Data Dissectors */
2420 static int8_t data(struct pkt_buff *pkt) {
2421 return 0;
2424 static int8_t data_cf_ack(struct pkt_buff *pkt) {
2425 return 0;
2428 static int8_t data_cf_poll(struct pkt_buff *pkt) {
2429 return 0;
2432 static int8_t data_cf_ack_poll(struct pkt_buff *pkt) {
2433 return 0;
2436 static int8_t null(struct pkt_buff *pkt) {
2437 return 0;
2440 static int8_t cf_ack(struct pkt_buff *pkt) {
2441 return 0;
2444 static int8_t cf_poll(struct pkt_buff *pkt) {
2445 return 0;
2448 static int8_t cf_ack_poll(struct pkt_buff *pkt) {
2449 return 0;
2451 /* End Data Dissectors */
2453 static const char *mgt_sub(u8 subtype, struct pkt_buff *pkt,
2454 int8_t (**get_content)(struct pkt_buff *pkt))
2456 u16 seq_ctrl;
2457 struct ieee80211_mgmt *mgmt;
2458 const char *dst, *src, *bssid;
2460 mgmt = (struct ieee80211_mgmt *) pkt_pull(pkt, sizeof(*mgmt));
2461 if (mgmt == NULL)
2462 return 0;
2464 dst = lookup_vendor((mgmt->da[0] << 16) |
2465 (mgmt->da[1] << 8) |
2466 mgmt->da[2]);
2467 src = lookup_vendor((mgmt->sa[0] << 16) |
2468 (mgmt->sa[1] << 8) |
2469 mgmt->sa[2]);
2471 bssid = lookup_vendor((mgmt->bssid[0] << 16) |
2472 (mgmt->bssid[1] << 8) |
2473 mgmt->bssid[2]);
2474 seq_ctrl = le16_to_cpu(mgmt->seq_ctrl);
2476 tprintf("Duration (%u),", le16_to_cpu(mgmt->duration));
2477 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
2478 mgmt->da[0], mgmt->da[1], mgmt->da[2],
2479 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
2480 if (dst) {
2481 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst,
2482 mgmt->da[3], mgmt->da[4], mgmt->da[5]);
2485 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
2486 mgmt->sa[0], mgmt->sa[1], mgmt->sa[2],
2487 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
2488 if (src) {
2489 tprintf("=> (%s:%.2x:%.2x:%.2x)", src,
2490 mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
2493 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
2494 mgmt->bssid[0], mgmt->bssid[1], mgmt->bssid[2],
2495 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
2496 if(bssid) {
2497 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid,
2498 mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
2501 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ",
2502 seq_ctrl & 0xf, seq_ctrl >> 4);
2504 switch (subtype) {
2505 case 0b0000:
2506 *get_content = assoc_req;
2507 return "Association Request";
2508 case 0b0001:
2509 *get_content = assoc_resp;
2510 return "Association Response";
2511 case 0b0010:
2512 *get_content = reassoc_req;
2513 return "Reassociation Request";
2514 case 0b0011:
2515 *get_content = reassoc_resp;
2516 return "Reassociation Response";
2517 case 0b0100:
2518 *get_content = probe_req;
2519 return "Probe Request";
2520 case 0b0101:
2521 *get_content = probe_resp;
2522 return "Probe Response";
2523 case 0b1000:
2524 *get_content = beacon;
2525 return "Beacon";
2526 case 0b1001:
2527 *get_content = atim;
2528 return "ATIM";
2529 case 0b1010:
2530 *get_content = disassoc;
2531 return "Disassociation";
2532 case 0b1011:
2533 *get_content = auth;
2534 return "Authentication";
2535 case 0b1100:
2536 *get_content = deauth;
2537 return "Deauthentication";
2538 case 0b0110 ... 0b0111:
2539 case 0b1101 ... 0b1111:
2540 *get_content = NULL;
2541 return "Reserved";
2542 default:
2543 *get_content = NULL;
2544 return "Management SubType unknown";
2548 static const char *ctrl_sub(u8 subtype, struct pkt_buff *pkt,
2549 int8_t (**get_content)(struct pkt_buff *pkt))
2551 switch (subtype) {
2552 case 0b1010:
2553 *get_content = ps_poll;
2554 return "PS-Poll";
2555 case 0b1011:
2556 *get_content = rts;
2557 return "RTS";
2558 case 0b1100:
2559 *get_content = cts;
2560 return "CTS";
2561 case 0b1101:
2562 *get_content = ack;
2563 return "ACK";
2564 case 0b1110:
2565 *get_content = cf_end;
2566 return "CF End";
2567 case 0b1111:
2568 *get_content = cf_end_ack;
2569 return "CF End + CF-ACK";
2570 case 0b0000 ... 0b1001:
2571 *get_content = NULL;
2572 return "Reserved";
2573 default:
2574 return "Control SubType unkown";
2578 static const char *data_sub(u8 subtype, struct pkt_buff *pkt,
2579 int8_t (**get_content)(struct pkt_buff *pkt))
2581 switch (subtype) {
2582 case 0b0000:
2583 *get_content = data;
2584 return "Data";
2585 case 0b0001:
2586 *get_content = data_cf_ack;
2587 return "Data + CF-ACK";
2588 case 0b0010:
2589 *get_content = data_cf_poll;
2590 return "Data + CF-Poll";
2591 case 0b0011:
2592 *get_content = data_cf_ack_poll;
2593 return "Data + CF-ACK + CF-Poll";
2594 case 0b0100:
2595 *get_content = null;
2596 return "Null";
2597 case 0b0101:
2598 *get_content = cf_ack;
2599 return "CF-ACK";
2600 case 0b0110:
2601 *get_content = cf_poll;
2602 return "CF-Poll";
2603 case 0b0111:
2604 *get_content = cf_ack_poll;
2605 return "CF-ACK + CF-Poll";
2606 case 0b1000 ... 0b1111:
2607 *get_content = NULL;
2608 return "Reserved";
2609 default:
2610 *get_content = NULL;
2611 return "Data SubType unkown";
2615 static const char *
2616 frame_control_type(u8 type, const char *(**get_subtype)(u8 subtype,
2617 struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)))
2619 switch (type) {
2620 case 0b00:
2621 *get_subtype = mgt_sub;
2622 return "Management";
2623 case 0b01:
2624 *get_subtype = ctrl_sub;
2625 return "Control";
2626 case 0b10:
2627 *get_subtype = data_sub;
2628 return "Data";
2629 case 0b11:
2630 *get_subtype = NULL;
2631 return "Reserved";
2632 default:
2633 *get_subtype = NULL;
2634 return "Control Type unkown";
2638 static void ieee80211(struct pkt_buff *pkt)
2640 int8_t (*get_content)(struct pkt_buff *pkt) = NULL;
2641 const char *(*get_subtype)(u8 subtype, struct pkt_buff *pkt,
2642 int8_t (**get_content)(struct pkt_buff *pkt)) = NULL;
2643 const char *subtype = NULL;
2644 struct ieee80211_frm_ctrl *frm_ctrl;
2646 frm_ctrl = (struct ieee80211_frm_ctrl *)
2647 pkt_pull(pkt, sizeof(*frm_ctrl));
2648 if (frm_ctrl == NULL)
2649 return;
2651 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
2652 le16_to_cpu(frm_ctrl->frame_control));
2654 tprintf(" [ Proto Version (%u), ", frm_ctrl->proto_version);
2655 tprintf("Type (%u, %s), ", frm_ctrl->type,
2656 frame_control_type(frm_ctrl->type, &get_subtype));
2657 if (get_subtype) {
2658 subtype = (*get_subtype)(frm_ctrl->subtype, pkt, &get_content);
2659 tprintf("Subtype (%u, %s)", frm_ctrl->subtype, subtype);
2660 } else {
2661 tprintf("%s%s%s", colorize_start_full(black, red),
2662 "No SubType Data available", colorize_end());
2665 tprintf("%s%s", frm_ctrl->to_ds ? ", Frame goes to DS" : "",
2666 frm_ctrl->from_ds ? ", Frame comes from DS" : "");
2667 tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : "");
2668 tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : "");
2669 tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : "");
2670 tprintf("%s", frm_ctrl->more_data ? ", More Data" : "");
2671 tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : "");
2672 tprintf("%s", frm_ctrl->order ? ", Order" : "");
2673 tprintf(" ]\n");
2675 if (get_content) {
2676 tprintf(" [ Subtype %s: ", subtype);
2677 if (!((*get_content) (pkt)))
2678 tprintf("%s%s%s", colorize_start_full(black, red),
2679 "Failed to dissect Subtype", colorize_end());
2680 tprintf(" ]");
2681 } else {
2682 tprintf("%s%s%s", colorize_start_full(black, red),
2683 "No SubType Data available", colorize_end());
2686 tprintf("\n");
2688 // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
2691 static void ieee80211_less(struct pkt_buff *pkt)
2693 tprintf("802.11 frame (more on todo)");
2696 struct protocol ieee80211_ops = {
2697 .key = 0,
2698 .print_full = ieee80211,
2699 .print_less = ieee80211_less,
2702 EXPORT_SYMBOL(ieee80211_ops);