aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant/ctrl_iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'wpa_supplicant/ctrl_iface.c')
-rw-r--r--wpa_supplicant/ctrl_iface.c260
1 files changed, 243 insertions, 17 deletions
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 041685a..059c586 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -12,6 +12,7 @@
#include "utils/eloop.h"
#include "common/version.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
#include "eap_peer/eap.h"
#include "eapol_supp/eapol_supp_sm.h"
@@ -29,6 +30,7 @@
#include "p2p_supplicant.h"
#include "p2p/p2p.h"
#include "hs20_supplicant.h"
+#include "wifi_display.h"
#include "notify.h"
#include "bss.h"
#include "scan.h"
@@ -98,6 +100,9 @@ static int pno_start(struct wpa_supplicant *wpa_s)
ssid = ssid->next;
}
+ if (wpa_s->conf->filter_rssi)
+ params.filter_rssi = wpa_s->conf->filter_rssi;
+
ret = wpa_drv_sched_scan(wpa_s, &params, 10 * 1000);
os_free(params.filter_ssids);
if (ret == 0)
@@ -130,7 +135,7 @@ static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
os_free(filter);
return -1;
}
- n = os_realloc(filter, (count + 1) * ETH_ALEN);
+ n = os_realloc_array(filter, count + 1, ETH_ALEN);
if (n == NULL) {
os_free(filter);
return -1;
@@ -280,6 +285,10 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
}
} else if (os_strcasecmp(cmd, "ps") == 0) {
ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
+#ifdef CONFIG_WIFI_DISPLAY
+ } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
+ wifi_display_enable(wpa_s->global, !!atoi(value));
+#endif /* CONFIG_WIFI_DISPLAY */
} else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
ret = set_bssid_filter(wpa_s, value);
} else {
@@ -307,6 +316,14 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
res = os_snprintf(buf, buflen, "%c%c",
wpa_s->conf->country[0],
wpa_s->conf->country[1]);
+#ifdef CONFIG_WIFI_DISPLAY
+ } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
+ res = os_snprintf(buf, buflen, "%d",
+ wpa_s->global->wifi_display);
+ if (res < 0 || (unsigned int) res >= buflen)
+ return -1;
+ return res;
+#endif /* CONFIG_WIFI_DISPLAY */
}
if (res < 0 || (unsigned int) res >= buflen)
@@ -1121,7 +1138,9 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_HS20
if (wpa_s->current_bss &&
- wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE)) {
+ wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE) &&
+ wpa_s->wpa_proto == WPA_PROTO_RSN &&
+ wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
ret = os_snprintf(pos, end - pos, "hs20=1\n");
if (ret < 0 || ret >= end - pos)
return pos - buf;
@@ -1377,10 +1396,12 @@ static int wpa_supplicant_ctrl_iface_list_networks(
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
- ret = os_snprintf(pos, end - pos, "\t%s%s%s",
+ ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
ssid == wpa_s->current_ssid ?
"[CURRENT]" : "",
ssid->disabled ? "[DISABLED]" : "",
+ ssid->disabled_until.sec ?
+ "[TEMP-DISABLED]" : "",
ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
"");
if (ret < 0 || ret >= end - pos)
@@ -1441,6 +1462,13 @@ static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
pos += ret;
first = 0;
}
+ if (cipher & WPA_CIPHER_GCMP) {
+ ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : "+");
+ if (ret < 0 || ret >= end - pos)
+ return pos;
+ pos += ret;
+ first = 0;
+ }
return pos;
}
@@ -1640,7 +1668,7 @@ static int wpa_supplicant_ctrl_iface_scan_result(
pos += ret;
}
#ifdef CONFIG_HS20
- if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
+ if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
ret = os_snprintf(pos, end - pos, "[HS20]");
if (ret < 0 || ret >= end - pos)
return -1;
@@ -2163,6 +2191,14 @@ static int ctrl_iface_get_capability_pairwise(int res, char *strict,
first = 0;
}
+ if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
+ ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ first = 0;
+ }
+
if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
if (ret < 0 || ret >= end - pos)
@@ -2211,6 +2247,14 @@ static int ctrl_iface_get_capability_group(int res, char *strict,
first = 0;
}
+ if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
+ ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ first = 0;
+ }
+
if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
if (ret < 0 || ret >= end - pos)
@@ -2406,7 +2450,7 @@ static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
hmode = "A";
break;
default:
- return pos - buf;
+ continue;
}
ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
if (ret < 0 || ret >= end - pos)
@@ -2414,6 +2458,8 @@ static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
pos += ret;
chnl = wpa_s->hw.modes[j].channels;
for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
+ if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
+ continue;
ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
if (ret < 0 || ret >= end - pos)
return pos - buf;
@@ -2715,6 +2761,31 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_WIFI_DISPLAY
+ if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
+ struct wpabuf *wfd;
+ ie = (const u8 *) (bss + 1);
+ wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
+ WFD_IE_VENDOR_TYPE);
+ if (wfd) {
+ ret = os_snprintf(pos, end - pos, "wfd_subelems=");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+
+ pos += wpa_snprintf_hex(pos, end - pos,
+ wpabuf_head(wfd),
+ wpabuf_len(wfd));
+ wpabuf_free(wfd);
+
+ ret = os_snprintf(pos, end - pos, "\n");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ }
+ }
+#endif /* CONFIG_WIFI_DISPLAY */
+
#ifdef CONFIG_INTERWORKING
if (mask & WPA_BSS_MASK_INTERNETW) {
pos = anqp_add_hex(pos, end, "anqp_venue_name",
@@ -2991,6 +3062,7 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
u8 dev_id[ETH_ALEN], *_dev_id = NULL;
char *pos;
+ unsigned int search_delay;
if (os_strstr(cmd, "type=social"))
type = P2P_FIND_ONLY_SOCIAL;
@@ -3005,7 +3077,15 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
_dev_id = dev_id;
}
- return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id);
+ pos = os_strstr(cmd, "delay=");
+ if (pos) {
+ pos += 6;
+ search_delay = atoi(pos);
+ } else
+ search_delay = wpas_p2p_search_delay(wpa_s);
+
+ return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id,
+ search_delay);
}
@@ -3025,10 +3105,12 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
int go_intent = -1;
int freq = 0;
int pd;
+ int ht40;
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
* [persistent|persistent=<network id>]
- * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] */
+ * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
+ * [ht40] */
if (hwaddr_aton(cmd, addr))
return -1;
@@ -3056,6 +3138,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;
pos2 = os_strstr(pos, " go_intent=");
if (pos2) {
@@ -3095,7 +3178,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);
+ auth, go_intent, freq, persistent_id, pd,
+ ht40);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
return 25;
@@ -3195,6 +3279,10 @@ static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
return -1;
pos++;
ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
+#ifdef CONFIG_WIFI_DISPLAY
+ } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
+ ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
+#endif /* CONFIG_WIFI_DISPLAY */
} else {
len = os_strlen(pos);
if (len & 1)
@@ -3517,7 +3605,7 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
- char *cmd, int freq)
+ char *cmd, int freq, int ht40)
{
int id;
struct wpa_ssid *ssid;
@@ -3531,26 +3619,31 @@ 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);
+ return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40);
}
static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
{
- int freq = 0;
+ int freq = 0, ht40;
char *pos;
pos = os_strstr(cmd, "freq=");
if (pos)
freq = atoi(pos + 5);
+ ht40 = os_strstr(cmd, "ht40") != NULL;
+
if (os_strncmp(cmd, "persistent=", 11) == 0)
- return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
+ return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
+ ht40);
if (os_strcmp(cmd, "persistent") == 0 ||
os_strncmp(cmd, "persistent ", 11) == 0)
- return wpas_p2p_group_add(wpa_s, 1, freq);
+ return wpas_p2p_group_add(wpa_s, 1, freq, ht40);
if (os_strncmp(cmd, "freq=", 5) == 0)
- return wpas_p2p_group_add(wpa_s, 0, freq);
+ return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
+ if (ht40)
+ return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
cmd);
@@ -3653,8 +3746,8 @@ static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
*/
pos = param;
while (pos && pos[0]) {
- n = os_realloc(freq,
- (count + 1) * sizeof(struct wpa_freq_range));
+ n = os_realloc_array(freq, count + 1,
+ sizeof(struct wpa_freq_range));
if (n == NULL) {
os_free(freq);
return -1;
@@ -3957,6 +4050,122 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
return anqp_send_req(wpa_s, dst_addr, id, num_id);
}
+
+
+static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ u8 dst_addr[ETH_ALEN];
+ struct wpabuf *advproto, *query = NULL;
+ int used, ret = -1;
+ char *pos, *end;
+ size_t len;
+
+ used = hwaddr_aton2(cmd, dst_addr);
+ if (used < 0)
+ return -1;
+
+ pos = cmd + used;
+ while (*pos == ' ')
+ pos++;
+
+ /* Advertisement Protocol ID */
+ end = os_strchr(pos, ' ');
+ if (end)
+ len = end - pos;
+ else
+ len = os_strlen(pos);
+ if (len & 0x01)
+ return -1;
+ len /= 2;
+ if (len == 0)
+ return -1;
+ advproto = wpabuf_alloc(len);
+ if (advproto == NULL)
+ return -1;
+ if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
+ goto fail;
+
+ if (end) {
+ /* Optional Query Request */
+ pos = end + 1;
+ while (*pos == ' ')
+ pos++;
+
+ len = os_strlen(pos);
+ if (len) {
+ if (len & 0x01)
+ goto fail;
+ len /= 2;
+ if (len == 0)
+ goto fail;
+ query = wpabuf_alloc(len);
+ if (query == NULL)
+ goto fail;
+ if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
+ goto fail;
+ }
+ }
+
+ ret = gas_send_request(wpa_s, dst_addr, advproto, query);
+
+fail:
+ wpabuf_free(advproto);
+ wpabuf_free(query);
+
+ return ret;
+}
+
+
+static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
+ size_t buflen)
+{
+ u8 addr[ETH_ALEN];
+ int dialog_token;
+ int used;
+ char *pos;
+ size_t resp_len, start, requested_len;
+
+ if (!wpa_s->last_gas_resp)
+ return -1;
+
+ used = hwaddr_aton2(cmd, addr);
+ if (used < 0)
+ return -1;
+
+ pos = cmd + used;
+ while (*pos == ' ')
+ pos++;
+ dialog_token = atoi(pos);
+
+ if (os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) != 0 ||
+ dialog_token != wpa_s->last_gas_dialog_token)
+ return -1;
+
+ resp_len = wpabuf_len(wpa_s->last_gas_resp);
+ start = 0;
+ requested_len = resp_len;
+
+ pos = os_strchr(pos, ' ');
+ if (pos) {
+ start = atoi(pos);
+ if (start > resp_len)
+ return os_snprintf(buf, buflen, "FAIL-Invalid range");
+ pos = os_strchr(pos, ',');
+ if (pos == NULL)
+ return -1;
+ pos++;
+ requested_len = atoi(pos);
+ if (start + requested_len > resp_len)
+ return os_snprintf(buf, buflen, "FAIL-Invalid range");
+ }
+
+ if (requested_len * 2 + 1 > buflen)
+ return os_snprintf(buf, buflen, "FAIL-Too long response");
+
+ return wpa_snprintf_hex(buf, buflen,
+ wpabuf_head_u8(wpa_s->last_gas_resp) + start,
+ requested_len);
+}
#endif /* CONFIG_INTERWORKING */
@@ -4185,6 +4394,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (os_strcmp(buf, "PING") == 0) {
os_memcpy(reply, "PONG\n", 5);
reply_len = 5;
+ } else if (os_strcmp(buf, "IFNAME") == 0) {
+ reply_len = os_strlen(wpa_s->ifname);
+ os_memcpy(reply, wpa_s->ifname, reply_len);
} else if (os_strncmp(buf, "RELOG", 5) == 0) {
if (wpa_debug_reopen_file() < 0)
reply_len = -1;
@@ -4375,7 +4587,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (wpas_p2p_group_remove(wpa_s, buf + 17))
reply_len = -1;
} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
- if (wpas_p2p_group_add(wpa_s, 0, 0))
+ if (wpas_p2p_group_add(wpa_s, 0, 0, 0))
reply_len = -1;
} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
if (p2p_ctrl_group_add(wpa_s, buf + 14))
@@ -4447,6 +4659,14 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
reply_len = -1;
#endif /* CONFIG_P2P */
+#ifdef CONFIG_WIFI_DISPLAY
+ } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
+ if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
+ reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
+ reply, reply_size);
+#endif /* CONFIG_WIFI_DISPLAY */
#ifdef CONFIG_INTERWORKING
} else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
if (interworking_fetch_anqp(wpa_s) < 0)
@@ -4463,6 +4683,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
if (get_anqp(wpa_s, buf + 9) < 0)
reply_len = -1;
+ } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
+ if (gas_request(wpa_s, buf + 12) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
+ reply_len = gas_response_get(wpa_s, buf + 17, reply,
+ reply_size);
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {