diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 0797d49eb..28b3fb4b1 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1704,18 +1704,9 @@ nla_put_failure: struct wiphy_info_data { - int max_scan_ssids; - int max_sched_scan_ssids; - int ap_supported; - int p2p_supported; - int p2p_concurrent; - int auth_supported; - int connect_supported; - int offchan_tx_supported; - int max_remain_on_chan; - int firmware_roam; - int sched_scan_supported; - int max_match_sets; + struct wpa_driver_capa *capa; + + unsigned int error:1; }; @@ -1725,6 +1716,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct wiphy_info_data *info = arg; int p2p_go_supported = 0, p2p_client_supported = 0; + int p2p_concurrent = 0; + int auth_supported = 0, connect_supported = 0; + struct wpa_driver_capa *capa = info->capa; static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = { [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED }, @@ -1741,15 +1735,15 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) genlmsg_attrlen(gnlh, 0), NULL); if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) - info->max_scan_ssids = + capa->max_scan_ssids = nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]); if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]) - info->max_sched_scan_ssids = + capa->max_sched_scan_ssids = nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]); if (tb[NL80211_ATTR_MAX_MATCH_SETS]) - info->max_match_sets = + capa->max_match_sets = nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]); if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) { @@ -1759,7 +1753,7 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) { switch (nla_type(nl_mode)) { case NL80211_IFTYPE_AP: - info->ap_supported = 1; + capa->flags |= WPA_DRIVER_FLAGS_AP; break; case NL80211_IFTYPE_P2P_GO: p2p_go_supported = 1; @@ -1819,7 +1813,7 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) } if (combination_has_p2p && combination_has_mgd) { - info->p2p_concurrent = 1; + p2p_concurrent = 1; break; } @@ -1828,34 +1822,61 @@ broken_combination: } } - info->p2p_supported = p2p_go_supported && p2p_client_supported; - if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) { struct nlattr *nl_cmd; int i; nla_for_each_nested(nl_cmd, tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { - u32 cmd = nla_get_u32(nl_cmd); - if (cmd == NL80211_CMD_AUTHENTICATE) - info->auth_supported = 1; - else if (cmd == NL80211_CMD_CONNECT) - info->connect_supported = 1; - else if (cmd == NL80211_CMD_START_SCHED_SCAN) - info->sched_scan_supported = 1; + switch (nla_get_u32(nl_cmd)) { + case NL80211_CMD_AUTHENTICATE: + auth_supported = 1; + break; + case NL80211_CMD_CONNECT: + connect_supported = 1; + break; + case NL80211_CMD_START_SCHED_SCAN: + capa->sched_scan_supported = 1; + break; + } } } - if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) - info->offchan_tx_supported = 1; + if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) { + wpa_printf(MSG_DEBUG, "nl80211: Using driver-based " + "off-channel TX"); + capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX; + } - if (tb[NL80211_ATTR_ROAM_SUPPORT]) - info->firmware_roam = 1; + if (tb[NL80211_ATTR_ROAM_SUPPORT]) { + wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming"); + capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION; + } + + /* default to 5000 since early versions of mac80211 don't set it */ + capa->max_remain_on_chan = 5000; if (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]) - info->max_remain_on_chan = + capa->max_remain_on_chan = nla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]); + if (auth_supported) + capa->flags |= WPA_DRIVER_FLAGS_SME; + else if (!connect_supported) { + wpa_printf(MSG_INFO, "nl80211: Driver does not support " + "authentication/association or connect commands"); + info->error = 1; + } + + if (p2p_go_supported && p2p_client_supported) + capa->flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE; + if (p2p_concurrent) { + wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group " + "interface (driver advertised support)"); + capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; + capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P; + } + return NL_SKIP; } @@ -1866,9 +1887,7 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg; os_memset(info, 0, sizeof(*info)); - - /* default to 5000 since early versions of mac80211 don't set it */ - info->max_remain_on_chan = 5000; + info->capa = &drv->capa; msg = nlmsg_alloc(); if (!msg) @@ -1893,6 +1912,10 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) struct wiphy_info_data info; if (wpa_driver_nl80211_get_info(drv, &info)) return -1; + + if (info.error) + return -1; + drv->has_capability = 1; /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | @@ -1907,46 +1930,10 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) WPA_DRIVER_AUTH_SHARED | WPA_DRIVER_AUTH_LEAP; - drv->capa.max_scan_ssids = info.max_scan_ssids; - drv->capa.max_sched_scan_ssids = info.max_sched_scan_ssids; - drv->capa.sched_scan_supported = info.sched_scan_supported; - drv->capa.max_match_sets = info.max_match_sets; - - if (info.ap_supported) - drv->capa.flags |= WPA_DRIVER_FLAGS_AP; - - if (info.auth_supported) - drv->capa.flags |= WPA_DRIVER_FLAGS_SME; - else if (!info.connect_supported) { - wpa_printf(MSG_INFO, "nl80211: Driver does not support " - "authentication/association or connect commands"); - return -1; - } - - if (info.offchan_tx_supported) { - wpa_printf(MSG_DEBUG, "nl80211: Using driver-based " - "off-channel TX"); - drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX; - } - - if (info.firmware_roam) { - wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming"); - drv->capa.flags |= WPA_DRIVER_FLAGS_BSS_SELECTION; - } - drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES; drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE; - if (info.p2p_supported) - drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE; - if (info.p2p_concurrent) { - wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group " - "interface (driver advertised support)"); - drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; - drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P; - } drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS; - drv->capa.max_remain_on_chan = info.max_remain_on_chan; return 0; }