示例#1
0
文件: wnm_sta.c 项目: gxk/hostap
static void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s,
			       struct wpa_bss *bss, struct wpa_ssid *ssid,
			       int after_new_scan)
{
	wpa_dbg(wpa_s, MSG_DEBUG,
		"WNM: Transition to BSS " MACSTR
		" based on BSS Transition Management Request (old BSSID "
		MACSTR " after_new_scan=%d)",
		MAC2STR(bss->bssid), MAC2STR(wpa_s->bssid), after_new_scan);

	/* Send the BSS Management Response - Accept */
	if (wpa_s->wnm_reply) {
		wpa_s->wnm_reply = 0;
		wpa_printf(MSG_DEBUG,
			   "WNM: Sending successful BSS Transition Management Response");
		wnm_send_bss_transition_mgmt_resp(
			wpa_s, wpa_s->wnm_dialog_token, WNM_BSS_TM_ACCEPT,
			MBO_TRANSITION_REASON_UNSPECIFIED, 0, bss->bssid);
	}

	if (bss == wpa_s->current_bss) {
		wpa_printf(MSG_DEBUG,
			   "WNM: Already associated with the preferred candidate");
		wnm_deallocate_memory(wpa_s);
		return;
	}

	wpa_s->reassociate = 1;
	wpa_printf(MSG_DEBUG, "WNM: Issuing connect");
	wpa_supplicant_connect(wpa_s, bss, ssid);
	wnm_deallocate_memory(wpa_s);
}
示例#2
0
void wnm_scan_response(struct wpa_supplicant *wpa_s,
		       struct wpa_scan_results *scan_res)
{
	u8 bssid[ETH_ALEN];

	if (scan_res == NULL) {
		wpa_printf(MSG_ERROR, "Scan result is NULL");
		goto send_bss_resp_fail;
	}

	/* Compare the Neighbor Report and scan results */
	if (compare_scan_neighbor_results(wpa_s, scan_res,
					  wpa_s->wnm_neighbor_report_elements,
					  wpa_s->wnm_num_neighbor_report,
					  bssid) == 1) {
		/* Associate to the network */
		struct wpa_bss *bss;
		struct wpa_ssid *ssid = wpa_s->current_ssid;

		bss = wpa_bss_get_bssid(wpa_s, bssid);
		if (!bss) {
			wpa_printf(MSG_DEBUG, "WNM: Target AP not found from "
				   "BSS table");
			goto send_bss_resp_fail;
		}

		/* Send the BSS Management Response - Accept */
		if (wpa_s->wnm_reply) {
			wnm_send_bss_transition_mgmt_resp(wpa_s,
						  wpa_s->wnm_dialog_token,
						  WNM_BSS_TM_ACCEPT,
						  0, bssid);
		}

		wpa_s->reassociate = 1;
		wpa_supplicant_connect(wpa_s, bss, ssid);
		wnm_deallocate_memory(wpa_s);
		return;
	}

	/* Send reject response for all the failures */
send_bss_resp_fail:
	wnm_deallocate_memory(wpa_s);
	if (wpa_s->wnm_reply) {
		wnm_send_bss_transition_mgmt_resp(wpa_s,
						  wpa_s->wnm_dialog_token,
						  WNM_BSS_TM_REJECT_UNSPECIFIED,
						  0, NULL);
	}
	return;
}
void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
			    union wpa_event_data *data)
{
	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
		"status code %d", MAC2STR(wpa_s->pending_bssid),
		data->assoc_reject.status_code);

	eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);

#ifdef CONFIG_SAE
	if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
	    wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
		wpa_dbg(wpa_s, MSG_DEBUG,
			"PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
		wpa_sm_aborted_cached(wpa_s->wpa);
		wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
		if (wpa_s->current_bss) {
			struct wpa_bss *bss = wpa_s->current_bss;
			struct wpa_ssid *ssid = wpa_s->current_ssid;

			wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
					       WLAN_REASON_DEAUTH_LEAVING);
			wpas_connect_work_done(wpa_s);
			wpa_supplicant_mark_disassoc(wpa_s);
			wpa_supplicant_connect(wpa_s, bss, ssid);
			return;
		}
	}
#endif /* CONFIG_SAE */

	/*
	 * For now, unconditionally terminate the previous authentication. In
	 * theory, this should not be needed, but mac80211 gets quite confused
	 * if the authentication is left pending.. Some roaming cases might
	 * benefit from using the previous authentication, so this could be
	 * optimized in the future.
	 */
	sme_deauth(wpa_s);
}
示例#4
0
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
					      union wpa_event_data *data)
{
	struct wpa_bss *selected;
	struct wpa_ssid *ssid = NULL;
	struct wpa_scan_results *scan_res;
	int ap = 0;

#ifdef CONFIG_AP
	if (wpa_s->ap_iface)
		ap = 1;
#endif /* CONFIG_AP */

	wpa_supplicant_notify_scanning(wpa_s, 0);

	scan_res = wpa_supplicant_get_scan_results(wpa_s,
						   data ? &data->scan_info :
						   NULL, 1);
	if (scan_res == NULL) {
		if (wpa_s->conf->ap_scan == 2 || ap)
			return;
		wpa_printf(MSG_DEBUG, "Failed to get scan results - try "
			   "scanning again");
		wpa_supplicant_req_new_scan(wpa_s, 1, 0);
		return;
	}

	if (wpa_s->scan_res_handler) {
		wpa_s->scan_res_handler(wpa_s, scan_res);
		wpa_s->scan_res_handler = NULL;
		wpa_scan_results_free(scan_res);
		return;
	}

	if (ap) {
		wpa_printf(MSG_DEBUG, "Ignore scan results in AP mode");
		wpa_scan_results_free(scan_res);
		return;
	}

	wpa_printf(MSG_DEBUG, "New scan results available");
	wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
	wpas_notify_scan_results(wpa_s);

	wpas_notify_scan_done(wpa_s, 1);

	if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) {
		wpa_scan_results_free(scan_res);
		return;
	}

	if (wpa_s->disconnected) {
		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
		wpa_scan_results_free(scan_res);
		return;
	}

	wpa_supplicant_rsn_preauth_scan_results(wpa_s, scan_res);

	selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid);

	if (selected) {
		int skip;
		skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid,
						    scan_res);
		wpa_scan_results_free(scan_res);
		if (skip)
			return;
		wpa_supplicant_connect(wpa_s, selected, ssid);
	} else {
		wpa_scan_results_free(scan_res);
		wpa_printf(MSG_DEBUG, "No suitable network found");
		ssid = wpa_supplicant_pick_new_network(wpa_s);
		if (ssid) {
			wpa_printf(MSG_DEBUG, "Setup a new network");
			wpa_supplicant_associate(wpa_s, NULL, ssid);
		} else {
			int timeout_sec = 5;
			int timeout_usec = 0;
#ifdef CONFIG_P2P
			if (wpa_s->p2p_in_provisioning) {
				/*
				 * Use shorter wait during P2P Provisioning
				 * state to speed up group formation.
				 */
				timeout_sec = 0;
				timeout_usec = 250000;
			}
#endif /* CONFIG_P2P */
			wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
						    timeout_usec);
		}
	}
}
示例#5
0
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail)
{
	struct wpa_bss *bss;
	struct wpa_ssid *ssid = wpa_s->current_ssid;
	enum bss_trans_mgmt_status_code status = WNM_BSS_TM_REJECT_UNSPECIFIED;

	if (!wpa_s->wnm_neighbor_report_elements)
		return 0;

	if (os_reltime_before(&wpa_s->wnm_cand_valid_until,
			      &wpa_s->scan_trigger_time)) {
		wpa_printf(MSG_DEBUG, "WNM: Previously stored BSS transition candidate list is not valid anymore - drop it");
		wnm_deallocate_memory(wpa_s);
		return 0;
	}

	if (!wpa_s->current_bss ||
	    os_memcmp(wpa_s->wnm_cand_from_bss, wpa_s->current_bss->bssid,
		      ETH_ALEN) != 0) {
		wpa_printf(MSG_DEBUG, "WNM: Stored BSS transition candidate list not from the current BSS - ignore it");
		return 0;
	}

	/* Compare the Neighbor Report and scan results */
	bss = compare_scan_neighbor_results(wpa_s);
	if (!bss) {
		wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
		status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
		goto send_bss_resp_fail;
	}

	/* Associate to the network */
	/* Send the BSS Management Response - Accept */
	if (wpa_s->wnm_reply) {
		wpa_s->wnm_reply = 0;
		wnm_send_bss_transition_mgmt_resp(wpa_s,
						  wpa_s->wnm_dialog_token,
						  WNM_BSS_TM_ACCEPT,
						  0, bss->bssid);
	}

	if (bss == wpa_s->current_bss) {
		wpa_printf(MSG_DEBUG,
			   "WNM: Already associated with the preferred candidate");
		return 1;
	}

	wpa_s->reassociate = 1;
	wpa_supplicant_connect(wpa_s, bss, ssid);
	wnm_deallocate_memory(wpa_s);
	return 1;

send_bss_resp_fail:
	if (!reply_on_fail)
		return 0;

	/* Send reject response for all the failures */

	if (wpa_s->wnm_reply) {
		wpa_s->wnm_reply = 0;
		wnm_send_bss_transition_mgmt_resp(wpa_s,
						  wpa_s->wnm_dialog_token,
						  status, 0, NULL);
	}
	wnm_deallocate_memory(wpa_s);

	return 0;
}
示例#6
0
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
					      union wpa_event_data *data)
{
	struct wpa_bss *selected;
	struct wpa_ssid *ssid = NULL;
	struct wpa_scan_results *scan_res;

	wpa_supplicant_notify_scanning(wpa_s, 0);

	scan_res = wpa_supplicant_get_scan_results(wpa_s,
						   data ? &data->scan_info :
						   NULL, 1);
	if (scan_res == NULL) {
		if (wpa_s->conf->ap_scan == 2)
			return;
		wpa_printf(MSG_DEBUG, "Failed to get scan results - try "
			   "scanning again");
		wpa_supplicant_req_new_scan(wpa_s, 1);
		return;
	}

	/*
	 * Don't post the results if this was the initial cached
	 * and there were no results.
	 */
	if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1 &&
	    scan_res->num == 0) {
		wpa_msg(wpa_s, MSG_DEBUG, "Cached scan results are "
			"empty - not posting");
	} else {
		wpa_printf(MSG_DEBUG, "New scan results available");
		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
		wpas_notify_scan_results(wpa_s);
	}

	wpas_notify_scan_done(wpa_s, 1);

	if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) {
		wpa_scan_results_free(scan_res);
		return;
	}

	if (wpa_s->disconnected) {
		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
		wpa_scan_results_free(scan_res);
		return;
	}

	if (bgscan_notify_scan(wpa_s) == 1) {
		wpa_scan_results_free(scan_res);
		return;
	}

	wpa_supplicant_rsn_preauth_scan_results(wpa_s, scan_res);

	selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid);

	if (selected) {
		int skip;
		skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid,
						    scan_res);
		wpa_scan_results_free(scan_res);
		if (skip)
			return;
		wpa_supplicant_connect(wpa_s, selected, ssid);
	} else {
		wpa_scan_results_free(scan_res);
		wpa_printf(MSG_DEBUG, "No suitable network found");
		ssid = wpa_supplicant_pick_new_network(wpa_s);
		if (ssid) {
			wpa_printf(MSG_DEBUG, "Setup a new network");
			wpa_supplicant_associate(wpa_s, NULL, ssid);
		} else
			wpa_supplicant_req_new_scan(wpa_s, 5);
	}
}