#include <sys/un.h>
#include <sys/stat.h>
+#include <stddef.h>
#include "hostapd.h"
#include "eloop.h"
#include "ctrl_iface.h"
#include "sta_info.h"
#include "accounting.h"
+#include "wps_hostapd.h"
+#include "driver.h"
struct wpa_ctrl_dst {
};
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ const char *buf, size_t len);
+
+
static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
struct sockaddr_un *from,
socklen_t fromlen)
dst->next = hapd->ctrl_dst;
hapd->ctrl_dst = dst;
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
- (u8 *) from->sun_path, fromlen);
+ (u8 *) from->sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path));
return 0;
}
dst = hapd->ctrl_dst;
while (dst) {
if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path, fromlen) ==
- 0) {
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
if (prev == NULL)
hapd->ctrl_dst = dst->next;
else
prev->next = dst->next;
os_free(dst);
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
- (u8 *) from->sun_path, fromlen);
+ (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
return 0;
}
prev = dst;
dst = hapd->ctrl_dst;
while (dst) {
if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path, fromlen) ==
- 0) {
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
- "level", (u8 *) from->sun_path, fromlen);
+ "level", (u8 *) from->sun_path, fromlen -
+ offsetof(struct sockaddr_un, sun_path));
dst->debug_level = atoi(level);
return 0;
}
}
+#ifdef CONFIG_IEEE80211W
+static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
+ const char *txtaddr)
+{
+ u8 addr[ETH_ALEN];
+ u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
+
+ if (hwaddr_aton(txtaddr, addr))
+ return -1;
+
+ os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+ ieee802_11_send_sa_query_req(hapd, addr, trans_id);
+
+ return 0;
+}
+#endif /* CONFIG_IEEE80211W */
+
+
+#ifdef CONFIG_WPS
+static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
+{
+ char *pin = os_strchr(txt, ' ');
+ if (pin == NULL)
+ return -1;
+ *pin++ = '\0';
+ return hostapd_wps_add_pin(hapd, txt, pin);
+}
+
+
+#ifdef CONFIG_WPS_OOB
+static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
+{
+ char *path, *method, *name;
+
+ path = os_strchr(txt, ' ');
+ if (path == NULL)
+ return -1;
+ *path++ = '\0';
+
+ method = os_strchr(path, ' ');
+ if (method == NULL)
+ return -1;
+ *method++ = '\0';
+
+ name = os_strchr(method, ' ');
+ if (name != NULL)
+ *name++ = '\0';
+
+ return hostapd_wps_start_oob(hapd, txt, path, method, name);
+}
+#endif /* CONFIG_WPS_OOB */
+#endif /* CONFIG_WPS */
+
+
static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
reply_len = -1;
+#ifdef CONFIG_IEEE80211W
+ } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
+ if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
+ reply_len = -1;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WPS
+ } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
+ if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
+ reply_len = -1;
+ } else if (os_strcmp(buf, "WPS_PBC") == 0) {
+ if (hostapd_wps_button_pushed(hapd))
+ reply_len = -1;
+#ifdef CONFIG_WPS_OOB
+ } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
+ if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8))
+ reply_len = -1;
+#endif /* CONFIG_WPS_OOB */
+#endif /* CONFIG_WPS */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
}
+static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
+ const char *txt, size_t len)
+{
+ struct hostapd_data *hapd = ctx;
+ if (hapd == NULL)
+ return;
+ hostapd_ctrl_iface_send(hapd, level, txt, len);
+}
+
+
int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
{
struct sockaddr_un addr;
}
os_memset(&addr, 0, sizeof(addr));
+#ifdef __FreeBSD__
+ addr.sun_len = sizeof(addr);
+#endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX;
fname = hostapd_ctrl_iface_path(hapd);
if (fname == NULL)
hapd->ctrl_sock = s;
eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
NULL);
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
return 0;
}
-void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
- char *buf, size_t len)
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ const char *buf, size_t len)
{
struct wpa_ctrl_dst *dst, *next;
struct msghdr msg;
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
io[0].iov_base = levelstr;
io[0].iov_len = os_strlen(levelstr);
- io[1].iov_base = buf;
+ io[1].iov_base = (char *) buf;
io[1].iov_len = len;
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
next = dst->next;
if (level >= dst->debug_level) {
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
- (u8 *) dst->addr.sun_path, dst->addrlen);
+ (u8 *) dst->addr.sun_path, dst->addrlen -
+ offsetof(struct sockaddr_un, sun_path));
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
- fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
- idx);
- perror("sendmsg");
+ int _errno = errno;
+ wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
+ "%d - %s",
+ idx, errno, strerror(errno));
dst->errors++;
- if (dst->errors > 10) {
+ if (dst->errors > 10 || _errno == ENOENT) {
hostapd_ctrl_iface_detach(
hapd, &dst->addr,
dst->addrlen);