Exemple #1
0
static int wpa_supplicant_ctrl_iface_scan_results(
	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
{
	char *pos, *end;
	struct wpa_scan_res *res;
	int ret;
	size_t i;

	if (wpa_s->scan_res == NULL &&
	    wpa_supplicant_get_scan_results(wpa_s) < 0)
		return 0;

	pos = buf;
	end = buf + buflen;
	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
			  "flags / ssid\n");
	if (ret < 0 || ret >= end - pos)
		return pos - buf;
	pos += ret;

	for (i = 0; i < wpa_s->scan_res->num; i++) {
		res = wpa_s->scan_res->res[i];
		ret = wpa_supplicant_ctrl_iface_scan_result(res, pos,
							    end - pos);
		if (ret < 0 || ret >= end - pos)
			return pos - buf;
		pos += ret;
	}

	return pos - buf;
}
/**
 * wpas_dbus_iface_scan_results - Get the results of a recent scan request
 * @message: Pointer to incoming dbus message
 * @wpa_s: wpa_supplicant structure for a network interface
 * Returns: a dbus message containing a dbus array of objects paths, or returns
 *          a dbus error message if not scan results could be found
 *
 * Handler function for "scanResults" method call of a network device. Returns
 * a dbus message containing the object paths of wireless networks found.
 */
DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
					   struct wpa_supplicant *wpa_s)
{
	DBusMessage *reply = NULL;
	DBusMessageIter iter;
	DBusMessageIter sub_iter;
	size_t i;

	/* Ensure we've actually got scan results to return */
	if (wpa_s->scan_res == NULL &&
	    wpa_supplicant_get_scan_results(wpa_s) < 0) {
		reply = dbus_message_new_error(message, WPAS_ERROR_SCAN_ERROR,
					       "An error ocurred getting scan "
					       "results.");
		goto out;
	}

	/* Create and initialize the return message */
	reply = dbus_message_new_method_return(message);
	dbus_message_iter_init_append(reply, &iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
					 DBUS_TYPE_OBJECT_PATH_AS_STRING,
					 &sub_iter);

	/* Loop through scan results and append each result's object path */
	for (i = 0; i < wpa_s->scan_res->num; i++) {
		struct wpa_scan_res *res = wpa_s->scan_res->res[i];
		char *path;

		path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
		if (path == NULL) {
			perror("wpas_dbus_iface_scan_results[dbus]: out of "
			       "memory.");
			wpa_printf(MSG_ERROR, "dbus control interface: not "
				   "enough memory to send scan results "
				   "signal.");
			break;
		}
		/* Construct the object path for this network.  Note that ':'
		 * is not a valid character in dbus object paths.
		 */
		snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
			 "%s/" WPAS_DBUS_BSSIDS_PART "/"
			 WPAS_DBUS_BSSID_FORMAT,
			 wpa_supplicant_get_dbus_path(wpa_s),
			 MAC2STR(res->bssid));
		dbus_message_iter_append_basic(&sub_iter,
					       DBUS_TYPE_OBJECT_PATH, &path);
		free(path);
	}

	dbus_message_iter_close_container(&iter, &sub_iter);

out:
	return reply;
}
Exemple #3
0
int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
{
	struct wpa_scan_results *scan_res;
	scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
	if (scan_res == NULL)
		return -1;
	wpa_scan_results_free(scan_res);

	return 0;
}
Exemple #4
0
static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
					      int registrar, const u8 *bssid)
{
	struct wpa_ssid *ssid;

	ssid = wpa_config_add_network(wpa_s->conf);
	if (ssid == NULL)
		return NULL;
	wpa_config_set_network_defaults(ssid);
	if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
	    wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
	    wpa_config_set(ssid, "identity", registrar ?
			   "\"" WSC_ID_REGISTRAR "\"" :
			   "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
		wpa_config_remove_network(wpa_s->conf, ssid->id);
		return NULL;
	}

	if (bssid) {
		size_t i;
		struct wpa_scan_res *res;

		os_memcpy(ssid->bssid, bssid, ETH_ALEN);
		ssid->bssid_set = 1;

		/* Try to get SSID from scan results */
		if (wpa_s->scan_res == NULL &&
		    wpa_supplicant_get_scan_results(wpa_s) < 0)
			return ssid; /* Could not find any scan results */

		for (i = 0; i < wpa_s->scan_res->num; i++) {
			const u8 *ie;

			res = wpa_s->scan_res->res[i];
			if (os_memcmp(bssid, res->bssid, ETH_ALEN) != 0)
				continue;

			ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
			if (ie == NULL)
				break;
			os_free(ssid->ssid);
			ssid->ssid = os_malloc(ie[1]);
			if (ssid->ssid == NULL)
				break;
			os_memcpy(ssid->ssid, ie + 2, ie[1]);
			ssid->ssid_len = ie[1];
			break;
		}
	}

	return ssid;
}
Exemple #5
0
static int wpa_supplicant_get_beacon_ie(void *ctx)
{
	struct wpa_supplicant *wpa_s = ctx;
	if (wpa_get_beacon_ie(wpa_s) == 0) {
		return 0;
	}

	/* No WPA/RSN IE found in the cached scan results. Try to get updated
	 * scan results from the driver. */
	if (wpa_supplicant_get_scan_results(wpa_s) < 0) {
		return -1;
	}

	return wpa_get_beacon_ie(wpa_s);
}
Exemple #6
0
/**
 * wpas_dispatch_bssid_method - dispatch messages for scanned networks
 * @message: the incoming dbus message
 * @wpa_s: a network interface's data
 * @bssid: bssid of the scanned network we're interested in
 * Returns: a reply dbus message, or a dbus error message
 *
 * This function dispatches all incoming dbus messages for scanned networks.
 */
static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message,
						struct wpa_supplicant *wpa_s,
						const char *bssid)
{
	DBusMessage *reply = NULL;
	const char *method = dbus_message_get_member(message);
	struct wpa_scan_res *res = NULL;
	size_t i;

	/* Ensure we actually have scan data */
	if (wpa_s->scan_res == NULL &&
	    wpa_supplicant_get_scan_results(wpa_s) < 0) {
		reply = wpas_dbus_new_invalid_bssid_error(message);
		goto out;
	}

	/* Find the bssid's scan data */
	for (i = 0; i < wpa_s->scan_res->num; i++) {
		struct wpa_scan_res *search_res = wpa_s->scan_res->res[i];
		char mac_str[18];

		memset(mac_str, 0, sizeof(mac_str));
		snprintf(mac_str, sizeof(mac_str) - 1, WPAS_DBUS_BSSID_FORMAT,
			 MAC2STR(search_res->bssid));
		if (!strcmp(bssid, mac_str)) {
			res = search_res;
			break;
		}
	}

	if (!res) {
		reply = wpas_dbus_new_invalid_bssid_error(message);
		goto out;
	}

	/* Dispatch the method call against the scanned bssid */
	if (!strcmp(method, "properties"))
		reply = wpas_dbus_bssid_properties(message, wpa_s, res);

out:
	return reply;
}
Exemple #7
0
static int wpa_supplicant_ctrl_iface_scan_results(
	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
{
	char *pos, *end, *retpos;
	struct wpa_scan_result *res;
	int i, ret;

	if (wpa_s->scan_results == NULL &&
	    wpa_supplicant_get_scan_results(wpa_s) < 0)
		return 0;
	if (wpa_s->scan_results == NULL)
		return 0;

	pos = buf;
	end = buf + buflen;
	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
			  "flags / ssid\n");
	if (ret < 0 || ret >= end - pos)
		return pos - buf;
	pos += ret;

	for (i = 0; i < wpa_s->num_scan_results; i++) {
		retpos = pos;
		res = &wpa_s->scan_results[i];
		ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
				  MAC2STR(res->bssid), res->freq, res->level);
		if (ret < 0 || ret >= end - pos)
			return retpos - buf;
		pos += ret;
		if (res->wpa_ie_len) {
			pos = wpa_supplicant_ie_txt(pos, end, "WPA",
						    res->wpa_ie,
						    res->wpa_ie_len);
		}
		if (res->rsn_ie_len) {
			pos = wpa_supplicant_ie_txt(pos, end, "WPA2",
						    res->rsn_ie,
						    res->rsn_ie_len);
		}
		if (!res->wpa_ie_len && !res->rsn_ie_len &&
		    res->caps & IEEE80211_CAP_PRIVACY) {
			ret = os_snprintf(pos, end - pos, "[WEP]");
			if (ret < 0 || ret >= end - pos)
				return retpos - buf;
			pos += ret;
		}
		if (res->caps & IEEE80211_CAP_IBSS) {
			ret = os_snprintf(pos, end - pos, "[IBSS]");
			if (ret < 0 || ret >= end - pos)
				return retpos - buf;
			pos += ret;
		}
		if (!res->wpa_ie_len && !res->rsn_ie_len) {
			ret = os_snprintf(pos, end - pos, "\t");
			if (ret < 0 || ret >= end - pos)
				return retpos - buf;
			pos += ret;
		}

		ret = os_snprintf(pos, end - pos, "\t%s",
				  wpa_ssid_txt(res->ssid, res->ssid_len));
		if (ret < 0 || ret >= end - pos)
			return retpos - buf;
		pos += ret;

		ret = os_snprintf(pos, end - pos, "\n");
		if (ret < 0 || ret >= end - pos)
			return retpos - buf;
		pos += ret;
	}

	return pos - buf;
}
Exemple #8
0
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
{
	int prio, timeout;
	struct wpa_scan_res *selected = NULL;
	struct wpa_ssid *ssid = NULL;

	wpa_supplicant_notify_scanning(wpa_s, 0);

	if (wpa_supplicant_get_scan_results(wpa_s) < 0) {
		if (wpa_s->conf->ap_scan == 2)
			return;
		wpa_printf(MSG_DEBUG, "Failed to get scan results - try "
			   "scanning again");
		timeout = 1;
		goto req_scan;
	}

	/*
	 * 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 &&
	    wpa_s->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);
		wpa_supplicant_dbus_notify_scan_results(wpa_s);
		wpas_wps_notify_scan_results(wpa_s);
	}

	if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
		return;

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

	while (selected == NULL) {
		for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
			selected = wpa_supplicant_select_bss(
				wpa_s, wpa_s->conf->pssid[prio], &ssid);
			if (selected)
				break;
		}

		if (selected == NULL && wpa_s->blacklist) {
			wpa_printf(MSG_DEBUG, "No APs found - clear blacklist "
				   "and try again");
			wpa_blacklist_clear(wpa_s);
			wpa_s->blacklist_cleared++;
		} else if (selected == NULL) {
			break;
		}
	}

	if (selected) {
		if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) {
			wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP
				"PBC session overlap");
			timeout = 10;
			goto req_scan;
		}

		/* Do not trigger new association unless the BSSID has changed
		 * or if reassociation is requested. If we are in process of
		 * associating with the selected BSSID, do not trigger new
		 * attempt. */
		if (wpa_s->reassociate ||
		    (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
		     (wpa_s->wpa_state != WPA_ASSOCIATING ||
		      os_memcmp(selected->bssid, wpa_s->pending_bssid,
				ETH_ALEN) != 0))) {
			if (wpa_supplicant_scard_init(wpa_s, ssid)) {
				wpa_supplicant_req_scan(wpa_s, 10, 0);
				return;
			}
			wpa_supplicant_associate(wpa_s, selected, ssid);
		} else {
			wpa_printf(MSG_DEBUG, "Already associated with the "
				   "selected AP.");
		}
		rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res);
	} else {
		wpa_printf(MSG_DEBUG, "No suitable AP found.");
		timeout = 5;
		goto req_scan;
	}

	return;

req_scan:
	if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1) {
		/*
		 * Quick recovery if the initial scan results were not
		 * complete when fetched before the first scan request.
		 */
		wpa_s->scan_res_tried++;
		timeout = 0;
	} else if (!wpa_supplicant_enabled_networks(wpa_s->conf)) {
		/*
		 * No networks are enabled; short-circuit request so
		 * we don't wait timeout seconds before transitioning
		 * to INACTIVE state.
		 */
		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
		return;
	}
	wpa_supplicant_req_scan(wpa_s, timeout, 0);
}
Exemple #9
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);
		}
	}
}
Exemple #10
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);
        
        ros_scan_completed(wpa_s, scan_res);

	if (scan_res == NULL) {
		if (wpa_s->conf->ap_scan == 2)
			return;
		wpa_printf(MSG_DEBUG, "Failed to get scan results - don't bother 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;
	}

	/*
	 * 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;
                wpa_s->more_bss_to_try = 1;
		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_s->more_bss_to_try = 0;
		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 = 1;
			int timeout_usec = 0;
			wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
						    timeout_usec);
		}
	} */
}
Exemple #11
0
static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
					 struct wpa_ssid *ssid,
					 const struct wps_credential *cred)
{
	struct wpa_driver_capa capa;
	size_t i;
	struct wpa_scan_res *bss;
	const u8 *ie;
	struct wpa_ie_data adv;
	int wpa2 = 0, ccmp = 0;

	/*
	 * Many existing WPS APs do not know how to negotiate WPA2 or CCMP in
	 * case they are configured for mixed mode operation (WPA+WPA2 and
	 * TKIP+CCMP). Try to use scan results to figure out whether the AP
	 * actually supports stronger security and select that if the client
	 * has support for it, too.
	 */

	if (wpa_drv_get_capa(wpa_s, &capa))
		return; /* Unknown what driver supports */

	if (wpa_supplicant_get_scan_results(wpa_s) || wpa_s->scan_res == NULL)
		return; /* Could not get scan results for checking advertised
			 * parameters */

	for (i = 0; i < wpa_s->scan_res->num; i++) {
		bss = wpa_s->scan_res->res[i];
		if (os_memcmp(bss->bssid, cred->mac_addr, ETH_ALEN) != 0)
			continue;
		ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
		if (ie == NULL)
			continue;
		if (ie[1] != ssid->ssid_len || ssid->ssid == NULL ||
		    os_memcmp(ie + 2, ssid->ssid, ssid->ssid_len) != 0)
			continue;

		wpa_printf(MSG_DEBUG, "WPS: AP found from scan results");
		break;
	}

	if (i == wpa_s->scan_res->num) {
		wpa_printf(MSG_DEBUG, "WPS: The AP was not found from scan "
			   "results - use credential as-is");
		return;
	}

	ie = wpa_scan_get_ie(bss, WLAN_EID_RSN);
	if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0) {
		wpa2 = 1;
		if (adv.pairwise_cipher & WPA_CIPHER_CCMP)
			ccmp = 1;
	} else {
		ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
		if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0 &&
		    adv.pairwise_cipher & WPA_CIPHER_CCMP)
			ccmp = 1;
	}

	if (ie == NULL && (ssid->proto & WPA_PROTO_WPA) &&
	    (ssid->pairwise_cipher & WPA_CIPHER_TKIP)) {
		/*
		 * TODO: This could be the initial AP configuration and the
		 * Beacon contents could change shortly. Should request a new
		 * scan and delay addition of the network until the updated
		 * scan results are available.
		 */
		wpa_printf(MSG_DEBUG, "WPS: The AP did not yet advertise WPA "
			   "support - use credential as-is");
		return;
	}

	if (ccmp && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
	    (ssid->pairwise_cipher & WPA_CIPHER_TKIP) &&
	    (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
		wpa_printf(MSG_DEBUG, "WPS: Add CCMP into the credential "
			   "based on scan results");
		if (wpa_s->conf->ap_scan == 1)
			ssid->pairwise_cipher |= WPA_CIPHER_CCMP;
		else
			ssid->pairwise_cipher = WPA_CIPHER_CCMP;
	}

	if (wpa2 && !(ssid->proto & WPA_PROTO_RSN) &&
	    (ssid->proto & WPA_PROTO_WPA) &&
	    (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP)) {
		wpa_printf(MSG_DEBUG, "WPS: Add WPA2 into the credential "
			   "based on scan results");
		if (wpa_s->conf->ap_scan == 1)
			ssid->proto |= WPA_PROTO_RSN;
		else
			ssid->proto = WPA_PROTO_RSN;
	}
}
static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
					 const char *cmd, char *buf,
					 size_t buflen)
{
	u8 bssid[ETH_ALEN];
	size_t i;
	struct wpa_scan_results *results;
	struct wpa_scan_res *bss;
	int ret;
	char *pos, *end;
	const u8 *ie, *ie2;

	if (wpa_s->scan_res == NULL &&
	    wpa_supplicant_get_scan_results(wpa_s) < 0)
		return 0;

	results = wpa_s->scan_res;
	if (results == NULL)
		return 0;

	if (hwaddr_aton(cmd, bssid) == 0) {
		for (i = 0; i < results->num; i++) {
			if (os_memcmp(bssid, results->res[i]->bssid, ETH_ALEN)
			    == 0)
				break;
		}
	} else
		i = atoi(cmd);

	if (i >= results->num || results->res[i] == NULL)
		return 0; /* no match found */

	bss = results->res[i];
	pos = buf;
	end = buf + buflen;
	ret = os_snprintf(pos, end - pos,
			  "bssid=" MACSTR "\n"
			  "freq=%d\n"
			  "beacon_int=%d\n"
			  "capabilities=0x%04x\n"
			  "qual=%d\n"
			  "noise=%d\n"
			  "level=%d\n"
			  "tsf=%016llu\n"
			  "ie=",
			  MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
			  bss->caps, bss->qual, bss->noise, bss->level,
			  (unsigned long long) bss->tsf);
	if (ret < 0 || ret >= end - pos)
		return pos - buf;
	pos += ret;

	ie = (const u8 *) (bss + 1);
	for (i = 0; i < bss->ie_len; i++) {
		ret = os_snprintf(pos, end - pos, "%02x", *ie++);
		if (ret < 0 || ret >= end - pos)
			return pos - buf;
		pos += ret;
	}

	ret = os_snprintf(pos, end - pos, "\n");
	if (ret < 0 || ret >= end - pos)
		return pos - buf;
	pos += ret;

	ret = os_snprintf(pos, end - pos, "flags=");
	if (ret < 0 || ret >= end - pos)
		return pos - buf;
	pos += ret;

	ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
	if (ie)
		pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
	ie2 = wpa_scan_get_ie(bss, WLAN_EID_RSN);
	if (ie2)
		pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
	pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
	if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
		ret = os_snprintf(pos, end - pos, "[WEP]");
		if (ret < 0 || ret >= end - pos)
			return pos - buf;
		pos += ret;
	}
	if (bss->caps & IEEE80211_CAP_IBSS) {
		ret = os_snprintf(pos, end - pos, "[IBSS]");
		if (ret < 0 || ret >= end - pos)
			return pos - buf;
		pos += ret;
	}

	ret = os_snprintf(pos, end - pos, "\n");
	if (ret < 0 || ret >= end - pos)
		return pos - buf;
	pos += ret;

	ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
	ret = os_snprintf(pos, end - pos, "ssid=%s\n",
			  ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
	if (ret < 0 || ret >= end - pos)
		return pos - buf;
	pos += ret;

	return pos - buf;
}
Exemple #13
0
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
{
	int num, prio, timeout;
	struct wpa_scan_result *selected = NULL;
	struct wpa_ssid *ssid = NULL;
	struct wpa_scan_result *results;

	if (wpa_supplicant_get_scan_results(wpa_s) < 0) {
		if (wpa_s->conf->ap_scan == 2)
			return;
		wpa_printf(MSG_DEBUG, "Failed to get scan results - try "
			   "scanning again");
		timeout = 1;
		goto req_scan;
	}

	wpa_supplicant_dbus_notify_scan_results(wpa_s);

	if (wpa_s->conf->ap_scan == 2)
		return;
	results = wpa_s->scan_results;
	num = wpa_s->num_scan_results;

	while (selected == NULL) {
		for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
			selected = wpa_supplicant_select_bss(
				wpa_s, wpa_s->conf->pssid[prio], results, num,
				&ssid);
			if (selected)
				break;
		}

		if (selected == NULL && wpa_s->blacklist) {
			wpa_printf(MSG_DEBUG, "No APs found - clear blacklist "
				   "and try again");
			wpa_blacklist_clear(wpa_s);
		} else if (selected == NULL) {
			break;
		}
	}

	if (selected) {
		/* Do not trigger new association unless the BSSID has changed
		 * or if reassociation is requested. If we are in process of
		 * associating with the selected BSSID, do not trigger new
		 * attempt. */
		if (wpa_s->reassociate ||
		    (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
		     (wpa_s->wpa_state != WPA_ASSOCIATING ||
		      os_memcmp(selected->bssid, wpa_s->pending_bssid,
				ETH_ALEN) != 0))) {
			if (wpa_supplicant_scard_init(wpa_s, ssid)) {
				wpa_supplicant_req_scan(wpa_s, 10, 0);
				return;
			}
			wpa_supplicant_associate(wpa_s, selected, ssid);
		} else {
			wpa_printf(MSG_DEBUG, "Already associated with the "
				   "selected AP.");
		}
		rsn_preauth_scan_results(wpa_s->wpa, results, num);
	} else {
		wpa_printf(MSG_DEBUG, "No suitable AP found.");
		timeout = 5;
		goto req_scan;
	}

	return;

req_scan:
	if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1) {
		/*
		 * Quick recovery if the initial scan results were not
		 * complete when fetched before the first scan request.
		 */
		wpa_s->scan_res_tried++;
		timeout = 0;
	}
	wpa_supplicant_req_scan(wpa_s, timeout, 0);
}