From eb51f1ff9341ce480c9a5c8451420ead0ae9a654 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Tue, 1 Feb 2011 16:38:07 -0800 Subject: [PATCH 12/16] nl80211: Use one global ioctl socket. Saves lots of sockets when using multiple VIFS in a single wpa_supplicant instance. Signed-off-by: Ben Greear --- :100644 100644 fa35106... ba32f88... M src/drivers/driver_nl80211.c src/drivers/driver_nl80211.c | 94 ++++++++++++++++++++++-------------------- 1 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index fa35106..ba32f88 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -128,7 +128,7 @@ struct nl80211_global { struct nl_cache *nl_cache_preq; struct nl_cb *nl_cb; struct genl_family *nl80211; - + int ioctl_sock; /* socket for ioctl() use */ }; static struct nl80211_global* global_ptr = NULL; @@ -153,7 +153,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; @@ -1692,7 +1691,8 @@ static void wpa_driver_nl80211_rfkill_unblocked(void *ctx) { struct wpa_driver_nl80211_data *drv = ctx; wpa_msg(drv->ctx, 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_msg(drv->ctx, MSG_DEBUG, "nl80211: Could not set interface UP " "after rfkill unblock"); return; @@ -1768,14 +1768,14 @@ static void wpa_driver_nl80211_deinit(void *priv) 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) + if (linux_br_del_if(drv->global->ioctl_sock, bss->brname, bss->ifname) < 0) wpa_msg(drv->ctx, 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_msg(drv->ctx, MSG_INFO, "nl80211: Failed to remove " "bridge %s: %s", bss->brname, strerror(errno)); @@ -1813,12 +1813,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); + linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0); wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - os_free(drv->filter_ssids); if (drv->global) @@ -1857,16 +1854,9 @@ 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; 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; @@ -1999,7 +1989,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) "use managed mode"); } - 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_msg(drv->ctx, MSG_DEBUG, "nl80211: Could not yet enable " "interface '%s' due to rfkill", @@ -2020,7 +2010,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) 1, IF_OPER_DORMANT); #endif /* HOSTAPD */ - 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) { @@ -3729,7 +3719,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; } @@ -4079,7 +4069,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)); @@ -4742,13 +4732,13 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode) wpa_msg(drv->ctx, MSG_DEBUG, "nl80211: Try mode change after setting " "interface down"); for (i = 0; i < 10; i++) { - if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0) == - 0) { + if (linux_set_iface_flags(drv->global->ioctl_sock, + bss->ifname, 0) == 0) { /* Try to set the mode again while the interface is * down */ ret = nl80211_set_mode(drv, drv->ifindex, nlmode); - if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, - 1)) + if (linux_set_iface_flags(drv->global->ioctl_sock, + bss->ifname, 1)) ret = -1; if (!ret) break; @@ -5324,11 +5314,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); @@ -5451,7 +5441,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_msg(drv->ctx, MSG_ERROR, "nl80211: Failed to add the " "bridge interface %s: %s", brname, strerror(errno)); @@ -5467,7 +5457,8 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv, wpa_msg(drv->ctx, 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_msg(drv->ctx, MSG_ERROR, "nl80211: Failed to " "remove interface %s from bridge " "%s: %s", @@ -5478,7 +5469,7 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv, wpa_msg(drv->ctx, 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_msg(drv->ctx, MSG_ERROR, "nl80211: Failed to add interface %s " "into bridge %s: %s", ifname, brname, strerror(errno)); @@ -5535,11 +5526,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; } @@ -5554,7 +5545,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)); @@ -5569,7 +5560,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; @@ -5681,7 +5673,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; } @@ -5693,10 +5686,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; } @@ -5707,7 +5700,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; @@ -5728,7 +5721,7 @@ 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; @@ -5762,14 +5755,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) + 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)); @@ -6170,7 +6163,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_msg(drv->ctx, MSG_DEBUG, "nl80211: Failed to set interface up on " "resume event"); } @@ -6187,7 +6180,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) { @@ -6346,6 +6340,9 @@ static void nl80211_global_deinit(void *priv) if (global->nl80211) genl_family_put(global->nl80211); + if (global->ioctl_sock >= 0) + close(global->ioctl_sock); + if (global == global_ptr) global_ptr = NULL; @@ -6367,6 +6364,7 @@ static void * nl80211_global_init(void) if (global == NULL) return NULL; global->struct_id = HAP_DRV_NL80211_GLOBAL; + global->ioctl_sock = -1; dl_list_init(&global->interfaces); cfg = os_zalloc(sizeof(*cfg)); @@ -6479,6 +6477,12 @@ static void * nl80211_global_init(void) /* Continue without regulatory events */ } + global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); + if (global->ioctl_sock < 0) { + perror("socket(PF_INET,SOCK_DGRAM)"); + goto err; + } + eloop_register_read_sock(nl_socket_get_fd(global->nl_handle_event), wpa_driver_nl80211_event_receive, global, global->nl_handle_event); -- 1.6.2.5