From 10d32e2c8d96b9277dc18d3c1503ee382e16988c Mon Sep 17 00:00:00 2001 From: Cedric Izoard Date: Mon, 26 Nov 2018 07:44:02 +0000 Subject: [PATCH] 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 40a68f33844f ("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 --- src/drivers/driver_nl80211.c | 34 +++++++++++++++++++++++-------- src/drivers/driver_nl80211.h | 4 +++- src/drivers/driver_nl80211_scan.c | 3 ++- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index b2c4120eb..c808b64aa 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -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, const u8 *addr, int cmd, u16 reason_code, - int local_state_change) + int local_state_change, + struct nl_handle *nl_connect) { int ret; struct nl_msg *msg; @@ -3179,7 +3180,10 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, 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) { wpa_dbg(drv->ctx, MSG_DEBUG, "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, - int reason_code) + int reason_code, + struct nl_handle *nl_connect) { int ret; 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); /* Disconnect command doesn't need BSSID - it uses cached value */ 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 * 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); return nl80211_leave_ibss(drv, 1); } - if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) - return wpa_driver_nl80211_disconnect(drv, reason_code); + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { + 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)", __func__, MAC2STR(addr), reason_code); nl80211_mark_disconnected(drv); 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 * DEAUTH event, so ignore the event from NL80211. @@ -5642,7 +5653,7 @@ static int wpa_driver_nl80211_connect( "disconnecting before reassociation " "attempt"); if (wpa_driver_nl80211_disconnect( - drv, WLAN_REASON_PREV_AUTH_NOT_VALID)) + drv, WLAN_REASON_PREV_AUTH_NOT_VALID, nl_connect)) return -1; 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) return -1; - if (params->auth_alg & WPA_AUTH_ALG_SAE) + if (params->auth_alg & WPA_AUTH_ALG_SAE) { 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); } diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 5ac0c7dfc..bc562ba7a 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -66,6 +66,7 @@ struct i802_bss { unsigned int wdev_id_set:1; unsigned int added_if:1; unsigned int static_ap:1; + unsigned int use_nl_connect:1; u8 addr[ETH_ALEN]; @@ -252,7 +253,8 @@ int wpa_driver_nl80211_set_mode(struct i802_bss *bss, enum nl80211_iftype nlmode); int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, 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); void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv); diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index 86501f46e..33a8d3598 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -866,7 +866,8 @@ static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv, "mismatch (" MACSTR ")", MAC2STR(addr)); wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, - WLAN_REASON_PREV_AUTH_NOT_VALID, 1); + WLAN_REASON_PREV_AUTH_NOT_VALID, 1, + NULL); } }