📄 ctrl_iface.c
字号:
* wpa_supplicant_ctrl_iface_init - Initialize control interface * @wpa_s: Pointer to wpa_supplicant data * Returns: 0 on success, -1 on failure * * Initialize the control interface and start receiving commands from external * programs. */int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s){ CTRL_IFACE_SOCK addr; int s = -1;#ifndef CONFIG_CTRL_IFACE_UDP char *fname = NULL;#endif /* CONFIG_CTRL_IFACE_UDP */ 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(WPA_CTRL_IFACE_PORT); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(AF_INET)"); 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);#ifndef CONFIG_CTRL_IFACE_UDP if (fname) { unlink(fname); free(fname); }#endif /* CONFIG_CTRL_IFACE_UDP */ return -1;}/** * wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface * @wpa_s: Pointer to wpa_supplicant data * * Deinitialize the control interface that was initialized with * wpa_supplicant_ctrl_iface_init(). */void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s){ struct wpa_ctrl_dst *dst, *prev; if (wpa_s->ctrl_sock > -1) {#ifndef CONFIG_CTRL_IFACE_UDP char *fname;#endif /* CONFIG_CTRL_IFACE_UDP */ 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;#ifndef CONFIG_CTRL_IFACE_UDP 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]"); } }#endif /* CONFIG_CTRL_IFACE_UDP */ } dst = wpa_s->ctrl_dst; while (dst) { prev = dst; dst = dst->next; free(prev); }}/** * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors * @wpa_s: Pointer to wpa_supplicant data * @level: Priority level of the message * @buf: Message data * @len: Message length * * Send a packet to all monitor programs attached to the control interface. */void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level, char *buf, size_t len){ struct wpa_ctrl_dst *dst, *next; char levelstr[10]; int idx;#ifdef CONFIG_CTRL_IFACE_UDP char *sbuf; int llen; dst = wpa_s->ctrl_dst; if (wpa_s->ctrl_sock < 0 || dst == NULL) return; snprintf(levelstr, sizeof(levelstr), "<%d>", level); llen = strlen(levelstr); sbuf = malloc(llen + len); if (sbuf == NULL) return; memcpy(sbuf, levelstr, llen); memcpy(sbuf + llen, buf, len); idx = 0; while (dst) { next = dst->next; if (level >= dst->debug_level) { wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", inet_ntoa(dst->addr.sin_addr), ntohs(dst->addr.sin_port)); if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0, (struct sockaddr *) &dst->addr, sizeof(dst->addr)) < 0) { perror("sendto(CTRL_IFACE monitor)"); dst->errors++; if (dst->errors > 10) { wpa_supplicant_ctrl_iface_detach( wpa_s, &dst->addr, dst->addrlen); } } else dst->errors = 0; } idx++; dst = next; } free(sbuf);#else /* CONFIG_CTRL_IFACE_UDP */ struct msghdr msg; struct iovec io[2]; dst = wpa_s->ctrl_dst; if (wpa_s->ctrl_sock < 0 || dst == NULL) return; snprintf(levelstr, sizeof(levelstr), "<%d>", level); io[0].iov_base = levelstr; io[0].iov_len = strlen(levelstr); io[1].iov_base = buf; io[1].iov_len = len; memset(&msg, 0, sizeof(msg)); msg.msg_iov = io; msg.msg_iovlen = 2; idx = 0; while (dst) { next = dst->next; if (level >= dst->debug_level) { wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", (u8 *) dst->addr.sun_path, dst->addrlen - sizeof(dst->addr.sun_family)); msg.msg_name = &dst->addr; msg.msg_namelen = dst->addrlen; if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) { perror("sendmsg(CTRL_IFACE monitor)"); dst->errors++; if (dst->errors > 10) { wpa_supplicant_ctrl_iface_detach( wpa_s, &dst->addr, dst->addrlen); } } else dst->errors = 0; } idx++; dst = next; }#endif /* CONFIG_CTRL_IFACE_UDP */}/** * wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor * @wpa_s: Pointer to wpa_supplicant data * * Wait until the first message from an external program using the control * interface is received. This function can be used to delay normal startup * processing to allow control interface programs to attach with * %wpa_supplicant before normal operations are started. */void wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s){ fd_set rfds; if (wpa_s->ctrl_sock < 0) return; wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", wpa_s->ifname); FD_ZERO(&rfds); FD_SET(wpa_s->ctrl_sock, &rfds); select(wpa_s->ctrl_sock + 1, &rfds, NULL, NULL, NULL);}static int wpa_supplicant_global_iface_add(struct wpa_global *global, char *cmd){ struct wpa_interface iface; char *pos; /* * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> */ wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); memset(&iface, 0, sizeof(iface)); do { iface.ifname = pos = cmd; pos = strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.ifname[0] == '\0') return -1; if (pos == NULL) break; iface.confname = pos; pos = strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.confname[0] == '\0') iface.confname = NULL; if (pos == NULL) break; iface.driver = pos; pos = strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.driver[0] == '\0') iface.driver = NULL; if (pos == NULL) break; iface.ctrl_interface = pos; pos = strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.ctrl_interface[0] == '\0') iface.ctrl_interface = NULL; if (pos == NULL) break; iface.driver_param = pos; pos = strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.driver_param[0] == '\0') iface.driver_param = NULL; if (pos == NULL) break; } while (0); if (wpa_supplicant_get_iface(global, iface.ifname)) return -1; return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;}static int wpa_supplicant_global_iface_remove(struct wpa_global *global, char *cmd){ struct wpa_supplicant *wpa_s; wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); wpa_s = wpa_supplicant_get_iface(global, cmd); if (wpa_s == NULL) return -1; return wpa_supplicant_remove_iface(global, wpa_s);}static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, void *sock_ctx){ struct wpa_global *global = eloop_ctx; char buf[256]; int res; CTRL_IFACE_SOCK from; socklen_t fromlen = sizeof(from); char *reply; const int reply_size = 2048; int reply_len; res = recvfrom(sock, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { perror("recvfrom(ctrl_iface)"); return; } buf[res] = '\0'; wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", (u8 *) buf, res); reply = malloc(reply_size); if (reply == NULL) { sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, fromlen); return; } memcpy(reply, "OK\n", 3); reply_len = 3; if (strcmp(buf, "PING") == 0) { memcpy(reply, "PONG\n", 5); reply_len = 5; } else if (strncmp(buf, "INTERFACE_ADD ", 14) == 0) { if (wpa_supplicant_global_iface_add(global, buf + 14)) reply_len = -1; } else if (strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { if (wpa_supplicant_global_iface_remove(global, buf + 17)) reply_len = -1; } else { memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; } if (reply_len < 0) { memcpy(reply, "FAIL\n", 5); reply_len = 5; } sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); free(reply);}/** * wpa_supplicant_global_ctrl_iface_init - Initialize global control interface * @global: Pointer to global data from wpa_supplicant_init() * Returns: 0 on success, -1 on failure * * Initialize the global control interface and start receiving commands from * external programs. */int wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global){ CTRL_IFACE_SOCK addr; int s = -1; global->ctrl_sock = -1; if (global->params.ctrl_interface == NULL) return 0; wpa_printf(MSG_DEBUG, "Global control interface '%s'", global->params.ctrl_interface);#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(WPA_GLOBAL_CTRL_IFACE_PORT); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(AF_INET)"); goto fail; }#else /* CONFIG_CTRL_IFACE_UDP */ 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; strncpy(addr.sun_path, global->params.ctrl_interface, 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(global->params.ctrl_interface) < 0) { perror("unlink[ctrl_iface]"); wpa_printf(MSG_ERROR, "Could not unlink " "existing ctrl_iface socket '%s'", global->params.ctrl_interface); 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'", global->params.ctrl_interface); } 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", global->params.ctrl_interface); goto fail; } }#endif /* CONFIG_CTRL_IFACE_UDP */ global->ctrl_sock = s; eloop_register_read_sock(s, wpa_supplicant_global_ctrl_iface_receive, global, NULL); return 0;fail: if (s >= 0) close(s); return -1;}/** * wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface * @global: Pointer to global data from wpa_supplicant_init() * * Deinitialize the global control interface that was initialized with * wpa_supplicant_global_ctrl_iface_init(). */void wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global){ if (global->ctrl_sock < 0) return; eloop_unregister_read_sock(global->ctrl_sock); close(global->ctrl_sock); global->ctrl_sock = -1;#ifndef CONFIG_CTRL_IFACE_UDP if (global->params.ctrl_interface) unlink(global->params.ctrl_interface);#endif /* CONFIG_CTRL_IFACE_UDP */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -