P2P: Do not consider the p2p_scan results after p2p_stop_find
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
index 510b802..58480a7 100644 (file)
@@ -7,6 +7,10 @@
  */
 
 #include "utils/includes.h"
+#ifdef CONFIG_TESTING_OPTIONS
+#include <net/ethernet.h>
+#include <netinet/ip.h>
+#endif /* CONFIG_TESTING_OPTIONS */
 
 #include "utils/common.h"
 #include "utils/eloop.h"
@@ -15,6 +19,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "common/wpa_ctrl.h"
+#include "ap/hostapd.h"
 #include "eap_peer/eap.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "rsn_supp/wpa.h"
@@ -420,6 +425,16 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
 #ifdef CONFIG_TESTING_OPTIONS
        } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
                wpa_s->ext_mgmt_frame_handling = !!atoi(value);
+       } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
+               wpa_s->ext_eapol_frame_io = !!atoi(value);
+#ifdef CONFIG_AP
+               if (wpa_s->ap_iface) {
+                       wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
+                               wpa_s->ext_eapol_frame_io;
+               }
+#endif /* CONFIG_AP */
+       } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
+               wpa_s->extra_roc_dur = atoi(value);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifndef CONFIG_NO_CONFIG_BLOBS
        } else if (os_strcmp(cmd, "blob") == 0) {
@@ -1540,6 +1555,11 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
                if (ret < 0 || ret >= end - pos)
                        return pos - buf;
                pos += ret;
+               ret = os_snprintf(pos, end - pos, "freq=%u\n",
+                                 wpa_s->assoc_freq);
+               if (ret < 0 || ret >= end - pos)
+                       return pos - buf;
+               pos += ret;
                if (ssid) {
                        u8 *_ssid = ssid->ssid;
                        size_t ssid_len = ssid->ssid_len;
@@ -2088,6 +2108,13 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
                        return pos;
                pos += ret;
        }
+       if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
+               ret = os_snprintf(pos, end - pos, "%sSAE",
+                                 pos == start ? "" : "+");
+               if (ret < 0 || ret >= end - pos)
+                       return pos;
+               pos += ret;
+       }
 #ifdef CONFIG_IEEE80211R
        if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
                ret = os_snprintf(pos, end - pos, "%sFT/EAP",
@@ -2103,6 +2130,13 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
                        return pos;
                pos += ret;
        }
+       if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
+               ret = os_snprintf(pos, end - pos, "%sFT/SAE",
+                                 pos == start ? "" : "+");
+               if (ret < 0 || ret >= end - pos)
+                       return pos;
+               pos += ret;
+       }
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_IEEE80211W
        if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
@@ -2188,8 +2222,9 @@ static int wpa_supplicant_ctrl_iface_scan_result(
 {
        char *pos, *end;
        int ret;
-       const u8 *ie, *ie2, *p2p;
+       const u8 *ie, *ie2, *p2p, *mesh;
 
+       mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
        p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
        if (!p2p)
                p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
@@ -2210,8 +2245,10 @@ static int wpa_supplicant_ctrl_iface_scan_result(
        if (ie)
                pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
        ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
-       if (ie2)
-               pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
+       if (ie2) {
+               pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
+                                           ie2, 2 + ie2[1]);
+       }
        pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
        if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
                ret = os_snprintf(pos, end - pos, "[WEP]");
@@ -2219,6 +2256,12 @@ static int wpa_supplicant_ctrl_iface_scan_result(
                        return -1;
                pos += ret;
        }
+       if (mesh) {
+               ret = os_snprintf(pos, end - pos, "[MESH]");
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
        if (bss_is_dmg(bss)) {
                const char *s;
                ret = os_snprintf(pos, end - pos, "[DMG]");
@@ -2569,6 +2612,8 @@ static int wpa_supplicant_ctrl_iface_update_network(
                wpa_config_update_psk(ssid);
        else if (os_strcmp(name, "priority") == 0)
                wpa_config_update_prio_list(wpa_s->conf);
+       else if (os_strcmp(name, "no_auto_peer") == 0)
+               ssid->no_auto_peer = atoi(value);
 
        return 0;
 }
@@ -3342,8 +3387,8 @@ static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
                                continue;
                        ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
                                          chnl[i].chan, chnl[i].freq,
-                                         chnl[i].flag & HOSTAPD_CHAN_NO_IBSS ?
-                                         " (NO_IBSS)" : "",
+                                         chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
+                                         " (NO_IR)" : "",
                                          chnl[i].flag & HOSTAPD_CHAN_RADAR ?
                                          " (DFS)" : "");
 
@@ -4990,6 +5035,7 @@ static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
 {
        os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
        wpa_s->force_long_sd = 0;
+       wpas_p2p_stop_find(wpa_s);
        if (wpa_s->global->p2p)
                p2p_flush(wpa_s->global->p2p);
 }
@@ -5789,6 +5835,10 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
 #endif /* CONFIG_INTERWORKING */
 
        wpa_s->ext_mgmt_frame_handling = 0;
+       wpa_s->ext_eapol_frame_io = 0;
+#ifdef CONFIG_TESTING_OPTIONS
+       wpa_s->extra_roc_dur = 0;
+#endif /* CONFIG_TESTING_OPTIONS */
 }
 
 
@@ -6239,6 +6289,187 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
        return 0;
 }
 
+
+static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
+{
+       char *pos;
+       u8 src[ETH_ALEN], *buf;
+       int used;
+       size_t len;
+
+       wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
+
+       pos = cmd;
+       used = hwaddr_aton2(pos, src);
+       if (used < 0)
+               return -1;
+       pos += used;
+       while (*pos == ' ')
+               pos++;
+
+       len = os_strlen(pos);
+       if (len & 1)
+               return -1;
+       len /= 2;
+
+       buf = os_malloc(len);
+       if (buf == NULL)
+               return -1;
+
+       if (hexstr2bin(pos, buf, len) < 0) {
+               os_free(buf);
+               return -1;
+       }
+
+       wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
+       os_free(buf);
+
+       return 0;
+}
+
+
+static u16 ipv4_hdr_checksum(const void *buf, size_t len)
+{
+       size_t i;
+       u32 sum = 0;
+       const u16 *pos = buf;
+
+       for (i = 0; i < len / 2; i++)
+               sum += *pos++;
+
+       while (sum >> 16)
+               sum = (sum & 0xffff) + (sum >> 16);
+
+       return sum ^ 0xffff;
+}
+
+
+#define HWSIM_PACKETLEN 1500
+#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
+
+void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+       const struct ether_header *eth;
+       const struct iphdr *ip;
+       const u8 *pos;
+       unsigned int i;
+
+       if (len != HWSIM_PACKETLEN)
+               return;
+
+       eth = (const struct ether_header *) buf;
+       ip = (const struct iphdr *) (eth + 1);
+       pos = (const u8 *) (ip + 1);
+
+       if (ip->ihl != 5 || ip->version != 4 ||
+           ntohs(ip->tot_len) != HWSIM_IP_LEN)
+               return;
+
+       for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) {
+               if (*pos != (u8) i)
+                       return;
+               pos++;
+       }
+
+       wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
+               MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
+}
+
+
+static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
+                                           char *cmd)
+{
+       int enabled = atoi(cmd);
+
+       if (!enabled) {
+               if (wpa_s->l2_test) {
+                       l2_packet_deinit(wpa_s->l2_test);
+                       wpa_s->l2_test = NULL;
+                       wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
+               }
+               return 0;
+       }
+
+       if (wpa_s->l2_test)
+               return 0;
+
+       wpa_s->l2_test = l2_packet_init(wpa_s->ifname, wpa_s->own_addr,
+                                       ETHERTYPE_IP, wpas_data_test_rx,
+                                       wpa_s, 1);
+       if (wpa_s->l2_test == NULL)
+               return -1;
+
+       wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
+
+       return 0;
+}
+
+
+static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
+{
+       u8 dst[ETH_ALEN], src[ETH_ALEN];
+       char *pos;
+       int used;
+       long int val;
+       u8 tos;
+       u8 buf[HWSIM_PACKETLEN];
+       struct ether_header *eth;
+       struct iphdr *ip;
+       u8 *dpos;
+       unsigned int i;
+
+       if (wpa_s->l2_test == NULL)
+               return -1;
+
+       /* format: <dst> <src> <tos> */
+
+       pos = cmd;
+       used = hwaddr_aton2(pos, dst);
+       if (used < 0)
+               return -1;
+       pos += used;
+       while (*pos == ' ')
+               pos++;
+       used = hwaddr_aton2(pos, src);
+       if (used < 0)
+               return -1;
+       pos += used;
+
+       val = strtol(pos, NULL, 0);
+       if (val < 0 || val > 0xff)
+               return -1;
+       tos = val;
+
+       eth = (struct ether_header *) buf;
+       os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
+       os_memcpy(eth->ether_shost, src, ETH_ALEN);
+       eth->ether_type = htons(ETHERTYPE_IP);
+       ip = (struct iphdr *) (eth + 1);
+       os_memset(ip, 0, sizeof(*ip));
+       ip->ihl = 5;
+       ip->version = 4;
+       ip->ttl = 64;
+       ip->tos = tos;
+       ip->tot_len = htons(HWSIM_IP_LEN);
+       ip->protocol = 1;
+       ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1);
+       ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2);
+       ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
+       dpos = (u8 *) (ip + 1);
+       for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
+               *dpos++ = i;
+
+       if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, buf,
+                          HWSIM_PACKETLEN) < 0)
+               return -1;
+
+       wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
+               " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
+
+       return 0;
+}
+
 #endif /* CONFIG_TESTING_OPTIONS */
 
 
@@ -6432,7 +6663,7 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
                        wpa_s->vendor_elem[frame] = NULL;
                } else {
                        os_memmove(ie, ie + len,
-                                  wpabuf_len(wpa_s->vendor_elem[frame]) - len);
+                                  end - (ie + len));
                        wpa_s->vendor_elem[frame]->used -= len;
                }
                os_free(buf);
@@ -7012,6 +7243,15 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
                if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
                        reply_len = -1;
+       } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
+               if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
+               if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
+               if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
+                       reply_len = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
        } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
                if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
@@ -7530,6 +7770,9 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
                if (wpas_module_tests() < 0)
                        reply_len = -1;
 #endif /* CONFIG_MODULE_TESTS */
+       } else if (os_strncmp(buf, "RELOG", 5) == 0) {
+               if (wpa_debug_reopen_file() < 0)
+                       reply_len = -1;
        } else {
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
                reply_len = 16;