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