mac80211: implement cfg80211 station handling
[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
19 static enum ieee80211_if_types
20 nl80211_type_to_mac80211_type(enum nl80211_iftype type)
21 {
22         switch (type) {
23         case NL80211_IFTYPE_UNSPECIFIED:
24                 return IEEE80211_IF_TYPE_STA;
25         case NL80211_IFTYPE_ADHOC:
26                 return IEEE80211_IF_TYPE_IBSS;
27         case NL80211_IFTYPE_STATION:
28                 return IEEE80211_IF_TYPE_STA;
29         case NL80211_IFTYPE_MONITOR:
30                 return IEEE80211_IF_TYPE_MNTR;
31         default:
32                 return IEEE80211_IF_TYPE_INVALID;
33         }
34 }
35
36 static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
37                                enum nl80211_iftype type)
38 {
39         struct ieee80211_local *local = wiphy_priv(wiphy);
40         enum ieee80211_if_types itype;
41
42         if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
43                 return -ENODEV;
44
45         itype = nl80211_type_to_mac80211_type(type);
46         if (itype == IEEE80211_IF_TYPE_INVALID)
47                 return -EINVAL;
48
49         return ieee80211_if_add(local->mdev, name, NULL, itype);
50 }
51
52 static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
53 {
54         struct ieee80211_local *local = wiphy_priv(wiphy);
55         struct net_device *dev;
56         char *name;
57
58         if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
59                 return -ENODEV;
60
61         /* we're under RTNL */
62         dev = __dev_get_by_index(&init_net, ifindex);
63         if (!dev)
64                 return 0;
65
66         name = dev->name;
67
68         return ieee80211_if_remove(local->mdev, name, -1);
69 }
70
71 static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
72                                   enum nl80211_iftype type)
73 {
74         struct ieee80211_local *local = wiphy_priv(wiphy);
75         struct net_device *dev;
76         enum ieee80211_if_types itype;
77         struct ieee80211_sub_if_data *sdata;
78
79         if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
80                 return -ENODEV;
81
82         /* we're under RTNL */
83         dev = __dev_get_by_index(&init_net, ifindex);
84         if (!dev)
85                 return -ENODEV;
86
87         if (netif_running(dev))
88                 return -EBUSY;
89
90         itype = nl80211_type_to_mac80211_type(type);
91         if (itype == IEEE80211_IF_TYPE_INVALID)
92                 return -EINVAL;
93
94         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
95
96         if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
97                 return -EOPNOTSUPP;
98
99         ieee80211_if_reinit(dev);
100         ieee80211_if_set_type(dev, itype);
101
102         return 0;
103 }
104
105 static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
106                              u8 key_idx, u8 *mac_addr,
107                              struct key_params *params)
108 {
109         struct ieee80211_sub_if_data *sdata;
110         struct sta_info *sta = NULL;
111         enum ieee80211_key_alg alg;
112         int ret;
113
114         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
115
116         switch (params->cipher) {
117         case WLAN_CIPHER_SUITE_WEP40:
118         case WLAN_CIPHER_SUITE_WEP104:
119                 alg = ALG_WEP;
120                 break;
121         case WLAN_CIPHER_SUITE_TKIP:
122                 alg = ALG_TKIP;
123                 break;
124         case WLAN_CIPHER_SUITE_CCMP:
125                 alg = ALG_CCMP;
126                 break;
127         default:
128                 return -EINVAL;
129         }
130
131         if (mac_addr) {
132                 sta = sta_info_get(sdata->local, mac_addr);
133                 if (!sta)
134                         return -ENOENT;
135         }
136
137         ret = 0;
138         if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
139                                  params->key_len, params->key))
140                 ret = -ENOMEM;
141
142         if (sta)
143                 sta_info_put(sta);
144
145         return ret;
146 }
147
148 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
149                              u8 key_idx, u8 *mac_addr)
150 {
151         struct ieee80211_sub_if_data *sdata;
152         struct sta_info *sta;
153         int ret;
154
155         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
156
157         if (mac_addr) {
158                 sta = sta_info_get(sdata->local, mac_addr);
159                 if (!sta)
160                         return -ENOENT;
161
162                 ret = 0;
163                 if (sta->key)
164                         ieee80211_key_free(sta->key);
165                 else
166                         ret = -ENOENT;
167
168                 sta_info_put(sta);
169                 return ret;
170         }
171
172         if (!sdata->keys[key_idx])
173                 return -ENOENT;
174
175         ieee80211_key_free(sdata->keys[key_idx]);
176
177         return 0;
178 }
179
180 static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
181                              u8 key_idx, u8 *mac_addr, void *cookie,
182                              void (*callback)(void *cookie,
183                                               struct key_params *params))
184 {
185         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
186         struct sta_info *sta = NULL;
187         u8 seq[6] = {0};
188         struct key_params params;
189         struct ieee80211_key *key;
190         u32 iv32;
191         u16 iv16;
192         int err = -ENOENT;
193
194         if (mac_addr) {
195                 sta = sta_info_get(sdata->local, mac_addr);
196                 if (!sta)
197                         goto out;
198
199                 key = sta->key;
200         } else
201                 key = sdata->keys[key_idx];
202
203         if (!key)
204                 goto out;
205
206         memset(&params, 0, sizeof(params));
207
208         switch (key->conf.alg) {
209         case ALG_TKIP:
210                 params.cipher = WLAN_CIPHER_SUITE_TKIP;
211
212                 iv32 = key->u.tkip.iv32;
213                 iv16 = key->u.tkip.iv16;
214
215                 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
216                     sdata->local->ops->get_tkip_seq)
217                         sdata->local->ops->get_tkip_seq(
218                                 local_to_hw(sdata->local),
219                                 key->conf.hw_key_idx,
220                                 &iv32, &iv16);
221
222                 seq[0] = iv16 & 0xff;
223                 seq[1] = (iv16 >> 8) & 0xff;
224                 seq[2] = iv32 & 0xff;
225                 seq[3] = (iv32 >> 8) & 0xff;
226                 seq[4] = (iv32 >> 16) & 0xff;
227                 seq[5] = (iv32 >> 24) & 0xff;
228                 params.seq = seq;
229                 params.seq_len = 6;
230                 break;
231         case ALG_CCMP:
232                 params.cipher = WLAN_CIPHER_SUITE_CCMP;
233                 seq[0] = key->u.ccmp.tx_pn[5];
234                 seq[1] = key->u.ccmp.tx_pn[4];
235                 seq[2] = key->u.ccmp.tx_pn[3];
236                 seq[3] = key->u.ccmp.tx_pn[2];
237                 seq[4] = key->u.ccmp.tx_pn[1];
238                 seq[5] = key->u.ccmp.tx_pn[0];
239                 params.seq = seq;
240                 params.seq_len = 6;
241                 break;
242         case ALG_WEP:
243                 if (key->conf.keylen == 5)
244                         params.cipher = WLAN_CIPHER_SUITE_WEP40;
245                 else
246                         params.cipher = WLAN_CIPHER_SUITE_WEP104;
247                 break;
248         }
249
250         params.key = key->conf.key;
251         params.key_len = key->conf.keylen;
252
253         callback(cookie, &params);
254         err = 0;
255
256  out:
257         if (sta)
258                 sta_info_put(sta);
259         return err;
260 }
261
262 static int ieee80211_config_default_key(struct wiphy *wiphy,
263                                         struct net_device *dev,
264                                         u8 key_idx)
265 {
266         struct ieee80211_sub_if_data *sdata;
267
268         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
269         ieee80211_set_default_key(sdata, key_idx);
270
271         return 0;
272 }
273
274 static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
275                                  u8 *mac, struct station_stats *stats)
276 {
277         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
278         struct sta_info *sta;
279
280         sta = sta_info_get(local, mac);
281         if (!sta)
282                 return -ENOENT;
283
284         /* XXX: verify sta->dev == dev */
285
286         stats->filled = STATION_STAT_INACTIVE_TIME |
287                         STATION_STAT_RX_BYTES |
288                         STATION_STAT_TX_BYTES;
289
290         stats->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
291         stats->rx_bytes = sta->rx_bytes;
292         stats->tx_bytes = sta->tx_bytes;
293
294         sta_info_put(sta);
295
296         return 0;
297 }
298
299 /*
300  * This handles both adding a beacon and setting new beacon info
301  */
302 static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
303                                    struct beacon_parameters *params)
304 {
305         struct beacon_data *new, *old;
306         int new_head_len, new_tail_len;
307         int size;
308         int err = -EINVAL;
309
310         old = sdata->u.ap.beacon;
311
312         /* head must not be zero-length */
313         if (params->head && !params->head_len)
314                 return -EINVAL;
315
316         /*
317          * This is a kludge. beacon interval should really be part
318          * of the beacon information.
319          */
320         if (params->interval) {
321                 sdata->local->hw.conf.beacon_int = params->interval;
322                 if (ieee80211_hw_config(sdata->local))
323                         return -EINVAL;
324                 /*
325                  * We updated some parameter so if below bails out
326                  * it's not an error.
327                  */
328                 err = 0;
329         }
330
331         /* Need to have a beacon head if we don't have one yet */
332         if (!params->head && !old)
333                 return err;
334
335         /* sorry, no way to start beaconing without dtim period */
336         if (!params->dtim_period && !old)
337                 return err;
338
339         /* new or old head? */
340         if (params->head)
341                 new_head_len = params->head_len;
342         else
343                 new_head_len = old->head_len;
344
345         /* new or old tail? */
346         if (params->tail || !old)
347                 /* params->tail_len will be zero for !params->tail */
348                 new_tail_len = params->tail_len;
349         else
350                 new_tail_len = old->tail_len;
351
352         size = sizeof(*new) + new_head_len + new_tail_len;
353
354         new = kzalloc(size, GFP_KERNEL);
355         if (!new)
356                 return -ENOMEM;
357
358         /* start filling the new info now */
359
360         /* new or old dtim period? */
361         if (params->dtim_period)
362                 new->dtim_period = params->dtim_period;
363         else
364                 new->dtim_period = old->dtim_period;
365
366         /*
367          * pointers go into the block we allocated,
368          * memory is | beacon_data | head | tail |
369          */
370         new->head = ((u8 *) new) + sizeof(*new);
371         new->tail = new->head + new_head_len;
372         new->head_len = new_head_len;
373         new->tail_len = new_tail_len;
374
375         /* copy in head */
376         if (params->head)
377                 memcpy(new->head, params->head, new_head_len);
378         else
379                 memcpy(new->head, old->head, new_head_len);
380
381         /* copy in optional tail */
382         if (params->tail)
383                 memcpy(new->tail, params->tail, new_tail_len);
384         else
385                 if (old)
386                         memcpy(new->tail, old->tail, new_tail_len);
387
388         rcu_assign_pointer(sdata->u.ap.beacon, new);
389
390         synchronize_rcu();
391
392         kfree(old);
393
394         return ieee80211_if_config_beacon(sdata->dev);
395 }
396
397 static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
398                                 struct beacon_parameters *params)
399 {
400         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
401         struct beacon_data *old;
402
403         if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
404                 return -EINVAL;
405
406         old = sdata->u.ap.beacon;
407
408         if (old)
409                 return -EALREADY;
410
411         return ieee80211_config_beacon(sdata, params);
412 }
413
414 static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
415                                 struct beacon_parameters *params)
416 {
417         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
418         struct beacon_data *old;
419
420         if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
421                 return -EINVAL;
422
423         old = sdata->u.ap.beacon;
424
425         if (!old)
426                 return -ENOENT;
427
428         return ieee80211_config_beacon(sdata, params);
429 }
430
431 static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
432 {
433         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
434         struct beacon_data *old;
435
436         if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
437                 return -EINVAL;
438
439         old = sdata->u.ap.beacon;
440
441         if (!old)
442                 return -ENOENT;
443
444         rcu_assign_pointer(sdata->u.ap.beacon, NULL);
445         synchronize_rcu();
446         kfree(old);
447
448         return ieee80211_if_config_beacon(dev);
449 }
450
451 /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
452 struct iapp_layer2_update {
453         u8 da[ETH_ALEN];        /* broadcast */
454         u8 sa[ETH_ALEN];        /* STA addr */
455         __be16 len;             /* 6 */
456         u8 dsap;                /* 0 */
457         u8 ssap;                /* 0 */
458         u8 control;
459         u8 xid_info[3];
460 } __attribute__ ((packed));
461
462 static void ieee80211_send_layer2_update(struct sta_info *sta)
463 {
464         struct iapp_layer2_update *msg;
465         struct sk_buff *skb;
466
467         /* Send Level 2 Update Frame to update forwarding tables in layer 2
468          * bridge devices */
469
470         skb = dev_alloc_skb(sizeof(*msg));
471         if (!skb)
472                 return;
473         msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
474
475         /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
476          * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
477
478         memset(msg->da, 0xff, ETH_ALEN);
479         memcpy(msg->sa, sta->addr, ETH_ALEN);
480         msg->len = htons(6);
481         msg->dsap = 0;
482         msg->ssap = 0x01;       /* NULL LSAP, CR Bit: Response */
483         msg->control = 0xaf;    /* XID response lsb.1111F101.
484                                  * F=0 (no poll command; unsolicited frame) */
485         msg->xid_info[0] = 0x81;        /* XID format identifier */
486         msg->xid_info[1] = 1;   /* LLC types/classes: Type 1 LLC */
487         msg->xid_info[2] = 0;   /* XID sender's receive window size (RW) */
488
489         skb->dev = sta->dev;
490         skb->protocol = eth_type_trans(skb, sta->dev);
491         memset(skb->cb, 0, sizeof(skb->cb));
492         netif_rx(skb);
493 }
494
495 static void sta_apply_parameters(struct ieee80211_local *local,
496                                  struct sta_info *sta,
497                                  struct station_parameters *params)
498 {
499         u32 rates;
500         int i, j;
501         struct ieee80211_hw_mode *mode;
502
503         if (params->station_flags & STATION_FLAG_CHANGED) {
504                 sta->flags &= ~WLAN_STA_AUTHORIZED;
505                 if (params->station_flags & STATION_FLAG_AUTHORIZED)
506                         sta->flags |= WLAN_STA_AUTHORIZED;
507
508                 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
509                 if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE)
510                         sta->flags |= WLAN_STA_SHORT_PREAMBLE;
511
512                 sta->flags &= ~WLAN_STA_WME;
513                 if (params->station_flags & STATION_FLAG_WME)
514                         sta->flags |= WLAN_STA_WME;
515         }
516
517         if (params->aid) {
518                 sta->aid = params->aid;
519                 if (sta->aid > IEEE80211_MAX_AID)
520                         sta->aid = 0; /* XXX: should this be an error? */
521         }
522
523         if (params->listen_interval >= 0)
524                 sta->listen_interval = params->listen_interval;
525
526         if (params->supported_rates) {
527                 rates = 0;
528                 mode = local->oper_hw_mode;
529                 for (i = 0; i < params->supported_rates_len; i++) {
530                         int rate = (params->supported_rates[i] & 0x7f) * 5;
531                         for (j = 0; j < mode->num_rates; j++) {
532                                 if (mode->rates[j].rate == rate)
533                                         rates |= BIT(j);
534                         }
535                 }
536                 sta->supp_rates = rates;
537         }
538 }
539
540 static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
541                                  u8 *mac, struct station_parameters *params)
542 {
543         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
544         struct sta_info *sta;
545         struct ieee80211_sub_if_data *sdata;
546
547         /* Prevent a race with changing the rate control algorithm */
548         if (!netif_running(dev))
549                 return -ENETDOWN;
550
551         /* XXX: get sta belonging to dev */
552         sta = sta_info_get(local, mac);
553         if (sta) {
554                 sta_info_put(sta);
555                 return -EEXIST;
556         }
557
558         if (params->vlan) {
559                 sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
560
561                 if (sdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
562                     sdata->vif.type != IEEE80211_IF_TYPE_AP)
563                         return -EINVAL;
564         } else
565                 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
566
567         sta = sta_info_add(local, dev, mac, GFP_KERNEL);
568         if (!sta)
569                 return -ENOMEM;
570
571         sta->dev = sdata->dev;
572         if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
573             sdata->vif.type == IEEE80211_IF_TYPE_AP)
574                 ieee80211_send_layer2_update(sta);
575
576         sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
577
578         sta_apply_parameters(local, sta, params);
579
580         rate_control_rate_init(sta, local);
581
582         sta_info_put(sta);
583
584         return 0;
585 }
586
587 static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
588                                  u8 *mac)
589 {
590         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
591         struct sta_info *sta;
592
593         if (mac) {
594                 /* XXX: get sta belonging to dev */
595                 sta = sta_info_get(local, mac);
596                 if (!sta)
597                         return -ENOENT;
598
599                 sta_info_free(sta);
600                 sta_info_put(sta);
601         } else
602                 sta_info_flush(local, dev);
603
604         return 0;
605 }
606
607 static int ieee80211_change_station(struct wiphy *wiphy,
608                                     struct net_device *dev,
609                                     u8 *mac,
610                                     struct station_parameters *params)
611 {
612         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
613         struct sta_info *sta;
614         struct ieee80211_sub_if_data *vlansdata;
615
616         /* XXX: get sta belonging to dev */
617         sta = sta_info_get(local, mac);
618         if (!sta)
619                 return -ENOENT;
620
621         if (params->vlan && params->vlan != sta->dev) {
622                 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
623
624                 if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
625                     vlansdata->vif.type != IEEE80211_IF_TYPE_AP)
626                         return -EINVAL;
627
628                 sta->dev = params->vlan;
629                 ieee80211_send_layer2_update(sta);
630         }
631
632         sta_apply_parameters(local, sta, params);
633
634         sta_info_put(sta);
635
636         return 0;
637 }
638
639 struct cfg80211_ops mac80211_config_ops = {
640         .add_virtual_intf = ieee80211_add_iface,
641         .del_virtual_intf = ieee80211_del_iface,
642         .change_virtual_intf = ieee80211_change_iface,
643         .add_key = ieee80211_add_key,
644         .del_key = ieee80211_del_key,
645         .get_key = ieee80211_get_key,
646         .set_default_key = ieee80211_config_default_key,
647         .add_beacon = ieee80211_add_beacon,
648         .set_beacon = ieee80211_set_beacon,
649         .del_beacon = ieee80211_del_beacon,
650         .add_station = ieee80211_add_station,
651         .del_station = ieee80211_del_station,
652         .change_station = ieee80211_change_station,
653         .get_station = ieee80211_get_station,
654 };