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 {
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;
}