summaryrefslogtreecommitdiff
path: root/proto_80211_mac_hdr.c
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
committerDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
commit1a9fbac03c684f29cff9ac44875bd9504a89f54e (patch)
tree1b2e40dbe5dc1899ef5b62c4325c9b94c9c450fc /proto_80211_mac_hdr.c
all: import netsniff-ng 0.5.8-rc0 source
We decided to get rid of the old Git history and start a new one for several reasons: *) Allow / enforce only high-quality commits (which was not the case for many commits in the history), have a policy that is more close to the one from the Linux kernel. With high quality commits, we mean code that is logically split into commits and commit messages that are signed-off and have a proper subject and message body. We do not allow automatic Github merges anymore, since they are total bullshit. However, we will either cherry-pick your patches or pull them manually. *) The old archive was about ~27MB for no particular good reason. This basically derived from the bad decision that also some PDF files where stored there. From this moment onwards, no binary objects are allowed to be stored in this repository anymore. The old archive is not wiped away from the Internet. You will still be able to find it, e.g. on git.cryptoism.org etc. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Diffstat (limited to 'proto_80211_mac_hdr.c')
-rw-r--r--proto_80211_mac_hdr.c3627
1 files changed, 3627 insertions, 0 deletions
diff --git a/proto_80211_mac_hdr.c b/proto_80211_mac_hdr.c
new file mode 100644
index 0000000..a496a1e
--- /dev/null
+++ b/proto_80211_mac_hdr.c
@@ -0,0 +1,3627 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Copyright 2012, 2013 Markus Amend <markus@netsniff-ng.org>
+ * Copyright 2012 Daniel Borkmann <daniel@netsniff-ng.org>
+ * Subject to the GPL, version 2.
+ */
+
+/* TODO
+ * check all possible frame combinations for their behavior
+ * with respect to endianess (little / big)
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <netinet/in.h> /* for ntohs() */
+#include <asm/byteorder.h>
+#include <arpa/inet.h> /* for inet_ntop() */
+
+#include "proto.h"
+#include "protos.h"
+#include "dissector_80211.h"
+#include "built_in.h"
+#include "pkt_buff.h"
+#include "oui.h"
+
+#define TU 0.001024
+
+/* Note: Fields are encoded in little-endian! */
+struct ieee80211_frm_ctrl {
+ union {
+ u16 frame_control;
+ struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ /* Correct order here ... */
+ __extension__ u16 proto_version:2,
+ type:2,
+ subtype:4,
+ to_ds:1,
+ from_ds:1,
+ more_frags:1,
+ retry:1,
+ power_mgmt:1,
+ more_data:1,
+ wep:1,
+ order:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __extension__ u16 subtype:4,
+ type:2,
+ proto_version:2,
+ order:1,
+ wep:1,
+ more_data:1,
+ power_mgmt:1,
+ retry:1,
+ more_frags:1,
+ from_ds:1,
+ to_ds:1;
+#else
+# error "Adjust your <asm/byteorder.h> defines"
+#endif
+ };
+ };
+} __packed;
+
+/* Management Frame start */
+/* Note: Fields are encoded in little-endian! */
+struct ieee80211_mgmt {
+ u16 duration;
+ u8 da[6];
+ u8 sa[6];
+ u8 bssid[6];
+ u16 seq_ctrl;
+} __packed;
+
+struct ieee80211_mgmt_auth {
+ u16 auth_alg;
+ u16 auth_transaction;
+ u16 status_code;
+ /* possibly followed by Challenge text */
+ u8 variable[0];
+} __packed;
+
+struct ieee80211_mgmt_deauth {
+ u16 reason_code;
+} __packed;
+
+struct ieee80211_mgmt_assoc_req {
+ u16 capab_info;
+ u16 listen_interval;
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+} __packed;
+
+struct ieee80211_mgmt_assoc_resp {
+ u16 capab_info;
+ u16 status_code;
+ u16 aid;
+ /* followed by Supported rates */
+ u8 variable[0];
+} __packed;
+
+struct ieee80211_mgmt_reassoc_resp {
+ u16 capab_info;
+ u16 status_code;
+ u16 aid;
+ /* followed by Supported rates */
+ u8 variable[0];
+} __packed;
+
+struct ieee80211_mgmt_reassoc_req {
+ u16 capab_info;
+ u16 listen_interval;
+ u8 current_ap[6];
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+} __packed;
+
+struct ieee80211_mgmt_disassoc {
+ u16 reason_code;
+} __packed;
+
+struct ieee80211_mgmt_probe_req {
+} __packed;
+
+struct ieee80211_mgmt_beacon {
+ u64 timestamp;
+ u16 beacon_int;
+ u16 capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params, TIM */
+ u8 variable[0];
+} __packed;
+
+struct ieee80211_mgmt_probe_resp {
+ u8 timestamp[8];
+ u16 beacon_int;
+ u16 capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params, TIM */
+ u8 variable[0];
+} __packed;
+/* Management Frame end */
+
+/* Control Frame start */
+/* Note: Fields are encoded in little-endian! */
+struct ieee80211_ctrl {
+} __packed;
+
+struct ieee80211_ctrl_rts {
+ u16 duration;
+ u8 da[6];
+ u8 sa[6];
+} __packed;
+
+struct ieee80211_ctrl_cts {
+ u16 duration;
+ u8 da[6];
+} __packed;
+
+struct ieee80211_ctrl_ack {
+ u16 duration;
+ u8 da[6];
+} __packed;
+
+struct ieee80211_ctrl_ps_poll {
+ u16 aid;
+ u8 bssid[6];
+ u8 sa[6];
+} __packed;
+
+struct ieee80211_ctrl_cf_end {
+ u16 duration;
+ u8 bssid[6];
+ u8 sa[6];
+} __packed;
+
+struct ieee80211_ctrl_cf_end_ack {
+ u16 duration;
+ u8 bssid[6];
+ u8 sa[6];
+} __packed;
+/* Control Frame end */
+
+/* Data Frame start */
+/* Note: Fields are encoded in little-endian! */
+struct ieee80211_data {
+} __packed;
+
+/* TODO: Extend */
+/* Data Frame end */
+
+struct element_reserved {
+ u8 len;
+} __packed;
+
+struct element_ssid {
+ u8 len;
+ u8 SSID[0];
+} __packed;
+
+struct element_supp_rates {
+ u8 len;
+ u8 rates[0];
+} __packed;
+
+struct element_fh_ps {
+ u8 len;
+ u16 dwell_time;
+ u8 hop_set;
+ u8 hop_pattern;
+ u8 hop_index;
+} __packed;
+
+struct element_dsss_ps {
+ u8 len;
+ u8 curr_ch;
+} __packed;
+
+struct element_cf_ps {
+ u8 len;
+ u8 cfp_cnt;
+ u8 cfp_period;
+ u16 cfp_max_dur;
+ u16 cfp_dur_rem;
+} __packed;
+
+struct element_tim {
+ u8 len;
+ u8 dtim_cnt;
+ u8 dtim_period;
+ u8 bmp_cntrl;
+ u8 part_virt_bmp[0];
+} __packed;
+
+struct element_ibss_ps {
+ u8 len;
+ u16 atim_win;
+} __packed;
+
+struct element_country_tripled {
+ u8 frst_ch;
+ u8 nr_ch;
+ u8 max_trans;
+} __packed;
+
+struct element_country {
+ u8 len;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ /* Correct order here ... */
+ u8 country_first;
+ u8 country_sec;
+ u8 country_third;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ u8 country_third;
+ u8 country_sec;
+ u8 country_first;
+#else
+# error "Adjust your <asm/byteorder.h> defines"
+#endif
+ /* triplet may repeat */
+ struct element_country_tripled tripled [0];
+ /* end triplet */
+ u8 pad[0];
+} __packed;
+
+struct element_hop_pp {
+ u8 len;
+ u8 prime_radix;
+ u8 nr_ch;
+} __packed;
+
+struct element_hop_pt {
+ u8 len;
+ u8 flag;
+ u8 nr_sets;
+ u8 modules;
+ u8 offs;
+ u8 rand_tabl[0];
+} __packed;
+
+struct element_req {
+ u8 len;
+ u8 req_elem_idl[0];
+} __packed;
+
+struct element_bss_load {
+ u8 len;
+ u16 station_cnt;
+ u8 ch_util;
+ u16 avlb_adm_cap;
+} __packed;
+
+struct element_edca_ps {
+ u8 len;
+ u8 qos_inf;
+ u8 res;
+ u32 ac_be;
+ u32 ac_bk;
+ u32 ac_vi;
+ u32 ac_vo;
+} __packed;
+
+struct element_tspec {
+ union {
+ u32 len_ts_info;
+ struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ /* Correct order here ... */
+ __extension__ u32 len:8,
+ traffic_type:1,
+ tsid:4,
+ direction:2,
+ access_policy:2,
+ aggr:1,
+ apsd:1,
+ user_prior:3,
+ tsinfo_ack_pol:2,
+ schedule:1,
+ res:7;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __extension__ u32 len:8,
+ res:7,
+ schedule:1,
+ tsinfo_ack_pol:2,
+ user_prior:3,
+ apsd:1,
+ aggr:1,
+ access_policy:2,
+ direction:2,
+ tsid:4,
+ traffic_type:1;
+#else
+# error "Adjust your <asm/byteorder.h> defines"
+#endif
+ };
+ };
+ u16 nom_msdu_size;
+ u16 max_msdu_size;
+ u32 min_srv_intv;
+ u32 max_srv_intv;
+ u32 inactive_intv;
+ u32 susp_intv;
+ u32 srv_start_time;
+ u32 min_data_rate;
+ u32 mean_data_rate;
+ u32 peak_data_rate;
+ u32 burst_size;
+ u32 delay_bound;
+ u32 min_phy_rate;
+ u16 surplus_bandw_allow;
+ u16 med_time;
+} __packed;
+
+struct element_tclas {
+ u8 len;
+ u8 user_priority;
+ u8 frm_class[0];
+} __packed;
+
+struct element_tclas_frm_class {
+ u8 type;
+ u8 mask;
+ u8 param[0];
+} __packed;
+
+struct element_tclas_type0 {
+ u8 sa[6];
+ u8 da[6];
+ u16 type;
+} __packed;
+
+struct element_tclas_type1 {
+ u8 version;
+ u8 subparam[0];
+} __packed;
+
+struct element_tclas_type1_ip4 {
+ u32 sa;
+ u32 da;
+ u16 sp;
+ u16 dp;
+ u8 dscp;
+ u8 proto;
+ u8 reserved;
+} __packed;
+
+struct element_tclas_type1_ip6 {
+ struct in6_addr sa;
+ struct in6_addr da;
+ u16 sp;
+ u16 dp;
+ union {
+ u8 flow_label[3];
+ struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __extension__ u8 flow_label3:8;
+ __extension__ u8 flow_label2:8;
+ __extension__ u8 flow_label1:8;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __extension__ u8 flow_label1:8;
+ __extension__ u8 flow_label2:8;
+ __extension__ u8 flow_label3:8;
+#else
+# error "Adjust your <asm/byteorder.h> defines"
+#endif
+ };
+ };
+} __packed;
+
+struct element_tclas_type2 {
+ u16 vlan_tci;
+} __packed;
+
+struct element_tclas_type3 {
+ u16 offs;
+ u8 value[0];
+ u8 mask[0];
+} __packed;
+
+struct element_tclas_type4 {
+ u8 version;
+ u8 subparam[0];
+} __packed;
+
+struct element_tclas_type4_ip4 {
+ u32 sa;
+ u32 da;
+ u16 sp;
+ u16 dp;
+ u8 dscp;
+ u8 proto;
+ u8 reserved;
+} __packed;
+
+struct element_tclas_type4_ip6 {
+ struct in6_addr sa;
+ struct in6_addr da;
+ u16 sp;
+ u16 dp;
+ u8 dscp;
+ u8 nxt_hdr;
+ union {
+ u8 flow_label[3];
+ struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __extension__ u8 flow_label3:8;
+ __extension__ u8 flow_label2:8;
+ __extension__ u8 flow_label1:8;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __extension__ u8 flow_label1:8;
+ __extension__ u8 flow_label2:8;
+ __extension__ u8 flow_label3:8;
+#else
+# error "Adjust your <asm/byteorder.h> defines"
+#endif
+ };
+ };
+} __packed;
+
+struct element_tclas_type5 {
+ u8 pcp;
+ u8 cfi;
+ u8 vid;
+} __packed;
+
+struct element_schedule {
+ u8 len;
+ u16 inf;
+ u32 start;
+ u32 serv_intv;
+ u16 spec_intv;
+} __packed;
+
+struct element_chall_txt {
+ u8 len;
+ u8 chall_txt[0];
+} __packed;
+
+struct element_pwr_constr {
+ u8 len;
+ u8 local_pwr_constr;
+} __packed;
+
+struct element_pwr_cap {
+ u8 len;
+ u8 min_pwr_cap;
+ u8 max_pwr_cap;
+} __packed;
+
+struct element_tpc_req {
+ u8 len;
+} __packed;
+
+struct element_tpc_rep {
+ u8 len;
+ u8 trans_pwr;
+ u8 link_marg;
+} __packed;
+
+struct element_supp_ch {
+ u8 len;
+ u8 first_ch_nr[0];
+ u8 nr_ch[0];
+} __packed;
+
+struct element_supp_ch_tuple {
+ u8 first_ch_nr;
+ u8 nr_ch;
+} __packed;
+
+struct element_ch_sw_ann {
+ u8 len;
+ u8 switch_mode;
+ u8 new_nr;
+ u8 switch_cnt;
+} __packed;
+
+struct element_meas_basic {
+ u8 ch_nr;
+ u64 start;
+ u16 dur;
+} __packed;
+
+struct element_meas_cca {
+ u8 ch_nr;
+ u64 start;
+ u16 dur;
+} __packed;
+
+struct element_meas_rpi {
+ u8 ch_nr;
+ u64 start;
+ u16 dur;
+} __packed;
+
+struct element_meas_ch_load {
+ u8 op_class;
+ u8 ch_nr;
+ u16 rand_intv;
+ u16 dur;
+ u8 sub[0];
+} __packed;
+
+struct element_meas_noise {
+ u8 op_class;
+ u8 ch_nr;
+ u16 rand_intv;
+ u16 dur;
+ u8 sub[0];
+} __packed;
+
+struct element_meas_beacon {
+ u8 op_class;
+ u8 ch_nr;
+ u16 rand_intv;
+ u16 dur;
+ u8 mode;
+ u8 bssid[6];
+ u8 sub[0];
+} __packed;
+
+struct element_meas_frame {
+ u8 op_class;
+ u8 ch_nr;
+ u16 rand_intv;
+ u16 dur;
+ u8 frame;
+ u8 mac[6];
+ u8 sub[0];
+} __packed;
+
+struct element_meas_sta {
+ u8 peer_mac[6];
+ u16 rand_intv;
+ u16 dur;
+ u8 group_id;
+ u8 sub[0];
+} __packed;
+
+struct element_meas_lci {
+ u8 loc_subj;
+ u8 latitude_req_res;
+ u8 longitude_req_res;
+ u8 altitude_req_res;
+ u8 sub[0];
+} __packed;
+
+struct element_meas_trans_str_cat {
+ u16 rand_intv;
+ u16 dur;
+ u8 peer_sta_addr[6];
+ u8 traffic_id;
+ u8 bin_0_range;
+ u8 sub[0];
+} __packed;
+
+struct element_meas_mcast_diag {
+ u16 rand_intv;
+ u16 dur;
+ u8 group_mac[6];
+ u8 mcast_triggered[0];
+ u8 sub[0];
+} __packed;
+
+struct element_meas_loc_civic {
+ u8 loc_subj;
+ u8 civic_loc;
+ u8 loc_srv_intv_unit;
+ u16 loc_srv_intv;
+ u8 sub[0];
+} __packed;
+
+struct element_meas_loc_id {
+ u8 loc_subj;
+ u8 loc_srv_intv_unit;
+ u16 loc_srv_intv;
+ u8 sub[0];
+} __packed;
+
+struct element_meas_pause {
+ u8 time;
+ u8 sub[0];
+} __packed;
+
+struct element_meas_req {
+ u8 len;
+ u8 token;
+ u8 req_mode;
+ u8 type;
+ u8 req[0];
+} __packed;
+
+struct element_meas_rep {
+ u8 len;
+ u8 token;
+ u8 rep_mode;
+ u8 type;
+ u8 rep[0];
+} __packed;
+
+struct element_quiet {
+ u8 len;
+ u8 cnt;
+ u8 period;
+ u16 dur;
+ u16 offs;
+} __packed;
+
+struct element_ibss_dfs {
+ u8 len;
+ u8 owner[6];
+ u8 rec_intv;
+ u8 ch_map[0];
+} __packed;
+
+struct element_ibss_dfs_tuple {
+ u8 ch_nr;
+ u8 map;
+} __packed;
+
+struct element_erp {
+ u8 len;
+ u8 param;
+} __packed;
+
+struct element_ts_del {
+ u8 len;
+ u32 delay;
+} __packed;
+
+struct element_tclas_proc {
+ u8 len;
+ u8 proc;
+} __packed;
+
+struct element_ht_cap {
+ u8 len;
+ union {
+ u16 info;
+ struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ /* Correct order here ... */
+ __extension__ u16 ldpc:1,
+ supp_width:1,
+ sm_pwr:2,
+ ht_green:1,
+ gi_20mhz:1,
+ gi_40mhz:1,
+ tx_stbc:1,
+ rx_stbc:2,
+ ht_ack:1,
+ max_msdu_length:1,
+ dsss_ck_mode:1,
+ res:1,
+ forty_int:1,
+ prot_supp:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __extension__ u16 rx_stbc:2,
+ ht_ack:1,
+ max_msdu_length:1,
+ dsss_ck_mode:1,
+ res:1,
+ forty_int:1,
+ prot_supp:1,
+ ldpc:1,
+ supp_width:1,
+ sm_pwr:2,
+ ht_green:1,
+ gi_20mhz:1,
+ gi_40mhz:1,
+ tx_stbc:1;
+#else
+# error "Adjust your <asm/byteorder.h> defines"
+#endif
+ };
+ };
+ u8 param;
+ union {
+ u8 mcs_set[16];
+ struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ /* Correct order here ... */
+ __extension__ u8 bitmask1:8;
+ __extension__ u8 bitmask2:8;
+ __extension__ u8 bitmask3:8;
+ __extension__ u8 bitmask4:8;
+ __extension__ u8 bitmask5:8;
+ __extension__ u8 bitmask6:8;
+ __extension__ u8 bitmask7:8;
+ __extension__ u8 bitmask8:8;
+ __extension__ u8 bitmask9:8;
+ __extension__ u8 bitmask10_res:8;
+ __extension__ u16 supp_rate_res:16;
+ __extension__ u32 tx_param_res:32;
+
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __extension__ u32 tx_param_res:32;
+ __extension__ u16 supp_rate_res:16;
+ __extension__ u8 bitmask10_res:8;
+ __extension__ u8 bitmask9:8;
+ __extension__ u8 bitmask8:8;
+ __extension__ u8 bitmask7:8;
+ __extension__ u8 bitmask6:8;
+ __extension__ u8 bitmask5:8;
+ __extension__ u8 bitmask4:8;
+ __extension__ u8 bitmask3:8;
+ __extension__ u8 bitmask2:8;
+ __extension__ u8 bitmask1:8;
+#else
+# error "Adjust your <asm/byteorder.h> defines"
+#endif
+ };
+ };
+ u16 ext_cap;
+ u32 beam_cap;
+ u8 asel_cap;
+} __packed;
+
+struct element_qos_cap {
+ u8 len;
+ u8 info;
+} __packed;
+
+struct element_ext_supp_rates {
+ u8 len;
+ u8 rates[0];
+} __packed;
+
+struct element_vend_spec {
+ u8 len;
+ u8 oui[0];
+ u8 specific[0];
+} __packed;
+
+static int8_t len_neq_error(u8 len, u8 intended)
+{
+ if(intended != len) {
+ tprintf("Length should be %u Bytes", intended);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int8_t len_lt_error(u8 len, u8 intended)
+{
+ if(len < intended) {
+ tprintf("Length should be greater %u Bytes", intended);
+ return 1;
+ }
+
+ return 0;
+}
+
+static float data_rates(u8 id)
+{
+ /* XXX Why not (id / 2.f)? */
+ switch (id) {
+ case 2: return 1.0f;
+ case 3: return 1.5f;
+ case 4: return 2.0f;
+ case 5: return 2.5f;
+ case 6: return 3.0f;
+ case 9: return 4.5f;
+ case 11: return 5.5f;
+ case 12: return 6.0f;
+ case 18: return 9.0f;
+ case 22: return 11.0f;
+ case 24: return 12.0f;
+ case 27: return 13.5f;
+ case 36: return 18.0f;
+ case 44: return 22.0f;
+ case 48: return 24.0f;
+ case 54: return 27.0f;
+ case 66: return 33.0f;
+ case 72: return 36.0f;
+ case 96: return 48.0f;
+ case 108: return 54.0f;
+ }
+
+ return 0.f;
+}
+
+struct subelement {
+ u8 id;
+ u8 len;
+ u8 data[0];
+} __packed;
+
+
+static int8_t subelements(struct pkt_buff *pkt, u8 len)
+{
+ u8 i, j;
+ u8 *data;
+
+ for (i=0; i<len;) {
+ struct subelement *sub;
+
+ sub = (struct subelement *) pkt_pull(pkt, sizeof(*sub));
+ if (sub == NULL)
+ return 0;
+
+ tprintf(", Subelement ID %u, ", sub->id);
+ tprintf("Length %u, ", sub->len);
+
+ data = pkt_pull(pkt, sub->len);
+ if (data == NULL)
+ return 0;
+
+ tprintf("Data: 0x");
+ for(j=0; j < sub->len; j++)
+ tprintf("%.2x ", data[j]);
+
+ i += sub->len + 1;
+ }
+
+ /* Not needed ?! Should break before*/
+ /*
+ *if (i != len) {
+ * tprintf("Length error");
+ * return 0;
+ *}
+ */
+
+ return 1;
+}
+
+static int8_t inf_reserved(struct pkt_buff *pkt, u8 *id)
+{
+ u8 i;
+ u8 *data;
+ struct element_reserved *reserved;
+
+ reserved = (struct element_reserved *) pkt_pull(pkt, sizeof(*reserved));
+ if (reserved == NULL)
+ return 0;
+
+ tprintf("Reserved (%u, Len (%u)): ", *id, reserved->len);
+
+ data = pkt_pull(pkt, reserved->len);
+ if (data == NULL)
+ return 0;
+
+ tprintf("Data 0x");
+ for (i = 0; i < reserved->len; i++)
+ tprintf("%.2x", data[i]);
+
+ return 1;
+}
+
+static int8_t inf_ssid(struct pkt_buff *pkt, u8 *id)
+{
+ u8 i;
+ struct element_ssid *ssid;
+ char *ssid_name;
+
+ ssid = (struct element_ssid *) pkt_pull(pkt, sizeof(*ssid));
+ if (ssid == NULL)
+ return 0;
+
+ tprintf(" SSID (%u, Len (%u)): ", *id, ssid->len);
+
+ if ((ssid->len - sizeof(*ssid) + 1) > 0) {
+ ssid_name = (char *) pkt_pull(pkt, ssid->len);
+ if (ssid_name == NULL)
+ return 0;
+
+ for (i = 0; i < ssid->len; i++)
+ tprintf("%c",ssid_name[i]);
+ } else {
+ tprintf("Wildcard SSID");
+ }
+
+ return 1;
+}
+
+static int8_t inf_supp_rates(struct pkt_buff *pkt, u8 *id)
+{
+ u8 i;
+ u8 *rates;
+ struct element_supp_rates *supp_rates;
+
+ supp_rates = (struct element_supp_rates *)
+ pkt_pull(pkt, sizeof(*supp_rates));
+ if (supp_rates == NULL)
+ return 0;
+
+ tprintf(" Supp. Rates (%u, Len (%u)): ", *id, supp_rates->len);
+ if (len_lt_error(supp_rates->len, 1))
+ return 0;
+
+ if ((supp_rates->len - sizeof(*supp_rates) + 1) > 0) {
+ rates = pkt_pull(pkt, supp_rates->len);
+ if (rates == NULL)
+ return 0;
+
+ for (i = 0; i < supp_rates->len; i++)
+ tprintf("%g%s ", ((rates[i] & 0x80) >> 7) ?
+ data_rates(rates[i] & 0x3f) :
+ ((rates[i] & 0x3f) * 0.5),
+ ((rates[i] & 0x80) >> 7) ? "(B)" : "");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int8_t inf_fh_ps(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_fh_ps *fh_ps;
+
+ fh_ps = (struct element_fh_ps *) pkt_pull(pkt, sizeof(*fh_ps));
+ if (fh_ps == NULL)
+ return 0;
+
+ tprintf(" FH Param Set (%u, Len(%u)): ", *id, fh_ps->len);
+ if (len_neq_error(fh_ps->len, 5))
+ return 0;
+ tprintf("Dwell Time: %fs, ", le16_to_cpu(fh_ps->dwell_time) * TU);
+ tprintf("HopSet: %u, ", fh_ps->hop_set);
+ tprintf("HopPattern: %u, ", fh_ps->hop_pattern);
+ tprintf("HopIndex: %u", fh_ps->hop_index);
+
+ return 1;
+}
+
+static int8_t inf_dsss_ps(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_dsss_ps *dsss_ps;
+
+ dsss_ps = (struct element_dsss_ps *) pkt_pull(pkt, sizeof(*dsss_ps));
+ if (dsss_ps == NULL)
+ return 0;
+
+ tprintf(" DSSS Param Set (%u, Len(%u)): ", *id, dsss_ps->len);
+ if (len_neq_error(dsss_ps->len, 1))
+ return 0;
+ tprintf("Current Channel: %u", dsss_ps->curr_ch);
+
+ return 1;
+}
+
+static int8_t inf_cf_ps(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_cf_ps *cf_ps;
+
+ cf_ps = (struct element_cf_ps *) pkt_pull(pkt, sizeof(*cf_ps));
+ if (cf_ps == NULL)
+ return 0;
+
+ tprintf(" CF Param Set (%u, Len(%u)): ", *id, cf_ps->len);
+ if (len_neq_error(cf_ps->len, 6))
+ return 0;
+ tprintf("CFP Count: %u, ", cf_ps->cfp_cnt);
+ tprintf("CFP Period: %u, ", cf_ps->cfp_period);
+ tprintf("CFP MaxDur: %fs, ", le16_to_cpu(cf_ps->cfp_max_dur) * TU);
+ tprintf("CFP DurRem: %fs", le16_to_cpu(cf_ps->cfp_dur_rem) * TU);
+
+ return 1;
+}
+
+static int8_t inf_tim(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_tim *tim;
+ u8 i;
+
+ tim = (struct element_tim *) pkt_pull(pkt, sizeof(*tim));
+ if (tim == NULL)
+ return 0;
+
+ tprintf(" TIM (%u, Len(%u)): ", *id, tim->len);
+ if (len_lt_error(tim->len, 3))
+ return 0;
+ tprintf("DTIM Count: %u, ", tim->dtim_cnt);
+ tprintf("DTIM Period: %u, ", tim->dtim_period);
+ tprintf("Bitmap Control: %u, ", tim->bmp_cntrl);
+ if ((tim->len - sizeof(*tim) + 1) > 0) {
+ u8 *bmp = pkt_pull(pkt, (tim->len - sizeof(*tim) + 1));
+ if (bmp == NULL)
+ return 0;
+
+ tprintf("Partial Virtual Bitmap: 0x");
+ for (i = 0; i < (tim->len - sizeof(*tim) + 1); i++)
+ tprintf("%.2x", bmp[i]);
+ }
+
+ return 1;
+}
+
+static int8_t inf_ibss_ps(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_ibss_ps *ibss_ps;
+
+ ibss_ps = (struct element_ibss_ps *) pkt_pull(pkt, sizeof(*ibss_ps));
+ if (ibss_ps == NULL)
+ return 0;
+
+ tprintf(" IBSS Param Set (%u, Len(%u)): ", *id, ibss_ps->len);
+ if (len_neq_error(ibss_ps->len, 2))
+ return 0;
+ tprintf("ATIM Window: %fs", le16_to_cpu(ibss_ps->atim_win) * TU);
+
+ return 1;
+}
+
+static int8_t inf_country(struct pkt_buff *pkt, u8 *id)
+{
+ u8 i;
+ u8 *pad;
+ struct element_country *country;
+
+ country = (struct element_country *) pkt_pull(pkt, sizeof(*country));
+ if (country == NULL)
+ return 0;
+
+ tprintf(" Country (%u, Len(%u)): ", *id, country->len);
+ if (len_lt_error(country->len, 6))
+ return 0;
+ tprintf("Country String: %c%c%c", country->country_first,
+ country->country_sec, country->country_third);
+
+ for (i = country->len % 3; i < (country->len - 3); i += 3) {
+ struct element_country_tripled *country_tripled;
+
+ country_tripled = (struct element_country_tripled *)
+ pkt_pull(pkt, sizeof(*country_tripled));
+ if (country_tripled == NULL)
+ return 0;
+
+ if(country_tripled->frst_ch >= 201) {
+ tprintf("Oper Ext ID: %u, ", country_tripled->frst_ch);
+ tprintf("Operating Class: %u, ", country_tripled->nr_ch);
+ tprintf("Coverage Class: %u", country_tripled->max_trans);
+ } else {
+ tprintf("First Ch Nr: %u, ", country_tripled->frst_ch);
+ tprintf("Nr of Ch: %u, ", country_tripled->nr_ch);
+ tprintf("Max Transmit Pwr Lvl: %u", country_tripled->max_trans);
+ }
+ }
+
+ if(country->len % 3) {
+ pad = pkt_pull(pkt, 1);
+ if (pad == NULL)
+ return 0;
+
+ tprintf(", Pad: 0x%x", *pad);
+ }
+
+ return 1;
+}
+
+static int8_t inf_hop_pp(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_hop_pp *hop_pp;
+
+ hop_pp = (struct element_hop_pp *) pkt_pull(pkt, sizeof(*hop_pp));
+ if (hop_pp == NULL)
+ return 0;
+
+ tprintf(" Hopping Pattern Param (%u, Len(%u)): ", *id, hop_pp->len);
+ if (len_neq_error(hop_pp->len, 2))
+ return 0;
+ tprintf("Prime Radix: %u, ", hop_pp->prime_radix);
+ tprintf("Nr of Ch: %u", hop_pp->nr_ch);
+
+ return 1;
+}
+
+static int8_t inf_hop_pt(struct pkt_buff *pkt, u8 *id)
+{
+ int i;
+ u8 *rand_tabl;
+ struct element_hop_pt *hop_pt;
+
+ hop_pt = (struct element_hop_pt *) pkt_pull(pkt, sizeof(*hop_pt));
+ if (hop_pt == NULL)
+ return 0;
+
+ tprintf(" Hopping Pattern Table (%u, Len(%u)): ", *id, hop_pt->len);
+ if (len_lt_error(hop_pt->len, 4))
+ return 0;
+ tprintf("Flag: %u, ", hop_pt->flag);
+ tprintf("Nr of Sets: %u, ", hop_pt->nr_sets);
+ tprintf("Modulus: %u, ", hop_pt->modules);
+ tprintf("Offs: %u", hop_pt->offs);
+
+ if ((hop_pt->len - sizeof(*hop_pt) + 1) > 0) {
+ rand_tabl = pkt_pull(pkt, (hop_pt->len - sizeof(*hop_pt) + 1));
+ if (rand_tabl == NULL)
+ return 0;
+
+ tprintf(", Rand table: 0x");
+ for (i = 0; i < (hop_pt->len - sizeof(*hop_pt) + 1); i++)
+ tprintf("%.2x", rand_tabl[i]);
+ }
+
+ return 1;
+}
+
+static int8_t inf_req(struct pkt_buff *pkt, u8 *id)
+{
+ int i;
+ struct element_req *req;
+ u8 *req_ids;
+
+ req = (struct element_req *) pkt_pull(pkt, sizeof(*req));
+ if (req == NULL)
+ return 0;
+
+ tprintf(" Request Element (%u, Len(%u)): ", *id, req->len);
+ if ((req->len - sizeof(*req) + 1) > 0) {
+ req_ids = pkt_pull(pkt, (req->len - sizeof(*req) + 1));
+ if (req_ids == NULL)
+ return 0;
+
+ tprintf(", Requested Element IDs: ");
+ for (i = 0; i < (req->len - sizeof(*req) + 1); i++)
+ tprintf("%u ", req_ids[i]);
+ }
+
+ return 1;
+}
+
+static int8_t inf_bss_load(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_bss_load *bss_load;
+
+ bss_load = (struct element_bss_load *) pkt_pull(pkt, sizeof(*bss_load));
+ if (bss_load == NULL)
+ return 0;
+
+ tprintf(" BSS Load element (%u, Len(%u)): ", *id, bss_load->len);
+ if (len_neq_error(bss_load->len, 5))
+ return 0;
+ tprintf("Station Count: %u, ", le16_to_cpu(bss_load->station_cnt));
+ tprintf("Channel Utilization: %u, ", bss_load->ch_util);
+ tprintf("Available Admission Capacity: %uus",
+ bss_load->avlb_adm_cap * 32);
+
+ return 1;
+}
+
+static int8_t inf_edca_ps(struct pkt_buff *pkt, u8 *id)
+{
+ u32 ac_be, ac_bk, ac_vi, ac_vo;
+ struct element_edca_ps *edca_ps;
+
+ edca_ps = (struct element_edca_ps *) pkt_pull(pkt, sizeof(*edca_ps));
+ if (edca_ps == NULL)
+ return 0;
+
+ ac_be = le32_to_cpu(edca_ps->ac_be);
+ ac_bk = le32_to_cpu(edca_ps->ac_bk);
+ ac_vi = le32_to_cpu(edca_ps->ac_vi);
+ ac_vo = le32_to_cpu(edca_ps->ac_vo);
+
+ tprintf(" EDCA Param Set (%u, Len(%u)): ", *id, edca_ps->len);
+ if (len_neq_error(edca_ps->len, 18))
+ return 0;
+ tprintf("QoS Info: 0x%x (-> EDCA Param Set Update Count (%u),"
+ "Q-Ack (%u), Queue Re (%u), TXOP Req(%u), Res(%u)), ",
+ edca_ps->qos_inf, edca_ps->qos_inf >> 4,
+ (edca_ps->qos_inf >> 3) & 1, (edca_ps->qos_inf >> 2) & 1,
+ (edca_ps->qos_inf >> 1) & 1, edca_ps->qos_inf & 1);
+ tprintf("Reserved: 0x%x, ", edca_ps->res);
+ tprintf("AC_BE Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
+ "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_be,
+ ac_be >> 28, (ac_be >> 27) & 1, (ac_be >> 25) & 3,
+ (ac_be >> 24) & 1, (ac_be >> 20) & 15, (ac_be >> 16) & 15,
+ bswap_16(ac_be & 0xFFFF) * 32);
+ tprintf("AC_BK Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
+ "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_bk,
+ ac_bk >> 28, (ac_bk >> 27) & 1, (ac_bk >> 25) & 3,
+ (ac_bk >> 24) & 1, (ac_bk >> 20) & 15, (ac_bk >> 16) & 15,
+ bswap_16(ac_bk & 0xFFFF) * 32);
+ tprintf("AC_VI Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
+ "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)), ", ac_vi,
+ ac_vi >> 28, (ac_vi >> 27) & 1, (ac_vi >> 25) & 3,
+ (ac_vi >> 24) & 1, (ac_vi >> 20) & 15, (ac_vi >> 16) & 15,
+ bswap_16(ac_vi & 0xFFFF) * 32);
+ tprintf("AC_VO Param Rec: 0x%x (-> AIFSN (%u), ACM (%u), ACI (%u),"
+ "Res (%u), ECWmin (%u), ECWmax(%u)), TXOP Limit (%uus)", ac_vo,
+ ac_vo >> 28, (ac_vo >> 27) & 1, (ac_vo >> 25) & 3,
+ (ac_vo >> 24) & 1, (ac_vo >> 20) & 15, (ac_vo >> 16) & 15,
+ bswap_16(ac_vo & 0xFFFF) * 32);
+
+ return 1;
+}
+
+static int8_t inf_tspec(struct pkt_buff *pkt, u8 *id)
+{
+ u16 nom_msdu_size, surplus_bandw_allow;
+ struct element_tspec *tspec;
+
+ tspec = (struct element_tspec *) pkt_pull(pkt, sizeof(*tspec));
+ if (tspec == NULL)
+ return 0;
+
+ nom_msdu_size = le16_to_cpu(tspec->nom_msdu_size);
+ surplus_bandw_allow = le16_to_cpu(tspec->surplus_bandw_allow);
+
+ tprintf(" TSPEC (%u, Len(%u)): ", *id, tspec->len);
+ if (len_neq_error(tspec->len, 55))
+ return 0;
+ tprintf("Traffic Type: %u, ", tspec->traffic_type);
+ tprintf("TSID: %u, ", tspec->tsid);
+ tprintf("Direction: %u, ", tspec->direction);
+ tprintf("Access Policy: %u, ", tspec->access_policy);
+ tprintf("Aggregation: %u, ", tspec->aggr);
+ tprintf("APSD: %u, ", tspec->apsd);
+ tprintf("User Priority: %u, ", tspec->user_prior);
+ tprintf("TSinfo Ack Policy: %u, ", tspec->tsinfo_ack_pol);
+ tprintf("Schedule: %u, ", tspec->schedule);
+ tprintf("Reserved: 0x%x, ", tspec->res);
+ tprintf("Nominal MSDU Size: %uB (Fixed (%u)), ",
+ nom_msdu_size >> 1, nom_msdu_size & 1);
+ tprintf("Maximum MSDU Size: %uB, ", le16_to_cpu(tspec->max_msdu_size));
+ tprintf("Minimum Service Interval: %uus, ",
+ le32_to_cpu(tspec->min_srv_intv));
+ tprintf("Maximum Service Interval: %uus, ",
+ le32_to_cpu(tspec->max_srv_intv));
+ tprintf("Inactivity Interval: %uus, ",
+ le32_to_cpu(tspec->inactive_intv));
+ tprintf("Suspension Interval: %uus, ", le32_to_cpu(tspec->susp_intv));
+ tprintf("Service Start Time: %uus, ",
+ le32_to_cpu(tspec->srv_start_time));
+ tprintf("Minimum Data Rate: %ub/s, ",le32_to_cpu(tspec->min_data_rate));
+ tprintf("Mean Data Rate: %ub/s, ", le32_to_cpu(tspec->mean_data_rate));
+ tprintf("Peak Data Rate: %ub/s, ",le32_to_cpu(tspec->peak_data_rate));
+ tprintf("Burst Size: %uB, ", le32_to_cpu(tspec->burst_size));
+ tprintf("Delay Bound: %uus, ", le32_to_cpu(tspec->delay_bound));
+ tprintf("Minimum PHY Rate: %ub/s, ", le32_to_cpu(tspec->min_phy_rate));
+ tprintf("Surplus Bandwidth: %u.%u, ", surplus_bandw_allow >> 13,
+ surplus_bandw_allow & 0x1FFF);
+ tprintf("Medium Time: %uus", le16_to_cpu(tspec->med_time) * 32);
+
+ return 1;
+}
+
+static const char *class_type(u8 type)
+{
+ switch (type) {
+ case 0: return "Ethernet parameters";
+ case 1: return "TCP/UDP IP parameters";
+ case 2: return "IEEE 802.1Q parameters";
+ case 3: return "Filter Offset parameters";
+ case 4: return "IP and higher layer parameters";
+ case 5: return "IEEE 802.1D/Q parameters";
+ default: return "Reserved";
+ }
+}
+
+static int8_t inf_tclas(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_tclas *tclas;
+ struct element_tclas_frm_class *frm_class;
+
+ tclas = (struct element_tclas *) pkt_pull(pkt, sizeof(*tclas));
+ if (tclas == NULL)
+ return 0;
+
+ frm_class = (struct element_tclas_frm_class *)
+ pkt_pull(pkt, sizeof(*frm_class));
+ if (frm_class == NULL)
+ return 0;
+
+ tprintf(" TCLAS (%u, Len(%u)): ", *id, tclas->len);
+ if (len_lt_error(tclas->len, 3))
+ return 0;
+ tprintf("User Priority: %u, ", tclas->user_priority);
+ tprintf("Classifier Type: %s (%u), ", class_type(frm_class->type),
+ frm_class->type);
+ tprintf("Classifier Mask: 0x%x, ", frm_class->mask);
+
+ if(frm_class->type == 0) {
+ struct element_tclas_type0 *type0;
+
+ type0 = (struct element_tclas_type0 *)
+ pkt_pull(pkt, sizeof(*type0));
+ if (type0 == NULL)
+ return 0;
+
+ /* I think little endian, like the rest */
+ tprintf("Src Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
+ type0->sa[5], type0->sa[4], type0->sa[3],
+ type0->sa[2], type0->sa[1], type0->sa[0]);
+ tprintf("Dst Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
+ type0->da[5], type0->da[4], type0->da[3],
+ type0->da[2], type0->da[1], type0->da[0]);
+ tprintf("Type: 0x%x", le16_to_cpu(type0->type));
+ }
+ else if(frm_class->type == 1) {
+ struct element_tclas_type1 *type1;
+
+ type1 = (struct element_tclas_type1 *)
+ pkt_pull(pkt, sizeof(*type1));
+ if (type1 == NULL)
+ return 0;
+
+ tprintf("Version: %u, ", type1->version);
+ /* big endian format follows */
+ if(type1->version == 4) {
+ struct element_tclas_type1_ip4 *type1_ip4;
+ char src_ip[INET_ADDRSTRLEN];
+ char dst_ip[INET_ADDRSTRLEN];
+
+ type1_ip4 = (struct element_tclas_type1_ip4 *)
+ pkt_pull(pkt, sizeof(*type1_ip4));
+ if (type1_ip4 == NULL)
+ return 0;
+
+ inet_ntop(AF_INET, &type1_ip4->sa, src_ip, sizeof(src_ip));
+ inet_ntop(AF_INET, &type1_ip4->da, dst_ip, sizeof(dst_ip));
+
+ tprintf("Src IP: %s, ", src_ip);
+ tprintf("Dst IP: %s, ", dst_ip);
+ tprintf("Src Port: %u, ", ntohs(type1_ip4->sp));
+ tprintf("Dst Port: %u, ", ntohs(type1_ip4->dp));
+ tprintf("DSCP: 0x%x, ", type1_ip4->dscp);
+ tprintf("Proto: %u, ", type1_ip4->proto);
+ tprintf("Res: 0x%x", type1_ip4->reserved);
+ }
+ else if(type1->version == 6) {
+ struct element_tclas_type1_ip6 *type1_ip6;
+ char src_ip[INET6_ADDRSTRLEN];
+ char dst_ip[INET6_ADDRSTRLEN];
+
+ type1_ip6 = (struct element_tclas_type1_ip6 *)
+ pkt_pull(pkt, sizeof(*type1_ip6));
+ if (type1_ip6 == NULL)
+ return 0;
+
+ inet_ntop(AF_INET6, &type1_ip6->sa,
+ src_ip, sizeof(src_ip));
+ inet_ntop(AF_INET6, &type1_ip6->da,
+ dst_ip, sizeof(dst_ip));
+
+ tprintf("Src IP: %s, ", src_ip);
+ tprintf("Dst IP: %s, ", dst_ip);
+ tprintf("Src Port: %u, ", ntohs(type1_ip6->sp));
+ tprintf("Dst Port: %u, ", ntohs(type1_ip6->dp));
+ tprintf("Flow Label: 0x%x%x%x", type1_ip6->flow_label1,
+ type1_ip6->flow_label2, type1_ip6->flow_label3);
+ }
+ else {
+ tprintf("Version (%u) not supported", type1->version);
+ return 0;
+ }
+
+ }
+ else if(frm_class->type == 2) {
+ struct element_tclas_type2 *type2;
+
+ type2 = (struct element_tclas_type2 *)
+ pkt_pull(pkt, sizeof(*type2));
+ if (type2 == NULL)
+ return 0;
+
+ tprintf("802.1Q VLAN TCI: 0x%x", ntohs(type2->vlan_tci));
+ }
+ else if(frm_class->type == 3) {
+ struct element_tclas_type3 *type3;
+ u8 len, i;
+ u8 *val;
+
+ type3 = (struct element_tclas_type3 *)
+ pkt_pull(pkt, sizeof(*type3));
+ if (type3 == NULL)
+ return 0;
+
+ len = (tclas->len - 5) / 2;
+
+ tprintf("Filter Offset: %u, ", type3->offs);
+
+ if((len & 1) || (len_lt_error(tclas->len, 5))) {
+ tprintf("Length of TCLAS (%u) not correct", tclas->len);
+ return 0;
+ }
+ else {
+ val = pkt_pull(pkt, len);
+ if (val == NULL)
+ return 0;
+
+ tprintf("Filter Value: 0x");
+ for (i = 0; i < len / 2; i++)
+ tprintf("%x ", val[i]);
+ tprintf(", ");
+ tprintf("Filter Mask: 0x");
+ for (i = len / 2; i < len; i++)
+ tprintf("%x ", val[i]);
+ }
+
+ }
+ else if(frm_class->type == 4) {
+ struct element_tclas_type4 *type4;
+
+ type4 = (struct element_tclas_type4 *)
+ pkt_pull(pkt, sizeof(*type4));
+ if (type4 == NULL)
+ return 0;
+
+ tprintf("Version: %u, ", type4->version);
+ /* big endian format follows */
+ if(type4->version == 4) {
+ struct element_tclas_type4_ip4 *type4_ip4;
+ char src_ip[INET_ADDRSTRLEN];
+ char dst_ip[INET_ADDRSTRLEN];
+
+ type4_ip4 = (struct element_tclas_type4_ip4 *)
+ pkt_pull(pkt, sizeof(*type4_ip4));
+ if (type4_ip4 == NULL)
+ return 0;
+
+ inet_ntop(AF_INET, &type4_ip4->sa, src_ip, sizeof(src_ip));
+ inet_ntop(AF_INET, &type4_ip4->da, dst_ip, sizeof(dst_ip));
+
+ tprintf("Src IP: %s, ", src_ip);
+ tprintf("Dst IP: %s, ", dst_ip);
+ tprintf("Src Port: %u, ", ntohs(type4_ip4->sp));
+ tprintf("Dst Port: %u, ", ntohs(type4_ip4->dp));
+ tprintf("DSCP: 0x%x, ", type4_ip4->dscp);
+ tprintf("Proto: %u, ", type4_ip4->proto);
+ tprintf("Res: 0x%x", type4_ip4->reserved);
+ }
+ else if(type4->version == 6) {
+ struct element_tclas_type4_ip6 *type4_ip6;
+ char src_ip[INET6_ADDRSTRLEN];
+ char dst_ip[INET6_ADDRSTRLEN];
+
+ type4_ip6 = (struct element_tclas_type4_ip6 *)
+ pkt_pull(pkt, sizeof(*type4_ip6));
+ if (type4_ip6 == NULL)
+ return 0;
+
+ inet_ntop(AF_INET6, &type4_ip6->sa,
+ src_ip, sizeof(src_ip));
+ inet_ntop(AF_INET6, &type4_ip6->da,
+ dst_ip, sizeof(dst_ip));
+
+ tprintf("Src IP: %s, ", src_ip);
+ tprintf("Dst IP: %s, ", dst_ip);
+ tprintf("Src Port: %u, ", ntohs(type4_ip6->sp));
+ tprintf("Dst Port: %u, ", ntohs(type4_ip6->dp));
+ tprintf("DSCP: 0x%x, ", type4_ip6->dscp);
+ tprintf("Nxt Hdr: %u, ", type4_ip6->nxt_hdr);
+ tprintf("Flow Label: 0x%x%x%x", type4_ip6->flow_label1,
+ type4_ip6->flow_label2, type4_ip6->flow_label3);
+ }
+ else {
+ tprintf("Version (%u) not supported", type4->version);
+ return 0;
+ }
+ }
+ else if(frm_class->type == 5) {
+ struct element_tclas_type5 *type5;
+
+ type5 = (struct element_tclas_type5 *)
+ pkt_pull(pkt, sizeof(*type5));
+ if (type5 == NULL)
+ return 0;
+
+ tprintf("802.1Q PCP: 0x%x, ", type5->pcp);
+ tprintf("802.1Q CFI: 0x%x, ", type5->cfi);
+ tprintf("802.1Q VID: 0x%x", type5->vid);
+ }
+ else {
+ tprintf("Classifier Type (%u) not supported", frm_class->type);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int8_t inf_sched(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_schedule *schedule;
+ u16 info;
+
+ schedule = (struct element_schedule *) pkt_pull(pkt, sizeof(*schedule));
+ if (schedule == NULL)
+ return 0;
+
+ info = le16_to_cpu(schedule->inf);
+
+ tprintf(" Schedule (%u, Len(%u)): ", *id, schedule->len);
+ if (len_neq_error(schedule->len, 12))
+ return 0;
+
+ tprintf("Aggregation: %u, ", info >> 15);
+ tprintf("TSID: %u, ", (info >> 11) & 0xF);
+ tprintf("Direction: %u, ", (info >> 9) & 0x3);
+ tprintf("Res: %u, ", info & 0x1FF);
+ tprintf("Serv Start Time: %uus, ", le32_to_cpu(schedule->start));
+ tprintf("Serv Interval: %uus, ", le32_to_cpu(schedule->serv_intv));
+ tprintf("Spec Interval: %fs", le32_to_cpu(schedule->spec_intv) * TU);
+
+ return 1;
+}
+
+static int8_t inf_chall_txt(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_chall_txt *chall_txt;
+ u8 i;
+ u8 *txt;
+
+ chall_txt = (struct element_chall_txt *)
+ pkt_pull(pkt, sizeof(*chall_txt));
+ if (chall_txt == NULL)
+ return 0;
+
+ tprintf(" Challenge Text (%u, Len(%u)): ", *id, chall_txt->len);
+ if ((chall_txt->len - sizeof(*chall_txt) + 1) > 0) {
+ txt = pkt_pull(pkt, (chall_txt->len - sizeof(*chall_txt) + 1));
+ if (txt == NULL)
+ return 0;
+
+ tprintf("0x");
+ for (i = 0; i < (chall_txt->len - sizeof(*chall_txt) + 1); i++)
+ tprintf("%x", txt[i]);
+ }
+
+ return 1;
+}
+
+static int8_t inf_pwr_constr(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_pwr_constr *pwr_constr;
+
+ pwr_constr = (struct element_pwr_constr *) pkt_pull(pkt, sizeof(*pwr_constr));
+ if (pwr_constr == NULL)
+ return 0;
+
+ tprintf(" Power Constraint (%u, Len(%u)): ", *id, pwr_constr->len);
+ if (len_neq_error(pwr_constr->len, 1))
+ return 0;
+
+ tprintf("Local Power Constraint: %udB", pwr_constr->local_pwr_constr);
+
+ return 1;
+}
+
+static int8_t inf_pwr_cap(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_pwr_cap *pwr_cap;
+
+ pwr_cap = (struct element_pwr_cap *) pkt_pull(pkt, sizeof(*pwr_cap));
+ if (pwr_cap == NULL)
+ return 0;
+
+ tprintf(" Power Capability (%u, Len(%u)): ", *id, pwr_cap->len);
+ if (len_neq_error(pwr_cap->len, 2))
+ return 0;
+
+ tprintf("Min. Transm. Pwr Cap.: %ddBm, ", (int8_t)pwr_cap->min_pwr_cap);
+ tprintf("Max. Transm. Pwr Cap.: %ddBm", (int8_t)pwr_cap->max_pwr_cap);
+
+ return 1;
+}
+
+static int8_t inf_tpc_req(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_tpc_req *tpc_req;
+
+ tpc_req = (struct element_tpc_req *) pkt_pull(pkt, sizeof(*tpc_req));
+ if (tpc_req == NULL)
+ return 0;
+
+ tprintf(" TPC Request (%u, Len(%u))", *id, tpc_req->len);
+ if (len_neq_error(tpc_req->len, 0))
+ return 0;
+
+ return 1;
+}
+
+static int8_t inf_tpc_rep(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_tpc_rep *tpc_rep;
+
+ tpc_rep = (struct element_tpc_rep *) pkt_pull(pkt, sizeof(*tpc_rep));
+ if (tpc_rep == NULL)
+ return 0;
+
+ tprintf(" TPC Report (%u, Len(%u)): ", *id, tpc_rep->len);
+ if (len_neq_error(tpc_rep->len, 2))
+ return 0;
+
+ tprintf("Transmit Power: %udBm, ", (int8_t)tpc_rep->trans_pwr);
+ tprintf("Link Margin: %udB", (int8_t)tpc_rep->trans_pwr);
+
+ return 1;
+}
+
+static int8_t inf_supp_ch(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_supp_ch *supp_ch;
+ u8 i;
+
+ supp_ch = (struct element_supp_ch *) pkt_pull(pkt, sizeof(*supp_ch));
+ if (supp_ch == NULL)
+ return 0;
+
+ tprintf(" Supp Channels (%u, Len(%u)): ", *id, supp_ch->len);
+ if (len_lt_error(supp_ch->len, 2))
+ return 0;
+
+ if(supp_ch->len & 1) {
+ tprintf("Length should be even");
+ return 0;
+ }
+
+ for (i = 0; i < supp_ch->len; i += 2) {
+ struct element_supp_ch_tuple *supp_ch_tuple;
+
+ supp_ch_tuple = (struct element_supp_ch_tuple *)
+ pkt_pull(pkt, sizeof(*supp_ch_tuple));
+ if (supp_ch_tuple == NULL)
+ return 0;
+
+ tprintf("First Channel Nr: %u, ", supp_ch_tuple->first_ch_nr);
+ tprintf("Nr of Channels: %u, ", supp_ch_tuple->nr_ch);
+ }
+
+ return 1;
+}
+
+static int8_t inf_ch_sw_ann(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_ch_sw_ann *ch_sw_ann;
+
+ ch_sw_ann = (struct element_ch_sw_ann *)
+ pkt_pull(pkt, sizeof(*ch_sw_ann));
+ if (ch_sw_ann == NULL)
+ return 0;
+
+ tprintf(" Channel Switch Announc (%u, Len(%u)): ", *id, ch_sw_ann->len);
+ if (len_neq_error(ch_sw_ann->len, 3))
+ return 0;
+
+ tprintf("Switch Mode: %u, ", ch_sw_ann->switch_mode);
+ tprintf("New Nr: %u, ", ch_sw_ann->new_nr);
+ tprintf("Switch Count: %u", ch_sw_ann->switch_cnt);
+
+ return 1;
+}
+
+static const char *meas_type(u8 type)
+{
+ switch (type) {
+ case 0: return "Basic";
+ case 1: return "Clear Channel assesment (CCA)";
+ case 2: return "Receive power indication (RPI) histogram";
+ case 3: return "Channel load";
+ case 4: return "Noise histogram";
+ case 5: return "Beacon";
+ case 6: return "Frame";
+ case 7: return "STA statistics";
+ case 8: return "LCI";
+ case 9: return "Transmit stream/category measurement";
+ case 10: return "Multicast diagnostics";
+ case 11: return "Location Civic";
+ case 12: return "Location Identifier";
+ case 13 ... 255: return "Reserved";
+ }
+}
+
+static int8_t inf_meas_req(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_meas_req *meas_req;
+
+ meas_req = (struct element_meas_req *) pkt_pull(pkt, sizeof(*meas_req));
+ if (meas_req == NULL)
+ return 0;
+
+ tprintf(" Measurement Req (%u, Len(%u)): ", *id, meas_req->len);
+ if (len_lt_error(meas_req->len, 3))
+ return 0;
+
+ tprintf("Token: %u, ", meas_req->token);
+ tprintf("Req Mode: 0x%x (Parallel (%u), Enable(%u), Request(%u), "
+ "Report(%u), Dur Mand(%u), Res(0x%x)), ", meas_req->req_mode,
+ meas_req->req_mode & 0x1,
+ (meas_req->req_mode >> 1) & 0x1,
+ (meas_req->req_mode >> 2) & 0x1,
+ (meas_req->req_mode >> 3) & 0x1,
+ (meas_req->req_mode >> 4) & 0x1,
+ meas_req->req_mode >> 7);
+ tprintf("Type: %s (%u), ", meas_type(meas_req->type), meas_req->type);
+
+ if(meas_req->len > 3) {
+ if(meas_req->type == 0) {
+ struct element_meas_basic *basic;
+
+ basic = (struct element_meas_basic *)
+ pkt_pull(pkt, sizeof(*basic));
+ if (basic == NULL)
+ return 0;
+
+ if ((meas_req->len - 3 - sizeof(*basic)) != 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Ch Nr: %uus, ", basic->ch_nr);
+ tprintf("Meas Start Time: %lu, ",
+ le64_to_cpu(basic->start));
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(basic->dur) * TU);
+
+ }
+ else if(meas_req->type == 1) {
+ struct element_meas_cca *cca;
+
+ cca = (struct element_meas_cca *)
+ pkt_pull(pkt, sizeof(*cca));
+ if (cca == NULL)
+ return 0;
+
+ if ((meas_req->len - 3 - sizeof(*cca)) != 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Ch Nr: %uus, ", cca->ch_nr);
+ tprintf("Meas Start Time: %lu, ",
+ le64_to_cpu(cca->start));
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(cca->dur) * TU);
+ }
+ else if(meas_req->type == 2) {
+ struct element_meas_rpi *rpi;
+
+ rpi = (struct element_meas_rpi *)
+ pkt_pull(pkt, sizeof(*rpi));
+ if (rpi == NULL)
+ return 0;
+
+ if ((meas_req->len - 3 - sizeof(*rpi)) != 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Ch Nr: %uus, ", rpi->ch_nr);
+ tprintf("Meas Start Time: %lu, ",
+ le64_to_cpu(rpi->start));
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(rpi->dur) * TU);
+ }
+ else if(meas_req->type == 3) {
+ struct element_meas_ch_load *ch_load;
+
+ ch_load = (struct element_meas_ch_load *)
+ pkt_pull(pkt, sizeof(*ch_load));
+ if (ch_load == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*ch_load)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("OP Class: %u, ", ch_load->op_class);
+ tprintf("Ch Nr: %u, ", ch_load->ch_nr);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(ch_load->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(ch_load->dur) * TU);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*ch_load)))
+ return 0;
+ }
+ else if(meas_req->type == 4) {
+ struct element_meas_noise *noise;
+
+ noise = (struct element_meas_noise *)
+ pkt_pull(pkt, sizeof(*noise));
+ if (noise == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*noise)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("OP Class: %u, ", noise->op_class);
+ tprintf("Ch Nr: %u, ", noise->ch_nr);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(noise->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(noise->dur) * TU);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*noise)))
+ return 0;
+ }
+ else if(meas_req->type == 5) {
+ struct element_meas_beacon *beacon;
+
+ beacon = (struct element_meas_beacon *)
+ pkt_pull(pkt, sizeof(*beacon));
+ if (beacon == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*beacon)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("OP Class: %u, ", beacon->op_class);
+ tprintf("Ch Nr: %u, ", beacon->ch_nr);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(beacon->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(beacon->dur) * TU);
+ tprintf("Mode: %u, ", beacon->mode);
+ tprintf("BSSID: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ beacon->bssid[0], beacon->bssid[1],
+ beacon->bssid[2], beacon->bssid[3],
+ beacon->bssid[4], beacon->bssid[5]);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*beacon)))
+ return 0;
+ }
+ else if(meas_req->type == 6) {
+ struct element_meas_frame *frame;
+
+ frame = (struct element_meas_frame *)
+ pkt_pull(pkt, sizeof(*frame));
+ if (frame == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*frame)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("OP Class: %u, ", frame->op_class);
+ tprintf("Ch Nr: %u, ", frame->ch_nr);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(frame->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(frame->dur) * TU);
+ tprintf("Request Type: %u, ", frame->frame);
+ tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ frame->mac[0], frame->mac[1],
+ frame->mac[2], frame->mac[3],
+ frame->mac[4], frame->mac[5]);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*frame)))
+ return 0;
+ }
+ else if(meas_req->type == 7) {
+ struct element_meas_sta *sta;
+
+ sta = (struct element_meas_sta *)
+ pkt_pull(pkt, sizeof(*sta));
+ if (sta == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*sta)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Peer MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ sta->peer_mac[0], sta->peer_mac[1],
+ sta->peer_mac[2], sta->peer_mac[3],
+ sta->peer_mac[4], sta->peer_mac[5]);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(sta->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(sta->dur) * TU);
+ tprintf("Group ID: %u, ", sta->group_id);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*sta)))
+ return 0;
+ }
+ else if(meas_req->type == 8) {
+ struct element_meas_lci *lci;
+
+ lci = (struct element_meas_lci *)
+ pkt_pull(pkt, sizeof(*lci));
+ if (lci == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*lci)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Location Subj: %u, ", lci->loc_subj);
+ tprintf("Latitude Req Res: %udeg",
+ lci->latitude_req_res);
+ tprintf("Longitude Req Res: %udeg",
+ lci->longitude_req_res);
+ tprintf("Altitude Req Res: %udeg",
+ lci->altitude_req_res);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*lci)))
+ return 0;
+ }
+ else if(meas_req->type == 9) {
+ struct element_meas_trans_str_cat *trans;
+
+ trans = (struct element_meas_trans_str_cat *)
+ pkt_pull(pkt, sizeof(*trans));
+ if (trans == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*trans)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(trans->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(trans->dur) * TU);
+ tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ trans->peer_sta_addr[0], trans->peer_sta_addr[1],
+ trans->peer_sta_addr[2], trans->peer_sta_addr[3],
+ trans->peer_sta_addr[4], trans->peer_sta_addr[5]);
+ tprintf("Traffic ID: %u, ", trans->traffic_id);
+ tprintf("Bin 0 Range: %u, ", trans->bin_0_range);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*trans)))
+ return 0;
+ }
+ else if(meas_req->type == 10) {
+ struct element_meas_mcast_diag *mcast;
+
+ mcast = (struct element_meas_mcast_diag *)
+ pkt_pull(pkt, sizeof(*mcast));
+ if (mcast == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*mcast)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(mcast->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(mcast->dur) * TU);
+ tprintf("Group MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ mcast->group_mac[0], mcast->group_mac[1],
+ mcast->group_mac[2], mcast->group_mac[3],
+ mcast->group_mac[4], mcast->group_mac[5]);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*mcast)))
+ return 0;
+ }
+ else if(meas_req->type == 11) {
+ struct element_meas_loc_civic *civic;
+
+ civic = (struct element_meas_loc_civic *)
+ pkt_pull(pkt, sizeof(*civic));
+ if (civic == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*civic)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Location Subj: %u, ", civic->loc_subj);
+ tprintf("Type: %u, ", civic->civic_loc);
+ tprintf("Srv Intv Units: %u, ",
+ le16_to_cpu(civic->loc_srv_intv_unit));
+ tprintf("Srv Intv: %u, ", civic->loc_srv_intv);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*civic)))
+ return 0;
+ }
+ else if(meas_req->type == 12) {
+ struct element_meas_loc_id *id;
+
+ id = (struct element_meas_loc_id *)
+ pkt_pull(pkt, sizeof(*id));
+ if (id == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*id)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Location Subj: %u, ", id->loc_subj);
+ tprintf("Srv Intv Units: %u, ",
+ le16_to_cpu(id->loc_srv_intv_unit));
+ tprintf("Srv Intv: %u", id->loc_srv_intv);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*id)))
+ return 0;
+ }
+ else if(meas_req->type == 255) {
+ struct element_meas_pause *pause;
+
+ pause = (struct element_meas_pause *)
+ pkt_pull(pkt, sizeof(*pause));
+ if (pause == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_req->len - 3 - sizeof(*pause)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_req->type);
+ return 0;
+ }
+
+ tprintf("Pause Time: %fs, ", pause->time * 10 * TU);
+
+ if(!subelements(pkt,
+ meas_req->len - 3 - sizeof(*pause)))
+ return 0;
+ }
+ else {
+ tprintf("Length field indicates data,"
+ " but could not interpreted");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int8_t inf_meas_rep(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_meas_rep *meas_rep;
+
+ meas_rep = (struct element_meas_rep *) pkt_pull(pkt, sizeof(*meas_rep));
+ if (meas_rep == NULL)
+ return 0;
+
+ tprintf(" Measurement Rep (%u, Len(%u)): ", *id, meas_rep->len);
+ if (len_lt_error(meas_rep->len, 3))
+ return 0;
+
+ tprintf("Token: %u, ", meas_rep->token);
+ tprintf("Rep Mode: 0x%x (Late (%u), Incapable(%u), Refused(%u), ",
+ meas_rep->rep_mode, meas_rep->rep_mode >> 7,
+ (meas_rep->rep_mode >> 6) & 0x1,
+ (meas_rep->rep_mode >> 5) & 0x1);
+ tprintf("Type: %s (%u), ", meas_type(meas_rep->type), meas_rep->type);
+
+ if(meas_rep->len > 3) {
+ if(meas_rep->type == 0) {
+ struct element_meas_basic *basic;
+
+ basic = (struct element_meas_basic *)
+ pkt_pull(pkt, sizeof(*basic));
+ if (basic == NULL)
+ return 0;
+
+ if ((meas_rep->len - 3 - sizeof(*basic)) != 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Ch Nr: %uus, ", basic->ch_nr);
+ tprintf("Meas Start Time: %lu, ",
+ le64_to_cpu(basic->start));
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(basic->dur) * TU);
+
+ }
+ else if(meas_rep->type == 1) {
+ struct element_meas_cca *cca;
+
+ cca = (struct element_meas_cca *)
+ pkt_pull(pkt, sizeof(*cca));
+ if (cca == NULL)
+ return 0;
+
+ if ((meas_rep->len - 3 - sizeof(*cca)) != 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Ch Nr: %uus, ", cca->ch_nr);
+ tprintf("Meas Start Time: %lu, ",
+ le64_to_cpu(cca->start));
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(cca->dur) * TU);
+ }
+ else if(meas_rep->type == 2) {
+ struct element_meas_rpi *rpi;
+
+ rpi = (struct element_meas_rpi *)
+ pkt_pull(pkt, sizeof(*rpi));
+ if (rpi == NULL)
+ return 0;
+
+ if ((meas_rep->len - 3 - sizeof(*rpi)) != 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Ch Nr: %uus, ", rpi->ch_nr);
+ tprintf("Meas Start Time: %lu, ",
+ le64_to_cpu(rpi->start));
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(rpi->dur) * TU);
+ }
+ else if(meas_rep->type == 3) {
+ struct element_meas_ch_load *ch_load;
+
+ ch_load = (struct element_meas_ch_load *)
+ pkt_pull(pkt, sizeof(*ch_load));
+ if (ch_load == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*ch_load)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("OP Class: %u, ", ch_load->op_class);
+ tprintf("Ch Nr: %u, ", ch_load->ch_nr);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(ch_load->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(ch_load->dur) * TU);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*ch_load)))
+ return 0;
+ }
+ else if(meas_rep->type == 4) {
+ struct element_meas_noise *noise;
+
+ noise = (struct element_meas_noise *)
+ pkt_pull(pkt, sizeof(*noise));
+ if (noise == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*noise)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("OP Class: %u, ", noise->op_class);
+ tprintf("Ch Nr: %u, ", noise->ch_nr);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(noise->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(noise->dur) * TU);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*noise)))
+ return 0;
+ }
+ else if(meas_rep->type == 5) {
+ struct element_meas_beacon *beacon;
+
+ beacon = (struct element_meas_beacon *)
+ pkt_pull(pkt, sizeof(*beacon));
+ if (beacon == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*beacon)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("OP Class: %u, ", beacon->op_class);
+ tprintf("Ch Nr: %u, ", beacon->ch_nr);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(beacon->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(beacon->dur) * TU);
+ tprintf("Mode: %u, ", beacon->mode);
+ tprintf("BSSID: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ beacon->bssid[0], beacon->bssid[1],
+ beacon->bssid[2], beacon->bssid[3],
+ beacon->bssid[4], beacon->bssid[5]);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*beacon)))
+ return 0;
+ }
+ else if(meas_rep->type == 6) {
+ struct element_meas_frame *frame;
+
+ frame = (struct element_meas_frame *)
+ pkt_pull(pkt, sizeof(*frame));
+ if (frame == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*frame)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("OP Class: %u, ", frame->op_class);
+ tprintf("Ch Nr: %u, ", frame->ch_nr);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(frame->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(frame->dur) * TU);
+ tprintf("Request Type: %u, ", frame->frame);
+ tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ frame->mac[0], frame->mac[1],
+ frame->mac[2], frame->mac[3],
+ frame->mac[4], frame->mac[5]);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*frame)))
+ return 0;
+ }
+ else if(meas_rep->type == 7) {
+ struct element_meas_sta *sta;
+
+ sta = (struct element_meas_sta *)
+ pkt_pull(pkt, sizeof(*sta));
+ if (sta == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*sta)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Peer MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
+ sta->peer_mac[0], sta->peer_mac[1],
+ sta->peer_mac[2], sta->peer_mac[3],
+ sta->peer_mac[4], sta->peer_mac[5]);
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(sta->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(sta->dur) * TU);
+ tprintf("Group ID: %u, ", sta->group_id);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*sta)))
+ return 0;
+ }
+ else if(meas_rep->type == 8) {
+ struct element_meas_lci *lci;
+
+ lci = (struct element_meas_lci *)
+ pkt_pull(pkt, sizeof(*lci));
+ if (lci == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*lci)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Location Subj: %u, ", lci->loc_subj);
+ tprintf("Latitude Req Res: %udeg",
+ lci->latitude_req_res);
+ tprintf("Longitude Req Res: %udeg",
+ lci->longitude_req_res);
+ tprintf("Altitude Req Res: %udeg",
+ lci->altitude_req_res);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*lci)))
+ return 0;
+ }
+ else if(meas_rep->type == 9) {
+ struct element_meas_trans_str_cat *trans;
+
+ trans = (struct element_meas_trans_str_cat *)
+ pkt_pull(pkt, sizeof(*trans));
+ if (trans == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*trans)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(trans->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(trans->dur) * TU);
+ tprintf("MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
+ trans->peer_sta_addr[0], trans->peer_sta_addr[1],
+ trans->peer_sta_addr[2], trans->peer_sta_addr[3],
+ trans->peer_sta_addr[4], trans->peer_sta_addr[5]);
+ tprintf("Traffic ID: %u, ", trans->traffic_id);
+ tprintf("Bin 0 Range: %u, ", trans->bin_0_range);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*trans)))
+ return 0;
+ }
+ else if(meas_rep->type == 10) {
+ struct element_meas_mcast_diag *mcast;
+
+ mcast = (struct element_meas_mcast_diag *)
+ pkt_pull(pkt, sizeof(*mcast));
+ if (mcast == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*mcast)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Rand Intv: %fs, ",
+ le16_to_cpu(mcast->rand_intv) * TU);
+ tprintf("Meas Duration: %fs",
+ le16_to_cpu(mcast->dur) * TU);
+ tprintf("Group MAC Addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ mcast->group_mac[0], mcast->group_mac[1],
+ mcast->group_mac[2], mcast->group_mac[3],
+ mcast->group_mac[4], mcast->group_mac[5]);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*mcast)))
+ return 0;
+ }
+ else if(meas_rep->type == 11) {
+ struct element_meas_loc_civic *civic;
+
+ civic = (struct element_meas_loc_civic *)
+ pkt_pull(pkt, sizeof(*civic));
+ if (civic == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*civic)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Location Subj: %u, ", civic->loc_subj);
+ tprintf("Type: %u, ", civic->civic_loc);
+ tprintf("Srv Intv Units: %u, ",
+ le16_to_cpu(civic->loc_srv_intv_unit));
+ tprintf("Srv Intv: %u, ", civic->loc_srv_intv);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*civic)))
+ return 0;
+ }
+ else if(meas_rep->type == 12) {
+ struct element_meas_loc_id *id;
+
+ id = (struct element_meas_loc_id *)
+ pkt_pull(pkt, sizeof(*id));
+ if (id == NULL)
+ return 0;
+
+ if ((ssize_t)(meas_rep->len - 3 - sizeof(*id)) < 0) {
+ tprintf("Length of Req matchs not Type %u",
+ meas_rep->type);
+ return 0;
+ }
+
+ tprintf("Location Subj: %u, ", id->loc_subj);
+ tprintf("Srv Intv Units: %u, ",
+ le16_to_cpu(id->loc_srv_intv_unit));
+ tprintf("Srv Intv: %u", id->loc_srv_intv);
+
+ if(!subelements(pkt,
+ meas_rep->len - 3 - sizeof(*id)))
+ return 0;
+ }
+ else {
+ tprintf("Length field indicates data,"
+ " but could not interpreted");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int8_t inf_quiet(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_quiet *quiet;
+
+ quiet = (struct element_quiet *) pkt_pull(pkt, sizeof(*quiet));
+ if (quiet == NULL)
+ return 0;
+
+ tprintf(" Quit (%u, Len(%u)): ", *id, quiet->len);
+ if (len_neq_error(quiet->len, 6))
+ return 0;
+
+ tprintf("Count: %ud, ", quiet->cnt);
+ tprintf("Period: %u, ", quiet->period);
+ tprintf("Duration: %fs, ", le16_to_cpu(quiet->dur) * TU);
+ tprintf("Offs: %fs", le16_to_cpu(quiet->offs) * TU);
+
+
+ return 1;
+}
+
+static int8_t inf_ibss_dfs(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_ibss_dfs *ibss_dfs;
+ u8 i;
+
+ ibss_dfs = (struct element_ibss_dfs *) pkt_pull(pkt, sizeof(*ibss_dfs));
+ if (ibss_dfs == NULL)
+ return 0;
+
+ tprintf(" IBSS DFS (%u, Len(%u)): ", *id, ibss_dfs->len);
+ if (len_lt_error(ibss_dfs->len, 7))
+ return 0;
+
+ tprintf("Owner: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, ",
+ ibss_dfs->owner[0], ibss_dfs->owner[1],
+ ibss_dfs->owner[2], ibss_dfs->owner[3],
+ ibss_dfs->owner[4], ibss_dfs->owner[5]);
+ tprintf("Recovery Intv: %u, ", ibss_dfs->rec_intv);
+
+ if((ibss_dfs->len - sizeof(*ibss_dfs) + 1) & 1) {
+ tprintf("Length of Channel Map should be modulo 2");
+ return 0;
+ }
+
+ for (i = 0; i < ibss_dfs->len; i += 2) {
+ struct element_ibss_dfs_tuple *ibss_dfs_tuple;
+
+ ibss_dfs_tuple = (struct element_ibss_dfs_tuple *)
+ pkt_pull(pkt, sizeof(*ibss_dfs_tuple));
+ if (ibss_dfs_tuple == NULL)
+ return 0;
+
+ tprintf("Channel Nr: %u, ", ibss_dfs_tuple->ch_nr);
+ tprintf("Map: %u, ", ibss_dfs_tuple->map);
+ }
+
+ return 1;
+}
+
+static int8_t inf_erp(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_erp *erp;
+
+ erp = (struct element_erp *) pkt_pull(pkt, sizeof(*erp));
+ if (erp == NULL)
+ return 0;
+
+ tprintf(" ERP (%u, Len(%u)): ", *id, erp->len);
+ if (len_neq_error(erp->len, 1))
+ return 0;
+ tprintf("Non ERP Present (%u), ", erp->param & 0x1);
+ tprintf("Use Protection (%u), ", (erp->param >> 1) & 0x1);
+ tprintf("Barker Preamble Mode (%u), ", (erp->param >> 2) & 0x1);
+ tprintf("Reserved (0x%.5x)", erp->param >> 3);
+
+ return 1;
+}
+
+static int8_t inf_ts_del(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_ts_del *ts_del;
+
+ ts_del = (struct element_ts_del *) pkt_pull(pkt, sizeof(*ts_del));
+ if (ts_del == NULL)
+ return 0;
+
+ tprintf(" TS Delay (%u, Len(%u)): ", *id, ts_del->len);
+ if (len_neq_error(ts_del->len, 4))
+ return 0;
+ tprintf("Delay (%fs)", le32_to_cpu(ts_del->delay) * TU);
+
+ return 1;
+}
+
+static int8_t inf_tclas_proc(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_tclas_proc *tclas_proc;
+
+ tclas_proc = (struct element_tclas_proc *)
+ pkt_pull(pkt, sizeof(*tclas_proc));
+ if (tclas_proc == NULL)
+ return 0;
+
+ tprintf(" TCLAS Procesing (%u, Len(%u)): ", *id, tclas_proc->len);
+ if (len_neq_error(tclas_proc->len, 1))
+ return 0;
+ tprintf("Processing (%u)", tclas_proc->proc);
+
+ return 1;
+}
+
+static int8_t inf_ht_cap(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_ht_cap *ht_cap;
+ u32 tx_param_res, beam_cap;
+ u16 ext_cap;
+
+ ht_cap = (struct element_ht_cap *)
+ pkt_pull(pkt, sizeof(*ht_cap));
+ if (ht_cap == NULL)
+ return 0;
+
+ tx_param_res = le32_to_cpu(ht_cap->tx_param_res);
+ beam_cap = le32_to_cpu(ht_cap->beam_cap);
+ ext_cap = le16_to_cpu(ht_cap->ext_cap);
+
+ tprintf(" HT Capabilities (%u, Len(%u)): ", *id, ht_cap->len);
+ if (len_neq_error(ht_cap->len, 26))
+ return 0;
+ tprintf("Info (LDCP Cod Cap (%u), Supp Ch Width Set (%u),"
+ " SM Pwr Save(%u), HT-Greenfield (%u), Short GI for 20/40 MHz"
+ " (%u/%u), Tx/Rx STBC (%u/%u), HT-Delayed Block Ack (%u),"
+ " Max A-MSDU Len (%u), DSSS/CCK Mode in 40 MHz (%u),"
+ " Res (0x%x), Forty MHz Intol (%u), L-SIG TXOP Protection Supp"
+ " (%u)), ", ht_cap->ldpc, ht_cap->supp_width,
+ ht_cap->sm_pwr, ht_cap->ht_green, ht_cap->gi_20mhz,
+ ht_cap->gi_40mhz, ht_cap->tx_stbc, ht_cap->rx_stbc,
+ ht_cap->ht_ack, ht_cap->max_msdu_length, ht_cap->dsss_ck_mode,
+ ht_cap->res, ht_cap->forty_int, ht_cap->prot_supp);
+ tprintf("A-MPDU Params (Max Len Exp (%u), Min Start Spacing (%u),"
+ " Res (0x%x)), ", ht_cap->param >> 6, (ht_cap->param >> 3) & 0x7,
+ ht_cap->param & 0x07);
+ tprintf("Supp MCS Set (Rx MCS Bitmask (0x%x%x%x%x%x%x%x%x%x%x),"
+ " Res (0x%x), Rx High Supp Data Rate (%u), Res (0x%x),"
+ " Tx MCS Set Def (%u), Tx Rx MCS Set Not Eq (%u),"
+ " Tx Max Number Spat Str Supp (%u),"
+ " Tx Uneq Mod Supp (%u), Res (0x%x)), ",
+ ht_cap->bitmask1, ht_cap->bitmask2, ht_cap->bitmask3,
+ ht_cap->bitmask4, ht_cap->bitmask5, ht_cap->bitmask6,
+ ht_cap->bitmask7, ht_cap->bitmask8, ht_cap->bitmask9,
+ ht_cap->bitmask10_res >> 3, ht_cap->bitmask10_res & 0x7,
+ le16_to_cpu(ht_cap->supp_rate_res) >> 6,
+ le16_to_cpu(ht_cap->supp_rate_res) & 0x3F,
+ tx_param_res >> 31, (tx_param_res >> 30) & 1,
+ (tx_param_res >> 28) & 3, (tx_param_res >> 27) & 1,
+ tx_param_res & 0x7FFFFFF);
+ tprintf("Ext Cap (PCO (%u), PCO Trans Time (%u), Res (0x%x),"
+ " MCS Feedb (%u), +HTC Supp (%u), RD Resp (%u), Res (0x%x)), ",
+ ext_cap >> 15, (ext_cap >> 13) & 3, (ext_cap >> 8) & 0x1F,
+ (ext_cap >> 6) & 3, (ext_cap >> 5) & 1, (ext_cap >> 4) & 1,
+ ext_cap & 0xF);
+ tprintf("Transm Beamf (Impl Transm Beamf Rec Cap (%u),"
+ " Rec/Transm Stagg Sound Cap (%u/%u),"
+ " Rec/Trans NDP Cap (%u/%u), Impl Transm Beamf Cap (%u),"
+ " Cal (%u), Expl CSI Transm Beamf Cap (%u),"
+ " Expl Noncmpr/Compr Steering Cap (%u/%u),"
+ " Expl Trans Beamf CSI Feedb (%u),"
+ " Expl Noncmpr/Cmpr Feedb Cap (%u/%u),"
+ " Min Grpg (%u), CSI Num Beamf Ant Supp (%u),"
+ " Noncmpr/Cmpr Steering Nr Beamf Ant Supp (%u/%u),"
+ " CSI Max Nr Rows Beamf Supp (%u),"
+ " Ch Estim Cap (%u), Res (0x%x)), ",
+ beam_cap >> 31, (beam_cap >> 30) & 1, (beam_cap >> 29) & 1,
+ (beam_cap >> 28) & 1, (beam_cap >> 27) & 1, (beam_cap >> 26) & 1,
+ (beam_cap >> 24) & 3, (beam_cap >> 23) & 1, (beam_cap >> 22) & 1,
+ (beam_cap >> 21) & 1, (beam_cap >> 19) & 3, (beam_cap >> 17) & 3,
+ (beam_cap >> 15) & 3, (beam_cap >> 13) & 3, (beam_cap >> 11) & 3,
+ (beam_cap >> 9) & 3, (beam_cap >> 7) & 3, (beam_cap >> 5) & 3,
+ (beam_cap >> 3) & 3, beam_cap & 7);
+ tprintf("ASEL (Ant Select Cap (%u),"
+ " Expl CSI Feedb Based Transm ASEL Cap (%u),"
+ " Ant Indic Feedb Based Transm ASEL Cap (%u),"
+ " Expl CSI Feedb Cap (%u), Ant Indic Feedb Cap (%u),"
+ " Rec ASEL Cap (%u), Transm Sound PPDUs Cap (%u), Res (0x%x))",
+ ht_cap->asel_cap >> 7, (ht_cap->asel_cap >> 6) & 1,
+ (ht_cap->asel_cap >> 5) & 1, (ht_cap->asel_cap >> 4) & 1,
+ (ht_cap->asel_cap >> 3) & 1, (ht_cap->asel_cap >> 2) & 1,
+ (ht_cap->asel_cap >> 1) & 1, ht_cap->asel_cap & 1);
+
+ return 1;
+}
+
+static int8_t inf_qos_cap(struct pkt_buff *pkt, u8 *id)
+{
+ struct element_qos_cap *qos_cap;
+
+ qos_cap = (struct element_qos_cap *)
+ pkt_pull(pkt, sizeof(*qos_cap));
+ if (qos_cap == NULL)
+ return 0;
+
+ tprintf(" QoS Capabilities (%u, Len(%u)): ", *id, qos_cap->len);
+ if (len_neq_error(qos_cap->len, 1))
+ return 0;
+
+ tprintf("Info (0x%x)", qos_cap->info);
+
+ return 1;
+}
+
+static int8_t inf_rsn(struct pkt_buff *pkt, u8 *id)
+{
+ return 0;
+}
+
+static int8_t inf_ext_supp_rates(struct pkt_buff *pkt, u8 *id)
+{
+ u8 i;
+ u8 *rates;
+ struct element_ext_supp_rates *ext_supp_rates;
+
+ ext_supp_rates = (struct element_ext_supp_rates *)
+ pkt_pull(pkt, sizeof(*ext_supp_rates));
+ if (ext_supp_rates == NULL)
+ return 0;
+
+ tprintf(" Ext Support Rates (%u, Len(%u)): ", *id, ext_supp_rates->len);
+
+ if ((ext_supp_rates->len - sizeof(*ext_supp_rates) + 1) > 0) {
+ rates = pkt_pull(pkt, ext_supp_rates->len);
+ if (rates == NULL)
+ return 0;
+
+ for (i = 0; i < ext_supp_rates->len; i++)
+ tprintf("%g ", (rates[i] & 0x80) ?
+ ((rates[i] & 0x3f) * 0.5) :
+ data_rates(rates[i]));
+ return 1;
+ }
+
+ return 0;
+}
+
+static int8_t inf_ap_ch_exp(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_neighb_rep(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_rcpi(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mde(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_fte(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_time_out_int(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_rde(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_dse_reg_loc(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_supp_op_class(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ext_ch_sw_ann(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ht_op(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_sec_ch_offs(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_bss_avg_acc_del(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ant(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_rsni(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_meas_pilot_trans(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_bss_avl_adm_cap(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_bss_ac_acc_del(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_time_adv(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_rm_ena_cap(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mult_bssid(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_20_40_bss_coex(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_20_40_bss_int_ch_rep(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_overl_bss_scan_para(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ric_desc(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mgmt_mic(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ev_req(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ev_rep(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_diagn_req(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_diagn_rep(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_loc_para(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_nontr_bssid_cap(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ssid_list(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mult_bssid_index(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_fms_desc(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_fms_req(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_fms_resp(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_qos_tfc_cap(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_bss_max_idle_per(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_tfs_req(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_tfs_resp(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_wnm_sleep_mod(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_tim_bcst_req(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_tim_bcst_resp(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_coll_interf_rep(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ch_usage(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_time_zone(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_dms_req(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_dms_resp(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_link_id(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_wakeup_sched(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ch_sw_timing(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_pti_ctrl(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_tpu_buff_status(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_interw(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_adv_proto(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_exp_bandw_req(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_qos_map_set(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_roam_cons(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_emer_alert_id(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mesh_conf(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mesh_id(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mesh_link_metr_rep(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_cong_notif(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mesh_peer_mgmt(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mesh_ch_sw_para(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mesh_awake_win(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_beacon_timing(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mccaop_setup_req(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mccaop_setup_rep(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mccaop_adv(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mccaop_teardwn(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_gann(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_rann(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_ext_cap(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_preq(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_prep(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_perr(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_pxu(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_pxuc(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_auth_mesh_peer_exch(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mic(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_dest_uri(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_u_apsd_coex(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_mccaop_adv_overv(struct pkt_buff *pkt, u8 *id) {
+ return 0;
+}
+
+static int8_t inf_vend_spec(struct pkt_buff *pkt, u8 *id)
+{
+ u8 i;
+ u8 *data;
+ struct element_vend_spec *vend_spec;
+
+ vend_spec = (struct element_vend_spec *)
+ pkt_pull(pkt, sizeof(*vend_spec));
+ if (vend_spec == NULL)
+ return 0;
+
+ tprintf(" Vendor Specific (%u, Len (%u)): ", *id, vend_spec->len);
+
+ data = pkt_pull(pkt, vend_spec->len);
+ if (data == NULL)
+ return 0;
+
+ tprintf("Data 0x");
+ for (i = 0; i < vend_spec->len; i++)
+ tprintf("%.2x", data[i]);
+
+ return 1;
+}
+
+static int8_t inf_elements(struct pkt_buff *pkt)
+{
+ u8 *id = pkt_pull(pkt, 1);
+ if (id == NULL)
+ return 0;
+
+ switch (*id) {
+ case 0: return inf_ssid(pkt, id);
+ case 1: return inf_supp_rates(pkt, id);
+ case 2: return inf_fh_ps(pkt, id);
+ case 3: return inf_dsss_ps(pkt, id);
+ case 4: return inf_cf_ps(pkt, id);
+ case 5: return inf_tim(pkt, id);
+ case 6: return inf_ibss_ps(pkt, id);
+ case 7: return inf_country(pkt, id);
+ case 8: return inf_hop_pp(pkt, id);
+ case 9: return inf_hop_pt(pkt, id);
+ case 10: return inf_req(pkt, id);
+ case 11: return inf_bss_load(pkt, id);
+ case 12: return inf_edca_ps(pkt, id);
+ case 13: return inf_tspec(pkt, id);
+ case 14: return inf_tclas(pkt, id);
+ case 15: return inf_sched(pkt, id);
+ case 16: return inf_chall_txt(pkt, id);
+ case 17 ... 31: return inf_reserved(pkt, id);
+ case 32: return inf_pwr_constr(pkt, id);
+ case 33: return inf_pwr_cap(pkt, id);
+ case 34: return inf_tpc_req(pkt, id);
+ case 35: return inf_tpc_rep(pkt, id);
+ case 36: return inf_supp_ch(pkt, id);
+ case 37: return inf_ch_sw_ann(pkt, id);
+ case 38: return inf_meas_req(pkt, id);
+ case 39: return inf_meas_rep(pkt, id);
+ case 40: return inf_quiet(pkt, id);
+ case 41: return inf_ibss_dfs(pkt, id);
+ case 42: return inf_erp(pkt, id);
+ case 43: return inf_ts_del(pkt, id);
+ case 44: return inf_tclas_proc(pkt, id);
+ case 45: return inf_ht_cap(pkt, id);
+ case 46: return inf_qos_cap(pkt, id);
+ case 47: return inf_reserved(pkt, id);
+ case 48: return inf_rsn(pkt, id);
+ case 49: return inf_rsn(pkt, id);
+ case 50: return inf_ext_supp_rates(pkt, id);
+ case 51: return inf_ap_ch_exp(pkt, id);
+ case 52: return inf_neighb_rep(pkt, id);
+ case 53: return inf_rcpi(pkt, id);
+ case 54: return inf_mde(pkt, id);
+ case 55: return inf_fte(pkt, id);
+ case 56: return inf_time_out_int(pkt, id);
+ case 57: return inf_rde(pkt, id);
+ case 58: return inf_dse_reg_loc(pkt, id);
+ case 59: return inf_supp_op_class(pkt, id);
+ case 60: return inf_ext_ch_sw_ann(pkt, id);
+ case 61: return inf_ht_op(pkt, id);
+ case 62: return inf_sec_ch_offs(pkt, id);
+ case 63: return inf_bss_avg_acc_del(pkt, id);
+ case 64: return inf_ant(pkt, id);
+ case 65: return inf_rsni(pkt, id);
+ case 66: return inf_meas_pilot_trans(pkt, id);
+ case 67: return inf_bss_avl_adm_cap(pkt, id);
+ case 68: return inf_bss_ac_acc_del(pkt, id);
+ case 69: return inf_time_adv(pkt, id);
+ case 70: return inf_rm_ena_cap(pkt, id);
+ case 71: return inf_mult_bssid(pkt, id);
+ case 72: return inf_20_40_bss_coex(pkt, id);
+ case 73: return inf_20_40_bss_int_ch_rep(pkt, id);
+ case 74: return inf_overl_bss_scan_para(pkt, id);
+ case 75: return inf_ric_desc(pkt, id);
+ case 76: return inf_mgmt_mic(pkt, id);
+ case 78: return inf_ev_req(pkt, id);
+ case 79: return inf_ev_rep(pkt, id);
+ case 80: return inf_diagn_req(pkt, id);
+ case 81: return inf_diagn_rep(pkt, id);
+ case 82: return inf_loc_para(pkt, id);
+ case 83: return inf_nontr_bssid_cap(pkt, id);
+ case 84: return inf_ssid_list(pkt, id);
+ case 85: return inf_mult_bssid_index(pkt, id);
+ case 86: return inf_fms_desc(pkt, id);
+ case 87: return inf_fms_req(pkt, id);
+ case 88: return inf_fms_resp(pkt, id);
+ case 89: return inf_qos_tfc_cap(pkt, id);
+ case 90: return inf_bss_max_idle_per(pkt, id);
+ case 91: return inf_tfs_req(pkt, id);
+ case 92: return inf_tfs_resp(pkt, id);
+ case 93: return inf_wnm_sleep_mod(pkt, id);
+ case 94: return inf_tim_bcst_req(pkt, id);
+ case 95: return inf_tim_bcst_resp(pkt, id);
+ case 96: return inf_coll_interf_rep(pkt, id);
+ case 97: return inf_ch_usage(pkt, id);
+ case 98: return inf_time_zone(pkt, id);
+ case 99: return inf_dms_req(pkt, id);
+ case 100: return inf_dms_resp(pkt, id);
+ case 101: return inf_link_id(pkt, id);
+ case 102: return inf_wakeup_sched(pkt, id);
+ case 104: return inf_ch_sw_timing(pkt, id);
+ case 105: return inf_pti_ctrl(pkt, id);
+ case 106: return inf_tpu_buff_status(pkt, id);
+ case 107: return inf_interw(pkt, id);
+ case 108: return inf_adv_proto(pkt, id);
+ case 109: return inf_exp_bandw_req(pkt, id);
+ case 110: return inf_qos_map_set(pkt, id);
+ case 111: return inf_roam_cons(pkt, id);
+ case 112: return inf_emer_alert_id(pkt, id);
+ case 113: return inf_mesh_conf(pkt, id);
+ case 114: return inf_mesh_id(pkt, id);
+ case 115: return inf_mesh_link_metr_rep(pkt, id);
+ case 116: return inf_cong_notif(pkt, id);
+ case 117: return inf_mesh_peer_mgmt(pkt, id);
+ case 118: return inf_mesh_ch_sw_para(pkt, id);
+ case 119: return inf_mesh_awake_win(pkt, id);
+ case 120: return inf_beacon_timing(pkt, id);
+ case 121: return inf_mccaop_setup_req(pkt, id);
+ case 122: return inf_mccaop_setup_rep(pkt, id);
+ case 123: return inf_mccaop_adv(pkt, id);
+ case 124: return inf_mccaop_teardwn(pkt, id);
+ case 125: return inf_gann(pkt, id);
+ case 126: return inf_rann(pkt, id);
+ case 127: return inf_ext_cap(pkt, id);
+ case 128: return inf_reserved(pkt, id);
+ case 129: return inf_reserved(pkt, id);
+ case 130: return inf_preq(pkt, id);
+ case 131: return inf_prep(pkt, id);
+ case 132: return inf_perr(pkt, id);
+ case 133: return inf_reserved(pkt, id);
+ case 134: return inf_reserved(pkt, id);
+ case 135: return inf_reserved(pkt, id);
+ case 136: return inf_reserved(pkt, id);
+ case 137: return inf_pxu(pkt, id);
+ case 138: return inf_pxuc(pkt, id);
+ case 139: return inf_auth_mesh_peer_exch(pkt, id);
+ case 140: return inf_mic(pkt, id);
+ case 141: return inf_dest_uri(pkt, id);
+ case 142: return inf_u_apsd_coex(pkt, id);
+ case 143 ... 173: return inf_reserved(pkt, id);
+ case 174: return inf_mccaop_adv_overv(pkt, id);
+ case 221: return inf_vend_spec(pkt, id);
+ }
+
+ return 0;
+}
+
+#define ESS 0b0000000000000001
+#define IBSS 0b0000000000000010
+#define CF_Pollable 0b0000000000000100
+#define CF_Poll_Req 0b0000000000001000
+#define Privacy 0b0000000000010000
+#define Short_Pre 0b0000000000100000
+#define PBCC 0b0000000001000000
+#define Ch_Agility 0b0000000010000000
+#define Spec_Mgmt 0b0000000100000000
+#define QoS 0b0000001000000000
+#define Short_Slot_t 0b0000010000000000
+#define APSD 0b0000100000000000
+#define Radio_Meas 0b0001000000000000
+#define DSSS_OFDM 0b0010000000000000
+#define Del_Block_ACK 0b0100000000000000
+#define Imm_Block_ACK 0b1000000000000000
+
+static int8_t cap_field(u16 cap_inf)
+{
+ if (ESS & cap_inf)
+ tprintf(" ESS;");
+ if (IBSS & cap_inf)
+ tprintf(" IBSS;");
+ if (CF_Pollable & cap_inf)
+ tprintf(" CF Pollable;");
+ if (CF_Poll_Req & cap_inf)
+ tprintf(" CF-Poll Request;");
+ if (Privacy & cap_inf)
+ tprintf(" Privacy;");
+ if (Short_Pre & cap_inf)
+ tprintf(" Short Preamble;");
+ if (PBCC & cap_inf)
+ tprintf(" PBCC;");
+ if (Ch_Agility & cap_inf)
+ tprintf(" Channel Agility;");
+ if (Spec_Mgmt & cap_inf)
+ tprintf(" Spectrum Management;");
+ if (QoS & cap_inf)
+ tprintf(" QoS;");
+ if (Short_Slot_t & cap_inf)
+ tprintf(" Short Slot Time;");
+ if (APSD & cap_inf)
+ tprintf(" APSD;");
+ if (Radio_Meas & cap_inf)
+ tprintf(" Radio Measurement;");
+ if (DSSS_OFDM & cap_inf)
+ tprintf(" DSSS-OFDM;");
+ if (Del_Block_ACK & cap_inf)
+ tprintf(" Delayed Block Ack;");
+ if (Imm_Block_ACK & cap_inf)
+ tprintf(" Immediate Block Ack;");
+
+ return 1;
+}
+
+/* Management Dissectors */
+static int8_t assoc_req(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t assoc_resp(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t reassoc_req(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t reassoc_resp(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t probe_req(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t probe_resp(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t beacon(struct pkt_buff *pkt)
+{
+ struct ieee80211_mgmt_beacon *beacon;
+
+ beacon = (struct ieee80211_mgmt_beacon *)
+ pkt_pull(pkt, sizeof(*beacon));
+ if (beacon == NULL)
+ return 0;
+
+ tprintf("Timestamp 0x%.16lx, ", le64_to_cpu(beacon->timestamp));
+ tprintf("Beacon Interval (%fs), ", le16_to_cpu(beacon->beacon_int)*TU);
+ tprintf("Capabilities (0x%x <->", le16_to_cpu(beacon->capab_info));
+ cap_field(le16_to_cpu(beacon->capab_info));
+ tprintf(")");
+
+ if(pkt_len(pkt)) {
+ tprintf("\n\tParameters:");
+ while (inf_elements(pkt)) {
+ tprintf("\n\t");
+ }
+ }
+
+ if(pkt_len(pkt))
+ return 0;
+ return 1;
+}
+
+static int8_t atim(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t disassoc(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t auth(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t deauth(struct pkt_buff *pkt) {
+ return 0;
+}
+/* End Management Dissectors */
+
+/* Control Dissectors */
+static int8_t ps_poll(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t rts(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t cts(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t ack(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t cf_end(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t cf_end_ack(struct pkt_buff *pkt) {
+ return 0;
+}
+/* End Control Dissectors */
+
+/* Data Dissectors */
+static int8_t data(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t data_cf_ack(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t data_cf_poll(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t data_cf_ack_poll(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t null(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t cf_ack(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t cf_poll(struct pkt_buff *pkt) {
+ return 0;
+}
+
+static int8_t cf_ack_poll(struct pkt_buff *pkt) {
+ return 0;
+}
+/* End Data Dissectors */
+
+static const char *mgt_sub(u8 subtype, struct pkt_buff *pkt,
+ int8_t (**get_content)(struct pkt_buff *pkt))
+{
+ u16 seq_ctrl;
+ struct ieee80211_mgmt *mgmt;
+ const char *dst, *src, *bssid;
+
+ mgmt = (struct ieee80211_mgmt *) pkt_pull(pkt, sizeof(*mgmt));
+ if (mgmt == NULL)
+ return 0;
+
+ dst = lookup_vendor((mgmt->da[0] << 16) |
+ (mgmt->da[1] << 8) |
+ mgmt->da[2]);
+ src = lookup_vendor((mgmt->sa[0] << 16) |
+ (mgmt->sa[1] << 8) |
+ mgmt->sa[2]);
+
+ bssid = lookup_vendor((mgmt->bssid[0] << 16) |
+ (mgmt->bssid[1] << 8) |
+ mgmt->bssid[2]);
+ seq_ctrl = le16_to_cpu(mgmt->seq_ctrl);
+
+ tprintf("Duration (%u),", le16_to_cpu(mgmt->duration));
+ tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
+ mgmt->da[0], mgmt->da[1], mgmt->da[2],
+ mgmt->da[3], mgmt->da[4], mgmt->da[5]);
+ if (dst) {
+ tprintf("=> (%s:%.2x:%.2x:%.2x)", dst,
+ mgmt->da[3], mgmt->da[4], mgmt->da[5]);
+ }
+
+ tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
+ mgmt->sa[0], mgmt->sa[1], mgmt->sa[2],
+ mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
+ if (src) {
+ tprintf("=> (%s:%.2x:%.2x:%.2x)", src,
+ mgmt->sa[3], mgmt->sa[4], mgmt->sa[5]);
+ }
+
+ tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
+ mgmt->bssid[0], mgmt->bssid[1], mgmt->bssid[2],
+ mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
+ if(bssid) {
+ tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid,
+ mgmt->bssid[3], mgmt->bssid[4], mgmt->bssid[5]);
+ }
+
+ tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ",
+ seq_ctrl & 0xf, seq_ctrl >> 4);
+
+ switch (subtype) {
+ case 0b0000:
+ *get_content = assoc_req;
+ return "Association Request";
+ case 0b0001:
+ *get_content = assoc_resp;
+ return "Association Response";
+ case 0b0010:
+ *get_content = reassoc_req;
+ return "Reassociation Request";
+ case 0b0011:
+ *get_content = reassoc_resp;
+ return "Reassociation Response";
+ case 0b0100:
+ *get_content = probe_req;
+ return "Probe Request";
+ case 0b0101:
+ *get_content = probe_resp;
+ return "Probe Response";
+ case 0b1000:
+ *get_content = beacon;
+ return "Beacon";
+ case 0b1001:
+ *get_content = atim;
+ return "ATIM";
+ case 0b1010:
+ *get_content = disassoc;
+ return "Disassociation";
+ case 0b1011:
+ *get_content = auth;
+ return "Authentication";
+ case 0b1100:
+ *get_content = deauth;
+ return "Deauthentication";
+ case 0b0110 ... 0b0111:
+ case 0b1101 ... 0b1111:
+ *get_content = NULL;
+ return "Reserved";
+ default:
+ *get_content = NULL;
+ return "Management SubType unknown";
+ }
+}
+
+static const char *ctrl_sub(u8 subtype, struct pkt_buff *pkt,
+ int8_t (**get_content)(struct pkt_buff *pkt))
+{
+ switch (subtype) {
+ case 0b1010:
+ *get_content = ps_poll;
+ return "PS-Poll";
+ case 0b1011:
+ *get_content = rts;
+ return "RTS";
+ case 0b1100:
+ *get_content = cts;
+ return "CTS";
+ case 0b1101:
+ *get_content = ack;
+ return "ACK";
+ case 0b1110:
+ *get_content = cf_end;
+ return "CF End";
+ case 0b1111:
+ *get_content = cf_end_ack;
+ return "CF End + CF-ACK";
+ case 0b0000 ... 0b1001:
+ *get_content = NULL;
+ return "Reserved";
+ default:
+ return "Control SubType unkown";
+ }
+}
+
+static const char *data_sub(u8 subtype, struct pkt_buff *pkt,
+ int8_t (**get_content)(struct pkt_buff *pkt))
+{
+ switch (subtype) {
+ case 0b0000:
+ *get_content = data;
+ return "Data";
+ case 0b0001:
+ *get_content = data_cf_ack;
+ return "Data + CF-ACK";
+ case 0b0010:
+ *get_content = data_cf_poll;
+ return "Data + CF-Poll";
+ case 0b0011:
+ *get_content = data_cf_ack_poll;
+ return "Data + CF-ACK + CF-Poll";
+ case 0b0100:
+ *get_content = null;
+ return "Null";
+ case 0b0101:
+ *get_content = cf_ack;
+ return "CF-ACK";
+ case 0b0110:
+ *get_content = cf_poll;
+ return "CF-Poll";
+ case 0b0111:
+ *get_content = cf_ack_poll;
+ return "CF-ACK + CF-Poll";
+ case 0b1000 ... 0b1111:
+ *get_content = NULL;
+ return "Reserved";
+ default:
+ *get_content = NULL;
+ return "Data SubType unkown";
+ }
+}
+
+static const char *
+frame_control_type(u8 type, const char *(**get_subtype)(u8 subtype,
+ struct pkt_buff *pkt, int8_t (**get_content)(struct pkt_buff *pkt)))
+{
+ switch (type) {
+ case 0b00:
+ *get_subtype = mgt_sub;
+ return "Management";
+ case 0b01:
+ *get_subtype = ctrl_sub;
+ return "Control";
+ case 0b10:
+ *get_subtype = data_sub;
+ return "Data";
+ case 0b11:
+ *get_subtype = NULL;
+ return "Reserved";
+ default:
+ *get_subtype = NULL;
+ return "Control Type unkown";
+ }
+}
+
+static void ieee80211(struct pkt_buff *pkt)
+{
+ int8_t (*get_content)(struct pkt_buff *pkt) = NULL;
+ const char *(*get_subtype)(u8 subtype, struct pkt_buff *pkt,
+ int8_t (**get_content)(struct pkt_buff *pkt)) = NULL;
+ const char *subtype = NULL;
+ struct ieee80211_frm_ctrl *frm_ctrl;
+
+ frm_ctrl = (struct ieee80211_frm_ctrl *)
+ pkt_pull(pkt, sizeof(*frm_ctrl));
+ if (frm_ctrl == NULL)
+ return;
+
+ tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
+ le16_to_cpu(frm_ctrl->frame_control));
+
+ tprintf(" [ Proto Version (%u), ", frm_ctrl->proto_version);
+ tprintf("Type (%u, %s), ", frm_ctrl->type,
+ frame_control_type(frm_ctrl->type, &get_subtype));
+ if (get_subtype) {
+ subtype = (*get_subtype)(frm_ctrl->subtype, pkt, &get_content);
+ tprintf("Subtype (%u, %s)", frm_ctrl->subtype, subtype);
+ } else {
+ tprintf("%s%s%s", colorize_start_full(black, red),
+ "No SubType Data available", colorize_end());
+ }
+
+ tprintf("%s%s", frm_ctrl->to_ds ? ", Frame goes to DS" : "",
+ frm_ctrl->from_ds ? ", Frame comes from DS" : "");
+ tprintf("%s", frm_ctrl->more_frags ? ", More Fragments" : "");
+ tprintf("%s", frm_ctrl->retry ? ", Frame is retransmitted" : "");
+ tprintf("%s", frm_ctrl->power_mgmt ? ", In Power Saving Mode" : "");
+ tprintf("%s", frm_ctrl->more_data ? ", More Data" : "");
+ tprintf("%s", frm_ctrl->wep ? ", Needs WEP" : "");
+ tprintf("%s", frm_ctrl->order ? ", Order" : "");
+ tprintf(" ]\n");
+
+ if (get_content) {
+ tprintf(" [ Subtype %s: ", subtype);
+ if (!((*get_content) (pkt)))
+ tprintf("%s%s%s", colorize_start_full(black, red),
+ "Failed to dissect Subtype", colorize_end());
+ tprintf(" ]");
+ } else {
+ tprintf("%s%s%s", colorize_start_full(black, red),
+ "No SubType Data available", colorize_end());
+ }
+
+ tprintf("\n");
+
+// pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
+}
+
+static void ieee80211_less(struct pkt_buff *pkt)
+{
+ tprintf("802.11 frame (more on todo)");
+}
+
+struct protocol ieee80211_ops = {
+ .key = 0,
+ .print_full = ieee80211,
+ .print_less = ieee80211_less,
+};