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