diff options
| author | Dmitry Shmidt <dimitrysh@google.com> | 2014-03-24 12:09:47 -0700 |
|---|---|---|
| committer | Dmitry Shmidt <dimitrysh@google.com> | 2014-03-24 12:09:47 -0700 |
| commit | d11f019d62a42a8fc4c4d1f2ec17cf35b0763153 (patch) | |
| tree | 1970556391556ef071070194d6d8129cb0a17990 | |
| parent | 6cb1f6521a84955752c2b99100cf1df87637f86c (diff) | |
| download | android_external_wpa_supplicant_8-d11f019d62a42a8fc4c4d1f2ec17cf35b0763153.tar.gz android_external_wpa_supplicant_8-d11f019d62a42a8fc4c4d1f2ec17cf35b0763153.tar.bz2 android_external_wpa_supplicant_8-d11f019d62a42a8fc4c4d1f2ec17cf35b0763153.zip | |
Cumulative patch from commit 31ded52e7084976c5f84caae6cb55e632dd8b013
31ded52 SME: Add more debug prints for OBSS scans and 20/40 MHz co-ex report
7f8eb34 SME: Fix OBSS scan result processing for 20/40 MHz co-ex report
b7a8d67 Allow hostapd to advertise 40 MHz intolerant HT capability
692ec30 FT: Add support for postponing FT response
6ace13a P2P: Clean up channel selection code to use helper functions
70c3523 WPS: Comment out unused AP WEP config write with WPS 2.0
c3ba70f P2P: Update op_reg_class in random social channel case
70634ee hostapd: Check driver DFS offload capability for channel disablement
65d645c nl80211: Fetch DFS offload capability from driver
a500f31 WPS: Comment out unused AP WEP config update with WPS 2.0
be4e5af Add SAE and FT-SAE key_mgmt to hostapd GET_CONFIG
1d4fe3b Remove unnecessary parameter validation
94b84bc P2P: Avoid unsafe pre-configured channel as channel preference
d3c9c35 Add freq= parameter to 'set pno' command
b998236 dbus: Implement P2P Peers info IEs buffer getter
c6f356f dbus: Export the peer's device address as a property
442adfd dbus: Declare properly ServiceDiscoveryRequest method
8903741 dbus: Cancelling a service request always reply by an error
13494c4 dbus: Remove duplicate signal declaration
513dcec Don't overwrite channel on hostapd config reload
5eae87a P2P: Fix GO failed interface init
c46235a wpa_supplicant: Fix radio_remove_interface
2ce7e4f Android: Enable CONFIG_EAP_AKA_PRIME option
95bf699 Add get_radio_name() driver wrapper for wpa_supplicant
d06ecab D-Bus: Make p2p_no_group_iface configurable
8b6b6d8 Fix hostapd.conf description of HT40+
Change-Id: I5e776f71050a106195a39e96d0c38930a387a806
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
28 files changed, 467 insertions, 97 deletions
diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 814468d1..e1f8b20d 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1067,6 +1067,8 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf, conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ; if (os_strstr(capab, "[PSMP]")) conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP; + if (os_strstr(capab, "[40-INTOLERANT]")) + conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT; if (os_strstr(capab, "[LSIG-TXOP-PROT]")) conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT; diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index dbdc8c67..29d5d8b2 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -940,6 +940,14 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, return pos - buf; pos += ret; } +#ifdef CONFIG_SAE + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { + ret = os_snprintf(pos, end - pos, "FT-SAE "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SAE */ #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { @@ -955,6 +963,14 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, pos += ret; } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { + ret = os_snprintf(pos, end - pos, "SAE "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SAE */ ret = os_snprintf(pos, end - pos, "\n"); if (ret < 0 || ret >= end - pos) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 23ee1e5b..b5770a4f 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -453,7 +453,7 @@ wmm_ac_vo_acm=0 # LDPC coding capability: [LDPC] = supported # Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary # channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz -# with secondary channel below the primary channel +# with secondary channel above the primary channel # (20 MHz only if neither is set) # Note: There are limits on which channels can be used with HT40- and # HT40+. Following table shows the channels that may be available for @@ -481,6 +481,7 @@ wmm_ac_vo_acm=0 # set) # DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set) # PSMP support: [PSMP] (disabled if not set) +# 40 MHz intolerant [40-INTOLERANT] (not advertised if not set) # L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set) #ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40] diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 11351c4b..e1020a67 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -469,9 +469,6 @@ int hostapd_parse_csa_settings(const char *pos, { char *end; - if (!settings) - return -1; - os_memset(settings, 0, sizeof(*settings)); settings->cs_count = strtol(pos, &end, 10); if (pos == end) { diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 4ed718cf..2ecaec82 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -171,6 +171,16 @@ int hostapd_reload_config(struct hostapd_iface *iface) for (j = 0; j < iface->num_bss; j++) { hapd = iface->bss[j]; hapd->iconf = newconf; + hapd->iconf->channel = oldconf->channel; + hapd->iconf->ieee80211n = oldconf->ieee80211n; + hapd->iconf->ieee80211ac = oldconf->ieee80211ac; + hapd->iconf->ht_capab = oldconf->ht_capab; + hapd->iconf->vht_capab = oldconf->vht_capab; + hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth; + hapd->iconf->vht_oper_centr_freq_seg0_idx = + oldconf->vht_oper_centr_freq_seg0_idx; + hapd->iconf->vht_oper_centr_freq_seg1_idx = + oldconf->vht_oper_centr_freq_seg1_idx; hapd->conf = newconf->bss[j]; hostapd_reload_bss(hapd); } diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index d319ce00..54a79b09 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -111,10 +111,13 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) if ((feature->channels[j].flag & HOSTAPD_CHAN_RADAR) && dfs_enabled) { dfs = 1; - } else if (feature->channels[j].flag & - (HOSTAPD_CHAN_NO_IBSS | - HOSTAPD_CHAN_PASSIVE_SCAN | - HOSTAPD_CHAN_RADAR)) { + } else if (((feature->channels[j].flag & + HOSTAPD_CHAN_RADAR) && + !(iface->drv_flags & + WPA_DRIVER_FLAGS_DFS_OFFLOAD)) || + (feature->channels[j].flag & + (HOSTAPD_CHAN_NO_IBSS | + HOSTAPD_CHAN_PASSIVE_SCAN))) { feature->channels[j].flag |= HOSTAPD_CHAN_DISABLED; } diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 4d19bb03..77e78584 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -621,6 +621,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) } #ifdef CONFIG_IEEE80211R os_free(sm->assoc_resp_ftie); + wpabuf_free(sm->ft_pending_req_ies); #endif /* CONFIG_IEEE80211R */ os_free(sm->last_rx_eapol_key); os_free(sm->wpa_ie); diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 3ab3e3d5..929a2535 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -42,6 +42,7 @@ struct ft_rrb_frame { #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 struct ft_r0kh_r1kh_pull_frame { u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ @@ -49,7 +50,7 @@ struct ft_r0kh_r1kh_pull_frame { le16 data_length; /* little endian length of data (44) */ u8 ap_address[ETH_ALEN]; - u8 nonce[16]; + u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; u8 pmk_r0_name[WPA_PMK_NAME_LEN]; u8 r1kh_id[FT_R1KH_ID_LEN]; u8 s1kh_id[ETH_ALEN]; @@ -63,7 +64,7 @@ struct ft_r0kh_r1kh_resp_frame { le16 data_length; /* little endian length of data (76) */ u8 ap_address[ETH_ALEN]; - u8 nonce[16]; /* copied from pull */ + u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */ u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */ u8 s1kh_id[ETH_ALEN]; /* copied from pull */ u8 pmk_r1[PMK_LEN]; diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index c22c4cca..77015961 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -1,6 +1,6 @@ /* * hostapd - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -9,6 +9,7 @@ #include "utils/includes.h" #include "utils/common.h" +#include "utils/eloop.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "crypto/aes_wrap.h" @@ -22,6 +23,12 @@ #ifdef CONFIG_IEEE80211R +static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm, + const u8 *current_ap, const u8 *sta_addr, + u16 status, const u8 *resp_ies, + size_t resp_ies_len); + + static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst, const u8 *data, size_t data_len) { @@ -293,22 +300,25 @@ static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, } -static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth, - const u8 *s1kh_id, const u8 *r0kh_id, - size_t r0kh_id_len, const u8 *pmk_r0_name) +static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, + const u8 *ies, size_t ies_len, + const u8 *pmk_r0_name) { struct ft_remote_r0kh *r0kh; struct ft_r0kh_r1kh_pull_frame frame, f; - r0kh = wpa_auth->conf.r0kh_list; + r0kh = sm->wpa_auth->conf.r0kh_list; while (r0kh) { - if (r0kh->id_len == r0kh_id_len && - os_memcmp(r0kh->id, r0kh_id, r0kh_id_len) == 0) + if (r0kh->id_len == sm->r0kh_id_len && + os_memcmp(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) == 0) break; r0kh = r0kh->next; } - if (r0kh == NULL) + if (r0kh == NULL) { + wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID", + sm->r0kh_id, sm->r0kh_id_len); return -1; + } wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH " "address " MACSTR, MAC2STR(r0kh->addr)); @@ -317,25 +327,32 @@ static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth, frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; frame.packet_type = FT_PACKET_R0KH_R1KH_PULL; frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN); - os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN); + os_memcpy(frame.ap_address, sm->wpa_auth->addr, ETH_ALEN); /* aes_wrap() does not support inplace encryption, so use a temporary * buffer for the data. */ - if (random_get_bytes(f.nonce, sizeof(f.nonce))) { + if (random_get_bytes(f.nonce, FT_R0KH_R1KH_PULL_NONCE_LEN)) { wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " "nonce"); return -1; } + os_memcpy(sm->ft_pending_pull_nonce, f.nonce, + FT_R0KH_R1KH_PULL_NONCE_LEN); os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN); - os_memcpy(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); - os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN); + os_memcpy(f.r1kh_id, sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); + os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN); os_memset(f.pad, 0, sizeof(f.pad)); if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, f.nonce, frame.nonce) < 0) return -1; - wpa_ft_rrb_send(wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame)); + wpabuf_free(sm->ft_pending_req_ies); + sm->ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len); + if (sm->ft_pending_req_ies == NULL) + return -1; + + wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame)); return 0; } @@ -777,7 +794,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) } -static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, +static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len, u8 **resp_ies, size_t *resp_ies_len) { @@ -848,19 +865,13 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1, &pairwise) < 0) { - if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id, - sm->r0kh_id_len, parse.rsn_pmkid) < 0) { + if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) { wpa_printf(MSG_DEBUG, "FT: Did not have matching " "PMK-R1 and unknown R0KH-ID"); return WLAN_STATUS_INVALID_PMKID; } - /* - * TODO: Should return "status pending" (and the caller should - * not send out response now). The real response will be sent - * once the response from R0KH is received. - */ - return WLAN_STATUS_INVALID_PMKID; + return -1; /* Status pending */ } wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN); @@ -940,6 +951,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, u16 status; u8 *resp_ies; size_t resp_ies_len; + int res; if (sm == NULL) { wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but " @@ -950,8 +962,16 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR " BSSID=" MACSTR " transaction=%d", MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction); - status = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies, - &resp_ies_len); + sm->ft_pending_cb = cb; + sm->ft_pending_cb_ctx = ctx; + sm->ft_pending_auth_transaction = auth_transaction; + res = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies, + &resp_ies_len); + if (res < 0) { + wpa_printf(MSG_DEBUG, "FT: Callback postponed until response is available"); + return; + } + status = res; wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR " auth_transaction=%d status=%d", @@ -1182,15 +1202,27 @@ int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len) } +static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst, const u8 *bssid, + u16 auth_transaction, u16 resp, + const u8 *ies, size_t ies_len) +{ + struct wpa_state_machine *sm = ctx; + wpa_printf(MSG_DEBUG, "FT: Over-the-DS RX request cb for " MACSTR, + MAC2STR(sm->addr)); + wpa_ft_send_rrb_auth_resp(sm, sm->ft_pending_current_ap, sm->addr, + WLAN_STATUS_SUCCESS, ies, ies_len); +} + + static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth, const u8 *current_ap, const u8 *sta_addr, const u8 *body, size_t len) { struct wpa_state_machine *sm; u16 status; - u8 *resp_ies, *pos; - size_t resp_ies_len, rlen; - struct ft_rrb_frame *frame; + u8 *resp_ies; + size_t resp_ies_len; + int res; sm = wpa_ft_add_sta(wpa_auth, sta_addr); if (sm == NULL) { @@ -1201,8 +1233,33 @@ static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth, wpa_hexdump(MSG_MSGDUMP, "FT: RRB Request Frame body", body, len); - status = wpa_ft_process_auth_req(sm, body, len, &resp_ies, - &resp_ies_len); + sm->ft_pending_cb = wpa_ft_rrb_rx_request_cb; + sm->ft_pending_cb_ctx = sm; + os_memcpy(sm->ft_pending_current_ap, current_ap, ETH_ALEN); + res = wpa_ft_process_auth_req(sm, body, len, &resp_ies, + &resp_ies_len); + if (res < 0) { + wpa_printf(MSG_DEBUG, "FT: No immediate response available - wait for pull response"); + return 0; + } + status = res; + + res = wpa_ft_send_rrb_auth_resp(sm, current_ap, sta_addr, status, + resp_ies, resp_ies_len); + os_free(resp_ies); + return res; +} + + +static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm, + const u8 *current_ap, const u8 *sta_addr, + u16 status, const u8 *resp_ies, + size_t resp_ies_len) +{ + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + size_t rlen; + struct ft_rrb_frame *frame; + u8 *pos; wpa_printf(MSG_DEBUG, "FT: RRB authentication response: STA=" MACSTR " CurrentAP=" MACSTR " status=%d", @@ -1218,10 +1275,8 @@ static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth, rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len; frame = os_malloc(sizeof(*frame) + rlen); - if (frame == NULL) { - os_free(resp_ies); + if (frame == NULL) return -1; - } frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; frame->packet_type = FT_PACKET_RESPONSE; frame->action_length = host_to_le16(rlen); @@ -1235,10 +1290,8 @@ static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth, pos += ETH_ALEN; WPA_PUT_LE16(pos, status); pos += 2; - if (resp_ies) { + if (resp_ies) os_memcpy(pos, resp_ies, resp_ies_len); - os_free(resp_ies); - } wpa_ft_rrb_send(wpa_auth, current_ap, (u8 *) frame, sizeof(*frame) + rlen); @@ -1290,7 +1343,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, f.nonce, sizeof(f.nonce)); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name", f.pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID=" + wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID=" MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id)); os_memset(&resp, 0, sizeof(resp)); @@ -1333,13 +1386,58 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, } +static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_state_machine *sm = eloop_ctx; + int res; + u8 *resp_ies; + size_t resp_ies_len; + u16 status; + + res = wpa_ft_process_auth_req(sm, wpabuf_head(sm->ft_pending_req_ies), + wpabuf_len(sm->ft_pending_req_ies), + &resp_ies, &resp_ies_len); + wpabuf_free(sm->ft_pending_req_ies); + sm->ft_pending_req_ies = NULL; + if (res < 0) + res = WLAN_STATUS_UNSPECIFIED_FAILURE; + status = res; + wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR + " - status %u", MAC2STR(sm->addr), status); + + sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr, sm->wpa_auth->addr, + sm->ft_pending_auth_transaction + 1, status, + resp_ies, resp_ies_len); + os_free(resp_ies); +} + + +static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx) +{ + struct ft_r0kh_r1kh_resp_frame *frame = ctx; + + if (os_memcmp(frame->s1kh_id, sm->addr, ETH_ALEN) != 0) + return 0; + if (os_memcmp(frame->nonce, sm->ft_pending_pull_nonce, + FT_R0KH_R1KH_PULL_NONCE_LEN) != 0) + return 0; + if (sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL) + return 0; + + wpa_printf(MSG_DEBUG, "FT: Response to a pending pull request for " + MACSTR " - process from timeout", MAC2STR(sm->addr)); + eloop_register_timeout(0, 0, ft_pull_resp_cb_finish, sm, NULL); + return 1; +} + + static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, const u8 *src_addr, const u8 *data, size_t data_len) { struct ft_r0kh_r1kh_resp_frame *frame, f; struct ft_remote_r0kh *r0kh; - int pairwise; + int pairwise, res; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response"); @@ -1376,14 +1474,10 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, return -1; } - /* TODO: verify that <nonce,s1kh_id> matches with a pending request - * and call this requests callback function to finish request - * processing */ - pairwise = le_to_host16(f.pairwise); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", f.nonce, sizeof(f.nonce)); - wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID=" + wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID=" MACSTR " pairwise=0x%x", MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1", @@ -1391,11 +1485,13 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name", f.pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, - pairwise); + res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, + pairwise); + wpa_printf(MSG_DEBUG, "FT: Look for pending pull request"); + wpa_auth_for_each_sta(wpa_auth, ft_pull_resp_cb, &f); os_memset(f.pmk_r1, 0, PMK_LEN); - return 0; + return res ? 0 : -1; } diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 2e1bdcf4..6960ff36 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -118,6 +118,15 @@ struct wpa_state_machine { u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key * message 2/4 */ u8 *assoc_resp_ftie; + + void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid, + u16 auth_transaction, u16 status, + const u8 *ies, size_t ies_len); + void *ft_pending_cb_ctx; + struct wpabuf *ft_pending_req_ies; + u8 ft_pending_pull_nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; + u8 ft_pending_auth_transaction; + u8 ft_pending_current_ap[ETH_ALEN]; #endif /* CONFIG_IEEE80211R */ int pending_1_of_4_timeout; diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 62cd03cf..e0033ced 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -378,6 +378,13 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, } bss->auth_algs = 1; } else { +#ifdef CONFIG_WPS2 + /* + * WPS 2.0 does not allow WEP to be configured, so no need to + * process that option here either. + */ + bss->auth_algs = 1; +#else /* CONFIG_WPS2 */ if ((cred->auth_type & WPS_AUTH_OPEN) && (cred->auth_type & WPS_AUTH_SHARED)) bss->auth_algs = 3; @@ -412,6 +419,7 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, } wep->keys_set = 1; } +#endif /* CONFIG_WPS2 */ } /* Schedule configuration reload after short period of time to allow @@ -586,6 +594,13 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) fprintf(nconf, "auth_algs=1\n"); } else { +#ifdef CONFIG_WPS2 + /* + * WPS 2.0 does not allow WEP to be configured, so no need to + * process that option here either. + */ + fprintf(nconf, "auth_algs=1\n"); +#else /* CONFIG_WPS2 */ if ((cred->auth_type & WPS_AUTH_OPEN) && (cred->auth_type & WPS_AUTH_SHARED)) fprintf(nconf, "auth_algs=3\n"); @@ -611,6 +626,7 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) } fprintf(nconf, "\n"); } +#endif /* CONFIG_WPS2 */ } fprintf(nconf, "# WPS configuration - END\n"); diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 0d83920a..80bad4f8 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -29,12 +29,16 @@ * ranges to avoid to reduce issues due to interference or internal * co-existence information in the driver. The event data structure is * defined in struct qca_avoid_freq_list. + * + * @QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: Command to check driver support + * for DFS offloading. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, QCA_NL80211_VENDOR_SUBCMD_TEST = 1, /* subcmds 2..9 not yet allocated */ QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10, + QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11, }; @@ -48,4 +52,13 @@ struct qca_avoid_freq_list { struct qca_avoid_freq_range range[0]; } STRUCT_PACKED; +enum qca_wlan_vendor_attr { + QCA_WLAN_VENDOR_ATTR_INVALID = 0, + /* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */ + QCA_WLAN_VENDOR_ATTR_DFS = 1, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1, +}; + #endif /* QCA_VENDOR_H */ diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 2eafc14c..59352739 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -897,7 +897,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_DRIVER_IE 0x00000001 /* Driver needs static WEP key setup after association command */ #define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002 -/* unused: 0x00000004 */ +/* Driver takes care of all DFS operations */ +#define WPA_DRIVER_FLAGS_DFS_OFFLOAD 0x00000004 /* Driver takes care of RSN 4-way handshake internally; PMK is configured with * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */ #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008 diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index dcd002e4..c3449ac9 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -303,6 +303,7 @@ struct wpa_driver_nl80211_data { unsigned int start_iface_up:1; unsigned int test_use_roc_tx:1; unsigned int ignore_deauth_event:1; + unsigned int dfs_vendor_cmd_avail:1; u64 remain_on_chan_cookie; u64 send_action_cookie; @@ -3725,6 +3726,10 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) continue; } vinfo = nla_data(nl); + if (vinfo->subcmd == + QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY) + drv->dfs_vendor_cmd_avail = 1; + wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u", vinfo->vendor_id, vinfo->subcmd); } @@ -8889,11 +8894,44 @@ done: } +static int dfs_info_handler(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + int *dfs_capability_ptr = arg; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (tb[NL80211_ATTR_VENDOR_DATA]) { + struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA]; + struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1]; + + nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX, + nla_data(nl_vend), nla_len(nl_vend), NULL); + + if (tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]) { + u32 val; + val = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]); + wpa_printf(MSG_DEBUG, "nl80211: DFS offload capability: %u", + val); + *dfs_capability_ptr = val; + } + } + + return NL_SKIP; +} + + static int wpa_driver_nl80211_get_capa(void *priv, struct wpa_driver_capa *capa) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int dfs_capability = 0; + int ret = 0; + if (!drv->has_capability) return -1; os_memcpy(capa, &drv->capa, sizeof(*capa)); @@ -8909,7 +8947,31 @@ static int wpa_driver_nl80211_get_capa(void *priv, capa->flags &= ~WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE; } - return 0; + if (drv->dfs_vendor_cmd_avail == 1) { + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); + NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, + QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY); + + ret = send_and_recv_msgs(drv, msg, dfs_info_handler, + &dfs_capability); + if (!ret) { + if (dfs_capability) + capa->flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD; + } + } + + return ret; + + nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; } diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index c5bf41fe..a1325d36 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1208,10 +1208,25 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p) 0) { p2p_dbg(p2p, "Select possible 5 GHz channel (op_class %u channel %u) as operating channel preference", p2p->op_reg_class, p2p->op_channel); - } else { + } else if (p2p_channels_includes(&p2p->cfg->channels, + p2p->cfg->op_reg_class, + p2p->cfg->op_channel)) { p2p_dbg(p2p, "Select pre-configured channel as operating channel preference"); p2p->op_reg_class = p2p->cfg->op_reg_class; p2p->op_channel = p2p->cfg->op_channel; + } else if (p2p_channel_random_social(&p2p->cfg->channels, + &p2p->op_reg_class, + &p2p->op_channel) == 0) { + p2p_dbg(p2p, "Select random available social channel %d from 2.4 GHz band as operating channel preference", + p2p->op_channel); + } else { + /* Select any random available channel from the first available + * operating class */ + p2p_channel_select(&p2p->cfg->channels, NULL, + &p2p->op_reg_class, + &p2p->op_channel); + p2p_dbg(p2p, "Select random available channel %d from operating class %d as operating channel preference", + p2p->op_channel, p2p->op_reg_class); } os_memcpy(&p2p->channels, &p2p->cfg->channels, diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 420c7391..8c225ec5 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -592,6 +592,8 @@ void p2p_channels_dump(struct p2p_data *p2p, const char *title, const struct p2p_channels *chan); int p2p_channel_select(struct p2p_channels *chans, const int *classes, u8 *op_class, u8 *op_channel); +int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, + u8 *op_channel); /* p2p_parse.c */ int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg); diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c index 161a402e..de47c122 100644 --- a/src/p2p/p2p_utils.c +++ b/src/p2p/p2p_utils.c @@ -441,31 +441,65 @@ void p2p_channels_dump(struct p2p_data *p2p, const char *title, } +static u8 p2p_channel_pick_random(const u8 *channels, unsigned int num_channels) +{ + unsigned int r; + os_get_random((u8 *) &r, sizeof(r)); + r %= num_channels; + return channels[r]; +} + + int p2p_channel_select(struct p2p_channels *chans, const int *classes, u8 *op_class, u8 *op_channel) { - unsigned int i, j, r; + unsigned int i, j; - for (j = 0; classes[j]; j++) { + for (j = 0; classes == NULL || classes[j]; j++) { for (i = 0; i < chans->reg_classes; i++) { struct p2p_reg_class *c = &chans->reg_class[i]; if (c->channels == 0) continue; - if (c->reg_class == classes[j]) { + if (classes == NULL || c->reg_class == classes[j]) { /* * Pick one of the available channels in the * operating class at random. */ - os_get_random((u8 *) &r, sizeof(r)); - r %= c->channels; *op_class = c->reg_class; - *op_channel = c->channel[r]; + *op_channel = p2p_channel_pick_random( + c->channel, c->channels); return 0; } } + if (classes == NULL) + break; } return -1; } + + +int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, + u8 *op_channel) +{ + u8 chan[3]; + unsigned int num_channels = 0; + + /* Try to find available social channels from 2.4 GHz */ + if (p2p_channels_includes(chans, 81, 1)) + chan[num_channels++] = 1; + if (p2p_channels_includes(chans, 81, 6)) + chan[num_channels++] = 6; + if (p2p_channels_includes(chans, 81, 11)) + chan[num_channels++] = 11; + + if (num_channels == 0) + return -1; + + *op_class = 81; + *op_channel = p2p_channel_pick_random(chan, num_channels); + + return 0; +} diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config index 184b41ed..7c80528e 100644 --- a/wpa_supplicant/android.config +++ b/wpa_supplicant/android.config @@ -123,7 +123,7 @@ CONFIG_EAP_AKA=y # EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used). # This requires CONFIG_EAP_AKA to be enabled, too. -#CONFIG_EAP_AKA_PRIME=y +CONFIG_EAP_AKA_PRIME=y # Enable USIM simulator (Milenage) for EAP-AKA #CONFIG_USIM_SIMULATOR=y diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 87ed3e26..704caa1e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -46,6 +46,8 @@ static int wpa_supplicant_global_iface_list(struct wpa_global *global, char *buf, int len); static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, char *buf, int len); +static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, + char *val); static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) { @@ -245,6 +247,33 @@ static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos) } #endif /* CONFIG_NO_CONFIG_BLOBS */ + +static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd) +{ + char *params; + char *pos; + int *freqs = NULL; + int ret; + + if (atoi(cmd)) { + params = os_strchr(cmd, ' '); + os_free(wpa_s->manual_sched_scan_freqs); + if (params) { + params++; + pos = os_strstr(params, "freq="); + if (pos) + freqs = freq_range_to_channel_list(wpa_s, + pos + 5); + } + wpa_s->manual_sched_scan_freqs = freqs; + ret = wpas_start_pno(wpa_s); + } else { + ret = wpas_stop_pno(wpa_s); + } + return ret; +} + + static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, char *cmd) { @@ -328,10 +357,7 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, wpa_tdls_enable(wpa_s->wpa, !disabled); #endif /* CONFIG_TDLS */ } else if (os_strcasecmp(cmd, "pno") == 0) { - if (atoi(value)) - ret = wpas_start_pno(wpa_s); - else - ret = wpas_stop_pno(wpa_s); + ret = wpas_ctrl_pno(wpa_s, value); } else if (os_strcasecmp(cmd, "radio_disabled") == 0) { int disabled = atoi(value); if (wpa_drv_radio_disable(wpa_s, disabled) < 0) diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 5e02956b..a0653f07 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -2649,6 +2649,7 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req, { { "args", "a{sv}", ARG_IN }, + { "ref", "t", ARG_OUT }, END_ARGS } }, @@ -2679,13 +2680,6 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { END_ARGS } }, - { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE, - (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external, - { - { "arg", "i", ARG_IN }, - END_ARGS - } - }, { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group, { @@ -3280,6 +3274,10 @@ static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = { wpas_dbus_getter_p2p_peer_ies, NULL }, + { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", + wpas_dbus_getter_p2p_peer_device_address, + NULL + }, { NULL, NULL, NULL, NULL, NULL } }; diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c index 2b83637e..7857bfd7 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c @@ -825,6 +825,11 @@ dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter, wpa_s->conf->disassoc_low_ack)) goto err_no_mem; + /* No Group Iface */ + if (!wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface", + wpa_s->conf->p2p_no_group_iface)) + goto err_no_mem; + if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || !dbus_message_iter_close_container(iter, &variant_iter)) goto err_no_mem; @@ -974,6 +979,9 @@ dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter, else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 && entry.type == DBUS_TYPE_UINT32) wpa_s->conf->disassoc_low_ack = entry.uint32_value; + else if (os_strcmp(entry.key, "NoGroupIface") == 0 && + entry.type == DBUS_TYPE_BOOLEAN) + wpa_s->conf->p2p_no_group_iface = entry.bool_value; else goto error; @@ -1470,12 +1478,46 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter, dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter, DBusError *error, void *user_data) { - dbus_bool_t success; - /* struct peer_handler_args *peer_args = user_data; */ + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; - success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, - NULL, 0, error); - return success; + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + + if (info->wfd_subelems == NULL) + return wpas_dbus_simple_array_property_getter(iter, + DBUS_TYPE_BYTE, + NULL, 0, error); + + return wpas_dbus_simple_array_property_getter( + iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf, + info->wfd_subelems->used, error); +} + + +dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; + + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + + return wpas_dbus_simple_array_property_getter( + iter, DBUS_TYPE_BYTE, (char *) peer_args->p2p_device_addr, + ETH_ALEN, error); } @@ -2407,7 +2449,7 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req( if (req == 0) goto error; - if (!wpas_p2p_sd_cancel_request(wpa_s, req)) + if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0) goto error; return NULL; diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h index a11b3c8d..67e0e9db 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h @@ -147,6 +147,10 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter, DBusError *error, void *user_data); +dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter, + DBusError *error, + void *user_data); + /* * P2P Group properties */ diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index b336afb0..bbcd6620 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -206,6 +206,14 @@ static inline const char * wpa_drv_get_ifname(struct wpa_supplicant *wpa_s) return NULL; } +static inline const char * +wpa_driver_get_radio_name(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->get_radio_name) + return wpa_s->driver->get_radio_name(wpa_s->drv_priv); + return NULL; +} + static inline const u8 * wpa_drv_get_mac_addr(struct wpa_supplicant *wpa_s) { if (wpa_s->driver->get_mac_addr) { diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 487d44d4..6f9f2176 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1622,6 +1622,9 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) wpas_p2p_init_group_interface(wpa_s, res->role_go); if (group_wpa_s == NULL) { wpas_p2p_remove_pending_group_interface(wpa_s); + eloop_cancel_timeout(wpas_p2p_long_listen_timeout, + wpa_s, NULL); + wpas_p2p_group_formation_failed(wpa_s); return; } if (group_wpa_s != wpa_s) { diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 1d8e8a60..48e94b61 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1923,6 +1923,11 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s) interval = wpa_s->conf->sched_scan_interval ? wpa_s->conf->sched_scan_interval : 10; + if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels"); + params.freqs = wpa_s->manual_sched_scan_freqs; + } + ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval); os_free(params.filter_ssids); if (ret == 0) diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 63beaefa..f01844eb 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -968,8 +968,11 @@ static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s, struct ieee80211_2040_intol_chan_report *ic_report; struct wpabuf *buf; - wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR, - MAC2STR(wpa_s->bssid)); + wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR + " (num_channels=%u num_intol=%u)", + MAC2STR(wpa_s->bssid), num_channels, num_intol); + wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels", + chan_list, num_channels); buf = wpabuf_alloc(2 + /* action.category + action_code */ sizeof(struct ieee80211_2040_bss_coex_ie) + @@ -1051,8 +1054,14 @@ int sme_proc_obss_scan(struct wpa_supplicant *wpa_s) ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP); ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0; + wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR + " freq=%u chan=%u ht_cap=0x%x", + MAC2STR(bss->bssid), bss->freq, channel, ht_cap); if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) { + if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT) + num_intol++; + /* Check whether the channel is already considered */ for (i = 0; i < num_channels; i++) { if (channel == chan_list[i]) @@ -1061,9 +1070,6 @@ int sme_proc_obss_scan(struct wpa_supplicant *wpa_s) if (i != num_channels) continue; - if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT) - num_intol++; - chan_list[num_channels++] = channel; } } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 499dcb33..dce1c008 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -460,6 +460,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) os_free(wpa_s->manual_scan_freqs); wpa_s->manual_scan_freqs = NULL; + os_free(wpa_s->manual_sched_scan_freqs); + wpa_s->manual_sched_scan_freqs = NULL; + gas_query_deinit(wpa_s->gas); wpa_s->gas = NULL; @@ -3204,15 +3207,13 @@ static void radio_remove_interface(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s", wpa_s->ifname, radio->name); dl_list_del(&wpa_s->radio_list); - if (!dl_list_empty(&radio->ifaces)) { - wpa_s->radio = NULL; + radio_remove_works(wpa_s, NULL, 0); + wpa_s->radio = NULL; + if (!dl_list_empty(&radio->ifaces)) return; /* Interfaces remain for this radio */ - } wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name); - radio_remove_works(wpa_s, NULL, 0); eloop_cancel_timeout(radio_start_next_work, radio, NULL); - wpa_s->radio = NULL; os_free(radio); } @@ -3361,10 +3362,7 @@ next_driver: os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); } - if (wpa_s->driver->get_radio_name) - rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv); - else - rn = NULL; + rn = wpa_driver_get_radio_name(wpa_s); if (rn && rn[0] == '\0') rn = NULL; @@ -4534,7 +4532,7 @@ int get_shared_radio_freqs(struct wpa_supplicant *wpa_s, } /* If get_radio_name is not supported, use only the local freq */ - if (!wpa_s->driver->get_radio_name) { + if (!wpa_driver_get_radio_name(wpa_s)) { freq = wpa_drv_shared_freq(wpa_s); if (freq > 0 && idx < len && (idx == 0 || freq_array[0] != freq)) diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 739b11f7..8a332866 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -547,6 +547,7 @@ struct wpa_supplicant { int scan_runs; /* number of scan runs since WPS was started */ int *next_scan_freqs; int *manual_scan_freqs; + int *manual_sched_scan_freqs; unsigned int manual_scan_passive:1; unsigned int manual_scan_use_id:1; unsigned int manual_scan_only_new:1; |
