nl80211: Use netlink connect socket for disconnect (ext auth)

When external authentication is used, a specific netlink socket is used
to send the connect command. If the same socket is not used for
disconnect command, cfg80211 will discard the command. This constraint
was added into the kernel in commit bad292973363 ("nl80211: Reject
disconnect commands except from conn_owner"). That requires an update
for the hostap.git commit 40a68f3384 ("nl80211: Create a netlink
socket handle for the Connect interface").

Add a new flag into struct i802_bss to indicate if the special
nl_connect socket was used for the connect command. When sending
disconnect command this flag is tested to select the correct socket.

Signed-off-by: Cedric Izoard <cedric.izoard@ceva-dsp.com>
This commit is contained in:
Cedric Izoard 2018-11-26 07:44:02 +00:00 committed by Jouni Malinen
parent 18a0508a41
commit 10d32e2c8d
3 changed files with 30 additions and 11 deletions

View file

@ -3165,7 +3165,8 @@ static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
const u8 *addr, int cmd, u16 reason_code, const u8 *addr, int cmd, u16 reason_code,
int local_state_change) int local_state_change,
struct nl_handle *nl_connect)
{ {
int ret; int ret;
struct nl_msg *msg; struct nl_msg *msg;
@ -3179,7 +3180,10 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
return -1; return -1;
} }
ret = send_and_recv_msgs(drv, msg, NULL, NULL); if (nl_connect)
ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL);
else
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret) { if (ret) {
wpa_dbg(drv->ctx, MSG_DEBUG, wpa_dbg(drv->ctx, MSG_DEBUG,
"nl80211: MLME command failed: reason=%u ret=%d (%s)", "nl80211: MLME command failed: reason=%u ret=%d (%s)",
@ -3190,7 +3194,8 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
int reason_code) int reason_code,
struct nl_handle *nl_connect)
{ {
int ret; int ret;
int drv_associated = drv->associated; int drv_associated = drv->associated;
@ -3199,7 +3204,7 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
nl80211_mark_disconnected(drv); nl80211_mark_disconnected(drv);
/* Disconnect command doesn't need BSSID - it uses cached value */ /* Disconnect command doesn't need BSSID - it uses cached value */
ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT, ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
reason_code, 0); reason_code, 0, nl_connect);
/* /*
* For locally generated disconnect, supplicant already generates a * For locally generated disconnect, supplicant already generates a
* DEAUTH event, so ignore the event from NL80211. * DEAUTH event, so ignore the event from NL80211.
@ -3221,13 +3226,19 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
nl80211_mark_disconnected(drv); nl80211_mark_disconnected(drv);
return nl80211_leave_ibss(drv, 1); return nl80211_leave_ibss(drv, 1);
} }
if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
return wpa_driver_nl80211_disconnect(drv, reason_code); struct nl_handle *nl_connect = NULL;
if (bss->use_nl_connect)
nl_connect = bss->nl_connect;
return wpa_driver_nl80211_disconnect(drv, reason_code,
nl_connect);
}
wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)", wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
__func__, MAC2STR(addr), reason_code); __func__, MAC2STR(addr), reason_code);
nl80211_mark_disconnected(drv); nl80211_mark_disconnected(drv);
ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
reason_code, 0); reason_code, 0, NULL);
/* /*
* For locally generated deauthenticate, supplicant already generates a * For locally generated deauthenticate, supplicant already generates a
* DEAUTH event, so ignore the event from NL80211. * DEAUTH event, so ignore the event from NL80211.
@ -5642,7 +5653,7 @@ static int wpa_driver_nl80211_connect(
"disconnecting before reassociation " "disconnecting before reassociation "
"attempt"); "attempt");
if (wpa_driver_nl80211_disconnect( if (wpa_driver_nl80211_disconnect(
drv, WLAN_REASON_PREV_AUTH_NOT_VALID)) drv, WLAN_REASON_PREV_AUTH_NOT_VALID, nl_connect))
return -1; return -1;
ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect); ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect);
} }
@ -5673,8 +5684,13 @@ static int wpa_driver_nl80211_associate(
if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0) if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
return -1; return -1;
if (params->auth_alg & WPA_AUTH_ALG_SAE) if (params->auth_alg & WPA_AUTH_ALG_SAE) {
nl_connect = bss->nl_connect; nl_connect = bss->nl_connect;
bss->use_nl_connect = 1;
} else {
bss->use_nl_connect = 0;
}
return wpa_driver_nl80211_connect(drv, params, nl_connect); return wpa_driver_nl80211_connect(drv, params, nl_connect);
} }

View file

@ -66,6 +66,7 @@ struct i802_bss {
unsigned int wdev_id_set:1; unsigned int wdev_id_set:1;
unsigned int added_if:1; unsigned int added_if:1;
unsigned int static_ap:1; unsigned int static_ap:1;
unsigned int use_nl_connect:1;
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
@ -252,7 +253,8 @@ int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
enum nl80211_iftype nlmode); enum nl80211_iftype nlmode);
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
const u8 *addr, int cmd, u16 reason_code, const u8 *addr, int cmd, u16 reason_code,
int local_state_change); int local_state_change,
struct nl_handle *nl_connect);
int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv); int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv);
void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv); void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv);

View file

@ -866,7 +866,8 @@ static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
"mismatch (" MACSTR ")", MAC2STR(addr)); "mismatch (" MACSTR ")", MAC2STR(addr));
wpa_driver_nl80211_mlme(drv, addr, wpa_driver_nl80211_mlme(drv, addr,
NL80211_CMD_DEAUTHENTICATE, NL80211_CMD_DEAUTHENTICATE,
WLAN_REASON_PREV_AUTH_NOT_VALID, 1); WLAN_REASON_PREV_AUTH_NOT_VALID, 1,
NULL);
} }
} }