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 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);
}