P2P: Run a scan before provision discovery in p2p_connect join
This is needed to make sure we have fresh BSS information for the GO.
This commit is contained in:
		
							parent
							
								
									c381508d88
								
							
						
					
					
						commit
						ef922c4a34
					
				
					 1 changed files with 96 additions and 16 deletions
				
			
		|  | @ -40,6 +40,7 @@ static struct wpa_supplicant * | ||||||
| wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated, | wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated, | ||||||
| 			 int go); | 			 int go); | ||||||
| static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s); | static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s); | ||||||
|  | static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx); | ||||||
| static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s); | static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -2141,6 +2142,7 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) | ||||||
| 	wpa_s->pending_action_tx = NULL; | 	wpa_s->pending_action_tx = NULL; | ||||||
| 	eloop_cancel_timeout(wpas_send_action_cb, wpa_s, NULL); | 	eloop_cancel_timeout(wpas_send_action_cb, wpa_s, NULL); | ||||||
| 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL); | 	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL); | ||||||
|  | 	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); | ||||||
| 	wpa_s->p2p_long_listen = 0; | 	wpa_s->p2p_long_listen = 0; | ||||||
| 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); | 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); | ||||||
| 	wpas_p2p_remove_pending_group_interface(wpa_s); | 	wpas_p2p_remove_pending_group_interface(wpa_s); | ||||||
|  | @ -2230,33 +2232,33 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, | static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, | ||||||
| 			 const u8 *dev_addr, enum p2p_wps_method wps_method) | 				   struct wpa_scan_results *scan_res) | ||||||
| { | { | ||||||
| 	struct wpa_bss *bss; | 	struct wpa_bss *bss; | ||||||
| 
 | 
 | ||||||
| 	wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface " | 	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); | ||||||
| 		   MACSTR " dev " MACSTR ")", |  | ||||||
| 		   MAC2STR(iface_addr), MAC2STR(dev_addr)); |  | ||||||
| 
 | 
 | ||||||
| 	os_memcpy(wpa_s->pending_join_iface_addr, iface_addr, ETH_ALEN); | 	if (wpa_s->global->p2p_disabled) | ||||||
| 	os_memcpy(wpa_s->pending_join_dev_addr, dev_addr, ETH_ALEN); | 		return; | ||||||
| 	wpa_s->pending_join_wps_method = wps_method; |  | ||||||
| 
 | 
 | ||||||
| 	/* Make sure we are not running find during connection establishment */ | 	wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS) for join", | ||||||
| 	wpas_p2p_stop_find(wpa_s); | 		   scan_res ? (int) scan_res->num : -1); | ||||||
| 
 | 
 | ||||||
| 	bss = wpa_bss_get_bssid(wpa_s, iface_addr); | 	if (scan_res) | ||||||
|  | 		wpas_p2p_scan_res_handler(wpa_s, scan_res); | ||||||
|  | 
 | ||||||
|  | 	bss = wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr); | ||||||
| 	if (bss) { | 	if (bss) { | ||||||
| 		u16 method; | 		u16 method; | ||||||
| 
 | 
 | ||||||
| 		wpa_printf(MSG_DEBUG, "P2P: Send Provision Discovery Request " | 		wpa_printf(MSG_DEBUG, "P2P: Send Provision Discovery Request " | ||||||
| 			   "prior to joining an existing group (GO " MACSTR | 			   "prior to joining an existing group (GO " MACSTR | ||||||
| 			   " freq=%u MHz)", | 			   " freq=%u MHz)", | ||||||
| 			   MAC2STR(dev_addr), bss->freq); | 			   MAC2STR(wpa_s->pending_join_dev_addr), bss->freq); | ||||||
| 		wpa_s->pending_pd_before_join = 1; | 		wpa_s->pending_pd_before_join = 1; | ||||||
| 
 | 
 | ||||||
| 		switch (wps_method) { | 		switch (wpa_s->pending_join_wps_method) { | ||||||
| 		case WPS_PIN_LABEL: | 		case WPS_PIN_LABEL: | ||||||
| 		case WPS_PIN_DISPLAY: | 		case WPS_PIN_DISPLAY: | ||||||
| 			method = WPS_CONFIG_KEYPAD; | 			method = WPS_CONFIG_KEYPAD; | ||||||
|  | @ -2272,7 +2274,8 @@ static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (p2p_prov_disc_req(wpa_s->global->p2p, dev_addr, method, 1) | 		if (p2p_prov_disc_req(wpa_s->global->p2p, | ||||||
|  | 				      wpa_s->pending_join_dev_addr, method, 1) | ||||||
| 		    < 0) { | 		    < 0) { | ||||||
| 			wpa_printf(MSG_DEBUG, "P2P: Failed to send Provision " | 			wpa_printf(MSG_DEBUG, "P2P: Failed to send Provision " | ||||||
| 				   "Discovery Request before joining an " | 				   "Discovery Request before joining an " | ||||||
|  | @ -2285,7 +2288,7 @@ static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, | ||||||
| 		 * Actual join operation will be started from the Action frame | 		 * Actual join operation will be started from the Action frame | ||||||
| 		 * TX status callback. | 		 * TX status callback. | ||||||
| 		 */ | 		 */ | ||||||
| 		return 0; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	wpa_printf(MSG_DEBUG, "P2P: Target BSS/GO not yet in BSS table - " | 	wpa_printf(MSG_DEBUG, "P2P: Target BSS/GO not yet in BSS table - " | ||||||
|  | @ -2293,7 +2296,83 @@ static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, | ||||||
| 
 | 
 | ||||||
| start: | start: | ||||||
| 	/* Start join operation immediately */ | 	/* Start join operation immediately */ | ||||||
| 	return wpas_p2p_join_start(wpa_s); | 	wpas_p2p_join_start(wpa_s); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx) | ||||||
|  | { | ||||||
|  | 	struct wpa_supplicant *wpa_s = eloop_ctx; | ||||||
|  | 	int ret; | ||||||
|  | 	struct wpa_driver_scan_params params; | ||||||
|  | 	struct wpabuf *wps_ie, *ies; | ||||||
|  | 
 | ||||||
|  | 	os_memset(¶ms, 0, sizeof(params)); | ||||||
|  | 
 | ||||||
|  | 	/* P2P Wildcard SSID */ | ||||||
|  | 	params.num_ssids = 1; | ||||||
|  | 	params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID; | ||||||
|  | 	params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN; | ||||||
|  | 
 | ||||||
|  | 	wpa_s->wps->dev.p2p = 1; | ||||||
|  | 	wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid, | ||||||
|  | 					WPS_REQ_ENROLLEE); | ||||||
|  | 	if (wps_ie == NULL) { | ||||||
|  | 		wpas_p2p_scan_res_join(wpa_s, NULL); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ies = wpabuf_alloc(wpabuf_len(wps_ie) + 100); | ||||||
|  | 	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); | ||||||
|  | 
 | ||||||
|  | 	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. | ||||||
|  | 	 */ | ||||||
|  | 	wpa_s->scan_res_handler = wpas_p2p_scan_res_join; | ||||||
|  | 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) | ||||||
|  | 		ret = ieee80211_sta_req_scan(wpa_s, ¶ms); | ||||||
|  | 	else | ||||||
|  | 		ret = wpa_drv_scan(wpa_s, ¶ms); | ||||||
|  | 
 | ||||||
|  | 	wpabuf_free(ies); | ||||||
|  | 
 | ||||||
|  | 	if (ret) { | ||||||
|  | 		wpa_printf(MSG_DEBUG, "P2P: Failed to start scan for join - " | ||||||
|  | 			   "try again later"); | ||||||
|  | 		eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); | ||||||
|  | 		eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, | ||||||
|  | 			 const u8 *dev_addr, enum p2p_wps_method wps_method) | ||||||
|  | { | ||||||
|  | 	wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface " | ||||||
|  | 		   MACSTR " dev " MACSTR ")", | ||||||
|  | 		   MAC2STR(iface_addr), MAC2STR(dev_addr)); | ||||||
|  | 
 | ||||||
|  | 	os_memcpy(wpa_s->pending_join_iface_addr, iface_addr, ETH_ALEN); | ||||||
|  | 	os_memcpy(wpa_s->pending_join_dev_addr, dev_addr, ETH_ALEN); | ||||||
|  | 	wpa_s->pending_join_wps_method = wps_method; | ||||||
|  | 
 | ||||||
|  | 	/* Make sure we are not running find during connection establishment */ | ||||||
|  | 	wpas_p2p_stop_find(wpa_s); | ||||||
|  | 
 | ||||||
|  | 	wpas_p2p_join_scan(wpa_s, NULL); | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -2818,6 +2897,7 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, | ||||||
| void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s) | void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s) | ||||||
| { | { | ||||||
| 	wpa_s->p2p_long_listen = 0; | 	wpa_s->p2p_long_listen = 0; | ||||||
|  | 	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); | ||||||
| 
 | 
 | ||||||
| 	p2p_stop_find(wpa_s->global->p2p); | 	p2p_stop_find(wpa_s->global->p2p); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Jouni Malinen
						Jouni Malinen