121878f3698de54649e622540a6f92eff9a4e0ab6Luis R. Rodriguez#include <stdbool.h> 279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg#include <errno.h> 32ef1be6884d781e2c57017b0862946f20bb9dec9Johannes Berg#include <net/if.h> 42ef1be6884d781e2c57017b0862946f20bb9dec9Johannes Berg 579f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg#include <netlink/genl/genl.h> 679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg#include <netlink/genl/family.h> 779f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg#include <netlink/genl/ctrl.h> 879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg#include <netlink/msg.h> 979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg#include <netlink/attr.h> 1079f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 11f408e01bbe5d3e25f909edffe4054513fb51d703Johannes Berg#include "nl80211.h" 1279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg#include "iw.h" 1379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 1479f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Bergstatic void print_flag(const char *name, int *open) 1579f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg{ 1679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg if (!*open) 1779f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg printf(" ("); 1879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg else 1979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg printf(", "); 2069283122a1cea2fc11e55a24d09389a6c1a875d9Johannes Berg printf("%s", name); 2179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg *open = 1; 2279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg} 2379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 24810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Bergstatic char *cipher_name(__u32 c) 25810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg{ 26810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg static char buf[20]; 27810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg 28810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg switch (c) { 29810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg case 0x000fac01: 30810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg return "WEP40 (00-0f-ac:1)"; 31810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg case 0x000fac05: 32810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg return "WEP104 (00-0f-ac:5)"; 33810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg case 0x000fac02: 34810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg return "TKIP (00-0f-ac:2)"; 35810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg case 0x000fac04: 36810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg return "CCMP (00-0f-ac:4)"; 37810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg case 0x000fac06: 38810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg return "CMAC (00-0f-ac:6)"; 39a8b3da9df8d15b857b13887feccdd05c46c7347eVladimir Kondratiev case 0x000fac08: 40a8b3da9df8d15b857b13887feccdd05c46c7347eVladimir Kondratiev return "GCMP (00-0f-ac:8)"; 41810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg case 0x00147201: 42810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg return "WPI-SMS4 (00-14-72:1)"; 43810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg default: 44810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg sprintf(buf, "%.2x-%.2x-%.2x:%d", 45810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg c >> 24, (c >> 16) & 0xff, 46810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg (c >> 8) & 0xff, c & 0xff); 47810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg 48810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg return buf; 49810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg } 50810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg} 51810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg 5248aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlichstatic char *dfs_state_name(enum nl80211_dfs_state state) 5348aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich{ 5448aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich switch (state) { 5548aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich case NL80211_DFS_USABLE: 5648aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich return "usable"; 5748aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich case NL80211_DFS_AVAILABLE: 5848aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich return "available"; 5948aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich case NL80211_DFS_UNAVAILABLE: 6048aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich return "unavailable"; 6148aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich default: 6248aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich return "unknown"; 6348aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich } 6448aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich} 6548aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich 66f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.comstatic int ext_feature_isset(const unsigned char *ext_features, int ext_features_len, 67f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com enum nl80211_ext_feature_index ftidx) 68f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com{ 69f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com unsigned char ft_byte; 70f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com 71f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com if ((int) ftidx / 8 >= ext_features_len) 72f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com return 0; 73f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com 74f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com ft_byte = ext_features[ftidx / 8]; 75f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com return (ft_byte & BIT(ftidx % 8)) != 0; 76f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com} 77f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com 7879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Bergstatic int print_phy_handler(struct nl_msg *msg, void *arg) 7979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg{ 8079f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; 8179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 8279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 8379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; 8479f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 8579f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; 8679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { 8779f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, 8879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG }, 89f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG }, 90f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer [__NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, 9179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, 92c1081c2008896ede5f50e9173f9427e212bf79f1Johannes Berg [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, 9379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg }; 9479f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 9579f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1]; 9679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = { 9779f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 }, 9879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG }, 9979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg }; 10079f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 10179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *nl_band; 10279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *nl_freq; 10379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *nl_rate; 1046367e71a165680225aec25f1c4521626f996b76eJohannes Berg struct nlattr *nl_mode; 1059990c1e9a89982efed4e50fb846968bcc6b60b46Marcel Holtmann struct nlattr *nl_cmd; 1069a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg struct nlattr *nl_if, *nl_ftype; 1079a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg int rem_band, rem_freq, rem_rate, rem_mode, rem_cmd, rem_ftype, rem_if; 10879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg int open; 109fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg /* 110fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg * static variables only work here, other applications need to use the 111fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg * callback pointer and store them there so they can be multithreaded 112fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg * and/or have multiple netlink sockets, etc. 113fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg */ 114fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg static int64_t phy_id = -1; 115fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg static int last_band = -1; 116fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg static bool band_had_freq = false; 117fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg bool print_name = true; 11879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 11979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 12079f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg genlmsg_attrlen(gnlh, 0), NULL); 12179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 122fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_msg[NL80211_ATTR_WIPHY]) { 123fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]) == phy_id) 124fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_name = false; 125fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg else 126fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg last_band = -1; 127fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg phy_id = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]); 128fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 129fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (print_name && tb_msg[NL80211_ATTR_WIPHY_NAME]) 130d631650b0d5725a487b87ad4d5d1238543aaf011Johannes Berg printf("Wiphy %s\n", nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME])); 131d631650b0d5725a487b87ad4d5d1238543aaf011Johannes Berg 132fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg /* needed for split dump */ 133fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_msg[NL80211_ATTR_WIPHY_BANDS]) { 134fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) { 135fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (last_band != nl_band->nla_type) { 136fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\tBand %d:\n", nl_band->nla_type + 1); 137fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg band_had_freq = false; 138ee9cd9875412bbe0ab24c4f8acd25253ec1410c4Johannes Berg } 139fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg last_band = nl_band->nla_type; 14048aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich 141fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band), 142fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_len(nl_band), NULL); 14348aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich 144fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) { 145fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg __u16 cap = nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]); 146fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_ht_capability(cap); 147fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 148fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) { 149fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg __u8 exponent = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]); 150fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_ampdu_length(exponent); 151fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 152fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) { 153fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg __u8 spacing = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]); 154fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_ampdu_spacing(spacing); 155fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 156fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] && 157fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]) == 16) 158fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_ht_mcs(nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET])); 159fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_VHT_CAPA] && 160fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]) 161fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_vht_info(nla_get_u32(tb_band[NL80211_BAND_ATTR_VHT_CAPA]), 162fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_data(tb_band[NL80211_BAND_ATTR_VHT_MCS_SET])); 163fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 164fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_FREQS]) { 165fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (!band_had_freq) { 166fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\t\tFrequencies:\n"); 167fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg band_had_freq = true; 168fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 169fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { 170fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg uint32_t freq; 171fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), 172fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_len(nl_freq), freq_policy); 173fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) 174fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg continue; 175fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); 176fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\t\t\t* %d MHz [%d]", freq, ieee80211_frequency_to_channel(freq)); 177fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 178fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] && 179fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) 180fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf(" (%.1f dBm)", 0.01 * nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER])); 181fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 182fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg open = 0; 183fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) { 184fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_flag("disabled", &open); 185fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg goto next; 186fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 187f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer 188f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer /* If both flags are set assume an new kernel */ 189f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR] && tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS]) { 190f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer print_flag("no IR", &open); 191f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer } else if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) { 192f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer print_flag("passive scan", &open); 193f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer } else if (tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS]){ 194f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer print_flag("no ibss", &open); 195f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer } 196f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer 197fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) 198fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_flag("radar detection", &open); 199fb70e110d39247eb1999fd094300fce6bc41002fJohannes Bergnext: 200fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (open) 201fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf(")"); 202fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\n"); 203fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 2044b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi if (!tb_freq[NL80211_FREQUENCY_ATTR_DISABLED] && tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) { 2054b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi enum nl80211_dfs_state state = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]); 2064b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi unsigned long time; 2074b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi 2084b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi printf("\t\t\t DFS state: %s", dfs_state_name(state)); 2094b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_TIME]) { 2104b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi time = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_TIME]); 2114b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi printf(" (for %lu sec)", time/1000); 2124b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi } 2134b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi printf("\n"); 2148220747fc0bddab4f368b2dcb3fa00370ad6246bJanusz Dziedzic if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]) 2158220747fc0bddab4f368b2dcb3fa00370ad6246bJanusz Dziedzic printf("\t\t\t DFS CAC time: %u ms\n", 2168220747fc0bddab4f368b2dcb3fa00370ad6246bJanusz Dziedzic nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME])); 217fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 2184b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi 21948aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich } 22048aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich } 22179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 222fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_RATES]) { 223fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\t\tBitrates (non-HT):\n"); 224fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { 225fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate), 226fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_len(nl_rate), rate_policy); 227fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) 228fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg continue; 229fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\t\t\t* %2.1f Mbps", 0.1 * nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE])); 230fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg open = 0; 231fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_rate[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE]) 232fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_flag("short preamble supported", &open); 233fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (open) 234fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf(")"); 235fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\n"); 236fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 237fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 23879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg } 23979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg } 24079f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 24141be37f2ac0a4d54525e1397c36fac64ae8ea412Johannes Berg if (tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) 24241be37f2ac0a4d54525e1397c36fac64ae8ea412Johannes Berg printf("\tmax # scan SSIDs: %d\n", 24341be37f2ac0a4d54525e1397c36fac64ae8ea412Johannes Berg nla_get_u8(tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])); 244f9c112b60d2c551f43419054f9613e3ddac8be18Johannes Berg if (tb_msg[NL80211_ATTR_MAX_SCAN_IE_LEN]) 245f9c112b60d2c551f43419054f9613e3ddac8be18Johannes Berg printf("\tmax scan IEs length: %d bytes\n", 2468eaa9ee5774d4eb512dd1cff2d8a6efa51bddf27Johannes Berg nla_get_u16(tb_msg[NL80211_ATTR_MAX_SCAN_IE_LEN])); 2473fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho if (tb_msg[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]) 2483fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho printf("\tmax # sched scan SSIDs: %d\n", 2493fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho nla_get_u8(tb_msg[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])); 2503fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho if (tb_msg[NL80211_ATTR_MAX_MATCH_SETS]) 2513fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho printf("\tmax # match sets: %d\n", 2523fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho nla_get_u8(tb_msg[NL80211_ATTR_MAX_MATCH_SETS])); 25341be37f2ac0a4d54525e1397c36fac64ae8ea412Johannes Berg 254625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg if (tb_msg[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { 255625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg unsigned int frag; 256625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg 257625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg frag = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]); 258625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg if (frag != (unsigned int)-1) 259625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg printf("\tFragmentation threshold: %d\n", frag); 260625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg } 261625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg 262625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg if (tb_msg[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) { 263625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg unsigned int rts; 264625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg 265625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg rts = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_RTS_THRESHOLD]); 266625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg if (rts != (unsigned int)-1) 267625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg printf("\tRTS threshold: %d\n", rts); 268625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg } 269625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg 270c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy if (tb_msg[NL80211_ATTR_WIPHY_RETRY_SHORT] || 271c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy tb_msg[NL80211_ATTR_WIPHY_RETRY_LONG]) { 272c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy unsigned char retry_short = 0, retry_long = 0; 273c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy 274c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy if (tb_msg[NL80211_ATTR_WIPHY_RETRY_SHORT]) 275c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy retry_short = nla_get_u8(tb_msg[NL80211_ATTR_WIPHY_RETRY_SHORT]); 276c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy if (tb_msg[NL80211_ATTR_WIPHY_RETRY_LONG]) 277c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy retry_long = nla_get_u8(tb_msg[NL80211_ATTR_WIPHY_RETRY_LONG]); 278c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy if (retry_short == retry_long) { 279c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy printf("\tRetry short long limit: %d\n", retry_short); 280c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy } else { 281c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy printf("\tRetry short limit: %d\n", retry_short); 282c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy printf("\tRetry long limit: %d\n", retry_long); 283c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy } 284c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy } 285c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy 286b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek if (tb_msg[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { 287b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek unsigned char coverage; 288b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek 289b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek coverage = nla_get_u8(tb_msg[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); 290b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek /* See handle_distance() for an explanation where the '450' comes from */ 291b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage); 292b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek } 293b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek 294810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) { 295810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg int num = nla_len(tb_msg[NL80211_ATTR_CIPHER_SUITES]) / sizeof(__u32); 296810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg int i; 297810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg __u32 *ciphers = nla_data(tb_msg[NL80211_ATTR_CIPHER_SUITES]); 298810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg if (num > 0) { 299810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg printf("\tSupported Ciphers:\n"); 300810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg for (i = 0; i < num; i++) 301810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg printf("\t\t* %s\n", 302810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg cipher_name(ciphers[i])); 303810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg } 304810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg } 305810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg 306afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX] && 307afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX]) 308afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf printf("\tAvailable Antennas: TX %#x RX %#x\n", 309afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX]), 310afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX])); 311afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf 312afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_TX] && 313afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf tb_msg[NL80211_ATTR_WIPHY_ANTENNA_RX]) 314afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf printf("\tConfigured Antennas: TX %#x RX %#x\n", 315afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_TX]), 316afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_RX])); 317afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf 3189a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]) { 3199a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\tSupported interface modes:\n"); 3209a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_mode, tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES], rem_mode) 3218ef6df4fc69453f89e586d5bde866a9d2c9d77eaJohannes Berg printf("\t\t * %s\n", iftype_name(nla_type(nl_mode))); 3229a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 3236367e71a165680225aec25f1c4521626f996b76eJohannes Berg 3241c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES]) { 3251c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("\tsoftware interface modes (can always be added):\n"); 3261c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_for_each_nested(nl_mode, tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES], rem_mode) 3271c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("\t\t * %s\n", iftype_name(nla_type(nl_mode))); 3281c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3291c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3301c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) { 3311c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg struct nlattr *nl_combi; 3321c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg int rem_combi; 333f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg bool have_combinations = false; 3341c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3351c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_for_each_nested(nl_combi, tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], rem_combi) { 3361c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = { 3371c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED }, 3381c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 }, 3391c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG }, 3401c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 }, 341c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 }, 3421c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg }; 3431c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB]; 3441c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = { 3451c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED }, 3461c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 }, 3471c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg }; 3481c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT]; 3491c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg struct nlattr *nl_limit; 3501c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg int err, rem_limit; 3511c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg bool comma = false; 3521c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 353f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg if (!have_combinations) { 354f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg printf("\tvalid interface combinations:\n"); 355f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg have_combinations = true; 356f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg } 357f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg 3581c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("\t\t * "); 3591c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3601c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB, 3611c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nl_combi, iface_combination_policy); 3621c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] || 3631c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg !tb_comb[NL80211_IFACE_COMB_MAXNUM] || 3641c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) { 3651c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf(" <failed to parse>\n"); 3661c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg goto broken_combination; 3671c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3681c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3691c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) { 3701c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg bool ift_comma = false; 3711c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3721c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT, 3731c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nl_limit, iface_limit_policy); 3741c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) { 3751c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("<failed to parse>\n"); 3761c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg goto broken_combination; 3771c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3781c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3791c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (comma) 3801c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf(", "); 3811c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg comma = true; 3821c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("#{"); 3831c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3841c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_for_each_nested(nl_mode, tb_limit[NL80211_IFACE_LIMIT_TYPES], rem_mode) { 3851c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("%s %s", ift_comma ? "," : "", 3861c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg iftype_name(nla_type(nl_mode))); 3871c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg ift_comma = true; 3881c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3891c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX])); 3901c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3911c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf(",\n\t\t "); 3921c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 393c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf("total <= %d, #channels <= %d%s", 3941c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]), 3951c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]), 3961c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ? 3971c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg ", STA/AP BI must match" : ""); 398c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) { 399c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]); 400c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich 401c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich if (widths) { 402c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich int width; 403c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich bool first = true; 404c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich 405c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf(", radar detect widths: {"); 406c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich for (width = 0; width < 32; width++) 407c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich if (widths & (1 << width)) { 408c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf("%s %s", 409c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich first ? "":",", 410c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich channel_width_name(width)); 411c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich first = false; 412c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich } 413c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf(" }\n"); 414c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich } 415c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich } 416c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf("\n"); 4171c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Bergbroken_combination: 4181c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg ; 4191c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 420f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg 421f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg if (!have_combinations) 422f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg printf("\tinterface combinations are not supported\n"); 4231c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 4241c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 4259a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) { 4269a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\tSupported commands:\n"); 4279a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_cmd, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS], rem_cmd) 4289a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\t\t * %s\n", command_name(nla_get_u32(nl_cmd))); 4299a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4306367e71a165680225aec25f1c4521626f996b76eJohannes Berg 4319a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (tb_msg[NL80211_ATTR_TX_FRAME_TYPES]) { 4329a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\tSupported TX frame types:\n"); 4339a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_if, tb_msg[NL80211_ATTR_TX_FRAME_TYPES], rem_if) { 4349a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg bool printed = false; 4359a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_ftype, nl_if, rem_ftype) { 4369a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (!printed) 4379a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\t\t * %s:", iftype_name(nla_type(nl_if))); 4389a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printed = true; 43958e343418820598cb58bd4bc7d5694e811a86972Johannes Berg printf(" 0x%.2x", nla_get_u16(nl_ftype)); 4409a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4419a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (printed) 4429a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\n"); 4439a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4449a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4459990c1e9a89982efed4e50fb846968bcc6b60b46Marcel Holtmann 4469a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (tb_msg[NL80211_ATTR_RX_FRAME_TYPES]) { 4479a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\tSupported RX frame types:\n"); 4489a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_if, tb_msg[NL80211_ATTR_RX_FRAME_TYPES], rem_if) { 4499a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg bool printed = false; 4509a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_ftype, nl_if, rem_ftype) { 4519a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (!printed) 4529a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\t\t * %s:", iftype_name(nla_type(nl_if))); 4539a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printed = true; 45458e343418820598cb58bd4bc7d5694e811a86972Johannes Berg printf(" 0x%.2x", nla_get_u16(nl_ftype)); 4559a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4569a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (printed) 4579a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\n"); 4589a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4599a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4609990c1e9a89982efed4e50fb846968bcc6b60b46Marcel Holtmann 4613ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_msg[NL80211_ATTR_SUPPORT_IBSS_RSN]) 46283f10169568ececba5d9f35c136c6475742a8487Johannes Berg printf("\tDevice supports RSN-IBSS.\n"); 4633ff24563977fba0242c359fb476229e4b4af97faJohannes Berg 4643ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_msg[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]) { 4653ff24563977fba0242c359fb476229e4b4af97faJohannes Berg struct nlattr *tb_wowlan[NUM_NL80211_WOWLAN_TRIG]; 4663ff24563977fba0242c359fb476229e4b4af97faJohannes Berg static struct nla_policy wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = { 4673ff24563977fba0242c359fb476229e4b4af97faJohannes Berg [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG }, 4683ff24563977fba0242c359fb476229e4b4af97faJohannes Berg [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG }, 4693ff24563977fba0242c359fb476229e4b4af97faJohannes Berg [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG }, 4701c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .minlen = 12 }, 4713a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED] = { .type = NLA_FLAG }, 4723a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG }, 4733a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG }, 4743a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG }, 4753a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG }, 4764888e6baeeecee786a81259e6ab327740215a7f0Luciano Coelho [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_U32 }, 477819b78cc931b9bb20f4c7e9879bde1d807cbdbb3Johannes Berg [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED }, 4783ff24563977fba0242c359fb476229e4b4af97faJohannes Berg }; 479c82868da4d5862751d9be9ee788d645184f323ecAmitkumar Karwar struct nl80211_pattern_support *pat; 4803ff24563977fba0242c359fb476229e4b4af97faJohannes Berg int err; 4813ff24563977fba0242c359fb476229e4b4af97faJohannes Berg 4823ff24563977fba0242c359fb476229e4b4af97faJohannes Berg err = nla_parse_nested(tb_wowlan, MAX_NL80211_WOWLAN_TRIG, 4833ff24563977fba0242c359fb476229e4b4af97faJohannes Berg tb_msg[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED], 4843ff24563977fba0242c359fb476229e4b4af97faJohannes Berg wowlan_policy); 4853ff24563977fba0242c359fb476229e4b4af97faJohannes Berg printf("\tWoWLAN support:"); 4863ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (err) { 4873ff24563977fba0242c359fb476229e4b4af97faJohannes Berg printf(" <failed to parse>\n"); 4883ff24563977fba0242c359fb476229e4b4af97faJohannes Berg } else { 4893ff24563977fba0242c359fb476229e4b4af97faJohannes Berg printf("\n"); 4903ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_ANY]) 4913a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on anything (device continues operating normally)\n"); 4923ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_DISCONNECT]) 4933a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on disconnect\n"); 4943ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_MAGIC_PKT]) 4953a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on magic packet\n"); 4963ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { 4973ff24563977fba0242c359fb476229e4b4af97faJohannes Berg pat = nla_data(tb_wowlan[NL80211_WOWLAN_TRIG_PKT_PATTERN]); 4981c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar printf("\t\t * wake up on pattern match, up to %u patterns of %u-%u bytes,\n" 4991c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar "\t\t maximum packet offset %u bytes\n", 5001c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar pat->max_patterns, pat->min_pattern_len, pat->max_pattern_len, 5011c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar (nla_len(tb_wowlan[NL80211_WOWLAN_TRIG_PKT_PATTERN]) < 5021c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar sizeof(*pat)) ? 0 : pat->max_pkt_offset); 5033ff24563977fba0242c359fb476229e4b4af97faJohannes Berg } 5043a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED]) 5053a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * can do GTK rekeying\n"); 5063a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) 5073a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on GTK rekey failure\n"); 5083a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) 5093a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on EAP identity request\n"); 5103a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) 5113a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on 4-way handshake\n"); 5123a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) 5133a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on rfkill release\n"); 514d516c5bc8cf32aab5cde9ed1aee4b2ae4794a917Luciano Coelho if (tb_wowlan[NL80211_WOWLAN_TRIG_NET_DETECT]) 5154888e6baeeecee786a81259e6ab327740215a7f0Luciano Coelho printf("\t\t * wake up on network detection, up to %d match sets\n", 5164888e6baeeecee786a81259e6ab327740215a7f0Luciano Coelho nla_get_u32(tb_wowlan[NL80211_WOWLAN_TRIG_NET_DETECT])); 517819b78cc931b9bb20f4c7e9879bde1d807cbdbb3Johannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) 518819b78cc931b9bb20f4c7e9879bde1d807cbdbb3Johannes Berg printf("\t\t * wake up on TCP connection\n"); 5193ff24563977fba0242c359fb476229e4b4af97faJohannes Berg } 52083f10169568ececba5d9f35c136c6475742a8487Johannes Berg } 52183f10169568ececba5d9f35c136c6475742a8487Johannes Berg 5222e4f65ca05f4dfb3b01638e69651c9bba942d3b7Johannes Berg if (tb_msg[NL80211_ATTR_ROAM_SUPPORT]) 5232e4f65ca05f4dfb3b01638e69651c9bba942d3b7Johannes Berg printf("\tDevice supports roaming.\n"); 5242e4f65ca05f4dfb3b01638e69651c9bba942d3b7Johannes Berg 5258b46999550ccd837df790f2927b0a8d0cff0cb98Johannes Berg if (tb_msg[NL80211_ATTR_SUPPORT_AP_UAPSD]) 5268b46999550ccd837df790f2927b0a8d0cff0cb98Johannes Berg printf("\tDevice supports AP-side u-APSD.\n"); 5278b46999550ccd837df790f2927b0a8d0cff0cb98Johannes Berg 528a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]) { 529a82abc2cac9dea7def53070565201145c76c8c6cBen Greear struct ieee80211_ht_cap *cm; 530a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\tHT Capability overrides:\n"); 531a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (nla_len(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]) >= sizeof(*cm)) { 532a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm = nla_data(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]); 533a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * MCS: %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx" 534a82abc2cac9dea7def53070565201145c76c8c6cBen Greear " %02hhx %02hhx %02hhx %02hhx\n", 535a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[0], cm->mcs.rx_mask[1], 536a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[2], cm->mcs.rx_mask[3], 537a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[4], cm->mcs.rx_mask[5], 538a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[6], cm->mcs.rx_mask[7], 539a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[8], cm->mcs.rx_mask[9]); 540a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->cap_info & htole16(IEEE80211_HT_CAP_MAX_AMSDU)) 541a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * maximum A-MSDU length\n"); 542a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->cap_info & htole16(IEEE80211_HT_CAP_SUP_WIDTH_20_40)) 543a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * supported channel width\n"); 544a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->cap_info & htole16(IEEE80211_HT_CAP_SGI_40)) 545a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * short GI for 40 MHz\n"); 546a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR) 547a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * max A-MPDU length exponent\n"); 548a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY) 549a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * min MPDU start spacing\n"); 550a82abc2cac9dea7def53070565201145c76c8c6cBen Greear } else { 551a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\tERROR: capabilities mask is too short, expected: %d, received: %d\n", 552a82abc2cac9dea7def53070565201145c76c8c6cBen Greear (int)(sizeof(*cm)), 553a82abc2cac9dea7def53070565201145c76c8c6cBen Greear (int)(nla_len(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]))); 554a82abc2cac9dea7def53070565201145c76c8c6cBen Greear } 555a82abc2cac9dea7def53070565201145c76c8c6cBen Greear } 556a82abc2cac9dea7def53070565201145c76c8c6cBen Greear 557632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg if (tb_msg[NL80211_ATTR_FEATURE_FLAGS]) { 558d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg unsigned int features = nla_get_u32(tb_msg[NL80211_ATTR_FEATURE_FLAGS]); 559d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg 560d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_SK_TX_STATUS) 561632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg printf("\tDevice supports TX status socket option.\n"); 562d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_HT_IBSS) 563632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg printf("\tDevice supports HT-IBSS.\n"); 564d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_INACTIVITY_TIMER) 565d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg printf("\tDevice has client inactivity timer.\n"); 566d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_CELL_BASE_REG_HINTS) 567d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg printf("\tDevice accepts cell base station regulatory hints.\n"); 568d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL) 569d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg printf("\tP2P Device uses a channel (of the concurrent ones)\n"); 5705973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_SAE) 5715973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports SAE with AUTHENTICATE command\n"); 572fe862239636c303372184abc5635097b43777e77Sam Leffler if (features & NL80211_FEATURE_LOW_PRIORITY_SCAN) 573fe862239636c303372184abc5635097b43777e77Sam Leffler printf("\tDevice supports low priority scan.\n"); 574fe862239636c303372184abc5635097b43777e77Sam Leffler if (features & NL80211_FEATURE_SCAN_FLUSH) 575fe862239636c303372184abc5635097b43777e77Sam Leffler printf("\tDevice supports scan flush.\n"); 576afa2be2ff4e033a07c8fa28b5f52087f5fe50ad6Antonio Quartulli if (features & NL80211_FEATURE_AP_SCAN) 577afa2be2ff4e033a07c8fa28b5f52087f5fe50ad6Antonio Quartulli printf("\tDevice supports AP scan.\n"); 5785973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_VIF_TXPOWER) 5795973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports per-vif TX power setting\n"); 5805973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_NEED_OBSS_SCAN) 5815973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tUserspace should do OBSS scan and generate 20/40 coex reports\n"); 5825973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_P2P_GO_CTWIN) 5835973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tP2P GO supports CT window setting\n"); 5845973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_P2P_GO_OPPPS) 5855973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tP2P GO supports opportunistic powersave setting\n"); 5865973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) 5875973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDriver supports full state transitions for AP/GO clients\n"); 5885973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_USERSPACE_MPM) 5895973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDriver supports a userspace MPM\n"); 5905973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_ACTIVE_MONITOR) 5915973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports active monitor (which will ACK incoming frames)\n"); 5925973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE) 5935973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDriver/device bandwidth changes during BSS lifetime (AP/GO mode)\n"); 5945973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) 5955973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice adds DS IE to probe requests\n"); 5965973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_WFA_TPC_IE_IN_PROBES) 5975973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice adds WFA TPC Report IE to probe requests\n"); 5985973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_QUIET) 5995973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports quiet requests from AP\n"); 6005973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_TX_POWER_INSERTION) 6015973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice can update TPC Report IE\n"); 602e642142d68850b7eb161489a984ec6817b10c51bLorenzo Bianconi if (features & NL80211_FEATURE_ACKTO_ESTIMATION) 603e642142d68850b7eb161489a984ec6817b10c51bLorenzo Bianconi printf("\tDevice supports ACK timeout estimation.\n"); 6045973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_STATIC_SMPS) 6055973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports static SMPS\n"); 6065973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_DYNAMIC_SMPS) 6075973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports dynamic SMPS\n"); 608e15ec7498ea2368ae13f9933eeac142bb464baf7Johannes Berg if (features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION) 609e15ec7498ea2368ae13f9933eeac142bb464baf7Johannes Berg printf("\tDevice supports WMM-AC admission (TSPECs)\n"); 610ced5522d199b7b1b5b10cf94b276b74314ca8da3Ben Greear if (features & NL80211_FEATURE_MAC_ON_CREATE) 611ced5522d199b7b1b5b10cf94b276b74314ca8da3Ben Greear printf("\tDevice supports configuring vdev MAC-addr on create.\n"); 612c2f0d6894e8c535c02e3de9d5820a06a95130906Arik Nemtsov if (features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) 613c2f0d6894e8c535c02e3de9d5820a06a95130906Arik Nemtsov printf("\tDevice supports TDLS channel switching\n"); 614632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg } 615632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg 616f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com if (tb_msg[NL80211_ATTR_EXT_FEATURES]) { 617f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com struct nlattr *tb = tb_msg[NL80211_ATTR_EXT_FEATURES]; 618f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com 619f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com if (ext_feature_isset(nla_data(tb), nla_len(tb), 620f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com NL80211_EXT_FEATURE_VHT_IBSS)) 621f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com printf("\tDevice supports VHT-IBSS.\n"); 622f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com } 623f0e30bd5ef6ded7b85e7513cab3e02f29883a574Janusz.Dziedzic@tieto.com 6249b4a19894ece2ea7cd47a8b30843ce7daa49452cJohannes Berg if (tb_msg[NL80211_ATTR_TDLS_SUPPORT]) 6259b4a19894ece2ea7cd47a8b30843ce7daa49452cJohannes Berg printf("\tDevice supports T-DLS.\n"); 6269b4a19894ece2ea7cd47a8b30843ce7daa49452cJohannes Berg 627aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar if (tb_msg[NL80211_ATTR_COALESCE_RULE]) { 628aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar struct nl80211_coalesce_rule_support *rule; 629aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar struct nl80211_pattern_support *pat; 630aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar 631aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar printf("\tCoalesce support:\n"); 632aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar rule = nla_data(tb_msg[NL80211_ATTR_COALESCE_RULE]); 633aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar pat = &rule->pat; 634aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar printf("\t\t * Maximum %u coalesce rules supported\n" 635aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar "\t\t * Each rule contains upto %u patterns of %u-%u bytes,\n" 636aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar "\t\t maximum packet offset %u bytes\n" 637aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar "\t\t * Maximum supported coalescing delay %u msecs\n", 638aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar rule->max_rules, pat->max_patterns, pat->min_pattern_len, 639aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar pat->max_pattern_len, pat->max_pkt_offset, rule->max_delay); 640aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar } 641aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar 64279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg return NL_SKIP; 64379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg} 64479f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 645c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Bergstatic bool nl80211_has_split_wiphy = false; 646c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg 6477c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_info(struct nl80211_state *state, 6487c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg struct nl_cb *cb, 649d631650b0d5725a487b87ad4d5d1238543aaf011Johannes Berg struct nl_msg *msg, 65005514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg int argc, char **argv, 65105514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg enum id_input id) 65279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg{ 653c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg char *feat_args[] = { "features", "-q" }; 654c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg int err; 655c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg 656c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg err = handle_cmd(state, CIB_NONE, 2, feat_args); 657c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg if (!err && nl80211_has_split_wiphy) { 658c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP); 659c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg nlmsg_hdr(msg)->nlmsg_flags |= NLM_F_DUMP; 660c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg } 661c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg 66279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_phy_handler, NULL); 66379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 66470391ccff8e0dd17e4cc9d54d6c9dd8830c99928Johannes Berg return 0; 66579f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg} 666c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg__COMMAND(NULL, info, "info", NULL, NL80211_CMD_GET_WIPHY, 0, 0, CIB_PHY, handle_info, 6671633ddf7c6a66933d77b052d8637b851d3f2048fJohannes Berg "Show capabilities for the specified wireless device.", NULL); 668ea35fc0b841466473cab58317ecef20742351c45Johannes BergTOPLEVEL(list, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info, 669ea35fc0b841466473cab58317ecef20742351c45Johannes Berg "List all wireless devices and their capabilities."); 67001ae06f9e9d2bf3e7e998bcbda06fd916c92f34eJohannes BergTOPLEVEL(phy, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info, NULL); 671bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg 672bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Bergstatic int handle_commands(struct nl80211_state *state, 673bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg struct nl_cb *cb, struct nl_msg *msg, 674bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg int argc, char **argv, enum id_input id) 675bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg{ 676bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg int i; 677bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg for (i = 1; i < NL80211_CMD_MAX; i++) 678bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg printf("%d (0x%x): %s\n", i, i, command_name(i)); 679bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg /* don't send netlink messages */ 680bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg return 2; 681bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg} 682bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes BergTOPLEVEL(commands, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_NONE, handle_commands, 683bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg "list all known commands and their decimal & hex value"); 684fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 685fb70e110d39247eb1999fd094300fce6bc41002fJohannes Bergstatic int print_feature_handler(struct nl_msg *msg, void *arg) 686fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg{ 687fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; 688fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 689c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg bool print = (unsigned long)arg; 690c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg#define maybe_printf(...) do { if (print) printf(__VA_ARGS__); } while (0) 691fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 692fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 693fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg genlmsg_attrlen(gnlh, 0), NULL); 694fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 695fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]) { 696fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg uint32_t feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]); 697fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 698c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg maybe_printf("nl80211 features: 0x%x\n", feat); 699c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP) { 700c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg maybe_printf("\t* split wiphy dump\n"); 701c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg nl80211_has_split_wiphy = true; 702c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg } 703fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 704fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 705fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg return NL_SKIP; 706fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg} 707fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 708fb70e110d39247eb1999fd094300fce6bc41002fJohannes Bergstatic int handle_features(struct nl80211_state *state, 709fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg struct nl_cb *cb, struct nl_msg *msg, 710fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg int argc, char **argv, enum id_input id) 711fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg{ 712c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg unsigned long print = argc == 0 || strcmp(argv[0], "-q"); 713c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_feature_handler, (void *)print); 714fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg return 0; 715fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg} 716fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 717c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes BergTOPLEVEL(features, "", NL80211_CMD_GET_PROTOCOL_FEATURES, 0, CIB_NONE, 718fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg handle_features, ""); 719