nl80211: Use one global ioctl socket

Saves sockets when using multiple VIFS in a single
wpa_supplicant process.

Signed-off-by: Ben Greear <greearb@candelatech.com>
This commit is contained in:
Ben Greear 2011-10-22 21:33:58 +03:00 committed by Jouni Malinen
parent 276e2d671c
commit c81eff1a61

View file

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