scan.c 12.7 KB
Newer Older
1
/*
2 3
 * Scanning implementation
 *
4 5 6 7 8 9 10 11 12 13 14
 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
 * Copyright 2004, Instant802 Networks, Inc.
 * Copyright 2005, Devicescape Software, Inc.
 * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

15
/* TODO: figure out how to avoid that the "current BSS" expires */
16

17 18
#include <linux/wireless.h>
#include <linux/if_arp.h>
19
#include <linux/rtnetlink.h>
20 21 22 23
#include <net/mac80211.h>
#include <net/iw_handler.h>

#include "ieee80211_i.h"
24
#include "mesh.h"
25 26 27 28 29

#define IEEE80211_PROBE_DELAY (HZ / 33)
#define IEEE80211_CHANNEL_TIME (HZ / 33)
#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)

30
struct ieee80211_bss *
31 32 33
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
		     u8 *ssid, u8 ssid_len)
{
34 35 36 37 38
	return (void *)cfg80211_get_bss(local->hw.wiphy,
					ieee80211_get_channel(local->hw.wiphy,
							      freq),
					bssid, ssid, ssid_len,
					0, 0);
39 40
}

41
static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
42
{
43
	struct ieee80211_bss *bss = (void *)cbss;
44 45 46 47 48 49

	kfree(bss_mesh_id(bss));
	kfree(bss_mesh_cfg(bss));
}

void ieee80211_rx_bss_put(struct ieee80211_local *local,
50
			  struct ieee80211_bss *bss)
51
{
52
	cfg80211_put_bss((struct cfg80211_bss *)bss);
53 54
}

55
struct ieee80211_bss *
56 57 58 59 60
ieee80211_bss_info_update(struct ieee80211_local *local,
			  struct ieee80211_rx_status *rx_status,
			  struct ieee80211_mgmt *mgmt,
			  size_t len,
			  struct ieee802_11_elems *elems,
61 62
			  struct ieee80211_channel *channel,
			  bool beacon)
63
{
64
	struct ieee80211_bss *bss;
65
	int clen;
66 67
	s32 signal = 0;

J
Johannes Berg 已提交
68
	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
69
		signal = rx_status->signal * 100;
J
Johannes Berg 已提交
70
	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
71 72
		signal = (rx_status->signal * 100) / local->hw.max_signal;

73
	bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel,
J
Johannes Berg 已提交
74
						mgmt, len, signal, GFP_ATOMIC);
75

76 77 78 79
	if (!bss)
		return NULL;

	bss->cbss.free_priv = ieee80211_rx_bss_free;
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

	/* save the ERP value so that it is available at association time */
	if (elems->erp_info && elems->erp_info_len >= 1) {
		bss->erp_value = elems->erp_info[0];
		bss->has_erp_value = 1;
	}

	if (elems->tim) {
		struct ieee80211_tim_ie *tim_ie =
			(struct ieee80211_tim_ie *)elems->tim;
		bss->dtim_period = tim_ie->dtim_period;
	}

	/* set default value for buggy APs */
	if (!elems->tim || bss->dtim_period == 0)
		bss->dtim_period = 1;

	bss->supp_rates_len = 0;
	if (elems->supp_rates) {
		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
		if (clen > elems->supp_rates_len)
			clen = elems->supp_rates_len;
		memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates,
		       clen);
		bss->supp_rates_len += clen;
	}
	if (elems->ext_supp_rates) {
		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
		if (clen > elems->ext_supp_rates_len)
			clen = elems->ext_supp_rates_len;
		memcpy(&bss->supp_rates[bss->supp_rates_len],
		       elems->ext_supp_rates, clen);
		bss->supp_rates_len += clen;
	}

	bss->wmm_used = elems->wmm_param || elems->wmm_info;

	if (!beacon)
		bss->last_probe_resp = jiffies;

	return bss;
}
122

123 124 125 126 127 128 129 130
void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid,
			     int freq, u8 *ssid, u8 ssid_len)
{
	struct ieee80211_bss *bss;
	struct ieee80211_local *local = sdata->local;

	bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len);
	if (bss) {
131
		cfg80211_unlink_bss(local->hw.wiphy, (void *)bss);
132 133 134 135
		ieee80211_rx_bss_put(local, bss);
	}
}

136
ieee80211_rx_result
137 138
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
		  struct ieee80211_rx_status *rx_status)
139 140
{
	struct ieee80211_mgmt *mgmt;
141
	struct ieee80211_bss *bss;
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
	u8 *elements;
	struct ieee80211_channel *channel;
	size_t baselen;
	int freq;
	__le16 fc;
	bool presp, beacon = false;
	struct ieee802_11_elems elems;

	if (skb->len < 2)
		return RX_DROP_UNUSABLE;

	mgmt = (struct ieee80211_mgmt *) skb->data;
	fc = mgmt->frame_control;

	if (ieee80211_is_ctl(fc))
		return RX_CONTINUE;

	if (skb->len < 24)
		return RX_DROP_MONITOR;

	presp = ieee80211_is_probe_resp(fc);
	if (presp) {
		/* ignore ProbeResp to foreign address */
		if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
			return RX_DROP_MONITOR;

		presp = true;
		elements = mgmt->u.probe_resp.variable;
		baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
	} else {
		beacon = ieee80211_is_beacon(fc);
		baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
		elements = mgmt->u.beacon.variable;
	}

	if (!presp && !beacon)
		return RX_CONTINUE;

	if (baselen > skb->len)
		return RX_DROP_MONITOR;

	ieee802_11_parse_elems(elements, skb->len - baselen, &elems);

	if (elems.ds_params && elems.ds_params_len == 1)
		freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
	else
		freq = rx_status->freq;

	channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq);

	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
		return RX_DROP_MONITOR;

	bss = ieee80211_bss_info_update(sdata->local, rx_status,
					mgmt, skb->len, &elems,
197
					channel, beacon);
198 199
	if (bss)
		ieee80211_rx_bss_put(sdata->local, bss);
200 201 202 203 204

	dev_kfree_skb(skb);
	return RX_QUEUED;
}

205 206 207 208 209 210 211 212 213 214 215 216
void ieee80211_scan_failed(struct ieee80211_local *local)
{
	if (WARN_ON(!local->scan_req))
		return;

	/* notify cfg80211 about the failed scan */
	if (local->scan_req != &local->int_scan_req)
		cfg80211_scan_done(local->scan_req, true);

	local->scan_req = NULL;
}

217
void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
218 219 220 221
{
	struct ieee80211_local *local = hw_to_local(hw);
	struct ieee80211_sub_if_data *sdata;

222
	if (WARN_ON(!local->hw_scanning && !local->sw_scanning))
223 224
		return;

225 226
	if (WARN_ON(!local->scan_req))
		return;
227

228 229 230 231 232
	if (local->scan_req != &local->int_scan_req)
		cfg80211_scan_done(local->scan_req, aborted);
	local->scan_req = NULL;

	local->last_scan_completed = jiffies;
233

234 235
	if (local->hw_scanning) {
		local->hw_scanning = false;
236 237 238 239 240 241
		/*
		 * Somebody might have requested channel change during scan
		 * that we won't have acted upon, try now. ieee80211_hw_config
		 * will set the flag based on actual changes.
		 */
		ieee80211_hw_config(local, 0);
242 243 244
		goto done;
	}

245
	local->sw_scanning = false;
246
	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
247 248 249 250 251 252 253 254 255 256 257 258 259

	netif_tx_lock_bh(local->mdev);
	netif_addr_lock(local->mdev);
	local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
	local->ops->configure_filter(local_to_hw(local),
				     FIF_BCN_PRBRESP_PROMISC,
				     &local->filter_flags,
				     local->mdev->mc_count,
				     local->mdev->mc_list);

	netif_addr_unlock(local->mdev);
	netif_tx_unlock_bh(local->mdev);

260 261 262
	if (local->ops->sw_scan_complete)
		local->ops->sw_scan_complete(local_to_hw(local));

263 264
	mutex_lock(&local->iflist_mtx);
	list_for_each_entry(sdata, &local->interfaces, list) {
265 266 267
		if (!netif_running(sdata->dev))
			continue;

268
		/* Tell AP we're back */
269
		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
270
			if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
271 272 273 274 275
				ieee80211_send_nullfunc(local, sdata, 0);
				netif_tx_wake_all_queues(sdata->dev);
			}
		} else
			netif_tx_wake_all_queues(sdata->dev);
276

J
Johannes Berg 已提交
277 278 279 280 281 282
		/* re-enable beaconing */
		if (sdata->vif.type == NL80211_IFTYPE_AP ||
		    sdata->vif.type == NL80211_IFTYPE_ADHOC ||
		    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
			ieee80211_if_config(sdata,
					    IEEE80211_IFCC_BEACON_ENABLED);
283
	}
284
	mutex_unlock(&local->iflist_mtx);
285 286 287

 done:
	ieee80211_mlme_notify_scan_completed(local);
288
	ieee80211_ibss_notify_scan_completed(local);
289
	ieee80211_mesh_notify_scan_completed(local);
290 291 292
}
EXPORT_SYMBOL(ieee80211_scan_completed);

293
void ieee80211_scan_work(struct work_struct *work)
294 295 296 297 298
{
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local, scan_work.work);
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
	struct ieee80211_channel *chan;
299
	int skip, i;
300 301
	unsigned long next_delay = 0;

302 303 304 305
	/*
	 * Avoid re-scheduling when the sdata is going away.
	 */
	if (!netif_running(sdata->dev))
306 307 308 309 310
		return;

	switch (local->scan_state) {
	case SCAN_SET_CHANNEL:
		/* if no more bands/channels left, complete scan */
311 312
		if (local->scan_channel_idx >= local->scan_req->n_channels) {
			ieee80211_scan_completed(local_to_hw(local), false);
313 314 315
			return;
		}
		skip = 0;
316
		chan = local->scan_req->channels[local->scan_channel_idx];
317 318

		if (chan->flags & IEEE80211_CHAN_DISABLED ||
319
		    (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
320 321 322 323 324
		     chan->flags & IEEE80211_CHAN_NO_IBSS))
			skip = 1;

		if (!skip) {
			local->scan_channel = chan;
325 326
			if (ieee80211_hw_config(local,
						IEEE80211_CONF_CHANGE_CHANNEL))
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
				skip = 1;
		}

		/* advance state machine to next channel/band */
		local->scan_channel_idx++;

		if (skip)
			break;

		next_delay = IEEE80211_PROBE_DELAY +
			     usecs_to_jiffies(local->hw.channel_change_time);
		local->scan_state = SCAN_SEND_PROBE;
		break;
	case SCAN_SEND_PROBE:
		next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
		local->scan_state = SCAN_SET_CHANNEL;

344 345
		if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
		    !local->scan_req->n_ssids)
346
			break;
347 348 349 350
		for (i = 0; i < local->scan_req->n_ssids; i++)
			ieee80211_send_probe_req(
				sdata, NULL,
				local->scan_req->ssids[i].ssid,
351 352
				local->scan_req->ssids[i].ssid_len,
				local->scan_req->ie, local->scan_req->ie_len);
353 354 355 356
		next_delay = IEEE80211_CHANNEL_TIME;
		break;
	}

357 358
	queue_delayed_work(local->hw.workqueue, &local->scan_work,
			   next_delay);
359 360 361
}


362
int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata,
363
			 struct cfg80211_scan_request *req)
364 365 366 367
{
	struct ieee80211_local *local = scan_sdata->local;
	struct ieee80211_sub_if_data *sdata;

368
	if (!req)
369 370
		return -EINVAL;

371 372 373 374 375
	if (local->scan_req && local->scan_req != req)
		return -EBUSY;

	local->scan_req = req;

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
	/* MLME-SCAN.request (page 118)  page 144 (11.1.3.1)
	 * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
	 * BSSID: MACAddress
	 * SSID
	 * ScanType: ACTIVE, PASSIVE
	 * ProbeDelay: delay (in microseconds) to be used prior to transmitting
	 *    a Probe frame during active scanning
	 * ChannelList
	 * MinChannelTime (>= ProbeDelay), in TU
	 * MaxChannelTime: (>= MinChannelTime), in TU
	 */

	 /* MLME-SCAN.confirm
	  * BSSDescriptionSet
	  * ResultCode: SUCCESS, INVALID_PARAMETERS
	 */

393
	if (local->sw_scanning || local->hw_scanning) {
394 395 396 397 398 399
		if (local->scan_sdata == scan_sdata)
			return 0;
		return -EBUSY;
	}

	if (local->ops->hw_scan) {
400 401
		int rc;

402
		local->hw_scanning = true;
403
		rc = local->ops->hw_scan(local_to_hw(local), req);
404
		if (rc) {
405
			local->hw_scanning = false;
406
			return rc;
407
		}
408 409
		local->scan_sdata = scan_sdata;
		return 0;
410 411
	}

412
	local->sw_scanning = true;
413 414
	if (local->ops->sw_scan_start)
		local->ops->sw_scan_start(local_to_hw(local));
415

416 417
	mutex_lock(&local->iflist_mtx);
	list_for_each_entry(sdata, &local->interfaces, list) {
418 419 420
		if (!netif_running(sdata->dev))
			continue;

J
Johannes Berg 已提交
421 422 423 424 425 426
		/* disable beaconing */
		if (sdata->vif.type == NL80211_IFTYPE_AP ||
		    sdata->vif.type == NL80211_IFTYPE_ADHOC ||
		    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
			ieee80211_if_config(sdata,
					    IEEE80211_IFCC_BEACON_ENABLED);
427

428
		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
429
			if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
430 431 432 433 434 435
				netif_tx_stop_all_queues(sdata->dev);
				ieee80211_send_nullfunc(local, sdata, 1);
			}
		} else
			netif_tx_stop_all_queues(sdata->dev);
	}
436
	mutex_unlock(&local->iflist_mtx);
437 438 439 440

	local->scan_state = SCAN_SET_CHANNEL;
	local->scan_channel_idx = 0;
	local->scan_sdata = scan_sdata;
441
	local->scan_req = req;
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459

	netif_addr_lock_bh(local->mdev);
	local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
	local->ops->configure_filter(local_to_hw(local),
				     FIF_BCN_PRBRESP_PROMISC,
				     &local->filter_flags,
				     local->mdev->mc_count,
				     local->mdev->mc_list);
	netif_addr_unlock_bh(local->mdev);

	/* TODO: start scan as soon as all nullfunc frames are ACKed */
	queue_delayed_work(local->hw.workqueue, &local->scan_work,
			   IEEE80211_CHANNEL_TIME);

	return 0;
}


460
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
461
			   struct cfg80211_scan_request *req)
462 463
{
	struct ieee80211_local *local = sdata->local;
464
	struct ieee80211_if_managed *ifmgd;
465

466 467 468 469 470 471 472 473
	if (!req)
		return -EINVAL;

	if (local->scan_req && local->scan_req != req)
		return -EBUSY;

	local->scan_req = req;

474
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
475
		return ieee80211_start_scan(sdata, req);
476

J
Johannes Berg 已提交
477 478 479 480 481 482
	/*
	 * STA has a state machine that might need to defer scanning
	 * while it's trying to associate/authenticate, therefore we
	 * queue it up to the state machine in that case.
	 */

483
	if (local->sw_scanning || local->hw_scanning) {
484 485 486 487 488
		if (local->scan_sdata == sdata)
			return 0;
		return -EBUSY;
	}

489 490 491
	ifmgd = &sdata->u.mgd;
	set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
	queue_work(local->hw.workqueue, &ifmgd->work);
J
Johannes Berg 已提交
492

493 494
	return 0;
}