]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Use one global ioctl socket
authorBen Greear <greearb@candelatech.com>
Sat, 22 Oct 2011 18:33:58 +0000 (21:33 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 22 Oct 2011 18:39:42 +0000 (21:39 +0300)
Saves sockets when using multiple VIFS in a single
wpa_supplicant process.

Signed-off-by: Ben Greear <greearb@candelatech.com>
src/drivers/driver_nl80211.c

index db8f5ebd2bfef0c6f25b2f2da59990f69b43ccb7..cdb015b7440079fc68667c556eb6b55ef70639d0 100644 (file)
@@ -171,6 +171,7 @@ struct nl80211_global {
        struct nl_cb *nl_cb;
        struct nl80211_handles nl;
        struct genl_family *nl80211;
+       int ioctl_sock; /* socket for ioctl() use */
 };
 
 static void nl80211_global_deinit(void *priv);
@@ -193,7 +194,6 @@ struct wpa_driver_nl80211_data {
        u8 addr[ETH_ALEN];
        char phyname[32];
        void *ctx;
-       int ioctl_sock; /* socket for ioctl() use */
        int ifindex;
        int if_removed;
        int if_disabled;
@@ -2105,7 +2105,8 @@ static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
 {
        struct wpa_driver_nl80211_data *drv = ctx;
        wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
-       if (linux_set_iface_flags(drv->ioctl_sock, drv->first_bss.ifname, 1)) {
+       if (linux_set_iface_flags(drv->global->ioctl_sock,
+                                 drv->first_bss.ifname, 1)) {
                wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
                           "after rfkill unblock");
                return;
@@ -2182,7 +2183,6 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
        os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
        drv->monitor_ifidx = -1;
        drv->monitor_sock = -1;
-       drv->ioctl_sock = -1;
        drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 
        if (wpa_driver_nl80211_init_nl(drv)) {
@@ -2192,12 +2192,6 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
 
        nl80211_get_phy_name(drv);
 
-       drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
-       if (drv->ioctl_sock < 0) {
-               perror("socket(PF_INET,SOCK_DGRAM)");
-               goto failed;
-       }
-
        rcfg = os_zalloc(sizeof(*rcfg));
        if (rcfg == NULL)
                goto failed;
@@ -2353,7 +2347,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
                return -1;
        }
 
-       if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
+       if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
                if (rfkill_is_blocked(drv->rfkill)) {
                        wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
                                   "interface '%s' due to rfkill",
@@ -2374,7 +2368,8 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
        if (wpa_driver_nl80211_capa(drv))
                return -1;
 
-       if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, drv->addr))
+       if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+                              drv->addr))
                return -1;
 
        if (nl80211_register_action_frames(drv) < 0) {
@@ -2433,14 +2428,14 @@ static void wpa_driver_nl80211_deinit(void *priv)
        if (drv->nl_preq.handle)
                wpa_driver_nl80211_probe_req_report(bss, 0);
        if (bss->added_if_into_bridge) {
-               if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname)
-                   < 0)
+               if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
+                                   bss->ifname) < 0)
                        wpa_printf(MSG_INFO, "nl80211: Failed to remove "
                                   "interface %s from bridge %s: %s",
                                   bss->ifname, bss->brname, strerror(errno));
        }
        if (bss->added_bridge) {
-               if (linux_br_del(drv->ioctl_sock, bss->brname) < 0)
+               if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
                        wpa_printf(MSG_INFO, "nl80211: Failed to remove "
                                   "bridge %s: %s",
                                   bss->brname, strerror(errno));
@@ -2478,12 +2473,9 @@ static void wpa_driver_nl80211_deinit(void *priv)
 
        eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
 
-       (void) linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0);
+       (void) linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
        wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION);
 
-       if (drv->ioctl_sock >= 0)
-               close(drv->ioctl_sock);
-
        eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_event.handle));
        nl_destroy_handles(&drv->nl_event);
 
@@ -4586,7 +4578,7 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
 #endif /* HOSTAPD */
 
        if (addr && iftype != NL80211_IFTYPE_MONITOR &&
-           linux_set_ifhwaddr(drv->ioctl_sock, ifname, addr)) {
+           linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
                nl80211_remove_iface(drv, ifidx);
                return -1;
        }
@@ -4964,7 +4956,7 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
        if (drv->monitor_ifidx < 0)
                return -1;
 
-       if (linux_set_iface_flags(drv->ioctl_sock, buf, 1))
+       if (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1))
                goto error;
 
        memset(&ll, 0, sizeof(ll));
@@ -5700,7 +5692,8 @@ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
                   "interface down");
        for (i = 0; i < 10; i++) {
                int res;
-               res = linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0);
+               res = linux_set_iface_flags(drv->global->ioctl_sock,
+                                           bss->ifname, 0);
                if (res == -EACCES || res == -ENODEV)
                        break;
                if (res == 0) {
@@ -5709,7 +5702,7 @@ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
                        ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
                        if (ret == -EACCES)
                                break;
-                       res = linux_set_iface_flags(drv->ioctl_sock,
+                       res = linux_set_iface_flags(drv->global->ioctl_sock,
                                                    bss->ifname, 1);
                        if (res && !ret)
                                ret = -1;
@@ -6293,11 +6286,11 @@ static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
                                                 NULL, 1) < 0)
                                return -1;
                        if (bridge_ifname &&
-                           linux_br_add_if(drv->ioctl_sock, bridge_ifname,
-                                           name) < 0)
+                           linux_br_add_if(drv->global->ioctl_sock,
+                                           bridge_ifname, name) < 0)
                                return -1;
                }
-               linux_set_iface_flags(drv->ioctl_sock, name, 1);
+               linux_set_iface_flags(drv->global->ioctl_sock, name, 1);
                return i802_set_sta_vlan(priv, addr, name, 0);
        } else {
                i802_set_sta_vlan(priv, addr, bss->ifname, 0);
@@ -6341,7 +6334,7 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
                 * Bridge was configured, but the bridge device does
                 * not exist. Try to add it now.
                 */
-               if (linux_br_add(drv->ioctl_sock, brname) < 0) {
+               if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
                        wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
                                   "bridge interface %s: %s",
                                   brname, strerror(errno));
@@ -6357,7 +6350,8 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
 
                wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
                           "bridge %s", ifname, in_br);
-               if (linux_br_del_if(drv->ioctl_sock, in_br, ifname) < 0) {
+               if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
+                   0) {
                        wpa_printf(MSG_ERROR, "nl80211: Failed to "
                                   "remove interface %s from bridge "
                                   "%s: %s",
@@ -6368,7 +6362,7 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
 
        wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
                   ifname, brname);
-       if (linux_br_add_if(drv->ioctl_sock, brname, ifname) < 0) {
+       if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
                wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
                           "into bridge %s: %s",
                           ifname, brname, strerror(errno));
@@ -6426,11 +6420,11 @@ static void *i802_init(struct hostapd_data *hapd,
        /* start listening for EAPOL on the default AP interface */
        add_ifidx(drv, drv->ifindex);
 
-       if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0))
+       if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0))
                goto failed;
 
        if (params->bssid) {
-               if (linux_set_ifhwaddr(drv->ioctl_sock, bss->ifname,
+               if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
                                       params->bssid))
                        goto failed;
        }
@@ -6445,7 +6439,7 @@ static void *i802_init(struct hostapd_data *hapd,
            i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)
                goto failed;
 
-       if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1))
+       if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1))
                goto failed;
 
        drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
@@ -6460,7 +6454,8 @@ static void *i802_init(struct hostapd_data *hapd,
                goto failed;
        }
 
-       if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, params->own_addr))
+       if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+                              params->own_addr))
                goto failed;
 
        return bss;
@@ -6572,7 +6567,8 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
        }
 
        if (!addr &&
-           linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, if_addr) < 0) {
+           linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+                              if_addr) < 0) {
                nl80211_remove_iface(drv, ifidx);
                return -1;
        }
@@ -6584,10 +6580,10 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
                /* Enforce unique P2P Interface Address */
                u8 new_addr[ETH_ALEN], own_addr[ETH_ALEN];
 
-               if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr)
-                   < 0 ||
-                   linux_get_ifhwaddr(drv->ioctl_sock, ifname, new_addr) < 0)
-               {
+               if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+                                      own_addr) < 0 ||
+                   linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
+                                      new_addr) < 0) {
                        nl80211_remove_iface(drv, ifidx);
                        return -1;
                }
@@ -6598,7 +6594,7 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
                                nl80211_remove_iface(drv, ifidx);
                                return -1;
                        }
-                       if (linux_set_ifhwaddr(drv->ioctl_sock, ifname,
+                       if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
                                               new_addr) < 0) {
                                nl80211_remove_iface(drv, ifidx);
                                return -1;
@@ -6619,7 +6615,8 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
        }
 
        if (type == WPA_IF_AP_BSS) {
-               if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) {
+               if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
+               {
                        nl80211_remove_iface(drv, ifidx);
                        os_free(new_bss);
                        return -1;
@@ -6656,14 +6653,14 @@ static int wpa_driver_nl80211_if_remove(void *priv,
 
 #ifdef HOSTAPD
        if (bss->added_if_into_bridge) {
-               if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname)
-                   < 0)
+               if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
+                                   bss->ifname) < 0)
                        wpa_printf(MSG_INFO, "nl80211: Failed to remove "
                                   "interface %s from bridge %s: %s",
                                   bss->ifname, bss->brname, strerror(errno));
        }
        if (bss->added_bridge) {
-               if (linux_br_del(drv->ioctl_sock, bss->brname) < 0)
+               if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
                        wpa_printf(MSG_INFO, "nl80211: Failed to remove "
                                   "bridge %s: %s",
                                   bss->brname, strerror(errno));
@@ -7003,7 +7000,7 @@ static void wpa_driver_nl80211_resume(void *priv)
 {
        struct i802_bss *bss = priv;
        struct wpa_driver_nl80211_data *drv = bss->drv;
-       if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
+       if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
                wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on "
                           "resume event");
        }
@@ -7020,7 +7017,8 @@ static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
        size_t data_len;
        u8 own_addr[ETH_ALEN];
 
-       if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr) < 0)
+       if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+                              own_addr) < 0)
                return -1;
 
        if (action != 1) {
@@ -7151,6 +7149,7 @@ static void * nl80211_global_init(void)
        global = os_zalloc(sizeof(*global));
        if (global == NULL)
                return NULL;
+       global->ioctl_sock = -1;
        dl_list_init(&global->interfaces);
        global->if_add_ifindex = -1;
 
@@ -7170,6 +7169,12 @@ static void * nl80211_global_init(void)
        if (wpa_driver_nl80211_init_nl_global(global) < 0)
                goto err;
 
+       global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
+       if (global->ioctl_sock < 0) {
+               perror("socket(PF_INET,SOCK_DGRAM)");
+               goto err;
+       }
+
        return global;
 
 err:
@@ -7199,6 +7204,9 @@ static void nl80211_global_deinit(void *priv)
        if (global->nl_cb)
                nl_cb_put(global->nl_cb);
 
+       if (global->ioctl_sock >= 0)
+               close(global->ioctl_sock);
+
        os_free(global);
 }