Convert ctrl_iface scan_results cmd to use BSS table
[libeap.git] / wpa_supplicant / ctrl_iface.c
index 81c52b3..9706ca7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "common.h"
-#include "eloop.h"
-#include "wpa.h"
-#include "config.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
+#include "eap_peer/eap.h"
 #include "eapol_supp/eapol_supp_sm.h"
+#include "rsn_supp/wpa.h"
+#include "rsn_supp/preauth.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "l2_packet/l2_packet.h"
+#include "wps/wps.h"
+#include "config.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
-#include "ctrl_iface.h"
-#include "l2_packet/l2_packet.h"
-#include "preauth.h"
-#include "pmksa_cache.h"
-#include "wpa_ctrl.h"
-#include "eap_peer/eap.h"
-#include "ieee802_11_defs.h"
 #include "wps_supplicant.h"
-#include "wps/wps.h"
 #include "ibss_rsn.h"
+#include "ap.h"
+#include "notify.h"
+#include "bss.h"
+#include "ctrl_iface.h"
 
-extern struct wpa_driver_ops *wpa_supplicant_drivers[];
+extern struct wpa_driver_ops *wpa_drivers[];
 
 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
                                            char *buf, int len);
@@ -150,18 +153,22 @@ static int wpa_supplicant_ctrl_iface_ft_ds(
 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
                                             char *cmd)
 {
-       u8 bssid[ETH_ALEN];
+       u8 bssid[ETH_ALEN], *_bssid = bssid;
 
        if (cmd == NULL || os_strcmp(cmd, "any") == 0)
-               return wpas_wps_start_pbc(wpa_s, NULL);
-
-       if (hwaddr_aton(cmd, bssid)) {
+               _bssid = NULL;
+       else if (hwaddr_aton(cmd, bssid)) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
                           cmd);
                return -1;
        }
 
-       return wpas_wps_start_pbc(wpa_s, bssid);
+#ifdef CONFIG_AP
+       if (wpa_s->ap_iface)
+               return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
+#endif /* CONFIG_AP */
+
+       return wpas_wps_start_pbc(wpa_s, _bssid);
 }
 
 
@@ -185,6 +192,12 @@ static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
+#ifdef CONFIG_AP
+       if (wpa_s->ap_iface)
+               return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
+                                                buf, buflen);
+#endif /* CONFIG_AP */
+
        if (pin) {
                ret = wpas_wps_start_pin(wpa_s, _bssid, pin);
                if (ret < 0)
@@ -237,6 +250,11 @@ static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
 {
        u8 bssid[ETH_ALEN], *_bssid = bssid;
        char *pin;
+       char *new_ssid;
+       char *new_auth;
+       char *new_encr;
+       char *new_key;
+       struct wps_new_ap_settings ap;
 
        pin = os_strchr(cmd, ' ');
        if (pin == NULL)
@@ -251,8 +269,60 @@ static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
-       return wpas_wps_start_reg(wpa_s, _bssid, pin);
+       new_ssid = os_strchr(pin, ' ');
+       if (new_ssid == NULL)
+               return wpas_wps_start_reg(wpa_s, _bssid, pin, NULL);
+       *new_ssid++ = '\0';
+
+       new_auth = os_strchr(new_ssid, ' ');
+       if (new_auth == NULL)
+               return -1;
+       *new_auth++ = '\0';
+
+       new_encr = os_strchr(new_auth, ' ');
+       if (new_encr == NULL)
+               return -1;
+       *new_encr++ = '\0';
+
+       new_key = os_strchr(new_encr, ' ');
+       if (new_key == NULL)
+               return -1;
+       *new_key++ = '\0';
+
+       os_memset(&ap, 0, sizeof(ap));
+       ap.ssid_hex = new_ssid;
+       ap.auth = new_auth;
+       ap.encr = new_encr;
+       ap.key_hex = new_key;
+       return wpas_wps_start_reg(wpa_s, _bssid, pin, &ap);
+}
+
+
+#ifdef CONFIG_WPS_ER
+static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
+                                               char *cmd)
+{
+       char *uuid = cmd, *pin;
+       pin = os_strchr(uuid, ' ');
+       if (pin == NULL)
+               return -1;
+       *pin++ = '\0';
+       return wpas_wps_er_add_pin(wpa_s, uuid, pin);
+}
+
+
+static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
+                                                 char *cmd)
+{
+       char *uuid = cmd, *pin;
+       pin = os_strchr(uuid, ' ');
+       if (pin == NULL)
+               return -1;
+       *pin++ = '\0';
+       return wpas_wps_er_learn(wpa_s, uuid, pin);
 }
+#endif /* CONFIG_WPS_ER */
+
 #endif /* CONFIG_WPS */
 
 
@@ -404,8 +474,36 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
                                        return pos - buf;
                                pos += ret;
                        }
+
+                       switch (ssid->mode) {
+                       case WPAS_MODE_INFRA:
+                               ret = os_snprintf(pos, end - pos,
+                                                 "mode=station\n");
+                               break;
+                       case WPAS_MODE_IBSS:
+                               ret = os_snprintf(pos, end - pos,
+                                                 "mode=IBSS\n");
+                               break;
+                       case WPAS_MODE_AP:
+                               ret = os_snprintf(pos, end - pos,
+                                                 "mode=AP\n");
+                               break;
+                       default:
+                               ret = 0;
+                               break;
+                       }
+                       if (ret < 0 || ret >= end - pos)
+                               return pos - buf;
+                       pos += ret;
                }
 
+#ifdef CONFIG_AP
+               if (wpa_s->ap_iface) {
+                       pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
+                                                           end - pos,
+                                                           verbose);
+               } else
+#endif /* CONFIG_AP */
                pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
        }
        ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
@@ -665,18 +763,16 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
        return pos;
 }
 
-static char * wpa_supplicant_wps_ie_txt(char *pos, char *end,
-                                       const struct wpa_scan_res *res)
-{
+
 #ifdef CONFIG_WPS
-       struct wpabuf *wps_ie;
+static char * wpa_supplicant_wps_ie_txt_buf(char *pos, char *end,
+                                           struct wpabuf *wps_ie)
+{
        int ret;
        const char *txt;
 
-       wps_ie = wpa_scan_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
        if (wps_ie == NULL)
                return pos;
-
        if (wps_is_selected_pbc_registrar(wps_ie))
                txt = "[WPS-PBC]";
        else if (wps_is_selected_pin_registrar(wps_ie))
@@ -688,15 +784,27 @@ static char * wpa_supplicant_wps_ie_txt(char *pos, char *end,
        if (ret >= 0 && ret < end - pos)
                pos += ret;
        wpabuf_free(wps_ie);
+       return pos;
+}
 #endif /* CONFIG_WPS */
 
+
+static char * wpa_supplicant_wps_ie_txt(char *pos, char *end,
+                                       const struct wpa_bss *bss)
+{
+#ifdef CONFIG_WPS
+       struct wpabuf *wps_ie;
+       wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
+       return wpa_supplicant_wps_ie_txt_buf(pos, end, wps_ie);
+#else /* CONFIG_WPS */
        return pos;
+#endif /* CONFIG_WPS */
 }
 
 
 /* Format one result on one text line into a buffer. */
 static int wpa_supplicant_ctrl_iface_scan_result(
-       const struct wpa_scan_res *res, char *buf, size_t buflen)
+       const struct wpa_bss *bss, char *buf, size_t buflen)
 {
        char *pos, *end;
        int ret;
@@ -706,33 +814,38 @@ static int wpa_supplicant_ctrl_iface_scan_result(
        end = buf + buflen;
 
        ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
-                         MAC2STR(res->bssid), res->freq, res->level);
+                         MAC2STR(bss->bssid), bss->freq, bss->level);
        if (ret < 0 || ret >= end - pos)
                return pos - buf;
        pos += ret;
-       ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
+       ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
        if (ie)
                pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
-       ie2 = wpa_scan_get_ie(res, WLAN_EID_RSN);
+       ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
        if (ie2)
                pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
-       pos = wpa_supplicant_wps_ie_txt(pos, end, res);
-       if (!ie && !ie2 && res->caps & IEEE80211_CAP_PRIVACY) {
+       pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
+       if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
                ret = os_snprintf(pos, end - pos, "[WEP]");
                if (ret < 0 || ret >= end - pos)
                        return pos - buf;
                pos += ret;
        }
-       if (res->caps & IEEE80211_CAP_IBSS) {
+       if (bss->caps & IEEE80211_CAP_IBSS) {
                ret = os_snprintf(pos, end - pos, "[IBSS]");
                if (ret < 0 || ret >= end - pos)
                        return pos - buf;
                pos += ret;
        }
+       if (bss->caps & IEEE80211_CAP_ESS) {
+               ret = os_snprintf(pos, end - pos, "[ESS]");
+               if (ret < 0 || ret >= end - pos)
+                       return pos - buf;
+               pos += ret;
+       }
 
-       ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
        ret = os_snprintf(pos, end - pos, "\t%s",
-                         ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
+                         wpa_ssid_txt(bss->ssid, bss->ssid_len));
        if (ret < 0 || ret >= end - pos)
                return pos - buf;
        pos += ret;
@@ -750,13 +863,8 @@ static int wpa_supplicant_ctrl_iface_scan_results(
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 {
        char *pos, *end;
-       struct wpa_scan_res *res;
+       struct wpa_bss *bss;
        int ret;
-       size_t i;
-
-       if (wpa_s->scan_res == NULL &&
-           wpa_supplicant_get_scan_results(wpa_s) < 0)
-               return 0;
 
        pos = buf;
        end = buf + buflen;
@@ -766,9 +874,8 @@ static int wpa_supplicant_ctrl_iface_scan_results(
                return pos - buf;
        pos += ret;
 
-       for (i = 0; i < wpa_s->scan_res->num; i++) {
-               res = wpa_s->scan_res->res[i];
-               ret = wpa_supplicant_ctrl_iface_scan_result(res, pos,
+       dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
+               ret = wpa_supplicant_ctrl_iface_scan_result(bss, pos,
                                                            end - pos);
                if (ret < 0 || ret >= end - pos)
                        return pos - buf;
@@ -788,37 +895,20 @@ static int wpa_supplicant_ctrl_iface_select_network(
        /* cmd: "<network id>" or "any" */
        if (os_strcmp(cmd, "any") == 0) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
-               ssid = wpa_s->conf->ssid;
-               while (ssid) {
-                       ssid->disabled = 0;
-                       ssid = ssid->next;
-               }
-               wpa_s->reassociate = 1;
-               wpa_supplicant_req_scan(wpa_s, 0, 0);
-               return 0;
-       }
-
-       id = atoi(cmd);
-       wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
+               ssid = NULL;
+       } else {
+               id = atoi(cmd);
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
 
-       ssid = wpa_config_get_network(wpa_s->conf, id);
-       if (ssid == NULL) {
-               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
-                          "id=%d", id);
-               return -1;
+               ssid = wpa_config_get_network(wpa_s->conf, id);
+               if (ssid == NULL) {
+                       wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
+                                  "network id=%d", id);
+                       return -1;
+               }
        }
 
-       if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
-               wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
-
-       /* Mark all other networks disabled and trigger reassociation */
-       ssid = wpa_s->conf->ssid;
-       while (ssid) {
-               ssid->disabled = id != ssid->id;
-               ssid = ssid->next;
-       }
-       wpa_s->reassociate = 1;
-       wpa_supplicant_req_scan(wpa_s, 0, 0);
+       wpa_supplicant_select_network(wpa_s, ssid);
 
        return 0;
 }
@@ -833,36 +923,19 @@ static int wpa_supplicant_ctrl_iface_enable_network(
        /* cmd: "<network id>" or "all" */
        if (os_strcmp(cmd, "all") == 0) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
-               ssid = wpa_s->conf->ssid;
-               while (ssid) {
-                       if (ssid == wpa_s->current_ssid && ssid->disabled)
-                               wpa_s->reassociate = 1;
-                       ssid->disabled = 0;
-                       ssid = ssid->next;
-               }
-               if (wpa_s->reassociate)
-                       wpa_supplicant_req_scan(wpa_s, 0, 0);
-               return 0;
-       }
-
-       id = atoi(cmd);
-       wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
-
-       ssid = wpa_config_get_network(wpa_s->conf, id);
-       if (ssid == NULL) {
-               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
-                          "id=%d", id);
-               return -1;
-       }
+               ssid = NULL;
+       } else {
+               id = atoi(cmd);
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
 
-       if (wpa_s->current_ssid == NULL && ssid->disabled) {
-               /*
-                * Try to reassociate since there is no current configuration
-                * and a new network was made available. */
-               wpa_s->reassociate = 1;
-               wpa_supplicant_req_scan(wpa_s, 0, 0);
+               ssid = wpa_config_get_network(wpa_s->conf, id);
+               if (ssid == NULL) {
+                       wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
+                                  "network id=%d", id);
+                       return -1;
+               }
        }
-       ssid->disabled = 0;
+       wpa_supplicant_enable_network(wpa_s, ssid);
 
        return 0;
 }
@@ -877,30 +950,19 @@ static int wpa_supplicant_ctrl_iface_disable_network(
        /* cmd: "<network id>" or "all" */
        if (os_strcmp(cmd, "all") == 0) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
-               ssid = wpa_s->conf->ssid;
-               while (ssid) {
-                       ssid->disabled = 1;
-                       ssid = ssid->next;
-               }
-               if (wpa_s->current_ssid)
-                       wpa_supplicant_disassociate(wpa_s,
-                                                   WLAN_REASON_DEAUTH_LEAVING);
-               return 0;
-       }
-
-       id = atoi(cmd);
-       wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
+               ssid = NULL;
+       } else {
+               id = atoi(cmd);
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
 
-       ssid = wpa_config_get_network(wpa_s->conf, id);
-       if (ssid == NULL) {
-               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
-                          "id=%d", id);
-               return -1;
+               ssid = wpa_config_get_network(wpa_s->conf, id);
+               if (ssid == NULL) {
+                       wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
+                                  "network id=%d", id);
+                       return -1;
+               }
        }
-
-       if (ssid == wpa_s->current_ssid)
-               wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
-       ssid->disabled = 1;
+       wpa_supplicant_disable_network(wpa_s, ssid);
 
        return 0;
 }
@@ -917,6 +979,9 @@ static int wpa_supplicant_ctrl_iface_add_network(
        ssid = wpa_config_add_network(wpa_s->conf);
        if (ssid == NULL)
                return -1;
+
+       wpas_notify_network_added(wpa_s, ssid);
+
        ssid->disabled = 1;
        wpa_config_set_network_defaults(ssid);
 
@@ -938,8 +1003,10 @@ static int wpa_supplicant_ctrl_iface_remove_network(
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
                ssid = wpa_s->conf->ssid;
                while (ssid) {
+                       struct wpa_ssid *remove_ssid = ssid;
                        id = ssid->id;
                        ssid = ssid->next;
+                       wpas_notify_network_removed(wpa_s, remove_ssid);
                        wpa_config_remove_network(wpa_s->conf, id);
                }
                if (wpa_s->current_ssid) {
@@ -1410,36 +1477,49 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
 {
        u8 bssid[ETH_ALEN];
        size_t i;
-       struct wpa_scan_results *results;
-       struct wpa_scan_res *bss;
+       struct wpa_bss *bss;
        int ret;
        char *pos, *end;
        const u8 *ie, *ie2;
 
-       if (wpa_s->scan_res == NULL &&
-           wpa_supplicant_get_scan_results(wpa_s) < 0)
-               return 0;
-
-       results = wpa_s->scan_res;
-       if (results == NULL)
-               return 0;
-
-       if (hwaddr_aton(cmd, bssid) == 0) {
-               for (i = 0; i < results->num; i++) {
-                       if (os_memcmp(bssid, results->res[i]->bssid, ETH_ALEN)
-                           == 0)
-                               break;
+       if (os_strcmp(cmd, "FIRST") == 0)
+               bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
+       else if (os_strncmp(cmd, "ID-", 3) == 0) {
+               i = atoi(cmd + 3);
+               bss = wpa_bss_get_id(wpa_s, i);
+       } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
+               i = atoi(cmd + 5);
+               bss = wpa_bss_get_id(wpa_s, i);
+               if (bss) {
+                       struct dl_list *next = bss->list_id.next;
+                       if (next == &wpa_s->bss_id)
+                               bss = NULL;
+                       else
+                               bss = dl_list_entry(next, struct wpa_bss,
+                                                   list_id);
                }
-       } else
+       } else if (hwaddr_aton(cmd, bssid) == 0)
+               bss = wpa_bss_get_bssid(wpa_s, bssid);
+       else {
+               struct wpa_bss *tmp;
                i = atoi(cmd);
+               bss = NULL;
+               dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
+               {
+                       if (i-- == 0) {
+                               bss = tmp;
+                               break;
+                       }
+               }
+       }
 
-       if (i >= results->num || results->res[i] == NULL)
-               return 0; /* no match found */
+       if (bss == NULL)
+               return 0;
 
-       bss = results->res[i];
        pos = buf;
        end = buf + buflen;
        ret = os_snprintf(pos, end - pos,
+                         "id=%u\n"
                          "bssid=" MACSTR "\n"
                          "freq=%d\n"
                          "beacon_int=%d\n"
@@ -1449,6 +1529,7 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
                          "level=%d\n"
                          "tsf=%016llu\n"
                          "ie=",
+                         bss->id,
                          MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
                          bss->caps, bss->qual, bss->noise, bss->level,
                          (unsigned long long) bss->tsf);
@@ -1474,10 +1555,10 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
                return pos - buf;
        pos += ret;
 
-       ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+       ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
        if (ie)
                pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
-       ie2 = wpa_scan_get_ie(bss, WLAN_EID_RSN);
+       ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
        if (ie2)
                pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
        pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
@@ -1493,19 +1574,32 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
                        return pos - buf;
                pos += ret;
        }
+       if (bss->caps & IEEE80211_CAP_ESS) {
+               ret = os_snprintf(pos, end - pos, "[ESS]");
+               if (ret < 0 || ret >= end - pos)
+                       return pos - buf;
+               pos += ret;
+       }
 
        ret = os_snprintf(pos, end - pos, "\n");
        if (ret < 0 || ret >= end - pos)
                return pos - buf;
        pos += ret;
 
-       ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
        ret = os_snprintf(pos, end - pos, "ssid=%s\n",
-                         ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
+                         wpa_ssid_txt(bss->ssid, bss->ssid_len));
        if (ret < 0 || ret >= end - pos)
                return pos - buf;
        pos += ret;
 
+#ifdef CONFIG_WPS
+       ie = (const u8 *) (bss + 1);
+       ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
+       if (ret < 0 || ret >= end - pos)
+               return pos - buf;
+       pos += ret;
+#endif /* CONFIG_WPS */
+
        return pos - buf;
 }
 
@@ -1514,11 +1608,7 @@ static int wpa_supplicant_ctrl_iface_ap_scan(
        struct wpa_supplicant *wpa_s, char *cmd)
 {
        int ap_scan = atoi(cmd);
-
-       if (ap_scan < 0 || ap_scan > 2)
-               return -1;
-       wpa_s->conf->ap_scan = ap_scan;
-       return 0;
+       return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
 }
 
 
@@ -1619,6 +1709,23 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
                if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
                        reply_len = -1;
+#ifdef CONFIG_WPS_ER
+       } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
+               if (wpas_wps_er_start(wpa_s))
+                       reply_len = -1;
+       } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
+               if (wpas_wps_er_stop(wpa_s))
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
+               if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
+               if (wpas_wps_er_pbc(wpa_s, buf + 11))
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
+               if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
+                       reply_len = -1;
+#endif /* CONFIG_WPS_ER */
 #endif /* CONFIG_WPS */
 #ifdef CONFIG_IBSS_RSN
        } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
@@ -1636,7 +1743,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (wpa_supplicant_reload_configuration(wpa_s))
                        reply_len = -1;
        } else if (os_strcmp(buf, "TERMINATE") == 0) {
-               eloop_terminate();
+               wpa_supplicant_terminate_proc(wpa_s->global);
        } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
                if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
                        reply_len = -1;
@@ -1694,6 +1801,16 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "BSS ", 4) == 0) {
                reply_len = wpa_supplicant_ctrl_iface_bss(
                        wpa_s, buf + 4, reply, reply_size);
+#ifdef CONFIG_AP
+       } else if (os_strcmp(buf, "STA-FIRST") == 0) {
+               reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
+       } else if (os_strncmp(buf, "STA ", 4) == 0) {
+               reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
+                                             reply_size);
+       } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
+               reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
+                                                  reply_size);
+#endif /* CONFIG_AP */
        } else {
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
                reply_len = 16;
@@ -1825,8 +1942,8 @@ static int wpa_supplicant_global_iface_list(struct wpa_global *global,
        struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
        char *pos, *end;
 
-       for (i = 0; wpa_supplicant_drivers[i]; i++) {
-               struct wpa_driver_ops *drv = wpa_supplicant_drivers[i];
+       for (i = 0; wpa_drivers[i]; i++) {
+               struct wpa_driver_ops *drv = wpa_drivers[i];
                if (drv->get_interfaces == NULL)
                        continue;
                tmp = drv->get_interfaces(global->drv_priv);
@@ -1919,7 +2036,7 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
                reply_len = wpa_supplicant_global_iface_interfaces(
                        global, reply, reply_size);
        } else if (os_strcmp(buf, "TERMINATE") == 0) {
-               eloop_terminate();
+               wpa_supplicant_terminate_proc(global);
        } else {
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
                reply_len = 16;