Cumulative patch from commit 12c1fdf19a721aaf29e1c77d63445c7f5b8c61c0
12c1fdf P2P: Update peer listen channel from Probe Request frames
a805731 P2P: Abort ongoing scan when p2p_find is stopped
7441698 nl80211: Abort an ongoing scan upon scan timeout indication
1446afc wpa_supplicant: Handle EVENT_SCAN_RESULTS when an interface is disabled
d14e63a WNM: Do not scan based on malformed BSS Transition Management Request
f420577 WNM: Fix candidates count in BSS Transition Management Request
3c58df7 wpa_cli: Support running action script on global control interface
b8f02d8 EAP-PWD peer: Fix possible memory leak on error path
8f38eed Android: Remove superfluous OpenSSL include paths
cbf8d18 HS 2.0R2: Clear fetch_anqp_in_progress if fopen fails
4a6e9e5 Fix CONFIG_WPA_TRACE=y compilation without CONFIG_WPA_TRACE_BFD=y
2bf9a53 Add EAP-AKA' and EAP-pwd to wpa_supplicant README
4196c08 Update notes about OpenSSL versions
5d7b1a3 Fix some typos in wpa_supplicant README files
4194fee README-P2P: Fix a typo
c58eed6 P2P: Add Dev Info attribute to Probe Request frames in 60 GHz
2b6e9f9 wpa_supplicant: Expose wpas_get_bands() and related API
94ad3c3 P2P: Change order of P2P IE and frequencies set up
61697c7 Android: Allow wpa_supplicant to write files to osu-info dir
0147afa FST: Enlarge State Transition Timeout (STT)
e1d00d4 Add error handling for offloaded ACS with vendor command failures
bef5e9a Fix scan rescheduling from wpas_stop_pno to check postponed case
b9ca12a nl80211: Add more address fields into RX frame debug message
debde14 RADIUS: Add Acct-Delay-Time into accounting messages
669b532 RADIUS: Update full message for interim accounting updates
251953b Document nas_identifier requirements for RADIUS accounting
902c07a Replace hostapd_mac_comp_empty() with is_zero_ether_addr()
5aef495 VLAN: Avoid use of libnl cache
732b1d2 nl80211: Clean up ifidx properly if interface in a bridge is removed
170c545 FT: Check destination MAC address on RRB receive
57b2c91 RADIUS: Allow RADIUS server to provide PSK instead of passphrase
d8912fd Cache hashed passphrase in RADIUS-based PSK delivery
f8e09bc Defer passphrase-to-PSK hashing out of 802.11 authentication ACL check
cc9c805 VLAN: Use stack instead of heap allocation for new interface name
d48d1b8 FT: Use BSSID as r1_key_holder if no value is configured
71456db FT: Check hapd->wpa_auth before RRB internal delivery
0270bde FT: Fix R0KH-R1KH protocol data length values
96a26ab P2P: Support dedicated P2P_DEVICE without separate group interface
ba307f8 P2P: Add a separate pointer to the P2P Device instance
e040197 GAS client: Make PMF check on RX more consistent
0645492 WNM: Optimize a single BSS transition management candidate scan
eb20cea nl80211: Add an option to specify the BSSID to scan for
adf0478 AP: Store STA supported operating classes information
Change-Id: If0ce28aae5591be783c38e5b60f7f9ff0fb9f8f2
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/accounting.c b/src/ap/accounting.c
index 9357a46..854174e 100644
--- a/src/ap/accounting.c
+++ b/src/ap/accounting.c
@@ -152,6 +152,15 @@
goto fail;
}
+ /*
+ * Add Acct-Delay-Time with zero value for the first transmission. This
+ * will be updated within radius_client.c when retransmitting the frame.
+ */
+ if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_DELAY_TIME, 0)) {
+ wpa_printf(MSG_INFO, "Could not add Acct-Delay-Time");
+ goto fail;
+ }
+
return msg;
fail:
@@ -450,6 +459,63 @@
}
+static void accounting_interim_error_cb(const u8 *addr, void *ctx)
+{
+ struct hostapd_data *hapd = ctx;
+ struct sta_info *sta;
+ unsigned int i, wait_time;
+ int res;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta)
+ return;
+ sta->acct_interim_errors++;
+ if (sta->acct_interim_errors > 10 /* RADIUS_CLIENT_MAX_RETRIES */) {
+ wpa_printf(MSG_DEBUG,
+ "Interim RADIUS accounting update failed for " MACSTR
+ " - too many errors, abandon this interim accounting update",
+ MAC2STR(addr));
+ sta->acct_interim_errors = 0;
+ /* Next update will be tried after normal update interval */
+ return;
+ }
+
+ /*
+ * Use a shorter update interval as an improved retransmission mechanism
+ * for failed interim accounting updates. This allows the statistics to
+ * be updated for each retransmission.
+ *
+ * RADIUS client code has already waited RADIUS_CLIENT_FIRST_WAIT.
+ * Schedule the first retry attempt immediately and every following one
+ * with exponential backoff.
+ */
+ if (sta->acct_interim_errors == 1) {
+ wait_time = 0;
+ } else {
+ wait_time = 3; /* RADIUS_CLIENT_FIRST_WAIT */
+ for (i = 1; i < sta->acct_interim_errors; i++)
+ wait_time *= 2;
+ }
+ res = eloop_deplete_timeout(wait_time, 0, accounting_interim_update,
+ hapd, sta);
+ if (res == 1)
+ wpa_printf(MSG_DEBUG,
+ "Interim RADIUS accounting update failed for " MACSTR
+ " (error count: %u) - schedule next update in %u seconds",
+ MAC2STR(addr), sta->acct_interim_errors, wait_time);
+ else if (res == 0)
+ wpa_printf(MSG_DEBUG,
+ "Interim RADIUS accounting update failed for " MACSTR
+ " (error count: %u)", MAC2STR(addr),
+ sta->acct_interim_errors);
+ else
+ wpa_printf(MSG_DEBUG,
+ "Interim RADIUS accounting update failed for " MACSTR
+ " (error count: %u) - no timer found", MAC2STR(addr),
+ sta->acct_interim_errors);
+}
+
+
/**
* accounting_init: Initialize accounting
* @hapd: hostapd BSS data
@@ -464,6 +530,8 @@
if (radius_client_register(hapd->radius, RADIUS_ACCT,
accounting_receive, hapd))
return -1;
+ radius_client_set_interim_error_cb(hapd->radius,
+ accounting_interim_error_cb, hapd);
accounting_report_state(hapd, 1);
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 477ea5b..66b843c 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -202,13 +202,6 @@
}
-int hostapd_mac_comp_empty(const void *a)
-{
- macaddr empty = { 0 };
- return os_memcmp(a, empty, sizeof(macaddr));
-}
-
-
static int hostapd_config_read_wpa_psk(const char *fname,
struct hostapd_ssid *ssid)
{
@@ -790,7 +783,7 @@
return -1;
}
- if (full_config && hostapd_mac_comp_empty(bss->bssid) != 0) {
+ if (full_config && !is_zero_ether_addr(bss->bssid)) {
size_t i;
for (i = 0; i < conf->num_bss; i++) {
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 9afca48..f19cac6 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -128,9 +128,14 @@
};
#define PMK_LEN 32
+#define MIN_PASSPHRASE_LEN 8
+#define MAX_PASSPHRASE_LEN 63
struct hostapd_sta_wpa_psk_short {
struct hostapd_sta_wpa_psk_short *next;
+ unsigned int is_passphrase:1;
u8 psk[PMK_LEN];
+ char passphrase[MAX_PASSPHRASE_LEN + 1];
+ int ref; /* (number of references held) - 1 */
};
struct hostapd_wpa_psk {
@@ -689,7 +694,6 @@
int hostapd_mac_comp(const void *a, const void *b);
-int hostapd_mac_comp_empty(const void *a);
struct hostapd_config * hostapd_config_defaults(void);
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index a95230e..9f249d7 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -166,6 +166,15 @@
if (res >= 0)
len += res;
+ if (sta->supp_op_classes &&
+ buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
+ len += os_snprintf(buf + len, buflen - len, "supp_op_classes=");
+ len += wpa_snprintf_hex(buf + len, buflen - len,
+ sta->supp_op_classes + 1,
+ sta->supp_op_classes[0]);
+ len += os_snprintf(buf + len, buflen - len, "\n");
+ }
+
return len;
}
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 702ee64..f54d1ad 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -176,6 +176,9 @@
mbo_ap_check_sta_assoc(hapd, sta, &elems);
+ ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
+ elems.supp_op_classes_len);
+
if (hapd->conf->wpa) {
if (ie == NULL || ielen == 0) {
#ifdef CONFIG_WPS
@@ -567,6 +570,7 @@
struct acs_selected_channels *acs_res)
{
int ret, i;
+ int err = 0;
if (hapd->iconf->channel) {
wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
@@ -588,7 +592,8 @@
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver selected to bad hw_mode");
- return;
+ err = 1;
+ goto out;
}
}
@@ -598,7 +603,8 @@
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver switched to bad channel");
- return;
+ err = 1;
+ goto out;
}
hapd->iconf->channel = acs_res->pri_channel;
@@ -612,7 +618,8 @@
hapd->iconf->secondary_channel = 1;
else {
wpa_printf(MSG_ERROR, "Invalid secondary channel!");
- return;
+ err = 1;
+ goto out;
}
if (hapd->iface->conf->ieee80211ac) {
@@ -641,7 +648,8 @@
}
}
- ret = hostapd_acs_completed(hapd->iface, 0);
+out:
+ ret = hostapd_acs_completed(hapd->iface, err);
if (ret) {
wpa_printf(MSG_ERROR,
"ACS: Possibly channel configuration is invalid");
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index dd2dc17..303786b 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -521,7 +521,7 @@
/* Determine the bits necessary to any configured BSSIDs,
if they are higher than the number of BSSIDs. */
for (j = 0; j < iface->conf->num_bss; j++) {
- if (hostapd_mac_comp_empty(iface->conf->bss[j]->bssid) == 0) {
+ if (is_zero_ether_addr(iface->conf->bss[j]->bssid)) {
if (j)
auto_addr++;
continue;
@@ -905,7 +905,7 @@
hapd->started = 1;
if (!first || first == -1) {
- if (hostapd_mac_comp_empty(conf->bssid) == 0) {
+ if (is_zero_ether_addr(conf->bssid)) {
/* Allocate the next available BSSID. */
do {
inc_byte_array(hapd->own_addr, ETH_ALEN);
@@ -940,6 +940,11 @@
if (conf->wmm_enabled < 0)
conf->wmm_enabled = hapd->iconf->ieee80211n;
+#ifdef CONFIG_IEEE80211R
+ if (is_zero_ether_addr(conf->r1_key_holder))
+ os_memcpy(conf->r1_key_holder, hapd->own_addr, ETH_ALEN);
+#endif /* CONFIG_IEEE80211R */
+
#ifdef CONFIG_MESH
if (hapd->iface->mconf == NULL)
flush_old_stations = 0;
@@ -1626,7 +1631,7 @@
} while (j-- > 0);
goto fail;
}
- if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
+ if (is_zero_ether_addr(hapd->conf->bssid))
prev_addr = hapd->own_addr;
}
hapd = iface->bss[0];
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 84e6e15..b36e68d 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1726,6 +1726,9 @@
}
#endif /* CONFIG_MBO */
+ ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
+ elems.supp_op_classes_len);
+
return WLAN_STATUS_SUCCESS;
}
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 78db204..1a96b33 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -130,4 +130,8 @@
#endif /* CONFIG_MBO */
+void ap_copy_sta_supp_op_classes(struct sta_info *sta,
+ const u8 *supp_op_classes,
+ size_t supp_op_classes_len);
+
#endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index f280709..9609152 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -15,7 +15,6 @@
#include "utils/common.h"
#include "utils/eloop.h"
-#include "crypto/sha1.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "hostapd.h"
@@ -77,23 +76,13 @@
static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
struct hostapd_sta_wpa_psk_short *src)
{
- struct hostapd_sta_wpa_psk_short **copy_to;
- struct hostapd_sta_wpa_psk_short *copy_from;
+ if (!psk)
+ return;
- /* Copy PSK linked list */
- copy_to = psk;
- copy_from = src;
- while (copy_from && copy_to) {
- *copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
- if (*copy_to == NULL)
- break;
- os_memcpy(*copy_to, copy_from,
- sizeof(struct hostapd_sta_wpa_psk_short));
- copy_from = copy_from->next;
- copy_to = &((*copy_to)->next);
- }
- if (copy_to)
- *copy_to = NULL;
+ if (src)
+ src->ref++;
+
+ *psk = src;
}
@@ -443,7 +432,7 @@
struct hostapd_cached_radius_acl *cache)
{
int passphraselen;
- char *passphrase, *strpassphrase;
+ char *passphrase;
size_t i;
struct hostapd_sta_wpa_psk_short *psk;
@@ -460,23 +449,40 @@
*/
if (passphrase == NULL)
break;
+
+ /*
+ * Passphase should be 8..63 chars (to be hashed with SSID)
+ * or 64 chars hex string (no separate hashing with SSID).
+ */
+
+ if (passphraselen < MIN_PASSPHRASE_LEN ||
+ passphraselen > MAX_PASSPHRASE_LEN + 1)
+ continue;
+
/*
* passphrase does not contain the NULL termination.
* Add it here as pbkdf2_sha1() requires it.
*/
- strpassphrase = os_zalloc(passphraselen + 1);
psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
- if (strpassphrase && psk) {
- os_memcpy(strpassphrase, passphrase, passphraselen);
- pbkdf2_sha1(strpassphrase,
- hapd->conf->ssid.ssid,
- hapd->conf->ssid.ssid_len, 4096,
- psk->psk, PMK_LEN);
+ if (psk) {
+ if ((passphraselen == MAX_PASSPHRASE_LEN + 1) &&
+ (hexstr2bin(passphrase, psk->psk, PMK_LEN) < 0)) {
+ hostapd_logger(hapd, cache->addr,
+ HOSTAPD_MODULE_RADIUS,
+ HOSTAPD_LEVEL_WARNING,
+ "invalid hex string (%d chars) in Tunnel-Password",
+ passphraselen);
+ goto skip;
+ } else if (passphraselen <= MAX_PASSPHRASE_LEN) {
+ os_memcpy(psk->passphrase, passphrase,
+ passphraselen);
+ psk->is_passphrase = 1;
+ }
psk->next = cache->psk;
cache->psk = psk;
psk = NULL;
}
- os_free(strpassphrase);
+skip:
os_free(psk);
os_free(passphrase);
}
@@ -671,6 +677,12 @@
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
{
+ if (psk && psk->ref) {
+ /* This will be freed when the last reference is dropped. */
+ psk->ref--;
+ return;
+ }
+
while (psk) {
struct hostapd_sta_wpa_psk_short *prev = psk;
psk = psk->next;
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 1077635..af858f0 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -558,3 +558,20 @@
}
#endif /* CONFIG_MBO */
+
+
+void ap_copy_sta_supp_op_classes(struct sta_info *sta,
+ const u8 *supp_op_classes,
+ size_t supp_op_classes_len)
+{
+ if (!supp_op_classes)
+ return;
+ os_free(sta->supp_op_classes);
+ sta->supp_op_classes = os_malloc(1 + supp_op_classes_len);
+ if (!sta->supp_op_classes)
+ return;
+
+ sta->supp_op_classes[0] = supp_op_classes_len;
+ os_memcpy(sta->supp_op_classes + 1, supp_op_classes,
+ supp_op_classes_len);
+}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 60058e4..c36842b 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -328,6 +328,7 @@
#endif /* CONFIG_SAE */
mbo_ap_sta_free(sta);
+ os_free(sta->supp_op_classes);
os_free(sta);
}
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 08e795e..cd89e99 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -118,6 +118,7 @@
int acct_session_started;
int acct_terminate_cause; /* Acct-Terminate-Cause */
int acct_interim_interval; /* Acct-Interim-Interval */
+ unsigned int acct_interim_errors;
/* For extending 32-bit driver counters to 64-bit counters */
u32 last_rx_bytes_hi;
@@ -190,6 +191,9 @@
* enum mbo_cellular_capa values */
struct mbo_non_pref_chan_info *non_pref_chan;
#endif /* CONFIG_MBO */
+
+ u8 *supp_op_classes; /* Supported Operating Classes element, if
+ * received, starting from the Length field */
};
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 8eab6cb..45d1a1c 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -1119,25 +1119,23 @@
int vlan_id,
struct vlan_description *vlan_desc)
{
- struct hostapd_vlan *n = NULL;
- char *ifname, *pos;
+ struct hostapd_vlan *n;
+ char ifname[IFNAMSIZ + 1], *pos;
if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
return NULL;
wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
__func__, vlan_id, vlan->ifname);
- ifname = os_strdup(vlan->ifname);
- if (ifname == NULL)
- return NULL;
+ os_strlcpy(ifname, vlan->ifname, sizeof(ifname));
pos = os_strchr(ifname, '#');
if (pos == NULL)
- goto free_ifname;
+ return NULL;
*pos++ = '\0';
n = os_zalloc(sizeof(*n));
if (n == NULL)
- goto free_ifname;
+ return NULL;
n->vlan_id = vlan_id;
if (vlan_desc)
@@ -1155,11 +1153,8 @@
hapd->conf->vlan = n->next;
os_free(n);
n = NULL;
- goto free_ifname;
}
-free_ifname:
- os_free(ifname);
return n;
}
diff --git a/src/ap/vlan_util.c b/src/ap/vlan_util.c
index d4e0efb..313d89f 100644
--- a/src/ap/vlan_util.c
+++ b/src/ap/vlan_util.c
@@ -33,7 +33,6 @@
{
int err, ret = -1;
struct nl_sock *handle = NULL;
- struct nl_cache *cache = NULL;
struct rtnl_link *rlink = NULL;
int if_idx = 0;
@@ -65,22 +64,19 @@
goto vlan_add_error;
}
- err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
+ err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
if (err < 0) {
- cache = NULL;
- wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
- nl_geterror(err));
- goto vlan_add_error;
- }
-
- if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
/* link does not exist */
wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
if_name);
goto vlan_add_error;
}
+ if_idx = rtnl_link_get_ifindex(rlink);
+ rtnl_link_put(rlink);
+ rlink = NULL;
- if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
+ err = rtnl_link_get_kernel(handle, 0, vlan_if_name, &rlink);
+ if (err >= 0) {
/* link does exist */
rtnl_link_put(rlink);
rlink = NULL;
@@ -127,8 +123,6 @@
vlan_add_error:
if (rlink)
rtnl_link_put(rlink);
- if (cache)
- nl_cache_free(cache);
if (handle)
nl_socket_free(handle);
return ret;
@@ -139,7 +133,6 @@
{
int err, ret = -1;
struct nl_sock *handle = NULL;
- struct nl_cache *cache = NULL;
struct rtnl_link *rlink = NULL;
wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
@@ -157,15 +150,8 @@
goto vlan_rem_error;
}
- err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
+ err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
if (err < 0) {
- cache = NULL;
- wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
- nl_geterror(err));
- goto vlan_rem_error;
- }
-
- if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
/* link does not exist */
wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
if_name);
@@ -184,8 +170,6 @@
vlan_rem_error:
if (rlink)
rtnl_link_put(rlink);
- if (cache)
- nl_cache_free(cache);
if (handle)
nl_socket_free(handle);
return ret;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index b303324..2b60114 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -42,10 +42,11 @@
#define FT_PACKET_R0KH_R1KH_RESP 201
#define FT_PACKET_R0KH_R1KH_PUSH 202
-#define FT_R0KH_R1KH_PULL_DATA_LEN 44
-#define FT_R0KH_R1KH_RESP_DATA_LEN 76
-#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
#define FT_R0KH_R1KH_PULL_NONCE_LEN 16
+#define FT_R0KH_R1KH_PULL_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
+ WPA_PMK_NAME_LEN + FT_R1KH_ID_LEN + \
+ ETH_ALEN)
+#define FT_R0KH_R1KH_PULL_PAD_LEN ((8 - FT_R0KH_R1KH_PULL_DATA_LEN % 8) % 8)
struct ft_r0kh_r1kh_pull_frame {
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
@@ -57,14 +58,18 @@
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
u8 r1kh_id[FT_R1KH_ID_LEN];
u8 s1kh_id[ETH_ALEN];
- u8 pad[4]; /* 8-octet boundary for AES key wrap */
+ u8 pad[FT_R0KH_R1KH_PULL_PAD_LEN]; /* 8-octet boundary for AES block */
u8 key_wrap_extra[8];
} STRUCT_PACKED;
+#define FT_R0KH_R1KH_RESP_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
+ FT_R1KH_ID_LEN + ETH_ALEN + PMK_LEN + \
+ WPA_PMK_NAME_LEN + 2)
+#define FT_R0KH_R1KH_RESP_PAD_LEN ((8 - FT_R0KH_R1KH_RESP_DATA_LEN % 8) % 8)
struct ft_r0kh_r1kh_resp_frame {
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
- le16 data_length; /* little endian length of data (76) */
+ le16 data_length; /* little endian length of data (78) */
u8 ap_address[ETH_ALEN];
u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */
@@ -73,14 +78,18 @@
u8 pmk_r1[PMK_LEN];
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
le16 pairwise;
- u8 pad[2]; /* 8-octet boundary for AES key wrap */
+ u8 pad[FT_R0KH_R1KH_RESP_PAD_LEN]; /* 8-octet boundary for AES block */
u8 key_wrap_extra[8];
} STRUCT_PACKED;
+#define FT_R0KH_R1KH_PUSH_DATA_LEN (4 + FT_R1KH_ID_LEN + ETH_ALEN + \
+ WPA_PMK_NAME_LEN + PMK_LEN + \
+ WPA_PMK_NAME_LEN + 2)
+#define FT_R0KH_R1KH_PUSH_PAD_LEN ((8 - FT_R0KH_R1KH_PUSH_DATA_LEN % 8) % 8)
struct ft_r0kh_r1kh_push_frame {
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
- le16 data_length; /* little endian length of data (88) */
+ le16 data_length; /* little endian length of data (82) */
u8 ap_address[ETH_ALEN];
/* Encrypted with AES key-wrap */
@@ -92,7 +101,7 @@
u8 pmk_r1[PMK_LEN];
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
le16 pairwise;
- u8 pad[6]; /* 8-octet boundary for AES key wrap */
+ u8 pad[FT_R0KH_R1KH_PUSH_PAD_LEN]; /* 8-octet boundary for AES block */
u8 key_wrap_extra[8];
} STRUCT_PACKED;
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index ffd0790..5fe0987 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -12,6 +12,7 @@
#include "common/ieee802_11_defs.h"
#include "common/sae.h"
#include "common/wpa_ctrl.h"
+#include "crypto/sha1.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h"
#include "eap_server/eap.h"
@@ -246,6 +247,13 @@
struct hostapd_sta_wpa_psk_short *pos;
psk = sta->psk->psk;
for (pos = sta->psk; pos; pos = pos->next) {
+ if (pos->is_passphrase) {
+ pbkdf2_sha1(pos->passphrase,
+ hapd->conf->ssid.ssid,
+ hapd->conf->ssid.ssid_len, 4096,
+ pos->psk, PMK_LEN);
+ pos->is_passphrase = 0;
+ }
if (pos->psk == prev_psk) {
psk = pos->next ? pos->next->psk : NULL;
break;
@@ -413,6 +421,8 @@
hapd = iface->bss[j];
if (hapd == idata->src_hapd)
continue;
+ if (!hapd->wpa_auth)
+ continue;
if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) {
wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to "
"locally managed BSS " MACSTR "@%s -> "
@@ -563,6 +573,9 @@
ethhdr = (struct l2_ethhdr *) buf;
wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
+ if (!is_multicast_ether_addr(ethhdr->h_dest) &&
+ os_memcmp(hapd->own_addr, ethhdr->h_dest, ETH_ALEN) != 0)
+ return;
wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
len - sizeof(*ethhdr));
}
diff --git a/src/common/defs.h b/src/common/defs.h
index b3ac4e8..6ef929c 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -335,4 +335,10 @@
WPA_SETBAND_2G
};
+enum wpa_radio_work_band {
+ BAND_2_4_GHZ = BIT(0),
+ BAND_5_GHZ = BIT(1),
+ BAND_60_GHZ = BIT(2),
+};
+
#endif /* DEFS_H */
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 2e503b9..5b05b68 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -371,6 +371,10 @@
elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
elems->mb_ies.nof_ies++;
break;
+ case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
+ elems->supp_op_classes = pos;
+ elems->supp_op_classes_len = elen;
+ break;
default:
unknown++;
if (!show_errors)
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 3a3dd4d..d9fecd6 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -62,6 +62,7 @@
const u8 *ampe;
const u8 *mic;
const u8 *pref_freq_list;
+ const u8 *supp_op_classes;
u8 ssid_len;
u8 supp_rates_len;
@@ -92,6 +93,8 @@
u8 ampe_len;
u8 mic_len;
u8 pref_freq_list_len;
+ u8 supp_op_classes_len;
+
struct mb_ies_info mb_ies;
};
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2315226..642276c 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -439,6 +439,15 @@
*/
unsigned int sched_scan_plans_num;
+ /**
+ * bssid - Specific BSSID to scan for
+ *
+ * This optional parameter can be used to replace the default wildcard
+ * BSSID with a specific BSSID to scan for if results are needed from
+ * only a single BSS.
+ */
+ const u8 *bssid;
+
/*
* NOTE: Whenever adding new parameters here, please make sure
* wpa_scan_clone_params() and wpa_scan_free_params() get updated with
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5fec430..570dee6 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -181,9 +181,14 @@
static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
int report);
-static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
-static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
-static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
+#define IFIDX_ANY -1
+
+static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason);
+static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason);
+static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason);
static int nl80211_set_channel(struct i802_bss *bss,
struct hostapd_freq_params *freq, int set_chan);
@@ -883,7 +888,7 @@
dl_list_for_each(drv, &global->interfaces,
struct wpa_driver_nl80211_data, list) {
if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
- have_ifidx(drv, idx))
+ have_ifidx(drv, idx, IFIDX_ANY))
return drv;
}
return NULL;
@@ -1062,7 +1067,7 @@
}
wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
brid, namebuf);
- add_ifidx(drv, brid);
+ add_ifidx(drv, brid, ifi->ifi_index);
for (bss = drv->first_bss; bss; bss = bss->next) {
if (os_strcmp(ifname, bss->ifname) == 0) {
@@ -1149,7 +1154,7 @@
"nl80211: Remove ifindex %u for bridge %s",
brid, namebuf);
}
- del_ifidx(drv, brid);
+ del_ifidx(drv, brid, ifi->ifi_index);
}
}
@@ -1716,6 +1721,7 @@
drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
drv->if_indices = drv->default_if_indices;
+ drv->if_indices_reason = drv->default_if_indices_reason;
drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
if (!drv->first_bss) {
@@ -2390,6 +2396,9 @@
if (drv->if_indices != drv->default_if_indices)
os_free(drv->if_indices);
+ if (drv->if_indices_reason != drv->default_if_indices_reason)
+ os_free(drv->if_indices_reason);
+
if (drv->disabled_11b_rates)
nl80211_disable_11b_rates(drv, drv->ifindex, 0);
@@ -4069,7 +4078,11 @@
/* stop listening for EAPOL on this interface */
dl_list_for_each(drv2, &drv->global->interfaces,
struct wpa_driver_nl80211_data, list)
- del_ifidx(drv2, ifidx);
+ {
+ del_ifidx(drv2, ifidx, IFIDX_ANY);
+ /* Remove all bridges learned for this iface */
+ del_ifidx(drv2, IFIDX_ANY, ifidx);
+ }
msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
@@ -4177,7 +4190,7 @@
iftype == NL80211_IFTYPE_WDS ||
iftype == NL80211_IFTYPE_MONITOR) {
/* start listening for EAPOL on this interface */
- add_ifidx(drv, ifidx);
+ add_ifidx(drv, ifidx, IFIDX_ANY);
}
if (addr && iftype != NL80211_IFTYPE_MONITOR &&
@@ -5635,7 +5648,9 @@
for (i = 0; i < drv->num_if_indices; i++) {
if (!drv->if_indices[i])
continue;
- res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]);
+ res = os_snprintf(pos, end - pos, " %d(%d)",
+ drv->if_indices[i],
+ drv->if_indices_reason[i]);
if (os_snprintf_error(end - pos, res))
break;
pos += res;
@@ -5647,14 +5662,16 @@
}
-static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason)
{
int i;
- int *old;
+ int *old, *old_reason;
- wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
- ifidx);
- if (have_ifidx(drv, ifidx)) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Add own interface ifindex %d (ifidx_reason %d)",
+ ifidx, ifidx_reason);
+ if (have_ifidx(drv, ifidx, ifidx_reason)) {
wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
ifidx);
return;
@@ -5662,6 +5679,7 @@
for (i = 0; i < drv->num_if_indices; i++) {
if (drv->if_indices[i] == 0) {
drv->if_indices[i] = ifidx;
+ drv->if_indices_reason[i] = ifidx_reason;
dump_ifidx(drv);
return;
}
@@ -5672,32 +5690,57 @@
else
old = NULL;
+ if (drv->if_indices_reason != drv->default_if_indices_reason)
+ old_reason = drv->if_indices_reason;
+ else
+ old_reason = NULL;
+
drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
sizeof(int));
+ drv->if_indices_reason = os_realloc_array(old_reason,
+ drv->num_if_indices + 1,
+ sizeof(int));
if (!drv->if_indices) {
if (!old)
drv->if_indices = drv->default_if_indices;
else
drv->if_indices = old;
+ }
+ if (!drv->if_indices_reason) {
+ if (!old_reason)
+ drv->if_indices_reason = drv->default_if_indices_reason;
+ else
+ drv->if_indices = old_reason;
+ }
+ if (!drv->if_indices || !drv->if_indices_reason) {
wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
"interfaces");
wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
return;
- } else if (!old)
+ }
+ if (!old)
os_memcpy(drv->if_indices, drv->default_if_indices,
sizeof(drv->default_if_indices));
+ if (!old_reason)
+ os_memcpy(drv->if_indices_reason,
+ drv->default_if_indices_reason,
+ sizeof(drv->default_if_indices_reason));
drv->if_indices[drv->num_if_indices] = ifidx;
+ drv->if_indices_reason[drv->num_if_indices] = ifidx_reason;
drv->num_if_indices++;
dump_ifidx(drv);
}
-static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason)
{
int i;
for (i = 0; i < drv->num_if_indices; i++) {
- if (drv->if_indices[i] == ifidx) {
+ if ((drv->if_indices[i] == ifidx || ifidx == IFIDX_ANY) &&
+ (drv->if_indices_reason[i] == ifidx_reason ||
+ ifidx_reason == IFIDX_ANY)) {
drv->if_indices[i] = 0;
break;
}
@@ -5706,12 +5749,15 @@
}
-static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason)
{
int i;
for (i = 0; i < drv->num_if_indices; i++)
- if (drv->if_indices[i] == ifidx)
+ if (drv->if_indices[i] == ifidx &&
+ (drv->if_indices_reason[i] == ifidx_reason ||
+ ifidx_reason == IFIDX_ANY))
return 1;
return 0;
@@ -5776,7 +5822,7 @@
return;
}
- if (have_ifidx(drv, lladdr.sll_ifindex))
+ if (have_ifidx(drv, lladdr.sll_ifindex, IFIDX_ANY))
drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
}
@@ -5803,7 +5849,7 @@
}
bss->added_bridge = 1;
br_ifindex = if_nametoindex(brname);
- add_ifidx(drv, br_ifindex);
+ add_ifidx(drv, br_ifindex, drv->ifindex);
}
bss->br_ifindex = br_ifindex;
@@ -5865,7 +5911,7 @@
wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in master %s",
params->ifname, master_ifname);
/* start listening for EAPOL on the master interface */
- add_ifidx(drv, if_nametoindex(master_ifname));
+ add_ifidx(drv, if_nametoindex(master_ifname), drv->ifindex);
} else {
master_ifname[0] = '\0';
}
@@ -5876,14 +5922,14 @@
if (params->bridge[i]) {
ifindex = if_nametoindex(params->bridge[i]);
if (ifindex)
- add_ifidx(drv, ifindex);
+ add_ifidx(drv, ifindex, drv->ifindex);
if (ifindex == br_ifindex)
br_added = 1;
}
}
/* start listening for EAPOL on the default AP interface */
- add_ifidx(drv, drv->ifindex);
+ add_ifidx(drv, drv->ifindex, IFIDX_ANY);
if (params->num_bridge && params->bridge[0]) {
if (i802_check_bridge(drv, bss, params->bridge[0],
@@ -5895,7 +5941,7 @@
if (!br_added && br_ifindex &&
(params->num_bridge == 0 || !params->bridge[0]))
- add_ifidx(drv, br_ifindex);
+ add_ifidx(drv, br_ifindex, drv->ifindex);
#ifdef CONFIG_LIBNL3_ROUTE
if (bss->added_if_into_bridge) {
@@ -6181,7 +6227,7 @@
nlmode == NL80211_IFTYPE_AP_VLAN ||
nlmode == NL80211_IFTYPE_WDS ||
nlmode == NL80211_IFTYPE_MONITOR))
- add_ifidx(drv, ifidx);
+ add_ifidx(drv, ifidx, IFIDX_ANY);
return 0;
}
@@ -6201,8 +6247,10 @@
else if (ifindex > 0 && !bss->added_if) {
struct wpa_driver_nl80211_data *drv2;
dl_list_for_each(drv2, &drv->global->interfaces,
- struct wpa_driver_nl80211_data, list)
- del_ifidx(drv2, ifindex);
+ struct wpa_driver_nl80211_data, list) {
+ del_ifidx(drv2, ifindex, IFIDX_ANY);
+ del_ifidx(drv2, IFIDX_ANY, ifindex);
+ }
}
if (type != WPA_IF_AP_BSS)
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 4fa7d5f..430369f 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -172,7 +172,10 @@
struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
int default_if_indices[16];
+ /* the AP/AP_VLAN iface that is in this bridge */
+ int default_if_indices_reason[16];
int *if_indices;
+ int *if_indices_reason;
int num_if_indices;
/* From failed authentication command */
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 98a2744..dae203a 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -572,9 +572,10 @@
rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
}
wpa_printf(MSG_DEBUG,
- "nl80211: RX frame sa=" MACSTR
+ "nl80211: RX frame da=" MACSTR " sa=" MACSTR " bssid=" MACSTR
" freq=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
- MAC2STR(mgmt->sa), rx_freq, ssi_signal, fc,
+ MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
+ rx_freq, ssi_signal, fc,
le_to_host16(mgmt->seq_ctrl), stype, fc2str(fc),
(unsigned int) len);
event.rx_mgmt.frame = frame;
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 2145022..c089891 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -96,12 +96,20 @@
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_nl80211_data *drv = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
+ if (!wpa_driver_nl80211_abort_scan(drv->first_bss))
+ return;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
+
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
wpa_driver_nl80211_set_mode(drv->first_bss,
drv->ap_scan_as_station);
drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
}
- wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
+
+ wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
}
@@ -257,6 +265,13 @@
goto fail;
}
+ if (params->bssid) {
+ wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: "
+ MACSTR, MAC2STR(params->bssid));
+ if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
+ goto fail;
+ }
+
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 1c8e88f..d2bc981 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -418,7 +418,6 @@
wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
goto fin;
}
- BN_clear_free(mask);
if (((x = BN_new()) == NULL) ||
((y = BN_new()) == NULL)) {
@@ -555,6 +554,7 @@
os_free(element);
BN_clear_free(x);
BN_clear_free(y);
+ BN_clear_free(mask);
BN_clear_free(cofactor);
EC_POINT_clear_free(K);
EC_POINT_clear_free(point);
diff --git a/src/fst/fst_session.c b/src/fst/fst_session.c
index 11f3b63..449e304 100644
--- a/src/fst/fst_session.c
+++ b/src/fst/fst_session.c
@@ -181,7 +181,8 @@
static void fst_session_stt_arm(struct fst_session *s)
{
- eloop_register_timeout(0, TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
+ /* Action frames sometimes get delayed. Use relaxed timeout (2*) */
+ eloop_register_timeout(0, 2 * TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
fst_session_timeout_handler, NULL, s);
s->stt_armed = TRUE;
}
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index d28b4cd..6942c85 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "eloop.h"
+#include "common/defs.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
@@ -2034,8 +2035,23 @@
dev = p2p_get_device(p2p, addr);
if (dev) {
- if (dev->country[0] == 0 && msg.listen_channel)
- os_memcpy(dev->country, msg.listen_channel, 3);
+ if (msg.listen_channel) {
+ int freq;
+
+ if (dev->country[0] == 0)
+ os_memcpy(dev->country, msg.listen_channel, 3);
+
+ freq = p2p_channel_to_freq(msg.listen_channel[3],
+ msg.listen_channel[4]);
+
+ if (freq > 0 && dev->listen_freq != freq) {
+ p2p_dbg(p2p,
+ "Updated peer " MACSTR " Listen channel (Probe Request): %d -> %d MHz",
+ MAC2STR(addr), dev->listen_freq, freq);
+ dev->listen_freq = freq;
+ }
+ }
+
os_get_reltime(&dev->last_seen);
p2p_parse_free(&msg);
return; /* already known */
@@ -3494,7 +3510,8 @@
}
-void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
+void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id,
+ unsigned int bands)
{
u8 dev_capab;
u8 *len;
@@ -3528,6 +3545,9 @@
p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
p2p->ext_listen_interval);
+ if (bands & BAND_60_GHZ)
+ p2p_buf_add_device_info(ies, p2p, NULL);
+
if (p2p->p2ps_seek && p2p->p2ps_seek_count)
p2p_buf_add_service_hash(ies, p2p);
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 244fca4..fc545b4 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1902,8 +1902,10 @@
* @p2p: P2P module context from p2p_init()
* @ies: Buffer for writing P2P IE
* @dev_id: Device ID to search for or %NULL for any
+ * @bands: Frequency bands used in the scan (enum wpa_radio_work_band bitmap)
*/
-void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id);
+void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id,
+ unsigned int bands);
/**
* p2p_scan_ie_buf_len - Get maximum buffer length needed for p2p_scan_ie
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index b24bbf8..a4edd5f 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -226,6 +226,16 @@
* next_radius_identifier - Next RADIUS message identifier to use
*/
u8 next_radius_identifier;
+
+ /**
+ * interim_error_cb - Interim accounting error callback
+ */
+ void (*interim_error_cb)(const u8 *addr, void *ctx);
+
+ /**
+ * interim_error_cb_ctx - interim_error_cb() context data
+ */
+ void *interim_error_cb_ctx;
};
@@ -297,6 +307,25 @@
}
+/**
+ * radius_client_set_interim_erro_cb - Register an interim acct error callback
+ * @radius: RADIUS client context from radius_client_init()
+ * @addr: Station address from the failed message
+ * @cb: Handler for interim accounting errors
+ * @ctx: Context pointer for handler callbacks
+ *
+ * This function is used to register a handler for processing failed
+ * transmission attempts of interim accounting update messages.
+ */
+void radius_client_set_interim_error_cb(struct radius_client_data *radius,
+ void (*cb)(const u8 *addr, void *ctx),
+ void *ctx)
+{
+ radius->interim_error_cb = cb;
+ radius->interim_error_cb_ctx = ctx;
+}
+
+
/*
* Returns >0 if message queue was flushed (i.e., the message that triggered
* the error is not available anymore)
@@ -336,6 +365,8 @@
int s;
struct wpabuf *buf;
size_t prev_num_msgs;
+ u8 *acct_delay_time;
+ size_t acct_delay_time_len;
if (entry->msg_type == RADIUS_ACCT ||
entry->msg_type == RADIUS_ACCT_INTERIM) {
@@ -371,12 +402,52 @@
conf->auth_server->retransmissions++;
}
}
+
+ if (entry->msg_type == RADIUS_ACCT_INTERIM) {
+ wpa_printf(MSG_DEBUG,
+ "RADIUS: Failed to transmit interim accounting update to "
+ MACSTR " - drop message and request a new update",
+ MAC2STR(entry->addr));
+ if (radius->interim_error_cb)
+ radius->interim_error_cb(entry->addr,
+ radius->interim_error_cb_ctx);
+ return 1;
+ }
+
if (s < 0) {
wpa_printf(MSG_INFO,
"RADIUS: No valid socket for retransmission");
return 1;
}
+ if (entry->msg_type == RADIUS_ACCT &&
+ radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME,
+ &acct_delay_time, &acct_delay_time_len,
+ NULL) == 0 &&
+ acct_delay_time_len == 4) {
+ struct radius_hdr *hdr;
+ u32 delay_time;
+
+ /*
+ * Need to assign a new identifier since attribute contents
+ * changes.
+ */
+ hdr = radius_msg_get_hdr(entry->msg);
+ hdr->identifier = radius_client_get_id(radius);
+
+ /* Update Acct-Delay-Time to show wait time in queue */
+ delay_time = now - entry->first_try;
+ WPA_PUT_BE32(acct_delay_time, delay_time);
+
+ wpa_printf(MSG_DEBUG,
+ "RADIUS: Updated Acct-Delay-Time to %u for retransmission",
+ delay_time);
+ radius_msg_finish_acct(entry->msg, entry->shared_secret,
+ entry->shared_secret_len);
+ if (radius->conf->msg_dumps)
+ radius_msg_dump(entry->msg);
+ }
+
/* retransmit; remove entry if too many attempts */
entry->attempts++;
hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
@@ -624,39 +695,6 @@
}
-static void radius_client_list_del(struct radius_client_data *radius,
- RadiusType msg_type, const u8 *addr)
-{
- struct radius_msg_list *entry, *prev, *tmp;
-
- if (addr == NULL)
- return;
-
- entry = radius->msgs;
- prev = NULL;
- while (entry) {
- if (entry->msg_type == msg_type &&
- os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
- if (prev)
- prev->next = entry->next;
- else
- radius->msgs = entry->next;
- tmp = entry;
- entry = entry->next;
- hostapd_logger(radius->ctx, addr,
- HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_DEBUG,
- "Removing matching RADIUS message");
- radius_client_msg_free(tmp);
- radius->num_msgs--;
- continue;
- }
- prev = entry;
- entry = entry->next;
- }
-}
-
-
/**
* radius_client_send - Send a RADIUS request
* @radius: RADIUS client context from radius_client_init()
@@ -668,16 +706,19 @@
* This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
* accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
* between accounting and interim accounting messages is that the interim
- * message will override any pending interim accounting updates while a new
- * accounting message does not remove any pending messages.
+ * message will not be retransmitted. Instead, a callback is used to indicate
+ * that the transmission failed for the specific station @addr so that a new
+ * interim accounting update message can be generated with up-to-date session
+ * data instead of trying to resend old information.
*
* The message is added on the retransmission queue and will be retransmitted
* automatically until a response is received or maximum number of retries
- * (RADIUS_CLIENT_MAX_RETRIES) is reached.
+ * (RADIUS_CLIENT_MAX_RETRIES) is reached. No such retries are used with
+ * RADIUS_ACCT_INTERIM, i.e., such a pending message is removed from the queue
+ * automatically on transmission failure.
*
* The related device MAC address can be used to identify pending messages that
- * can be removed with radius_client_flush_auth() or with interim accounting
- * updates.
+ * can be removed with radius_client_flush_auth().
*/
int radius_client_send(struct radius_client_data *radius,
struct radius_msg *msg, RadiusType msg_type,
@@ -690,11 +731,6 @@
int s, res;
struct wpabuf *buf;
- if (msg_type == RADIUS_ACCT_INTERIM) {
- /* Remove any pending interim acct update for the same STA. */
- radius_client_list_del(radius, msg_type, addr);
- }
-
if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
if (conf->acct_server && radius->acct_sock < 0)
radius_client_init_acct(radius);
diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
index 3db16aa..8ca0874 100644
--- a/src/radius/radius_client.h
+++ b/src/radius/radius_client.h
@@ -241,6 +241,9 @@
const u8 *shared_secret, size_t shared_secret_len,
void *data),
void *data);
+void radius_client_set_interim_error_cb(struct radius_client_data *radius,
+ void (*cb)(const u8 *addr, void *ctx),
+ void *ctx);
int radius_client_send(struct radius_client_data *radius,
struct radius_msg *msg,
RadiusType msg_type, const u8 *addr);
diff --git a/src/utils/trace.c b/src/utils/trace.c
index d98c4b0..d72cf60 100644
--- a/src/utils/trace.c
+++ b/src/utils/trace.c
@@ -369,8 +369,10 @@
void wpa_trace_deinit(void)
{
+#ifdef WPA_TRACE_BFD
free(syms);
syms = NULL;
+#endif /* WPA_TRACE_BFD */
}
#endif /* WPA_TRACE */