Cumulative patch from commit efc64886b8a285440e9954b5395a5370d8c5f84f
efc6488 nl80211: Pass station supported channel and oper class info
3ed9727 TDLS: Pass peer's Supported channel and oper class info during sta_add
eed65aa hostapd: DFS setup seg0 correctly for HT40-
25592b2 hostapd: DFS/CSA check if CSA in progress
b19ef32 Android: Remove hostapd dump_file functionality
c48414a P2P: Limit join-a-group scans based on SSID from invitation
78f0c93 Flush secondary device types on FLUSH command
2b38410 P2P: Allow requested device type to be specified with p2p_find
d9bb282 Clear configuration blobs on FLUSH command
c60ba9f Skip network disabling on expected EAP failure
7185e16 EAP-FAST peer: Make debug clearer on missing pac_file configuration
7b88b64 EXT PW: Fix hash return in password fetching
08081ad hostapd: Skip full AP configuration validation on SET command
1785d2e P2P: Wait on GO Negotiation Confirm transmit
472fa21 P2P: Cancel action frame offchan wait after recv GO Neg Conf
bfdc2a3 bsd: Fix NULL pointer dereference on error path
38bbd06 bsd: Prepare event buffer on init process
3043b4f nl80211: Document how to configure for libnl 2.0 and 3.2
Change-Id: Ia592bc948eaa43dbfaf0b4a20231efca61acb11f
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index a29f4d0..79ab4ba 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -1,6 +1,6 @@
/*
* hostapd / Configuration helper functions
- * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -670,9 +670,10 @@
static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
- struct hostapd_config *conf)
+ struct hostapd_config *conf,
+ int full_config)
{
- if (bss->ieee802_1x && !bss->eap_server &&
+ if (full_config && bss->ieee802_1x && !bss->eap_server &&
!bss->radius->auth_servers) {
wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
"EAP authenticator configured).");
@@ -697,14 +698,15 @@
}
}
- if (bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
+ if (full_config && bss->wpa &&
+ bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
"RADIUS checking (macaddr_acl=2) enabled.");
return -1;
}
- if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
+ if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
bss->ssid.wpa_psk_file == NULL &&
(bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
@@ -714,7 +716,7 @@
return -1;
}
- if (hostapd_mac_comp_empty(bss->bssid) != 0) {
+ if (full_config && hostapd_mac_comp_empty(bss->bssid) != 0) {
size_t i;
for (i = 0; i < conf->num_bss; i++) {
@@ -731,7 +733,7 @@
}
#ifdef CONFIG_IEEE80211R
- if (wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
+ if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
(bss->nas_identifier == NULL ||
os_strlen(bss->nas_identifier) < 1 ||
os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
@@ -743,20 +745,21 @@
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211N
- if (conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
+ if (full_config && conf->ieee80211n &&
+ conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
"allowed, disabling HT capabilites");
}
- if (conf->ieee80211n &&
+ if (full_config && conf->ieee80211n &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
"allowed, disabling HT capabilities");
}
- if (conf->ieee80211n && bss->wpa &&
+ if (full_config && conf->ieee80211n && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
@@ -769,19 +772,20 @@
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_WPS2
- if (bss->wps_state && bss->ignore_broadcast_ssid) {
+ if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
"configuration forced WPS to be disabled");
bss->wps_state = 0;
}
- if (bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) {
+ if (full_config && bss->wps_state &&
+ bss->ssid.wep.keys_set && bss->wpa == 0) {
wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
"disabled");
bss->wps_state = 0;
}
- if (bss->wps_state && bss->wpa &&
+ if (full_config && bss->wps_state && bss->wpa &&
(!(bss->wpa & 2) ||
!(bss->rsn_pairwise & WPA_CIPHER_CCMP))) {
wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
@@ -791,7 +795,7 @@
#endif /* CONFIG_WPS2 */
#ifdef CONFIG_HS20
- if (bss->hs20 &&
+ if (full_config && bss->hs20 &&
(!(bss->wpa & 2) ||
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
WPA_CIPHER_CCMP_256 |
@@ -807,24 +811,25 @@
}
-int hostapd_config_check(struct hostapd_config *conf)
+int hostapd_config_check(struct hostapd_config *conf, int full_config)
{
size_t i;
- if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) {
+ if (full_config && conf->ieee80211d &&
+ (!conf->country[0] || !conf->country[1])) {
wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
"setting the country_code");
return -1;
}
- if (conf->ieee80211h && !conf->ieee80211d) {
+ if (full_config && 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))
+ if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
return -1;
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index af30ac4..0bb937e 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -570,7 +570,7 @@
int vlan_id);
struct hostapd_radius_attr *
hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
-int hostapd_config_check(struct hostapd_config *conf);
+int hostapd_config_check(struct hostapd_config *conf, int full_config);
void hostapd_set_security_params(struct hostapd_bss_config *bss);
#endif /* HOSTAPD_CONFIG_H */
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index caf4092..e4c00f8 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -176,6 +176,7 @@
static void dfs_adjust_vht_center_freq(struct hostapd_iface *iface,
struct hostapd_channel_data *chan,
+ int secondary_channel,
u8 *vht_oper_centr_freq_seg0_idx,
u8 *vht_oper_centr_freq_seg1_idx)
{
@@ -189,9 +190,9 @@
switch (iface->conf->vht_oper_chwidth) {
case VHT_CHANWIDTH_USE_HT:
- if (iface->conf->secondary_channel == 1)
+ if (secondary_channel == 1)
*vht_oper_centr_freq_seg0_idx = chan->chan + 2;
- else if (iface->conf->secondary_channel == -1)
+ else if (secondary_channel == -1)
*vht_oper_centr_freq_seg0_idx = chan->chan - 2;
else
*vht_oper_centr_freq_seg0_idx = chan->chan;
@@ -366,6 +367,7 @@
*secondary_channel = 0;
dfs_adjust_vht_center_freq(iface, chan,
+ *secondary_channel,
vht_oper_centr_freq_seg0_idx,
vht_oper_centr_freq_seg1_idx);
@@ -680,14 +682,18 @@
struct hostapd_data *hapd = iface->bss[0];
int err = 1;
- wpa_printf(MSG_DEBUG, "%s called (CAC active: %s)", __func__,
- iface->cac_started ? "yes" : "no");
+ wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
+ __func__, iface->cac_started ? "yes" : "no",
+ iface->csa_in_progress ? "yes" : "no");
+
+ /* Check if CSA in progress */
+ if (iface->csa_in_progress)
+ return 0;
/* Check if active CAC */
if (iface->cac_started)
return hostapd_dfs_start_channel_switch_cac(iface);
-
/* Perform channel switch/CSA */
channel = dfs_get_valid_channel(iface, &secondary_channel,
&vht_oper_centr_freq_seg0_idx,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 44d05c5..220211c 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1,6 +1,6 @@
/*
* hostapd / Initialization and configuration
- * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -1537,6 +1537,11 @@
wpa_printf(MSG_DEBUG, "Enable interface %s",
hapd_iface->conf->bss[0]->iface);
+ if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
+ wpa_printf(MSG_INFO, "Invalid configuration - cannot enable");
+ return -1;
+ }
+
if (hapd_iface->interfaces == NULL ||
hapd_iface->interfaces->driver_init == NULL ||
hapd_iface->interfaces->driver_init(hapd_iface))
@@ -1569,7 +1574,7 @@
hapd_iface->conf->bss[0]->iface);
for (j = 0; j < hapd_iface->num_bss; j++)
hostapd_set_security_params(hapd_iface->conf->bss[j]);
- if (hostapd_config_check(hapd_iface->conf) < 0) {
+ if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
wpa_printf(MSG_ERROR, "Updated configuration is invalid");
return -1;
}
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 7d78648..12dc83e 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -227,6 +227,7 @@
#define WLAN_EID_FAST_BSS_TRANSITION 55
#define WLAN_EID_TIMEOUT_INTERVAL 56
#define WLAN_EID_RIC_DATA 57
+#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
#define WLAN_EID_HT_OPERATION 61
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
#define WLAN_EID_WAPI 68
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index db34ed1..4fd16ed 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1012,6 +1012,10 @@
u8 qosinfo;
const u8 *ext_capab;
size_t ext_capab_len;
+ const u8 *supp_channels;
+ size_t supp_channels_len;
+ const u8 *supp_oper_classes;
+ size_t supp_oper_classes_len;
};
struct hostapd_freq_params {
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index 7f5e231..71c9ce9 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -62,6 +62,8 @@
int prev_privacy; /* privacy state to restore on deinit */
int prev_wpa; /* wpa state to restore on deinit */
enum ieee80211_opmode opmode; /* operation mode */
+ char *event_buf;
+ size_t event_buf_len;
};
/* Generic functions for hostapd and wpa_supplicant */
@@ -642,7 +644,7 @@
return 0;
}
-static int
+static size_t
rtbuf_len(void)
{
size_t len;
@@ -779,37 +781,26 @@
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct bsd_driver_data *drv = ctx;
- char *buf;
struct if_announcemsghdr *ifan;
struct rt_msghdr *rtm;
struct ieee80211_michael_event *mic;
struct ieee80211_join_event *join;
struct ieee80211_leave_event *leave;
- int n, len;
+ int n;
union wpa_event_data data;
- len = rtbuf_len();
-
- buf = os_malloc(len);
- if (buf == NULL) {
- wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
- return;
- }
-
- n = read(sock, buf, len);
+ n = read(sock, drv->event_buf, drv->event_buf_len);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_ERROR, "%s read() failed: %s\n",
__func__, strerror(errno));
- os_free(buf);
return;
}
- rtm = (struct rt_msghdr *) buf;
+ rtm = (struct rt_msghdr *) drv->event_buf;
if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
rtm->rtm_version);
- os_free(buf);
return;
}
ifan = (struct if_announcemsghdr *) rtm;
@@ -850,7 +841,6 @@
}
break;
}
- os_free(buf);
}
static void
@@ -867,7 +857,15 @@
drv = os_zalloc(sizeof(struct bsd_driver_data));
if (drv == NULL) {
- printf("Could not allocate memory for bsd driver data\n");
+ wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data");
+ return NULL;
+ }
+
+ drv->event_buf_len = rtbuf_len();
+
+ drv->event_buf = os_malloc(drv->event_buf_len);
+ if (drv->event_buf == NULL) {
+ wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
goto bad;
}
@@ -910,6 +908,7 @@
l2_packet_deinit(drv->sock_xmit);
if (drv->sock >= 0)
close(drv->sock);
+ os_free(drv->event_buf);
if (drv != NULL)
os_free(drv);
return NULL;
@@ -930,6 +929,7 @@
close(drv->sock);
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
+ os_free(drv->event_buf);
os_free(drv);
}
@@ -1208,7 +1208,6 @@
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct bsd_driver_data *drv = sock_ctx;
- char *buf;
struct if_announcemsghdr *ifan;
struct if_msghdr *ifm;
struct rt_msghdr *rtm;
@@ -1216,30 +1215,20 @@
struct ieee80211_michael_event *mic;
struct ieee80211_leave_event *leave;
struct ieee80211_join_event *join;
- int n, len;
+ int n;
- len = rtbuf_len();
-
- buf = os_malloc(len);
- if (buf == NULL) {
- wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
- return;
- }
-
- n = read(sock, buf, len);
+ n = read(sock, drv->event_buf, drv->event_buf_len);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_ERROR, "%s read() failed: %s\n",
__func__, strerror(errno));
- os_free(buf);
return;
}
- rtm = (struct rt_msghdr *) buf;
+ rtm = (struct rt_msghdr *) drv->event_buf;
if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
rtm->rtm_version);
- os_free(buf);
return;
}
os_memset(&event, 0, sizeof(event));
@@ -1254,7 +1243,6 @@
case IFAN_DEPARTURE:
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
default:
- os_free(buf);
return;
}
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
@@ -1327,7 +1315,6 @@
}
break;
}
- os_free(buf);
}
static void
@@ -1508,6 +1495,15 @@
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
+
+ drv->event_buf_len = rtbuf_len();
+
+ drv->event_buf = os_malloc(drv->event_buf_len);
+ if (drv->event_buf == NULL) {
+ wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
+ goto fail1;
+ }
+
/*
* NB: We require the interface name be mappable to an index.
* This implies we do not support having wpa_supplicant
@@ -1562,6 +1558,7 @@
fail:
close(drv->sock);
fail1:
+ os_free(drv->event_buf);
os_free(drv);
return NULL;
#undef GETPARAM
@@ -1587,6 +1584,7 @@
l2_packet_deinit(drv->sock_xmit);
(void) close(drv->route); /* ioctl socket */
(void) close(drv->sock); /* event socket */
+ os_free(drv->event_buf);
os_free(drv);
}
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index fce6efd..0b8eed5 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -7208,6 +7208,22 @@
params->ext_capab_len, params->ext_capab);
}
+ if (params->supp_channels) {
+ wpa_hexdump(MSG_DEBUG, " * supported channels",
+ params->supp_channels, params->supp_channels_len);
+ NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_CHANNELS,
+ params->supp_channels_len, params->supp_channels);
+ }
+
+ if (params->supp_oper_classes) {
+ wpa_hexdump(MSG_DEBUG, " * supported operating classes",
+ params->supp_oper_classes,
+ params->supp_oper_classes_len);
+ NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
+ params->supp_oper_classes_len,
+ params->supp_oper_classes);
+ }
+
os_memset(&upd, 0, sizeof(upd));
upd.mask = sta_flags_nl80211(params->flags);
upd.set = upd.mask;
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 98abd4e..47cbbee 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -179,6 +179,7 @@
eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
sm->num_rounds = 0;
sm->prev_failure = 0;
+ sm->expected_failure = 0;
}
@@ -2046,6 +2047,8 @@
if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
if (eap_get_ext_password(sm, config) < 0)
return NULL;
+ if (hash)
+ *hash = 0;
*len = wpabuf_len(sm->ext_pw_buf);
return wpabuf_head(sm->ext_pw_buf);
}
@@ -2415,3 +2418,9 @@
if (sm->eapol_cb->set_anon_id)
sm->eapol_cb->set_anon_id(sm->eapol_ctx, id, len);
}
+
+
+int eap_peer_was_failure_expected(struct eap_sm *sm)
+{
+ return sm->expected_failure;
+}
diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h
index 711f41f..712e929 100644
--- a/src/eap_peer/eap.h
+++ b/src/eap_peer/eap.h
@@ -320,6 +320,7 @@
struct ext_password_data;
void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext);
void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len);
+int eap_peer_was_failure_expected(struct eap_sm *sm);
#endif /* IEEE8021X_EAPOL */
diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c
index 3b8d803..1b0c562 100644
--- a/src/eap_peer/eap_fast.c
+++ b/src/eap_peer/eap_fast.c
@@ -196,14 +196,22 @@
"workarounds");
}
+ if (!config->pac_file) {
+ wpa_printf(MSG_INFO, "EAP-FAST: No PAC file configured");
+ eap_fast_deinit(sm, data);
+ return NULL;
+ }
+
if (data->use_pac_binary_format &&
eap_fast_load_pac_bin(sm, &data->pac, config->pac_file) < 0) {
+ wpa_printf(MSG_INFO, "EAP-FAST: Failed to load PAC file");
eap_fast_deinit(sm, data);
return NULL;
}
if (!data->use_pac_binary_format &&
eap_fast_load_pac(sm, &data->pac, config->pac_file) < 0) {
+ wpa_printf(MSG_INFO, "EAP-FAST: Failed to load PAC file");
eap_fast_deinit(sm, data);
return NULL;
}
@@ -1047,6 +1055,7 @@
}
wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV "
"- Provisioning completed successfully");
+ sm->expected_failure = 1;
} else {
/*
* This is PAC refreshing, i.e., normal authentication that is
@@ -1244,6 +1253,7 @@
"provisioning completed successfully.");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
+ sm->expected_failure = 1;
} else {
wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication "
"completed successfully.");
diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h
index 9307f3f..8288ba5 100644
--- a/src/eap_peer/eap_i.h
+++ b/src/eap_peer/eap_i.h
@@ -350,6 +350,8 @@
struct wpabuf *ext_pw_buf;
int external_sim;
+
+ unsigned int expected_failure:1;
};
const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len);
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index 05b9851..cbcde7e 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -940,9 +940,15 @@
}
if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
- int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0;
+ enum eapol_supp_result result;
+ if (sm->cb_status == EAPOL_CB_SUCCESS)
+ result = EAPOL_SUPP_RESULT_SUCCESS;
+ else if (eap_peer_was_failure_expected(sm->eap))
+ result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
+ else
+ result = EAPOL_SUPP_RESULT_FAILURE;
sm->cb_status = EAPOL_CB_IN_PROGRESS;
- sm->ctx->cb(sm, success, sm->ctx->cb_ctx);
+ sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
}
}
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index 54e8a27..934eda0 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -63,6 +63,12 @@
struct eapol_sm;
struct wpa_config_blob;
+enum eapol_supp_result {
+ EAPOL_SUPP_RESULT_FAILURE,
+ EAPOL_SUPP_RESULT_SUCCESS,
+ EAPOL_SUPP_RESULT_EXPECTED_FAILURE
+};
+
/**
* struct eapol_ctx - Global (for all networks) EAPOL state machine context
*/
@@ -83,7 +89,7 @@
/**
* cb - Function to be called when EAPOL negotiation has been completed
* @eapol: Pointer to EAPOL state machine data
- * @success: Whether the authentication was completed successfully
+ * @result: Whether the authentication was completed successfully
* @ctx: Pointer to context data (cb_ctx)
*
* This optional callback function will be called when the EAPOL
@@ -91,7 +97,8 @@
* EAPOL state machine to process the key and terminate the EAPOL state
* machine. Currently, this is used only in RSN pre-authentication.
*/
- void (*cb)(struct eapol_sm *eapol, int success, void *ctx);
+ void (*cb)(struct eapol_sm *eapol, enum eapol_supp_result result,
+ void *ctx);
/**
* cb_ctx - Callback context for cb()
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 0e688a9..874f434 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -1037,7 +1037,7 @@
else
freq = dev->listen_freq;
if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa,
- wpabuf_head(conf), wpabuf_len(conf), 0) < 0) {
+ wpabuf_head(conf), wpabuf_len(conf), 200) < 0) {
p2p_dbg(p2p, "Failed to send Action frame");
p2p_go_neg_failed(p2p, dev, -1);
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
@@ -1079,6 +1079,7 @@
return;
}
dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
+ p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
if (msg.dialog_token != dev->dialog_token) {
p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c
index c51620e..915f85e 100644
--- a/src/rsn_supp/preauth.c
+++ b/src/rsn_supp/preauth.c
@@ -70,13 +70,14 @@
}
-static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success,
+static void rsn_preauth_eapol_cb(struct eapol_sm *eapol,
+ enum eapol_supp_result result,
void *ctx)
{
struct wpa_sm *sm = ctx;
u8 pmk[PMK_LEN];
- if (success) {
+ if (result == EAPOL_SUPP_RESULT_SUCCESS) {
int res, pmk_len;
pmk_len = PMK_LEN;
res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
@@ -100,13 +101,14 @@
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"RSN: failed to get master session key from "
"pre-auth EAPOL state machines");
- success = 0;
+ result = EAPOL_SUPP_RESULT_FAILURE;
}
}
wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
MACSTR " %s", MAC2STR(sm->preauth_bssid),
- success ? "completed successfully" : "failed");
+ result == EAPOL_SUPP_RESULT_SUCCESS ? "completed successfully" :
+ "failed");
rsn_preauth_deinit(sm);
rsn_preauth_candidate_process(sm);
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index efc6431..8a978f7 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -136,6 +136,12 @@
u8 *ext_capab;
size_t ext_capab_len;
+
+ u8 *supp_channels;
+ size_t supp_channels_len;
+
+ u8 *supp_oper_classes;
+ size_t supp_oper_classes_len;
};
@@ -633,6 +639,10 @@
peer->vht_capabilities = NULL;
os_free(peer->ext_capab);
peer->ext_capab = NULL;
+ os_free(peer->supp_channels);
+ peer->supp_channels = NULL;
+ os_free(peer->supp_oper_classes);
+ peer->supp_oper_classes = NULL;
peer->rsnie_i_len = peer->rsnie_p_len = 0;
peer->cipher = 0;
peer->tpk_set = peer->tpk_success = 0;
@@ -1456,6 +1466,58 @@
}
+static int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde,
+ struct wpa_tdls_peer *peer)
+{
+ if (!kde->supp_channels) {
+ wpa_printf(MSG_DEBUG, "TDLS: No supported channels received");
+ return 0;
+ }
+
+ if (!peer->supp_channels ||
+ peer->supp_channels_len < kde->supp_channels_len) {
+ os_free(peer->supp_channels);
+ peer->supp_channels = os_zalloc(kde->supp_channels_len);
+ if (peer->supp_channels == NULL)
+ return -1;
+ }
+
+ peer->supp_channels_len = kde->supp_channels_len;
+
+ os_memcpy(peer->supp_channels, kde->supp_channels,
+ peer->supp_channels_len);
+ wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels",
+ (u8 *) peer->supp_channels, peer->supp_channels_len);
+ return 0;
+}
+
+
+static int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde,
+ struct wpa_tdls_peer *peer)
+{
+ if (!kde->supp_oper_classes) {
+ wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received");
+ return 0;
+ }
+
+ if (!peer->supp_oper_classes ||
+ peer->supp_oper_classes_len < kde->supp_oper_classes_len) {
+ os_free(peer->supp_oper_classes);
+ peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len);
+ if (peer->supp_oper_classes == NULL)
+ return -1;
+ }
+
+ peer->supp_oper_classes_len = kde->supp_oper_classes_len;
+ os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes,
+ peer->supp_oper_classes_len);
+ wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes",
+ (u8 *) peer->supp_oper_classes,
+ peer->supp_oper_classes_len);
+ return 0;
+}
+
+
static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len)
{
@@ -1568,6 +1630,12 @@
if (copy_peer_ext_capab(&kde, peer) < 0)
goto error;
+ if (copy_peer_supp_channels(&kde, peer) < 0)
+ goto error;
+
+ if (copy_peer_supp_oper_classes(&kde, peer) < 0)
+ goto error;
+
peer->qos_info = kde.qosinfo;
peer->aid = kde.aid;
@@ -1761,7 +1829,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, 0, NULL, 0, NULL, NULL, 0,
- NULL, 0);
+ NULL, 0, NULL, 0, NULL, 0);
peer->tpk_in_progress = 1;
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
@@ -1810,7 +1878,11 @@
peer->ht_capabilities,
peer->vht_capabilities,
peer->qos_info, peer->ext_capab,
- peer->ext_capab_len) < 0)
+ peer->ext_capab_len,
+ peer->supp_channels,
+ peer->supp_channels_len,
+ peer->supp_oper_classes,
+ peer->supp_oper_classes_len) < 0)
return -1;
if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
@@ -1938,6 +2010,12 @@
if (copy_peer_ext_capab(&kde, peer) < 0)
goto error;
+ if (copy_peer_supp_channels(&kde, peer) < 0)
+ goto error;
+
+ if (copy_peer_supp_oper_classes(&kde, peer) < 0)
+ goto error;
+
peer->qos_info = kde.qosinfo;
peer->aid = kde.aid;
@@ -2289,7 +2367,7 @@
/* add the peer to the driver as a "setup in progress" peer */
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
- NULL, 0);
+ NULL, 0, NULL, 0, NULL, 0);
peer->tpk_in_progress = 1;
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index e189a58..9884ce1 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -62,7 +62,10 @@
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
u8 qosinfo, const u8 *ext_capab,
- size_t ext_capab_len);
+ size_t ext_capab_len, const u8 *supp_channels,
+ size_t supp_channels_len,
+ const u8 *supp_oper_classes,
+ size_t supp_oper_classes_len);
#endif /* CONFIG_TDLS */
void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck,
const u8 *replay_ctr);
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 0e0d373..cad6c8d 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -286,14 +286,21 @@
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
- u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
+ u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
+ const u8 *supp_channels, size_t supp_channels_len,
+ const u8 *supp_oper_classes,
+ size_t supp_oper_classes_len)
{
if (sm->ctx->tdls_peer_addset)
return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
aid, capability, supp_rates,
supp_rates_len, ht_capab,
vht_capab, qosinfo,
- ext_capab, ext_capab_len);
+ ext_capab, ext_capab_len,
+ supp_channels,
+ supp_channels_len,
+ supp_oper_classes,
+ supp_oper_classes_len);
return -1;
}
#endif /* CONFIG_TDLS */
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 50b9272..ab8d104 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -434,6 +434,12 @@
ie->vht_capabilities_len = pos[1];
} else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
ie->qosinfo = pos[2];
+ } else if (*pos == WLAN_EID_SUPPORTED_CHANNELS) {
+ ie->supp_channels = pos + 2;
+ ie->supp_channels_len = pos[1];
+ } else if (*pos == WLAN_EID_SUPPORTED_OPERATING_CLASSES) {
+ ie->supp_oper_classes = pos + 2;
+ ie->supp_oper_classes_len = pos[1];
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, end, ie);
if (ret < 0)
diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h
index 2c78801..0375767 100644
--- a/src/rsn_supp/wpa_ie.h
+++ b/src/rsn_supp/wpa_ie.h
@@ -53,6 +53,10 @@
size_t ht_capabilities_len;
const u8 *vht_capabilities;
size_t vht_capabilities_len;
+ const u8 *supp_channels;
+ size_t supp_channels_len;
+ const u8 *supp_oper_classes;
+ size_t supp_oper_classes_len;
u8 qosinfo;
u16 aid;
};