info.c revision ced5522d199b7b1b5b10cf94b276b74314ca8da3
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 6679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Bergstatic int print_phy_handler(struct nl_msg *msg, void *arg) 6779f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg{ 6879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; 6979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 7079f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 7179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; 7279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 7379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; 7479f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { 7579f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, 7679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG }, 77f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG }, 78f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer [__NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, 7979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, 80c1081c2008896ede5f50e9173f9427e212bf79f1Johannes Berg [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, 8179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg }; 8279f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 8379f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1]; 8479f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = { 8579f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 }, 8679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG }, 8779f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg }; 8879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 8979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *nl_band; 9079f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *nl_freq; 9179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg struct nlattr *nl_rate; 926367e71a165680225aec25f1c4521626f996b76eJohannes Berg struct nlattr *nl_mode; 939990c1e9a89982efed4e50fb846968bcc6b60b46Marcel Holtmann struct nlattr *nl_cmd; 949a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg struct nlattr *nl_if, *nl_ftype; 959a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg int rem_band, rem_freq, rem_rate, rem_mode, rem_cmd, rem_ftype, rem_if; 9679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg int open; 97fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg /* 98fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg * static variables only work here, other applications need to use the 99fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg * callback pointer and store them there so they can be multithreaded 100fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg * and/or have multiple netlink sockets, etc. 101fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg */ 102fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg static int64_t phy_id = -1; 103fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg static int last_band = -1; 104fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg static bool band_had_freq = false; 105fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg bool print_name = true; 10679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 10779f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 10879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg genlmsg_attrlen(gnlh, 0), NULL); 10979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 110fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_msg[NL80211_ATTR_WIPHY]) { 111fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]) == phy_id) 112fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_name = false; 113fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg else 114fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg last_band = -1; 115fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg phy_id = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]); 116fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 117fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (print_name && tb_msg[NL80211_ATTR_WIPHY_NAME]) 118d631650b0d5725a487b87ad4d5d1238543aaf011Johannes Berg printf("Wiphy %s\n", nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME])); 119d631650b0d5725a487b87ad4d5d1238543aaf011Johannes Berg 120fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg /* needed for split dump */ 121fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_msg[NL80211_ATTR_WIPHY_BANDS]) { 122fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) { 123fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (last_band != nl_band->nla_type) { 124fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\tBand %d:\n", nl_band->nla_type + 1); 125fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg band_had_freq = false; 126ee9cd9875412bbe0ab24c4f8acd25253ec1410c4Johannes Berg } 127fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg last_band = nl_band->nla_type; 12848aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich 129fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band), 130fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_len(nl_band), NULL); 13148aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich 132fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) { 133fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg __u16 cap = nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]); 134fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_ht_capability(cap); 135fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 136fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) { 137fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg __u8 exponent = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]); 138fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_ampdu_length(exponent); 139fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 140fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) { 141fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg __u8 spacing = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]); 142fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_ampdu_spacing(spacing); 143fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 144fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] && 145fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]) == 16) 146fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_ht_mcs(nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET])); 147fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_VHT_CAPA] && 148fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]) 149fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_vht_info(nla_get_u32(tb_band[NL80211_BAND_ATTR_VHT_CAPA]), 150fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_data(tb_band[NL80211_BAND_ATTR_VHT_MCS_SET])); 151fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 152fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_FREQS]) { 153fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (!band_had_freq) { 154fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\t\tFrequencies:\n"); 155fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg band_had_freq = true; 156fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 157fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { 158fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg uint32_t freq; 159fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), 160fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_len(nl_freq), freq_policy); 161fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) 162fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg continue; 163fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); 164fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\t\t\t* %d MHz [%d]", freq, ieee80211_frequency_to_channel(freq)); 165fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 166fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] && 167fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) 168fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf(" (%.1f dBm)", 0.01 * nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER])); 169fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 170fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg open = 0; 171fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) { 172fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_flag("disabled", &open); 173fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg goto next; 174fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 175f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer 176f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer /* If both flags are set assume an new kernel */ 177f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR] && tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS]) { 178f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer print_flag("no IR", &open); 179f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer } else if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) { 180f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer print_flag("passive scan", &open); 181f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer } else if (tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS]){ 182f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer print_flag("no ibss", &open); 183f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer } 184f0c48e7bbda5feb73d4f90c01367d17b8595d08bIlan Peer 185fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) 186fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_flag("radar detection", &open); 187fb70e110d39247eb1999fd094300fce6bc41002fJohannes Bergnext: 188fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (open) 189fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf(")"); 190fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\n"); 191fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 1924b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi if (!tb_freq[NL80211_FREQUENCY_ATTR_DISABLED] && tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) { 1934b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi enum nl80211_dfs_state state = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]); 1944b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi unsigned long time; 1954b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi 1964b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi printf("\t\t\t DFS state: %s", dfs_state_name(state)); 1974b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_TIME]) { 1984b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi time = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_TIME]); 1994b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi printf(" (for %lu sec)", time/1000); 2004b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi } 2014b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi printf("\n"); 2028220747fc0bddab4f368b2dcb3fa00370ad6246bJanusz Dziedzic if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]) 2038220747fc0bddab4f368b2dcb3fa00370ad6246bJanusz Dziedzic printf("\t\t\t DFS CAC time: %u ms\n", 2048220747fc0bddab4f368b2dcb3fa00370ad6246bJanusz Dziedzic nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME])); 205fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 2064b99e6a68c2c37e3c8087265c85f2c4d7326f2ecZefir Kurtisi 20748aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich } 20848aaf2d951c1890d1d6d3fbb761975f0f9f1df0aSimon Wunderlich } 20979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 210fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_band[NL80211_BAND_ATTR_RATES]) { 211fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\t\tBitrates (non-HT):\n"); 212fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { 213fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate), 214fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_len(nl_rate), rate_policy); 215fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) 216fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg continue; 217fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\t\t\t* %2.1f Mbps", 0.1 * nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE])); 218fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg open = 0; 219fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_rate[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE]) 220fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg print_flag("short preamble supported", &open); 221fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (open) 222fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf(")"); 223fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg printf("\n"); 224fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 225fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 22679f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg } 22779f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg } 22879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 22941be37f2ac0a4d54525e1397c36fac64ae8ea412Johannes Berg if (tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) 23041be37f2ac0a4d54525e1397c36fac64ae8ea412Johannes Berg printf("\tmax # scan SSIDs: %d\n", 23141be37f2ac0a4d54525e1397c36fac64ae8ea412Johannes Berg nla_get_u8(tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])); 232f9c112b60d2c551f43419054f9613e3ddac8be18Johannes Berg if (tb_msg[NL80211_ATTR_MAX_SCAN_IE_LEN]) 233f9c112b60d2c551f43419054f9613e3ddac8be18Johannes Berg printf("\tmax scan IEs length: %d bytes\n", 2348eaa9ee5774d4eb512dd1cff2d8a6efa51bddf27Johannes Berg nla_get_u16(tb_msg[NL80211_ATTR_MAX_SCAN_IE_LEN])); 23541be37f2ac0a4d54525e1397c36fac64ae8ea412Johannes Berg 236625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg if (tb_msg[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { 237625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg unsigned int frag; 238625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg 239625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg frag = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]); 240625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg if (frag != (unsigned int)-1) 241625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg printf("\tFragmentation threshold: %d\n", frag); 242625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg } 243625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg 244625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg if (tb_msg[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) { 245625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg unsigned int rts; 246625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg 247625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg rts = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_RTS_THRESHOLD]); 248625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg if (rts != (unsigned int)-1) 249625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg printf("\tRTS threshold: %d\n", rts); 250625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg } 251625aa4aefa0ddc0579e12c0fcf9f2780c10d28d5Johannes Berg 252c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy if (tb_msg[NL80211_ATTR_WIPHY_RETRY_SHORT] || 253c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy tb_msg[NL80211_ATTR_WIPHY_RETRY_LONG]) { 254c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy unsigned char retry_short = 0, retry_long = 0; 255c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy 256c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy if (tb_msg[NL80211_ATTR_WIPHY_RETRY_SHORT]) 257c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy retry_short = nla_get_u8(tb_msg[NL80211_ATTR_WIPHY_RETRY_SHORT]); 258c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy if (tb_msg[NL80211_ATTR_WIPHY_RETRY_LONG]) 259c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy retry_long = nla_get_u8(tb_msg[NL80211_ATTR_WIPHY_RETRY_LONG]); 260c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy if (retry_short == retry_long) { 261c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy printf("\tRetry short long limit: %d\n", retry_short); 262c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy } else { 263c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy printf("\tRetry short limit: %d\n", retry_short); 264c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy printf("\tRetry long limit: %d\n", retry_long); 265c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy } 266c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy } 267c993e6e7d58f542a3f3a4fd744578fab15e305bdUjjal Roy 268b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek if (tb_msg[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { 269b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek unsigned char coverage; 270b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek 271b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek coverage = nla_get_u8(tb_msg[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); 272b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek /* See handle_distance() for an explanation where the '450' comes from */ 273b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage); 274b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek } 275b2f92dd087b807c6d34d26810bb1f912d8e4f804Lukáš Turek 276810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) { 277810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg int num = nla_len(tb_msg[NL80211_ATTR_CIPHER_SUITES]) / sizeof(__u32); 278810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg int i; 279810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg __u32 *ciphers = nla_data(tb_msg[NL80211_ATTR_CIPHER_SUITES]); 280810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg if (num > 0) { 281810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg printf("\tSupported Ciphers:\n"); 282810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg for (i = 0; i < num; i++) 283810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg printf("\t\t* %s\n", 284810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg cipher_name(ciphers[i])); 285810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg } 286810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg } 287810e05c3e167da0ba64fea622a263f090c7ce31fJohannes Berg 288afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX] && 289afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX]) 290afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf printf("\tAvailable Antennas: TX %#x RX %#x\n", 291afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX]), 292afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX])); 293afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf 294afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_TX] && 295afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf tb_msg[NL80211_ATTR_WIPHY_ANTENNA_RX]) 296afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf printf("\tConfigured Antennas: TX %#x RX %#x\n", 297afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_TX]), 298afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_RX])); 299afce7986d04d025c2893591cfde20c124b1170d8Bruno Randolf 3009a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]) { 3019a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\tSupported interface modes:\n"); 3029a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_mode, tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES], rem_mode) 3038ef6df4fc69453f89e586d5bde866a9d2c9d77eaJohannes Berg printf("\t\t * %s\n", iftype_name(nla_type(nl_mode))); 3049a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 3056367e71a165680225aec25f1c4521626f996b76eJohannes Berg 3061c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES]) { 3071c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("\tsoftware interface modes (can always be added):\n"); 3081c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_for_each_nested(nl_mode, tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES], rem_mode) 3091c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("\t\t * %s\n", iftype_name(nla_type(nl_mode))); 3101c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3111c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3121c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) { 3131c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg struct nlattr *nl_combi; 3141c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg int rem_combi; 315f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg bool have_combinations = false; 3161c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3171c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_for_each_nested(nl_combi, tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], rem_combi) { 3181c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = { 3191c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED }, 3201c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 }, 3211c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG }, 3221c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 }, 323c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 }, 3241c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg }; 3251c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB]; 3261c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = { 3271c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED }, 3281c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 }, 3291c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg }; 3301c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT]; 3311c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg struct nlattr *nl_limit; 3321c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg int err, rem_limit; 3331c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg bool comma = false; 3341c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 335f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg if (!have_combinations) { 336f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg printf("\tvalid interface combinations:\n"); 337f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg have_combinations = true; 338f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg } 339f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg 3401c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("\t\t * "); 3411c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3421c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB, 3431c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nl_combi, iface_combination_policy); 3441c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] || 3451c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg !tb_comb[NL80211_IFACE_COMB_MAXNUM] || 3461c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) { 3471c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf(" <failed to parse>\n"); 3481c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg goto broken_combination; 3491c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3501c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3511c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) { 3521c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg bool ift_comma = false; 3531c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3541c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT, 3551c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nl_limit, iface_limit_policy); 3561c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) { 3571c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("<failed to parse>\n"); 3581c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg goto broken_combination; 3591c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3601c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3611c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg if (comma) 3621c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf(", "); 3631c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg comma = true; 3641c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("#{"); 3651c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 3661c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_for_each_nested(nl_mode, tb_limit[NL80211_IFACE_LIMIT_TYPES], rem_mode) { 3671c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf("%s %s", ift_comma ? "," : "", 3681c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg iftype_name(nla_type(nl_mode))); 3691c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg ift_comma = true; 3701c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3711c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX])); 3721c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 3731c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg printf(",\n\t\t "); 3741c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 375c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf("total <= %d, #channels <= %d%s", 3761c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]), 3771c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]), 3781c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ? 3791c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg ", STA/AP BI must match" : ""); 380c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) { 381c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]); 382c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich 383c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich if (widths) { 384c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich int width; 385c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich bool first = true; 386c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich 387c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf(", radar detect widths: {"); 388c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich for (width = 0; width < 32; width++) 389c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich if (widths & (1 << width)) { 390c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf("%s %s", 391c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich first ? "":",", 392c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich channel_width_name(width)); 393c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich first = false; 394c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich } 395c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf(" }\n"); 396c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich } 397c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich } 398c5df9eb6b5112c9d4131f4cf500c2c6bf42901aeSimon Wunderlich printf("\n"); 3991c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Bergbroken_combination: 4001c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg ; 4011c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 402f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg 403f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg if (!have_combinations) 404f5f6f15f38dc9cdce17807efb05d840cb39f5bdbJohannes Berg printf("\tinterface combinations are not supported\n"); 4051c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg } 4061c5b4a826b2a9b00a78ea023414b4fbe036dc289Johannes Berg 4079a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) { 4089a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\tSupported commands:\n"); 4099a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_cmd, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS], rem_cmd) 4109a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\t\t * %s\n", command_name(nla_get_u32(nl_cmd))); 4119a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4126367e71a165680225aec25f1c4521626f996b76eJohannes Berg 4139a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (tb_msg[NL80211_ATTR_TX_FRAME_TYPES]) { 4149a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\tSupported TX frame types:\n"); 4159a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_if, tb_msg[NL80211_ATTR_TX_FRAME_TYPES], rem_if) { 4169a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg bool printed = false; 4179a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_ftype, nl_if, rem_ftype) { 4189a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (!printed) 4199a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\t\t * %s:", iftype_name(nla_type(nl_if))); 4209a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printed = true; 42158e343418820598cb58bd4bc7d5694e811a86972Johannes Berg printf(" 0x%.2x", nla_get_u16(nl_ftype)); 4229a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4239a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (printed) 4249a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\n"); 4259a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4269a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4279990c1e9a89982efed4e50fb846968bcc6b60b46Marcel Holtmann 4289a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (tb_msg[NL80211_ATTR_RX_FRAME_TYPES]) { 4299a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\tSupported RX frame types:\n"); 4309a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_if, tb_msg[NL80211_ATTR_RX_FRAME_TYPES], rem_if) { 4319a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg bool printed = false; 4329a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg nla_for_each_nested(nl_ftype, nl_if, rem_ftype) { 4339a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (!printed) 4349a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\t\t * %s:", iftype_name(nla_type(nl_if))); 4359a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printed = true; 43658e343418820598cb58bd4bc7d5694e811a86972Johannes Berg printf(" 0x%.2x", nla_get_u16(nl_ftype)); 4379a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4389a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg if (printed) 4399a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg printf("\n"); 4409a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4419a4a14bda58b8415fa660643cf16c8f47e477085Johannes Berg } 4429990c1e9a89982efed4e50fb846968bcc6b60b46Marcel Holtmann 4433ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_msg[NL80211_ATTR_SUPPORT_IBSS_RSN]) 44483f10169568ececba5d9f35c136c6475742a8487Johannes Berg printf("\tDevice supports RSN-IBSS.\n"); 4453ff24563977fba0242c359fb476229e4b4af97faJohannes Berg 4463ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_msg[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]) { 4473ff24563977fba0242c359fb476229e4b4af97faJohannes Berg struct nlattr *tb_wowlan[NUM_NL80211_WOWLAN_TRIG]; 4483ff24563977fba0242c359fb476229e4b4af97faJohannes Berg static struct nla_policy wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = { 4493ff24563977fba0242c359fb476229e4b4af97faJohannes Berg [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG }, 4503ff24563977fba0242c359fb476229e4b4af97faJohannes Berg [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG }, 4513ff24563977fba0242c359fb476229e4b4af97faJohannes Berg [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG }, 4521c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .minlen = 12 }, 4533a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED] = { .type = NLA_FLAG }, 4543a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG }, 4553a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG }, 4563a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG }, 4573a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG }, 458819b78cc931b9bb20f4c7e9879bde1d807cbdbb3Johannes Berg [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED }, 4593ff24563977fba0242c359fb476229e4b4af97faJohannes Berg }; 460c82868da4d5862751d9be9ee788d645184f323ecAmitkumar Karwar struct nl80211_pattern_support *pat; 4613ff24563977fba0242c359fb476229e4b4af97faJohannes Berg int err; 4623ff24563977fba0242c359fb476229e4b4af97faJohannes Berg 4633ff24563977fba0242c359fb476229e4b4af97faJohannes Berg err = nla_parse_nested(tb_wowlan, MAX_NL80211_WOWLAN_TRIG, 4643ff24563977fba0242c359fb476229e4b4af97faJohannes Berg tb_msg[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED], 4653ff24563977fba0242c359fb476229e4b4af97faJohannes Berg wowlan_policy); 4663ff24563977fba0242c359fb476229e4b4af97faJohannes Berg printf("\tWoWLAN support:"); 4673ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (err) { 4683ff24563977fba0242c359fb476229e4b4af97faJohannes Berg printf(" <failed to parse>\n"); 4693ff24563977fba0242c359fb476229e4b4af97faJohannes Berg } else { 4703ff24563977fba0242c359fb476229e4b4af97faJohannes Berg printf("\n"); 4713ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_ANY]) 4723a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on anything (device continues operating normally)\n"); 4733ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_DISCONNECT]) 4743a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on disconnect\n"); 4753ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_MAGIC_PKT]) 4763a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on magic packet\n"); 4773ff24563977fba0242c359fb476229e4b4af97faJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { 4783ff24563977fba0242c359fb476229e4b4af97faJohannes Berg pat = nla_data(tb_wowlan[NL80211_WOWLAN_TRIG_PKT_PATTERN]); 4791c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar printf("\t\t * wake up on pattern match, up to %u patterns of %u-%u bytes,\n" 4801c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar "\t\t maximum packet offset %u bytes\n", 4811c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar pat->max_patterns, pat->min_pattern_len, pat->max_pattern_len, 4821c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar (nla_len(tb_wowlan[NL80211_WOWLAN_TRIG_PKT_PATTERN]) < 4831c8f49c5379d6e5e1212f0439761768712bf7982Amitkumar Karwar sizeof(*pat)) ? 0 : pat->max_pkt_offset); 4843ff24563977fba0242c359fb476229e4b4af97faJohannes Berg } 4853a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED]) 4863a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * can do GTK rekeying\n"); 4873a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) 4883a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on GTK rekey failure\n"); 4893a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) 4903a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on EAP identity request\n"); 4913a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) 4923a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on 4-way handshake\n"); 4933a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) 4943a6636b1b98d7ca6cc2ae192040a542a3cf27ebfJohannes Berg printf("\t\t * wake up on rfkill release\n"); 495819b78cc931b9bb20f4c7e9879bde1d807cbdbb3Johannes Berg if (tb_wowlan[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) 496819b78cc931b9bb20f4c7e9879bde1d807cbdbb3Johannes Berg printf("\t\t * wake up on TCP connection\n"); 4973ff24563977fba0242c359fb476229e4b4af97faJohannes Berg } 49883f10169568ececba5d9f35c136c6475742a8487Johannes Berg } 49983f10169568ececba5d9f35c136c6475742a8487Johannes Berg 5002e4f65ca05f4dfb3b01638e69651c9bba942d3b7Johannes Berg if (tb_msg[NL80211_ATTR_ROAM_SUPPORT]) 5012e4f65ca05f4dfb3b01638e69651c9bba942d3b7Johannes Berg printf("\tDevice supports roaming.\n"); 5022e4f65ca05f4dfb3b01638e69651c9bba942d3b7Johannes Berg 5038b46999550ccd837df790f2927b0a8d0cff0cb98Johannes Berg if (tb_msg[NL80211_ATTR_SUPPORT_AP_UAPSD]) 5048b46999550ccd837df790f2927b0a8d0cff0cb98Johannes Berg printf("\tDevice supports AP-side u-APSD.\n"); 5058b46999550ccd837df790f2927b0a8d0cff0cb98Johannes Berg 506a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]) { 507a82abc2cac9dea7def53070565201145c76c8c6cBen Greear struct ieee80211_ht_cap *cm; 508a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\tHT Capability overrides:\n"); 509a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (nla_len(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]) >= sizeof(*cm)) { 510a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm = nla_data(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]); 511a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * MCS: %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx" 512a82abc2cac9dea7def53070565201145c76c8c6cBen Greear " %02hhx %02hhx %02hhx %02hhx\n", 513a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[0], cm->mcs.rx_mask[1], 514a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[2], cm->mcs.rx_mask[3], 515a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[4], cm->mcs.rx_mask[5], 516a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[6], cm->mcs.rx_mask[7], 517a82abc2cac9dea7def53070565201145c76c8c6cBen Greear cm->mcs.rx_mask[8], cm->mcs.rx_mask[9]); 518a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->cap_info & htole16(IEEE80211_HT_CAP_MAX_AMSDU)) 519a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * maximum A-MSDU length\n"); 520a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->cap_info & htole16(IEEE80211_HT_CAP_SUP_WIDTH_20_40)) 521a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * supported channel width\n"); 522a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->cap_info & htole16(IEEE80211_HT_CAP_SGI_40)) 523a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * short GI for 40 MHz\n"); 524a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR) 525a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * max A-MPDU length exponent\n"); 526a82abc2cac9dea7def53070565201145c76c8c6cBen Greear if (cm->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY) 527a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\t\t * min MPDU start spacing\n"); 528a82abc2cac9dea7def53070565201145c76c8c6cBen Greear } else { 529a82abc2cac9dea7def53070565201145c76c8c6cBen Greear printf("\tERROR: capabilities mask is too short, expected: %d, received: %d\n", 530a82abc2cac9dea7def53070565201145c76c8c6cBen Greear (int)(sizeof(*cm)), 531a82abc2cac9dea7def53070565201145c76c8c6cBen Greear (int)(nla_len(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]))); 532a82abc2cac9dea7def53070565201145c76c8c6cBen Greear } 533a82abc2cac9dea7def53070565201145c76c8c6cBen Greear } 534a82abc2cac9dea7def53070565201145c76c8c6cBen Greear 535632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg if (tb_msg[NL80211_ATTR_FEATURE_FLAGS]) { 536d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg unsigned int features = nla_get_u32(tb_msg[NL80211_ATTR_FEATURE_FLAGS]); 537d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg 538d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_SK_TX_STATUS) 539632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg printf("\tDevice supports TX status socket option.\n"); 540d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_HT_IBSS) 541632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg printf("\tDevice supports HT-IBSS.\n"); 542d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_INACTIVITY_TIMER) 543d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg printf("\tDevice has client inactivity timer.\n"); 544d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_CELL_BASE_REG_HINTS) 545d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg printf("\tDevice accepts cell base station regulatory hints.\n"); 546d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg if (features & NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL) 547d28df6b499b47451d1ba8224114c34c713a6bae5Johannes Berg printf("\tP2P Device uses a channel (of the concurrent ones)\n"); 5485973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_SAE) 5495973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports SAE with AUTHENTICATE command\n"); 550fe862239636c303372184abc5635097b43777e77Sam Leffler if (features & NL80211_FEATURE_LOW_PRIORITY_SCAN) 551fe862239636c303372184abc5635097b43777e77Sam Leffler printf("\tDevice supports low priority scan.\n"); 552fe862239636c303372184abc5635097b43777e77Sam Leffler if (features & NL80211_FEATURE_SCAN_FLUSH) 553fe862239636c303372184abc5635097b43777e77Sam Leffler printf("\tDevice supports scan flush.\n"); 554afa2be2ff4e033a07c8fa28b5f52087f5fe50ad6Antonio Quartulli if (features & NL80211_FEATURE_AP_SCAN) 555afa2be2ff4e033a07c8fa28b5f52087f5fe50ad6Antonio Quartulli printf("\tDevice supports AP scan.\n"); 5565973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_VIF_TXPOWER) 5575973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports per-vif TX power setting\n"); 5585973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_NEED_OBSS_SCAN) 5595973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tUserspace should do OBSS scan and generate 20/40 coex reports\n"); 5605973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_P2P_GO_CTWIN) 5615973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tP2P GO supports CT window setting\n"); 5625973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_P2P_GO_OPPPS) 5635973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tP2P GO supports opportunistic powersave setting\n"); 5645973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) 5655973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDriver supports full state transitions for AP/GO clients\n"); 5665973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_USERSPACE_MPM) 5675973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDriver supports a userspace MPM\n"); 5685973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_ACTIVE_MONITOR) 5695973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports active monitor (which will ACK incoming frames)\n"); 5705973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE) 5715973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDriver/device bandwidth changes during BSS lifetime (AP/GO mode)\n"); 5725973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) 5735973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice adds DS IE to probe requests\n"); 5745973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_WFA_TPC_IE_IN_PROBES) 5755973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice adds WFA TPC Report IE to probe requests\n"); 5765973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_QUIET) 5775973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports quiet requests from AP\n"); 5785973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_TX_POWER_INSERTION) 5795973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice can update TPC Report IE\n"); 580e642142d68850b7eb161489a984ec6817b10c51bLorenzo Bianconi if (features & NL80211_FEATURE_ACKTO_ESTIMATION) 581e642142d68850b7eb161489a984ec6817b10c51bLorenzo Bianconi printf("\tDevice supports ACK timeout estimation.\n"); 5825973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_STATIC_SMPS) 5835973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports static SMPS\n"); 5845973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg if (features & NL80211_FEATURE_DYNAMIC_SMPS) 5855973e65b64c27dbe92b34be454b7988c280b4969Johannes Berg printf("\tDevice supports dynamic SMPS\n"); 586ced5522d199b7b1b5b10cf94b276b74314ca8da3Ben Greear if (features & NL80211_FEATURE_MAC_ON_CREATE) 587ced5522d199b7b1b5b10cf94b276b74314ca8da3Ben Greear printf("\tDevice supports configuring vdev MAC-addr on create.\n"); 588632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg } 589632004a002a0149b5100acbb5df3a2c41a723799Johannes Berg 5909b4a19894ece2ea7cd47a8b30843ce7daa49452cJohannes Berg if (tb_msg[NL80211_ATTR_TDLS_SUPPORT]) 5919b4a19894ece2ea7cd47a8b30843ce7daa49452cJohannes Berg printf("\tDevice supports T-DLS.\n"); 5929b4a19894ece2ea7cd47a8b30843ce7daa49452cJohannes Berg 593aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar if (tb_msg[NL80211_ATTR_COALESCE_RULE]) { 594aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar struct nl80211_coalesce_rule_support *rule; 595aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar struct nl80211_pattern_support *pat; 596aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar 597aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar printf("\tCoalesce support:\n"); 598aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar rule = nla_data(tb_msg[NL80211_ATTR_COALESCE_RULE]); 599aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar pat = &rule->pat; 600aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar printf("\t\t * Maximum %u coalesce rules supported\n" 601aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar "\t\t * Each rule contains upto %u patterns of %u-%u bytes,\n" 602aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar "\t\t maximum packet offset %u bytes\n" 603aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar "\t\t * Maximum supported coalescing delay %u msecs\n", 604aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar rule->max_rules, pat->max_patterns, pat->min_pattern_len, 605aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar pat->max_pattern_len, pat->max_pkt_offset, rule->max_delay); 606aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar } 607aa0f5dbe3d759ca2ad6bdd67177467f02050eb67Amitkumar Karwar 60879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg return NL_SKIP; 60979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg} 61079f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 611c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Bergstatic bool nl80211_has_split_wiphy = false; 612c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg 6137c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_info(struct nl80211_state *state, 6147c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg struct nl_cb *cb, 615d631650b0d5725a487b87ad4d5d1238543aaf011Johannes Berg struct nl_msg *msg, 61605514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg int argc, char **argv, 61705514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg enum id_input id) 61879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg{ 619c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg char *feat_args[] = { "features", "-q" }; 620c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg int err; 621c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg 622c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg err = handle_cmd(state, CIB_NONE, 2, feat_args); 623c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg if (!err && nl80211_has_split_wiphy) { 624c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP); 625c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg nlmsg_hdr(msg)->nlmsg_flags |= NLM_F_DUMP; 626c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg } 627c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg 62879f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_phy_handler, NULL); 62979f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg 63070391ccff8e0dd17e4cc9d54d6c9dd8830c99928Johannes Berg return 0; 63179f99b9ad89494fc81d5c966a32dcebe9742f12cJohannes Berg} 632c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg__COMMAND(NULL, info, "info", NULL, NL80211_CMD_GET_WIPHY, 0, 0, CIB_PHY, handle_info, 6331633ddf7c6a66933d77b052d8637b851d3f2048fJohannes Berg "Show capabilities for the specified wireless device.", NULL); 634ea35fc0b841466473cab58317ecef20742351c45Johannes BergTOPLEVEL(list, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info, 635ea35fc0b841466473cab58317ecef20742351c45Johannes Berg "List all wireless devices and their capabilities."); 63601ae06f9e9d2bf3e7e998bcbda06fd916c92f34eJohannes BergTOPLEVEL(phy, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info, NULL); 637bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg 638bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Bergstatic int handle_commands(struct nl80211_state *state, 639bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg struct nl_cb *cb, struct nl_msg *msg, 640bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg int argc, char **argv, enum id_input id) 641bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg{ 642bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg int i; 643bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg for (i = 1; i < NL80211_CMD_MAX; i++) 644bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg printf("%d (0x%x): %s\n", i, i, command_name(i)); 645bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg /* don't send netlink messages */ 646bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg return 2; 647bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg} 648bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes BergTOPLEVEL(commands, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_NONE, handle_commands, 649bcdff0b2c98e4fad9c71f1c67c438e2faa31258fJohannes Berg "list all known commands and their decimal & hex value"); 650fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 651fb70e110d39247eb1999fd094300fce6bc41002fJohannes Bergstatic int print_feature_handler(struct nl_msg *msg, void *arg) 652fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg{ 653fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; 654fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 655c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg bool print = (unsigned long)arg; 656c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg#define maybe_printf(...) do { if (print) printf(__VA_ARGS__); } while (0) 657fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 658fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 659fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg genlmsg_attrlen(gnlh, 0), NULL); 660fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 661fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]) { 662fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg uint32_t feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]); 663fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 664c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg maybe_printf("nl80211 features: 0x%x\n", feat); 665c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP) { 666c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg maybe_printf("\t* split wiphy dump\n"); 667c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg nl80211_has_split_wiphy = true; 668c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg } 669fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg } 670fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 671fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg return NL_SKIP; 672fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg} 673fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 674fb70e110d39247eb1999fd094300fce6bc41002fJohannes Bergstatic int handle_features(struct nl80211_state *state, 675fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg struct nl_cb *cb, struct nl_msg *msg, 676fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg int argc, char **argv, enum id_input id) 677fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg{ 678c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg unsigned long print = argc == 0 || strcmp(argv[0], "-q"); 679c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes Berg nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_feature_handler, (void *)print); 680fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg return 0; 681fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg} 682fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg 683c142fa28e0613019e3aa92626ad12d4002ee05dfJohannes BergTOPLEVEL(features, "", NL80211_CMD_GET_PROTOCOL_FEATURES, 0, CIB_NONE, 684fb70e110d39247eb1999fd094300fce6bc41002fJohannes Berg handle_features, ""); 685