]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - net/mac80211/cfg.c
a8501f14b1676a130732ddf8534a2a79769875d7
[linux-2.6-omap-h63xx.git] / net / mac80211 / cfg.c
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
20 struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy)
21 {
22         struct ieee80211_local *local = wiphy_priv(wiphy);
23         return &local->hw;
24 }
25 EXPORT_SYMBOL(wiphy_to_hw);
26
27 static bool nl80211_type_check(enum nl80211_iftype type)
28 {
29         switch (type) {
30         case NL80211_IFTYPE_ADHOC:
31         case NL80211_IFTYPE_STATION:
32         case NL80211_IFTYPE_MONITOR:
33 #ifdef CONFIG_MAC80211_MESH
34         case NL80211_IFTYPE_MESH_POINT:
35 #endif
36         case NL80211_IFTYPE_WDS:
37                 return true;
38         default:
39                 return false;
40         }
41 }
42
43 static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
44                                enum nl80211_iftype type, u32 *flags,
45                                struct vif_params *params)
46 {
47         struct ieee80211_local *local = wiphy_priv(wiphy);
48         struct net_device *dev;
49         struct ieee80211_sub_if_data *sdata;
50         int err;
51
52         if (!nl80211_type_check(type))
53                 return -EINVAL;
54
55         err = ieee80211_if_add(local, name, &dev, type, params);
56         if (err || type != NL80211_IFTYPE_MONITOR || !flags)
57                 return err;
58
59         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
60         sdata->u.mntr_flags = *flags;
61         return 0;
62 }
63
64 static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
65 {
66         struct net_device *dev;
67         struct ieee80211_sub_if_data *sdata;
68
69         /* we're under RTNL */
70         dev = __dev_get_by_index(&init_net, ifindex);
71         if (!dev)
72                 return -ENODEV;
73
74         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
75
76         ieee80211_if_remove(sdata);
77
78         return 0;
79 }
80
81 static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
82                                   enum nl80211_iftype type, u32 *flags,
83                                   struct vif_params *params)
84 {
85         struct net_device *dev;
86         struct ieee80211_sub_if_data *sdata;
87         int ret;
88
89         /* we're under RTNL */
90         dev = __dev_get_by_index(&init_net, ifindex);
91         if (!dev)
92                 return -ENODEV;
93
94         if (!nl80211_type_check(type))
95                 return -EINVAL;
96
97         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
98
99         ret = ieee80211_if_change_type(sdata, type);
100         if (ret)
101                 return ret;
102
103         if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
104                 ieee80211_sdata_set_mesh_id(sdata,
105                                             params->mesh_id_len,
106                                             params->mesh_id);
107
108         if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
109                 return 0;
110
111         sdata->u.mntr_flags = *flags;
112         return 0;
113 }
114
115 static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
116                              u8 key_idx, u8 *mac_addr,
117                              struct key_params *params)
118 {
119         struct ieee80211_sub_if_data *sdata;
120         struct sta_info *sta = NULL;
121         enum ieee80211_key_alg alg;
122         struct ieee80211_key *key;
123         int err;
124
125         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
126
127         switch (params->cipher) {
128         case WLAN_CIPHER_SUITE_WEP40:
129         case WLAN_CIPHER_SUITE_WEP104:
130                 alg = ALG_WEP;
131                 break;
132         case WLAN_CIPHER_SUITE_TKIP:
133                 alg = ALG_TKIP;
134                 break;
135         case WLAN_CIPHER_SUITE_CCMP:
136                 alg = ALG_CCMP;
137                 break;
138         default:
139                 return -EINVAL;
140         }
141
142         key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
143         if (!key)
144                 return -ENOMEM;
145
146         rcu_read_lock();
147
148         if (mac_addr) {
149                 sta = sta_info_get(sdata->local, mac_addr);
150                 if (!sta) {
151                         ieee80211_key_free(key);
152                         err = -ENOENT;
153                         goto out_unlock;
154                 }
155         }
156
157         ieee80211_key_link(key, sdata, sta);
158
159         err = 0;
160  out_unlock:
161         rcu_read_unlock();
162
163         return err;
164 }
165
166 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
167                              u8 key_idx, u8 *mac_addr)
168 {
169         struct ieee80211_sub_if_data *sdata;
170         struct sta_info *sta;
171         int ret;
172
173         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
174
175         rcu_read_lock();
176
177         if (mac_addr) {
178                 ret = -ENOENT;
179
180                 sta = sta_info_get(sdata->local, mac_addr);
181                 if (!sta)
182                         goto out_unlock;
183
184                 if (sta->key) {
185                         ieee80211_key_free(sta->key);
186                         WARN_ON(sta->key);
187                         ret = 0;
188                 }
189
190                 goto out_unlock;
191         }
192
193         if (!sdata->keys[key_idx]) {
194                 ret = -ENOENT;
195                 goto out_unlock;
196         }
197
198         ieee80211_key_free(sdata->keys[key_idx]);
199         WARN_ON(sdata->keys[key_idx]);
200
201         ret = 0;
202  out_unlock:
203         rcu_read_unlock();
204
205         return ret;
206 }
207
208 static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
209                              u8 key_idx, u8 *mac_addr, void *cookie,
210                              void (*callback)(void *cookie,
211                                               struct key_params *params))
212 {
213         struct ieee80211_sub_if_data *sdata;
214         struct sta_info *sta = NULL;
215         u8 seq[6] = {0};
216         struct key_params params;
217         struct ieee80211_key *key;
218         u32 iv32;
219         u16 iv16;
220         int err = -ENOENT;
221
222         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
223
224         rcu_read_lock();
225
226         if (mac_addr) {
227                 sta = sta_info_get(sdata->local, mac_addr);
228                 if (!sta)
229                         goto out;
230
231                 key = sta->key;
232         } else
233                 key = sdata->keys[key_idx];
234
235         if (!key)
236                 goto out;
237
238         memset(&params, 0, sizeof(params));
239
240         switch (key->conf.alg) {
241         case ALG_TKIP:
242                 params.cipher = WLAN_CIPHER_SUITE_TKIP;
243
244                 iv32 = key->u.tkip.tx.iv32;
245                 iv16 = key->u.tkip.tx.iv16;
246
247                 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
248                     sdata->local->ops->get_tkip_seq)
249                         sdata->local->ops->get_tkip_seq(
250                                 local_to_hw(sdata->local),
251                                 key->conf.hw_key_idx,
252                                 &iv32, &iv16);
253
254                 seq[0] = iv16 & 0xff;
255                 seq[1] = (iv16 >> 8) & 0xff;
256                 seq[2] = iv32 & 0xff;
257                 seq[3] = (iv32 >> 8) & 0xff;
258                 seq[4] = (iv32 >> 16) & 0xff;
259                 seq[5] = (iv32 >> 24) & 0xff;
260                 params.seq = seq;
261                 params.seq_len = 6;
262                 break;
263         case ALG_CCMP:
264                 params.cipher = WLAN_CIPHER_SUITE_CCMP;
265                 seq[0] = key->u.ccmp.tx_pn[5];
266                 seq[1] = key->u.ccmp.tx_pn[4];
267                 seq[2] = key->u.ccmp.tx_pn[3];
268                 seq[3] = key->u.ccmp.tx_pn[2];
269                 seq[4] = key->u.ccmp.tx_pn[1];
270                 seq[5] = key->u.ccmp.tx_pn[0];
271                 params.seq = seq;
272                 params.seq_len = 6;
273                 break;
274         case ALG_WEP:
275                 if (key->conf.keylen == 5)
276                         params.cipher = WLAN_CIPHER_SUITE_WEP40;
277                 else
278                         params.cipher = WLAN_CIPHER_SUITE_WEP104;
279                 break;
280         }
281
282         params.key = key->conf.key;
283         params.key_len = key->conf.keylen;
284
285         callback(cookie, &params);
286         err = 0;
287
288  out:
289         rcu_read_unlock();
290         return err;
291 }
292
293 static int ieee80211_config_default_key(struct wiphy *wiphy,
294                                         struct net_device *dev,
295                                         u8 key_idx)
296 {
297         struct ieee80211_sub_if_data *sdata;
298
299         rcu_read_lock();
300
301         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
302         ieee80211_set_default_key(sdata, key_idx);
303
304         rcu_read_unlock();
305
306         return 0;
307 }
308
309 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
310 {
311         struct ieee80211_sub_if_data *sdata = sta->sdata;
312
313         sinfo->filled = STATION_INFO_INACTIVE_TIME |
314                         STATION_INFO_RX_BYTES |
315                         STATION_INFO_TX_BYTES;
316
317         sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
318         sinfo->rx_bytes = sta->rx_bytes;
319         sinfo->tx_bytes = sta->tx_bytes;
320
321         if (ieee80211_vif_is_mesh(&sdata->vif)) {
322 #ifdef CONFIG_MAC80211_MESH
323                 sinfo->filled |= STATION_INFO_LLID |
324                                  STATION_INFO_PLID |
325                                  STATION_INFO_PLINK_STATE;
326
327                 sinfo->llid = le16_to_cpu(sta->llid);
328                 sinfo->plid = le16_to_cpu(sta->plid);
329                 sinfo->plink_state = sta->plink_state;
330 #endif
331         }
332 }
333
334
335 static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
336                                  int idx, u8 *mac, struct station_info *sinfo)
337 {
338         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
339         struct sta_info *sta;
340         int ret = -ENOENT;
341
342         rcu_read_lock();
343
344         sta = sta_info_get_by_idx(local, idx, dev);
345         if (sta) {
346                 ret = 0;
347                 memcpy(mac, sta->sta.addr, ETH_ALEN);
348                 sta_set_sinfo(sta, sinfo);
349         }
350
351         rcu_read_unlock();
352
353         return ret;
354 }
355
356 static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
357                                  u8 *mac, struct station_info *sinfo)
358 {
359         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
360         struct sta_info *sta;
361         int ret = -ENOENT;
362
363         rcu_read_lock();
364
365         /* XXX: verify sta->dev == dev */
366
367         sta = sta_info_get(local, mac);
368         if (sta) {
369                 ret = 0;
370                 sta_set_sinfo(sta, sinfo);
371         }
372
373         rcu_read_unlock();
374
375         return ret;
376 }
377
378 /*
379  * This handles both adding a beacon and setting new beacon info
380  */
381 static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
382                                    struct beacon_parameters *params)
383 {
384         struct beacon_data *new, *old;
385         int new_head_len, new_tail_len;
386         int size;
387         int err = -EINVAL;
388
389         old = sdata->u.ap.beacon;
390
391         /* head must not be zero-length */
392         if (params->head && !params->head_len)
393                 return -EINVAL;
394
395         /*
396          * This is a kludge. beacon interval should really be part
397          * of the beacon information.
398          */
399         if (params->interval) {
400                 sdata->local->hw.conf.beacon_int = params->interval;
401                 if (ieee80211_hw_config(sdata->local))
402                         return -EINVAL;
403                 /*
404                  * We updated some parameter so if below bails out
405                  * it's not an error.
406                  */
407                 err = 0;
408         }
409
410         /* Need to have a beacon head if we don't have one yet */
411         if (!params->head && !old)
412                 return err;
413
414         /* sorry, no way to start beaconing without dtim period */
415         if (!params->dtim_period && !old)
416                 return err;
417
418         /* new or old head? */
419         if (params->head)
420                 new_head_len = params->head_len;
421         else
422                 new_head_len = old->head_len;
423
424         /* new or old tail? */
425         if (params->tail || !old)
426                 /* params->tail_len will be zero for !params->tail */
427                 new_tail_len = params->tail_len;
428         else
429                 new_tail_len = old->tail_len;
430
431         size = sizeof(*new) + new_head_len + new_tail_len;
432
433         new = kzalloc(size, GFP_KERNEL);
434         if (!new)
435                 return -ENOMEM;
436
437         /* start filling the new info now */
438
439         /* new or old dtim period? */
440         if (params->dtim_period)
441                 new->dtim_period = params->dtim_period;
442         else
443                 new->dtim_period = old->dtim_period;
444
445         /*
446          * pointers go into the block we allocated,
447          * memory is | beacon_data | head | tail |
448          */
449         new->head = ((u8 *) new) + sizeof(*new);
450         new->tail = new->head + new_head_len;
451         new->head_len = new_head_len;
452         new->tail_len = new_tail_len;
453
454         /* copy in head */
455         if (params->head)
456                 memcpy(new->head, params->head, new_head_len);
457         else
458                 memcpy(new->head, old->head, new_head_len);
459
460         /* copy in optional tail */
461         if (params->tail)
462                 memcpy(new->tail, params->tail, new_tail_len);
463         else
464                 if (old)
465                         memcpy(new->tail, old->tail, new_tail_len);
466
467         rcu_assign_pointer(sdata->u.ap.beacon, new);
468
469         synchronize_rcu();
470
471         kfree(old);
472
473         return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
474 }
475
476 static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
477                                 struct beacon_parameters *params)
478 {
479         struct ieee80211_sub_if_data *sdata;
480         struct beacon_data *old;
481
482         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
483
484         if (sdata->vif.type != NL80211_IFTYPE_AP)
485                 return -EINVAL;
486
487         old = sdata->u.ap.beacon;
488
489         if (old)
490                 return -EALREADY;
491
492         return ieee80211_config_beacon(sdata, params);
493 }
494
495 static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
496                                 struct beacon_parameters *params)
497 {
498         struct ieee80211_sub_if_data *sdata;
499         struct beacon_data *old;
500
501         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
502
503         if (sdata->vif.type != NL80211_IFTYPE_AP)
504                 return -EINVAL;
505
506         old = sdata->u.ap.beacon;
507
508         if (!old)
509                 return -ENOENT;
510
511         return ieee80211_config_beacon(sdata, params);
512 }
513
514 static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
515 {
516         struct ieee80211_sub_if_data *sdata;
517         struct beacon_data *old;
518
519         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
520
521         if (sdata->vif.type != NL80211_IFTYPE_AP)
522                 return -EINVAL;
523
524         old = sdata->u.ap.beacon;
525
526         if (!old)
527                 return -ENOENT;
528
529         rcu_assign_pointer(sdata->u.ap.beacon, NULL);
530         synchronize_rcu();
531         kfree(old);
532
533         return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
534 }
535
536 /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
537 struct iapp_layer2_update {
538         u8 da[ETH_ALEN];        /* broadcast */
539         u8 sa[ETH_ALEN];        /* STA addr */
540         __be16 len;             /* 6 */
541         u8 dsap;                /* 0 */
542         u8 ssap;                /* 0 */
543         u8 control;
544         u8 xid_info[3];
545 } __attribute__ ((packed));
546
547 static void ieee80211_send_layer2_update(struct sta_info *sta)
548 {
549         struct iapp_layer2_update *msg;
550         struct sk_buff *skb;
551
552         /* Send Level 2 Update Frame to update forwarding tables in layer 2
553          * bridge devices */
554
555         skb = dev_alloc_skb(sizeof(*msg));
556         if (!skb)
557                 return;
558         msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
559
560         /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
561          * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
562
563         memset(msg->da, 0xff, ETH_ALEN);
564         memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
565         msg->len = htons(6);
566         msg->dsap = 0;
567         msg->ssap = 0x01;       /* NULL LSAP, CR Bit: Response */
568         msg->control = 0xaf;    /* XID response lsb.1111F101.
569                                  * F=0 (no poll command; unsolicited frame) */
570         msg->xid_info[0] = 0x81;        /* XID format identifier */
571         msg->xid_info[1] = 1;   /* LLC types/classes: Type 1 LLC */
572         msg->xid_info[2] = 0;   /* XID sender's receive window size (RW) */
573
574         skb->dev = sta->sdata->dev;
575         skb->protocol = eth_type_trans(skb, sta->sdata->dev);
576         memset(skb->cb, 0, sizeof(skb->cb));
577         netif_rx(skb);
578 }
579
580 static void sta_apply_parameters(struct ieee80211_local *local,
581                                  struct sta_info *sta,
582                                  struct station_parameters *params)
583 {
584         u32 rates;
585         int i, j;
586         struct ieee80211_supported_band *sband;
587         struct ieee80211_sub_if_data *sdata = sta->sdata;
588
589         /*
590          * FIXME: updating the flags is racy when this function is
591          *        called from ieee80211_change_station(), this will
592          *        be resolved in a future patch.
593          */
594
595         if (params->station_flags & STATION_FLAG_CHANGED) {
596                 spin_lock_bh(&sta->lock);
597                 sta->flags &= ~WLAN_STA_AUTHORIZED;
598                 if (params->station_flags & STATION_FLAG_AUTHORIZED)
599                         sta->flags |= WLAN_STA_AUTHORIZED;
600
601                 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
602                 if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE)
603                         sta->flags |= WLAN_STA_SHORT_PREAMBLE;
604
605                 sta->flags &= ~WLAN_STA_WME;
606                 if (params->station_flags & STATION_FLAG_WME)
607                         sta->flags |= WLAN_STA_WME;
608                 spin_unlock_bh(&sta->lock);
609         }
610
611         /*
612          * FIXME: updating the following information is racy when this
613          *        function is called from ieee80211_change_station().
614          *        However, all this information should be static so
615          *        maybe we should just reject attemps to change it.
616          */
617
618         if (params->aid) {
619                 sta->sta.aid = params->aid;
620                 if (sta->sta.aid > IEEE80211_MAX_AID)
621                         sta->sta.aid = 0; /* XXX: should this be an error? */
622         }
623
624         if (params->listen_interval >= 0)
625                 sta->listen_interval = params->listen_interval;
626
627         if (params->supported_rates) {
628                 rates = 0;
629                 sband = local->hw.wiphy->bands[local->oper_channel->band];
630
631                 for (i = 0; i < params->supported_rates_len; i++) {
632                         int rate = (params->supported_rates[i] & 0x7f) * 5;
633                         for (j = 0; j < sband->n_bitrates; j++) {
634                                 if (sband->bitrates[j].bitrate == rate)
635                                         rates |= BIT(j);
636                         }
637                 }
638                 sta->sta.supp_rates[local->oper_channel->band] = rates;
639         }
640
641         if (params->ht_capa) {
642                 ieee80211_ht_cap_ie_to_ht_info(params->ht_capa,
643                                                &sta->sta.ht_info);
644         }
645
646         if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
647                 switch (params->plink_action) {
648                 case PLINK_ACTION_OPEN:
649                         mesh_plink_open(sta);
650                         break;
651                 case PLINK_ACTION_BLOCK:
652                         mesh_plink_block(sta);
653                         break;
654                 }
655         }
656 }
657
658 static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
659                                  u8 *mac, struct station_parameters *params)
660 {
661         struct ieee80211_local *local = wiphy_priv(wiphy);
662         struct sta_info *sta;
663         struct ieee80211_sub_if_data *sdata;
664         int err;
665
666         /* Prevent a race with changing the rate control algorithm */
667         if (!netif_running(dev))
668                 return -ENETDOWN;
669
670         if (params->vlan) {
671                 sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
672
673                 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
674                     sdata->vif.type != NL80211_IFTYPE_AP)
675                         return -EINVAL;
676         } else
677                 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
678
679         if (compare_ether_addr(mac, dev->dev_addr) == 0)
680                 return -EINVAL;
681
682         if (is_multicast_ether_addr(mac))
683                 return -EINVAL;
684
685         sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
686         if (!sta)
687                 return -ENOMEM;
688
689         sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
690
691         sta_apply_parameters(local, sta, params);
692
693         rate_control_rate_init(sta, local);
694
695         rcu_read_lock();
696
697         err = sta_info_insert(sta);
698         if (err) {
699                 /* STA has been freed */
700                 rcu_read_unlock();
701                 return err;
702         }
703
704         if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
705             sdata->vif.type == NL80211_IFTYPE_AP)
706                 ieee80211_send_layer2_update(sta);
707
708         rcu_read_unlock();
709
710         return 0;
711 }
712
713 static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
714                                  u8 *mac)
715 {
716         struct ieee80211_local *local = wiphy_priv(wiphy);
717         struct ieee80211_sub_if_data *sdata;
718         struct sta_info *sta;
719
720         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
721
722         if (mac) {
723                 rcu_read_lock();
724
725                 /* XXX: get sta belonging to dev */
726                 sta = sta_info_get(local, mac);
727                 if (!sta) {
728                         rcu_read_unlock();
729                         return -ENOENT;
730                 }
731
732                 sta_info_unlink(&sta);
733                 rcu_read_unlock();
734
735                 sta_info_destroy(sta);
736         } else
737                 sta_info_flush(local, sdata);
738
739         return 0;
740 }
741
742 static int ieee80211_change_station(struct wiphy *wiphy,
743                                     struct net_device *dev,
744                                     u8 *mac,
745                                     struct station_parameters *params)
746 {
747         struct ieee80211_local *local = wiphy_priv(wiphy);
748         struct sta_info *sta;
749         struct ieee80211_sub_if_data *vlansdata;
750
751         rcu_read_lock();
752
753         /* XXX: get sta belonging to dev */
754         sta = sta_info_get(local, mac);
755         if (!sta) {
756                 rcu_read_unlock();
757                 return -ENOENT;
758         }
759
760         if (params->vlan && params->vlan != sta->sdata->dev) {
761                 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
762
763                 if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
764                     vlansdata->vif.type != NL80211_IFTYPE_AP) {
765                         rcu_read_unlock();
766                         return -EINVAL;
767                 }
768
769                 sta->sdata = vlansdata;
770                 ieee80211_send_layer2_update(sta);
771         }
772
773         sta_apply_parameters(local, sta, params);
774
775         rcu_read_unlock();
776
777         return 0;
778 }
779
780 #ifdef CONFIG_MAC80211_MESH
781 static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
782                                  u8 *dst, u8 *next_hop)
783 {
784         struct ieee80211_local *local = wiphy_priv(wiphy);
785         struct ieee80211_sub_if_data *sdata;
786         struct mesh_path *mpath;
787         struct sta_info *sta;
788         int err;
789
790         if (!netif_running(dev))
791                 return -ENETDOWN;
792
793         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
794
795         if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
796                 return -ENOTSUPP;
797
798         rcu_read_lock();
799         sta = sta_info_get(local, next_hop);
800         if (!sta) {
801                 rcu_read_unlock();
802                 return -ENOENT;
803         }
804
805         err = mesh_path_add(dst, sdata);
806         if (err) {
807                 rcu_read_unlock();
808                 return err;
809         }
810
811         mpath = mesh_path_lookup(dst, sdata);
812         if (!mpath) {
813                 rcu_read_unlock();
814                 return -ENXIO;
815         }
816         mesh_path_fix_nexthop(mpath, sta);
817
818         rcu_read_unlock();
819         return 0;
820 }
821
822 static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
823                                  u8 *dst)
824 {
825         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
826
827         if (dst)
828                 return mesh_path_del(dst, sdata);
829
830         mesh_path_flush(sdata);
831         return 0;
832 }
833
834 static int ieee80211_change_mpath(struct wiphy *wiphy,
835                                     struct net_device *dev,
836                                     u8 *dst, u8 *next_hop)
837 {
838         struct ieee80211_local *local = wiphy_priv(wiphy);
839         struct ieee80211_sub_if_data *sdata;
840         struct mesh_path *mpath;
841         struct sta_info *sta;
842
843         if (!netif_running(dev))
844                 return -ENETDOWN;
845
846         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
847
848         if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
849                 return -ENOTSUPP;
850
851         rcu_read_lock();
852
853         sta = sta_info_get(local, next_hop);
854         if (!sta) {
855                 rcu_read_unlock();
856                 return -ENOENT;
857         }
858
859         mpath = mesh_path_lookup(dst, sdata);
860         if (!mpath) {
861                 rcu_read_unlock();
862                 return -ENOENT;
863         }
864
865         mesh_path_fix_nexthop(mpath, sta);
866
867         rcu_read_unlock();
868         return 0;
869 }
870
871 static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
872                             struct mpath_info *pinfo)
873 {
874         if (mpath->next_hop)
875                 memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
876         else
877                 memset(next_hop, 0, ETH_ALEN);
878
879         pinfo->filled = MPATH_INFO_FRAME_QLEN |
880                         MPATH_INFO_DSN |
881                         MPATH_INFO_METRIC |
882                         MPATH_INFO_EXPTIME |
883                         MPATH_INFO_DISCOVERY_TIMEOUT |
884                         MPATH_INFO_DISCOVERY_RETRIES |
885                         MPATH_INFO_FLAGS;
886
887         pinfo->frame_qlen = mpath->frame_queue.qlen;
888         pinfo->dsn = mpath->dsn;
889         pinfo->metric = mpath->metric;
890         if (time_before(jiffies, mpath->exp_time))
891                 pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
892         pinfo->discovery_timeout =
893                         jiffies_to_msecs(mpath->discovery_timeout);
894         pinfo->discovery_retries = mpath->discovery_retries;
895         pinfo->flags = 0;
896         if (mpath->flags & MESH_PATH_ACTIVE)
897                 pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
898         if (mpath->flags & MESH_PATH_RESOLVING)
899                 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
900         if (mpath->flags & MESH_PATH_DSN_VALID)
901                 pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
902         if (mpath->flags & MESH_PATH_FIXED)
903                 pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
904         if (mpath->flags & MESH_PATH_RESOLVING)
905                 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
906
907         pinfo->flags = mpath->flags;
908 }
909
910 static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
911                                u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
912
913 {
914         struct ieee80211_sub_if_data *sdata;
915         struct mesh_path *mpath;
916
917         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
918
919         if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
920                 return -ENOTSUPP;
921
922         rcu_read_lock();
923         mpath = mesh_path_lookup(dst, sdata);
924         if (!mpath) {
925                 rcu_read_unlock();
926                 return -ENOENT;
927         }
928         memcpy(dst, mpath->dst, ETH_ALEN);
929         mpath_set_pinfo(mpath, next_hop, pinfo);
930         rcu_read_unlock();
931         return 0;
932 }
933
934 static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
935                                  int idx, u8 *dst, u8 *next_hop,
936                                  struct mpath_info *pinfo)
937 {
938         struct ieee80211_sub_if_data *sdata;
939         struct mesh_path *mpath;
940
941         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
942
943         if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
944                 return -ENOTSUPP;
945
946         rcu_read_lock();
947         mpath = mesh_path_lookup_by_idx(idx, sdata);
948         if (!mpath) {
949                 rcu_read_unlock();
950                 return -ENOENT;
951         }
952         memcpy(dst, mpath->dst, ETH_ALEN);
953         mpath_set_pinfo(mpath, next_hop, pinfo);
954         rcu_read_unlock();
955         return 0;
956 }
957 #endif
958
959 static int ieee80211_change_bss(struct wiphy *wiphy,
960                                 struct net_device *dev,
961                                 struct bss_parameters *params)
962 {
963         struct ieee80211_sub_if_data *sdata;
964         u32 changed = 0;
965
966         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
967
968         if (sdata->vif.type != NL80211_IFTYPE_AP)
969                 return -EINVAL;
970
971         if (params->use_cts_prot >= 0) {
972                 sdata->bss_conf.use_cts_prot = params->use_cts_prot;
973                 changed |= BSS_CHANGED_ERP_CTS_PROT;
974         }
975         if (params->use_short_preamble >= 0) {
976                 sdata->bss_conf.use_short_preamble =
977                         params->use_short_preamble;
978                 changed |= BSS_CHANGED_ERP_PREAMBLE;
979         }
980         if (params->use_short_slot_time >= 0) {
981                 sdata->bss_conf.use_short_slot =
982                         params->use_short_slot_time;
983                 changed |= BSS_CHANGED_ERP_SLOT;
984         }
985
986         ieee80211_bss_info_change_notify(sdata, changed);
987
988         return 0;
989 }
990
991 struct cfg80211_ops mac80211_config_ops = {
992         .add_virtual_intf = ieee80211_add_iface,
993         .del_virtual_intf = ieee80211_del_iface,
994         .change_virtual_intf = ieee80211_change_iface,
995         .add_key = ieee80211_add_key,
996         .del_key = ieee80211_del_key,
997         .get_key = ieee80211_get_key,
998         .set_default_key = ieee80211_config_default_key,
999         .add_beacon = ieee80211_add_beacon,
1000         .set_beacon = ieee80211_set_beacon,
1001         .del_beacon = ieee80211_del_beacon,
1002         .add_station = ieee80211_add_station,
1003         .del_station = ieee80211_del_station,
1004         .change_station = ieee80211_change_station,
1005         .get_station = ieee80211_get_station,
1006         .dump_station = ieee80211_dump_station,
1007 #ifdef CONFIG_MAC80211_MESH
1008         .add_mpath = ieee80211_add_mpath,
1009         .del_mpath = ieee80211_del_mpath,
1010         .change_mpath = ieee80211_change_mpath,
1011         .get_mpath = ieee80211_get_mpath,
1012         .dump_mpath = ieee80211_dump_mpath,
1013 #endif
1014         .change_bss = ieee80211_change_bss,
1015 };