]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/ctrl_iface.c
dbus: Add support for vendor specific elements
[thirdparty/hostap.git] / wpa_supplicant / ctrl_iface.c
index cbb877e9f8c6bbf9aa2479d894737919a662f1c8..1f4630f3d08f8fa4e3829b0f70748877b29fb983 100644 (file)
@@ -467,6 +467,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                wpa_s->extra_roc_dur = atoi(value);
        } else if (os_strcasecmp(cmd, "test_failure") == 0) {
                wpa_s->test_failure = atoi(value);
+       } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
+               wpa_s->p2p_go_csa_on_inv = !!atoi(value);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifndef CONFIG_NO_CONFIG_BLOBS
        } else if (os_strcmp(cmd, "blob") == 0) {
@@ -2136,45 +2138,6 @@ static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
 }
 
 
-static const char * debug_level_str(int level)
-{
-       switch (level) {
-       case MSG_EXCESSIVE:
-               return "EXCESSIVE";
-       case MSG_MSGDUMP:
-               return "MSGDUMP";
-       case MSG_DEBUG:
-               return "DEBUG";
-       case MSG_INFO:
-               return "INFO";
-       case MSG_WARNING:
-               return "WARNING";
-       case MSG_ERROR:
-               return "ERROR";
-       default:
-               return "?";
-       }
-}
-
-
-static int str_to_debug_level(const char *s)
-{
-       if (os_strcasecmp(s, "EXCESSIVE") == 0)
-               return MSG_EXCESSIVE;
-       if (os_strcasecmp(s, "MSGDUMP") == 0)
-               return MSG_MSGDUMP;
-       if (os_strcasecmp(s, "DEBUG") == 0)
-               return MSG_DEBUG;
-       if (os_strcasecmp(s, "INFO") == 0)
-               return MSG_INFO;
-       if (os_strcasecmp(s, "WARNING") == 0)
-               return MSG_WARNING;
-       if (os_strcasecmp(s, "ERROR") == 0)
-               return MSG_ERROR;
-       return -1;
-}
-
-
 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
                                               char *cmd, char *buf,
                                               size_t buflen)
@@ -2207,7 +2170,7 @@ static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
                }
        }
 
-       if (cmd && os_strlen(cmd)) {
+       if (os_strlen(cmd)) {
                int level = str_to_debug_level(cmd);
                if (level < 0)
                        return -1;
@@ -2783,6 +2746,8 @@ static int wpa_supplicant_ctrl_iface_select_network(
                }
        }
 
+       wpa_s->scan_min_time.sec = 0;
+       wpa_s->scan_min_time.usec = 0;
        wpa_supplicant_select_network(wpa_s, ssid);
 
        return 0;
@@ -2820,6 +2785,8 @@ static int wpa_supplicant_ctrl_iface_enable_network(
                        return 0;
                }
        }
+       wpa_s->scan_min_time.sec = 0;
+       wpa_s->scan_min_time.usec = 0;
        wpa_supplicant_enable_network(wpa_s, ssid);
 
        return 0;
@@ -3074,19 +3041,19 @@ static int wpa_supplicant_ctrl_iface_get_network(
        *name++ = '\0';
 
        id = atoi(cmd);
-       wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
+       wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
                   id, name);
 
        ssid = wpa_config_get_network(wpa_s->conf, id);
        if (ssid == NULL) {
-               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
+               wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network "
                           "id=%d", id);
                return -1;
        }
 
        value = wpa_config_get_no_key(ssid, name);
        if (value == NULL) {
-               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
+               wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network "
                           "variable '%s'", name);
                return -1;
        }
@@ -4219,9 +4186,10 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
        if (mask & WPA_BSS_MASK_WPS_SCAN) {
                ie = (const u8 *) (bss + 1);
                ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
-               if (ret < 0 || ret >= end - pos)
+               if (ret >= end - pos)
                        return 0;
-               pos += ret;
+               if (ret > 0)
+                       pos += ret;
        }
 #endif /* CONFIG_WPS */
 
@@ -4265,6 +4233,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 #ifdef CONFIG_INTERWORKING
        if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
                struct wpa_bss_anqp *anqp = bss->anqp;
+               struct wpa_bss_anqp_elem *elem;
+
                pos = anqp_add_hex(pos, end, "anqp_capability_list",
                                   anqp->capability_list);
                pos = anqp_add_hex(pos, end, "anqp_venue_name",
@@ -4294,6 +4264,15 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
                                   anqp->hs20_osu_providers_list);
 #endif /* CONFIG_HS20 */
+
+               dl_list_for_each(elem, &anqp->anqp_elems,
+                                struct wpa_bss_anqp_elem, list) {
+                       char title[20];
+
+                       os_snprintf(title, sizeof(title), "anqp[%u]",
+                                   elem->infoid);
+                       pos = anqp_add_hex(pos, end, title, elem->payload);
+               }
        }
 #endif /* CONFIG_INTERWORKING */
 
@@ -4875,11 +4854,37 @@ static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
        if (!p2ps_prov)
                return -1;
 
+       p2ps_prov->pd_seeker = 1;
+
        return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
                                  p2ps_prov);
 }
 
 
+static int parse_freq(int chwidth, int freq2)
+{
+       if (freq2 < 0)
+               return -1;
+       if (freq2)
+               return VHT_CHANWIDTH_80P80MHZ;
+
+       switch (chwidth) {
+       case 0:
+       case 20:
+       case 40:
+               return VHT_CHANWIDTH_USE_HT;
+       case 80:
+               return VHT_CHANWIDTH_80MHZ;
+       case 160:
+               return VHT_CHANWIDTH_160MHZ;
+       default:
+               wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
+                          chwidth);
+               return -1;
+       }
+}
+
+
 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
                            char *buf, size_t buflen)
 {
@@ -4896,7 +4901,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
        int go_intent = -1;
        int freq = 0;
        int pd;
-       int ht40, vht;
+       int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
 
        if (!wpa_s->global->p2p_init_wpa_s)
                return -1;
@@ -4957,6 +4962,18 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
                        return -1;
        }
 
+       pos2 = os_strstr(pos, " freq2=");
+       if (pos2)
+               freq2 = atoi(pos2 + 7);
+
+       pos2 = os_strstr(pos, " max_oper_chwidth=");
+       if (pos2)
+               chwidth = atoi(pos2 + 18);
+
+       max_oper_chwidth = parse_freq(chwidth, freq2);
+       if (max_oper_chwidth < 0)
+               return -1;
+
        if (os_strncmp(pos, "pin", 3) == 0) {
                /* Request random PIN (to be displayed) and enable the PIN */
                wps_method = WPS_PIN_DISPLAY;
@@ -4981,8 +4998,8 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
 
        new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
                                   persistent_group, automatic, join,
-                                  auth, go_intent, freq, persistent_id, pd,
-                                  ht40, vht);
+                                  auth, go_intent, freq, freq2, persistent_id,
+                                  pd, ht40, vht, max_oper_chwidth);
        if (new_pin == -2) {
                os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
                return 25;
@@ -5537,7 +5554,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
        struct wpa_ssid *ssid;
        u8 *_peer = NULL, peer[ETH_ALEN];
        int freq = 0, pref_freq = 0;
-       int ht40, vht;
+       int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
 
        id = atoi(cmd);
        pos = os_strstr(cmd, " peer=");
@@ -5575,8 +5592,20 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
        ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
                vht;
 
-       return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
-                              pref_freq);
+       pos = os_strstr(cmd, "freq2=");
+       if (pos)
+               freq2 = atoi(pos + 6);
+
+       pos = os_strstr(cmd, " max_oper_chwidth=");
+       if (pos)
+               chwidth = atoi(pos + 18);
+
+       max_oper_chwidth = parse_freq(chwidth, freq2);
+       if (max_oper_chwidth < 0)
+               return -1;
+
+       return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
+                              max_oper_chwidth, pref_freq);
 }
 
 
@@ -5623,7 +5652,8 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
 
 
 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
-                                        int id, int freq, int ht40, int vht)
+                                        int id, int freq, int vht_center_freq2,
+                                        int ht40, int vht, int vht_chwidth)
 {
        struct wpa_ssid *ssid;
 
@@ -5635,8 +5665,9 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
-       return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
-                                            NULL, 0);
+       return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
+                                            vht_center_freq2, 0, ht40, vht,
+                                            vht_chwidth, NULL, 0, 0);
 }
 
 
@@ -5645,11 +5676,14 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
        int freq = 0, persistent = 0, group_id = -1;
        int vht = wpa_s->conf->p2p_go_vht;
        int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+       int max_oper_chwidth, chwidth = 0, freq2 = 0;
        char *token, *context = NULL;
 
        while ((token = str_token(cmd, " ", &context))) {
                if (sscanf(token, "freq=%d", &freq) == 1 ||
-                   sscanf(token, "persistent=%d", &group_id) == 1) {
+                   sscanf(token, "freq2=%d", &freq2) == 1 ||
+                   sscanf(token, "persistent=%d", &group_id) == 1 ||
+                   sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
                        continue;
                } else if (os_strcmp(token, "ht40") == 0) {
                        ht40 = 1;
@@ -5666,11 +5700,17 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
                }
        }
 
+       max_oper_chwidth = parse_freq(chwidth, freq2);
+       if (max_oper_chwidth < 0)
+               return -1;
+
        if (group_id >= 0)
                return p2p_ctrl_group_add_persistent(wpa_s, group_id,
-                                                    freq, ht40, vht);
+                                                    freq, freq2, ht40, vht,
+                                                    max_oper_chwidth);
 
-       return wpas_p2p_group_add(wpa_s, persistent, freq, ht40, vht);
+       return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
+                                 max_oper_chwidth);
 }
 
 
@@ -5800,7 +5840,7 @@ static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
                           freq->min, freq->max);
        }
 
-       wpas_p2p_update_channel_list(wpa_s);
+       wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
        return 0;
 }
 
@@ -6017,6 +6057,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);
+       wpa_s->parent->p2ps_method_config_any = 0;
        if (wpa_s->global->p2p)
                p2p_flush(wpa_s->global->p2p);
 }
@@ -6821,6 +6862,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
 
        wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
 
+       wpas_abort_ongoing_scan(wpa_s);
+
 #ifdef CONFIG_P2P
        wpas_p2p_cancel(p2p_wpa_s);
        p2p_ctrl_flush(p2p_wpa_s);
@@ -6832,7 +6875,9 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
        p2p_wpa_s->p2p_disable_ip_addr_req = 0;
        os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
        p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
+       p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
        p2p_wpa_s->global->pending_p2ps_group = 0;
+       p2p_wpa_s->global->pending_p2ps_group_freq = 0;
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_WPS_TESTING
@@ -6896,7 +6941,9 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
        wpa_s->next_ssid = NULL;
 
 #ifdef CONFIG_INTERWORKING
+#ifdef CONFIG_HS20
        hs20_cancel_fetch_osu(wpa_s);
+#endif /* CONFIG_HS20 */
 #endif /* CONFIG_INTERWORKING */
 
        wpa_s->ext_mgmt_frame_handling = 0;
@@ -6904,6 +6951,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
 #ifdef CONFIG_TESTING_OPTIONS
        wpa_s->extra_roc_dur = 0;
        wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
+       wpa_s->p2p_go_csa_on_inv = 0;
 #endif /* CONFIG_TESTING_OPTIONS */
 
        wpa_s->disconnected = 0;
@@ -6921,6 +6969,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
        }
 
        eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+       wpa_s->wnmsleep_used = 0;
 }
 
 
@@ -7765,62 +7814,35 @@ static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
 #endif /* WPA_TRACE_BFD */
 }
 
-#endif /* CONFIG_TESTING_OPTIONS */
-
 
-static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s)
+static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
 {
-       unsigned int i;
-       char buf[30];
-
-       wpa_printf(MSG_DEBUG, "Update vendor elements");
-
-       for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
-               if (wpa_s->vendor_elem[i]) {
-                       int res;
+       struct wpa_supplicant *wpa_s = eloop_ctx;
+       int i, count = (intptr_t) timeout_ctx;
 
-                       res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
-                       if (!os_snprintf_error(sizeof(buf), res)) {
-                               wpa_hexdump_buf(MSG_DEBUG, buf,
-                                               wpa_s->vendor_elem[i]);
-                       }
-               }
+       wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
+                  count);
+       for (i = 0; i < count; i++) {
+               wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
+                            i + 1, count);
        }
-
-#ifdef CONFIG_P2P
-       if (wpa_s->parent == wpa_s &&
-           wpa_s->global->p2p &&
-           !wpa_s->global->p2p_disabled)
-               p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
-#endif /* CONFIG_P2P */
 }
 
 
-static struct wpa_supplicant *
-wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s,
-                           enum wpa_vendor_elem_frame frame)
+static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
 {
-       switch (frame) {
-#ifdef CONFIG_P2P
-       case VENDOR_ELEM_PROBE_REQ_P2P:
-       case VENDOR_ELEM_PROBE_RESP_P2P:
-       case VENDOR_ELEM_PROBE_RESP_P2P_GO:
-       case VENDOR_ELEM_BEACON_P2P_GO:
-       case VENDOR_ELEM_P2P_PD_REQ:
-       case VENDOR_ELEM_P2P_PD_RESP:
-       case VENDOR_ELEM_P2P_GO_NEG_REQ:
-       case VENDOR_ELEM_P2P_GO_NEG_RESP:
-       case VENDOR_ELEM_P2P_GO_NEG_CONF:
-       case VENDOR_ELEM_P2P_INV_REQ:
-       case VENDOR_ELEM_P2P_INV_RESP:
-       case VENDOR_ELEM_P2P_ASSOC_REQ:
-               return wpa_s->parent;
-#endif /* CONFIG_P2P */
-       default:
-               return wpa_s;
-       }
+       int count;
+
+       count = atoi(cmd);
+       if (count <= 0)
+               return -1;
+
+       return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
+                                     (void *) (intptr_t) count);
 }
 
+#endif /* CONFIG_TESTING_OPTIONS */
+
 
 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
 {
@@ -7833,7 +7855,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
        frame = atoi(pos);
        if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
                return -1;
-       wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+       wpa_s = wpas_vendor_elem(wpa_s, frame);
 
        pos = os_strchr(pos, ' ');
        if (pos == NULL)
@@ -7864,7 +7886,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
 
        if (wpa_s->vendor_elem[frame] == NULL) {
                wpa_s->vendor_elem[frame] = buf;
-               wpas_ctrl_vendor_elem_update(wpa_s);
+               wpas_vendor_elem_update(wpa_s);
                return 0;
        }
 
@@ -7875,7 +7897,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
 
        wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
        wpabuf_free(buf);
-       wpas_ctrl_vendor_elem_update(wpa_s);
+       wpas_vendor_elem_update(wpa_s);
 
        return 0;
 }
@@ -7888,7 +7910,7 @@ static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
 
        if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
                return -1;
-       wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+       wpa_s = wpas_vendor_elem(wpa_s, frame);
 
        if (wpa_s->vendor_elem[frame] == NULL)
                return 0;
@@ -7906,12 +7928,12 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
        size_t len;
        u8 *buf;
        struct ieee802_11_elems elems;
-       u8 *ie, *end;
+       int res;
 
        frame = atoi(pos);
        if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
                return -1;
-       wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+       wpa_s = wpas_vendor_elem(wpa_s, frame);
 
        pos = os_strchr(pos, ' ');
        if (pos == NULL)
@@ -7921,7 +7943,7 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
        if (*pos == '*') {
                wpabuf_free(wpa_s->vendor_elem[frame]);
                wpa_s->vendor_elem[frame] = NULL;
-               wpas_ctrl_vendor_elem_update(wpa_s);
+               wpas_vendor_elem_update(wpa_s);
                return 0;
        }
 
@@ -7949,31 +7971,9 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
                return -1;
        }
 
-       ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
-       end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
-
-       for (; ie + 1 < end; ie += 2 + ie[1]) {
-               if (ie + len > end)
-                       break;
-               if (os_memcmp(ie, buf, len) != 0)
-                       continue;
-
-               if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
-                       wpabuf_free(wpa_s->vendor_elem[frame]);
-                       wpa_s->vendor_elem[frame] = NULL;
-               } else {
-                       os_memmove(ie, ie + len,
-                                  end - (ie + len));
-                       wpa_s->vendor_elem[frame]->used -= len;
-               }
-               os_free(buf);
-               wpas_ctrl_vendor_elem_update(wpa_s);
-               return 0;
-       }
-
+       res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
        os_free(buf);
-
-       return -1;
+       return res;
 }
 
 
@@ -8142,6 +8142,19 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
 }
 
 
+static int wpas_ctrl_cmd_debug_level(const char *cmd)
+{
+       if (os_strcmp(cmd, "PING") == 0 ||
+           os_strncmp(cmd, "BSS ", 4) == 0 ||
+           os_strncmp(cmd, "GET_NETWORK ", 12) == 0 ||
+           os_strncmp(cmd, "STATUS", 6) == 0 ||
+           os_strncmp(cmd, "STA ", 4) == 0 ||
+           os_strncmp(cmd, "STA-", 4) == 0)
+               return MSG_EXCESSIVE;
+       return MSG_DEBUG;
+}
+
+
 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                                         char *buf, size_t *resp_len)
 {
@@ -8165,9 +8178,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
                                      (const u8 *) buf, os_strlen(buf));
        } else {
-               int level = MSG_DEBUG;
-               if (os_strcmp(buf, "PING") == 0)
-                       level = MSG_EXCESSIVE;
+               int level = wpas_ctrl_cmd_debug_level(buf);
                wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
        }
 
@@ -8584,6 +8595,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
                reply_len = wpa_supplicant_ctrl_iface_scan_results(
                        wpa_s, reply, reply_size);
+       } else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
+               if (wpas_abort_ongoing_scan(wpa_s) < 0)
+                       reply_len = -1;
        } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
                if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
                        reply_len = -1;
@@ -8788,6 +8802,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                        reply_len = -1;
        } else if (os_strcmp(buf, "GET_FAIL") == 0) {
                reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
+       } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
+               if (wpas_ctrl_event_test(wpa_s, buf + 11) < 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)
@@ -8832,10 +8849,11 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
        struct wpa_supplicant *wpa_s;
        unsigned int create_iface = 0;
        u8 mac_addr[ETH_ALEN];
+       enum wpa_driver_if_type type = WPA_IF_STATION;
 
        /*
         * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
-        * TAB<bridge_ifname>[TAB<create>]
+        * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
         */
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
 
@@ -8903,9 +8921,22 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
                if (!extra[0])
                        break;
 
-               if (os_strcmp(extra, "create") == 0)
+               if (os_strcmp(extra, "create") == 0) {
                        create_iface = 1;
-               else {
+                       if (!pos)
+                               break;
+
+                       if (os_strcmp(pos, "sta") == 0) {
+                               type = WPA_IF_STATION;
+                       } else if (os_strcmp(pos, "ap") == 0) {
+                               type = WPA_IF_AP_BSS;
+                       } else {
+                               wpa_printf(MSG_DEBUG,
+                                          "INTERFACE_ADD unsupported interface type: '%s'",
+                                          pos);
+                               return -1;
+                       }
+               } else {
                        wpa_printf(MSG_DEBUG,
                                   "INTERFACE_ADD unsupported extra parameter: '%s'",
                                   extra);
@@ -8918,7 +8949,7 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
                           iface.ifname);
                if (!global->ifaces)
                        return -1;
-               if (wpa_drv_if_add(global->ifaces, WPA_IF_STATION, iface.ifname,
+               if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
                                   NULL, NULL, NULL, mac_addr, NULL) < 0) {
                        wpa_printf(MSG_ERROR,
                                   "CTRL_IFACE interface creation failed");