]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Use two sockets to avoid mixing command replies with events
authorJouni Malinen <jouni.malinen@atheros.com>
Wed, 26 Aug 2009 09:10:50 +0000 (12:10 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 26 Aug 2009 09:10:50 +0000 (12:10 +0300)
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

index 9b2bf7ca25bf88989210bdbde3e2fda7a225a424..f8f6c765d9b9d21ce5caadebb32f233af9906149 100644 (file)
@@ -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);