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