示例#1
0
文件: wnm_sta.c 项目: gxk/hostap
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;
	enum mbo_transition_reject_reason reason =
		MBO_TRANSITION_REJECT_REASON_UNSPECIFIED;

	if (!wpa_s->wnm_neighbor_report_elements)
		return 0;

	wpa_dbg(wpa_s, MSG_DEBUG,
		"WNM: Process scan results for BSS Transition Management");
	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, 0, &reason);
	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 */
	wnm_bss_tm_connect(wpa_s, bss, ssid, 1);
	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, reason, 0, NULL);
	}
	wnm_deallocate_memory(wpa_s);

	return 0;
}
示例#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;
}
示例#3
0
文件: wnm_sta.c 项目: gxk/hostap
static int wnm_fetch_scan_results(struct wpa_supplicant *wpa_s)
{
	struct wpa_scan_results *scan_res;
	struct wpa_bss *bss;
	struct wpa_ssid *ssid = wpa_s->current_ssid;
	u8 i, found = 0;
	size_t j;

	wpa_dbg(wpa_s, MSG_DEBUG,
		"WNM: Fetch current scan results from the driver for checking transition candidates");
	scan_res = wpa_drv_get_scan_results2(wpa_s);
	if (!scan_res) {
		wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Failed to get scan results");
		return 0;
	}

	if (scan_res->fetch_time.sec == 0)
		os_get_reltime(&scan_res->fetch_time);

	filter_scan_res(wpa_s, scan_res);

	for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
		struct neighbor_report *nei;

		nei = &wpa_s->wnm_neighbor_report_elements[i];
		if (nei->preference_present && nei->preference == 0)
			continue;

		for (j = 0; j < scan_res->num; j++) {
			struct wpa_scan_res *res;
			const u8 *ssid_ie;

			res = scan_res->res[j];
			if (os_memcmp(nei->bssid, res->bssid, ETH_ALEN) != 0 ||
			    res->age > WNM_SCAN_RESULT_AGE * 1000)
				continue;
			bss = wpa_s->current_bss;
			ssid_ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
			if (bss && ssid_ie &&
			    (bss->ssid_len != ssid_ie[1] ||
			     os_memcmp(bss->ssid, ssid_ie + 2,
				       bss->ssid_len) != 0))
				continue;

			/* Potential candidate found */
			found = 1;
			scan_snr(res);
			scan_est_throughput(wpa_s, res);
			wpa_bss_update_scan_res(wpa_s, res,
						&scan_res->fetch_time);
		}
	}

	wpa_scan_results_free(scan_res);
	if (!found) {
		wpa_dbg(wpa_s, MSG_DEBUG,
			"WNM: No transition candidate matches existing scan results");
		return 0;
	}

	bss = compare_scan_neighbor_results(wpa_s, WNM_SCAN_RESULT_AGE, NULL);
	if (!bss) {
		wpa_dbg(wpa_s, MSG_DEBUG,
			"WNM: Comparison of scan results against transition candidates did not find matches");
		return 0;
	}

	/* Associate to the network */
	wnm_bss_tm_connect(wpa_s, bss, ssid, 0);
	return 1;
}