xref: /linux/net/wireless/mlme.c (revision a115bc070b1fc57ab23f3972401425927b5b465c)
1 /*
2  * cfg80211 MLME SAP interface
3  *
4  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
5  */
6 
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10 #include <linux/nl80211.h>
11 #include <linux/wireless.h>
12 #include <net/cfg80211.h>
13 #include <net/iw_handler.h>
14 #include "core.h"
15 #include "nl80211.h"
16 
17 void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
18 {
19 	struct wireless_dev *wdev = dev->ieee80211_ptr;
20 	struct wiphy *wiphy = wdev->wiphy;
21 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
22 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
23 	u8 *bssid = mgmt->bssid;
24 	int i;
25 	u16 status = le16_to_cpu(mgmt->u.auth.status_code);
26 	bool done = false;
27 
28 	wdev_lock(wdev);
29 
30 	for (i = 0; i < MAX_AUTH_BSSES; i++) {
31 		if (wdev->authtry_bsses[i] &&
32 		    memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
33 							ETH_ALEN) == 0) {
34 			if (status == WLAN_STATUS_SUCCESS) {
35 				wdev->auth_bsses[i] = wdev->authtry_bsses[i];
36 			} else {
37 				cfg80211_unhold_bss(wdev->authtry_bsses[i]);
38 				cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
39 			}
40 			wdev->authtry_bsses[i] = NULL;
41 			done = true;
42 			break;
43 		}
44 	}
45 
46 	WARN_ON(!done);
47 
48 	nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
49 	cfg80211_sme_rx_auth(dev, buf, len);
50 
51 	wdev_unlock(wdev);
52 }
53 EXPORT_SYMBOL(cfg80211_send_rx_auth);
54 
55 void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
56 {
57 	u16 status_code;
58 	struct wireless_dev *wdev = dev->ieee80211_ptr;
59 	struct wiphy *wiphy = wdev->wiphy;
60 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
61 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
62 	u8 *ie = mgmt->u.assoc_resp.variable;
63 	int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
64 	struct cfg80211_internal_bss *bss = NULL;
65 
66 	wdev_lock(wdev);
67 
68 	status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
69 
70 	/*
71 	 * This is a bit of a hack, we don't notify userspace of
72 	 * a (re-)association reply if we tried to send a reassoc
73 	 * and got a reject -- we only try again with an assoc
74 	 * frame instead of reassoc.
75 	 */
76 	if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
77 	    cfg80211_sme_failed_reassoc(wdev))
78 		goto out;
79 
80 	nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
81 
82 	if (status_code == WLAN_STATUS_SUCCESS) {
83 		for (i = 0; i < MAX_AUTH_BSSES; i++) {
84 			if (!wdev->auth_bsses[i])
85 				continue;
86 			if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid,
87 				   ETH_ALEN) == 0) {
88 				bss = wdev->auth_bsses[i];
89 				wdev->auth_bsses[i] = NULL;
90 				/* additional reference to drop hold */
91 				cfg80211_ref_bss(bss);
92 				break;
93 			}
94 		}
95 
96 		/*
97 		 * We might be coming here because the driver reported
98 		 * a successful association at the same time as the
99 		 * user requested a deauth. In that case, we will have
100 		 * removed the BSS from the auth_bsses list due to the
101 		 * deauth request when the assoc response makes it. If
102 		 * the two code paths acquire the lock the other way
103 		 * around, that's just the standard situation of a
104 		 * deauth being requested while connected.
105 		 */
106 		if (!bss)
107 			goto out;
108 	} else if (wdev->conn) {
109 		cfg80211_sme_failed_assoc(wdev);
110 		/*
111 		 * do not call connect_result() now because the
112 		 * sme will schedule work that does it later.
113 		 */
114 		goto out;
115 	}
116 
117 	if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
118 		/*
119 		 * This is for the userspace SME, the CONNECTING
120 		 * state will be changed to CONNECTED by
121 		 * __cfg80211_connect_result() below.
122 		 */
123 		wdev->sme_state = CFG80211_SME_CONNECTING;
124 	}
125 
126 	/* this consumes one bss reference (unless bss is NULL) */
127 	__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
128 				  status_code,
129 				  status_code == WLAN_STATUS_SUCCESS,
130 				  bss ? &bss->pub : NULL);
131 	/* drop hold now, and also reference acquired above */
132 	if (bss) {
133 		cfg80211_unhold_bss(bss);
134 		cfg80211_put_bss(&bss->pub);
135 	}
136 
137  out:
138 	wdev_unlock(wdev);
139 }
140 EXPORT_SYMBOL(cfg80211_send_rx_assoc);
141 
142 void __cfg80211_send_deauth(struct net_device *dev,
143 				   const u8 *buf, size_t len)
144 {
145 	struct wireless_dev *wdev = dev->ieee80211_ptr;
146 	struct wiphy *wiphy = wdev->wiphy;
147 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
148 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
149 	const u8 *bssid = mgmt->bssid;
150 	int i;
151 	bool found = false;
152 
153 	ASSERT_WDEV_LOCK(wdev);
154 
155 	if (wdev->current_bss &&
156 	    memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
157 		cfg80211_unhold_bss(wdev->current_bss);
158 		cfg80211_put_bss(&wdev->current_bss->pub);
159 		wdev->current_bss = NULL;
160 		found = true;
161 	} else for (i = 0; i < MAX_AUTH_BSSES; i++) {
162 		if (wdev->auth_bsses[i] &&
163 		    memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
164 			cfg80211_unhold_bss(wdev->auth_bsses[i]);
165 			cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
166 			wdev->auth_bsses[i] = NULL;
167 			found = true;
168 			break;
169 		}
170 		if (wdev->authtry_bsses[i] &&
171 		    memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
172 			cfg80211_unhold_bss(wdev->authtry_bsses[i]);
173 			cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
174 			wdev->authtry_bsses[i] = NULL;
175 			found = true;
176 			break;
177 		}
178 	}
179 
180 	if (!found)
181 		return;
182 
183 	nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
184 
185 	if (wdev->sme_state == CFG80211_SME_CONNECTED) {
186 		u16 reason_code;
187 		bool from_ap;
188 
189 		reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
190 
191 		from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
192 		__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
193 	} else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
194 		__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
195 					  WLAN_STATUS_UNSPECIFIED_FAILURE,
196 					  false, NULL);
197 	}
198 }
199 EXPORT_SYMBOL(__cfg80211_send_deauth);
200 
201 void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
202 {
203 	struct wireless_dev *wdev = dev->ieee80211_ptr;
204 
205 	wdev_lock(wdev);
206 	__cfg80211_send_deauth(dev, buf, len);
207 	wdev_unlock(wdev);
208 }
209 EXPORT_SYMBOL(cfg80211_send_deauth);
210 
211 void __cfg80211_send_disassoc(struct net_device *dev,
212 				     const u8 *buf, size_t len)
213 {
214 	struct wireless_dev *wdev = dev->ieee80211_ptr;
215 	struct wiphy *wiphy = wdev->wiphy;
216 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
217 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
218 	const u8 *bssid = mgmt->bssid;
219 	int i;
220 	u16 reason_code;
221 	bool from_ap;
222 	bool done = false;
223 
224 	ASSERT_WDEV_LOCK(wdev);
225 
226 	nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
227 
228 	if (wdev->sme_state != CFG80211_SME_CONNECTED)
229 		return;
230 
231 	if (wdev->current_bss &&
232 	    memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
233 		for (i = 0; i < MAX_AUTH_BSSES; i++) {
234 			if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
235 				continue;
236 			wdev->auth_bsses[i] = wdev->current_bss;
237 			wdev->current_bss = NULL;
238 			done = true;
239 			cfg80211_sme_disassoc(dev, i);
240 			break;
241 		}
242 		WARN_ON(!done);
243 	} else
244 		WARN_ON(1);
245 
246 
247 	reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
248 
249 	from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
250 	__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
251 }
252 EXPORT_SYMBOL(__cfg80211_send_disassoc);
253 
254 void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
255 {
256 	struct wireless_dev *wdev = dev->ieee80211_ptr;
257 
258 	wdev_lock(wdev);
259 	__cfg80211_send_disassoc(dev, buf, len);
260 	wdev_unlock(wdev);
261 }
262 EXPORT_SYMBOL(cfg80211_send_disassoc);
263 
264 static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr)
265 {
266 	int i;
267 	bool done = false;
268 
269 	ASSERT_WDEV_LOCK(wdev);
270 
271 	for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
272 		if (wdev->authtry_bsses[i] &&
273 		    memcmp(wdev->authtry_bsses[i]->pub.bssid,
274 			   addr, ETH_ALEN) == 0) {
275 			cfg80211_unhold_bss(wdev->authtry_bsses[i]);
276 			cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
277 			wdev->authtry_bsses[i] = NULL;
278 			done = true;
279 			break;
280 		}
281 	}
282 
283 	WARN_ON(!done);
284 }
285 
286 void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr)
287 {
288 	__cfg80211_auth_remove(dev->ieee80211_ptr, addr);
289 }
290 EXPORT_SYMBOL(__cfg80211_auth_canceled);
291 
292 void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
293 {
294 	struct wireless_dev *wdev = dev->ieee80211_ptr;
295 	struct wiphy *wiphy = wdev->wiphy;
296 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
297 
298 	wdev_lock(wdev);
299 
300 	nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
301 	if (wdev->sme_state == CFG80211_SME_CONNECTING)
302 		__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
303 					  WLAN_STATUS_UNSPECIFIED_FAILURE,
304 					  false, NULL);
305 
306 	__cfg80211_auth_remove(wdev, addr);
307 
308 	wdev_unlock(wdev);
309 }
310 EXPORT_SYMBOL(cfg80211_send_auth_timeout);
311 
312 void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
313 {
314 	struct wireless_dev *wdev = dev->ieee80211_ptr;
315 	struct wiphy *wiphy = wdev->wiphy;
316 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
317 	int i;
318 	bool done = false;
319 
320 	wdev_lock(wdev);
321 
322 	nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
323 	if (wdev->sme_state == CFG80211_SME_CONNECTING)
324 		__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
325 					  WLAN_STATUS_UNSPECIFIED_FAILURE,
326 					  false, NULL);
327 
328 	for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
329 		if (wdev->auth_bsses[i] &&
330 		    memcmp(wdev->auth_bsses[i]->pub.bssid,
331 			   addr, ETH_ALEN) == 0) {
332 			cfg80211_unhold_bss(wdev->auth_bsses[i]);
333 			cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
334 			wdev->auth_bsses[i] = NULL;
335 			done = true;
336 			break;
337 		}
338 	}
339 
340 	WARN_ON(!done);
341 
342 	wdev_unlock(wdev);
343 }
344 EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
345 
346 void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
347 				  enum nl80211_key_type key_type, int key_id,
348 				  const u8 *tsc, gfp_t gfp)
349 {
350 	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
351 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
352 #ifdef CONFIG_CFG80211_WEXT
353 	union iwreq_data wrqu;
354 	char *buf = kmalloc(128, gfp);
355 
356 	if (buf) {
357 		sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
358 			"keyid=%d %scast addr=%pM)", key_id,
359 			key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
360 			addr);
361 		memset(&wrqu, 0, sizeof(wrqu));
362 		wrqu.data.length = strlen(buf);
363 		wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
364 		kfree(buf);
365 	}
366 #endif
367 
368 	nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
369 }
370 EXPORT_SYMBOL(cfg80211_michael_mic_failure);
371 
372 /* some MLME handling for userspace SME */
373 int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
374 			 struct net_device *dev,
375 			 struct ieee80211_channel *chan,
376 			 enum nl80211_auth_type auth_type,
377 			 const u8 *bssid,
378 			 const u8 *ssid, int ssid_len,
379 			 const u8 *ie, int ie_len,
380 			 const u8 *key, int key_len, int key_idx)
381 {
382 	struct wireless_dev *wdev = dev->ieee80211_ptr;
383 	struct cfg80211_auth_request req;
384 	struct cfg80211_internal_bss *bss;
385 	int i, err, slot = -1, nfree = 0;
386 
387 	ASSERT_WDEV_LOCK(wdev);
388 
389 	if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
390 		if (!key || !key_len || key_idx < 0 || key_idx > 4)
391 			return -EINVAL;
392 
393 	if (wdev->current_bss &&
394 	    memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
395 		return -EALREADY;
396 
397 	for (i = 0; i < MAX_AUTH_BSSES; i++) {
398 		if (wdev->authtry_bsses[i] &&
399 		    memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid,
400 						ETH_ALEN) == 0)
401 			return -EALREADY;
402 		if (wdev->auth_bsses[i] &&
403 		    memcmp(bssid, wdev->auth_bsses[i]->pub.bssid,
404 						ETH_ALEN) == 0)
405 			return -EALREADY;
406 	}
407 
408 	memset(&req, 0, sizeof(req));
409 
410 	req.ie = ie;
411 	req.ie_len = ie_len;
412 	req.auth_type = auth_type;
413 	req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
414 				   WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
415 	req.key = key;
416 	req.key_len = key_len;
417 	req.key_idx = key_idx;
418 	if (!req.bss)
419 		return -ENOENT;
420 
421 	bss = bss_from_pub(req.bss);
422 
423 	for (i = 0; i < MAX_AUTH_BSSES; i++) {
424 		if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) {
425 			slot = i;
426 			nfree++;
427 		}
428 	}
429 
430 	/* we need one free slot for disassoc and one for this auth */
431 	if (nfree < 2) {
432 		err = -ENOSPC;
433 		goto out;
434 	}
435 
436 	wdev->authtry_bsses[slot] = bss;
437 	cfg80211_hold_bss(bss);
438 
439 	err = rdev->ops->auth(&rdev->wiphy, dev, &req);
440 	if (err) {
441 		wdev->authtry_bsses[slot] = NULL;
442 		cfg80211_unhold_bss(bss);
443 	}
444 
445  out:
446 	if (err)
447 		cfg80211_put_bss(req.bss);
448 	return err;
449 }
450 
451 int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
452 		       struct net_device *dev, struct ieee80211_channel *chan,
453 		       enum nl80211_auth_type auth_type, const u8 *bssid,
454 		       const u8 *ssid, int ssid_len,
455 		       const u8 *ie, int ie_len,
456 		       const u8 *key, int key_len, int key_idx)
457 {
458 	int err;
459 
460 	wdev_lock(dev->ieee80211_ptr);
461 	err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
462 				   ssid, ssid_len, ie, ie_len,
463 				   key, key_len, key_idx);
464 	wdev_unlock(dev->ieee80211_ptr);
465 
466 	return err;
467 }
468 
469 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
470 			  struct net_device *dev,
471 			  struct ieee80211_channel *chan,
472 			  const u8 *bssid, const u8 *prev_bssid,
473 			  const u8 *ssid, int ssid_len,
474 			  const u8 *ie, int ie_len, bool use_mfp,
475 			  struct cfg80211_crypto_settings *crypt)
476 {
477 	struct wireless_dev *wdev = dev->ieee80211_ptr;
478 	struct cfg80211_assoc_request req;
479 	struct cfg80211_internal_bss *bss;
480 	int i, err, slot = -1;
481 	bool was_connected = false;
482 
483 	ASSERT_WDEV_LOCK(wdev);
484 
485 	memset(&req, 0, sizeof(req));
486 
487 	if (wdev->current_bss && prev_bssid &&
488 	    memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) {
489 		/*
490 		 * Trying to reassociate: Allow this to proceed and let the old
491 		 * association to be dropped when the new one is completed.
492 		 */
493 		if (wdev->sme_state == CFG80211_SME_CONNECTED) {
494 			was_connected = true;
495 			wdev->sme_state = CFG80211_SME_CONNECTING;
496 		}
497 	} else if (wdev->current_bss)
498 		return -EALREADY;
499 
500 	req.ie = ie;
501 	req.ie_len = ie_len;
502 	memcpy(&req.crypto, crypt, sizeof(req.crypto));
503 	req.use_mfp = use_mfp;
504 	req.prev_bssid = prev_bssid;
505 	req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
506 				   WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
507 	if (!req.bss) {
508 		if (was_connected)
509 			wdev->sme_state = CFG80211_SME_CONNECTED;
510 		return -ENOENT;
511 	}
512 
513 	bss = bss_from_pub(req.bss);
514 
515 	for (i = 0; i < MAX_AUTH_BSSES; i++) {
516 		if (bss == wdev->auth_bsses[i]) {
517 			slot = i;
518 			break;
519 		}
520 	}
521 
522 	if (slot < 0) {
523 		err = -ENOTCONN;
524 		goto out;
525 	}
526 
527 	err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
528  out:
529 	if (err && was_connected)
530 		wdev->sme_state = CFG80211_SME_CONNECTED;
531 	/* still a reference in wdev->auth_bsses[slot] */
532 	cfg80211_put_bss(req.bss);
533 	return err;
534 }
535 
536 int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
537 			struct net_device *dev,
538 			struct ieee80211_channel *chan,
539 			const u8 *bssid, const u8 *prev_bssid,
540 			const u8 *ssid, int ssid_len,
541 			const u8 *ie, int ie_len, bool use_mfp,
542 			struct cfg80211_crypto_settings *crypt)
543 {
544 	struct wireless_dev *wdev = dev->ieee80211_ptr;
545 	int err;
546 
547 	wdev_lock(wdev);
548 	err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
549 				    ssid, ssid_len, ie, ie_len, use_mfp, crypt);
550 	wdev_unlock(wdev);
551 
552 	return err;
553 }
554 
555 int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
556 			   struct net_device *dev, const u8 *bssid,
557 			   const u8 *ie, int ie_len, u16 reason)
558 {
559 	struct wireless_dev *wdev = dev->ieee80211_ptr;
560 	struct cfg80211_deauth_request req;
561 	int i;
562 
563 	ASSERT_WDEV_LOCK(wdev);
564 
565 	memset(&req, 0, sizeof(req));
566 	req.reason_code = reason;
567 	req.ie = ie;
568 	req.ie_len = ie_len;
569 	if (wdev->current_bss &&
570 	    memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
571 		req.bss = &wdev->current_bss->pub;
572 	} else for (i = 0; i < MAX_AUTH_BSSES; i++) {
573 		if (wdev->auth_bsses[i] &&
574 		    memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
575 			req.bss = &wdev->auth_bsses[i]->pub;
576 			break;
577 		}
578 		if (wdev->authtry_bsses[i] &&
579 		    memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
580 			req.bss = &wdev->authtry_bsses[i]->pub;
581 			break;
582 		}
583 	}
584 
585 	if (!req.bss)
586 		return -ENOTCONN;
587 
588 	return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
589 }
590 
591 int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
592 			 struct net_device *dev, const u8 *bssid,
593 			 const u8 *ie, int ie_len, u16 reason)
594 {
595 	struct wireless_dev *wdev = dev->ieee80211_ptr;
596 	int err;
597 
598 	wdev_lock(wdev);
599 	err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason);
600 	wdev_unlock(wdev);
601 
602 	return err;
603 }
604 
605 static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
606 				    struct net_device *dev, const u8 *bssid,
607 				    const u8 *ie, int ie_len, u16 reason)
608 {
609 	struct wireless_dev *wdev = dev->ieee80211_ptr;
610 	struct cfg80211_disassoc_request req;
611 
612 	ASSERT_WDEV_LOCK(wdev);
613 
614 	if (wdev->sme_state != CFG80211_SME_CONNECTED)
615 		return -ENOTCONN;
616 
617 	if (WARN_ON(!wdev->current_bss))
618 		return -ENOTCONN;
619 
620 	memset(&req, 0, sizeof(req));
621 	req.reason_code = reason;
622 	req.ie = ie;
623 	req.ie_len = ie_len;
624 	if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
625 		req.bss = &wdev->current_bss->pub;
626 	else
627 		return -ENOTCONN;
628 
629 	return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev);
630 }
631 
632 int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
633 			   struct net_device *dev, const u8 *bssid,
634 			   const u8 *ie, int ie_len, u16 reason)
635 {
636 	struct wireless_dev *wdev = dev->ieee80211_ptr;
637 	int err;
638 
639 	wdev_lock(wdev);
640 	err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason);
641 	wdev_unlock(wdev);
642 
643 	return err;
644 }
645 
646 void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
647 			struct net_device *dev)
648 {
649 	struct wireless_dev *wdev = dev->ieee80211_ptr;
650 	struct cfg80211_deauth_request req;
651 	int i;
652 
653 	ASSERT_WDEV_LOCK(wdev);
654 
655 	if (!rdev->ops->deauth)
656 		return;
657 
658 	memset(&req, 0, sizeof(req));
659 	req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
660 	req.ie = NULL;
661 	req.ie_len = 0;
662 
663 	if (wdev->current_bss) {
664 		req.bss = &wdev->current_bss->pub;
665 		rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
666 		if (wdev->current_bss) {
667 			cfg80211_unhold_bss(wdev->current_bss);
668 			cfg80211_put_bss(&wdev->current_bss->pub);
669 			wdev->current_bss = NULL;
670 		}
671 	}
672 
673 	for (i = 0; i < MAX_AUTH_BSSES; i++) {
674 		if (wdev->auth_bsses[i]) {
675 			req.bss = &wdev->auth_bsses[i]->pub;
676 			rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
677 			if (wdev->auth_bsses[i]) {
678 				cfg80211_unhold_bss(wdev->auth_bsses[i]);
679 				cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
680 				wdev->auth_bsses[i] = NULL;
681 			}
682 		}
683 		if (wdev->authtry_bsses[i]) {
684 			req.bss = &wdev->authtry_bsses[i]->pub;
685 			rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
686 			if (wdev->authtry_bsses[i]) {
687 				cfg80211_unhold_bss(wdev->authtry_bsses[i]);
688 				cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
689 				wdev->authtry_bsses[i] = NULL;
690 			}
691 		}
692 	}
693 }
694 
695 void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
696 			       struct ieee80211_channel *chan,
697 			       enum nl80211_channel_type channel_type,
698 			       unsigned int duration, gfp_t gfp)
699 {
700 	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
701 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
702 
703 	nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type,
704 				       duration, gfp);
705 }
706 EXPORT_SYMBOL(cfg80211_ready_on_channel);
707 
708 void cfg80211_remain_on_channel_expired(struct net_device *dev,
709 					u64 cookie,
710 					struct ieee80211_channel *chan,
711 					enum nl80211_channel_type channel_type,
712 					gfp_t gfp)
713 {
714 	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
715 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
716 
717 	nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan,
718 					      channel_type, gfp);
719 }
720 EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
721 
722 void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
723 		      struct station_info *sinfo, gfp_t gfp)
724 {
725 	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
726 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
727 
728 	nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
729 }
730 EXPORT_SYMBOL(cfg80211_new_sta);
731 
732 struct cfg80211_action_registration {
733 	struct list_head list;
734 
735 	u32 nlpid;
736 
737 	int match_len;
738 
739 	u8 match[];
740 };
741 
742 int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
743 				  const u8 *match_data, int match_len)
744 {
745 	struct cfg80211_action_registration *reg, *nreg;
746 	int err = 0;
747 
748 	nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
749 	if (!nreg)
750 		return -ENOMEM;
751 
752 	spin_lock_bh(&wdev->action_registrations_lock);
753 
754 	list_for_each_entry(reg, &wdev->action_registrations, list) {
755 		int mlen = min(match_len, reg->match_len);
756 
757 		if (memcmp(reg->match, match_data, mlen) == 0) {
758 			err = -EALREADY;
759 			break;
760 		}
761 	}
762 
763 	if (err) {
764 		kfree(nreg);
765 		goto out;
766 	}
767 
768 	memcpy(nreg->match, match_data, match_len);
769 	nreg->match_len = match_len;
770 	nreg->nlpid = snd_pid;
771 	list_add(&nreg->list, &wdev->action_registrations);
772 
773  out:
774 	spin_unlock_bh(&wdev->action_registrations_lock);
775 	return err;
776 }
777 
778 void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid)
779 {
780 	struct cfg80211_action_registration *reg, *tmp;
781 
782 	spin_lock_bh(&wdev->action_registrations_lock);
783 
784 	list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
785 		if (reg->nlpid == nlpid) {
786 			list_del(&reg->list);
787 			kfree(reg);
788 		}
789 	}
790 
791 	spin_unlock_bh(&wdev->action_registrations_lock);
792 }
793 
794 void cfg80211_mlme_purge_actions(struct wireless_dev *wdev)
795 {
796 	struct cfg80211_action_registration *reg, *tmp;
797 
798 	spin_lock_bh(&wdev->action_registrations_lock);
799 
800 	list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
801 		list_del(&reg->list);
802 		kfree(reg);
803 	}
804 
805 	spin_unlock_bh(&wdev->action_registrations_lock);
806 }
807 
808 int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
809 			 struct net_device *dev,
810 			 struct ieee80211_channel *chan,
811 			 enum nl80211_channel_type channel_type,
812 			 const u8 *buf, size_t len, u64 *cookie)
813 {
814 	struct wireless_dev *wdev = dev->ieee80211_ptr;
815 	const struct ieee80211_mgmt *mgmt;
816 
817 	if (rdev->ops->action == NULL)
818 		return -EOPNOTSUPP;
819 	if (len < 24 + 1)
820 		return -EINVAL;
821 
822 	mgmt = (const struct ieee80211_mgmt *) buf;
823 	if (!ieee80211_is_action(mgmt->frame_control))
824 		return -EINVAL;
825 	if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
826 		/* Verify that we are associated with the destination AP */
827 		if (!wdev->current_bss ||
828 		    memcmp(wdev->current_bss->pub.bssid, mgmt->bssid,
829 			   ETH_ALEN) != 0 ||
830 		    memcmp(wdev->current_bss->pub.bssid, mgmt->da,
831 			   ETH_ALEN) != 0)
832 			return -ENOTCONN;
833 	}
834 
835 	if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
836 		return -EINVAL;
837 
838 	/* Transmit the Action frame as requested by user space */
839 	return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type,
840 				 buf, len, cookie);
841 }
842 
843 bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
844 			size_t len, gfp_t gfp)
845 {
846 	struct wireless_dev *wdev = dev->ieee80211_ptr;
847 	struct wiphy *wiphy = wdev->wiphy;
848 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
849 	struct cfg80211_action_registration *reg;
850 	const u8 *action_data;
851 	int action_data_len;
852 	bool result = false;
853 
854 	/* frame length - min size excluding category */
855 	action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1);
856 
857 	/* action data starts with category */
858 	action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1;
859 
860 	spin_lock_bh(&wdev->action_registrations_lock);
861 
862 	list_for_each_entry(reg, &wdev->action_registrations, list) {
863 		if (reg->match_len > action_data_len)
864 			continue;
865 
866 		if (memcmp(reg->match, action_data, reg->match_len))
867 			continue;
868 
869 		/* found match! */
870 
871 		/* Indicate the received Action frame to user space */
872 		if (nl80211_send_action(rdev, dev, reg->nlpid, freq,
873 					buf, len, gfp))
874 			continue;
875 
876 		result = true;
877 		break;
878 	}
879 
880 	spin_unlock_bh(&wdev->action_registrations_lock);
881 
882 	return result;
883 }
884 EXPORT_SYMBOL(cfg80211_rx_action);
885 
886 void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
887 			       const u8 *buf, size_t len, bool ack, gfp_t gfp)
888 {
889 	struct wireless_dev *wdev = dev->ieee80211_ptr;
890 	struct wiphy *wiphy = wdev->wiphy;
891 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
892 
893 	/* Indicate TX status of the Action frame to user space */
894 	nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
895 }
896 EXPORT_SYMBOL(cfg80211_action_tx_status);
897