void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) { struct wpa_ctrl_dst *dst, *prev; if (priv->sock > -1) { char *fname; char *buf, *dir = NULL, *gid_str = NULL; eloop_unregister_read_sock(priv->sock); if (priv->ctrl_dst) { /* * Wait a second before closing the control socket if * there are any attached monitors in order to allow * them to receive any pending messages. */ wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " "monitors to receive messages"); os_sleep(1, 0); } close(priv->sock); priv->sock = -1; fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); if (fname) { unlink(fname); os_free(fname); } buf = os_strdup(priv->wpa_s->conf->ctrl_interface); if (buf == NULL) goto free_dst; if (os_strncmp(buf, "DIR=", 4) == 0) { dir = buf + 4; gid_str = os_strstr(dir, " GROUP="); if (gid_str) { *gid_str = '\0'; gid_str += 7; } } else dir = buf; if (rmdir(dir) < 0) { if (errno == ENOTEMPTY) { wpa_printf(MSG_DEBUG, "Control interface " "directory not empty - leaving it " "behind"); } else { perror("rmdir[ctrl_interface]"); } } os_free(buf); } free_dst: dst = priv->ctrl_dst; while (dst) { prev = dst; dst = dst->next; os_free(prev); } os_free(priv); }
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s) { struct wpa_ctrl_dst *dst, *prev; if (wpa_s->ctrl_sock > -1) { char *fname; eloop_unregister_read_sock(wpa_s->ctrl_sock); if (wpa_s->ctrl_dst) { /* * Wait a second before closing the control socket if * there are any attached monitors in order to allow * them to receive any pending messages. */ wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " "monitors to receive messages"); sleep(1); } close(wpa_s->ctrl_sock); wpa_s->ctrl_sock = -1; fname = wpa_supplicant_ctrl_iface_path(wpa_s); if (fname) unlink(fname); free(fname); if (rmdir(wpa_s->conf->ctrl_interface) < 0) { if (errno == ENOTEMPTY) { wpa_printf(MSG_DEBUG, "Control interface " "directory not empty - leaving it " "behind"); } else { perror("rmdir[ctrl_interface]"); } } } dst = wpa_s->ctrl_dst; while (dst) { prev = dst; dst = dst->next; free(prev); } }
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) { struct wpa_ctrl_dst *dst, *prev; struct ctrl_iface_msg *msg, *prev_msg; struct ctrl_iface_global_priv *gpriv; if (priv->sock > -1) { char *fname; char *buf, *dir = NULL; eloop_unregister_read_sock(priv->sock); if (!dl_list_empty(&priv->ctrl_dst)) { /* * Wait before closing the control socket if * there are any attached monitors in order to allow * them to receive any pending messages. */ wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " "monitors to receive messages"); os_sleep(0, 100000); } close(priv->sock); priv->sock = -1; fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); if (fname) { unlink(fname); os_free(fname); } if (priv->wpa_s->conf->ctrl_interface == NULL) goto free_dst; buf = os_strdup(priv->wpa_s->conf->ctrl_interface); if (buf == NULL) goto free_dst; if (os_strncmp(buf, "DIR=", 4) == 0) { char *gid_str; dir = buf + 4; gid_str = os_strstr(dir, " GROUP="); if (gid_str) *gid_str = '\0'; } else dir = buf; if (rmdir(dir) < 0) { if (errno == ENOTEMPTY) { wpa_printf(MSG_DEBUG, "Control interface " "directory not empty - leaving it " "behind"); } else { wpa_printf(MSG_ERROR, "rmdir[ctrl_interface=%s]: %s", dir, strerror(errno)); } } os_free(buf); } free_dst: dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst, list) { dl_list_del(&dst->list); os_free(dst); } dl_list_for_each_safe(msg, prev_msg, &priv->msg_queue, struct ctrl_iface_msg, list) { dl_list_del(&msg->list); os_free(msg); } gpriv = priv->wpa_s->global->ctrl_iface; if (gpriv) { dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue, struct ctrl_iface_msg, list) { if (msg->wpa_s == priv->wpa_s) { dl_list_del(&msg->list); os_free(msg); } } } eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL); os_free(priv); }
static int wpas_ctrl_iface_open_sock(struct wpa_supplicant *wpa_s, struct ctrl_iface_priv *priv) { struct sockaddr_un addr; char *fname = NULL; gid_t gid = 0; int gid_set = 0; char *buf, *dir = NULL, *gid_str = NULL; struct group *grp; char *endp; int flags; buf = os_strdup(wpa_s->conf->ctrl_interface); if (buf == NULL) goto fail; #ifdef ANDROID os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", wpa_s->conf->ctrl_interface); priv->sock = android_get_control_socket(addr.sun_path); if (priv->sock >= 0) { priv->android_control_socket = 1; goto havesock; } #endif /* ANDROID */ if (os_strncmp(buf, "DIR=", 4) == 0) { dir = buf + 4; gid_str = os_strstr(dir, " GROUP="); if (gid_str) { *gid_str = '\0'; gid_str += 7; } } else { dir = buf; gid_str = wpa_s->conf->ctrl_interface_group; } if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) { if (errno == EEXIST) { wpa_printf(MSG_DEBUG, "Using existing control " "interface directory."); } else { wpa_printf(MSG_ERROR, "mkdir[ctrl_interface=%s]: %s", dir, strerror(errno)); goto fail; } } #ifdef ANDROID /* * wpa_supplicant is started from /init.*.rc on Android and that seems * to be using umask 0077 which would leave the control interface * directory without group access. This breaks things since Wi-Fi * framework assumes that this directory can be accessed by other * applications in the wifi group. Fix this by adding group access even * if umask value would prevent this. */ if (chmod(dir, S_IRWXU | S_IRWXG) < 0) { wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s", strerror(errno)); /* Try to continue anyway */ } #endif /* ANDROID */ if (gid_str) { grp = getgrnam(gid_str); if (grp) { gid = grp->gr_gid; gid_set = 1; wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" " (from group name '%s')", (int) gid, gid_str); } else { /* Group name not found - try to parse this as gid */ gid = strtol(gid_str, &endp, 10); if (*gid_str == '\0' || *endp != '\0') { wpa_printf(MSG_ERROR, "CTRL: Invalid group " "'%s'", gid_str); goto fail; } gid_set = 1; wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", (int) gid); } } if (gid_set && chown(dir, -1, gid) < 0) { wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s", dir, (int) gid, strerror(errno)); goto fail; } /* Make sure the group can enter and read the directory */ if (gid_set && chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) < 0) { wpa_printf(MSG_ERROR, "CTRL: chmod[ctrl_interface]: %s", strerror(errno)); goto fail; } if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= sizeof(addr.sun_path)) { wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded"); goto fail; } priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); if (priv->sock < 0) { wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); goto fail; } os_memset(&addr, 0, sizeof(addr)); #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) addr.sun_len = sizeof(addr); #endif /* __FreeBSD__ */ addr.sun_family = AF_UNIX; fname = wpa_supplicant_ctrl_iface_path(wpa_s); if (fname == NULL) goto fail; os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", strerror(errno)); if (connect(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" " allow connections - assuming it was left" "over from forced program termination"); if (unlink(fname) < 0) { wpa_printf(MSG_ERROR, "Could not unlink existing ctrl_iface socket '%s': %s", fname, strerror(errno)); goto fail; } if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_ERROR, "supp-ctrl-iface-init: bind(PF_UNIX): %s", strerror(errno)); goto fail; } wpa_printf(MSG_DEBUG, "Successfully replaced leftover " "ctrl_iface socket '%s'", fname); } else { wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " "be in use - cannot override it"); wpa_printf(MSG_INFO, "Delete '%s' manually if it is " "not used anymore", fname); os_free(fname); fname = NULL; goto fail; } } if (gid_set && chown(fname, -1, gid) < 0) { wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s", fname, (int) gid, strerror(errno)); goto fail; } if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { wpa_printf(MSG_ERROR, "chmod[ctrl_interface=%s]: %s", fname, strerror(errno)); goto fail; } os_free(fname); #ifdef ANDROID havesock: #endif /* ANDROID */ /* * Make socket non-blocking so that we don't hang forever if * target dies unexpectedly. */ flags = fcntl(priv->sock, F_GETFL); if (flags >= 0) { flags |= O_NONBLOCK; if (fcntl(priv->sock, F_SETFL, flags) < 0) { wpa_printf(MSG_INFO, "fcntl(ctrl, O_NONBLOCK): %s", strerror(errno)); /* Not fatal, continue on.*/ } } eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv); wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); os_free(buf); return 0; fail: if (priv->sock >= 0) { close(priv->sock); priv->sock = -1; } if (fname) { unlink(fname); os_free(fname); } os_free(buf); return -1; }
struct ctrl_iface_priv * wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) { struct ctrl_iface_priv *priv; struct sockaddr_un addr; char *fname = NULL; gid_t gid = 0; int gid_set = 0; char *buf, *dir = NULL, *gid_str = NULL; struct group *grp; char *endp; priv = os_zalloc(sizeof(*priv)); if (priv == NULL) return NULL; priv->wpa_s = wpa_s; priv->sock = -1; if (wpa_s->conf->ctrl_interface == NULL) return priv; buf = os_strdup(wpa_s->conf->ctrl_interface); if (buf == NULL) goto fail; if (os_strncmp(buf, "DIR=", 4) == 0) { dir = buf + 4; gid_str = os_strstr(dir, " GROUP="); if (gid_str) { *gid_str = '\0'; gid_str += 7; } } else { dir = buf; gid_str = wpa_s->conf->ctrl_interface_group; } if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) { if (errno == EEXIST) { wpa_printf(MSG_DEBUG, "Using existing control " "interface directory."); } else { perror("mkdir[ctrl_interface]"); goto fail; } } if (gid_str) { grp = getgrnam(gid_str); if (grp) { gid = grp->gr_gid; gid_set = 1; wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" " (from group name '%s')", (int) gid, gid_str); } else { /* Group name not found - try to parse this as gid */ gid = strtol(gid_str, &endp, 10); if (*gid_str == '\0' || *endp != '\0') { wpa_printf(MSG_DEBUG, "CTRL: Invalid group " "'%s'", gid_str); goto fail; } gid_set = 1; wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", (int) gid); } } if (gid_set && chown(dir, -1, gid) < 0) { perror("chown[ctrl_interface]"); goto fail; } if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= sizeof(addr.sun_path)) goto fail; priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); if (priv->sock < 0) { perror("socket(PF_UNIX)"); goto fail; } os_memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; fname = wpa_supplicant_ctrl_iface_path(wpa_s); if (fname == NULL) goto fail; os_strncpy(addr.sun_path, fname, sizeof(addr.sun_path)); if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", strerror(errno)); if (connect(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" " allow connections - assuming it was left" "over from forced program termination"); if (unlink(fname) < 0) { perror("unlink[ctrl_iface]"); wpa_printf(MSG_ERROR, "Could not unlink " "existing ctrl_iface socket '%s'", fname); goto fail; } if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(PF_UNIX)"); goto fail; } wpa_printf(MSG_DEBUG, "Successfully replaced leftover " "ctrl_iface socket '%s'", fname); } else { wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " "be in use - cannot override it"); wpa_printf(MSG_INFO, "Delete '%s' manually if it is " "not used anymore", fname); os_free(fname); fname = NULL; goto fail; } } if (gid_set && chown(fname, -1, gid) < 0) { perror("chown[ctrl_interface/ifname]"); goto fail; } if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { perror("chmod[ctrl_interface/ifname]"); goto fail; } os_free(fname); eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv); wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); os_free(buf); return priv; fail: if (priv->sock >= 0) close(priv->sock); os_free(priv); if (fname) { unlink(fname); os_free(fname); } os_free(buf); return NULL; }
int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) { CTRL_IFACE_SOCK addr; int s = -1; char *fname = NULL; wpa_s->ctrl_sock = -1; if (wpa_s->conf->ctrl_interface == NULL) return 0; #ifdef CONFIG_CTRL_IFACE_UDP s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket(PF_INET)"); goto fail; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl((127 << 24) | 1); addr.sin_port = htons(9877); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(AF_UNIX)"); goto fail; } #else /* CONFIG_CTRL_IFACE_UDP */ if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { if (errno == EEXIST) { wpa_printf(MSG_DEBUG, "Using existing control " "interface directory."); } else { perror("mkdir[ctrl_interface]"); goto fail; } } if (wpa_s->conf->ctrl_interface_gid_set && chown(wpa_s->conf->ctrl_interface, 0, wpa_s->conf->ctrl_interface_gid) < 0) { perror("chown[ctrl_interface]"); return -1; } if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >= sizeof(addr.sun_path)) goto fail; s = socket(PF_UNIX, SOCK_DGRAM, 0); if (s < 0) { perror("socket(PF_UNIX)"); goto fail; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; fname = wpa_supplicant_ctrl_iface_path(wpa_s); if (fname == NULL) goto fail; strncpy(addr.sun_path, fname, sizeof(addr.sun_path)); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(PF_UNIX)"); if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" " allow connections - assuming it was left" "over from forced program termination"); if (unlink(fname) < 0) { perror("unlink[ctrl_iface]"); wpa_printf(MSG_ERROR, "Could not unlink " "existing ctrl_iface socket '%s'", fname); goto fail; } if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(PF_UNIX)"); goto fail; } wpa_printf(MSG_DEBUG, "Successfully replaced leftover " "ctrl_iface socket '%s'", fname); } else { wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " "be in use - cannot override it"); wpa_printf(MSG_INFO, "Delete '%s' manually if it is " "not used anymore", fname); free(fname); fname = NULL; goto fail; } } if (wpa_s->conf->ctrl_interface_gid_set && chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) { perror("chown[ctrl_interface/ifname]"); goto fail; } if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { perror("chmod[ctrl_interface/ifname]"); goto fail; } free(fname); #endif /* CONFIG_CTRL_IFACE_UDP */ wpa_s->ctrl_sock = s; eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s, NULL); return 0; fail: if (s >= 0) close(s); if (fname) { unlink(fname); free(fname); } return -1; }