]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/ctrl_iface.c
Maintain maximum blacklist count over list clear operations
[thirdparty/hostap.git] / wpa_supplicant / ctrl_iface.c
index 51b6fdb1f2a44d9332f9b01e503ba0763a742150..328d382fa6800fb3f539529f4ad87221d1afde61 100644 (file)
@@ -158,6 +158,128 @@ static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
 }
 
 
+static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
+{
+       char *pos;
+       u8 addr[ETH_ALEN], *bssid = NULL, *n;
+       struct wpa_ssid_value *ssid = NULL, *ns;
+       size_t count = 0, ssid_count = 0;
+       struct wpa_ssid *c;
+
+       /*
+        * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | “”
+        * SSID_SPEC ::= ssid <SSID_HEX>
+        * BSSID_SPEC ::= bssid <BSSID_HEX>
+        */
+
+       pos = val;
+       while (pos) {
+               if (*pos == '\0')
+                       break;
+               if (os_strncmp(pos, "bssid ", 6) == 0) {
+                       int res;
+                       pos += 6;
+                       res = hwaddr_aton2(pos, addr);
+                       if (res < 0) {
+                               os_free(ssid);
+                               os_free(bssid);
+                               wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
+                                          "BSSID value '%s'", pos);
+                               return -1;
+                       }
+                       pos += res;
+                       n = os_realloc_array(bssid, count + 1, ETH_ALEN);
+                       if (n == NULL) {
+                               os_free(ssid);
+                               os_free(bssid);
+                               return -1;
+                       }
+                       bssid = n;
+                       os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
+                       count++;
+               } else if (os_strncmp(pos, "ssid ", 5) == 0) {
+                       char *end;
+                       pos += 5;
+
+                       end = pos;
+                       while (*end) {
+                               if (*end == '\0' || *end == ' ')
+                                       break;
+                               end++;
+                       }
+
+                       ns = os_realloc_array(ssid, ssid_count + 1,
+                                             sizeof(struct wpa_ssid_value));
+                       if (ns == NULL) {
+                               os_free(ssid);
+                               os_free(bssid);
+                               return -1;
+                       }
+                       ssid = ns;
+
+                       if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
+                           hexstr2bin(pos, ssid[ssid_count].ssid,
+                                      (end - pos) / 2) < 0) {
+                               os_free(ssid);
+                               os_free(bssid);
+                               wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
+                                          "SSID value '%s'", pos);
+                               return -1;
+                       }
+                       ssid[ssid_count].ssid_len = (end - pos) / 2;
+                       wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
+                                         ssid[ssid_count].ssid,
+                                         ssid[ssid_count].ssid_len);
+                       ssid_count++;
+                       pos = end;
+               } else {
+                       wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
+                                  "'%s'", pos);
+                       os_free(ssid);
+                       os_free(bssid);
+                       return -1;
+               }
+
+               pos = os_strchr(pos, ' ');
+               if (pos)
+                       pos++;
+       }
+
+       wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
+       os_free(wpa_s->disallow_aps_bssid);
+       wpa_s->disallow_aps_bssid = bssid;
+       wpa_s->disallow_aps_bssid_count = count;
+
+       wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
+       os_free(wpa_s->disallow_aps_ssid);
+       wpa_s->disallow_aps_ssid = ssid;
+       wpa_s->disallow_aps_ssid_count = ssid_count;
+
+       if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
+               return 0;
+
+       c = wpa_s->current_ssid;
+       if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
+               return 0;
+
+       if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
+           !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
+               return 0;
+
+       wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
+                  "because current AP was marked disallowed");
+
+#ifdef CONFIG_SME
+       wpa_s->sme.prev_bssid_set = 0;
+#endif /* CONFIG_SME */
+       wpa_s->reassociate = 1;
+       wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+       wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+       return 0;
+}
+
+
 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                                         char *cmd)
 {
@@ -291,6 +413,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_WIFI_DISPLAY */
        } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
                ret = set_bssid_filter(wpa_s, value);
+       } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
+               ret = set_disallow_aps(wpa_s, value);
        } else {
                value[-1] = '=';
                ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -540,9 +664,21 @@ static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
        }
 
 #ifdef CONFIG_AP
-       if (wpa_s->ap_iface)
+       if (wpa_s->ap_iface) {
+               int timeout = 0;
+               char *pos;
+
+               if (pin) {
+                       pos = os_strchr(pin, ' ');
+                       if (pos) {
+                               *pos++ = '\0';
+                               timeout = atoi(pos);
+                       }
+               }
+
                return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
-                                                buf, buflen);
+                                                buf, buflen, timeout);
+       }
 #endif /* CONFIG_AP */
 
        if (pin) {
@@ -614,31 +750,6 @@ static int wpa_supplicant_ctrl_iface_wps_check_pin(
 }
 
 
-#ifdef CONFIG_WPS_OOB
-static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
-                                            char *cmd)
-{
-       char *path, *method, *name;
-
-       path = os_strchr(cmd, ' ');
-       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 wpas_wps_start_oob(wpa_s, cmd, path, method, name);
-}
-#endif /* CONFIG_WPS_OOB */
-
-
 #ifdef CONFIG_WPS_NFC
 
 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
@@ -710,6 +821,149 @@ static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
        return ret;
 }
 
+
+static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
+                                             char *reply, size_t max_len)
+{
+       struct wpabuf *buf;
+       int res;
+
+       buf = wpas_wps_nfc_handover_req(wpa_s);
+       if (buf == NULL)
+               return -1;
+
+       res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+                                        wpabuf_len(buf));
+       reply[res++] = '\n';
+       reply[res] = '\0';
+
+       wpabuf_free(buf);
+
+       return res;
+}
+
+
+static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
+                                         char *cmd, char *reply,
+                                         size_t max_len)
+{
+       char *pos;
+
+       pos = os_strchr(cmd, ' ');
+       if (pos == NULL)
+               return -1;
+       *pos++ = '\0';
+
+       if (os_strcmp(cmd, "NDEF") != 0)
+               return -1;
+
+       if (os_strcmp(pos, "WPS") == 0) {
+               return wpas_ctrl_nfc_get_handover_req_wps(wpa_s, reply,
+                                                         max_len);
+       }
+
+       return -1;
+}
+
+
+static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
+                                             char *reply, size_t max_len)
+{
+       struct wpabuf *buf;
+       int res;
+
+       buf = wpas_wps_nfc_handover_sel(wpa_s);
+       if (buf == NULL)
+               return -1;
+
+       res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+                                        wpabuf_len(buf));
+       reply[res++] = '\n';
+       reply[res] = '\0';
+
+       wpabuf_free(buf);
+
+       return res;
+}
+
+
+static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
+                                         char *cmd, char *reply,
+                                         size_t max_len)
+{
+       char *pos;
+
+       pos = os_strchr(cmd, ' ');
+       if (pos == NULL)
+               return -1;
+       *pos++ = '\0';
+
+       if (os_strcmp(cmd, "NDEF") != 0)
+               return -1;
+
+       if (os_strcmp(pos, "WPS") == 0) {
+               return wpas_ctrl_nfc_get_handover_sel_wps(wpa_s, reply,
+                                                         max_len);
+       }
+
+       return -1;
+}
+
+
+static int wpas_ctrl_nfc_rx_handover_req(struct wpa_supplicant *wpa_s,
+                                        char *cmd, char *reply,
+                                        size_t max_len)
+{
+       size_t len;
+       struct wpabuf *buf;
+       int ret;
+
+       len = os_strlen(cmd);
+       if (len & 0x01)
+               return -1;
+       len /= 2;
+
+       buf = wpabuf_alloc(len);
+       if (buf == NULL)
+               return -1;
+       if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
+               wpabuf_free(buf);
+               return -1;
+       }
+
+       ret = wpas_wps_nfc_rx_handover_req(wpa_s, buf);
+       wpabuf_free(buf);
+
+       return ret;
+}
+
+
+static int wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
+                                        char *cmd)
+{
+       size_t len;
+       struct wpabuf *buf;
+       int ret;
+
+       len = os_strlen(cmd);
+       if (len & 0x01)
+               return -1;
+       len /= 2;
+
+       buf = wpabuf_alloc(len);
+       if (buf == NULL)
+               return -1;
+       if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
+               wpabuf_free(buf);
+               return -1;
+       }
+
+       ret = wpas_wps_nfc_rx_handover_sel(wpa_s, buf);
+       wpabuf_free(buf);
+
+       return ret;
+}
+
 #endif /* CONFIG_WPS_NFC */
 
 
@@ -1146,6 +1400,45 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
                        return pos - buf;
                pos += ret;
        }
+
+       if (wpa_s->current_ssid) {
+               struct wpa_cred *cred;
+               char *type;
+
+               for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
+                       if (wpa_s->current_ssid->parent_cred != cred)
+                               continue;
+                       if (!cred->domain)
+                               continue;
+
+                       ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
+                                         cred->domain);
+                       if (ret < 0 || ret >= end - pos)
+                               return pos - buf;
+                       pos += ret;
+
+                       if (wpa_s->current_bss == NULL ||
+                           wpa_s->current_bss->anqp == NULL)
+                               res = -1;
+                       else
+                               res = interworking_home_sp_cred(
+                                       wpa_s, cred,
+                                       wpa_s->current_bss->anqp->domain_name);
+                       if (res > 0)
+                               type = "home";
+                       else if (res == 0)
+                               type = "roaming";
+                       else
+                               type = "unknown";
+
+                       ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
+                       if (ret < 0 || ret >= end - pos)
+                               return pos - buf;
+                       pos += ret;
+
+                       break;
+               }
+       }
 #endif /* CONFIG_HS20 */
 
        if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
@@ -1849,8 +2142,8 @@ static int wpa_supplicant_ctrl_iface_remove_network(
 #endif /* CONFIG_SME */
                        wpa_sm_set_config(wpa_s->wpa, NULL);
                        eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
-                       wpa_supplicant_disassociate(wpa_s,
-                                                   WLAN_REASON_DEAUTH_LEAVING);
+                       wpa_supplicant_deauthenticate(
+                               wpa_s, WLAN_REASON_DEAUTH_LEAVING);
                }
                return 0;
        }
@@ -1882,7 +2175,8 @@ static int wpa_supplicant_ctrl_iface_remove_network(
                wpa_sm_set_config(wpa_s->wpa, NULL);
                eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
 
-               wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+               wpa_supplicant_deauthenticate(wpa_s,
+                                             WLAN_REASON_DEAUTH_LEAVING);
        }
 
        if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
@@ -1932,7 +2226,9 @@ static int wpa_supplicant_ctrl_iface_set_network(
                return -1;
        }
 
-       wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+       if (os_strcmp(name, "bssid") != 0 &&
+           os_strcmp(name, "priority") != 0)
+               wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
 
        if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
                /*
@@ -2049,20 +2345,62 @@ static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
 }
 
 
+static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
+                                struct wpa_cred *cred)
+{
+       struct wpa_ssid *ssid;
+       char str[20];
+
+       if (cred == NULL || wpa_config_remove_cred(wpa_s->conf, cred->id) < 0) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
+               return -1;
+       }
+
+       /* Remove any network entry created based on the removed credential */
+       ssid = wpa_s->conf->ssid;
+       while (ssid) {
+               if (ssid->parent_cred == cred) {
+                       wpa_printf(MSG_DEBUG, "Remove network id %d since it "
+                                  "used the removed credential", ssid->id);
+                       os_snprintf(str, sizeof(str), "%d", ssid->id);
+                       ssid = ssid->next;
+                       wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
+               } else
+                       ssid = ssid->next;
+       }
+
+       return 0;
+}
+
+
 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
                                                 char *cmd)
 {
        int id;
-       struct wpa_cred *cred;
+       struct wpa_cred *cred, *prev;
 
-       /* cmd: "<cred id>" or "all" */
+       /* cmd: "<cred id>", "all", or "sp_fqdn=<FQDN>" */
        if (os_strcmp(cmd, "all") == 0) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
                cred = wpa_s->conf->cred;
                while (cred) {
-                       id = cred->id;
+                       prev = cred;
+                       cred = cred->next;
+                       wpas_ctrl_remove_cred(wpa_s, prev);
+               }
+               return 0;
+       }
+
+       if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
+                          cmd + 8);
+               cred = wpa_s->conf->cred;
+               while (cred) {
+                       prev = cred;
                        cred = cred->next;
-                       wpa_config_remove_cred(wpa_s->conf, id);
+                       if (prev->domain &&
+                           os_strcmp(prev->domain, cmd + 8) == 0)
+                               wpas_ctrl_remove_cred(wpa_s, prev);
                }
                return 0;
        }
@@ -2071,14 +2409,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
 
        cred = wpa_config_get_cred(wpa_s->conf, id);
-       if (cred == NULL ||
-           wpa_config_remove_cred(wpa_s->conf, id) < 0) {
-               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
-                          id);
-               return -1;
-       }
-
-       return 0;
+       return wpas_ctrl_remove_cred(wpa_s, cred);
 }
 
 
@@ -3117,7 +3448,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
        auth = os_strstr(pos, " auth") != NULL;
        automatic = os_strstr(pos, " auto") != NULL;
        pd = os_strstr(pos, " provdisc") != NULL;
-       ht40 = os_strstr(pos, " ht40") != NULL;
+       ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
 
        pos2 = os_strstr(pos, " go_intent=");
        if (pos2) {
@@ -3548,7 +3879,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
                        return -1;
        }
 
-       ht40 = os_strstr(cmd, " ht40") != NULL;
+       ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
 
        return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40);
 }
@@ -3624,7 +3955,7 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
        if (pos)
                freq = atoi(pos + 5);
 
-       ht40 = os_strstr(cmd, "ht40") != NULL;
+       ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
 
        if (os_strncmp(cmd, "persistent=", 11) == 0)
                return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
@@ -3652,6 +3983,7 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
        char *pos, *end;
        char devtype[WPS_DEV_TYPE_BUFSIZE];
        struct wpa_ssid *ssid;
+       size_t i;
 
        if (!wpa_s->global->p2p)
                return -1;
@@ -3705,6 +4037,18 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
                return pos - buf;
        pos += res;
 
+       for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
+       {
+               const u8 *t;
+               t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
+               res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
+                                 wps_dev_type_bin2str(t, devtype,
+                                                      sizeof(devtype)));
+               if (res < 0 || res >= end - pos)
+                       return pos - buf;
+               pos += res;
+       }
+
        ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
        if (ssid) {
                res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
@@ -3933,6 +4277,30 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
        if (os_strcmp(cmd, "disallow_freq") == 0)
                return p2p_ctrl_disallow_freq(wpa_s, param);
 
+       if (os_strcmp(cmd, "disc_int") == 0) {
+               int min_disc_int, max_disc_int, max_disc_tu;
+               char *pos;
+
+               pos = param;
+
+               min_disc_int = atoi(pos);
+               pos = os_strchr(pos, ' ');
+               if (pos == NULL)
+                       return -1;
+               *pos++ = '\0';
+
+               max_disc_int = atoi(pos);
+               pos = os_strchr(pos, ' ');
+               if (pos == NULL)
+                       return -1;
+               *pos++ = '\0';
+
+               max_disc_tu = atoi(pos);
+
+               return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
+                                       max_disc_int, max_disc_tu);
+       }
+
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
                   cmd);
 
@@ -4351,7 +4719,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        int reply_len;
 
        if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
-           os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
+           os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
+           os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
+           os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
                wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
                                      (const u8 *) buf, os_strlen(buf));
        } else {
@@ -4360,6 +4730,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                        level = MSG_EXCESSIVE;
                wpa_hexdump_ascii(level, "RX ctrl_iface",
                                  (const u8 *) buf, os_strlen(buf));
+               wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
        }
 
        reply = os_malloc(reply_size);
@@ -4415,6 +4786,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
                        reply_len = -1;
                else {
+                       wpa_s->extra_blacklist_count = 0;
                        wpa_s->disconnected = 0;
                        wpa_s->reassociate = 1;
                        wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -4425,6 +4797,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
                        reply_len = -1;
                else if (wpa_s->disconnected) {
+                       wpa_s->extra_blacklist_count = 0;
                        wpa_s->disconnected = 0;
                        wpa_s->reassociate = 1;
                        wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -4469,11 +4842,6 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
                if (wpas_wps_cancel(wpa_s))
                        reply_len = -1;
-#ifdef CONFIG_WPS_OOB
-       } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
-               if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
-                       reply_len = -1;
-#endif /* CONFIG_WPS_OOB */
 #ifdef CONFIG_WPS_NFC
        } else if (os_strcmp(buf, "WPS_NFC") == 0) {
                if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
@@ -4488,6 +4856,18 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
                                                               buf + 17))
                        reply_len = -1;
+       } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
+               reply_len = wpas_ctrl_nfc_get_handover_req(
+                       wpa_s, buf + 21, reply, reply_size);
+       } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
+               reply_len = wpas_ctrl_nfc_get_handover_sel(
+                       wpa_s, buf + 21, reply, reply_size);
+       } else if (os_strncmp(buf, "NFC_RX_HANDOVER_REQ ", 20) == 0) {
+               reply_len = wpas_ctrl_nfc_rx_handover_req(
+                       wpa_s, buf + 20, reply, reply_size);
+       } else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) {
+               if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20))
+                       reply_len = -1;
 #endif /* CONFIG_WPS_NFC */
        } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
                if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
@@ -4716,14 +5096,14 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                            ((wpa_s->wpa_state <= WPA_SCANNING) ||
                             (wpa_s->wpa_state == WPA_COMPLETED))) {
                                wpa_s->normal_scans = 0;
-                               wpa_s->scan_req = 2;
+                               wpa_s->scan_req = MANUAL_SCAN_REQ;
                                wpa_supplicant_req_scan(wpa_s, 0, 0);
                        } else if (wpa_s->sched_scanning) {
                                wpa_printf(MSG_DEBUG, "Stop ongoing "
                                           "sched_scan to allow requested "
                                           "full scan to proceed");
                                wpa_supplicant_cancel_sched_scan(wpa_s);
-                               wpa_s->scan_req = 2;
+                               wpa_s->scan_req = MANUAL_SCAN_REQ;
                                wpa_supplicant_req_scan(wpa_s, 0, 0);
                        } else {
                                wpa_printf(MSG_DEBUG, "Ongoing scan action - "