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