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 <jouni@codeaurora.org>
This commit is contained in:
Sunil Dutt 2018-02-01 16:52:57 +05:30 committed by Jouni Malinen
parent ba71cb821a
commit 40a68f3384
3 changed files with 59 additions and 22 deletions

View file

@ -130,7 +130,7 @@ static void nl_destroy_handles(struct nl_handle **handle)
static void nl80211_register_eloop_read(struct nl_handle **handle, static void nl80211_register_eloop_read(struct nl_handle **handle,
eloop_sock_handler handler, eloop_sock_handler handler,
void *eloop_data) void *eloop_data, int persist)
{ {
#ifdef CONFIG_LIBNL20 #ifdef CONFIG_LIBNL20
/* /*
@ -151,13 +151,17 @@ static void nl80211_register_eloop_read(struct nl_handle **handle,
nl_socket_set_nonblocking(*handle); nl_socket_set_nonblocking(*handle);
eloop_register_read_sock(nl_socket_get_fd(*handle), handler, eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
eloop_data, *handle); 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)); eloop_unregister_read_sock(nl_socket_get_fd(*handle));
nl_destroy_handles(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_register_eloop_read(&w->nl_beacons,
nl80211_recv_beacons, w); nl80211_recv_beacons, w, 0);
} }
dl_list_add(&nl80211_wiphys, &w->list); dl_list_add(&nl80211_wiphys, &w->list);
@ -772,7 +776,7 @@ static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
return; return;
if (w->nl_beacons) 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); nl_cb_put(w->nl_cb);
dl_list_del(&w->list); 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, nl80211_register_eloop_read(&global->nl_event,
wpa_driver_nl80211_event_receive, wpa_driver_nl80211_event_receive,
global->nl_cb); global->nl_cb, 0);
return 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, nl80211_register_eloop_read(&bss->nl_mgmt,
wpa_driver_nl80211_event_receive, 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) static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
{ {
struct wpa_driver_nl80211_data *drv = bss->drv; 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; return;
wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p " wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
"(%s)", bss->nl_mgmt, reason); "(%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); 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) if (drv->vendor_cmd_test_avail)
qca_vendor_test(drv); qca_vendor_test(drv);
nl80211_init_connect_handle(bss);
return 0; return 0;
} }
@ -2642,6 +2667,9 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
nl80211_del_p2pdev(bss); nl80211_del_p2pdev(bss);
} }
if (bss->nl_connect)
nl80211_destroy_eloop_handle(&bss->nl_connect, 1);
nl80211_destroy_bss(drv->first_bss); nl80211_destroy_bss(drv->first_bss);
os_free(drv->filter_ssids); 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( static int wpa_driver_nl80211_try_connect(
struct wpa_driver_nl80211_data *drv, 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; struct nl_msg *msg;
enum nl80211_auth_type type; enum nl80211_auth_type type;
@ -5435,7 +5464,11 @@ skip_auth_type:
if (ret) if (ret)
goto fail; 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; msg = NULL;
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
@ -5454,7 +5487,8 @@ fail:
static int wpa_driver_nl80211_connect( static int wpa_driver_nl80211_connect(
struct wpa_driver_nl80211_data *drv, 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; int ret;
@ -5464,7 +5498,7 @@ static int wpa_driver_nl80211_connect(
else else
os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN); 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) { if (ret == -EALREADY) {
/* /*
* cfg80211 does not currently accept new connections if * cfg80211 does not currently accept new connections if
@ -5477,7 +5511,7 @@ static int wpa_driver_nl80211_connect(
if (wpa_driver_nl80211_disconnect( if (wpa_driver_nl80211_disconnect(
drv, WLAN_REASON_PREV_AUTH_NOT_VALID)) drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
return -1; return -1;
ret = wpa_driver_nl80211_try_connect(drv, params); ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect);
} }
return ret; return ret;
} }
@ -5502,10 +5536,13 @@ static int wpa_driver_nl80211_associate(
if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
enum nl80211_iftype nlmode = params->p2p ? enum nl80211_iftype nlmode = params->p2p ?
NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION; NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
struct nl_handle *nl_connect = NULL;
if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0) if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
return -1; 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); 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) { } else if (bss->nl_preq) {
wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request " wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
"reporting nl_preq=%p", bss->nl_preq); "reporting nl_preq=%p", bss->nl_preq);
nl80211_destroy_eloop_handle(&bss->nl_preq); nl80211_destroy_eloop_handle(&bss->nl_preq, 0);
} }
return 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, nl80211_register_eloop_read(&bss->nl_preq,
wpa_driver_nl80211_event_receive, wpa_driver_nl80211_event_receive,
bss->nl_cb); bss->nl_cb, 0);
return 0; return 0;
@ -7555,7 +7592,7 @@ static void nl80211_global_deinit(void *priv)
nl_destroy_handles(&global->nl); nl_destroy_handles(&global->nl);
if (global->nl_event) 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); nl_cb_put(global->nl_cb);

View file

@ -73,7 +73,7 @@ struct i802_bss {
int if_dynamic; int if_dynamic;
void *ctx; void *ctx;
struct nl_handle *nl_preq, *nl_mgmt; struct nl_handle *nl_preq, *nl_mgmt, *nl_connect;
struct nl_cb *nl_cb; struct nl_cb *nl_cb;
struct nl80211_wiphy_data *wiphy_data; struct nl80211_wiphy_data *wiphy_data;

View file

@ -2418,9 +2418,6 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_NEW_PEER_CANDIDATE: case NL80211_CMD_NEW_PEER_CANDIDATE:
nl80211_new_peer_candidate(drv, tb); nl80211_new_peer_candidate(drv, tb);
break; break;
case NL80211_CMD_EXTERNAL_AUTH:
nl80211_external_auth(drv, tb);
break;
default: default:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", cmd); "(cmd=%d)", cmd);
@ -2506,6 +2503,9 @@ int process_bss_event(struct nl_msg *msg, void *arg)
case NL80211_CMD_UNEXPECTED_4ADDR_FRAME: case NL80211_CMD_UNEXPECTED_4ADDR_FRAME:
nl80211_spurious_frame(bss, tb, 1); nl80211_spurious_frame(bss, tb, 1);
break; break;
case NL80211_CMD_EXTERNAL_AUTH:
nl80211_external_auth(bss->drv, tb);
break;
default: default:
wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event " wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", gnlh->cmd); "(cmd=%d)", gnlh->cmd);