Move network add/remove operations to a common function
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
index 05e28e9..9543fd1 100644 (file)
@@ -15,6 +15,7 @@
 #include "utils/common.h"
 #include "utils/eloop.h"
 #include "utils/uuid.h"
+#include "utils/module_tests.h"
 #include "common/version.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
@@ -420,7 +421,6 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
 #ifdef CONFIG_TDLS
 #ifdef CONFIG_TDLS_TESTING
        } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
-               extern unsigned int tdls_testing;
                tdls_testing = strtol(value, NULL, 0);
                wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
 #endif /* CONFIG_TDLS_TESTING */
@@ -2919,15 +2919,10 @@ static int wpa_supplicant_ctrl_iface_add_network(
 
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
 
-       ssid = wpa_config_add_network(wpa_s->conf);
+       ssid = wpa_supplicant_add_network(wpa_s);
        if (ssid == NULL)
                return -1;
 
-       wpas_notify_network_added(wpa_s, ssid);
-
-       ssid->disabled = 1;
-       wpa_config_set_network_defaults(ssid);
-
        ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
        if (os_snprintf_error(buflen, ret))
                return -1;
@@ -2940,7 +2935,7 @@ static int wpa_supplicant_ctrl_iface_remove_network(
 {
        int id;
        struct wpa_ssid *ssid;
-       int was_disabled;
+       int result;
 
        /* cmd: "<network id>" or "all" */
        if (os_strcmp(cmd, "all") == 0) {
@@ -2976,54 +2971,17 @@ static int wpa_supplicant_ctrl_iface_remove_network(
        id = atoi(cmd);
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
 
-       ssid = wpa_config_get_network(wpa_s->conf, id);
-       if (ssid)
-               wpas_notify_network_removed(wpa_s, ssid);
-       if (ssid == NULL) {
+       result = wpa_supplicant_remove_network(wpa_s, id);
+       if (result == -1) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
                           "id=%d", id);
                return -1;
        }
-
-       if (wpa_s->last_ssid == ssid)
-               wpa_s->last_ssid = NULL;
-
-       if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
-#ifdef CONFIG_SME
-               wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
-               /*
-                * Invalidate the EAP session cache if the current or
-                * previously used network is removed.
-                */
-               eapol_sm_invalidate_cached_session(wpa_s->eapol);
-       }
-
-       if (ssid == wpa_s->current_ssid) {
-               wpa_sm_set_config(wpa_s->wpa, NULL);
-               eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
-
-               if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
-                       wpa_s->own_disconnect_req = 1;
-               wpa_supplicant_deauthenticate(wpa_s,
-                                             WLAN_REASON_DEAUTH_LEAVING);
-       }
-
-       was_disabled = ssid->disabled;
-
-       if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+       if (result == -2) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
                           "network id=%d", id);
                return -1;
        }
-
-       if (!was_disabled && wpa_s->sched_scanning) {
-               wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
-                          "network from filters");
-               wpa_supplicant_cancel_sched_scan(wpa_s);
-               wpa_supplicant_req_scan(wpa_s, 0, 0);
-       }
-
        return 0;
 }
 
@@ -4298,9 +4256,10 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
        if (mask & WPA_BSS_MASK_P2P_SCAN) {
                ie = (const u8 *) (bss + 1);
                ret = wpas_p2p_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_P2P */
 
@@ -4381,9 +4340,10 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
        if (mask & WPA_BSS_MASK_MESH_SCAN) {
                ie = (const u8 *) (bss + 1);
                ret = wpas_mesh_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_MESH */
 
@@ -5098,6 +5058,8 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
                wps_method = WPS_PIN_DISPLAY;
        } else if (os_strncmp(pos, "pbc", 3) == 0) {
                wps_method = WPS_PBC;
+       } else if (os_strstr(pos, "p2ps") != NULL) {
+               wps_method = WPS_P2PS;
        } else {
                pin = pos;
                pos = os_strchr(pin, ' ');
@@ -5106,8 +5068,6 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
                        *pos++ = '\0';
                        if (os_strncmp(pos, "display", 7) == 0)
                                wps_method = WPS_PIN_DISPLAY;
-                       else if (os_strncmp(pos, "p2ps", 4) == 0)
-                               wps_method = WPS_P2PS;
                }
                if (!wps_pin_str_valid(pin)) {
                        os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
@@ -6281,6 +6241,21 @@ static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
        return 0;
 }
 
+
+static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
+{
+       int freq = 0, period = 0, interval = 0, count = 0;
+
+       if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
+       {
+               wpa_printf(MSG_DEBUG,
+                          "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
+               return -1;
+       }
+
+       return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
+}
+
 #endif /* CONFIG_P2P */
 
 
@@ -6981,6 +6956,34 @@ static int wpas_ctrl_iface_get_pref_freq_list(
 }
 
 
+static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
+                                       char *buf, size_t buflen)
+{
+       int ret, i;
+       char *pos, *end;
+
+       ret = os_snprintf(buf, buflen, "%016llX:\n",
+                         (long long unsigned) wpa_s->drv_flags);
+       if (os_snprintf_error(buflen, ret))
+               return -1;
+
+       pos = buf + ret;
+       end = buf + buflen;
+
+       for (i = 0; i < 64; i++) {
+               if (wpa_s->drv_flags & (1LLU << i)) {
+                       ret = os_snprintf(pos, end - pos, "%s\n",
+                                         driver_flag_to_string(1LLU << i));
+                       if (os_snprintf_error(end - pos, ret))
+                               return -1;
+                       pos += ret;
+               }
+       }
+
+       return pos - buf;
+}
+
+
 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
                                      size_t buflen)
 {
@@ -7135,7 +7138,6 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
 
 #ifdef CONFIG_TDLS
 #ifdef CONFIG_TDLS_TESTING
-       extern unsigned int tdls_testing;
        tdls_testing = 0;
 #endif /* CONFIG_TDLS_TESTING */
        wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
@@ -7212,6 +7214,10 @@ 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;
+
+#ifdef CONFIG_SME
+       wpa_s->sme.last_unprot_disconnect.sec = 0;
+#endif /* CONFIG_SME */
 }
 
 
@@ -7268,6 +7274,13 @@ static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
                        eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
                                             work, NULL);
 
+               /*
+                * work->type points to a buffer in ework, so need to replace
+                * that here with a fixed string to avoid use of freed memory
+                * in debug prints.
+                */
+               work->type = "freed-ext-work";
+               work->ctx = NULL;
                os_free(ework);
                return;
        }
@@ -7886,7 +7899,8 @@ static u16 ipv4_hdr_checksum(const void *buf, size_t len)
 #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)
+static 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;
@@ -8062,8 +8076,6 @@ done:
 static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
 {
 #ifdef WPA_TRACE_BFD
-       extern char wpa_trace_fail_func[256];
-       extern unsigned int wpa_trace_fail_after;
        char *pos;
 
        wpa_trace_fail_after = atoi(cmd);
@@ -8086,9 +8098,6 @@ static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
                                    char *buf, size_t buflen)
 {
 #ifdef WPA_TRACE_BFD
-       extern char wpa_trace_fail_func[256];
-       extern unsigned int wpa_trace_fail_after;
-
        return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
                           wpa_trace_fail_func);
 #else /* WPA_TRACE_BFD */
@@ -8100,8 +8109,6 @@ static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
 static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
 {
 #ifdef WPA_TRACE_BFD
-       extern char wpa_trace_test_fail_func[256];
-       extern unsigned int wpa_trace_test_fail_after;
        char *pos;
 
        wpa_trace_test_fail_after = atoi(cmd);
@@ -8124,9 +8131,6 @@ static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s,
                                    char *buf, size_t buflen)
 {
 #ifdef WPA_TRACE_BFD
-       extern char wpa_trace_test_fail_func[256];
-       extern unsigned int wpa_trace_test_fail_after;
-
        return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
                           wpa_trace_test_fail_func);
 #else /* WPA_TRACE_BFD */
@@ -8969,6 +8973,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
                if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
                        reply_len = -1;
+       } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
+               if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
+                       reply_len = -1;
+       } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
+               if (wpas_p2p_lo_stop(wpa_s))
+                       reply_len = -1;
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_WIFI_DISPLAY
        } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
@@ -9033,7 +9043,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (del_hs20_icon(wpa_s, buf + 14) < 0)
                        reply_len = -1;
        } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
-               if (hs20_fetch_osu(wpa_s) < 0)
+               if (hs20_fetch_osu(wpa_s, 0) < 0)
+                       reply_len = -1;
+       } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
+               if (hs20_fetch_osu(wpa_s, 1) < 0)
                        reply_len = -1;
        } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
                hs20_cancel_fetch_osu(wpa_s);
@@ -9072,16 +9085,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                reply_len = wpa_supplicant_ctrl_iface_list_networks(
                        wpa_s, NULL, reply, reply_size);
        } else if (os_strcmp(buf, "DISCONNECT") == 0) {
-#ifdef CONFIG_SME
-               wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
-               wpa_s->reassociate = 0;
-               wpa_s->disconnected = 1;
-               wpa_supplicant_cancel_sched_scan(wpa_s);
-               wpa_supplicant_cancel_scan(wpa_s);
-               wpa_supplicant_deauthenticate(wpa_s,
-                                             WLAN_REASON_DEAUTH_LEAVING);
-               eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+               wpas_request_disconnection(wpa_s);
        } else if (os_strcmp(buf, "SCAN") == 0) {
                wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
        } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
@@ -9244,6 +9248,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
                        reply_len = -1;
 #endif /* CONFIG_AUTOSCAN */
+       } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
+               reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
+                                                        reply_size);
 #ifdef ANDROID
        } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
                reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
@@ -10023,7 +10030,6 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
                                                          reply_size);
 #ifdef CONFIG_MODULE_TESTS
        } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
-               int wpas_module_tests(void);
                if (wpas_module_tests() < 0)
                        reply_len = -1;
 #endif /* CONFIG_MODULE_TESTS */