nl80211: Update drv->ssid on connect/associate event based on BSS data
On a connect nl80211 event, wpa_supplicant uses wpa_driver_nl80211_get_ssid() to fetch the current associated SSID to compare to existing configurations. However, wpa_driver_nl80211_get_ssid() uses drv->ssid, which is a cached value. It is set when we explicitly initial a connect request using wpa_supplicant. If the association was initiated outside of wpa_supplicant, we need another way to populate drv->ssid. This commit sets drv->ssid based on cfg80211 BSS information on connect/associate nl80211 events. Signed-off-by: Ningyuan Wang <nywang@google.com>
This commit is contained in:
parent
9f346fadc8
commit
ed0a4ddc22
3 changed files with 66 additions and 1 deletions
|
@ -1186,6 +1186,8 @@ struct nl80211_get_assoc_freq_arg {
|
||||||
unsigned int assoc_freq;
|
unsigned int assoc_freq;
|
||||||
unsigned int ibss_freq;
|
unsigned int ibss_freq;
|
||||||
u8 assoc_bssid[ETH_ALEN];
|
u8 assoc_bssid[ETH_ALEN];
|
||||||
|
u8 assoc_ssid[SSID_MAX_LEN];
|
||||||
|
u8 assoc_ssid_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int nl80211_get_assoc_freq_handler(struct nl_msg *msg, void *arg)
|
static int nl80211_get_assoc_freq_handler(struct nl_msg *msg, void *arg)
|
||||||
|
@ -1196,6 +1198,7 @@ static int nl80211_get_assoc_freq_handler(struct nl_msg *msg, void *arg)
|
||||||
static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
|
static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
|
||||||
[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
|
[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
|
||||||
[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
|
[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
|
||||||
|
[NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
|
||||||
[NL80211_BSS_STATUS] = { .type = NLA_U32 },
|
[NL80211_BSS_STATUS] = { .type = NLA_U32 },
|
||||||
};
|
};
|
||||||
struct nl80211_get_assoc_freq_arg *ctx = arg;
|
struct nl80211_get_assoc_freq_arg *ctx = arg;
|
||||||
|
@ -1230,10 +1233,45 @@ static int nl80211_get_assoc_freq_handler(struct nl_msg *msg, void *arg)
|
||||||
MACSTR, MAC2STR(ctx->assoc_bssid));
|
MACSTR, MAC2STR(ctx->assoc_bssid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status == NL80211_BSS_STATUS_ASSOCIATED &&
|
||||||
|
bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
|
||||||
|
const u8 *ie, *ssid;
|
||||||
|
size_t ie_len;
|
||||||
|
|
||||||
|
ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
||||||
|
ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
||||||
|
ssid = get_ie(ie, ie_len, WLAN_EID_SSID);
|
||||||
|
if (ssid && ssid[1] > 0 && ssid[1] <= SSID_MAX_LEN) {
|
||||||
|
ctx->assoc_ssid_len = ssid[1];
|
||||||
|
os_memcpy(ctx->assoc_ssid, ssid + 2, ssid[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int nl80211_get_assoc_ssid(struct wpa_driver_nl80211_data *drv, u8 *ssid)
|
||||||
|
{
|
||||||
|
struct nl_msg *msg;
|
||||||
|
int ret;
|
||||||
|
struct nl80211_get_assoc_freq_arg arg;
|
||||||
|
|
||||||
|
msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
|
||||||
|
os_memset(&arg, 0, sizeof(arg));
|
||||||
|
arg.drv = drv;
|
||||||
|
ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler,
|
||||||
|
&arg);
|
||||||
|
if (ret == 0) {
|
||||||
|
os_memcpy(ssid, arg.assoc_ssid, arg.assoc_ssid_len);
|
||||||
|
return arg.assoc_ssid_len;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d (%s)",
|
||||||
|
ret, strerror(-ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
|
unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
|
|
|
@ -228,6 +228,7 @@ int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
|
||||||
void *arg, int use_existing);
|
void *arg, int use_existing);
|
||||||
void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx);
|
void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx);
|
||||||
unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv);
|
unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv);
|
||||||
|
int nl80211_get_assoc_ssid(struct wpa_driver_nl80211_data *drv, u8 *ssid);
|
||||||
enum chan_width convert2width(int width);
|
enum chan_width convert2width(int width);
|
||||||
void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv);
|
void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv);
|
||||||
struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv,
|
struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv,
|
||||||
|
|
|
@ -206,6 +206,7 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
|
||||||
const struct ieee80211_mgmt *mgmt;
|
const struct ieee80211_mgmt *mgmt;
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
u16 status;
|
u16 status;
|
||||||
|
int ssid_len;
|
||||||
|
|
||||||
if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
|
if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
|
||||||
drv->force_connect_cmd) {
|
drv->force_connect_cmd) {
|
||||||
|
@ -257,6 +258,16 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
|
||||||
|
|
||||||
event.assoc_info.freq = drv->assoc_freq;
|
event.assoc_info.freq = drv->assoc_freq;
|
||||||
|
|
||||||
|
/* When this association was initiated outside of wpa_supplicant,
|
||||||
|
* drv->ssid needs to be set here to satisfy later checking. */
|
||||||
|
ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid);
|
||||||
|
if (ssid_len > 0) {
|
||||||
|
drv->ssid_len = ssid_len;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Set drv->ssid based on scan res info to '%s'",
|
||||||
|
wpa_ssid_txt(drv->ssid, drv->ssid_len));
|
||||||
|
}
|
||||||
|
|
||||||
nl80211_parse_wmm_params(wmm, &event.assoc_info.wmm_params);
|
nl80211_parse_wmm_params(wmm, &event.assoc_info.wmm_params);
|
||||||
|
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
|
||||||
|
@ -275,8 +286,9 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
|
||||||
struct nlattr *subnet_status)
|
struct nlattr *subnet_status)
|
||||||
{
|
{
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
const u8 *ssid;
|
const u8 *ssid = NULL;
|
||||||
u16 status_code;
|
u16 status_code;
|
||||||
|
int ssid_len;
|
||||||
|
|
||||||
if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
|
if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
|
||||||
/*
|
/*
|
||||||
|
@ -347,6 +359,10 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
|
||||||
if (ssid && ssid[1] > 0 && ssid[1] <= 32) {
|
if (ssid && ssid[1] > 0 && ssid[1] <= 32) {
|
||||||
drv->ssid_len = ssid[1];
|
drv->ssid_len = ssid[1];
|
||||||
os_memcpy(drv->ssid, ssid + 2, ssid[1]);
|
os_memcpy(drv->ssid, ssid + 2, ssid[1]);
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Set drv->ssid based on req_ie to '%s'",
|
||||||
|
wpa_ssid_txt(drv->ssid,
|
||||||
|
drv->ssid_len));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,6 +373,16 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
|
||||||
|
|
||||||
event.assoc_info.freq = nl80211_get_assoc_freq(drv);
|
event.assoc_info.freq = nl80211_get_assoc_freq(drv);
|
||||||
|
|
||||||
|
if ((!ssid || ssid[1] == 0 || ssid[1] > 32) &&
|
||||||
|
(ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid)) > 0) {
|
||||||
|
/* When this connection was initiated outside of wpa_supplicant,
|
||||||
|
* drv->ssid needs to be set here to satisfy later checking. */
|
||||||
|
drv->ssid_len = ssid_len;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Set drv->ssid based on scan res info to '%s'",
|
||||||
|
wpa_ssid_txt(drv->ssid, drv->ssid_len));
|
||||||
|
}
|
||||||
|
|
||||||
if (authorized && nla_get_u8(authorized)) {
|
if (authorized && nla_get_u8(authorized)) {
|
||||||
event.assoc_info.authorized = 1;
|
event.assoc_info.authorized = 1;
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: connection authorized");
|
wpa_printf(MSG_DEBUG, "nl80211: connection authorized");
|
||||||
|
|
Loading…
Add table
Reference in a new issue