nl80211: Clean up capability querying

There's no need to store everything once and then copy it. Just fill the
capa struct directly in the function that parses the info from nl80211.
This commit is contained in:
Johannes Berg 2011-10-20 21:57:32 +03:00 committed by Jouni Malinen
parent 9b90955ec7
commit e8b5e24e04

View file

@ -1704,18 +1704,9 @@ nla_put_failure:
struct wiphy_info_data { struct wiphy_info_data {
int max_scan_ssids; struct wpa_driver_capa *capa;
int max_sched_scan_ssids;
int ap_supported; unsigned int error:1;
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;
}; };
@ -1725,6 +1716,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct wiphy_info_data *info = arg; struct wiphy_info_data *info = arg;
int p2p_go_supported = 0, p2p_client_supported = 0; 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 static struct nla_policy
iface_combination_policy[NUM_NL80211_IFACE_COMB] = { iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED }, [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); genlmsg_attrlen(gnlh, 0), NULL);
if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) 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]); nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
if (tb[NL80211_ATTR_MAX_NUM_SCHED_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]); nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
if (tb[NL80211_ATTR_MAX_MATCH_SETS]) if (tb[NL80211_ATTR_MAX_MATCH_SETS])
info->max_match_sets = capa->max_match_sets =
nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]); nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) { 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) { tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {
switch (nla_type(nl_mode)) { switch (nla_type(nl_mode)) {
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
info->ap_supported = 1; capa->flags |= WPA_DRIVER_FLAGS_AP;
break; break;
case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_P2P_GO:
p2p_go_supported = 1; 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) { if (combination_has_p2p && combination_has_mgd) {
info->p2p_concurrent = 1; p2p_concurrent = 1;
break; break;
} }
@ -1828,34 +1822,61 @@ broken_combination:
} }
} }
info->p2p_supported = p2p_go_supported && p2p_client_supported;
if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) { if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {
struct nlattr *nl_cmd; struct nlattr *nl_cmd;
int i; int i;
nla_for_each_nested(nl_cmd, nla_for_each_nested(nl_cmd,
tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) {
u32 cmd = nla_get_u32(nl_cmd); switch (nla_get_u32(nl_cmd)) {
if (cmd == NL80211_CMD_AUTHENTICATE) case NL80211_CMD_AUTHENTICATE:
info->auth_supported = 1; auth_supported = 1;
else if (cmd == NL80211_CMD_CONNECT) break;
info->connect_supported = 1; case NL80211_CMD_CONNECT:
else if (cmd == NL80211_CMD_START_SCHED_SCAN) connect_supported = 1;
info->sched_scan_supported = 1; break;
case NL80211_CMD_START_SCHED_SCAN:
capa->sched_scan_supported = 1;
break;
}
} }
} }
if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
info->offchan_tx_supported = 1; wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
"off-channel TX");
capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
}
if (tb[NL80211_ATTR_ROAM_SUPPORT]) if (tb[NL80211_ATTR_ROAM_SUPPORT]) {
info->firmware_roam = 1; 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]) 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]); 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; return NL_SKIP;
} }
@ -1866,9 +1887,7 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
struct nl_msg *msg; struct nl_msg *msg;
os_memset(info, 0, sizeof(*info)); os_memset(info, 0, sizeof(*info));
info->capa = &drv->capa;
/* default to 5000 since early versions of mac80211 don't set it */
info->max_remain_on_chan = 5000;
msg = nlmsg_alloc(); msg = nlmsg_alloc();
if (!msg) if (!msg)
@ -1893,6 +1912,10 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
struct wiphy_info_data info; struct wiphy_info_data info;
if (wpa_driver_nl80211_get_info(drv, &info)) if (wpa_driver_nl80211_get_info(drv, &info))
return -1; return -1;
if (info.error)
return -1;
drv->has_capability = 1; drv->has_capability = 1;
/* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */
drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | 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_SHARED |
WPA_DRIVER_AUTH_LEAP; 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_SANE_ERROR_CODES;
drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE; 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_EAPOL_TX_STATUS;
drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS; drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
drv->capa.max_remain_on_chan = info.max_remain_on_chan;
return 0; return 0;
} }