am 18493732: (-s ours) Reconcile with jb-mr2-zeroday-release - do not merge
* commit '184937322b767748f4d65758616cc9db2d670564':
Mark interface disconnected on removal request, DO NOT MERGE
Do not try auto connect mechanism in disconnected state, DO NOT MERGE
Do not add BSS to blacklist on local disconnection request, 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 a4ceaec..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;
@@ -3077,6 +3117,8 @@
wpa_config_free(wpa_s->conf);
wpa_s->conf = NULL;
}
+
+ os_free(wpa_s);
}
@@ -3127,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;
}
@@ -3187,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;
}
@@ -3307,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);
@@ -3416,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);
@@ -3449,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);
@@ -3597,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;
@@ -3872,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;