am 82c2c233: (-s ours) am 26a545dc: Do not try auto connect mechanism in disconnected state, DO NOT MERGE
* commit '82c2c2331d5d0bccf5d49f03347c9a23285a305b':
Do not try auto connect mechanism in disconnected state, DO NOT MERGE
diff --git a/Android.mk b/Android.mk
index 76afb77..4a74b24 100644
--- a/Android.mk
+++ b/Android.mk
@@ -11,3 +11,6 @@
include $(LOCAL_PATH)/hostapd/Android.mk \
$(LOCAL_PATH)/wpa_supplicant/Android.mk
endif
+ifeq ($(WPA_SUPPLICANT_VERSION),VER_2_1_DEVEL)
+include $(call all-subdir-makefiles)
+endif
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0d97a21..7ecbc65 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -57,3 +57,5 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_cli_intermediates/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_supplicant_intermediates/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/hostapd_intermediates/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_supplicant_intermediates/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/hostapd_intermediates/*)
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 1c2e1f5..1054dc0 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -367,6 +367,13 @@
NEED_SHA256=y
endif
+ifdef CONFIG_EAP_EKE
+L_CFLAGS += -DEAP_SERVER_EKE
+OBJS += src/eap_server/eap_server_eke.c src/eap_common/eap_eke_common.c
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+endif
+
ifdef CONFIG_EAP_VENDOR_TEST
L_CFLAGS += -DEAP_SERVER_VENDOR_TEST
OBJS += src/eap_server/eap_server_vendor_test.c
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 8404e0c..a30a244 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -323,6 +323,13 @@
NEED_SHA256=y
endif
+ifdef CONFIG_EAP_EKE
+CFLAGS += -DEAP_SERVER_EKE
+OBJS += ../src/eap_server/eap_server_eke.o ../src/eap_common/eap_eke_common.o
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+endif
+
ifdef CONFIG_EAP_VENDOR_TEST
CFLAGS += -DEAP_SERVER_VENDOR_TEST
OBJS += ../src/eap_server/eap_server_vendor_test.o
@@ -824,6 +831,10 @@
LIBS_h += -lsqlite3
endif
+ifdef CONFIG_TESTING_OPTIONS
+CFLAGS += -DCONFIG_TESTING_OPTIONS
+endif
+
ALL=hostapd hostapd_cli
all: verify_config $(ALL)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 12d627a..8e6f35a 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -83,7 +83,7 @@
return -1;
}
- vlan = os_malloc(sizeof(*vlan));
+ vlan = os_zalloc(sizeof(*vlan));
if (vlan == NULL) {
wpa_printf(MSG_ERROR, "Out of memory while reading "
"VLAN interfaces from '%s'", fname);
@@ -91,7 +91,6 @@
return -1;
}
- os_memset(vlan, 0, sizeof(*vlan));
vlan->vlan_id = vlan_id;
os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
if (bss->vlan_tail)
@@ -711,14 +710,14 @@
}
-static int hostapd_parse_rates(int **rate_list, char *val)
+static int hostapd_parse_intlist(int **int_list, char *val)
{
int *list;
int count;
char *pos, *end;
- os_free(*rate_list);
- *rate_list = NULL;
+ os_free(*int_list);
+ *int_list = NULL;
pos = val;
count = 0;
@@ -745,7 +744,7 @@
}
list[count] = -1;
- *rate_list = list;
+ *int_list = list;
return 0;
}
@@ -1224,6 +1223,12 @@
return -1;
}
+ if (conf->ieee80211h && !conf->ieee80211d) {
+ wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without "
+ "IEEE 802.11d enabled");
+ return -1;
+ }
+
for (i = 0; i < conf->num_bss; i++) {
if (hostapd_config_check_bss(&conf->bss[i], conf))
return -1;
@@ -1684,6 +1689,9 @@
sizeof(conf->bss[0].iface));
} else if (os_strcmp(buf, "bridge") == 0) {
os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
+ } else if (os_strcmp(buf, "vlan_bridge") == 0) {
+ os_strlcpy(bss->vlan_bridge, pos,
+ sizeof(bss->vlan_bridge));
} else if (os_strcmp(buf, "wds_bridge") == 0) {
os_strlcpy(bss->wds_bridge, pos,
sizeof(bss->wds_bridge));
@@ -1785,6 +1793,8 @@
conf->country[2] = ' ';
} else if (os_strcmp(buf, "ieee80211d") == 0) {
conf->ieee80211d = atoi(pos);
+ } else if (os_strcmp(buf, "ieee80211h") == 0) {
+ conf->ieee80211h = atoi(pos);
} else if (os_strcmp(buf, "ieee8021x") == 0) {
bss->ieee802_1x = atoi(pos);
} else if (os_strcmp(buf, "eapol_version") == 0) {
@@ -1823,6 +1833,9 @@
bss->private_key_passwd = os_strdup(pos);
} else if (os_strcmp(buf, "check_crl") == 0) {
bss->check_crl = atoi(pos);
+ } else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
+ os_free(bss->ocsp_stapling_response);
+ bss->ocsp_stapling_response = os_strdup(pos);
} else if (os_strcmp(buf, "dh_file") == 0) {
os_free(bss->dh_file);
bss->dh_file = os_strdup(pos);
@@ -2349,13 +2362,14 @@
} else
conf->send_probe_response = val;
} else if (os_strcmp(buf, "supported_rates") == 0) {
- if (hostapd_parse_rates(&conf->supported_rates, pos)) {
+ if (hostapd_parse_intlist(&conf->supported_rates, pos))
+ {
wpa_printf(MSG_ERROR, "Line %d: invalid rate "
"list", line);
errors++;
}
} else if (os_strcmp(buf, "basic_rates") == 0) {
- if (hostapd_parse_rates(&conf->basic_rates, pos)) {
+ if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid rate "
"list", line);
errors++;
@@ -2620,6 +2634,9 @@
bss->upc = os_strdup(pos);
} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
bss->pbc_in_m1 = atoi(pos);
+ } else if (os_strcmp(buf, "server_id") == 0) {
+ os_free(bss->server_id);
+ bss->server_id = os_strdup(pos);
#ifdef CONFIG_WPS_NFC
} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
bss->wps_nfc_dev_pw_id = atoi(pos);
@@ -2876,6 +2893,26 @@
bss->hs20_operating_class = oper_class;
bss->hs20_operating_class_len = oper_class_len;
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_TESTING_OPTIONS
+#define PARSE_TEST_PROBABILITY(_val) \
+ } else if (os_strcmp(buf, #_val) == 0) { \
+ char *end; \
+ \
+ conf->_val = strtod(pos, &end); \
+ if (*end || conf->_val < 0.0d || \
+ conf->_val > 1.0d) { \
+ wpa_printf(MSG_ERROR, \
+ "Line %d: Invalid value '%s'", \
+ line, pos); \
+ errors++; \
+ return errors; \
+ }
+ PARSE_TEST_PROBABILITY(ignore_probe_probability)
+ PARSE_TEST_PROBABILITY(ignore_auth_probability)
+ PARSE_TEST_PROBABILITY(ignore_assoc_probability)
+ PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
+ PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
+#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcmp(buf, "vendor_elements") == 0) {
struct wpabuf *elems;
size_t len = os_strlen(pos);
@@ -2907,7 +2944,7 @@
} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
bss->sae_anti_clogging_threshold = atoi(pos);
} else if (os_strcmp(buf, "sae_groups") == 0) {
- if (hostapd_parse_rates(&bss->sae_groups, pos)) {
+ if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
wpa_printf(MSG_ERROR, "Line %d: Invalid "
"sae_groups value '%s'", line, pos);
return 1;
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 2153329..021cbe5 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -29,6 +29,7 @@
#include "ap/wps_hostapd.h"
#include "ap/ctrl_iface_ap.h"
#include "ap/ap_drv_ops.h"
+#include "ap/wpa_auth.h"
#include "wps/wps_defs.h"
#include "wps/wps.h"
#include "config_file.h"
@@ -537,15 +538,25 @@
const char *cmd)
{
u8 addr[ETH_ALEN];
- const char *url;
+ const char *url, *timerstr;
u8 buf[1000], *pos;
struct ieee80211_mgmt *mgmt;
size_t url_len;
+ int disassoc_timer;
if (hwaddr_aton(cmd, addr))
return -1;
- url = cmd + 17;
- if (*url != ' ')
+
+ timerstr = cmd + 17;
+ if (*timerstr != ' ')
+ return -1;
+ timerstr++;
+ disassoc_timer = atoi(timerstr);
+ if (disassoc_timer < 0 || disassoc_timer > 65535)
+ return -1;
+
+ url = os_strchr(timerstr, ' ');
+ if (url == NULL)
return -1;
url++;
url_len = os_strlen(url);
@@ -564,8 +575,9 @@
mgmt->u.action.u.bss_tm_req.dialog_token = 1;
mgmt->u.action.u.bss_tm_req.req_mode =
WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
- mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
- mgmt->u.action.u.bss_tm_req.validity_interval = 0;
+ mgmt->u.action.u.bss_tm_req.disassoc_timer =
+ host_to_le16(disassoc_timer);
+ mgmt->u.action.u.bss_tm_req.validity_interval = 0x01;
pos = mgmt->u.action.u.bss_tm_req.variable;
@@ -580,6 +592,41 @@
return -1;
}
+ /* send disassociation frame after time-out */
+ if (disassoc_timer) {
+ struct sta_info *sta;
+ int timeout, beacon_int;
+
+ /*
+ * Prevent STA from reconnecting using cached PMKSA to force
+ * full authentication with the authentication server (which may
+ * decide to reject the connection),
+ */
+ wpa_auth_pmksa_remove(hapd->wpa_auth, addr);
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
+ "for ESS disassociation imminent message",
+ MAC2STR(addr));
+ return -1;
+ }
+
+ beacon_int = hapd->iconf->beacon_int;
+ if (beacon_int < 1)
+ beacon_int = 100; /* best guess */
+ /* Calculate timeout in ms based on beacon_int in TU */
+ timeout = disassoc_timer * beacon_int * 128 / 125;
+ wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR
+ " set to %d ms", MAC2STR(addr), timeout);
+
+ sta->timeout_next = STA_DISASSOC_FROM_CLI;
+ eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+ eloop_register_timeout(timeout / 1000,
+ timeout % 1000 * 1000,
+ ap_handle_timer, hapd, sta);
+ }
+
return 0;
}
@@ -1035,7 +1082,7 @@
}
-static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
+static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
const char *txt, size_t len)
{
struct hostapd_data *hapd = ctx;
diff --git a/hostapd/defconfig b/hostapd/defconfig
index b5ddca3..c288f46 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -117,6 +117,9 @@
# Trusted Network Connect (EAP-TNC)
#CONFIG_EAP_TNC=y
+# EAP-EKE for the integrated EAP server
+#CONFIG_EAP_EKE=y
+
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
@@ -267,3 +270,11 @@
# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
#CONFIG_SQLITE=y
+
+# Testing options
+# This can be used to enable some testing options (see also the example
+# configuration file) that are really useful only for testing clients that
+# connect to this hostapd. These options allow, for example, to drop a
+# certain percentage of probe requests or auth/(re)assoc frames.
+#
+#CONFIG_TESTING_OPTIONS=y
diff --git a/hostapd/eap_register.c b/hostapd/eap_register.c
index 0a7ff91..981e539 100644
--- a/hostapd/eap_register.c
+++ b/hostapd/eap_register.c
@@ -134,5 +134,10 @@
ret = eap_server_pwd_register();
#endif /* EAP_SERVER_PWD */
+#ifdef EAP_SERVER_EKE
+ if (ret == 0)
+ ret = eap_server_eke_register();
+#endif /* EAP_SERVER_EKE */
+
return ret;
}
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 17bb7ed..68c4069 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -105,6 +105,12 @@
# (default: 0 = disabled)
#ieee80211d=1
+# Enable IEEE 802.11h. This enables radar detection and DFS support if
+# available. DFS support is required on outdoor 5 GHz channels in most countries
+# of the world. This can be used only with ieee80211d=1.
+# (default: 0 = disabled)
+#ieee80211h=1
+
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
# specify band)
@@ -660,6 +666,11 @@
# Passphrase for private key
#private_key_passwd=secret passphrase
+# Server identity
+# EAP methods that provide mechanism for authenticated server identity delivery
+# use this value. If not set, "hostapd" is used as a default.
+#server_id=server.example.com
+
# Enable CRL verification.
# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a
# valid CRL signed by the CA is required to be included in the ca_cert file.
@@ -671,6 +682,20 @@
# 2 = check all CRLs in the certificate path
#check_crl=1
+# Cached OCSP stapling response (DER encoded)
+# If set, this file is sent as a certificate status response by the EAP server
+# if the EAP peer requests certificate status in the ClientHello message.
+# This cache file can be updated, e.g., by running following command
+# periodically to get an update from the OCSP responder:
+# openssl ocsp \
+# -no_nonce \
+# -CAfile /etc/hostapd.ca.pem \
+# -issuer /etc/hostapd.ca.pem \
+# -cert /etc/hostapd.server.pem \
+# -url http://ocsp.example.com:8888/ \
+# -respout /tmp/ocsp-cache.der
+#ocsp_stapling_response=/tmp/ocsp-cache.der
+
# dh_file: File path to DH/DSA parameters file (in PEM format)
# This is an optional configuration file for setting parameters for an
# ephemeral DH key exchange. In most cases, the default RSA authentication does
@@ -814,9 +839,8 @@
# is used for the stations. This information is parsed from following RADIUS
# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),
# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value
-# VLANID as a string). vlan_file option below must be configured if dynamic
-# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be
-# used to set static client MAC address to VLAN ID mapping.
+# VLANID as a string). Optionally, the local MAC ACL list (accept_mac_file) can
+# be used to set static client MAC address to VLAN ID mapping.
# 0 = disabled (default)
# 1 = option; use default interface if RADIUS server does not include VLAN ID
# 2 = required; reject authentication if RADIUS server does not include VLAN ID
@@ -828,6 +852,8 @@
# multiple BSSIDs or SSIDs. Each line in this text file is defining a new
# interface and the line must include VLAN ID and interface name separated by
# white space (space or tab).
+# If no entries are provided by this file, the station is statically mapped
+# to <bss-iface>.<vlan-id> interfaces.
#vlan_file=/etc/hostapd.vlan
# Interface where 802.1q tagged packets should appear when a RADIUS server is
@@ -837,6 +863,12 @@
# to the bridge.
#vlan_tagged_interface=eth0
+# Bridge (prefix) to add the wifi and the tagged interface to. This gets the
+# VLAN ID appended. It defaults to brvlan%d if no tagged interface is given
+# and br%s.%d if a tagged interface is given, provided %s = tagged interface
+# and %d = VLAN ID.
+#vlan_bridge=brvlan
+
# When hostapd creates a VLAN interface on vlan_tagged_interfaces, it needs
# to know how to name it.
# 0 = vlan<XXX>, e.g., vlan1
@@ -1521,6 +1553,28 @@
# channels 36-48):
#hs20_operating_class=5173
+##### TESTING OPTIONS #########################################################
+#
+# The options in this section are only available when the build configuration
+# option CONFIG_TESTING_OPTIONS is set while compiling hostapd. They allow
+# testing some scenarios that are otherwise difficult to reproduce.
+#
+# Ignore probe requests sent to hostapd with the given probability, must be a
+# floating point number in the range [0, 1).
+#ignore_probe_probability=0.0
+#
+# Ignore authentication frames with the given probability
+#ignore_auth_probability=0.0
+#
+# Ignore association requests with the given probability
+#ignore_assoc_probability=0.0
+#
+# Ignore reassociation requests with the given probability
+#ignore_reassoc_probability=0.0
+#
+# Corrupt Key MIC in GTK rekey EAPOL-Key frames with the given probability
+#corrupt_gtk_rekey_mic_probability=0.0
+
##### Multiple BSSID support ##################################################
#
# Above configuration is using the default interface (wlan#, or multi-SSID VLAN
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 1537275..7071594 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -593,14 +593,14 @@
char buf[300];
int res;
- if (argc < 2) {
- printf("Invalid 'ess_disassoc' command - two arguments (STA "
- "addr and URL) are needed\n");
+ if (argc < 3) {
+ printf("Invalid 'ess_disassoc' command - three arguments (STA "
+ "addr, disassoc timer, and URL) are needed\n");
return -1;
}
- res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
- argv[0], argv[1]);
+ res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
+ argv[0], argv[1], argv[2]);
if (res < 0 || res >= (int) sizeof(buf))
return -1;
return wpa_ctrl_command(ctrl, buf);
diff --git a/hostapd/main.c b/hostapd/main.c
index d2ec1a5..90e5966 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -194,6 +194,8 @@
return hapd_iface;
fail:
+ wpa_printf(MSG_ERROR, "Failed to set up interface with %s",
+ config_file);
if (conf)
hostapd_config_free(conf);
if (hapd_iface) {
@@ -277,6 +279,7 @@
iface->extended_capa = capa.extended_capa;
iface->extended_capa_mask = capa.extended_capa_mask;
iface->extended_capa_len = capa.extended_capa_len;
+ iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
}
return 0;
@@ -301,13 +304,18 @@
iface->bss[0]->conf->logger_stdout_level--;
}
- if (iface->conf->bss[0].iface[0] != 0 ||
- hostapd_drv_none(iface->bss[0])) {
- if (hostapd_driver_init(iface) ||
- hostapd_setup_interface(iface)) {
- hostapd_interface_deinit_free(iface);
- return NULL;
- }
+ if (iface->conf->bss[0].iface[0] == '\0' &&
+ !hostapd_drv_none(iface->bss[0])) {
+ wpa_printf(MSG_ERROR, "Interface name not specified in %s",
+ config_fname);
+ hostapd_interface_deinit_free(iface);
+ return NULL;
+ }
+
+ if (hostapd_driver_init(iface) ||
+ hostapd_setup_interface(iface)) {
+ hostapd_interface_deinit_free(iface);
+ return NULL;
}
return iface;
@@ -647,22 +655,28 @@
}
}
- if (hostapd_global_init(&interfaces, entropy_file))
+ if (hostapd_global_init(&interfaces, entropy_file)) {
+ wpa_printf(MSG_ERROR, "Failed to initilize global context");
return -1;
+ }
/* Initialize interfaces */
for (i = 0; i < interfaces.count; i++) {
interfaces.iface[i] = hostapd_interface_init(&interfaces,
argv[optind + i],
debug);
- if (!interfaces.iface[i])
+ if (!interfaces.iface[i]) {
+ wpa_printf(MSG_ERROR, "Failed to initialize interface");
goto out;
+ }
}
hostapd_global_ctrl_iface_init(&interfaces);
- if (hostapd_global_run(&interfaces, daemonize, pid_file))
+ if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
+ wpa_printf(MSG_ERROR, "Failed to start eloop");
goto out;
+ }
ret = 0;
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 922f564..fbc1ee0 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -163,6 +163,14 @@
conf->ap_table_max_size = 255;
conf->ap_table_expiration_time = 60;
+#ifdef CONFIG_TESTING_OPTIONS
+ conf->ignore_probe_probability = 0.0d;
+ conf->ignore_auth_probability = 0.0d;
+ conf->ignore_assoc_probability = 0.0d;
+ conf->ignore_reassoc_probability = 0.0d;
+ conf->corrupt_gtk_rekey_mic_probability = 0.0d;
+#endif /* CONFIG_TESTING_OPTIONS */
+
return conf;
}
@@ -432,6 +440,7 @@
os_free(conf->server_cert);
os_free(conf->private_key);
os_free(conf->private_key_passwd);
+ os_free(conf->ocsp_stapling_response);
os_free(conf->dh_file);
os_free(conf->pac_opaque_encr_key);
os_free(conf->eap_fast_a_id);
@@ -523,6 +532,8 @@
wpabuf_free(conf->vendor_elements);
os_free(conf->sae_groups);
+
+ os_free(conf->server_id);
}
@@ -598,11 +609,23 @@
}
-const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
+int hostapd_vlan_id_valid(struct hostapd_vlan *vlan, int vlan_id)
{
struct hostapd_vlan *v = vlan;
while (v) {
if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
+ return 1;
+ v = v->next;
+ }
+ return 0;
+}
+
+
+const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
+{
+ struct hostapd_vlan *v = vlan;
+ while (v) {
+ if (v->vlan_id == vlan_id)
return v->ifname;
v = v->next;
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index d9ef984..a744ba6 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -180,6 +180,7 @@
struct hostapd_bss_config {
char iface[IFNAMSIZ + 1];
char bridge[IFNAMSIZ + 1];
+ char vlan_bridge[IFNAMSIZ + 1];
char wds_bridge[IFNAMSIZ + 1];
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
@@ -294,6 +295,7 @@
char *private_key;
char *private_key_passwd;
int check_crl;
+ char *ocsp_stapling_response;
char *dh_file;
u8 *pac_opaque_encr_key;
u8 *eap_fast_a_id;
@@ -373,6 +375,7 @@
struct wpabuf *wps_nfc_dev_pw;
#endif /* CONFIG_WPS */
int pbc_in_m1;
+ char *server_id;
#define P2P_ENABLED BIT(0)
#define P2P_GROUP_OWNER BIT(1)
@@ -498,6 +501,8 @@
int ieee80211d;
+ int ieee80211h; /* DFS */
+
struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES];
/*
@@ -520,6 +525,14 @@
u8 vht_oper_chwidth;
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ double ignore_probe_probability;
+ double ignore_auth_probability;
+ double ignore_assoc_probability;
+ double ignore_reassoc_probability;
+ double corrupt_gtk_rekey_mic_probability;
+#endif /* CONFIG_TESTING_OPTIONS */
};
@@ -536,6 +549,7 @@
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *prev_psk);
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
+int hostapd_vlan_id_valid(struct hostapd_vlan *vlan, int vlan_id);
const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
int vlan_id);
struct hostapd_radius_attr *
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index ceb7e68..70fab55 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -173,6 +173,14 @@
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
}
+static inline int hostapd_drv_set_acl(struct hostapd_data *hapd,
+ struct hostapd_acl_params *params)
+{
+ if (hapd->driver == NULL || hapd->driver->set_acl == NULL)
+ return 0;
+ return hapd->driver->set_acl(hapd->drv_priv, params);
+}
+
static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
struct wpa_driver_ap_params *params)
{
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index d66d97e..68ad4dc 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -111,6 +111,7 @@
srv.eap_req_id_text = conf->eap_req_id_text;
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
srv.pwd_group = conf->pwd_group;
+ srv.server_id = conf->server_id ? conf->server_id : "hostapd";
#ifdef CONFIG_RADIUS_TEST
srv.dump_msk_file = conf->dump_msk_file;
#endif /* CONFIG_RADIUS_TEST */
@@ -148,6 +149,8 @@
params.private_key = hapd->conf->private_key;
params.private_key_passwd = hapd->conf->private_key_passwd;
params.dh_file = hapd->conf->dh_file;
+ params.ocsp_stapling_response =
+ hapd->conf->ocsp_stapling_response;
if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) {
wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 4c47c75..2f4ba23 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -485,9 +485,30 @@
}
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_P2P
+ if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
+ supp_rates_11b_only(&elems)) {
+ /* Indicates support for 11b rates only */
+ wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from "
+ MACSTR " with only 802.11b rates",
+ MAC2STR(mgmt->sa));
+ return;
+ }
+#endif /* CONFIG_P2P */
+
/* TODO: verify that supp_rates contains at least one matching rate
* with AP configuration */
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->iconf->ignore_probe_probability > 0.0d &&
+ drand48() < hapd->iconf->ignore_probe_probability) {
+ wpa_printf(MSG_INFO,
+ "TESTING: ignoring probe request from " MACSTR,
+ MAC2STR(mgmt->sa));
+ return;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
&resp_len);
if (resp == NULL)
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 6d22d49..fa4b5e4 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -85,6 +85,7 @@
sta = ap_get_sta(hapd, addr);
if (sta) {
+ ap_sta_no_session_timeout(hapd, sta);
accounting_sta_stop(hapd, sta);
/*
@@ -469,7 +470,7 @@
if (!sta) {
sta = ap_sta_add(hapd, rx_auth->peer);
if (sta == NULL) {
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto fail;
}
}
@@ -730,6 +731,9 @@
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
level = MSG_EXCESSIVE;
+ if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+ WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ)
+ level = MSG_EXCESSIVE;
}
wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index a0ac38c..780b2e2 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -837,6 +837,74 @@
}
+static int hostapd_set_acl_list(struct hostapd_data *hapd,
+ struct mac_acl_entry *mac_acl,
+ int n_entries, u8 accept_acl)
+{
+ struct hostapd_acl_params *acl_params;
+ int i, err;
+
+ acl_params = os_zalloc(sizeof(*acl_params) +
+ (n_entries * sizeof(acl_params->mac_acl[0])));
+ if (!acl_params)
+ return -ENOMEM;
+
+ for (i = 0; i < n_entries; i++)
+ os_memcpy(acl_params->mac_acl[i].addr, mac_acl[i].addr,
+ ETH_ALEN);
+
+ acl_params->acl_policy = accept_acl;
+ acl_params->num_mac_acl = n_entries;
+
+ err = hostapd_drv_set_acl(hapd, acl_params);
+
+ os_free(acl_params);
+
+ return err;
+}
+
+
+static void hostapd_set_acl(struct hostapd_data *hapd)
+{
+ struct hostapd_config *conf = hapd->iconf;
+ int err;
+ u8 accept_acl;
+
+ if (hapd->iface->drv_max_acl_mac_addrs == 0)
+ return;
+ if (!(conf->bss->num_accept_mac || conf->bss->num_deny_mac))
+ return;
+
+ if (conf->bss->macaddr_acl == DENY_UNLESS_ACCEPTED) {
+ if (conf->bss->num_accept_mac) {
+ accept_acl = 1;
+ err = hostapd_set_acl_list(hapd, conf->bss->accept_mac,
+ conf->bss->num_accept_mac,
+ accept_acl);
+ if (err) {
+ wpa_printf(MSG_DEBUG, "Failed to set accept acl");
+ return;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file");
+ }
+ } else if (conf->bss->macaddr_acl == ACCEPT_UNLESS_DENIED) {
+ if (conf->bss->num_deny_mac) {
+ accept_acl = 0;
+ err = hostapd_set_acl_list(hapd, conf->bss->deny_mac,
+ conf->bss->num_deny_mac,
+ accept_acl);
+ if (err) {
+ wpa_printf(MSG_DEBUG, "Failed to set deny acl");
+ return;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file");
+ }
+ }
+}
+
+
static int setup_interface(struct hostapd_iface *iface)
{
struct hostapd_data *hapd = iface->bss[0];
@@ -962,6 +1030,8 @@
ap_list_init(iface);
+ hostapd_set_acl(hapd);
+
if (hostapd_driver_commit(hapd) < 0) {
wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
"configuration", __func__);
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 9a3bb68..75d9c66 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -25,6 +25,7 @@
union wps_event_data;
struct hostapd_iface;
+struct hostapd_dynamic_iface;
struct hapd_interfaces {
int (*reload_config)(struct hostapd_iface *iface);
@@ -37,11 +38,13 @@
int (*driver_init)(struct hostapd_iface *iface);
size_t count;
+ size_t count_dynamic;
int global_ctrl_sock;
char *global_iface_path;
char *global_iface_name;
gid_t ctrl_iface_group;
struct hostapd_iface **iface;
+ struct hostapd_dynamic_iface **dynamic_iface;
};
@@ -233,6 +236,8 @@
const u8 *extended_capa, *extended_capa_mask;
unsigned int extended_capa_len;
+ unsigned int drv_max_acl_mac_addrs;
+
struct hostapd_hw_modes *hw_features;
int num_hw_features;
struct hostapd_hw_modes *current_mode;
@@ -273,6 +278,16 @@
void (*scan_cb)(struct hostapd_iface *iface);
};
+/**
+ * struct hostapd_dynamic_iface - hostapd per dynamically allocated
+ * or added interface data structure
+ */
+struct hostapd_dynamic_iface {
+ char parent[IFNAMSIZ + 1];
+ char iface[IFNAMSIZ + 1];
+ unsigned int usage;
+};
+
/* hostapd.c */
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 8baa15e..5503af1 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -557,6 +557,16 @@
return;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->iconf->ignore_auth_probability > 0.0d &&
+ drand48() < hapd->iconf->ignore_auth_probability) {
+ wpa_printf(MSG_INFO,
+ "TESTING: ignoring auth frame from " MACSTR,
+ MAC2STR(mgmt->sa));
+ return;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
status_code = le_to_host16(mgmt->u.auth.status_code);
@@ -635,13 +645,12 @@
sta = ap_sta_add(hapd, mgmt->sa);
if (!sta) {
- resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto fail;
}
if (vlan_id > 0) {
- if (hostapd_get_vlan_id_ifname(hapd->conf->vlan,
- vlan_id) == NULL) {
+ if (!hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
"%d received from RADIUS server",
@@ -1226,6 +1235,26 @@
return;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (reassoc) {
+ if (hapd->iconf->ignore_reassoc_probability > 0.0d &&
+ drand48() < hapd->iconf->ignore_reassoc_probability) {
+ wpa_printf(MSG_INFO,
+ "TESTING: ignoring reassoc request from "
+ MACSTR, MAC2STR(mgmt->sa));
+ return;
+ }
+ } else {
+ if (hapd->iconf->ignore_assoc_probability > 0.0d &&
+ drand48() < hapd->iconf->ignore_assoc_probability) {
+ wpa_printf(MSG_INFO,
+ "TESTING: ignoring assoc request from "
+ MACSTR, MAC2STR(mgmt->sa));
+ return;
+ }
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
if (reassoc) {
capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
listen_interval = le_to_host16(
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index a832a73..3554e8b 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -399,15 +399,13 @@
/* Save station identity for future RADIUS packets */
os_free(sm->identity);
- sm->identity = os_malloc(identity_len + 1);
+ sm->identity = (u8 *) dup_binstr(identity, identity_len);
if (sm->identity == NULL) {
sm->identity_len = 0;
return;
}
- os_memcpy(sm->identity, identity, identity_len);
sm->identity_len = identity_len;
- sm->identity[identity_len] = '\0';
hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "STA identity '%s'", sm->identity);
sm->dot1xAuthEapolRespIdFramesRx++;
@@ -1272,13 +1270,10 @@
NULL) < 0)
return;
- identity = os_malloc(len + 1);
+ identity = (u8 *) dup_binstr(buf, len);
if (identity == NULL)
return;
- os_memcpy(identity, buf, len);
- identity[len] = '\0';
-
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with "
"User-Name from Access-Accept '%s'",
@@ -1443,8 +1438,7 @@
sta->vlan_id = radius_msg_get_vlanid(msg);
}
if (sta->vlan_id > 0 &&
- hostapd_get_vlan_id_ifname(hapd->conf->vlan,
- sta->vlan_id)) {
+ hostapd_vlan_id_valid(hapd->conf->vlan, sta->vlan_id)) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
@@ -1834,6 +1828,13 @@
conf.fragment_size = hapd->conf->fragment_size;
conf.pwd_group = hapd->conf->pwd_group;
conf.pbc_in_m1 = hapd->conf->pbc_in_m1;
+ if (hapd->conf->server_id) {
+ conf.server_id = (const u8 *) hapd->conf->server_id;
+ conf.server_id_len = os_strlen(hapd->conf->server_id);
+ } else {
+ conf.server_id = (const u8 *) "hostapd";
+ conf.server_id_len = 7;
+ }
os_memset(&cb, 0, sizeof(cb));
cb.eapol_send = ieee802_1x_eapol_send;
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index d27fd30..40972e9 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -48,8 +48,8 @@
}
-static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
- struct rsn_pmksa_cache_entry *entry)
+void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry)
{
struct rsn_pmksa_cache_entry *pos, *prev;
diff --git a/src/ap/pmksa_cache_auth.h b/src/ap/pmksa_cache_auth.h
index d473f3f..aa90024 100644
--- a/src/ap/pmksa_cache_auth.h
+++ b/src/ap/pmksa_cache_auth.h
@@ -55,5 +55,7 @@
const u8 *aa, const u8 *pmkid);
void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
struct eapol_state_machine *eapol);
+void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry);
#endif /* PMKSA_CACHE_H */
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index cbafb47..833f1b2 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -283,6 +283,7 @@
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
unsigned long next_time = 0;
+ int reason;
wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d",
__func__, MAC2STR(sta->addr), sta->flags,
@@ -378,9 +379,11 @@
hapd, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
} else {
- hostapd_drv_sta_disassoc(
- hapd, sta->addr,
- WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
+ reason = (sta->timeout_next == STA_DISASSOC) ?
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY :
+ WLAN_REASON_PREV_AUTH_NOT_VALID;
+
+ hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
}
}
@@ -394,6 +397,7 @@
hapd, sta);
break;
case STA_DISASSOC:
+ case STA_DISASSOC_FROM_CLI:
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~WLAN_STA_ASSOC;
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
@@ -405,14 +409,16 @@
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disassociated due to "
"inactivity");
+ reason = (sta->timeout_next == STA_DISASSOC) ?
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY :
+ WLAN_REASON_PREV_AUTH_NOT_VALID;
sta->timeout_next = STA_DEAUTH;
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)",
__func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY);
eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
hapd, sta);
- mlme_disassociate_indication(
- hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
+ mlme_disassociate_indication(hapd, sta, reason);
break;
case STA_DEAUTH:
case STA_REMOVE:
@@ -855,6 +861,7 @@
int authorized)
{
const u8 *dev_addr = NULL;
+ char buf[100];
#ifdef CONFIG_P2P
u8 addr[ETH_ALEN];
#endif /* CONFIG_P2P */
@@ -871,44 +878,29 @@
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
#endif /* CONFIG_P2P */
+ if (dev_addr)
+ os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR,
+ MAC2STR(sta->addr), MAC2STR(dev_addr));
+ else
+ os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
+
if (authorized) {
- if (dev_addr)
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
- MACSTR " p2p_dev_addr=" MACSTR,
- MAC2STR(sta->addr), MAC2STR(dev_addr));
- else
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
- MACSTR, MAC2STR(sta->addr));
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s", buf);
+
if (hapd->msg_ctx_parent &&
- hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_CONNECTED MACSTR " p2p_dev_addr="
- MACSTR,
- MAC2STR(sta->addr), MAC2STR(dev_addr));
- else if (hapd->msg_ctx_parent &&
- hapd->msg_ctx_parent != hapd->msg_ctx)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
+ hapd->msg_ctx_parent != hapd->msg_ctx)
+ wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
+ AP_STA_CONNECTED "%s", buf);
sta->flags |= WLAN_STA_AUTHORIZED;
} else {
- if (dev_addr)
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
- MACSTR " p2p_dev_addr=" MACSTR,
- MAC2STR(sta->addr), MAC2STR(dev_addr));
- else
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
- MACSTR, MAC2STR(sta->addr));
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
+
if (hapd->msg_ctx_parent &&
- hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_DISCONNECTED MACSTR " p2p_dev_addr="
- MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr));
- else if (hapd->msg_ctx_parent &&
- hapd->msg_ctx_parent != hapd->msg_ctx)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
+ hapd->msg_ctx_parent != hapd->msg_ctx)
+ wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
+ AP_STA_DISCONNECTED "%s", buf);
+
sta->flags &= ~WLAN_STA_AUTHORIZED;
}
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 32ea46e..f8f5a83 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -62,7 +62,8 @@
u8 previous_ap[6];
enum {
- STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
+ STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE,
+ STA_DISASSOC_FROM_CLI
} timeout_next;
u16 deauth_reason;
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 7b1a9e6..70affda 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -480,6 +480,123 @@
#endif /* CONFIG_VLAN_NETLINK */
+/**
+ * Increase the usage counter for given parent/ifname combination.
+ * If create is set, then this iface is added to the global list.
+ * Returns
+ * -1 on error
+ * 0 if iface is not in list
+ * 1 if iface is in list (was there or has been added)
+ */
+static int hapd_get_dynamic_iface(const char *parent, const char *ifname,
+ int create, struct hostapd_data *hapd)
+{
+ size_t i;
+ struct hostapd_dynamic_iface *j = NULL, **tmp;
+ struct hapd_interfaces *hapd_global = hapd->iface->interfaces;
+
+ if (!parent)
+ parent = "";
+
+ for (i = 0; i < hapd_global->count_dynamic; i++) {
+ j = hapd_global->dynamic_iface[i];
+ if (os_strncmp(j->iface, ifname, sizeof(j->iface)) == 0 &&
+ os_strncmp(j->parent, parent, sizeof(j->parent)) == 0)
+ break;
+ }
+ if (i < hapd_global->count_dynamic) {
+ j->usage++;
+ return 1;
+ }
+
+ /* new entry required */
+ if (!create)
+ return 0;
+
+ j = os_zalloc(sizeof(*j));
+ if (!j)
+ return -1;
+ os_strlcpy(j->iface, ifname, sizeof(j->iface));
+ os_strlcpy(j->parent, parent, sizeof(j->parent));
+
+ tmp = os_realloc_array(hapd_global->dynamic_iface, i + 1,
+ sizeof(*hapd_global->dynamic_iface));
+ if (!tmp) {
+ wpa_printf(MSG_ERROR, "VLAN: Failed to allocate memory in %s",
+ __func__);
+ return -1;
+ }
+ hapd_global->count_dynamic++;
+ hapd_global->dynamic_iface = tmp;
+ hapd_global->dynamic_iface[i] = j;
+
+ return 1;
+}
+
+
+/**
+ * Decrease the usage counter for given ifname.
+ * Returns
+ * -1 on error or if iface was not found
+ * 0 if iface was found and is still present
+ * 1 if iface was removed from global list
+ */
+static int hapd_put_dynamic_iface(const char *parent, const char *ifname,
+ struct hostapd_data *hapd)
+{
+ size_t i;
+ struct hostapd_dynamic_iface *j = NULL, **tmp;
+ struct hapd_interfaces *hapd_glob = hapd->iface->interfaces;
+
+ if (!parent)
+ parent = "";
+
+ for (i = 0; i < hapd_glob->count_dynamic; i++) {
+ j = hapd_glob->dynamic_iface[i];
+ if (os_strncmp(j->iface, ifname, sizeof(j->iface)) == 0 &&
+ os_strncmp(j->parent, parent, sizeof(j->parent)) == 0)
+ break;
+ }
+
+ if (i == hapd_glob->count_dynamic) {
+ /*
+ * Interface not in global list. This can happen if alloc in
+ * _get_ failed.
+ */
+ return -1;
+ }
+
+ if (j->usage > 0) {
+ j->usage--;
+ return 0;
+ }
+
+ os_free(j);
+ for (; i < hapd_glob->count_dynamic - 1; i++)
+ hapd_glob->dynamic_iface[i] = hapd_glob->dynamic_iface[i + 1];
+ hapd_glob->dynamic_iface[hapd_glob->count_dynamic - 1] = NULL;
+ hapd_glob->count_dynamic--;
+
+ if (hapd_glob->count_dynamic == 0) {
+ os_free(hapd_glob->dynamic_iface);
+ hapd_glob->dynamic_iface = NULL;
+ return 1;
+ }
+
+ tmp = os_realloc_array(hapd_glob->dynamic_iface,
+ hapd_glob->count_dynamic,
+ sizeof(*hapd_glob->dynamic_iface));
+ if (!tmp) {
+ wpa_printf(MSG_ERROR, "VLAN: Failed to release memory in %s",
+ __func__);
+ return -1;
+ }
+ hapd_glob->dynamic_iface = tmp;
+
+ return 1;
+}
+
+
static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
{
char vlan_ifname[IFNAMSIZ];
@@ -487,16 +604,29 @@
struct hostapd_vlan *vlan = hapd->conf->vlan;
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
int vlan_naming = hapd->conf->ssid.vlan_naming;
+ int ret;
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
while (vlan) {
if (os_strcmp(ifname, vlan->ifname) == 0) {
- os_snprintf(br_name, sizeof(br_name), "brvlan%d",
- vlan->vlan_id);
+ if (hapd->conf->vlan_bridge[0]) {
+ os_snprintf(br_name, sizeof(br_name), "%s%d",
+ hapd->conf->vlan_bridge,
+ vlan->vlan_id);
+ } else if (tagged_interface) {
+ os_snprintf(br_name, sizeof(br_name),
+ "br%s.%d", tagged_interface,
+ vlan->vlan_id);
+ } else {
+ os_snprintf(br_name, sizeof(br_name),
+ "brvlan%d", vlan->vlan_id);
+ }
- if (!br_addbr(br_name))
+ ret = br_addbr(br_name);
+ if (hapd_get_dynamic_iface(NULL, br_name, ret == 0,
+ hapd))
vlan->clean |= DVLAN_CLEAN_BR;
ifconfig_up(br_name);
@@ -514,17 +644,24 @@
"vlan%d", vlan->vlan_id);
ifconfig_up(tagged_interface);
- if (!vlan_add(tagged_interface, vlan->vlan_id,
- vlan_ifname))
+ ret = vlan_add(tagged_interface, vlan->vlan_id,
+ vlan_ifname);
+ if (hapd_get_dynamic_iface(NULL, vlan_ifname,
+ ret == 0, hapd))
vlan->clean |= DVLAN_CLEAN_VLAN;
- if (!br_addif(br_name, vlan_ifname))
+ ret = br_addif(br_name, vlan_ifname);
+ if (hapd_get_dynamic_iface(br_name,
+ vlan_ifname,
+ ret == 0, hapd))
vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
ifconfig_up(vlan_ifname);
}
- if (!br_addif(br_name, ifname))
+ ret = br_addif(br_name, ifname);
+ if (hapd_get_dynamic_iface(br_name, ifname, ret == 0,
+ hapd))
vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
ifconfig_up(ifname);
@@ -550,10 +687,21 @@
while (vlan) {
if (os_strcmp(ifname, vlan->ifname) == 0) {
- os_snprintf(br_name, sizeof(br_name), "brvlan%d",
- vlan->vlan_id);
+ if (hapd->conf->vlan_bridge[0]) {
+ os_snprintf(br_name, sizeof(br_name), "%s%d",
+ hapd->conf->vlan_bridge,
+ vlan->vlan_id);
+ } else if (tagged_interface) {
+ os_snprintf(br_name, sizeof(br_name),
+ "br%s.%d", tagged_interface,
+ vlan->vlan_id);
+ } else {
+ os_snprintf(br_name, sizeof(br_name),
+ "brvlan%d", vlan->vlan_id);
+ }
- if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
+ if ((vlan->clean & DVLAN_CLEAN_WLAN_PORT) &&
+ hapd_put_dynamic_iface(br_name, vlan->ifname, hapd))
br_delif(br_name, vlan->ifname);
if (tagged_interface) {
@@ -567,15 +715,20 @@
os_snprintf(vlan_ifname,
sizeof(vlan_ifname),
"vlan%d", vlan->vlan_id);
- if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
+ if ((vlan->clean & DVLAN_CLEAN_VLAN_PORT) &&
+ hapd_put_dynamic_iface(br_name, vlan_ifname,
+ hapd))
br_delif(br_name, vlan_ifname);
ifconfig_down(vlan_ifname);
- if (vlan->clean & DVLAN_CLEAN_VLAN)
+ if ((vlan->clean & DVLAN_CLEAN_VLAN) &&
+ hapd_put_dynamic_iface(NULL, vlan_ifname,
+ hapd))
vlan_rem(vlan_ifname);
}
if ((vlan->clean & DVLAN_CLEAN_BR) &&
+ hapd_put_dynamic_iface(NULL, br_name, hapd) &&
br_getnumports(br_name) == 0) {
ifconfig_down(br_name);
br_delbr(br_name);
@@ -837,6 +990,27 @@
hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+ if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED &&
+ !hapd->conf->vlan) {
+ /* dynamic vlans enabled but no (or empty) vlan_file given */
+ struct hostapd_vlan *vlan;
+ vlan = os_zalloc(sizeof(*vlan));
+ if (vlan == NULL) {
+ wpa_printf(MSG_ERROR, "Out of memory while assigning "
+ "VLAN interfaces");
+ return -1;
+ }
+
+ vlan->vlan_id = VLAN_ID_WILDCARD;
+ os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
+ hapd->conf->iface);
+ if (hapd->conf->vlan_tail)
+ hapd->conf->vlan_tail->next = vlan;
+ else
+ hapd->conf->vlan = vlan;
+ hapd->conf->vlan_tail = vlan;
+ }
+
if (vlan_dynamic_add(hapd, hapd->conf->vlan))
return -1;
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 4f1f6fb..83cc857 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1232,7 +1232,7 @@
else
version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
- pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
+ pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d "
"ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d "
@@ -1347,6 +1347,16 @@
}
wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len,
key->key_mic);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (!pairwise &&
+ wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0d &&
+ drand48() <
+ wpa_auth->conf.corrupt_gtk_rekey_mic_probability) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "Corrupting group EAPOL-Key Key MIC");
+ key->key_mic[0]++;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
}
wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,
@@ -2934,6 +2944,22 @@
}
+void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr)
+{
+ struct rsn_pmksa_cache_entry *pmksa;
+
+ if (wpa_auth == NULL || wpa_auth->pmksa == NULL)
+ return;
+ pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
+ if (pmksa) {
+ wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
+ MACSTR " based on request", MAC2STR(sta_addr));
+ pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
+ }
+}
+
+
static struct wpa_group *
wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
{
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 465eec6..ebfe86f 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -160,6 +160,9 @@
#endif /* CONFIG_IEEE80211R */
int disable_gtk;
int ap_mlme;
+#ifdef CONFIG_TESTING_OPTIONS
+ double corrupt_gtk_rekey_mic_probability;
+#endif /* CONFIG_TESTING_OPTIONS */
};
typedef enum {
@@ -260,6 +263,8 @@
const u8 *pmk, size_t len, const u8 *sta_addr,
int session_timeout,
struct eapol_state_machine *eapol);
+void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr);
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int ack);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index ccb3f82..1bb5d97 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -1166,6 +1166,8 @@
/* RRB - Forward action frame to the target AP */
frame = os_malloc(sizeof(*frame) + len);
+ if (frame == NULL)
+ return -1;
frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
frame->packet_type = FT_PACKET_REQUEST;
frame->action_length = host_to_le16(len);
@@ -1216,6 +1218,10 @@
rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len;
frame = os_malloc(sizeof(*frame) + rlen);
+ if (frame == NULL) {
+ os_free(resp_ies);
+ return -1;
+ }
frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
frame->packet_type = FT_PACKET_RESPONSE;
frame->action_length = host_to_le16(rlen);
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index fdaaaff..e2be1ea 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -28,6 +28,7 @@
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
+ struct hostapd_config *iconf,
struct wpa_auth_config *wconf)
{
os_memset(wconf, 0, sizeof(*wconf));
@@ -74,6 +75,10 @@
#ifdef CONFIG_HS20
wconf->disable_gtk = conf->disable_dgaf;
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_TESTING_OPTIONS
+ wconf->corrupt_gtk_rekey_mic_probability =
+ iconf->corrupt_gtk_rekey_mic_probability;
+#endif /* CONFIG_TESTING_OPTIONS */
}
@@ -509,7 +514,7 @@
const u8 *wpa_ie;
size_t wpa_ie_len;
- hostapd_wpa_auth_conf(hapd->conf, &_conf);
+ hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
_conf.tx_status = 1;
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
@@ -583,7 +588,7 @@
void hostapd_reconfig_wpa(struct hostapd_data *hapd)
{
struct wpa_auth_config wpa_auth_conf;
- hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf);
+ hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &wpa_auth_conf);
wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
}
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 98fadda..aab8ac6 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1,6 +1,6 @@
/*
* IEEE 802.11 Common routines
- * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -9,6 +9,7 @@
#include "includes.h"
#include "common.h"
+#include "defs.h"
#include "ieee802_11_defs.h"
#include "ieee802_11_common.h"
@@ -486,3 +487,61 @@
return 0;
}
+
+
+enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
+{
+ enum hostapd_hw_mode mode = NUM_HOSTAPD_MODES;
+
+ if (freq >= 2412 && freq <= 2472) {
+ mode = HOSTAPD_MODE_IEEE80211G;
+ *channel = (freq - 2407) / 5;
+ } else if (freq == 2484) {
+ mode = HOSTAPD_MODE_IEEE80211B;
+ *channel = 14;
+ } else if (freq >= 4900 && freq < 5000) {
+ mode = HOSTAPD_MODE_IEEE80211A;
+ *channel = (freq - 4000) / 5;
+ } else if (freq >= 5000 && freq < 5900) {
+ mode = HOSTAPD_MODE_IEEE80211A;
+ *channel = (freq - 5000) / 5;
+ } else if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
+ mode = HOSTAPD_MODE_IEEE80211AD;
+ *channel = (freq - 56160) / 2160;
+ }
+
+ return mode;
+}
+
+
+static int is_11b(u8 rate)
+{
+ return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
+}
+
+
+int supp_rates_11b_only(struct ieee802_11_elems *elems)
+{
+ int num_11b = 0, num_others = 0;
+ int i;
+
+ if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
+ return 0;
+
+ for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
+ if (is_11b(elems->supp_rates[i]))
+ num_11b++;
+ else
+ num_others++;
+ }
+
+ for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
+ i++) {
+ if (is_11b(elems->ext_supp_rates[i]))
+ num_11b++;
+ else
+ num_others++;
+ }
+
+ return num_11b > 0 && num_others == 0;
+}
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 55fa49d..68c6b96 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -99,5 +99,8 @@
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
const char *name, const char *val);
+enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
+
+int supp_rates_11b_only(struct ieee802_11_elems *elems);
#endif /* IEEE802_11_COMMON_H */
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index f782c86..137c309 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -549,6 +549,14 @@
* Entries (optional) */
u8 variable[0];
} STRUCT_PACKED bss_tm_resp;
+ struct {
+ u8 action; /* 6 */
+ u8 dialog_token;
+ u8 query_reason;
+ /* BSS Transition Candidate List
+ * Entries (optional) */
+ u8 variable[0];
+ } STRUCT_PACKED bss_tm_query;
} u;
} STRUCT_PACKED action;
} u;
@@ -1049,6 +1057,28 @@
#define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)
#define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)
+/* IEEE Std 802.11-2012 - Table 8-253 */
+enum bss_trans_mgmt_status_code {
+ WNM_BSS_TM_ACCEPT = 0,
+ WNM_BSS_TM_REJECT_UNSPECIFIED = 1,
+ WNM_BSS_TM_REJECT_INSUFFICIENT_BEACON = 2,
+ WNM_BSS_TM_REJECT_INSUFFICIENT_CAPABITY = 3,
+ WNM_BSS_TM_REJECT_UNDESIRED = 4,
+ WNM_BSS_TM_REJECT_DELAY_REQUEST = 5,
+ WNM_BSS_TM_REJECT_STA_CANDIDATE_LIST_PROVIDED = 6,
+ WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES = 7,
+ WNM_BSS_TM_REJECT_LEAVING_ESS = 8
+};
+
+#define WNM_NEIGHBOR_TSF 1
+#define WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING 2
+#define WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE 3
+#define WNM_NEIGHBOR_BSS_TERMINATION_DURATION 4
+#define WNM_NEIGHBOR_BEARING 5
+#define WNM_NEIGHBOR_MEASUREMENT_PILOT 66
+#define WNM_NEIGHBOR_RRM_ENABLED_CAPABILITIES 70
+#define WNM_NEIGHBOR_MULTIPLE_BSSID 71
+
/* IEEE Std 802.11-2012, 8.4.2.62 20/40 BSS Coexistence element */
#define WLAN_20_40_BSS_COEX_INFO_REQ BIT(0)
#define WLAN_20_40_BSS_COEX_40MHZ_INTOL BIT(1)
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index a8cf6be..c3afbfd 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -335,7 +335,6 @@
#endif /* CONFIG_IEEE80211R */
-#ifndef CONFIG_NO_WPA2
static int rsn_selector_to_bitfield(const u8 *s)
{
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
@@ -384,7 +383,6 @@
#endif /* CONFIG_SAE */
return 0;
}
-#endif /* CONFIG_NO_WPA2 */
/**
@@ -397,7 +395,6 @@
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data)
{
-#ifndef CONFIG_NO_WPA2
const struct rsn_ie_hdr *hdr;
const u8 *pos;
int left;
@@ -551,9 +548,6 @@
}
return 0;
-#else /* CONFIG_NO_WPA2 */
- return -1;
-#endif /* CONFIG_NO_WPA2 */
}
diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
index 58cbe6a..d9a7509 100644
--- a/src/common/wpa_ctrl.c
+++ b/src/common/wpa_ctrl.c
@@ -82,6 +82,9 @@
int tries = 0;
int flags;
+ if (ctrl_path == NULL)
+ return NULL;
+
ctrl = os_malloc(sizeof(*ctrl));
if (ctrl == NULL)
return NULL;
@@ -126,13 +129,27 @@
#ifdef ANDROID
chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
+
+ if (os_strncmp(ctrl_path, "@android:", 9) == 0) {
+ if (socket_local_client_connect(
+ ctrl->s, ctrl_path + 9,
+ ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_DGRAM) < 0) {
+ close(ctrl->s);
+ unlink(ctrl->local.sun_path);
+ os_free(ctrl);
+ return NULL;
+ }
+ return ctrl;
+ }
+
/*
* If the ctrl_path isn't an absolute pathname, assume that
* it's the name of a socket in the Android reserved namespace.
* Otherwise, it's a normal UNIX domain socket appearing in the
* filesystem.
*/
- if (ctrl_path != NULL && *ctrl_path != '/') {
+ if (*ctrl_path != '/') {
char buf[21];
os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path);
if (socket_local_client_connect(
@@ -149,12 +166,18 @@
#endif /* ANDROID */
ctrl->dest.sun_family = AF_UNIX;
- res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
- sizeof(ctrl->dest.sun_path));
- if (res >= sizeof(ctrl->dest.sun_path)) {
- close(ctrl->s);
- os_free(ctrl);
- return NULL;
+ if (os_strncmp(ctrl_path, "@abstract:", 10) == 0) {
+ ctrl->dest.sun_path[0] = '\0';
+ os_strlcpy(ctrl->dest.sun_path + 1, ctrl_path + 10,
+ sizeof(ctrl->dest.sun_path) - 1);
+ } else {
+ res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
+ sizeof(ctrl->dest.sun_path));
+ if (res >= sizeof(ctrl->dest.sun_path)) {
+ close(ctrl->s);
+ os_free(ctrl);
+ return NULL;
+ }
}
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index dbabe8c..0c05a41 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -44,6 +44,8 @@
#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT "
/** EAP TLS certificate chain validation error */
#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
+/** EAP status */
+#define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS "
/** EAP authentication completed successfully */
#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
/** EAP authentication failed (EAP-Failure received) */
@@ -134,6 +136,9 @@
#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT "
#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED "
+/* parameters: <PMF enabled> <timeout in ms> <Session Information URL> */
+#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
+
#define INTERWORKING_AP "INTERWORKING-AP "
#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index b61e439..2fdaa02 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -1,6 +1,6 @@
/*
* SSL/TLS interface definition
- * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -82,6 +82,8 @@
#define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0)
#define TLS_CONN_DISABLE_TIME_CHECKS BIT(1)
#define TLS_CONN_DISABLE_SESSION_TICKET BIT(2)
+#define TLS_CONN_REQUEST_OCSP BIT(3)
+#define TLS_CONN_REQUIRE_OCSP BIT(4)
/**
* struct tls_connection_params - Parameters for TLS connection
@@ -117,6 +119,8 @@
* @cert_id: the certificate's id when using engine
* @ca_cert_id: the CA certificate's id when using engine
* @flags: Parameter options (TLS_CONN_*)
+ * @ocsp_stapling_response: DER encoded file with cached OCSP stapling response
+ * or %NULL if OCSP is not enabled
*
* TLS connection parameters to be configured with tls_connection_set_params()
* and tls_global_set_params().
@@ -153,6 +157,7 @@
const char *ca_cert_id;
unsigned int flags;
+ const char *ocsp_stapling_response;
};
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index e226f1a..d27af0a 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -1,6 +1,6 @@
/*
* SSL/TLS interface functions for OpenSSL
- * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -34,6 +34,10 @@
#define OPENSSL_d2i_TYPE unsigned char **
#endif
+#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
+#define OPENSSL_SUPPORTS_CTX_APP_DATA
+#endif
+
#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT
#ifdef SSL_OP_NO_TICKET
/*
@@ -61,19 +65,28 @@
}
#endif /* ANDROID */
+#ifdef SSL_set_tlsext_status_type
+#ifndef OPENSSL_NO_TLSEXT
+#define HAVE_OCSP
+#include <openssl/ocsp.h>
+#endif /* OPENSSL_NO_TLSEXT */
+#endif /* SSL_set_tlsext_status_type */
+
static int tls_openssl_ref_count = 0;
-struct tls_global {
+struct tls_context {
void (*event_cb)(void *ctx, enum tls_event ev,
union tls_event_data *data);
void *cb_ctx;
int cert_in_cb;
+ char *ocsp_stapling_response;
};
-static struct tls_global *tls_global = NULL;
+static struct tls_context *tls_global = NULL;
struct tls_connection {
+ struct tls_context *context;
SSL *ssl;
BIO *ssl_in, *ssl_out;
#ifndef OPENSSL_NO_ENGINE
@@ -97,9 +110,26 @@
u8 srv_cert_hash[32];
unsigned int flags;
+
+ X509 *peer_cert;
+ X509 *peer_issuer;
};
+static struct tls_context * tls_context_new(const struct tls_config *conf)
+{
+ struct tls_context *context = os_zalloc(sizeof(*context));
+ if (context == NULL)
+ return NULL;
+ if (conf) {
+ context->event_cb = conf->event_cb;
+ context->cb_ctx = conf->cb_ctx;
+ context->cert_in_cb = conf->cert_in_cb;
+ }
+ return context;
+}
+
+
#ifdef CONFIG_NO_STDOUT_DEBUG
static void _tls_show_errors(void)
@@ -525,6 +555,7 @@
wpa_printf(MSG_DEBUG, "SSL: %s:%s",
str, SSL_state_string_long(ssl));
} else if (where & SSL_CB_ALERT) {
+ struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
where & SSL_CB_READ ?
"read (remote end reported an error)" :
@@ -532,21 +563,19 @@
SSL_alert_type_string_long(ret),
SSL_alert_desc_string_long(ret));
if ((ret >> 8) == SSL3_AL_FATAL) {
- struct tls_connection *conn =
- SSL_get_app_data((SSL *) ssl);
if (where & SSL_CB_READ)
conn->read_alerts++;
else
conn->write_alerts++;
}
- if (tls_global->event_cb != NULL) {
+ if (conn->context->event_cb != NULL) {
union tls_event_data ev;
+ struct tls_context *context = conn->context;
os_memset(&ev, 0, sizeof(ev));
ev.alert.is_local = !(where & SSL_CB_READ);
ev.alert.type = SSL_alert_type_string_long(ret);
ev.alert.description = SSL_alert_desc_string_long(ret);
- tls_global->event_cb(tls_global->cb_ctx, TLS_ALERT,
- &ev);
+ context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
}
} else if (where & SSL_CB_EXIT && ret <= 0) {
wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
@@ -704,17 +733,12 @@
void * tls_init(const struct tls_config *conf)
{
SSL_CTX *ssl;
+ struct tls_context *context;
if (tls_openssl_ref_count == 0) {
- tls_global = os_zalloc(sizeof(*tls_global));
- if (tls_global == NULL)
+ tls_global = context = tls_context_new(conf);
+ if (context == NULL)
return NULL;
- if (conf) {
- tls_global->event_cb = conf->event_cb;
- tls_global->cb_ctx = conf->cb_ctx;
- tls_global->cert_in_cb = conf->cert_in_cb;
- }
-
#ifdef CONFIG_FIPS
#ifdef OPENSSL_FIPS
if (conf && conf->fips_mode) {
@@ -760,14 +784,33 @@
#endif /* OPENSSL_NO_RC2 */
PKCS12_PBE_add();
#endif /* PKCS12_FUNCS */
+ } else {
+ context = tls_global;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ /* Newer OpenSSL can store app-data per-SSL */
+ context = tls_context_new(conf);
+ if (context == NULL)
+ return NULL;
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
}
tls_openssl_ref_count++;
ssl = SSL_CTX_new(TLSv1_method());
- if (ssl == NULL)
+ if (ssl == NULL) {
+ tls_openssl_ref_count--;
+ if (tls_openssl_ref_count == 0) {
+ os_free(tls_global);
+ tls_global = NULL;
+ } else if (context != tls_global) {
+ os_free(context);
+ }
return NULL;
+ }
SSL_CTX_set_info_callback(ssl, ssl_info_cb);
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ SSL_CTX_set_app_data(ssl, context);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
#ifndef OPENSSL_NO_ENGINE
if (conf &&
@@ -793,6 +836,11 @@
void tls_deinit(void *ssl_ctx)
{
SSL_CTX *ssl = ssl_ctx;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ struct tls_context *context = SSL_CTX_get_app_data(ssl);
+ if (context != tls_global)
+ os_free(context);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
SSL_CTX_free(ssl);
tls_openssl_ref_count--;
@@ -804,6 +852,8 @@
ERR_remove_state(0);
ERR_free_strings();
EVP_cleanup();
+ os_free(tls_global->ocsp_stapling_response);
+ tls_global->ocsp_stapling_response = NULL;
os_free(tls_global);
tls_global = NULL;
}
@@ -936,6 +986,10 @@
SSL_CTX *ssl = ssl_ctx;
struct tls_connection *conn;
long options;
+ struct tls_context *context = tls_global;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+ context = SSL_CTX_get_app_data(ssl);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
conn = os_zalloc(sizeof(*conn));
if (conn == NULL)
@@ -948,6 +1002,7 @@
return NULL;
}
+ conn->context = context;
SSL_set_app_data(conn->ssl, conn);
options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_SINGLE_DH_USE;
@@ -1148,8 +1203,9 @@
{
union tls_event_data ev;
struct wpabuf *cert = NULL;
+ struct tls_context *context = conn->context;
- if (tls_global->event_cb == NULL)
+ if (context->event_cb == NULL)
return;
cert = get_x509_cert(err_cert);
@@ -1160,7 +1216,7 @@
ev.cert_fail.subject = subject;
ev.cert_fail.reason_txt = err_str;
ev.cert_fail.cert = cert;
- tls_global->event_cb(tls_global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
+ context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
wpabuf_free(cert);
}
@@ -1171,15 +1227,16 @@
{
struct wpabuf *cert = NULL;
union tls_event_data ev;
+ struct tls_context *context = conn->context;
#ifdef CONFIG_SHA256
u8 hash[32];
#endif /* CONFIG_SHA256 */
- if (tls_global->event_cb == NULL)
+ if (context->event_cb == NULL)
return;
os_memset(&ev, 0, sizeof(ev));
- if (conn->cert_probe || tls_global->cert_in_cb) {
+ if (conn->cert_probe || context->cert_in_cb) {
cert = get_x509_cert(err_cert);
ev.peer_cert.cert = cert;
}
@@ -1197,7 +1254,7 @@
#endif /* CONFIG_SHA256 */
ev.peer_cert.depth = depth;
ev.peer_cert.subject = subject;
- tls_global->event_cb(tls_global->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
+ context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
wpabuf_free(cert);
}
@@ -1209,6 +1266,7 @@
int err, depth;
SSL *ssl;
struct tls_connection *conn;
+ struct tls_context *context;
char *match, *altmatch;
const char *err_str;
@@ -1222,6 +1280,13 @@
conn = SSL_get_app_data(ssl);
if (conn == NULL)
return 0;
+
+ if (depth == 0)
+ conn->peer_cert = err_cert;
+ else if (depth == 1)
+ conn->peer_issuer = err_cert;
+
+ context = conn->context;
match = conn->subject_match;
altmatch = conn->altsubject_match;
@@ -1304,9 +1369,9 @@
TLS_FAIL_SERVER_CHAIN_PROBE);
}
- if (preverify_ok && tls_global->event_cb != NULL)
- tls_global->event_cb(tls_global->cb_ctx,
- TLS_CERT_CHAIN_SUCCESS, NULL);
+ if (preverify_ok && context->event_cb != NULL)
+ context->event_cb(context->cb_ctx,
+ TLS_CERT_CHAIN_SUCCESS, NULL);
return preverify_ok;
}
@@ -2702,11 +2767,187 @@
}
+#ifdef HAVE_OCSP
+
+static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
+{
+#ifndef CONFIG_NO_STDOUT_DEBUG
+ extern int wpa_debug_level;
+ BIO *out;
+ size_t rlen;
+ char *txt;
+ int res;
+
+ if (wpa_debug_level > MSG_DEBUG)
+ return;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return;
+
+ OCSP_RESPONSE_print(out, rsp, 0);
+ rlen = BIO_ctrl_pending(out);
+ txt = os_malloc(rlen + 1);
+ if (!txt) {
+ BIO_free(out);
+ return;
+ }
+
+ res = BIO_read(out, txt, rlen);
+ if (res > 0) {
+ txt[res] = '\0';
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt);
+ }
+ os_free(txt);
+ BIO_free(out);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+}
+
+
+static int ocsp_resp_cb(SSL *s, void *arg)
+{
+ struct tls_connection *conn = arg;
+ const unsigned char *p;
+ int len, status, reason;
+ OCSP_RESPONSE *rsp;
+ OCSP_BASICRESP *basic;
+ OCSP_CERTID *id;
+ ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
+
+ len = SSL_get_tlsext_status_ocsp_resp(s, &p);
+ if (!p) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
+ return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
+
+ rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
+ if (!rsp) {
+ wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
+ return 0;
+ }
+
+ ocsp_debug_print_resp(rsp);
+
+ status = OCSP_response_status(rsp);
+ if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+ wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
+ status, OCSP_response_status_str(status));
+ return 0;
+ }
+
+ basic = OCSP_response_get1_basic(rsp);
+ if (!basic) {
+ wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
+ return 0;
+ }
+
+ status = OCSP_basic_verify(basic, NULL, SSL_CTX_get_cert_store(s->ctx),
+ 0);
+ if (status <= 0) {
+ tls_show_errors(MSG_INFO, __func__,
+ "OpenSSL: OCSP response failed verification");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
+
+ if (!conn->peer_cert || !conn->peer_issuer) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate or issue certificate not available for OCSP status check");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
+ if (!id) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: Could not create OCSP certificate identifier");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ if (!OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
+ &this_update, &next_update)) {
+ wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
+ (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
+ " (OCSP not required)");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
+ }
+
+ if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
+ tls_show_errors(MSG_INFO, __func__,
+ "OpenSSL: OCSP status times invalid");
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+ return 0;
+ }
+
+ OCSP_BASICRESP_free(basic);
+ OCSP_RESPONSE_free(rsp);
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
+ OCSP_cert_status_str(status));
+
+ if (status == V_OCSP_CERTSTATUS_GOOD)
+ return 1;
+ if (status == V_OCSP_CERTSTATUS_REVOKED)
+ return 0;
+ if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
+ return 0;
+ }
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
+ return 1;
+}
+
+
+static int ocsp_status_cb(SSL *s, void *arg)
+{
+ char *tmp;
+ char *resp;
+ size_t len;
+
+ if (tls_global->ocsp_stapling_response == NULL) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured");
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+ resp = os_readfile(tls_global->ocsp_stapling_response, &len);
+ if (resp == NULL) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file");
+ /* TODO: Build OCSPResponse with responseStatus = internalError
+ */
+ return SSL_TLSEXT_ERR_OK;
+ }
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response");
+ tmp = OPENSSL_malloc(len);
+ if (tmp == NULL) {
+ os_free(resp);
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ }
+
+ os_memcpy(tmp, resp, len);
+ os_free(resp);
+ SSL_set_tlsext_status_ocsp_resp(s, tmp, len);
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+#endif /* HAVE_OCSP */
+
+
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
const struct tls_connection_params *params)
{
int ret;
unsigned long err;
+ SSL_CTX *ssl_ctx = tls_ctx;
if (conn == NULL)
return -1;
@@ -2770,10 +3011,20 @@
#ifdef SSL_OP_NO_TICKET
if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
SSL_set_options(conn->ssl, SSL_OP_NO_TICKET);
+#ifdef SSL_clear_options
else
SSL_clear_options(conn->ssl, SSL_OP_NO_TICKET);
+#endif /* SSL_clear_options */
#endif /* SSL_OP_NO_TICKET */
+#ifdef HAVE_OCSP
+ if (params->flags & TLS_CONN_REQUEST_OCSP) {
+ SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp);
+ SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
+ SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn);
+ }
+#endif /* HAVE_OCSP */
+
conn->flags = params->flags;
tls_get_errors(tls_ctx);
@@ -2812,10 +3063,23 @@
#ifdef SSL_OP_NO_TICKET
if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
+#ifdef SSL_CTX_clear_options
else
SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET);
+#endif /* SSL_clear_options */
#endif /* SSL_OP_NO_TICKET */
+#ifdef HAVE_OCSP
+ SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb);
+ SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx);
+ os_free(tls_global->ocsp_stapling_response);
+ if (params->ocsp_stapling_response)
+ tls_global->ocsp_stapling_response =
+ os_strdup(params->ocsp_stapling_response);
+ else
+ tls_global->ocsp_stapling_response = NULL;
+#endif /* HAVE_OCSP */
+
return 0;
}
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 14b64a6..0604fef 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -29,6 +29,12 @@
#define HOSTAPD_CHAN_HT40MINUS 0x00000020
#define HOSTAPD_CHAN_HT40 0x00000040
+#define HOSTAPD_CHAN_DFS_UNKNOWN 0x00000000
+#define HOSTAPD_CHAN_DFS_USABLE 0x00000100
+#define HOSTAPD_CHAN_DFS_UNAVAILABLE 0x00000200
+#define HOSTAPD_CHAN_DFS_AVAILABLE 0x00000300
+#define HOSTAPD_CHAN_DFS_MASK 0x00000300
+
/**
* struct hostapd_channel_data - Channel information
*/
@@ -824,7 +830,7 @@
* it cannot be used for P2P group operations or non-P2P purposes.
*/
#define WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE 0x00000400
-/* This interface is P2P capable (P2P Device, GO, or P2P Client */
+/* This interface is P2P capable (P2P GO or P2P Client) */
#define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800
/* Driver supports concurrent operations on multiple channels */
#define WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT 0x00001000
@@ -866,6 +872,10 @@
#define WPA_DRIVER_FLAGS_OBSS_SCAN 0x04000000
/* Driver supports IBSS (Ad-hoc) mode */
#define WPA_DRIVER_FLAGS_IBSS 0x08000000
+/* Driver supports radar detection */
+#define WPA_DRIVER_FLAGS_RADAR 0x10000000
+/* Driver supports a dedicated interface for P2P Device */
+#define WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE 0x20000000
unsigned int flags;
int max_scan_ssids;
@@ -898,6 +908,8 @@
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING 0x00000008
unsigned int probe_resp_offloads;
+ unsigned int max_acl_mac_addrs;
+
/**
* extended_capa - extended capabilities in driver/device
*
@@ -958,6 +970,16 @@
int bandwidth;
};
+struct mac_address {
+ u8 addr[ETH_ALEN];
+};
+
+struct hostapd_acl_params {
+ u8 acl_policy;
+ unsigned int num_mac_acl;
+ struct mac_address mac_acl[0];
+};
+
enum wpa_driver_if_type {
/**
* WPA_IF_STATION - Station mode interface
@@ -993,7 +1015,13 @@
* WPA_IF_P2P_GROUP - P2P Group interface (will become either
* WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known)
*/
- WPA_IF_P2P_GROUP
+ WPA_IF_P2P_GROUP,
+
+ /**
+ * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the
+ * abstracted P2P Device function in the driver
+ */
+ WPA_IF_P2P_DEVICE
};
struct wpa_init_params {
@@ -1070,6 +1098,17 @@
WNM_SLEEP_TFS_IE_DEL /* AP delete the TFS IE */
};
+/* enum chan_width - Channel width definitions */
+enum chan_width {
+ CHAN_WIDTH_20_NOHT,
+ CHAN_WIDTH_20,
+ CHAN_WIDTH_40,
+ CHAN_WIDTH_80,
+ CHAN_WIDTH_80P80,
+ CHAN_WIDTH_160,
+ CHAN_WIDTH_UNKNOWN
+};
+
/**
* struct wpa_signal_info - Information about channel signal quality
*/
@@ -1077,8 +1116,12 @@
u32 frequency;
int above_threshold;
int current_signal;
+ int avg_signal;
int current_noise;
int current_txrate;
+ enum chan_width chanwidth;
+ int center_frq1;
+ int center_frq2;
};
/**
@@ -1588,6 +1631,16 @@
int (*set_ap)(void *priv, struct wpa_driver_ap_params *params);
/**
+ * set_acl - Set ACL in AP mode
+ * @priv: Private driver interface data
+ * @params: Parameters to configure ACL
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is used only for the drivers which support MAC address ACL.
+ */
+ int (*set_acl)(void *priv, struct hostapd_acl_params *params);
+
+ /**
* hapd_init - Initialize driver interface (hostapd only)
* @hapd: Pointer to hostapd context
* @params: Configuration for the driver wrapper
@@ -2658,6 +2711,25 @@
* avoid frequency conflict in single channel concurrency.
*/
int (*switch_channel)(void *priv, unsigned int freq);
+
+ /**
+ * start_dfs_cac - Listen for radar interference on the channel
+ * @priv: Private driver interface data
+ * @freq: Frequency (in MHz) of the channel
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*start_dfs_cac)(void *priv, int freq);
+
+ /**
+ * stop_ap - Removes beacon from AP
+ * @priv: Private driver interface data
+ * Returns: 0 on success, -1 on failure (or if not supported)
+ *
+ * This optional function can be used to disable AP mode related
+ * configuration. Unlike deinit_ap, it does not change to station
+ * mode.
+ */
+ int (*stop_ap)(void *priv);
};
@@ -3111,7 +3183,38 @@
* with the specified client (for example, max client reached, etc.) in
* AP mode.
*/
- EVENT_CONNECT_FAILED_REASON
+ EVENT_CONNECT_FAILED_REASON,
+
+ /**
+ * EVENT_RADAR_DETECTED - Notify of radar detection
+ *
+ * A radar has been detected on the supplied frequency, hostapd should
+ * react accordingly (e.g., change channel).
+ */
+ EVENT_DFS_RADAR_DETECTED,
+
+ /**
+ * EVENT_CAC_FINISHED - Notify that channel availability check has been completed
+ *
+ * After a successful CAC, the channel can be marked clear and used.
+ */
+ EVENT_DFS_CAC_FINISHED,
+
+ /**
+ * EVENT_CAC_ABORTED - Notify that channel availability check has been aborted
+ *
+ * The CAC was not successful, and the channel remains in the previous
+ * state. This may happen due to a radar beeing detected or other
+ * external influences.
+ */
+ EVENT_DFS_CAC_ABORTED,
+
+ /**
+ * EVENT_DFS_CAC_NOP_FINISHED - Notify that non-occupancy period is over
+ *
+ * The channel which was previously unavailable is now available again.
+ */
+ EVENT_DFS_NOP_FINISHED
};
@@ -3749,6 +3852,14 @@
BLOCKED_CLIENT
} code;
} connect_failed_reason;
+
+ /**
+ * struct dfs_event - Data for radar detected events
+ * @freq: Frequency of the channel in MHz
+ */
+ struct dfs_event {
+ int freq;
+ } dfs_event;
};
/**
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index 565a01b..12ccc14 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -80,6 +80,10 @@
E2S(CH_SWITCH);
E2S(WNM);
E2S(CONNECT_FAILED_REASON);
+ E2S(DFS_RADAR_DETECTED);
+ E2S(DFS_CAC_FINISHED);
+ E2S(DFS_CAC_ABORTED);
+ E2S(DFS_NOP_FINISHED);
}
return "UNKNOWN";
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 7af3317..4656c1b 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -2110,14 +2110,8 @@
dlen = dpos - desc;
else
dlen = os_strlen(desc);
- drv->adapter_desc = os_malloc(dlen + 1);
- if (drv->adapter_desc) {
- os_memcpy(drv->adapter_desc, desc, dlen);
- drv->adapter_desc[dlen] = '\0';
- }
-
+ drv->adapter_desc = dup_binstr(desc, dlen);
os_free(b);
-
if (drv->adapter_desc == NULL)
return -1;
@@ -2284,14 +2278,8 @@
} else {
dlen = os_strlen(desc[i]);
}
- drv->adapter_desc = os_malloc(dlen + 1);
- if (drv->adapter_desc) {
- os_memcpy(drv->adapter_desc, desc[i], dlen);
- drv->adapter_desc[dlen] = '\0';
- }
-
+ drv->adapter_desc = dup_binstr(desc[i], dlen);
os_free(names);
-
if (drv->adapter_desc == NULL)
return -1;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c59d5bf..bcd0a94 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -157,6 +157,8 @@
struct nl80211_global {
struct dl_list interfaces;
int if_add_ifindex;
+ u64 if_add_wdevid;
+ int if_add_wdevid_set;
struct netlink_data *netlink;
struct nl_cb *nl_cb;
struct nl_handle *nl;
@@ -183,12 +185,14 @@
struct wpa_driver_nl80211_data *drv;
struct i802_bss *next;
int ifindex;
+ u64 wdev_id;
char ifname[IFNAMSIZ + 1];
char brname[IFNAMSIZ];
unsigned int beacon_set:1;
unsigned int added_if_into_bridge:1;
unsigned int added_bridge:1;
unsigned int in_deinit:1;
+ unsigned int wdev_id_set:1;
u8 addr[ETH_ALEN];
@@ -225,7 +229,9 @@
struct nl_cb *nl_cb;
u8 auth_bssid[ETH_ALEN];
+ u8 auth_attempt_bssid[ETH_ALEN];
u8 bssid[ETH_ALEN];
+ u8 prev_bssid[ETH_ALEN];
int associated;
u8 ssid[32];
size_t ssid_len;
@@ -247,6 +253,7 @@
unsigned int retry_auth:1;
unsigned int use_monitor:1;
unsigned int ignore_next_local_disconnect:1;
+ unsigned int allow_p2p_device:1;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
@@ -355,6 +362,117 @@
struct wpa_driver_nl80211_data *drv);
+static const char * nl80211_command_to_string(enum nl80211_commands cmd)
+{
+#define C2S(x) case x: return #x;
+ switch (cmd) {
+ C2S(NL80211_CMD_UNSPEC)
+ C2S(NL80211_CMD_GET_WIPHY)
+ C2S(NL80211_CMD_SET_WIPHY)
+ C2S(NL80211_CMD_NEW_WIPHY)
+ C2S(NL80211_CMD_DEL_WIPHY)
+ C2S(NL80211_CMD_GET_INTERFACE)
+ C2S(NL80211_CMD_SET_INTERFACE)
+ C2S(NL80211_CMD_NEW_INTERFACE)
+ C2S(NL80211_CMD_DEL_INTERFACE)
+ C2S(NL80211_CMD_GET_KEY)
+ C2S(NL80211_CMD_SET_KEY)
+ C2S(NL80211_CMD_NEW_KEY)
+ C2S(NL80211_CMD_DEL_KEY)
+ C2S(NL80211_CMD_GET_BEACON)
+ C2S(NL80211_CMD_SET_BEACON)
+ C2S(NL80211_CMD_START_AP)
+ C2S(NL80211_CMD_STOP_AP)
+ C2S(NL80211_CMD_GET_STATION)
+ C2S(NL80211_CMD_SET_STATION)
+ C2S(NL80211_CMD_NEW_STATION)
+ C2S(NL80211_CMD_DEL_STATION)
+ C2S(NL80211_CMD_GET_MPATH)
+ C2S(NL80211_CMD_SET_MPATH)
+ C2S(NL80211_CMD_NEW_MPATH)
+ C2S(NL80211_CMD_DEL_MPATH)
+ C2S(NL80211_CMD_SET_BSS)
+ C2S(NL80211_CMD_SET_REG)
+ C2S(NL80211_CMD_REQ_SET_REG)
+ C2S(NL80211_CMD_GET_MESH_CONFIG)
+ C2S(NL80211_CMD_SET_MESH_CONFIG)
+ C2S(NL80211_CMD_SET_MGMT_EXTRA_IE)
+ C2S(NL80211_CMD_GET_REG)
+ C2S(NL80211_CMD_GET_SCAN)
+ C2S(NL80211_CMD_TRIGGER_SCAN)
+ C2S(NL80211_CMD_NEW_SCAN_RESULTS)
+ C2S(NL80211_CMD_SCAN_ABORTED)
+ C2S(NL80211_CMD_REG_CHANGE)
+ C2S(NL80211_CMD_AUTHENTICATE)
+ C2S(NL80211_CMD_ASSOCIATE)
+ C2S(NL80211_CMD_DEAUTHENTICATE)
+ C2S(NL80211_CMD_DISASSOCIATE)
+ C2S(NL80211_CMD_MICHAEL_MIC_FAILURE)
+ C2S(NL80211_CMD_REG_BEACON_HINT)
+ C2S(NL80211_CMD_JOIN_IBSS)
+ C2S(NL80211_CMD_LEAVE_IBSS)
+ C2S(NL80211_CMD_TESTMODE)
+ C2S(NL80211_CMD_CONNECT)
+ C2S(NL80211_CMD_ROAM)
+ C2S(NL80211_CMD_DISCONNECT)
+ C2S(NL80211_CMD_SET_WIPHY_NETNS)
+ C2S(NL80211_CMD_GET_SURVEY)
+ C2S(NL80211_CMD_NEW_SURVEY_RESULTS)
+ C2S(NL80211_CMD_SET_PMKSA)
+ C2S(NL80211_CMD_DEL_PMKSA)
+ C2S(NL80211_CMD_FLUSH_PMKSA)
+ C2S(NL80211_CMD_REMAIN_ON_CHANNEL)
+ C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL)
+ C2S(NL80211_CMD_SET_TX_BITRATE_MASK)
+ C2S(NL80211_CMD_REGISTER_FRAME)
+ C2S(NL80211_CMD_FRAME)
+ C2S(NL80211_CMD_FRAME_TX_STATUS)
+ C2S(NL80211_CMD_SET_POWER_SAVE)
+ C2S(NL80211_CMD_GET_POWER_SAVE)
+ C2S(NL80211_CMD_SET_CQM)
+ C2S(NL80211_CMD_NOTIFY_CQM)
+ C2S(NL80211_CMD_SET_CHANNEL)
+ C2S(NL80211_CMD_SET_WDS_PEER)
+ C2S(NL80211_CMD_FRAME_WAIT_CANCEL)
+ C2S(NL80211_CMD_JOIN_MESH)
+ C2S(NL80211_CMD_LEAVE_MESH)
+ C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE)
+ C2S(NL80211_CMD_UNPROT_DISASSOCIATE)
+ C2S(NL80211_CMD_NEW_PEER_CANDIDATE)
+ C2S(NL80211_CMD_GET_WOWLAN)
+ C2S(NL80211_CMD_SET_WOWLAN)
+ C2S(NL80211_CMD_START_SCHED_SCAN)
+ C2S(NL80211_CMD_STOP_SCHED_SCAN)
+ C2S(NL80211_CMD_SCHED_SCAN_RESULTS)
+ C2S(NL80211_CMD_SCHED_SCAN_STOPPED)
+ C2S(NL80211_CMD_SET_REKEY_OFFLOAD)
+ C2S(NL80211_CMD_PMKSA_CANDIDATE)
+ C2S(NL80211_CMD_TDLS_OPER)
+ C2S(NL80211_CMD_TDLS_MGMT)
+ C2S(NL80211_CMD_UNEXPECTED_FRAME)
+ C2S(NL80211_CMD_PROBE_CLIENT)
+ C2S(NL80211_CMD_REGISTER_BEACONS)
+ C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME)
+ C2S(NL80211_CMD_SET_NOACK_MAP)
+ C2S(NL80211_CMD_CH_SWITCH_NOTIFY)
+ C2S(NL80211_CMD_START_P2P_DEVICE)
+ C2S(NL80211_CMD_STOP_P2P_DEVICE)
+ C2S(NL80211_CMD_CONN_FAILED)
+ C2S(NL80211_CMD_SET_MCAST_RATE)
+ C2S(NL80211_CMD_SET_MAC_ACL)
+ C2S(NL80211_CMD_RADAR_DETECT)
+ C2S(NL80211_CMD_GET_PROTOCOL_FEATURES)
+ C2S(NL80211_CMD_UPDATE_FT_IES)
+ C2S(NL80211_CMD_FT_EVENT)
+ C2S(NL80211_CMD_CRIT_PROTOCOL_START)
+ C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
+ default:
+ return "NL80211_CMD_UNKNOWN";
+ }
+#undef C2S
+}
+
+
static int is_ap_interface(enum nl80211_iftype nlmode)
{
return (nlmode == NL80211_IFTYPE_AP ||
@@ -369,13 +487,22 @@
}
-static int is_p2p_interface(enum nl80211_iftype nlmode)
+static int is_p2p_net_interface(enum nl80211_iftype nlmode)
{
return (nlmode == NL80211_IFTYPE_P2P_CLIENT ||
nlmode == NL80211_IFTYPE_P2P_GO);
}
+static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
+{
+ if (drv->associated)
+ os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
+ drv->associated = 0;
+ os_memset(drv->bssid, 0, ETH_ALEN);
+}
+
+
struct nl80211_bss_info_arg {
struct wpa_driver_nl80211_data *drv;
struct wpa_scan_results *res;
@@ -480,6 +607,19 @@
};
+static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss)
+{
+ if (bss->wdev_id_set)
+ NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
+ else
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+
static int family_handler(struct nl_msg *msg, void *arg)
{
struct family_data *res = arg;
@@ -546,6 +686,8 @@
struct wiphy_idx_data {
int wiphy_idx;
+ enum nl80211_iftype nlmode;
+ u8 *macaddr;
};
@@ -561,6 +703,13 @@
if (tb[NL80211_ATTR_WIPHY])
info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
+ if (tb[NL80211_ATTR_IFTYPE])
+ info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
+
+ if (tb[NL80211_ATTR_MAC] && info->macaddr)
+ os_memcpy(info->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
+ ETH_ALEN);
+
return NL_SKIP;
}
@@ -570,15 +719,17 @@
struct nl_msg *msg;
struct wiphy_idx_data data = {
.wiphy_idx = -1,
+ .macaddr = NULL,
};
msg = nlmsg_alloc();
if (!msg)
- return -1;
+ return NL80211_IFTYPE_UNSPECIFIED;
nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
return data.wiphy_idx;
@@ -589,6 +740,57 @@
}
+static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
+{
+ struct nl_msg *msg;
+ struct wiphy_idx_data data = {
+ .nlmode = NL80211_IFTYPE_UNSPECIFIED,
+ .macaddr = NULL,
+ };
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
+
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
+
+ if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
+ return data.nlmode;
+ msg = NULL;
+nla_put_failure:
+ nlmsg_free(msg);
+ return NL80211_IFTYPE_UNSPECIFIED;
+}
+
+
+#ifndef HOSTAPD
+static int nl80211_get_macaddr(struct i802_bss *bss)
+{
+ struct nl_msg *msg;
+ struct wiphy_idx_data data = {
+ .macaddr = bss->addr,
+ };
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return NL80211_IFTYPE_UNSPECIFIED;
+
+ nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
+
+ return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return NL80211_IFTYPE_UNSPECIFIED;
+}
+#endif /* HOSTAPD */
+
+
static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
struct nl80211_wiphy_data *w)
{
@@ -1053,6 +1255,7 @@
}
os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
+ os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
os_memset(&event, 0, sizeof(event));
os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
@@ -1132,6 +1335,7 @@
drv->associated = 1;
os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
+ os_memcpy(drv->prev_bssid, mgmt->sa, ETH_ALEN);
os_memset(&event, 0, sizeof(event));
if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
@@ -1183,8 +1387,10 @@
}
drv->associated = 1;
- if (addr)
+ if (addr) {
os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
+ os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
+ }
if (req_ie) {
event.assoc_info.req_ies = nla_data(req_ie);
@@ -1231,7 +1437,7 @@
}
wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(&data, 0, sizeof(data));
if (reason)
data.deauth_info.reason_code = nla_get_u16(reason);
@@ -1308,7 +1514,7 @@
u16 fc, stype;
int ssi_signal = 0;
- wpa_printf(MSG_DEBUG, "nl80211: Frame event");
+ wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
mgmt = (const struct ieee80211_mgmt *) frame;
if (len < 24) {
wpa_printf(MSG_DEBUG, "nl80211: Too short action frame");
@@ -1400,6 +1606,22 @@
if (len >= 24) {
bssid = mgmt->bssid;
+ if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
+ !drv->associated &&
+ os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
+ os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
+ os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
+ /*
+ * Avoid issues with some roaming cases where
+ * disconnection event for the old AP may show up after
+ * we have started connection with the new AP.
+ */
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
+ MAC2STR(bssid),
+ MAC2STR(drv->auth_attempt_bssid));
+ return;
+ }
+
if (drv->associated != 0 &&
os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
@@ -1415,7 +1637,7 @@
}
}
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(&event, 0, sizeof(event));
/* Note: Same offset for Reason Code in both frame subtypes */
@@ -1485,24 +1707,49 @@
}
-static void mlme_event(struct wpa_driver_nl80211_data *drv,
+static void mlme_event(struct i802_bss *bss,
enum nl80211_commands cmd, struct nlattr *frame,
struct nlattr *addr, struct nlattr *timed_out,
struct nlattr *freq, struct nlattr *ack,
struct nlattr *cookie, struct nlattr *sig)
{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ const u8 *data;
+ size_t len;
+
if (timed_out && addr) {
mlme_timeout_event(drv, cmd, addr);
return;
}
if (frame == NULL) {
- wpa_printf(MSG_DEBUG, "nl80211: MLME event %d without frame "
- "data", cmd);
+ wpa_printf(MSG_DEBUG,
+ "nl80211: MLME event %d (%s) without frame data",
+ cmd, nl80211_command_to_string(cmd));
return;
}
- wpa_printf(MSG_DEBUG, "nl80211: MLME event %d", cmd);
+ data = nla_data(frame);
+ len = nla_len(frame);
+ if (len < 4 + 2 * ETH_ALEN) {
+ wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s("
+ MACSTR ") - too short",
+ cmd, nl80211_command_to_string(cmd), bss->ifname,
+ MAC2STR(bss->addr));
+ return;
+ }
+ wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s(" MACSTR
+ ") A1=" MACSTR " A2=" MACSTR, cmd,
+ nl80211_command_to_string(cmd), bss->ifname,
+ MAC2STR(bss->addr), MAC2STR(data + 4),
+ MAC2STR(data + 4 + ETH_ALEN));
+ if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) &&
+ os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 &&
+ os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0) {
+ wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
+ "for foreign address", bss->ifname);
+ return;
+ }
wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame",
nla_data(frame), nla_len(frame));
@@ -1728,6 +1975,7 @@
struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+ [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
};
struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
@@ -1750,6 +1998,12 @@
sig_change->current_signal =
(s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
+ if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
+ sig_change->avg_signal =
+ (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
+ else
+ sig_change->avg_signal = 0;
+
if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
sinfo[NL80211_STA_INFO_TX_BITRATE],
@@ -2229,6 +2483,43 @@
}
+static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
+ struct nlattr **tb)
+{
+ union wpa_event_data data;
+ enum nl80211_radar_event event_type;
+
+ if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
+ return;
+
+ os_memset(&data, 0, sizeof(data));
+ data.dfs_event.freq = nla_get_u16(tb[NL80211_ATTR_WIPHY_FREQ]);
+ event_type = nla_get_u8(tb[NL80211_ATTR_RADAR_EVENT]);
+
+ wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz",
+ data.dfs_event.freq);
+
+ switch (event_type) {
+ case NL80211_RADAR_DETECTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
+ break;
+ case NL80211_RADAR_CAC_FINISHED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
+ break;
+ case NL80211_RADAR_CAC_ABORTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
+ break;
+ case NL80211_RADAR_NOP_FINISHED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
+ "received", event_type);
+ break;
+ }
+}
+
+
static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
int wds)
{
@@ -2252,6 +2543,9 @@
{
struct wpa_driver_nl80211_data *drv = bss->drv;
+ wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
+ cmd, nl80211_command_to_string(cmd), bss->ifname);
+
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
(cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
cmd == NL80211_CMD_SCAN_ABORTED)) {
@@ -2301,7 +2595,7 @@
case NL80211_CMD_FRAME_TX_STATUS:
case NL80211_CMD_UNPROT_DEAUTHENTICATE:
case NL80211_CMD_UNPROT_DISASSOCIATE:
- mlme_event(drv, cmd, tb[NL80211_ATTR_FRAME],
+ mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
tb[NL80211_ATTR_COOKIE],
@@ -2373,6 +2667,9 @@
case NL80211_CMD_FT_EVENT:
mlme_event_ft_event(drv, tb);
break;
+ case NL80211_CMD_RADAR_DETECT:
+ nl80211_radar_event(drv, tb);
+ break;
default:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", cmd);
@@ -2392,19 +2689,31 @@
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
- if (tb[NL80211_ATTR_IFINDEX])
+ if (tb[NL80211_ATTR_IFINDEX]) {
ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
- for (bss = &drv->first_bss; bss; bss = bss->next) {
- if (ifidx == -1 || ifidx == bss->ifindex) {
- do_process_drv_event(bss, gnlh->cmd, tb);
- return NL_SKIP;
+ for (bss = &drv->first_bss; bss; bss = bss->next)
+ if (ifidx == -1 || ifidx == bss->ifindex) {
+ do_process_drv_event(bss, gnlh->cmd, tb);
+ return NL_SKIP;
+ }
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignored event (cmd=%d) for foreign interface (ifindex %d)",
+ gnlh->cmd, ifidx);
+ } else if (tb[NL80211_ATTR_WDEV]) {
+ u64 wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
+ wpa_printf(MSG_DEBUG, "nl80211: Process event on P2P device");
+ for (bss = &drv->first_bss; bss; bss = bss->next) {
+ if (bss->wdev_id_set && wdev_id == bss->wdev_id) {
+ do_process_drv_event(bss, gnlh->cmd, tb);
+ return NL_SKIP;
+ }
}
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignored event (cmd=%d) for foreign interface (wdev 0x%llx)",
+ gnlh->cmd, (long long unsigned int) wdev_id);
}
- wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d) for foreign "
- "interface (ifindex %d)", gnlh->cmd, ifidx);
-
return NL_SKIP;
}
@@ -2417,17 +2726,26 @@
struct wpa_driver_nl80211_data *drv, *tmp;
int ifidx = -1;
struct i802_bss *bss;
+ u64 wdev_id = 0;
+ int wdev_id_set = 0;
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
if (tb[NL80211_ATTR_IFINDEX])
ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
+ else if (tb[NL80211_ATTR_WDEV]) {
+ wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
+ wdev_id_set = 1;
+ }
dl_list_for_each_safe(drv, tmp, &global->interfaces,
struct wpa_driver_nl80211_data, list) {
for (bss = &drv->first_bss; bss; bss = bss->next) {
- if (ifidx == -1 || ifidx == bss->ifindex) {
+ if ((ifidx == -1 && !wdev_id_set) ||
+ ifidx == bss->ifindex ||
+ (wdev_id_set && bss->wdev_id_set &&
+ wdev_id == bss->wdev_id)) {
do_process_drv_event(bss, gnlh->cmd, tb);
return NL_SKIP;
}
@@ -2447,10 +2765,14 @@
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
+ wpa_printf(MSG_DEBUG, "nl80211: BSS Event %d (%s) received for %s",
+ gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
+ bss->ifname);
+
switch (gnlh->cmd) {
case NL80211_CMD_FRAME:
case NL80211_CMD_FRAME_TX_STATUS:
- mlme_event(bss->drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],
+ mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
tb[NL80211_ATTR_COOKIE],
@@ -2477,7 +2799,7 @@
{
struct nl_cb *cb = eloop_ctx;
- wpa_printf(MSG_DEBUG, "nl80211: Event message available");
+ wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");
nl_recvmsgs(handle, cb);
}
@@ -2607,6 +2929,10 @@
case NL80211_IFTYPE_ADHOC:
info->capa->flags |= WPA_DRIVER_FLAGS_IBSS;
break;
+ case NL80211_IFTYPE_P2P_DEVICE:
+ info->capa->flags |=
+ WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
+ break;
case NL80211_IFTYPE_P2P_GO:
info->p2p_go_supported = 1;
break;
@@ -2635,6 +2961,7 @@
[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
+ [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
},
iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
@@ -2648,6 +2975,9 @@
!tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
return 0; /* broken combination */
+ if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS])
+ info->capa->flags |= WPA_DRIVER_FLAGS_RADAR;
+
nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS],
rem_limit) {
err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
@@ -2727,9 +3057,6 @@
static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
struct nlattr *tb)
{
- /* default to 5000 since early versions of mac80211 don't set it */
- capa->max_remain_on_chan = 5000;
-
if (tb)
capa->max_remain_on_chan = nla_get_u32(tb);
}
@@ -2803,6 +3130,10 @@
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
+ if (tb[NL80211_ATTR_WIPHY_NAME])
+ os_strncpy(drv->phyname,
+ nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
+ sizeof(drv->phyname));
if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
capa->max_scan_ssids =
nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
@@ -2815,6 +3146,10 @@
capa->max_match_sets =
nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
+ if (tb[NL80211_ATTR_MAC_ACL_MAX])
+ capa->max_acl_mac_addrs =
+ nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
+
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
@@ -2895,7 +3230,8 @@
nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->first_bss.ifindex);
+ if (nl80211_set_iface_id(msg, &drv->first_bss) < 0)
+ goto nla_put_failure;
if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info))
return -1;
@@ -2921,6 +3257,11 @@
"concurrent (driver advertised support)");
drv->capa.flags |= WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT;
}
+
+ /* default to 5000 since early versions of mac80211 don't set it */
+ if (!drv->capa.max_remain_on_chan)
+ drv->capa.max_remain_on_chan = 5000;
+
return 0;
nla_put_failure:
nlmsg_free(msg);
@@ -3163,39 +3504,6 @@
}
-static void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv)
-{
- /* Find phy (radio) to which this interface belongs */
- char buf[90], *pos;
- int f, rv;
-
- drv->phyname[0] = '\0';
- snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name",
- drv->first_bss.ifname);
- f = open(buf, O_RDONLY);
- if (f < 0) {
- wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
- buf, strerror(errno));
- return;
- }
-
- rv = read(f, drv->phyname, sizeof(drv->phyname) - 1);
- close(f);
- if (rv < 0) {
- wpa_printf(MSG_DEBUG, "Could not read file %s: %s",
- buf, strerror(errno));
- return;
- }
-
- drv->phyname[rv] = '\0';
- pos = os_strchr(drv->phyname, '\n');
- if (pos)
- *pos = '\0';
- wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
- drv->first_bss.ifname, drv->phyname);
-}
-
-
static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
void *eloop_ctx,
void *handle)
@@ -3317,8 +3625,6 @@
if (nl80211_init_bss(bss))
goto failed;
- nl80211_get_phy_name(drv);
-
rcfg = os_zalloc(sizeof(*rcfg));
if (rcfg == NULL)
goto failed;
@@ -3389,7 +3695,9 @@
nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
+
NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);
@@ -3626,27 +3934,124 @@
}
+static void nl80211_del_p2pdev(struct i802_bss *bss)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return;
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
+ NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
+ bss->ifname, (long long unsigned int) bss->wdev_id,
+ strerror(ret));
+
+nla_put_failure:
+ nlmsg_free(msg);
+}
+
+
+static int nl80211_set_p2pdev(struct i802_bss *bss, int start)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret = -1;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ if (start)
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_START_P2P_DEVICE);
+ else
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_P2P_DEVICE);
+
+ NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+
+ wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
+ start ? "Start" : "Stop",
+ bss->ifname, (long long unsigned int) bss->wdev_id,
+ strerror(ret));
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+}
+
+
+static int i802_set_iface_flags(struct i802_bss *bss, int up)
+{
+ enum nl80211_iftype nlmode;
+
+ nlmode = nl80211_get_ifmode(bss);
+ if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
+ return linux_set_iface_flags(bss->drv->global->ioctl_sock,
+ bss->ifname, up);
+ }
+
+ /* P2P Device has start/stop which is equivalent */
+ return nl80211_set_p2pdev(bss, up);
+}
+
+
static int
wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
{
+#ifndef HOSTAPD
+ enum nl80211_iftype nlmode = NL80211_IFTYPE_STATION;
+#endif /* HOSTAPD */
struct i802_bss *bss = &drv->first_bss;
int send_rfkill_event = 0;
+ int dynamic_if;
drv->ifindex = if_nametoindex(bss->ifname);
- drv->first_bss.ifindex = drv->ifindex;
+ bss->ifindex = drv->ifindex;
+ bss->wdev_id = drv->global->if_add_wdevid;
+ bss->wdev_id_set = drv->global->if_add_wdevid_set;
+
+ dynamic_if = drv->ifindex == drv->global->if_add_ifindex;
+ dynamic_if = dynamic_if || drv->global->if_add_wdevid_set;
+ drv->global->if_add_wdevid_set = 0;
+
+ if (wpa_driver_nl80211_capa(drv))
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
+ bss->ifname, drv->phyname);
#ifndef HOSTAPD
+ if (dynamic_if)
+ nlmode = nl80211_get_ifmode(bss);
+
/*
* Make sure the interface starts up in station mode unless this is a
* dynamically added interface (e.g., P2P) that was already configured
* with proper iftype.
*/
- if (drv->ifindex != drv->global->if_add_ifindex &&
- wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {
- wpa_printf(MSG_ERROR, "nl80211: Could not configure driver to "
- "use managed mode");
+ if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
+ wpa_printf(MSG_ERROR, "nl80211: Could not configure driver to use managed mode");
return -1;
}
+ drv->nlmode = nlmode;
+
+ if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
+ int ret = nl80211_set_p2pdev(bss, 1);
+ if (ret < 0)
+ wpa_printf(MSG_ERROR, "nl80211: Could not start P2P device");
+ nl80211_get_macaddr(bss);
+ return ret;
+ }
if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
if (rfkill_is_blocked(drv->rfkill)) {
@@ -3666,9 +4071,6 @@
1, IF_OPER_DORMANT);
#endif /* HOSTAPD */
- if (wpa_driver_nl80211_capa(drv))
- return -1;
-
if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
bss->addr))
return -1;
@@ -3765,10 +4167,13 @@
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
- (void) linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
- wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION);
- nl80211_mgmt_unsubscribe(bss, "deinit");
-
+ (void) i802_set_iface_flags(bss, 0);
+ if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
+ wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION);
+ } else {
+ nl80211_mgmt_unsubscribe(bss, "deinit");
+ nl80211_del_p2pdev(bss);
+ }
nl_cb_put(drv->nl_cb);
nl80211_destroy_bss(&drv->first_bss);
@@ -3809,10 +4214,9 @@
static struct nl_msg *
nl80211_scan_common(struct wpa_driver_nl80211_data *drv, u8 cmd,
- struct wpa_driver_scan_params *params)
+ struct wpa_driver_scan_params *params, u64 *wdev_id)
{
struct nl_msg *msg;
- int err;
size_t i;
msg = nlmsg_alloc();
@@ -3821,27 +4225,26 @@
nl80211_cmd(drv, msg, 0, cmd);
- if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, drv->ifindex) < 0)
- goto fail;
+ if (!wdev_id)
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ else
+ NLA_PUT_U64(msg, NL80211_ATTR_WDEV, *wdev_id);
if (params->num_ssids) {
- struct nl_msg *ssids = nlmsg_alloc();
+ struct nlattr *ssids;
+
+ ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
if (ssids == NULL)
goto fail;
for (i = 0; i < params->num_ssids; i++) {
wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
params->ssids[i].ssid,
params->ssids[i].ssid_len);
- if (nla_put(ssids, i + 1, params->ssids[i].ssid_len,
- params->ssids[i].ssid) < 0) {
- nlmsg_free(ssids);
+ if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
+ params->ssids[i].ssid) < 0)
goto fail;
- }
}
- err = nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
- nlmsg_free(ssids);
- if (err < 0)
- goto fail;
+ nla_nest_end(msg, ssids);
}
if (params->extra_ies) {
@@ -3853,22 +4256,17 @@
}
if (params->freqs) {
- struct nl_msg *freqs = nlmsg_alloc();
+ struct nlattr *freqs;
+ freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
if (freqs == NULL)
goto fail;
for (i = 0; params->freqs[i]; i++) {
wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
"MHz", params->freqs[i]);
- if (nla_put_u32(freqs, i + 1, params->freqs[i]) < 0) {
- nlmsg_free(freqs);
+ if (nla_put_u32(msg, i + 1, params->freqs[i]) < 0)
goto fail;
- }
}
- err = nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES,
- freqs);
- nlmsg_free(freqs);
- if (err < 0)
- goto fail;
+ nla_nest_end(msg, freqs);
}
os_free(drv->filter_ssids);
@@ -3879,6 +4277,7 @@
return msg;
fail:
+nla_put_failure:
nlmsg_free(msg);
return NULL;
}
@@ -3895,19 +4294,22 @@
{
struct wpa_driver_nl80211_data *drv = bss->drv;
int ret = -1, timeout;
- struct nl_msg *msg, *rates = NULL;
+ struct nl_msg *msg = NULL;
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
drv->scan_for_auth = 0;
- msg = nl80211_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params);
+ msg = nl80211_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params,
+ bss->wdev_id_set ? &bss->wdev_id : NULL);
if (!msg)
return -1;
if (params->p2p_probe) {
+ struct nlattr *rates;
+
wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
- rates = nlmsg_alloc();
+ rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
if (rates == NULL)
goto nla_put_failure;
@@ -3917,11 +4319,9 @@
* 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
* rates are left enabled.
*/
- NLA_PUT(rates, NL80211_BAND_2GHZ, 8,
+ NLA_PUT(msg, NL80211_BAND_2GHZ, 8,
"\x0c\x12\x18\x24\x30\x48\x60\x6c");
- if (nla_put_nested(msg, NL80211_ATTR_SCAN_SUPP_RATES, rates) <
- 0)
- goto nla_put_failure;
+ nla_nest_end(msg, rates);
NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
}
@@ -3975,7 +4375,6 @@
nla_put_failure:
nlmsg_free(msg);
- nlmsg_free(rates);
return ret;
}
@@ -3995,8 +4394,6 @@
struct wpa_driver_nl80211_data *drv = bss->drv;
int ret = -1;
struct nl_msg *msg;
- struct nl_msg *match_set_ssid = NULL, *match_sets = NULL;
- struct nl_msg *match_set_rssi = NULL;
size_t i;
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
@@ -4006,7 +4403,8 @@
return android_pno_start(bss, params);
#endif /* ANDROID */
- msg = nl80211_scan_common(drv, NL80211_CMD_START_SCHED_SCAN, params);
+ msg = nl80211_scan_common(drv, NL80211_CMD_START_SCHED_SCAN, params,
+ bss->wdev_id_set ? &bss->wdev_id : NULL);
if (!msg)
goto nla_put_failure;
@@ -4015,46 +4413,42 @@
if ((drv->num_filter_ssids &&
(int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
params->filter_rssi) {
- match_sets = nlmsg_alloc();
+ struct nlattr *match_sets;
+ match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
if (match_sets == NULL)
goto nla_put_failure;
for (i = 0; i < drv->num_filter_ssids; i++) {
+ struct nlattr *match_set_ssid;
wpa_hexdump_ascii(MSG_MSGDUMP,
"nl80211: Sched scan filter SSID",
drv->filter_ssids[i].ssid,
drv->filter_ssids[i].ssid_len);
- match_set_ssid = nlmsg_alloc();
+ match_set_ssid = nla_nest_start(msg, i + 1);
if (match_set_ssid == NULL)
goto nla_put_failure;
- NLA_PUT(match_set_ssid,
- NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
+ NLA_PUT(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
drv->filter_ssids[i].ssid_len,
drv->filter_ssids[i].ssid);
- if (nla_put_nested(match_sets, i + 1, match_set_ssid) <
- 0)
- goto nla_put_failure;
+ nla_nest_end(msg, match_set_ssid);
}
if (params->filter_rssi) {
- match_set_rssi = nlmsg_alloc();
+ struct nlattr *match_set_rssi;
+ match_set_rssi = nla_nest_start(msg, 0);
if (match_set_rssi == NULL)
goto nla_put_failure;
- NLA_PUT_U32(match_set_rssi,
- NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
+ NLA_PUT_U32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
params->filter_rssi);
wpa_printf(MSG_MSGDUMP,
"nl80211: Sched scan RSSI filter %d dBm",
params->filter_rssi);
- if (nla_put_nested(match_sets, 0, match_set_rssi) < 0)
- goto nla_put_failure;
+ nla_nest_end(msg, match_set_rssi);
}
- if (nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH,
- match_sets) < 0)
- goto nla_put_failure;
+ nla_nest_end(msg, match_sets);
}
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -4072,9 +4466,6 @@
"scan interval %d msec", ret, interval);
nla_put_failure:
- nlmsg_free(match_set_ssid);
- nlmsg_free(match_sets);
- nlmsg_free(match_set_rssi);
nlmsg_free(msg);
return ret;
}
@@ -4416,7 +4807,8 @@
goto nla_put_failure;
nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ if (nl80211_set_iface_id(msg, &drv->first_bss) < 0)
+ goto nla_put_failure;
arg.drv = drv;
arg.res = res;
@@ -4487,13 +4879,18 @@
const u8 *key, size_t key_len)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
- int ifindex = if_nametoindex(ifname);
+ int ifindex;
struct nl_msg *msg;
int ret;
- wpa_printf(MSG_DEBUG, "%s: ifindex=%d alg=%d addr=%p key_idx=%d "
+ /* Ignore for P2P Device */
+ if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
+ return 0;
+
+ ifindex = if_nametoindex(ifname);
+ wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
"set_tx=%d seq_len=%lu key_len=%lu",
- __func__, ifindex, alg, addr, key_idx, set_tx,
+ __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
(unsigned long) seq_len, (unsigned long) key_len);
#ifdef CONFIG_TDLS
if (key_idx == -1)
@@ -4563,18 +4960,15 @@
NL80211_KEYTYPE_GROUP);
}
} else if (addr && is_broadcast_ether_addr(addr)) {
- struct nl_msg *types;
- int err;
+ struct nlattr *types;
+
wpa_printf(MSG_DEBUG, " broadcast key");
- types = nlmsg_alloc();
+
+ types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
if (!types)
goto nla_put_failure;
- NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
- err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
- types);
- nlmsg_free(types);
- if (err)
- goto nla_put_failure;
+ NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
+ nla_nest_end(msg, types);
}
NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
@@ -4608,29 +5002,21 @@
else
NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
if (addr && is_broadcast_ether_addr(addr)) {
- struct nl_msg *types;
- int err;
- types = nlmsg_alloc();
+ struct nlattr *types;
+
+ types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
if (!types)
goto nla_put_failure;
- NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
- err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
- types);
- nlmsg_free(types);
- if (err)
- goto nla_put_failure;
+ NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
+ nla_nest_end(msg, types);
} else if (addr) {
- struct nl_msg *types;
- int err;
- types = nlmsg_alloc();
+ struct nlattr *types;
+
+ types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
if (!types)
goto nla_put_failure;
- NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_UNICAST);
- err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
- types);
- nlmsg_free(types);
- if (err)
- goto nla_put_failure;
+ NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST);
+ nla_nest_end(msg, types);
}
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -4804,7 +5190,7 @@
int reason_code)
{
wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
drv->ignore_next_local_disconnect = 0;
/* Disconnect command doesn't need BSSID - it uses cached value */
return wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
@@ -4820,7 +5206,7 @@
return wpa_driver_nl80211_disconnect(drv, reason_code);
wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
__func__, MAC2STR(addr), reason_code);
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
if (drv->nlmode == NL80211_IFTYPE_ADHOC)
return nl80211_leave_ibss(drv);
return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
@@ -4888,8 +5274,12 @@
is_retry = drv->retry_auth;
drv->retry_auth = 0;
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(drv->auth_bssid, 0, ETH_ALEN);
+ if (params->bssid)
+ os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
+ else
+ os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
/* FIX: IBSS mode */
nlmode = params->p2p ?
NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
@@ -5131,35 +5521,11 @@
struct hostapd_channel_data *chan,
struct nlattr *tb_freq[])
{
- enum hostapd_hw_mode m;
-
+ u8 channel;
chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
chan->flag = 0;
-
- if (chan->freq < 4000)
- m = HOSTAPD_MODE_IEEE80211B;
- else if (chan->freq > 50000)
- m = HOSTAPD_MODE_IEEE80211AD;
- else
- m = HOSTAPD_MODE_IEEE80211A;
-
- switch (m) {
- case HOSTAPD_MODE_IEEE80211AD:
- chan->chan = (chan->freq - 56160) / 2160;
- break;
- case HOSTAPD_MODE_IEEE80211A:
- chan->chan = chan->freq / 5 - 1000;
- break;
- case HOSTAPD_MODE_IEEE80211B:
- case HOSTAPD_MODE_IEEE80211G:
- if (chan->freq == 2484)
- chan->chan = 14;
- else
- chan->chan = (chan->freq - 2407) / 5;
- break;
- default:
- break;
- }
+ if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
+ chan->chan = channel;
if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
chan->flag |= HOSTAPD_CHAN_DISABLED;
@@ -5174,6 +5540,22 @@
!tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
chan->max_tx_power = nla_get_u32(
tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100;
+ if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) {
+ enum nl80211_dfs_state state =
+ nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]);
+
+ switch (state) {
+ case NL80211_DFS_USABLE:
+ chan->flag |= HOSTAPD_CHAN_DFS_USABLE;
+ break;
+ case NL80211_DFS_AVAILABLE:
+ chan->flag |= HOSTAPD_CHAN_DFS_AVAILABLE;
+ break;
+ case NL80211_DFS_UNAVAILABLE:
+ chan->flag |= HOSTAPD_CHAN_DFS_UNAVAILABLE;
+ break;
+ }
+ }
}
@@ -5187,6 +5569,7 @@
[NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
[NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
+ [NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 },
};
int new_channels = 0;
struct hostapd_channel_data *channel;
@@ -5716,7 +6099,8 @@
mgmt = (struct ieee80211_mgmt *) data;
fc = le_to_host16(mgmt->frame_control);
- if (is_sta_interface(drv->nlmode) &&
+ if ((is_sta_interface(drv->nlmode) ||
+ drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
/*
@@ -5807,6 +6191,60 @@
}
+static int wpa_driver_nl80211_set_acl(void *priv,
+ struct hostapd_acl_params *params)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *acl;
+ unsigned int i;
+ int ret = 0;
+
+ if (!(drv->capa.max_acl_mac_addrs))
+ return -ENOTSUP;
+
+ if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
+ return -ENOTSUP;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
+ params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_MAC_ACL);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
+ NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
+ NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED);
+
+ acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
+ if (acl == NULL)
+ goto nla_put_failure;
+
+ for (i = 0; i < params->num_mac_acl; i++)
+ NLA_PUT(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr);
+
+ nla_nest_end(msg, acl);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
+ ret, strerror(-ret));
+ }
+
+nla_put_failure:
+ nlmsg_free(msg);
+
+ return ret;
+}
+
+
static int wpa_driver_nl80211_set_ap(void *priv,
struct wpa_driver_ap_params *params)
{
@@ -6102,7 +6540,7 @@
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
- struct nl_msg *msg, *wme = NULL;
+ struct nl_msg *msg;
struct nl80211_sta_flag_update upd;
int ret = -ENOBUFS;
@@ -6126,12 +6564,25 @@
wpa_hexdump(MSG_DEBUG, " * supported rates", params->supp_rates,
params->supp_rates_len);
if (!params->set) {
- wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
- NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
+ if (params->aid) {
+ wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
+ NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
+ } else {
+ /*
+ * cfg80211 validates that AID is non-zero, so we have
+ * to make this a non-zero value for the TDLS case where
+ * a dummy STA entry is used for now.
+ */
+ wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)");
+ NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, 1);
+ }
wpa_printf(MSG_DEBUG, " * listen_interval=%u",
params->listen_interval);
NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
params->listen_interval);
+ } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
+ wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
+ NLA_PUT_U16(msg, NL80211_ATTR_PEER_AID, params->aid);
}
if (params->ht_capabilities) {
wpa_hexdump(MSG_DEBUG, " * ht_capabilities",
@@ -6169,18 +6620,18 @@
NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
if (params->flags & WPA_STA_WMM) {
- wme = nlmsg_alloc();
+ struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME);
+
if (!wme)
goto nla_put_failure;
wpa_printf(MSG_DEBUG, " * qosinfo=0x%x", params->qosinfo);
- NLA_PUT_U8(wme, NL80211_STA_WME_UAPSD_QUEUES,
+ NLA_PUT_U8(msg, NL80211_STA_WME_UAPSD_QUEUES,
params->qosinfo & WMM_QOSINFO_STA_AC_MASK);
- NLA_PUT_U8(wme, NL80211_STA_WME_MAX_SP,
+ NLA_PUT_U8(msg, NL80211_STA_WME_MAX_SP,
(params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &
WMM_QOSINFO_STA_SP_MASK);
- if (nla_put_nested(msg, NL80211_ATTR_STA_WME, wme) < 0)
- goto nla_put_failure;
+ nla_nest_end(msg, wme);
}
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -6192,7 +6643,6 @@
if (ret == -EEXIST)
ret = 0;
nla_put_failure:
- nlmsg_free(wme);
nlmsg_free(msg);
return ret;
}
@@ -6259,12 +6709,20 @@
return "STATION";
case NL80211_IFTYPE_AP:
return "AP";
+ case NL80211_IFTYPE_AP_VLAN:
+ return "AP_VLAN";
+ case NL80211_IFTYPE_WDS:
+ return "WDS";
case NL80211_IFTYPE_MONITOR:
return "MONITOR";
+ case NL80211_IFTYPE_MESH_POINT:
+ return "MESH_POINT";
case NL80211_IFTYPE_P2P_CLIENT:
return "P2P_CLIENT";
case NL80211_IFTYPE_P2P_GO:
return "P2P_GO";
+ case NL80211_IFTYPE_P2P_DEVICE:
+ return "P2P_DEVICE";
default:
return "unknown";
}
@@ -6274,9 +6732,11 @@
static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
const char *ifname,
enum nl80211_iftype iftype,
- const u8 *addr, int wds)
+ const u8 *addr, int wds,
+ int (*handler)(struct nl_msg *, void *),
+ void *arg)
{
- struct nl_msg *msg, *flags = NULL;
+ struct nl_msg *msg;
int ifidx;
int ret = -ENOBUFS;
@@ -6288,30 +6748,26 @@
return -1;
nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ if (nl80211_set_iface_id(msg, &drv->first_bss) < 0)
+ goto nla_put_failure;
NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
if (iftype == NL80211_IFTYPE_MONITOR) {
- int err;
+ struct nlattr *flags;
- flags = nlmsg_alloc();
+ flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS);
if (!flags)
goto nla_put_failure;
- NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);
+ NLA_PUT_FLAG(msg, NL80211_MNTR_FLAG_COOK_FRAMES);
- err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);
-
- nlmsg_free(flags);
-
- if (err)
- goto nla_put_failure;
+ nla_nest_end(msg, flags);
} else if (wds) {
NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
}
- ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ ret = send_and_recv_msgs(drv, msg, handler, arg);
msg = NULL;
if (ret) {
nla_put_failure:
@@ -6321,6 +6777,9 @@
return ret;
}
+ if (iftype == NL80211_IFTYPE_P2P_DEVICE)
+ return 0;
+
ifidx = if_nametoindex(ifname);
wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d",
ifname, ifidx);
@@ -6343,11 +6802,14 @@
static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
const char *ifname, enum nl80211_iftype iftype,
- const u8 *addr, int wds)
+ const u8 *addr, int wds,
+ int (*handler)(struct nl_msg *, void *),
+ void *arg)
{
int ret;
- ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds);
+ ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler,
+ arg);
/* if error occurred and interface exists already */
if (ret == -ENFILE && if_nametoindex(ifname)) {
@@ -6358,10 +6820,10 @@
/* Try to create the interface again */
ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
- wds);
+ wds, handler, arg);
}
- if (ret >= 0 && is_p2p_interface(iftype))
+ if (ret >= 0 && is_p2p_net_interface(iftype))
nl80211_disable_11b_rates(drv, ret, 1);
return ret;
@@ -6708,7 +7170,7 @@
drv->monitor_ifidx =
nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,
- 0);
+ 0, NULL, NULL);
if (drv->monitor_ifidx == -EOPNOTSUPP) {
/*
@@ -6939,19 +7401,14 @@
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
- struct nl_msg *msg, *flags = NULL;
+ struct nl_msg *msg;
+ struct nlattr *flags;
struct nl80211_sta_flag_update upd;
msg = nlmsg_alloc();
if (!msg)
return -ENOMEM;
- flags = nlmsg_alloc();
- if (!flags) {
- nlmsg_free(msg);
- return -ENOMEM;
- }
-
nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
@@ -6962,35 +7419,34 @@
* Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
* can be removed eventually.
*/
+ flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS);
+ if (!flags)
+ goto nla_put_failure;
if (total_flags & WPA_STA_AUTHORIZED)
- NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);
+ NLA_PUT_FLAG(msg, NL80211_STA_FLAG_AUTHORIZED);
if (total_flags & WPA_STA_WMM)
- NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);
+ NLA_PUT_FLAG(msg, NL80211_STA_FLAG_WME);
if (total_flags & WPA_STA_SHORT_PREAMBLE)
- NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);
+ NLA_PUT_FLAG(msg, NL80211_STA_FLAG_SHORT_PREAMBLE);
if (total_flags & WPA_STA_MFP)
- NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP);
+ NLA_PUT_FLAG(msg, NL80211_STA_FLAG_MFP);
if (total_flags & WPA_STA_TDLS_PEER)
- NLA_PUT_FLAG(flags, NL80211_STA_FLAG_TDLS_PEER);
+ NLA_PUT_FLAG(msg, NL80211_STA_FLAG_TDLS_PEER);
- if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
- goto nla_put_failure;
+ nla_nest_end(msg, flags);
os_memset(&upd, 0, sizeof(upd));
upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
upd.set = sta_flags_nl80211(flags_or);
NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
- nlmsg_free(flags);
-
return send_and_recv_msgs(drv, msg, NULL, NULL);
nla_put_failure:
nlmsg_free(msg);
- nlmsg_free(flags);
return -ENOBUFS;
}
@@ -7410,7 +7866,7 @@
return wpa_driver_nl80211_connect(drv, params);
}
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
msg = nlmsg_alloc();
if (!msg)
@@ -7577,7 +8033,8 @@
return -ENOMEM;
nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
+ if (nl80211_set_iface_id(msg, &drv->first_bss) < 0)
+ goto nla_put_failure;
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -7602,6 +8059,9 @@
int res;
res = nl80211_set_mode(drv, drv->ifindex, nlmode);
+ if (res && nlmode == nl80211_get_ifmode(bss))
+ res = 0;
+
if (res == 0) {
drv->nlmode = nlmode;
ret = 0;
@@ -7625,8 +8085,7 @@
wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
"interface down");
for (i = 0; i < 10; i++) {
- res = linux_set_iface_flags(drv->global->ioctl_sock,
- bss->ifname, 0);
+ res = i802_set_iface_flags(bss, 0);
if (res == -EACCES || res == -ENODEV)
break;
if (res == 0) {
@@ -7635,8 +8094,7 @@
ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
if (ret == -EACCES)
break;
- res = linux_set_iface_flags(drv->global->ioctl_sock,
- bss->ifname, 1);
+ res = i802_set_iface_flags(bss, 1);
if (res && !ret)
ret = -1;
else if (ret != -EBUSY)
@@ -7661,7 +8119,7 @@
return ret;
}
- if (is_p2p_interface(nlmode))
+ if (is_p2p_net_interface(nlmode))
nl80211_disable_11b_rates(drv, drv->ifindex, 1);
else if (drv->disabled_11b_rates)
nl80211_disable_11b_rates(drv, drv->ifindex, 0);
@@ -7700,6 +8158,13 @@
capa->extended_capa_mask = drv->extended_capa_mask;
capa->extended_capa_len = drv->extended_capa_len;
}
+
+ if ((capa->flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
+ !drv->allow_p2p_device) {
+ wpa_printf(MSG_DEBUG, "nl80211: Do not indicate P2P_DEVICE support (p2p_device=1 driver param not specified)");
+ capa->flags &= ~WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
+ }
+
return 0;
}
@@ -7724,6 +8189,9 @@
struct nl_msg *msg;
struct nl80211_sta_flag_update upd;
+ wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
+ MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
+
msg = nlmsg_alloc();
if (!msg)
return -ENOMEM;
@@ -8235,7 +8703,7 @@
if (!if_nametoindex(name)) {
if (nl80211_create_iface(drv, name,
NL80211_IFTYPE_AP_VLAN,
- bss->addr, 1) < 0)
+ bss->addr, 1, NULL, NULL) < 0)
return -1;
if (bridge_ifname &&
linux_br_add_if(drv->global->ioctl_sock,
@@ -8451,6 +8919,8 @@
return NL80211_IFTYPE_AP;
case WPA_IF_P2P_GO:
return NL80211_IFTYPE_P2P_GO;
+ case WPA_IF_P2P_DEVICE:
+ return NL80211_IFTYPE_P2P_DEVICE;
}
return -1;
}
@@ -8497,12 +8967,40 @@
#endif /* CONFIG_P2P */
+struct wdev_info {
+ u64 wdev_id;
+ int wdev_id_set;
+ u8 macaddr[ETH_ALEN];
+};
+
+static int nl80211_wdev_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct wdev_info *wi = arg;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+ if (tb[NL80211_ATTR_WDEV]) {
+ wi->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
+ wi->wdev_id_set = 1;
+ }
+
+ if (tb[NL80211_ATTR_MAC])
+ os_memcpy(wi->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
+ ETH_ALEN);
+
+ return NL_SKIP;
+}
+
+
static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
const char *ifname, const u8 *addr,
void *bss_ctx, void **drv_priv,
char *force_ifname, u8 *if_addr,
const char *bridge)
{
+ enum nl80211_iftype nlmode;
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
int ifidx;
@@ -8518,21 +9016,46 @@
if (addr)
os_memcpy(if_addr, addr, ETH_ALEN);
- ifidx = nl80211_create_iface(drv, ifname,
- wpa_driver_nl80211_if_type(type), addr,
- 0);
- if (ifidx < 0) {
+ nlmode = wpa_driver_nl80211_if_type(type);
+ if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
+ struct wdev_info p2pdev_info;
+
+ os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
+ ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
+ 0, nl80211_wdev_handler,
+ &p2pdev_info);
+ if (!p2pdev_info.wdev_id_set || ifidx != 0) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s",
+ ifname);
+ return -1;
+ }
+
+ drv->global->if_add_wdevid = p2pdev_info.wdev_id;
+ drv->global->if_add_wdevid_set = p2pdev_info.wdev_id_set;
+ if (!is_zero_ether_addr(p2pdev_info.macaddr))
+ os_memcpy(if_addr, p2pdev_info.macaddr, ETH_ALEN);
+ wpa_printf(MSG_DEBUG, "nl80211: New P2P Device interface %s (0x%llx) created",
+ ifname,
+ (long long unsigned int) p2pdev_info.wdev_id);
+ } else {
+ ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
+ 0, NULL, NULL);
+ if (ifidx < 0) {
#ifdef HOSTAPD
- os_free(new_bss);
+ os_free(new_bss);
#endif /* HOSTAPD */
- return -1;
+ return -1;
+ }
}
- if (!addr &&
- linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
- if_addr) < 0) {
- nl80211_remove_iface(drv, ifidx);
- return -1;
+ if (!addr) {
+ if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
+ os_memcpy(if_addr, bss->addr, ETH_ALEN);
+ else if (linux_get_ifhwaddr(drv->global->ioctl_sock,
+ bss->ifname, if_addr) < 0) {
+ nl80211_remove_iface(drv, ifidx);
+ return -1;
+ }
}
#ifdef CONFIG_P2P
@@ -8540,16 +9063,14 @@
(type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||
type == WPA_IF_P2P_GO)) {
/* Enforce unique P2P Interface Address */
- u8 new_addr[ETH_ALEN], own_addr[ETH_ALEN];
+ u8 new_addr[ETH_ALEN];
- if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
- own_addr) < 0 ||
- linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
+ if (linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
new_addr) < 0) {
nl80211_remove_iface(drv, ifidx);
return -1;
}
- if (os_memcmp(own_addr, new_addr, ETH_ALEN) == 0) {
+ if (nl80211_addr_in_use(drv->global, new_addr)) {
wpa_printf(MSG_DEBUG, "nl80211: Allocate new address "
"for P2P group interface");
if (nl80211_p2p_interface_addr(drv, new_addr) < 0) {
@@ -8692,12 +9213,14 @@
if (!msg)
return -1;
- wpa_printf(MSG_DEBUG, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
+ wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
"no_ack=%d offchanok=%d",
freq, wait, no_cck, no_ack, offchanok);
nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
+
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
if (wait)
NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
@@ -8719,7 +9242,7 @@
freq, wait);
goto nla_put_failure;
}
- wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted%s; "
+ wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; "
"cookie 0x%llx", no_ack ? " (no ACK)" : "",
(long long unsigned int) cookie);
@@ -8790,7 +9313,8 @@
(long long unsigned int) drv->send_action_cookie);
nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -8819,7 +9343,9 @@
nl80211_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
+
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);
@@ -8866,7 +9392,9 @@
nl80211_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
+
NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -8996,6 +9524,18 @@
}
+static int wpa_driver_nl80211_stop_ap(void *priv)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ if (!is_ap_interface(drv->nlmode))
+ return -1;
+ wpa_driver_nl80211_del_beacon(drv);
+ bss->beacon_set = 0;
+ return 0;
+}
+
+
static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
{
struct i802_bss *bss = priv;
@@ -9009,11 +9549,9 @@
static void wpa_driver_nl80211_resume(void *priv)
{
struct i802_bss *bss = priv;
- struct wpa_driver_nl80211_data *drv = bss->drv;
- if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
- wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on "
- "resume event");
- }
+
+ if (i802_set_iface_flags(bss, 1))
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event");
}
@@ -9068,7 +9606,8 @@
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
- struct nl_msg *msg, *cqm = NULL;
+ struct nl_msg *msg;
+ struct nlattr *cqm;
int ret = -1;
wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
@@ -9082,25 +9621,92 @@
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
- cqm = nlmsg_alloc();
+ cqm = nla_nest_start(msg, NL80211_ATTR_CQM);
if (cqm == NULL)
goto nla_put_failure;
- NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
- NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);
- if (nla_put_nested(msg, NL80211_ATTR_CQM, cqm) < 0)
- goto nla_put_failure;
+ NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
+ NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);
+ nla_nest_end(msg, cqm);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
nla_put_failure:
- nlmsg_free(cqm);
nlmsg_free(msg);
return ret;
}
+/* Converts nl80211_chan_width to a common format */
+static enum chan_width convert2width(int width)
+{
+ switch (width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ return CHAN_WIDTH_20_NOHT;
+ case NL80211_CHAN_WIDTH_20:
+ return CHAN_WIDTH_20;
+ case NL80211_CHAN_WIDTH_40:
+ return CHAN_WIDTH_40;
+ case NL80211_CHAN_WIDTH_80:
+ return CHAN_WIDTH_80;
+ case NL80211_CHAN_WIDTH_80P80:
+ return CHAN_WIDTH_80P80;
+ case NL80211_CHAN_WIDTH_160:
+ return CHAN_WIDTH_160;
+ }
+ return CHAN_WIDTH_UNKNOWN;
+}
+
+
+static int get_channel_width(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct wpa_signal_info *sig_change = arg;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ sig_change->center_frq1 = -1;
+ sig_change->center_frq2 = -1;
+ sig_change->chanwidth = CHAN_WIDTH_UNKNOWN;
+
+ if (tb[NL80211_ATTR_CHANNEL_WIDTH]) {
+ sig_change->chanwidth = convert2width(
+ nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
+ if (tb[NL80211_ATTR_CENTER_FREQ1])
+ sig_change->center_frq1 =
+ nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
+ if (tb[NL80211_ATTR_CENTER_FREQ2])
+ sig_change->center_frq2 =
+ nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
+ }
+
+ return NL_SKIP;
+}
+
+
+static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
+ struct wpa_signal_info *sig)
+{
+ struct nl_msg *msg;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_INTERFACE);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+ return send_and_recv_msgs(drv, msg, get_channel_width, sig);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+
static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
{
struct i802_bss *bss = priv;
@@ -9112,6 +9718,10 @@
if (res != 0)
return res;
+ res = nl80211_get_channel_width(drv, si);
+ if (res != 0)
+ return res;
+
return nl80211_get_link_noise(drv, si);
}
@@ -9186,6 +9796,13 @@
drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
}
+
+ if (os_strstr(param, "p2p_device=1")) {
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ drv->allow_p2p_device = 1;
+ }
+
#ifdef ANDROID_P2P
if(os_strstr(param, "use_multi_chan_concurrent=1")) {
struct i802_bss *bss = priv;
@@ -9474,6 +10091,40 @@
}
+static int nl80211_start_radar_detection(void *priv, int freq)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Start radar detection (CAC)");
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
+ wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar "
+ "detection");
+ return -1;
+ }
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_RADAR_DETECT);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+
+ /* only HT20 is supported at this point */
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT20);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret == 0)
+ return 0;
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
+ "%d (%s)", ret, strerror(-ret));
+nla_put_failure:
+ return -1;
+}
+
#ifdef CONFIG_TDLS
static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
@@ -9835,6 +10486,18 @@
}
+const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+
+ if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE)
+ return NULL;
+
+ return bss->addr;
+}
+
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@@ -9857,6 +10520,7 @@
.set_supp_port = wpa_driver_nl80211_set_supp_port,
.set_country = wpa_driver_nl80211_set_country,
.set_ap = wpa_driver_nl80211_set_ap,
+ .set_acl = wpa_driver_nl80211_set_acl,
.if_add = wpa_driver_nl80211_if_add,
.if_remove = driver_nl80211_if_remove,
.send_mlme = driver_nl80211_send_mlme,
@@ -9906,11 +10570,14 @@
.set_rekey_info = nl80211_set_rekey_info,
.poll_client = nl80211_poll_client,
.set_p2p_powersave = nl80211_set_p2p_powersave,
+ .start_dfs_cac = nl80211_start_radar_detection,
+ .stop_ap = wpa_driver_nl80211_stop_ap,
#ifdef CONFIG_TDLS
.send_tdls_mgmt = nl80211_send_tdls_mgmt,
.tdls_oper = nl80211_tdls_oper,
#endif /* CONFIG_TDLS */
.update_ft_ies = wpa_driver_nl80211_update_ft_ies,
+ .get_mac_addr = wpa_driver_nl80211_get_macaddr,
#ifdef ANDROID_P2P
.set_noa = wpa_driver_set_p2p_noa,
.get_noa = wpa_driver_get_p2p_noa,
diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c
index c99802a..541ebcc 100644
--- a/src/drivers/driver_test.c
+++ b/src/drivers/driver_test.c
@@ -3195,6 +3195,12 @@
/* TODO */
}
+
+static void test_p2p_debug_print(void *ctx, int level, const char *msg)
+{
+ wpa_printf(level, "P2P: %s", msg);
+}
+
#endif /* CONFIG_P2P */
@@ -3206,8 +3212,8 @@
int i;
os_memset(&p2p, 0, sizeof(p2p));
- p2p.msg_ctx = drv->ctx;
p2p.cb_ctx = drv;
+ p2p.debug_print = test_p2p_debug_print;
p2p.p2p_scan = test_p2p_scan;
p2p.send_action = test_send_action;
p2p.send_action_done = test_send_action_done;
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 9733e01..1401050 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -502,11 +502,9 @@
"IWEVCUSTOM length");
return;
}
- buf = os_malloc(iwe->u.data.length + 1);
+ buf = dup_binstr(custom, iwe->u.data.length);
if (buf == NULL)
return;
- os_memcpy(buf, custom, iwe->u.data.length);
- buf[iwe->u.data.length] = '\0';
wpa_driver_wext_event_wireless_custom(drv->ctx, buf);
os_free(buf);
break;
diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
index 1d0ff6e..04eb4fd 100644
--- a/src/drivers/drivers.c
+++ b/src/drivers/drivers.c
@@ -50,12 +50,12 @@
struct wpa_driver_ops *wpa_drivers[] =
{
-#ifdef CONFIG_DRIVER_WEXT
- &wpa_driver_wext_ops,
-#endif /* CONFIG_DRIVER_WEXT */
#ifdef CONFIG_DRIVER_NL80211
&wpa_driver_nl80211_ops,
#endif /* CONFIG_DRIVER_NL80211 */
+#ifdef CONFIG_DRIVER_WEXT
+ &wpa_driver_wext_ops,
+#endif /* CONFIG_DRIVER_WEXT */
#ifdef CONFIG_DRIVER_HOSTAP
&wpa_driver_hostap_ops,
#endif /* CONFIG_DRIVER_HOSTAP */
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 79da871..32b060e 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -27,6 +27,8 @@
#include <linux/types.h>
+#define NL80211_GENL_NAME "nl80211"
+
/**
* DOC: Station handling
*
@@ -639,6 +641,13 @@
* with the relevant Information Elements. This event is used to report
* received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
*
+ * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running
+ * a critical protocol that needs more reliability in the connection to
+ * complete.
+ *
+ * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
+ * return back to normal.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -798,6 +807,9 @@
NL80211_CMD_UPDATE_FT_IES,
NL80211_CMD_FT_EVENT,
+ NL80211_CMD_CRIT_PROTOCOL_START,
+ NL80211_CMD_CRIT_PROTOCOL_STOP,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1414,6 +1426,16 @@
* @NL80211_ATTR_IE_RIC: Resource Information Container Information
* Element
*
+ * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased
+ * reliability, see &enum nl80211_crit_proto_id (u16).
+ * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
+ * the connection should have increased reliability (u16).
+ *
+ * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16).
+ * This is similar to @NL80211_ATTR_STA_AID but with a difference of being
+ * allowed to be used with the first @NL80211_CMD_SET_STATION command to
+ * update a TDLS peer STA entry.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1709,6 +1731,11 @@
NL80211_ATTR_MDID,
NL80211_ATTR_IE_RIC,
+ NL80211_ATTR_CRIT_PROT_ID,
+ NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+
+ NL80211_ATTR_PEER_AID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1973,6 +2000,10 @@
* @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode
* @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards
* non-peer STA
+ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
+ * Contains a nested array of signal strength attributes (u8, dBm)
+ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+ * Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
@@ -2002,6 +2033,8 @@
NL80211_STA_INFO_NONPEER_PM,
NL80211_STA_INFO_RX_BYTES64,
NL80211_STA_INFO_TX_BYTES64,
+ NL80211_STA_INFO_CHAIN_SIGNAL,
+ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
@@ -2619,6 +2652,10 @@
* @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will
* implement an MPM which handles peer allocation and state.
*
+ * @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication
+ * method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE).
+ * Default is no authentication method required.
+ *
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
*
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
@@ -2632,6 +2669,7 @@
NL80211_MESH_SETUP_USERSPACE_AMPE,
NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,
NL80211_MESH_SETUP_USERSPACE_MPM,
+ NL80211_MESH_SETUP_AUTH_PROTOCOL,
/* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST,
@@ -3682,4 +3720,25 @@
NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0,
};
+/**
+ * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers
+ *
+ * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified.
+ * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol.
+ * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol.
+ * @NL80211_CRIT_PROTO_APIPA: APIPA protocol.
+ * @NUM_NL80211_CRIT_PROTO: must be kept last.
+ */
+enum nl80211_crit_proto_id {
+ NL80211_CRIT_PROTO_UNSPEC,
+ NL80211_CRIT_PROTO_DHCP,
+ NL80211_CRIT_PROTO_EAPOL,
+ NL80211_CRIT_PROTO_APIPA,
+ /* add other protocols before this one */
+ NUM_NL80211_CRIT_PROTO
+};
+
+/* maximum duration for critical protocol measures */
+#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */
+
#endif /* __LINUX_NL80211_H */
diff --git a/src/eap_common/eap_defs.h b/src/eap_common/eap_defs.h
index 0d247c4..f5890be 100644
--- a/src/eap_common/eap_defs.h
+++ b/src/eap_common/eap_defs.h
@@ -63,6 +63,7 @@
EAP_TYPE_AKA_PRIME = 50 /* RFC 5448 */,
EAP_TYPE_GPSK = 51 /* RFC 5433 */,
EAP_TYPE_PWD = 52 /* RFC 5931 */,
+ EAP_TYPE_EKE = 53 /* RFC 6124 */,
EAP_TYPE_EXPANDED = 254 /* RFC 3748 */
} EapType;
diff --git a/src/eap_common/eap_eke_common.c b/src/eap_common/eap_eke_common.c
new file mode 100644
index 0000000..a62ac8e
--- /dev/null
+++ b/src/eap_common/eap_eke_common.c
@@ -0,0 +1,768 @@
+/*
+ * EAP server/peer: EAP-EKE shared routines
+ * Copyright (c) 2011-2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/aes.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
+#include "crypto/dh_groups.h"
+#include "crypto/random.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "eap_common/eap_defs.h"
+#include "eap_eke_common.h"
+
+
+static int eap_eke_dh_len(u8 group)
+{
+ switch (group) {
+ case EAP_EKE_DHGROUP_EKE_2:
+ return 128;
+ case EAP_EKE_DHGROUP_EKE_5:
+ return 192;
+ case EAP_EKE_DHGROUP_EKE_14:
+ return 256;
+ case EAP_EKE_DHGROUP_EKE_15:
+ return 384;
+ case EAP_EKE_DHGROUP_EKE_16:
+ return 512;
+ }
+
+ return -1;
+}
+
+
+static int eap_eke_dhcomp_len(u8 dhgroup, u8 encr)
+{
+ int dhlen;
+
+ dhlen = eap_eke_dh_len(dhgroup);
+ if (dhlen < 0)
+ return -1;
+ if (encr != EAP_EKE_ENCR_AES128_CBC)
+ return -1;
+ return AES_BLOCK_SIZE + dhlen;
+}
+
+
+static const struct dh_group * eap_eke_dh_group(u8 group)
+{
+ switch (group) {
+ case EAP_EKE_DHGROUP_EKE_2:
+ return dh_groups_get(2);
+ case EAP_EKE_DHGROUP_EKE_5:
+ return dh_groups_get(5);
+ case EAP_EKE_DHGROUP_EKE_14:
+ return dh_groups_get(14);
+ case EAP_EKE_DHGROUP_EKE_15:
+ return dh_groups_get(15);
+ case EAP_EKE_DHGROUP_EKE_16:
+ return dh_groups_get(16);
+ }
+
+ return NULL;
+}
+
+
+static int eap_eke_dh_generator(u8 group)
+{
+ switch (group) {
+ case EAP_EKE_DHGROUP_EKE_2:
+ return 5;
+ case EAP_EKE_DHGROUP_EKE_5:
+ return 31;
+ case EAP_EKE_DHGROUP_EKE_14:
+ return 11;
+ case EAP_EKE_DHGROUP_EKE_15:
+ return 5;
+ case EAP_EKE_DHGROUP_EKE_16:
+ return 5;
+ }
+
+ return -1;
+}
+
+
+static int eap_eke_pnonce_len(u8 mac)
+{
+ int mac_len;
+
+ if (mac == EAP_EKE_MAC_HMAC_SHA1)
+ mac_len = SHA1_MAC_LEN;
+ else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
+ mac_len = SHA256_MAC_LEN;
+ else
+ return -1;
+
+ return AES_BLOCK_SIZE + 16 + mac_len;
+}
+
+
+static int eap_eke_pnonce_ps_len(u8 mac)
+{
+ int mac_len;
+
+ if (mac == EAP_EKE_MAC_HMAC_SHA1)
+ mac_len = SHA1_MAC_LEN;
+ else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
+ mac_len = SHA256_MAC_LEN;
+ else
+ return -1;
+
+ return AES_BLOCK_SIZE + 2 * 16 + mac_len;
+}
+
+
+static int eap_eke_prf_len(u8 prf)
+{
+ if (prf == EAP_EKE_PRF_HMAC_SHA1)
+ return 20;
+ if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
+ return 32;
+ return -1;
+}
+
+
+static int eap_eke_nonce_len(u8 prf)
+{
+ int prf_len;
+
+ prf_len = eap_eke_prf_len(prf);
+ if (prf_len < 0)
+ return -1;
+
+ if (prf_len > 2 * 16)
+ return (prf_len + 1) / 2;
+
+ return 16;
+}
+
+
+static int eap_eke_auth_len(u8 prf)
+{
+ switch (prf) {
+ case EAP_EKE_PRF_HMAC_SHA1:
+ return SHA1_MAC_LEN;
+ case EAP_EKE_PRF_HMAC_SHA2_256:
+ return SHA256_MAC_LEN;
+ }
+
+ return -1;
+}
+
+
+int eap_eke_dh_init(u8 group, u8 *ret_priv, u8 *ret_pub)
+{
+ int generator;
+ u8 gen;
+ const struct dh_group *dh;
+ size_t pub_len, i;
+
+ generator = eap_eke_dh_generator(group);
+ if (generator < 0 || generator > 255)
+ return -1;
+ gen = generator;
+
+ dh = eap_eke_dh_group(group);
+ if (dh == NULL)
+ return -1;
+
+ /* x = random number 2 .. p-1 */
+ if (random_get_bytes(ret_priv, dh->prime_len))
+ return -1;
+ if (os_memcmp(ret_priv, dh->prime, dh->prime_len) > 0) {
+ /* Make sure private value is smaller than prime */
+ ret_priv[0] = 0;
+ }
+ for (i = 0; i < dh->prime_len - 1; i++) {
+ if (ret_priv[i])
+ break;
+ }
+ if (i == dh->prime_len - 1 && (ret_priv[i] == 0 || ret_priv[i] == 1))
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: DH private value",
+ ret_priv, dh->prime_len);
+
+ /* y = g ^ x (mod p) */
+ pub_len = dh->prime_len;
+ if (crypto_mod_exp(&gen, 1, ret_priv, dh->prime_len,
+ dh->prime, dh->prime_len, ret_pub, &pub_len) < 0)
+ return -1;
+ if (pub_len < dh->prime_len) {
+ size_t pad = dh->prime_len - pub_len;
+ os_memmove(ret_pub + pad, ret_pub, pub_len);
+ os_memset(ret_pub, 0, pad);
+ }
+
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: DH public value",
+ ret_pub, dh->prime_len);
+
+ return 0;
+}
+
+
+static int eap_eke_prf(u8 prf, const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, const u8 *data2, size_t data2_len,
+ u8 *res)
+{
+ const u8 *addr[2];
+ size_t len[2];
+ size_t num_elem = 1;
+
+ addr[0] = data;
+ len[0] = data_len;
+ if (data2) {
+ num_elem++;
+ addr[1] = data2;
+ len[1] = data2_len;
+ }
+
+ if (prf == EAP_EKE_PRF_HMAC_SHA1)
+ return hmac_sha1_vector(key, key_len, num_elem, addr, len, res);
+ if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
+ return hmac_sha256_vector(key, key_len, num_elem, addr, len,
+ res);
+ return -1;
+}
+
+
+static int eap_eke_prf_hmac_sha1(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *res, size_t len)
+{
+ u8 hash[SHA1_MAC_LEN];
+ u8 idx;
+ const u8 *addr[3];
+ size_t vlen[3];
+ int ret;
+
+ idx = 0;
+ addr[0] = hash;
+ vlen[0] = SHA1_MAC_LEN;
+ addr[1] = data;
+ vlen[1] = data_len;
+ addr[2] = &idx;
+ vlen[2] = 1;
+
+ while (len > 0) {
+ idx++;
+ if (idx == 1)
+ ret = hmac_sha1_vector(key, key_len, 2, &addr[1],
+ &vlen[1], hash);
+ else
+ ret = hmac_sha1_vector(key, key_len, 3, addr, vlen,
+ hash);
+ if (ret < 0)
+ return -1;
+ if (len > SHA1_MAC_LEN) {
+ os_memcpy(res, hash, SHA1_MAC_LEN);
+ res += SHA1_MAC_LEN;
+ len -= SHA1_MAC_LEN;
+ } else {
+ os_memcpy(res, hash, len);
+ len = 0;
+ }
+ }
+
+ return 0;
+}
+
+
+static int eap_eke_prf_hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *res, size_t len)
+{
+ u8 hash[SHA256_MAC_LEN];
+ u8 idx;
+ const u8 *addr[3];
+ size_t vlen[3];
+ int ret;
+
+ idx = 0;
+ addr[0] = hash;
+ vlen[0] = SHA256_MAC_LEN;
+ addr[1] = data;
+ vlen[1] = data_len;
+ addr[2] = &idx;
+ vlen[2] = 1;
+
+ while (len > 0) {
+ idx++;
+ if (idx == 1)
+ ret = hmac_sha256_vector(key, key_len, 2, &addr[1],
+ &vlen[1], hash);
+ else
+ ret = hmac_sha256_vector(key, key_len, 3, addr, vlen,
+ hash);
+ if (ret < 0)
+ return -1;
+ if (len > SHA256_MAC_LEN) {
+ os_memcpy(res, hash, SHA256_MAC_LEN);
+ res += SHA256_MAC_LEN;
+ len -= SHA256_MAC_LEN;
+ } else {
+ os_memcpy(res, hash, len);
+ len = 0;
+ }
+ }
+
+ return 0;
+}
+
+
+static int eap_eke_prfplus(u8 prf, const u8 *key, size_t key_len,
+ const u8 *data, size_t data_len, u8 *res, size_t len)
+{
+ if (prf == EAP_EKE_PRF_HMAC_SHA1)
+ return eap_eke_prf_hmac_sha1(key, key_len, data, data_len, res,
+ len);
+ if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
+ return eap_eke_prf_hmac_sha256(key, key_len, data, data_len,
+ res, len);
+ return -1;
+}
+
+
+int eap_eke_derive_key(struct eap_eke_session *sess,
+ const u8 *password, size_t password_len,
+ const u8 *id_s, size_t id_s_len, const u8 *id_p,
+ size_t id_p_len, u8 *key)
+{
+ u8 zeros[EAP_EKE_MAX_HASH_LEN];
+ u8 temp[EAP_EKE_MAX_HASH_LEN];
+ size_t key_len = 16; /* Only AES-128-CBC is used here */
+ u8 *id;
+
+ /* temp = prf(0+, password) */
+ os_memset(zeros, 0, sess->prf_len);
+ if (eap_eke_prf(sess->prf, zeros, sess->prf_len,
+ password, password_len, NULL, 0, temp) < 0)
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: temp = prf(0+, password)",
+ temp, sess->prf_len);
+
+ /* key = prf+(temp, ID_S | ID_P) */
+ id = os_malloc(id_s_len + id_p_len);
+ if (id == NULL)
+ return -1;
+ os_memcpy(id, id_s, id_s_len);
+ os_memcpy(id + id_s_len, id_p, id_p_len);
+ wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: ID_S | ID_P",
+ id, id_s_len + id_p_len);
+ if (eap_eke_prfplus(sess->prf, temp, sess->prf_len,
+ id, id_s_len + id_p_len, key, key_len) < 0) {
+ os_free(id);
+ return -1;
+ }
+ os_free(id);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: key = prf+(temp, ID_S | ID_P)",
+ key, key_len);
+
+ return 0;
+}
+
+
+int eap_eke_dhcomp(struct eap_eke_session *sess, const u8 *key, const u8 *dhpub,
+ u8 *ret_dhcomp)
+{
+ u8 pub[EAP_EKE_MAX_DH_LEN];
+ int dh_len;
+ u8 iv[AES_BLOCK_SIZE];
+
+ dh_len = eap_eke_dh_len(sess->dhgroup);
+ if (dh_len < 0)
+ return -1;
+
+ /*
+ * DHComponent = Encr(key, y)
+ *
+ * All defined DH groups use primes that have length devisible by 16, so
+ * no need to do extra padding for y (= pub).
+ */
+ if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
+ return -1;
+ if (random_get_bytes(iv, AES_BLOCK_SIZE))
+ return -1;
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Encr(key, y)",
+ iv, AES_BLOCK_SIZE);
+ os_memcpy(pub, dhpub, dh_len);
+ if (aes_128_cbc_encrypt(key, iv, pub, dh_len) < 0)
+ return -1;
+ os_memcpy(ret_dhcomp, iv, AES_BLOCK_SIZE);
+ os_memcpy(ret_dhcomp + AES_BLOCK_SIZE, pub, dh_len);
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent = Encr(key, y)",
+ ret_dhcomp, AES_BLOCK_SIZE + dh_len);
+
+ return 0;
+}
+
+
+int eap_eke_shared_secret(struct eap_eke_session *sess, const u8 *key,
+ const u8 *dhpriv, const u8 *peer_dhcomp)
+{
+ u8 zeros[EAP_EKE_MAX_HASH_LEN];
+ u8 peer_pub[EAP_EKE_MAX_DH_LEN];
+ u8 modexp[EAP_EKE_MAX_DH_LEN];
+ size_t len;
+ const struct dh_group *dh;
+
+ if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
+ return -1;
+
+ dh = eap_eke_dh_group(sess->dhgroup);
+ if (dh == NULL)
+ return -1;
+
+ /* Decrypt peer DHComponent */
+ os_memcpy(peer_pub, peer_dhcomp + AES_BLOCK_SIZE, dh->prime_len);
+ if (aes_128_cbc_decrypt(key, peer_dhcomp, peer_pub, dh->prime_len) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt DHComponent");
+ return -1;
+ }
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted peer DH pubkey",
+ peer_pub, dh->prime_len);
+
+ /* SharedSecret = prf(0+, g ^ (x_s * x_p) (mod p)) */
+ len = dh->prime_len;
+ if (crypto_mod_exp(peer_pub, dh->prime_len, dhpriv, dh->prime_len,
+ dh->prime, dh->prime_len, modexp, &len) < 0)
+ return -1;
+ if (len < dh->prime_len) {
+ size_t pad = dh->prime_len - len;
+ os_memmove(modexp + pad, modexp, len);
+ os_memset(modexp, 0, pad);
+ }
+
+ os_memset(zeros, 0, sess->auth_len);
+ if (eap_eke_prf(sess->prf, zeros, sess->auth_len, modexp, dh->prime_len,
+ NULL, 0, sess->shared_secret) < 0)
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: SharedSecret",
+ sess->shared_secret, sess->auth_len);
+
+ return 0;
+}
+
+
+int eap_eke_derive_ke_ki(struct eap_eke_session *sess,
+ const u8 *id_s, size_t id_s_len,
+ const u8 *id_p, size_t id_p_len)
+{
+ u8 buf[EAP_EKE_MAX_KE_LEN + EAP_EKE_MAX_KI_LEN];
+ size_t ke_len, ki_len;
+ u8 *data;
+ size_t data_len;
+ const char *label = "EAP-EKE Keys";
+ size_t label_len;
+
+ /*
+ * Ke | Ki = prf+(SharedSecret, "EAP-EKE Keys" | ID_S | ID_P)
+ * Ke = encryption key
+ * Ki = integrity protection key
+ * Length of each key depends on the selected algorithms.
+ */
+
+ if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
+ ke_len = 16;
+ else
+ return -1;
+
+ if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
+ ki_len = 20;
+ else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
+ ki_len = 32;
+ else
+ return -1;
+
+ label_len = os_strlen(label);
+ data_len = label_len + id_s_len + id_p_len;
+ data = os_malloc(data_len);
+ if (data == NULL)
+ return -1;
+ os_memcpy(data, label, label_len);
+ os_memcpy(data + label_len, id_s, id_s_len);
+ os_memcpy(data + label_len + id_s_len, id_p, id_p_len);
+ if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
+ data, data_len, buf, ke_len + ki_len) < 0) {
+ os_free(data);
+ return -1;
+ }
+
+ os_memcpy(sess->ke, buf, ke_len);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ke", sess->ke, ke_len);
+ os_memcpy(sess->ki, buf + ke_len, ki_len);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ki", sess->ki, ki_len);
+
+ os_free(data);
+ return 0;
+}
+
+
+int eap_eke_derive_ka(struct eap_eke_session *sess,
+ const u8 *id_s, size_t id_s_len,
+ const u8 *id_p, size_t id_p_len,
+ const u8 *nonce_p, const u8 *nonce_s)
+{
+ u8 *data, *pos;
+ size_t data_len;
+ const char *label = "EAP-EKE Ka";
+ size_t label_len;
+
+ /*
+ * Ka = prf+(SharedSecret, "EAP-EKE Ka" | ID_S | ID_P | Nonce_P |
+ * Nonce_S)
+ * Ka = authentication key
+ * Length of the key depends on the selected algorithms.
+ */
+
+ label_len = os_strlen(label);
+ data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
+ data = os_malloc(data_len);
+ if (data == NULL)
+ return -1;
+ pos = data;
+ os_memcpy(pos, label, label_len);
+ pos += label_len;
+ os_memcpy(pos, id_s, id_s_len);
+ pos += id_s_len;
+ os_memcpy(pos, id_p, id_p_len);
+ pos += id_p_len;
+ os_memcpy(pos, nonce_p, sess->nonce_len);
+ pos += sess->nonce_len;
+ os_memcpy(pos, nonce_s, sess->nonce_len);
+ if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
+ data, data_len, sess->ka, sess->prf_len) < 0) {
+ os_free(data);
+ return -1;
+ }
+ os_free(data);
+
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka", sess->ka, sess->prf_len);
+
+ return 0;
+}
+
+
+int eap_eke_derive_msk(struct eap_eke_session *sess,
+ const u8 *id_s, size_t id_s_len,
+ const u8 *id_p, size_t id_p_len,
+ const u8 *nonce_p, const u8 *nonce_s,
+ u8 *msk, u8 *emsk)
+{
+ u8 *data, *pos;
+ size_t data_len;
+ const char *label = "EAP-EKE Exported Keys";
+ size_t label_len;
+ u8 buf[EAP_MSK_LEN + EAP_EMSK_LEN];
+
+ /*
+ * MSK | EMSK = prf+(SharedSecret, "EAP-EKE Exported Keys" | ID_S |
+ * ID_P | Nonce_P | Nonce_S)
+ */
+
+ label_len = os_strlen(label);
+ data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
+ data = os_malloc(data_len);
+ if (data == NULL)
+ return -1;
+ pos = data;
+ os_memcpy(pos, label, label_len);
+ pos += label_len;
+ os_memcpy(pos, id_s, id_s_len);
+ pos += id_s_len;
+ os_memcpy(pos, id_p, id_p_len);
+ pos += id_p_len;
+ os_memcpy(pos, nonce_p, sess->nonce_len);
+ pos += sess->nonce_len;
+ os_memcpy(pos, nonce_s, sess->nonce_len);
+ if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
+ data, data_len, buf, EAP_MSK_LEN + EAP_EMSK_LEN) <
+ 0) {
+ os_free(data);
+ return -1;
+ }
+ os_free(data);
+
+ os_memcpy(msk, buf, EAP_MSK_LEN);
+ os_memcpy(emsk, buf + EAP_MSK_LEN, EAP_EMSK_LEN);
+ os_memset(buf, 0, sizeof(buf));
+
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: MSK", msk, EAP_MSK_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: EMSK", msk, EAP_EMSK_LEN);
+
+ return 0;
+}
+
+
+static int eap_eke_mac(u8 mac, const u8 *key, const u8 *data, size_t data_len,
+ u8 *res)
+{
+ if (mac == EAP_EKE_MAC_HMAC_SHA1)
+ return hmac_sha1(key, SHA1_MAC_LEN, data, data_len, res);
+ if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
+ return hmac_sha256(key, SHA256_MAC_LEN, data, data_len, res);
+ return -1;
+}
+
+
+int eap_eke_prot(struct eap_eke_session *sess,
+ const u8 *data, size_t data_len,
+ u8 *prot, size_t *prot_len)
+{
+ size_t block_size, icv_len, pad;
+ u8 *pos, *iv, *e;
+
+ if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
+ block_size = AES_BLOCK_SIZE;
+ else
+ return -1;
+
+ if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
+ icv_len = SHA1_MAC_LEN;
+ else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
+ icv_len = SHA256_MAC_LEN;
+ else
+ return -1;
+
+ pad = data_len % block_size;
+ if (pad)
+ pad = block_size - pad;
+
+ if (*prot_len < block_size + data_len + pad + icv_len) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data");
+ }
+ pos = prot;
+
+ if (random_get_bytes(pos, block_size))
+ return -1;
+ iv = pos;
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Prot()", iv, block_size);
+ pos += block_size;
+
+ e = pos;
+ os_memcpy(pos, data, data_len);
+ pos += data_len;
+ if (pad) {
+ if (random_get_bytes(pos, pad))
+ return -1;
+ pos += pad;
+ }
+
+ if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0)
+ return -1;
+
+ if (eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
+ return -1;
+ pos += icv_len;
+
+ *prot_len = pos - prot;
+ return 0;
+}
+
+
+int eap_eke_decrypt_prot(struct eap_eke_session *sess,
+ const u8 *prot, size_t prot_len,
+ u8 *data, size_t *data_len)
+{
+ size_t block_size, icv_len;
+ u8 icv[EAP_EKE_MAX_HASH_LEN];
+
+ if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
+ block_size = AES_BLOCK_SIZE;
+ else
+ return -1;
+
+ if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
+ icv_len = SHA1_MAC_LEN;
+ else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
+ icv_len = SHA256_MAC_LEN;
+ else
+ return -1;
+
+ if (prot_len < 2 * block_size + icv_len)
+ return -1;
+ if ((prot_len - icv_len) % block_size)
+ return -1;
+
+ if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
+ prot_len - block_size - icv_len, icv) < 0)
+ return -1;
+ if (os_memcmp(icv, prot + prot_len - icv_len, icv_len) != 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: ICV mismatch in Prot() data");
+ return -1;
+ }
+
+ if (*data_len < prot_len - block_size - icv_len) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for decrypted Prot() data");
+ return -1;
+ }
+
+ *data_len = prot_len - block_size - icv_len;
+ os_memcpy(data, prot + block_size, *data_len);
+ if (aes_128_cbc_decrypt(sess->ke, prot, data, *data_len) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt Prot() data");
+ return -1;
+ }
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted Prot() data",
+ data, *data_len);
+
+ return 0;
+}
+
+
+int eap_eke_auth(struct eap_eke_session *sess, const char *label,
+ const struct wpabuf *msgs, u8 *auth)
+{
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Auth(%s)", label);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka for Auth",
+ sess->ka, sess->auth_len);
+ wpa_hexdump_buf(MSG_MSGDUMP, "EAP-EKE: Messages for Auth", msgs);
+ return eap_eke_prf(sess->prf, sess->ka, sess->auth_len,
+ (const u8 *) label, os_strlen(label),
+ wpabuf_head(msgs), wpabuf_len(msgs), auth);
+}
+
+
+int eap_eke_session_init(struct eap_eke_session *sess, u8 dhgroup, u8 encr,
+ u8 prf, u8 mac)
+{
+ sess->dhgroup = dhgroup;
+ sess->encr = encr;
+ sess->prf = prf;
+ sess->mac = mac;
+
+ sess->prf_len = eap_eke_prf_len(prf);
+ if (sess->prf_len < 0)
+ return -1;
+ sess->nonce_len = eap_eke_nonce_len(prf);
+ if (sess->nonce_len < 0)
+ return -1;
+ sess->auth_len = eap_eke_auth_len(prf);
+ if (sess->auth_len < 0)
+ return -1;
+ sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr);
+ if (sess->dhcomp_len < 0)
+ return -1;
+ sess->pnonce_len = eap_eke_pnonce_len(sess->mac);
+ if (sess->pnonce_len < 0)
+ return -1;
+ sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac);
+ if (sess->pnonce_ps_len < 0)
+ return -1;
+
+ return 0;
+}
+
+
+void eap_eke_session_clean(struct eap_eke_session *sess)
+{
+ os_memset(sess->shared_secret, 0, EAP_EKE_MAX_HASH_LEN);
+ os_memset(sess->ke, 0, EAP_EKE_MAX_KE_LEN);
+ os_memset(sess->ki, 0, EAP_EKE_MAX_KI_LEN);
+ os_memset(sess->ka, 0, EAP_EKE_MAX_KA_LEN);
+}
diff --git a/src/eap_common/eap_eke_common.h b/src/eap_common/eap_eke_common.h
new file mode 100644
index 0000000..a4c0422
--- /dev/null
+++ b/src/eap_common/eap_eke_common.h
@@ -0,0 +1,114 @@
+/*
+ * EAP server/peer: EAP-EKE shared routines
+ * Copyright (c) 2011-2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_EKE_COMMON_H
+#define EAP_EKE_COMMON_H
+
+/* EKE Exchange */
+#define EAP_EKE_ID 1
+#define EAP_EKE_COMMIT 2
+#define EAP_EKE_CONFIRM 3
+#define EAP_EKE_FAILURE 4
+
+/* Diffie-Hellman Group Registry */
+#define EAP_EKE_DHGROUP_EKE_2 1
+#define EAP_EKE_DHGROUP_EKE_5 2
+#define EAP_EKE_DHGROUP_EKE_14 3 /* mandatory to implement */
+#define EAP_EKE_DHGROUP_EKE_15 4
+#define EAP_EKE_DHGROUP_EKE_16 5
+
+/* Encryption Algorithm Registry */
+#define EAP_EKE_ENCR_AES128_CBC 1 /* mandatory to implement */
+
+/* Pseudo Random Function Registry */
+#define EAP_EKE_PRF_HMAC_SHA1 1 /* mandatory to implement */
+#define EAP_EKE_PRF_HMAC_SHA2_256 2
+
+/* Keyed Message Digest (MAC) Registry */
+#define EAP_EKE_MAC_HMAC_SHA1 1 /* mandatory to implement */
+#define EAP_EKE_MAC_HMAC_SHA2_256 2
+
+/* Identity Type Registry */
+#define EAP_EKE_ID_OPAQUE 1
+#define EAP_EKE_ID_NAI 2
+#define EAP_EKE_ID_IPv4 3
+#define EAP_EKE_ID_IPv6 4
+#define EAP_EKE_ID_FQDN 5
+#define EAP_EKE_ID_DN 6
+
+/* Failure-Code */
+#define EAP_EKE_FAIL_NO_ERROR 1
+#define EAP_EKE_FAIL_PROTO_ERROR 2
+#define EAP_EKE_FAIL_PASSWD_NOT_FOUND 3
+#define EAP_EKE_FAIL_AUTHENTICATION_FAIL 4
+#define EAP_EKE_FAIL_AUTHORIZATION_FAIL 5
+#define EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN 6
+#define EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR 0xffffffff
+
+#define EAP_EKE_MAX_DH_LEN 512
+#define EAP_EKE_MAX_HASH_LEN 32
+#define EAP_EKE_MAX_KEY_LEN 16
+#define EAP_EKE_MAX_KE_LEN 16
+#define EAP_EKE_MAX_KI_LEN 32
+#define EAP_EKE_MAX_KA_LEN 32
+#define EAP_EKE_MAX_NONCE_LEN 16
+
+struct eap_eke_session {
+ /* Selected proposal */
+ u8 dhgroup;
+ u8 encr;
+ u8 prf;
+ u8 mac;
+
+ u8 shared_secret[EAP_EKE_MAX_HASH_LEN];
+ u8 ke[EAP_EKE_MAX_KE_LEN];
+ u8 ki[EAP_EKE_MAX_KI_LEN];
+ u8 ka[EAP_EKE_MAX_KA_LEN];
+
+ int prf_len;
+ int nonce_len;
+ int auth_len;
+ int dhcomp_len;
+ int pnonce_len;
+ int pnonce_ps_len;
+};
+
+int eap_eke_session_init(struct eap_eke_session *sess, u8 dhgroup, u8 encr,
+ u8 prf, u8 mac);
+void eap_eke_session_clean(struct eap_eke_session *sess);
+int eap_eke_dh_init(u8 group, u8 *ret_priv, u8 *ret_pub);
+int eap_eke_derive_key(struct eap_eke_session *sess,
+ const u8 *password, size_t password_len,
+ const u8 *id_s, size_t id_s_len, const u8 *id_p,
+ size_t id_p_len, u8 *key);
+int eap_eke_dhcomp(struct eap_eke_session *sess, const u8 *key, const u8 *dhpub,
+ u8 *ret_dhcomp);
+int eap_eke_shared_secret(struct eap_eke_session *sess, const u8 *key,
+ const u8 *dhpriv, const u8 *peer_dhcomp);
+int eap_eke_derive_ke_ki(struct eap_eke_session *sess,
+ const u8 *id_s, size_t id_s_len,
+ const u8 *id_p, size_t id_p_len);
+int eap_eke_derive_ka(struct eap_eke_session *sess,
+ const u8 *id_s, size_t id_s_len,
+ const u8 *id_p, size_t id_p_len,
+ const u8 *nonce_p, const u8 *nonce_s);
+int eap_eke_derive_msk(struct eap_eke_session *sess,
+ const u8 *id_s, size_t id_s_len,
+ const u8 *id_p, size_t id_p_len,
+ const u8 *nonce_p, const u8 *nonce_s,
+ u8 *msk, u8 *emsk);
+int eap_eke_prot(struct eap_eke_session *sess,
+ const u8 *data, size_t data_len,
+ u8 *prot, size_t *prot_len);
+int eap_eke_decrypt_prot(struct eap_eke_session *sess,
+ const u8 *prot, size_t prot_len,
+ u8 *data, size_t *data_len);
+int eap_eke_auth(struct eap_eke_session *sess, const char *label,
+ const struct wpabuf *msgs, u8 *auth);
+
+#endif /* EAP_EKE_COMMON_H */
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 4df8853..c0d7078 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -406,9 +406,11 @@
sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
&sm->eapKeyDataLen);
os_free(sm->eapSessionId);
- sm->eapSessionId = sm->m->getSessionId(sm, sm->eap_method_priv,
- &sm->eapSessionIdLen);
- if (sm->eapSessionId) {
+ sm->eapSessionId = NULL;
+ if (sm->m->getSessionId) {
+ sm->eapSessionId = sm->m->getSessionId(
+ sm, sm->eap_method_priv,
+ &sm->eapSessionIdLen);
wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
sm->eapSessionId, sm->eapSessionIdLen);
}
diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h
index ed90919..42f525b 100644
--- a/src/eap_peer/eap_config.h
+++ b/src/eap_peer/eap_config.h
@@ -1,6 +1,6 @@
/*
* EAP peer configuration data
- * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -634,6 +634,15 @@
* password field is the name of that external entry
*/
u32 flags;
+
+ /**
+ * ocsp - Whether to use/require OCSP to check server certificate
+ *
+ * 0 = do not use OCSP stapling (TLS certificate status extension)
+ * 1 = try to use OCSP stapling, but not require response
+ * 2 = require valid OCSP stapling response
+ */
+ int ocsp;
};
diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c
new file mode 100644
index 0000000..c71db5f
--- /dev/null
+++ b/src/eap_peer/eap_eke.c
@@ -0,0 +1,723 @@
+/*
+ * EAP peer method: EAP-EKE (RFC 6124)
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/random.h"
+#include "eap_peer/eap_i.h"
+#include "eap_common/eap_eke_common.h"
+
+struct eap_eke_data {
+ enum {
+ IDENTITY, COMMIT, CONFIRM, SUCCESS, FAILURE
+ } state;
+ u8 msk[EAP_MSK_LEN];
+ u8 emsk[EAP_EMSK_LEN];
+ u8 *peerid;
+ size_t peerid_len;
+ u8 *serverid;
+ size_t serverid_len;
+ u8 dh_priv[EAP_EKE_MAX_DH_LEN];
+ struct eap_eke_session sess;
+ u8 nonce_p[EAP_EKE_MAX_NONCE_LEN];
+ u8 nonce_s[EAP_EKE_MAX_NONCE_LEN];
+ struct wpabuf *msgs;
+};
+
+
+static const char * eap_eke_state_txt(int state)
+{
+ switch (state) {
+ case IDENTITY:
+ return "IDENTITY";
+ case COMMIT:
+ return "COMMIT";
+ case CONFIRM:
+ return "CONFIRM";
+ case SUCCESS:
+ return "SUCCESS";
+ case FAILURE:
+ return "FAILURE";
+ default:
+ return "?";
+ }
+}
+
+
+static void eap_eke_state(struct eap_eke_data *data, int state)
+{
+ wpa_printf(MSG_DEBUG, "EAP-EKE: %s -> %s",
+ eap_eke_state_txt(data->state), eap_eke_state_txt(state));
+ data->state = state;
+}
+
+
+static void eap_eke_deinit(struct eap_sm *sm, void *priv);
+
+
+static void * eap_eke_init(struct eap_sm *sm)
+{
+ struct eap_eke_data *data;
+ const u8 *identity, *password;
+ size_t identity_len, password_len;
+
+ password = eap_get_config_password(sm, &password_len);
+ if (!password) {
+ wpa_printf(MSG_INFO, "EAP-EKE: No password configured");
+ return NULL;
+ }
+
+ data = os_zalloc(sizeof(*data));
+ if (data == NULL)
+ return NULL;
+ eap_eke_state(data, IDENTITY);
+
+ identity = eap_get_config_identity(sm, &identity_len);
+ if (identity) {
+ data->peerid = os_malloc(identity_len);
+ if (data->peerid == NULL) {
+ eap_eke_deinit(sm, data);
+ return NULL;
+ }
+ os_memcpy(data->peerid, identity, identity_len);
+ data->peerid_len = identity_len;
+ }
+
+ return data;
+}
+
+
+static void eap_eke_deinit(struct eap_sm *sm, void *priv)
+{
+ struct eap_eke_data *data = priv;
+ eap_eke_session_clean(&data->sess);
+ os_free(data->serverid);
+ os_free(data->peerid);
+ wpabuf_free(data->msgs);
+ os_free(data);
+}
+
+
+static struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data, int id,
+ size_t length, u8 eke_exch)
+{
+ struct wpabuf *msg;
+ size_t plen;
+
+ plen = 1 + length;
+
+ msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen,
+ EAP_CODE_RESPONSE, id);
+ if (msg == NULL) {
+ wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory");
+ return NULL;
+ }
+
+ wpabuf_put_u8(msg, eke_exch);
+
+ return msg;
+}
+
+
+static int eap_eke_supp_dhgroup(u8 dhgroup)
+{
+ return dhgroup == EAP_EKE_DHGROUP_EKE_2 ||
+ dhgroup == EAP_EKE_DHGROUP_EKE_5 ||
+ dhgroup == EAP_EKE_DHGROUP_EKE_14 ||
+ dhgroup == EAP_EKE_DHGROUP_EKE_15 ||
+ dhgroup == EAP_EKE_DHGROUP_EKE_16;
+}
+
+
+static int eap_eke_supp_encr(u8 encr)
+{
+ return encr == EAP_EKE_ENCR_AES128_CBC;
+}
+
+
+static int eap_eke_supp_prf(u8 prf)
+{
+ return prf == EAP_EKE_PRF_HMAC_SHA1 ||
+ prf == EAP_EKE_PRF_HMAC_SHA2_256;
+}
+
+
+static int eap_eke_supp_mac(u8 mac)
+{
+ return mac == EAP_EKE_MAC_HMAC_SHA1 ||
+ mac == EAP_EKE_MAC_HMAC_SHA2_256;
+}
+
+
+static struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData,
+ u32 failure_code)
+{
+ struct wpabuf *resp;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x",
+ failure_code);
+
+ resp = eap_eke_build_msg(data, eap_get_id(reqData), 4, EAP_EKE_FAILURE);
+ if (resp)
+ wpabuf_put_be32(resp, failure_code);
+
+ os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
+ eap_eke_session_clean(&data->sess);
+
+ eap_eke_state(data, FAILURE);
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ ret->allowNotifications = FALSE;
+
+ return resp;
+}
+
+
+static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData,
+ const u8 *payload,
+ size_t payload_len)
+{
+ struct wpabuf *resp;
+ unsigned num_prop, i;
+ const u8 *pos, *end;
+ const u8 *prop = NULL;
+ u8 idtype;
+
+ if (data->state != IDENTITY) {
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PROTO_ERROR);
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-ID/Request");
+
+ if (payload_len < 2 + 4) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PROTO_ERROR);
+ }
+
+ pos = payload;
+ end = payload + payload_len;
+
+ num_prop = *pos++;
+ pos++; /* Ignore Reserved field */
+
+ if (pos + num_prop * 4 > end) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data (num_prop=%u)",
+ num_prop);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PROTO_ERROR);
+ }
+
+ for (i = 0; i < num_prop; i++) {
+ const u8 *tmp = pos;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Proposal #%u: dh=%u encr=%u prf=%u mac=%u",
+ i, pos[0], pos[1], pos[2], pos[3]);
+ pos += 4;
+
+ if (!eap_eke_supp_dhgroup(*tmp))
+ continue;
+ tmp++;
+ if (!eap_eke_supp_encr(*tmp))
+ continue;
+ tmp++;
+ if (!eap_eke_supp_prf(*tmp))
+ continue;
+ tmp++;
+ if (!eap_eke_supp_mac(*tmp))
+ continue;
+
+ prop = tmp - 3;
+ if (eap_eke_session_init(&data->sess, prop[0], prop[1], prop[2],
+ prop[3]) < 0) {
+ prop = NULL;
+ continue;
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Selected proposal");
+ break;
+ }
+
+ if (prop == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: No acceptable proposal found");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN);
+ }
+
+ pos += (num_prop - i - 1) * 4;
+
+ if (pos == end) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data to include IDType/Identity");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PROTO_ERROR);
+ }
+
+ idtype = *pos++;
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Server IDType %u", idtype);
+ wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Server Identity",
+ pos, end - pos);
+ os_free(data->serverid);
+ data->serverid = os_malloc(end - pos);
+ if (data->serverid == NULL) {
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ os_memcpy(data->serverid, pos, end - pos);
+ data->serverid_len = end - pos;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-ID/Response");
+
+ resp = eap_eke_build_msg(data, eap_get_id(reqData),
+ 2 + 4 + 1 + data->peerid_len,
+ EAP_EKE_ID);
+ if (resp == NULL) {
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ wpabuf_put_u8(resp, 1); /* NumProposals */
+ wpabuf_put_u8(resp, 0); /* Reserved */
+ wpabuf_put_data(resp, prop, 4); /* Selected Proposal */
+ wpabuf_put_u8(resp, EAP_EKE_ID_NAI);
+ if (data->peerid)
+ wpabuf_put_data(resp, data->peerid, data->peerid_len);
+
+ wpabuf_free(data->msgs);
+ data->msgs = wpabuf_alloc(wpabuf_len(reqData) + wpabuf_len(resp));
+ if (data->msgs == NULL) {
+ wpabuf_free(resp);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ wpabuf_put_buf(data->msgs, reqData);
+ wpabuf_put_buf(data->msgs, resp);
+
+ eap_eke_state(data, COMMIT);
+
+ return resp;
+}
+
+
+static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm,
+ struct eap_eke_data *data,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData,
+ const u8 *payload,
+ size_t payload_len)
+{
+ struct wpabuf *resp;
+ const u8 *pos, *end, *dhcomp;
+ size_t prot_len;
+ u8 *rpos;
+ u8 key[EAP_EKE_MAX_KEY_LEN];
+ u8 pub[EAP_EKE_MAX_DH_LEN];
+ const u8 *password;
+ size_t password_len;
+
+ if (data->state != COMMIT) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Commit/Request received in unexpected state (%d)", data->state);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PROTO_ERROR);
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Commit/Request");
+
+ password = eap_get_config_password(sm, &password_len);
+ if (password == NULL) {
+ wpa_printf(MSG_INFO, "EAP-EKE: No password configured!");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PASSWD_NOT_FOUND);
+ }
+
+ pos = payload;
+ end = payload + payload_len;
+
+ if (pos + data->sess.dhcomp_len > end) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PROTO_ERROR);
+ }
+
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_S",
+ pos, data->sess.dhcomp_len);
+ dhcomp = pos;
+ pos += data->sess.dhcomp_len;
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos);
+
+ /*
+ * temp = prf(0+, password)
+ * key = prf+(temp, ID_S | ID_P)
+ */
+ if (eap_eke_derive_key(&data->sess, password, password_len,
+ data->serverid, data->serverid_len,
+ data->peerid, data->peerid_len, key) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ /*
+ * y_p = g ^ x_p (mod p)
+ * x_p = random number 2 .. p-1
+ */
+ if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH");
+ os_memset(key, 0, sizeof(key));
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ if (eap_eke_shared_secret(&data->sess, key, data->dh_priv, dhcomp) < 0)
+ {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret");
+ os_memset(key, 0, sizeof(key));
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ if (eap_eke_derive_ke_ki(&data->sess,
+ data->serverid, data->serverid_len,
+ data->peerid, data->peerid_len) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki");
+ os_memset(key, 0, sizeof(key));
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Commit/Response");
+
+ resp = eap_eke_build_msg(data, eap_get_id(reqData),
+ data->sess.dhcomp_len + data->sess.pnonce_len,
+ EAP_EKE_COMMIT);
+ if (resp == NULL) {
+ os_memset(key, 0, sizeof(key));
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ /* DHComponent_P = Encr(key, y_p) */
+ rpos = wpabuf_put(resp, data->sess.dhcomp_len);
+ if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S");
+ os_memset(key, 0, sizeof(key));
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ os_memset(key, 0, sizeof(key));
+
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P",
+ rpos, data->sess.dhcomp_len);
+
+ if (random_get_bytes(data->nonce_p, data->sess.nonce_len)) {
+ wpabuf_free(resp);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P",
+ data->nonce_p, data->sess.nonce_len);
+ prot_len = wpabuf_tailroom(resp);
+ if (eap_eke_prot(&data->sess, data->nonce_p, data->sess.nonce_len,
+ wpabuf_put(resp, 0), &prot_len) < 0) {
+ wpabuf_free(resp);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P",
+ wpabuf_put(resp, 0), prot_len);
+ wpabuf_put(resp, prot_len);
+
+ /* TODO: CBValue */
+
+ if (wpabuf_resize(&data->msgs, wpabuf_len(reqData) + wpabuf_len(resp))
+ < 0) {
+ wpabuf_free(resp);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ wpabuf_put_buf(data->msgs, reqData);
+ wpabuf_put_buf(data->msgs, resp);
+
+ eap_eke_state(data, CONFIRM);
+
+ return resp;
+}
+
+
+static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData,
+ const u8 *payload,
+ size_t payload_len)
+{
+ struct wpabuf *resp;
+ const u8 *pos, *end;
+ size_t prot_len;
+ u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN];
+ u8 auth_s[EAP_EKE_MAX_HASH_LEN];
+ size_t decrypt_len;
+ u8 *auth;
+
+ if (data->state != CONFIRM) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Confirm/Request received in unexpected state (%d)",
+ data->state);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PROTO_ERROR);
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Confirm/Request");
+
+ pos = payload;
+ end = payload + payload_len;
+
+ if (pos + data->sess.pnonce_ps_len + data->sess.prf_len > end) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PROTO_ERROR);
+ }
+
+ decrypt_len = sizeof(nonces);
+ if (eap_eke_decrypt_prot(&data->sess, pos, data->sess.pnonce_ps_len,
+ nonces, &decrypt_len) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_PS");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ }
+ if (decrypt_len != (size_t) 2 * data->sess.nonce_len) {
+ wpa_printf(MSG_INFO, "EAP-EKE: PNonce_PS protected data length does not match length of Nonce_P and Nonce_S");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ }
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_P | Nonce_S",
+ nonces, 2 * data->sess.nonce_len);
+ if (os_memcmp(data->nonce_p, nonces, data->sess.nonce_len) != 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match trnsmitted Nonce_P");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ }
+
+ os_memcpy(data->nonce_s, nonces + data->sess.nonce_len,
+ data->sess.nonce_len);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S",
+ data->nonce_s, data->sess.nonce_len);
+
+ if (eap_eke_derive_ka(&data->sess, data->serverid, data->serverid_len,
+ data->peerid, data->peerid_len,
+ data->nonce_p, data->nonce_s) < 0) {
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth_s) < 0)
+ {
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth_s, data->sess.prf_len);
+ if (os_memcmp(auth_s, pos + data->sess.pnonce_ps_len,
+ data->sess.prf_len) != 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Auth_S does not match");
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Confirm/Response");
+
+ resp = eap_eke_build_msg(data, eap_get_id(reqData),
+ data->sess.pnonce_len + data->sess.prf_len,
+ EAP_EKE_CONFIRM);
+ if (resp == NULL) {
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ prot_len = wpabuf_tailroom(resp);
+ if (eap_eke_prot(&data->sess, data->nonce_s, data->sess.nonce_len,
+ wpabuf_put(resp, 0), &prot_len) < 0) {
+ wpabuf_free(resp);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ wpabuf_put(resp, prot_len);
+
+ auth = wpabuf_put(resp, data->sess.prf_len);
+ if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth) < 0) {
+ wpabuf_free(resp);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth, data->sess.prf_len);
+
+ if (eap_eke_derive_msk(&data->sess, data->serverid, data->serverid_len,
+ data->peerid, data->peerid_len,
+ data->nonce_s, data->nonce_p,
+ data->msk, data->emsk) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK");
+ wpabuf_free(resp);
+ return eap_eke_build_fail(data, ret, reqData,
+ EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ }
+
+ os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
+ eap_eke_session_clean(&data->sess);
+
+ eap_eke_state(data, SUCCESS);
+ ret->methodState = METHOD_MAY_CONT;
+ ret->decision = DECISION_COND_SUCC;
+ ret->allowNotifications = FALSE;
+
+ return resp;
+}
+
+
+static struct wpabuf * eap_eke_process_failure(struct eap_eke_data *data,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData,
+ const u8 *payload,
+ size_t payload_len)
+{
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Failure/Request");
+
+ if (payload_len < 4) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure");
+ } else {
+ u32 code;
+ code = WPA_GET_BE32(payload);
+ wpa_printf(MSG_INFO, "EAP-EKE: Failure-Code 0x%x", code);
+ }
+
+ return eap_eke_build_fail(data, ret, reqData, EAP_EKE_FAIL_NO_ERROR);
+}
+
+
+static struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData)
+{
+ struct eap_eke_data *data = priv;
+ struct wpabuf *resp;
+ const u8 *pos, *end;
+ size_t len;
+ u8 eke_exch;
+
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, reqData, &len);
+ if (pos == NULL || len < 1) {
+ ret->ignore = TRUE;
+ return NULL;
+ }
+
+ end = pos + len;
+ eke_exch = *pos++;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: exch %d", eke_exch);
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received Data", pos, end - pos);
+
+ ret->ignore = FALSE;
+ ret->methodState = METHOD_MAY_CONT;
+ ret->decision = DECISION_FAIL;
+ ret->allowNotifications = TRUE;
+
+ switch (eke_exch) {
+ case EAP_EKE_ID:
+ resp = eap_eke_process_id(data, ret, reqData, pos, end - pos);
+ break;
+ case EAP_EKE_COMMIT:
+ resp = eap_eke_process_commit(sm, data, ret, reqData,
+ pos, end - pos);
+ break;
+ case EAP_EKE_CONFIRM:
+ resp = eap_eke_process_confirm(data, ret, reqData,
+ pos, end - pos);
+ break;
+ case EAP_EKE_FAILURE:
+ resp = eap_eke_process_failure(data, ret, reqData,
+ pos, end - pos);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Ignoring message with unknown EKE-Exch %d", eke_exch);
+ ret->ignore = TRUE;
+ return NULL;
+ }
+
+ if (ret->methodState == METHOD_DONE)
+ ret->allowNotifications = FALSE;
+
+ return resp;
+}
+
+
+static Boolean eap_eke_isKeyAvailable(struct eap_sm *sm, void *priv)
+{
+ struct eap_eke_data *data = priv;
+ return data->state == SUCCESS;
+}
+
+
+static u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_eke_data *data = priv;
+ u8 *key;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ key = os_malloc(EAP_MSK_LEN);
+ if (key == NULL)
+ return NULL;
+ os_memcpy(key, data->msk, EAP_MSK_LEN);
+ *len = EAP_MSK_LEN;
+
+ return key;
+}
+
+
+static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_eke_data *data = priv;
+ u8 *key;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ key = os_malloc(EAP_EMSK_LEN);
+ if (key == NULL)
+ return NULL;
+ os_memcpy(key, data->emsk, EAP_EMSK_LEN);
+ *len = EAP_EMSK_LEN;
+
+ return key;
+}
+
+
+int eap_peer_eke_register(void)
+{
+ struct eap_method *eap;
+ int ret;
+
+ eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+ EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE");
+ if (eap == NULL)
+ return -1;
+
+ eap->init = eap_eke_init;
+ eap->deinit = eap_eke_deinit;
+ eap->process = eap_eke_process;
+ eap->isKeyAvailable = eap_eke_isKeyAvailable;
+ eap->getKey = eap_eke_getKey;
+ eap->get_emsk = eap_eke_get_emsk;
+
+ ret = eap_peer_method_register(eap);
+ if (ret)
+ eap_peer_method_free(eap);
+ return ret;
+}
diff --git a/src/eap_peer/eap_methods.h b/src/eap_peer/eap_methods.h
index 4994ff1..a465fd2 100644
--- a/src/eap_peer/eap_methods.h
+++ b/src/eap_peer/eap_methods.h
@@ -105,5 +105,6 @@
int eap_peer_vendor_test_register(void);
int eap_peer_tnc_register(void);
int eap_peer_pwd_register(void);
+int eap_peer_eke_register(void);
#endif /* EAP_METHODS_H */
diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c
index fb6c282..f9aa742 100644
--- a/src/eap_peer/eap_mschapv2.c
+++ b/src/eap_peer/eap_mschapv2.c
@@ -644,10 +644,8 @@
* must allocate a large enough temporary buffer to create that since
* the received message does not include nul termination.
*/
- buf = os_malloc(len + 1);
+ buf = dup_binstr(msdata, len);
if (buf) {
- os_memcpy(buf, msdata, len);
- buf[len] = '\0';
retry = eap_mschapv2_failure_txt(sm, data, buf);
os_free(buf);
}
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index a777bb0..be8c301 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -1,6 +1,6 @@
/*
* EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -164,6 +164,10 @@
{
int res;
+ if (config->ocsp)
+ params->flags |= TLS_CONN_REQUEST_OCSP;
+ if (config->ocsp == 2)
+ params->flags |= TLS_CONN_REQUIRE_OCSP;
data->conn = tls_connection_init(data->ssl_ctx);
if (data->conn == NULL) {
wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
diff --git a/src/eap_peer/tncc.c b/src/eap_peer/tncc.c
index f5edfd5..a3ec395 100644
--- a/src/eap_peer/tncc.c
+++ b/src/eap_peer/tncc.c
@@ -741,12 +741,10 @@
enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION;
int recommendation_msg = 0;
- buf = os_malloc(len + 1);
+ buf = dup_binstr(msg, len);
if (buf == NULL)
return TNCCS_PROCESS_ERROR;
- os_memcpy(buf, msg, len);
- buf[len] = '\0';
start = os_strstr(buf, "<TNCCS-Batch ");
end = os_strstr(buf, "</TNCCS-Batch>");
if (start == NULL || end == NULL || start > end) {
diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h
index f2a7cd7..36b230b 100644
--- a/src/eap_server/eap.h
+++ b/src/eap_server/eap.h
@@ -104,6 +104,9 @@
int fragment_size;
int pbc_in_m1;
+
+ const u8 *server_id;
+ size_t server_id_len;
};
diff --git a/src/eap_server/eap_i.h b/src/eap_server/eap_i.h
index f92704a..003e202 100644
--- a/src/eap_server/eap_i.h
+++ b/src/eap_server/eap_i.h
@@ -188,6 +188,9 @@
int fragment_size;
int pbc_in_m1;
+
+ const u8 *server_id;
+ size_t server_id_len;
};
int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
diff --git a/src/eap_server/eap_methods.h b/src/eap_server/eap_methods.h
index bc810a9..429cb72 100644
--- a/src/eap_server/eap_methods.h
+++ b/src/eap_server/eap_methods.h
@@ -45,5 +45,6 @@
int eap_server_ikev2_register(void);
int eap_server_tnc_register(void);
int eap_server_pwd_register(void);
+int eap_server_eke_register(void);
#endif /* EAP_SERVER_METHODS_H */
diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c
index 15f7e22..54b7533 100644
--- a/src/eap_server/eap_server.c
+++ b/src/eap_server/eap_server.c
@@ -1278,6 +1278,8 @@
sm->fragment_size = conf->fragment_size;
sm->pwd_group = conf->pwd_group;
sm->pbc_in_m1 = conf->pbc_in_m1;
+ sm->server_id = conf->server_id;
+ sm->server_id_len = conf->server_id_len;
wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
diff --git a/src/eap_server/eap_server_eke.c b/src/eap_server/eap_server_eke.c
new file mode 100644
index 0000000..b19a321
--- /dev/null
+++ b/src/eap_server/eap_server_eke.c
@@ -0,0 +1,793 @@
+/*
+ * hostapd / EAP-EKE (RFC 6124) server
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/random.h"
+#include "eap_server/eap_i.h"
+#include "eap_common/eap_eke_common.h"
+
+
+struct eap_eke_data {
+ enum {
+ IDENTITY, COMMIT, CONFIRM, FAILURE_REPORT, SUCCESS, FAILURE
+ } state;
+ u8 msk[EAP_MSK_LEN];
+ u8 emsk[EAP_EMSK_LEN];
+ u8 *peerid;
+ size_t peerid_len;
+ u8 peerid_type;
+ u8 serverid_type;
+ u8 dh_priv[EAP_EKE_MAX_DH_LEN];
+ u8 key[EAP_EKE_MAX_KEY_LEN];
+ struct eap_eke_session sess;
+ u8 nonce_p[EAP_EKE_MAX_NONCE_LEN];
+ u8 nonce_s[EAP_EKE_MAX_NONCE_LEN];
+ struct wpabuf *msgs;
+ int phase2;
+ u32 failure_code;
+};
+
+
+static const char * eap_eke_state_txt(int state)
+{
+ switch (state) {
+ case IDENTITY:
+ return "IDENTITY";
+ case COMMIT:
+ return "COMMIT";
+ case CONFIRM:
+ return "CONFIRM";
+ case FAILURE_REPORT:
+ return "FAILURE_REPORT";
+ case SUCCESS:
+ return "SUCCESS";
+ case FAILURE:
+ return "FAILURE";
+ default:
+ return "?";
+ }
+}
+
+
+static void eap_eke_state(struct eap_eke_data *data, int state)
+{
+ wpa_printf(MSG_DEBUG, "EAP-EKE: %s -> %s",
+ eap_eke_state_txt(data->state),
+ eap_eke_state_txt(state));
+ data->state = state;
+}
+
+
+static void eap_eke_fail(struct eap_eke_data *data, u32 code)
+{
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Failure - code 0x%x", code);
+ data->failure_code = code;
+ eap_eke_state(data, FAILURE_REPORT);
+}
+
+
+static void * eap_eke_init(struct eap_sm *sm)
+{
+ struct eap_eke_data *data;
+ size_t i;
+
+ data = os_zalloc(sizeof(*data));
+ if (data == NULL)
+ return NULL;
+ eap_eke_state(data, IDENTITY);
+
+ data->serverid_type = EAP_EKE_ID_OPAQUE;
+ for (i = 0; i < sm->server_id_len; i++) {
+ if (sm->server_id[i] == '.' &&
+ data->serverid_type == EAP_EKE_ID_OPAQUE)
+ data->serverid_type = EAP_EKE_ID_FQDN;
+ if (sm->server_id[i] == '@')
+ data->serverid_type = EAP_EKE_ID_NAI;
+ }
+
+ data->phase2 = sm->init_phase2;
+
+ return data;
+}
+
+
+static void eap_eke_reset(struct eap_sm *sm, void *priv)
+{
+ struct eap_eke_data *data = priv;
+ eap_eke_session_clean(&data->sess);
+ os_free(data->peerid);
+ wpabuf_free(data->msgs);
+ os_free(data);
+}
+
+
+static struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data,
+ u8 id, size_t length, u8 eke_exch)
+{
+ struct wpabuf *msg;
+ size_t plen;
+
+ plen = 1 + length;
+
+ msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen,
+ EAP_CODE_REQUEST, id);
+ if (msg == NULL) {
+ wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory");
+ return NULL;
+ }
+
+ wpabuf_put_u8(msg, eke_exch);
+
+ return msg;
+}
+
+
+static int supported_proposal(const u8 *pos)
+{
+ if (pos[0] == EAP_EKE_DHGROUP_EKE_16 &&
+ pos[1] == EAP_EKE_ENCR_AES128_CBC &&
+ pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
+ pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
+ return 1;
+
+ if (pos[0] == EAP_EKE_DHGROUP_EKE_15 &&
+ pos[1] == EAP_EKE_ENCR_AES128_CBC &&
+ pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
+ pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
+ return 1;
+
+ if (pos[0] == EAP_EKE_DHGROUP_EKE_14 &&
+ pos[1] == EAP_EKE_ENCR_AES128_CBC &&
+ pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
+ pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
+ return 1;
+
+ if (pos[0] == EAP_EKE_DHGROUP_EKE_14 &&
+ pos[1] == EAP_EKE_ENCR_AES128_CBC &&
+ pos[2] == EAP_EKE_PRF_HMAC_SHA1 &&
+ pos[3] == EAP_EKE_MAC_HMAC_SHA1)
+ return 1;
+
+ return 0;
+}
+
+
+static struct wpabuf * eap_eke_build_failure(struct eap_eke_data *data, u8 id)
+{
+ struct wpabuf *msg;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Failure: Failure-Code=0x%x",
+ data->failure_code);
+
+ msg = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE);
+ if (msg == NULL) {
+ eap_eke_state(data, FAILURE);
+ return NULL;
+ }
+ wpabuf_put_be32(msg, data->failure_code);
+
+ return msg;
+}
+
+
+static struct wpabuf * eap_eke_build_identity(struct eap_sm *sm,
+ struct eap_eke_data *data,
+ u8 id)
+{
+ struct wpabuf *msg;
+ size_t plen;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Identity");
+
+ plen = 2 + 4 * 4 + 1 + sm->server_id_len;
+ msg = eap_eke_build_msg(data, id, plen, EAP_EKE_ID);
+ if (msg == NULL)
+ return NULL;
+
+ wpabuf_put_u8(msg, 4); /* NumProposals */
+ wpabuf_put_u8(msg, 0); /* Reserved */
+
+ /* Proposal - DH Group 16 with AES128-CBC and SHA256 */
+ wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_16); /* Group Description */
+ wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
+ wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
+ wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */
+
+ /* Proposal - DH Group 15 with AES128-CBC and SHA256 */
+ wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_15); /* Group Description */
+ wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
+ wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
+ wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */
+
+ /* Proposal - DH Group 14 with AES128-CBC and SHA256 */
+ wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */
+ wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
+ wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
+ wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */
+
+ /*
+ * Proposal - DH Group 14 with AES128-CBC and SHA1
+ * (mandatory to implement algorithms)
+ */
+ wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */
+ wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
+ wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA1); /* PRF */
+ wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA1); /* MAC */
+
+ /* Server IDType + Identity */
+ wpabuf_put_u8(msg, data->serverid_type);
+ wpabuf_put_data(msg, sm->server_id, sm->server_id_len);
+
+ wpabuf_free(data->msgs);
+ data->msgs = wpabuf_dup(msg);
+ if (data->msgs == NULL) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+ return msg;
+}
+
+
+static struct wpabuf * eap_eke_build_commit(struct eap_sm *sm,
+ struct eap_eke_data *data, u8 id)
+{
+ struct wpabuf *msg;
+ u8 pub[EAP_EKE_MAX_DH_LEN];
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Commit");
+
+ if (sm->user == NULL || sm->user->password == NULL) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Password with not configured");
+ eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
+ return eap_eke_build_failure(data, id);
+ }
+
+ if (eap_eke_derive_key(&data->sess, sm->user->password,
+ sm->user->password_len,
+ sm->server_id, sm->server_id_len,
+ data->peerid, data->peerid_len, data->key) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key");
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+
+ msg = eap_eke_build_msg(data, id, data->sess.dhcomp_len,
+ EAP_EKE_COMMIT);
+ if (msg == NULL) {
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+
+ /*
+ * y_s = g ^ x_s (mod p)
+ * x_s = random number 2 .. p-1
+ * temp = prf(0+, password)
+ * key = prf+(temp, ID_S | ID_P)
+ * DHComponent_S = Encr(key, y_s)
+ */
+
+ if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH");
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+
+ if (eap_eke_dhcomp(&data->sess, data->key, pub,
+ wpabuf_put(msg, data->sess.dhcomp_len))
+ < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S");
+ wpabuf_free(msg);
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+
+ if (wpabuf_resize(&data->msgs, wpabuf_len(msg)) < 0) {
+ wpabuf_free(msg);
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+ wpabuf_put_buf(data->msgs, msg);
+
+ return msg;
+}
+
+
+static struct wpabuf * eap_eke_build_confirm(struct eap_sm *sm,
+ struct eap_eke_data *data, u8 id)
+{
+ struct wpabuf *msg;
+ size_t plen, prot_len;
+ u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN];
+ u8 *auth;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Confirm");
+
+ plen = data->sess.pnonce_ps_len + data->sess.prf_len;
+ msg = eap_eke_build_msg(data, id, plen, EAP_EKE_CONFIRM);
+ if (msg == NULL) {
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+
+ if (random_get_bytes(data->nonce_s, data->sess.nonce_len)) {
+ wpabuf_free(msg);
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S",
+ data->nonce_s, data->sess.nonce_len);
+
+ os_memcpy(nonces, data->nonce_p, data->sess.nonce_len);
+ os_memcpy(nonces + data->sess.nonce_len, data->nonce_s,
+ data->sess.nonce_len);
+ prot_len = wpabuf_tailroom(msg);
+ if (eap_eke_prot(&data->sess, nonces, 2 * data->sess.nonce_len,
+ wpabuf_put(msg, 0), &prot_len) < 0) {
+ wpabuf_free(msg);
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+ wpabuf_put(msg, prot_len);
+
+ if (eap_eke_derive_ka(&data->sess,
+ sm->server_id, sm->server_id_len,
+ data->peerid, data->peerid_len,
+ data->nonce_p, data->nonce_s) < 0) {
+ wpabuf_free(msg);
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+
+ auth = wpabuf_put(msg, data->sess.prf_len);
+ if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth) < 0) {
+ wpabuf_free(msg);
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return eap_eke_build_failure(data, id);
+ }
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth, data->sess.prf_len);
+
+ return msg;
+}
+
+
+static struct wpabuf * eap_eke_buildReq(struct eap_sm *sm, void *priv, u8 id)
+{
+ struct eap_eke_data *data = priv;
+
+ switch (data->state) {
+ case IDENTITY:
+ return eap_eke_build_identity(sm, data, id);
+ case COMMIT:
+ return eap_eke_build_commit(sm, data, id);
+ case CONFIRM:
+ return eap_eke_build_confirm(sm, data, id);
+ case FAILURE_REPORT:
+ return eap_eke_build_failure(data, id);
+ default:
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Unknown state %d in buildReq",
+ data->state);
+ break;
+ }
+ return NULL;
+}
+
+
+static Boolean eap_eke_check(struct eap_sm *sm, void *priv,
+ struct wpabuf *respData)
+{
+ struct eap_eke_data *data = priv;
+ size_t len;
+ const u8 *pos;
+ u8 eke_exch;
+
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len);
+ if (pos == NULL || len < 1) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Invalid frame");
+ return TRUE;
+ }
+
+ eke_exch = *pos;
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: EKE-Exch=%d", eke_exch);
+
+ if (data->state == IDENTITY && eke_exch == EAP_EKE_ID)
+ return FALSE;
+
+ if (data->state == COMMIT && eke_exch == EAP_EKE_COMMIT)
+ return FALSE;
+
+ if (data->state == CONFIRM && eke_exch == EAP_EKE_CONFIRM)
+ return FALSE;
+
+ if (eke_exch == EAP_EKE_FAILURE)
+ return FALSE;
+
+ wpa_printf(MSG_INFO, "EAP-EKE: Unexpected EKE-Exch=%d in state=%d",
+ eke_exch, data->state);
+
+ return TRUE;
+}
+
+
+static void eap_eke_process_identity(struct eap_sm *sm,
+ struct eap_eke_data *data,
+ const struct wpabuf *respData,
+ const u8 *payload, size_t payloadlen)
+{
+ const u8 *pos, *end;
+ int i;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Identity");
+
+ if (data->state != IDENTITY) {
+ eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
+ return;
+ }
+
+ pos = payload;
+ end = payload + payloadlen;
+
+ if (pos + 2 + 4 + 1 > end) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Too short EAP-EKE-ID payload");
+ eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
+ return;
+ }
+
+ if (*pos != 1) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Unexpected NumProposals %d (expected 1)",
+ *pos);
+ eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
+ return;
+ }
+
+ pos += 2;
+
+ if (!supported_proposal(pos)) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Unexpected Proposal (%u:%u:%u:%u)",
+ pos[0], pos[1], pos[2], pos[3]);
+ eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Selected Proposal (%u:%u:%u:%u)",
+ pos[0], pos[1], pos[2], pos[3]);
+ if (eap_eke_session_init(&data->sess, pos[0], pos[1], pos[2], pos[3]) <
+ 0) {
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return;
+ }
+ pos += 4;
+
+ data->peerid_type = *pos++;
+ os_free(data->peerid);
+ data->peerid = os_malloc(end - pos);
+ if (data->peerid == NULL) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to allocate memory for peerid");
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return;
+ }
+ os_memcpy(data->peerid, pos, end - pos);
+ data->peerid_len = end - pos;
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Peer IDType %u", data->peerid_type);
+ wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Peer Identity",
+ data->peerid, data->peerid_len);
+
+ if (eap_user_get(sm, data->peerid, data->peerid_len, data->phase2)) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Peer Identity not found from user database");
+ eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
+ return;
+ }
+
+ for (i = 0; i < EAP_MAX_METHODS; i++) {
+ if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
+ sm->user->methods[i].method == EAP_TYPE_EKE)
+ break;
+ }
+ if (i == EAP_MAX_METHODS) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Matching user entry does not allow EAP-EKE");
+ eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
+ return;
+ }
+
+ if (sm->user->password == NULL || sm->user->password_len == 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: No password configured for peer");
+ eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
+ return;
+ }
+
+ if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) {
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return;
+ }
+ wpabuf_put_buf(data->msgs, respData);
+
+ eap_eke_state(data, COMMIT);
+}
+
+
+static void eap_eke_process_commit(struct eap_sm *sm,
+ struct eap_eke_data *data,
+ const struct wpabuf *respData,
+ const u8 *payload, size_t payloadlen)
+{
+ const u8 *pos, *end, *dhcomp, *pnonce;
+ size_t decrypt_len;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Commit");
+
+ if (data->state != COMMIT) {
+ eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
+ return;
+ }
+
+ pos = payload;
+ end = payload + payloadlen;
+
+ if (pos + data->sess.dhcomp_len + data->sess.pnonce_len > end) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit");
+ eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
+ return;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P",
+ pos, data->sess.dhcomp_len);
+ dhcomp = pos;
+ pos += data->sess.dhcomp_len;
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P", pos, data->sess.pnonce_len);
+ pnonce = pos;
+ pos += data->sess.pnonce_len;
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos);
+
+ if (eap_eke_shared_secret(&data->sess, data->key, data->dh_priv, dhcomp)
+ < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret");
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return;
+ }
+
+ if (eap_eke_derive_ke_ki(&data->sess,
+ sm->server_id, sm->server_id_len,
+ data->peerid, data->peerid_len) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki");
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return;
+ }
+
+ decrypt_len = sizeof(data->nonce_p);
+ if (eap_eke_decrypt_prot(&data->sess, pnonce, data->sess.pnonce_len,
+ data->nonce_p, &decrypt_len) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_P");
+ eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ return;
+ }
+ if (decrypt_len < (size_t) data->sess.nonce_len) {
+ wpa_printf(MSG_INFO, "EAP-EKE: PNonce_P protected data too short to include Nonce_P");
+ eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ return;
+ }
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P",
+ data->nonce_p, data->sess.nonce_len);
+
+ if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) {
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return;
+ }
+ wpabuf_put_buf(data->msgs, respData);
+
+ eap_eke_state(data, CONFIRM);
+}
+
+
+static void eap_eke_process_confirm(struct eap_sm *sm,
+ struct eap_eke_data *data,
+ const struct wpabuf *respData,
+ const u8 *payload, size_t payloadlen)
+{
+ size_t decrypt_len;
+ u8 nonce[EAP_EKE_MAX_NONCE_LEN];
+ u8 auth_p[EAP_EKE_MAX_HASH_LEN];
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm");
+
+ if (data->state != CONFIRM) {
+ eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm");
+
+ if (payloadlen < (size_t) data->sess.pnonce_len + data->sess.prf_len) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm");
+ eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
+ return;
+ }
+
+ decrypt_len = sizeof(nonce);
+ if (eap_eke_decrypt_prot(&data->sess, payload, data->sess.pnonce_len,
+ nonce, &decrypt_len) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_S");
+ eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ return;
+ }
+ if (decrypt_len < (size_t) data->sess.nonce_len) {
+ wpa_printf(MSG_INFO, "EAP-EKE: PNonce_S protected data too short to include Nonce_S");
+ eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ return;
+ }
+ wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_S",
+ nonce, data->sess.nonce_len);
+ if (os_memcmp(nonce, data->nonce_s, data->sess.nonce_len) != 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_S does not match previously sent Nonce_S");
+ eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ return;
+ }
+
+ if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth_p) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Could not derive Auth_P");
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return;
+ }
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth_p, data->sess.prf_len);
+ if (os_memcmp(auth_p, payload + data->sess.pnonce_len,
+ data->sess.prf_len) != 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Auth_P does not match");
+ eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
+ return;
+ }
+
+ if (eap_eke_derive_msk(&data->sess, sm->server_id, sm->server_id_len,
+ data->peerid, data->peerid_len,
+ data->nonce_s, data->nonce_p,
+ data->msk, data->emsk) < 0) {
+ wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK");
+ eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
+ return;
+ }
+
+ os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
+ os_memset(data->key, 0, sizeof(data->key));
+ eap_eke_session_clean(&data->sess);
+
+ eap_eke_state(data, SUCCESS);
+}
+
+
+static void eap_eke_process_failure(struct eap_sm *sm,
+ struct eap_eke_data *data,
+ const struct wpabuf *respData,
+ const u8 *payload, size_t payloadlen)
+{
+ u32 code;
+
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Failure");
+
+ if (payloadlen < 4) {
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure");
+ eap_eke_state(data, FAILURE);
+ return;
+ }
+
+ code = WPA_GET_BE32(payload);
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Peer reported failure code 0x%x", code);
+
+ eap_eke_state(data, FAILURE);
+}
+
+
+static void eap_eke_process(struct eap_sm *sm, void *priv,
+ struct wpabuf *respData)
+{
+ struct eap_eke_data *data = priv;
+ u8 eke_exch;
+ size_t len;
+ const u8 *pos, *end;
+
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len);
+ if (pos == NULL || len < 1)
+ return;
+
+ eke_exch = *pos;
+ end = pos + len;
+ pos++;
+
+ wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received payload", pos, end - pos);
+
+ switch (eke_exch) {
+ case EAP_EKE_ID:
+ eap_eke_process_identity(sm, data, respData, pos, end - pos);
+ break;
+ case EAP_EKE_COMMIT:
+ eap_eke_process_commit(sm, data, respData, pos, end - pos);
+ break;
+ case EAP_EKE_CONFIRM:
+ eap_eke_process_confirm(sm, data, respData, pos, end - pos);
+ break;
+ case EAP_EKE_FAILURE:
+ eap_eke_process_failure(sm, data, respData, pos, end - pos);
+ break;
+ }
+}
+
+
+static Boolean eap_eke_isDone(struct eap_sm *sm, void *priv)
+{
+ struct eap_eke_data *data = priv;
+ return data->state == SUCCESS || data->state == FAILURE;
+}
+
+
+static u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_eke_data *data = priv;
+ u8 *key;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ key = os_malloc(EAP_MSK_LEN);
+ if (key == NULL)
+ return NULL;
+ os_memcpy(key, data->msk, EAP_MSK_LEN);
+ *len = EAP_MSK_LEN;
+
+ return key;
+}
+
+
+static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_eke_data *data = priv;
+ u8 *key;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ key = os_malloc(EAP_EMSK_LEN);
+ if (key == NULL)
+ return NULL;
+ os_memcpy(key, data->emsk, EAP_EMSK_LEN);
+ *len = EAP_EMSK_LEN;
+
+ return key;
+}
+
+
+static Boolean eap_eke_isSuccess(struct eap_sm *sm, void *priv)
+{
+ struct eap_eke_data *data = priv;
+ return data->state == SUCCESS;
+}
+
+
+int eap_server_eke_register(void)
+{
+ struct eap_method *eap;
+ int ret;
+
+ eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
+ EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE");
+ if (eap == NULL)
+ return -1;
+
+ eap->init = eap_eke_init;
+ eap->reset = eap_eke_reset;
+ eap->buildReq = eap_eke_buildReq;
+ eap->check = eap_eke_check;
+ eap->process = eap_eke_process;
+ eap->isDone = eap_eke_isDone;
+ eap->getKey = eap_eke_getKey;
+ eap->isSuccess = eap_eke_isSuccess;
+ eap->get_emsk = eap_eke_get_emsk;
+
+ ret = eap_server_method_register(eap);
+ if (ret)
+ eap_server_method_free(eap);
+ return ret;
+}
diff --git a/src/eap_server/eap_server_gpsk.c b/src/eap_server/eap_server_gpsk.c
index 2853c48..66f4271 100644
--- a/src/eap_server/eap_server_gpsk.c
+++ b/src/eap_server/eap_server_gpsk.c
@@ -26,8 +26,6 @@
size_t pk_len;
u8 *id_peer;
size_t id_peer_len;
- u8 *id_server;
- size_t id_server_len;
#define MAX_NUM_CSUITES 2
struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES];
size_t csuite_count;
@@ -71,11 +69,6 @@
return NULL;
data->state = GPSK_1;
- /* TODO: add support for configuring ID_Server */
- data->id_server = (u8 *) os_strdup("hostapd");
- if (data->id_server)
- data->id_server_len = os_strlen((char *) data->id_server);
-
data->csuite_count = 0;
if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
EAP_GPSK_CIPHER_AES)) {
@@ -101,7 +94,6 @@
static void eap_gpsk_reset(struct eap_sm *sm, void *priv)
{
struct eap_gpsk_data *data = priv;
- os_free(data->id_server);
os_free(data->id_peer);
os_free(data);
}
@@ -123,7 +115,7 @@
wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server",
data->rand_server, EAP_GPSK_RAND_LEN);
- len = 1 + 2 + data->id_server_len + EAP_GPSK_RAND_LEN + 2 +
+ len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 +
data->csuite_count * sizeof(struct eap_gpsk_csuite);
req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
EAP_CODE_REQUEST, id);
@@ -135,8 +127,8 @@
}
wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1);
- wpabuf_put_be16(req, data->id_server_len);
- wpabuf_put_data(req, data->id_server, data->id_server_len);
+ wpabuf_put_be16(req, sm->server_id_len);
+ wpabuf_put_data(req, sm->server_id, sm->server_id_len);
wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
wpabuf_put_be16(req,
data->csuite_count * sizeof(struct eap_gpsk_csuite));
@@ -158,7 +150,7 @@
wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3");
miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
- len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + data->id_server_len +
+ len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len +
sizeof(struct eap_gpsk_csuite) + 2 + miclen;
req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
EAP_CODE_REQUEST, id);
@@ -174,8 +166,8 @@
wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN);
wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
- wpabuf_put_be16(req, data->id_server_len);
- wpabuf_put_data(req, data->id_server, data->id_server_len);
+ wpabuf_put_be16(req, sm->server_id_len);
+ wpabuf_put_data(req, sm->server_id, sm->server_id_len);
csuite = wpabuf_put(req, sizeof(*csuite));
WPA_PUT_BE32(csuite->vendor, data->vendor);
WPA_PUT_BE16(csuite->specifier, data->specifier);
@@ -301,8 +293,8 @@
eap_gpsk_state(data, FAILURE);
return;
}
- if (alen != data->id_server_len ||
- os_memcmp(pos, data->id_server, alen) != 0) {
+ if (alen != sm->server_id_len ||
+ os_memcmp(pos, sm->server_id, alen) != 0) {
wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and "
"GPSK-2 did not match");
eap_gpsk_state(data, FAILURE);
@@ -416,7 +408,7 @@
data->vendor, data->specifier,
data->rand_peer, data->rand_server,
data->id_peer, data->id_peer_len,
- data->id_server, data->id_server_len,
+ sm->server_id, sm->server_id_len,
data->msk, data->emsk,
data->sk, &data->sk_len,
data->pk, &data->pk_len) < 0) {
diff --git a/src/eap_server/eap_server_ikev2.c b/src/eap_server/eap_server_ikev2.c
index 42aaca2..1ada0c8 100644
--- a/src/eap_server/eap_server_ikev2.c
+++ b/src/eap_server/eap_server_ikev2.c
@@ -103,8 +103,11 @@
data->ikev2.proposal.encr = ENCR_AES_CBC;
data->ikev2.proposal.dh = DH_GROUP2_1024BIT_MODP;
- data->ikev2.IDi = (u8 *) os_strdup("hostapd");
- data->ikev2.IDi_len = 7;
+ data->ikev2.IDi = os_malloc(sm->server_id_len);
+ if (data->ikev2.IDi == NULL)
+ goto failed;
+ os_memcpy(data->ikev2.IDi, sm->server_id, sm->server_id_len);
+ data->ikev2.IDi_len = sm->server_id_len;
data->ikev2.get_shared_secret = eap_ikev2_get_shared_secret;
data->ikev2.cb_ctx = sm;
diff --git a/src/eap_server/eap_server_mschapv2.c b/src/eap_server/eap_server_mschapv2.c
index 8d3dd52..3153d2e 100644
--- a/src/eap_server/eap_server_mschapv2.c
+++ b/src/eap_server/eap_server_mschapv2.c
@@ -100,7 +100,6 @@
{
struct wpabuf *req;
struct eap_mschapv2_hdr *ms;
- char *name = "hostapd"; /* TODO: make this configurable */
size_t ms_len;
if (!data->auth_challenge_from_tls &&
@@ -111,7 +110,7 @@
return NULL;
}
- ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + os_strlen(name);
+ ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->server_id_len;
req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
EAP_CODE_REQUEST, id);
if (req == NULL) {
@@ -133,7 +132,7 @@
wpabuf_put(req, CHALLENGE_LEN);
wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge",
data->auth_challenge, CHALLENGE_LEN);
- wpabuf_put_data(req, name, os_strlen(name));
+ wpabuf_put_data(req, sm->server_id, sm->server_id_len);
return req;
}
diff --git a/src/eap_server/eap_server_psk.c b/src/eap_server/eap_server_psk.c
index 0cd9799..46bedd9 100644
--- a/src/eap_server/eap_server_psk.c
+++ b/src/eap_server/eap_server_psk.c
@@ -22,8 +22,8 @@
enum { PSK_1, PSK_3, SUCCESS, FAILURE } state;
u8 rand_s[EAP_PSK_RAND_LEN];
u8 rand_p[EAP_PSK_RAND_LEN];
- u8 *id_p, *id_s;
- size_t id_p_len, id_s_len;
+ u8 *id_p;
+ size_t id_p_len;
u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
u8 msk[EAP_MSK_LEN];
u8 emsk[EAP_EMSK_LEN];
@@ -38,8 +38,6 @@
if (data == NULL)
return NULL;
data->state = PSK_1;
- data->id_s = (u8 *) "hostapd";
- data->id_s_len = 7;
return data;
}
@@ -70,7 +68,7 @@
data->rand_s, EAP_PSK_RAND_LEN);
req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK,
- sizeof(*psk) + data->id_s_len,
+ sizeof(*psk) + sm->server_id_len,
EAP_CODE_REQUEST, id);
if (req == NULL) {
wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory "
@@ -82,7 +80,7 @@
psk = wpabuf_put(req, sizeof(*psk));
psk->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */
os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
- wpabuf_put_data(req, data->id_s, data->id_s_len);
+ wpabuf_put_data(req, sm->server_id, sm->server_id_len);
return req;
}
@@ -112,13 +110,13 @@
os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
/* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
- buflen = data->id_s_len + EAP_PSK_RAND_LEN;
+ buflen = sm->server_id_len + EAP_PSK_RAND_LEN;
buf = os_malloc(buflen);
if (buf == NULL)
goto fail;
- os_memcpy(buf, data->id_s, data->id_s_len);
- os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
+ os_memcpy(buf, sm->server_id, sm->server_id_len);
+ os_memcpy(buf + sm->server_id_len, data->rand_p, EAP_PSK_RAND_LEN);
if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) {
os_free(buf);
goto fail;
@@ -296,7 +294,7 @@
os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN);
/* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
- buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
+ buflen = data->id_p_len + sm->server_id_len + 2 * EAP_PSK_RAND_LEN;
buf = os_malloc(buflen);
if (buf == NULL) {
data->state = FAILURE;
@@ -304,8 +302,8 @@
}
os_memcpy(buf, data->id_p, data->id_p_len);
pos = buf + data->id_p_len;
- os_memcpy(pos, data->id_s, data->id_s_len);
- pos += data->id_s_len;
+ os_memcpy(pos, sm->server_id, sm->server_id_len);
+ pos += sm->server_id_len;
os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN);
pos += EAP_PSK_RAND_LEN;
os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
diff --git a/src/eap_server/eap_server_sake.c b/src/eap_server/eap_server_sake.c
index f72e1bf..68dd76b 100644
--- a/src/eap_server/eap_server_sake.c
+++ b/src/eap_server/eap_server_sake.c
@@ -27,8 +27,6 @@
u8 session_id;
u8 *peerid;
size_t peerid_len;
- u8 *serverid;
- size_t serverid_len;
};
@@ -77,11 +75,6 @@
wpa_printf(MSG_DEBUG, "EAP-SAKE: Initialized Session ID %d",
data->session_id);
- /* TODO: add support for configuring SERVERID */
- data->serverid = (u8 *) os_strdup("hostapd");
- if (data->serverid)
- data->serverid_len = os_strlen((char *) data->serverid);
-
return data;
}
@@ -89,7 +82,6 @@
static void eap_sake_reset(struct eap_sm *sm, void *priv)
{
struct eap_sake_data *data = priv;
- os_free(data->serverid);
os_free(data->peerid);
os_free(data);
}
@@ -131,8 +123,7 @@
wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Identity");
plen = 4;
- if (data->serverid)
- plen += 2 + data->serverid_len;
+ plen += 2 + sm->server_id_len;
msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_IDENTITY);
if (msg == NULL) {
data->state = FAILURE;
@@ -142,11 +133,9 @@
wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PERM_ID_REQ");
eap_sake_add_attr(msg, EAP_SAKE_AT_PERM_ID_REQ, NULL, 2);
- if (data->serverid) {
- wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID");
- eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID,
- data->serverid, data->serverid_len);
- }
+ wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID");
+ eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID,
+ sm->server_id, sm->server_id_len);
return msg;
}
@@ -169,9 +158,7 @@
wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)",
data->rand_s, EAP_SAKE_RAND_LEN);
- plen = 2 + EAP_SAKE_RAND_LEN;
- if (data->serverid)
- plen += 2 + data->serverid_len;
+ plen = 2 + EAP_SAKE_RAND_LEN + 2 + sm->server_id_len;
msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_CHALLENGE);
if (msg == NULL) {
data->state = FAILURE;
@@ -182,11 +169,9 @@
eap_sake_add_attr(msg, EAP_SAKE_AT_RAND_S,
data->rand_s, EAP_SAKE_RAND_LEN);
- if (data->serverid) {
- wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID");
- eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID,
- data->serverid, data->serverid_len);
- }
+ wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID");
+ eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID,
+ sm->server_id, sm->server_id_len);
return msg;
}
@@ -213,7 +198,7 @@
wpabuf_put_u8(msg, 2 + EAP_SAKE_MIC_LEN);
mic = wpabuf_put(msg, EAP_SAKE_MIC_LEN);
if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
- data->serverid, data->serverid_len,
+ sm->server_id, sm->server_id_len,
data->peerid, data->peerid_len, 0,
wpabuf_head(msg), wpabuf_len(msg), mic, mic))
{
@@ -362,7 +347,7 @@
(u8 *) &data->tek, data->msk, data->emsk);
eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
- data->serverid, data->serverid_len,
+ sm->server_id, sm->server_id_len,
data->peerid, data->peerid_len, 1,
wpabuf_head(respData), wpabuf_len(respData),
attr.mic_p, mic_p);
@@ -399,7 +384,7 @@
}
eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
- data->serverid, data->serverid_len,
+ sm->server_id, sm->server_id_len,
data->peerid, data->peerid_len, 1,
wpabuf_head(respData), wpabuf_len(respData),
attr.mic_p, mic_p);
diff --git a/src/eap_server/eap_sim_db.c b/src/eap_server/eap_sim_db.c
index 257013e..1b9d701 100644
--- a/src/eap_server/eap_sim_db.c
+++ b/src/eap_server/eap_sim_db.c
@@ -1480,7 +1480,6 @@
*/
char * sim_get_username(const u8 *identity, size_t identity_len)
{
- char *username;
size_t pos;
if (identity == NULL)
@@ -1491,11 +1490,5 @@
break;
}
- username = os_malloc(pos + 1);
- if (username == NULL)
- return NULL;
- os_memcpy(username, identity, pos);
- username[pos] = '\0';
-
- return username;
+ return dup_binstr(identity, pos);
}
diff --git a/src/eap_server/tncs.c b/src/eap_server/tncs.c
index 5e332ae..e429f1e 100644
--- a/src/eap_server/tncs.c
+++ b/src/eap_server/tncs.c
@@ -851,12 +851,10 @@
unsigned char *decoded;
size_t decoded_len;
- buf = os_malloc(len + 1);
+ buf = dup_binstr(msg, len);
if (buf == NULL)
return TNCCS_PROCESS_ERROR;
- os_memcpy(buf, msg, len);
- buf[len] = '\0';
start = os_strstr(buf, "<TNCCS-Batch ");
end = os_strstr(buf, "</TNCCS-Batch>");
if (start == NULL || end == NULL || start > end) {
diff --git a/src/eapol_auth/eapol_auth_sm.c b/src/eapol_auth/eapol_auth_sm.c
index c3ccb46..013d781 100644
--- a/src/eapol_auth/eapol_auth_sm.c
+++ b/src/eapol_auth/eapol_auth_sm.c
@@ -830,6 +830,8 @@
eap_conf.fragment_size = eapol->conf.fragment_size;
eap_conf.pwd_group = eapol->conf.pwd_group;
eap_conf.pbc_in_m1 = eapol->conf.pbc_in_m1;
+ eap_conf.server_id = eapol->conf.server_id;
+ eap_conf.server_id_len = eapol->conf.server_id_len;
sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
if (sm->eap == NULL) {
eapol_auth_free(sm);
@@ -1045,6 +1047,8 @@
os_free(dst->eap_req_id_text);
dst->pwd_group = src->pwd_group;
dst->pbc_in_m1 = src->pbc_in_m1;
+ dst->server_id = src->server_id;
+ dst->server_id_len = src->server_id_len;
if (src->eap_req_id_text) {
dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
if (dst->eap_req_id_text == NULL)
diff --git a/src/eapol_auth/eapol_auth_sm.h b/src/eapol_auth/eapol_auth_sm.h
index b50bbdd..3a0f450 100644
--- a/src/eapol_auth/eapol_auth_sm.h
+++ b/src/eapol_auth/eapol_auth_sm.h
@@ -37,6 +37,8 @@
int fragment_size;
u16 pwd_group;
int pbc_in_m1;
+ const u8 *server_id;
+ size_t server_id_len;
/* Opaque context pointer to owner data for callback functions */
void *ctx;
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index 2e56086..9b054fc 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -1533,6 +1533,10 @@
{
if (sm) {
sm->userLogoff = logoff;
+ if (!logoff) {
+ /* If there is a delayed txStart queued, start now. */
+ sm->startWhen = 0;
+ }
eapol_sm_step(sm);
}
}
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 2b5e5bd..0a414ee 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -12,7 +12,6 @@
#include "eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
-#include "common/wpa_ctrl.h"
#include "wps/wps_i.h"
#include "p2p_i.h"
#include "p2p.h"
@@ -119,8 +118,9 @@
continue;
#endif
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Expiring old peer "
- "entry " MACSTR, MAC2STR(dev->info.p2p_device_addr));
+ p2p_dbg(p2p, "Expiring old peer entry " MACSTR,
+ MAC2STR(dev->info.p2p_device_addr));
+
#ifdef ANDROID_P2P
/* SD_FAIR_POLICY: Update the current sd_dev_list pointer to next device */
if(&dev->list == p2p->sd_dev_list)
@@ -210,7 +210,7 @@
void p2p_set_state(struct p2p_data *p2p, int new_state)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: State %s -> %s",
+ p2p_dbg(p2p, "State %s -> %s",
p2p_state_txt(p2p->state), p2p_state_txt(new_state));
p2p->state = new_state;
}
@@ -218,8 +218,7 @@
void p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, unsigned int usec)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Set timeout (state=%s): %u.%06u sec",
+ p2p_dbg(p2p, "Set timeout (state=%s): %u.%06u sec",
p2p_state_txt(p2p->state), sec, usec);
eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL);
@@ -228,8 +227,7 @@
void p2p_clear_timeout(struct p2p_data *p2p)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear timeout (state=%s)",
- p2p_state_txt(p2p->state));
+ p2p_dbg(p2p, "Clear timeout (state=%s)", p2p_state_txt(p2p->state));
eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
}
@@ -264,15 +262,12 @@
int freq;
struct wpabuf *ies;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Starting short listen state (state=%s)",
+ p2p_dbg(p2p, "Starting short listen state (state=%s)",
p2p_state_txt(p2p->state));
- freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
- p2p->cfg->channel);
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
if (freq < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown regulatory class/channel");
+ p2p_dbg(p2p, "Unknown regulatory class/channel");
return;
}
@@ -287,8 +282,7 @@
tu = p2p->cfg->max_listen * 1000 / 1024;
if (tu == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip listen state "
- "since duration was 0 TU");
+ p2p_dbg(p2p, "Skip listen state since duration was 0 TU");
p2p_set_timeout(p2p, 0, 0);
return;
}
@@ -303,8 +297,7 @@
if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000,
ies) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to start listen mode");
+ p2p_dbg(p2p, "Failed to start listen mode");
p2p->pending_listen_freq = 0;
}
wpabuf_free(ies);
@@ -316,14 +309,11 @@
int freq;
struct wpabuf *ies;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Going to listen(only) state");
+ p2p_dbg(p2p, "Going to listen(only) state");
- freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
- p2p->cfg->channel);
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
if (freq < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown regulatory class/channel");
+ p2p_dbg(p2p, "Unknown regulatory class/channel");
return -1;
}
@@ -333,13 +323,10 @@
if (p2p->p2p_scan_running) {
if (p2p->start_after_scan == P2P_AFTER_SCAN_CONNECT) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: p2p_scan running - connect is already "
- "pending - skip listen");
+ p2p_dbg(p2p, "p2p_scan running - connect is already pending - skip listen");
return 0;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: p2p_scan running - delay start of listen state");
+ p2p_dbg(p2p, "p2p_scan running - delay start of listen state");
p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
return 0;
}
@@ -349,8 +336,7 @@
return -1;
if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to start listen mode");
+ p2p_dbg(p2p, "Failed to start listen mode");
p2p->pending_listen_freq = 0;
wpabuf_free(ies);
return -1;
@@ -432,9 +418,7 @@
oldest = dev;
}
if (count + 1 > p2p->cfg->max_peers && oldest) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Remove oldest peer entry to make room for a new "
- "peer");
+ p2p_dbg(p2p, "Remove oldest peer entry to make room for a new peer");
#ifdef ANDROID_P2P
/* SD_FAIR_POLICY: Update the current sd_dev_list pointer to next device */
if(&oldest->list == p2p->sd_dev_list)
@@ -548,8 +532,8 @@
}
-static void p2p_copy_wps_info(struct p2p_device *dev, int probe_req,
- const struct p2p_message *msg)
+static void p2p_copy_wps_info(struct p2p_data *p2p, struct p2p_device *dev,
+ int probe_req, const struct p2p_message *msg)
{
os_memcpy(dev->info.device_name, msg->device_name,
sizeof(dev->info.device_name));
@@ -624,11 +608,11 @@
msg->config_methods : msg->wps_config_methods;
if (new_config_methods &&
dev->info.config_methods != new_config_methods) {
- wpa_printf(MSG_DEBUG, "P2P: Update peer " MACSTR
- " config_methods 0x%x -> 0x%x",
- MAC2STR(dev->info.p2p_device_addr),
- dev->info.config_methods,
- new_config_methods);
+ p2p_dbg(p2p, "Update peer " MACSTR
+ " config_methods 0x%x -> 0x%x",
+ MAC2STR(dev->info.p2p_device_addr),
+ dev->info.config_methods,
+ new_config_methods);
dev->info.config_methods = new_config_methods;
}
}
@@ -665,8 +649,7 @@
os_memset(&msg, 0, sizeof(msg));
if (p2p_parse_ies(ies, ies_len, &msg)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to parse P2P IE for a device entry");
+ p2p_dbg(p2p, "Failed to parse P2P IE for a device entry");
p2p_parse_free(&msg);
return -1;
}
@@ -676,18 +659,15 @@
else if (msg.device_id)
p2p_dev_addr = msg.device_id;
else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore scan data without P2P Device Info or "
- "P2P Device Id");
+ p2p_dbg(p2p, "Ignore scan data without P2P Device Info or P2P Device Id");
p2p_parse_free(&msg);
return -1;
}
if (!is_zero_ether_addr(p2p->peer_filter) &&
os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not add peer "
- "filter for " MACSTR " due to peer filter",
- MAC2STR(p2p_dev_addr));
+ p2p_dbg(p2p, "Do not add peer filter for " MACSTR
+ " due to peer filter", MAC2STR(p2p_dev_addr));
p2p_parse_free(&msg);
return 0;
}
@@ -709,9 +689,7 @@
*/
if (dev->last_seen.sec > 0 &&
os_time_before(rx_time, &dev->last_seen)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not update peer "
- "entry based on old frame (rx_time=%u.%06u "
- "last_seen=%u.%06u)",
+ p2p_dbg(p2p, "Do not update peer entry based on old frame (rx_time=%u.%06u last_seen=%u.%06u)",
(unsigned int) rx_time->sec,
(unsigned int) rx_time->usec,
(unsigned int) dev->last_seen.sec,
@@ -742,18 +720,15 @@
else
ds_freq = 2407 + *msg.ds_params * 5;
if (freq != ds_freq) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Update Listen frequency based on DS "
- "Parameter Set IE: %d -> %d MHz",
+ p2p_dbg(p2p, "Update Listen frequency based on DS Parameter Set IE: %d -> %d MHz",
freq, ds_freq);
freq = ds_freq;
}
}
if (dev->listen_freq && dev->listen_freq != freq && scan_res) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Update Listen frequency based on scan "
- "results (" MACSTR " %d -> %d MHz (DS param %d)",
+ p2p_dbg(p2p, "Update Listen frequency based on scan results ("
+ MACSTR " %d -> %d MHz (DS param %d)",
MAC2STR(dev->info.p2p_device_addr), dev->listen_freq,
freq, msg.ds_params ? *msg.ds_params : -1);
}
@@ -764,7 +739,7 @@
}
dev->info.level = level;
- p2p_copy_wps_info(dev, 0, &msg);
+ p2p_copy_wps_info(p2p, dev, 0, &msg);
for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
wpabuf_free(dev->info.wps_vendor_ext[i]);
@@ -798,13 +773,11 @@
if (dev->flags & P2P_DEV_REPORTED)
return 0;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Peer found with Listen frequency %d MHz "
- "(rx_time=%u.%06u)", freq, (unsigned int) rx_time->sec,
+ p2p_dbg(p2p, "Peer found with Listen frequency %d MHz (rx_time=%u.%06u)",
+ freq, (unsigned int) rx_time->sec,
(unsigned int) rx_time->usec);
if (dev->flags & P2P_DEV_USER_REJECTED) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Do not report rejected device");
+ p2p_dbg(p2p, "Do not report rejected device");
return 0;
}
@@ -824,9 +797,8 @@
* Probe Response frame that includes the config_methods
* information.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Do not report peer " MACSTR " with unknown "
- "config methods", MAC2STR(addr));
+ p2p_dbg(p2p, "Do not report peer " MACSTR
+ " with unknown config methods", MAC2STR(addr));
return 0;
}
@@ -914,9 +886,8 @@
channel = c->reg_class[cl].channel[ch];
}
- freq = p2p_channel_to_freq(p2p->cfg->country, reg_class, channel);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Next progressive search "
- "channel: reg_class %u channel %u -> %d MHz",
+ freq = p2p_channel_to_freq(reg_class, channel);
+ p2p_dbg(p2p, "Next progressive search channel: reg_class %u channel %u -> %d MHz",
reg_class, channel, freq);
p2p->last_prog_scan_class = reg_class;
p2p->last_prog_scan_chan = channel;
@@ -935,9 +906,7 @@
int res;
if (p2p->drv_in_listen) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still "
- "in Listen state - wait for it to end before "
- "continuing");
+ p2p_dbg(p2p, "Driver is still in Listen state - wait for it to end before continuing");
return;
}
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
@@ -945,27 +914,23 @@
if (p2p->find_type == P2P_FIND_PROGRESSIVE &&
(freq = p2p_get_next_prog_freq(p2p)) > 0) {
type = P2P_SCAN_SOCIAL_PLUS_ONE;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
- "(+ freq %u)", freq);
+ p2p_dbg(p2p, "Starting search (+ freq %u)", freq);
} else {
type = P2P_SCAN_SOCIAL;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search");
+ p2p_dbg(p2p, "Starting search");
}
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
p2p->num_req_dev_types, p2p->req_dev_types,
p2p->find_dev_id, pw_id);
if (res < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Scan request failed");
+ p2p_dbg(p2p, "Scan request failed");
p2p_continue_find(p2p);
} else if (res == 1) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start "
- "p2p_scan at this point - will try again after "
- "previous scan completes");
+ p2p_dbg(p2p, "Could not start p2p_scan at this point - will try again after previous scan completes");
p2p_set_state(p2p, P2P_CONTINUE_SEARCH_WHEN_READY);
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
+ p2p_dbg(p2p, "Running p2p_scan");
p2p->p2p_scan_running = 1;
eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
@@ -977,7 +942,7 @@
static void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct p2p_data *p2p = eloop_ctx;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Find timeout -> stop");
+ p2p_dbg(p2p, "Find timeout -> stop");
p2p_stop_find(p2p);
}
@@ -988,10 +953,8 @@
enum p2p_after_scan op;
if (p2p->after_scan_tx) {
- /* TODO: schedule p2p_run_after_scan to be called from TX
- * status callback(?) */
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending "
- "Action frame at p2p_scan completion");
+ p2p->after_scan_tx_in_progress = 1;
+ p2p_dbg(p2p, "Send pending Action frame at p2p_scan completion");
p2p->cfg->send_action(p2p->cfg->cb_ctx,
p2p->after_scan_tx->freq,
p2p->after_scan_tx->dst,
@@ -1019,19 +982,16 @@
case P2P_AFTER_SCAN_NOTHING:
break;
case P2P_AFTER_SCAN_LISTEN:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
- "requested Listen state");
+ p2p_dbg(p2p, "Start previously requested Listen state");
p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
p2p->pending_listen_usec / 1000);
return 1;
case P2P_AFTER_SCAN_CONNECT:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
- "requested connect with " MACSTR,
+ p2p_dbg(p2p, "Start previously requested connect with " MACSTR,
MAC2STR(p2p->after_scan_peer));
dev = p2p_get_device(p2p, p2p->after_scan_peer);
if (dev == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer not "
- "known anymore");
+ p2p_dbg(p2p, "Peer not known anymore");
break;
}
p2p_connect_send(p2p, dev);
@@ -1046,8 +1006,7 @@
{
struct p2p_data *p2p = eloop_ctx;
int running;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan timeout "
- "(running=%d)", p2p->p2p_scan_running);
+ p2p_dbg(p2p, "p2p_scan timeout (running=%d)", p2p->p2p_scan_running);
running = p2p->p2p_scan_running;
/* Make sure we recover from missed scan results callback */
p2p->p2p_scan_running = 0;
@@ -1072,12 +1031,10 @@
{
int res;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)",
- type);
+ p2p_dbg(p2p, "Starting find (type=%d)", type);
os_get_time(&p2p->find_start);
if (p2p->p2p_scan_running) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is "
- "already running");
+ p2p_dbg(p2p, "p2p_scan is already running");
}
p2p_free_req_dev_types(p2p);
@@ -1129,21 +1086,18 @@
}
if (res == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
+ p2p_dbg(p2p, "Running p2p_scan");
p2p->p2p_scan_running = 1;
eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
p2p, NULL);
} else if (res == 1) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start "
- "p2p_scan at this point - will try again after "
- "previous scan completes");
+ p2p_dbg(p2p, "Could not start p2p_scan at this point - will try again after previous scan completes");
res = 0;
p2p_set_state(p2p, P2P_SEARCH_WHEN_READY);
eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
- "p2p_scan");
+ p2p_dbg(p2p, "Failed to start p2p_scan");
p2p_set_state(p2p, P2P_IDLE);
eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
}
@@ -1173,12 +1127,11 @@
}
if (p2p->state != P2P_SEARCH_WHEN_READY)
return 0;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find "
- "now that previous scan was completed");
+ p2p_dbg(p2p, "Starting pending P2P find now that previous scan was completed");
if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
p2p->num_req_dev_types, p2p->req_dev_types,
p2p->find_dev_id, p2p->search_delay) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
+ p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
return 0;
}
return 1;
@@ -1187,13 +1140,13 @@
void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find");
+ p2p_dbg(p2p, "Stopping find");
eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
p2p_clear_timeout(p2p);
if (p2p->state == P2P_SEARCH ||
p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY ||
p2p->state == P2P_SEARCH_WHEN_READY)
- wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
+ p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
p2p_set_state(p2p, P2P_IDLE);
p2p_free_req_dev_types(p2p);
p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
@@ -1209,8 +1162,7 @@
void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
{
if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen "
- "since we are on correct channel for response");
+ p2p_dbg(p2p, "Skip stop_listen since we are on correct channel for response");
return;
}
if (p2p->in_listen) {
@@ -1223,8 +1175,7 @@
* when the operation gets canceled, so clear the internal
* variable that is tracking driver state.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear "
- "drv_in_listen (%d)", p2p->drv_in_listen);
+ p2p_dbg(p2p, "Clear drv_in_listen (%d)", p2p->drv_in_listen);
p2p->drv_in_listen = 0;
}
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
@@ -1244,17 +1195,14 @@
u8 op_class, op_channel;
unsigned int freq = force_freq ? force_freq : pref_freq;
- if (p2p_freq_to_channel(p2p->cfg->country, freq,
- &op_class, &op_channel) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported frequency %u MHz", freq);
+ if (p2p_freq_to_channel(freq, &op_class, &op_channel) < 0) {
+ p2p_dbg(p2p, "Unsupported frequency %u MHz", freq);
return -1;
}
if (!p2p_channels_includes(&p2p->cfg->channels, op_class, op_channel)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Frequency %u MHz (oper_class %u channel %u) not "
- "allowed for P2P", freq, op_class, op_channel);
+ p2p_dbg(p2p, "Frequency %u MHz (oper_class %u channel %u) not allowed for P2P",
+ freq, op_class, op_channel);
return -1;
}
@@ -1281,26 +1229,23 @@
if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
p2p_supported_freq(p2p, p2p->best_freq_overall) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
- &op_class, &op_channel) == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best "
- "overall channel as operating channel preference");
+ p2p_freq_to_channel(p2p->best_freq_overall, &op_class, &op_channel)
+ == 0) {
+ p2p_dbg(p2p, "Select best overall channel as operating channel preference");
p2p->op_reg_class = op_class;
p2p->op_channel = op_channel;
} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
p2p_supported_freq(p2p, p2p->best_freq_5) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
- &op_class, &op_channel) == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best 5 GHz "
- "channel as operating channel preference");
+ p2p_freq_to_channel(p2p->best_freq_5, &op_class, &op_channel)
+ == 0) {
+ p2p_dbg(p2p, "Select best 5 GHz channel as operating channel preference");
p2p->op_reg_class = op_class;
p2p->op_channel = op_channel;
} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_24 > 0 &&
p2p_supported_freq(p2p, p2p->best_freq_24) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
- &op_class, &op_channel) == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best 2.4 "
- "GHz channel as operating channel preference");
+ p2p_freq_to_channel(p2p->best_freq_24, &op_class,
+ &op_channel) == 0) {
+ p2p_dbg(p2p, "Select best 2.4 GHz channel as operating channel preference");
p2p->op_reg_class = op_class;
p2p->op_channel = op_channel;
} else {
@@ -1335,9 +1280,7 @@
} else {
p2p_prepare_channel_best(p2p);
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Own preference for operation channel: "
- "Operating Class %u Channel %u%s",
+ p2p_dbg(p2p, "Own preference for operation channel: Operating Class %u Channel %u%s",
p2p->op_reg_class, p2p->op_channel,
force_freq ? " (forced)" : "");
@@ -1379,8 +1322,7 @@
{
struct p2p_device *dev;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Request to start group negotiation - peer=" MACSTR
+ p2p_dbg(p2p, "Request to start group negotiation - peer=" MACSTR
" GO Intent=%d Intended Interface Address=" MACSTR
" wps_method=%d persistent_group=%d pd_before_go_neg=%d",
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
@@ -1388,8 +1330,7 @@
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cannot connect to unknown P2P Device " MACSTR,
+ p2p_dbg(p2p, "Cannot connect to unknown P2P Device " MACSTR,
MAC2STR(peer_addr));
return -1;
}
@@ -1400,15 +1341,13 @@
if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
if (!(dev->info.dev_capab &
P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cannot connect to P2P Device " MACSTR
+ p2p_dbg(p2p, "Cannot connect to P2P Device " MACSTR
" that is in a group and is not discoverable",
MAC2STR(peer_addr));
return -1;
}
if (dev->oper_freq <= 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cannot connect to P2P Device " MACSTR
+ p2p_dbg(p2p, "Cannot connect to P2P Device " MACSTR
" with incomplete information",
MAC2STR(peer_addr));
return -1;
@@ -1464,9 +1403,7 @@
* new GO Negotiation, e.g., when the pending frame was from a
* previous attempt at starting a GO Negotiation.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
- "previous pending Action frame TX that was waiting "
- "for p2p_scan completion");
+ p2p_dbg(p2p, "Dropped previous pending Action frame TX that was waiting for p2p_scan completion");
os_free(p2p->after_scan_tx);
p2p->after_scan_tx = NULL;
}
@@ -1475,8 +1412,7 @@
dev->status = P2P_SC_SUCCESS;
if (p2p->p2p_scan_running) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: p2p_scan running - delay connect send");
+ p2p_dbg(p2p, "p2p_scan running - delay connect send");
p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
return 0;
@@ -1496,8 +1432,7 @@
{
struct p2p_device *dev;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Request to authorize group negotiation - peer=" MACSTR
+ p2p_dbg(p2p, "Request to authorize group negotiation - peer=" MACSTR
" GO Intent=%d Intended Interface Address=" MACSTR
" wps_method=%d persistent_group=%d",
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
@@ -1505,8 +1440,7 @@
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cannot authorize unknown P2P Device " MACSTR,
+ p2p_dbg(p2p, "Cannot authorize unknown P2P Device " MACSTR,
MAC2STR(peer_addr));
return -1;
}
@@ -1543,16 +1477,14 @@
{
os_get_time(&dev->last_seen);
- p2p_copy_wps_info(dev, 0, msg);
+ p2p_copy_wps_info(p2p, dev, 0, msg);
if (msg->listen_channel) {
int freq;
- freq = p2p_channel_to_freq((char *) msg->listen_channel,
- msg->listen_channel[3],
+ freq = p2p_channel_to_freq(msg->listen_channel[3],
msg->listen_channel[4]);
if (freq < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown peer Listen channel: "
+ p2p_dbg(p2p, "Unknown peer Listen channel: "
"country=%c%c(0x%02x) reg_class=%u channel=%u",
msg->listen_channel[0],
msg->listen_channel[1],
@@ -1560,8 +1492,8 @@
msg->listen_channel[3],
msg->listen_channel[4]);
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update "
- "peer " MACSTR " Listen channel: %u -> %u MHz",
+ p2p_dbg(p2p, "Update peer " MACSTR
+ " Listen channel: %u -> %u MHz",
MAC2STR(dev->info.p2p_device_addr),
dev->listen_freq, freq);
dev->listen_freq = freq;
@@ -1575,12 +1507,9 @@
if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Completed device entry based on data from "
- "GO Negotiation Request");
+ p2p_dbg(p2p, "Completed device entry based on data from GO Negotiation Request");
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Created device entry based on GO Neg Req: "
+ p2p_dbg(p2p, "Created device entry based on GO Neg Req: "
MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
"listen_freq=%d",
MAC2STR(dev->info.p2p_device_addr),
@@ -1591,8 +1520,7 @@
dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
if (dev->flags & P2P_DEV_USER_REJECTED) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Do not report rejected device");
+ p2p_dbg(p2p, "Do not report rejected device");
return;
}
@@ -1628,10 +1556,8 @@
int freqs;
size_t i, j;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation with " MACSTR " completed (%s will be "
- "GO)", MAC2STR(peer->info.p2p_device_addr),
- go ? "local end" : "peer");
+ p2p_dbg(p2p, "GO Negotiation with " MACSTR " completed (%s will be GO)",
+ MAC2STR(peer->info.p2p_device_addr), go ? "local end" : "peer");
os_memset(&res, 0, sizeof(res));
res.role_go = go;
@@ -1647,8 +1573,7 @@
if (go) {
/* Setup AP mode for WPS provisioning */
- res.freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->op_reg_class,
+ res.freq = p2p_channel_to_freq(p2p->op_reg_class,
p2p->op_channel);
os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
res.ssid_len = p2p->ssid_len;
@@ -1672,8 +1597,7 @@
int freq;
if (freqs + 1 == P2P_MAX_CHANNELS)
break;
- freq = p2p_channel_to_freq(peer->country, c->reg_class,
- c->channel[j]);
+ freq = p2p_channel_to_freq(c->reg_class, c->channel[j]);
if (freq < 0)
continue;
res.freq_list[freqs++] = freq;
@@ -1695,8 +1619,7 @@
static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: RX P2P Public Action from " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "RX P2P Public Action from " MACSTR, MAC2STR(sa));
wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
if (len < 1)
@@ -1732,8 +1655,7 @@
p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
break;
default:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported P2P Public Action frame type %d",
+ p2p_dbg(p2p, "Unsupported P2P Public Action frame type %d",
data[0]);
break;
}
@@ -1808,16 +1730,14 @@
len--;
/* P2P action frame */
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: RX P2P Action from " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "RX P2P Action from " MACSTR, MAC2STR(sa));
wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
if (len < 1)
return;
switch (data[0]) {
case P2P_NOA:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received P2P Action - Notice of Absence");
+ p2p_dbg(p2p, "Received P2P Action - Notice of Absence");
/* TODO */
break;
case P2P_PRESENCE_REQ:
@@ -1830,8 +1750,7 @@
p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
break;
default:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received P2P Action - unknown type %u", data[0]);
+ p2p_dbg(p2p, "Received P2P Action - unknown type %u", data[0]);
break;
}
}
@@ -1903,12 +1822,11 @@
if (msg.listen_channel) {
os_memcpy(dev->country, msg.listen_channel, 3);
- dev->listen_freq = p2p_channel_to_freq(dev->country,
- msg.listen_channel[3],
+ dev->listen_freq = p2p_channel_to_freq(msg.listen_channel[3],
msg.listen_channel[4]);
}
- p2p_copy_wps_info(dev, 1, &msg);
+ p2p_copy_wps_info(p2p, dev, 1, &msg);
if (msg.wfd_subelems) {
wpabuf_free(dev->info.wfd_subelems);
@@ -1917,8 +1835,7 @@
p2p_parse_free(&msg);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Created device entry based on Probe Req: " MACSTR
+ p2p_dbg(p2p, "Created device entry based on Probe Req: " MACSTR
" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
dev->info.group_capab, dev->info.device_name,
@@ -2050,39 +1967,6 @@
}
-static int is_11b(u8 rate)
-{
- return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
-}
-
-
-static int supp_rates_11b_only(struct ieee802_11_elems *elems)
-{
- int num_11b = 0, num_others = 0;
- int i;
-
- if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
- return 0;
-
- for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
- if (is_11b(elems->supp_rates[i]))
- num_11b++;
- else
- num_others++;
- }
-
- for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
- i++) {
- if (is_11b(elems->ext_supp_rates[i]))
- num_11b++;
- else
- num_others++;
- }
-
- return num_11b > 0 && num_others == 0;
-}
-
-
static enum p2p_probe_req_status
p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
const u8 *bssid, const u8 *ie, size_t ie_len)
@@ -2160,8 +2044,7 @@
return P2P_PREQ_NOT_PROCESSED;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Reply to P2P Probe Request in Listen state");
+ p2p_dbg(p2p, "Reply to P2P Probe Request in Listen state");
/*
* We do not really have a specific BSS that this frame is advertising,
@@ -2240,9 +2123,7 @@
== 0 &&
!(p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
/* Received a Probe Request from GO Negotiation peer */
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Found GO Negotiation peer - try to start GO "
- "negotiation from timeout");
+ p2p_dbg(p2p, "Found GO Negotiation peer - try to start GO negotiation from timeout");
eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
return P2P_PREQ_PROCESSED;
@@ -2253,9 +2134,7 @@
os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
== 0) {
/* Received a Probe Request from Invite peer */
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Found Invite peer - try to start Invite from "
- "timeout");
+ p2p_dbg(p2p, "Found Invite peer - try to start Invite from timeout");
eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
return P2P_PREQ_PROCESSED;
}
@@ -2430,24 +2309,20 @@
void p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
{
if (p2p->go_neg_peer == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No pending Group Formation - "
- "ignore WPS registration success notification");
+ p2p_dbg(p2p, "No pending Group Formation - ignore WPS registration success notification");
return; /* No pending Group Formation */
}
if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore WPS registration success notification "
- "for " MACSTR " (GO Negotiation peer " MACSTR ")",
+ p2p_dbg(p2p, "Ignore WPS registration success notification for "
+ MACSTR " (GO Negotiation peer " MACSTR ")",
MAC2STR(mac_addr),
MAC2STR(p2p->go_neg_peer->intended_addr));
return; /* Ignore unexpected peer address */
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Group Formation completed successfully with " MACSTR,
+ p2p_dbg(p2p, "Group Formation completed successfully with " MACSTR,
MAC2STR(mac_addr));
p2p_clear_go_neg(p2p);
@@ -2457,14 +2332,11 @@
void p2p_group_formation_failed(struct p2p_data *p2p)
{
if (p2p->go_neg_peer == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No pending Group Formation - "
- "ignore group formation failure notification");
+ p2p_dbg(p2p, "No pending Group Formation - ignore group formation failure notification");
return; /* No pending Group Formation */
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Group Formation failed with " MACSTR,
+ p2p_dbg(p2p, "Group Formation failed with " MACSTR,
MAC2STR(p2p->go_neg_peer->intended_addr));
p2p_clear_go_neg(p2p);
@@ -2601,8 +2473,7 @@
if (dev == NULL)
return -1;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unauthorizing " MACSTR,
- MAC2STR(addr));
+ p2p_dbg(p2p, "Unauthorizing " MACSTR, MAC2STR(addr));
if (p2p->go_neg_peer == dev)
p2p->go_neg_peer = NULL;
@@ -2803,8 +2674,7 @@
break;
} else if (dev->req_config_methods &&
!(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
- "pending Provision Discovery Request to "
+ p2p_dbg(p2p, "Send pending Provision Discovery Request to "
MACSTR " (config methods 0x%x)",
MAC2STR(dev->info.p2p_device_addr),
dev->req_config_methods);
@@ -2819,8 +2689,7 @@
static void p2p_sd_cb(struct p2p_data *p2p, int success)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Service Discovery Query TX callback: success=%d",
+ p2p_dbg(p2p, "Service Discovery Query TX callback: success=%d",
success);
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
@@ -2834,8 +2703,7 @@
}
if (p2p->sd_peer == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No SD peer entry known");
+ p2p_dbg(p2p, "No SD peer entry known");
p2p_continue_find(p2p);
return;
}
@@ -2869,8 +2737,7 @@
if (!dev->req_config_methods)
continue;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
- "pending Provision Discovery Request to "
+ p2p_dbg(p2p, "Send pending Provision Discovery Request to "
MACSTR " (config methods 0x%x)",
MAC2STR(dev->info.p2p_device_addr),
dev->req_config_methods);
@@ -2883,8 +2750,7 @@
static void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Provision Discovery Request TX callback: success=%d",
+ p2p_dbg(p2p, "Provision Discovery Request TX callback: success=%d",
success);
/*
@@ -2951,8 +2817,8 @@
* that have based on frames received after the last p2p_find
* operation was started.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore old scan "
- "result for " MACSTR " (rx_time=%u.%06u)",
+ p2p_dbg(p2p, "Ignore old scan result for " MACSTR
+ " (rx_time=%u.%06u)",
MAC2STR(bssid), (unsigned int) rx_time->sec,
(unsigned int) rx_time->usec);
return 0;
@@ -2967,8 +2833,7 @@
void p2p_scan_res_handled(struct p2p_data *p2p)
{
if (!p2p->p2p_scan_running) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan was not "
- "running, but scan results received");
+ p2p_dbg(p2p, "p2p_scan was not running, but scan results received");
}
p2p->p2p_scan_running = 0;
eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
@@ -3030,13 +2895,10 @@
struct p2p_device *dev = p2p->go_neg_peer;
int timeout;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation Request TX callback: success=%d",
- success);
+ p2p_dbg(p2p, "GO Negotiation Request TX callback: success=%d", success);
if (dev == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No pending GO Negotiation");
+ p2p_dbg(p2p, "No pending GO Negotiation");
return;
}
@@ -3053,9 +2915,7 @@
if (!success &&
(dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
!is_zero_ether_addr(dev->member_in_go_dev)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Peer " MACSTR " did not acknowledge request - "
- "try to use device discoverability through its GO",
+ p2p_dbg(p2p, "Peer " MACSTR " did not acknowledge request - try to use device discoverability through its GO",
MAC2STR(dev->info.p2p_device_addr));
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
p2p_send_dev_disc_req(p2p, dev);
@@ -3086,13 +2946,10 @@
static void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation Response TX callback: success=%d",
+ p2p_dbg(p2p, "GO Negotiation Response TX callback: success=%d",
success);
if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore TX callback event - GO Negotiation is "
- "not running anymore");
+ p2p_dbg(p2p, "Ignore TX callback event - GO Negotiation is not running anymore");
return;
}
p2p_set_state(p2p, P2P_CONNECT);
@@ -3100,14 +2957,19 @@
}
-static void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success)
+static void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success,
+ const u8 *addr)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation Response (failure) TX callback: "
- "success=%d", success);
+ p2p_dbg(p2p, "GO Negotiation Response (failure) TX callback: success=%d", success);
if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
p2p_go_neg_failed(p2p, p2p->go_neg_peer,
p2p->go_neg_peer->status);
+ } else if (success) {
+ struct p2p_device *dev;
+ dev = p2p_get_device(p2p, addr);
+ if (dev &&
+ dev->status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
+ dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
}
}
@@ -3117,9 +2979,7 @@
{
struct p2p_device *dev;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation Confirm TX callback: result=%d",
- result);
+ p2p_dbg(p2p, "GO Negotiation Confirm TX callback: result=%d", result);
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
if (result == P2P_SEND_ACTION_FAILED) {
p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
@@ -3136,10 +2996,7 @@
* peer did indeed receive the frame, continue regardless of
* the TX status.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Assume GO Negotiation Confirm TX was actually "
- "received by the peer even though Ack was not "
- "reported");
+ p2p_dbg(p2p, "Assume GO Negotiation Confirm TX was actually received by the peer even though Ack was not reported");
}
dev = p2p->go_neg_peer;
@@ -3157,8 +3014,7 @@
enum p2p_pending_action_state state;
int success;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Action frame TX callback (state=%d freq=%u dst=" MACSTR
+ p2p_dbg(p2p, "Action frame TX callback (state=%d freq=%u dst=" MACSTR
" src=" MACSTR " bssid=" MACSTR " result=%d",
p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
MAC2STR(bssid), result);
@@ -3167,6 +3023,16 @@
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
switch (state) {
case P2P_NO_PENDING_ACTION:
+ if (p2p->after_scan_tx_in_progress) {
+ p2p->after_scan_tx_in_progress = 0;
+ if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
+ p2p_run_after_scan(p2p))
+ break;
+ if (p2p->state == P2P_SEARCH) {
+ p2p_dbg(p2p, "Continue find after after_scan_tx completion");
+ p2p_continue_find(p2p);
+ }
+ }
break;
case P2P_PENDING_GO_NEG_REQUEST:
p2p_go_neg_req_cb(p2p, success);
@@ -3175,7 +3041,7 @@
p2p_go_neg_resp_cb(p2p, success);
break;
case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
- p2p_go_neg_resp_failure_cb(p2p, success);
+ p2p_go_neg_resp_failure_cb(p2p, success, dst);
break;
case P2P_PENDING_GO_NEG_CONFIRM:
p2p_go_neg_conf_cb(p2p, result);
@@ -3202,6 +3068,8 @@
p2p_go_disc_req_cb(p2p, success);
break;
}
+
+ p2p->after_scan_tx_in_progress = 0;
}
@@ -3209,23 +3077,18 @@
unsigned int duration)
{
if (freq == p2p->pending_client_disc_freq) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Client discoverability remain-awake completed");
+ p2p_dbg(p2p, "Client discoverability remain-awake completed");
p2p->pending_client_disc_freq = 0;
return;
}
if (freq != p2p->pending_listen_freq) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected listen callback for freq=%u "
- "duration=%u (pending_listen_freq=%u)",
+ p2p_dbg(p2p, "Unexpected listen callback for freq=%u duration=%u (pending_listen_freq=%u)",
freq, duration, p2p->pending_listen_freq);
return;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Starting Listen timeout(%u,%u) on freq=%u based on "
- "callback",
+ p2p_dbg(p2p, "Starting Listen timeout(%u,%u) on freq=%u based on callback",
p2p->pending_listen_sec, p2p->pending_listen_usec,
p2p->pending_listen_freq);
p2p->in_listen = 1;
@@ -3246,17 +3109,14 @@
int p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver ended Listen "
- "state (freq=%u)", freq);
+ p2p_dbg(p2p, "Driver ended Listen state (freq=%u)", freq);
p2p->drv_in_listen = 0;
if (p2p->in_listen)
return 0; /* Internal timeout will trigger the next step */
if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
if (p2p->go_neg_peer->connect_reqs >= 120) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Timeout on sending GO Negotiation "
- "Request without getting response");
+ p2p_dbg(p2p, "Timeout on sending GO Negotiation Request without getting response");
p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
return 0;
}
@@ -3274,9 +3134,7 @@
* operation while in p2p_find. Avoid an attempt to
* restart a scan here.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan "
- "already in progress - do not try to start a "
- "new one");
+ p2p_dbg(p2p, "p2p_scan already in progress - do not try to start a new one");
return 1;
}
if (p2p->pending_listen_freq) {
@@ -3285,15 +3143,12 @@
* offchannel operation for some reason. p2p_search()
* will be started from internal timeout.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Listen "
- "operation did not seem to start - delay "
- "search phase to avoid busy loop");
+ p2p_dbg(p2p, "Listen operation did not seem to start - delay search phase to avoid busy loop");
p2p_set_timeout(p2p, 0, 100000);
return 1;
}
if (p2p->search_delay) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay "
- "search operation by %u ms",
+ p2p_dbg(p2p, "Delay search operation by %u ms",
p2p->search_delay);
p2p_set_timeout(p2p, p2p->search_delay / 1000,
(p2p->search_delay % 1000) * 1000);
@@ -3312,17 +3167,14 @@
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
if (p2p->go_neg_peer &&
(p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Wait for GO "
- "Negotiation Confirm timed out - assume GO "
- "Negotiation failed");
+ p2p_dbg(p2p, "Wait for GO Negotiation Confirm timed out - assume GO Negotiation failed");
p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
return;
}
if (p2p->go_neg_peer &&
(p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE) &&
p2p->go_neg_peer->connect_reqs < 120) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer expected to "
- "wait our response - skip listen");
+ p2p_dbg(p2p, "Peer expected to wait our response - skip listen");
p2p_connect_send(p2p, p2p->go_neg_peer);
return;
}
@@ -3336,16 +3188,12 @@
{
if (p2p->go_neg_peer) {
if (p2p->drv_in_listen) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is "
- "still in Listen state; wait for it to "
- "complete");
+ p2p_dbg(p2p, "Driver is still in Listen state; wait for it to complete");
return;
}
if (p2p->go_neg_peer->connect_reqs >= 120) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Timeout on sending GO Negotiation "
- "Request without getting response");
+ p2p_dbg(p2p, "Timeout on sending GO Negotiation Request without getting response");
p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
return;
}
@@ -3374,23 +3222,18 @@
struct p2p_device *dev = p2p->go_neg_peer;
if (dev == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown GO Neg peer - stop GO Neg wait");
+ p2p_dbg(p2p, "Unknown GO Neg peer - stop GO Neg wait");
return;
}
dev->wait_count++;
if (dev->wait_count >= 120) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Timeout on waiting peer to become ready for GO "
- "Negotiation");
+ p2p_dbg(p2p, "Timeout on waiting peer to become ready for GO Negotiation");
p2p_go_neg_failed(p2p, dev, -1);
return;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Go to Listen state while waiting for the peer to become "
- "ready for GO Negotiation");
+ p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation");
p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
p2p_listen_in_find(p2p, 0);
}
@@ -3398,8 +3241,7 @@
static void p2p_timeout_sd_during_find(struct p2p_data *p2p)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Service Discovery Query timeout");
+ p2p_dbg(p2p, "Service Discovery Query timeout");
if (p2p->sd_peer) {
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
@@ -3411,8 +3253,7 @@
static void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Provision Discovery Request timeout");
+ p2p_dbg(p2p, "Provision Discovery Request timeout");
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
p2p_continue_find(p2p);
}
@@ -3430,8 +3271,7 @@
if (!p2p->user_initiated_pd)
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: User initiated Provision Discovery Request timeout");
+ p2p_dbg(p2p, "User initiated Provision Discovery Request timeout");
if (p2p->pd_retries) {
p2p->pd_retries--;
@@ -3469,8 +3309,7 @@
* Better remain on operating channel instead of listen channel
* when running a group.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Inviting in "
- "active GO role - wait on operating channel");
+ p2p_dbg(p2p, "Inviting in active GO role - wait on operating channel");
p2p_set_timeout(p2p, 0, 100000);
return;
}
@@ -3486,8 +3325,7 @@
p2p->invite_go_dev_addr);
} else {
if (p2p->invite_peer) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invitation Request retry limit reached");
+ p2p_dbg(p2p, "Invitation Request retry limit reached");
if (p2p->cfg->invitation_result)
p2p->cfg->invitation_result(
p2p->cfg->cb_ctx, -1, NULL, NULL,
@@ -3502,8 +3340,7 @@
{
struct p2p_data *p2p = eloop_ctx;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Timeout (state=%s)",
- p2p_state_txt(p2p->state));
+ p2p_dbg(p2p, "Timeout (state=%s)", p2p_state_txt(p2p->state));
p2p->in_listen = 0;
@@ -3518,8 +3355,7 @@
if (p2p->pending_action_state == P2P_PENDING_PD)
p2p_timeout_prov_disc_req(p2p);
if (p2p->search_delay && !p2p->in_search_delay) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay "
- "search operation by %u ms",
+ p2p_dbg(p2p, "Delay search operation by %u ms",
p2p->search_delay);
p2p->in_search_delay = 1;
p2p_set_timeout(p2p, p2p->search_delay / 1000,
@@ -3543,9 +3379,7 @@
p2p_timeout_prov_disc_req(p2p);
if (p2p->ext_listen_only) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Extended Listen Timing - Listen State "
- "completed");
+ p2p_dbg(p2p, "Extended Listen Timing - Listen State completed");
p2p->ext_listen_only = 0;
p2p_set_state(p2p, P2P_IDLE);
}
@@ -3583,11 +3417,10 @@
struct p2p_device *dev;
dev = p2p_get_device(p2p, peer_addr);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Local request to reject "
- "connection attempts by peer " MACSTR, MAC2STR(peer_addr));
+ p2p_dbg(p2p, "Local request to reject connection attempts by peer "
+ MACSTR, MAC2STR(peer_addr));
if (dev == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
- " unknown", MAC2STR(peer_addr));
+ p2p_dbg(p2p, "Peer " MACSTR " unknown", MAC2STR(peer_addr));
return -1;
}
dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
@@ -3788,12 +3621,10 @@
void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
{
if (enabled) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
- "discoverability enabled");
+ p2p_dbg(p2p, "Client discoverability enabled");
p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
- "discoverability disabled");
+ p2p_dbg(p2p, "Client discoverability disabled");
p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
}
}
@@ -3842,9 +3673,9 @@
{
struct wpabuf *req;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send Presence Request to "
- "GO " MACSTR " (own interface " MACSTR ") freq=%u dur1=%u "
- "int1=%u dur2=%u int2=%u",
+ p2p_dbg(p2p, "Send Presence Request to GO " MACSTR
+ " (own interface " MACSTR ") freq=%u dur1=%u int1=%u "
+ "dur2=%u int2=%u",
MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
freq, duration1, interval1, duration2, interval2);
@@ -3857,8 +3688,7 @@
if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
go_interface_addr,
wpabuf_head(req), wpabuf_len(req), 200) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
}
wpabuf_free(req);
@@ -3904,8 +3734,7 @@
u8 noa[50];
int noa_len;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received P2P Action - P2P Presence Request");
+ p2p_dbg(p2p, "Received P2P Action - P2P Presence Request");
for (g = 0; g < p2p->num_groups; g++) {
if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
@@ -3915,23 +3744,20 @@
}
}
if (group == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore P2P Presence Request for unknown group "
+ p2p_dbg(p2p, "Ignore P2P Presence Request for unknown group "
MACSTR, MAC2STR(da));
return;
}
if (p2p_parse(data, len, &msg) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to parse P2P Presence Request");
+ p2p_dbg(p2p, "Failed to parse P2P Presence Request");
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
parsed = 1;
if (msg.noa == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No NoA attribute in P2P Presence Request");
+ p2p_dbg(p2p, "No NoA attribute in P2P Presence Request");
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
@@ -3955,8 +3781,7 @@
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
if (p2p_send_action(p2p, rx_freq, sa, da, da,
wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
}
wpabuf_free(resp);
}
@@ -3967,33 +3792,27 @@
{
struct p2p_message msg;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received P2P Action - P2P Presence Response");
+ p2p_dbg(p2p, "Received P2P Action - P2P Presence Response");
if (p2p_parse(data, len, &msg) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to parse P2P Presence Response");
+ p2p_dbg(p2p, "Failed to parse P2P Presence Response");
return;
}
if (msg.status == NULL || msg.noa == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Status or NoA attribute in P2P Presence "
- "Response");
+ p2p_dbg(p2p, "No Status or NoA attribute in P2P Presence Response");
p2p_parse_free(&msg);
return;
}
if (*msg.status) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: P2P Presence Request was rejected: status %u",
+ p2p_dbg(p2p, "P2P Presence Request was rejected: status %u",
*msg.status);
p2p_parse_free(&msg);
return;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: P2P Presence Request was accepted");
+ p2p_dbg(p2p, "P2P Presence Request was accepted");
wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
msg.noa, msg.noa_len);
/* TODO: process NoA */
@@ -4019,25 +3838,20 @@
* running at an inconvenient time. As a workaround, allow new
* Extended Listen operation to be started.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Previous "
- "Extended Listen operation had not been completed - "
- "try again");
+ p2p_dbg(p2p, "Previous Extended Listen operation had not been completed - try again");
p2p->ext_listen_only = 0;
p2p_set_state(p2p, P2P_IDLE);
}
if (p2p->state != P2P_IDLE) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip Extended "
- "Listen timeout in active state (%s)",
- p2p_state_txt(p2p->state));
+ p2p_dbg(p2p, "Skip Extended Listen timeout in active state (%s)", p2p_state_txt(p2p->state));
return;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Extended Listen timeout");
+ p2p_dbg(p2p, "Extended Listen timeout");
p2p->ext_listen_only = 1;
if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
- "Listen state for Extended Listen Timing");
+ p2p_dbg(p2p, "Failed to start Listen state for Extended Listen Timing");
p2p->ext_listen_only = 0;
}
}
@@ -4048,25 +3862,22 @@
{
if (period > 65535 || interval > 65535 || period > interval ||
(period == 0 && interval > 0) || (period > 0 && interval == 0)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid Extended Listen Timing request: "
- "period=%u interval=%u", period, interval);
+ p2p_dbg(p2p, "Invalid Extended Listen Timing request: period=%u interval=%u",
+ period, interval);
return -1;
}
eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
if (interval == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Disabling Extended Listen Timing");
+ p2p_dbg(p2p, "Disabling Extended Listen Timing");
p2p->ext_listen_period = 0;
p2p->ext_listen_interval = 0;
return 0;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Enabling Extended Listen Timing: period %u msec, "
- "interval %u msec", period, interval);
+ p2p_dbg(p2p, "Enabling Extended Listen Timing: period %u msec, interval %u msec",
+ period, interval);
p2p->ext_listen_period = period;
p2p->ext_listen_interval = interval;
p2p->ext_listen_interval_sec = interval / 1000;
@@ -4094,8 +3905,7 @@
if (msg.minor_reason_code == NULL)
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
- "P2P: Deauthentication notification BSSID " MACSTR
+ p2p_dbg(p2p, "Deauthentication notification BSSID " MACSTR
" reason_code=%u minor_reason_code=%u",
MAC2STR(bssid), reason_code, *msg.minor_reason_code);
@@ -4117,8 +3927,7 @@
if (msg.minor_reason_code == NULL)
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
- "P2P: Disassociation notification BSSID " MACSTR
+ p2p_dbg(p2p, "Disassociation notification BSSID " MACSTR
" reason_code=%u minor_reason_code=%u",
MAC2STR(bssid), reason_code, *msg.minor_reason_code);
@@ -4129,12 +3938,10 @@
void p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
{
if (enabled) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
- "Device operations enabled");
+ p2p_dbg(p2p, "Managed P2P Device operations enabled");
p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
- "Device operations disabled");
+ p2p_dbg(p2p, "Managed P2P Device operations disabled");
p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
}
}
@@ -4142,11 +3949,11 @@
int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
{
- if (p2p_channel_to_freq(p2p->cfg->country, reg_class, channel) < 0)
+ if (p2p_channel_to_freq(reg_class, channel) < 0)
return -1;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set Listen channel: "
- "reg_class %u channel %u", reg_class, channel);
+ p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
+ reg_class, channel);
p2p->cfg->reg_class = reg_class;
p2p->cfg->channel = channel;
@@ -4156,7 +3963,7 @@
int p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
{
- wpa_hexdump_ascii(MSG_DEBUG, "P2P: New SSID postfix", postfix, len);
+ p2p_dbg(p2p, "New SSID postfix: %s", wpa_ssid_txt(postfix, len));
if (postfix == NULL) {
p2p->cfg->ssid_postfix_len = 0;
return 0;
@@ -4172,12 +3979,11 @@
int p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
int cfg_op_channel)
{
- if (p2p_channel_to_freq(p2p->cfg->country, op_reg_class, op_channel)
- < 0)
+ if (p2p_channel_to_freq(op_reg_class, op_channel) < 0)
return -1;
- wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, "P2P: Set Operating channel: "
- "reg_class %u channel %u", op_reg_class, op_channel);
+ p2p_dbg(p2p, "Set Operating channel: reg_class %u channel %u",
+ op_reg_class, op_channel);
p2p->cfg->op_reg_class = op_reg_class;
p2p->cfg->op_channel = op_channel;
p2p->cfg->cfg_op_channel = cfg_op_channel;
@@ -4233,18 +4039,16 @@
{
os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
if (is_zero_ether_addr(p2p->peer_filter))
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Disable peer "
- "filter");
+ p2p_dbg(p2p, "Disable peer filter");
else
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer "
- "filter for " MACSTR, MAC2STR(p2p->peer_filter));
+ p2p_dbg(p2p, "Enable peer filter for " MACSTR,
+ MAC2STR(p2p->peer_filter));
}
void p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Cross connection %s",
- enabled ? "enabled" : "disabled");
+ p2p_dbg(p2p, "Cross connection %s", enabled ? "enabled" : "disabled");
if (p2p->cross_connect == enabled)
return;
p2p->cross_connect = enabled;
@@ -4265,7 +4069,7 @@
void p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Intra BSS distribution %s",
+ p2p_dbg(p2p, "Intra BSS distribution %s",
enabled ? "enabled" : "disabled");
p2p->cfg->p2p_intra_bss = enabled;
}
@@ -4273,7 +4077,7 @@
void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update channel list");
+ p2p_dbg(p2p, "Update channel list");
os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
}
@@ -4283,11 +4087,9 @@
size_t len, unsigned int wait_time)
{
if (p2p->p2p_scan_running) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay Action "
- "frame TX until p2p_scan completes");
+ p2p_dbg(p2p, "Delay Action frame TX until p2p_scan completes");
if (p2p->after_scan_tx) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
- "previous pending Action frame TX");
+ p2p_dbg(p2p, "Dropped previous pending Action frame TX");
os_free(p2p->after_scan_tx);
}
p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
@@ -4312,8 +4114,8 @@
void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
int freq_overall)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Best channel: 2.4 GHz: %d,"
- " 5 GHz: %d, overall: %d", freq_24, freq_5, freq_overall);
+ p2p_dbg(p2p, "Best channel: 2.4 GHz: %d, 5 GHz: %d, overall: %d",
+ freq_24, freq_5, freq_overall);
p2p->best_freq_24 = freq_24;
p2p->best_freq_5 = freq_5;
p2p->best_freq_overall = freq_overall;
@@ -4322,8 +4124,7 @@
void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own frequency preference: "
- "%d MHz", freq);
+ p2p_dbg(p2p, "Own frequency preference: %d MHz", freq);
p2p->own_freq_preference = freq;
}
@@ -4548,9 +4349,56 @@
p2p->min_disc_int = min_disc_int;
p2p->max_disc_int = max_disc_int;
p2p->max_disc_tu = max_disc_tu;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set discoverable interval: "
- "min=%d max=%d max_tu=%d", min_disc_int, max_disc_int,
- max_disc_tu);
+ p2p_dbg(p2p, "Set discoverable interval: min=%d max=%d max_tu=%d",
+ min_disc_int, max_disc_int, max_disc_tu);
return 0;
}
+
+
+void p2p_dbg(struct p2p_data *p2p, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[500];
+
+ if (!p2p->cfg->debug_print)
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ buf[sizeof(buf) - 1] = '\0';
+ va_end(ap);
+ p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_DEBUG, buf);
+}
+
+
+void p2p_info(struct p2p_data *p2p, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[500];
+
+ if (!p2p->cfg->debug_print)
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ buf[sizeof(buf) - 1] = '\0';
+ va_end(ap);
+ p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_INFO, buf);
+}
+
+
+void p2p_err(struct p2p_data *p2p, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[500];
+
+ if (!p2p->cfg->debug_print)
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ buf[sizeof(buf) - 1] = '\0';
+ va_end(ap);
+ p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_ERROR, buf);
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 28a0a1d..c392d57 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -384,15 +384,18 @@
#endif
/**
- * msg_ctx - Context to use with wpa_msg() calls
- */
- void *msg_ctx;
-
- /**
* cb_ctx - Context to use with callback functions
*/
void *cb_ctx;
+ /**
+ * debug_print - Debug print
+ * @ctx: Callback context from cb_ctx
+ * @level: Debug verbosity level (MSG_*)
+ * @msg: Debug message
+ */
+ void (*debug_print)(void *ctx, int level, const char *msg);
+
/* Callbacks to request lower layer driver operations */
@@ -558,6 +561,12 @@
void (*dev_lost)(void *ctx, const u8 *dev_addr);
/**
+ * find_stopped - Notification of a p2p_find operation stopping
+ * @ctx: Callback context from cb_ctx
+ */
+ void (*find_stopped)(void *ctx);
+
+ /**
* go_neg_req_rx - Notification of a receive GO Negotiation Request
* @ctx: Callback context from cb_ctx
* @src: Source address of the message triggering this notification
@@ -693,6 +702,7 @@
* @persistent_group: Whether this is an invitation to reinvoke a
* persistent group (instead of invitation to join an active
* group)
+ * @channels: Available operating channels for the group
* Returns: Status code (P2P_SC_*)
*
* This optional callback can be used to implement persistent reconnect
@@ -713,7 +723,8 @@
u8 (*invitation_process)(void *ctx, const u8 *sa, const u8 *bssid,
const u8 *go_dev_addr, const u8 *ssid,
size_t ssid_len, int *go, u8 *group_bssid,
- int *force_freq, int persistent_group);
+ int *force_freq, int persistent_group,
+ const struct p2p_channels *channels);
/**
* invitation_received - Callback on Invitation Request RX
@@ -1648,6 +1659,15 @@
*/
int p2p_supported_freq(struct p2p_data *p2p, unsigned int freq);
+/**
+ * p2p_get_pref_freq - Get channel from preferred channel list
+ * @p2p: P2P module context from p2p_init()
+ * @channels: List of channels
+ * Returns: Preferred channel
+ */
+unsigned int p2p_get_pref_freq(struct p2p_data *p2p,
+ const struct p2p_channels *channels);
+
void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan);
/**
diff --git a/src/p2p/p2p_dev_disc.c b/src/p2p/p2p_dev_disc.c
index c976b7c..76d01cf 100644
--- a/src/p2p/p2p_dev_disc.c
+++ b/src/p2p/p2p_dev_disc.c
@@ -42,8 +42,7 @@
void p2p_dev_disc_req_cb(struct p2p_data *p2p, int success)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Device Discoverability Request TX callback: success=%d",
+ p2p_dbg(p2p, "Device Discoverability Request TX callback: success=%d",
success);
if (!success) {
@@ -56,9 +55,7 @@
return;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO acknowledged Device Discoverability Request - wait "
- "for response");
+ p2p_dbg(p2p, "GO acknowledged Device Discoverability Request - wait for response");
/*
* TODO: is the remain-on-channel from Action frame TX long enough for
* most cases or should we try to increase its duration and/or start
@@ -74,9 +71,7 @@
go = p2p_get_device(p2p, dev->member_in_go_dev);
if (go == NULL || dev->oper_freq <= 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Could not find peer entry for GO and frequency "
- "to send Device Discoverability Request");
+ p2p_dbg(p2p, "Could not find peer entry for GO and frequency to send Device Discoverability Request");
return -1;
}
@@ -84,8 +79,7 @@
if (req == NULL)
return -1;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Sending Device Discoverability Request to GO " MACSTR
+ p2p_dbg(p2p, "Sending Device Discoverability Request to GO " MACSTR
" for client " MACSTR,
MAC2STR(go->info.p2p_device_addr),
MAC2STR(dev->info.p2p_device_addr));
@@ -97,8 +91,7 @@
if (p2p_send_action(p2p, dev->oper_freq, go->info.p2p_device_addr,
p2p->cfg->dev_addr, go->info.p2p_device_addr,
wpabuf_head(req), wpabuf_len(req), 1000) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
wpabuf_free(req);
/* TODO: how to recover from failure? */
return -1;
@@ -131,8 +124,7 @@
void p2p_dev_disc_resp_cb(struct p2p_data *p2p, int success)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Device Discoverability Response TX callback: success=%d",
+ p2p_dbg(p2p, "Device Discoverability Response TX callback: success=%d",
success);
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
}
@@ -147,8 +139,7 @@
if (resp == NULL)
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Sending Device Discoverability Response to " MACSTR
+ p2p_dbg(p2p, "Sending Device Discoverability Response to " MACSTR
" (status %u freq %d)",
MAC2STR(addr), status, freq);
@@ -156,8 +147,7 @@
if (p2p_send_action(p2p, freq, addr, p2p->cfg->dev_addr,
p2p->cfg->dev_addr,
wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
}
wpabuf_free(resp);
@@ -170,17 +160,14 @@
struct p2p_message msg;
size_t g;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received Device Discoverability Request from " MACSTR
+ p2p_dbg(p2p, "Received Device Discoverability Request from " MACSTR
" (freq=%d)", MAC2STR(sa), rx_freq);
if (p2p_parse(data, len, &msg))
return;
if (msg.dialog_token == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid Dialog Token 0 (must be nonzero) in "
- "Device Discoverability Request");
+ p2p_dbg(p2p, "Invalid Dialog Token 0 (must be nonzero) in Device Discoverability Request");
p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq,
P2P_SC_FAIL_INVALID_PARAMS);
p2p_parse_free(&msg);
@@ -188,9 +175,7 @@
}
if (msg.device_id == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: P2P Device ID attribute missing from Device "
- "Discoverability Request");
+ p2p_dbg(p2p, "P2P Device ID attribute missing from Device Discoverability Request");
p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq,
P2P_SC_FAIL_INVALID_PARAMS);
p2p_parse_free(&msg);
@@ -200,9 +185,7 @@
for (g = 0; g < p2p->num_groups; g++) {
if (p2p_group_go_discover(p2p->groups[g], msg.device_id, sa,
rx_freq) == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Scheduled "
- "GO Discoverability Request for the target "
- "device");
+ p2p_dbg(p2p, "Scheduled GO Discoverability Request for the target device");
/*
* P2P group code will use a callback to indicate TX
* status, so that we can reply to the request once the
@@ -217,9 +200,7 @@
}
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Requested client "
- "was not found in any group or did not support client "
- "discoverability");
+ p2p_dbg(p2p, "Requested client was not found in any group or did not support client discoverability");
p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq,
P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE);
p2p_parse_free(&msg);
@@ -233,15 +214,13 @@
struct p2p_device *go;
u8 status;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received Device Discoverability Response from " MACSTR,
+ p2p_dbg(p2p, "Received Device Discoverability Response from " MACSTR,
MAC2STR(sa));
go = p2p->pending_client_disc_go;
if (go == NULL ||
os_memcmp(sa, go->info.p2p_device_addr, ETH_ALEN) != 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore unexpected "
- "Device Discoverability Response");
+ p2p_dbg(p2p, "Ignore unexpected Device Discoverability Response");
return;
}
@@ -254,9 +233,7 @@
}
if (msg.dialog_token != go->dialog_token) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore Device "
- "Discoverability Response with unexpected dialog "
- "token %u (expected %u)",
+ p2p_dbg(p2p, "Ignore Device Discoverability Response with unexpected dialog token %u (expected %u)",
msg.dialog_token, go->dialog_token);
p2p_parse_free(&msg);
return;
@@ -265,17 +242,14 @@
status = *msg.status;
p2p_parse_free(&msg);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Device Discoverability Response status %u", status);
+ p2p_dbg(p2p, "Device Discoverability Response status %u", status);
if (p2p->go_neg_peer == NULL ||
os_memcmp(p2p->pending_client_disc_addr,
p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN) != 0 ||
os_memcmp(p2p->go_neg_peer->member_in_go_dev,
go->info.p2p_device_addr, ETH_ALEN) != 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending "
- "operation with the client discoverability peer "
- "anymore");
+ p2p_dbg(p2p, "No pending operation with the client discoverability peer anymore");
return;
}
@@ -284,8 +258,7 @@
* Peer is expected to be awake for at least 100 TU; try to
* connect immediately.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Client discoverability request succeeded");
+ p2p_dbg(p2p, "Client discoverability request succeeded");
if (p2p->state == P2P_CONNECT) {
/*
* Change state to force the timeout to start in
@@ -301,8 +274,7 @@
* Client discoverability request failed; try to connect from
* timeout.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Client discoverability request failed");
+ p2p_dbg(p2p, "Client discoverability request failed");
p2p_set_timeout(p2p, 0, 500000);
}
@@ -311,14 +283,12 @@
void p2p_go_disc_req_cb(struct p2p_data *p2p, int success)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Discoverability Request TX callback: success=%d",
+ p2p_dbg(p2p, "GO Discoverability Request TX callback: success=%d",
success);
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
if (p2p->pending_dev_disc_dialog_token == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending Device "
- "Discoverability Request");
+ p2p_dbg(p2p, "No pending Device Discoverability Request");
return;
}
@@ -338,9 +308,7 @@
unsigned int tu;
struct wpabuf *ies;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received GO Discoverability Request - remain awake for "
- "100 TU");
+ p2p_dbg(p2p, "Received GO Discoverability Request - remain awake for 100 TU");
ies = p2p_build_probe_resp_ies(p2p);
if (ies == NULL)
@@ -351,9 +319,7 @@
tu = 100;
if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, rx_freq, 1024 * tu / 1000,
ies) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to start listen mode for client "
- "discoverability");
+ p2p_dbg(p2p, "Failed to start listen mode for client discoverability");
}
wpabuf_free(ies);
}
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index c143ef4..4fba550 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -49,8 +49,7 @@
os_memcpy(dev->country, pos, 3);
wpa_hexdump_ascii(MSG_DEBUG, "P2P: Peer country", pos, 3);
if (pos[2] != 0x04 && os_memcmp(pos, p2p->cfg->country, 2) != 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
- "P2P: Mismatching country (ours=%c%c peer's=%c%c)",
+ p2p_info(p2p, "Mismatching country (ours=%c%c peer's=%c%c)",
p2p->cfg->country[0], p2p->cfg->country[1],
pos[0], pos[1]);
return -1;
@@ -61,8 +60,7 @@
struct p2p_reg_class *cl = &ch->reg_class[ch->reg_classes];
cl->reg_class = *pos++;
if (pos + 1 + pos[0] > end) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
- "P2P: Invalid peer Channel List");
+ p2p_info(p2p, "Invalid peer Channel List");
return -1;
}
channels = *pos++;
@@ -76,14 +74,12 @@
}
p2p_channels_intersect(own, &dev->channels, &intersection);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own reg_classes %d "
- "peer reg_classes %d intersection reg_classes %d",
+ p2p_dbg(p2p, "Own reg_classes %d peer reg_classes %d intersection reg_classes %d",
(int) own->reg_classes,
(int) dev->channels.reg_classes,
(int) intersection.reg_classes);
if (intersection.reg_classes == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
- "P2P: No common channels found");
+ p2p_info(p2p, "No common channels found");
return -1;
}
return 0;
@@ -194,8 +190,7 @@
if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
u16 config_method;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Use PD-before-GO-Neg workaround for " MACSTR,
+ p2p_dbg(p2p, "Use PD-before-GO-Neg workaround for " MACSTR,
MAC2STR(dev->info.p2p_device_addr));
if (dev->wps_method == WPS_PIN_DISPLAY)
config_method = WPS_CONFIG_KEYPAD;
@@ -211,9 +206,8 @@
freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
if (freq <= 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Listen/Operating frequency known for the "
- "peer " MACSTR " to send GO Negotiation Request",
+ p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
+ MACSTR " to send GO Negotiation Request",
MAC2STR(dev->info.p2p_device_addr));
return -1;
}
@@ -221,8 +215,7 @@
req = p2p_build_go_neg_req(p2p, dev);
if (req == NULL)
return -1;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Sending GO Negotiation Request");
+ p2p_dbg(p2p, "Sending GO Negotiation Request");
p2p_set_state(p2p, P2P_CONNECT);
p2p->pending_action_state = P2P_PENDING_GO_NEG_REQUEST;
p2p->go_neg_peer = dev;
@@ -231,8 +224,7 @@
if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
p2p->cfg->dev_addr, dev->info.p2p_device_addr,
wpabuf_head(req), wpabuf_len(req), 500) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
/* Use P2P find to recover and retry */
p2p_set_timeout(p2p, 0, 0);
} else
@@ -254,8 +246,7 @@
u8 group_capab;
size_t extra = 0;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Building GO Negotiation Response");
+ p2p_dbg(p2p, "Building GO Negotiation Response");
#ifdef CONFIG_WIFI_DISPLAY
if (p2p->wfd_ie_go_neg)
@@ -289,8 +280,7 @@
p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker);
p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout);
if (peer && peer->go_state == REMOTE_GO) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Omit Operating "
- "Channel attribute");
+ p2p_dbg(p2p, "Omit Operating Channel attribute");
} else {
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
p2p->op_reg_class,
@@ -351,23 +341,21 @@
unsigned int i;
if (p2p->own_freq_preference > 0 &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->own_freq_preference,
+ p2p_freq_to_channel(p2p->own_freq_preference,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick own channel "
- "preference (reg_class %u channel %u) from "
- "intersection", op_reg_class, op_channel);
+ p2p_dbg(p2p, "Pick own channel preference (reg_class %u channel %u) from intersection",
+ op_reg_class, op_channel);
p2p->op_reg_class = op_reg_class;
p2p->op_channel = op_channel;
return;
}
if (p2p->best_freq_overall > 0 &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
+ p2p_freq_to_channel(p2p->best_freq_overall,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best overall "
- "channel (reg_class %u channel %u) from intersection",
+ p2p_dbg(p2p, "Pick best overall channel (reg_class %u channel %u) from intersection",
op_reg_class, op_channel);
p2p->op_reg_class = op_reg_class;
p2p->op_channel = op_channel;
@@ -375,16 +363,14 @@
}
/* First, try to pick the best channel from another band */
- freq = p2p_channel_to_freq(p2p->cfg->country, p2p->op_reg_class,
- p2p->op_channel);
+ freq = p2p_channel_to_freq(p2p->op_reg_class, p2p->op_channel);
if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 &&
!p2p_channels_includes(intersection, p2p->op_reg_class,
p2p->op_channel) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
+ p2p_freq_to_channel(p2p->best_freq_5,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 5 GHz "
- "channel (reg_class %u channel %u) from intersection",
+ p2p_dbg(p2p, "Pick best 5 GHz channel (reg_class %u channel %u) from intersection",
op_reg_class, op_channel);
p2p->op_reg_class = op_reg_class;
p2p->op_channel = op_channel;
@@ -394,11 +380,10 @@
if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 &&
!p2p_channels_includes(intersection, p2p->op_reg_class,
p2p->op_channel) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
+ p2p_freq_to_channel(p2p->best_freq_24,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 2.4 GHz "
- "channel (reg_class %u channel %u) from intersection",
+ p2p_dbg(p2p, "Pick best 2.4 GHz channel (reg_class %u channel %u) from intersection",
op_reg_class, op_channel);
p2p->op_reg_class = op_reg_class;
p2p->op_channel = op_channel;
@@ -412,9 +397,7 @@
p2p->cfg->pref_chan[i].chan)) {
p2p->op_reg_class = p2p->cfg->pref_chan[i].op_class;
p2p->op_channel = p2p->cfg->pref_chan[i].chan;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick "
- "highest preferred chnnel (op_class %u "
- "channel %u) from intersection",
+ p2p_dbg(p2p, "Pick highest preferred channel (op_class %u channel %u) from intersection",
p2p->op_reg_class, p2p->op_channel);
return;
}
@@ -425,9 +408,7 @@
struct p2p_reg_class *c = &intersection->reg_class[i];
if (c->reg_class == 116 || c->reg_class == 117 ||
c->reg_class == 126 || c->reg_class == 127) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Pick possible HT40 channel (reg_class "
- "%u channel %u) from intersection",
+ p2p_dbg(p2p, "Pick possible HT40 channel (reg_class %u channel %u) from intersection",
c->reg_class, c->channel[0]);
p2p->op_reg_class = c->reg_class;
p2p->op_channel = c->channel[0];
@@ -442,9 +423,7 @@
*/
if (p2p_channels_includes(intersection, p2p->op_reg_class,
p2p->op_channel)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Using original operating class and channel "
- "(op_class %u channel %u) from intersection",
+ p2p_dbg(p2p, "Using original operating class and channel (op_class %u channel %u) from intersection",
p2p->op_reg_class, p2p->op_channel);
return;
}
@@ -454,8 +433,7 @@
* no better options seems to be available.
*/
cl = &intersection->reg_class[0];
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick another channel "
- "(reg_class %u channel %u) from intersection",
+ p2p_dbg(p2p, "Pick another channel (reg_class %u channel %u) from intersection",
cl->reg_class, cl->channel[0]);
p2p->op_reg_class = cl->reg_class;
p2p->op_channel = cl->channel[0];
@@ -472,15 +450,14 @@
if (intersection.reg_classes == 0 ||
intersection.reg_class[0].channels == 0) {
*status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No common channels found");
+ p2p_dbg(p2p, "No common channels found");
return -1;
}
for (i = 0; i < intersection.reg_classes; i++) {
struct p2p_reg_class *c;
c = &intersection.reg_class[i];
- wpa_printf(MSG_DEBUG, "P2P: reg_class %u", c->reg_class);
+ p2p_dbg(p2p, "reg_class %u", c->reg_class);
wpa_hexdump(MSG_DEBUG, "P2P: channels",
c->channel, c->channels);
}
@@ -489,20 +466,16 @@
p2p->op_channel)) {
if (dev->flags & P2P_DEV_FORCE_FREQ) {
*status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer does "
- "not support the forced channel");
+ p2p_dbg(p2p, "Peer does not support the forced channel");
return -1;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
- "channel (op_class %u channel %u) not acceptable to "
- "the peer", p2p->op_reg_class, p2p->op_channel);
+ p2p_dbg(p2p, "Selected operating channel (op_class %u channel %u) not acceptable to the peer",
+ p2p->op_reg_class, p2p->op_channel);
p2p_reselect_channel(p2p, &intersection);
} else if (!(dev->flags & P2P_DEV_FORCE_FREQ) &&
!p2p->cfg->cfg_op_channel) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Try to optimize "
- "channel selection with peer information received; "
- "previously selected op_class %u channel %u",
+ p2p_dbg(p2p, "Try to optimize channel selection with peer information received; previously selected op_class %u channel %u",
p2p->op_reg_class, p2p->op_channel);
p2p_reselect_channel(p2p, &intersection);
}
@@ -526,17 +499,14 @@
int tie_breaker = 0;
int freq;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received GO Negotiation Request from " MACSTR
- "(freq=%d)", MAC2STR(sa), rx_freq);
+ p2p_dbg(p2p, "Received GO Negotiation Request from " MACSTR "(freq=%d)",
+ MAC2STR(sa), rx_freq);
if (p2p_parse(data, len, &msg))
return;
if (!msg.capability) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory Capability attribute missing from GO "
- "Negotiation Request");
+ p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Request");
#ifdef CONFIG_P2P_STRICT
goto fail;
#endif /* CONFIG_P2P_STRICT */
@@ -545,53 +515,42 @@
if (msg.go_intent)
tie_breaker = *msg.go_intent & 0x01;
else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory GO Intent attribute missing from GO "
- "Negotiation Request");
+ p2p_dbg(p2p, "Mandatory GO Intent attribute missing from GO Negotiation Request");
#ifdef CONFIG_P2P_STRICT
goto fail;
#endif /* CONFIG_P2P_STRICT */
}
if (!msg.config_timeout) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory Configuration Timeout attribute "
- "missing from GO Negotiation Request");
+ p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Request");
#ifdef CONFIG_P2P_STRICT
goto fail;
#endif /* CONFIG_P2P_STRICT */
}
if (!msg.listen_channel) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Listen Channel attribute received");
+ p2p_dbg(p2p, "No Listen Channel attribute received");
goto fail;
}
if (!msg.operating_channel) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Operating Channel attribute received");
+ p2p_dbg(p2p, "No Operating Channel attribute received");
goto fail;
}
if (!msg.channel_list) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Channel List attribute received");
+ p2p_dbg(p2p, "No Channel List attribute received");
goto fail;
}
if (!msg.intended_addr) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Intended P2P Interface Address attribute "
- "received");
+ p2p_dbg(p2p, "No Intended P2P Interface Address attribute received");
goto fail;
}
if (!msg.p2p_device_info) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No P2P Device Info attribute received");
+ p2p_dbg(p2p, "No P2P Device Info attribute received");
goto fail;
}
if (os_memcmp(msg.p2p_device_addr, sa, ETH_ALEN) != 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected GO Negotiation Request SA=" MACSTR
+ p2p_dbg(p2p, "Unexpected GO Negotiation Request SA=" MACSTR
" != dev_addr=" MACSTR,
MAC2STR(sa), MAC2STR(msg.p2p_device_addr));
goto fail;
@@ -600,9 +559,8 @@
dev = p2p_get_device(p2p, sa);
if (msg.status && *msg.status) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected Status attribute (%d) in GO "
- "Negotiation Request", *msg.status);
+ p2p_dbg(p2p, "Unexpected Status attribute (%d) in GO Negotiation Request",
+ *msg.status);
goto fail;
}
@@ -611,122 +569,96 @@
else if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
p2p_add_dev_info(p2p, sa, dev, &msg);
if (dev && dev->flags & P2P_DEV_USER_REJECTED) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: User has rejected this peer");
+ p2p_dbg(p2p, "User has rejected this peer");
status = P2P_SC_FAIL_REJECTED_BY_USER;
} else if (dev == NULL || dev->wps_method == WPS_NOT_READY) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Not ready for GO negotiation with " MACSTR,
+ p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
MAC2STR(sa));
status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
- if (dev)
- dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
p2p->cfg->go_neg_req_rx(p2p->cfg->cb_ctx, sa,
msg.dev_password_id);
} else if (p2p->go_neg_peer && p2p->go_neg_peer != dev) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Already in Group Formation with another peer");
+ p2p_dbg(p2p, "Already in Group Formation with another peer");
status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
} else {
int go;
if (!p2p->go_neg_peer) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting "
- "GO Negotiation with previously authorized "
- "peer");
+ p2p_dbg(p2p, "Starting GO Negotiation with previously authorized peer");
if (!(dev->flags & P2P_DEV_FORCE_FREQ)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Use default channel settings");
+ p2p_dbg(p2p, "Use default channel settings");
p2p->op_reg_class = p2p->cfg->op_reg_class;
p2p->op_channel = p2p->cfg->op_channel;
os_memcpy(&p2p->channels, &p2p->cfg->channels,
sizeof(struct p2p_channels));
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Use previously configured "
- "forced channel settings");
+ p2p_dbg(p2p, "Use previously configured forced channel settings");
}
}
dev->flags &= ~P2P_DEV_NOT_YET_READY;
if (!msg.go_intent) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No GO Intent attribute received");
+ p2p_dbg(p2p, "No GO Intent attribute received");
goto fail;
}
if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid GO Intent value (%u) received",
+ p2p_dbg(p2p, "Invalid GO Intent value (%u) received",
*msg.go_intent >> 1);
goto fail;
}
if (dev->go_neg_req_sent &&
os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Do not reply since peer has higher "
- "address and GO Neg Request already sent");
+ p2p_dbg(p2p, "Do not reply since peer has higher address and GO Neg Request already sent");
p2p_parse_free(&msg);
return;
}
go = p2p_go_det(p2p->go_intent, *msg.go_intent);
if (go < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Incompatible GO Intent");
+ p2p_dbg(p2p, "Incompatible GO Intent");
status = P2P_SC_FAIL_BOTH_GO_INTENT_15;
goto fail;
}
if (p2p_peer_channels(p2p, dev, msg.channel_list,
msg.channel_list_len) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No common channels found");
+ p2p_dbg(p2p, "No common channels found");
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
switch (msg.dev_password_id) {
case DEV_PW_REGISTRAR_SPECIFIED:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: PIN from peer Display");
+ p2p_dbg(p2p, "PIN from peer Display");
if (dev->wps_method != WPS_PIN_KEYPAD) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: We have wps_method=%s -> "
- "incompatible",
+ p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
p2p_wps_method_str(dev->wps_method));
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
}
break;
case DEV_PW_USER_SPECIFIED:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Peer entered PIN on Keypad");
+ p2p_dbg(p2p, "Peer entered PIN on Keypad");
if (dev->wps_method != WPS_PIN_DISPLAY) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: We have wps_method=%s -> "
- "incompatible",
+ p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
p2p_wps_method_str(dev->wps_method));
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
}
break;
case DEV_PW_PUSHBUTTON:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Peer using pushbutton");
+ p2p_dbg(p2p, "Peer using pushbutton");
if (dev->wps_method != WPS_PBC) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: We have wps_method=%s -> "
- "incompatible",
+ p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
p2p_wps_method_str(dev->wps_method));
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
}
break;
default:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported Device Password ID %d",
+ p2p_dbg(p2p, "Unsupported Device Password ID %d",
msg.dev_password_id);
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
@@ -736,20 +668,17 @@
goto fail;
dev->go_state = go ? LOCAL_GO : REMOTE_GO;
- dev->oper_freq = p2p_channel_to_freq((const char *)
- msg.operating_channel,
- msg.operating_channel[3],
+ dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
msg.operating_channel[4]);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
- "channel preference: %d MHz", dev->oper_freq);
+ p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
+ dev->oper_freq);
if (msg.config_timeout) {
dev->go_timeout = msg.config_timeout[0];
dev->client_timeout = msg.config_timeout[1];
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation with " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa));
if (p2p->state != P2P_IDLE)
p2p_stop_find_for_freq(p2p, rx_freq);
p2p_set_state(p2p, P2P_GO_NEG);
@@ -768,17 +697,14 @@
p2p_parse_free(&msg);
if (resp == NULL)
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Sending GO Negotiation Response");
+ p2p_dbg(p2p, "Sending GO Negotiation Response");
if (rx_freq > 0)
freq = rx_freq;
else
- freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->cfg->reg_class,
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown regulatory class/channel");
+ p2p_dbg(p2p, "Unknown regulatory class/channel");
wpabuf_free(resp);
return;
}
@@ -802,8 +728,7 @@
if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
p2p->cfg->dev_addr,
wpabuf_head(resp), wpabuf_len(resp), 500) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
}
wpabuf_free(resp);
@@ -821,8 +746,7 @@
u8 group_capab;
size_t extra = 0;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Building GO Negotiation Confirm");
+ p2p_dbg(p2p, "Building GO Negotiation Confirm");
#ifdef CONFIG_WIFI_DISPLAY
if (p2p->wfd_ie_go_neg)
@@ -887,14 +811,12 @@
u8 status = P2P_SC_SUCCESS;
int freq;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received GO Negotiation Response from " MACSTR
+ p2p_dbg(p2p, "Received GO Negotiation Response from " MACSTR
" (freq=%d)", MAC2STR(sa), rx_freq);
dev = p2p_get_device(p2p, sa);
if (dev == NULL || dev->wps_method == WPS_NOT_READY ||
dev != p2p->go_neg_peer) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Not ready for GO negotiation with " MACSTR,
+ p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
MAC2STR(sa));
return;
}
@@ -903,44 +825,35 @@
return;
if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Was not expecting GO Negotiation Response - "
- "ignore");
+ p2p_dbg(p2p, "Was not expecting GO Negotiation Response - ignore");
p2p_parse_free(&msg);
return;
}
dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
if (msg.dialog_token != dev->dialog_token) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected Dialog Token %u (expected %u)",
+ p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
msg.dialog_token, dev->dialog_token);
p2p_parse_free(&msg);
return;
}
if (!msg.status) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Status attribute received");
+ p2p_dbg(p2p, "No Status attribute received");
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
if (*msg.status) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation rejected: status %d",
- *msg.status);
+ p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status);
dev->go_neg_req_sent = 0;
if (*msg.status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Wait for the peer to become ready for "
- "GO Negotiation");
+ p2p_dbg(p2p, "Wait for the peer to become ready for GO Negotiation");
dev->flags |= P2P_DEV_NOT_YET_READY;
dev->wait_count = 0;
p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
p2p_set_timeout(p2p, 0, 0);
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Stop GO Negotiation attempt");
+ p2p_dbg(p2p, "Stop GO Negotiation attempt");
p2p_go_neg_failed(p2p, dev, *msg.status);
}
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
@@ -949,9 +862,7 @@
}
if (!msg.capability) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory Capability attribute missing from GO "
- "Negotiation Response");
+ p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Response");
#ifdef CONFIG_P2P_STRICT
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
@@ -959,9 +870,7 @@
}
if (!msg.p2p_device_info) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory P2P Device Info attribute missing "
- "from GO Negotiation Response");
+ p2p_dbg(p2p, "Mandatory P2P Device Info attribute missing from GO Negotiation Response");
#ifdef CONFIG_P2P_STRICT
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
@@ -969,22 +878,18 @@
}
if (!msg.intended_addr) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Intended P2P Interface Address attribute "
- "received");
+ p2p_dbg(p2p, "No Intended P2P Interface Address attribute received");
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
if (!msg.go_intent) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No GO Intent attribute received");
+ p2p_dbg(p2p, "No GO Intent attribute received");
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid GO Intent value (%u) received",
+ p2p_dbg(p2p, "Invalid GO Intent value (%u) received",
*msg.go_intent >> 1);
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
@@ -992,8 +897,7 @@
go = p2p_go_det(p2p->go_intent, *msg.go_intent);
if (go < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Incompatible GO Intent");
+ p2p_dbg(p2p, "Incompatible GO Intent");
status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
goto fail;
}
@@ -1003,18 +907,14 @@
p2p->ssid_len = msg.group_id_len - ETH_ALEN;
os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len);
} else if (!go) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory P2P Group ID attribute missing from "
- "GO Negotiation Response");
+ p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Response");
p2p->ssid_len = 0;
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
if (!msg.config_timeout) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory Configuration Timeout attribute "
- "missing from GO Negotiation Response");
+ p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Response");
#ifdef CONFIG_P2P_STRICT
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
@@ -1029,76 +929,61 @@
* Note: P2P Client may omit Operating Channel attribute to
* indicate it does not have a preference.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Operating Channel attribute received");
+ p2p_dbg(p2p, "No Operating Channel attribute received");
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
if (!msg.channel_list) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Channel List attribute received");
+ p2p_dbg(p2p, "No Channel List attribute received");
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
if (p2p_peer_channels(p2p, dev, msg.channel_list,
msg.channel_list_len) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No common channels found");
+ p2p_dbg(p2p, "No common channels found");
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
if (msg.operating_channel) {
- dev->oper_freq = p2p_channel_to_freq((const char *)
- msg.operating_channel,
- msg.operating_channel[3],
+ dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
msg.operating_channel[4]);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
- "channel preference: %d MHz", dev->oper_freq);
+ p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
+ dev->oper_freq);
} else
dev->oper_freq = 0;
switch (msg.dev_password_id) {
case DEV_PW_REGISTRAR_SPECIFIED:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: PIN from peer Display");
+ p2p_dbg(p2p, "PIN from peer Display");
if (dev->wps_method != WPS_PIN_KEYPAD) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: We have wps_method=%s -> "
- "incompatible",
+ p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
p2p_wps_method_str(dev->wps_method));
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
}
break;
case DEV_PW_USER_SPECIFIED:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Peer entered PIN on Keypad");
+ p2p_dbg(p2p, "Peer entered PIN on Keypad");
if (dev->wps_method != WPS_PIN_DISPLAY) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: We have wps_method=%s -> "
- "incompatible",
+ p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
p2p_wps_method_str(dev->wps_method));
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
}
break;
case DEV_PW_PUSHBUTTON:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Peer using pushbutton");
+ p2p_dbg(p2p, "Peer using pushbutton");
if (dev->wps_method != WPS_PBC) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: We have wps_method=%s -> "
- "incompatible",
+ p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
p2p_wps_method_str(dev->wps_method));
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
}
break;
default:
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported Device Password ID %d",
+ p2p_dbg(p2p, "Unsupported Device Password ID %d",
msg.dev_password_id);
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
@@ -1110,8 +995,7 @@
p2p_set_state(p2p, P2P_GO_NEG);
p2p_clear_timeout(p2p);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation with " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa));
os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN);
fail:
@@ -1120,8 +1004,7 @@
p2p_parse_free(&msg);
if (conf == NULL)
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Sending GO Negotiation Confirm");
+ p2p_dbg(p2p, "Sending GO Negotiation Confirm");
if (status == P2P_SC_SUCCESS) {
p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM;
dev->go_state = go ? LOCAL_GO : REMOTE_GO;
@@ -1133,14 +1016,12 @@
freq = dev->listen_freq;
if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa,
wpabuf_head(conf), wpabuf_len(conf), 0) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
p2p_go_neg_failed(p2p, dev, -1);
}
wpabuf_free(conf);
if (status != P2P_SC_SUCCESS) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation failed");
+ p2p_dbg(p2p, "GO Negotiation failed");
p2p_go_neg_failed(p2p, dev, status);
}
}
@@ -1152,22 +1033,18 @@
struct p2p_device *dev;
struct p2p_message msg;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received GO Negotiation Confirm from " MACSTR,
+ p2p_dbg(p2p, "Received GO Negotiation Confirm from " MACSTR,
MAC2STR(sa));
dev = p2p_get_device(p2p, sa);
if (dev == NULL || dev->wps_method == WPS_NOT_READY ||
dev != p2p->go_neg_peer) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Not ready for GO negotiation with " MACSTR,
+ p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
MAC2STR(sa));
return;
}
if (p2p->pending_action_state == P2P_PENDING_GO_NEG_RESPONSE) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopped waiting "
- "for TX status on GO Negotiation Response since we "
- "already received Confirmation");
+ p2p_dbg(p2p, "Stopped waiting for TX status on GO Negotiation Response since we already received Confirmation");
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
}
@@ -1175,31 +1052,25 @@
return;
if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Was not expecting GO Negotiation Confirm - "
- "ignore");
+ p2p_dbg(p2p, "Was not expecting GO Negotiation Confirm - ignore");
return;
}
dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
if (msg.dialog_token != dev->dialog_token) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected Dialog Token %u (expected %u)",
+ p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
msg.dialog_token, dev->dialog_token);
p2p_parse_free(&msg);
return;
}
if (!msg.status) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Status attribute received");
+ p2p_dbg(p2p, "No Status attribute received");
p2p_parse_free(&msg);
return;
}
if (*msg.status) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GO Negotiation rejected: status %d",
- *msg.status);
+ p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status);
p2p_go_neg_failed(p2p, dev, *msg.status);
p2p_parse_free(&msg);
return;
@@ -1210,9 +1081,7 @@
p2p->ssid_len = msg.group_id_len - ETH_ALEN;
os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len);
} else if (dev->go_state == REMOTE_GO) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory P2P Group ID attribute missing from "
- "GO Negotiation Confirmation");
+ p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Confirmation");
p2p->ssid_len = 0;
p2p_go_neg_failed(p2p, dev, P2P_SC_FAIL_INVALID_PARAMS);
p2p_parse_free(&msg);
@@ -1220,9 +1089,7 @@
}
if (!msg.operating_channel) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory Operating Channel attribute missing "
- "from GO Negotiation Confirmation");
+ p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation");
#ifdef CONFIG_P2P_STRICT
p2p_parse_free(&msg);
return;
@@ -1231,20 +1098,16 @@
#ifdef ANDROID_P2P
if (msg.operating_channel) {
- dev->oper_freq = p2p_channel_to_freq((const char *)
- msg.operating_channel,
- msg.operating_channel[3],
+ dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
msg.operating_channel[4]);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
- "channel preference: %d MHz", dev->oper_freq);
+ p2p_dbg(p2p, "P2P: Peer operating channel preference: %d MHz",
+ dev->oper_freq);
} else
dev->oper_freq = 0;
#endif
if (!msg.channel_list) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory Operating Channel attribute missing "
- "from GO Negotiation Confirmation");
+ p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation");
#ifdef CONFIG_P2P_STRICT
p2p_parse_free(&msg);
return;
@@ -1258,9 +1121,7 @@
* This should not happen since GO negotiation has already
* been completed.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected GO Neg state - do not know which end "
- "becomes GO");
+ p2p_dbg(p2p, "Unexpected GO Neg state - do not know which end becomes GO");
return;
}
@@ -1272,8 +1133,7 @@
* the group so that we will remain on the current channel to
* acknowledge any possible retransmission from the peer.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: 20 ms wait on current "
- "channel before starting group");
+ p2p_dbg(p2p, "20 ms wait on current channel before starting group");
os_sleep(0, 20000);
p2p_go_complete(p2p, dev);
diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c
index 852ddf5..15e7622 100644
--- a/src/p2p/p2p_group.c
+++ b/src/p2p/p2p_group.c
@@ -378,8 +378,8 @@
} else {
WPA_PUT_BE16(len, (u8 *) wpabuf_put(wfd_subelems, 0) - len -
2);
- wpa_printf(MSG_DEBUG, "WFD: WFD Session Info: %u descriptors",
- count);
+ p2p_dbg(group->p2p, "WFD: WFD Session Info: %u descriptors",
+ count);
}
wfd_ie = wifi_display_encaps(wfd_subelems);
@@ -588,7 +588,7 @@
m->next = group->members;
group->members = m;
group->num_members++;
- wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Add client " MACSTR
+ p2p_dbg(group->p2p, "Add client " MACSTR
" to group (p2p=%d wfd=%d client_info=%d); num_members=%u/%u",
MAC2STR(addr), m->p2p_ie ? 1 : 0, m->wfd_ie ? 1 : 0,
m->client_info ? 1 : 0,
@@ -641,8 +641,8 @@
void p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr)
{
if (p2p_group_remove_member(group, addr)) {
- wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove "
- "client " MACSTR " from group; num_members=%u/%u",
+ p2p_dbg(group->p2p, "Remove client " MACSTR
+ " from group; num_members=%u/%u",
MAC2STR(addr), group->num_members,
group->cfg->max_clients);
if (group->num_members == group->cfg->max_clients - 1)
@@ -854,20 +854,18 @@
m = p2p_group_get_client(group, dev_id);
if (m == NULL || m->client_info == NULL) {
- wpa_printf(MSG_DEBUG, "P2P: Requested client was not in this "
- "group " MACSTR,
- MAC2STR(group->cfg->interface_addr));
+ p2p_dbg(group->p2p, "Requested client was not in this group "
+ MACSTR, MAC2STR(group->cfg->interface_addr));
return -1;
}
if (!(m->dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
- wpa_printf(MSG_DEBUG, "P2P: Requested client does not support "
- "client discoverability");
+ p2p_dbg(group->p2p, "Requested client does not support client discoverability");
return -1;
}
- wpa_printf(MSG_DEBUG, "P2P: Schedule GO Discoverability Request to be "
- "sent to " MACSTR, MAC2STR(dev_id));
+ p2p_dbg(group->p2p, "Schedule GO Discoverability Request to be sent to "
+ MACSTR, MAC2STR(dev_id));
req = p2p_build_go_disc_req();
if (req == NULL)
@@ -882,8 +880,7 @@
group->cfg->interface_addr,
wpabuf_head(req), wpabuf_len(req), 200) < 0)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
}
wpabuf_free(req);
@@ -908,7 +905,7 @@
m = p2p_group_get_client_iface(group, client_interface_addr);
if (m == NULL || m->client_info == NULL) {
- wpa_printf(MSG_DEBUG, "P2P: Client was not in this group");
+ p2p_dbg(group->p2p, "Client was not in this group");
return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
}
@@ -921,9 +918,9 @@
else
curr_noa_len = -1;
if (curr_noa_len < 0)
- wpa_printf(MSG_DEBUG, "P2P: Failed to fetch current NoA");
+ p2p_dbg(group->p2p, "Failed to fetch current NoA");
else if (curr_noa_len == 0)
- wpa_printf(MSG_DEBUG, "P2P: No NoA being advertized");
+ p2p_dbg(group->p2p, "No NoA being advertized");
else
wpa_hexdump(MSG_DEBUG, "P2P: Current NoA", curr_noa,
curr_noa_len);
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index d5ce52f..dc629f8 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -398,6 +398,7 @@
} start_after_scan;
u8 after_scan_peer[ETH_ALEN];
struct p2p_pending_action_tx *after_scan_tx;
+ unsigned int after_scan_tx_in_progress:1;
/* Requested device types for find/search */
unsigned int num_req_dev_types;
@@ -569,9 +570,8 @@
/* p2p_utils.c */
int p2p_random(char *buf, size_t len);
-int p2p_channel_to_freq(const char *country, int reg_class, int channel);
-int p2p_freq_to_channel(const char *country, unsigned int freq, u8 *reg_class,
- u8 *channel);
+int p2p_channel_to_freq(int op_class, int channel);
+int p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel);
void p2p_channels_intersect(const struct p2p_channels *a,
const struct p2p_channels *b,
struct p2p_channels *res);
@@ -730,5 +730,11 @@
void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq);
int p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
unsigned int force_freq, unsigned int pref_freq);
+void p2p_dbg(struct p2p_data *p2p, const char *fmt, ...)
+PRINTF_FORMAT(2, 3);
+void p2p_info(struct p2p_data *p2p, const char *fmt, ...)
+PRINTF_FORMAT(2, 3);
+void p2p_err(struct p2p_data *p2p, const char *fmt, ...)
+PRINTF_FORMAT(2, 3);
#endif /* P2P_I_H */
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 3beefd2..6b3dafb 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -166,8 +166,7 @@
os_memset(group_bssid, 0, sizeof(group_bssid));
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received Invitation Request from " MACSTR " (freq=%d)",
+ p2p_dbg(p2p, "Received Invitation Request from " MACSTR " (freq=%d)",
MAC2STR(sa), rx_freq);
if (p2p_parse(data, len, &msg))
@@ -175,14 +174,12 @@
dev = p2p_get_device(p2p, sa);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invitation Request from unknown peer "
- MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "Invitation Request from unknown peer " MACSTR,
+ MAC2STR(sa));
if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
0)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invitation Request add device failed "
+ p2p_dbg(p2p, "Invitation Request add device failed "
MACSTR, MAC2STR(sa));
status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
goto fail;
@@ -190,18 +187,16 @@
dev = p2p_get_device(p2p, sa);
if (dev == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Reject Invitation Request from unknown "
- "peer " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "Reject Invitation Request from unknown peer "
+ MACSTR, MAC2STR(sa));
status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
goto fail;
}
}
if (!msg.group_id || !msg.channel_list) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory attribute missing in Invitation "
- "Request from " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "Mandatory attribute missing in Invitation Request from "
+ MACSTR, MAC2STR(sa));
status = P2P_SC_FAIL_INVALID_PARAMS;
goto fail;
}
@@ -214,46 +209,42 @@
* the request was for a persistent group if the attribute is
* missing.
*/
- wpa_printf(MSG_DEBUG, "P2P: Mandatory Invitation Flags "
- "attribute missing from Invitation Request");
+ p2p_dbg(p2p, "Mandatory Invitation Flags attribute missing from Invitation Request");
persistent = 1;
}
if (p2p_peer_channels_check(p2p, &p2p->cfg->channels, dev,
msg.channel_list, msg.channel_list_len) <
0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No common channels found");
+ p2p_dbg(p2p, "No common channels found");
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
+ p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
+ &intersection);
+
if (p2p->cfg->invitation_process) {
status = p2p->cfg->invitation_process(
p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id,
msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
- &go, group_bssid, &op_freq, persistent);
+ &go, group_bssid, &op_freq, persistent, &intersection);
}
if (op_freq) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Invitation "
- "processing forced frequency %d MHz", op_freq);
- if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
- ®_class, &channel) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown forced freq %d MHz from "
- "invitation_process()", op_freq);
+ p2p_dbg(p2p, "Invitation processing forced frequency %d MHz",
+ op_freq);
+ if (p2p_freq_to_channel(op_freq, ®_class, &channel) < 0) {
+ p2p_dbg(p2p, "Unknown forced freq %d MHz from invitation_process()",
+ op_freq);
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
- p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
- &intersection);
if (!p2p_channels_includes(&intersection, reg_class, channel))
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: forced freq %d MHz not in the supported "
- "channels interaction", op_freq);
+ p2p_dbg(p2p, "forced freq %d MHz not in the supported channels interaction",
+ op_freq);
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
@@ -261,28 +252,21 @@
if (status == P2P_SC_SUCCESS)
channels = &intersection;
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No forced channel from invitation processing - "
- "figure out best one to use");
+ p2p_dbg(p2p, "No forced channel from invitation processing - figure out best one to use");
- p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
- &intersection);
/* Default to own configuration as a starting point */
p2p->op_reg_class = p2p->cfg->op_reg_class;
p2p->op_channel = p2p->cfg->op_channel;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own default "
- "op_class %d channel %d",
+ p2p_dbg(p2p, "Own default op_class %d channel %d",
p2p->op_reg_class, p2p->op_channel);
/* Use peer preference if specified and compatible */
if (msg.operating_channel) {
int req_freq;
req_freq = p2p_channel_to_freq(
- (const char *) msg.operating_channel,
msg.operating_channel[3],
msg.operating_channel[4]);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer "
- "operating channel preference: %d MHz",
+ p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
req_freq);
if (req_freq > 0 &&
p2p_channels_includes(&intersection,
@@ -290,56 +274,45 @@
msg.operating_channel[4])) {
p2p->op_reg_class = msg.operating_channel[3];
p2p->op_channel = msg.operating_channel[4];
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Use peer preference op_class %d "
- "channel %d",
+ p2p_dbg(p2p, "Use peer preference op_class %d channel %d",
p2p->op_reg_class, p2p->op_channel);
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cannot use peer channel "
- "preference");
+ p2p_dbg(p2p, "Cannot use peer channel preference");
}
}
if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
p2p->op_channel)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Initially selected channel (op_class %d "
- "channel %d) not in channel intersection - try "
- "to reselect",
+ p2p_dbg(p2p, "Initially selected channel (op_class %d channel %d) not in channel intersection - try to reselect",
p2p->op_reg_class, p2p->op_channel);
p2p_reselect_channel(p2p, &intersection);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Re-selection result: op_class %d "
- "channel %d",
+ p2p_dbg(p2p, "Re-selection result: op_class %d channel %d",
p2p->op_reg_class, p2p->op_channel);
if (!p2p_channels_includes(&intersection,
p2p->op_reg_class,
p2p->op_channel)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Peer does not support selected "
- "operating channel (reg_class=%u "
- "channel=%u)",
+ p2p_dbg(p2p, "Peer does not support selected operating channel (reg_class=%u channel=%u)",
p2p->op_reg_class, p2p->op_channel);
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
+ } else if (!(dev->flags & P2P_DEV_FORCE_FREQ) &&
+ !p2p->cfg->cfg_op_channel) {
+ p2p_dbg(p2p, "Try to reselect channel selection with peer information received; previously selected op_class %u channel %u",
+ p2p->op_reg_class, p2p->op_channel);
+ p2p_reselect_channel(p2p, &intersection);
}
- op_freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->op_reg_class,
+ op_freq = p2p_channel_to_freq(p2p->op_reg_class,
p2p->op_channel);
if (op_freq < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown operational channel "
- "(country=%c%c reg_class=%u channel=%u)",
+ p2p_dbg(p2p, "Unknown operational channel (country=%c%c reg_class=%u channel=%u)",
p2p->cfg->country[0], p2p->cfg->country[1],
p2p->op_reg_class, p2p->op_channel);
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
- "channel - %d MHz", op_freq);
+ p2p_dbg(p2p, "Selected operating channel - %d MHz", op_freq);
if (status == P2P_SC_SUCCESS) {
reg_class = p2p->op_reg_class;
@@ -362,12 +335,10 @@
if (rx_freq > 0)
freq = rx_freq;
else
- freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->cfg->reg_class,
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown regulatory class/channel");
+ p2p_dbg(p2p, "Unknown regulatory class/channel");
goto out;
}
@@ -394,8 +365,7 @@
if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
p2p->cfg->dev_addr,
wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
}
out:
@@ -411,21 +381,18 @@
struct p2p_message msg;
struct p2p_channels intersection, *channels = NULL;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received Invitation Response from " MACSTR,
+ p2p_dbg(p2p, "Received Invitation Response from " MACSTR,
MAC2STR(sa));
dev = p2p_get_device(p2p, sa);
if (dev == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore Invitation Response from unknown peer "
+ p2p_dbg(p2p, "Ignore Invitation Response from unknown peer "
MACSTR, MAC2STR(sa));
return;
}
if (dev != p2p->invite_peer) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore unexpected Invitation Response from peer "
+ p2p_dbg(p2p, "Ignore unexpected Invitation Response from peer "
MACSTR, MAC2STR(sa));
return;
}
@@ -434,17 +401,15 @@
return;
if (!msg.status) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory Status attribute missing in "
- "Invitation Response from " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "Mandatory Status attribute missing in Invitation Response from "
+ MACSTR, MAC2STR(sa));
p2p_parse_free(&msg);
return;
}
if (!msg.channel_list) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Mandatory Channel List attribute missing in "
- "Invitation Response from " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "Mandatory Channel List attribute missing in Invitation Response from "
+ MACSTR, MAC2STR(sa));
#ifdef CONFIG_P2P_STRICT
p2p_parse_free(&msg);
return;
@@ -454,8 +419,7 @@
} else if (p2p_peer_channels_check(p2p, &p2p->channels, dev,
msg.channel_list,
msg.channel_list_len) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No common channels found");
+ p2p_dbg(p2p, "No common channels found");
p2p_parse_free(&msg);
return;
} else {
@@ -484,9 +448,8 @@
freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
if (freq <= 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Listen/Operating frequency known for the "
- "peer " MACSTR " to send Invitation Request",
+ p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
+ MACSTR " to send Invitation Request",
MAC2STR(dev->info.p2p_device_addr));
return -1;
}
@@ -496,8 +459,7 @@
return -1;
if (p2p->state != P2P_IDLE)
p2p_stop_listen_for_freq(p2p, freq);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Sending Invitation Request");
+ p2p_dbg(p2p, "Sending Invitation Request");
p2p_set_state(p2p, P2P_INVITE);
p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
p2p->invite_peer = dev;
@@ -505,8 +467,7 @@
if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
p2p->cfg->dev_addr, dev->info.p2p_device_addr,
wpabuf_head(req), wpabuf_len(req), 200) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
/* Use P2P find to recover and retry */
p2p_set_timeout(p2p, 0, 0);
}
@@ -519,12 +480,10 @@
void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invitation Request TX callback: success=%d", success);
+ p2p_dbg(p2p, "Invitation Request TX callback: success=%d", success);
if (p2p->invite_peer == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No pending Invite");
+ p2p_dbg(p2p, "No pending Invite");
return;
}
@@ -533,25 +492,17 @@
* channel.
*/
p2p_set_state(p2p, P2P_INVITE);
-#ifdef ANDROID_P2P
- p2p_set_timeout(p2p, 0, 350000);
-#else
- p2p_set_timeout(p2p, 0, 100000);
-#endif
+ p2p_set_timeout(p2p, 0, success ? 350000 : 100000);
}
void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
{
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invitation Response TX callback: success=%d", success);
+ p2p_dbg(p2p, "Invitation Response TX callback: success=%d", success);
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
if (!success)
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Assume Invitation Response was actually "
- "received by the peer even though Ack was not "
- "reported");
+ p2p_dbg(p2p, "Assume Invitation Response was actually received by the peer even though Ack was not reported");
if (p2p->cfg->invitation_received) {
p2p->cfg->invitation_received(p2p->cfg->cb_ctx,
@@ -572,28 +523,24 @@
{
struct p2p_device *dev;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Request to invite peer " MACSTR " role=%d persistent=%d "
+ p2p_dbg(p2p, "Request to invite peer " MACSTR " role=%d persistent=%d "
"force_freq=%u",
MAC2STR(peer), role, persistent_group, force_freq);
if (bssid)
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invitation for BSSID " MACSTR, MAC2STR(bssid));
+ p2p_dbg(p2p, "Invitation for BSSID " MACSTR, MAC2STR(bssid));
if (go_dev_addr) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invitation for GO Device Address " MACSTR,
+ p2p_dbg(p2p, "Invitation for GO Device Address " MACSTR,
MAC2STR(go_dev_addr));
os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN);
p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf;
} else
p2p->invite_go_dev_addr = NULL;
- wpa_hexdump_ascii(MSG_DEBUG, "P2P: Invitation for SSID",
+ wpa_hexdump_ascii(MSG_DEBUG, "Invitation for SSID",
ssid, ssid_len);
dev = p2p_get_device(p2p, peer);
if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cannot invite unknown P2P Device " MACSTR,
+ p2p_dbg(p2p, "Cannot invite unknown P2P Device " MACSTR,
MAC2STR(peer));
return -1;
}
@@ -610,8 +557,7 @@
if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
if (!(dev->info.dev_capab &
P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cannot invite a P2P Device " MACSTR
+ p2p_dbg(p2p, "Cannot invite a P2P Device " MACSTR
" that is in a group and is not discoverable",
MAC2STR(peer));
}
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index a1268e4..54aa428 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -141,22 +141,19 @@
if (p2p_parse(data, len, &msg))
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received Provision Discovery Request from " MACSTR
+ p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR
" with config methods 0x%x (freq=%d)",
MAC2STR(sa), msg.wps_config_methods, rx_freq);
dev = p2p_get_device(p2p, sa);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Provision Discovery Request from "
- "unknown peer " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "Provision Discovery Request from unknown peer "
+ MACSTR, MAC2STR(sa));
if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
0)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Provision Discovery Request add device "
- "failed " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "Provision Discovery Request add device failed "
+ MACSTR, MAC2STR(sa));
}
} else if (msg.wfd_subelems) {
wpabuf_free(dev->info.wfd_subelems);
@@ -166,8 +163,7 @@
if (!(msg.wps_config_methods &
(WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD |
WPS_CONFIG_PUSHBUTTON))) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unsupported "
- "Config Methods in Provision Discovery Request");
+ p2p_dbg(p2p, "Unsupported Config Methods in Provision Discovery Request");
goto out;
}
@@ -180,8 +176,7 @@
break;
}
if (i == p2p->num_groups) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: PD "
- "request for unknown P2P Group ID - reject");
+ p2p_dbg(p2p, "PD request for unknown P2P Group ID - reject");
goto out;
}
}
@@ -190,12 +185,12 @@
dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
P2P_DEV_PD_PEER_KEYPAD);
if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
+ p2p_dbg(p2p, "Peer " MACSTR
" requested us to show a PIN on display", MAC2STR(sa));
if (dev)
dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
+ p2p_dbg(p2p, "Peer " MACSTR
" requested us to write its PIN using keypad",
MAC2STR(sa));
if (dev)
@@ -212,17 +207,14 @@
p2p_parse_free(&msg);
return;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Sending Provision Discovery Response");
+ p2p_dbg(p2p, "Sending Provision Discovery Response");
if (rx_freq > 0)
freq = rx_freq;
else
- freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->cfg->reg_class,
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unknown regulatory class/channel");
+ p2p_dbg(p2p, "Unknown regulatory class/channel");
wpabuf_free(resp);
p2p_parse_free(&msg);
return;
@@ -231,8 +223,7 @@
if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
p2p->cfg->dev_addr,
wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
}
wpabuf_free(resp);
@@ -265,24 +256,20 @@
if (p2p_parse(data, len, &msg))
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received Provision Discovery Response from " MACSTR
+ p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR
" with config methods 0x%x",
MAC2STR(sa), msg.wps_config_methods);
dev = p2p_get_device(p2p, sa);
if (dev == NULL || !dev->req_config_methods) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore Provision Discovery Response from "
- MACSTR " with no pending request", MAC2STR(sa));
+ p2p_dbg(p2p, "Ignore Provision Discovery Response from " MACSTR
+ " with no pending request", MAC2STR(sa));
p2p_parse_free(&msg);
return;
}
if (dev->dialog_token != msg.dialog_token) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore Provision Discovery Response with "
- "unexpected Dialog Token %u (expected %u)",
+ p2p_dbg(p2p, "Ignore Provision Discovery Response with unexpected Dialog Token %u (expected %u)",
msg.dialog_token, dev->dialog_token);
p2p_parse_free(&msg);
return;
@@ -308,9 +295,7 @@
p2p_reset_pending_pd(p2p);
if (msg.wps_config_methods != req_config_methods) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer rejected "
- "our Provision Discovery Request (received "
- "config_methods 0x%x expected 0x%x",
+ p2p_dbg(p2p, "Peer rejected our Provision Discovery Request (received config_methods 0x%x expected 0x%x",
msg.wps_config_methods, req_config_methods);
if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
@@ -323,11 +308,11 @@
dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
P2P_DEV_PD_PEER_KEYPAD);
if (req_config_methods & WPS_CONFIG_DISPLAY) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
+ p2p_dbg(p2p, "Peer " MACSTR
" accepted to show a PIN on display", MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
+ p2p_dbg(p2p, "Peer " MACSTR
" accepted to write our PIN using keypad",
MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
@@ -343,10 +328,8 @@
dev->req_config_methods = 0;
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Start GO Neg after the PD-before-GO-Neg "
- "workaround with " MACSTR,
- MAC2STR(dev->info.p2p_device_addr));
+ p2p_dbg(p2p, "Start GO Neg after the PD-before-GO-Neg workaround with "
+ MACSTR, MAC2STR(dev->info.p2p_device_addr));
dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
p2p_connect_send(p2p, dev);
return;
@@ -374,9 +357,8 @@
freq = dev->listen_freq > 0 ? dev->listen_freq :
dev->oper_freq;
if (freq <= 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Listen/Operating frequency known for the "
- "peer " MACSTR " to send Provision Discovery Request",
+ p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
+ MACSTR " to send Provision Discovery Request",
MAC2STR(dev->info.p2p_device_addr));
return -1;
}
@@ -384,8 +366,7 @@
if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
if (!(dev->info.dev_capab &
P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cannot use PD with P2P Device " MACSTR
+ p2p_dbg(p2p, "Cannot use PD with P2P Device " MACSTR
" that is in a group and is not discoverable",
MAC2STR(dev->info.p2p_device_addr));
return -1;
@@ -405,8 +386,7 @@
if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
p2p->cfg->dev_addr, dev->info.p2p_device_addr,
wpabuf_head(req), wpabuf_len(req), 200) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
wpabuf_free(req);
return -1;
}
@@ -428,14 +408,13 @@
if (dev == NULL)
dev = p2p_get_device_interface(p2p, peer_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision "
- "Discovery Request destination " MACSTR
+ p2p_dbg(p2p, "Provision Discovery Request destination " MACSTR
" not yet known", MAC2STR(peer_addr));
return -1;
}
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision Discovery "
- "Request with " MACSTR " (config methods 0x%x)",
+ p2p_dbg(p2p, "Provision Discovery Request with " MACSTR
+ " (config methods 0x%x)",
MAC2STR(peer_addr), config_methods);
if (config_methods == 0)
return -1;
@@ -451,9 +430,8 @@
if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH &&
p2p->state != P2P_LISTEN_ONLY) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Busy with other "
- "operations; postpone Provision Discovery Request "
- "with " MACSTR " (config methods 0x%x)",
+ p2p_dbg(p2p, "Busy with other operations; postpone Provision Discovery Request with "
+ MACSTR " (config methods 0x%x)",
MAC2STR(peer_addr), config_methods);
return 0;
}
diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c
index bf75605..5d9c1bb 100644
--- a/src/p2p/p2p_sd.c
+++ b/src/p2p/p2p_sd.c
@@ -157,8 +157,7 @@
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr, dst,
wpabuf_head(req), wpabuf_len(req), 200) < 0)
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
wpabuf_free(req);
}
@@ -235,9 +234,8 @@
freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
if (freq <= 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: No Listen/Operating frequency known for the "
- "peer " MACSTR " to send SD Request",
+ p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
+ MACSTR " to send SD Request",
MAC2STR(dev->info.p2p_device_addr));
return -1;
}
@@ -246,8 +244,7 @@
if (query == NULL)
return -1;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Start Service Discovery with " MACSTR,
+ p2p_dbg(p2p, "Start Service Discovery with " MACSTR,
MAC2STR(dev->info.p2p_device_addr));
req = p2p_build_sd_query(p2p->srv_update_indic, query->tlvs);
@@ -261,8 +258,7 @@
if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
p2p->cfg->dev_addr, dev->info.p2p_device_addr,
wpabuf_head(req), wpabuf_len(req), 5000) < 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
ret = -1;
}
@@ -290,8 +286,7 @@
if (rx_freq > 0)
freq = rx_freq;
else
- freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->cfg->reg_class,
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0)
return;
@@ -300,14 +295,12 @@
return;
dialog_token = *pos++;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: GAS Initial Request from " MACSTR " (dialog token %u, "
- "freq %d)",
+ p2p_dbg(p2p, "GAS Initial Request from " MACSTR
+ " (dialog token %u, freq %d)",
MAC2STR(sa), dialog_token, rx_freq);
if (*pos != WLAN_EID_ADV_PROTO) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected IE in GAS Initial Request: %u", *pos);
+ p2p_dbg(p2p, "Unexpected IE in GAS Initial Request: %u", *pos);
return;
}
pos++;
@@ -315,15 +308,13 @@
slen = *pos++;
next = pos + slen;
if (next > end || slen < 2) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid IE in GAS Initial Request");
+ p2p_dbg(p2p, "Invalid IE in GAS Initial Request");
return;
}
pos++; /* skip QueryRespLenLimit and PAME-BI */
if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported GAS advertisement protocol id %u",
+ p2p_dbg(p2p, "Unsupported GAS advertisement protocol id %u",
*pos);
return;
}
@@ -342,8 +333,7 @@
if (pos + 4 > end)
return;
if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
+ p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
return;
}
pos += 2;
@@ -351,21 +341,18 @@
slen = WPA_GET_LE16(pos);
pos += 2;
if (pos + slen > end || slen < 3 + 1) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid ANQP Query Request length");
+ p2p_dbg(p2p, "Invalid ANQP Query Request length");
return;
}
if (WPA_GET_BE24(pos) != OUI_WFA) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
+ p2p_dbg(p2p, "Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
return;
}
pos += 3;
if (*pos != P2P_OUI_TYPE) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP vendor type %u", *pos);
+ p2p_dbg(p2p, "Unsupported ANQP vendor type %u", *pos);
return;
}
pos++;
@@ -373,8 +360,7 @@
if (pos + 2 > end)
return;
update_indic = WPA_GET_LE16(pos);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Service Update Indicator: %u", update_indic);
+ p2p_dbg(p2p, "Service Update Indicator: %u", update_indic);
pos += 2;
p2p->cfg->sd_request(p2p->cfg->cb_ctx, freq, sa, dialog_token,
@@ -390,8 +376,7 @@
/* TODO: fix the length limit to match with the maximum frame length */
if (wpabuf_len(resp_tlvs) > 1400) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: SD response long "
- "enough to require fragmentation");
+ p2p_dbg(p2p, "SD response long enough to require fragmentation");
if (p2p->sd_resp) {
/*
* TODO: Could consider storing the fragmented response
@@ -400,14 +385,12 @@
* Though, that would eat more memory, so there are
* also benefits to just using a single buffer.
*/
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Drop "
- "previous SD response");
+ p2p_dbg(p2p, "Drop previous SD response");
wpabuf_free(p2p->sd_resp);
}
p2p->sd_resp = wpabuf_dup(resp_tlvs);
if (p2p->sd_resp == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_ERROR, "P2P: Failed to "
- "allocate SD response fragmentation area");
+ p2p_err(p2p, "Failed to allocate SD response fragmentation area");
return;
}
os_memcpy(p2p->sd_resp_addr, dst, ETH_ALEN);
@@ -417,8 +400,7 @@
resp = p2p_build_sd_response(dialog_token, WLAN_STATUS_SUCCESS,
1, p2p->srv_update_indic, NULL);
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: SD response fits "
- "in initial response");
+ p2p_dbg(p2p, "SD response fits in initial response");
resp = p2p_build_sd_response(dialog_token,
WLAN_STATUS_SUCCESS, 0,
p2p->srv_update_indic, resp_tlvs);
@@ -430,8 +412,7 @@
if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr,
p2p->cfg->dev_addr,
wpabuf_head(resp), wpabuf_len(resp), 200) < 0)
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
wpabuf_free(resp);
}
@@ -451,8 +432,7 @@
#ifdef ANDROID_P2P
if (p2p->state != P2P_SD_DURING_FIND) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: #### Not ignoring unexpected GAS Initial Response from "
+ p2p_dbg(p2p, "P2P: #### Not ignoring unexpected GAS Initial Response from "
MACSTR " state %d", MAC2STR(sa), p2p->state);
}
if (p2p->sd_peer == NULL ||
@@ -460,21 +440,18 @@
if (p2p->state != P2P_SD_DURING_FIND || p2p->sd_peer == NULL ||
#endif
os_memcmp(sa, p2p->sd_peer->info.p2p_device_addr, ETH_ALEN) != 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore unexpected GAS Initial Response from "
+ p2p_dbg(p2p, "Ignore unexpected GAS Initial Response from "
MACSTR, MAC2STR(sa));
return;
}
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
p2p_clear_timeout(p2p);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received GAS Initial Response from " MACSTR " (len=%d)",
+ p2p_dbg(p2p, "Received GAS Initial Response from " MACSTR " (len=%d)",
MAC2STR(sa), (int) len);
if (len < 5 + 2) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Too short GAS Initial Response frame");
+ p2p_dbg(p2p, "Too short GAS Initial Response frame");
return;
}
@@ -484,20 +461,16 @@
pos += 2;
comeback_delay = WPA_GET_LE16(pos);
pos += 2;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: dialog_token=%u status_code=%u comeback_delay=%u",
+ p2p_dbg(p2p, "dialog_token=%u status_code=%u comeback_delay=%u",
dialog_token, status_code, comeback_delay);
if (status_code) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Service Discovery failed: status code %u",
+ p2p_dbg(p2p, "Service Discovery failed: status code %u",
status_code);
return;
}
if (*pos != WLAN_EID_ADV_PROTO) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected IE in GAS Initial Response: %u",
- *pos);
+ p2p_dbg(p2p, "Unexpected IE in GAS Initial Response: %u", *pos);
return;
}
pos++;
@@ -505,15 +478,13 @@
slen = *pos++;
next = pos + slen;
if (next > end || slen < 2) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid IE in GAS Initial Response");
+ p2p_dbg(p2p, "Invalid IE in GAS Initial Response");
return;
}
pos++; /* skip QueryRespLenLimit and PAME-BI */
if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported GAS advertisement protocol id %u",
+ p2p_dbg(p2p, "Unsupported GAS advertisement protocol id %u",
*pos);
return;
}
@@ -521,27 +492,22 @@
pos = next;
/* Query Response */
if (pos + 2 > end) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Too short Query "
- "Response");
+ p2p_dbg(p2p, "Too short Query Response");
return;
}
slen = WPA_GET_LE16(pos);
pos += 2;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Query Response Length: %d",
- slen);
+ p2p_dbg(p2p, "Query Response Length: %d", slen);
if (pos + slen > end) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Not enough Query "
- "Response data");
+ p2p_dbg(p2p, "Not enough Query Response data");
return;
}
end = pos + slen;
if (comeback_delay) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Fragmented "
- "response - request fragments");
+ p2p_dbg(p2p, "Fragmented response - request fragments");
if (p2p->sd_rx_resp) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Drop "
- "old SD reassembly buffer");
+ p2p_dbg(p2p, "Drop old SD reassembly buffer");
wpabuf_free(p2p->sd_rx_resp);
p2p->sd_rx_resp = NULL;
}
@@ -553,8 +519,7 @@
if (pos + 4 > end)
return;
if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
+ p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
return;
}
pos += 2;
@@ -562,21 +527,18 @@
slen = WPA_GET_LE16(pos);
pos += 2;
if (pos + slen > end || slen < 3 + 1) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid ANQP Query Response length");
+ p2p_dbg(p2p, "Invalid ANQP Query Response length");
return;
}
if (WPA_GET_BE24(pos) != OUI_WFA) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
+ p2p_dbg(p2p, "Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
return;
}
pos += 3;
if (*pos != P2P_OUI_TYPE) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP vendor type %u", *pos);
+ p2p_dbg(p2p, "Unsupported ANQP vendor type %u", *pos);
return;
}
pos++;
@@ -584,8 +546,7 @@
if (pos + 2 > end)
return;
update_indic = WPA_GET_LE16(pos);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Service Update Indicator: %u", update_indic);
+ p2p_dbg(p2p, "Service Update Indicator: %u", update_indic);
pos += 2;
p2p->sd_peer->flags |= P2P_DEV_SD_INFO;
@@ -595,8 +556,7 @@
if (p2p->sd_query) {
if (!p2p->sd_query->for_all_peers) {
struct p2p_sd_query *q;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Remove completed SD query %p",
+ p2p_dbg(p2p, "Remove completed SD query %p",
p2p->sd_query);
q = p2p->sd_query;
p2p_unlink_sd_query(p2p, p2p->sd_query);
@@ -624,22 +584,20 @@
if (len < 1)
return;
dialog_token = *data;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dialog Token: %u",
- dialog_token);
+ p2p_dbg(p2p, "Dialog Token: %u", dialog_token);
if (dialog_token != p2p->sd_resp_dialog_token) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending SD "
- "response fragment for dialog token %u", dialog_token);
+ p2p_dbg(p2p, "No pending SD response fragment for dialog token %u",
+ dialog_token);
return;
}
if (p2p->sd_resp == NULL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending SD "
- "response fragment available");
+ p2p_dbg(p2p, "No pending SD response fragment available");
return;
}
if (os_memcmp(sa, p2p->sd_resp_addr, ETH_ALEN) != 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending SD "
- "response fragment for " MACSTR, MAC2STR(sa));
+ p2p_dbg(p2p, "No pending SD response fragment for " MACSTR,
+ MAC2STR(sa));
return;
}
@@ -656,19 +614,16 @@
wpabuf_len(p2p->sd_resp));
if (resp == NULL)
return;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send GAS Comeback "
- "Response (frag_id %d more=%d frag_len=%d)",
+ p2p_dbg(p2p, "Send GAS Comeback Response (frag_id %d more=%d frag_len=%d)",
p2p->sd_frag_id, more, (int) frag_len);
p2p->sd_frag_id++;
p2p->sd_resp_pos += frag_len;
if (more) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: %d more bytes "
- "remain to be sent",
+ p2p_dbg(p2p, "%d more bytes remain to be sent",
(int) (wpabuf_len(p2p->sd_resp) - p2p->sd_resp_pos));
} else {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: All fragments of "
- "SD response sent");
+ p2p_dbg(p2p, "All fragments of SD response sent");
wpabuf_free(p2p->sd_resp);
p2p->sd_resp = NULL;
}
@@ -677,8 +632,7 @@
if (p2p_send_action(p2p, rx_freq, sa, p2p->cfg->dev_addr,
p2p->cfg->dev_addr,
wpabuf_head(resp), wpabuf_len(resp), 200) < 0)
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Failed to send Action frame");
+ p2p_dbg(p2p, "Failed to send Action frame");
wpabuf_free(resp);
}
@@ -701,8 +655,7 @@
#ifdef ANDROID_P2P
if (p2p->state != P2P_SD_DURING_FIND) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: #### Not ignoring unexpected GAS Comeback Response from "
+ p2p_dbg(p2p, "P2P: #### Not ignoring unexpected GAS Comeback Response from "
MACSTR " state %d", MAC2STR(sa), p2p->state);
}
if (p2p->sd_peer == NULL ||
@@ -710,21 +663,18 @@
if (p2p->state != P2P_SD_DURING_FIND || p2p->sd_peer == NULL ||
#endif
os_memcmp(sa, p2p->sd_peer->info.p2p_device_addr, ETH_ALEN) != 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Ignore unexpected GAS Comeback Response from "
+ p2p_dbg(p2p, "Ignore unexpected GAS Comeback Response from "
MACSTR, MAC2STR(sa));
return;
}
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
p2p_clear_timeout(p2p);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Received GAS Comeback Response from " MACSTR " (len=%d)",
+ p2p_dbg(p2p, "Received GAS Comeback Response from " MACSTR " (len=%d)",
MAC2STR(sa), (int) len);
if (len < 6 + 2) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Too short GAS Comeback Response frame");
+ p2p_dbg(p2p, "Too short GAS Comeback Response frame");
return;
}
@@ -737,22 +687,19 @@
pos++;
comeback_delay = WPA_GET_LE16(pos);
pos += 2;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: dialog_token=%u status_code=%u frag_id=%d more_frags=%d "
+ p2p_dbg(p2p, "dialog_token=%u status_code=%u frag_id=%d more_frags=%d "
"comeback_delay=%u",
dialog_token, status_code, frag_id, more_frags,
comeback_delay);
/* TODO: check frag_id match */
if (status_code) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Service Discovery failed: status code %u",
+ p2p_dbg(p2p, "Service Discovery failed: status code %u",
status_code);
return;
}
if (*pos != WLAN_EID_ADV_PROTO) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unexpected IE in GAS Comeback Response: %u",
+ p2p_dbg(p2p, "Unexpected IE in GAS Comeback Response: %u",
*pos);
return;
}
@@ -761,15 +708,13 @@
slen = *pos++;
next = pos + slen;
if (next > end || slen < 2) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid IE in GAS Comeback Response");
+ p2p_dbg(p2p, "Invalid IE in GAS Comeback Response");
return;
}
pos++; /* skip QueryRespLenLimit and PAME-BI */
if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported GAS advertisement protocol id %u",
+ p2p_dbg(p2p, "Unsupported GAS advertisement protocol id %u",
*pos);
return;
}
@@ -777,22 +722,18 @@
pos = next;
/* Query Response */
if (pos + 2 > end) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Too short Query "
- "Response");
+ p2p_dbg(p2p, "Too short Query Response");
return;
}
slen = WPA_GET_LE16(pos);
pos += 2;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Query Response Length: %d",
- slen);
+ p2p_dbg(p2p, "Query Response Length: %d", slen);
if (pos + slen > end) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Not enough Query "
- "Response data");
+ p2p_dbg(p2p, "Not enough Query Response data");
return;
}
if (slen == 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No Query Response "
- "data");
+ p2p_dbg(p2p, "No Query Response data");
return;
}
end = pos + slen;
@@ -809,34 +750,29 @@
if (pos + 4 > end)
return;
if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
+ p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
return;
}
pos += 2;
slen = WPA_GET_LE16(pos);
pos += 2;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: ANQP Query Response "
- "length: %u", slen);
+ p2p_dbg(p2p, "ANQP Query Response length: %u", slen);
if (slen < 3 + 1) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Invalid ANQP Query Response length");
+ p2p_dbg(p2p, "Invalid ANQP Query Response length");
return;
}
if (pos + 4 > end)
return;
if (WPA_GET_BE24(pos) != OUI_WFA) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
+ p2p_dbg(p2p, "Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
return;
}
pos += 3;
if (*pos != P2P_OUI_TYPE) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported ANQP vendor type %u", *pos);
+ p2p_dbg(p2p, "Unsupported ANQP vendor type %u", *pos);
return;
}
pos++;
@@ -844,27 +780,23 @@
if (pos + 2 > end)
return;
p2p->sd_rx_update_indic = WPA_GET_LE16(pos);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Service Update Indicator: %u", p2p->sd_rx_update_indic);
+ p2p_dbg(p2p, "Service Update Indicator: %u", p2p->sd_rx_update_indic);
pos += 2;
skip_nqp_header:
if (wpabuf_resize(&p2p->sd_rx_resp, end - pos) < 0)
return;
wpabuf_put_data(p2p->sd_rx_resp, pos, end - pos);
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Current SD reassembly "
- "buffer length: %u",
+ p2p_dbg(p2p, "Current SD reassembly buffer length: %u",
(unsigned int) wpabuf_len(p2p->sd_rx_resp));
if (more_frags) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: More fragments "
- "remains");
+ p2p_dbg(p2p, "More fragments remains");
/* TODO: what would be a good size limit? */
if (wpabuf_len(p2p->sd_rx_resp) > 64000) {
wpabuf_free(p2p->sd_rx_resp);
p2p->sd_rx_resp = NULL;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Too long "
- "SD response - drop it");
+ p2p_dbg(p2p, "Too long SD response - drop it");
return;
}
p2p_send_gas_comeback_req(p2p, sa, dialog_token, rx_freq);
@@ -878,8 +810,7 @@
if (p2p->sd_query) {
if (!p2p->sd_query->for_all_peers) {
struct p2p_sd_query *q;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Remove completed SD query %p",
+ p2p_dbg(p2p, "Remove completed SD query %p",
p2p->sd_query);
q = p2p->sd_query;
p2p_unlink_sd_query(p2p, p2p->sd_query);
@@ -935,7 +866,7 @@
q->next = p2p->sd_queries;
p2p->sd_queries = q;
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Added SD Query %p", q);
+ p2p_dbg(p2p, "Added SD Query %p", q);
if (dst == NULL) {
struct p2p_device *dev;
@@ -993,8 +924,7 @@
int p2p_sd_cancel_request(struct p2p_data *p2p, void *req)
{
if (p2p_unlink_sd_query(p2p, req)) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Cancel pending SD query %p", req);
+ p2p_dbg(p2p, "Cancel pending SD query %p", req);
#ifdef ANDROID_P2P
p2p->sd_dev_list = NULL;
#endif
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index 37b9361..0da2682 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -46,11 +46,17 @@
}
-static int p2p_channel_to_freq_j4(int reg_class, int channel)
+/**
+ * p2p_channel_to_freq - Convert channel info to frequency
+ * @op_class: Operating class
+ * @channel: Channel number
+ * Returns: Frequency in MHz or -1 if the specified channel is unknown
+ */
+int p2p_channel_to_freq(int op_class, int channel)
{
- /* Table J-4 in P802.11REVmb/D4.0 - Global operating classes */
- /* TODO: more regulatory classes */
- switch (reg_class) {
+ /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
+ /* TODO: more operating classes */
+ switch (op_class) {
case 81:
/* channels 1..13 */
if (channel < 1 || channel > 13)
@@ -94,75 +100,34 @@
/**
- * p2p_channel_to_freq - Convert channel info to frequency
- * @country: Country code
- * @reg_class: Regulatory class
- * @channel: Channel number
- * Returns: Frequency in MHz or -1 if the specified channel is unknown
- */
-int p2p_channel_to_freq(const char *country, int reg_class, int channel)
-{
- if (country[2] == 0x04)
- return p2p_channel_to_freq_j4(reg_class, channel);
-
- /* These are mainly for backwards compatibility; to be removed */
- switch (reg_class) {
- case 1: /* US/1, EU/1, JP/1 = 5 GHz, channels 36,40,44,48 */
- if (channel < 36 || channel > 48)
- return -1;
- return 5000 + 5 * channel;
- case 3: /* US/3 = 5 GHz, channels 149,153,157,161 */
- case 5: /* US/5 = 5 GHz, channels 149,153,157,161 */
- if (channel < 149 || channel > 161)
- return -1;
- return 5000 + 5 * channel;
- case 4: /* EU/4 = 2.407 GHz, channels 1..13 */
- case 12: /* US/12 = 2.407 GHz, channels 1..11 */
- case 30: /* JP/30 = 2.407 GHz, channels 1..13 */
- if (channel < 1 || channel > 13)
- return -1;
- return 2407 + 5 * channel;
- case 31: /* JP/31 = 2.414 GHz, channel 14 */
- if (channel != 14)
- return -1;
- return 2414 + 5 * channel;
- }
-
- return -1;
-}
-
-
-/**
* p2p_freq_to_channel - Convert frequency into channel info
- * @country: Country code
- * @reg_class: Buffer for returning regulatory class
+ * @op_class: Buffer for returning operating class
* @channel: Buffer for returning channel number
* Returns: 0 on success, -1 if the specified frequency is unknown
*/
-int p2p_freq_to_channel(const char *country, unsigned int freq, u8 *reg_class,
- u8 *channel)
+int p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel)
{
/* TODO: more operating classes */
if (freq >= 2412 && freq <= 2472) {
- *reg_class = 81; /* 2.407 GHz, channels 1..13 */
+ *op_class = 81; /* 2.407 GHz, channels 1..13 */
*channel = (freq - 2407) / 5;
return 0;
}
if (freq == 2484) {
- *reg_class = 82; /* channel 14 */
+ *op_class = 82; /* channel 14 */
*channel = 14;
return 0;
}
if (freq >= 5180 && freq <= 5240) {
- *reg_class = 115; /* 5 GHz, channels 36..48 */
+ *op_class = 115; /* 5 GHz, channels 36..48 */
*channel = (freq - 5000) / 5;
return 0;
}
if (freq >= 5745 && freq <= 5805) {
- *reg_class = 124; /* 5 GHz, channels 149..161 */
+ *op_class = 124; /* 5 GHz, channels 149..161 */
*channel = (freq - 5000) / 5;
return 0;
}
@@ -261,9 +226,8 @@
for (i = 0; i < channels->reg_classes; i++) {
const struct p2p_reg_class *reg = &channels->reg_class[i];
for (j = 0; j < reg->channels; j++) {
- if (p2p_channel_to_freq_j4(reg->reg_class,
- reg->channel[j]) ==
- (int) freq)
+ if (p2p_channel_to_freq(reg->reg_class,
+ reg->channel[j]) == (int) freq)
return 1;
}
}
@@ -274,9 +238,36 @@
int p2p_supported_freq(struct p2p_data *p2p, unsigned int freq)
{
u8 op_reg_class, op_channel;
- if (p2p_freq_to_channel(p2p->cfg->country, freq,
- &op_reg_class, &op_channel) < 0)
+ if (p2p_freq_to_channel(freq, &op_reg_class, &op_channel) < 0)
return 0;
return p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
op_channel);
}
+
+
+unsigned int p2p_get_pref_freq(struct p2p_data *p2p,
+ const struct p2p_channels *channels)
+{
+ unsigned int i;
+ int freq = 0;
+
+ if (channels == NULL) {
+ if (p2p->cfg->num_pref_chan) {
+ freq = p2p_channel_to_freq(
+ p2p->cfg->pref_chan[0].op_class,
+ p2p->cfg->pref_chan[0].chan);
+ if (freq < 0)
+ freq = 0;
+ }
+ return freq;
+ }
+
+ for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) {
+ freq = p2p_channel_to_freq(p2p->cfg->pref_chan[i].op_class,
+ p2p->cfg->pref_chan[i].chan);
+ if (p2p_channels_includes_freq(channels, freq))
+ return freq;
+ }
+
+ return 0;
+}
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index 5b2d711..0144c9f 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -223,6 +223,11 @@
u16 pwd_group;
/**
+ * server_id - Server identity
+ */
+ const char *server_id;
+
+ /**
* wps - Wi-Fi Protected Setup context
*
* If WPS is used with an external RADIUS server (which is quite
@@ -511,6 +516,8 @@
eap_conf.tnc = data->tnc;
eap_conf.wps = data->wps;
eap_conf.pwd_group = data->pwd_group;
+ eap_conf.server_id = (const u8 *) data->server_id;
+ eap_conf.server_id_len = os_strlen(data->server_id);
sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
&eap_conf);
if (sess->eap == NULL) {
@@ -1280,6 +1287,7 @@
data->tnc = conf->tnc;
data->wps = conf->wps;
data->pwd_group = conf->pwd_group;
+ data->server_id = conf->server_id;
if (conf->eap_req_id_text) {
data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
if (data->eap_req_id_text) {
diff --git a/src/radius/radius_server.h b/src/radius/radius_server.h
index 82466c3..284bd59 100644
--- a/src/radius/radius_server.h
+++ b/src/radius/radius_server.h
@@ -144,6 +144,11 @@
u16 pwd_group;
/**
+ * server_id - Server identity
+ */
+ const char *server_id;
+
+ /**
* wps - Wi-Fi Protected Setup context
*
* If WPS is used with an external RADIUS server (which is quite
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index df67583..33fa1a2 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -15,7 +15,7 @@
#include "wpa_i.h"
#include "pmksa_cache.h"
-#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
+#ifdef IEEE8021X_EAPOL
static const int pmksa_cache_max_entries = 32;
@@ -164,17 +164,23 @@
pmksa->pmksa = pos->next;
else
prev->next = pos->next;
- wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for "
- "the current AP");
- pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
/*
* If OKC is used, there may be other PMKSA cache
* entries based on the same PMK. These needs to be
* flushed so that a new entry can be created based on
- * the new PMK.
+ * the new PMK. Only clear other entries if they have a
+ * matching PMK and this PMK has been used successfully
+ * with the current AP, i.e., if opportunistic flag has
+ * been cleared in wpa_supplicant_key_neg_complete().
*/
- pmksa_cache_flush(pmksa, network_ctx);
+ wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for "
+ "the current AP and any PMKSA cache entry "
+ "that was based on the old PMK");
+ if (!pos->opportunistic)
+ pmksa_cache_flush(pmksa, network_ctx, pos->pmk,
+ pos->pmk_len);
+ pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
break;
}
prev = pos;
@@ -235,15 +241,22 @@
* pmksa_cache_flush - Flush PMKSA cache entries for a specific network
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
* @network_ctx: Network configuration context or %NULL to flush all entries
+ * @pmk: PMK to match for or %NYLL to match all PMKs
+ * @pmk_len: PMK length
*/
-void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx)
+void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
+ const u8 *pmk, size_t pmk_len)
{
struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp;
int removed = 0;
entry = pmksa->pmksa;
while (entry) {
- if (entry->network_ctx == network_ctx || network_ctx == NULL) {
+ if ((entry->network_ctx == network_ctx ||
+ network_ctx == NULL) &&
+ (pmk == NULL ||
+ (pmk_len == entry->pmk_len &&
+ os_memcmp(pmk, entry->pmk, pmk_len) == 0))) {
wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry "
"for " MACSTR, MAC2STR(entry->aa));
if (prev)
@@ -509,4 +522,4 @@
return pmksa;
}
-#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
+#endif /* IEEE8021X_EAPOL */
diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h
index 6f3dfb3..6cbf89a 100644
--- a/src/rsn_supp/pmksa_cache.h
+++ b/src/rsn_supp/pmksa_cache.h
@@ -44,7 +44,7 @@
PMKSA_EXPIRE,
};
-#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
+#ifdef IEEE8021X_EAPOL
struct rsn_pmksa_cache *
pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
@@ -66,9 +66,10 @@
struct rsn_pmksa_cache_entry *
pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
void *network_ctx, const u8 *aa);
-void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx);
+void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
+ const u8 *pmk, size_t pmk_len);
-#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
+#else /* IEEE8021X_EAPOL */
static inline struct rsn_pmksa_cache *
pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
@@ -121,10 +122,11 @@
}
static inline void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa,
- void *network_ctx)
+ void *network_ctx,
+ const u8 *pmk, size_t pmk_len)
{
}
-#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
+#endif /* IEEE8021X_EAPOL */
#endif /* PMKSA_CACHE_H */
diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c
index ab61867..c51620e 100644
--- a/src/rsn_supp/preauth.c
+++ b/src/rsn_supp/preauth.c
@@ -18,7 +18,7 @@
#include "wpa_i.h"
-#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
+#ifdef IEEE8021X_EAPOL
#define PMKID_CANDIDATE_PRIO_SCAN 1000
@@ -508,4 +508,4 @@
return sm->preauth_eapol != NULL;
}
-#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
+#endif /* IEEE8021X_EAPOL */
diff --git a/src/rsn_supp/preauth.h b/src/rsn_supp/preauth.h
index 27d3112..277f066 100644
--- a/src/rsn_supp/preauth.h
+++ b/src/rsn_supp/preauth.h
@@ -11,7 +11,7 @@
struct wpa_scan_results;
-#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
+#ifdef IEEE8021X_EAPOL
void pmksa_candidate_free(struct wpa_sm *sm);
int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
@@ -27,7 +27,7 @@
int verbose);
int rsn_preauth_in_progress(struct wpa_sm *sm);
-#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
+#else /* IEEE8021X_EAPOL */
static inline void pmksa_candidate_free(struct wpa_sm *sm)
{
@@ -74,6 +74,6 @@
return 0;
}
-#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
+#endif /* IEEE8021X_EAPOL */
#endif /* PREAUTH_H */
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 8ceaf6c..539aa25 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -37,8 +37,10 @@
#endif /* CONFIG_TDLS_TESTING */
#define TPK_LIFETIME 43200 /* 12 hours */
-#define TPK_RETRY_COUNT 3
-#define TPK_TIMEOUT 5000 /* in milliseconds */
+#define TPK_M1_RETRY_COUNT 3
+#define TPK_M1_TIMEOUT 5000 /* in milliseconds */
+#define TPK_M2_RETRY_COUNT 10
+#define TPK_M2_TIMEOUT 500 /* in milliseconds */
#define TDLS_MIC_LEN 16
@@ -86,6 +88,7 @@
struct wpa_tdls_peer {
struct wpa_tdls_peer *next;
+ unsigned int reconfig_key:1;
int initiator; /* whether this end was initiator for TDLS setup */
u8 addr[ETH_ALEN]; /* other end MAC address */
u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
@@ -126,6 +129,8 @@
u8 qos_info;
+ u16 aid;
+
u8 *ext_capab;
size_t ext_capab_len;
};
@@ -241,8 +246,13 @@
eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
- peer->sm_tmr.count = TPK_RETRY_COUNT;
- peer->sm_tmr.timer = TPK_TIMEOUT;
+ if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
+ peer->sm_tmr.count = TPK_M2_RETRY_COUNT;
+ peer->sm_tmr.timer = TPK_M2_TIMEOUT;
+ } else {
+ peer->sm_tmr.count = TPK_M1_RETRY_COUNT;
+ peer->sm_tmr.timer = TPK_M1_TIMEOUT;
+ }
/* Copy message to resend on timeout */
os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN);
@@ -258,7 +268,8 @@
wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered "
"(action_code=%u)", action_code);
- eloop_register_timeout(peer->sm_tmr.timer / 1000, 0,
+ eloop_register_timeout(peer->sm_tmr.timer / 1000,
+ (peer->sm_tmr.timer % 1000) * 1000,
wpa_tdls_tpk_retry_timeout, sm, peer);
return 0;
}
@@ -293,7 +304,6 @@
if (peer->sm_tmr.count) {
peer->sm_tmr.count--;
- peer->sm_tmr.timer = TPK_TIMEOUT;
wpa_printf(MSG_INFO, "TDLS: Retrying sending of message "
"(action_code=%u)",
@@ -320,7 +330,8 @@
}
eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
- eloop_register_timeout(peer->sm_tmr.timer / 1000, 0,
+ eloop_register_timeout(peer->sm_tmr.timer / 1000,
+ (peer->sm_tmr.timer % 1000) * 1000,
wpa_tdls_tpk_retry_timeout, sm, peer);
} else {
eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
@@ -616,6 +627,7 @@
MAC2STR(peer->addr));
eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
+ peer->reconfig_key = 0;
peer->initiator = 0;
os_free(peer->sm_tmr.buf);
peer->sm_tmr.buf = NULL;
@@ -694,13 +706,8 @@
return -1;
pos = rbuf;
- if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) {
- if (reason_code != WLAN_REASON_DEAUTH_LEAVING) {
- /* Overwrite the reason code */
- reason_code = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
- }
+ if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
goto skip_ies;
- }
ftie = (struct wpa_tdls_ftie *) pos;
ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
@@ -1340,7 +1347,8 @@
peer->supp_rates_len = merge_byte_arrays(
peer->supp_rates, sizeof(peer->supp_rates),
kde->supp_rates + 2, kde->supp_rates_len - 2,
- kde->ext_supp_rates + 2, kde->ext_supp_rates_len - 2);
+ kde->ext_supp_rates ? kde->ext_supp_rates + 2 : NULL,
+ kde->ext_supp_rates_len - 2);
return 0;
}
@@ -1556,6 +1564,8 @@
peer->qos_info = kde.qosinfo;
+ peer->aid = kde.aid;
+
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
peer = wpa_tdls_add_peer(sm, src_addr, NULL);
@@ -1733,7 +1743,7 @@
skip_rsn_check:
/* add the peer to the driver as a "setup in progress" peer */
- wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0,
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
NULL, 0);
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
@@ -1751,7 +1761,7 @@
}
-static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
+static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
{
peer->tpk_success = 1;
eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
@@ -1775,13 +1785,23 @@
}
/* add supported rates, capabilities, and qos_info to the TDLS peer */
- wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
- peer->supp_rates, peer->supp_rates_len,
- peer->ht_capabilities, peer->vht_capabilities,
- peer->qos_info, peer->ext_capab,
- peer->ext_capab_len);
+ if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->aid,
+ peer->capability,
+ peer->supp_rates, peer->supp_rates_len,
+ peer->ht_capabilities,
+ peer->vht_capabilities,
+ peer->qos_info, peer->ext_capab,
+ peer->ext_capab_len) < 0)
+ return -1;
- wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
+ if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
+ wpa_printf(MSG_INFO, "TDLS: Could not configure key to the "
+ "driver");
+ return -1;
+ }
+ peer->reconfig_key = 0;
+
+ return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
}
@@ -1800,6 +1820,7 @@
int ielen;
u16 status;
const u8 *pos;
+ int ret;
wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
"(Peer " MACSTR ")", MAC2STR(src_addr));
@@ -1896,6 +1917,8 @@
peer->qos_info = kde.qosinfo;
+ peer->aid = kde.aid;
+
if (!wpa_tdls_get_privacy(sm)) {
peer->rsnie_p_len = 0;
peer->cipher = WPA_CIPHER_NONE;
@@ -1992,7 +2015,15 @@
return -1;
}
- wpa_tdls_set_key(sm, peer);
+ if (wpa_tdls_set_key(sm, peer) < 0) {
+ /*
+ * Some drivers may not be able to config the key prior to full
+ * STA entry having been configured.
+ */
+ wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
+ "STA entry is complete");
+ peer->reconfig_key = 1;
+ }
skip_rsn:
peer->dtoken = dtoken;
@@ -2001,9 +2032,13 @@
"TPK Handshake Message 3");
wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer);
- wpa_tdls_enable_link(sm, peer);
-
- return 0;
+ ret = wpa_tdls_enable_link(sm, peer);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
+ wpa_tdls_do_teardown(sm, peer,
+ WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, 1);
+ }
+ return ret;
error:
wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken,
@@ -2026,6 +2061,7 @@
u16 status;
const u8 *pos;
u32 lifetime;
+ int ret;
wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
"(Peer " MACSTR ")", MAC2STR(src_addr));
@@ -2136,13 +2172,24 @@
return -1;
}
- if (wpa_tdls_set_key(sm, peer) < 0)
- return -1;
+ if (wpa_tdls_set_key(sm, peer) < 0) {
+ /*
+ * Some drivers may not be able to config the key prior to full
+ * STA entry having been configured.
+ */
+ wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
+ "STA entry is complete");
+ peer->reconfig_key = 1;
+ }
skip_rsn:
- wpa_tdls_enable_link(sm, peer);
-
- return 0;
+ ret = wpa_tdls_enable_link(sm, peer);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
+ wpa_tdls_do_teardown(sm, peer,
+ WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, 1);
+ }
+ return ret;
}
@@ -2199,7 +2246,7 @@
peer->initiator = 1;
/* add the peer to the driver as a "setup in progress" peer */
- wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0,
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
NULL, 0);
if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index e50404c..292255c 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -392,7 +392,6 @@
os_memset(&ie, 0, sizeof(ie));
-#ifndef CONFIG_NO_WPA2
if (sm->proto == WPA_PROTO_RSN) {
/* RSN: msg 1/4 should contain PMKID for the selected PMK */
const u8 *_buf = (const u8 *) (key + 1);
@@ -405,7 +404,6 @@
"Authenticator", ie.pmkid, PMKID_LEN);
}
}
-#endif /* CONFIG_NO_WPA2 */
res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
if (res == -2) {
@@ -664,7 +662,6 @@
const u8 *gtk, size_t gtk_len,
int key_info)
{
-#ifndef CONFIG_NO_WPA2
struct wpa_gtk_data gd;
/*
@@ -703,9 +700,6 @@
wpa_supplicant_key_neg_complete(sm, sm->bssid,
key_info & WPA_KEY_INFO_SECURE);
return 0;
-#else /* CONFIG_NO_WPA2 */
- return -1;
-#endif /* CONFIG_NO_WPA2 */
}
@@ -2412,6 +2406,21 @@
}
+int wpa_sm_pmf_enabled(struct wpa_sm *sm)
+{
+ struct wpa_ie_data rsn;
+
+ if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
+ return 0;
+
+ if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
+ rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
+ return 1;
+
+ return 0;
+}
+
+
/**
* wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -2586,11 +2595,7 @@
int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
{
-#ifndef CONFIG_NO_WPA2
return pmksa_cache_list(sm->pmksa, buf, len);
-#else /* CONFIG_NO_WPA2 */
- return -1;
-#endif /* CONFIG_NO_WPA2 */
}
@@ -2621,9 +2626,7 @@
void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
{
-#ifndef CONFIG_NO_WPA2
- pmksa_cache_flush(sm->pmksa, network_ctx);
-#endif /* CONFIG_NO_WPA2 */
+ pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
}
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index dbb493e..26e9c6c 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -56,7 +56,7 @@
u8 action_code, u8 dialog_token,
u16 status_code, const u8 *buf, size_t len);
int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
- int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add,
+ int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid,
u16 capability, const u8 *supp_rates,
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
@@ -123,6 +123,7 @@
int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
int verbose);
+int wpa_sm_pmf_enabled(struct wpa_sm *sm);
void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise);
@@ -244,6 +245,11 @@
return 0;
}
+static inline int wpa_sm_pmf_enabled(struct wpa_sm *sm)
+{
+ return 0;
+}
+
static inline void wpa_sm_key_request(struct wpa_sm *sm, int error,
int pairwise)
{
@@ -315,6 +321,7 @@
int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len);
int wpa_ft_is_completed(struct wpa_sm *sm);
+void wpa_reset_ft_completed(struct wpa_sm *sm);
int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
size_t ies_len, const u8 *src_addr);
int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
@@ -346,6 +353,10 @@
return 0;
}
+static inline void wpa_reset_ft_completed(struct wpa_sm *sm)
+{
+}
+
static inline int
wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
const u8 *src_addr)
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 4b08a62..3a40c96 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -534,6 +534,13 @@
}
+void wpa_reset_ft_completed(struct wpa_sm *sm)
+{
+ if (sm != NULL)
+ sm->ft_completed = 0;
+}
+
+
static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
size_t gtk_elem_len)
{
@@ -589,6 +596,13 @@
}
wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
+ if (sm->group_cipher == WPA_CIPHER_TKIP) {
+ /* Swap Tx/Rx keys for Michael MIC */
+ u8 tmp[8];
+ os_memcpy(tmp, gtk + 16, 8);
+ os_memcpy(gtk + 16, gtk + 24, 8);
+ os_memcpy(gtk + 24, tmp, 8);
+ }
if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 877e6de..0e0d373 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -282,7 +282,7 @@
static inline int
wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
- u16 capability, const u8 *supp_rates,
+ u16 aid, u16 capability, const u8 *supp_rates,
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
@@ -290,7 +290,7 @@
{
if (sm->ctx->tdls_peer_addset)
return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
- capability, supp_rates,
+ aid, capability, supp_rates,
supp_rates_len, ht_capab,
vht_capab, qosinfo,
ext_capab, ext_capab_len);
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 652197f..50b9272 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -107,7 +107,6 @@
int key_mgmt, int mgmt_group_cipher,
struct wpa_sm *sm)
{
-#ifndef CONFIG_NO_WPA2
u8 *pos;
struct rsn_ie_hdr *hdr;
u16 capab;
@@ -220,9 +219,6 @@
WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);
return pos - rsn_ie;
-#else /* CONFIG_NO_WPA2 */
- return -1;
-#endif /* CONFIG_NO_WPA2 */
}
@@ -430,6 +426,9 @@
} else if (*pos == WLAN_EID_HT_CAP) {
ie->ht_capabilities = pos + 2;
ie->ht_capabilities_len = pos[1];
+ } else if (*pos == WLAN_EID_VHT_AID) {
+ if (pos[1] >= 2)
+ ie->aid = WPA_GET_LE16(pos + 2);
} else if (*pos == WLAN_EID_VHT_CAP) {
ie->vht_capabilities = pos + 2;
ie->vht_capabilities_len = pos[1];
diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h
index 82a5c08..2c78801 100644
--- a/src/rsn_supp/wpa_ie.h
+++ b/src/rsn_supp/wpa_ie.h
@@ -54,6 +54,7 @@
const u8 *vht_capabilities;
size_t vht_capabilities_len;
u8 qosinfo;
+ u16 aid;
};
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
diff --git a/src/tls/x509v3.c b/src/tls/x509v3.c
index 87c5178..06540bf 100644
--- a/src/tls/x509v3.c
+++ b/src/tls/x509v3.c
@@ -443,17 +443,16 @@
return -1;
}
- val = os_malloc(hdr.length + 1);
+ val = dup_binstr(hdr.payload, hdr.length);
if (val == NULL) {
x509_free_name(name);
return -1;
}
- os_memcpy(val, hdr.payload, hdr.length);
- val[hdr.length] = '\0';
if (os_strlen(val) != hdr.length) {
wpa_printf(MSG_INFO, "X509: Reject certificate with "
"embedded NUL byte in a string (%s[NUL])",
val);
+ os_free(val);
x509_free_name(name);
return -1;
}
diff --git a/src/utils/Makefile b/src/utils/Makefile
index 0f1f191..940b4d8 100644
--- a/src/utils/Makefile
+++ b/src/utils/Makefile
@@ -14,6 +14,7 @@
LIB_OBJS= \
base64.o \
+ bitfield.o \
common.o \
ip_addr.o \
radiotap.o \
diff --git a/src/utils/bitfield.c b/src/utils/bitfield.c
new file mode 100644
index 0000000..f90e4be
--- /dev/null
+++ b/src/utils/bitfield.c
@@ -0,0 +1,89 @@
+/*
+ * Bitfield
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "bitfield.h"
+
+
+struct bitfield {
+ u8 *bits;
+ size_t max_bits;
+};
+
+
+struct bitfield * bitfield_alloc(size_t max_bits)
+{
+ struct bitfield *bf;
+
+ bf = os_zalloc(sizeof(*bf) + (max_bits + 7) / 8);
+ if (bf == NULL)
+ return NULL;
+ bf->bits = (u8 *) (bf + 1);
+ bf->max_bits = max_bits;
+ return bf;
+}
+
+
+void bitfield_free(struct bitfield *bf)
+{
+ os_free(bf);
+}
+
+
+void bitfield_set(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return;
+ bf->bits[bit / 8] |= BIT(bit % 8);
+}
+
+
+void bitfield_clear(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return;
+ bf->bits[bit / 8] &= ~BIT(bit % 8);
+}
+
+
+int bitfield_is_set(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return 0;
+ return !!(bf->bits[bit / 8] & BIT(bit % 8));
+}
+
+
+static int first_zero(u8 val)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (!(val & 0x01))
+ return i;
+ val >>= 1;
+ }
+ return -1;
+}
+
+
+int bitfield_get_first_zero(struct bitfield *bf)
+{
+ size_t i;
+ for (i = 0; i <= (bf->max_bits + 7) / 8; i++) {
+ if (bf->bits[i] != 0xff)
+ break;
+ }
+ if (i > (bf->max_bits + 7) / 8)
+ return -1;
+ i = i * 8 + first_zero(bf->bits[i]);
+ if (i >= bf->max_bits)
+ return -1;
+ return i;
+}
diff --git a/src/utils/bitfield.h b/src/utils/bitfield.h
new file mode 100644
index 0000000..7050a20
--- /dev/null
+++ b/src/utils/bitfield.h
@@ -0,0 +1,21 @@
+/*
+ * Bitfield
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BITFIELD_H
+#define BITFIELD_H
+
+struct bitfield;
+
+struct bitfield * bitfield_alloc(size_t max_bits);
+void bitfield_free(struct bitfield *bf);
+void bitfield_set(struct bitfield *bf, size_t bit);
+void bitfield_clear(struct bitfield *bf, size_t bit);
+int bitfield_is_set(struct bitfield *bf, size_t bit);
+int bitfield_get_first_zero(struct bitfield *bf);
+
+#endif /* BITFIELD_H */
diff --git a/src/utils/build_config.h b/src/utils/build_config.h
index f947388..c6f4e43 100644
--- a/src/utils/build_config.h
+++ b/src/utils/build_config.h
@@ -47,31 +47,4 @@
#endif /* USE_INTERNAL_CRYPTO */
#endif /* CONFIG_WIN32_DEFAULTS */
-#ifdef CONFIG_XCODE_DEFAULTS
-#define CONFIG_DRIVER_OSX
-#define CONFIG_BACKEND_FILE
-#define IEEE8021X_EAPOL
-#define PKCS12_FUNCS
-#define CONFIG_CTRL_IFACE
-#define CONFIG_CTRL_IFACE_UNIX
-#define CONFIG_DEBUG_FILE
-#define EAP_MD5
-#define EAP_TLS
-#define EAP_MSCHAPv2
-#define EAP_PEAP
-#define EAP_TTLS
-#define EAP_GTC
-#define EAP_OTP
-#define EAP_LEAP
-#define EAP_TNC
-#define CONFIG_WPS
-#define EAP_WSC
-
-#ifdef USE_INTERNAL_CRYPTO
-#define CONFIG_TLS_INTERNAL_CLIENT
-#define CONFIG_INTERNAL_LIBTOMMATH
-#define CONFIG_CRYPTO_INTERNAL
-#endif /* USE_INTERNAL_CRYPTO */
-#endif /* CONFIG_XCODE_DEFAULTS */
-
#endif /* BUILD_CONFIG_H */
diff --git a/src/utils/common.c b/src/utils/common.c
index e636984..bf326cd 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -517,11 +517,9 @@
if (pos == NULL || pos[1] != '\0')
return NULL;
*len = pos - value;
- str = os_malloc(*len + 1);
+ str = dup_binstr(value, *len);
if (str == NULL)
return NULL;
- os_memcpy(str, value, *len);
- str[*len] = '\0';
return str;
} else if (*value == 'P' && value[1] == '"') {
const char *pos;
@@ -532,11 +530,9 @@
if (pos == NULL || pos[1] != '\0')
return NULL;
tlen = pos - value;
- tstr = os_malloc(tlen + 1);
+ tstr = dup_binstr(value, tlen);
if (tstr == NULL)
return NULL;
- os_memcpy(tstr, value, tlen);
- tstr[tlen] = '\0';
str = os_malloc(tlen + 1);
if (str == NULL) {
@@ -610,3 +606,19 @@
return len;
}
+
+
+char * dup_binstr(const void *src, size_t len)
+{
+ char *res;
+
+ if (src == NULL)
+ return NULL;
+ res = os_malloc(len + 1);
+ if (res == NULL)
+ return NULL;
+ os_memcpy(res, src, len);
+ res[len] = '\0';
+
+ return res;
+}
diff --git a/src/utils/common.h b/src/utils/common.h
index a859042..e4f7031 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -487,6 +487,7 @@
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len);
+char * dup_binstr(const void *src, size_t len);
static inline int is_zero_ether_addr(const u8 *a)
{
diff --git a/src/utils/edit.c b/src/utils/edit.c
index b01e08d..177ecf4 100644
--- a/src/utils/edit.c
+++ b/src/utils/edit.c
@@ -345,7 +345,7 @@
static void process_cmd(void)
{
-
+ currbuf_valid = 0;
if (cmdbuf_len == 0) {
printf("\n%s> ", ps2 ? ps2 : "");
fflush(stdout);
diff --git a/src/utils/edit_readline.c b/src/utils/edit_readline.c
index add26fa..c2a5bca 100644
--- a/src/utils/edit_readline.c
+++ b/src/utils/edit_readline.c
@@ -167,9 +167,9 @@
if (filter_cb && filter_cb(edit_cb_ctx, p)) {
h = remove_history(where_history());
if (h) {
- os_free(h->line);
+ free(h->line);
free(h->data);
- os_free(h);
+ free(h);
} else
next_history();
} else
diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index 2de3e01..f62e2b7 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -799,6 +799,7 @@
#endif /* CONFIG_ELOOP_POLL */
}
+ eloop.terminate = 0;
out:
#ifndef CONFIG_ELOOP_POLL
os_free(rfds);
diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c
index 5511ef1..38ea8aa 100644
--- a/src/utils/wpa_debug.c
+++ b/src/utils/wpa_debug.c
@@ -1,6 +1,6 @@
/*
* wpa_supplicant/hostapd / Debug prints
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -620,7 +620,7 @@
va_end(ap);
wpa_printf(level, "%s%s", prefix, buf);
if (wpa_msg_cb)
- wpa_msg_cb(ctx, level, buf, len);
+ wpa_msg_cb(ctx, level, 0, buf, len);
os_free(buf);
}
@@ -644,9 +644,56 @@
va_start(ap, fmt);
len = vsnprintf(buf, buflen, fmt, ap);
va_end(ap);
- wpa_msg_cb(ctx, level, buf, len);
+ wpa_msg_cb(ctx, level, 0, buf, len);
os_free(buf);
}
+
+
+void wpa_msg_global(void *ctx, int level, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ const int buflen = 2048;
+ int len;
+
+ buf = os_malloc(buflen);
+ if (buf == NULL) {
+ wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate "
+ "message buffer");
+ return;
+ }
+ va_start(ap, fmt);
+ len = vsnprintf(buf, buflen, fmt, ap);
+ va_end(ap);
+ wpa_printf(level, "%s", buf);
+ if (wpa_msg_cb)
+ wpa_msg_cb(ctx, level, 1, buf, len);
+ os_free(buf);
+}
+
+
+void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ const int buflen = 2048;
+ int len;
+
+ buf = os_malloc(buflen);
+ if (buf == NULL) {
+ wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate "
+ "message buffer");
+ return;
+ }
+ va_start(ap, fmt);
+ len = vsnprintf(buf, buflen, fmt, ap);
+ va_end(ap);
+ wpa_printf(level, "%s", buf);
+ if (wpa_msg_cb)
+ wpa_msg_cb(ctx, level, 2, buf, len);
+ os_free(buf);
+}
+
#endif /* CONFIG_NO_WPA_MSG */
diff --git a/src/utils/wpa_debug.h b/src/utils/wpa_debug.h
index 339c749..2ed1bd8 100644
--- a/src/utils/wpa_debug.h
+++ b/src/utils/wpa_debug.h
@@ -1,6 +1,6 @@
/*
* wpa_supplicant/hostapd / Debug prints
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -155,6 +155,8 @@
#ifdef CONFIG_NO_WPA_MSG
#define wpa_msg(args...) do { } while (0)
#define wpa_msg_ctrl(args...) do { } while (0)
+#define wpa_msg_global(args...) do { } while (0)
+#define wpa_msg_no_global(args...) do { } while (0)
#define wpa_msg_register_cb(f) do { } while (0)
#define wpa_msg_register_ifname_cb(f) do { } while (0)
#else /* CONFIG_NO_WPA_MSG */
@@ -189,8 +191,38 @@
void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
PRINTF_FORMAT(3, 4);
-typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt,
- size_t len);
+/**
+ * wpa_msg_global - Global printf for ctrl_iface monitors
+ * @ctx: Pointer to context data; this is the ctx variable registered
+ * with struct wpa_driver_ops::init()
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages.
+ * This function is like wpa_msg(), but it sends the output as a global event,
+ * i.e., without being specific to an interface. For backwards compatibility,
+ * an old style event is also delivered on one of the interfaces (the one
+ * specified by the context data).
+ */
+void wpa_msg_global(void *ctx, int level, const char *fmt, ...)
+PRINTF_FORMAT(3, 4);
+
+/**
+ * wpa_msg_no_global - Conditional printf for ctrl_iface monitors
+ * @ctx: Pointer to context data; this is the ctx variable registered
+ * with struct wpa_driver_ops::init()
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages.
+ * This function is like wpa_msg(), but it does not send the output as a global
+ * event.
+ */
+void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...)
+PRINTF_FORMAT(3, 4);
+
+typedef void (*wpa_msg_cb_func)(void *ctx, int level, int global,
+ const char *txt, size_t len);
/**
* wpa_msg_register_cb - Register callback function for wpa_msg() messages
diff --git a/src/wps/http_client.c b/src/wps/http_client.c
index c6d6c7f..0290013 100644
--- a/src/wps/http_client.c
+++ b/src/wps/http_client.c
@@ -92,7 +92,7 @@
(unsigned long) wpabuf_len(c->req),
(unsigned long) wpabuf_len(c->req) - c->req_pos);
- res = send(c->sd, wpabuf_head(c->req) + c->req_pos,
+ res = send(c->sd, wpabuf_head_u8(c->req) + c->req_pos,
wpabuf_len(c->req) - c->req_pos, 0);
if (res < 0) {
wpa_printf(MSG_DEBUG, "HTTP: Failed to send buffer: %s",
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index edcc18c..ac9bb1e 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -417,3 +417,14 @@
return ie;
}
+
+
+int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")",
+ MAC2STR(addr));
+ wpabuf_put_be16(msg, ATTR_MAC_ADDR);
+ wpabuf_put_be16(msg, ETH_ALEN);
+ wpabuf_put_data(msg, addr, ETH_ALEN);
+ return 0;
+}
diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
index 0897b7b..4e4da5e 100644
--- a/src/wps/wps_common.c
+++ b/src/wps/wps_common.c
@@ -343,10 +343,36 @@
if (wps_build_version(plain) ||
wps_build_cred(&data, plain) ||
wps_build_wfa_ext(plain, 0, NULL, 0)) {
+ os_free(data.new_psk);
wpabuf_free(plain);
return NULL;
}
+ if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk &&
+ wps->ap) {
+ struct wps_credential cred;
+
+ wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based "
+ "on credential token generation");
+
+ os_memset(&cred, 0, sizeof(cred));
+ os_memcpy(cred.ssid, wps->ssid, wps->ssid_len);
+ cred.ssid_len = wps->ssid_len;
+ cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK;
+ cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES;
+ os_memcpy(cred.key, data.new_psk, data.new_psk_len);
+ cred.key_len = data.new_psk_len;
+
+ wps->wps_state = WPS_STATE_CONFIGURED;
+ wpa_hexdump_ascii_key(MSG_DEBUG,
+ "WPS: Generated random passphrase",
+ data.new_psk, data.new_psk_len);
+ if (wps->cred_cb)
+ wps->cred_cb(wps->cb_ctx, &cred);
+ }
+
+ os_free(data.new_psk);
+
return plain;
}
diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c
index 3c94a43..7a7c099 100644
--- a/src/wps/wps_dev_attr.c
+++ b/src/wps/wps_dev_attr.c
@@ -257,11 +257,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
os_free(dev->manufacturer);
- dev->manufacturer = os_malloc(str_len + 1);
+ dev->manufacturer = dup_binstr(str, str_len);
if (dev->manufacturer == NULL)
return -1;
- os_memcpy(dev->manufacturer, str, str_len);
- dev->manufacturer[str_len] = '\0';
return 0;
}
@@ -278,11 +276,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
os_free(dev->model_name);
- dev->model_name = os_malloc(str_len + 1);
+ dev->model_name = dup_binstr(str, str_len);
if (dev->model_name == NULL)
return -1;
- os_memcpy(dev->model_name, str, str_len);
- dev->model_name[str_len] = '\0';
return 0;
}
@@ -299,11 +295,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
os_free(dev->model_number);
- dev->model_number = os_malloc(str_len + 1);
+ dev->model_number = dup_binstr(str, str_len);
if (dev->model_number == NULL)
return -1;
- os_memcpy(dev->model_number, str, str_len);
- dev->model_number[str_len] = '\0';
return 0;
}
@@ -320,11 +314,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
os_free(dev->serial_number);
- dev->serial_number = os_malloc(str_len + 1);
+ dev->serial_number = dup_binstr(str, str_len);
if (dev->serial_number == NULL)
return -1;
- os_memcpy(dev->serial_number, str, str_len);
- dev->serial_number[str_len] = '\0';
return 0;
}
@@ -341,11 +333,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
os_free(dev->device_name);
- dev->device_name = os_malloc(str_len + 1);
+ dev->device_name = dup_binstr(str, str_len);
if (dev->device_name == NULL)
return -1;
- os_memcpy(dev->device_name, str, str_len);
- dev->device_name[str_len] = '\0';
return 0;
}
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index 9c0cebb..27c554f 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -16,16 +16,6 @@
#include "wps_dev_attr.h"
-static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * MAC Address");
- wpabuf_put_be16(msg, ATTR_MAC_ADDR);
- wpabuf_put_be16(msg, ETH_ALEN);
- wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN);
- return 0;
-}
-
-
static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg)
{
u8 state;
@@ -149,7 +139,7 @@
if (wps_build_version(msg) ||
wps_build_msg_type(msg, WPS_M1) ||
wps_build_uuid_e(msg, wps->uuid_e) ||
- wps_build_mac_addr(wps, msg) ||
+ wps_build_mac_addr(msg, wps->mac_addr_e) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_public_key(wps, msg) ||
wps_build_auth_type_flags(wps, msg) ||
@@ -852,6 +842,24 @@
return 0;
}
+#ifdef CONFIG_P2P
+ if ((id == DEV_PW_DEFAULT &&
+ wps->dev_pw_id == DEV_PW_REGISTRAR_SPECIFIED) ||
+ (id == DEV_PW_REGISTRAR_SPECIFIED &&
+ wps->dev_pw_id == DEV_PW_DEFAULT)) {
+ /*
+ * Common P2P use cases indicate whether the PIN is from the
+ * client or GO using Device Password Id in M1/M2 in a way that
+ * does not look fully compliant with WSC specification. Anyway,
+ * this is deployed and needs to be allowed, so ignore changes
+ * between Registrar-Specified and Default PIN.
+ */
+ wpa_printf(MSG_DEBUG, "WPS: Allow PIN Device Password ID "
+ "change");
+ return 0;
+ }
+#endif /* CONFIG_P2P */
+
wpa_printf(MSG_DEBUG, "WPS: Registrar trying to change Device Password "
"ID from %u to %u", wps->dev_pw_id, id);
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 14c1b77..5694997 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -796,52 +796,31 @@
if (attr->manufacturer) {
os_free(sta->manufacturer);
- sta->manufacturer = os_malloc(attr->manufacturer_len + 1);
- if (sta->manufacturer) {
- os_memcpy(sta->manufacturer, attr->manufacturer,
- attr->manufacturer_len);
- sta->manufacturer[attr->manufacturer_len] = '\0';
- }
+ sta->manufacturer = dup_binstr(attr->manufacturer,
+ attr->manufacturer_len);
}
if (attr->model_name) {
os_free(sta->model_name);
- sta->model_name = os_malloc(attr->model_name_len + 1);
- if (sta->model_name) {
- os_memcpy(sta->model_name, attr->model_name,
- attr->model_name_len);
- sta->model_name[attr->model_name_len] = '\0';
- }
+ sta->model_name = dup_binstr(attr->model_name,
+ attr->model_name_len);
}
if (attr->model_number) {
os_free(sta->model_number);
- sta->model_number = os_malloc(attr->model_number_len + 1);
- if (sta->model_number) {
- os_memcpy(sta->model_number, attr->model_number,
- attr->model_number_len);
- sta->model_number[attr->model_number_len] = '\0';
- }
+ sta->model_number = dup_binstr(attr->model_number,
+ attr->model_number_len);
}
if (attr->serial_number) {
os_free(sta->serial_number);
- sta->serial_number = os_malloc(attr->serial_number_len + 1);
- if (sta->serial_number) {
- os_memcpy(sta->serial_number, attr->serial_number,
- attr->serial_number_len);
- sta->serial_number[attr->serial_number_len] = '\0';
- }
+ sta->serial_number = dup_binstr(attr->serial_number,
+ attr->serial_number_len);
}
if (attr->dev_name) {
os_free(sta->dev_name);
- sta->dev_name = os_malloc(attr->dev_name_len + 1);
- if (sta->dev_name) {
- os_memcpy(sta->dev_name, attr->dev_name,
- attr->dev_name_len);
- sta->dev_name[attr->dev_name_len] = '\0';
- }
+ sta->dev_name = dup_binstr(attr->dev_name, attr->dev_name_len);
}
eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
@@ -1292,6 +1271,22 @@
/* Limit event_id to < 32 bits to avoid issues with atoi() */
er->event_id &= 0x0fffffff;
+ if (filter && os_strncmp(filter, "ifname=", 7) == 0) {
+ const char *pos, *end;
+ pos = filter + 7;
+ end = os_strchr(pos, ' ');
+ if (end) {
+ size_t len = end - pos;
+ os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ?
+ len + 1 : sizeof(er->ifname));
+ filter = end + 1;
+ } else {
+ os_strlcpy(er->ifname, pos, sizeof(er->ifname));
+ filter = NULL;
+ }
+ er->forced_ifname = 1;
+ }
+
if (filter) {
if (inet_aton(filter, &er->filter_addr) == 0) {
wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter "
@@ -1302,10 +1297,10 @@
wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections "
"with %s", filter);
}
- if (get_netif_info(ifname, &er->ip_addr, &er->ip_addr_text,
+ if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text,
er->mac_addr)) {
wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
- "for %s. Does it have IP address?", ifname);
+ "for %s. Does it have IP address?", er->ifname);
wps_er_deinit(er, NULL, NULL);
return NULL;
}
diff --git a/src/wps/wps_er.h b/src/wps/wps_er.h
index 6119647..4b48ff6 100644
--- a/src/wps/wps_er.h
+++ b/src/wps/wps_er.h
@@ -76,6 +76,7 @@
struct wps_er {
struct wps_context *wps;
char ifname[17];
+ int forced_ifname;
u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */
char *ip_addr_text; /* IP address of network i.f. we use */
unsigned ip_addr; /* IP address of network i.f. we use (host order) */
diff --git a/src/wps/wps_er_ssdp.c b/src/wps/wps_er_ssdp.c
index f9f6e6c..e381fec 100644
--- a/src/wps/wps_er_ssdp.c
+++ b/src/wps/wps_er_ssdp.c
@@ -166,7 +166,9 @@
return -1;
}
- er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr);
+ er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr,
+ er->forced_ifname ?
+ er->ifname : NULL);
if (er->multicast_sd < 0) {
wpa_printf(MSG_INFO, "WPS ER: Failed to open multicast socket "
"for SSDP");
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 6efc3bf..413379b 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -169,6 +169,7 @@
const struct wpabuf *pubkey, const u8 *dev_pw,
size_t dev_pw_len);
struct wpabuf * wps_ie_encapsulate(struct wpabuf *data);
+int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr);
/* wps_attr_process.c */
int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
@@ -196,7 +197,8 @@
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg);
int wps_device_store(struct wps_registrar *reg,
struct wps_device_data *dev, const u8 *uuid);
-void wps_registrar_selected_registrar_changed(struct wps_registrar *reg);
+void wps_registrar_selected_registrar_changed(struct wps_registrar *reg,
+ u16 dev_pw_id);
const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count);
int wps_registrar_pbc_overlap(struct wps_registrar *reg,
const u8 *addr, const u8 *uuid_e);
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 86ef022..d182f14 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -771,7 +771,7 @@
else
wps_registrar_add_authorized_mac(
reg, (u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
wps_registrar_set_selected_timeout,
@@ -793,7 +793,7 @@
addr = pin->enrollee_addr;
wps_registrar_remove_authorized_mac(reg, addr);
wps_remove_pin(pin);
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -956,7 +956,7 @@
os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
wps_registrar_remove_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -1004,7 +1004,7 @@
os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
wps_registrar_add_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
@@ -1027,7 +1027,7 @@
wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar");
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
reg->selected_registrar = 0;
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -1531,18 +1531,6 @@
}
-static int wps_build_cred_mac_addr(struct wpabuf *msg,
- const struct wps_credential *cred)
-{
- wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")",
- MAC2STR(cred->mac_addr));
- wpabuf_put_be16(msg, ATTR_MAC_ADDR);
- wpabuf_put_be16(msg, ETH_ALEN);
- wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN);
- return 0;
-}
-
-
static int wps_build_credential(struct wpabuf *msg,
const struct wps_credential *cred)
{
@@ -1551,7 +1539,7 @@
wps_build_cred_auth_type(msg, cred) ||
wps_build_cred_encr_type(msg, cred) ||
wps_build_cred_network_key(msg, cred) ||
- wps_build_cred_mac_addr(msg, cred))
+ wps_build_mac_addr(msg, cred->mac_addr))
return -1;
return 0;
}
@@ -3296,7 +3284,7 @@
"unselect internal Registrar");
reg->selected_registrar = 0;
reg->pbc = 0;
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -3368,7 +3356,8 @@
* This function is called when selected registrar state changes, e.g., when an
* AP receives a SetSelectedRegistrar UPnP message.
*/
-void wps_registrar_selected_registrar_changed(struct wps_registrar *reg)
+void wps_registrar_selected_registrar_changed(struct wps_registrar *reg,
+ u16 dev_pw_id)
{
wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed");
@@ -3392,7 +3381,8 @@
reg->sel_reg_dev_password_id_override =
DEV_PW_PUSHBUTTON;
wps_set_pushbutton(&methods, reg->wps->config_methods);
- }
+ } else if (dev_pw_id)
+ reg->sel_reg_dev_password_id_override = dev_pw_id;
wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected "
"(pbc=%d)", reg->pbc);
reg->sel_reg_config_methods_override = methods;
@@ -3514,12 +3504,15 @@
reg->pbc = 0;
wps_registrar_add_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, pw_id);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
wps_registrar_set_selected_timeout,
reg, NULL);
+ wpa_printf(MSG_DEBUG, "WPS: Added NFC Device Password %u to Registrar",
+ pw_id);
+
return 0;
}
@@ -3561,7 +3554,7 @@
{
wps_registrar_remove_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
#endif /* CONFIG_WPS_NFC */
diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c
index 09a46a2..bea2b33 100644
--- a/src/wps/wps_upnp.c
+++ b/src/wps/wps_upnp.c
@@ -322,11 +322,9 @@
url_len -= 7;
/* Make a copy of the string to allow modification during parsing */
- scratch_mem = os_malloc(url_len + 1);
+ scratch_mem = dup_binstr(url, url_len);
if (scratch_mem == NULL)
goto fail;
- os_memcpy(scratch_mem, url, url_len);
- scratch_mem[url_len] = '\0';
wpa_printf(MSG_DEBUG, "WPS UPnP: Adding URL '%s'", scratch_mem);
host = scratch_mem;
path = os_strchr(host, '/');
@@ -984,6 +982,7 @@
wpa_printf(MSG_DEBUG, "WPS UPnP: Stop device");
web_listener_stop(sm);
+ ssdp_listener_stop(sm);
upnp_wps_free_msearchreply(&sm->msearch_replies);
upnp_wps_free_subscriptions(&sm->subscriptions, NULL);
@@ -997,7 +996,6 @@
if (sm->multicast_sd >= 0)
close(sm->multicast_sd);
sm->multicast_sd = -1;
- ssdp_listener_stop(sm);
sm->started = 0;
}
diff --git a/src/wps/wps_upnp_ap.c b/src/wps/wps_upnp_ap.c
index 54ed98f..4f1dd8f 100644
--- a/src/wps/wps_upnp_ap.c
+++ b/src/wps/wps_upnp_ap.c
@@ -22,7 +22,7 @@
struct wps_registrar *reg = timeout_ctx;
wpa_printf(MSG_DEBUG, "WPS: SetSelectedRegistrar from ER timed out");
s->selected_registrar = 0;
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -71,7 +71,7 @@
upnp_er_set_selected_timeout, s, reg);
}
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
return 0;
}
@@ -83,5 +83,5 @@
s->selected_registrar = 0;
eloop_cancel_timeout(upnp_er_set_selected_timeout, s, reg);
if (reg)
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h
index 7f3c561..5c39f7e 100644
--- a/src/wps/wps_upnp_i.h
+++ b/src/wps/wps_upnp_i.h
@@ -171,7 +171,7 @@
int ssdp_listener_start(struct upnp_wps_device_sm *sm);
int ssdp_listener_open(void);
int add_ssdp_network(const char *net_if);
-int ssdp_open_multicast_sock(u32 ip_addr);
+int ssdp_open_multicast_sock(u32 ip_addr, const char *forced_ifname);
int ssdp_open_multicast(struct upnp_wps_device_sm *sm);
/* wps_upnp_web.c */
diff --git a/src/wps/wps_upnp_ssdp.c b/src/wps/wps_upnp_ssdp.c
index 17a8207..416961c 100644
--- a/src/wps/wps_upnp_ssdp.c
+++ b/src/wps/wps_upnp_ssdp.c
@@ -3,7 +3,7 @@
* Copyright (c) 2000-2003 Intel Corporation
* Copyright (c) 2006-2007 Sony Corporation
* Copyright (c) 2008-2009 Atheros Communications
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi>
*
* See wps_upnp.c for more details on licensing and code history.
*/
@@ -13,6 +13,9 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/route.h>
+#ifdef __linux__
+#include <net/if.h>
+#endif /* __linux__ */
#include "common.h"
#include "uuid.h"
@@ -854,7 +857,7 @@
}
-int ssdp_open_multicast_sock(u32 ip_addr)
+int ssdp_open_multicast_sock(u32 ip_addr, const char *forced_ifname)
{
int sd;
/* per UPnP-arch-DeviceArchitecture, 1. Discovery, keep IP packet
@@ -865,6 +868,22 @@
if (sd < 0)
return -1;
+ if (forced_ifname) {
+#ifdef __linux__
+ struct ifreq req;
+ os_memset(&req, 0, sizeof(req));
+ os_strlcpy(req.ifr_name, forced_ifname, sizeof(req.ifr_name));
+ if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, &req,
+ sizeof(req)) < 0) {
+ wpa_printf(MSG_INFO, "WPS UPnP: Failed to bind "
+ "multicast socket to ifname %s: %s",
+ forced_ifname, strerror(errno));
+ close(sd);
+ return -1;
+ }
+#endif /* __linux__ */
+ }
+
#if 0 /* maybe ok if we sometimes block on writes */
if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) {
close(sd);
@@ -924,7 +943,7 @@
*/
int ssdp_open_multicast(struct upnp_wps_device_sm *sm)
{
- sm->multicast_sd = ssdp_open_multicast_sock(sm->ip_addr);
+ sm->multicast_sd = ssdp_open_multicast_sock(sm->ip_addr, NULL);
if (sm->multicast_sd < 0)
return -1;
return 0;
diff --git a/src/wps/wps_upnp_web.c b/src/wps/wps_upnp_web.c
index ce0bede..11386d8 100644
--- a/src/wps/wps_upnp_web.c
+++ b/src/wps/wps_upnp_web.c
@@ -996,13 +996,11 @@
h++;
len = end - h;
os_free(callback_urls);
- callback_urls = os_malloc(len + 1);
+ callback_urls = dup_binstr(h, len);
if (callback_urls == NULL) {
ret = HTTP_INTERNAL_SERVER_ERROR;
goto error;
}
- os_memcpy(callback_urls, h, len);
- callback_urls[len] = 0;
continue;
}
/* SID is only for renewal */
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index a0c97f0..8515b5a 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -236,7 +236,7 @@
NEED_MD5=y
NEED_RC4=y
else
-L_CFLAGS += -DCONFIG_NO_WPA -DCONFIG_NO_WPA2
+L_CFLAGS += -DCONFIG_NO_WPA
endif
ifdef CONFIG_IBSS_RSN
@@ -286,10 +286,6 @@
NEED_GAS=y
endif
-ifdef CONFIG_NO_WPA2
-L_CFLAGS += -DCONFIG_NO_WPA2
-endif
-
include $(LOCAL_PATH)/src/drivers/drivers.mk
ifdef CONFIG_AP
@@ -601,6 +597,22 @@
NEED_SHA256=y
endif
+ifdef CONFIG_EAP_EKE
+# EAP-EKE
+ifeq ($(CONFIG_EAP_EKE), dyn)
+L_CFLAGS += -DEAP_EKE_DYNAMIC
+EAPDYN += src/eap_peer/eap_eke.so
+else
+L_CFLAGS += -DEAP_EKE
+OBJS += src/eap_peer/eap_eke.c src/eap_common/eap_eke_common.c
+OBJS_h += src/eap_server/eap_server_eke.c
+endif
+CONFIG_IEEE8021X_EAPOL=y
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+NEED_SHA256=y
+endif
+
ifdef CONFIG_WPS
ifdef CONFIG_WPS2
L_CFLAGS += -DCONFIG_WPS2
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 0634219..5698619 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -215,7 +215,7 @@
NEED_MD5=y
NEED_RC4=y
else
-CFLAGS += -DCONFIG_NO_WPA -DCONFIG_NO_WPA2
+CFLAGS += -DCONFIG_NO_WPA
endif
ifdef CONFIG_IBSS_RSN
@@ -265,10 +265,6 @@
NEED_GAS=y
endif
-ifdef CONFIG_NO_WPA2
-CFLAGS += -DCONFIG_NO_WPA2
-endif
-
include ../src/drivers/drivers.mak
ifdef CONFIG_AP
OBJS_d += $(DRV_BOTH_OBJS)
@@ -579,6 +575,22 @@
NEED_SHA256=y
endif
+ifdef CONFIG_EAP_EKE
+# EAP-EKE
+ifeq ($(CONFIG_EAP_EKE), dyn)
+CFLAGS += -DEAP_EKE_DYNAMIC
+EAPDYN += ../src/eap_peer/eap_eke.so
+else
+CFLAGS += -DEAP_EKE
+OBJS += ../src/eap_peer/eap_eke.o ../src/eap_common/eap_eke_common.o
+OBJS_h += ../src/eap_server/eap_server_eke.o
+endif
+CONFIG_IEEE8021X_EAPOL=y
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+NEED_SHA256=y
+endif
+
ifdef CONFIG_WPS
ifdef CONFIG_WPS2
CFLAGS += -DCONFIG_WPS2
@@ -1581,6 +1593,10 @@
$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
-Deap_peer_ikev2_register=eap_peer_method_dynamic_init
+eap_eke.so: ../src/eap_peer/eap_eke.c ../src/eap_common/eap_eke_common.c
+ $(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+ -Deap_peer_eke_register=eap_peer_method_dynamic_init
+
%.so: %.c
$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \
-D$(*F:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index d84e61e..78df89e 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -115,13 +115,15 @@
- NetBSD-current
- Microsoft Windows with WinPcap (at least WinXP, may work with other versions)
- drivers:
- Linux drivers that support WPA/WPA2 configuration with the generic
- Linux wireless extensions (WE-18 or newer). Even though there are
+ Linux drivers that support cfg80211/nl80211. Even though there are
number of driver specific interface included in wpa_supplicant, please
- note that Linux drivers are moving to use generic wireless extensions
- and driver_wext (-Dwext on wpa_supplicant command line) should be the
- default option to start with before falling back to driver specific
- interface.
+ note that Linux drivers are moving to use generic wireless configuration
+ interface driver_nl80211 (-Dnl80211 on wpa_supplicant command line)
+ should be the default option to start with before falling back to driver
+ specific interface.
+
+ Linux drivers that support WPA/WPA2 configuration with the generic
+ Linux wireless extensions (WE-18 or newer). Obsoleted by nl80211.
In theory, any driver that supports Linux wireless extensions can be
used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in
@@ -408,6 +410,7 @@
usage:
wpa_supplicant [-BddfhKLqqtuvwW] [-P<pid file>] [-g<global ctrl>] \
+ [-G<group>] \
-i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
[-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
[-p<driver_param>] [-b<br_ifname>] ...]
@@ -422,6 +425,7 @@
-D = driver name (can be multiple drivers: nl80211,wext)
-f = Log output to default log location (normally /tmp)
-g = global ctrl_interface
+ -G = global ctrl_interface group
-K = include keys (passwords, etc.) in debug output
-t = include timestamp in debug messages
-h = show this help text
@@ -436,6 +440,7 @@
-N = start describing new interface
drivers:
+ nl80211 = Linux nl80211/cfg80211
wext = Linux wireless extensions (generic)
wired = wpa_supplicant wired Ethernet driver
roboswitch = wpa_supplicant Broadcom switch driver
@@ -477,7 +482,7 @@
interface needs to be configured to wpa_supplicant in addition to the
main interface:
-wpa_supplicant -cw.conf -Dwext -iwlan0 -bbr0
+wpa_supplicant -cw.conf -Dnl80211 -iwlan0 -bbr0
Configuration file
@@ -869,10 +874,10 @@
# Start wpa_supplicant in the background
wpa_supplicant -g/var/run/wpa_supplicant-global -B
-# Add a new interface (wlan0, no configuration file, driver=wext, and
+# Add a new interface (wlan0, no configuration file, driver=nl80211, and
# enable control interface)
wpa_cli -g/var/run/wpa_supplicant-global interface_add wlan0 \
- "" wext /var/run/wpa_supplicant
+ "" nl80211 /var/run/wpa_supplicant
# Configure a network using the newly added network interface:
wpa_cli -iwlan0 add_network
@@ -933,7 +938,7 @@
chmod 0750 /var/run/wpa_priv
- start wpa_priv as root (e.g., from system startup scripts) with the
enabled interfaces configured on the command line:
- wpa_priv -B -P /var/run/wpa_priv.pid wext:ath0
+ wpa_priv -B -P /var/run/wpa_priv.pid nl80211:wlan0
- run wpa_supplicant as non-root with a user that is in wpapriv group:
wpa_supplicant -i ath0 -c wpa_supplicant.conf
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index b86c4c7..8b3d6b4 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -176,7 +176,7 @@
CONFIG_EAP_LEAP=y
# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
-#CONFIG_EAP_AKA=y
+CONFIG_EAP_AKA=y
# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
# This requires CONFIG_EAP_AKA to be enabled, too.
@@ -201,10 +201,12 @@
# Enable WSC 2.0 support
CONFIG_WPS2=y
# Enable WPS external registrar functionality
-#CONFIG_WPS_ER=y
+CONFIG_WPS_ER=y
# Disable credentials for an open network by default when acting as a WPS
# registrar.
#CONFIG_WPS_REG_DISABLE_OPEN=y
+# Enable WPS support with NFC config method
+CONFIG_WPS_NFC=y
# EAP-IKEv2
#CONFIG_EAP_IKEV2=y
@@ -234,6 +236,7 @@
# unix = UNIX domain sockets (default for Linux/*BSD)
# udp = UDP sockets using localhost (127.0.0.1)
# named_pipe = Windows Named Pipe (default for Windows)
+# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
# y = use default (backwards compatibility)
# If this option is commented out, control interface is not included in the
# build.
@@ -259,11 +262,6 @@
# 35-50 kB in code size.
#CONFIG_NO_WPA=y
-# Remove WPA2 support. This allows WPA to be used, but removes WPA2 code to
-# save about 1 kB in code size when building only WPA-Personal (no EAP support)
-# or 6 kB if building for WPA-Enterprise.
-#CONFIG_NO_WPA2=y
-
# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
# This option can be used to reduce code size by removing support for
# converting ASCII passphrases into PSK. If this functionality is removed, the
@@ -325,9 +323,7 @@
# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
CONFIG_PEERKEY=y
-# IEEE 802.11w (management frame protection)
-# This version is an experimental implementation based on IEEE 802.11w/D1.0
-# draft and is subject to change since the standard has not yet been finalized.
+# IEEE 802.11w (management frame protection), also known as PMF
# Driver support is also needed for IEEE 802.11w.
#CONFIG_IEEE80211W=y
@@ -486,6 +482,10 @@
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
CONFIG_IEEE80211N=y
+# Wireless Network Management (IEEE Std 802.11v-2011)
+# Note: This is experimental and not complete implementation.
+#CONFIG_WNM=y
+
# Interworking (IEEE 802.11u)
# This can be used to enable functionality to improve interworking with
# external networks (GAS/ANQP to learn more about the networks and network
@@ -498,12 +498,39 @@
# Disable roaming in wpa_supplicant
CONFIG_NO_ROAMING=y
-# Enable TDLS
-CONFIG_TDLS=y
-
-# Enable P2P
-CONFIG_P2P=y
+# AP mode operations with wpa_supplicant
+# This can be used for controlling AP mode operations with wpa_supplicant. It
+# should be noted that this is mainly aimed at simple cases like
+# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
+# external RADIUS server can be supported with hostapd.
CONFIG_AP=y
+# P2P (Wi-Fi Direct)
+# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
+# more information on P2P operations.
+CONFIG_P2P=y
+
+CONFIG_TDLS=y
+
#Enable Wifi Display
CONFIG_WIFI_DISPLAY=y
+
+# Autoscan
+# This can be used to enable automatic scan support in wpa_supplicant.
+# See wpa_supplicant.conf for more information on autoscan usage.
+#
+# Enabling directly a module will enable autoscan support.
+# For exponential module:
+#CONFIG_AUTOSCAN_EXPONENTIAL=y
+# For periodic module:
+#CONFIG_AUTOSCAN_PERIODIC=y
+
+# Password (and passphrase, etc.) backend for external storage
+# These optional mechanisms can be used to add support for storing passwords
+# and other secrets in external (to wpa_supplicant) location. This allows, for
+# example, operating system specific key storage to be used
+#
+# External password backend for testing purposes (developer use)
+#CONFIG_EXT_PASSWORD_TEST=y
+
+include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 3ba4496..c48a286 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -55,21 +55,14 @@
/* default channel 11 */
conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
conf->channel = 11;
- } else if (ssid->frequency >= 2412 && ssid->frequency <= 2472) {
- conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
- conf->channel = (ssid->frequency - 2407) / 5;
- } else if ((ssid->frequency >= 5180 && ssid->frequency <= 5240) ||
- (ssid->frequency >= 5745 && ssid->frequency <= 5825)) {
- conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
- conf->channel = (ssid->frequency - 5000) / 5;
- } else if (ssid->frequency >= 56160 + 2160 * 1 &&
- ssid->frequency <= 56160 + 2160 * 4) {
- conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
- conf->channel = (ssid->frequency - 56160) / 2160;
} else {
- wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
- ssid->frequency);
- return -1;
+ conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
+ &conf->channel);
+ if (conf->hw_mode == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: "
+ "%d MHz", ssid->frequency);
+ return -1;
+ }
}
/* TODO: enable HT40 if driver supports it;
@@ -131,7 +124,9 @@
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_P2P
- if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
+ if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
+ (ssid->mode == WPAS_MODE_P2P_GO ||
+ ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)) {
/* Remove 802.11b rates from supported and basic rate sets */
int *list = os_malloc(4 * sizeof(int));
if (list) {
@@ -251,6 +246,16 @@
bss->rsn_pairwise = WPA_CIPHER_NONE;
}
+ if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) &&
+ (bss->wpa_group == WPA_CIPHER_CCMP ||
+ bss->wpa_group == WPA_CIPHER_GCMP)) {
+ /*
+ * Strong ciphers do not need frequent rekeying, so increase
+ * the default GTK rekeying period to 24 hours.
+ */
+ bss->wpa_group_rekey = 86400;
+ }
+
#ifdef CONFIG_WPS
/*
* Enable WPS by default for open and WPA/WPA2-Personal network, but
@@ -489,6 +494,11 @@
if (wpa_drv_associate(wpa_s, ¶ms) < 0) {
wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
+#ifdef CONFIG_P2P
+ if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION &&
+ wpa_s->global->p2p_group_formation == wpa_s)
+ wpas_p2p_group_formation_failed(wpa_s->parent);
+#endif /* CONFIG_P2P */
return -1;
}
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 0d98884..a35be51 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -322,11 +322,9 @@
return 0;
ssid->psk_set = 0;
os_free(ssid->passphrase);
- ssid->passphrase = os_malloc(len + 1);
+ ssid->passphrase = dup_binstr(value, len);
if (ssid->passphrase == NULL)
return -1;
- os_memcpy(ssid->passphrase, value, len);
- ssid->passphrase[len] = '\0';
return 0;
#else /* CONFIG_NO_PBKDF2 */
wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
@@ -1524,6 +1522,7 @@
{ INT(eap_workaround) },
{ STRe(pac_file) },
{ INTe(fragment_size) },
+ { INTe(ocsp) },
#endif /* IEEE8021X_EAPOL */
{ INT_RANGE(mode, 0, 4) },
{ INT_RANGE(proactive_key_caching, 0, 1) },
@@ -1828,6 +1827,7 @@
os_free(config->pssid);
os_free(config->p2p_pref_chan);
os_free(config->autoscan);
+ os_free(config->freq_list);
wpabuf_free(config->wps_nfc_dh_pubkey);
wpabuf_free(config->wps_nfc_dh_privkey);
wpabuf_free(config->wps_nfc_dev_pw);
@@ -2585,6 +2585,7 @@
config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
config->max_num_sta = DEFAULT_MAX_NUM_STA;
config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
+ config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
config->wmm_ac_params[0] = ac_be;
config->wmm_ac_params[1] = ac_bk;
config->wmm_ac_params[2] = ac_vi;
@@ -2735,6 +2736,21 @@
}
+static int wpa_config_process_freq_list(const struct global_parse_data *data,
+ struct wpa_config *config, int line,
+ const char *value)
+{
+ int *freqs;
+
+ freqs = wpa_config_parse_int_array(value);
+ if (freqs == NULL)
+ return -1;
+ os_free(config->freq_list);
+ config->freq_list = freqs;
+ return 0;
+}
+
+
static int wpa_config_process_country(const struct global_parse_data *data,
struct wpa_config *config, int line,
const char *pos)
@@ -3090,6 +3106,9 @@
{ INT(beacon_int), 0 },
{ FUNC(ap_vendor_elements), 0 },
{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
+ { FUNC(freq_list), 0 },
+ { INT(scan_cur_freq), 0 },
+ { INT(sched_scan_interval), 0 },
};
#undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 4a175ce..1748cf3 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -24,6 +24,7 @@
#define DEFAULT_BSS_EXPIRATION_SCAN_COUNT 2
#define DEFAULT_MAX_NUM_STA 128
#define DEFAULT_ACCESS_NETWORK_TYPE 15
+#define DEFAULT_SCAN_CUR_FREQ 0
#include "config_ssid.h"
#include "wps/wps.h"
@@ -645,6 +646,22 @@
unsigned int max_num_sta;
/**
+ * freq_list - Array of allowed scan frequencies or %NULL for all
+ *
+ * This is an optional zero-terminated array of frequencies in
+ * megahertz (MHz) to allow for narrowing scanning range.
+ */
+ int *freq_list;
+
+ /**
+ * scan_cur_freq - Whether to scan only the current channel
+ *
+ * If true, attempt to scan only the current channel if any other
+ * VIFs on this radio are already associated on a particular channel.
+ */
+ int scan_cur_freq;
+
+ /**
* changed_parameters - Bitmap of changed parameters since last update
*/
unsigned int changed_parameters;
@@ -854,6 +871,11 @@
* allowing it to update the internal BSS table.
*/
int ignore_old_scan_res;
+
+ /**
+ * sched_scan_interval - schedule scan interval
+ */
+ unsigned int sched_scan_interval;
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 8604ae8..d03de0b 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1015,6 +1015,22 @@
if (config->ignore_old_scan_res)
fprintf(f, "ignore_old_scan_res=%d\n",
config->ignore_old_scan_res);
+
+ if (config->freq_list && config->freq_list[0]) {
+ int i;
+ fprintf(f, "freq_list=");
+ for (i = 0; config->freq_list[i]; i++) {
+ fprintf(f, "%s%u", i > 0 ? " " : "",
+ config->freq_list[i]);
+ }
+ fprintf(f, "\n");
+ }
+ if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ)
+ fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq);
+
+ if (config->sched_scan_interval)
+ fprintf(f, "sched_scan_interval=%u\n",
+ config->sched_scan_interval);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index ad0392f..a24abaf 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -461,6 +461,14 @@
return -1;
return res;
#endif /* CONFIG_WIFI_DISPLAY */
+#ifdef CONFIG_TESTING_GET_GTK
+ } else if (os_strcmp(cmd, "gtk") == 0) {
+ if (wpa_s->last_gtk_len == 0)
+ return -1;
+ res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
+ wpa_s->last_gtk_len);
+ return res;
+#endif /* CONFIG_TESTING_GET_GTK */
}
if (res < 0 || (unsigned int) res >= buflen)
@@ -2963,6 +2971,60 @@
}
+static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
+ char *buf, size_t buflen)
+{
+ struct hostapd_channel_data *chnl;
+ int ret, i, j;
+ char *pos, *end, *hmode;
+
+ pos = buf;
+ end = pos + buflen;
+
+ for (j = 0; j < wpa_s->hw.num_modes; j++) {
+ switch (wpa_s->hw.modes[j].mode) {
+ case HOSTAPD_MODE_IEEE80211B:
+ hmode = "B";
+ break;
+ case HOSTAPD_MODE_IEEE80211G:
+ hmode = "G";
+ break;
+ case HOSTAPD_MODE_IEEE80211A:
+ hmode = "A";
+ break;
+ case HOSTAPD_MODE_IEEE80211AD:
+ hmode = "AD";
+ break;
+ default:
+ continue;
+ }
+ ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
+ hmode);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ 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 = %d MHz%s\n",
+ chnl[i].chan, chnl[i].freq,
+ chnl[i].flag & HOSTAPD_CHAN_NO_IBSS ?
+ " (NO_IBSS)" : "");
+ 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;
+ }
+
+ return pos - buf;
+}
+
+
static int wpa_supplicant_ctrl_iface_get_capability(
struct wpa_supplicant *wpa_s, const char *_field, char *buf,
size_t buflen)
@@ -3020,6 +3082,9 @@
if (os_strcmp(field, "channels") == 0)
return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
+ if (os_strcmp(field, "freq") == 0)
+ return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
field);
@@ -4937,26 +5002,92 @@
return ret;
}
+
+static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ int query_reason;
+
+ query_reason = atoi(cmd);
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
+ query_reason);
+
+ return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
+}
+
#endif /* CONFIG_WNM */
+/* Get string representation of channel width */
+static const char * channel_width_name(enum chan_width width)
+{
+ switch (width) {
+ case CHAN_WIDTH_20_NOHT:
+ return "20 MHz (no HT)";
+ case CHAN_WIDTH_20:
+ return "20 MHz";
+ case CHAN_WIDTH_40:
+ return "40 MHz";
+ case CHAN_WIDTH_80:
+ return "80 MHz";
+ case CHAN_WIDTH_80P80:
+ return "80+80 MHz";
+ case CHAN_WIDTH_160:
+ return "160 MHz";
+ default:
+ return "unknown";
+ }
+}
+
+
static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
size_t buflen)
{
struct wpa_signal_info si;
int ret;
+ char *pos, *end;
ret = wpa_drv_signal_poll(wpa_s, &si);
if (ret)
return -1;
- ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
+ pos = buf;
+ end = buf + buflen;
+
+ ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
"NOISE=%d\nFREQUENCY=%u\n",
si.current_signal, si.current_txrate / 1000,
si.current_noise, si.frequency);
- if (ret < 0 || (unsigned int) ret > buflen)
+ if (ret < 0 || ret > end - pos)
return -1;
- return ret;
+ pos += ret;
+
+ if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
+ ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
+ channel_width_name(si.chanwidth));
+ if (ret < 0 || ret > end - pos)
+ return -1;
+ pos += ret;
+ }
+
+ if (si.center_frq1 > 0 && si.center_frq2 > 0) {
+ ret = os_snprintf(pos, end - pos,
+ "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
+ si.center_frq1, si.center_frq2);
+ if (ret < 0 || ret > end - pos)
+ return -1;
+ pos += ret;
+ }
+
+ if (si.avg_signal) {
+ ret = os_snprintf(pos, end - pos,
+ "AVG_RSSI=%d\n", si.avg_signal);
+ if (ret < 0 || ret >= end - pos)
+ return -1;
+ pos += ret;
+ }
+
+ return pos - buf;
}
@@ -5019,6 +5150,9 @@
wpa_tdls_enable(wpa_s->wpa, 1);
#endif /* CONFIG_TDLS */
+ eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
+ wpa_supplicant_stop_countermeasures(wpa_s, NULL);
+
wpa_s->no_keep_alive = 0;
os_free(wpa_s->disallow_aps_bssid);
@@ -5035,6 +5169,7 @@
wpa_bss_flush(wpa_s);
wpa_blacklist_clear(wpa_s);
+ wpa_s->extra_blacklist_count = 0;
wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
}
@@ -5573,6 +5708,9 @@
} else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
reply_len = -1;
+ } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 10) == 0) {
+ if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 10))
+ reply_len = -1;
#endif /* CONFIG_WNM */
} else if (os_strcmp(buf, "FLUSH") == 0) {
wpa_supplicant_ctrl_iface_flush(wpa_s);
@@ -5766,6 +5904,126 @@
}
+static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
+ const char *ifname,
+ char *cmd, size_t *resp_len)
+{
+ struct wpa_supplicant *wpa_s;
+
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ if (os_strcmp(ifname, wpa_s->ifname) == 0)
+ break;
+ }
+
+ if (wpa_s == NULL) {
+ char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
+ if (resp)
+ *resp_len = os_strlen(resp);
+ else
+ *resp_len = 1;
+ return resp;
+ }
+
+ return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
+}
+
+
+static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
+ char *buf, size_t *resp_len)
+{
+#ifdef CONFIG_P2P
+ static const char * cmd[] = {
+ "P2P_FIND",
+ "P2P_STOP_FIND",
+ "P2P_LISTEN",
+ "P2P_GROUP_ADD",
+ "P2P_GET_PASSPHRASE",
+ "P2P_SERVICE_UPDATE",
+ "P2P_SERVICE_FLUSH",
+ "P2P_FLUSH",
+ "P2P_CANCEL",
+ "P2P_PRESENCE_REQ",
+ "P2P_EXT_LISTEN",
+ NULL
+ };
+ static const char * prefix[] = {
+ "P2P_FIND ",
+ "P2P_CONNECT ",
+ "P2P_LISTEN ",
+ "P2P_GROUP_REMOVE ",
+ "P2P_GROUP_ADD ",
+ "P2P_PROV_DISC ",
+ "P2P_SERV_DISC_REQ ",
+ "P2P_SERV_DISC_CANCEL_REQ ",
+ "P2P_SERV_DISC_RESP ",
+ "P2P_SERV_DISC_EXTERNAL ",
+ "P2P_SERVICE_ADD ",
+ "P2P_SERVICE_DEL ",
+ "P2P_REJECT ",
+ "P2P_INVITE ",
+ "P2P_PEER ",
+ "P2P_SET ",
+ "P2P_UNAUTHORIZE ",
+ "P2P_PRESENCE_REQ ",
+ "P2P_EXT_LISTEN ",
+ NULL
+ };
+ int found = 0;
+ int i;
+
+ if (global->p2p_init_wpa_s == NULL)
+ return NULL;
+
+ for (i = 0; !found && cmd[i]; i++) {
+ if (os_strcmp(buf, cmd[i]) == 0)
+ found = 1;
+ }
+
+ for (i = 0; !found && prefix[i]; i++) {
+ if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
+ found = 1;
+ }
+
+ if (found)
+ return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
+ buf, resp_len);
+#endif /* CONFIG_P2P */
+ return NULL;
+}
+
+
+static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
+ char *buf, size_t *resp_len)
+{
+#ifdef CONFIG_WIFI_DISPLAY
+ if (global->p2p_init_wpa_s == NULL)
+ return NULL;
+ if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
+ os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
+ return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
+ buf, resp_len);
+#endif /* CONFIG_WIFI_DISPLAY */
+ return NULL;
+}
+
+
+static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
+ char *buf, size_t *resp_len)
+{
+ char *ret;
+
+ ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
+ if (ret)
+ return ret;
+
+ ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
+ if (ret)
+ return ret;
+
+ return NULL;
+}
+
+
char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
char *buf, size_t *resp_len)
{
@@ -5774,6 +6032,20 @@
int reply_len;
int level = MSG_DEBUG;
+ if (os_strncmp(buf, "IFNAME=", 7) == 0) {
+ char *pos = os_strchr(buf + 7, ' ');
+ if (pos) {
+ *pos++ = '\0';
+ return wpas_global_ctrl_iface_ifname(global,
+ buf + 7, pos,
+ resp_len);
+ }
+ }
+
+ reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
+ if (reply)
+ return reply;
+
if (os_strcmp(buf, "PING") == 0)
level = MSG_EXCESSIVE;
wpa_hexdump_ascii(level, "RX global ctrl_iface",
diff --git a/wpa_supplicant/ctrl_iface_named_pipe.c b/wpa_supplicant/ctrl_iface_named_pipe.c
index fd417ff..dc02db2 100644
--- a/wpa_supplicant/ctrl_iface_named_pipe.c
+++ b/wpa_supplicant/ctrl_iface_named_pipe.c
@@ -423,7 +423,7 @@
}
-static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
+static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, int global,
const char *txt, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c
index 994f9b1..f3b660d 100644
--- a/wpa_supplicant/ctrl_iface_udp.c
+++ b/wpa_supplicant/ctrl_iface_udp.c
@@ -255,7 +255,7 @@
}
-static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
+static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, int global,
const char *txt, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 4dfabc8..fc0d649 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / UNIX domain socket -based control interface
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -50,12 +50,20 @@
};
-static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
+struct ctrl_iface_global_priv {
+ struct wpa_global *global;
+ int sock;
+ struct dl_list ctrl_dst;
+};
+
+
+static void wpa_supplicant_ctrl_iface_send(const char *ifname, int sock,
+ struct dl_list *ctrl_dst,
int level, const char *buf,
size_t len);
-static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
+static int wpa_supplicant_ctrl_iface_attach(struct dl_list *ctrl_dst,
struct sockaddr_un *from,
socklen_t fromlen)
{
@@ -67,7 +75,7 @@
os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
dst->addrlen = fromlen;
dst->debug_level = MSG_INFO;
- dl_list_add(&priv->ctrl_dst, &dst->list);
+ dl_list_add(ctrl_dst, &dst->list);
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
(u8 *) from->sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path));
@@ -75,13 +83,13 @@
}
-static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
+static int wpa_supplicant_ctrl_iface_detach(struct dl_list *ctrl_dst,
struct sockaddr_un *from,
socklen_t fromlen)
{
struct wpa_ctrl_dst *dst;
- dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
+ dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
if (fromlen == dst->addrlen &&
os_memcmp(from->sun_path, dst->addr.sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path))
@@ -148,14 +156,16 @@
buf[res] = '\0';
if (os_strcmp(buf, "ATTACH") == 0) {
- if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
+ if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
+ fromlen))
reply_len = 1;
else {
new_attached = 1;
reply_len = 2;
}
} else if (os_strcmp(buf, "DETACH") == 0) {
- if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
+ if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
+ fromlen))
reply_len = 1;
else
reply_len = 2;
@@ -166,30 +176,6 @@
else
reply_len = 2;
} else {
-#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
- char *ifname, *ifend;
-
- ifname = os_strstr(buf, "interface=");
- if (ifname != NULL) {
- ifend = os_strchr(ifname + 10, ' ');
- if (ifend != NULL)
- *ifend++ = '\0';
- else
- *(ifname - 1) = '\0';
- wpa_printf(MSG_DEBUG, "Found %s", ifname);
- for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
- if (os_strcmp(wpa_s->ifname, ifname + 10) == 0)
- break;
- }
- if (wpa_s == NULL) {
- wpa_printf(MSG_ERROR, "P2P: %s does not exist", ifname);
- wpa_s = eloop_ctx;
- }
- if (ifend != NULL)
- os_memmove(ifname, ifend, strlen(ifend) + 1);
- wpa_printf(MSG_INFO, "wpa_s->ifname %s cmd %s", wpa_s ? wpa_s->ifname : "NULL", buf);
- }
-#endif /* defined CONFIG_P2P && defined ANDROID_P2P */
reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
&reply_len);
}
@@ -264,13 +250,30 @@
}
-static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
+static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, int global,
const char *txt, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
- if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
+
+ if (wpa_s == NULL)
return;
- wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
+
+ if (global != 2 && wpa_s->global->ctrl_iface) {
+ struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
+ if (!dl_list_empty(&priv->ctrl_dst)) {
+ wpa_supplicant_ctrl_iface_send(global ? NULL :
+ wpa_s->ifname,
+ priv->sock,
+ &priv->ctrl_dst,
+ level, txt, len);
+ }
+ }
+
+ if (wpa_s->ctrl_iface == NULL)
+ return;
+ wpa_supplicant_ctrl_iface_send(NULL, wpa_s->ctrl_iface->sock,
+ &wpa_s->ctrl_iface->ctrl_dst,
+ level, txt, len);
}
@@ -543,14 +546,17 @@
/**
* wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
- * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
+ * @ifname: Interface name for global control socket or %NULL
+ * @sock: Local socket fd
+ * @ctrl_dst: List of attached listeners
* @level: Priority level of the message
* @buf: Message data
* @len: Message length
*
* Send a packet to all monitor programs attached to the control interface.
*/
-static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
+static void wpa_supplicant_ctrl_iface_send(const char *ifname, int sock,
+ struct dl_list *ctrl_dst,
int level, const char *buf,
size_t len)
{
@@ -558,32 +564,45 @@
char levelstr[10];
int idx, res;
struct msghdr msg;
- struct iovec io[2];
+ struct iovec io[5];
- if (priv->sock < 0 || dl_list_empty(&priv->ctrl_dst))
+ if (sock < 0 || dl_list_empty(ctrl_dst))
return;
res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
if (res < 0 || (size_t) res >= sizeof(levelstr))
return;
- io[0].iov_base = levelstr;
- io[0].iov_len = os_strlen(levelstr);
- io[1].iov_base = (char *) buf;
- io[1].iov_len = len;
+ idx = 0;
+ if (ifname) {
+ io[idx].iov_base = "IFNAME=";
+ io[idx].iov_len = 7;
+ idx++;
+ io[idx].iov_base = (char *) ifname;
+ io[idx].iov_len = os_strlen(ifname);
+ idx++;
+ io[idx].iov_base = " ";
+ io[idx].iov_len = 1;
+ idx++;
+ }
+ io[idx].iov_base = levelstr;
+ io[idx].iov_len = os_strlen(levelstr);
+ idx++;
+ io[idx].iov_base = (char *) buf;
+ io[idx].iov_len = len;
+ idx++;
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
- msg.msg_iovlen = 2;
+ msg.msg_iovlen = idx;
idx = 0;
- dl_list_for_each_safe(dst, next, &priv->ctrl_dst, struct wpa_ctrl_dst,
- list) {
+ dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
if (level >= dst->debug_level) {
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
(u8 *) dst->addr.sun_path, dst->addrlen -
offsetof(struct sockaddr_un, sun_path));
msg.msg_name = (void *) &dst->addr;
msg.msg_namelen = dst->addrlen;
- if (sendmsg(priv->sock, &msg, 0) < 0) {
+ if (sendmsg(sock, &msg, MSG_DONTWAIT) < 0) {
int _errno = errno;
wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
"%d - %s",
@@ -593,7 +612,7 @@
(_errno != ENOBUFS && dst->errors > 10) ||
_errno == ENOENT) {
wpa_supplicant_ctrl_iface_detach(
- priv, &dst->addr,
+ ctrl_dst, &dst->addr,
dst->addrlen);
}
} else
@@ -626,8 +645,8 @@
if (os_strcmp(buf, "ATTACH") == 0) {
/* handle ATTACH signal of first monitor interface */
- if (!wpa_supplicant_ctrl_iface_attach(priv, &from,
- fromlen)) {
+ if (!wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
+ &from, fromlen)) {
sendto(priv->sock, "OK\n", 3, 0,
(struct sockaddr *) &from, fromlen);
/* OK to continue */
@@ -647,21 +666,16 @@
/* Global ctrl_iface */
-struct ctrl_iface_global_priv {
- struct wpa_global *global;
- int sock;
-};
-
-
static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct wpa_global *global = eloop_ctx;
+ struct ctrl_iface_global_priv *priv = sock_ctx;
char buf[256];
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
- char *reply;
+ char *reply = NULL;
size_t reply_len;
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
@@ -672,16 +686,32 @@
}
buf[res] = '\0';
- reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
- &reply_len);
+ if (os_strcmp(buf, "ATTACH") == 0) {
+ if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
+ fromlen))
+ reply_len = 1;
+ else
+ reply_len = 2;
+ } else if (os_strcmp(buf, "DETACH") == 0) {
+ if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
+ fromlen))
+ reply_len = 1;
+ else
+ reply_len = 2;
+ } else {
+ reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
+ &reply_len);
+ }
if (reply) {
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen);
os_free(reply);
- } else if (reply_len) {
+ } else if (reply_len == 1) {
sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
fromlen);
+ } else if (reply_len == 2) {
+ sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen);
}
}
@@ -691,24 +721,48 @@
{
struct ctrl_iface_global_priv *priv;
struct sockaddr_un addr;
+ const char *ctrl = global->params.ctrl_interface;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
+ dl_list_init(&priv->ctrl_dst);
priv->global = global;
priv->sock = -1;
- if (global->params.ctrl_interface == NULL)
+ if (ctrl == NULL)
return priv;
-#ifdef ANDROID
- priv->sock = android_get_control_socket(global->params.ctrl_interface);
- if (priv->sock >= 0)
- goto havesock;
-#endif /* ANDROID */
+ wpa_printf(MSG_DEBUG, "Global control interface '%s'", ctrl);
- wpa_printf(MSG_DEBUG, "Global control interface '%s'",
- global->params.ctrl_interface);
+#ifdef ANDROID
+ if (os_strncmp(ctrl, "@android:", 9) == 0) {
+ priv->sock = android_get_control_socket(ctrl + 9);
+ if (priv->sock < 0) {
+ wpa_printf(MSG_ERROR, "Failed to open Android control "
+ "socket '%s'", ctrl + 9);
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG, "Using Android control socket '%s'",
+ ctrl + 9);
+ goto havesock;
+ }
+
+ if (os_strncmp(ctrl, "@abstract:", 10) != 0) {
+ /*
+ * Backwards compatibility - try to open an Android control
+ * socket and if that fails, assume this was a UNIX domain
+ * socket instead.
+ */
+ priv->sock = android_get_control_socket(ctrl);
+ if (priv->sock >= 0) {
+ wpa_printf(MSG_DEBUG,
+ "Using Android control socket '%s'",
+ ctrl);
+ goto havesock;
+ }
+ }
+#endif /* ANDROID */
priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if (priv->sock < 0) {
@@ -721,8 +775,23 @@
addr.sun_len = sizeof(addr);
#endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX;
- os_strlcpy(addr.sun_path, global->params.ctrl_interface,
- sizeof(addr.sun_path));
+
+ if (os_strncmp(ctrl, "@abstract:", 10) == 0) {
+ addr.sun_path[0] = '\0';
+ os_strlcpy(addr.sun_path + 1, ctrl + 10,
+ sizeof(addr.sun_path) - 1);
+ if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) <
+ 0) {
+ wpa_printf(MSG_ERROR, "supp-global-ctrl-iface-init: "
+ "bind(PF_UNIX) failed: %s", strerror(errno));
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG, "Using Abstract control socket '%s'",
+ ctrl + 10);
+ goto havesock;
+ }
+
+ os_strlcpy(addr.sun_path, ctrl, sizeof(addr.sun_path));
if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("supp-global-ctrl-iface-init (will try fixup): "
"bind(PF_UNIX)");
@@ -731,11 +800,11 @@
wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
" allow connections - assuming it was left"
"over from forced program termination");
- if (unlink(global->params.ctrl_interface) < 0) {
+ if (unlink(ctrl) < 0) {
perror("unlink[ctrl_iface]");
wpa_printf(MSG_ERROR, "Could not unlink "
"existing ctrl_iface socket '%s'",
- global->params.ctrl_interface);
+ ctrl);
goto fail;
}
if (bind(priv->sock, (struct sockaddr *) &addr,
@@ -745,23 +814,59 @@
}
wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
"ctrl_iface socket '%s'",
- global->params.ctrl_interface);
+ ctrl);
} else {
wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
"be in use - cannot override it");
wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
"not used anymore",
- global->params.ctrl_interface);
+ ctrl);
goto fail;
}
}
-#ifdef ANDROID
+ wpa_printf(MSG_DEBUG, "Using UNIX control socket '%s'", ctrl);
+
+ if (global->params.ctrl_interface_group) {
+ char *gid_str = global->params.ctrl_interface_group;
+ gid_t gid = 0;
+ struct group *grp;
+ char *endp;
+
+ grp = getgrnam(gid_str);
+ if (grp) {
+ gid = grp->gr_gid;
+ wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
+ " (from group name '%s')",
+ (int) gid, gid_str);
+ } else {
+ /* Group name not found - try to parse this as gid */
+ gid = strtol(gid_str, &endp, 10);
+ if (*gid_str == '\0' || *endp != '\0') {
+ wpa_printf(MSG_ERROR, "CTRL: Invalid group "
+ "'%s'", gid_str);
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
+ (int) gid);
+ }
+ if (chown(ctrl, -1, gid) < 0) {
+ perror("chown[global_ctrl_interface/ifname]");
+ goto fail;
+ }
+
+ if (chmod(ctrl, S_IRWXU | S_IRWXG) < 0) {
+ perror("chmod[global_ctrl_interface/ifname]");
+ goto fail;
+ }
+ } else {
+ chmod(ctrl, S_IRWXU);
+ }
+
havesock:
-#endif /* ANDROID */
eloop_register_read_sock(priv->sock,
wpa_supplicant_global_ctrl_iface_receive,
- global, NULL);
+ global, priv);
return priv;
@@ -776,11 +881,16 @@
void
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
{
+ struct wpa_ctrl_dst *dst, *prev;
+
if (priv->sock >= 0) {
eloop_unregister_read_sock(priv->sock);
close(priv->sock);
}
if (priv->global->params.ctrl_interface)
unlink(priv->global->params.ctrl_interface);
+ dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
+ list)
+ os_free(dst);
os_free(priv);
}
diff --git a/wpa_supplicant/dbus/dbus_common.c b/wpa_supplicant/dbus/dbus_common.c
index 5d0e31e..6caf740 100644
--- a/wpa_supplicant/dbus/dbus_common.c
+++ b/wpa_supplicant/dbus/dbus_common.c
@@ -17,6 +17,7 @@
#include "dbus_common_i.h"
#include "dbus_new.h"
#include "dbus_old.h"
+#include "../wpa_supplicant_i.h"
#ifndef SIGPOLL
@@ -257,6 +258,22 @@
}
+static DBusHandlerResult disconnect_filter(DBusConnection *conn,
+ DBusMessage *message, void *data)
+{
+ struct wpas_dbus_priv *priv = data;
+
+ if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL,
+ "Disconnected")) {
+ wpa_printf(MSG_DEBUG, "dbus: bus disconnected, terminating");
+ dbus_connection_set_exit_on_disconnect(conn, FALSE);
+ wpa_supplicant_terminate_proc(priv->global);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ } else
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
static int wpas_dbus_init_common(struct wpas_dbus_priv *priv)
{
DBusError error;
@@ -265,7 +282,10 @@
/* Get a reference to the system bus */
dbus_error_init(&error);
priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
- if (!priv->con) {
+ if (priv->con) {
+ dbus_connection_add_filter(priv->con, disconnect_filter, priv,
+ NULL);
+ } else {
wpa_printf(MSG_ERROR, "dbus: Could not acquire the system "
"bus: %s - %s", error.name, error.message);
ret = -1;
@@ -304,6 +324,9 @@
NULL, NULL, NULL);
dbus_connection_set_timeout_functions(priv->con, NULL, NULL,
NULL, NULL, NULL);
+ dbus_connection_remove_filter(priv->con, disconnect_filter,
+ priv);
+
dbus_connection_unref(priv->con);
}
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 136dd1a..ddd2c82 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -869,6 +869,76 @@
}
+/**
+ * wpas_dbus_signal_sta - Send a station related event signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @sta: station mac address
+ * @sig_name: signal name - StaAuthorized or StaDeauthorized
+ *
+ * Notify listeners about event related with station
+ */
+static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s,
+ const u8 *sta, const char *sig_name)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX];
+ char *dev_mac;
+
+ os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta));
+ dev_mac = sta_mac;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (iface == NULL)
+ return;
+
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
+ if (msg == NULL)
+ return;
+
+ if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac,
+ DBUS_TYPE_INVALID))
+ dbus_connection_send(iface->con, msg, NULL);
+ else
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ dbus_message_unref(msg);
+
+ wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'",
+ sta_mac, sig_name);
+}
+
+
+/**
+ * wpas_dbus_signal_sta_authorized - Send a STA authorized signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @sta: station mac address
+ *
+ * Notify listeners a new station has been authorized
+ */
+void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
+ const u8 *sta)
+{
+ wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized");
+}
+
+
+/**
+ * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @sta: station mac address
+ *
+ * Notify listeners a station has been deauthorized
+ */
+void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
+ const u8 *sta)
+{
+ wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized");
+}
+
+
#ifdef CONFIG_P2P
/**
@@ -1920,15 +1990,6 @@
END_ARGS
}
},
-#ifdef CONFIG_AUTOSCAN
- { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
- (WPADBusMethodHandler) &wpas_dbus_handler_autoscan,
- {
- { "arg", "s", ARG_IN },
- END_ARGS
- }
- },
-#endif /* CONFIG_AUTOSCAN */
{ NULL, NULL, NULL, { END_ARGS } }
};
@@ -2654,6 +2715,27 @@
}
},
#endif /* CONFIG_AP */
+ { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) &wpas_dbus_handler_eap_logoff,
+ {
+ END_ARGS
+ }
+ },
+ { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) &wpas_dbus_handler_eap_logon,
+ {
+ END_ARGS
+ }
+ },
+#ifdef CONFIG_AUTOSCAN
+ { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) &wpas_dbus_handler_autoscan,
+ {
+ { "arg", "s", ARG_IN },
+ END_ARGS
+ }
+ },
+#endif /* CONFIG_AUTOSCAN */
{ NULL, NULL, NULL, { END_ARGS } }
};
@@ -3005,6 +3087,18 @@
END_ARGS
}
},
+ { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "name", "s", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "name", "s", ARG_OUT },
+ END_ARGS
+ }
+ },
{ NULL, NULL, { END_ARGS } }
};
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 363a7e5..61c480a 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -222,6 +222,10 @@
const u8 *ie, size_t ie_len, u32 ssi_signal);
void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
const char *status, const char *parameter);
+void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
+ const u8 *sta);
+void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
+ const u8 *sta);
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
@@ -493,6 +497,18 @@
{
}
+static inline
+void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
+ const u8 *sta)
+{
+}
+
+static inline
+void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
+ const u8 *sta)
+{
+}
+
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 335c25f..478d02f 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -1938,6 +1938,38 @@
#endif /* CONFIG_AUTOSCAN */
+/*
+ * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL
+ *
+ * Handler function for "EAPLogoff" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
+ return NULL;
+}
+
+
+/*
+ * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL
+ *
+ * Handler function for "EAPLogin" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
+ return NULL;
+}
+
+
/**
* wpas_dbus_getter_capabilities - Return interface capabilities
* @iter: Pointer to incoming dbus message iter
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index aa56550..fbc8358 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -128,6 +128,12 @@
DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+
dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
DBusError *error, void *user_data);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index e867bae..aa6005f 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -210,6 +210,9 @@
# EAP-IKEv2
#CONFIG_EAP_IKEV2=y
+# EAP-EKE
+#CONFIG_EAP_EKE=y
+
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
@@ -261,11 +264,6 @@
# 35-50 kB in code size.
#CONFIG_NO_WPA=y
-# Remove WPA2 support. This allows WPA to be used, but removes WPA2 code to
-# save about 1 kB in code size when building only WPA-Personal (no EAP support)
-# or 6 kB if building for WPA-Enterprise.
-#CONFIG_NO_WPA2=y
-
# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
# This option can be used to reduce code size by removing support for
# converting ASCII passphrases into PSK. If this functionality is removed, the
@@ -423,6 +421,10 @@
# same file, e.g., using trace-cmd.
#CONFIG_DEBUG_LINUX_TRACING=y
+# Add support for writing debug log to Android logcat instead of standard
+# output
+#CONFIG_ANDROID_LOG=y
+
# Enable privilege separation (see README 'Privilege separation' for details)
#CONFIG_PRIVSEP=y
@@ -495,6 +497,9 @@
# Hotspot 2.0
#CONFIG_HS20=y
+# Disable roaming in wpa_supplicant
+#CONFIG_NO_ROAMING=y
+
# AP mode operations with wpa_supplicant
# This can be used for controlling AP mode operations with wpa_supplicant. It
# should be noted that this is mainly aimed at simple cases like
@@ -507,6 +512,9 @@
# more information on P2P operations.
#CONFIG_P2P=y
+# Enable TDLS support
+#CONFIG_TDLS=y
+
# Autoscan
# This can be used to enable automatic scan support in wpa_supplicant.
# See wpa_supplicant.conf for more information on autoscan usage.
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 6bab19c..9922e07 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -129,6 +129,16 @@
return -1;
}
+static inline int wpa_drv_sta_deauth(struct wpa_supplicant *wpa_s,
+ const u8 *addr, int reason_code)
+{
+ if (wpa_s->driver->sta_deauth) {
+ return wpa_s->driver->sta_deauth(wpa_s->drv_priv, NULL, addr,
+ reason_code);
+ }
+ return -1;
+}
+
static inline int wpa_drv_deauthenticate(struct wpa_supplicant *wpa_s,
const u8 *addr, int reason_code)
{
diff --git a/wpa_supplicant/eap_register.c b/wpa_supplicant/eap_register.c
index d1eb4ff..6cd2fc5 100644
--- a/wpa_supplicant/eap_register.c
+++ b/wpa_supplicant/eap_register.c
@@ -135,6 +135,11 @@
ret = eap_peer_pwd_register();
#endif /* EAP_PWD */
+#ifdef EAP_EKE
+ if (ret == 0)
+ ret = eap_peer_eke_register();
+#endif /* EAP_EKE */
+
#ifdef EAP_SERVER_IDENTITY
if (ret == 0)
ret = eap_server_identity_register();
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 671fd74..d39216f 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -44,7 +44,10 @@
#include "interworking.h"
-static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s);
+#ifndef CONFIG_NO_SCAN_PROCESSING
+static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
+ int new_scan);
+#endif /* CONFIG_NO_SCAN_PROCESSING */
static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
@@ -928,6 +931,15 @@
return -1;
}
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "Considering connect request: reassociate: %d selected: "
+ MACSTR " bssid: " MACSTR " pending: " MACSTR
+ " wpa_state: %s ssid=%p current_ssid=%p",
+ wpa_s->reassociate, MAC2STR(selected->bssid),
+ MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
+ wpa_supplicant_state_txt(wpa_s->wpa_state),
+ ssid, wpa_s->current_ssid);
+
/*
* Do not trigger new association unless the BSSID has changed or if
* reassociation is requested. If we are in process of associating with
@@ -937,22 +949,21 @@
(os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
((wpa_s->wpa_state != WPA_ASSOCIATING &&
wpa_s->wpa_state != WPA_AUTHENTICATING) ||
- os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) !=
- 0))) {
+ (!is_zero_ether_addr(wpa_s->pending_bssid) &&
+ os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) !=
+ 0) ||
+ (is_zero_ether_addr(wpa_s->pending_bssid) &&
+ ssid != wpa_s->current_ssid)))) {
if (wpa_supplicant_scard_init(wpa_s, ssid)) {
wpa_supplicant_req_new_scan(wpa_s, 10, 0);
return 0;
}
- wpa_msg(wpa_s, MSG_DEBUG, "Request association: "
- "reassociate: %d selected: "MACSTR " bssid: " MACSTR
- " pending: " MACSTR " wpa_state: %s",
- wpa_s->reassociate, MAC2STR(selected->bssid),
- MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
- wpa_supplicant_state_txt(wpa_s->wpa_state));
+ wpa_msg(wpa_s, MSG_DEBUG, "Request association with " MACSTR,
+ MAC2STR(selected->bssid));
wpa_supplicant_associate(wpa_s, selected, ssid);
} else {
- wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with the "
- "selected AP");
+ wpa_dbg(wpa_s, MSG_DEBUG, "Already associated or trying to "
+ "connect with the selected AP");
}
return 0;
@@ -1214,11 +1225,12 @@
wpa_scan_results_free(scan_res);
- return wpas_select_network_from_last_scan(wpa_s);
+ return wpas_select_network_from_last_scan(wpa_s, 1);
}
-static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s)
+static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
+ int new_scan)
{
struct wpa_bss *selected;
struct wpa_ssid *ssid = NULL;
@@ -1229,7 +1241,8 @@
int skip;
skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid);
if (skip) {
- wpa_supplicant_rsn_preauth_scan_results(wpa_s);
+ if (new_scan)
+ wpa_supplicant_rsn_preauth_scan_results(wpa_s);
return 0;
}
@@ -1237,7 +1250,8 @@
wpa_dbg(wpa_s, MSG_DEBUG, "Connect failed");
return -1;
}
- wpa_supplicant_rsn_preauth_scan_results(wpa_s);
+ if (new_scan)
+ wpa_supplicant_rsn_preauth_scan_results(wpa_s);
/*
* Do not notify other virtual radios of scan results since we do not
* want them to start other associations at the same time.
@@ -1249,7 +1263,8 @@
if (ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Setup a new network");
wpa_supplicant_associate(wpa_s, NULL, ssid);
- wpa_supplicant_rsn_preauth_scan_results(wpa_s);
+ if (new_scan)
+ wpa_supplicant_rsn_preauth_scan_results(wpa_s);
} else {
int timeout_sec = wpa_s->scan_interval;
int timeout_usec = 0;
@@ -1354,7 +1369,7 @@
return -1;
}
- return wpas_select_network_from_last_scan(wpa_s);
+ return wpas_select_network_from_last_scan(wpa_s, 0);
#endif /* CONFIG_NO_SCAN_PROCESSING */
}
@@ -1674,7 +1689,6 @@
{
u8 bssid[ETH_ALEN];
int ft_completed;
- struct wpa_driver_capa capa;
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
@@ -1780,6 +1794,16 @@
wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE ||
(wpa_s->current_ssid &&
wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) {
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE &&
+ (wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
+ /*
+ * Set the key after having received joined-IBSS event
+ * from the driver.
+ */
+ wpa_supplicant_set_wpa_none_key(wpa_s,
+ wpa_s->current_ssid);
+ }
wpa_supplicant_cancel_auth_timeout(wpa_s);
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
} else if (!ft_completed) {
@@ -1840,8 +1864,8 @@
if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
- wpa_s->current_ssid && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
- capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE) {
+ wpa_s->current_ssid &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
/* Set static WEP keys again */
wpa_set_wep_keys(wpa_s, wpa_s->current_ssid);
}
@@ -1935,7 +1959,9 @@
int authenticating;
u8 prev_pending_bssid[ETH_ALEN];
struct wpa_bss *fast_reconnect = NULL;
+#ifndef CONFIG_NO_SCAN_PROCESSING
struct wpa_ssid *fast_reconnect_ssid = NULL;
+#endif /* CONFIG_NO_SCAN_PROCESSING */
struct wpa_ssid *last_ssid;
authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
@@ -1976,7 +2002,9 @@
* time for some common cases.
*/
fast_reconnect = wpa_s->current_bss;
+#ifndef CONFIG_NO_SCAN_PROCESSING
fast_reconnect_ssid = wpa_s->current_ssid;
+#endif /* CONFIG_NO_SCAN_PROCESSING */
} else if (wpa_s->wpa_state >= WPA_ASSOCIATING)
#ifdef ANDROID
wpa_supplicant_req_scan(wpa_s, 0, 500000);
@@ -2473,6 +2501,7 @@
data->deauth_info.ie,
data->deauth_info.ie_len);
}
+ wpa_reset_ft_completed(wpa_s->wpa);
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface && data && data->deauth_info.addr) {
diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py
index dbc143a..d6dec85 100755
--- a/wpa_supplicant/examples/wps-nfc.py
+++ b/wpa_supplicant/examples/wps-nfc.py
@@ -49,17 +49,22 @@
def wpas_tag_read(message):
wpas = wpas_connect()
if (wpas == None):
- return
- print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex"))
-
+ return False
+ if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + message.encode("hex")):
+ return False
+ return True
def wpas_get_config_token(id=None):
wpas = wpas_connect()
if (wpas == None):
return None
if id:
- return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF " + id).rstrip().decode("hex")
- return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex")
+ ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF " + id)
+ else:
+ ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF")
+ if "FAIL" in ret:
+ return None
+ return ret.rstrip().decode("hex")
def wpas_get_er_config_token(uuid):
@@ -241,7 +246,8 @@
print "Done with handover"
-def wps_tag_read(tag):
+def wps_tag_read(tag, wait_remove=True):
+ success = False
if len(tag.ndef.message):
message = nfc.ndef.Message(tag.ndef.message)
print "message type " + message.type
@@ -250,21 +256,25 @@
print "record type " + record.type
if record.type == "application/vnd.wfa.wsc":
print "WPS tag - send to wpa_supplicant"
- wpas_tag_read(tag.ndef.message)
+ success = wpas_tag_read(tag.ndef.message)
break
else:
print "Empty tag"
- print "Remove tag"
- while tag.is_present:
- time.sleep(0.1)
+ if wait_remove:
+ print "Remove tag"
+ while tag.is_present:
+ time.sleep(0.1)
+
+ return success
-def wps_write_config_tag(clf, id=None):
+def wps_write_config_tag(clf, id=None, wait_remove=True):
print "Write WPS config token"
data = wpas_get_config_token(id)
if (data == None):
print "Could not get WPS config token from wpa_supplicant"
+ sys.exit(1)
return
print "Touch an NFC tag"
@@ -278,7 +288,7 @@
print "Tag found - writing"
tag.ndef.message = data
print "Done - remove tag"
- while tag.is_present:
+ while wait_remove and tag.is_present:
time.sleep(0.1)
@@ -304,7 +314,7 @@
time.sleep(0.1)
-def wps_write_password_tag(clf):
+def wps_write_password_tag(clf, wait_remove=True):
print "Write WPS password token"
data = wpas_get_password_token()
if (data == None):
@@ -322,7 +332,7 @@
print "Tag found - writing"
tag.ndef.message = data
print "Done - remove tag"
- while tag.is_present:
+ while wait_remove and tag.is_present:
time.sleep(0.1)
@@ -359,13 +369,22 @@
try:
arg_uuid = None
- if len(sys.argv) > 1:
+ if len(sys.argv) > 1 and sys.argv[1] != '-1':
arg_uuid = sys.argv[1]
+ if len(sys.argv) > 1 and sys.argv[1] == '-1':
+ only_one = True
+ else:
+ only_one = False
+
if len(sys.argv) > 1 and sys.argv[1] == "write-config":
wps_write_config_tag(clf)
raise SystemExit
+ if len(sys.argv) > 1 and sys.argv[1] == "write-config-no-wait":
+ wps_write_config_tag(clf, wait_remove=False)
+ raise SystemExit
+
if len(sys.argv) > 2 and sys.argv[1] == "write-config-id":
wps_write_config_tag(clf, sys.argv[2])
raise SystemExit
@@ -378,6 +397,10 @@
wps_write_password_tag(clf)
raise SystemExit
+ if len(sys.argv) > 1 and sys.argv[1] == "write-password-no-wait":
+ wps_write_password_tag(clf, wait_remove=False)
+ raise SystemExit
+
while True:
print "Waiting for a tag or peer to be touched"
@@ -389,13 +412,21 @@
wps_handover_resp(tag, None)
else:
wps_handover_resp(tag, arg_uuid)
+ if only_one:
+ break
continue
if tag.ndef:
- wps_tag_read(tag)
+ success = wps_tag_read(tag, not only_one)
+ if only_one:
+ if not success:
+ sys.exit(1)
+ break
continue
print "Not an NDEF tag - remove tag"
+ if only_one:
+ sys.exit(1)
while tag.is_present:
time.sleep(0.1)
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index 27bcc7a..06a97d3 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -20,7 +20,7 @@
/** GAS query timeout in seconds */
-#define GAS_QUERY_TIMEOUT_PERIOD 5
+#define GAS_QUERY_TIMEOUT_PERIOD 2
/**
@@ -271,6 +271,11 @@
if (frag_id != query->next_frag_id) {
wpa_printf(MSG_DEBUG, "GAS: Unexpected frag_id in response "
"from " MACSTR, MAC2STR(query->addr));
+ if (frag_id + 1 == query->next_frag_id) {
+ wpa_printf(MSG_DEBUG, "GAS: Drop frame as possible "
+ "retry of previous fragment");
+ return;
+ }
gas_query_done(gas, query, GAS_QUERY_PEER_ERROR);
return;
}
@@ -461,16 +466,20 @@
{
struct gas_query_pending *query;
int dialog_token;
+ static int next_start = 0;
if (wpabuf_len(req) < 3)
return -1;
for (dialog_token = 0; dialog_token < 256; dialog_token++) {
- if (gas_query_dialog_token_available(gas, dst, dialog_token))
+ if (gas_query_dialog_token_available(
+ gas, dst, (next_start + dialog_token) % 256))
break;
}
if (dialog_token == 256)
return -1; /* Too many pending queries */
+ dialog_token = (next_start + dialog_token) % 256;
+ next_start = (dialog_token + 1) % 256;
query = os_zalloc(sizeof(*query));
if (query == NULL)
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 1404241..4048cf7 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -33,6 +33,35 @@
}
+int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ struct wpa_bss *bss)
+{
+ if (!wpa_s->conf->hs20 || !ssid)
+ return 0;
+
+ if (ssid->parent_cred)
+ return 1;
+
+ if (bss && !wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE))
+ return 0;
+
+ /*
+ * This may catch some non-Hotspot 2.0 cases, but it is safer to do that
+ * than cause Hotspot 2.0 connections without indication element getting
+ * added. Non-Hotspot 2.0 APs should ignore the unknown vendor element.
+ */
+
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X))
+ return 0;
+ if (!(ssid->pairwise_cipher & WPA_CIPHER_CCMP))
+ return 0;
+ if (ssid->proto != WPA_PROTO_RSN)
+ return 0;
+
+ return 1;
+}
+
+
struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
size_t payload_len)
{
diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h
index 6eb3926..1c8481b 100644
--- a/wpa_supplicant/hs20_supplicant.h
+++ b/wpa_supplicant/hs20_supplicant.h
@@ -16,5 +16,7 @@
size_t payload_len);
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *data, size_t slen);
+int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ struct wpa_bss *bss);
#endif /* HS20_SUPPLICANT_H */
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 046f181..687c042 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -296,6 +296,13 @@
}
+static void ibss_rsn_disconnect(void *ctx, const u8 *addr, u16 reason)
+{
+ struct ibss_rsn *ibss_rsn = ctx;
+ wpa_drv_sta_deauth(ibss_rsn->wpa_s, addr, reason);
+}
+
+
static int auth_for_each_sta(void *ctx, int (*cb)(struct wpa_state_machine *sm,
void *ctx),
void *cb_ctx)
@@ -386,6 +393,7 @@
cb.get_psk = auth_get_psk;
cb.set_key = auth_set_key;
cb.for_each_sta = auth_for_each_sta;
+ cb.disconnect = ibss_rsn_disconnect;
ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb);
if (ibss_rsn->auth_group == NULL) {
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index b59dd6a..36f75a1 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -408,11 +408,9 @@
return NULL;
}
wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len);
- r->realm = os_malloc(realm_len + 1);
+ r->realm = dup_binstr(pos, realm_len);
if (r->realm == NULL)
return NULL;
- os_memcpy(r->realm, pos, realm_len);
- r->realm[realm_len] = '\0';
pos += realm_len;
if (pos + 1 > f_end) {
@@ -601,19 +599,29 @@
static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
{
- u8 plmn[3];
+ u8 plmn[3], plmn2[3];
const u8 *pos, *end;
u8 udhl;
- /* See Annex A of 3GPP TS 24.234 v8.1.0 for description */
+ /*
+ * See Annex A of 3GPP TS 24.234 v8.1.0 for description. The network
+ * operator is allowed to include only two digits of the MNC, so allow
+ * matches based on both two and three digit MNC assumptions. Since some
+ * SIM/USIM cards may not expose MNC length conveniently, we may be
+ * provided the default MNC length 3 here and as such, checking with MNC
+ * length 2 is justifiable even though 3GPP TS 24.234 does not mention
+ * that case. Anyway, MCC/MNC pair where both 2 and 3 digit MNC is used
+ * with otherwise matching values would not be good idea in general, so
+ * this should not result in selecting incorrect networks.
+ */
+ /* Match with 3 digit MNC */
plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4);
- plmn[1] = imsi[2] - '0';
- /* default to MNC length 3 if unknown */
- if (mnc_len != 2)
- plmn[1] |= (imsi[5] - '0') << 4;
- else
- plmn[1] |= 0xf0;
+ plmn[1] = (imsi[2] - '0') | ((imsi[5] - '0') << 4);
plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4);
+ /* Match with 2 digit MNC */
+ plmn2[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4);
+ plmn2[1] = (imsi[2] - '0') | 0xf0;
+ plmn2[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4);
if (anqp == NULL)
return 0;
@@ -633,6 +641,10 @@
}
end = pos + udhl;
+ wpa_printf(MSG_DEBUG, "Interworking: Matching against MCC/MNC alternatives: %02x:%02x:%02x or %02x:%02x:%02x (IMSI %s, MNC length %d)",
+ plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2],
+ imsi, mnc_len);
+
while (pos + 2 <= end) {
u8 iei, len;
const u8 *l_end;
@@ -645,14 +657,20 @@
if (iei == 0 && len > 0) {
/* PLMN List */
u8 num, i;
+ wpa_hexdump(MSG_DEBUG, "Interworking: PLMN List information element",
+ pos, len);
num = *pos++;
for (i = 0; i < num; i++) {
- if (pos + 3 > end)
+ if (pos + 3 > l_end)
break;
- if (os_memcmp(pos, plmn, 3) == 0)
+ if (os_memcmp(pos, plmn, 3) == 0 ||
+ os_memcmp(pos, plmn2, 3) == 0)
return 1; /* Found matching PLMN */
pos += 3;
}
+ } else {
+ wpa_hexdump(MSG_DEBUG, "Interworking: Unrecognized 3GPP information element",
+ pos, len);
}
pos = l_end;
@@ -1339,6 +1357,8 @@
char *sep;
const char *imsi;
int mnc_len;
+ char imsi_buf[16];
+ size_t msin_len;
#ifdef PCSC_FUNCS
if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard &&
@@ -1348,6 +1368,13 @@
goto compare;
}
#endif /* PCSC_FUNCS */
+#ifdef CONFIG_EAP_PROXY
+ if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) {
+ imsi = wpa_s->imsi;
+ mnc_len = wpa_s->mnc_len;
+ goto compare;
+ }
+#endif /* CONFIG_EAP_PROXY */
if (cred->imsi == NULL || !cred->imsi[0] ||
cred->milenage == NULL || !cred->milenage[0])
@@ -1358,11 +1385,18 @@
(sep - cred->imsi != 5 && sep - cred->imsi != 6))
continue;
mnc_len = sep - cred->imsi - 3;
- imsi = cred->imsi;
+ os_memcpy(imsi_buf, cred->imsi, 3 + mnc_len);
+ sep++;
+ msin_len = os_strlen(cred->imsi);
+ if (3 + mnc_len + msin_len >= sizeof(imsi_buf) - 1)
+ msin_len = sizeof(imsi_buf) - 3 - mnc_len - 1;
+ os_memcpy(&imsi_buf[3 + mnc_len], sep, msin_len);
+ imsi_buf[3 + mnc_len + msin_len] = '\0';
+ imsi = imsi_buf;
-#ifdef PCSC_FUNCS
+#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY)
compare:
-#endif /* PCSC_FUNCS */
+#endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */
wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from "
MACSTR, MAC2STR(bss->bssid));
ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len);
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index 1744620..39b837e 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / main() function for UNIX like OSes and MinGW
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -14,6 +14,7 @@
#include "common.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
+#include "p2p_supplicant.h"
extern struct wpa_driver_ops *wpa_drivers[];
@@ -25,6 +26,7 @@
"usage:\n"
" wpa_supplicant [-BddhKLqqstuvW] [-P<pid file>] "
"[-g<global ctrl>] \\\n"
+ " [-G<group>] \\\n"
" -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
"[-p<driver_param>] \\\n"
" [-b<br_ifname>] [-f<debug file>] [-e<entropy file>] "
@@ -59,6 +61,7 @@
printf(" -f = log output to debug file instead of stdout\n");
#endif /* CONFIG_DEBUG_FILE */
printf(" -g = global ctrl_interface\n"
+ " -G = global ctrl_interface group\n"
" -K = include keys (passwords, etc.) in debug output\n");
#ifdef CONFIG_DEBUG_SYSLOG
printf(" -s = log output to syslog instead of stdout\n");
@@ -84,7 +87,7 @@
printf("example:\n"
" wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
- wpa_drivers[i] ? wpa_drivers[i]->name : "wext");
+ wpa_drivers[0] ? wpa_drivers[0]->name : "nl80211");
#endif /* CONFIG_NO_STDOUT_DEBUG */
}
@@ -157,7 +160,7 @@
for (;;) {
c = getopt(argc, argv,
- "b:Bc:C:D:de:f:g:hi:I:KLNo:O:p:P:qsTtuvW");
+ "b:Bc:C:D:de:f:g:G:hi:I:KLNo:O:p:P:qsTtuvW");
if (c < 0)
break;
switch (c) {
@@ -197,6 +200,9 @@
case 'g':
params.ctrl_interface = optarg;
break;
+ case 'G':
+ params.ctrl_interface_group = optarg;
+ break;
case 'h':
usage();
exitcode = 0;
@@ -284,6 +290,8 @@
}
for (i = 0; exitcode == 0 && i < iface_count; i++) {
+ struct wpa_supplicant *wpa_s;
+
if ((ifaces[i].confname == NULL &&
ifaces[i].ctrl_interface == NULL) ||
ifaces[i].ifname == NULL) {
@@ -294,8 +302,18 @@
exitcode = -1;
break;
}
- if (wpa_supplicant_add_iface(global, &ifaces[i]) == NULL)
+ wpa_s = wpa_supplicant_add_iface(global, &ifaces[i]);
+ if (wpa_s == NULL) {
exitcode = -1;
+ break;
+ }
+#ifdef CONFIG_P2P
+ if (wpa_s->global->p2p == NULL &&
+ (wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
+ wpas_p2p_add_p2pdev_interface(wpa_s) < 0)
+ exitcode = -1;
+#endif /* CONFIG_P2P */
}
if (exitcode == 0)
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 4479c09..f2cbdd7 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -551,6 +551,9 @@
*/
wpas_dbus_signal_p2p_peer_joined(wpa_s, sta);
#endif /* CONFIG_P2P */
+
+ /* Notify listeners a new station has been authorized */
+ wpas_dbus_signal_sta_authorized(wpa_s, sta);
}
@@ -570,6 +573,9 @@
*/
wpas_dbus_signal_p2p_peer_disconnected(wpa_s, sta);
#endif /* CONFIG_P2P */
+
+ /* Notify listeners a station has been deauthorized */
+ wpas_dbus_signal_sta_deauthorized(wpa_s, sta);
}
@@ -631,4 +637,7 @@
const char *parameter)
{
wpas_dbus_signal_eap_status(wpa_s, status, parameter);
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_EAP_STATUS
+ "status='%s' parameter='%s'",
+ status, parameter);
}
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 4b505b5..37f5ad3 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -65,6 +65,8 @@
#define P2P_CONCURRENT_SEARCH_DELAY 500
#endif /* P2P_CONCURRENT_SEARCH_DELAY */
+#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
+
enum p2p_group_removal_reason {
P2P_GROUP_REMOVAL_UNKNOWN,
P2P_GROUP_REMOVAL_SILENT,
@@ -95,6 +97,9 @@
static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
void *timeout_ctx);
+#ifdef ANDROID_P2P
+static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx);
+#endif
static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
int group_added);
static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
@@ -318,9 +323,9 @@
gtype = "GO";
if (wpa_s->cross_connect_in_use) {
wpa_s->cross_connect_in_use = 0;
- wpa_msg(wpa_s->parent, MSG_INFO,
- P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
- wpa_s->ifname, wpa_s->cross_connect_uplink);
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
+ wpa_s->ifname, wpa_s->cross_connect_uplink);
}
switch (removal_reason) {
case P2P_GROUP_REMOVAL_REQUESTED:
@@ -348,11 +353,14 @@
break;
}
if (removal_reason != P2P_GROUP_REMOVAL_SILENT) {
- wpa_msg(wpa_s->parent, MSG_INFO,
- P2P_EVENT_GROUP_REMOVED "%s %s%s",
- wpa_s->ifname, gtype, reason);
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_GROUP_REMOVED "%s %s%s",
+ wpa_s->ifname, gtype, reason);
}
+#ifdef ANDROID_P2P
+ eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
+#endif
if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
@@ -657,14 +665,15 @@
wpa_s->p2p_in_provisioning = 0;
if (!success) {
- wpa_msg(wpa_s->parent, MSG_INFO,
- P2P_EVENT_GROUP_FORMATION_FAILURE);
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_GROUP_FORMATION_FAILURE);
wpas_p2p_group_delete(wpa_s,
P2P_GROUP_REMOVAL_FORMATION_FAILED);
return;
}
- wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_FORMATION_SUCCESS);
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_GROUP_FORMATION_SUCCESS);
ssid = wpa_s->current_ssid;
if (ssid && ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
@@ -711,22 +720,23 @@
} else if (ssid && ssid->passphrase == NULL && ssid->psk_set) {
char psk[65];
wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
- wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
- "%s GO ssid=\"%s\" freq=%d psk=%s go_dev_addr=" MACSTR
- "%s",
- wpa_s->ifname, ssid_txt, ssid->frequency, psk,
- MAC2STR(go_dev_addr),
- persistent ? " [PERSISTENT]" : "");
+ wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
+ "%s GO ssid=\"%s\" freq=%d psk=%s go_dev_addr="
+ MACSTR "%s",
+ wpa_s->ifname, ssid_txt, ssid->frequency, psk,
+ MAC2STR(go_dev_addr),
+ persistent ? " [PERSISTENT]" : "");
wpas_p2p_cross_connect_setup(wpa_s);
wpas_p2p_set_group_idle_timeout(wpa_s);
} else {
- wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
- "%s GO ssid=\"%s\" freq=%d passphrase=\"%s\" "
- "go_dev_addr=" MACSTR "%s",
- wpa_s->ifname, ssid_txt, ssid ? ssid->frequency : 0,
- ssid && ssid->passphrase ? ssid->passphrase : "",
- MAC2STR(go_dev_addr),
- persistent ? " [PERSISTENT]" : "");
+ wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
+ "%s GO ssid=\"%s\" freq=%d passphrase=\"%s\" "
+ "go_dev_addr=" MACSTR "%s",
+ wpa_s->ifname, ssid_txt,
+ ssid ? ssid->frequency : 0,
+ ssid && ssid->passphrase ? ssid->passphrase : "",
+ MAC2STR(go_dev_addr),
+ persistent ? " [PERSISTENT]" : "");
wpas_p2p_cross_connect_setup(wpa_s);
wpas_p2p_set_group_idle_timeout(wpa_s);
}
@@ -849,26 +859,30 @@
if (wpa_s->global->p2p_group_formation == wpa_s)
wpa_s->global->p2p_group_formation = NULL;
if (os_strlen(params->passphrase) > 0) {
- wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
- "%s GO ssid=\"%s\" freq=%d passphrase=\"%s\" "
- "go_dev_addr=" MACSTR "%s", wpa_s->ifname,
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
- ssid->frequency, params->passphrase,
- MAC2STR(wpa_s->global->p2p_dev_addr),
- params->persistent_group ? " [PERSISTENT]" :
- "");
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_GROUP_STARTED
+ "%s GO ssid=\"%s\" freq=%d "
+ "passphrase=\"%s\" go_dev_addr=" MACSTR
+ "%s", wpa_s->ifname,
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+ ssid->frequency, params->passphrase,
+ MAC2STR(wpa_s->global->p2p_dev_addr),
+ params->persistent_group ?
+ " [PERSISTENT]" : "");
} else {
char psk[65];
wpa_snprintf_hex(psk, sizeof(psk), params->psk,
sizeof(params->psk));
- wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
- "%s GO ssid=\"%s\" freq=%d psk=%s "
- "go_dev_addr=" MACSTR "%s", wpa_s->ifname,
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
- ssid->frequency, psk,
- MAC2STR(wpa_s->global->p2p_dev_addr),
- params->persistent_group ? " [PERSISTENT]" :
- "");
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_GROUP_STARTED
+ "%s GO ssid=\"%s\" freq=%d psk=%s "
+ "go_dev_addr=" MACSTR "%s",
+ wpa_s->ifname,
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+ ssid->frequency, psk,
+ MAC2STR(wpa_s->global->p2p_dev_addr),
+ params->persistent_group ?
+ " [PERSISTENT]" : "");
}
if (params->persistent_group)
@@ -942,8 +956,8 @@
if (os_strlen(params->passphrase) > 0) {
ssid->passphrase = os_strdup(params->passphrase);
if (ssid->passphrase == NULL) {
- wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to copy "
- "passphrase for GO");
+ wpa_msg_global(wpa_s, MSG_ERROR,
+ "P2P: Failed to copy passphrase for GO");
wpa_config_remove_network(wpa_s->conf, ssid->id);
return;
}
@@ -997,6 +1011,27 @@
d->max_num_sta = s->max_num_sta;
d->pbc_in_m1 = s->pbc_in_m1;
d->ignore_old_scan_res = s->ignore_old_scan_res;
+ d->beacon_int = s->beacon_int;
+}
+
+
+static void wpas_p2p_get_group_ifname(struct wpa_supplicant *wpa_s,
+ char *ifname, size_t len)
+{
+ char *ifname_ptr = wpa_s->ifname;
+
+ if (os_strncmp(wpa_s->ifname, P2P_MGMT_DEVICE_PREFIX,
+ os_strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+ ifname_ptr = os_strrchr(wpa_s->ifname, '-') + 1;
+ }
+
+ os_snprintf(ifname, len, "p2p-%s-%d", ifname_ptr, wpa_s->p2p_group_idx);
+ if (os_strlen(ifname) >= IFNAMSIZ &&
+ os_strlen(wpa_s->ifname) < IFNAMSIZ) {
+ /* Try to avoid going over the IFNAMSIZ length limit */
+ os_snprintf(ifname, sizeof(ifname), "p2p-%d",
+ wpa_s->p2p_group_idx);
+ }
}
@@ -1017,14 +1052,7 @@
return 0;
}
- os_snprintf(ifname, sizeof(ifname), "p2p-%s-%d", wpa_s->ifname,
- wpa_s->p2p_group_idx);
- if (os_strlen(ifname) >= IFNAMSIZ &&
- os_strlen(wpa_s->ifname) < IFNAMSIZ) {
- /* Try to avoid going over the IFNAMSIZ length limit */
- os_snprintf(ifname, sizeof(ifname), "p2p-%d",
- wpa_s->p2p_group_idx);
- }
+ wpas_p2p_get_group_ifname(wpa_s, ifname, sizeof(ifname));
force_ifname[0] = '\0';
wpa_printf(MSG_DEBUG, "P2P: Create a new interface %s for the group",
@@ -1094,7 +1122,13 @@
os_memset(&iface, 0, sizeof(iface));
iface.ifname = wpa_s->pending_interface_name;
iface.driver = wpa_s->driver->name;
- iface.ctrl_interface = wpa_s->conf->ctrl_interface;
+ if (wpa_s->conf->ctrl_interface == NULL &&
+ wpa_s->parent != wpa_s &&
+ wpa_s->p2p_mgmt &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE))
+ iface.ctrl_interface = wpa_s->parent->conf->ctrl_interface;
+ else
+ iface.ctrl_interface = wpa_s->conf->ctrl_interface;
iface.driver_param = wpa_s->conf->driver_param;
group_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
if (group_wpa_s == NULL) {
@@ -1119,6 +1153,14 @@
{
struct wpa_supplicant *wpa_s = eloop_ctx;
wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out");
+ wpas_p2p_group_formation_failed(wpa_s);
+}
+
+
+void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s)
+{
+ eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
+ wpa_s->parent, NULL);
if (wpa_s->global->p2p)
p2p_group_formation_failed(wpa_s->global->p2p);
else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
@@ -1138,8 +1180,9 @@
}
if (res->status) {
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_FAILURE "status=%d",
- res->status);
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_GO_NEG_FAILURE "status=%d",
+ res->status);
wpas_notify_p2p_go_neg_completed(wpa_s, res);
wpas_p2p_remove_pending_group_interface(wpa_s);
return;
@@ -1148,7 +1191,7 @@
if (wpa_s->p2p_go_ht40)
res->ht40 = 1;
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS);
wpas_notify_p2p_go_neg_completed(wpa_s, res);
if (res->role_go && wpa_s->p2p_persistent_id >= 0) {
@@ -1208,8 +1251,8 @@
void wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
{
struct wpa_supplicant *wpa_s = ctx;
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_REQUEST MACSTR
- " dev_passwd_id=%u", MAC2STR(src), dev_passwd_id);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_REQUEST MACSTR
+ " dev_passwd_id=%u", MAC2STR(src), dev_passwd_id);
wpas_notify_p2p_go_neg_req(wpa_s, src, dev_passwd_id);
}
@@ -1232,16 +1275,16 @@
WFD_DEV_INFO_SIZE);
}
#endif /* CONFIG_WIFI_DISPLAY */
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
- " p2p_dev_addr=" MACSTR
- " pri_dev_type=%s name='%s' config_methods=0x%x "
- "dev_capab=0x%x group_capab=0x%x%s%s",
- MAC2STR(addr), MAC2STR(info->p2p_device_addr),
- wps_dev_type_bin2str(info->pri_dev_type, devtype,
- sizeof(devtype)),
- info->device_name, info->config_methods,
- info->dev_capab, info->group_capab,
- wfd_dev_info_hex[0] ? " wfd_dev_info=0x" : "", wfd_dev_info_hex);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
+ " p2p_dev_addr=" MACSTR
+ " pri_dev_type=%s name='%s' config_methods=0x%x "
+ "dev_capab=0x%x group_capab=0x%x%s%s",
+ MAC2STR(addr), MAC2STR(info->p2p_device_addr),
+ wps_dev_type_bin2str(info->pri_dev_type, devtype,
+ sizeof(devtype)),
+ info->device_name, info->config_methods,
+ info->dev_capab, info->group_capab,
+ wfd_dev_info_hex[0] ? " wfd_dev_info=0x" : "", wfd_dev_info_hex);
#endif /* CONFIG_NO_STDOUT_DEBUG */
wpas_notify_p2p_device_found(ctx, info->p2p_device_addr, new_device);
@@ -1252,13 +1295,20 @@
{
struct wpa_supplicant *wpa_s = ctx;
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_LOST
- "p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_LOST
+ "p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
wpas_notify_p2p_device_lost(wpa_s, dev_addr);
}
+static void wpas_find_stopped(void *ctx)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED);
+}
+
+
static int wpas_start_listen(void *ctx, unsigned int freq,
unsigned int duration,
const struct wpabuf *probe_resp_ie)
@@ -2267,16 +2317,16 @@
const u8 *peer, const char *params,
unsigned int generated_pin)
{
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_SHOW_PIN MACSTR " %08d%s",
- MAC2STR(peer), generated_pin, params);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_SHOW_PIN MACSTR
+ " %08d%s", MAC2STR(peer), generated_pin, params);
}
static void wpas_prov_disc_local_keypad(struct wpa_supplicant *wpa_s,
const u8 *peer, const char *params)
{
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_ENTER_PIN MACSTR "%s",
- MAC2STR(peer), params);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_ENTER_PIN MACSTR
+ "%s", MAC2STR(peer), params);
}
@@ -2328,8 +2378,8 @@
} else if (config_methods & WPS_CONFIG_KEYPAD)
wpas_prov_disc_local_keypad(wpa_s, peer, params);
else if (config_methods & WPS_CONFIG_PUSHBUTTON)
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_REQ MACSTR
- "%s", MAC2STR(peer), params);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_REQ
+ MACSTR "%s", MAC2STR(peer), params);
wpas_notify_p2p_provision_discovery(wpa_s, peer, 1 /* request */,
P2P_PROV_DISC_SUCCESS,
@@ -2367,8 +2417,8 @@
wpas_prov_disc_local_display(wpa_s, peer, params,
generated_pin);
} else if (config_methods & WPS_CONFIG_PUSHBUTTON)
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP MACSTR
- "%s", MAC2STR(peer), params);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP
+ MACSTR "%s", MAC2STR(peer), params);
wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
P2P_PROV_DISC_SUCCESS,
@@ -2397,19 +2447,29 @@
return;
}
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
- " p2p_dev_addr=" MACSTR " status=%d",
- MAC2STR(peer), status);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
+ " p2p_dev_addr=" MACSTR " status=%d",
+ MAC2STR(peer), status);
wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
status, 0, 0);
}
+static int freq_included(const struct p2p_channels *channels, unsigned int freq)
+{
+ if (channels == NULL)
+ return 1; /* Assume no restrictions */
+ return p2p_channels_includes_freq(channels, freq);
+
+}
+
+
static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
const u8 *go_dev_addr, const u8 *ssid,
size_t ssid_len, int *go, u8 *group_bssid,
- int *force_freq, int persistent_group)
+ int *force_freq, int persistent_group,
+ const struct p2p_channels *channels)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *s;
@@ -2507,6 +2567,25 @@
wpas_p2p_set_own_freq_preference(wpa_s, res);
}
+ if (*force_freq > 0 &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
+ if (*go == 0) {
+ /* We are the client */
+ wpa_printf(MSG_DEBUG, "P2P: Peer was found to be "
+ "running a GO but we are capable of MCC, "
+ "figure out the best channel to use");
+ *force_freq = 0;
+ } else if (!freq_included(channels, *force_freq)) {
+ /* We are the GO, and *force_freq is not in the
+ * intersection */
+ wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
+ "in intersection but we are capable of MCC, "
+ "figure out the best channel to use",
+ *force_freq);
+ *force_freq = 0;
+ }
+ }
+
return P2P_SC_SUCCESS;
}
@@ -2550,27 +2629,30 @@
if (!s) {
if (bssid) {
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
- "sa=" MACSTR " go_dev_addr=" MACSTR
- " bssid=" MACSTR " unknown-network",
- MAC2STR(sa), MAC2STR(go_dev_addr),
- MAC2STR(bssid));
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_INVITATION_RECEIVED
+ "sa=" MACSTR " go_dev_addr=" MACSTR
+ " bssid=" MACSTR " unknown-network",
+ MAC2STR(sa), MAC2STR(go_dev_addr),
+ MAC2STR(bssid));
} else {
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
- "sa=" MACSTR " go_dev_addr=" MACSTR
- " unknown-network",
- MAC2STR(sa), MAC2STR(go_dev_addr));
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_INVITATION_RECEIVED
+ "sa=" MACSTR " go_dev_addr=" MACSTR
+ " unknown-network",
+ MAC2STR(sa), MAC2STR(go_dev_addr));
}
return;
}
if (s->mode == WPAS_MODE_P2P_GO && op_freq) {
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED "sa="
- MACSTR " persistent=%d freq=%d",
- MAC2STR(sa), s->id, op_freq);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
+ "sa=" MACSTR " persistent=%d freq=%d",
+ MAC2STR(sa), s->id, op_freq);
} else {
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED "sa="
- MACSTR " persistent=%d", MAC2STR(sa), s->id);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
+ "sa=" MACSTR " persistent=%d",
+ MAC2STR(sa), s->id);
}
}
@@ -2642,12 +2724,12 @@
struct wpa_ssid *ssid;
if (bssid) {
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
- "status=%d " MACSTR,
- status, MAC2STR(bssid));
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
+ "status=%d " MACSTR,
+ status, MAC2STR(bssid));
} else {
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
- "status=%d ", status);
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
+ "status=%d ", status);
}
wpas_notify_p2p_invitation_result(wpa_s, status, bssid);
@@ -2988,6 +3070,52 @@
}
+static void wpas_p2p_debug_print(void *ctx, int level, const char *msg)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ wpa_msg_global(wpa_s, level, "P2P: %s", msg);
+}
+
+
+int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_interface iface;
+ struct wpa_supplicant *p2pdev_wpa_s;
+ char ifname[100];
+ char force_name[100];
+ int ret;
+
+ os_snprintf(ifname, sizeof(ifname), P2P_MGMT_DEVICE_PREFIX "%s",
+ wpa_s->ifname);
+ force_name[0] = '\0';
+ wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE;
+ ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, NULL, NULL,
+ force_name, wpa_s->pending_interface_addr, NULL);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to create P2P Device interface");
+ return ret;
+ }
+ os_strlcpy(wpa_s->pending_interface_name, ifname,
+ sizeof(wpa_s->pending_interface_name));
+
+ os_memset(&iface, 0, sizeof(iface));
+ iface.p2p_mgmt = 1;
+ iface.ifname = wpa_s->pending_interface_name;
+ iface.driver = wpa_s->driver->name;
+ iface.driver_param = wpa_s->conf->driver_param;
+ iface.confname = wpa_s->confname;
+ p2pdev_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
+ if (!p2pdev_wpa_s) {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to add P2P Device interface");
+ return -1;
+ }
+ p2pdev_wpa_s->parent = wpa_s;
+
+ wpa_s->pending_interface_name[0] = '\0';
+ return 0;
+}
+
+
/**
* wpas_p2p_init - Initialize P2P module for %wpa_supplicant
* @global: Pointer to global data from wpa_supplicant_init()
@@ -3026,8 +3154,8 @@
}
os_memset(&p2p, 0, sizeof(p2p));
- p2p.msg_ctx = wpa_s;
p2p.cb_ctx = wpa_s;
+ p2p.debug_print = wpas_p2p_debug_print;
p2p.p2p_scan = wpas_p2p_scan;
p2p.send_action = wpas_send_action;
p2p.send_action_done = wpas_send_action_done;
@@ -3035,6 +3163,7 @@
p2p.go_neg_req_rx = wpas_go_neg_req_rx;
p2p.dev_found = wpas_dev_found;
p2p.dev_lost = wpas_dev_lost;
+ p2p.find_stopped = wpas_find_stopped;
p2p.start_listen = wpas_start_listen;
p2p.stop_listen = wpas_stop_listen;
p2p.send_probe_resp = wpas_send_probe_resp;
@@ -3096,6 +3225,12 @@
wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
"%d:%d", p2p.op_reg_class, p2p.op_channel);
}
+
+ if (wpa_s->conf->p2p_pref_chan && wpa_s->conf->num_p2p_pref_chan) {
+ p2p.pref_chan = wpa_s->conf->p2p_pref_chan;
+ p2p.num_pref_chan = wpa_s->conf->num_p2p_pref_chan;
+ }
+
if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
os_memcpy(p2p.country, wpa_s->conf->country, 2);
p2p.country[2] = 0x04;
@@ -3180,6 +3315,9 @@
os_free(wpa_s->go_params);
wpa_s->go_params = NULL;
+#ifdef ANDROID_P2P
+ eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
+#endif
eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
wpa_s->p2p_long_listen = 0;
@@ -3242,7 +3380,8 @@
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s)
{
- if (wpa_s->conf->p2p_no_group_iface)
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
+ wpa_s->conf->p2p_no_group_iface)
return 0; /* separate interface disabled per configuration */
if (wpa_s->drv_flags &
(WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE |
@@ -3322,13 +3461,14 @@
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
if (wpa_s->p2p_auto_pd) {
wpa_s->p2p_auto_pd = 0;
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
- " p2p_dev_addr=" MACSTR " status=N/A",
- MAC2STR(wpa_s->pending_join_dev_addr));
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_PROV_DISC_FAILURE
+ " p2p_dev_addr=" MACSTR " status=N/A",
+ MAC2STR(wpa_s->pending_join_dev_addr));
return;
}
- wpa_msg(wpa_s->parent, MSG_INFO,
- P2P_EVENT_GROUP_FORMATION_FAILURE);
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_GROUP_FORMATION_FAILURE);
}
}
@@ -3452,9 +3592,10 @@
wpa_s->pending_pd_config_methods, join,
0, wpa_s->user_initiated_pd) < 0) {
wpa_s->p2p_auto_pd = 0;
- wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
- " p2p_dev_addr=" MACSTR " status=N/A",
- MAC2STR(wpa_s->pending_join_dev_addr));
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_PROV_DISC_FAILURE
+ " p2p_dev_addr=" MACSTR " status=N/A",
+ MAC2STR(wpa_s->pending_join_dev_addr));
}
return;
}
@@ -3516,9 +3657,9 @@
u16 method;
if (wpas_check_freq_conflict(wpa_s, freq) > 0) {
- wpa_msg(wpa_s->parent, MSG_INFO,
- P2P_EVENT_GROUP_FORMATION_FAILURE
- "reason=FREQ_CONFLICT");
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_GROUP_FORMATION_FAILURE
+ "reason=FREQ_CONFLICT");
return;
}
@@ -4059,11 +4200,57 @@
}
-static int freq_included(const struct p2p_channels *channels, unsigned int freq)
+static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
{
- if (channels == NULL)
- return 1; /* Assume no restrictions */
- return p2p_channels_includes_freq(channels, freq);
+ unsigned int r;
+
+ if (freq == 2) {
+ wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 2.4 GHz "
+ "band");
+ if (wpa_s->best_24_freq > 0 &&
+ p2p_supported_freq(wpa_s->global->p2p,
+ wpa_s->best_24_freq)) {
+ freq = wpa_s->best_24_freq;
+ wpa_printf(MSG_DEBUG, "P2P: Use best 2.4 GHz band "
+ "channel: %d MHz", freq);
+ } else {
+ os_get_random((u8 *) &r, sizeof(r));
+ freq = 2412 + (r % 3) * 25;
+ wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
+ "channel: %d MHz", freq);
+ }
+ }
+
+ if (freq == 5) {
+ wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 5 GHz "
+ "band");
+ if (wpa_s->best_5_freq > 0 &&
+ p2p_supported_freq(wpa_s->global->p2p,
+ wpa_s->best_5_freq)) {
+ freq = wpa_s->best_5_freq;
+ wpa_printf(MSG_DEBUG, "P2P: Use best 5 GHz band "
+ "channel: %d MHz", freq);
+ } else {
+ os_get_random((u8 *) &r, sizeof(r));
+ freq = 5180 + (r % 4) * 20;
+ if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
+ wpa_printf(MSG_DEBUG, "P2P: Could not select "
+ "5 GHz channel for P2P group");
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "P2P: Use random 5 GHz band "
+ "channel: %d MHz", freq);
+ }
+ }
+
+ if (freq > 0 && !p2p_supported_freq(wpa_s->global->p2p, freq)) {
+ wpa_printf(MSG_DEBUG, "P2P: The forced channel for GO "
+ "(%u MHz) is not supported for P2P uses",
+ freq);
+ return -1;
+ }
+
+ return freq;
}
@@ -4074,6 +4261,7 @@
{
u8 bssid[ETH_ALEN];
int res;
+ unsigned int pref_freq;
os_memset(params, 0, sizeof(*params));
params->role_go = 1;
@@ -4130,6 +4318,11 @@
params->freq = wpa_s->best_5_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
"channel %d MHz", params->freq);
+ } else if ((pref_freq = p2p_get_pref_freq(wpa_s->global->p2p,
+ channels))) {
+ params->freq = pref_freq;
+ wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred "
+ "channels", params->freq);
} else {
int chan;
for (chan = 0; chan < 11; chan++) {
@@ -4224,13 +4417,14 @@
if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
WPA_IF_P2P_CLIENT) < 0) {
- wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to add group interface");
+ wpa_msg_global(wpa_s, MSG_ERROR,
+ "P2P: Failed to add group interface");
return NULL;
}
group_wpa_s = wpas_p2p_init_group_interface(wpa_s, go);
if (group_wpa_s == NULL) {
- wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to initialize group "
- "interface");
+ wpa_msg_global(wpa_s, MSG_ERROR,
+ "P2P: Failed to initialize group interface");
wpas_p2p_remove_pending_group_interface(wpa_s);
return NULL;
}
@@ -4255,7 +4449,6 @@
int freq, int ht40)
{
struct p2p_go_neg_results params;
- unsigned int r;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
@@ -4264,51 +4457,9 @@
wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
wpas_p2p_stop_find_oper(wpa_s);
- if (freq == 2) {
- wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 2.4 GHz "
- "band");
- if (wpa_s->best_24_freq > 0 &&
- p2p_supported_freq(wpa_s->global->p2p,
- wpa_s->best_24_freq)) {
- freq = wpa_s->best_24_freq;
- wpa_printf(MSG_DEBUG, "P2P: Use best 2.4 GHz band "
- "channel: %d MHz", freq);
- } else {
- os_get_random((u8 *) &r, sizeof(r));
- freq = 2412 + (r % 3) * 25;
- wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
- "channel: %d MHz", freq);
- }
- }
-
- if (freq == 5) {
- wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 5 GHz "
- "band");
- if (wpa_s->best_5_freq > 0 &&
- p2p_supported_freq(wpa_s->global->p2p,
- wpa_s->best_5_freq)) {
- freq = wpa_s->best_5_freq;
- wpa_printf(MSG_DEBUG, "P2P: Use best 5 GHz band "
- "channel: %d MHz", freq);
- } else {
- os_get_random((u8 *) &r, sizeof(r));
- freq = 5180 + (r % 4) * 20;
- if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
- wpa_printf(MSG_DEBUG, "P2P: Could not select "
- "5 GHz channel for P2P group");
- return -1;
- }
- wpa_printf(MSG_DEBUG, "P2P: Use random 5 GHz band "
- "channel: %d MHz", freq);
- }
- }
-
- if (freq > 0 && !p2p_supported_freq(wpa_s->global->p2p, freq)) {
- wpa_printf(MSG_DEBUG, "P2P: The forced channel for GO "
- "(%u MHz) is not supported for P2P uses",
- freq);
+ freq = wpas_p2p_select_go_freq(wpa_s, freq);
+ if (freq < 0)
return -1;
- }
if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, NULL))
return -1;
@@ -4404,6 +4555,10 @@
if (ssid->mode != WPAS_MODE_P2P_GO)
return -1;
+ freq = wpas_p2p_select_go_freq(wpa_s, freq);
+ if (freq < 0)
+ return -1;
+
if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, channels))
return -1;
@@ -5034,20 +5189,20 @@
if (ssid->passphrase == NULL && ssid->psk_set) {
char psk[65];
wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
- wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
- "%s client ssid=\"%s\" freq=%d psk=%s go_dev_addr="
- MACSTR "%s",
- wpa_s->ifname, ssid_txt, freq, psk,
- MAC2STR(go_dev_addr),
- persistent ? " [PERSISTENT]" : "");
+ wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
+ "%s client ssid=\"%s\" freq=%d psk=%s "
+ "go_dev_addr=" MACSTR "%s",
+ wpa_s->ifname, ssid_txt, freq, psk,
+ MAC2STR(go_dev_addr),
+ persistent ? " [PERSISTENT]" : "");
} else {
- wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
- "%s client ssid=\"%s\" freq=%d passphrase=\"%s\" "
- "go_dev_addr=" MACSTR "%s",
- wpa_s->ifname, ssid_txt, freq,
- ssid->passphrase ? ssid->passphrase : "",
- MAC2STR(go_dev_addr),
- persistent ? " [PERSISTENT]" : "");
+ wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
+ "%s client ssid=\"%s\" freq=%d "
+ "passphrase=\"%s\" go_dev_addr=" MACSTR "%s",
+ wpa_s->ifname, ssid_txt, freq,
+ ssid->passphrase ? ssid->passphrase : "",
+ MAC2STR(go_dev_addr),
+ persistent ? " [PERSISTENT]" : "");
}
if (persistent)
@@ -5379,9 +5534,10 @@
iface->cross_connect_enabled = 0;
iface->cross_connect_in_use = 0;
- wpa_msg(iface->parent, MSG_INFO,
- P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
- iface->ifname, iface->cross_connect_uplink);
+ wpa_msg_global(iface->parent, MSG_INFO,
+ P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
+ iface->ifname,
+ iface->cross_connect_uplink);
}
}
@@ -5408,9 +5564,9 @@
continue;
iface->cross_connect_in_use = 1;
- wpa_msg(iface->parent, MSG_INFO,
- P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
- iface->ifname, iface->cross_connect_uplink);
+ wpa_msg_global(iface->parent, MSG_INFO,
+ P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
+ iface->ifname, iface->cross_connect_uplink);
}
}
@@ -5428,9 +5584,9 @@
if (!iface->cross_connect_in_use)
continue;
- wpa_msg(iface->parent, MSG_INFO,
- P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
- iface->ifname, iface->cross_connect_uplink);
+ wpa_msg_global(iface->parent, MSG_INFO,
+ P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
+ iface->ifname, iface->cross_connect_uplink);
iface->cross_connect_in_use = 0;
}
}
@@ -5490,9 +5646,9 @@
break;
wpa_s->cross_connect_in_use = 1;
- wpa_msg(wpa_s->parent, MSG_INFO,
- P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
- wpa_s->ifname, wpa_s->cross_connect_uplink);
+ wpa_msg_global(wpa_s->parent, MSG_INFO,
+ P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
+ wpa_s->ifname, wpa_s->cross_connect_uplink);
break;
}
}
@@ -5508,14 +5664,7 @@
"session overlap");
if (wpa_s != wpa_s->parent)
wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP);
-
- if (wpa_s->global->p2p)
- p2p_group_formation_failed(wpa_s->global->p2p);
-
- eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
-
- wpas_group_formation_completed(wpa_s, 0);
+ wpas_p2p_group_formation_failed(wpa_s);
return 1;
}
@@ -5858,6 +6007,14 @@
}
#ifdef ANDROID_P2P
+static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG, "P2P: Frequency conflict - terminate group");
+ wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_FREQ_CONFLICT);
+}
+
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq,
struct wpa_ssid *ssid)
{
@@ -5890,7 +6047,8 @@
* P2P connection. So remove the interface */
wpa_printf(MSG_DEBUG, "P2P: Removing P2P connection due to Single channel"
"concurrent mode frequency conflict");
- wpas_p2p_group_delete(iface, P2P_GROUP_REMOVAL_FREQ_CONFLICT);
+ eloop_register_timeout(0, 0, wpas_p2p_group_freq_conflict,
+ iface, NULL);
/* If connection in progress is p2p connection, do not proceed for the connection */
if (wpa_s == iface)
return -1;
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 04ba9b2..3ca6222 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -14,10 +14,12 @@
enum p2p_send_action_result;
struct p2p_peer_info;
struct p2p_channels;
+struct wps_event_fail;
int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s);
void wpas_p2p_deinit(struct wpa_supplicant *wpa_s);
void wpas_p2p_deinit_global(struct wpa_global *global);
+int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s);
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
const char *pin, enum p2p_wps_method wps_method,
int persistent_group, int auto_join, int join,
@@ -76,6 +78,7 @@
void wpas_dev_found(void *ctx, const u8 *addr,
const struct p2p_peer_info *info,
int new_device);
+void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s);
void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res);
void wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id);
void wpas_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index db73a18..8cd0f1d 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -453,6 +453,11 @@
#endif /* CONFIG_WPS */
+#ifdef CONFIG_HS20
+ if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
+ wpas_hs20_add_indication(extra_ie);
+#endif /* CONFIG_HS20 */
+
return extra_ie;
}
@@ -481,6 +486,7 @@
return 0;
}
+#endif /* CONFIG_P2P */
/*
* Find the operating frequency of any other virtual interface that is using
@@ -520,7 +526,62 @@
return 0;
}
-#endif /* CONFIG_P2P */
+
+static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
+ u16 num_modes,
+ enum hostapd_hw_mode mode)
+{
+ u16 i;
+
+ for (i = 0; i < num_modes; i++) {
+ if (modes[i].mode == mode)
+ return &modes[i];
+ }
+
+ return NULL;
+}
+
+
+static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
+ enum hostapd_hw_mode band,
+ struct wpa_driver_scan_params *params)
+{
+ /* Include only supported channels for the specified band */
+ struct hostapd_hw_modes *mode;
+ int count, i;
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
+ if (mode == NULL) {
+ /* No channels supported in this band - use empty list */
+ params->freqs = os_zalloc(sizeof(int));
+ return;
+ }
+
+ params->freqs = os_zalloc((mode->num_channels + 1) * sizeof(int));
+ if (params->freqs == NULL)
+ return;
+ for (count = 0, i = 0; i < mode->num_channels; i++) {
+ if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
+ continue;
+ params->freqs[count++] = mode->channels[i].freq;
+ }
+}
+
+
+static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params)
+{
+ if (wpa_s->hw.modes == NULL)
+ return; /* unknown what channels the driver supports */
+ if (params->freqs)
+ return; /* already using a limited channel set */
+ if (wpa_s->setband == WPA_SETBAND_5G)
+ wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
+ params);
+ else if (wpa_s->setband == WPA_SETBAND_2G)
+ wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
+ params);
+}
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
@@ -576,7 +637,7 @@
}
#ifdef CONFIG_P2P
- if (wpas_p2p_in_progress(wpa_s)) {
+ if (wpas_p2p_in_progress(wpa_s) || wpas_wpa_is_in_progress(wpa_s)) {
if (wpa_s->sta_scan_pending &&
wpas_p2p_in_progress(wpa_s) == 2 &&
wpa_s->global->p2p_cb_on_scan_complete) {
@@ -749,11 +810,6 @@
wpa_supplicant_optimize_freqs(wpa_s, ¶ms);
extra_ie = wpa_supplicant_extra_ies(wpa_s);
-#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
- wpas_hs20_add_indication(extra_ie);
-#endif /* CONFIG_HS20 */
-
if (params.freqs == NULL && wpa_s->next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
"generated frequency list");
@@ -761,6 +817,27 @@
} else
os_free(wpa_s->next_scan_freqs);
wpa_s->next_scan_freqs = NULL;
+ wpa_setband_scan_freqs(wpa_s, ¶ms);
+
+ /* See if user specified frequencies. If so, scan only those. */
+ if (wpa_s->conf->freq_list && !params.freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Optimize scan based on conf->freq_list");
+ int_array_concat(¶ms.freqs, wpa_s->conf->freq_list);
+ }
+
+ /* Use current associated channel? */
+ if (wpa_s->conf->scan_cur_freq && !params.freqs) {
+ int freq = shared_vif_oper_freq(wpa_s);
+ if (freq > 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current "
+ "operating channel (%d MHz) since "
+ "scan_cur_freq is enabled", freq);
+ params.freqs = os_zalloc(sizeof(int) * 2);
+ if (params.freqs)
+ params.freqs[0] = freq;
+ }
+ }
params.filter_ssids = wpa_supplicant_build_filter_ssids(
wpa_s->conf, ¶ms.num_filter_ssids);
@@ -1028,7 +1105,9 @@
if (!ssid || !wpa_s->prev_sched_ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
-
+ if (wpa_s->conf->sched_scan_interval)
+ wpa_s->sched_scan_interval =
+ wpa_s->conf->sched_scan_interval;
if (wpa_s->sched_scan_interval == 0)
wpa_s->sched_scan_interval = 10;
wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
@@ -1115,6 +1194,8 @@
wpa_s->sched_scan_interval);
}
+ wpa_setband_scan_freqs(wpa_s, scan_params);
+
ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
wpa_s->sched_scan_interval);
wpabuf_free(extra_ie);
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 4c78161..0371628 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -353,7 +353,7 @@
#endif /* CONFIG_P2P */
#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20) {
+ if (is_hs20_network(wpa_s, ssid, bss)) {
struct wpabuf *hs20;
hs20 = wpabuf_alloc(20);
if (hs20) {
@@ -942,39 +942,6 @@
}
-/**
- * enum wpas_band - Frequency band
- * @WPAS_BAND_2GHZ: 2.4 GHz ISM band
- * @WPAS_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
- */
-enum wpas_band {
- WPAS_BAND_2GHZ,
- WPAS_BAND_5GHZ,
- WPAS_BAND_INVALID
-};
-
-/**
- * freq_to_channel - Convert frequency into channel info
- * @channel: Buffer for returning channel number
- * Returns: Band (2 or 5 GHz)
- */
-static enum wpas_band freq_to_channel(int freq, u8 *channel)
-{
- enum wpas_band band = (freq <= 2484) ? WPAS_BAND_2GHZ : WPAS_BAND_5GHZ;
- u8 chan = 0;
-
- if (freq >= 2412 && freq <= 2472)
- chan = (freq - 2407) / 5;
- else if (freq == 2484)
- chan = 14;
- else if (freq >= 5180 && freq <= 5805)
- chan = (freq - 5000) / 5;
-
- *channel = chan;
- return band;
-}
-
-
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
{
struct wpa_bss *bss;
@@ -1011,7 +978,10 @@
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
/* Skip other band bss */
- if (freq_to_channel(bss->freq, &channel) != WPAS_BAND_2GHZ)
+ enum hostapd_hw_mode mode;
+ mode = ieee80211_freq_to_chan(bss->freq, &channel);
+ if (mode != HOSTAPD_MODE_IEEE80211G &&
+ mode != HOSTAPD_MODE_IEEE80211B)
continue;
ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
diff --git a/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in
index 76aba12..bfdee25 100644
--- a/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in
+++ b/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in
@@ -10,4 +10,4 @@
ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-nl80211-%I.conf -Dnl80211 -i%I
[Install]
-Alias=multi-user.target.wants/wpa_supplicant-nl80211@wlan0.service
+Alias=multi-user.target.wants/wpa_supplicant-nl80211@%i.service
diff --git a/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in
index ff384ae..20ba0ad 100644
--- a/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in
+++ b/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in
@@ -10,4 +10,4 @@
ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-wired-%I.conf -Dwired -i%I
[Install]
-Alias=multi-user.target.wants/wpa_supplicant-wired@wlan0.service
+Alias=multi-user.target.wants/wpa_supplicant-wired@%i.service
diff --git a/wpa_supplicant/systemd/wpa_supplicant.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant.service.arg.in
index c215567..10e62bc 100644
--- a/wpa_supplicant/systemd/wpa_supplicant.service.arg.in
+++ b/wpa_supplicant/systemd/wpa_supplicant.service.arg.in
@@ -10,4 +10,4 @@
ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I
[Install]
-Alias=multi-user.target.wants/wpa_supplicant@wlan0.service
+Alias=multi-user.target.wants/wpa_supplicant@%i.service
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 4d9e453..4f8d895 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -1,6 +1,6 @@
/*
* wpa_supplicant - WNM
- * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,12 +10,17 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
#include "rsn_supp/wpa.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "scan.h"
+#include "ctrl_iface.h"
+#include "bss.h"
+#include "wnm_sta.h"
#define MAX_TFS_IE_LEN 1024
+#define WNM_MAX_NEIGHBOR_REPORT 10
/* get the TFS IE from driver */
@@ -294,9 +299,203 @@
}
-static void wnm_send_bss_transition_mgmt_resp(struct wpa_supplicant *wpa_s,
- u8 dialog_token, u8 status,
- u8 delay, const u8 *target_bssid)
+void wnm_deallocate_memory(struct wpa_supplicant *wpa_s)
+{
+ int i;
+
+ for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
+ os_free(wpa_s->wnm_neighbor_report_elements[i].tsf_info);
+ os_free(wpa_s->wnm_neighbor_report_elements[i].con_coun_str);
+ os_free(wpa_s->wnm_neighbor_report_elements[i].bss_tran_can);
+ os_free(wpa_s->wnm_neighbor_report_elements[i].bss_term_dur);
+ os_free(wpa_s->wnm_neighbor_report_elements[i].bearing);
+ os_free(wpa_s->wnm_neighbor_report_elements[i].meas_pilot);
+ os_free(wpa_s->wnm_neighbor_report_elements[i].rrm_cap);
+ os_free(wpa_s->wnm_neighbor_report_elements[i].mul_bssid);
+ }
+
+ os_free(wpa_s->wnm_neighbor_report_elements);
+ wpa_s->wnm_neighbor_report_elements = NULL;
+}
+
+
+static void wnm_parse_neighbor_report_elem(struct neighbor_report *rep,
+ u8 id, u8 elen, const u8 *pos)
+{
+ switch (id) {
+ case WNM_NEIGHBOR_TSF:
+ if (elen < 2 + 2) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short TSF");
+ break;
+ }
+ rep->tsf_info = os_zalloc(sizeof(struct tsf_info));
+ if (rep->tsf_info == NULL)
+ break;
+ rep->tsf_info->present = 1;
+ os_memcpy(rep->tsf_info->tsf_offset, pos, 2);
+ os_memcpy(rep->tsf_info->beacon_interval, pos + 2, 2);
+ break;
+ case WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING:
+ if (elen < 2) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short condensed "
+ "country string");
+ break;
+ }
+ rep->con_coun_str =
+ os_zalloc(sizeof(struct condensed_country_string));
+ if (rep->con_coun_str == NULL)
+ break;
+ rep->con_coun_str->present = 1;
+ os_memcpy(rep->con_coun_str->country_string, pos, 2);
+ break;
+ case WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE:
+ if (elen < 1) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short BSS transition "
+ "candidate");
+ break;
+ }
+ rep->bss_tran_can =
+ os_zalloc(sizeof(struct bss_transition_candidate));
+ if (rep->bss_tran_can == NULL)
+ break;
+ rep->bss_tran_can->present = 1;
+ rep->bss_tran_can->preference = pos[0];
+ break;
+ case WNM_NEIGHBOR_BSS_TERMINATION_DURATION:
+ if (elen < 12) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short BSS termination "
+ "duration");
+ break;
+ }
+ rep->bss_term_dur =
+ os_zalloc(sizeof(struct bss_termination_duration));
+ if (rep->bss_term_dur == NULL)
+ break;
+ rep->bss_term_dur->present = 1;
+ os_memcpy(rep->bss_term_dur->duration, pos, 12);
+ break;
+ case WNM_NEIGHBOR_BEARING:
+ if (elen < 8) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short neighbor "
+ "bearing");
+ break;
+ }
+ rep->bearing = os_zalloc(sizeof(struct bearing));
+ if (rep->bearing == NULL)
+ break;
+ rep->bearing->present = 1;
+ os_memcpy(rep->bearing->bearing, pos, 8);
+ break;
+ case WNM_NEIGHBOR_MEASUREMENT_PILOT:
+ if (elen < 2) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short measurement "
+ "pilot");
+ break;
+ }
+ rep->meas_pilot = os_zalloc(sizeof(struct measurement_pilot));
+ if (rep->meas_pilot == NULL)
+ break;
+ rep->meas_pilot->present = 1;
+ rep->meas_pilot->measurement_pilot = pos[0];
+ rep->meas_pilot->num_vendor_specific = pos[1];
+ os_memcpy(rep->meas_pilot->vendor_specific, pos + 2, elen - 2);
+ break;
+ case WNM_NEIGHBOR_RRM_ENABLED_CAPABILITIES:
+ if (elen < 4) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short RRM enabled "
+ "capabilities");
+ break;
+ }
+ rep->rrm_cap =
+ os_zalloc(sizeof(struct rrm_enabled_capabilities));
+ if (rep->rrm_cap == NULL)
+ break;
+ rep->rrm_cap->present = 1;
+ os_memcpy(rep->rrm_cap->capabilities, pos, 4);
+ break;
+ case WNM_NEIGHBOR_MULTIPLE_BSSID:
+ if (elen < 2) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short multiple BSSID");
+ break;
+ }
+ rep->mul_bssid = os_zalloc(sizeof(struct multiple_bssid));
+ if (rep->mul_bssid == NULL)
+ break;
+ rep->mul_bssid->present = 1;
+ rep->mul_bssid->max_bssid_indicator = pos[0];
+ rep->mul_bssid->num_vendor_specific = pos[1];
+ os_memcpy(rep->mul_bssid->vendor_specific, pos + 2, elen - 2);
+ break;
+ }
+}
+
+
+static void wnm_parse_neighbor_report(struct wpa_supplicant *wpa_s,
+ const u8 *pos, u8 len,
+ struct neighbor_report *rep)
+{
+ u8 left = len;
+
+ if (left < 13) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short neighbor report");
+ return;
+ }
+
+ os_memcpy(rep->bssid, pos, ETH_ALEN);
+ os_memcpy(rep->bssid_information, pos + ETH_ALEN, 4);
+ rep->regulatory_class = *(pos + 10);
+ rep->channel_number = *(pos + 11);
+ rep->phy_type = *(pos + 12);
+
+ pos += 13;
+ left -= 13;
+
+ while (left >= 2) {
+ u8 id, elen;
+
+ id = *pos++;
+ elen = *pos++;
+ wnm_parse_neighbor_report_elem(rep, id, elen, pos);
+ left -= 2 + elen;
+ pos += elen;
+ }
+}
+
+
+static int compare_scan_neighbor_results(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res,
+ struct neighbor_report *neigh_rep,
+ u8 num_neigh_rep, u8 *bssid_to_connect)
+{
+
+ u8 i, j;
+
+ if (scan_res == NULL || num_neigh_rep == 0)
+ return 0;
+
+ for (i = 0; i < num_neigh_rep; i++) {
+ for (j = 0; j < scan_res->num; j++) {
+ /* Check for a better RSSI AP */
+ if (os_memcmp(scan_res->res[j]->bssid,
+ neigh_rep[i].bssid, ETH_ALEN) == 0 &&
+ scan_res->res[j]->level >
+ wpa_s->current_bss->level) {
+ /* Got a BSSID with better RSSI value */
+ os_memcpy(bssid_to_connect, neigh_rep[i].bssid,
+ ETH_ALEN);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+static void wnm_send_bss_transition_mgmt_resp(
+ struct wpa_supplicant *wpa_s, u8 dialog_token,
+ enum bss_trans_mgmt_status_code status, u8 delay,
+ const u8 *target_bssid)
{
u8 buf[1000], *pos;
struct ieee80211_mgmt *mgmt;
@@ -332,30 +531,93 @@
}
+void wnm_scan_response(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res)
+{
+ u8 bssid[ETH_ALEN];
+
+ if (scan_res == NULL) {
+ wpa_printf(MSG_ERROR, "Scan result is NULL");
+ goto send_bss_resp_fail;
+ }
+
+ /* Compare the Neighbor Report and scan results */
+ if (compare_scan_neighbor_results(wpa_s, scan_res,
+ wpa_s->wnm_neighbor_report_elements,
+ wpa_s->wnm_num_neighbor_report,
+ bssid) == 1) {
+ /* Associate to the network */
+ struct wpa_bss *bss;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+ bss = wpa_bss_get_bssid(wpa_s, bssid);
+ if (!bss) {
+ wpa_printf(MSG_DEBUG, "WNM: Target AP not found from "
+ "BSS table");
+ goto send_bss_resp_fail;
+ }
+
+ /* Send the BSS Management Response - Accept */
+ if (wpa_s->wnm_reply) {
+ wnm_send_bss_transition_mgmt_resp(wpa_s,
+ wpa_s->wnm_dialog_token,
+ WNM_BSS_TM_ACCEPT,
+ 0, NULL);
+ }
+
+ wpa_s->reassociate = 1;
+ wpa_supplicant_connect(wpa_s, bss, ssid);
+ wnm_deallocate_memory(wpa_s);
+ return;
+ }
+
+ /* Send reject response for all the failures */
+send_bss_resp_fail:
+ wnm_deallocate_memory(wpa_s);
+ if (wpa_s->wnm_reply) {
+ wnm_send_bss_transition_mgmt_resp(wpa_s,
+ wpa_s->wnm_dialog_token,
+ WNM_BSS_TM_REJECT_UNSPECIFIED,
+ 0, NULL);
+ }
+ return;
+}
+
+
static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
const u8 *pos, const u8 *end,
int reply)
{
- u8 dialog_token;
- u8 mode;
- u16 disassoc_timer;
-
if (pos + 5 > end)
return;
- dialog_token = pos[0];
- mode = pos[1];
- disassoc_timer = WPA_GET_LE16(pos + 2);
+ wpa_s->wnm_dialog_token = pos[0];
+ wpa_s->wnm_mode = pos[1];
+ wpa_s->wnm_dissoc_timer = WPA_GET_LE16(pos + 2);
+ wpa_s->wnm_validity_interval = pos[4];
+ wpa_s->wnm_reply = reply;
wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Request: "
"dialog_token=%u request_mode=0x%x "
"disassoc_timer=%u validity_interval=%u",
- dialog_token, mode, disassoc_timer, pos[4]);
+ wpa_s->wnm_dialog_token, wpa_s->wnm_mode,
+ wpa_s->wnm_dissoc_timer, wpa_s->wnm_validity_interval);
+
pos += 5;
- if (mode & 0x08)
+
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
+ if (pos + 12 > end) {
+ wpa_printf(MSG_DEBUG, "WNM: Too short BSS TM Request");
+ return;
+ }
+ os_memcpy(wpa_s->wnm_bss_termination_duration, pos, 12);
pos += 12; /* BSS Termination Duration */
- if (mode & 0x10) {
+ }
+
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) {
char url[256];
+ unsigned int beacon_int;
+
if (pos + 1 > end || pos + 1 + pos[0] > end) {
wpa_printf(MSG_DEBUG, "WNM: Invalid BSS Transition "
"Management Request (URL)");
@@ -363,14 +625,22 @@
}
os_memcpy(url, pos + 1, pos[0]);
url[pos[0]] = '\0';
- wpa_msg(wpa_s, MSG_INFO, "WNM: ESS Disassociation Imminent - "
- "session_info_url=%s", url);
+ pos += 1 + pos[0];
+
+ if (wpa_s->current_bss)
+ beacon_int = wpa_s->current_bss->beacon_int;
+ else
+ beacon_int = 100; /* best guess */
+
+ wpa_msg(wpa_s, MSG_INFO, ESS_DISASSOC_IMMINENT "%d %u %s",
+ wpa_sm_pmf_enabled(wpa_s->wpa),
+ wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125, url);
}
- if (mode & 0x04) {
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
wpa_msg(wpa_s, MSG_INFO, "WNM: Disassociation Imminent - "
- "Disassociation Timer %u", disassoc_timer);
- if (disassoc_timer && !wpa_s->scanning) {
+ "Disassociation Timer %u", wpa_s->wnm_dissoc_timer);
+ if (wpa_s->wnm_dissoc_timer && !wpa_s->scanning) {
/* TODO: mark current BSS less preferred for
* selection */
wpa_printf(MSG_DEBUG, "Trying to find another BSS");
@@ -378,15 +648,89 @@
}
}
- if (reply) {
- /* TODO: add support for reporting Accept */
- wnm_send_bss_transition_mgmt_resp(wpa_s, dialog_token,
- 1 /* Reject - unspecified */,
- 0, NULL);
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
+ wpa_msg(wpa_s, MSG_INFO, "WNM: Preferred List Available");
+ wpa_s->wnm_num_neighbor_report = 0;
+ os_free(wpa_s->wnm_neighbor_report_elements);
+ wpa_s->wnm_neighbor_report_elements = os_zalloc(
+ WNM_MAX_NEIGHBOR_REPORT *
+ sizeof(struct neighbor_report));
+ if (wpa_s->wnm_neighbor_report_elements == NULL)
+ return;
+
+ while (pos + 2 <= end &&
+ wpa_s->wnm_num_neighbor_report < WNM_MAX_NEIGHBOR_REPORT)
+ {
+ u8 tag = *pos++;
+ u8 len = *pos++;
+
+ wpa_printf(MSG_DEBUG, "WNM: Neighbor report tag %u",
+ tag);
+ if (pos + len > end) {
+ wpa_printf(MSG_DEBUG, "WNM: Truncated request");
+ return;
+ }
+ wnm_parse_neighbor_report(
+ wpa_s, pos, len,
+ &wpa_s->wnm_neighbor_report_elements[
+ wpa_s->wnm_num_neighbor_report]);
+
+ pos += len;
+ wpa_s->wnm_num_neighbor_report++;
+ }
+
+ wpa_s->scan_res_handler = wnm_scan_response;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ } else if (reply) {
+ enum bss_trans_mgmt_status_code status;
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT)
+ status = WNM_BSS_TM_ACCEPT;
+ else {
+ wpa_msg(wpa_s, MSG_INFO, "WNM: BSS Transition Management Request did not include candidates");
+ status = WNM_BSS_TM_REJECT_UNSPECIFIED;
+ }
+ wnm_send_bss_transition_mgmt_resp(wpa_s,
+ wpa_s->wnm_dialog_token,
+ status, 0, NULL);
}
}
+int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
+ u8 query_reason)
+{
+ u8 buf[1000], *pos;
+ struct ieee80211_mgmt *mgmt;
+ size_t len;
+ int ret;
+
+ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Query to "
+ MACSTR " query_reason=%u",
+ MAC2STR(wpa_s->bssid), query_reason);
+
+ mgmt = (struct ieee80211_mgmt *) buf;
+ os_memset(&buf, 0, sizeof(buf));
+ os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
+ os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
+ os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
+ mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ mgmt->u.action.category = WLAN_ACTION_WNM;
+ mgmt->u.action.u.bss_tm_query.action = WNM_BSS_TRANS_MGMT_QUERY;
+ mgmt->u.action.u.bss_tm_query.dialog_token = 0;
+ mgmt->u.action.u.bss_tm_query.query_reason = query_reason;
+ pos = mgmt->u.action.u.bss_tm_query.variable;
+
+ len = pos - (u8 *) &mgmt->u.action.category;
+
+ ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ &mgmt->u.action.category, len, 0);
+
+ return ret;
+}
+
+
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
struct rx_action *action)
{
@@ -418,6 +762,7 @@
ieee802_11_rx_wnmsleep_resp(wpa_s, action->data, action->len);
break;
default:
+ wpa_printf(MSG_ERROR, "WNM: Unknown request");
break;
}
}
diff --git a/wpa_supplicant/wnm_sta.h b/wpa_supplicant/wnm_sta.h
index 3f9d88b..2933926 100644
--- a/wpa_supplicant/wnm_sta.h
+++ b/wpa_supplicant/wnm_sta.h
@@ -12,10 +12,79 @@
struct rx_action;
struct wpa_supplicant;
+struct tsf_info {
+ u8 present;
+ u8 tsf_offset[2];
+ u8 beacon_interval[2];
+};
+
+struct condensed_country_string {
+ u8 present;
+ u8 country_string[2];
+};
+
+struct bss_transition_candidate {
+ u8 present;
+ u8 preference;
+};
+
+struct bss_termination_duration {
+ u8 present;
+ u8 duration[12];
+};
+
+struct bearing {
+ u8 present;
+ u8 bearing[8];
+};
+
+struct measurement_pilot {
+ u8 present;
+ u8 measurement_pilot;
+ u8 num_vendor_specific;
+ u8 vendor_specific[255];
+};
+
+struct rrm_enabled_capabilities {
+ u8 present;
+ u8 capabilities[4];
+};
+
+struct multiple_bssid {
+ u8 present;
+ u8 max_bssid_indicator;
+ u8 num_vendor_specific;
+ u8 vendor_specific[255];
+};
+
+struct neighbor_report {
+ u8 bssid[ETH_ALEN];
+ u8 bssid_information[4];
+ u8 regulatory_class;
+ u8 channel_number;
+ u8 phy_type;
+ struct tsf_info *tsf_info;
+ struct condensed_country_string *con_coun_str;
+ struct bss_transition_candidate *bss_tran_can;
+ struct bss_termination_duration *bss_term_dur;
+ struct bearing *bearing;
+ struct measurement_pilot *meas_pilot;
+ struct rrm_enabled_capabilities *rrm_cap;
+ struct multiple_bssid *mul_bssid;
+};
+
+
int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
u8 action, u16 intval, struct wpabuf *tfs_req);
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
struct rx_action *action);
+void wnm_scan_response(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res);
+
+int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
+ u8 query_reason);
+void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
+
#endif /* WNM_STA_H */
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index cdbe011..ba1f207 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -81,9 +81,7 @@
static const char *action_file = NULL;
static int ping_interval = 5;
static int interactive = 0;
-#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
-static char* redirect_interface = NULL;
-#endif
+static char *ifname_prefix = NULL;
struct cli_txt_entry {
struct dl_list list;
@@ -93,6 +91,7 @@
static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
+static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
static void print_help(const char *cmd);
@@ -176,11 +175,9 @@
end = os_strchr(txt, ' ');
if (end == NULL)
end = txt + os_strlen(txt);
- buf = os_malloc(end - txt + 1);
+ buf = dup_binstr(txt, end - txt);
if (buf == NULL)
return;
- os_memcpy(buf, txt, end - txt);
- buf[end - txt] = '\0';
cli_txt_list_del(txt_list, buf);
os_free(buf);
}
@@ -226,11 +223,9 @@
end = os_strchr(txt, ' ');
if (end == NULL)
end = txt + os_strlen(txt);
- buf = os_malloc(end - txt + 1);
+ buf = dup_binstr(txt, end - txt);
if (buf == NULL)
return -1;
- os_memcpy(buf, txt, end - txt);
- buf[end - txt] = '\0';
ret = cli_txt_list_add(txt_list, buf);
os_free(buf);
return ret;
@@ -404,9 +399,6 @@
static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
{
char buf[4096];
-#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
- char _cmd[256];
-#endif
size_t len;
int ret;
@@ -414,22 +406,12 @@
printf("Not connected to wpa_supplicant - command dropped.\n");
return -1;
}
-#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
- if (redirect_interface) {
- char *arg;
- arg = os_strchr(cmd, ' ');
- if (arg) {
- *arg++ = '\0';
- ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s %s", cmd, redirect_interface, arg);
- }
- else {
- ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s", cmd, redirect_interface);
- }
- cmd = _cmd;
- os_free(redirect_interface);
- redirect_interface = NULL;
+ if (ifname_prefix) {
+ os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
+ ifname_prefix, cmd);
+ buf[sizeof(buf) - 1] = '\0';
+ cmd = buf;
}
-#endif
len = sizeof(buf) - 1;
ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
wpa_cli_msg_cb);
@@ -489,7 +471,7 @@
static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
int argc, char *argv[])
{
- char buf[256];
+ char buf[4096];
if (argc < min_args) {
printf("Invalid %s command - at least %d argument%s "
"required.\n", cmd, min_args,
@@ -586,52 +568,81 @@
}
-static void wpa_cli_show_variables(void)
-{
- printf("set variables:\n"
- " EAPOL::heldPeriod (EAPOL state machine held period, "
- "in seconds)\n"
- " EAPOL::authPeriod (EAPOL state machine authentication "
- "period, in seconds)\n"
- " EAPOL::startPeriod (EAPOL state machine start period, in "
- "seconds)\n"
- " EAPOL::maxStart (EAPOL state machine maximum start "
- "attempts)\n");
- printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
- "seconds)\n"
- " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
- " threshold\n\tpercentage)\n"
- " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
- "security\n\tassociation in seconds)\n");
-}
-
-
static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
int res;
- if (argc == 0) {
- wpa_cli_show_variables();
- return 0;
- }
-
- if (argc != 1 && argc != 2) {
- printf("Invalid SET command: needs two arguments (variable "
- "name and value)\n");
- return -1;
- }
-
- if (argc == 1)
+ if (argc == 1) {
res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
- else
- res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
- argv[0], argv[1]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
- printf("Too long SET command.\n");
- return -1;
+ if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ printf("Too long SET command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
}
- return wpa_ctrl_command(ctrl, cmd);
+
+ return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
+}
+
+
+static char ** wpa_cli_complete_set(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ const char *fields[] = {
+ /* runtime values */
+ "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
+ "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
+ "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
+ "wps_fragment_size", "wps_version_number", "ampdu",
+ "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
+ "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
+ "no_keep_alive",
+ /* global configuration parameters */
+ "eapol_version", "ap_scan", "disable_scan_offload",
+ "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
+ "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
+ "driver_param", "dot11RSNAConfigPMKLifetime",
+ "dot11RSNAConfigPMKReauthThreshold",
+ "dot11RSNAConfigSATimeout",
+ "update_config", "load_dynamic_eap", "uuid", "device_name",
+ "manufacturer", "model_name", "model_number", "serial_number",
+ "device_type", "os_version", "config_methods",
+ "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
+ "p2p_listen_reg_class", "p2p_listen_channel",
+ "p2p_oper_reg_class", "p2p_oper_channel",
+ "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
+ "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
+ "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
+ "p2p_ignore_shared_freq", "country", "bss_max_count",
+ "bss_expiration_age", "bss_expiration_scan_count",
+ "filter_ssids", "filter_rssi", "max_num_sta",
+ "disassoc_low_ack", "hs20", "interworking", "hessid",
+ "access_network_type", "pbc_in_m1", "autoscan",
+ "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
+ "wps_nfc_dev_pw", "ext_password_backend",
+ "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
+ "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
+ "ignore_old_scan_res", "freq_list"
+ };
+ int i, num_fields = sizeof(fields) / sizeof(fields[0]);
+
+ if (arg == 1) {
+ char **res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(fields[i]);
+ if (res[i] == NULL)
+ return res;
+ }
+ return res;
+ }
+
+ if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
+ return cli_txt_list_array(&bsses);
+
+ return NULL;
}
@@ -2290,6 +2301,12 @@
return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
}
+
+static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
+}
+
#endif /* CONFIG_WNM */
@@ -2376,7 +2393,7 @@
{ "quit", wpa_cli_cmd_quit, NULL,
cli_cmd_flag_none,
"= exit wpa_cli" },
- { "set", wpa_cli_cmd_set, NULL,
+ { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
cli_cmd_flag_none,
"= set variables (shows list of variables when run without "
"arguments)" },
@@ -2489,7 +2506,7 @@
"<<idx> | <bssid>> = get detailed scan result info" },
{ "get_capability", wpa_cli_cmd_get_capability, NULL,
cli_cmd_flag_none,
- "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/modes> "
+ "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
"= get capabilies" },
{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
cli_cmd_flag_none,
@@ -2773,6 +2790,8 @@
#ifdef CONFIG_WNM
{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
"<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
+ { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
+ "<query reason> = Send BSS Transition Management Query" },
#endif /* CONFIG_WNM */
{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
"<params..> = Sent unprocessed command" },
@@ -2841,9 +2860,12 @@
{
char **res;
int i, count;
+ struct cli_txt_entry *e;
count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
- res = os_calloc(count, sizeof(char *));
+ count += dl_list_len(&p2p_groups);
+ count += dl_list_len(&ifnames);
+ res = os_calloc(count + 1, sizeof(char *));
if (res == NULL)
return NULL;
@@ -2853,6 +2875,22 @@
break;
}
+ dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
+ size_t len = 8 + os_strlen(e->txt);
+ res[i] = os_malloc(len);
+ if (res[i] == NULL)
+ break;
+ os_snprintf(res[i], len, "ifname=%s", e->txt);
+ i++;
+ }
+
+ dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
+ res[i] = os_strdup(e->txt);
+ if (res[i] == NULL)
+ break;
+ i++;
+ }
+
return res;
}
@@ -2884,6 +2922,14 @@
const char *end;
char *cmd;
+ if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
+ end = os_strchr(str, ' ');
+ if (end && pos > end - str) {
+ pos -= end - str + 1;
+ str = end + 1;
+ }
+ }
+
end = os_strchr(str, ' ');
if (end == NULL || str + pos < end)
return wpa_list_cmd_list();
@@ -2905,6 +2951,16 @@
int count;
int ret = 0;
+ if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
+ ifname_prefix = argv[0] + 7;
+ argv = &argv[1];
+ argc--;
+ } else
+ ifname_prefix = NULL;
+
+ if (argc == 0)
+ return -1;
+
count = 0;
cmd = wpa_cli_commands;
while (cmd->cmd) {
@@ -2937,13 +2993,6 @@
printf("Unknown command '%s'\n", argv[0]);
ret = 1;
} else {
-#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
- if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
- redirect_interface = os_strdup(argv[1]);
- ret = match->handler(ctrl, argc - 2, &argv[2]);
- }
- else
-#endif
ret = match->handler(ctrl, argc - 1, &argv[1]);
}
@@ -3059,6 +3108,8 @@
wpa_cli_exec(action_file, ctrl_ifname, pos);
} else if (str_match(pos, AP_STA_DISCONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
+ } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
+ wpa_cli_exec(action_file, ctrl_ifname, pos);
} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
printf("wpa_supplicant is terminating - stop monitoring\n");
wpa_cli_quit = 1;
@@ -3320,8 +3371,74 @@
}
+static void update_bssid_list(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ char *cmd = "BSS RANGE=ALL MASK=0x2";
+ char *pos, *end;
+
+ if (ctrl == NULL)
+ return;
+ ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+ if (ret < 0)
+ return;
+ buf[len] = '\0';
+
+ pos = buf;
+ while (pos) {
+ pos = os_strstr(pos, "bssid=");
+ if (pos == NULL)
+ break;
+ pos += 6;
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ cli_txt_list_add(&bsses, pos);
+ pos = end + 1;
+ }
+}
+
+
+static void update_ifnames(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ char *cmd = "INTERFACES";
+ char *pos, *end;
+ char txt[200];
+
+ cli_txt_list_flush(&ifnames);
+
+ if (ctrl == NULL)
+ return;
+ ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+ if (ret < 0)
+ return;
+ buf[len] = '\0';
+
+ pos = buf;
+ while (pos) {
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
+ if (ret > 0 && ret < (int) sizeof(txt))
+ cli_txt_list_add(&ifnames, txt);
+ pos = end + 1;
+ }
+}
+
+
static void try_connection(void *eloop_ctx, void *timeout_ctx)
{
+ if (ctrl_conn)
+ goto done;
+
if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname();
@@ -3335,9 +3452,12 @@
return;
}
+ update_bssid_list(ctrl_conn);
+
if (warning_displayed)
printf("Connection established.\n");
+done:
start_edit();
}
@@ -3353,6 +3473,7 @@
cli_txt_list_flush(&p2p_peers);
cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses);
+ cli_txt_list_flush(&ifnames);
if (edit_started)
edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
os_free(hfile);
@@ -3459,7 +3580,7 @@
#endif /* CONFIG_CTRL_IFACE_UNIX */
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
- char buf[2048], *pos;
+ char buf[4096], *pos;
size_t len;
struct wpa_ctrl *ctrl;
int ret;
@@ -3553,6 +3674,24 @@
global, strerror(errno));
return -1;
}
+
+ if (interactive) {
+ update_ifnames(ctrl_conn);
+ mon_conn = wpa_ctrl_open(global);
+ if (mon_conn) {
+ if (wpa_ctrl_attach(mon_conn) == 0) {
+ wpa_cli_attached = 1;
+ eloop_register_read_sock(
+ wpa_ctrl_get_fd(mon_conn),
+ wpa_cli_mon_receive,
+ NULL, NULL);
+ } else {
+ printf("Failed to open monitor "
+ "connection through global "
+ "control interface\n");
+ }
+ }
+ }
}
eloop_register_signal_terminate(wpa_cli_terminate, NULL);
diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
index ad6a080..4afaae9 100644
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -573,13 +573,11 @@
iface->fd = -1;
len = pos - params;
- iface->driver_name = os_malloc(len + 1);
+ iface->driver_name = dup_binstr(params, len);
if (iface->driver_name == NULL) {
wpa_priv_interface_deinit(iface);
return NULL;
}
- os_memcpy(iface->driver_name, params, len);
- iface->driver_name[len] = '\0';
for (i = 0; wpa_drivers[i]; i++) {
if (os_strcmp(iface->driver_name,
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index a9a939b..f6b881b 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -17,6 +17,7 @@
#include "crypto/sha1.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "eap_peer/eap.h"
+#include "eap_peer/eap_proxy.h"
#include "eap_server/eap_methods.h"
#include "rsn_supp/wpa.h"
#include "eloop.h"
@@ -49,6 +50,7 @@
#include "scan.h"
#include "offchannel.h"
#include "hs20_supplicant.h"
+#include "wnm_sta.h"
const char *wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
@@ -126,8 +128,8 @@
}
-static int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
+int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
{
u8 key[32];
size_t keylen;
@@ -470,6 +472,9 @@
wpa_s->disallow_aps_ssid = NULL;
wnm_bss_keep_alive_deinit(wpa_s);
+#ifdef CONFIG_WNM
+ wnm_deallocate_memory(wpa_s);
+#endif /* CONFIG_WNM */
ext_password_deinit(wpa_s->ext_pw);
wpa_s->ext_pw = NULL;
@@ -1271,7 +1276,6 @@
enum wpa_cipher cipher_pairwise, cipher_group;
struct wpa_driver_associate_params params;
int wep_keys_set = 0;
- struct wpa_driver_capa capa;
int assoc_failed = 0;
struct wpa_ssid *old_ssid;
u8 ext_capab[10];
@@ -1475,7 +1479,7 @@
#endif /* CONFIG_P2P */
#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20) {
+ if (is_hs20_network(wpa_s, ssid, bss)) {
struct wpabuf *hs20;
hs20 = wpabuf_alloc(20);
if (hs20) {
@@ -1686,8 +1690,8 @@
wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
}
- if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
- capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) {
+ if (wep_keys_set &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
/* Set static WEP keys again */
wpa_set_wep_keys(wpa_s, ssid);
}
@@ -1821,7 +1825,8 @@
wpa_supplicant_cancel_sched_scan(wpa_s);
}
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+ if (wpa_supplicant_fast_associate(wpa_s) != 1)
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
}
}
@@ -2344,7 +2349,10 @@
const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
if (addr)
os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
- } else if (!(wpa_s->drv_flags &
+ } else if ((!wpa_s->p2p_mgmt ||
+ !(wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
+ !(wpa_s->drv_flags &
WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
l2_packet_deinit(wpa_s->l2);
wpa_s->l2 = l2_packet_init(wpa_s->ifname,
@@ -2364,10 +2372,6 @@
return -1;
}
- wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
- MAC2STR(wpa_s->own_addr));
- wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
-
return 0;
}
@@ -2413,6 +2417,10 @@
if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
return -1;
+ wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
+ MAC2STR(wpa_s->own_addr));
+ wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
+
if (wpa_s->bridge_ifname[0]) {
wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
"interface '%s'", wpa_s->bridge_ifname);
@@ -2851,6 +2859,11 @@
wpa_s->conf->driver_param =
os_strdup(iface->driver_param);
}
+
+ if (iface->p2p_mgmt && !iface->ctrl_interface) {
+ os_free(wpa_s->conf->ctrl_interface);
+ wpa_s->conf->ctrl_interface = NULL;
+ }
} else
wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
iface->driver_param);
@@ -2976,11 +2989,24 @@
if (wpa_s->max_remain_on_chan == 0)
wpa_s->max_remain_on_chan = 1000;
+ /*
+ * Only take p2p_mgmt parameters when P2P Device is supported.
+ * Doing it here as it determines whether l2_packet_init() will be done
+ * during wpa_supplicant_driver_init().
+ */
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
+ wpa_s->p2p_mgmt = iface->p2p_mgmt;
+ else
+ iface->p2p_mgmt = 1;
+
if (wpa_supplicant_driver_init(wpa_s) < 0)
return -1;
#ifdef CONFIG_TDLS
- if (wpa_tdls_init(wpa_s->wpa))
+ if ((!iface->p2p_mgmt ||
+ !(wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
+ wpa_tdls_init(wpa_s->wpa))
return -1;
#endif /* CONFIG_TDLS */
@@ -3018,7 +3044,7 @@
}
#ifdef CONFIG_P2P
- if (wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
+ if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
return -1;
}
@@ -3027,6 +3053,20 @@
if (wpa_bss_init(wpa_s) < 0)
return -1;
+#ifdef CONFIG_EAP_PROXY
+{
+ size_t len;
+ wpa_s->mnc_len = eap_proxy_get_imsi(wpa_s->imsi, &len);
+ if (wpa_s->mnc_len > 0) {
+ wpa_s->imsi[len] = '\0';
+ wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
+ wpa_s->imsi, wpa_s->mnc_len);
+ } else {
+ wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
+ }
+}
+#endif /* CONFIG_EAP_PROXY */
+
if (pcsc_reader_init(wpa_s) < 0)
return -1;
@@ -3040,6 +3080,7 @@
static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
int notify, int terminate)
{
+ wpa_s->disconnected = 1;
if (wpa_s->drv_priv) {
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
@@ -3076,6 +3117,8 @@
wpa_config_free(wpa_s->conf);
wpa_s->conf = NULL;
}
+
+ os_free(wpa_s);
}
@@ -3126,14 +3169,12 @@
wpa_printf(MSG_DEBUG, "Failed to add interface %s",
iface->ifname);
wpa_supplicant_deinit_iface(wpa_s, 0, 0);
- os_free(wpa_s);
return NULL;
}
/* Notify the control interfaces about new iface */
if (wpas_notify_iface_added(wpa_s)) {
wpa_supplicant_deinit_iface(wpa_s, 1, 0);
- os_free(wpa_s);
return NULL;
}
@@ -3186,7 +3227,6 @@
if (global->p2p_invite_group == wpa_s)
global->p2p_invite_group = NULL;
wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
- os_free(wpa_s);
return 0;
}
@@ -3306,6 +3346,9 @@
if (params->ctrl_interface)
global->params.ctrl_interface =
os_strdup(params->ctrl_interface);
+ if (params->ctrl_interface_group)
+ global->params.ctrl_interface_group =
+ os_strdup(params->ctrl_interface_group);
if (params->override_driver)
global->params.override_driver =
os_strdup(params->override_driver);
@@ -3415,9 +3458,6 @@
#ifdef CONFIG_WIFI_DISPLAY
wifi_display_deinit(global);
#endif /* CONFIG_WIFI_DISPLAY */
-#ifdef CONFIG_P2P
- wpas_p2p_deinit_global(global);
-#endif /* CONFIG_P2P */
while (global->ifaces)
wpa_supplicant_remove_iface(global, global->ifaces, 1);
@@ -3448,6 +3488,7 @@
os_free(global->params.pid_file);
}
os_free(global->params.ctrl_interface);
+ os_free(global->params.ctrl_interface_group);
os_free(global->params.override_driver);
os_free(global->params.override_ctrl_interface);
@@ -3596,6 +3637,12 @@
*/
count += wpa_s->extra_blacklist_count;
+ if (count > 3 && wpa_s->current_ssid) {
+ wpa_printf(MSG_DEBUG, "Continuous association failures - "
+ "consider temporary network disabling");
+ wpas_auth_failed(wpa_s);
+ }
+
switch (count) {
case 1:
timeout = 100;
@@ -3871,3 +3918,42 @@
if (wpa_supplicant_fast_associate(wpa_s) != 1)
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
+
+
+/**
+ * wpas_wpa_is_in_progress - Check whether a connection is in progress
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * This function is to check if the wpa state is in beginning of the connection
+ * during 4-way handshake or group key handshake with WPA on any shared
+ * interface.
+ */
+int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s)
+{
+ const char *rn, *rn2;
+ struct wpa_supplicant *ifs;
+
+ if (!wpa_s->driver->get_radio_name)
+ return 0;
+
+ rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
+ if (rn == NULL || rn[0] == '\0')
+ return 0;
+
+ for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
+ if (ifs == wpa_s || !ifs->driver->get_radio_name)
+ continue;
+
+ rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
+ if (!rn2 || os_strcmp(rn, rn2) != 0)
+ continue;
+ if (ifs->wpa_state >= WPA_AUTHENTICATING &&
+ ifs->wpa_state != WPA_COMPLETED) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Connection is in progress "
+ "on interface %s - defer scan", ifs->ifname);
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 0935a06..d73d371 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -310,6 +310,10 @@
# allowing it to update the internal BSS table.
#ignore_old_scan_res=0
+# scan_cur_freq: Whether to scan only the current frequency
+# 0: Scan all available frequencies. (Default)
+# 1: Scan current operating frequency if another VIF on the same radio
+# is already associated.
# Interworking (IEEE 802.11u)
@@ -524,6 +528,9 @@
# set, scan results that do not match any of the specified frequencies are not
# considered when selecting a BSS.
#
+# This can also be set on the outside of the network block. In this case,
+# it limits the frequencies that will be scanned.
+#
# bgscan: Background scanning
# wpa_supplicant behavior for background scanning can be specified by
# configuring a bgscan module. These modules are responsible for requesting
@@ -808,6 +815,11 @@
# interface used for EAPOL. The default value is suitable for most
# cases.
#
+# ocsp: Whether to use/require OCSP to check server certificate
+# 0 = do not use OCSP stapling (TLS certificate status extension)
+# 1 = try to use OCSP stapling, but not require response
+# 2 = require valid OCSP stapling response
+#
# EAP-FAST variables:
# pac_file: File path for the PAC entries. wpa_supplicant will need to be able
# to create this file and write updates to it when PAC is being
@@ -1231,3 +1243,10 @@
network={
key_mgmt=NONE
}
+
+
+# Example config file that will only scan on channel 36.
+freq_list=5180
+network={
+ key_mgmt=NONE
+}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index f96b245..9240863 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -104,6 +104,15 @@
* receiving of EAPOL frames from an additional interface.
*/
const char *bridge_ifname;
+
+ /**
+ * p2p_mgmt - Interface used for P2P management (P2P Device operations)
+ *
+ * Indicates whether wpas_p2p_init() must be called for this interface.
+ * This is used only when the driver supports a dedicated P2P Device
+ * interface that is not a network interface.
+ */
+ int p2p_mgmt;
};
/**
@@ -155,6 +164,11 @@
char *ctrl_interface;
/**
+ * ctrl_interface_group - Global ctrl_iface group
+ */
+ char *ctrl_interface_group;
+
+ /**
* dbus_ctrl_interface - Enable the DBus control interface
*/
int dbus_ctrl_interface;
@@ -348,6 +362,8 @@
struct wpa_ssid_value *disallow_aps_ssid;
size_t disallow_aps_ssid_count;
+ enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband;
+
/* previous scan was wildcard when interleaving between
* wildcard scans and specific SSID scan when max_ssids=1 */
int prev_scan_wildcard;
@@ -400,10 +416,8 @@
* previous association event */
struct scard_data *scard;
-#ifdef PCSC_FUNCS
char imsi[20];
int mnc_len;
-#endif /* PCSC_FUNCS */
unsigned char last_eapol_src[ETH_ALEN];
@@ -561,6 +575,8 @@
unsigned int roc_waiting_drv_freq;
int action_tx_wait_time;
+ int p2p_mgmt;
+
#ifdef CONFIG_P2P
struct p2p_go_neg_results *go_params;
int create_p2p_iface;
@@ -690,6 +706,22 @@
u8 last_gas_dialog_token;
unsigned int no_keep_alive:1;
+
+#ifdef CONFIG_WNM
+ u8 wnm_dialog_token;
+ u8 wnm_reply;
+ u8 wnm_num_neighbor_report;
+ u8 wnm_mode;
+ u16 wnm_dissoc_timer;
+ u8 wnm_validity_interval;
+ u8 wnm_bss_termination_duration[12];
+ struct neighbor_report *wnm_neighbor_report_elements;
+#endif /* CONFIG_WNM */
+
+#ifdef CONFIG_TESTING_GET_GTK
+ u8 last_gtk[32];
+ size_t last_gtk_len;
+#endif /* CONFIG_TESTING_GET_GTK */
};
@@ -702,6 +734,8 @@
struct wpa_driver_associate_params *params);
int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s);
@@ -780,6 +814,7 @@
size_t ssid_len);
void wpas_request_connection(struct wpa_supplicant *wpa_s);
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf);
+int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s);
/**
* wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index cd51873..61a42bd 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -437,6 +437,13 @@
/* Clear the MIC error counter when setting a new PTK. */
wpa_s->mic_errors_seen = 0;
}
+#ifdef CONFIG_TESTING_GET_GTK
+ if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) &&
+ alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) {
+ os_memcpy(wpa_s->last_gtk, key, key_len);
+ wpa_s->last_gtk_len = key_len;
+ }
+#endif /* CONFIG_TESTING_GET_GTK */
return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
key, key_len);
}
@@ -506,8 +513,6 @@
}
#endif /* CONFIG_IEEE80211R */
-#endif /* CONFIG_NO_WPA */
-
#ifdef CONFIG_TDLS
@@ -551,7 +556,7 @@
static int wpa_supplicant_tdls_peer_addset(
- void *ctx, const u8 *peer, int add, u16 capability,
+ void *ctx, const u8 *peer, int add, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
@@ -563,7 +568,7 @@
os_memset(¶ms, 0, sizeof(params));
params.addr = peer;
- params.aid = 1;
+ params.aid = aid;
params.capability = capability;
params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
@@ -589,6 +594,8 @@
#endif /* CONFIG_TDLS */
+#endif /* CONFIG_NO_WPA */
+
enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field)
{
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 9af6084..8e0207c 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -219,6 +219,80 @@
}
+static void wpas_wps_remove_dup_network(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *new_ssid)
+{
+ struct wpa_ssid *ssid, *next;
+
+ for (ssid = wpa_s->conf->ssid, next = ssid ? ssid->next : NULL; ssid;
+ ssid = next, next = ssid ? ssid->next : NULL) {
+ /*
+ * new_ssid has already been added to the list in
+ * wpas_wps_add_network(), so skip it.
+ */
+ if (ssid == new_ssid)
+ continue;
+
+ if (ssid->bssid_set || new_ssid->bssid_set) {
+ if (ssid->bssid_set != new_ssid->bssid_set)
+ continue;
+ if (os_memcmp(ssid->bssid, new_ssid->bssid, ETH_ALEN) !=
+ 0)
+ continue;
+ }
+
+ /* compare SSID */
+ if (ssid->ssid_len == 0 || ssid->ssid_len != new_ssid->ssid_len)
+ continue;
+
+ if (ssid->ssid && new_ssid->ssid) {
+ if (os_memcmp(ssid->ssid, new_ssid->ssid,
+ ssid->ssid_len) != 0)
+ continue;
+ } else if (ssid->ssid || new_ssid->ssid)
+ continue;
+
+ /* compare security parameters */
+ if (ssid->auth_alg != new_ssid->auth_alg ||
+ ssid->key_mgmt != new_ssid->key_mgmt ||
+ ssid->proto != new_ssid->proto ||
+ ssid->pairwise_cipher != new_ssid->pairwise_cipher ||
+ ssid->group_cipher != new_ssid->group_cipher)
+ continue;
+
+ if (ssid->passphrase && new_ssid->passphrase) {
+ if (os_strlen(ssid->passphrase) !=
+ os_strlen(new_ssid->passphrase))
+ continue;
+ if (os_strcmp(ssid->passphrase, new_ssid->passphrase) !=
+ 0)
+ continue;
+ } else if (ssid->passphrase || new_ssid->passphrase)
+ continue;
+
+ if ((ssid->psk_set || new_ssid->psk_set) &&
+ os_memcmp(ssid->psk, new_ssid->psk, sizeof(ssid->psk)) != 0)
+ continue;
+
+ if (ssid->auth_alg == WPA_ALG_WEP) {
+ if (ssid->wep_tx_keyidx != new_ssid->wep_tx_keyidx)
+ continue;
+ if (os_memcmp(ssid->wep_key, new_ssid->wep_key,
+ sizeof(ssid->wep_key)))
+ continue;
+ if (os_memcmp(ssid->wep_key_len, new_ssid->wep_key_len,
+ sizeof(ssid->wep_key_len)))
+ continue;
+ }
+
+ /* Remove the duplicated older network entry. */
+ wpa_printf(MSG_DEBUG, "Remove duplicate network %d", ssid->id);
+ wpas_notify_network_removed(wpa_s, ssid);
+ wpa_config_remove_network(wpa_s->conf, ssid->id);
+ }
+}
+
+
static int wpa_supplicant_wps_cred(void *ctx,
const struct wps_credential *cred)
{
@@ -438,6 +512,8 @@
if (cred->ap_channel)
wpa_s->wps_ap_channel = cred->ap_channel;
+ wpas_wps_remove_dup_network(wpa_s, ssid);
+
#ifndef CONFIG_NO_CONFIG_WRITE
if (wpa_s->conf->update_config &&
wpa_config_write(wpa_s->confname, wpa_s->conf)) {
@@ -572,6 +648,9 @@
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
wpa_s->wps_success = 1;
wpas_notify_wps_event_success(wpa_s);
+ if (wpa_s->current_ssid)
+ wpas_clear_temp_disabled(wpa_s, wpa_s->current_ssid, 1);
+ wpa_s->extra_blacklist_count = 0;
/*
* Enable the networks disabled during wpas_wps_reassoc after 10
@@ -789,9 +868,8 @@
while (ssid) {
if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
if (ssid == wpa_s->current_ssid) {
- wpa_s->current_ssid = NULL;
- if (ssid != NULL)
- wpas_notify_network_changed(wpa_s);
+ wpa_supplicant_deauthenticate(
+ wpa_s, WLAN_REASON_DEAUTH_LEAVING);
}
id = ssid->id;
remove_ssid = ssid;
@@ -888,21 +966,10 @@
}
-static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *selected, const u8 *bssid)
+static void wpas_wps_temp_disable(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *selected)
{
struct wpa_ssid *ssid;
- struct wpa_bss *bss;
-
- wpa_s->after_wps = 0;
- wpa_s->known_wps_freq = 0;
- if (bssid) {
- bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
- if (bss && bss->freq > 0) {
- wpa_s->known_wps_freq = 1;
- wpa_s->wps_freq = bss->freq;
- }
- }
if (wpa_s->current_ssid)
wpa_supplicant_deauthenticate(
@@ -930,6 +997,26 @@
}
ssid = ssid->next;
}
+}
+
+
+static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *selected, const u8 *bssid)
+{
+ struct wpa_bss *bss;
+
+ wpa_s->after_wps = 0;
+ wpa_s->known_wps_freq = 0;
+ if (bssid) {
+ bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+ if (bss && bss->freq > 0) {
+ wpa_s->known_wps_freq = 1;
+ wpa_s->wps_freq = bss->freq;
+ }
+ }
+
+ wpas_wps_temp_disable(wpa_s, selected);
+
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
wpa_s->scan_runs = 0;
@@ -2011,6 +2098,15 @@
{
wpa_s->wps_ap_channel = 0;
+ /*
+ * Disable existing networks temporarily to allow the newly learned
+ * credential to be preferred. Enable the temporarily disabled networks
+ * after 10 seconds.
+ */
+ wpas_wps_temp_disable(wpa_s, NULL);
+ eloop_register_timeout(10, 0, wpas_wps_reenable_networks_cb, wpa_s,
+ NULL);
+
if (wps_oob_use_cred(wpa_s->wps, attr) < 0)
return -1;