Declare all read only data structures as const
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
index 428a496..91617fb 100644 (file)
@@ -153,7 +153,8 @@ static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
                        }
                        ssid = ns;
 
-                       if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
+                       if ((end - pos) & 0x01 ||
+                           end - pos > 2 * SSID_MAX_LEN ||
                            hexstr2bin(pos, ssid[ssid_count].ssid,
                                       (end - pos) / 2) < 0) {
                                os_free(ssid);
@@ -209,6 +210,7 @@ static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
        wpa_s->sme.prev_bssid_set = 0;
 #endif /* CONFIG_SME */
        wpa_s->reassociate = 1;
+       wpa_s->own_disconnect_req = 1;
        wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
        wpa_supplicant_req_scan(wpa_s, 0, 0);
 
@@ -498,6 +500,8 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_TESTING_GET_GTK */
        } else if (os_strcmp(cmd, "tls_library") == 0) {
                res = tls_get_library_version(buf, buflen);
+       } else {
+               res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
        }
 
        if (os_snprintf_error(buflen, res))
@@ -1725,7 +1729,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
                if (ssid) {
                        u8 *_ssid = ssid->ssid;
                        size_t ssid_len = ssid->ssid_len;
-                       u8 ssid_buf[MAX_SSID_LEN];
+                       u8 ssid_buf[SSID_MAX_LEN];
                        if (ssid_len == 0) {
                                int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
                                if (_res < 0)
@@ -2363,6 +2367,14 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
        }
 #endif /* CONFIG_SUITEB192 */
 
+       if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
+               ret = os_snprintf(pos, end - pos, "%sOSEN",
+                                 pos == start ? "" : "+");
+               if (os_snprintf_error(end - pos, ret))
+                       return pos;
+               pos += ret;
+       }
+
        pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
 
        if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
@@ -2430,7 +2442,7 @@ static int wpa_supplicant_ctrl_iface_scan_result(
 {
        char *pos, *end;
        int ret;
-       const u8 *ie, *ie2, *p2p, *mesh;
+       const u8 *ie, *ie2, *osen_ie, *p2p, *mesh;
 
        mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
        p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
@@ -2457,8 +2469,12 @@ static int wpa_supplicant_ctrl_iface_scan_result(
                pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
                                            ie2, 2 + ie2[1]);
        }
+       osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+       if (osen_ie)
+               pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
+                                           osen_ie, 2 + osen_ie[1]);
        pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
-       if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
+       if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
                ret = os_snprintf(pos, end - pos, "[WEP]");
                if (os_snprintf_error(end - pos, ret))
                        return -1;
@@ -2833,6 +2849,7 @@ 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_s->own_disconnect_req = 1;
                        wpa_supplicant_deauthenticate(
                                wpa_s, WLAN_REASON_DEAUTH_LEAVING);
                }
@@ -2879,6 +2896,7 @@ 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_s->own_disconnect_req = 1;
                wpa_supplicant_deauthenticate(wpa_s,
                                              WLAN_REASON_DEAUTH_LEAVING);
        }
@@ -2930,8 +2948,6 @@ 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;
 }
@@ -3934,7 +3950,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
        size_t i;
        int ret;
        char *pos, *end;
-       const u8 *ie, *ie2;
+       const u8 *ie, *ie2, *osen_ie;
 
        pos = buf;
        end = buf + buflen;
@@ -4051,8 +4067,13 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                if (ie2)
                        pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
                                                    2 + ie2[1]);
+               osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+               if (osen_ie)
+                       pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
+                                                   osen_ie, 2 + osen_ie[1]);
                pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
-               if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
+               if (!ie && !ie2 && !osen_ie &&
+                   (bss->caps & IEEE80211_CAP_PRIVACY)) {
                        ret = os_snprintf(pos, end - pos, "[WEP]");
                        if (os_snprintf_error(end - pos, ret))
                                return 0;
@@ -4176,6 +4197,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;
+               pos = anqp_add_hex(pos, end, "anqp_capability_list",
+                                  anqp->capability_list);
                pos = anqp_add_hex(pos, end, "anqp_venue_name",
                                   anqp->venue_name);
                pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
@@ -4190,6 +4213,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                pos = anqp_add_hex(pos, end, "anqp_domain_name",
                                   anqp->domain_name);
 #ifdef CONFIG_HS20
+               pos = anqp_add_hex(pos, end, "hs20_capability_list",
+                                  anqp->hs20_capability_list);
                pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
                                   anqp->hs20_operator_friendly_name);
                pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
@@ -4214,6 +4239,21 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
        }
 #endif /* CONFIG_MESH */
 
+       if (mask & WPA_BSS_MASK_SNR) {
+               ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
+               if (os_snprintf_error(end - pos, ret))
+                       return 0;
+               pos += ret;
+       }
+
+       if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
+               ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
+                                 bss->est_throughput);
+               if (os_snprintf_error(end - pos, ret))
+                       return 0;
+               pos += ret;
+       }
+
        if (mask & WPA_BSS_MASK_DELIM) {
                ret = os_snprintf(pos, end - pos, "====\n");
                if (os_snprintf_error(end - pos, ret))
@@ -4489,8 +4529,9 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
        u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
        char *pos;
        unsigned int search_delay;
-       const char *seek[P2P_MAX_QUERY_HASH + 1];
+       const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
        u8 seek_count = 0;
+       int freq = 0;
 
        if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
                wpa_dbg(wpa_s, MSG_INFO,
@@ -4531,27 +4572,28 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
                char *term;
 
                term = os_strchr(pos + 1, ' ');
-               seek[seek_count++] = pos + 6;
+               _seek[seek_count++] = pos + 6;
+               seek = _seek;
                pos = os_strstr(pos + 6, " seek=");
 
                if (term)
                        *term = '\0';
        }
-
-       if (!seek_count)
-               return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL,
-                                    _dev_type, _dev_id,
-                                    search_delay, 0, NULL);
-
        if (seek_count > P2P_MAX_QUERY_HASH) {
                seek[0] = NULL;
-               return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL,
-                                    _dev_type, _dev_id,
-                                    search_delay, 1, seek);
+               seek_count = 1;
+       }
+
+       pos = os_strstr(cmd, "freq=");
+       if (pos) {
+               pos += 5;
+               freq = atoi(pos);
+               if (freq <= 0)
+                       return -1;
        }
 
        return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
-                            _dev_id, search_delay, seek_count, seek);
+                            _dev_id, search_delay, seek_count, seek, freq);
 }
 
 
@@ -4720,10 +4762,18 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
        int pd;
        int ht40, vht;
 
+       if (!wpa_s->global->p2p_init_wpa_s)
+               return -1;
+       if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
+                       wpa_s->global->p2p_init_wpa_s->ifname);
+               wpa_s = wpa_s->global->p2p_init_wpa_s;
+       }
+
        /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
         * [persistent|persistent=<network id>]
         * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
-        * [ht40] [vht] */
+        * [ht40] [vht] [auto] */
 
        if (hwaddr_aton(cmd, addr))
                return -1;
@@ -5267,6 +5317,11 @@ static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
 {
        u32 adv_id;
 
+       if (os_strcmp(cmd, "all") == 0) {
+               wpas_p2p_service_flush_asp(wpa_s);
+               return 0;
+       }
+
        if (sscanf(cmd, "%x", &adv_id) != 1)
                return -1;
 
@@ -5948,7 +6003,8 @@ static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
 }
 
 
-static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
+static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
+                                    int only_add)
 {
        u8 bssid[ETH_ALEN];
        struct wpa_bss *bss;
@@ -5986,7 +6042,7 @@ static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
                           "Found another matching BSS entry with SSID");
        }
 
-       return interworking_connect(wpa_s, bss);
+       return interworking_connect(wpa_s, bss, only_add);
 }
 
 
@@ -6443,6 +6499,14 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
                pos += ret;
        }
 
+       if (si.avg_beacon_signal) {
+               ret = os_snprintf(pos, end - pos,
+                                 "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal);
+               if (os_snprintf_error(end - pos, ret))
+                       return -1;
+               pos += ret;
+       }
+
        return pos - buf;
 }
 
@@ -6598,6 +6662,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
        wpa_supplicant_stop_countermeasures(wpa_s, NULL);
 
        wpa_s->no_keep_alive = 0;
+       wpa_s->own_disconnect_req = 0;
 
        os_free(wpa_s->disallow_aps_bssid);
        wpa_s->disallow_aps_bssid = NULL;
@@ -6655,6 +6720,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
                           MAC2STR(wpa_s->bssid),
                           MAC2STR(wpa_s->pending_bssid));
        }
+
+       eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
 }
 
 
@@ -6901,6 +6968,15 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
                return;
        }
 
+#ifdef CONFIG_INTERWORKING
+       if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
+               wpa_printf(MSG_DEBUG,
+                          "Interworking select in progress - reject new scan");
+               *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
+               return;
+       }
+#endif /* CONFIG_INTERWORKING */
+
        if (params) {
                if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
                        scan_only = 1;
@@ -7631,7 +7707,7 @@ static int wpas_ctrl_iface_send_neigbor_rep(struct wpa_supplicant *wpa_s,
 
        if (os_strncmp(cmd, " ssid=", 6) == 0) {
                ssid.ssid_len = os_strlen(cmd + 6);
-               if (ssid.ssid_len > 32)
+               if (ssid.ssid_len > SSID_MAX_LEN)
                        return -1;
                ssid.ssid = (u8 *) (cmd + 6);
                ssid_p = &ssid;
@@ -7839,6 +7915,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "SET ", 4) == 0) {
                if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
                        reply_len = -1;
+       } else if (os_strncmp(buf, "DUMP", 4) == 0) {
+               reply_len = wpa_config_dump_values(wpa_s->conf,
+                                                  reply, reply_size);
        } else if (os_strncmp(buf, "GET ", 4) == 0) {
                reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
                                                          reply, reply_size);
@@ -8121,8 +8200,19 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
                        reply_len = -1;
        } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
-               if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
+               if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
                        reply_len = -1;
+       } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
+               int id;
+
+               id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
+               if (id < 0)
+                       reply_len = -1;
+               else {
+                       reply_len = os_snprintf(reply, reply_size, "%d\n", id);
+                       if (os_snprintf_error(reply_size, reply_len))
+                               reply_len = -1;
+               }
        } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
                if (get_anqp(wpa_s, buf + 9) < 0)
                        reply_len = -1;
@@ -8192,6 +8282,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *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);
        } 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) {
@@ -8280,6 +8371,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
                if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
                        reply_len = -1;
+       } else if (os_strcmp(buf, "STOP_AP") == 0) {
+               if (wpas_ap_stop_ap(wpa_s))
+                       reply_len = -1;
 #endif /* CONFIG_AP */
        } else if (os_strcmp(buf, "SUSPEND") == 0) {
                wpas_notify_suspend(wpa_s->global);
@@ -8428,11 +8522,14 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
                                           char *cmd)
 {
        struct wpa_interface iface;
-       char *pos;
+       char *pos, *extra;
+       struct wpa_supplicant *wpa_s;
+       unsigned int create_iface = 0;
+       u8 mac_addr[ETH_ALEN];
 
        /*
         * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
-        * TAB<bridge_ifname>
+        * TAB<bridge_ifname>[TAB<create>]
         */
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
 
@@ -8492,12 +8589,54 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
                        iface.bridge_ifname = NULL;
                if (pos == NULL)
                        break;
+
+               extra = pos;
+               pos = os_strchr(pos, '\t');
+               if (pos)
+                       *pos++ = '\0';
+               if (!extra[0])
+                       break;
+
+               if (os_strcmp(extra, "create") == 0)
+                       create_iface = 1;
+               else {
+                       wpa_printf(MSG_DEBUG,
+                                  "INTERFACE_ADD unsupported extra parameter: '%s'",
+                                  extra);
+                       return -1;
+               }
        } while (0);
 
+       if (create_iface) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
+                          iface.ifname);
+               if (!global->ifaces)
+                       return -1;
+               if (wpa_drv_if_add(global->ifaces, WPA_IF_STATION, iface.ifname,
+                                  NULL, NULL, NULL, mac_addr, NULL) < 0) {
+                       wpa_printf(MSG_ERROR,
+                                  "CTRL_IFACE interface creation failed");
+                       return -1;
+               }
+
+               wpa_printf(MSG_DEBUG,
+                          "CTRL_IFACE interface '%s' created with MAC addr: "
+                          MACSTR, iface.ifname, MAC2STR(mac_addr));
+       }
+
        if (wpa_supplicant_get_iface(global, iface.ifname))
-               return -1;
+               goto fail;
 
-       return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
+       wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
+       if (!wpa_s)
+               goto fail;
+       wpa_s->added_vif = create_iface;
+       return 0;
+
+fail:
+       if (create_iface)
+               wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
+       return -1;
 }
 
 
@@ -8505,13 +8644,22 @@ static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
                                              char *cmd)
 {
        struct wpa_supplicant *wpa_s;
+       int ret;
+       unsigned int delete_iface;
 
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
 
        wpa_s = wpa_supplicant_get_iface(global, cmd);
        if (wpa_s == NULL)
                return -1;
-       return wpa_supplicant_remove_iface(global, wpa_s, 0);
+       delete_iface = wpa_s->added_vif;
+       ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
+       if (!ret && delete_iface) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
+                          cmd);
+               ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
+       }
+       return ret;
 }
 
 
@@ -8538,7 +8686,7 @@ static int wpa_supplicant_global_iface_list(struct wpa_global *global,
        char *pos, *end;
 
        for (i = 0; wpa_drivers[i]; i++) {
-               struct wpa_driver_ops *drv = wpa_drivers[i];
+               const struct wpa_driver_ops *drv = wpa_drivers[i];
                if (drv->get_interfaces == NULL)
                        continue;
                tmp = drv->get_interfaces(global->drv_priv[i]);