diff options
author | Dmitry Shmidt <dimitrysh@google.com> | 2016-03-04 01:47:02 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-03-04 01:47:02 +0000 |
commit | fed5ddb554a3f3bc71827d2df722b97a57f483f4 (patch) | |
tree | c4344a4dd6bcdfcc21068c6df95d590e6bca12f6 | |
parent | 8843ecaf2eb81dd202ee513c4068808e6dfd7b43 (diff) | |
parent | 9c17526f86859e2b6aebac0ed4f2561601816103 (diff) | |
download | wpa_supplicant_8-fed5ddb554a3f3bc71827d2df722b97a57f483f4.tar.gz |
Cumulative patch from commit 12c1fdf19a721aaf29e1c77d63445c7f5b8c61c0
am: 9c17526f86
* commit '9c17526f86859e2b6aebac0ed4f2561601816103':
Cumulative patch from commit 12c1fdf19a721aaf29e1c77d63445c7f5b8c61c0
49 files changed, 799 insertions, 363 deletions
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index d535eec4..3d5c5e2c 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -909,11 +909,23 @@ eap_server=0 # The own IP address of the access point (used as NAS-IP-Address) own_ip_addr=127.0.0.1 -# Optional NAS-Identifier string for RADIUS messages. When used, this should be -# a unique to the NAS within the scope of the RADIUS server. For example, a -# fully qualified domain name can be used here. +# NAS-Identifier string for RADIUS messages. When used, this should be unique +# to the NAS within the scope of the RADIUS server. Please note that hostapd +# uses a separate RADIUS client for each BSS and as such, a unique +# nas_identifier value should be configured separately for each BSS. This is +# particularly important for cases where RADIUS accounting is used +# (Accounting-On/Off messages are interpreted as clearing all ongoing sessions +# and that may get interpreted as applying to all BSSes if the same +# NAS-Identifier value is used.) For example, a fully qualified domain name +# prefixed with a unique identifier of the BSS (e.g., BSSID) can be used here. +# # When using IEEE 802.11r, nas_identifier must be set and must be between 1 and # 48 octets long. +# +# It is mandatory to configure either own_ip_addr or nas_identifier to be +# compliant with the RADIUS protocol. When using RADIUS accounting, it is +# strongly recommended that nas_identifier is set to a unique value for each +# BSS. #nas_identifier=ap.example.com # RADIUS client forced local IP address for the access point @@ -1260,6 +1272,7 @@ own_ip_addr=127.0.0.1 # PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID) # 6-octet identifier as a hex string. +# Defaults to BSSID. #r1_key_holder=000102030405 # Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535) diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c index 35793c80..2907c641 100644 --- a/hs20/client/osu_client.c +++ b/hs20/client/osu_client.c @@ -2339,12 +2339,23 @@ static int cmd_signup(struct hs20_osu_client *ctx, int no_prod_assoc, return -1; snprintf(fname, sizeof(fname), "%s/osu-info", dir); - if (mkdir(fname, S_IRWXU | S_IRWXG) < 0 && errno != EEXIST) { + if (mkdir(fname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 && + errno != EEXIST) { wpa_printf(MSG_INFO, "mkdir(%s) failed: %s", fname, strerror(errno)); return -1; } +#ifdef ANDROID + /* Allow processes running with Group ID as AID_WIFI + * to read/write files from osu-info directory + */ + if (chown(fname, -1, AID_WIFI)) { + wpa_printf(MSG_INFO, "Could not chown osu-info directory: %s", + strerror(errno)); + } +#endif /* ANDROID */ + snprintf(buf, sizeof(buf), "SET osu_dir %s", fname); if (wpa_command(ifname, buf) < 0) { wpa_printf(MSG_INFO, "Failed to configure osu_dir to wpa_supplicant"); diff --git a/src/ap/accounting.c b/src/ap/accounting.c index 9357a467..854174ec 100644 --- a/src/ap/accounting.c +++ b/src/ap/accounting.c @@ -152,6 +152,15 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, 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_report_state(struct hostapd_data *hapd, int on) } +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 @@ int accounting_init(struct hostapd_data *hapd) 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 477ea5bb..66b843ca 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -202,13 +202,6 @@ int hostapd_mac_comp(const void *a, const void *b) } -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 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, 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 9afca48b..f19cac6c 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -128,9 +128,14 @@ struct hostapd_vlan { }; #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 @@ struct hostapd_config { 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 a95230e0..9f249d74 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -166,6 +166,15 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, 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 702ee647..f54d1ade 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -176,6 +176,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, 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 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, 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 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, 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 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, 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 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, 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 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, } } - 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 dd2dc17d..303786b4 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -521,7 +521,7 @@ static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) /* 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 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) 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 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) 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 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface, } 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 84e6e15a..b36e68dd 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1726,6 +1726,9 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, } #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 78db2044..1a96b331 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -130,4 +130,8 @@ static inline u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) #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 f2807098..96091526 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 hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) 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; - - /* 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 (!psk) + return; + + if (src) + src->ref++; + + *psk = src; } @@ -443,7 +432,7 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd, 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 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd, */ 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_acl_deinit(struct hostapd_data *hapd) 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 10776353..af858f09 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -558,3 +558,20 @@ u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) } #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 60058e45..c36842b3 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -328,6 +328,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) #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 08e795e1..cd89e998 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -118,6 +118,7 @@ struct sta_info { 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 @@ struct sta_info { * 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 8eab6cb4..45d1a1c8 100644 --- a/src/ap/vlan_init.c +++ b/src/ap/vlan_init.c @@ -1119,25 +1119,23 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, 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 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, 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 d4e0efb9..313d89fe 100644 --- a/src/ap/vlan_util.c +++ b/src/ap/vlan_util.c @@ -33,7 +33,6 @@ int vlan_add(const char *if_name, int vid, const char *vlan_if_name) { 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 @@ int vlan_add(const char *if_name, int vid, const char *vlan_if_name) 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 @@ int vlan_add(const char *if_name, int vid, const char *vlan_if_name) 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 vlan_rem(const char *if_name) { 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 @@ int vlan_rem(const char *if_name) 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 @@ int vlan_rem(const char *if_name) 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 b303324c..2b601146 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -42,10 +42,11 @@ struct ft_rrb_frame { #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 @@ struct ft_r0kh_r1kh_pull_frame { 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 @@ struct ft_r0kh_r1kh_resp_frame { 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 @@ struct ft_r0kh_r1kh_push_frame { 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 ffd0790f..5fe0987f 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 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, 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 @@ static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx) 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 @@ static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, 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 b3ac4e86..6ef929cf 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -335,4 +335,10 @@ enum set_band { 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 2e503b95..5b05b68f 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -371,6 +371,10 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, 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 3a3dd4d1..d9fecd6c 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -62,6 +62,7 @@ struct ieee802_11_elems { 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 @@ struct ieee802_11_elems { 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 23152260..642276ce 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -439,6 +439,15 @@ struct wpa_driver_scan_params { */ 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 5fec430c..570dee66 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -181,9 +181,14 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss, 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 @@ nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len) 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 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, } 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 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx, "nl80211: Remove ifindex %u for bridge %s", brid, namebuf); } - del_ifidx(drv, brid); + del_ifidx(drv, brid, ifi->ifi_index); } } @@ -1716,6 +1721,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, 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 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) 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 @@ void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx) /* 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 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv, 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 @@ static void dump_ifidx(struct wpa_driver_nl80211_data *drv) 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 dump_ifidx(struct wpa_driver_nl80211_data *drv) } -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 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 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 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 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 void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) } -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 @@ static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) 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 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv, } 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 @@ static void *i802_init(struct hostapd_data *hapd, 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 @@ static void *i802_init(struct hostapd_data *hapd, 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 @@ static void *i802_init(struct hostapd_data *hapd, 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 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, 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 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss, 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 4fa7d5f8..430369f3 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -172,7 +172,10 @@ struct wpa_driver_nl80211_data { 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 98a27445..dae203a1 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -572,9 +572,10 @@ static void mlme_event_mgmt(struct i802_bss *bss, 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 21450229..c0898914 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -96,12 +96,20 @@ static int nl80211_get_noise_for_scan_results( 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 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss, 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 1c8e88f6..d2bc981c 100644 --- a/src/eap_peer/eap_pwd.c +++ b/src/eap_peer/eap_pwd.c @@ -418,7 +418,6 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 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 @@ fin: 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 11f3b638..449e3044 100644 --- a/src/fst/fst_session.c +++ b/src/fst/fst_session.c @@ -181,7 +181,8 @@ static void fst_session_timeout_handler(void *eloop_data, void *user_ctx) 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 d28b4cd2..6942c851 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 @@ static void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr, 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_res_handled(struct p2p_data *p2p) } -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 @@ void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id) 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 244fca43..fc545b41 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1902,8 +1902,10 @@ int p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf, * @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 b24bbf89..a4edd5fa 100644 --- a/src/radius/radius_client.c +++ b/src/radius/radius_client.c @@ -226,6 +226,16 @@ struct radius_client_data { * 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 @@ int radius_client_register(struct radius_client_data *radius, } +/** + * 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 @@ static int radius_client_retransmit(struct radius_client_data *radius, 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 @@ static int radius_client_retransmit(struct radius_client_data *radius, 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_add(struct radius_client_data *radius, } -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 @@ static void radius_client_list_del(struct radius_client_data *radius, * 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 radius_client_send(struct radius_client_data *radius, 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 3db16aa2..8ca0874d 100644 --- a/src/radius/radius_client.h +++ b/src/radius/radius_client.h @@ -241,6 +241,9 @@ int radius_client_register(struct radius_client_data *radius, 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 d98c4b04..d72cf604 100644 --- a/src/utils/trace.c +++ b/src/utils/trace.c @@ -369,8 +369,10 @@ void wpa_trace_check_ref(const void *addr) void wpa_trace_deinit(void) { +#ifdef WPA_TRACE_BFD free(syms); syms = NULL; +#endif /* WPA_TRACE_BFD */ } #endif /* WPA_TRACE */ diff --git a/wpa_supplicant/README b/wpa_supplicant/README index 32233128..fefc0d37 100644 --- a/wpa_supplicant/README +++ b/wpa_supplicant/README @@ -72,11 +72,13 @@ Supported WPA/IEEE 802.11i features: * EAP-TTLS/CHAP * EAP-SIM * EAP-AKA + * EAP-AKA' * EAP-PSK * EAP-PAX * EAP-SAKE * EAP-IKEv2 * EAP-GPSK + * EAP-pwd * LEAP (note: requires special support from the driver for IEEE 802.11 authentication) (following methods are supported, but since they do not generate keying @@ -163,18 +165,12 @@ systems. In case of Windows builds, WinPcap is used by default Optional libraries for EAP-TLS, EAP-PEAP, and EAP-TTLS: -- OpenSSL (tested with 0.9.7c and 0.9.7d, and 0.9.8 versions; assumed to +- OpenSSL (tested with 1.0.1 and 1.0.2 versions; assumed to work with most relatively recent versions; this is likely to be available with most distributions, http://www.openssl.org/) - GnuTLS - internal TLSv1 implementation -TLS options for EAP-FAST: -- OpenSSL 0.9.8d _with_ openssl-0.9.8d-tls-extensions.patch applied - (i.e., the default OpenSSL package does not include support for - extensions needed for EAP-FAST) -- internal TLSv1 implementation - One of these libraries is needed when EAP-TLS, EAP-PEAP, EAP-TTLS, or EAP-FAST support is enabled. WPA-PSK mode does not require this or EAPOL/EAP implementation. A configuration file, .config, for compilation is @@ -308,7 +304,7 @@ Following build time configuration options are used to control IEEE 802.1X/EAPOL and EAP state machines and all EAP methods. Including TLS, PEAP, or TTLS will require linking wpa_supplicant with OpenSSL library for TLS implementation. Alternatively, GnuTLS or the internal -TLSv1 implementation can be used for TLS functionaly. +TLSv1 implementation can be used for TLS functionality. CONFIG_IEEE8021X_EAPOL=y CONFIG_EAP_MD5=y @@ -320,15 +316,17 @@ CONFIG_EAP_GTC=y CONFIG_EAP_OTP=y CONFIG_EAP_SIM=y CONFIG_EAP_AKA=y +CONFIG_EAP_AKA_PRIME=y CONFIG_EAP_PSK=y CONFIG_EAP_SAKE=y CONFIG_EAP_GPSK=y CONFIG_EAP_PAX=y CONFIG_EAP_LEAP=y CONFIG_EAP_IKEV2=y +CONFIG_EAP_PWD=y Following option can be used to include GSM SIM/USIM interface for GSM/UMTS -authentication algorithm (for EAP-SIM/EAP-AKA). This requires pcsc-lite +authentication algorithm (for EAP-SIM/EAP-AKA/EAP-AKA'). This requires pcsc-lite (http://www.linuxnet.com/) for smart card access. CONFIG_PCSC=y @@ -499,7 +497,7 @@ reloading can be triggered with 'wpa_cli reconfigure' command. Configuration file can include one or more network blocks, e.g., one for each used SSID. wpa_supplicant will automatically select the best -betwork based on the order of network blocks in the configuration +network based on the order of network blocks in the configuration file, network security level (WPA/WPA2 is preferred), and signal strength. @@ -791,7 +789,7 @@ addresses, etc. One wpa_cli process in "action" mode needs to be started for each interface. For example, the following command starts wpa_cli for the -default ingterface (-i can be used to select the interface in case of +default interface (-i can be used to select the interface in case of more than one interface being used at the same time): wpa_cli -a/sbin/wpa_action.sh -B @@ -1007,8 +1005,8 @@ event message is indicated that the external processing can start. Once the operation has been completed, "RADIO_WORK done <id>" is used to indicate that to wpa_supplicant. This allows other radio works to be performed. If this command is forgotten (e.g., due to the external -program terminating), wpa_supplicant will time out the radio owrk item -and send "EXT-RADIO-WORK-TIMEOUT <id>" event ot indicate that this has +program terminating), wpa_supplicant will time out the radio work item +and send "EXT-RADIO-WORK-TIMEOUT <id>" event to indicate that this has happened. "RADIO_WORK done <id>" can also be used to cancel items that have not yet been started. diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20 index e523b582..e4eed207 100644 --- a/wpa_supplicant/README-HS20 +++ b/wpa_supplicant/README-HS20 @@ -229,7 +229,7 @@ Credentials can be pre-configured for automatic network selection: # # sp_priority: Credential priority within a provisioning SP # This is the priority of the credential among all credentials -# provisionined by the same SP (i.e., for entries that have identical +# provisioned by the same SP (i.e., for entries that have identical # provisioning_sp value). The range of this priority is 0-255 with 0 # being the highest and 255 the lower priority. # diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P index 19cf1556..b8cf2091 100644 --- a/wpa_supplicant/README-P2P +++ b/wpa_supplicant/README-P2P @@ -205,8 +205,8 @@ recently. P2PS attribute changes to p2p_connect command: P2PS supports two WPS provisioning methods namely PIN method and P2PS default. -The remaining paramters hold same role as in legacy P2P. In case of P2PS default -config method "p2ps" keyword is added in p2p_connect command. +The remaining parameters hold same role as in legacy P2P. In case of P2PS +default config method "p2ps" keyword is added in p2p_connect command. For example: p2p_connect 02:0a:f5:85:11:00 12345670 p2ps persistent join @@ -288,7 +288,7 @@ group interface is used as a parameter for this command. p2p_cancel Cancel an ongoing P2P group formation and joining-a-group related -operation. This operations unauthorizes the specific peer device (if any +operation. This operation unauthorizes the specific peer device (if any had been authorized to start group formation), stops P2P find (if in progress), stops pending operations for join-a-group, and removes the P2P group interface (if one was used) that is in the WPS provisioning @@ -657,7 +657,7 @@ p2p_set per_sta_psk <0/1> Disabled(default)/enables use of per-client PSK in the P2P groups. This can be used to request GO to assign a unique PSK for each client during WPS provisioning. When enabled, this allow clients to be removed from -the group securily with p2p_remove_client command since that client's +the group securely with p2p_remove_client command since that client's PSK is removed at the same time to prevent it from connecting back using the old PSK. When per-client PSK is not used, the client can still be disconnected, but it will be able to re-join the group since the PSK it diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 60f8c0d6..fd5b03fd 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -262,12 +262,12 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; if (ssid->p2p_group) { - os_memcpy(bss->ip_addr_go, wpa_s->parent->conf->ip_addr_go, 4); - os_memcpy(bss->ip_addr_mask, wpa_s->parent->conf->ip_addr_mask, + os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4); + os_memcpy(bss->ip_addr_mask, wpa_s->p2pdev->conf->ip_addr_mask, 4); os_memcpy(bss->ip_addr_start, - wpa_s->parent->conf->ip_addr_start, 4); - os_memcpy(bss->ip_addr_end, wpa_s->parent->conf->ip_addr_end, + wpa_s->p2pdev->conf->ip_addr_start, 4); + os_memcpy(bss->ip_addr_end, wpa_s->p2pdev->conf->ip_addr_end, 4); } #endif /* CONFIG_P2P */ @@ -487,14 +487,14 @@ static void ap_wps_event_cb(void *ctx, enum wps_event event, if (event == WPS_EV_FAIL) { struct wps_event_fail *fail = &data->fail; - if (wpa_s->parent && wpa_s->parent != wpa_s && + if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s && wpa_s == wpa_s->global->p2p_group_formation) { /* * src/ap/wps_hostapd.c has already sent this on the * main interface, so only send on the parent interface * here if needed. */ - wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL + wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL "msg=%d config_error=%d", fail->msg, fail->config_error); } @@ -639,8 +639,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, params.p2p = 1; #endif /* CONFIG_P2P */ - if (wpa_s->parent->set_ap_uapsd) - params.uapsd = wpa_s->parent->ap_uapsd; + if (wpa_s->p2pdev->set_ap_uapsd) + params.uapsd = wpa_s->p2pdev->ap_uapsd; else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD)) params.uapsd = 1; /* mandatory for P2P GO */ else @@ -719,7 +719,7 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, } hapd_iface->bss[i]->msg_ctx = wpa_s; - hapd_iface->bss[i]->msg_ctx_parent = wpa_s->parent; + hapd_iface->bss[i]->msg_ctx_parent = wpa_s->p2pdev; hapd_iface->bss[i]->public_action_cb = ap_public_action_rx; hapd_iface->bss[i]->public_action_cb_ctx = wpa_s; hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx; @@ -1320,8 +1320,8 @@ int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id, hapd = wpa_s->ap_iface->bss[0]; wps = hapd->wps; - if (wpa_s->parent->conf->wps_nfc_dh_pubkey == NULL || - wpa_s->parent->conf->wps_nfc_dh_privkey == NULL) { + if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL || + wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) { wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known"); return -1; } @@ -1330,9 +1330,9 @@ int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id, wpabuf_free(wps->dh_pubkey); wpabuf_free(wps->dh_privkey); wps->dh_privkey = wpabuf_dup( - wpa_s->parent->conf->wps_nfc_dh_privkey); + wpa_s->p2pdev->conf->wps_nfc_dh_privkey); wps->dh_pubkey = wpabuf_dup( - wpa_s->parent->conf->wps_nfc_dh_pubkey); + wpa_s->p2pdev->conf->wps_nfc_dh_pubkey); if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) { wps->dh_ctx = NULL; wpabuf_free(wps->dh_pubkey); diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 91a1511a..d74630ee 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -1207,7 +1207,7 @@ static int match_group_where_peer_is_client(struct p2p_group *group, cfg->ssid_len); if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) { wpas_dbus_signal_peer_groups_changed( - data->wpa_s->parent, data->info->p2p_device_addr); + data->wpa_s->p2pdev, data->info->p2p_device_addr); return 0; } @@ -1224,7 +1224,7 @@ static void signal_peer_groups_changed(struct p2p_peer_info *info, wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s, info->p2p_device_addr); if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) { - wpas_dbus_signal_peer_groups_changed(data->wpa_s->parent, + wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev, info->p2p_device_addr); return; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index ecb22e2c..b3e730f1 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3347,6 +3347,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED && event != EVENT_INTERFACE_ENABLED && event != EVENT_INTERFACE_STATUS && + event != EVENT_SCAN_RESULTS && event != EVENT_SCHED_SCAN_STOPPED) { wpa_dbg(wpa_s, MSG_DEBUG, "Ignore event %s (%d) while interface is disabled", @@ -3433,6 +3434,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, } break; case EVENT_SCAN_RESULTS: + if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { + wpa_s->scan_res_handler = NULL; + wpa_s->own_scan_running = 0; + wpa_s->radio->external_scan_running = 0; + wpa_s->last_scan_req = NORMAL_SCAN_REQ; + break; + } + if (!(data && data->scan_info.external_scan) && os_reltime_initialized(&wpa_s->scan_start_time)) { struct os_reltime now, diff; @@ -3931,7 +3940,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, case EVENT_SCHED_SCAN_STOPPED: wpa_s->pno = 0; wpa_s->sched_scanning = 0; - resched = wpa_s->scanning; + resched = wpa_s->scanning && wpas_scan_scheduled(wpa_s); wpa_supplicant_notify_scanning(wpa_s, 0); if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c index 457f5fb6..4f0d0e62 100644 --- a/wpa_supplicant/gas_query.c +++ b/wpa_supplicant/gas_query.c @@ -501,7 +501,7 @@ int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa, return -1; prot = categ == WLAN_ACTION_PROTECTED_DUAL; - pmf = pmf_in_use(gas->wpa_s, bssid); + pmf = pmf_in_use(gas->wpa_s, sa); if (prot && !pmf) { wpa_printf(MSG_DEBUG, "GAS: Drop unexpected protected GAS frame when PMF is disabled"); return 0; diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index 57b99436..3128fcb3 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -664,6 +664,7 @@ static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s) f = fopen(fname, "w"); if (f == NULL) { hs20_free_osu_prov(wpa_s); + wpa_s->fetch_anqp_in_progress = 0; return; } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index d2746678..cf2653de 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -351,6 +351,7 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, int social_channels_freq[] = { 2412, 2437, 2462, 60480 }; size_t ielen; u8 *n, i; + unsigned int bands; if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; @@ -380,28 +381,6 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, if (wps_ie == NULL) goto fail; - ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); - ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); - if (ies == NULL) { - wpabuf_free(wps_ie); - goto fail; - } - wpabuf_put_buf(ies, wps_ie); - wpabuf_free(wps_ie); - - p2p_scan_ie(wpa_s->global->p2p, ies, dev_id); - - params->p2p_probe = 1; - n = os_malloc(wpabuf_len(ies)); - if (n == NULL) { - wpabuf_free(ies); - goto fail; - } - os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies)); - params->extra_ies = n; - params->extra_ies_len = wpabuf_len(ies); - wpabuf_free(ies); - switch (type) { case P2P_SCAN_SOCIAL: params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1, @@ -442,6 +421,29 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, break; } + ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); + ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); + if (ies == NULL) { + wpabuf_free(wps_ie); + goto fail; + } + wpabuf_put_buf(ies, wps_ie); + wpabuf_free(wps_ie); + + bands = wpas_get_bands(wpa_s, params->freqs); + p2p_scan_ie(wpa_s->global->p2p, ies, dev_id, bands); + + params->p2p_probe = 1; + n = os_malloc(wpabuf_len(ies)); + if (n == NULL) { + wpabuf_free(ies); + goto fail; + } + os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies)); + params->extra_ies = n; + params->extra_ies_len = wpabuf_len(ies); + wpabuf_free(ies); + radio_remove_works(wpa_s, "p2p-scan", 0); if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb, params) < 0) @@ -800,6 +802,8 @@ grp_owner: s = wpas_p2p_get_persistent_go(wpa_s); if (!s && !go_wpa_s && p2p_no_group_iface) { p2p_set_intended_addr(wpa_s->global->p2p, + wpa_s->p2p_mgmt ? + wpa_s->parent->own_addr : wpa_s->own_addr); } else if (!s && !go_wpa_s) { if (wpas_p2p_add_group_interface(wpa_s, @@ -873,7 +877,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, if (wpa_s->cross_connect_in_use) { wpa_s->cross_connect_in_use = 0; - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s", wpa_s->ifname, wpa_s->cross_connect_uplink); } @@ -904,7 +908,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, break; } if (removal_reason != P2P_GROUP_REMOVAL_SILENT) { - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_GROUP_REMOVED "%s %s%s", wpa_s->ifname, gtype, reason); } @@ -914,7 +918,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, 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_s->p2pdev, NULL) > 0) { wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group formation " "timeout"); wpa_s->p2p_in_provisioning = 0; @@ -949,6 +953,12 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, return 1; } + /* + * The primary interface was used for P2P group operations, so + * need to reset its p2pdev. + */ + wpa_s->p2pdev = wpa_s->parent; + if (!wpa_s->p2p_go_group_formation_completed) { wpa_s->global->p2p_group_formation = NULL; wpa_s->p2p_in_provisioning = 0; @@ -1264,7 +1274,7 @@ static void wpas_p2p_group_started(struct wpa_supplicant *wpa_s, * Include PSK/passphrase only in the control interface message and * leave it out from the debug log entry. */ - wpa_msg_global_ctrl(wpa_s->parent, MSG_INFO, + wpa_msg_global_ctrl(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_GROUP_STARTED "%s %s ssid=\"%s\" freq=%d%s%s%s%s%s go_dev_addr=" MACSTR "%s%s", @@ -1307,7 +1317,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, wpa_s->group_formation_reported = 1; if (!success) { - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_GROUP_FORMATION_FAILURE); wpas_notify_p2p_group_formation_failure(wpa_s, ""); if (already_deleted) @@ -1317,7 +1327,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, return; } - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_GROUP_FORMATION_SUCCESS); ssid = wpa_s->current_ssid; @@ -1365,7 +1375,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, } if (persistent) - network_id = wpas_p2p_store_persistent_group(wpa_s->parent, + network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev, ssid, go_dev_addr); else { os_free(wpa_s->global->add_psk); @@ -1489,7 +1499,7 @@ static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s, wpa_s->pending_pd_before_join = 0; wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req " "during p2p_connect-auto"); - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG "reason=no-ACK-to-PD-Req"); wpas_p2p_fallback_to_go_neg(wpa_s, 0); @@ -1632,11 +1642,11 @@ static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s, } else if (res->wps_method == WPS_NFC) { wpas_wps_start_nfc(wpa_s, res->peer_device_addr, res->peer_interface_addr, - wpa_s->parent->p2p_oob_dev_pw, - wpa_s->parent->p2p_oob_dev_pw_id, 1, - wpa_s->parent->p2p_oob_dev_pw_id == + wpa_s->p2pdev->p2p_oob_dev_pw, + wpa_s->p2pdev->p2p_oob_dev_pw_id, 1, + wpa_s->p2pdev->p2p_oob_dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER ? - wpa_s->parent->p2p_peer_oob_pubkey_hash : + wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL, NULL, 0, 0); #endif /* CONFIG_WPS_NFC */ @@ -1662,7 +1672,7 @@ static void wpas_p2p_add_psk_list(struct wpa_supplicant *wpa_s, if (!wpa_s->ap_iface) return; - persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid, + persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid, ssid->ssid_len); if (persistent == NULL) return; @@ -1727,8 +1737,8 @@ static void p2p_go_save_group_common_freqs(struct wpa_supplicant *wpa_s, static void p2p_config_write(struct wpa_supplicant *wpa_s) { #ifndef CONFIG_NO_CONFIG_WRITE - if (wpa_s->parent->conf->update_config && - wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf)) + if (wpa_s->p2pdev->conf->update_config && + wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf)) wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration"); #endif /* CONFIG_NO_CONFIG_WRITE */ } @@ -1766,8 +1776,8 @@ static void p2p_go_configured(void *ctx, void *data) params->persistent_group, ""); wpa_s->group_formation_reported = 1; - if (wpa_s->parent->p2ps_method_config_any) { - if (is_zero_ether_addr(wpa_s->parent->p2ps_join_addr)) { + if (wpa_s->p2pdev->p2ps_method_config_any) { + if (is_zero_ether_addr(wpa_s->p2pdev->p2ps_join_addr)) { wpa_dbg(wpa_s, MSG_DEBUG, "P2PS: Setting default PIN for ANY"); wpa_supplicant_ap_wps_pin(wpa_s, NULL, @@ -1776,18 +1786,18 @@ static void p2p_go_configured(void *ctx, void *data) } else { wpa_dbg(wpa_s, MSG_DEBUG, "P2PS: Setting default PIN for " MACSTR, - MAC2STR(wpa_s->parent->p2ps_join_addr)); + MAC2STR(wpa_s->p2pdev->p2ps_join_addr)); wpa_supplicant_ap_wps_pin( - wpa_s, wpa_s->parent->p2ps_join_addr, + wpa_s, wpa_s->p2pdev->p2ps_join_addr, "12345670", NULL, 0, 0); } - wpa_s->parent->p2ps_method_config_any = 0; + wpa_s->p2pdev->p2ps_method_config_any = 0; } os_get_reltime(&wpa_s->global->p2p_go_wait_client); if (params->persistent_group) { network_id = wpas_p2p_store_persistent_group( - wpa_s->parent, ssid, + wpa_s->p2pdev, ssid, wpa_s->global->p2p_dev_addr); wpas_p2p_add_psk_list(wpa_s, ssid); } @@ -1804,11 +1814,11 @@ static void p2p_go_configured(void *ctx, void *data) wpa_s->p2p_go_group_formation_completed = 0; wpa_s->global->p2p_group_formation = wpa_s; eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); eloop_register_timeout( wpa_s->p2p_first_connection_timeout, 0, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); } return; @@ -1826,17 +1836,17 @@ static void p2p_go_configured(void *ctx, void *data) params->peer_device_addr); #ifdef CONFIG_WPS_NFC } else if (params->wps_method == WPS_NFC) { - if (wpa_s->parent->p2p_oob_dev_pw_id != + if (wpa_s->p2pdev->p2p_oob_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && - !wpa_s->parent->p2p_oob_dev_pw) { + !wpa_s->p2pdev->p2p_oob_dev_pw) { wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known"); return; } wpas_ap_wps_add_nfc_pw( - wpa_s, wpa_s->parent->p2p_oob_dev_pw_id, - wpa_s->parent->p2p_oob_dev_pw, - wpa_s->parent->p2p_peer_oob_pk_hash_known ? - wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL); + wpa_s, wpa_s->p2pdev->p2p_oob_dev_pw_id, + wpa_s->p2pdev->p2p_oob_dev_pw, + wpa_s->p2pdev->p2p_peer_oob_pk_hash_known ? + wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL); #endif /* CONFIG_WPS_NFC */ } else if (wpa_s->p2p_pin[0]) wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr, @@ -1916,7 +1926,7 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, os_memcpy(ssid->psk, params->psk, sizeof(ssid->psk)); else if (ssid->passphrase) wpa_config_update_psk(ssid); - ssid->ap_max_inactivity = wpa_s->parent->conf->p2p_go_max_inactivity; + ssid->ap_max_inactivity = wpa_s->p2pdev->conf->p2p_go_max_inactivity; wpa_s->ap_configured_cb = p2p_go_configured; wpa_s->ap_configured_cb_ctx = wpa_s; @@ -1976,6 +1986,23 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst, } +static void wpas_p2p_clone_config_dh(struct wpa_supplicant *dst, + const struct wpa_supplicant *src) +{ + struct wpa_config *d; + const struct wpa_config *s; + + d = dst->conf; + s = src->conf; + + if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey && + !d->wps_nfc_dh_privkey && !d->wps_nfc_dh_pubkey) { + d->wps_nfc_dh_privkey = wpabuf_dup(s->wps_nfc_dh_privkey); + d->wps_nfc_dh_pubkey = wpabuf_dup(s->wps_nfc_dh_pubkey); + } +} + + static void wpas_p2p_get_group_ifname(struct wpa_supplicant *wpa_s, char *ifname, size_t len) { @@ -2126,7 +2153,7 @@ static void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s, int already_deleted) { eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); if (wpa_s->global->p2p) p2p_group_formation_failed(wpa_s->global->p2p); wpas_group_formation_completed(wpa_s, 0, already_deleted); @@ -2137,9 +2164,9 @@ static void wpas_p2p_grpform_fail_after_wps(struct wpa_supplicant *wpa_s) { wpa_printf(MSG_DEBUG, "P2P: Reject group formation due to WPS provisioning failure"); eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); wpa_s->global->p2p_fail_on_wps_complete = 0; } @@ -2150,15 +2177,16 @@ void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s) return; /* Speed up group formation timeout since this cannot succeed */ eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); } static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) { struct wpa_supplicant *wpa_s = ctx; + struct wpa_supplicant *group_wpa_s; if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) { wpa_drv_cancel_remain_on_channel(wpa_s); @@ -2211,7 +2239,7 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) } if (wpa_s->create_p2p_iface) { - struct wpa_supplicant *group_wpa_s = + group_wpa_s = wpas_p2p_init_group_interface(wpa_s, res->role_go); if (group_wpa_s == NULL) { wpas_p2p_remove_pending_group_interface(wpa_s); @@ -2220,31 +2248,27 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) wpas_p2p_group_formation_failed(wpa_s, 1); return; } - if (group_wpa_s != wpa_s) { - os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin, - sizeof(group_wpa_s->p2p_pin)); - group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method; - } os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN); wpa_s->pending_interface_name[0] = '\0'; - group_wpa_s->p2p_in_provisioning = 1; - - if (res->role_go) { - wpas_start_wps_go(group_wpa_s, res, 1); - } else { - os_get_reltime(&group_wpa_s->scan_min_time); - wpas_start_wps_enrollee(group_wpa_s, res); - } } else { - wpa_s->p2p_in_provisioning = 1; - wpa_s->global->p2p_group_formation = wpa_s; + group_wpa_s = wpa_s->parent; + wpa_s->global->p2p_group_formation = group_wpa_s; + if (group_wpa_s != wpa_s) + wpas_p2p_clone_config_dh(group_wpa_s, wpa_s); + } - if (res->role_go) { - wpas_start_wps_go(wpa_s, res, 1); - } else { - os_get_reltime(&wpa_s->scan_min_time); - wpas_start_wps_enrollee(ctx, res); - } + group_wpa_s->p2p_in_provisioning = 1; + group_wpa_s->p2pdev = wpa_s; + if (group_wpa_s != wpa_s) { + os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin, + sizeof(group_wpa_s->p2p_pin)); + group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method; + } + if (res->role_go) { + wpas_start_wps_go(group_wpa_s, res, 1); + } else { + os_get_reltime(&group_wpa_s->scan_min_time); + wpas_start_wps_enrollee(group_wpa_s, res); } wpa_s->p2p_long_listen = 0; @@ -2365,6 +2389,10 @@ static void wpas_dev_lost(void *ctx, const u8 *dev_addr) static void wpas_find_stopped(void *ctx) { struct wpa_supplicant *wpa_s = ctx; + + if (wpa_s->p2p_scan_work && wpas_abort_ongoing_scan(wpa_s) < 0) + wpa_printf(MSG_DEBUG, "P2P: Abort ongoing scan failed"); + wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED); wpas_notify_p2p_find_stopped(wpa_s); } @@ -2658,7 +2686,7 @@ static void wpas_prov_disc_fail(void *ctx, const u8 *peer, if (wpa_s->p2p_fallback_to_go_neg) { wpa_dbg(wpa_s, MSG_DEBUG, "P2P: PD for p2p_connect-auto " "failed - fall back to GO Negotiation"); - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG "reason=PD-failed"); wpas_p2p_fallback_to_go_neg(wpa_s, 0); @@ -2903,7 +2931,11 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid, "invitation"); return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; } - os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN); + if (wpa_s->p2p_mgmt) + os_memcpy(group_bssid, wpa_s->parent->own_addr, + ETH_ALEN); + else + os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN); } else if (s->mode == WPAS_MODE_P2P_GO) { *go = 1; if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO) < 0) @@ -3091,7 +3123,7 @@ static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s, if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || !ssid->p2p_persistent_group) return; /* Not operating as a GO in persistent group */ - ssid = wpas_p2p_get_persistent(wpa_s->parent, peer, + ssid = wpas_p2p_get_persistent(wpa_s->p2pdev, peer, ssid->ssid, ssid->ssid_len); wpas_remove_persistent_peer(wpa_s, ssid, peer, 1); } @@ -3733,6 +3765,7 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s, return -1; } + p2pdev_wpa_s->p2pdev = p2pdev_wpa_s; wpa_s->pending_interface_name[0] = '\0'; return 0; } @@ -4514,8 +4547,7 @@ static void wpas_p2p_deinit_global(struct wpa_global *global) static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s) { - if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) && - wpa_s->conf->p2p_no_group_iface) + if (wpa_s->conf->p2p_no_group_iface) return 0; /* separate interface disabled per configuration */ if (wpa_s->drv_flags & (WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE | @@ -4596,7 +4628,7 @@ static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s) MAC2STR(wpa_s->pending_join_dev_addr)); return; } - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_GROUP_FORMATION_FAILURE); wpas_notify_p2p_group_formation_failure(wpa_s, ""); } @@ -4732,7 +4764,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, if (join < 0) { wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be " "running a GO -> use GO Negotiation"); - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG "reason=peer-not-running-GO"); wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, @@ -4754,7 +4786,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, "try to join the group", join ? "" : " in older scan"); if (!join) { - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED); wpa_s->p2p_fallback_to_go_neg = 1; } @@ -4823,7 +4855,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, u16 method; if (wpas_check_freq_conflict(wpa_s, freq) > 0) { - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_GROUP_FORMATION_FAILURE "reason=FREQ_CONFLICT"); wpas_notify_p2p_group_formation_failure( @@ -4904,6 +4936,7 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, struct wpabuf *wps_ie, *ies; size_t ielen; int freqs[2] = { 0, 0 }; + unsigned int bands; os_memset(¶ms, 0, sizeof(params)); @@ -4929,22 +4962,6 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, return; } - ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); - ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); - if (ies == NULL) { - wpabuf_free(wps_ie); - wpas_p2p_scan_res_join(wpa_s, NULL); - return; - } - wpabuf_put_buf(ies, wps_ie); - wpabuf_free(wps_ie); - - p2p_scan_ie(wpa_s->global->p2p, ies, NULL); - - params.p2p_probe = 1; - params.extra_ies = wpabuf_head(ies); - params.extra_ies_len = wpabuf_len(ies); - if (!freq) { int oper_freq; /* @@ -4961,6 +4978,23 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, params.freqs = freqs; } + ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); + ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); + if (ies == NULL) { + wpabuf_free(wps_ie); + wpas_p2p_scan_res_join(wpa_s, NULL); + return; + } + wpabuf_put_buf(ies, wps_ie); + wpabuf_free(wps_ie); + + bands = wpas_get_bands(wpa_s, freqs); + p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands); + + params.p2p_probe = 1; + params.extra_ies = wpabuf_head(ies); + params.extra_ies_len = wpabuf_len(ies); + /* * Run a scan to update BSS table and start Provision Discovery once * the new scan results become available. @@ -5397,7 +5431,10 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, if_addr = wpa_s->pending_interface_addr; } else { - if_addr = wpa_s->own_addr; + if (wpa_s->p2p_mgmt) + if_addr = wpa_s->parent->own_addr; + else + if_addr = wpa_s->own_addr; os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN); } @@ -5943,9 +5980,20 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated, struct wpa_supplicant *group_wpa_s; if (!wpas_p2p_create_iface(wpa_s)) { - wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group " - "operations"); + if (wpa_s->p2p_mgmt) { + /* + * We may be called on the p2p_dev interface which + * cannot be used for group operations, so always use + * the primary interface. + */ + wpa_s->parent->p2pdev = wpa_s; + wpa_s = wpa_s->parent; + } + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Use primary interface for group operations"); wpa_s->p2p_first_connection_timeout = 0; + if (wpa_s != wpa_s->p2pdev) + wpas_p2p_clone_config_dh(wpa_s, wpa_s->p2pdev); return wpa_s; } @@ -6084,11 +6132,11 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s, wpa_s->p2p_go_group_formation_completed = 0; wpa_s->global->p2p_group_formation = wpa_s; - eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent, + eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev, NULL); eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); wpa_supplicant_select_network(wpa_s, ssid); return 0; @@ -6115,7 +6163,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, "already running"); if (go == 0 && eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL)) { + wpa_s->p2pdev, NULL)) { /* * This can happen if Invitation Response frame was lost * and the peer (GO of a persistent group) tries to @@ -6128,7 +6176,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, "P2P: Reschedule group formation timeout since peer is still trying to invite us"); eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); } return 0; } @@ -6311,7 +6359,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, p2p_clear_provisioning_info(wpa_s->global->p2p, go_dev_addr); } - eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent, + eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev, NULL); wpa_s->p2p_go_group_formation_completed = 1; if (ssid && ssid->mode == WPAS_MODE_INFRA) { @@ -6326,7 +6374,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, P2P_MAX_INITIAL_CONN_WAIT); eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); /* Complete group formation on successful data connection. */ wpa_s->p2p_go_group_formation_completed = 0; } else if (ssid) { @@ -6340,7 +6388,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, P2P_MAX_INITIAL_CONN_WAIT_GO); eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT_GO, 0, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); /* * Complete group formation on first successful data connection */ @@ -6379,7 +6427,7 @@ void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, wpa_s->global->p2p_fail_on_wps_complete = 1; eloop_deplete_timeout(0, 50000, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); } } @@ -6673,12 +6721,15 @@ void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da, void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies) { + unsigned int bands; + if (wpa_s->global->p2p_disabled) return; if (wpa_s->global->p2p == NULL) return; - p2p_scan_ie(wpa_s->global->p2p, ies, NULL); + bands = wpas_get_bands(wpa_s, NULL); + p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands); } @@ -6745,7 +6796,9 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, return -1; } bssid = wpa_s->pending_interface_addr; - } else + } else if (wpa_s->p2p_mgmt) + bssid = wpa_s->parent->own_addr; + else bssid = wpa_s->own_addr; } else { role = P2P_INVITE_ROLE_CLIENT; @@ -6823,7 +6876,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, wpa_s->global->p2p_invite_group = wpa_s; persistent = ssid->p2p_persistent_group && - wpas_p2p_get_persistent(wpa_s->parent, peer_addr, + wpas_p2p_get_persistent(wpa_s->p2pdev, peer_addr, ssid->ssid, ssid->ssid_len); if (ssid->mode == WPAS_MODE_P2P_GO) { @@ -6846,7 +6899,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, freq = wpa_s->current_bss ? wpa_s->current_bss->freq : (int) wpa_s->assoc_freq; } - wpa_s->parent->pending_invite_ssid_id = -1; + wpa_s->p2pdev->pending_invite_ssid_id = -1; if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; @@ -6877,7 +6930,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) { eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); } if (!wpa_s->show_group_started || !ssid) @@ -6928,7 +6981,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) ip_addr); if (persistent) - network_id = wpas_p2p_store_persistent_group(wpa_s->parent, + network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev, ssid, go_dev_addr); if (network_id < 0) network_id = ssid->id; @@ -7265,7 +7318,7 @@ int wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled) iface->cross_connect_enabled = 0; iface->cross_connect_in_use = 0; - wpa_msg_global(iface->parent, MSG_INFO, + wpa_msg_global(iface->p2pdev, MSG_INFO, P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s", iface->ifname, iface->cross_connect_uplink); @@ -7295,7 +7348,7 @@ static void wpas_p2p_enable_cross_connect(struct wpa_supplicant *uplink) continue; iface->cross_connect_in_use = 1; - wpa_msg_global(iface->parent, MSG_INFO, + wpa_msg_global(iface->p2pdev, MSG_INFO, P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s", iface->ifname, iface->cross_connect_uplink); } @@ -7315,7 +7368,7 @@ static void wpas_p2p_disable_cross_connect(struct wpa_supplicant *uplink) if (!iface->cross_connect_in_use) continue; - wpa_msg_global(iface->parent, MSG_INFO, + wpa_msg_global(iface->p2pdev, MSG_INFO, P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s", iface->ifname, iface->cross_connect_uplink); iface->cross_connect_in_use = 0; @@ -7378,7 +7431,7 @@ static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s) break; wpa_s->cross_connect_in_use = 1; - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s", wpa_s->ifname, wpa_s->cross_connect_uplink); break; @@ -7394,8 +7447,8 @@ int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "P2P: Terminate connection due to WPS PBC " "session overlap"); - if (wpa_s != wpa_s->parent) - wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP); + if (wpa_s != wpa_s->p2pdev) + wpa_msg_ctrl(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_OVERLAP); wpas_p2p_group_formation_failed(wpa_s, 0); return 1; } @@ -7502,7 +7555,7 @@ int wpas_p2p_cancel(struct wpa_supplicant *wpa_s) wpa_s->ifname); found = 1; eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); if (wpa_s->p2p_in_provisioning) { wpas_group_formation_completed(wpa_s, 0, 0); break; @@ -7632,7 +7685,7 @@ void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s, { if (wpa_s->p2p_in_provisioning && ssid->p2p_group && eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL) > 0) { + wpa_s->p2pdev, NULL) > 0) { /** * Remove the network by scheduling the group formation * timeout to happen immediately. The teardown code @@ -7644,7 +7697,7 @@ void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "P2P: Canceled group formation due to " "P2P group network getting removed"); eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL); + wpa_s->p2pdev, NULL); } } @@ -7688,7 +7741,7 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, const u8 *addr) { if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout, - wpa_s->parent, NULL) > 0) { + wpa_s->p2pdev, NULL) > 0) { /* * This can happen if WPS provisioning step is not terminated * cleanly (e.g., P2P Client does not send WSC_Done). Since the @@ -7767,7 +7820,7 @@ int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s) wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - " "fallback to GO Negotiation"); - wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG "reason=GO-not-found"); res = wpas_p2p_fallback_to_go_neg(wpa_s, 1); @@ -7876,7 +7929,7 @@ void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr, return; } - persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid, + persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid, ssid->ssid_len); if (!persistent) { wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not find persistent group information to store the new PSK"); @@ -7905,7 +7958,7 @@ void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr, os_free(last); } - wpas_p2p_remove_psk_entry(wpa_s->parent, persistent, + wpas_p2p_remove_psk_entry(wpa_s->p2pdev, persistent, p2p_dev_addr ? p2p_dev_addr : mac_addr, p2p_dev_addr == NULL); if (p2p_dev_addr) { @@ -7917,8 +7970,8 @@ void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr, } dl_list_add(&persistent->psk_list, &p->list); - if (wpa_s->parent->conf->update_config && - wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf)) + if (wpa_s->p2pdev->conf->update_config && + wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf)) wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration"); } @@ -8097,14 +8150,14 @@ int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s) wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Two 4-way handshake failures for a P2P group - go_dev_addr=" MACSTR, MAC2STR(go_dev_addr)); - persistent = wpas_p2p_get_persistent(wpa_s->parent, go_dev_addr, + persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, go_dev_addr, ssid->ssid, ssid->ssid_len); if (persistent == NULL || persistent->mode != WPAS_MODE_INFRA) { wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No matching persistent group stored"); goto disconnect; } - wpa_msg_global(wpa_s->parent, MSG_INFO, + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_PERSISTENT_PSK_FAIL "%d", persistent->id); disconnect: @@ -8671,7 +8724,9 @@ int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled) } if_addr = wpa_s->pending_interface_addr; - } else + } else if (wpa_s->p2p_mgmt) + if_addr = wpa_s->parent->own_addr; + else if_addr = wpa_s->own_addr; wpa_s->p2p_nfc_tag_enabled = enabled; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index c333e574..3463dd92 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1006,6 +1006,27 @@ ssid_list_set: } } + if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) { + struct wpa_bss *bss; + + params.bssid = wpa_s->next_scan_bssid; + bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid); + if (bss && bss->ssid_len && params.num_ssids == 1 && + params.ssids[0].ssid_len == 0) { + params.ssids[0].ssid = bss->ssid; + params.ssids[0].ssid_len = bss->ssid_len; + wpa_dbg(wpa_s, MSG_DEBUG, + "Scan a previously specified BSSID " MACSTR + " and SSID %s", + MAC2STR(params.bssid), + wpa_ssid_txt(bss->ssid, bss->ssid_len)); + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "Scan a previously specified BSSID " MACSTR, + MAC2STR(params.bssid)); + } + } + scan_params = ¶ms; scan: @@ -1066,6 +1087,8 @@ scan: #ifdef CONFIG_INTERWORKING wpa_s->interworking_fast_assoc_tried = 0; #endif /* CONFIG_INTERWORKING */ + if (params.bssid) + os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN); } } @@ -2259,6 +2282,17 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src) params->mac_addr_mask = mac_addr + ETH_ALEN; } } + + if (src->bssid) { + u8 *bssid; + + bssid = os_malloc(ETH_ALEN); + if (!bssid) + goto failed; + os_memcpy(bssid, src->bssid, ETH_ALEN); + params->bssid = bssid; + } + return params; failed: @@ -2287,6 +2321,8 @@ void wpa_scan_free_params(struct wpa_driver_scan_params *params) */ os_free((u8 *) params->mac_addr); + os_free((u8 *) params->bssid); + os_free(params); } @@ -2508,7 +2544,13 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s, int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s) { - if (wpa_s->scan_work && wpa_s->own_scan_running) { + int scan_work = !!wpa_s->scan_work; + +#ifdef CONFIG_P2P + scan_work |= !!wpa_s->p2p_scan_work; +#endif /* CONFIG_P2P */ + + if (scan_work && wpa_s->own_scan_running) { wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan"); return wpa_drv_abort_scan(wpa_s); } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index f09534df..a6ace1ad 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1009,8 +1009,8 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) params.p2p = 1; - if (wpa_s->parent->set_sta_uapsd) - params.uapsd = wpa_s->parent->sta_uapsd; + if (wpa_s->p2pdev->set_sta_uapsd) + params.uapsd = wpa_s->p2pdev->sta_uapsd; else params.uapsd = -1; diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 0dc41dca..7d2a92fa 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -1115,11 +1115,22 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s, rep = &wpa_s->wnm_neighbor_report_elements[ wpa_s->wnm_num_neighbor_report]; wnm_parse_neighbor_report(wpa_s, pos, len, rep); + wpa_s->wnm_num_neighbor_report++; } pos += len; - wpa_s->wnm_num_neighbor_report++; } + + if (!wpa_s->wnm_num_neighbor_report) { + wpa_printf(MSG_DEBUG, + "WNM: Candidate list included bit is set, but no candidates found"); + wnm_send_bss_transition_mgmt_resp( + wpa_s, wpa_s->wnm_dialog_token, + WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES, + 0, NULL); + return; + } + wnm_sort_cand_list(wpa_s); wnm_dump_cand_list(wpa_s); valid_ms = valid_int * beacon_int * 128 / 125; @@ -1148,6 +1159,14 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s, } wnm_set_scan_freqs(wpa_s); + if (wpa_s->wnm_num_neighbor_report == 1) { + os_memcpy(wpa_s->next_scan_bssid, + wpa_s->wnm_neighbor_report_elements[0].bssid, + ETH_ALEN); + wpa_printf(MSG_DEBUG, + "WNM: Scan only for a specific BSSID since there is only a single candidate " + MACSTR, MAC2STR(wpa_s->next_scan_bssid)); + } wpa_supplicant_req_scan(wpa_s, 0, 0); } else if (reply) { enum bss_trans_mgmt_status_code status; diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index f8bf6bd6..eecb1dca 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -3659,6 +3659,10 @@ static int wpa_cli_exec(const char *program, const char *arg1, size_t len; int res; + /* If no interface is specified, set the global */ + if (!arg1) + arg1 = "global"; + len = os_strlen(arg1) + os_strlen(arg2) + 2; arg = os_malloc(len); if (arg == NULL) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index dbfc34e0..136cb58e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2490,8 +2490,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.p2p = ssid->p2p_group; - if (wpa_s->parent->set_sta_uapsd) - params.uapsd = wpa_s->parent->sta_uapsd; + if (wpa_s->p2pdev->set_sta_uapsd) + params.uapsd = wpa_s->p2pdev->sta_uapsd; else params.uapsd = -1; @@ -3510,6 +3510,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent) wpa_s->scan_interval = 5; wpa_s->new_connection = 1; wpa_s->parent = parent ? parent : wpa_s; + wpa_s->p2pdev = wpa_s->parent; wpa_s->sched_scanning = 0; dl_list_init(&wpa_s->bss_tmp_disallowed); @@ -4021,7 +4022,7 @@ static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s, } -static enum wpa_radio_work_band wpas_freq_to_band(int freq) +enum wpa_radio_work_band wpas_freq_to_band(int freq) { if (freq < 3000) return BAND_2_4_GHZ; @@ -4031,8 +4032,7 @@ static enum wpa_radio_work_band wpas_freq_to_band(int freq) } -static unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, - const int *freqs) +unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs) { int i; unsigned int band = 0; @@ -4839,6 +4839,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, iface = global->ifaces; while (iface) { + if (iface->p2pdev == wpa_s) + iface->p2pdev = iface->parent; if (iface == wpa_s || iface->parent != wpa_s) { iface = iface->next; continue; @@ -6248,7 +6250,7 @@ wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame) case VENDOR_ELEM_P2P_INV_RESP: case VENDOR_ELEM_P2P_ASSOC_REQ: case VENDOR_ELEM_P2P_ASSOC_RESP: - return wpa_s->parent; + return wpa_s->p2pdev; #endif /* CONFIG_P2P */ default: return wpa_s; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 0e3e42a5..1b16d281 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -308,11 +308,6 @@ struct wpa_radio { #define MAX_ACTIVE_WORKS 2 -enum wpa_radio_work_band { - BAND_2_4_GHZ = BIT(0), - BAND_5_GHZ = BIT(1), - BAND_60_GHZ = BIT(2), -}; /** * struct wpa_radio_work - Radio work item @@ -358,6 +353,9 @@ struct wpa_external_work { unsigned int timeout; }; +enum wpa_radio_work_band wpas_freq_to_band(int freq); +unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs); + /** * offchannel_send_action_result - Result of offchannel send Action frame */ @@ -453,6 +451,7 @@ struct wpa_supplicant { struct wpa_radio *radio; /* shared radio context */ struct dl_list radio_list; /* list head: struct wpa_radio::ifaces */ struct wpa_supplicant *parent; + struct wpa_supplicant *p2pdev; struct wpa_supplicant *next; struct l2_packet_data *l2; struct l2_packet_data *l2_br; @@ -640,6 +639,7 @@ struct wpa_supplicant { #define MAX_SCAN_ID 16 int scan_id[MAX_SCAN_ID]; unsigned int scan_id_count; + u8 next_scan_bssid[ETH_ALEN]; struct wpa_ssid_value *ssids_from_scan_req; unsigned int num_ssids_from_scan_req; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 07452ada..0860eb40 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -583,8 +583,8 @@ static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s, m2d->dev_password_id, m2d->config_error); wpas_notify_wps_event_m2d(wpa_s, m2d); #ifdef CONFIG_P2P - if (wpa_s->parent && wpa_s->parent != wpa_s) { - wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_M2D + if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s) { + wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_M2D "dev_password_id=%d config_error=%d", m2d->dev_password_id, m2d->config_error); } @@ -617,8 +617,8 @@ static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s, WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)", fail->msg, fail->config_error, fail->error_indication, wps_ei_str(fail->error_indication)); - if (wpa_s->parent && wpa_s->parent != wpa_s) - wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL + if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s) + wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)", fail->msg, fail->config_error, fail->error_indication, @@ -627,8 +627,8 @@ static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL "msg=%d config_error=%d", fail->msg, fail->config_error); - if (wpa_s->parent && wpa_s->parent != wpa_s) - wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL + if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s) + wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL "msg=%d config_error=%d", fail->msg, fail->config_error); } |