Accumulative patch from commit b618a469c42120e984ab1c85ed6058504d1fca78
Author: Jouni Malinen <jouni@qca.qualcomm.com>
Date: Sat Feb 16 19:54:09 2013 +0200
Interworking: Select highest priority cred if multiple matches
Interworking: Select highest priority cred if multiple matches
GAS server: Fix a regression in GAS server callback
hostapd: Fix Max SP Length derivation from QoS Info
nl80211: Configure STA Capabilities and Extended Capabilities
Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
WPS: Fix build without CONFIG_WPS_NFC
WPS: Add support for NFC handover select generation with wpa_supplicant
WPS: Update NFC connection handover documentation
WPS: Add support for config token generation with wpa_supplicant
WPS: Allow password token to be written with nfcpy
WPS: Use pre-configured NFC password token instead of overriding it
TDLS: Pass peer's Capability and Ext Capability info during sta_add
TDLS: Pass peer's HT Capability and QOS information during sta_add
nl80211: Add debug prints for STA add/set operations
TDLS: Fix add/set STA operation
Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
WPS: Allow Device Password to be changed from M1 to M2
WPS: Fix wps_reg nfc-pw option
TDLS: Tear down peers when disconnecting from the AP
P2P: Do not use old scan result data for peer discovery
Use more accurate timestamps for scan results
P2P: Postpone P2P-DEVICE-FOUND if config_methods not known
P2P: Do not allow peer update to clear config_methods
WPS: Report NFC connection handover completion differently
P2P: Avoid concurrent scans during all steps of group formation
P2P: Cancel group formation timeout on group removal (on client)
WPS: Change listen time to match nfcpy default (250 ms)
WPS: Report only the carrier record from NFC to wpa_supplicant
WPS: Fetch only the carrier record from wpa_supplicant for NFC
WPS: Update nfcpy script to support AP mode NFC connection handover
WPS: Add command for fetching carrier record for NFC handover
WPS: Clean up debug prints with nfcpy
WPS: Remove 0.5 sec extra wait from NFC handover with nfcpy
WPS: Use alternating poll/listen for NFC peer discovery with nfcpy
WPS: Configure logging to show nfcpy log message
WPS: Add an example python script for NFC operations with hostapd
hostapd: Do not change HT40 capability due to OBSS scan
dbus: Add missing signal description for WPS (7)
EAP peer: Add Session-Id derivation to more EAP methods
EAP peer: Add Session-Id derivation
EAP-IKEV2 server: Fix invalid memory freeing operation
eap_proxy: Add a dummy implementation for compilation testing
eap_proxy: Add mechanism for allowing EAP methods to be offloaded
Android: Allow setgroups to be overridden from build configuration
P2P: Send p2p_stop_find event on failure to start pending p2p_find
P2P: Fix GO Probe Response IEs when Wi-Fi Display is enabled
Capability matching for 60 GHz band
nl80211: Add ctrl_iface message for AP mode connection rejection
P2P: Allow local configuration to use 5 GHz band 40 MHz channels
Fix BSS RANGE command for no exact id match cases
Change-Id: Iac9284bba31db40911aecc3adf2843c9b1576db1
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 7545ab2..4332d82 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -504,6 +504,13 @@
NEED_AES_CBC=y
endif
+ifdef CONFIG_EAP_PROXY
+L_CFLAGS += -DCONFIG_EAP_PROXY
+OBJS += src/eap_peer/eap_proxy_$(CONFIG_EAP_PROXY).c
+include eap_proxy_$(CONFIG_EAP_PROXY).mk
+CONFIG_IEEE8021X_EAPOL=y
+endif
+
ifdef CONFIG_EAP_AKA_PRIME
# EAP-AKA'
ifeq ($(CONFIG_EAP_AKA_PRIME), dyn)
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index f39a3d7..da2abfc 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -482,6 +482,13 @@
NEED_AES_CBC=y
endif
+ifdef CONFIG_EAP_PROXY
+CFLAGS += -DCONFIG_EAP_PROXY
+OBJS += ../src/eap_peer/eap_proxy_$(CONFIG_EAP_PROXY).o
+include eap_proxy_$(CONFIG_EAP_PROXY).mk
+CONFIG_IEEE8021X_EAPOL=y
+endif
+
ifdef CONFIG_EAP_AKA_PRIME
# EAP-AKA'
ifeq ($(CONFIG_EAP_AKA_PRIME), dyn)
diff --git a/wpa_supplicant/README-WPS b/wpa_supplicant/README-WPS
index 1ea9843..2a1dda5 100644
--- a/wpa_supplicant/README-WPS
+++ b/wpa_supplicant/README-WPS
@@ -336,6 +336,16 @@
tokens during manufacturing (each station needs to have its own random
keys).
+The "wps_nfc_config_token <WPS/NDEF>" command can be used to build an
+NFC configuration token when wpa_supplicant is controlling an AP
+interface (AP or P2P GO). The output value from this command is a
+hexdump of the current AP configuration (WPS parameter requests this to
+include only the WPS attributes; NDEF parameter requests additional NDEF
+encapsulation to be included). This data needs to be written to an NFC
+tag with an external program. Once written, the NFC configuration token
+can be used to touch an NFC interface on a station to provision the
+credentials needed to access the network.
+
If the station includes NFC interface and reads an NFC tag with a MIME
media type "application/vnd.wfa.wsc", the NDEF message payload (with or
without NDEF encapsulation) can be delivered to wpa_supplicant using the
@@ -375,3 +385,10 @@
of NFC connection handover select. The payload may include multiple
carriers the the applicable ones are matched based on the media
type.
+
+"nfc_report_handover <INIT/RESP> WPS <carrier from handover request>
+<carrier from handover select>" can be used as an alternative way for
+reporting completed NFC connection handover. The first parameter
+indicates whether the local device initiated or responded to the
+connection handover and the carrier records are the selected carrier
+from the handover request and select messages as a hexdump.
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 85ee6cb..82b7e19 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -848,6 +848,34 @@
hapd->conf->ap_pin = NULL;
}
+
+#ifdef CONFIG_WPS_NFC
+
+struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
+ int ndef)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return NULL;
+ hapd = wpa_s->ap_iface->bss[0];
+ return hostapd_wps_nfc_config_token(hapd, ndef);
+}
+
+
+struct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+ int ndef)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return NULL;
+ hapd = wpa_s->ap_iface->bss[0];
+ return hostapd_wps_nfc_hs_cr(hapd, ndef);
+}
+
+#endif /* CONFIG_WPS_NFC */
+
#endif /* CONFIG_WPS */
diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h
index 536064f..fd4c25a 100644
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -52,5 +52,9 @@
void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s);
void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
int offset);
+struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
+ int ndef);
+struct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+ int ndef);
#endif /* AP_H */
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 87b7db8..c50de53 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -224,7 +224,8 @@
}
-static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src)
+static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
+ struct os_time *fetch_time)
{
os_time_t usec;
@@ -238,7 +239,8 @@
dst->level = src->level;
dst->tsf = src->tsf;
- os_get_time(&dst->last_update);
+ dst->last_update.sec = fetch_time->sec;
+ dst->last_update.usec = fetch_time->usec;
dst->last_update.sec -= src->age / 1000;
usec = (src->age % 1000) * 1000;
if (dst->last_update.usec < usec) {
@@ -315,7 +317,8 @@
static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
const u8 *ssid, size_t ssid_len,
- struct wpa_scan_res *res)
+ struct wpa_scan_res *res,
+ struct os_time *fetch_time)
{
struct wpa_bss *bss;
@@ -324,7 +327,7 @@
return NULL;
bss->id = wpa_s->bss_next_id++;
bss->last_update_idx = wpa_s->bss_update_idx;
- wpa_bss_copy_res(bss, res);
+ wpa_bss_copy_res(bss, res, fetch_time);
os_memcpy(bss->ssid, ssid, ssid_len);
bss->ssid_len = ssid_len;
bss->ie_len = res->ie_len;
@@ -480,14 +483,14 @@
static struct wpa_bss *
wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
- struct wpa_scan_res *res)
+ struct wpa_scan_res *res, struct os_time *fetch_time)
{
u32 changes;
changes = wpa_bss_compare_res(bss, res);
bss->scan_miss_count = 0;
bss->last_update_idx = wpa_s->bss_update_idx;
- wpa_bss_copy_res(bss, res);
+ wpa_bss_copy_res(bss, res, fetch_time);
/* Move the entry to the end of the list */
dl_list_del(&bss->list);
if (bss->ie_len + bss->beacon_ie_len >=
@@ -551,13 +554,15 @@
* wpa_bss_update_scan_res - Update a BSS table entry based on a scan result
* @wpa_s: Pointer to wpa_supplicant data
* @res: Scan result
+ * @fetch_time: Time when the result was fetched from the driver
*
* This function updates a BSS table entry (or adds one) based on a scan result.
* This is called separately for each scan result between the calls to
* wpa_bss_update_start() and wpa_bss_update_end().
*/
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *res)
+ struct wpa_scan_res *res,
+ struct os_time *fetch_time)
{
const u8 *ssid, *p2p;
struct wpa_bss *bss;
@@ -595,9 +600,9 @@
* (to save memory) */
bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
if (bss == NULL)
- bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res);
+ bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res, fetch_time);
else
- bss = wpa_bss_update(wpa_s, bss, res);
+ bss = wpa_bss_update(wpa_s, bss, res, fetch_time);
if (bss == NULL)
return;
@@ -865,6 +870,29 @@
/**
+ * wpa_bss_get_id_range - Fetch a BSS table entry based on identifier range
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @idf: Smallest allowed identifier assigned for the entry
+ * @idf: Largest allowed identifier assigned for the entry
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ *
+ * This function is similar to wpa_bss_get_id() but allows a BSS entry with the
+ * smallest id value to be fetched within the specified range without the
+ * caller having to know the exact id.
+ */
+struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
+ unsigned int idf, unsigned int idl)
+{
+ struct wpa_bss *bss;
+ dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
+ if (bss->id >= idf && bss->id <= idl)
+ return bss;
+ }
+ return NULL;
+}
+
+
+/**
* wpa_bss_get_ie - Fetch a specified information element from a BSS entry
* @bss: BSS table entry
* @ie: Information element identitifier (WLAN_EID_*)
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 01f6c59..9f14d0e 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -97,7 +97,8 @@
void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *res);
+ struct wpa_scan_res *res,
+ struct os_time *fetch_time);
void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
int new_scan);
int wpa_bss_init(struct wpa_supplicant *wpa_s);
@@ -111,6 +112,8 @@
struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
const u8 *dev_addr);
struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id);
+struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
+ unsigned int idf, unsigned int idl);
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 2c52c68..ee634a5 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2980,10 +2980,11 @@
{ INT_RANGE(access_network_type, 0, 15), 0 },
{ INT_RANGE(pbc_in_m1, 0, 1), 0 },
{ STR(autoscan), 0 },
- { INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff), 0 },
- { BIN(wps_nfc_dh_pubkey), 0 },
- { BIN(wps_nfc_dh_privkey), 0 },
- { BIN(wps_nfc_dev_pw), 0 },
+ { INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff),
+ CFG_CHANGED_NFC_PASSWORD_TOKEN },
+ { BIN(wps_nfc_dh_pubkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
+ { BIN(wps_nfc_dh_privkey), CFG_CHANGED_NFC_PASSWORD_TOKEN },
+ { BIN(wps_nfc_dev_pw), CFG_CHANGED_NFC_PASSWORD_TOKEN },
{ STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND },
{ INT(p2p_go_max_inactivity), 0 },
{ INT_RANGE(auto_interworking, 0, 1), 0 },
@@ -3020,6 +3021,8 @@
"parse '%s'.", line, pos);
ret = -1;
}
+ if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN)
+ config->wps_nfc_pw_from_config = 1;
config->changed_parameters |= field->changed_flag;
break;
}
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 0c3cb9a..2b88bb5 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -220,6 +220,7 @@
#define CFG_CHANGED_P2P_OPER_CHANNEL BIT(12)
#define CFG_CHANGED_P2P_PREF_CHAN BIT(13)
#define CFG_CHANGED_EXT_PW_BACKEND BIT(14)
+#define CFG_CHANGED_NFC_PASSWORD_TOKEN BIT(15)
/**
* struct wpa_config - wpa_supplicant configuration data
@@ -706,6 +707,15 @@
char *autoscan;
/**
+ * wps_nfc_pw_from_config - NFC Device Password was read from config
+ *
+ * This parameter can be determined whether the NFC Device Password was
+ * included in the configuration (1) or generated dynamically (0). Only
+ * the former case is re-written back to the configuration file.
+ */
+ int wps_nfc_pw_from_config;
+
+ /**
* wps_nfc_dev_pw_id - NFC Device Password ID for password token
*/
int wps_nfc_dev_pw_id;
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 50c3533..f29f7a6 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -950,12 +950,16 @@
#endif /* CONFIG_INTERWORKING */
if (config->pbc_in_m1)
fprintf(f, "pbc_in_m1=%u\n", config->pbc_in_m1);
- if (config->wps_nfc_dev_pw_id)
- fprintf(f, "wps_nfc_dev_pw_id=%d\n",
- config->wps_nfc_dev_pw_id);
- write_global_bin(f, "wps_nfc_dh_pubkey", config->wps_nfc_dh_pubkey);
- write_global_bin(f, "wps_nfc_dh_privkey", config->wps_nfc_dh_privkey);
- write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw);
+ if (config->wps_nfc_pw_from_config) {
+ if (config->wps_nfc_dev_pw_id)
+ fprintf(f, "wps_nfc_dev_pw_id=%d\n",
+ config->wps_nfc_dev_pw_id);
+ write_global_bin(f, "wps_nfc_dh_pubkey",
+ config->wps_nfc_dh_pubkey);
+ write_global_bin(f, "wps_nfc_dh_privkey",
+ config->wps_nfc_dh_privkey);
+ write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw);
+ }
if (config->ext_password_backend)
fprintf(f, "ext_password_backend=%s\n",
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index d3c87da..dbe9153 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -778,6 +778,35 @@
}
+static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
+ struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
+{
+ int ndef;
+ struct wpabuf *buf;
+ int res;
+
+ if (os_strcmp(cmd, "WPS") == 0)
+ ndef = 0;
+ else if (os_strcmp(cmd, "NDEF") == 0)
+ ndef = 1;
+ else
+ return -1;
+
+ buf = wpas_wps_nfc_config_token(wpa_s, ndef);
+ if (buf == NULL)
+ return -1;
+
+ res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+ wpabuf_len(buf));
+ reply[res++] = '\n';
+ reply[res] = '\0';
+
+ wpabuf_free(buf);
+
+ return res;
+}
+
+
static int wpa_supplicant_ctrl_iface_wps_nfc_token(
struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
{
@@ -835,12 +864,13 @@
static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
- char *reply, size_t max_len)
+ char *reply, size_t max_len,
+ int cr)
{
struct wpabuf *buf;
int res;
- buf = wpas_wps_nfc_handover_req(wpa_s);
+ buf = wpas_wps_nfc_handover_req(wpa_s, cr);
if (buf == NULL)
return -1;
@@ -869,9 +899,9 @@
if (os_strcmp(cmd, "NDEF") != 0)
return -1;
- if (os_strcmp(pos, "WPS") == 0) {
- return wpas_ctrl_nfc_get_handover_req_wps(wpa_s, reply,
- max_len);
+ if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
+ return wpas_ctrl_nfc_get_handover_req_wps(
+ wpa_s, reply, max_len, os_strcmp(pos, "WPS-CR") == 0);
}
return -1;
@@ -879,12 +909,13 @@
static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
- char *reply, size_t max_len)
+ char *reply, size_t max_len,
+ int ndef, int cr)
{
struct wpabuf *buf;
int res;
- buf = wpas_wps_nfc_handover_sel(wpa_s);
+ buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr);
if (buf == NULL)
return -1;
@@ -904,18 +935,24 @@
size_t max_len)
{
char *pos;
+ int ndef;
pos = os_strchr(cmd, ' ');
if (pos == NULL)
return -1;
*pos++ = '\0';
- if (os_strcmp(cmd, "NDEF") != 0)
+ if (os_strcmp(cmd, "WPS") == 0)
+ ndef = 0;
+ else if (os_strcmp(cmd, "NDEF") == 0)
+ ndef = 1;
+ else
return -1;
- if (os_strcmp(pos, "WPS") == 0) {
- return wpas_ctrl_nfc_get_handover_sel_wps(wpa_s, reply,
- max_len);
+ if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
+ return wpas_ctrl_nfc_get_handover_sel_wps(
+ wpa_s, reply, max_len, ndef,
+ os_strcmp(pos, "WPS-CR") == 0);
}
return -1;
@@ -976,6 +1013,76 @@
return ret;
}
+
+static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ size_t len;
+ struct wpabuf *req, *sel;
+ int ret;
+ char *pos, *role, *type, *pos2;
+
+ role = cmd;
+ pos = os_strchr(role, ' ');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+
+ type = pos;
+ pos = os_strchr(type, ' ');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+
+ pos2 = os_strchr(pos, ' ');
+ if (pos2 == NULL)
+ return -1;
+ *pos2++ = '\0';
+
+ len = os_strlen(pos);
+ if (len & 0x01)
+ return -1;
+ len /= 2;
+
+ req = wpabuf_alloc(len);
+ if (req == NULL)
+ return -1;
+ if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
+ wpabuf_free(req);
+ return -1;
+ }
+
+ len = os_strlen(pos2);
+ if (len & 0x01) {
+ wpabuf_free(req);
+ return -1;
+ }
+ len /= 2;
+
+ sel = wpabuf_alloc(len);
+ if (sel == NULL) {
+ wpabuf_free(req);
+ return -1;
+ }
+ if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
+ wpabuf_free(req);
+ wpabuf_free(sel);
+ return -1;
+ }
+
+ if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
+ ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
+ } else {
+ wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
+ "reported: role=%s type=%s", role, type);
+ ret = -1;
+ }
+ wpabuf_free(req);
+ wpabuf_free(sel);
+
+ return ret;
+}
+
#endif /* CONFIG_WPS_NFC */
@@ -3174,10 +3281,17 @@
return 0;
}
- id1 = atoi(cmd + 6);
- bss = wpa_bss_get_id(wpa_s, id1);
- id2 = atoi(ctmp + 1);
- if (id2 == 0)
+ if (*(cmd + 6) == '-')
+ id1 = 0;
+ else
+ id1 = atoi(cmd + 6);
+ ctmp++;
+ if (*ctmp >= '0' && *ctmp <= '9')
+ id2 = atoi(ctmp);
+ else
+ id2 = (unsigned int) -1;
+ bss = wpa_bss_get_id_range(wpa_s, id1, id2);
+ if (id2 == (unsigned int) -1)
bsslast = dl_list_last(&wpa_s->bss_id,
struct wpa_bss,
list_id);
@@ -4803,6 +4917,7 @@
if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
+ os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0 ||
os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
(const u8 *) buf, os_strlen(buf));
@@ -4919,6 +5034,9 @@
} else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
reply_len = -1;
+ } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
+ wpa_s, buf + 21, reply, reply_size);
} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
wpa_s, buf + 14, reply, reply_size);
@@ -4938,6 +5056,9 @@
} else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) {
if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20))
reply_len = -1;
+ } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
+ if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
+ reply_len = -1;
#endif /* CONFIG_WPS_NFC */
} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 8bc6618..5b4a0a4 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -1808,6 +1808,9 @@
case WPAS_DBUS_BSS_PROP_RSN:
prop = "RSN";
break;
+ case WPAS_DBUS_BSS_PROP_WPS:
+ prop = "WPS";
+ break;
case WPAS_DBUS_BSS_PROP_IES:
prop = "IEs";
break;
diff --git a/wpa_supplicant/eap_proxy_dummy.mk b/wpa_supplicant/eap_proxy_dummy.mk
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wpa_supplicant/eap_proxy_dummy.mk
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 945ba4a..871e99c 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -639,6 +639,28 @@
}
+static int bss_is_dmg(struct wpa_bss *bss)
+{
+ return bss->freq > 45000;
+}
+
+
+/*
+ * Test whether BSS is in an ESS.
+ * This is done differently in DMG (60 GHz) and non-DMG bands
+ */
+static int bss_is_ess(struct wpa_bss *bss)
+{
+ if (bss_is_dmg(bss)) {
+ return (bss->caps & IEEE80211_CAP_DMG_MASK) ==
+ IEEE80211_CAP_DMG_AP;
+ }
+
+ return ((bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
+ IEEE80211_CAP_ESS);
+}
+
+
static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int i, struct wpa_bss *bss,
struct wpa_ssid *group)
@@ -772,9 +794,8 @@
continue;
}
- if (bss->caps & IEEE80211_CAP_IBSS) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - IBSS (adhoc) "
- "network");
+ if (!bss_is_ess(bss)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - not ESS network");
continue;
}
@@ -3051,6 +3072,16 @@
wpas_wps_start_pbc(wpa_s, NULL, 0);
#endif /* CONFIG_WPS */
break;
+ case EVENT_CONNECT_FAILED_REASON:
+#ifdef CONFIG_AP
+ if (!wpa_s->ap_iface || !data)
+ break;
+ hostapd_event_connect_failed_reason(
+ wpa_s->ap_iface->bss[0],
+ data->connect_failed_reason.addr,
+ data->connect_failed_reason.code);
+#endif /* CONFIG_AP */
+ break;
default:
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
break;
diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py
index 0cfc1f6..14acc5b 100755
--- a/wpa_supplicant/examples/wps-nfc.py
+++ b/wpa_supplicant/examples/wps-nfc.py
@@ -1,7 +1,7 @@
#!/usr/bin/python
#
# Example nfcpy to wpa_supplicant wrapper for WPS NFC operations
-# Copyright (c) 2012, Jouni Malinen <j@w1.fi>
+# Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
@@ -9,12 +9,17 @@
import os
import sys
import time
+import random
+import StringIO
import nfc
import nfc.ndef
import nfc.llcp
import nfc.handover
+import logging
+logging.basicConfig()
+
import wpactrl
wpas_ctrl = '/var/run/wpa_supplicant'
@@ -49,18 +54,34 @@
print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex"))
+def wpas_get_config_token():
+ wpas = wpas_connect()
+ if (wpas == None):
+ return None
+ return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex")
+
+
+def wpas_get_password_token():
+ wpas = wpas_connect()
+ if (wpas == None):
+ return None
+ return wpas.request("WPS_NFC_TOKEN NDEF").rstrip().decode("hex")
+
+
def wpas_get_handover_req():
wpas = wpas_connect()
if (wpas == None):
return None
- return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS").rstrip().decode("hex")
+ return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip().decode("hex")
-def wpas_put_handover_sel(message):
+def wpas_report_handover(req, sel):
wpas = wpas_connect()
if (wpas == None):
- return
- print wpas.request("NFC_RX_HANDOVER_SEL " + str(message).encode("hex"))
+ return None
+ return wpas.request("NFC_REPORT_HANDOVER INIT WPS " +
+ str(req).encode("hex") + " " +
+ str(sel).encode("hex"))
def wps_handover_init(peer):
@@ -68,14 +89,24 @@
data = wpas_get_handover_req()
if (data == None):
- print "Could not get handover request message from wpa_supplicant"
+ print "Could not get handover request carrier record from wpa_supplicant"
return
- print "Handover request from wpa_supplicant: " + data.encode("hex")
- message = nfc.ndef.Message(data)
- print "Parsed handover request: " + message.pretty()
+ print "Handover request carrier record from wpa_supplicant: " + data.encode("hex")
+ record = nfc.ndef.Record()
+ f = StringIO.StringIO(data)
+ record._read(f)
+ record = nfc.ndef.HandoverCarrierRecord(record)
+ print "Parsed handover request carrier record:"
+ print record.pretty()
+
+ message = nfc.ndef.HandoverRequestMessage(version="1.2")
+ message.nonce = random.randint(0, 0xffff)
+ message.add_carrier(record, "active")
+
+ print "Handover request:"
+ print message.pretty()
nfc.llcp.activate(peer);
- time.sleep(0.5)
client = nfc.handover.HandoverClient()
try:
@@ -95,9 +126,30 @@
print "Receiving handover response"
message = client._recv()
+ if message is None:
+ print "No response received"
+ nfc.llcp.shutdown()
+ client.close()
+ return
+ if message.type != "urn:nfc:wkt:Hs":
+ print "Response was not Hs - received: " + message.type
+ nfc.llcp.shutdown()
+ client.close()
+ return
+
+ print "Received message"
+ print message.pretty()
+ message = nfc.ndef.HandoverSelectMessage(message)
print "Handover select received"
print message.pretty()
- wpas_put_handover_sel(message)
+
+ for carrier in message.carriers:
+ print "Remote carrier type: " + carrier.type
+ if carrier.type == "application/vnd.wfa.wsc":
+ print "WPS carrier type match - send to wpa_supplicant"
+ wpas_report_handover(data, carrier.record)
+ wifi = nfc.ndef.WifiConfigRecord(carrier.record)
+ print wifi.pretty()
print "Remove peer"
nfc.llcp.shutdown()
@@ -124,32 +176,105 @@
time.sleep(0.1)
+def wps_write_config_tag(clf):
+ print "Write WPS config token"
+ data = wpas_get_config_token()
+ if (data == None):
+ print "Could not get WPS config token from wpa_supplicant"
+ return
+
+ print "Touch an NFC tag"
+ while True:
+ tag = clf.poll()
+ if tag == None:
+ time.sleep(0.1)
+ continue
+ break
+
+ print "Tag found - writing"
+ tag.ndef.message = data
+ print "Done - remove tag"
+ while tag.is_present:
+ time.sleep(0.1)
+
+
+def wps_write_password_tag(clf):
+ print "Write WPS password token"
+ data = wpas_get_password_token()
+ if (data == None):
+ print "Could not get WPS password token from wpa_supplicant"
+ return
+
+ print "Touch an NFC tag"
+ while True:
+ tag = clf.poll()
+ if tag == None:
+ time.sleep(0.1)
+ continue
+ break
+
+ print "Tag found - writing"
+ tag.ndef.message = data
+ print "Done - remove tag"
+ while tag.is_present:
+ time.sleep(0.1)
+
+
+def find_peer(clf):
+ while True:
+ if nfc.llcp.connected():
+ print "LLCP connected"
+ general_bytes = nfc.llcp.startup({})
+ peer = clf.listen(ord(os.urandom(1)) + 250, general_bytes)
+ if isinstance(peer, nfc.DEP):
+ print "listen -> DEP";
+ if peer.general_bytes.startswith("Ffm"):
+ print "Found DEP"
+ return peer
+ print "mismatch in general_bytes"
+ print peer.general_bytes
+
+ peer = clf.poll(general_bytes)
+ if isinstance(peer, nfc.DEP):
+ print "poll -> DEP";
+ if peer.general_bytes.startswith("Ffm"):
+ print "Found DEP"
+ return peer
+ print "mismatch in general_bytes"
+ print peer.general_bytes
+
+ if peer:
+ print "Found tag"
+ return peer
+
+
def main():
clf = nfc.ContactlessFrontend()
try:
+ 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-password":
+ wps_write_password_tag(clf)
+ raise SystemExit
+
while True:
print "Waiting for a tag or peer to be touched"
- while True:
- general_bytes = nfc.llcp.startup({})
- tag = clf.poll(general_bytes)
- if tag == None:
- continue
+ tag = find_peer(clf)
+ if isinstance(tag, nfc.DEP):
+ wps_handover_init(tag)
+ continue
- if isinstance(tag, nfc.DEP):
- wps_handover_init(tag)
- break
+ if tag.ndef:
+ wps_tag_read(tag)
+ continue
- if tag.ndef:
- wps_tag_read(tag)
- break
-
- if tag:
- print "Not an NDEF tag - remove tag"
- while tag.is_present:
- time.sleep(0.1)
- break
+ print "Not an NDEF tag - remove tag"
+ while tag.is_present:
+ time.sleep(0.1)
except KeyboardInterrupt:
raise SystemExit
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index e1f58a6..3602b07 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -42,6 +42,10 @@
#endif
static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s);
+static struct wpa_cred * interworking_credentials_available_realm(
+ struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
+static struct wpa_cred * interworking_credentials_available_3gpp(
+ struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
static void interworking_reconnect(struct wpa_supplicant *wpa_s)
@@ -740,10 +744,10 @@
static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
+ struct wpa_cred *cred,
struct wpa_bss *bss)
{
#ifdef INTERWORKING_3GPP
- struct wpa_cred *cred;
struct wpa_ssid *ssid;
const u8 *ie;
int eap_type;
@@ -753,40 +757,6 @@
if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
return -1;
- for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
- char *sep;
- const char *imsi;
- int mnc_len;
-
-#ifdef PCSC_FUNCS
- if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard &&
- wpa_s->imsi[0]) {
- imsi = wpa_s->imsi;
- mnc_len = wpa_s->mnc_len;
- goto compare;
- }
-#endif /* PCSC_FUNCS */
-
- if (cred->imsi == NULL || !cred->imsi[0] ||
- cred->milenage == NULL || !cred->milenage[0])
- continue;
-
- sep = os_strchr(cred->imsi, '-');
- if (sep == NULL ||
- (sep - cred->imsi != 5 && sep - cred->imsi != 6))
- continue;
- mnc_len = sep - cred->imsi - 3;
- imsi = cred->imsi;
-
-#ifdef PCSC_FUNCS
- compare:
-#endif /* PCSC_FUNCS */
- if (plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len))
- break;
- }
- if (cred == NULL)
- return -1;
-
ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
if (ie == NULL)
return -1;
@@ -1167,7 +1137,7 @@
int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{
- struct wpa_cred *cred;
+ struct wpa_cred *cred, *cred_rc, *cred_3gpp;
struct wpa_ssid *ssid;
struct nai_realm *realm;
struct nai_realm_eap *eap = NULL;
@@ -1194,39 +1164,61 @@
return -1;
}
- cred = interworking_credentials_available_roaming_consortium(wpa_s,
- bss);
- if (cred)
- return interworking_connect_roaming_consortium(wpa_s, cred,
+ cred_rc = interworking_credentials_available_roaming_consortium(wpa_s,
+ bss);
+ if (cred_rc) {
+ wpa_printf(MSG_DEBUG, "Interworking: Highest roaming "
+ "consortium matching credential priority %d",
+ cred_rc->priority);
+ }
+
+ cred = interworking_credentials_available_realm(wpa_s, bss);
+ if (cred) {
+ wpa_printf(MSG_DEBUG, "Interworking: Highest NAI Realm list "
+ "matching credential priority %d",
+ cred->priority);
+ }
+
+ cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss);
+ if (cred_3gpp) {
+ wpa_printf(MSG_DEBUG, "Interworking: Highest 3GPP matching "
+ "credential priority %d", cred_3gpp->priority);
+ }
+
+ if (cred_rc &&
+ (cred == NULL || cred_rc->priority >= cred->priority) &&
+ (cred_3gpp == NULL || cred_rc->priority >= cred_3gpp->priority))
+ return interworking_connect_roaming_consortium(wpa_s, cred_rc,
bss, ie);
+ if (cred_3gpp &&
+ (cred == NULL || cred_3gpp->priority >= cred->priority)) {
+ return interworking_connect_3gpp(wpa_s, cred_3gpp, bss);
+ }
+
+ if (cred == NULL) {
+ wpa_printf(MSG_DEBUG, "Interworking: No matching credentials "
+ "found for " MACSTR, MAC2STR(bss->bssid));
+ return -1;
+ }
+
realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL,
&count);
if (realm == NULL) {
wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI "
"Realm list from " MACSTR, MAC2STR(bss->bssid));
- count = 0;
+ return -1;
}
- for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
- for (i = 0; i < count; i++) {
- if (!nai_realm_match(&realm[i], cred->realm))
- continue;
- eap = nai_realm_find_eap(cred, &realm[i]);
- if (eap)
- break;
- }
+ for (i = 0; i < count; i++) {
+ if (!nai_realm_match(&realm[i], cred->realm))
+ continue;
+ eap = nai_realm_find_eap(cred, &realm[i]);
if (eap)
break;
}
if (!eap) {
- if (interworking_connect_3gpp(wpa_s, bss) == 0) {
- if (realm)
- nai_realm_free(realm, count);
- return 0;
- }
-
wpa_printf(MSG_DEBUG, "Interworking: No matching credentials "
"and EAP method found for " MACSTR,
MAC2STR(bss->bssid));
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 3e02099..6cff577 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -93,6 +93,8 @@
static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
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);
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);
@@ -111,8 +113,12 @@
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *bss = scan_res->res[i];
+ struct os_time time_tmp_age, entry_ts;
+ time_tmp_age.sec = bss->age / 1000;
+ time_tmp_age.usec = (bss->age % 1000) * 1000;
+ os_time_sub(&scan_res->fetch_time, &time_tmp_age, &entry_ts);
if (p2p_scan_res_handler(wpa_s->global->p2p, bss->bssid,
- bss->freq, bss->age, bss->level,
+ bss->freq, &entry_ts, bss->level,
(const u8 *) (bss + 1),
bss->ie_len) > 0)
break;
@@ -333,6 +339,10 @@
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,
+ wpa_s->parent, NULL) > 0)
+ wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group formation "
+ "timeout");
if (removal_reason != P2P_GROUP_REMOVAL_SILENT && ssid)
wpas_notify_p2p_group_removed(wpa_s, ssid, gtype);
@@ -3944,7 +3954,11 @@
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
"frequency %d MHz", params->freq);
} else if (wpa_s->conf->p2p_oper_reg_class == 115 ||
- wpa_s->conf->p2p_oper_reg_class == 124) {
+ wpa_s->conf->p2p_oper_reg_class == 116 ||
+ wpa_s->conf->p2p_oper_reg_class == 117 ||
+ wpa_s->conf->p2p_oper_reg_class == 124 ||
+ wpa_s->conf->p2p_oper_reg_class == 126 ||
+ wpa_s->conf->p2p_oper_reg_class == 127) {
params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
"frequency %d MHz", params->freq);
@@ -5495,10 +5509,29 @@
int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s)
{
+ int ret;
+
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return 0;
- return p2p_in_progress(wpa_s->global->p2p);
+ ret = p2p_in_progress(wpa_s->global->p2p);
+ if (ret == 0) {
+ /*
+ * Check whether there is an ongoing WPS provisioning step (or
+ * other parts of group formation) on another interface since
+ * p2p_in_progress() does not report this to avoid issues for
+ * scans during such provisioning step.
+ */
+ if (wpa_s->global->p2p_group_formation &&
+ wpa_s->global->p2p_group_formation != wpa_s) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Another interface (%s) "
+ "in group formation",
+ wpa_s->global->p2p_group_formation->ifname);
+ ret = 1;
+ }
+ }
+
+ return ret;
}
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 9b71400..91a436a 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -1461,15 +1461,17 @@
== WPA_SCAN_LEVEL_DBM) {
int snr = r->level - r->noise;
wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
- "noise=%d level=%d snr=%d%s flags=0x%x",
+ "noise=%d level=%d snr=%d%s flags=0x%x "
+ "age=%u",
MAC2STR(r->bssid), r->freq, r->qual,
r->noise, r->level, snr,
- snr >= GREAT_SNR ? "*" : "", r->flags);
+ snr >= GREAT_SNR ? "*" : "", r->flags,
+ r->age);
} else {
wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
- "noise=%d level=%d flags=0x%x",
+ "noise=%d level=%d flags=0x%x age=%u",
MAC2STR(r->bssid), r->freq, r->qual,
- r->noise, r->level, r->flags);
+ r->noise, r->level, r->flags, r->age);
}
pos = (u8 *) (r + 1);
if (r->ie_len)
@@ -1560,6 +1562,13 @@
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
return NULL;
}
+ if (scan_res->fetch_time.sec == 0) {
+ /*
+ * Make sure we have a valid timestamp if the driver wrapper
+ * does not set this.
+ */
+ os_get_time(&scan_res->fetch_time);
+ }
filter_scan_res(wpa_s, scan_res);
#ifdef CONFIG_WPS
@@ -1576,7 +1585,8 @@
wpa_bss_update_start(wpa_s);
for (i = 0; i < scan_res->num; i++)
- wpa_bss_update_scan_res(wpa_s, scan_res->res[i]);
+ wpa_bss_update_scan_res(wpa_s, scan_res->res[i],
+ &scan_res->fetch_time);
wpa_bss_update_end(wpa_s, info, new_scan);
return scan_res;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 6d8b1f5..0630a4b 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -770,6 +770,13 @@
}
+static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
+}
+
+
static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -868,6 +875,13 @@
return ret;
}
+
+static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
+}
+
#endif /* CONFIG_WPS_NFC */
@@ -2529,6 +2543,9 @@
{ "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
cli_cmd_flag_none,
"[BSSID] = start Wi-Fi Protected Setup: NFC" },
+ { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
+ cli_cmd_flag_none,
+ "<WPS|NDEF> = build configuration token" },
{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
cli_cmd_flag_none,
"<WPS|NDEF> = create password token" },
@@ -2547,6 +2564,10 @@
{ "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
cli_cmd_flag_none,
"<hexdump of payload> = report received NFC handover select" },
+ { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
+ cli_cmd_flag_none,
+ "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
+ "NFC handover" },
#endif /* CONFIG_WPS_NFC */
{ "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
cli_cmd_flag_sensitive,
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 725364a..a9af2d6 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -664,8 +664,8 @@
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
struct wpa_ssid *ssid = wpa_s->current_ssid;
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
- MACSTR " completed %s [id=%d id_str=%s]",
- MAC2STR(wpa_s->bssid), "(auth)",
+ MACSTR " completed (auth) [id=%d id_str=%s]",
+ MAC2STR(wpa_s->bssid),
ssid ? ssid->id : -1,
ssid && ssid->id_str ? ssid->id_str : "");
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
@@ -1730,6 +1730,10 @@
zero_addr = 1;
}
+#ifdef CONFIG_TDLS
+ wpa_tdls_teardown_peers(wpa_s->wpa);
+#endif /* CONFIG_TDLS */
+
if (addr) {
wpa_drv_deauthenticate(wpa_s, addr, reason_code);
os_memset(&event, 0, sizeof(event));
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 4859774..dfc3b76 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -552,20 +552,35 @@
static int wpa_supplicant_tdls_peer_addset(
void *ctx, const u8 *peer, int add, u16 capability,
- const u8 *supp_rates, size_t supp_rates_len)
+ const u8 *supp_rates, size_t supp_rates_len,
+ const struct ieee80211_ht_capabilities *ht_capab,
+ u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
{
struct wpa_supplicant *wpa_s = ctx;
struct hostapd_sta_add_params params;
+ os_memset(¶ms, 0, sizeof(params));
+
params.addr = peer;
params.aid = 1;
params.capability = capability;
params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
- params.ht_capabilities = NULL;
+
+ /*
+ * TDLS Setup frames do not contain WMM IEs, hence need to depend on
+ * qosinfo to check if the peer is WMM capable.
+ */
+ if (qosinfo)
+ params.flags |= WPA_STA_WMM;
+
+ params.ht_capabilities = ht_capab;
+ params.qosinfo = qosinfo;
params.listen_interval = 0;
params.supp_rates = supp_rates;
params.supp_rates_len = supp_rates_len;
params.set = !add;
+ params.ext_capab = ext_capab;
+ params.ext_capab_len = ext_capab_len;
return wpa_drv_sta_add(wpa_s, ¶ms);
}
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 711c3c0..c89479f 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -1830,8 +1830,26 @@
#ifdef CONFIG_WPS_NFC
+struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
+ int ndef)
+{
+#ifdef CONFIG_AP
+ if (wpa_s->ap_iface)
+ return wpas_ap_wps_nfc_config_token(wpa_s, ndef);
+#endif /* CONFIG_AP */
+ return NULL;
+}
+
+
struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef)
{
+ if (wpa_s->conf->wps_nfc_pw_from_config) {
+ return wps_nfc_token_build(ndef,
+ wpa_s->conf->wps_nfc_dev_pw_id,
+ wpa_s->conf->wps_nfc_dh_pubkey,
+ wpa_s->conf->wps_nfc_dev_pw);
+ }
+
return wps_nfc_token_gen(ndef, &wpa_s->conf->wps_nfc_dev_pw_id,
&wpa_s->conf->wps_nfc_dh_pubkey,
&wpa_s->conf->wps_nfc_dh_privkey,
@@ -1977,15 +1995,20 @@
}
-struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s)
+struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr)
{
+ if (cr)
+ return ndef_build_wifi_hc(1);
return ndef_build_wifi_hr();
}
-struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s)
+struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+ int ndef, int cr)
{
- return NULL;
+ if (!cr)
+ return NULL;
+ return wpas_ap_wps_nfc_handover_sel(wpa_s, ndef);
}
@@ -2015,6 +2038,17 @@
return ret;
}
+
+int wpas_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
+ const struct wpabuf *req,
+ const struct wpabuf *sel)
+{
+ wpa_printf(MSG_DEBUG, "NFC: WPS connection handover reported");
+ wpa_hexdump_buf_key(MSG_DEBUG, "WPS: Carrier record in request", req);
+ wpa_hexdump_buf_key(MSG_DEBUG, "WPS: Carrier record in select", sel);
+ return wpas_wps_nfc_rx_handover_sel(wpa_s, sel);
+}
+
#endif /* CONFIG_WPS_NFC */
diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
index dd0dc60..5bc5ffa 100644
--- a/wpa_supplicant/wps_supplicant.h
+++ b/wpa_supplicant/wps_supplicant.h
@@ -62,16 +62,22 @@
int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
int wpas_wps_in_progress(struct wpa_supplicant *wpa_s);
void wpas_wps_update_config(struct wpa_supplicant *wpa_s);
+struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
+ int ndef);
struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef);
int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid);
int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
const struct wpabuf *data);
-struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s);
-struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s);
+struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr);
+struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+ int ndef, int cr);
int wpas_wps_nfc_rx_handover_req(struct wpa_supplicant *wpa_s,
const struct wpabuf *data);
int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
const struct wpabuf *data);
+int wpas_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
+ const struct wpabuf *req,
+ const struct wpabuf *sel);
void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid);