diff options
| author | Steve Kondik <shade@chemlab.org> | 2013-11-07 22:49:49 -0800 |
|---|---|---|
| committer | Steve Kondik <shade@chemlab.org> | 2013-11-07 22:49:49 -0800 |
| commit | b38f0593f59a3973dcea351341fee133122b21d1 (patch) | |
| tree | adc46f70ba699e60f35d4e962d1b7c614aedce9b | |
| parent | df1b44455368d305d40299c6393f4d6b5b4b28a6 (diff) | |
| parent | 0b621177b23952a4574f3cbf160bb36e4d370532 (diff) | |
| download | android_external_wpa_supplicant_8-stable/cm-10.2.tar.gz android_external_wpa_supplicant_8-stable/cm-10.2.tar.bz2 android_external_wpa_supplicant_8-stable/cm-10.2.zip | |
Merge branch 'jb_mr2' of git://codeaurora.org/platform/external/wpa_supplicant_8 into cm-10.2cm-10.2.1cm-10.2.0stable/cm-10.2cm-10.2
| -rw-r--r-- | hostapd/Makefile | 9 | ||||
| -rw-r--r-- | src/p2p/p2p_invitation.c | 4 | ||||
| -rw-r--r-- | src/rsn_supp/wpa.c | 8 | ||||
| -rw-r--r-- | src/wps/wps_enrollee.c | 18 | ||||
| -rw-r--r-- | wpa_supplicant/bss.c | 53 | ||||
| -rw-r--r-- | wpa_supplicant/bss.h | 2 | ||||
| -rw-r--r-- | wpa_supplicant/ctrl_iface.c | 19 | ||||
| -rw-r--r-- | wpa_supplicant/dbus/dbus_new_handlers_p2p.c | 2 | ||||
| -rw-r--r-- | wpa_supplicant/events.c | 70 | ||||
| -rw-r--r-- | wpa_supplicant/p2p_supplicant.c | 117 | ||||
| -rw-r--r-- | wpa_supplicant/p2p_supplicant.h | 3 | ||||
| -rw-r--r-- | wpa_supplicant/scan.c | 37 | ||||
| -rw-r--r-- | wpa_supplicant/scan.h | 2 | ||||
| -rw-r--r-- | wpa_supplicant/wpa_supplicant.c | 4 | ||||
| -rw-r--r-- | wpa_supplicant/wpa_supplicant_i.h | 2 | ||||
| -rw-r--r-- | wpa_supplicant/wpa_supplicant_template.conf | 1 |
16 files changed, 316 insertions, 35 deletions
diff --git a/hostapd/Makefile b/hostapd/Makefile index 8404e0cb..6e422a9e 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -6,6 +6,8 @@ ifndef CFLAGS CFLAGS = -MMD -O2 -Wall -g endif +export BINDIR ?= /usr/local/sbin/ + CFLAGS += -I../src CFLAGS += -I../src/utils @@ -848,9 +850,10 @@ verify_config: exit 1; \ fi -install: all - mkdir -p $(DESTDIR)/usr/local/bin - for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done +$(DESTDIR)$(BINDIR)/%: % + install -D $(<) $(@) + +install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL)) ../src/drivers/build.hostapd: @if [ -f ../src/drivers/build.wpa_supplicant ]; then \ diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c index 11a7727c..858898cf 100644 --- a/src/p2p/p2p_invitation.c +++ b/src/p2p/p2p_invitation.c @@ -507,7 +507,7 @@ int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev, dev->invitation_reqs++; if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, p2p->cfg->dev_addr, dev->info.p2p_device_addr, - wpabuf_head(req), wpabuf_len(req), 200) < 0) { + wpabuf_head(req), wpabuf_len(req), 500) < 0) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to send Action frame"); /* Use P2P find to recover and retry */ @@ -537,7 +537,7 @@ void p2p_invitation_req_cb(struct p2p_data *p2p, int success) */ p2p_set_state(p2p, P2P_INVITE); - p2p_set_timeout(p2p, 0, success ? 350000 : 100000); + p2p_set_timeout(p2p, 0, success ? 500000 : 100000); } diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index e50404ce..ce3f3180 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1132,7 +1132,8 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, goto failed; } - wpa_sm_set_rekey_offload(sm); + if (ie.gtk) + wpa_sm_set_rekey_offload(sm); return; @@ -1353,13 +1354,14 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); wpa_sm_cancel_auth_timeout(sm); wpa_sm_set_state(sm, WPA_COMPLETED); - - wpa_sm_set_rekey_offload(sm); } else { wpa_supplicant_key_neg_complete(sm, sm->bssid, key_info & WPA_KEY_INFO_SECURE); } + + wpa_sm_set_rekey_offload(sm); + return; failed: diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 9a62fce8..ae17a278 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -852,6 +852,24 @@ static int wps_process_dev_pw_id(struct wps_data *wps, const u8 *dev_pw_id) return 0; } +#ifdef CONFIG_P2P + if ((id == DEV_PW_DEFAULT && + wps->dev_pw_id == DEV_PW_REGISTRAR_SPECIFIED) || + (id == DEV_PW_REGISTRAR_SPECIFIED && + wps->dev_pw_id == DEV_PW_DEFAULT)) { + /* + * Common P2P use cases indicate whether the PIN is from the + * client or GO using Device Password Id in M1/M2 in a way that + * does not look fully compliant with WSC specification. Anyway, + * this is deployed and needs to be allowed, so ignore changes + * between Registrar-Specified and Default PIN. + */ + wpa_printf(MSG_DEBUG, "WPS: Allow PIN Device Password ID " + "change"); + return 0; + } +#endif /* CONFIG_P2P */ + wpa_printf(MSG_DEBUG, "WPS: Registrar trying to change Device Password " "ID from %u to %u", wps->dev_pw_id, id); diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 0e1576b0..caec1bae 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -501,6 +501,22 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, wpa_bss_copy_res(bss, res, fetch_time); /* Move the entry to the end of the list */ dl_list_del(&bss->list); +#ifdef CONFIG_P2P + if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE)) { + /* + * This can happen when non-P2P station interface runs a scan + * without P2P IE in the Probe Request frame. P2P GO would reply + * to that with a Probe Response that does not include P2P IE. + * Do not update the IEs in this BSS entry to avoid such loss of + * information that may be needed for P2P operations to + * determine group information. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Do not update scan IEs for " + MACSTR " since that would remove P2P IE information", + MAC2STR(bss->bssid)); + } else +#endif /* CONFIG_P2P */ if (bss->ie_len + bss->beacon_ie_len >= res->ie_len + res->beacon_ie_len) { os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); @@ -1001,6 +1017,43 @@ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) /** + * wpa_bss_get_vendor_ie_beacon - Fetch a vendor information from a BSS entry + * @bss: BSS table entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the BSS + * entry. + * + * This function is like wpa_bss_get_vendor_ie(), but uses IE buffer only + * from Beacon frames instead of either Beacon or Probe Response frames. + */ +const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, + u32 vendor_type) +{ + const u8 *end, *pos; + + if (bss->beacon_ie_len == 0) + return NULL; + + pos = (const u8 *) (bss + 1); + pos += bss->ie_len; + end = pos + bss->beacon_ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** * wpa_bss_get_vendor_ie_multi - Fetch vendor IE data from a BSS entry * @bss: BSS table entry * @vendor_type: Vendor type (four octets starting the IE payload) diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 2b419488..0d2693fd 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -118,6 +118,8 @@ struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, unsigned int idf, unsigned int idl); const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); +const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, + u32 vendor_type); struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, u32 vendor_type); struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss, diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index b06b90cd..ee7fbd63 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -572,6 +572,7 @@ static int wpa_supplicant_ctrl_iface_tdls_teardown( struct wpa_supplicant *wpa_s, char *addr) { u8 peer[ETH_ALEN]; + int ret; if (hwaddr_aton(addr, peer)) { wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " @@ -582,8 +583,14 @@ static int wpa_supplicant_ctrl_iface_tdls_teardown( wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, MAC2STR(peer)); - return wpa_tdls_teardown_link(wpa_s->wpa, peer, - WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); + if (wpa_tdls_is_external_setup(wpa_s->wpa)) + ret = wpa_tdls_teardown_link( + wpa_s->wpa, peer, + WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); + else + ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); + + return ret; } #endif /* CONFIG_TDLS */ @@ -2015,6 +2022,8 @@ static int wpa_supplicant_ctrl_iface_scan_result( const u8 *ie, *ie2, *p2p; p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); + if (!p2p) + p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE); if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) @@ -3259,7 +3268,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, return 0; pos += ret; } - if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) { + if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || + wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { ret = os_snprintf(pos, end - pos, "[P2P]"); if (ret < 0 || ret >= end - pos) return 0; @@ -4202,7 +4212,8 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, return -1; } - return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40, NULL); + return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40, NULL, + 0); } diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c index 6ec96dfe..52b36b4a 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c @@ -347,7 +347,7 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message, goto inv_args; if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, - NULL)) { + NULL, 0)) { reply = wpas_dbus_error_unknown_error( message, "Failed to reinvoke a persistent group"); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 184b14ef..d0e3f4ab 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -688,10 +688,13 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, rsn_ie_len = ie ? ie[1] : 0; wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' " - "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s", + "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s%s", i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), wpa_ie_len, rsn_ie_len, bss->caps, bss->level, - wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : ""); + wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "", + (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || + wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ? + " p2p" : ""); e = wpa_blacklist_get(wpa_s, bss->bssid); if (e) { @@ -829,6 +832,13 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, } #ifdef CONFIG_P2P + if (ssid->p2p_group && + !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P IE seen"); + continue; + } + /* * TODO: skip the AP if its P2P IE has Group Formation * bit set in the P2P Group Capability Bitmap and we @@ -2396,6 +2406,51 @@ static void wpa_supplicant_event_unprot_disassoc(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IEEE80211W */ } +static void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s) +{ + const char *rn, *rn2; + struct wpa_supplicant *ifs; + + if (wpa_s->drv_priv == NULL) + return; /* Ignore event during drv initialization */ + + free_hw_features(wpa_s); + wpa_s->hw.modes = wpa_drv_get_hw_feature_data( + wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags); + +#ifdef CONFIG_P2P + wpas_p2p_update_channel_list(wpa_s); +#endif /* CONFIG_P2P */ + + /* + * Check other interfaces to see if they have the same radio-name. If + * so, they get updated with this same hw mode info. + */ + if (!wpa_s->driver->get_radio_name) + return; + + rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv); + if (rn == NULL || rn[0] == '\0') + return; + + wpa_dbg(wpa_s, MSG_DEBUG, "Checking for other virtual interfaces " + "sharing same radio (%s) in event_channel_list_change", rn); + + for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) { + if (ifs == wpa_s || !ifs->driver->get_radio_name) + continue; + + rn2 = ifs->driver->get_radio_name(ifs->drv_priv); + if (rn2 && os_strcmp(rn, rn2) == 0) { + wpa_printf(MSG_DEBUG, "%s: Updating hw mode", + ifs->ifname); + free_hw_features(ifs); + ifs->hw.modes = wpa_drv_get_hw_feature_data( + ifs, &ifs->hw.num_modes, &ifs->hw.flags); + } + } +} + void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) @@ -2958,16 +3013,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); break; case EVENT_CHANNEL_LIST_CHANGED: - if (wpa_s->drv_priv == NULL) - break; /* Ignore event during drv initialization */ - - free_hw_features(wpa_s); - wpa_s->hw.modes = wpa_drv_get_hw_feature_data( - wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags); - -#ifdef CONFIG_P2P - wpas_p2p_update_channel_list(wpa_s); -#endif /* CONFIG_P2P */ + wpa_supplicant_update_channel_list(wpa_s); break; case EVENT_INTERFACE_UNAVAILABLE: #ifdef CONFIG_P2P diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 7216c3aa..ae26867f 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -71,6 +71,15 @@ #define P2P_MAX_INITIAL_CONN_WAIT_GO 10 #endif /* P2P_MAX_INITIAL_CONN_WAIT_GO */ +#ifndef P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE +/* + * How many seconds to wait for initial 4-way handshake to get completed after + * re-invocation of a persistent group on the GO when the client is expected + * to connect automatically (no user interaction). + */ +#define P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE 15 +#endif /* P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE */ + #ifndef P2P_CONCURRENT_SEARCH_DELAY #define P2P_CONCURRENT_SEARCH_DELAY 500 #endif /* P2P_CONCURRENT_SEARCH_DELAY */ @@ -137,13 +146,28 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; struct os_time time_tmp_age, entry_ts; + const u8 *ies; + size_t ies_len; + time_tmp_age.sec = bss->age / 1000; time_tmp_age.usec = (bss->age % 1000) * 1000; os_time_sub(&scan_res->fetch_time, &time_tmp_age, &entry_ts); + + ies = (const u8 *) (bss + 1); + ies_len = bss->ie_len; + if (bss->beacon_ie_len > 0 && + !wpa_scan_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + wpa_scan_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { + wpa_printf(MSG_DEBUG, "P2P: Use P2P IE(s) from Beacon frame since no P2P IE(s) in Probe Response frames received for " + MACSTR, MAC2STR(bss->bssid)); + ies = ies + ies_len; + ies_len = bss->beacon_ie_len; + } + + if (p2p_scan_res_handler(wpa_s->global->p2p, bss->bssid, bss->freq, &entry_ts, bss->level, - (const u8 *) (bss + 1), - bss->ie_len) > 0) + ies, ies_len) > 0) break; } @@ -372,6 +396,12 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, wpa_s->p2p_in_provisioning = 0; } + /* + * Make sure wait for the first client does not remain active after the + * group has been removed. + */ + wpa_s->global->p2p_go_wait_client.sec = 0; + if (removal_reason != P2P_GROUP_REMOVAL_SILENT && ssid) wpas_notify_p2p_group_removed(wpa_s, ssid, gtype); @@ -392,6 +422,11 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, return 1; } + if (!wpa_s->p2p_go_group_formation_completed) { + wpa_s->global->p2p_group_formation = NULL; + wpa_s->p2p_in_provisioning = 0; + } + wpa_printf(MSG_DEBUG, "P2P: Remove temporary group network"); if (ssid && (ssid->p2p_group || ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION || @@ -458,6 +493,9 @@ static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s, } p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE); + if (p2p == NULL) + p2p = wpa_bss_get_vendor_ie_multi_beacon(bss, + P2P_IE_VENDOR_TYPE); if (p2p == NULL) { wpa_printf(MSG_DEBUG, "P2P: Could not figure out whether " "group is persistent - BSS " MACSTR @@ -663,8 +701,10 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, */ if (wpa_s->global->p2p_group_formation) wpa_s = wpa_s->global->p2p_group_formation; - wpa_s->global->p2p_group_formation = NULL; - wpa_s->p2p_in_provisioning = 0; + if (wpa_s->p2p_go_group_formation_completed) { + wpa_s->global->p2p_group_formation = NULL; + wpa_s->p2p_in_provisioning = 0; + } if (!success) { wpa_msg(wpa_s->parent, MSG_INFO, @@ -883,6 +923,7 @@ static void p2p_go_configured(void *ctx, void *data) ""); } + os_get_time(&wpa_s->global->p2p_go_wait_client); if (params->persistent_group) network_id = wpas_p2p_store_persistent_group( wpa_s->parent, ssid, @@ -892,6 +933,21 @@ static void p2p_go_configured(void *ctx, void *data) wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0); wpas_p2p_cross_connect_setup(wpa_s); wpas_p2p_set_group_idle_timeout(wpa_s); + + if (wpa_s->p2p_first_connection_timeout) { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Start group formation timeout of %d seconds until first data connection on GO", + wpa_s->p2p_first_connection_timeout); + 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); + eloop_register_timeout( + wpa_s->p2p_first_connection_timeout, 0, + wpas_p2p_group_formation_timeout, + wpa_s->parent, NULL); + } + return; } @@ -2574,7 +2630,8 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid, if (s) { int go = s->mode == WPAS_MODE_P2P_GO; wpas_p2p_group_add_persistent( - wpa_s, s, go, go ? op_freq : 0, 0, NULL); + wpa_s, s, go, go ? op_freq : 0, 0, NULL, + go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0); } else if (bssid) { wpa_s->user_initiated_pd = 0; wpas_p2p_join(wpa_s, bssid, go_dev_addr, @@ -2745,7 +2802,10 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid, wpas_p2p_group_add_persistent(wpa_s, ssid, ssid->mode == WPAS_MODE_P2P_GO, wpa_s->p2p_persistent_go_freq, - wpa_s->p2p_go_ht40, channels); + wpa_s->p2p_go_ht40, channels, + ssid->mode == WPAS_MODE_P2P_GO ? + P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : + 0); } @@ -4324,6 +4384,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated, if (!wpas_p2p_create_iface(wpa_s)) { wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group " "operations"); + wpa_s->p2p_first_connection_timeout = 0; return wpa_s; } @@ -4342,6 +4403,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated, wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s", group_wpa_s->ifname); + group_wpa_s->p2p_first_connection_timeout = 0; return group_wpa_s; } @@ -4440,7 +4502,8 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s, int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int addr_allocated, int freq, int ht40, - const struct p2p_channels *channels) + const struct p2p_channels *channels, + int connection_timeout) { struct p2p_go_neg_results params; int go = 0; @@ -4494,6 +4557,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, if (wpa_s == NULL) return -1; + wpa_s->p2p_first_connection_timeout = connection_timeout; wpas_start_wps_go(wpa_s, ¶ms, 0); return 0; @@ -4601,6 +4665,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent, NULL); + wpa_s->p2p_go_group_formation_completed = 1; if (ssid && ssid->mode == WPAS_MODE_INFRA) { /* * Use a separate timeout for initial data connection to @@ -4608,9 +4673,28 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, * something goes wrong in this step before the P2P group idle * timeout mechanism is taken into use. */ + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Re-start group formation timeout (%d seconds) as client for initial connection", + P2P_MAX_INITIAL_CONN_WAIT); eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0, wpas_p2p_group_formation_timeout, wpa_s->parent, NULL); + } else if (ssid) { + /* + * Use a separate timeout for initial data connection to + * complete to allow the group to be removed automatically if + * the client does not complete data connection successfully. + */ + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Re-start group formation timeout (%d seconds) as GO for initial connection", + 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); + /* + * Complete group formation on first successful data connection + */ + wpa_s->p2p_go_group_formation_completed = 0; } if (wpa_s->global->p2p) p2p_wps_success_cb(wpa_s->global->p2p, peer_addr); @@ -5832,6 +5916,25 @@ struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s, 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) { + /* + * This can happen if WPS provisioning step is not terminated + * cleanly (e.g., P2P Client does not send WSC_Done). Since the + * peer was able to connect, there is no need to time out group + * formation after this, though. In addition, this is used with + * the initial connection wait on the GO as a separate formation + * timeout and as such, expected to be hit after the initial WPS + * provisioning step. + */ + wpa_printf(MSG_DEBUG, "P2P: Canceled P2P group formation timeout on data connection"); + } + if (!wpa_s->p2p_go_group_formation_completed) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Marking group formation completed on GO on first data connection"); + wpa_s->p2p_go_group_formation_completed = 1; + wpa_s->global->p2p_group_formation = NULL; + wpa_s->p2p_in_provisioning = 0; + } wpa_s->global->p2p_go_wait_client.sec = 0; if (addr == NULL) return; diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 04ba9b20..db4cadb6 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -37,7 +37,8 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int addr_allocated, int freq, int ht40, - const struct p2p_channels *channels); + const struct p2p_channels *channels, + int connection_timeout); struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 07e3e06c..25717477 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1345,6 +1345,43 @@ const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, /** + * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result + * @res: Scan result entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the scan + * result. + * + * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only + * from Beacon frames instead of either Beacon or Probe Response frames. + */ +const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, + u32 vendor_type) +{ + const u8 *end, *pos; + + if (res->beacon_ie_len == 0) + return NULL; + + pos = (const u8 *) (res + 1); + pos += res->ie_len; + end = pos + res->beacon_ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result * @res: Scan result entry * @vendor_type: Vendor type (four octets starting the IE payload) diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h index e892479f..6eeb19a9 100644 --- a/wpa_supplicant/scan.h +++ b/wpa_supplicant/scan.h @@ -28,6 +28,8 @@ int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s); const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie); const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, u32 vendor_type); +const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, + u32 vendor_type); struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, u32 vendor_type); int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 15e35f86..c3b70f08 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1812,7 +1812,7 @@ static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s, * Try to reassociate since there is no current configuration and a new * network was made available. */ - if (!wpa_s->current_ssid) + if (!wpa_s->current_ssid && !wpa_s->disconnected) wpa_s->reassociate = 1; } @@ -1833,7 +1833,7 @@ void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, } else wpa_supplicant_enable_one_network(wpa_s, ssid); - if (wpa_s->reassociate) { + if (wpa_s->reassociate && !wpa_s->disconnected) { if (wpa_s->sched_scanning) { wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add " "new network to scan filters"); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index c7623ac4..2a8a381a 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -632,6 +632,8 @@ struct wpa_supplicant { unsigned int p2p_pd_before_go_neg:1; unsigned int p2p_go_ht40:1; unsigned int user_initiated_pd:1; + unsigned int p2p_go_group_formation_completed:1; + int p2p_first_connection_timeout; int p2p_persistent_go_freq; int p2p_persistent_id; int p2p_go_intent; diff --git a/wpa_supplicant/wpa_supplicant_template.conf b/wpa_supplicant/wpa_supplicant_template.conf index eee48a77..9828679f 100644 --- a/wpa_supplicant/wpa_supplicant_template.conf +++ b/wpa_supplicant/wpa_supplicant_template.conf @@ -6,3 +6,4 @@ ap_scan=1 fast_reauth=1 ### flag to avoid creating new interface for p2p p2p_no_group_iface=1 +disable_scan_offload=1 |
