From 335ce76b1c6761779827d24e7f07672dacdb4872 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 26 Aug 2009 12:10:50 +0300 Subject: [PATCH] nl80211: Use two sockets to avoid mixing command replies with events Previously, both the command replies and unsolicited events were received from the same socket. This could cause problems if an event message is received between a command and the response to that command. Using two sockets avoids this issue. --- src/drivers/driver_nl80211.c | 44 +++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 9b2bf7ca2..f8f6c765d 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -90,7 +90,9 @@ struct wpa_driver_nl80211_data { int scan_complete_events; struct nl_handle *nl_handle; + struct nl_handle *nl_handle_event; struct nl_cache *nl_cache; + struct nl_cache *nl_cache_event; struct nl_cb *nl_cb; struct genl_family *nl80211; @@ -922,7 +924,7 @@ static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx, return; nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv); - nl_recvmsgs(drv->nl_handle, cb); + nl_recvmsgs(drv->nl_handle_event, cb); nl_cb_put(cb); } @@ -1103,18 +1105,37 @@ static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv, goto err2; } + drv->nl_handle_event = nl_handle_alloc_cb(drv->nl_cb); + if (drv->nl_handle_event == NULL) { + wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " + "callbacks (event)"); + goto err2b; + } + if (genl_connect(drv->nl_handle)) { wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " "netlink"); goto err3; } + if (genl_connect(drv->nl_handle_event)) { + wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " + "netlink (event)"); + goto err3; + } + #ifdef CONFIG_LIBNL20 if (genl_ctrl_alloc_cache(drv->nl_handle, &drv->nl_cache) < 0) { wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " "netlink cache"); goto err3; } + if (genl_ctrl_alloc_cache(drv->nl_handle_event, &drv->nl_cache_event) < + 0) { + wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " + "netlink cache (event)"); + goto err3b; + } #else /* CONFIG_LIBNL20 */ drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle); if (drv->nl_cache == NULL) { @@ -1122,9 +1143,14 @@ static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv, "netlink cache"); goto err3; } + drv->nl_cache_event = genl_ctrl_alloc_cache(drv->nl_handle_event); + if (drv->nl_cache_event == NULL) { + wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " + "netlink cache (event)"); + goto err3b; + } #endif /* CONFIG_LIBNL20 */ - drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211"); if (drv->nl80211 == NULL) { wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not " @@ -1134,7 +1160,7 @@ static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv, ret = nl_get_multicast_id(drv, "nl80211", "scan"); if (ret >= 0) - ret = nl_socket_add_membership(drv->nl_handle, ret); + ret = nl_socket_add_membership(drv->nl_handle_event, ret); if (ret < 0) { wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " "membership for scan events: %d (%s)", @@ -1144,7 +1170,7 @@ static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv, ret = nl_get_multicast_id(drv, "nl80211", "mlme"); if (ret >= 0) - ret = nl_socket_add_membership(drv->nl_handle, ret); + ret = nl_socket_add_membership(drv->nl_handle_event, ret); if (ret < 0) { wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " "membership for mlme events: %d (%s)", @@ -1152,14 +1178,18 @@ static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv, goto err4; } - eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle), + eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event), wpa_driver_nl80211_event_receive, drv, ctx); return 0; err4: + nl_cache_free(drv->nl_cache_event); +err3b: nl_cache_free(drv->nl_cache); err3: + nl_handle_destroy(drv->nl_handle_event); +err2b: nl_handle_destroy(drv->nl_handle); err2: nl_cb_put(drv->nl_cb); @@ -1380,10 +1410,12 @@ static void wpa_driver_nl80211_deinit(void *priv) if (drv->ioctl_sock >= 0) close(drv->ioctl_sock); - eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle)); + eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event)); genl_family_put(drv->nl80211); nl_cache_free(drv->nl_cache); + nl_cache_free(drv->nl_cache_event); nl_handle_destroy(drv->nl_handle); + nl_handle_destroy(drv->nl_handle_event); nl_cb_put(drv->nl_cb); os_free(drv);