WPS: Add support for setting timeout for PIN
[wpasupplicant] / hostapd / ctrl_iface.c
index 9e6505a..3cd498c 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <sys/un.h>
 #include <sys/stat.h>
+#include <stddef.h>
 
 #include "hostapd.h"
 #include "eloop.h"
@@ -30,7 +31,7 @@
 #include "sta_info.h"
 #include "accounting.h"
 #include "wps_hostapd.h"
-#include "driver.h"
+#include "drivers/driver.h"
 
 
 struct wpa_ctrl_dst {
@@ -61,7 +62,8 @@ static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
        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;
 }
 
@@ -75,15 +77,18 @@ static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
        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;
@@ -105,10 +110,12 @@ static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
        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;
                }
@@ -224,6 +231,7 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
 
 
 #ifdef CONFIG_IEEE80211W
+#ifdef NEED_MLME
 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
                                       const char *txtaddr)
 {
@@ -240,6 +248,7 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
 
        return 0;
 }
+#endif /* NEED_MLME */
 #endif /* CONFIG_IEEE80211W */
 
 
@@ -247,16 +256,28 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
 {
        char *pin = os_strchr(txt, ' ');
+       char *timeout_txt;
+       int timeout;
+
        if (pin == NULL)
                return -1;
        *pin++ = '\0';
-       return hostapd_wps_add_pin(hapd, txt, pin);
+
+       timeout_txt = os_strchr(pin, ' ');
+       if (timeout_txt) {
+               *timeout_txt++ = '\0';
+               timeout = atoi(timeout_txt);
+       } else
+               timeout = 0;
+
+       return hostapd_wps_add_pin(hapd, txt, pin, timeout);
 }
 
 
+#ifdef CONFIG_WPS_OOB
 static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
 {
-       char *path, *method;
+       char *path, *method, *name;
 
        path = os_strchr(txt, ' ');
        if (path == NULL)
@@ -268,8 +289,13 @@ static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
                return -1;
        *method++ = '\0';
 
-       return hostapd_wps_start_oob(hapd, txt, path, method);
+       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 */
 
 
@@ -357,9 +383,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
                if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
                        reply_len = -1;
 #ifdef CONFIG_IEEE80211W
+#ifdef NEED_MLME
        } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
                if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
                        reply_len = -1;
+#endif /* NEED_MLME */
 #endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_WPS
        } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
@@ -368,9 +396,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
        } 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);
@@ -456,14 +486,44 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
        }
 
        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)
                goto fail;
        os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
        if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-               perror("bind(PF_UNIX)");
-               goto fail;
+               wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
+                          strerror(errno));
+               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);
+                       os_free(fname);
+                       fname = NULL;
+                       goto fail;
+               }
        }
 
        if (hapd->conf->ctrl_interface_gid_set &&
@@ -558,15 +618,17 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
                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);