]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Use netlink connect socket for disconnect (ext auth)
authorCedric Izoard <Cedric.Izoard@ceva-dsp.com>
Mon, 26 Nov 2018 07:44:02 +0000 (07:44 +0000)
committerJouni Malinen <j@w1.fi>
Mon, 26 Nov 2018 17:24:31 +0000 (19:24 +0200)
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 <cedric.izoard@ceva-dsp.com>
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_scan.c

index b2c4120ebf72e581ad7a921f9537152a455ac049..c808b64aa88f5a09de5c1330d609f95d0bf917e4 100644 (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,
                            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);
        }
 
index 5ac0c7dfc8e856c238cf55e480f6f4b5de6fad10..bc562ba7a8cca8940c4857acd06bfec103cfda2c 100644 (file)
@@ -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);
index 86501f46ecf7067cac08220099a3c8b7bf995c79..33a8d359848fb0dea9a7885af30954b99204fab3 100644 (file)
@@ -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);
        }
 }