diff options
author | sam <sam@FreeBSD.org> | 2005-06-05 20:52:14 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2005-06-05 20:52:14 +0000 |
commit | 2b0ba7bae5b60321ee7843871a2cf15ad6b3f65b (patch) | |
tree | 98be326632e2ea3857ee0d9f831c91ea0823bb0d /contrib/wpa_supplicant/ctrl_iface.c | |
download | FreeBSD-src-2b0ba7bae5b60321ee7843871a2cf15ad6b3f65b.zip FreeBSD-src-2b0ba7bae5b60321ee7843871a2cf15ad6b3f65b.tar.gz |
Stripped down import of wpa_supplicant v0.3.8
Diffstat (limited to 'contrib/wpa_supplicant/ctrl_iface.c')
-rw-r--r-- | contrib/wpa_supplicant/ctrl_iface.c | 728 |
1 files changed, 728 insertions, 0 deletions
diff --git a/contrib/wpa_supplicant/ctrl_iface.c b/contrib/wpa_supplicant/ctrl_iface.c new file mode 100644 index 0000000..e418811 --- /dev/null +++ b/contrib/wpa_supplicant/ctrl_iface.c @@ -0,0 +1,728 @@ +/* + * WPA Supplicant / UNIX domain socket -based control interface + * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#ifndef CONFIG_NATIVE_WINDOWS +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/uio.h> +#endif /* CONFIG_NATIVE_WINDOWS */ + +#include "common.h" +#include "eloop.h" +#include "wpa.h" +#include "wpa_supplicant.h" +#include "config.h" +#include "eapol_sm.h" +#include "wpa_supplicant_i.h" +#include "ctrl_iface.h" +#include "l2_packet.h" + + +#ifdef CONFIG_NATIVE_WINDOWS +typedef int socklen_t; +#endif /* CONFIG_NATIVE_WINDOWS */ + +#ifdef CONFIG_CTRL_IFACE_UDP +#define CTRL_IFACE_SOCK struct sockaddr_in +#else /* CONFIG_CTRL_IFACE_UDP */ +#define CTRL_IFACE_SOCK struct sockaddr_un +#endif /* CONFIG_CTRL_IFACE_UDP */ + + +struct wpa_ctrl_dst { + struct wpa_ctrl_dst *next; + CTRL_IFACE_SOCK addr; + socklen_t addrlen; + int debug_level; + int errors; +}; + + +static const char * wpa_state_txt(int state) +{ + switch (state) { + case WPA_DISCONNECTED: + return "DISCONNECTED"; + case WPA_SCANNING: + return "SCANNING"; + case WPA_ASSOCIATING: + return "ASSOCIATING"; + case WPA_ASSOCIATED: + return "ASSOCIATED"; + case WPA_4WAY_HANDSHAKE: + return "4WAY_HANDSHAKE"; + case WPA_GROUP_HANDSHAKE: + return "GROUP_HANDSHAKE"; + case WPA_COMPLETED: + return "COMPLETED"; + default: + return "UNKNOWN"; + } +} + + +static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, + char *cmd) +{ + char *value; + + value = strchr(cmd, ' '); + if (value == NULL) + return -1; + *value++ = '\0'; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); + if (strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { + eapol_sm_configure(wpa_s->eapol, + atoi(value), -1, -1, -1); + } else if (strcasecmp(cmd, "EAPOL::authPeriod") == 0) { + eapol_sm_configure(wpa_s->eapol, + -1, atoi(value), -1, -1); + } else if (strcasecmp(cmd, "EAPOL::startPeriod") == 0) { + eapol_sm_configure(wpa_s->eapol, + -1, -1, atoi(value), -1); + } else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) { + eapol_sm_configure(wpa_s->eapol, + -1, -1, -1, atoi(value)); + } else + return -1; + return 0; +} + + +static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, + char *addr) +{ + u8 bssid[ETH_ALEN]; + + if (hwaddr_aton(addr, bssid)) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " + "'%s'", addr); + return -1; + } + + wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); + rsn_preauth_deinit(wpa_s); + if (rsn_preauth_init(wpa_s, bssid)) + return -1; + + return 0; +} + + +static int wpa_supplicant_ctrl_iface_attach(struct wpa_supplicant *wpa_s, + CTRL_IFACE_SOCK *from, + socklen_t fromlen) +{ + struct wpa_ctrl_dst *dst; + + dst = malloc(sizeof(*dst)); + if (dst == NULL) + return -1; + memset(dst, 0, sizeof(*dst)); + memcpy(&dst->addr, from, sizeof(CTRL_IFACE_SOCK)); + dst->addrlen = fromlen; + dst->debug_level = MSG_INFO; + dst->next = wpa_s->ctrl_dst; + wpa_s->ctrl_dst = dst; +#ifdef CONFIG_CTRL_IFACE_UDP + wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d", + inet_ntoa(from->sin_addr), ntohs(from->sin_port)); +#else /* CONFIG_CTRL_IFACE_UDP */ + wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", + (u8 *) from->sun_path, fromlen); +#endif /* CONFIG_CTRL_IFACE_UDP */ + return 0; +} + + +static int wpa_supplicant_ctrl_iface_detach(struct wpa_supplicant *wpa_s, + CTRL_IFACE_SOCK *from, + socklen_t fromlen) +{ + struct wpa_ctrl_dst *dst, *prev = NULL; + + dst = wpa_s->ctrl_dst; + while (dst) { +#ifdef CONFIG_CTRL_IFACE_UDP + if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && + from->sin_port == dst->addr.sin_port) { + if (prev == NULL) + wpa_s->ctrl_dst = dst->next; + else + prev->next = dst->next; + free(dst); + wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached " + "%s:%d", inet_ntoa(from->sin_addr), + ntohs(from->sin_port)); + return 0; + } +#else /* CONFIG_CTRL_IFACE_UDP */ + if (fromlen == dst->addrlen && + memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) { + if (prev == NULL) + wpa_s->ctrl_dst = dst->next; + else + prev->next = dst->next; + free(dst); + wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", + (u8 *) from->sun_path, fromlen); + return 0; + } +#endif /* CONFIG_CTRL_IFACE_UDP */ + prev = dst; + dst = dst->next; + } + return -1; +} + + +static int wpa_supplicant_ctrl_iface_level(struct wpa_supplicant *wpa_s, + CTRL_IFACE_SOCK *from, + socklen_t fromlen, + char *level) +{ + struct wpa_ctrl_dst *dst; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); + + dst = wpa_s->ctrl_dst; + while (dst) { +#ifdef CONFIG_CTRL_IFACE_UDP + if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && + from->sin_port == dst->addr.sin_port) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor " + "level %s:%d", inet_ntoa(from->sin_addr), + ntohs(from->sin_port)); + dst->debug_level = atoi(level); + return 0; + } +#else /* CONFIG_CTRL_IFACE_UDP */ + if (fromlen == dst->addrlen && + memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) { + wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " + "level", (u8 *) from->sun_path, fromlen); + dst->debug_level = atoi(level); + return 0; + } +#endif /* CONFIG_CTRL_IFACE_UDP */ + dst = dst->next; + } + + return -1; +} + + +static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, + char *rsp) +{ + char *pos, *id_pos; + int id; + struct wpa_ssid *ssid; + + pos = strchr(rsp, '-'); + if (pos == NULL) + return -1; + *pos++ = '\0'; + id_pos = pos; + pos = strchr(pos, ':'); + if (pos == NULL) + return -1; + *pos++ = '\0'; + id = atoi(id_pos); + wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d value='%s'", + rsp, id, pos); + + ssid = wpa_s->conf->ssid; + while (ssid) { + if (id == ssid->id) + break; + ssid = ssid->next; + } + + if (ssid == NULL) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " + "to update", id); + return -1; + } + + if (strcmp(rsp, "IDENTITY") == 0) { + free(ssid->identity); + ssid->identity = (u8 *) strdup(pos); + ssid->identity_len = strlen(pos); + ssid->pending_req_identity = 0; + if (ssid == wpa_s->current_ssid) + wpa_s->reassociate = 1; + } else if (strcmp(rsp, "PASSWORD") == 0) { + free(ssid->password); + ssid->password = (u8 *) strdup(pos); + ssid->password_len = strlen(pos); + ssid->pending_req_password = 0; + if (ssid == wpa_s->current_ssid) + wpa_s->reassociate = 1; + } else if (strcmp(rsp, "OTP") == 0) { + free(ssid->otp); + ssid->otp = (u8 *) strdup(pos); + ssid->otp_len = strlen(pos); + free(ssid->pending_req_otp); + ssid->pending_req_otp = NULL; + ssid->pending_req_otp_len = 0; + } else { + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); + return -1; + } + + return 0; +} + + +static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, + const char *params, + char *buf, size_t buflen) +{ + char *pos, *end; + int res, verbose; + + verbose = strcmp(params, "-VERBOSE") == 0; + pos = buf; + end = buf + buflen; + pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n", + MAC2STR(wpa_s->bssid)); + if (wpa_s->current_ssid) { + pos += snprintf(pos, end - pos, "ssid=%s\n", + wpa_ssid_txt(wpa_s->current_ssid->ssid, + wpa_s->current_ssid->ssid_len)); + } + pos += snprintf(pos, end - pos, + "pairwise_cipher=%s\n" + "group_cipher=%s\n" + "key_mgmt=%s\n" + "wpa_state=%s\n", + wpa_cipher_txt(wpa_s->pairwise_cipher), + wpa_cipher_txt(wpa_s->group_cipher), + wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->proto), + wpa_state_txt(wpa_s->wpa_state)); + + res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose); + if (res >= 0) + pos += res; + + if (wpa_s->preauth_eapol) { + pos += snprintf(pos, end - pos, "Pre-authentication " + "EAPOL state machines:\n"); + res = eapol_sm_get_status(wpa_s->preauth_eapol, + pos, end - pos, verbose); + if (res >= 0) + pos += res; + } + + return pos - buf; +} + + +static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, + void *sock_ctx) +{ + struct wpa_supplicant *wpa_s = 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; + int new_attached = 0, ctrl_rsp = 0; + + res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + (struct sockaddr *) &from, &fromlen); + if (res < 0) { + perror("recvfrom(ctrl_iface)"); + return; + } + buf[res] = '\0'; + if (strncmp(buf, "CTRL-RSP-", 9) == 0) { + wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", + (u8 *) buf, res); + } else { + wpa_hexdump_ascii(MSG_DEBUG, "RX 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 (strcmp(buf, "MIB") == 0) { + reply_len = wpa_get_mib(wpa_s, reply, reply_size); + if (reply_len >= 0) { + res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, + reply_size - reply_len); + if (res < 0) + reply_len = -1; + else + reply_len += res; + } + } else if (strncmp(buf, "STATUS", 6) == 0) { + reply_len = wpa_supplicant_ctrl_iface_status( + wpa_s, buf + 6, reply, reply_size); + } else if (strcmp(buf, "PMKSA") == 0) { + reply_len = pmksa_cache_list(wpa_s, reply, reply_size); + } else if (strncmp(buf, "SET ", 4) == 0) { + if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) + reply_len = -1; + } else if (strcmp(buf, "LOGON") == 0) { + eapol_sm_notify_logoff(wpa_s->eapol, FALSE); + } else if (strcmp(buf, "LOGOFF") == 0) { + eapol_sm_notify_logoff(wpa_s->eapol, TRUE); + } else if (strcmp(buf, "REASSOCIATE") == 0) { + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } else if (strncmp(buf, "PREAUTH ", 8) == 0) { + if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) + reply_len = -1; + } else if (strcmp(buf, "ATTACH") == 0) { + if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen)) + reply_len = -1; + else + new_attached = 1; + } else if (strcmp(buf, "DETACH") == 0) { + if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen)) + reply_len = -1; + } else if (strncmp(buf, "LEVEL ", 6) == 0) { + if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen, + buf + 6)) + reply_len = -1; + } else if (strncmp(buf, "CTRL-RSP-", 9) == 0) { + if (wpa_supplicant_ctrl_iface_ctrl_rsp(wpa_s, buf + 9)) + reply_len = -1; + else + ctrl_rsp = 1; + } else if (strcmp(buf, "RECONFIGURE") == 0) { + if (wpa_supplicant_reload_configuration(wpa_s)) + reply_len = -1; + } else if (strcmp(buf, "TERMINATE") == 0) { + eloop_terminate(); + } 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); + + if (new_attached) + eapol_sm_notify_ctrl_attached(wpa_s->eapol); + if (ctrl_rsp) + eapol_sm_notify_ctrl_response(wpa_s->eapol); +} + + +static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s) +{ + char *buf; + size_t len; + + if (wpa_s->conf->ctrl_interface == NULL) + return NULL; + + len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2; + buf = malloc(len); + if (buf == NULL) + return NULL; + + snprintf(buf, len, "%s/%s", + wpa_s->conf->ctrl_interface, wpa_s->ifname); +#ifdef __CYGWIN__ + { + /* Windows/WinPcap uses interface names that are not suitable + * as a file name - convert invalid chars to underscores */ + char *pos = buf; + while (*pos) { + if (*pos == '\\') + *pos = '_'; + pos++; + } + } +#endif /* __CYGWIN__ */ + return buf; +} + + +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; +} + + +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); + 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_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) { + fprintf(stderr, "CTRL_IFACE monitor[%d]: ", + idx); + perror("sendto"); + 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); + msg.msg_name = &dst->addr; + msg.msg_namelen = dst->addrlen; + if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) { + fprintf(stderr, "CTRL_IFACE monitor[%d]: ", + idx); + perror("sendmsg"); + 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 */ +} |