LCOV - code coverage report
Current view: top level - src/drivers - driver_nl80211_capa.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1426431149 Lines: 602 775 77.7 %
Date: 2015-03-15 Functions: 36 40 90.0 %

          Line data    Source code
       1             : /*
       2             :  * Driver interaction with Linux nl80211/cfg80211 - Capabilities
       3             :  * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
       4             :  * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
       5             :  * Copyright (c) 2009-2010, Atheros Communications
       6             :  *
       7             :  * This software may be distributed under the terms of the BSD license.
       8             :  * See README for more details.
       9             :  */
      10             : 
      11             : #include "includes.h"
      12             : #include <netlink/genl/genl.h>
      13             : 
      14             : #include "utils/common.h"
      15             : #include "common/ieee802_11_defs.h"
      16             : #include "common/ieee802_11_common.h"
      17             : #include "common/qca-vendor.h"
      18             : #include "common/qca-vendor-attr.h"
      19             : #include "driver_nl80211.h"
      20             : 
      21             : 
      22       10158 : static int protocol_feature_handler(struct nl_msg *msg, void *arg)
      23             : {
      24       10158 :         u32 *feat = arg;
      25             :         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
      26       10158 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
      27             : 
      28       10158 :         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
      29             :                   genlmsg_attrlen(gnlh, 0), NULL);
      30             : 
      31       10158 :         if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES])
      32       10158 :                 *feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]);
      33             : 
      34       10158 :         return NL_SKIP;
      35             : }
      36             : 
      37             : 
      38       10158 : static u32 get_nl80211_protocol_features(struct wpa_driver_nl80211_data *drv)
      39             : {
      40       10158 :         u32 feat = 0;
      41             :         struct nl_msg *msg;
      42             : 
      43       10158 :         msg = nlmsg_alloc();
      44       10158 :         if (!msg)
      45           0 :                 return 0;
      46             : 
      47       10158 :         if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_PROTOCOL_FEATURES)) {
      48           0 :                 nlmsg_free(msg);
      49           0 :                 return 0;
      50             :         }
      51             : 
      52       10158 :         if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat) == 0)
      53       10158 :                 return feat;
      54             : 
      55           0 :         return 0;
      56             : }
      57             : 
      58             : 
      59             : struct wiphy_info_data {
      60             :         struct wpa_driver_nl80211_data *drv;
      61             :         struct wpa_driver_capa *capa;
      62             : 
      63             :         unsigned int num_multichan_concurrent;
      64             : 
      65             :         unsigned int error:1;
      66             :         unsigned int device_ap_sme:1;
      67             :         unsigned int poll_command_supported:1;
      68             :         unsigned int data_tx_status:1;
      69             :         unsigned int monitor_supported:1;
      70             :         unsigned int auth_supported:1;
      71             :         unsigned int connect_supported:1;
      72             :         unsigned int p2p_go_supported:1;
      73             :         unsigned int p2p_client_supported:1;
      74             :         unsigned int p2p_go_ctwindow_supported:1;
      75             :         unsigned int p2p_concurrent:1;
      76             :         unsigned int channel_switch_supported:1;
      77             :         unsigned int set_qos_map_supported:1;
      78             :         unsigned int have_low_prio_scan:1;
      79             :         unsigned int wmm_ac_supported:1;
      80             :         unsigned int mac_addr_rand_scan_supported:1;
      81             :         unsigned int mac_addr_rand_sched_scan_supported:1;
      82             : };
      83             : 
      84             : 
      85           0 : static unsigned int probe_resp_offload_support(int supp_protocols)
      86             : {
      87           0 :         unsigned int prot = 0;
      88             : 
      89           0 :         if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS)
      90           0 :                 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS;
      91           0 :         if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)
      92           0 :                 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2;
      93           0 :         if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P)
      94           0 :                 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P;
      95           0 :         if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U)
      96           0 :                 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING;
      97             : 
      98           0 :         return prot;
      99             : }
     100             : 
     101             : 
     102       66474 : static void wiphy_info_supported_iftypes(struct wiphy_info_data *info,
     103             :                                          struct nlattr *tb)
     104             : {
     105             :         struct nlattr *nl_mode;
     106             :         int i;
     107             : 
     108       66474 :         if (tb == NULL)
     109      131717 :                 return;
     110             : 
     111       11102 :         nla_for_each_nested(nl_mode, tb, i) {
     112        9871 :                 switch (nla_type(nl_mode)) {
     113             :                 case NL80211_IFTYPE_AP:
     114        1231 :                         info->capa->flags |= WPA_DRIVER_FLAGS_AP;
     115        1231 :                         break;
     116             :                 case NL80211_IFTYPE_MESH_POINT:
     117        1231 :                         info->capa->flags |= WPA_DRIVER_FLAGS_MESH;
     118        1231 :                         break;
     119             :                 case NL80211_IFTYPE_ADHOC:
     120        1231 :                         info->capa->flags |= WPA_DRIVER_FLAGS_IBSS;
     121        1231 :                         break;
     122             :                 case NL80211_IFTYPE_P2P_DEVICE:
     123          23 :                         info->capa->flags |=
     124             :                                 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
     125          23 :                         break;
     126             :                 case NL80211_IFTYPE_P2P_GO:
     127        1231 :                         info->p2p_go_supported = 1;
     128        1231 :                         break;
     129             :                 case NL80211_IFTYPE_P2P_CLIENT:
     130        1231 :                         info->p2p_client_supported = 1;
     131        1231 :                         break;
     132             :                 case NL80211_IFTYPE_MONITOR:
     133        1231 :                         info->monitor_supported = 1;
     134        1231 :                         break;
     135             :                 }
     136             :         }
     137             : }
     138             : 
     139             : 
     140        2448 : static int wiphy_info_iface_comb_process(struct wiphy_info_data *info,
     141             :                                          struct nlattr *nl_combi)
     142             : {
     143             :         struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
     144             :         struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
     145             :         struct nlattr *nl_limit, *nl_mode;
     146             :         int err, rem_limit, rem_mode;
     147        2448 :         int combination_has_p2p = 0, combination_has_mgd = 0;
     148             :         static struct nla_policy
     149             :         iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
     150             :                 [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
     151             :                 [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
     152             :                 [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
     153             :                 [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
     154             :                 [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
     155             :         },
     156             :         iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
     157             :                 [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
     158             :                 [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
     159             :         };
     160             : 
     161        2448 :         err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
     162             :                                nl_combi, iface_combination_policy);
     163        4896 :         if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
     164        4896 :             !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
     165        2448 :             !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
     166           0 :                 return 0; /* broken combination */
     167             : 
     168        2448 :         if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS])
     169        2448 :                 info->capa->flags |= WPA_DRIVER_FLAGS_RADAR;
     170             : 
     171        4896 :         nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS],
     172             :                             rem_limit) {
     173        3679 :                 err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
     174             :                                        nl_limit, iface_limit_policy);
     175        3679 :                 if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES])
     176           0 :                         return 0; /* broken combination */
     177             : 
     178       12282 :                 nla_for_each_nested(nl_mode,
     179             :                                     tb_limit[NL80211_IFACE_LIMIT_TYPES],
     180             :                                     rem_mode) {
     181        8603 :                         int ift = nla_type(nl_mode);
     182        8603 :                         if (ift == NL80211_IFTYPE_P2P_GO ||
     183             :                             ift == NL80211_IFTYPE_P2P_CLIENT)
     184        2462 :                                 combination_has_p2p = 1;
     185        8603 :                         if (ift == NL80211_IFTYPE_STATION)
     186        1231 :                                 combination_has_mgd = 1;
     187             :                 }
     188        3679 :                 if (combination_has_p2p && combination_has_mgd)
     189        1231 :                         break;
     190             :         }
     191             : 
     192        2448 :         if (combination_has_p2p && combination_has_mgd) {
     193        1231 :                 unsigned int num_channels =
     194        1231 :                         nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]);
     195             : 
     196        1231 :                 info->p2p_concurrent = 1;
     197        1231 :                 if (info->num_multichan_concurrent < num_channels)
     198        1231 :                         info->num_multichan_concurrent = num_channels;
     199             :         }
     200             : 
     201        2448 :         return 0;
     202             : }
     203             : 
     204             : 
     205       66474 : static void wiphy_info_iface_comb(struct wiphy_info_data *info,
     206             :                                   struct nlattr *tb)
     207             : {
     208             :         struct nlattr *nl_combi;
     209             :         int rem_combi;
     210             : 
     211       66474 :         if (tb == NULL)
     212      131717 :                 return;
     213             : 
     214        3679 :         nla_for_each_nested(nl_combi, tb, rem_combi) {
     215        2448 :                 if (wiphy_info_iface_comb_process(info, nl_combi) > 0)
     216           0 :                         break;
     217             :         }
     218             : }
     219             : 
     220             : 
     221       66474 : static void wiphy_info_supp_cmds(struct wiphy_info_data *info,
     222             :                                  struct nlattr *tb)
     223             : {
     224             :         struct nlattr *nl_cmd;
     225             :         int i;
     226             : 
     227       66474 :         if (tb == NULL)
     228      131717 :                 return;
     229             : 
     230       40623 :         nla_for_each_nested(nl_cmd, tb, i) {
     231       39392 :                 switch (nla_get_u32(nl_cmd)) {
     232             :                 case NL80211_CMD_AUTHENTICATE:
     233        1231 :                         info->auth_supported = 1;
     234        1231 :                         break;
     235             :                 case NL80211_CMD_CONNECT:
     236        1231 :                         info->connect_supported = 1;
     237        1231 :                         break;
     238             :                 case NL80211_CMD_START_SCHED_SCAN:
     239           0 :                         info->capa->sched_scan_supported = 1;
     240           0 :                         break;
     241             :                 case NL80211_CMD_PROBE_CLIENT:
     242        1231 :                         info->poll_command_supported = 1;
     243        1231 :                         break;
     244             :                 case NL80211_CMD_CHANNEL_SWITCH:
     245        1231 :                         info->channel_switch_supported = 1;
     246        1231 :                         break;
     247             :                 case NL80211_CMD_SET_QOS_MAP:
     248        1231 :                         info->set_qos_map_supported = 1;
     249        1231 :                         break;
     250             :                 }
     251             :         }
     252             : }
     253             : 
     254             : 
     255       66474 : static void wiphy_info_cipher_suites(struct wiphy_info_data *info,
     256             :                                      struct nlattr *tb)
     257             : {
     258             :         int i, num;
     259             :         u32 *ciphers;
     260             : 
     261       66474 :         if (tb == NULL)
     262      131717 :                 return;
     263             : 
     264        1231 :         num = nla_len(tb) / sizeof(u32);
     265        1231 :         ciphers = nla_data(tb);
     266       14772 :         for (i = 0; i < num; i++) {
     267       13541 :                 u32 c = ciphers[i];
     268             : 
     269       40623 :                 wpa_printf(MSG_DEBUG, "nl80211: Supported cipher %02x-%02x-%02x:%d",
     270       13541 :                            c >> 24, (c >> 16) & 0xff,
     271       13541 :                            (c >> 8) & 0xff, c & 0xff);
     272       13541 :                 switch (c) {
     273             :                 case WLAN_CIPHER_SUITE_CCMP_256:
     274        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP_256;
     275        1231 :                         break;
     276             :                 case WLAN_CIPHER_SUITE_GCMP_256:
     277        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP_256;
     278        1231 :                         break;
     279             :                 case WLAN_CIPHER_SUITE_CCMP:
     280        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP;
     281        1231 :                         break;
     282             :                 case WLAN_CIPHER_SUITE_GCMP:
     283        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP;
     284        1231 :                         break;
     285             :                 case WLAN_CIPHER_SUITE_TKIP:
     286        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_TKIP;
     287        1231 :                         break;
     288             :                 case WLAN_CIPHER_SUITE_WEP104:
     289        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP104;
     290        1231 :                         break;
     291             :                 case WLAN_CIPHER_SUITE_WEP40:
     292        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP40;
     293        1231 :                         break;
     294             :                 case WLAN_CIPHER_SUITE_AES_CMAC:
     295        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP;
     296        1231 :                         break;
     297             :                 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
     298        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_128;
     299        1231 :                         break;
     300             :                 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
     301        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_256;
     302        1231 :                         break;
     303             :                 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
     304        1231 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_CMAC_256;
     305        1231 :                         break;
     306             :                 case WLAN_CIPHER_SUITE_NO_GROUP_ADDR:
     307           0 :                         info->capa->enc |= WPA_DRIVER_CAPA_ENC_GTK_NOT_USED;
     308           0 :                         break;
     309             :                 }
     310             :         }
     311             : }
     312             : 
     313             : 
     314       66474 : static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
     315             :                                struct nlattr *tb)
     316             : {
     317       66474 :         if (tb)
     318        1231 :                 capa->max_remain_on_chan = nla_get_u32(tb);
     319       66474 : }
     320             : 
     321             : 
     322       66474 : static void wiphy_info_tdls(struct wpa_driver_capa *capa, struct nlattr *tdls,
     323             :                             struct nlattr *ext_setup)
     324             : {
     325       66474 :         if (tdls == NULL)
     326      131717 :                 return;
     327             : 
     328        1231 :         wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
     329        1231 :         capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
     330             : 
     331        1231 :         if (ext_setup) {
     332        1231 :                 wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
     333        1231 :                 capa->flags |= WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
     334             :         }
     335             : }
     336             : 
     337             : 
     338       66474 : static void wiphy_info_feature_flags(struct wiphy_info_data *info,
     339             :                                      struct nlattr *tb)
     340             : {
     341             :         u32 flags;
     342       66474 :         struct wpa_driver_capa *capa = info->capa;
     343             : 
     344       66474 :         if (tb == NULL)
     345      131717 :                 return;
     346             : 
     347        1231 :         flags = nla_get_u32(tb);
     348             : 
     349        1231 :         if (flags & NL80211_FEATURE_SK_TX_STATUS)
     350        1231 :                 info->data_tx_status = 1;
     351             : 
     352        1231 :         if (flags & NL80211_FEATURE_INACTIVITY_TIMER)
     353           0 :                 capa->flags |= WPA_DRIVER_FLAGS_INACTIVITY_TIMER;
     354             : 
     355        1231 :         if (flags & NL80211_FEATURE_SAE)
     356        1231 :                 capa->flags |= WPA_DRIVER_FLAGS_SAE;
     357             : 
     358        1231 :         if (flags & NL80211_FEATURE_NEED_OBSS_SCAN)
     359           0 :                 capa->flags |= WPA_DRIVER_FLAGS_OBSS_SCAN;
     360             : 
     361        1231 :         if (flags & NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)
     362        1231 :                 capa->flags |= WPA_DRIVER_FLAGS_HT_2040_COEX;
     363             : 
     364        1231 :         if (flags & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) {
     365        1231 :                 wpa_printf(MSG_DEBUG, "nl80211: TDLS channel switch");
     366        1231 :                 capa->flags |= WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH;
     367             :         }
     368             : 
     369        1231 :         if (flags & NL80211_FEATURE_P2P_GO_CTWIN)
     370           0 :                 info->p2p_go_ctwindow_supported = 1;
     371             : 
     372        1231 :         if (flags & NL80211_FEATURE_LOW_PRIORITY_SCAN)
     373        1217 :                 info->have_low_prio_scan = 1;
     374             : 
     375        1231 :         if (flags & NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR)
     376        1231 :                 info->mac_addr_rand_scan_supported = 1;
     377             : 
     378        1231 :         if (flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR)
     379           0 :                 info->mac_addr_rand_sched_scan_supported = 1;
     380             : 
     381        1231 :         if (flags & NL80211_FEATURE_STATIC_SMPS)
     382        1231 :                 capa->smps_modes |= WPA_DRIVER_SMPS_MODE_STATIC;
     383             : 
     384        1231 :         if (flags & NL80211_FEATURE_DYNAMIC_SMPS)
     385        1231 :                 capa->smps_modes |= WPA_DRIVER_SMPS_MODE_DYNAMIC;
     386             : 
     387        1231 :         if (flags & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
     388           0 :                 info->wmm_ac_supported = 1;
     389             : 
     390        1231 :         if (flags & NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES)
     391        1231 :                 capa->rrm_flags |= WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES;
     392             : 
     393        1231 :         if (flags & NL80211_FEATURE_WFA_TPC_IE_IN_PROBES)
     394           0 :                 capa->rrm_flags |= WPA_DRIVER_FLAGS_WFA_TPC_IE_IN_PROBES;
     395             : 
     396        1231 :         if (flags & NL80211_FEATURE_QUIET)
     397        1231 :                 capa->rrm_flags |= WPA_DRIVER_FLAGS_QUIET;
     398             : 
     399        1231 :         if (flags & NL80211_FEATURE_TX_POWER_INSERTION)
     400           0 :                 capa->rrm_flags |= WPA_DRIVER_FLAGS_TX_POWER_INSERTION;
     401             : 
     402        1231 :         if (flags & NL80211_FEATURE_HT_IBSS)
     403        1231 :                 capa->flags |= WPA_DRIVER_FLAGS_HT_IBSS;
     404             : }
     405             : 
     406             : 
     407       66474 : static void wiphy_info_probe_resp_offload(struct wpa_driver_capa *capa,
     408             :                                           struct nlattr *tb)
     409             : {
     410             :         u32 protocols;
     411             : 
     412       66474 :         if (tb == NULL)
     413      132948 :                 return;
     414             : 
     415           0 :         protocols = nla_get_u32(tb);
     416           0 :         wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response offload in AP "
     417             :                    "mode");
     418           0 :         capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
     419           0 :         capa->probe_resp_offloads = probe_resp_offload_support(protocols);
     420             : }
     421             : 
     422             : 
     423       66474 : static void wiphy_info_wowlan_triggers(struct wpa_driver_capa *capa,
     424             :                                        struct nlattr *tb)
     425             : {
     426             :         struct nlattr *triggers[MAX_NL80211_WOWLAN_TRIG + 1];
     427             : 
     428       66474 :         if (tb == NULL)
     429      132948 :                 return;
     430             : 
     431           0 :         if (nla_parse_nested(triggers, MAX_NL80211_WOWLAN_TRIG,
     432             :                              tb, NULL))
     433           0 :                 return;
     434             : 
     435           0 :         if (triggers[NL80211_WOWLAN_TRIG_ANY])
     436           0 :                 capa->wowlan_triggers.any = 1;
     437           0 :         if (triggers[NL80211_WOWLAN_TRIG_DISCONNECT])
     438           0 :                 capa->wowlan_triggers.disconnect = 1;
     439           0 :         if (triggers[NL80211_WOWLAN_TRIG_MAGIC_PKT])
     440           0 :                 capa->wowlan_triggers.magic_pkt = 1;
     441           0 :         if (triggers[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE])
     442           0 :                 capa->wowlan_triggers.gtk_rekey_failure = 1;
     443           0 :         if (triggers[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST])
     444           0 :                 capa->wowlan_triggers.eap_identity_req = 1;
     445           0 :         if (triggers[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE])
     446           0 :                 capa->wowlan_triggers.four_way_handshake = 1;
     447           0 :         if (triggers[NL80211_WOWLAN_TRIG_RFKILL_RELEASE])
     448           0 :                 capa->wowlan_triggers.rfkill_release = 1;
     449             : }
     450             : 
     451             : 
     452       66474 : static int wiphy_info_handler(struct nl_msg *msg, void *arg)
     453             : {
     454             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
     455       66474 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     456       66474 :         struct wiphy_info_data *info = arg;
     457       66474 :         struct wpa_driver_capa *capa = info->capa;
     458       66474 :         struct wpa_driver_nl80211_data *drv = info->drv;
     459             : 
     460       66474 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     461             :                   genlmsg_attrlen(gnlh, 0), NULL);
     462             : 
     463       66474 :         if (tb[NL80211_ATTR_WIPHY_NAME])
     464       66474 :                 os_strlcpy(drv->phyname,
     465       66474 :                            nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
     466             :                            sizeof(drv->phyname));
     467       66474 :         if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
     468        1231 :                 capa->max_scan_ssids =
     469        1231 :                         nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
     470             : 
     471       66474 :         if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])
     472        1231 :                 capa->max_sched_scan_ssids =
     473        1231 :                         nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
     474             : 
     475       66474 :         if (tb[NL80211_ATTR_MAX_MATCH_SETS])
     476        1231 :                 capa->max_match_sets =
     477        1231 :                         nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
     478             : 
     479       66474 :         if (tb[NL80211_ATTR_MAC_ACL_MAX])
     480           0 :                 capa->max_acl_mac_addrs =
     481           0 :                         nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
     482             : 
     483       66474 :         wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
     484       66474 :         wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
     485       66474 :         wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
     486       66474 :         wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]);
     487             : 
     488       66474 :         if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
     489        1231 :                 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
     490             :                            "off-channel TX");
     491        1231 :                 capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
     492             :         }
     493             : 
     494       66474 :         if (tb[NL80211_ATTR_ROAM_SUPPORT]) {
     495           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming");
     496           0 :                 capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
     497             :         }
     498             : 
     499       66474 :         wiphy_info_max_roc(capa,
     500             :                            tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
     501             : 
     502       66474 :         if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
     503        1231 :                 capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
     504             : 
     505       66474 :         wiphy_info_tdls(capa, tb[NL80211_ATTR_TDLS_SUPPORT],
     506             :                         tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]);
     507             : 
     508       66474 :         if (tb[NL80211_ATTR_DEVICE_AP_SME])
     509           0 :                 info->device_ap_sme = 1;
     510             : 
     511       66474 :         wiphy_info_feature_flags(info, tb[NL80211_ATTR_FEATURE_FLAGS]);
     512       66474 :         wiphy_info_probe_resp_offload(capa,
     513             :                                       tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
     514             : 
     515       67705 :         if (tb[NL80211_ATTR_EXT_CAPA] && tb[NL80211_ATTR_EXT_CAPA_MASK] &&
     516        1231 :             drv->extended_capa == NULL) {
     517        1231 :                 drv->extended_capa =
     518        1231 :                         os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA]));
     519        1231 :                 if (drv->extended_capa) {
     520        1231 :                         os_memcpy(drv->extended_capa,
     521             :                                   nla_data(tb[NL80211_ATTR_EXT_CAPA]),
     522             :                                   nla_len(tb[NL80211_ATTR_EXT_CAPA]));
     523        1231 :                         drv->extended_capa_len =
     524        1231 :                                 nla_len(tb[NL80211_ATTR_EXT_CAPA]);
     525             :                 }
     526        1231 :                 drv->extended_capa_mask =
     527        1231 :                         os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA_MASK]));
     528        1231 :                 if (drv->extended_capa_mask) {
     529        1231 :                         os_memcpy(drv->extended_capa_mask,
     530             :                                   nla_data(tb[NL80211_ATTR_EXT_CAPA_MASK]),
     531             :                                   nla_len(tb[NL80211_ATTR_EXT_CAPA_MASK]));
     532             :                 } else {
     533           0 :                         os_free(drv->extended_capa);
     534           0 :                         drv->extended_capa = NULL;
     535           0 :                         drv->extended_capa_len = 0;
     536             :                 }
     537             :         }
     538             : 
     539       66474 :         if (tb[NL80211_ATTR_VENDOR_DATA]) {
     540             :                 struct nlattr *nl;
     541             :                 int rem;
     542             : 
     543        2462 :                 nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
     544             :                         struct nl80211_vendor_cmd_info *vinfo;
     545        1231 :                         if (nla_len(nl) != sizeof(*vinfo)) {
     546           0 :                                 wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
     547           0 :                                 continue;
     548             :                         }
     549        1231 :                         vinfo = nla_data(nl);
     550        1231 :                         switch (vinfo->subcmd) {
     551             :                         case QCA_NL80211_VENDOR_SUBCMD_TEST:
     552        1231 :                                 drv->vendor_cmd_test_avail = 1;
     553        1231 :                                 break;
     554             :                         case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
     555           0 :                                 drv->roaming_vendor_cmd_avail = 1;
     556           0 :                                 break;
     557             :                         case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY:
     558           0 :                                 drv->dfs_vendor_cmd_avail = 1;
     559           0 :                                 break;
     560             :                         case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
     561           0 :                                 drv->get_features_vendor_cmd_avail = 1;
     562           0 :                                 break;
     563             :                         case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
     564           0 :                                 drv->capa.flags |= WPA_DRIVER_FLAGS_ACS_OFFLOAD;
     565           0 :                                 break;
     566             :                         }
     567             : 
     568        1231 :                         wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
     569             :                                    vinfo->vendor_id, vinfo->subcmd);
     570             :                 }
     571             :         }
     572             : 
     573       66474 :         if (tb[NL80211_ATTR_VENDOR_EVENTS]) {
     574             :                 struct nlattr *nl;
     575             :                 int rem;
     576             : 
     577        2462 :                 nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_EVENTS], rem) {
     578             :                         struct nl80211_vendor_cmd_info *vinfo;
     579        1231 :                         if (nla_len(nl) != sizeof(*vinfo)) {
     580           0 :                                 wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
     581           0 :                                 continue;
     582             :                         }
     583        1231 :                         vinfo = nla_data(nl);
     584        1231 :                         wpa_printf(MSG_DEBUG, "nl80211: Supported vendor event: vendor_id=0x%x subcmd=%u",
     585             :                                    vinfo->vendor_id, vinfo->subcmd);
     586             :                 }
     587             :         }
     588             : 
     589       66474 :         wiphy_info_wowlan_triggers(capa,
     590             :                                    tb[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]);
     591             : 
     592       66474 :         if (tb[NL80211_ATTR_MAX_AP_ASSOC_STA])
     593           0 :                 capa->max_stations =
     594           0 :                         nla_get_u32(tb[NL80211_ATTR_MAX_AP_ASSOC_STA]);
     595             : 
     596       66474 :         return NL_SKIP;
     597             : }
     598             : 
     599             : 
     600        1234 : static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
     601             :                                        struct wiphy_info_data *info)
     602             : {
     603             :         u32 feat;
     604             :         struct nl_msg *msg;
     605        1234 :         int flags = 0;
     606             : 
     607        1234 :         os_memset(info, 0, sizeof(*info));
     608        1234 :         info->capa = &drv->capa;
     609        1234 :         info->drv = drv;
     610             : 
     611        1234 :         feat = get_nl80211_protocol_features(drv);
     612        1234 :         if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
     613        1234 :                 flags = NLM_F_DUMP;
     614        1234 :         msg = nl80211_cmd_msg(drv->first_bss, flags, NL80211_CMD_GET_WIPHY);
     615        1234 :         if (!msg || nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
     616           0 :                 nlmsg_free(msg);
     617           0 :                 return -1;
     618             :         }
     619             : 
     620        1234 :         if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info))
     621           0 :                 return -1;
     622             : 
     623        1234 :         if (info->auth_supported)
     624        1231 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_SME;
     625           3 :         else if (!info->connect_supported) {
     626           3 :                 wpa_printf(MSG_INFO, "nl80211: Driver does not support "
     627             :                            "authentication/association or connect commands");
     628           3 :                 info->error = 1;
     629             :         }
     630             : 
     631        1234 :         if (info->p2p_go_supported && info->p2p_client_supported)
     632        1231 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
     633        1234 :         if (info->p2p_concurrent) {
     634        1231 :                 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
     635             :                            "interface (driver advertised support)");
     636        1231 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
     637        1231 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
     638             :         }
     639        1234 :         if (info->num_multichan_concurrent > 1) {
     640          14 :                 wpa_printf(MSG_DEBUG, "nl80211: Enable multi-channel "
     641             :                            "concurrent (driver advertised support)");
     642          14 :                 drv->capa.num_multichan_concurrent =
     643          14 :                         info->num_multichan_concurrent;
     644             :         }
     645        1234 :         if (drv->capa.flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
     646          23 :                 wpa_printf(MSG_DEBUG, "nl80211: use P2P_DEVICE support");
     647             : 
     648             :         /* default to 5000 since early versions of mac80211 don't set it */
     649        1234 :         if (!drv->capa.max_remain_on_chan)
     650           3 :                 drv->capa.max_remain_on_chan = 5000;
     651             : 
     652        1234 :         if (info->channel_switch_supported)
     653        1231 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_CSA;
     654        1234 :         drv->capa.wmm_ac_supported = info->wmm_ac_supported;
     655             : 
     656        1234 :         drv->capa.mac_addr_rand_sched_scan_supported =
     657        1234 :                 info->mac_addr_rand_sched_scan_supported;
     658        1234 :         drv->capa.mac_addr_rand_scan_supported =
     659        1234 :                 info->mac_addr_rand_scan_supported;
     660             : 
     661        1234 :         return 0;
     662             : }
     663             : 
     664             : 
     665           0 : static int dfs_info_handler(struct nl_msg *msg, void *arg)
     666             : {
     667             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
     668           0 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     669           0 :         int *dfs_capability_ptr = arg;
     670             : 
     671           0 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     672             :                   genlmsg_attrlen(gnlh, 0), NULL);
     673             : 
     674           0 :         if (tb[NL80211_ATTR_VENDOR_DATA]) {
     675           0 :                 struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
     676             :                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
     677             : 
     678           0 :                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
     679           0 :                           nla_data(nl_vend), nla_len(nl_vend), NULL);
     680             : 
     681           0 :                 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]) {
     682             :                         u32 val;
     683           0 :                         val = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]);
     684           0 :                         wpa_printf(MSG_DEBUG, "nl80211: DFS offload capability: %u",
     685             :                                    val);
     686           0 :                         *dfs_capability_ptr = val;
     687             :                 }
     688             :         }
     689             : 
     690           0 :         return NL_SKIP;
     691             : }
     692             : 
     693             : 
     694        1231 : static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data *drv)
     695             : {
     696             :         struct nl_msg *msg;
     697        1231 :         int dfs_capability = 0;
     698             :         int ret;
     699             : 
     700        1231 :         if (!drv->dfs_vendor_cmd_avail)
     701        2462 :                 return;
     702             : 
     703           0 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
     704           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
     705           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
     706             :                         QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY)) {
     707           0 :                 nlmsg_free(msg);
     708           0 :                 return;
     709             :         }
     710             : 
     711           0 :         ret = send_and_recv_msgs(drv, msg, dfs_info_handler, &dfs_capability);
     712           0 :         if (!ret && dfs_capability)
     713           0 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD;
     714             : }
     715             : 
     716             : 
     717             : struct features_info {
     718             :         u8 *flags;
     719             :         size_t flags_len;
     720             : };
     721             : 
     722             : 
     723           0 : static int features_info_handler(struct nl_msg *msg, void *arg)
     724             : {
     725             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
     726           0 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     727           0 :         struct features_info *info = arg;
     728             :         struct nlattr *nl_vend, *attr;
     729             : 
     730           0 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     731             :                   genlmsg_attrlen(gnlh, 0), NULL);
     732             : 
     733           0 :         nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
     734           0 :         if (nl_vend) {
     735             :                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
     736             : 
     737           0 :                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
     738           0 :                           nla_data(nl_vend), nla_len(nl_vend), NULL);
     739             : 
     740           0 :                 attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS];
     741           0 :                 if (attr) {
     742           0 :                         info->flags = nla_data(attr);
     743           0 :                         info->flags_len = nla_len(attr);
     744             :                 }
     745             :         }
     746             : 
     747           0 :         return NL_SKIP;
     748             : }
     749             : 
     750             : 
     751           0 : static int check_feature(enum qca_wlan_vendor_features feature,
     752             :                          struct features_info *info)
     753             : {
     754           0 :         size_t idx = feature / 8;
     755             : 
     756           0 :         return (idx < info->flags_len) &&
     757           0 :                 (info->flags[idx] & BIT(feature % 8));
     758             : }
     759             : 
     760             : 
     761        1231 : static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
     762             : {
     763             :         struct nl_msg *msg;
     764             :         struct features_info info;
     765             :         int ret;
     766             : 
     767        1231 :         if (!drv->get_features_vendor_cmd_avail)
     768        2462 :                 return;
     769             : 
     770           0 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
     771           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
     772           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
     773             :                         QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES)) {
     774           0 :                 nlmsg_free(msg);
     775           0 :                 return;
     776             :         }
     777             : 
     778           0 :         os_memset(&info, 0, sizeof(info));
     779           0 :         ret = send_and_recv_msgs(drv, msg, features_info_handler, &info);
     780           0 :         if (ret || !info.flags)
     781           0 :                 return;
     782             : 
     783           0 :         if (check_feature(QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD, &info))
     784           0 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD;
     785             : }
     786             : 
     787             : 
     788        1234 : int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
     789             : {
     790             :         struct wiphy_info_data info;
     791        1234 :         if (wpa_driver_nl80211_get_info(drv, &info))
     792           0 :                 return -1;
     793             : 
     794        1234 :         if (info.error)
     795           3 :                 return -1;
     796             : 
     797        1231 :         drv->has_capability = 1;
     798        1231 :         drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
     799             :                 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
     800             :                 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
     801             :                 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
     802             :                 WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
     803             :                 WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
     804        1231 :         drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
     805             :                 WPA_DRIVER_AUTH_SHARED |
     806             :                 WPA_DRIVER_AUTH_LEAP;
     807             : 
     808        1231 :         drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
     809        1231 :         drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
     810        1231 :         drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
     811             : 
     812             :         /*
     813             :          * As all cfg80211 drivers must support cases where the AP interface is
     814             :          * removed without the knowledge of wpa_supplicant/hostapd, e.g., in
     815             :          * case that the user space daemon has crashed, they must be able to
     816             :          * cleanup all stations and key entries in the AP tear down flow. Thus,
     817             :          * this flag can/should always be set for cfg80211 drivers.
     818             :          */
     819        1231 :         drv->capa.flags |= WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT;
     820             : 
     821        1231 :         if (!info.device_ap_sme) {
     822        1231 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
     823             : 
     824             :                 /*
     825             :                  * No AP SME is currently assumed to also indicate no AP MLME
     826             :                  * in the driver/firmware.
     827             :                  */
     828        1231 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_MLME;
     829             :         }
     830             : 
     831        1231 :         drv->device_ap_sme = info.device_ap_sme;
     832        1231 :         drv->poll_command_supported = info.poll_command_supported;
     833        1231 :         drv->data_tx_status = info.data_tx_status;
     834        1231 :         drv->p2p_go_ctwindow_supported = info.p2p_go_ctwindow_supported;
     835        1231 :         if (info.set_qos_map_supported)
     836        1231 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;
     837        1231 :         drv->have_low_prio_scan = info.have_low_prio_scan;
     838             : 
     839             :         /*
     840             :          * If poll command and tx status are supported, mac80211 is new enough
     841             :          * to have everything we need to not need monitor interfaces.
     842             :          */
     843        1231 :         drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;
     844             : 
     845        1231 :         if (drv->device_ap_sme && drv->use_monitor) {
     846             :                 /*
     847             :                  * Non-mac80211 drivers may not support monitor interface.
     848             :                  * Make sure we do not get stuck with incorrect capability here
     849             :                  * by explicitly testing this.
     850             :                  */
     851           0 :                 if (!info.monitor_supported) {
     852           0 :                         wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor "
     853             :                                    "with device_ap_sme since no monitor mode "
     854             :                                    "support detected");
     855           0 :                         drv->use_monitor = 0;
     856             :                 }
     857             :         }
     858             : 
     859             :         /*
     860             :          * If we aren't going to use monitor interfaces, but the
     861             :          * driver doesn't support data TX status, we won't get TX
     862             :          * status for EAPOL frames.
     863             :          */
     864        1231 :         if (!drv->use_monitor && !info.data_tx_status)
     865           0 :                 drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
     866             : 
     867        1231 :         qca_nl80211_check_dfs_capa(drv);
     868        1231 :         qca_nl80211_get_features(drv);
     869             : 
     870        1231 :         return 0;
     871             : }
     872             : 
     873             : 
     874             : struct phy_info_arg {
     875             :         u16 *num_modes;
     876             :         struct hostapd_hw_modes *modes;
     877             :         int last_mode, last_chan_idx;
     878             : };
     879             : 
     880      374556 : static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
     881             :                              struct nlattr *ampdu_factor,
     882             :                              struct nlattr *ampdu_density,
     883             :                              struct nlattr *mcs_set)
     884             : {
     885      374556 :         if (capa)
     886       17836 :                 mode->ht_capab = nla_get_u16(capa);
     887             : 
     888      374556 :         if (ampdu_factor)
     889       17836 :                 mode->a_mpdu_params |= nla_get_u8(ampdu_factor) & 0x03;
     890             : 
     891      374556 :         if (ampdu_density)
     892       17836 :                 mode->a_mpdu_params |= nla_get_u8(ampdu_density) << 2;
     893             : 
     894      374556 :         if (mcs_set && nla_len(mcs_set) >= 16) {
     895             :                 u8 *mcs;
     896       17836 :                 mcs = nla_data(mcs_set);
     897       17836 :                 os_memcpy(mode->mcs_set, mcs, 16);
     898             :         }
     899      374556 : }
     900             : 
     901             : 
     902      374556 : static void phy_info_vht_capa(struct hostapd_hw_modes *mode,
     903             :                               struct nlattr *capa,
     904             :                               struct nlattr *mcs_set)
     905             : {
     906      374556 :         if (capa)
     907       17836 :                 mode->vht_capab = nla_get_u32(capa);
     908             : 
     909      374556 :         if (mcs_set && nla_len(mcs_set) >= 8) {
     910             :                 u8 *mcs;
     911       17836 :                 mcs = nla_data(mcs_set);
     912       17836 :                 os_memcpy(mode->vht_mcs_set, mcs, 8);
     913             :         }
     914      374556 : }
     915             : 
     916             : 
     917      338884 : static void phy_info_freq(struct hostapd_hw_modes *mode,
     918             :                           struct hostapd_channel_data *chan,
     919             :                           struct nlattr *tb_freq[])
     920             : {
     921             :         u8 channel;
     922      338884 :         chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
     923      338884 :         chan->flag = 0;
     924      338884 :         chan->dfs_cac_ms = 0;
     925      338884 :         if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
     926      338884 :                 chan->chan = channel;
     927             : 
     928      338884 :         if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
     929        3879 :                 chan->flag |= HOSTAPD_CHAN_DISABLED;
     930      338884 :         if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR])
     931      233959 :                 chan->flag |= HOSTAPD_CHAN_NO_IR;
     932      338884 :         if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
     933      133770 :                 chan->flag |= HOSTAPD_CHAN_RADAR;
     934      338884 :         if (tb_freq[NL80211_FREQUENCY_ATTR_INDOOR_ONLY])
     935         200 :                 chan->flag |= HOSTAPD_CHAN_INDOOR_ONLY;
     936      338884 :         if (tb_freq[NL80211_FREQUENCY_ATTR_GO_CONCURRENT])
     937           0 :                 chan->flag |= HOSTAPD_CHAN_GO_CONCURRENT;
     938             : 
     939      338884 :         if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) {
     940      133770 :                 enum nl80211_dfs_state state =
     941      133770 :                         nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]);
     942             : 
     943      133770 :                 switch (state) {
     944             :                 case NL80211_DFS_USABLE:
     945      133770 :                         chan->flag |= HOSTAPD_CHAN_DFS_USABLE;
     946      133770 :                         break;
     947             :                 case NL80211_DFS_AVAILABLE:
     948           0 :                         chan->flag |= HOSTAPD_CHAN_DFS_AVAILABLE;
     949           0 :                         break;
     950             :                 case NL80211_DFS_UNAVAILABLE:
     951           0 :                         chan->flag |= HOSTAPD_CHAN_DFS_UNAVAILABLE;
     952           0 :                         break;
     953             :                 }
     954             :         }
     955             : 
     956      338884 :         if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]) {
     957      133770 :                 chan->dfs_cac_ms = nla_get_u32(
     958      133770 :                         tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]);
     959             :         }
     960      338884 : }
     961             : 
     962             : 
     963      374556 : static int phy_info_freqs(struct phy_info_arg *phy_info,
     964             :                           struct hostapd_hw_modes *mode, struct nlattr *tb)
     965             : {
     966             :         static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
     967             :                 [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
     968             :                 [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
     969             :                 [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
     970             :                 [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
     971             :                 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
     972             :                 [NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 },
     973             :         };
     974      374556 :         int new_channels = 0;
     975             :         struct hostapd_channel_data *channel;
     976             :         struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
     977             :         struct nlattr *nl_freq;
     978             :         int rem_freq, idx;
     979             : 
     980      374556 :         if (tb == NULL)
     981       17836 :                 return NL_OK;
     982             : 
     983      695604 :         nla_for_each_nested(nl_freq, tb, rem_freq) {
     984      677768 :                 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
     985      338884 :                           nla_data(nl_freq), nla_len(nl_freq), freq_policy);
     986      338884 :                 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
     987           0 :                         continue;
     988      338884 :                 new_channels++;
     989             :         }
     990             : 
     991      356720 :         channel = os_realloc_array(mode->channels,
     992      356720 :                                    mode->num_channels + new_channels,
     993             :                                    sizeof(struct hostapd_channel_data));
     994      356720 :         if (!channel)
     995           0 :                 return NL_SKIP;
     996             : 
     997      356720 :         mode->channels = channel;
     998      356720 :         mode->num_channels += new_channels;
     999             : 
    1000      356720 :         idx = phy_info->last_chan_idx;
    1001             : 
    1002      695604 :         nla_for_each_nested(nl_freq, tb, rem_freq) {
    1003      677768 :                 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
    1004      338884 :                           nla_data(nl_freq), nla_len(nl_freq), freq_policy);
    1005      338884 :                 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
    1006           0 :                         continue;
    1007      338884 :                 phy_info_freq(mode, &mode->channels[idx], tb_freq);
    1008      338884 :                 idx++;
    1009             :         }
    1010      356720 :         phy_info->last_chan_idx = idx;
    1011             : 
    1012      356720 :         return NL_OK;
    1013             : }
    1014             : 
    1015             : 
    1016      374556 : static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
    1017             : {
    1018             :         static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {
    1019             :                 [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },
    1020             :                 [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] =
    1021             :                 { .type = NLA_FLAG },
    1022             :         };
    1023             :         struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
    1024             :         struct nlattr *nl_rate;
    1025             :         int rem_rate, idx;
    1026             : 
    1027      374556 :         if (tb == NULL)
    1028      356720 :                 return NL_OK;
    1029             : 
    1030      196196 :         nla_for_each_nested(nl_rate, tb, rem_rate) {
    1031      356720 :                 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
    1032      178360 :                           nla_data(nl_rate), nla_len(nl_rate),
    1033             :                           rate_policy);
    1034      178360 :                 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
    1035           0 :                         continue;
    1036      178360 :                 mode->num_rates++;
    1037             :         }
    1038             : 
    1039       17836 :         mode->rates = os_calloc(mode->num_rates, sizeof(int));
    1040       17836 :         if (!mode->rates)
    1041           0 :                 return NL_SKIP;
    1042             : 
    1043       17836 :         idx = 0;
    1044             : 
    1045      196196 :         nla_for_each_nested(nl_rate, tb, rem_rate) {
    1046      356720 :                 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
    1047      178360 :                           nla_data(nl_rate), nla_len(nl_rate),
    1048             :                           rate_policy);
    1049      178360 :                 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
    1050           0 :                         continue;
    1051      178360 :                 mode->rates[idx] = nla_get_u32(
    1052             :                         tb_rate[NL80211_BITRATE_ATTR_RATE]);
    1053      178360 :                 idx++;
    1054             :         }
    1055             : 
    1056       17836 :         return NL_OK;
    1057             : }
    1058             : 
    1059             : 
    1060      374556 : static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
    1061             : {
    1062             :         struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
    1063             :         struct hostapd_hw_modes *mode;
    1064             :         int ret;
    1065             : 
    1066      374556 :         if (phy_info->last_mode != nl_band->nla_type) {
    1067       17836 :                 mode = os_realloc_array(phy_info->modes,
    1068       17836 :                                         *phy_info->num_modes + 1,
    1069             :                                         sizeof(*mode));
    1070       17836 :                 if (!mode)
    1071           0 :                         return NL_SKIP;
    1072       17836 :                 phy_info->modes = mode;
    1073             : 
    1074       17836 :                 mode = &phy_info->modes[*(phy_info->num_modes)];
    1075       17836 :                 os_memset(mode, 0, sizeof(*mode));
    1076       17836 :                 mode->mode = NUM_HOSTAPD_MODES;
    1077       17836 :                 mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN |
    1078             :                         HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN;
    1079             : 
    1080             :                 /*
    1081             :                  * Unsupported VHT MCS stream is defined as value 3, so the VHT
    1082             :                  * MCS RX/TX map must be initialized with 0xffff to mark all 8
    1083             :                  * possible streams as unsupported. This will be overridden if
    1084             :                  * driver advertises VHT support.
    1085             :                  */
    1086       17836 :                 mode->vht_mcs_set[0] = 0xff;
    1087       17836 :                 mode->vht_mcs_set[1] = 0xff;
    1088       17836 :                 mode->vht_mcs_set[4] = 0xff;
    1089       17836 :                 mode->vht_mcs_set[5] = 0xff;
    1090             : 
    1091       17836 :                 *(phy_info->num_modes) += 1;
    1092       17836 :                 phy_info->last_mode = nl_band->nla_type;
    1093       17836 :                 phy_info->last_chan_idx = 0;
    1094             :         } else
    1095      356720 :                 mode = &phy_info->modes[*(phy_info->num_modes) - 1];
    1096             : 
    1097      374556 :         nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
    1098             :                   nla_len(nl_band), NULL);
    1099             : 
    1100      374556 :         phy_info_ht_capa(mode, tb_band[NL80211_BAND_ATTR_HT_CAPA],
    1101             :                          tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR],
    1102             :                          tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY],
    1103             :                          tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);
    1104      374556 :         phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
    1105             :                           tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
    1106      374556 :         ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]);
    1107      374556 :         if (ret != NL_OK)
    1108           0 :                 return ret;
    1109      374556 :         ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
    1110      374556 :         if (ret != NL_OK)
    1111           0 :                 return ret;
    1112             : 
    1113      374556 :         return NL_OK;
    1114             : }
    1115             : 
    1116             : 
    1117      481572 : static int phy_info_handler(struct nl_msg *msg, void *arg)
    1118             : {
    1119             :         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
    1120      481572 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    1121      481572 :         struct phy_info_arg *phy_info = arg;
    1122             :         struct nlattr *nl_band;
    1123             :         int rem_band;
    1124             : 
    1125      481572 :         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    1126             :                   genlmsg_attrlen(gnlh, 0), NULL);
    1127             : 
    1128      481572 :         if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
    1129       98098 :                 return NL_SKIP;
    1130             : 
    1131      758030 :         nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band)
    1132             :         {
    1133      374556 :                 int res = phy_info_band(phy_info, nl_band);
    1134      374556 :                 if (res != NL_OK)
    1135           0 :                         return res;
    1136             :         }
    1137             : 
    1138      383474 :         return NL_SKIP;
    1139             : }
    1140             : 
    1141             : 
    1142             : static struct hostapd_hw_modes *
    1143        8924 : wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
    1144             :                                      u16 *num_modes)
    1145             : {
    1146             :         u16 m;
    1147        8924 :         struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
    1148        8924 :         int i, mode11g_idx = -1;
    1149             : 
    1150             :         /* heuristic to set up modes */
    1151       26760 :         for (m = 0; m < *num_modes; m++) {
    1152       17836 :                 if (!modes[m].num_channels)
    1153           0 :                         continue;
    1154       17836 :                 if (modes[m].channels[0].freq < 4000) {
    1155        8918 :                         modes[m].mode = HOSTAPD_MODE_IEEE80211B;
    1156       80262 :                         for (i = 0; i < modes[m].num_rates; i++) {
    1157       80262 :                                 if (modes[m].rates[i] > 200) {
    1158        8918 :                                         modes[m].mode = HOSTAPD_MODE_IEEE80211G;
    1159        8918 :                                         break;
    1160             :                                 }
    1161             :                         }
    1162        8918 :                 } else if (modes[m].channels[0].freq > 50000)
    1163           0 :                         modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
    1164             :                 else
    1165        8918 :                         modes[m].mode = HOSTAPD_MODE_IEEE80211A;
    1166             :         }
    1167             : 
    1168             :         /* If only 802.11g mode is included, use it to construct matching
    1169             :          * 802.11b mode data. */
    1170             : 
    1171       26760 :         for (m = 0; m < *num_modes; m++) {
    1172       17836 :                 if (modes[m].mode == HOSTAPD_MODE_IEEE80211B)
    1173           0 :                         return modes; /* 802.11b already included */
    1174       17836 :                 if (modes[m].mode == HOSTAPD_MODE_IEEE80211G)
    1175        8918 :                         mode11g_idx = m;
    1176             :         }
    1177             : 
    1178        8924 :         if (mode11g_idx < 0)
    1179           6 :                 return modes; /* 2.4 GHz band not supported at all */
    1180             : 
    1181        8918 :         nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes));
    1182        8918 :         if (nmodes == NULL)
    1183           0 :                 return modes; /* Could not add 802.11b mode */
    1184             : 
    1185        8918 :         mode = &nmodes[*num_modes];
    1186        8918 :         os_memset(mode, 0, sizeof(*mode));
    1187        8918 :         (*num_modes)++;
    1188        8918 :         modes = nmodes;
    1189             : 
    1190        8918 :         mode->mode = HOSTAPD_MODE_IEEE80211B;
    1191             : 
    1192        8918 :         mode11g = &modes[mode11g_idx];
    1193        8918 :         mode->num_channels = mode11g->num_channels;
    1194        8918 :         mode->channels = os_malloc(mode11g->num_channels *
    1195             :                                    sizeof(struct hostapd_channel_data));
    1196        8918 :         if (mode->channels == NULL) {
    1197           0 :                 (*num_modes)--;
    1198           0 :                 return modes; /* Could not add 802.11b mode */
    1199             :         }
    1200        8918 :         os_memcpy(mode->channels, mode11g->channels,
    1201             :                   mode11g->num_channels * sizeof(struct hostapd_channel_data));
    1202             : 
    1203        8918 :         mode->num_rates = 0;
    1204        8918 :         mode->rates = os_malloc(4 * sizeof(int));
    1205        8918 :         if (mode->rates == NULL) {
    1206           0 :                 os_free(mode->channels);
    1207           0 :                 (*num_modes)--;
    1208           0 :                 return modes; /* Could not add 802.11b mode */
    1209             :         }
    1210             : 
    1211       35672 :         for (i = 0; i < mode11g->num_rates; i++) {
    1212       53508 :                 if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&
    1213       26754 :                     mode11g->rates[i] != 55 && mode11g->rates[i] != 110)
    1214           0 :                         continue;
    1215       35672 :                 mode->rates[mode->num_rates] = mode11g->rates[i];
    1216       35672 :                 mode->num_rates++;
    1217       35672 :                 if (mode->num_rates == 4)
    1218        8918 :                         break;
    1219             :         }
    1220             : 
    1221        8918 :         if (mode->num_rates == 0) {
    1222           0 :                 os_free(mode->channels);
    1223           0 :                 os_free(mode->rates);
    1224           0 :                 (*num_modes)--;
    1225           0 :                 return modes; /* No 802.11b rates */
    1226             :         }
    1227             : 
    1228        8918 :         wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g "
    1229             :                    "information");
    1230             : 
    1231        8918 :         return modes;
    1232             : }
    1233             : 
    1234             : 
    1235      123326 : static void nl80211_set_ht40_mode(struct hostapd_hw_modes *mode, int start,
    1236             :                                   int end)
    1237             : {
    1238             :         int c;
    1239             : 
    1240     2466520 :         for (c = 0; c < mode->num_channels; c++) {
    1241     2343194 :                 struct hostapd_channel_data *chan = &mode->channels[c];
    1242     2343194 :                 if (chan->freq - 10 >= start && chan->freq + 10 <= end)
    1243      326455 :                         chan->flag |= HOSTAPD_CHAN_HT40;
    1244             :         }
    1245      123326 : }
    1246             : 
    1247             : 
    1248      140426 : static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,
    1249             :                                       int end)
    1250             : {
    1251             :         int c;
    1252             : 
    1253     2808520 :         for (c = 0; c < mode->num_channels; c++) {
    1254     2668094 :                 struct hostapd_channel_data *chan = &mode->channels[c];
    1255     2668094 :                 if (!(chan->flag & HOSTAPD_CHAN_HT40))
    1256       88038 :                         continue;
    1257     2580056 :                 if (chan->freq - 30 >= start && chan->freq - 10 <= end)
    1258      264474 :                         chan->flag |= HOSTAPD_CHAN_HT40MINUS;
    1259     2580056 :                 if (chan->freq + 10 >= start && chan->freq + 30 <= end)
    1260      272972 :                         chan->flag |= HOSTAPD_CHAN_HT40PLUS;
    1261             :         }
    1262      140426 : }
    1263             : 
    1264             : 
    1265       70261 : static void nl80211_reg_rule_max_eirp(u32 start, u32 end, u32 max_eirp,
    1266             :                                       struct phy_info_arg *results)
    1267             : {
    1268             :         u16 m;
    1269             : 
    1270      210687 :         for (m = 0; m < *results->num_modes; m++) {
    1271             :                 int c;
    1272      140426 :                 struct hostapd_hw_modes *mode = &results->modes[m];
    1273             : 
    1274     2808520 :                 for (c = 0; c < mode->num_channels; c++) {
    1275     2668094 :                         struct hostapd_channel_data *chan = &mode->channels[c];
    1276     4027728 :                         if ((u32) chan->freq - 10 >= start &&
    1277     1359634 :                             (u32) chan->freq + 10 <= end)
    1278      335005 :                                 chan->max_tx_power = max_eirp;
    1279             :                 }
    1280             :         }
    1281       70261 : }
    1282             : 
    1283             : 
    1284       61705 : static void nl80211_reg_rule_ht40(u32 start, u32 end,
    1285             :                                   struct phy_info_arg *results)
    1286             : {
    1287             :         u16 m;
    1288             : 
    1289      185031 :         for (m = 0; m < *results->num_modes; m++) {
    1290      123326 :                 if (!(results->modes[m].ht_capab &
    1291             :                       HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
    1292           0 :                         continue;
    1293      123326 :                 nl80211_set_ht40_mode(&results->modes[m], start, end);
    1294             :         }
    1295       61705 : }
    1296             : 
    1297             : 
    1298       70261 : static void nl80211_reg_rule_sec(struct nlattr *tb[],
    1299             :                                  struct phy_info_arg *results)
    1300             : {
    1301             :         u32 start, end, max_bw;
    1302             :         u16 m;
    1303             : 
    1304      140522 :         if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
    1305      140522 :             tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
    1306       70261 :             tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
    1307           0 :                 return;
    1308             : 
    1309       70261 :         start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
    1310       70261 :         end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
    1311       70261 :         max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
    1312             : 
    1313       70261 :         if (max_bw < 20)
    1314           0 :                 return;
    1315             : 
    1316      210687 :         for (m = 0; m < *results->num_modes; m++) {
    1317      140426 :                 if (!(results->modes[m].ht_capab &
    1318             :                       HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
    1319           0 :                         continue;
    1320      140426 :                 nl80211_set_ht40_mode_sec(&results->modes[m], start, end);
    1321             :         }
    1322             : }
    1323             : 
    1324             : 
    1325       88336 : static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
    1326             :                                  int end)
    1327             : {
    1328             :         int c;
    1329             : 
    1330     1766720 :         for (c = 0; c < mode->num_channels; c++) {
    1331     1678384 :                 struct hostapd_channel_data *chan = &mode->channels[c];
    1332     1678384 :                 if (chan->freq - 10 >= start && chan->freq + 70 <= end)
    1333      113622 :                         chan->flag |= HOSTAPD_CHAN_VHT_10_70;
    1334             : 
    1335     1678384 :                 if (chan->freq - 30 >= start && chan->freq + 50 <= end)
    1336      113672 :                         chan->flag |= HOSTAPD_CHAN_VHT_30_50;
    1337             : 
    1338     1678384 :                 if (chan->freq - 50 >= start && chan->freq + 30 <= end)
    1339      113672 :                         chan->flag |= HOSTAPD_CHAN_VHT_50_30;
    1340             : 
    1341     1678384 :                 if (chan->freq - 70 >= start && chan->freq + 10 <= end)
    1342      105124 :                         chan->flag |= HOSTAPD_CHAN_VHT_70_10;
    1343             :         }
    1344       88336 : }
    1345             : 
    1346             : 
    1347       70261 : static void nl80211_reg_rule_vht(struct nlattr *tb[],
    1348             :                                  struct phy_info_arg *results)
    1349             : {
    1350             :         u32 start, end, max_bw;
    1351             :         u16 m;
    1352             : 
    1353      140522 :         if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
    1354      140522 :             tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
    1355       70261 :             tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
    1356           0 :                 return;
    1357             : 
    1358       70261 :         start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
    1359       70261 :         end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
    1360       70261 :         max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
    1361             : 
    1362       70261 :         if (max_bw < 80)
    1363       26063 :                 return;
    1364             : 
    1365      132534 :         for (m = 0; m < *results->num_modes; m++) {
    1366       88336 :                 if (!(results->modes[m].ht_capab &
    1367             :                       HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
    1368           0 :                         continue;
    1369             :                 /* TODO: use a real VHT support indication */
    1370       88336 :                 if (!results->modes[m].vht_capab)
    1371           0 :                         continue;
    1372             : 
    1373       88336 :                 nl80211_set_vht_mode(&results->modes[m], start, end);
    1374             :         }
    1375             : }
    1376             : 
    1377             : 
    1378         395 : static const char * dfs_domain_name(enum nl80211_dfs_regions region)
    1379             : {
    1380         395 :         switch (region) {
    1381             :         case NL80211_DFS_UNSET:
    1382           0 :                 return "DFS-UNSET";
    1383             :         case NL80211_DFS_FCC:
    1384         192 :                 return "DFS-FCC";
    1385             :         case NL80211_DFS_ETSI:
    1386         176 :                 return "DFS-ETSI";
    1387             :         case NL80211_DFS_JP:
    1388          27 :                 return "DFS-JP";
    1389             :         default:
    1390           0 :                 return "DFS-invalid";
    1391             :         }
    1392             : }
    1393             : 
    1394             : 
    1395        8924 : static int nl80211_get_reg(struct nl_msg *msg, void *arg)
    1396             : {
    1397        8924 :         struct phy_info_arg *results = arg;
    1398             :         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
    1399        8924 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    1400             :         struct nlattr *nl_rule;
    1401             :         struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
    1402             :         int rem_rule;
    1403             :         static struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
    1404             :                 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
    1405             :                 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
    1406             :                 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
    1407             :                 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
    1408             :                 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
    1409             :                 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
    1410             :         };
    1411             : 
    1412        8924 :         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    1413             :                   genlmsg_attrlen(gnlh, 0), NULL);
    1414       17848 :         if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
    1415        8924 :             !tb_msg[NL80211_ATTR_REG_RULES]) {
    1416           0 :                 wpa_printf(MSG_DEBUG, "nl80211: No regulatory information "
    1417             :                            "available");
    1418           0 :                 return NL_SKIP;
    1419             :         }
    1420             : 
    1421        8924 :         if (tb_msg[NL80211_ATTR_DFS_REGION]) {
    1422             :                 enum nl80211_dfs_regions dfs_domain;
    1423         395 :                 dfs_domain = nla_get_u8(tb_msg[NL80211_ATTR_DFS_REGION]);
    1424         790 :                 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s (%s)",
    1425         395 :                            (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]),
    1426             :                            dfs_domain_name(dfs_domain));
    1427             :         } else {
    1428        8529 :                 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s",
    1429        8529 :                            (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));
    1430             :         }
    1431             : 
    1432       79185 :         nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
    1433             :         {
    1434       70261 :                 u32 start, end, max_eirp = 0, max_bw = 0, flags = 0;
    1435      140522 :                 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
    1436       70261 :                           nla_data(nl_rule), nla_len(nl_rule), reg_policy);
    1437      140522 :                 if (tb_rule[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
    1438       70261 :                     tb_rule[NL80211_ATTR_FREQ_RANGE_END] == NULL)
    1439           0 :                         continue;
    1440       70261 :                 start = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
    1441       70261 :                 end = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
    1442       70261 :                 if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
    1443       70261 :                         max_eirp = nla_get_u32(tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP]) / 100;
    1444       70261 :                 if (tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW])
    1445       70261 :                         max_bw = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
    1446       70261 :                 if (tb_rule[NL80211_ATTR_REG_RULE_FLAGS])
    1447       70261 :                         flags = nla_get_u32(tb_rule[NL80211_ATTR_REG_RULE_FLAGS]);
    1448             : 
    1449      562088 :                 wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s",
    1450             :                            start, end, max_bw, max_eirp,
    1451       70261 :                            flags & NL80211_RRF_NO_OFDM ? " (no OFDM)" : "",
    1452       70261 :                            flags & NL80211_RRF_NO_CCK ? " (no CCK)" : "",
    1453       70261 :                            flags & NL80211_RRF_NO_INDOOR ? " (no indoor)" : "",
    1454       70261 :                            flags & NL80211_RRF_NO_OUTDOOR ? " (no outdoor)" :
    1455             :                            "",
    1456       70261 :                            flags & NL80211_RRF_DFS ? " (DFS)" : "",
    1457       70261 :                            flags & NL80211_RRF_PTP_ONLY ? " (PTP only)" : "",
    1458       70261 :                            flags & NL80211_RRF_PTMP_ONLY ? " (PTMP only)" : "",
    1459       70261 :                            flags & NL80211_RRF_NO_IR ? " (no IR)" : "");
    1460       70261 :                 if (max_bw >= 40)
    1461       61705 :                         nl80211_reg_rule_ht40(start, end, results);
    1462       70261 :                 if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
    1463       70261 :                         nl80211_reg_rule_max_eirp(start, end, max_eirp,
    1464             :                                                   results);
    1465             :         }
    1466             : 
    1467       79185 :         nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
    1468             :         {
    1469      140522 :                 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
    1470       70261 :                           nla_data(nl_rule), nla_len(nl_rule), reg_policy);
    1471       70261 :                 nl80211_reg_rule_sec(tb_rule, results);
    1472             :         }
    1473             : 
    1474       79185 :         nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
    1475             :         {
    1476      140522 :                 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
    1477       70261 :                           nla_data(nl_rule), nla_len(nl_rule), reg_policy);
    1478       70261 :                 nl80211_reg_rule_vht(tb_rule, results);
    1479             :         }
    1480             : 
    1481        8924 :         return NL_SKIP;
    1482             : }
    1483             : 
    1484             : 
    1485        8924 : static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv,
    1486             :                                         struct phy_info_arg *results)
    1487             : {
    1488             :         struct nl_msg *msg;
    1489             : 
    1490        8924 :         msg = nlmsg_alloc();
    1491        8924 :         if (!msg)
    1492           0 :                 return -ENOMEM;
    1493             : 
    1494        8924 :         nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
    1495        8924 :         return send_and_recv_msgs(drv, msg, nl80211_get_reg, results);
    1496             : }
    1497             : 
    1498             : 
    1499             : struct hostapd_hw_modes *
    1500        8924 : nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
    1501             : {
    1502             :         u32 feat;
    1503        8924 :         struct i802_bss *bss = priv;
    1504        8924 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    1505        8924 :         int nl_flags = 0;
    1506             :         struct nl_msg *msg;
    1507        8924 :         struct phy_info_arg result = {
    1508             :                 .num_modes = num_modes,
    1509             :                 .modes = NULL,
    1510             :                 .last_mode = -1,
    1511             :         };
    1512             : 
    1513        8924 :         *num_modes = 0;
    1514        8924 :         *flags = 0;
    1515             : 
    1516        8924 :         feat = get_nl80211_protocol_features(drv);
    1517        8924 :         if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
    1518        8924 :                 nl_flags = NLM_F_DUMP;
    1519       17848 :         if (!(msg = nl80211_cmd_msg(bss, nl_flags, NL80211_CMD_GET_WIPHY)) ||
    1520        8924 :             nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
    1521           0 :                 nlmsg_free(msg);
    1522           0 :                 return NULL;
    1523             :         }
    1524             : 
    1525        8924 :         if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
    1526        8924 :                 nl80211_set_regulatory_flags(drv, &result);
    1527        8924 :                 return wpa_driver_nl80211_postprocess_modes(result.modes,
    1528             :                                                             num_modes);
    1529             :         }
    1530             : 
    1531           0 :         return NULL;
    1532             : }

Generated by: LCOV version 1.10