Home | History | Annotate | Download | only in drivers
      1 /*
      2  * Driver interaction with Linux nl80211/cfg80211 - Scanning
      3  * Copyright (c) 2002-2014, Jouni Malinen <j (at) w1.fi>
      4  * Copyright (c) 2007, Johannes Berg <johannes (at) sipsolutions.net>
      5  * Copyright (c) 2009-2010, Atheros Communications
      6  *
      7  * This software may be distributed under the terms of the BSD license.
      8  * See README for more details.
      9  */
     10 
     11 #include "includes.h"
     12 #include <netlink/genl/genl.h>
     13 
     14 #include "utils/common.h"
     15 #include "utils/eloop.h"
     16 #include "common/ieee802_11_defs.h"
     17 #include "driver_nl80211.h"
     18 
     19 
     20 static int get_noise_for_scan_results(struct nl_msg *msg, void *arg)
     21 {
     22 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
     23 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     24 	struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
     25 	static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
     26 		[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
     27 		[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
     28 	};
     29 	struct wpa_scan_results *scan_results = arg;
     30 	struct wpa_scan_res *scan_res;
     31 	size_t i;
     32 
     33 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     34 		  genlmsg_attrlen(gnlh, 0), NULL);
     35 
     36 	if (!tb[NL80211_ATTR_SURVEY_INFO]) {
     37 		wpa_printf(MSG_DEBUG, "nl80211: Survey data missing");
     38 		return NL_SKIP;
     39 	}
     40 
     41 	if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
     42 			     tb[NL80211_ATTR_SURVEY_INFO],
     43 			     survey_policy)) {
     44 		wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested "
     45 			   "attributes");
     46 		return NL_SKIP;
     47 	}
     48 
     49 	if (!sinfo[NL80211_SURVEY_INFO_NOISE])
     50 		return NL_SKIP;
     51 
     52 	if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
     53 		return NL_SKIP;
     54 
     55 	for (i = 0; i < scan_results->num; ++i) {
     56 		scan_res = scan_results->res[i];
     57 		if (!scan_res)
     58 			continue;
     59 		if ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
     60 		    scan_res->freq)
     61 			continue;
     62 		if (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))
     63 			continue;
     64 		scan_res->noise = (s8)
     65 			nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
     66 		scan_res->flags &= ~WPA_SCAN_NOISE_INVALID;
     67 	}
     68 
     69 	return NL_SKIP;
     70 }
     71 
     72 
     73 static int nl80211_get_noise_for_scan_results(
     74 	struct wpa_driver_nl80211_data *drv,
     75 	struct wpa_scan_results *scan_res)
     76 {
     77 	struct nl_msg *msg;
     78 
     79 	msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
     80 	return send_and_recv_msgs(drv, msg, get_noise_for_scan_results,
     81 				  scan_res);
     82 }
     83 
     84 
     85 /**
     86  * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion
     87  * @eloop_ctx: Driver private data
     88  * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init()
     89  *
     90  * This function can be used as registered timeout when starting a scan to
     91  * generate a scan completed event if the driver does not report this.
     92  */
     93 void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
     94 {
     95 	struct wpa_driver_nl80211_data *drv = eloop_ctx;
     96 	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
     97 		wpa_driver_nl80211_set_mode(drv->first_bss,
     98 					    drv->ap_scan_as_station);
     99 		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
    100 	}
    101 	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
    102 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
    103 }
    104 
    105 
    106 static struct nl_msg *
    107 nl80211_scan_common(struct i802_bss *bss, u8 cmd,
    108 		    struct wpa_driver_scan_params *params)
    109 {
    110 	struct wpa_driver_nl80211_data *drv = bss->drv;
    111 	struct nl_msg *msg;
    112 	size_t i;
    113 	u32 scan_flags = 0;
    114 
    115 	msg = nl80211_cmd_msg(bss, 0, cmd);
    116 	if (!msg)
    117 		return NULL;
    118 
    119 	if (params->num_ssids) {
    120 		struct nlattr *ssids;
    121 
    122 		ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
    123 		if (ssids == NULL)
    124 			goto fail;
    125 		for (i = 0; i < params->num_ssids; i++) {
    126 			wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
    127 					  params->ssids[i].ssid,
    128 					  params->ssids[i].ssid_len);
    129 			if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
    130 				    params->ssids[i].ssid))
    131 				goto fail;
    132 		}
    133 		nla_nest_end(msg, ssids);
    134 	}
    135 
    136 	if (params->extra_ies) {
    137 		wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
    138 			    params->extra_ies, params->extra_ies_len);
    139 		if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,
    140 			    params->extra_ies))
    141 			goto fail;
    142 	}
    143 
    144 	if (params->freqs) {
    145 		struct nlattr *freqs;
    146 		freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
    147 		if (freqs == NULL)
    148 			goto fail;
    149 		for (i = 0; params->freqs[i]; i++) {
    150 			wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
    151 				   "MHz", params->freqs[i]);
    152 			if (nla_put_u32(msg, i + 1, params->freqs[i]))
    153 				goto fail;
    154 		}
    155 		nla_nest_end(msg, freqs);
    156 	}
    157 
    158 	os_free(drv->filter_ssids);
    159 	drv->filter_ssids = params->filter_ssids;
    160 	params->filter_ssids = NULL;
    161 	drv->num_filter_ssids = params->num_filter_ssids;
    162 
    163 	if (params->only_new_results) {
    164 		wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH");
    165 		scan_flags |= NL80211_SCAN_FLAG_FLUSH;
    166 	}
    167 
    168 	if (params->low_priority && drv->have_low_prio_scan) {
    169 		wpa_printf(MSG_DEBUG,
    170 			   "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY");
    171 		scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
    172 	}
    173 
    174 	if (params->mac_addr_rand) {
    175 		wpa_printf(MSG_DEBUG,
    176 			   "nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR");
    177 		scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
    178 
    179 		if (params->mac_addr) {
    180 			wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR,
    181 				   MAC2STR(params->mac_addr));
    182 			if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
    183 				    params->mac_addr))
    184 				goto fail;
    185 		}
    186 
    187 		if (params->mac_addr_mask) {
    188 			wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: "
    189 				   MACSTR, MAC2STR(params->mac_addr_mask));
    190 			if (nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
    191 				    params->mac_addr_mask))
    192 				goto fail;
    193 		}
    194 	}
    195 
    196 	if (scan_flags &&
    197 	    nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags))
    198 		goto fail;
    199 
    200 	return msg;
    201 
    202 fail:
    203 	nlmsg_free(msg);
    204 	return NULL;
    205 }
    206 
    207 
    208 /**
    209  * wpa_driver_nl80211_scan - Request the driver to initiate scan
    210  * @bss: Pointer to private driver data from wpa_driver_nl80211_init()
    211  * @params: Scan parameters
    212  * Returns: 0 on success, -1 on failure
    213  */
    214 int wpa_driver_nl80211_scan(struct i802_bss *bss,
    215 			    struct wpa_driver_scan_params *params)
    216 {
    217 	struct wpa_driver_nl80211_data *drv = bss->drv;
    218 	int ret = -1, timeout;
    219 	struct nl_msg *msg = NULL;
    220 
    221 	wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
    222 	drv->scan_for_auth = 0;
    223 
    224 	msg = nl80211_scan_common(bss, NL80211_CMD_TRIGGER_SCAN, params);
    225 	if (!msg)
    226 		return -1;
    227 
    228 	if (params->p2p_probe) {
    229 		struct nlattr *rates;
    230 
    231 		wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
    232 
    233 		rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
    234 		if (rates == NULL)
    235 			goto fail;
    236 
    237 		/*
    238 		 * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
    239 		 * by masking out everything else apart from the OFDM rates 6,
    240 		 * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
    241 		 * rates are left enabled.
    242 		 */
    243 		if (nla_put(msg, NL80211_BAND_2GHZ, 8,
    244 			    "\x0c\x12\x18\x24\x30\x48\x60\x6c"))
    245 			goto fail;
    246 		nla_nest_end(msg, rates);
    247 
    248 		if (nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE))
    249 			goto fail;
    250 	}
    251 
    252 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    253 	msg = NULL;
    254 	if (ret) {
    255 		wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
    256 			   "(%s)", ret, strerror(-ret));
    257 		if (drv->hostapd && is_ap_interface(drv->nlmode)) {
    258 			enum nl80211_iftype old_mode = drv->nlmode;
    259 
    260 			/*
    261 			 * mac80211 does not allow scan requests in AP mode, so
    262 			 * try to do this in station mode.
    263 			 */
    264 			if (wpa_driver_nl80211_set_mode(
    265 				    bss, NL80211_IFTYPE_STATION))
    266 				goto fail;
    267 
    268 			if (wpa_driver_nl80211_scan(bss, params)) {
    269 				wpa_driver_nl80211_set_mode(bss, old_mode);
    270 				goto fail;
    271 			}
    272 
    273 			/* Restore AP mode when processing scan results */
    274 			drv->ap_scan_as_station = old_mode;
    275 			ret = 0;
    276 		} else
    277 			goto fail;
    278 	}
    279 
    280 	drv->scan_state = SCAN_REQUESTED;
    281 	/* Not all drivers generate "scan completed" wireless event, so try to
    282 	 * read results after a timeout. */
    283 	timeout = 10;
    284 	if (drv->scan_complete_events) {
    285 		/*
    286 		 * The driver seems to deliver events to notify when scan is
    287 		 * complete, so use longer timeout to avoid race conditions
    288 		 * with scanning and following association request.
    289 		 */
    290 		timeout = 30;
    291 	}
    292 	wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
    293 		   "seconds", ret, timeout);
    294 	eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
    295 	eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
    296 			       drv, drv->ctx);
    297 
    298 fail:
    299 	nlmsg_free(msg);
    300 	return ret;
    301 }
    302 
    303 
    304 /**
    305  * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
    306  * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
    307  * @params: Scan parameters
    308  * @interval: Interval between scan cycles in milliseconds
    309  * Returns: 0 on success, -1 on failure or if not supported
    310  */
    311 int wpa_driver_nl80211_sched_scan(void *priv,
    312 				  struct wpa_driver_scan_params *params,
    313 				  u32 interval)
    314 {
    315 	struct i802_bss *bss = priv;
    316 	struct wpa_driver_nl80211_data *drv = bss->drv;
    317 	int ret = -1;
    318 	struct nl_msg *msg;
    319 	size_t i;
    320 
    321 	wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
    322 
    323 #ifdef ANDROID
    324 	if (!drv->capa.sched_scan_supported)
    325 		return android_pno_start(bss, params);
    326 #endif /* ANDROID */
    327 
    328 	msg = nl80211_scan_common(bss, NL80211_CMD_START_SCHED_SCAN, params);
    329 	if (!msg ||
    330 	    nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval))
    331 		goto fail;
    332 
    333 	if ((drv->num_filter_ssids &&
    334 	    (int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
    335 	    params->filter_rssi) {
    336 		struct nlattr *match_sets;
    337 		match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
    338 		if (match_sets == NULL)
    339 			goto fail;
    340 
    341 		for (i = 0; i < drv->num_filter_ssids; i++) {
    342 			struct nlattr *match_set_ssid;
    343 			wpa_hexdump_ascii(MSG_MSGDUMP,
    344 					  "nl80211: Sched scan filter SSID",
    345 					  drv->filter_ssids[i].ssid,
    346 					  drv->filter_ssids[i].ssid_len);
    347 
    348 			match_set_ssid = nla_nest_start(msg, i + 1);
    349 			if (match_set_ssid == NULL ||
    350 			    nla_put(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
    351 				    drv->filter_ssids[i].ssid_len,
    352 				    drv->filter_ssids[i].ssid) ||
    353 			    (params->filter_rssi &&
    354 			     nla_put_u32(msg,
    355 					 NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
    356 					 params->filter_rssi)))
    357 				goto fail;
    358 
    359 			nla_nest_end(msg, match_set_ssid);
    360 		}
    361 
    362 		/*
    363 		 * Due to backward compatibility code, newer kernels treat this
    364 		 * matchset (with only an RSSI filter) as the default for all
    365 		 * other matchsets, unless it's the only one, in which case the
    366 		 * matchset will actually allow all SSIDs above the RSSI.
    367 		 */
    368 		if (params->filter_rssi) {
    369 			struct nlattr *match_set_rssi;
    370 			match_set_rssi = nla_nest_start(msg, 0);
    371 			if (match_set_rssi == NULL ||
    372 			    nla_put_u32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
    373 					params->filter_rssi))
    374 				goto fail;
    375 			wpa_printf(MSG_MSGDUMP,
    376 				   "nl80211: Sched scan RSSI filter %d dBm",
    377 				   params->filter_rssi);
    378 			nla_nest_end(msg, match_set_rssi);
    379 		}
    380 
    381 		nla_nest_end(msg, match_sets);
    382 	}
    383 
    384 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    385 
    386 	/* TODO: if we get an error here, we should fall back to normal scan */
    387 
    388 	msg = NULL;
    389 	if (ret) {
    390 		wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: "
    391 			   "ret=%d (%s)", ret, strerror(-ret));
    392 		goto fail;
    393 	}
    394 
    395 	wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) - "
    396 		   "scan interval %d msec", ret, interval);
    397 
    398 fail:
    399 	nlmsg_free(msg);
    400 	return ret;
    401 }
    402 
    403 
    404 /**
    405  * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan
    406  * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
    407  * Returns: 0 on success, -1 on failure or if not supported
    408  */
    409 int wpa_driver_nl80211_stop_sched_scan(void *priv)
    410 {
    411 	struct i802_bss *bss = priv;
    412 	struct wpa_driver_nl80211_data *drv = bss->drv;
    413 	int ret;
    414 	struct nl_msg *msg;
    415 
    416 #ifdef ANDROID
    417 	if (!drv->capa.sched_scan_supported)
    418 		return android_pno_stop(bss);
    419 #endif /* ANDROID */
    420 
    421 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_STOP_SCHED_SCAN);
    422 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    423 	if (ret) {
    424 		wpa_printf(MSG_DEBUG,
    425 			   "nl80211: Sched scan stop failed: ret=%d (%s)",
    426 			   ret, strerror(-ret));
    427 	} else {
    428 		wpa_printf(MSG_DEBUG,
    429 			   "nl80211: Sched scan stop sent");
    430 	}
    431 
    432 	return ret;
    433 }
    434 
    435 
    436 const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
    437 {
    438 	const u8 *end, *pos;
    439 
    440 	if (ies == NULL)
    441 		return NULL;
    442 
    443 	pos = ies;
    444 	end = ies + ies_len;
    445 
    446 	while (pos + 1 < end) {
    447 		if (pos + 2 + pos[1] > end)
    448 			break;
    449 		if (pos[0] == ie)
    450 			return pos;
    451 		pos += 2 + pos[1];
    452 	}
    453 
    454 	return NULL;
    455 }
    456 
    457 
    458 static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
    459 				 const u8 *ie, size_t ie_len)
    460 {
    461 	const u8 *ssid;
    462 	size_t i;
    463 
    464 	if (drv->filter_ssids == NULL)
    465 		return 0;
    466 
    467 	ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID);
    468 	if (ssid == NULL)
    469 		return 1;
    470 
    471 	for (i = 0; i < drv->num_filter_ssids; i++) {
    472 		if (ssid[1] == drv->filter_ssids[i].ssid_len &&
    473 		    os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==
    474 		    0)
    475 			return 0;
    476 	}
    477 
    478 	return 1;
    479 }
    480 
    481 
    482 int bss_info_handler(struct nl_msg *msg, void *arg)
    483 {
    484 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
    485 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    486 	struct nlattr *bss[NL80211_BSS_MAX + 1];
    487 	static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
    488 		[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
    489 		[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
    490 		[NL80211_BSS_TSF] = { .type = NLA_U64 },
    491 		[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
    492 		[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
    493 		[NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
    494 		[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
    495 		[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
    496 		[NL80211_BSS_STATUS] = { .type = NLA_U32 },
    497 		[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
    498 		[NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
    499 	};
    500 	struct nl80211_bss_info_arg *_arg = arg;
    501 	struct wpa_scan_results *res = _arg->res;
    502 	struct wpa_scan_res **tmp;
    503 	struct wpa_scan_res *r;
    504 	const u8 *ie, *beacon_ie;
    505 	size_t ie_len, beacon_ie_len;
    506 	u8 *pos;
    507 	size_t i;
    508 
    509 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    510 		  genlmsg_attrlen(gnlh, 0), NULL);
    511 	if (!tb[NL80211_ATTR_BSS])
    512 		return NL_SKIP;
    513 	if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
    514 			     bss_policy))
    515 		return NL_SKIP;
    516 	if (bss[NL80211_BSS_STATUS]) {
    517 		enum nl80211_bss_status status;
    518 		status = nla_get_u32(bss[NL80211_BSS_STATUS]);
    519 		if (status == NL80211_BSS_STATUS_ASSOCIATED &&
    520 		    bss[NL80211_BSS_FREQUENCY]) {
    521 			_arg->assoc_freq =
    522 				nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
    523 			wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
    524 				   _arg->assoc_freq);
    525 		}
    526 		if (status == NL80211_BSS_STATUS_IBSS_JOINED &&
    527 		    bss[NL80211_BSS_FREQUENCY]) {
    528 			_arg->ibss_freq =
    529 				nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
    530 			wpa_printf(MSG_DEBUG, "nl80211: IBSS-joined on %u MHz",
    531 				   _arg->ibss_freq);
    532 		}
    533 		if (status == NL80211_BSS_STATUS_ASSOCIATED &&
    534 		    bss[NL80211_BSS_BSSID]) {
    535 			os_memcpy(_arg->assoc_bssid,
    536 				  nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
    537 			wpa_printf(MSG_DEBUG, "nl80211: Associated with "
    538 				   MACSTR, MAC2STR(_arg->assoc_bssid));
    539 		}
    540 	}
    541 	if (!res)
    542 		return NL_SKIP;
    543 	if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
    544 		ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
    545 		ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
    546 	} else {
    547 		ie = NULL;
    548 		ie_len = 0;
    549 	}
    550 	if (bss[NL80211_BSS_BEACON_IES]) {
    551 		beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);
    552 		beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);
    553 	} else {
    554 		beacon_ie = NULL;
    555 		beacon_ie_len = 0;
    556 	}
    557 
    558 	if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie,
    559 				  ie ? ie_len : beacon_ie_len))
    560 		return NL_SKIP;
    561 
    562 	r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);
    563 	if (r == NULL)
    564 		return NL_SKIP;
    565 	if (bss[NL80211_BSS_BSSID])
    566 		os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),
    567 			  ETH_ALEN);
    568 	if (bss[NL80211_BSS_FREQUENCY])
    569 		r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
    570 	if (bss[NL80211_BSS_BEACON_INTERVAL])
    571 		r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);
    572 	if (bss[NL80211_BSS_CAPABILITY])
    573 		r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
    574 	r->flags |= WPA_SCAN_NOISE_INVALID;
    575 	if (bss[NL80211_BSS_SIGNAL_MBM]) {
    576 		r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
    577 		r->level /= 100; /* mBm to dBm */
    578 		r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;
    579 	} else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
    580 		r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
    581 		r->flags |= WPA_SCAN_QUAL_INVALID;
    582 	} else
    583 		r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;
    584 	if (bss[NL80211_BSS_TSF])
    585 		r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);
    586 	if (bss[NL80211_BSS_SEEN_MS_AGO])
    587 		r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
    588 	r->ie_len = ie_len;
    589 	pos = (u8 *) (r + 1);
    590 	if (ie) {
    591 		os_memcpy(pos, ie, ie_len);
    592 		pos += ie_len;
    593 	}
    594 	r->beacon_ie_len = beacon_ie_len;
    595 	if (beacon_ie)
    596 		os_memcpy(pos, beacon_ie, beacon_ie_len);
    597 
    598 	if (bss[NL80211_BSS_STATUS]) {
    599 		enum nl80211_bss_status status;
    600 		status = nla_get_u32(bss[NL80211_BSS_STATUS]);
    601 		switch (status) {
    602 		case NL80211_BSS_STATUS_ASSOCIATED:
    603 			r->flags |= WPA_SCAN_ASSOCIATED;
    604 			break;
    605 		default:
    606 			break;
    607 		}
    608 	}
    609 
    610 	/*
    611 	 * cfg80211 maintains separate BSS table entries for APs if the same
    612 	 * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does
    613 	 * not use frequency as a separate key in the BSS table, so filter out
    614 	 * duplicated entries. Prefer associated BSS entry in such a case in
    615 	 * order to get the correct frequency into the BSS table. Similarly,
    616 	 * prefer newer entries over older.
    617 	 */
    618 	for (i = 0; i < res->num; i++) {
    619 		const u8 *s1, *s2;
    620 		if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)
    621 			continue;
    622 
    623 		s1 = nl80211_get_ie((u8 *) (res->res[i] + 1),
    624 				    res->res[i]->ie_len, WLAN_EID_SSID);
    625 		s2 = nl80211_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
    626 		if (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||
    627 		    os_memcmp(s1, s2, 2 + s1[1]) != 0)
    628 			continue;
    629 
    630 		/* Same BSSID,SSID was already included in scan results */
    631 		wpa_printf(MSG_DEBUG, "nl80211: Remove duplicated scan result "
    632 			   "for " MACSTR, MAC2STR(r->bssid));
    633 
    634 		if (((r->flags & WPA_SCAN_ASSOCIATED) &&
    635 		     !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) ||
    636 		    r->age < res->res[i]->age) {
    637 			os_free(res->res[i]);
    638 			res->res[i] = r;
    639 		} else
    640 			os_free(r);
    641 		return NL_SKIP;
    642 	}
    643 
    644 	tmp = os_realloc_array(res->res, res->num + 1,
    645 			       sizeof(struct wpa_scan_res *));
    646 	if (tmp == NULL) {
    647 		os_free(r);
    648 		return NL_SKIP;
    649 	}
    650 	tmp[res->num++] = r;
    651 	res->res = tmp;
    652 
    653 	return NL_SKIP;
    654 }
    655 
    656 
    657 static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
    658 				 const u8 *addr)
    659 {
    660 	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
    661 		wpa_printf(MSG_DEBUG, "nl80211: Clear possible state "
    662 			   "mismatch (" MACSTR ")", MAC2STR(addr));
    663 		wpa_driver_nl80211_mlme(drv, addr,
    664 					NL80211_CMD_DEAUTHENTICATE,
    665 					WLAN_REASON_PREV_AUTH_NOT_VALID, 1);
    666 	}
    667 }
    668 
    669 
    670 static void wpa_driver_nl80211_check_bss_status(
    671 	struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res)
    672 {
    673 	size_t i;
    674 
    675 	for (i = 0; i < res->num; i++) {
    676 		struct wpa_scan_res *r = res->res[i];
    677 
    678 		if (r->flags & WPA_SCAN_ASSOCIATED) {
    679 			wpa_printf(MSG_DEBUG, "nl80211: Scan results "
    680 				   "indicate BSS status with " MACSTR
    681 				   " as associated",
    682 				   MAC2STR(r->bssid));
    683 			if (is_sta_interface(drv->nlmode) &&
    684 			    !drv->associated) {
    685 				wpa_printf(MSG_DEBUG, "nl80211: Local state "
    686 					   "(not associated) does not match "
    687 					   "with BSS state");
    688 				clear_state_mismatch(drv, r->bssid);
    689 			} else if (is_sta_interface(drv->nlmode) &&
    690 				   os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
    691 				   0) {
    692 				wpa_printf(MSG_DEBUG, "nl80211: Local state "
    693 					   "(associated with " MACSTR ") does "
    694 					   "not match with BSS state",
    695 					   MAC2STR(drv->bssid));
    696 				clear_state_mismatch(drv, r->bssid);
    697 				clear_state_mismatch(drv, drv->bssid);
    698 			}
    699 		}
    700 	}
    701 }
    702 
    703 
    704 static struct wpa_scan_results *
    705 nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
    706 {
    707 	struct nl_msg *msg;
    708 	struct wpa_scan_results *res;
    709 	int ret;
    710 	struct nl80211_bss_info_arg arg;
    711 
    712 	res = os_zalloc(sizeof(*res));
    713 	if (res == NULL)
    714 		return NULL;
    715 	if (!(msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP,
    716 				    NL80211_CMD_GET_SCAN))) {
    717 		wpa_scan_results_free(res);
    718 		return NULL;
    719 	}
    720 
    721 	arg.drv = drv;
    722 	arg.res = res;
    723 	ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
    724 	if (ret == 0) {
    725 		wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu "
    726 			   "BSSes)", (unsigned long) res->num);
    727 		nl80211_get_noise_for_scan_results(drv, res);
    728 		return res;
    729 	}
    730 	wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
    731 		   "(%s)", ret, strerror(-ret));
    732 	wpa_scan_results_free(res);
    733 	return NULL;
    734 }
    735 
    736 
    737 /**
    738  * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
    739  * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
    740  * Returns: Scan results on success, -1 on failure
    741  */
    742 struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv)
    743 {
    744 	struct i802_bss *bss = priv;
    745 	struct wpa_driver_nl80211_data *drv = bss->drv;
    746 	struct wpa_scan_results *res;
    747 
    748 	res = nl80211_get_scan_results(drv);
    749 	if (res)
    750 		wpa_driver_nl80211_check_bss_status(drv, res);
    751 	return res;
    752 }
    753 
    754 
    755 void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv)
    756 {
    757 	struct wpa_scan_results *res;
    758 	size_t i;
    759 
    760 	res = nl80211_get_scan_results(drv);
    761 	if (res == NULL) {
    762 		wpa_printf(MSG_DEBUG, "nl80211: Failed to get scan results");
    763 		return;
    764 	}
    765 
    766 	wpa_printf(MSG_DEBUG, "nl80211: Scan result dump");
    767 	for (i = 0; i < res->num; i++) {
    768 		struct wpa_scan_res *r = res->res[i];
    769 		wpa_printf(MSG_DEBUG, "nl80211: %d/%d " MACSTR "%s",
    770 			   (int) i, (int) res->num, MAC2STR(r->bssid),
    771 			   r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : "");
    772 	}
    773 
    774 	wpa_scan_results_free(res);
    775 }
    776