cfg.c revision 636a5d3625993c5ca59abc81794b9ded93cdb740
1/*
2 * mac80211 configuration hooks for cfg80211
3 *
4 * Copyright 2006, 2007	Johannes Berg <johannes@sipsolutions.net>
5 *
6 * This file is GPLv2 as found in COPYING.
7 */
8
9#include <linux/ieee80211.h>
10#include <linux/nl80211.h>
11#include <linux/rtnetlink.h>
12#include <net/net_namespace.h>
13#include <linux/rcupdate.h>
14#include <net/cfg80211.h>
15#include "ieee80211_i.h"
16#include "cfg.h"
17#include "rate.h"
18#include "mesh.h"
19
20static bool nl80211_type_check(enum nl80211_iftype type)
21{
22	switch (type) {
23	case NL80211_IFTYPE_ADHOC:
24	case NL80211_IFTYPE_STATION:
25	case NL80211_IFTYPE_MONITOR:
26#ifdef CONFIG_MAC80211_MESH
27	case NL80211_IFTYPE_MESH_POINT:
28#endif
29	case NL80211_IFTYPE_AP:
30	case NL80211_IFTYPE_AP_VLAN:
31	case NL80211_IFTYPE_WDS:
32		return true;
33	default:
34		return false;
35	}
36}
37
38static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
39			       enum nl80211_iftype type, u32 *flags,
40			       struct vif_params *params)
41{
42	struct ieee80211_local *local = wiphy_priv(wiphy);
43	struct net_device *dev;
44	struct ieee80211_sub_if_data *sdata;
45	int err;
46
47	if (!nl80211_type_check(type))
48		return -EINVAL;
49
50	err = ieee80211_if_add(local, name, &dev, type, params);
51	if (err || type != NL80211_IFTYPE_MONITOR || !flags)
52		return err;
53
54	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
55	sdata->u.mntr_flags = *flags;
56	return 0;
57}
58
59static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
60{
61	struct net_device *dev;
62	struct ieee80211_sub_if_data *sdata;
63
64	/* we're under RTNL */
65	dev = __dev_get_by_index(&init_net, ifindex);
66	if (!dev)
67		return -ENODEV;
68
69	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
70
71	ieee80211_if_remove(sdata);
72
73	return 0;
74}
75
76static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
77				  enum nl80211_iftype type, u32 *flags,
78				  struct vif_params *params)
79{
80	struct net_device *dev;
81	struct ieee80211_sub_if_data *sdata;
82	int ret;
83
84	/* we're under RTNL */
85	dev = __dev_get_by_index(&init_net, ifindex);
86	if (!dev)
87		return -ENODEV;
88
89	if (!nl80211_type_check(type))
90		return -EINVAL;
91
92	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
93
94	ret = ieee80211_if_change_type(sdata, type);
95	if (ret)
96		return ret;
97
98	if (netif_running(sdata->dev))
99		return -EBUSY;
100
101	if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
102		ieee80211_sdata_set_mesh_id(sdata,
103					    params->mesh_id_len,
104					    params->mesh_id);
105
106	if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
107		return 0;
108
109	sdata->u.mntr_flags = *flags;
110	return 0;
111}
112
113static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
114			     u8 key_idx, u8 *mac_addr,
115			     struct key_params *params)
116{
117	struct ieee80211_sub_if_data *sdata;
118	struct sta_info *sta = NULL;
119	enum ieee80211_key_alg alg;
120	struct ieee80211_key *key;
121	int err;
122
123	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
124
125	switch (params->cipher) {
126	case WLAN_CIPHER_SUITE_WEP40:
127	case WLAN_CIPHER_SUITE_WEP104:
128		alg = ALG_WEP;
129		break;
130	case WLAN_CIPHER_SUITE_TKIP:
131		alg = ALG_TKIP;
132		break;
133	case WLAN_CIPHER_SUITE_CCMP:
134		alg = ALG_CCMP;
135		break;
136	case WLAN_CIPHER_SUITE_AES_CMAC:
137		alg = ALG_AES_CMAC;
138		break;
139	default:
140		return -EINVAL;
141	}
142
143	key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
144	if (!key)
145		return -ENOMEM;
146
147	rcu_read_lock();
148
149	if (mac_addr) {
150		sta = sta_info_get(sdata->local, mac_addr);
151		if (!sta) {
152			ieee80211_key_free(key);
153			err = -ENOENT;
154			goto out_unlock;
155		}
156	}
157
158	ieee80211_key_link(key, sdata, sta);
159
160	err = 0;
161 out_unlock:
162	rcu_read_unlock();
163
164	return err;
165}
166
167static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
168			     u8 key_idx, u8 *mac_addr)
169{
170	struct ieee80211_sub_if_data *sdata;
171	struct sta_info *sta;
172	int ret;
173
174	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
175
176	rcu_read_lock();
177
178	if (mac_addr) {
179		ret = -ENOENT;
180
181		sta = sta_info_get(sdata->local, mac_addr);
182		if (!sta)
183			goto out_unlock;
184
185		if (sta->key) {
186			ieee80211_key_free(sta->key);
187			WARN_ON(sta->key);
188			ret = 0;
189		}
190
191		goto out_unlock;
192	}
193
194	if (!sdata->keys[key_idx]) {
195		ret = -ENOENT;
196		goto out_unlock;
197	}
198
199	ieee80211_key_free(sdata->keys[key_idx]);
200	WARN_ON(sdata->keys[key_idx]);
201
202	ret = 0;
203 out_unlock:
204	rcu_read_unlock();
205
206	return ret;
207}
208
209static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
210			     u8 key_idx, u8 *mac_addr, void *cookie,
211			     void (*callback)(void *cookie,
212					      struct key_params *params))
213{
214	struct ieee80211_sub_if_data *sdata;
215	struct sta_info *sta = NULL;
216	u8 seq[6] = {0};
217	struct key_params params;
218	struct ieee80211_key *key;
219	u32 iv32;
220	u16 iv16;
221	int err = -ENOENT;
222
223	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
224
225	rcu_read_lock();
226
227	if (mac_addr) {
228		sta = sta_info_get(sdata->local, mac_addr);
229		if (!sta)
230			goto out;
231
232		key = sta->key;
233	} else
234		key = sdata->keys[key_idx];
235
236	if (!key)
237		goto out;
238
239	memset(&params, 0, sizeof(params));
240
241	switch (key->conf.alg) {
242	case ALG_TKIP:
243		params.cipher = WLAN_CIPHER_SUITE_TKIP;
244
245		iv32 = key->u.tkip.tx.iv32;
246		iv16 = key->u.tkip.tx.iv16;
247
248		if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
249		    sdata->local->ops->get_tkip_seq)
250			sdata->local->ops->get_tkip_seq(
251				local_to_hw(sdata->local),
252				key->conf.hw_key_idx,
253				&iv32, &iv16);
254
255		seq[0] = iv16 & 0xff;
256		seq[1] = (iv16 >> 8) & 0xff;
257		seq[2] = iv32 & 0xff;
258		seq[3] = (iv32 >> 8) & 0xff;
259		seq[4] = (iv32 >> 16) & 0xff;
260		seq[5] = (iv32 >> 24) & 0xff;
261		params.seq = seq;
262		params.seq_len = 6;
263		break;
264	case ALG_CCMP:
265		params.cipher = WLAN_CIPHER_SUITE_CCMP;
266		seq[0] = key->u.ccmp.tx_pn[5];
267		seq[1] = key->u.ccmp.tx_pn[4];
268		seq[2] = key->u.ccmp.tx_pn[3];
269		seq[3] = key->u.ccmp.tx_pn[2];
270		seq[4] = key->u.ccmp.tx_pn[1];
271		seq[5] = key->u.ccmp.tx_pn[0];
272		params.seq = seq;
273		params.seq_len = 6;
274		break;
275	case ALG_WEP:
276		if (key->conf.keylen == 5)
277			params.cipher = WLAN_CIPHER_SUITE_WEP40;
278		else
279			params.cipher = WLAN_CIPHER_SUITE_WEP104;
280		break;
281	case ALG_AES_CMAC:
282		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
283		seq[0] = key->u.aes_cmac.tx_pn[5];
284		seq[1] = key->u.aes_cmac.tx_pn[4];
285		seq[2] = key->u.aes_cmac.tx_pn[3];
286		seq[3] = key->u.aes_cmac.tx_pn[2];
287		seq[4] = key->u.aes_cmac.tx_pn[1];
288		seq[5] = key->u.aes_cmac.tx_pn[0];
289		params.seq = seq;
290		params.seq_len = 6;
291		break;
292	}
293
294	params.key = key->conf.key;
295	params.key_len = key->conf.keylen;
296
297	callback(cookie, &params);
298	err = 0;
299
300 out:
301	rcu_read_unlock();
302	return err;
303}
304
305static int ieee80211_config_default_key(struct wiphy *wiphy,
306					struct net_device *dev,
307					u8 key_idx)
308{
309	struct ieee80211_sub_if_data *sdata;
310
311	rcu_read_lock();
312
313	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
314	ieee80211_set_default_key(sdata, key_idx);
315
316	rcu_read_unlock();
317
318	return 0;
319}
320
321static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
322					     struct net_device *dev,
323					     u8 key_idx)
324{
325	struct ieee80211_sub_if_data *sdata;
326
327	rcu_read_lock();
328
329	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
330	ieee80211_set_default_mgmt_key(sdata, key_idx);
331
332	rcu_read_unlock();
333
334	return 0;
335}
336
337static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
338{
339	struct ieee80211_sub_if_data *sdata = sta->sdata;
340
341	sinfo->filled = STATION_INFO_INACTIVE_TIME |
342			STATION_INFO_RX_BYTES |
343			STATION_INFO_TX_BYTES |
344			STATION_INFO_RX_PACKETS |
345			STATION_INFO_TX_PACKETS |
346			STATION_INFO_TX_BITRATE;
347
348	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
349	sinfo->rx_bytes = sta->rx_bytes;
350	sinfo->tx_bytes = sta->tx_bytes;
351	sinfo->rx_packets = sta->rx_packets;
352	sinfo->tx_packets = sta->tx_packets;
353
354	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
355		sinfo->filled |= STATION_INFO_SIGNAL;
356		sinfo->signal = (s8)sta->last_signal;
357	}
358
359	sinfo->txrate.flags = 0;
360	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
361		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
362	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
363		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
364	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
365		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
366
367	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
368		struct ieee80211_supported_band *sband;
369		sband = sta->local->hw.wiphy->bands[
370				sta->local->hw.conf.channel->band];
371		sinfo->txrate.legacy =
372			sband->bitrates[sta->last_tx_rate.idx].bitrate;
373	} else
374		sinfo->txrate.mcs = sta->last_tx_rate.idx;
375
376	if (ieee80211_vif_is_mesh(&sdata->vif)) {
377#ifdef CONFIG_MAC80211_MESH
378		sinfo->filled |= STATION_INFO_LLID |
379				 STATION_INFO_PLID |
380				 STATION_INFO_PLINK_STATE;
381
382		sinfo->llid = le16_to_cpu(sta->llid);
383		sinfo->plid = le16_to_cpu(sta->plid);
384		sinfo->plink_state = sta->plink_state;
385#endif
386	}
387}
388
389
390static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
391				 int idx, u8 *mac, struct station_info *sinfo)
392{
393	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
394	struct sta_info *sta;
395	int ret = -ENOENT;
396
397	rcu_read_lock();
398
399	sta = sta_info_get_by_idx(local, idx, dev);
400	if (sta) {
401		ret = 0;
402		memcpy(mac, sta->sta.addr, ETH_ALEN);
403		sta_set_sinfo(sta, sinfo);
404	}
405
406	rcu_read_unlock();
407
408	return ret;
409}
410
411static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
412				 u8 *mac, struct station_info *sinfo)
413{
414	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
415	struct sta_info *sta;
416	int ret = -ENOENT;
417
418	rcu_read_lock();
419
420	/* XXX: verify sta->dev == dev */
421
422	sta = sta_info_get(local, mac);
423	if (sta) {
424		ret = 0;
425		sta_set_sinfo(sta, sinfo);
426	}
427
428	rcu_read_unlock();
429
430	return ret;
431}
432
433/*
434 * This handles both adding a beacon and setting new beacon info
435 */
436static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
437				   struct beacon_parameters *params)
438{
439	struct beacon_data *new, *old;
440	int new_head_len, new_tail_len;
441	int size;
442	int err = -EINVAL;
443
444	old = sdata->u.ap.beacon;
445
446	/* head must not be zero-length */
447	if (params->head && !params->head_len)
448		return -EINVAL;
449
450	/*
451	 * This is a kludge. beacon interval should really be part
452	 * of the beacon information.
453	 */
454	if (params->interval && (sdata->local->hw.conf.beacon_int !=
455				 params->interval)) {
456		sdata->local->hw.conf.beacon_int = params->interval;
457		err = ieee80211_hw_config(sdata->local,
458					IEEE80211_CONF_CHANGE_BEACON_INTERVAL);
459		if (err < 0)
460			return err;
461		/*
462		 * We updated some parameter so if below bails out
463		 * it's not an error.
464		 */
465		err = 0;
466	}
467
468	/* Need to have a beacon head if we don't have one yet */
469	if (!params->head && !old)
470		return err;
471
472	/* sorry, no way to start beaconing without dtim period */
473	if (!params->dtim_period && !old)
474		return err;
475
476	/* new or old head? */
477	if (params->head)
478		new_head_len = params->head_len;
479	else
480		new_head_len = old->head_len;
481
482	/* new or old tail? */
483	if (params->tail || !old)
484		/* params->tail_len will be zero for !params->tail */
485		new_tail_len = params->tail_len;
486	else
487		new_tail_len = old->tail_len;
488
489	size = sizeof(*new) + new_head_len + new_tail_len;
490
491	new = kzalloc(size, GFP_KERNEL);
492	if (!new)
493		return -ENOMEM;
494
495	/* start filling the new info now */
496
497	/* new or old dtim period? */
498	if (params->dtim_period)
499		new->dtim_period = params->dtim_period;
500	else
501		new->dtim_period = old->dtim_period;
502
503	/*
504	 * pointers go into the block we allocated,
505	 * memory is | beacon_data | head | tail |
506	 */
507	new->head = ((u8 *) new) + sizeof(*new);
508	new->tail = new->head + new_head_len;
509	new->head_len = new_head_len;
510	new->tail_len = new_tail_len;
511
512	/* copy in head */
513	if (params->head)
514		memcpy(new->head, params->head, new_head_len);
515	else
516		memcpy(new->head, old->head, new_head_len);
517
518	/* copy in optional tail */
519	if (params->tail)
520		memcpy(new->tail, params->tail, new_tail_len);
521	else
522		if (old)
523			memcpy(new->tail, old->tail, new_tail_len);
524
525	rcu_assign_pointer(sdata->u.ap.beacon, new);
526
527	synchronize_rcu();
528
529	kfree(old);
530
531	return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
532					  IEEE80211_IFCC_BEACON_ENABLED);
533}
534
535static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
536				struct beacon_parameters *params)
537{
538	struct ieee80211_sub_if_data *sdata;
539	struct beacon_data *old;
540
541	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
542
543	if (sdata->vif.type != NL80211_IFTYPE_AP)
544		return -EINVAL;
545
546	old = sdata->u.ap.beacon;
547
548	if (old)
549		return -EALREADY;
550
551	return ieee80211_config_beacon(sdata, params);
552}
553
554static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
555				struct beacon_parameters *params)
556{
557	struct ieee80211_sub_if_data *sdata;
558	struct beacon_data *old;
559
560	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
561
562	if (sdata->vif.type != NL80211_IFTYPE_AP)
563		return -EINVAL;
564
565	old = sdata->u.ap.beacon;
566
567	if (!old)
568		return -ENOENT;
569
570	return ieee80211_config_beacon(sdata, params);
571}
572
573static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
574{
575	struct ieee80211_sub_if_data *sdata;
576	struct beacon_data *old;
577
578	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
579
580	if (sdata->vif.type != NL80211_IFTYPE_AP)
581		return -EINVAL;
582
583	old = sdata->u.ap.beacon;
584
585	if (!old)
586		return -ENOENT;
587
588	rcu_assign_pointer(sdata->u.ap.beacon, NULL);
589	synchronize_rcu();
590	kfree(old);
591
592	return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED);
593}
594
595/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
596struct iapp_layer2_update {
597	u8 da[ETH_ALEN];	/* broadcast */
598	u8 sa[ETH_ALEN];	/* STA addr */
599	__be16 len;		/* 6 */
600	u8 dsap;		/* 0 */
601	u8 ssap;		/* 0 */
602	u8 control;
603	u8 xid_info[3];
604} __attribute__ ((packed));
605
606static void ieee80211_send_layer2_update(struct sta_info *sta)
607{
608	struct iapp_layer2_update *msg;
609	struct sk_buff *skb;
610
611	/* Send Level 2 Update Frame to update forwarding tables in layer 2
612	 * bridge devices */
613
614	skb = dev_alloc_skb(sizeof(*msg));
615	if (!skb)
616		return;
617	msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
618
619	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
620	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
621
622	memset(msg->da, 0xff, ETH_ALEN);
623	memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
624	msg->len = htons(6);
625	msg->dsap = 0;
626	msg->ssap = 0x01;	/* NULL LSAP, CR Bit: Response */
627	msg->control = 0xaf;	/* XID response lsb.1111F101.
628				 * F=0 (no poll command; unsolicited frame) */
629	msg->xid_info[0] = 0x81;	/* XID format identifier */
630	msg->xid_info[1] = 1;	/* LLC types/classes: Type 1 LLC */
631	msg->xid_info[2] = 0;	/* XID sender's receive window size (RW) */
632
633	skb->dev = sta->sdata->dev;
634	skb->protocol = eth_type_trans(skb, sta->sdata->dev);
635	memset(skb->cb, 0, sizeof(skb->cb));
636	netif_rx(skb);
637}
638
639static void sta_apply_parameters(struct ieee80211_local *local,
640				 struct sta_info *sta,
641				 struct station_parameters *params)
642{
643	u32 rates;
644	int i, j;
645	struct ieee80211_supported_band *sband;
646	struct ieee80211_sub_if_data *sdata = sta->sdata;
647
648	sband = local->hw.wiphy->bands[local->oper_channel->band];
649
650	/*
651	 * FIXME: updating the flags is racy when this function is
652	 *	  called from ieee80211_change_station(), this will
653	 *	  be resolved in a future patch.
654	 */
655
656	if (params->station_flags & STATION_FLAG_CHANGED) {
657		spin_lock_bh(&sta->lock);
658		sta->flags &= ~WLAN_STA_AUTHORIZED;
659		if (params->station_flags & STATION_FLAG_AUTHORIZED)
660			sta->flags |= WLAN_STA_AUTHORIZED;
661
662		sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
663		if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE)
664			sta->flags |= WLAN_STA_SHORT_PREAMBLE;
665
666		sta->flags &= ~WLAN_STA_WME;
667		if (params->station_flags & STATION_FLAG_WME)
668			sta->flags |= WLAN_STA_WME;
669
670		sta->flags &= ~WLAN_STA_MFP;
671		if (params->station_flags & STATION_FLAG_MFP)
672			sta->flags |= WLAN_STA_MFP;
673		spin_unlock_bh(&sta->lock);
674	}
675
676	/*
677	 * FIXME: updating the following information is racy when this
678	 *	  function is called from ieee80211_change_station().
679	 *	  However, all this information should be static so
680	 *	  maybe we should just reject attemps to change it.
681	 */
682
683	if (params->aid) {
684		sta->sta.aid = params->aid;
685		if (sta->sta.aid > IEEE80211_MAX_AID)
686			sta->sta.aid = 0; /* XXX: should this be an error? */
687	}
688
689	if (params->listen_interval >= 0)
690		sta->listen_interval = params->listen_interval;
691
692	if (params->supported_rates) {
693		rates = 0;
694
695		for (i = 0; i < params->supported_rates_len; i++) {
696			int rate = (params->supported_rates[i] & 0x7f) * 5;
697			for (j = 0; j < sband->n_bitrates; j++) {
698				if (sband->bitrates[j].bitrate == rate)
699					rates |= BIT(j);
700			}
701		}
702		sta->sta.supp_rates[local->oper_channel->band] = rates;
703	}
704
705	if (params->ht_capa)
706		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
707						  params->ht_capa,
708						  &sta->sta.ht_cap);
709
710	if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
711		switch (params->plink_action) {
712		case PLINK_ACTION_OPEN:
713			mesh_plink_open(sta);
714			break;
715		case PLINK_ACTION_BLOCK:
716			mesh_plink_block(sta);
717			break;
718		}
719	}
720}
721
722static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
723				 u8 *mac, struct station_parameters *params)
724{
725	struct ieee80211_local *local = wiphy_priv(wiphy);
726	struct sta_info *sta;
727	struct ieee80211_sub_if_data *sdata;
728	int err;
729	int layer2_update;
730
731	/* Prevent a race with changing the rate control algorithm */
732	if (!netif_running(dev))
733		return -ENETDOWN;
734
735	if (params->vlan) {
736		sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
737
738		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
739		    sdata->vif.type != NL80211_IFTYPE_AP)
740			return -EINVAL;
741	} else
742		sdata = IEEE80211_DEV_TO_SUB_IF(dev);
743
744	if (compare_ether_addr(mac, dev->dev_addr) == 0)
745		return -EINVAL;
746
747	if (is_multicast_ether_addr(mac))
748		return -EINVAL;
749
750	sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
751	if (!sta)
752		return -ENOMEM;
753
754	sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
755
756	sta_apply_parameters(local, sta, params);
757
758	rate_control_rate_init(sta);
759
760	layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
761		sdata->vif.type == NL80211_IFTYPE_AP;
762
763	rcu_read_lock();
764
765	err = sta_info_insert(sta);
766	if (err) {
767		/* STA has been freed */
768		if (err == -EEXIST && layer2_update) {
769			/* Need to update layer 2 devices on reassociation */
770			sta = sta_info_get(local, mac);
771			if (sta)
772				ieee80211_send_layer2_update(sta);
773		}
774		rcu_read_unlock();
775		return err;
776	}
777
778	if (layer2_update)
779		ieee80211_send_layer2_update(sta);
780
781	rcu_read_unlock();
782
783	return 0;
784}
785
786static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
787				 u8 *mac)
788{
789	struct ieee80211_local *local = wiphy_priv(wiphy);
790	struct ieee80211_sub_if_data *sdata;
791	struct sta_info *sta;
792
793	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
794
795	if (mac) {
796		rcu_read_lock();
797
798		/* XXX: get sta belonging to dev */
799		sta = sta_info_get(local, mac);
800		if (!sta) {
801			rcu_read_unlock();
802			return -ENOENT;
803		}
804
805		sta_info_unlink(&sta);
806		rcu_read_unlock();
807
808		sta_info_destroy(sta);
809	} else
810		sta_info_flush(local, sdata);
811
812	return 0;
813}
814
815static int ieee80211_change_station(struct wiphy *wiphy,
816				    struct net_device *dev,
817				    u8 *mac,
818				    struct station_parameters *params)
819{
820	struct ieee80211_local *local = wiphy_priv(wiphy);
821	struct sta_info *sta;
822	struct ieee80211_sub_if_data *vlansdata;
823
824	rcu_read_lock();
825
826	/* XXX: get sta belonging to dev */
827	sta = sta_info_get(local, mac);
828	if (!sta) {
829		rcu_read_unlock();
830		return -ENOENT;
831	}
832
833	if (params->vlan && params->vlan != sta->sdata->dev) {
834		vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
835
836		if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
837		    vlansdata->vif.type != NL80211_IFTYPE_AP) {
838			rcu_read_unlock();
839			return -EINVAL;
840		}
841
842		sta->sdata = vlansdata;
843		ieee80211_send_layer2_update(sta);
844	}
845
846	sta_apply_parameters(local, sta, params);
847
848	rcu_read_unlock();
849
850	return 0;
851}
852
853#ifdef CONFIG_MAC80211_MESH
854static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
855				 u8 *dst, u8 *next_hop)
856{
857	struct ieee80211_local *local = wiphy_priv(wiphy);
858	struct ieee80211_sub_if_data *sdata;
859	struct mesh_path *mpath;
860	struct sta_info *sta;
861	int err;
862
863	if (!netif_running(dev))
864		return -ENETDOWN;
865
866	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
867
868	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
869		return -ENOTSUPP;
870
871	rcu_read_lock();
872	sta = sta_info_get(local, next_hop);
873	if (!sta) {
874		rcu_read_unlock();
875		return -ENOENT;
876	}
877
878	err = mesh_path_add(dst, sdata);
879	if (err) {
880		rcu_read_unlock();
881		return err;
882	}
883
884	mpath = mesh_path_lookup(dst, sdata);
885	if (!mpath) {
886		rcu_read_unlock();
887		return -ENXIO;
888	}
889	mesh_path_fix_nexthop(mpath, sta);
890
891	rcu_read_unlock();
892	return 0;
893}
894
895static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
896				 u8 *dst)
897{
898	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
899
900	if (dst)
901		return mesh_path_del(dst, sdata);
902
903	mesh_path_flush(sdata);
904	return 0;
905}
906
907static int ieee80211_change_mpath(struct wiphy *wiphy,
908				    struct net_device *dev,
909				    u8 *dst, u8 *next_hop)
910{
911	struct ieee80211_local *local = wiphy_priv(wiphy);
912	struct ieee80211_sub_if_data *sdata;
913	struct mesh_path *mpath;
914	struct sta_info *sta;
915
916	if (!netif_running(dev))
917		return -ENETDOWN;
918
919	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
920
921	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
922		return -ENOTSUPP;
923
924	rcu_read_lock();
925
926	sta = sta_info_get(local, next_hop);
927	if (!sta) {
928		rcu_read_unlock();
929		return -ENOENT;
930	}
931
932	mpath = mesh_path_lookup(dst, sdata);
933	if (!mpath) {
934		rcu_read_unlock();
935		return -ENOENT;
936	}
937
938	mesh_path_fix_nexthop(mpath, sta);
939
940	rcu_read_unlock();
941	return 0;
942}
943
944static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
945			    struct mpath_info *pinfo)
946{
947	if (mpath->next_hop)
948		memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
949	else
950		memset(next_hop, 0, ETH_ALEN);
951
952	pinfo->filled = MPATH_INFO_FRAME_QLEN |
953			MPATH_INFO_DSN |
954			MPATH_INFO_METRIC |
955			MPATH_INFO_EXPTIME |
956			MPATH_INFO_DISCOVERY_TIMEOUT |
957			MPATH_INFO_DISCOVERY_RETRIES |
958			MPATH_INFO_FLAGS;
959
960	pinfo->frame_qlen = mpath->frame_queue.qlen;
961	pinfo->dsn = mpath->dsn;
962	pinfo->metric = mpath->metric;
963	if (time_before(jiffies, mpath->exp_time))
964		pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
965	pinfo->discovery_timeout =
966			jiffies_to_msecs(mpath->discovery_timeout);
967	pinfo->discovery_retries = mpath->discovery_retries;
968	pinfo->flags = 0;
969	if (mpath->flags & MESH_PATH_ACTIVE)
970		pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
971	if (mpath->flags & MESH_PATH_RESOLVING)
972		pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
973	if (mpath->flags & MESH_PATH_DSN_VALID)
974		pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
975	if (mpath->flags & MESH_PATH_FIXED)
976		pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
977	if (mpath->flags & MESH_PATH_RESOLVING)
978		pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
979
980	pinfo->flags = mpath->flags;
981}
982
983static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
984			       u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
985
986{
987	struct ieee80211_sub_if_data *sdata;
988	struct mesh_path *mpath;
989
990	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
991
992	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
993		return -ENOTSUPP;
994
995	rcu_read_lock();
996	mpath = mesh_path_lookup(dst, sdata);
997	if (!mpath) {
998		rcu_read_unlock();
999		return -ENOENT;
1000	}
1001	memcpy(dst, mpath->dst, ETH_ALEN);
1002	mpath_set_pinfo(mpath, next_hop, pinfo);
1003	rcu_read_unlock();
1004	return 0;
1005}
1006
1007static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
1008				 int idx, u8 *dst, u8 *next_hop,
1009				 struct mpath_info *pinfo)
1010{
1011	struct ieee80211_sub_if_data *sdata;
1012	struct mesh_path *mpath;
1013
1014	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1015
1016	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
1017		return -ENOTSUPP;
1018
1019	rcu_read_lock();
1020	mpath = mesh_path_lookup_by_idx(idx, sdata);
1021	if (!mpath) {
1022		rcu_read_unlock();
1023		return -ENOENT;
1024	}
1025	memcpy(dst, mpath->dst, ETH_ALEN);
1026	mpath_set_pinfo(mpath, next_hop, pinfo);
1027	rcu_read_unlock();
1028	return 0;
1029}
1030
1031static int ieee80211_get_mesh_params(struct wiphy *wiphy,
1032				struct net_device *dev,
1033				struct mesh_config *conf)
1034{
1035	struct ieee80211_sub_if_data *sdata;
1036	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1037
1038	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
1039		return -ENOTSUPP;
1040	memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config));
1041	return 0;
1042}
1043
1044static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask)
1045{
1046	return (mask >> (parm-1)) & 0x1;
1047}
1048
1049static int ieee80211_set_mesh_params(struct wiphy *wiphy,
1050				struct net_device *dev,
1051				const struct mesh_config *nconf, u32 mask)
1052{
1053	struct mesh_config *conf;
1054	struct ieee80211_sub_if_data *sdata;
1055	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1056
1057	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
1058		return -ENOTSUPP;
1059
1060	/* Set the config options which we are interested in setting */
1061	conf = &(sdata->u.mesh.mshcfg);
1062	if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask))
1063		conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout;
1064	if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask))
1065		conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout;
1066	if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask))
1067		conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout;
1068	if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask))
1069		conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks;
1070	if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask))
1071		conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries;
1072	if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
1073		conf->dot11MeshTTL = nconf->dot11MeshTTL;
1074	if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
1075		conf->auto_open_plinks = nconf->auto_open_plinks;
1076	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask))
1077		conf->dot11MeshHWMPmaxPREQretries =
1078			nconf->dot11MeshHWMPmaxPREQretries;
1079	if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask))
1080		conf->path_refresh_time = nconf->path_refresh_time;
1081	if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask))
1082		conf->min_discovery_timeout = nconf->min_discovery_timeout;
1083	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask))
1084		conf->dot11MeshHWMPactivePathTimeout =
1085			nconf->dot11MeshHWMPactivePathTimeout;
1086	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask))
1087		conf->dot11MeshHWMPpreqMinInterval =
1088			nconf->dot11MeshHWMPpreqMinInterval;
1089	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
1090			   mask))
1091		conf->dot11MeshHWMPnetDiameterTraversalTime =
1092			nconf->dot11MeshHWMPnetDiameterTraversalTime;
1093	return 0;
1094}
1095
1096#endif
1097
1098static int ieee80211_change_bss(struct wiphy *wiphy,
1099				struct net_device *dev,
1100				struct bss_parameters *params)
1101{
1102	struct ieee80211_sub_if_data *sdata;
1103	u32 changed = 0;
1104
1105	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1106
1107	if (sdata->vif.type != NL80211_IFTYPE_AP)
1108		return -EINVAL;
1109
1110	if (params->use_cts_prot >= 0) {
1111		sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
1112		changed |= BSS_CHANGED_ERP_CTS_PROT;
1113	}
1114	if (params->use_short_preamble >= 0) {
1115		sdata->vif.bss_conf.use_short_preamble =
1116			params->use_short_preamble;
1117		changed |= BSS_CHANGED_ERP_PREAMBLE;
1118	}
1119	if (params->use_short_slot_time >= 0) {
1120		sdata->vif.bss_conf.use_short_slot =
1121			params->use_short_slot_time;
1122		changed |= BSS_CHANGED_ERP_SLOT;
1123	}
1124
1125	if (params->basic_rates) {
1126		int i, j;
1127		u32 rates = 0;
1128		struct ieee80211_local *local = wiphy_priv(wiphy);
1129		struct ieee80211_supported_band *sband =
1130			wiphy->bands[local->oper_channel->band];
1131
1132		for (i = 0; i < params->basic_rates_len; i++) {
1133			int rate = (params->basic_rates[i] & 0x7f) * 5;
1134			for (j = 0; j < sband->n_bitrates; j++) {
1135				if (sband->bitrates[j].bitrate == rate)
1136					rates |= BIT(j);
1137			}
1138		}
1139		sdata->vif.bss_conf.basic_rates = rates;
1140		changed |= BSS_CHANGED_BASIC_RATES;
1141	}
1142
1143	ieee80211_bss_info_change_notify(sdata, changed);
1144
1145	return 0;
1146}
1147
1148static int ieee80211_set_txq_params(struct wiphy *wiphy,
1149				    struct ieee80211_txq_params *params)
1150{
1151	struct ieee80211_local *local = wiphy_priv(wiphy);
1152	struct ieee80211_tx_queue_params p;
1153
1154	if (!local->ops->conf_tx)
1155		return -EOPNOTSUPP;
1156
1157	memset(&p, 0, sizeof(p));
1158	p.aifs = params->aifs;
1159	p.cw_max = params->cwmax;
1160	p.cw_min = params->cwmin;
1161	p.txop = params->txop;
1162	if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) {
1163		printk(KERN_DEBUG "%s: failed to set TX queue "
1164		       "parameters for queue %d\n", local->mdev->name,
1165		       params->queue);
1166		return -EINVAL;
1167	}
1168
1169	return 0;
1170}
1171
1172static int ieee80211_set_channel(struct wiphy *wiphy,
1173				 struct ieee80211_channel *chan,
1174				 enum nl80211_channel_type channel_type)
1175{
1176	struct ieee80211_local *local = wiphy_priv(wiphy);
1177
1178	local->oper_channel = chan;
1179	local->oper_channel_type = channel_type;
1180
1181	return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
1182}
1183
1184static int set_mgmt_extra_ie_sta(struct ieee80211_sub_if_data *sdata,
1185				 u8 subtype, u8 *ies, size_t ies_len)
1186{
1187	struct ieee80211_local *local = sdata->local;
1188	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1189
1190	switch (subtype) {
1191	case IEEE80211_STYPE_PROBE_REQ >> 4:
1192		if (local->ops->hw_scan)
1193			break;
1194		kfree(ifmgd->ie_probereq);
1195		ifmgd->ie_probereq = ies;
1196		ifmgd->ie_probereq_len = ies_len;
1197		return 0;
1198	case IEEE80211_STYPE_PROBE_RESP >> 4:
1199		kfree(ifmgd->ie_proberesp);
1200		ifmgd->ie_proberesp = ies;
1201		ifmgd->ie_proberesp_len = ies_len;
1202		return 0;
1203	case IEEE80211_STYPE_AUTH >> 4:
1204		kfree(ifmgd->ie_auth);
1205		ifmgd->ie_auth = ies;
1206		ifmgd->ie_auth_len = ies_len;
1207		return 0;
1208	case IEEE80211_STYPE_ASSOC_REQ >> 4:
1209		kfree(ifmgd->ie_assocreq);
1210		ifmgd->ie_assocreq = ies;
1211		ifmgd->ie_assocreq_len = ies_len;
1212		return 0;
1213	case IEEE80211_STYPE_REASSOC_REQ >> 4:
1214		kfree(ifmgd->ie_reassocreq);
1215		ifmgd->ie_reassocreq = ies;
1216		ifmgd->ie_reassocreq_len = ies_len;
1217		return 0;
1218	case IEEE80211_STYPE_DEAUTH >> 4:
1219		kfree(ifmgd->ie_deauth);
1220		ifmgd->ie_deauth = ies;
1221		ifmgd->ie_deauth_len = ies_len;
1222		return 0;
1223	case IEEE80211_STYPE_DISASSOC >> 4:
1224		kfree(ifmgd->ie_disassoc);
1225		ifmgd->ie_disassoc = ies;
1226		ifmgd->ie_disassoc_len = ies_len;
1227		return 0;
1228	}
1229
1230	return -EOPNOTSUPP;
1231}
1232
1233static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy,
1234				       struct net_device *dev,
1235				       struct mgmt_extra_ie_params *params)
1236{
1237	struct ieee80211_sub_if_data *sdata;
1238	u8 *ies;
1239	size_t ies_len;
1240	int ret = -EOPNOTSUPP;
1241
1242	if (params->ies) {
1243		ies = kmemdup(params->ies, params->ies_len, GFP_KERNEL);
1244		if (ies == NULL)
1245			return -ENOMEM;
1246		ies_len = params->ies_len;
1247	} else {
1248		ies = NULL;
1249		ies_len = 0;
1250	}
1251
1252	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1253
1254	switch (sdata->vif.type) {
1255	case NL80211_IFTYPE_STATION:
1256		ret = set_mgmt_extra_ie_sta(sdata, params->subtype,
1257					    ies, ies_len);
1258		break;
1259	default:
1260		ret = -EOPNOTSUPP;
1261		break;
1262	}
1263
1264	if (ret)
1265		kfree(ies);
1266	return ret;
1267}
1268
1269#ifdef CONFIG_PM
1270static int ieee80211_suspend(struct wiphy *wiphy)
1271{
1272	return __ieee80211_suspend(wiphy_priv(wiphy));
1273}
1274
1275static int ieee80211_resume(struct wiphy *wiphy)
1276{
1277	return __ieee80211_resume(wiphy_priv(wiphy));
1278}
1279#else
1280#define ieee80211_suspend NULL
1281#define ieee80211_resume NULL
1282#endif
1283
1284static int ieee80211_scan(struct wiphy *wiphy,
1285			  struct net_device *dev,
1286			  struct cfg80211_scan_request *req)
1287{
1288	struct ieee80211_sub_if_data *sdata;
1289
1290	if (!netif_running(dev))
1291		return -ENETDOWN;
1292
1293	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1294
1295	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
1296	    sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1297	    sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
1298		return -EOPNOTSUPP;
1299
1300	return ieee80211_request_scan(sdata, req);
1301}
1302
1303static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
1304			  struct cfg80211_auth_request *req)
1305{
1306	struct ieee80211_sub_if_data *sdata;
1307
1308	if (!netif_running(dev))
1309		return -ENETDOWN;
1310
1311	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1312
1313	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1314		return -EOPNOTSUPP;
1315
1316	switch (req->auth_type) {
1317	case NL80211_AUTHTYPE_OPEN_SYSTEM:
1318		sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_OPEN;
1319		break;
1320	case NL80211_AUTHTYPE_SHARED_KEY:
1321		sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_SHARED_KEY;
1322		break;
1323	case NL80211_AUTHTYPE_FT:
1324		sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_FT;
1325		break;
1326	case NL80211_AUTHTYPE_NETWORK_EAP:
1327		sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_LEAP;
1328		break;
1329	default:
1330		return -EOPNOTSUPP;
1331	}
1332
1333	memcpy(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN);
1334	sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
1335	sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
1336
1337	/* TODO: req->chan */
1338	sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
1339
1340	if (req->ssid) {
1341		sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
1342		memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
1343		sdata->u.mgd.ssid_len = req->ssid_len;
1344		sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
1345	}
1346
1347	kfree(sdata->u.mgd.sme_auth_ie);
1348	sdata->u.mgd.sme_auth_ie = NULL;
1349	sdata->u.mgd.sme_auth_ie_len = 0;
1350	if (req->ie) {
1351		sdata->u.mgd.sme_auth_ie = kmalloc(req->ie_len, GFP_KERNEL);
1352		if (sdata->u.mgd.sme_auth_ie == NULL)
1353			return -ENOMEM;
1354		memcpy(sdata->u.mgd.sme_auth_ie, req->ie, req->ie_len);
1355		sdata->u.mgd.sme_auth_ie_len = req->ie_len;
1356	}
1357
1358	sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
1359	sdata->u.mgd.state = IEEE80211_STA_MLME_DIRECT_PROBE;
1360	ieee80211_sta_req_auth(sdata);
1361	return 0;
1362}
1363
1364static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
1365			   struct cfg80211_assoc_request *req)
1366{
1367	struct ieee80211_sub_if_data *sdata;
1368	int ret;
1369
1370	if (!netif_running(dev))
1371		return -ENETDOWN;
1372
1373	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1374
1375	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1376		return -EOPNOTSUPP;
1377
1378	if (memcmp(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN) != 0 ||
1379	    !(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED))
1380		return -ENOLINK; /* not authenticated */
1381
1382	sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
1383	sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
1384
1385	/* TODO: req->chan */
1386	sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
1387
1388	if (req->ssid) {
1389		sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
1390		memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
1391		sdata->u.mgd.ssid_len = req->ssid_len;
1392		sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
1393	} else
1394		sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
1395
1396	ret = ieee80211_sta_set_extra_ie(sdata, req->ie, req->ie_len);
1397	if (ret)
1398		return ret;
1399
1400	sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
1401	sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE;
1402	ieee80211_sta_req_auth(sdata);
1403	return 0;
1404}
1405
1406static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
1407			    struct cfg80211_deauth_request *req)
1408{
1409	struct ieee80211_sub_if_data *sdata;
1410
1411	if (!netif_running(dev))
1412		return -ENETDOWN;
1413
1414	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1415	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1416		return -EOPNOTSUPP;
1417
1418	/* TODO: req->ie */
1419	return ieee80211_sta_deauthenticate(sdata, req->reason_code);
1420}
1421
1422static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
1423			      struct cfg80211_disassoc_request *req)
1424{
1425	struct ieee80211_sub_if_data *sdata;
1426
1427	if (!netif_running(dev))
1428		return -ENETDOWN;
1429
1430	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1431
1432	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1433		return -EOPNOTSUPP;
1434
1435	/* TODO: req->ie */
1436	return ieee80211_sta_disassociate(sdata, req->reason_code);
1437}
1438
1439struct cfg80211_ops mac80211_config_ops = {
1440	.add_virtual_intf = ieee80211_add_iface,
1441	.del_virtual_intf = ieee80211_del_iface,
1442	.change_virtual_intf = ieee80211_change_iface,
1443	.add_key = ieee80211_add_key,
1444	.del_key = ieee80211_del_key,
1445	.get_key = ieee80211_get_key,
1446	.set_default_key = ieee80211_config_default_key,
1447	.set_default_mgmt_key = ieee80211_config_default_mgmt_key,
1448	.add_beacon = ieee80211_add_beacon,
1449	.set_beacon = ieee80211_set_beacon,
1450	.del_beacon = ieee80211_del_beacon,
1451	.add_station = ieee80211_add_station,
1452	.del_station = ieee80211_del_station,
1453	.change_station = ieee80211_change_station,
1454	.get_station = ieee80211_get_station,
1455	.dump_station = ieee80211_dump_station,
1456#ifdef CONFIG_MAC80211_MESH
1457	.add_mpath = ieee80211_add_mpath,
1458	.del_mpath = ieee80211_del_mpath,
1459	.change_mpath = ieee80211_change_mpath,
1460	.get_mpath = ieee80211_get_mpath,
1461	.dump_mpath = ieee80211_dump_mpath,
1462	.set_mesh_params = ieee80211_set_mesh_params,
1463	.get_mesh_params = ieee80211_get_mesh_params,
1464#endif
1465	.change_bss = ieee80211_change_bss,
1466	.set_txq_params = ieee80211_set_txq_params,
1467	.set_channel = ieee80211_set_channel,
1468	.set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie,
1469	.suspend = ieee80211_suspend,
1470	.resume = ieee80211_resume,
1471	.scan = ieee80211_scan,
1472	.auth = ieee80211_auth,
1473	.assoc = ieee80211_assoc,
1474	.deauth = ieee80211_deauth,
1475	.disassoc = ieee80211_disassoc,
1476};
1477