Abstract and Android sockets for global ctrl_iface

The wpa_supplicant global control interface parameter can now be used to
explicitly specify an abstract UNIX domain socket (Linux specific
extension) with "@abstract:" prefix and an Android control socket with
"@android:" prefix.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2013-05-18 11:42:09 +03:00
parent 6fd5ceaf70
commit d2a9e2c76d
2 changed files with 88 additions and 26 deletions

View file

@ -82,6 +82,9 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
int tries = 0; int tries = 0;
int flags; int flags;
if (ctrl_path == NULL)
return NULL;
ctrl = os_malloc(sizeof(*ctrl)); ctrl = os_malloc(sizeof(*ctrl));
if (ctrl == NULL) if (ctrl == NULL)
return NULL; return NULL;
@ -126,13 +129,27 @@ try_again:
#ifdef ANDROID #ifdef ANDROID
chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI); chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
if (os_strncmp(ctrl_path, "@android:", 9) == 0) {
if (socket_local_client_connect(
ctrl->s, ctrl_path + 9,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_DGRAM) < 0) {
close(ctrl->s);
unlink(ctrl->local.sun_path);
os_free(ctrl);
return NULL;
}
return ctrl;
}
/* /*
* If the ctrl_path isn't an absolute pathname, assume that * If the ctrl_path isn't an absolute pathname, assume that
* it's the name of a socket in the Android reserved namespace. * it's the name of a socket in the Android reserved namespace.
* Otherwise, it's a normal UNIX domain socket appearing in the * Otherwise, it's a normal UNIX domain socket appearing in the
* filesystem. * filesystem.
*/ */
if (ctrl_path != NULL && *ctrl_path != '/') { if (*ctrl_path != '/') {
char buf[21]; char buf[21];
os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path); os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path);
if (socket_local_client_connect( if (socket_local_client_connect(
@ -149,12 +166,18 @@ try_again:
#endif /* ANDROID */ #endif /* ANDROID */
ctrl->dest.sun_family = AF_UNIX; ctrl->dest.sun_family = AF_UNIX;
res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, if (os_strncmp(ctrl_path, "@abstract:", 10) == 0) {
sizeof(ctrl->dest.sun_path)); ctrl->dest.sun_path[0] = '\0';
if (res >= sizeof(ctrl->dest.sun_path)) { os_strlcpy(ctrl->dest.sun_path + 1, ctrl_path + 10,
close(ctrl->s); sizeof(ctrl->dest.sun_path) - 1);
os_free(ctrl); } else {
return NULL; res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
sizeof(ctrl->dest.sun_path));
if (res >= sizeof(ctrl->dest.sun_path)) {
close(ctrl->s);
os_free(ctrl);
return NULL;
}
} }
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) { sizeof(ctrl->dest)) < 0) {

View file

@ -667,6 +667,7 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
{ {
struct ctrl_iface_global_priv *priv; struct ctrl_iface_global_priv *priv;
struct sockaddr_un addr; struct sockaddr_un addr;
const char *ctrl = global->params.ctrl_interface;
priv = os_zalloc(sizeof(*priv)); priv = os_zalloc(sizeof(*priv));
if (priv == NULL) if (priv == NULL)
@ -674,17 +675,39 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
priv->global = global; priv->global = global;
priv->sock = -1; priv->sock = -1;
if (global->params.ctrl_interface == NULL) if (ctrl == NULL)
return priv; return priv;
#ifdef ANDROID wpa_printf(MSG_DEBUG, "Global control interface '%s'", ctrl);
priv->sock = android_get_control_socket(global->params.ctrl_interface);
if (priv->sock >= 0)
goto havesock;
#endif /* ANDROID */
wpa_printf(MSG_DEBUG, "Global control interface '%s'", #ifdef ANDROID
global->params.ctrl_interface); if (os_strncmp(ctrl, "@android:", 9) == 0) {
priv->sock = android_get_control_socket(ctrl + 9);
if (priv->sock < 0) {
wpa_printf(MSG_ERROR, "Failed to open Android control "
"socket '%s'", ctrl + 9);
goto fail;
}
wpa_printf(MSG_DEBUG, "Using Android control socket '%s'",
ctrl + 9);
goto havesock;
}
if (os_strncmp(ctrl, "@abstract:", 10) != 0) {
/*
* Backwards compatibility - try to open an Android control
* socket and if that fails, assume this was a UNIX domain
* socket instead.
*/
priv->sock = android_get_control_socket(ctrl);
if (priv->sock >= 0) {
wpa_printf(MSG_DEBUG,
"Using Android control socket '%s'",
ctrl);
goto havesock;
}
}
#endif /* ANDROID */
priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if (priv->sock < 0) { if (priv->sock < 0) {
@ -697,8 +720,23 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
addr.sun_len = sizeof(addr); addr.sun_len = sizeof(addr);
#endif /* __FreeBSD__ */ #endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX; addr.sun_family = AF_UNIX;
os_strlcpy(addr.sun_path, global->params.ctrl_interface,
sizeof(addr.sun_path)); if (os_strncmp(ctrl, "@abstract:", 10) == 0) {
addr.sun_path[0] = '\0';
os_strlcpy(addr.sun_path + 1, ctrl + 10,
sizeof(addr.sun_path) - 1);
if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) <
0) {
wpa_printf(MSG_ERROR, "supp-global-ctrl-iface-init: "
"bind(PF_UNIX) failed: %s", strerror(errno));
goto fail;
}
wpa_printf(MSG_DEBUG, "Using Abstract control socket '%s'",
ctrl + 10);
goto havesock;
}
os_strlcpy(addr.sun_path, ctrl, sizeof(addr.sun_path));
if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("supp-global-ctrl-iface-init (will try fixup): " perror("supp-global-ctrl-iface-init (will try fixup): "
"bind(PF_UNIX)"); "bind(PF_UNIX)");
@ -707,11 +745,11 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
" allow connections - assuming it was left" " allow connections - assuming it was left"
"over from forced program termination"); "over from forced program termination");
if (unlink(global->params.ctrl_interface) < 0) { if (unlink(ctrl) < 0) {
perror("unlink[ctrl_iface]"); perror("unlink[ctrl_iface]");
wpa_printf(MSG_ERROR, "Could not unlink " wpa_printf(MSG_ERROR, "Could not unlink "
"existing ctrl_iface socket '%s'", "existing ctrl_iface socket '%s'",
global->params.ctrl_interface); ctrl);
goto fail; goto fail;
} }
if (bind(priv->sock, (struct sockaddr *) &addr, if (bind(priv->sock, (struct sockaddr *) &addr,
@ -721,17 +759,19 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
} }
wpa_printf(MSG_DEBUG, "Successfully replaced leftover " wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
"ctrl_iface socket '%s'", "ctrl_iface socket '%s'",
global->params.ctrl_interface); ctrl);
} else { } else {
wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
"be in use - cannot override it"); "be in use - cannot override it");
wpa_printf(MSG_INFO, "Delete '%s' manually if it is " wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
"not used anymore", "not used anymore",
global->params.ctrl_interface); ctrl);
goto fail; goto fail;
} }
} }
wpa_printf(MSG_DEBUG, "Using UNIX control socket '%s'", ctrl);
if (global->params.ctrl_interface_group) { if (global->params.ctrl_interface_group) {
char *gid_str = global->params.ctrl_interface_group; char *gid_str = global->params.ctrl_interface_group;
gid_t gid = 0; gid_t gid = 0;
@ -755,21 +795,20 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
(int) gid); (int) gid);
} }
if (chown(global->params.ctrl_interface, -1, gid) < 0) { if (chown(ctrl, -1, gid) < 0) {
perror("chown[global_ctrl_interface/ifname]"); perror("chown[global_ctrl_interface/ifname]");
goto fail; goto fail;
} }
if (chmod(global->params.ctrl_interface, S_IRWXU | S_IRWXG) < 0) if (chmod(ctrl, S_IRWXU | S_IRWXG) < 0) {
{
perror("chmod[global_ctrl_interface/ifname]"); perror("chmod[global_ctrl_interface/ifname]");
goto fail; goto fail;
} }
} else {
chmod(ctrl, S_IRWXU);
} }
#ifdef ANDROID
havesock: havesock:
#endif /* ANDROID */
eloop_register_read_sock(priv->sock, eloop_register_read_sock(priv->sock,
wpa_supplicant_global_ctrl_iface_receive, wpa_supplicant_global_ctrl_iface_receive,
global, NULL); global, NULL);