From 40a68f33844f3215a9f7d1c64659138567b92b6e Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Thu, 1 Feb 2018 16:52:57 +0530 Subject: [PATCH] nl80211: Create a netlink socket handle for the Connect interface This netlink socket handle owns the connect request and is further used by the host driver/kernel to request for the external authentication. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 73 ++++++++++++++++++++++-------- src/drivers/driver_nl80211.h | 2 +- src/drivers/driver_nl80211_event.c | 6 +-- 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index d6bf12160..dc453ab27 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -130,7 +130,7 @@ static void nl_destroy_handles(struct nl_handle **handle) static void nl80211_register_eloop_read(struct nl_handle **handle, eloop_sock_handler handler, - void *eloop_data) + void *eloop_data, int persist) { #ifdef CONFIG_LIBNL20 /* @@ -151,13 +151,17 @@ static void nl80211_register_eloop_read(struct nl_handle **handle, nl_socket_set_nonblocking(*handle); eloop_register_read_sock(nl_socket_get_fd(*handle), handler, eloop_data, *handle); - *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID); + if (!persist) + *handle = (void *) (((intptr_t) *handle) ^ + ELOOP_SOCKET_INVALID); } -static void nl80211_destroy_eloop_handle(struct nl_handle **handle) +static void nl80211_destroy_eloop_handle(struct nl_handle **handle, int persist) { - *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID); + if (!persist) + *handle = (void *) (((intptr_t) *handle) ^ + ELOOP_SOCKET_INVALID); eloop_unregister_read_sock(nl_socket_get_fd(*handle)); nl_destroy_handles(handle); } @@ -723,7 +727,7 @@ nl80211_get_wiphy_data_ap(struct i802_bss *bss) } nl80211_register_eloop_read(&w->nl_beacons, - nl80211_recv_beacons, w); + nl80211_recv_beacons, w, 0); } dl_list_add(&nl80211_wiphys, &w->list); @@ -772,7 +776,7 @@ static void nl80211_put_wiphy_data_ap(struct i802_bss *bss) return; if (w->nl_beacons) - nl80211_destroy_eloop_handle(&w->nl_beacons); + nl80211_destroy_eloop_handle(&w->nl_beacons, 0); nl_cb_put(w->nl_cb); dl_list_del(&w->list); @@ -1631,7 +1635,7 @@ static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global) nl80211_register_eloop_read(&global->nl_event, wpa_driver_nl80211_event_receive, - global->nl_cb); + global->nl_cb, 0); return 0; @@ -1997,7 +2001,7 @@ static void nl80211_mgmt_handle_register_eloop(struct i802_bss *bss) { nl80211_register_eloop_read(&bss->nl_mgmt, wpa_driver_nl80211_event_receive, - bss->nl_cb); + bss->nl_cb, 0); } @@ -2010,6 +2014,25 @@ static int nl80211_register_action_frame(struct i802_bss *bss, } +static int nl80211_init_connect_handle(struct i802_bss *bss) +{ + if (bss->nl_connect) { + wpa_printf(MSG_DEBUG, + "nl80211: Connect handle already created (nl_connect=%p)", + bss->nl_connect); + return -1; + } + + bss->nl_connect = nl_create_handle(bss->nl_cb, "connect"); + if (!bss->nl_connect) + return -1; + nl80211_register_eloop_read(&bss->nl_connect, + wpa_driver_nl80211_event_receive, + bss->nl_cb, 1); + return 0; +} + + static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) { struct wpa_driver_nl80211_data *drv = bss->drv; @@ -2313,7 +2336,7 @@ static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason) return; wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p " "(%s)", bss->nl_mgmt, reason); - nl80211_destroy_eloop_handle(&bss->nl_mgmt); + nl80211_destroy_eloop_handle(&bss->nl_mgmt, 0); nl80211_put_wiphy_data_ap(bss); } @@ -2529,6 +2552,8 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, if (drv->vendor_cmd_test_avail) qca_vendor_test(drv); + nl80211_init_connect_handle(bss); + return 0; } @@ -2642,6 +2667,9 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) nl80211_del_p2pdev(bss); } + if (bss->nl_connect) + nl80211_destroy_eloop_handle(&bss->nl_connect, 1); + nl80211_destroy_bss(drv->first_bss); os_free(drv->filter_ssids); @@ -5381,7 +5409,8 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, static int wpa_driver_nl80211_try_connect( struct wpa_driver_nl80211_data *drv, - struct wpa_driver_associate_params *params) + struct wpa_driver_associate_params *params, + struct nl_handle *nl_connect) { struct nl_msg *msg; enum nl80211_auth_type type; @@ -5435,7 +5464,11 @@ skip_auth_type: if (ret) goto fail; - 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); + msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " @@ -5454,7 +5487,8 @@ fail: static int wpa_driver_nl80211_connect( struct wpa_driver_nl80211_data *drv, - struct wpa_driver_associate_params *params) + struct wpa_driver_associate_params *params, + struct nl_handle *nl_connect) { int ret; @@ -5464,7 +5498,7 @@ static int wpa_driver_nl80211_connect( else os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN); - ret = wpa_driver_nl80211_try_connect(drv, params); + ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect); if (ret == -EALREADY) { /* * cfg80211 does not currently accept new connections if @@ -5477,7 +5511,7 @@ static int wpa_driver_nl80211_connect( if (wpa_driver_nl80211_disconnect( drv, WLAN_REASON_PREV_AUTH_NOT_VALID)) return -1; - ret = wpa_driver_nl80211_try_connect(drv, params); + ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect); } return ret; } @@ -5502,10 +5536,13 @@ static int wpa_driver_nl80211_associate( if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { enum nl80211_iftype nlmode = params->p2p ? NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION; + struct nl_handle *nl_connect = NULL; if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0) return -1; - return wpa_driver_nl80211_connect(drv, params); + if (params->auth_alg & WPA_AUTH_ALG_SAE) + nl_connect = bss->nl_connect; + return wpa_driver_nl80211_connect(drv, params, nl_connect); } nl80211_mark_disconnected(drv); @@ -7215,7 +7252,7 @@ static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report) } else if (bss->nl_preq) { wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request " "reporting nl_preq=%p", bss->nl_preq); - nl80211_destroy_eloop_handle(&bss->nl_preq); + nl80211_destroy_eloop_handle(&bss->nl_preq, 0); } return 0; } @@ -7240,7 +7277,7 @@ static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report) nl80211_register_eloop_read(&bss->nl_preq, wpa_driver_nl80211_event_receive, - bss->nl_cb); + bss->nl_cb, 0); return 0; @@ -7555,7 +7592,7 @@ static void nl80211_global_deinit(void *priv) nl_destroy_handles(&global->nl); if (global->nl_event) - nl80211_destroy_eloop_handle(&global->nl_event); + nl80211_destroy_eloop_handle(&global->nl_event, 0); nl_cb_put(global->nl_cb); diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 23cf9dbeb..4bdeaa066 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -73,7 +73,7 @@ struct i802_bss { int if_dynamic; void *ctx; - struct nl_handle *nl_preq, *nl_mgmt; + struct nl_handle *nl_preq, *nl_mgmt, *nl_connect; struct nl_cb *nl_cb; struct nl80211_wiphy_data *wiphy_data; diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 5591cebe8..66a3667fe 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -2418,9 +2418,6 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, case NL80211_CMD_NEW_PEER_CANDIDATE: nl80211_new_peer_candidate(drv, tb); break; - case NL80211_CMD_EXTERNAL_AUTH: - nl80211_external_auth(drv, tb); - break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", cmd); @@ -2506,6 +2503,9 @@ int process_bss_event(struct nl_msg *msg, void *arg) case NL80211_CMD_UNEXPECTED_4ADDR_FRAME: nl80211_spurious_frame(bss, tb, 1); break; + case NL80211_CMD_EXTERNAL_AUTH: + nl80211_external_auth(bss->drv, tb); + break; default: wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", gnlh->cmd);