igb: remove unneeded declaration shadowing earlier one
[linux-2.6] / net / wireless / nl80211.c
1 /*
2  * This is the new netlink-based wireless configuration interface.
3  *
4  * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
5  */
6
7 #include <linux/if.h>
8 #include <linux/module.h>
9 #include <linux/err.h>
10 #include <linux/mutex.h>
11 #include <linux/list.h>
12 #include <linux/if_ether.h>
13 #include <linux/ieee80211.h>
14 #include <linux/nl80211.h>
15 #include <linux/rtnetlink.h>
16 #include <linux/netlink.h>
17 #include <net/genetlink.h>
18 #include <net/cfg80211.h>
19 #include "core.h"
20 #include "nl80211.h"
21
22 /* the netlink family */
23 static struct genl_family nl80211_fam = {
24         .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
25         .name = "nl80211",      /* have users key off the name instead */
26         .hdrsize = 0,           /* no private header */
27         .version = 1,           /* no particular meaning now */
28         .maxattr = NL80211_ATTR_MAX,
29 };
30
31 /* internal helper: get drv and dev */
32 static int get_drv_dev_by_info_ifindex(struct genl_info *info,
33                                        struct cfg80211_registered_device **drv,
34                                        struct net_device **dev)
35 {
36         int ifindex;
37
38         if (!info->attrs[NL80211_ATTR_IFINDEX])
39                 return -EINVAL;
40
41         ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
42         *dev = dev_get_by_index(&init_net, ifindex);
43         if (!*dev)
44                 return -ENODEV;
45
46         *drv = cfg80211_get_dev_from_ifindex(ifindex);
47         if (IS_ERR(*drv)) {
48                 dev_put(*dev);
49                 return PTR_ERR(*drv);
50         }
51
52         return 0;
53 }
54
55 /* policy for the attributes */
56 static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
57         [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
58         [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
59                                       .len = BUS_ID_SIZE-1 },
60
61         [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
62         [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
63         [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
64
65         [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
66
67         [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
68                                     .len = WLAN_MAX_KEY_LEN },
69         [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
70         [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
71         [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
72
73         [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
74         [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
75         [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
76                                        .len = IEEE80211_MAX_DATA_LEN },
77         [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
78                                        .len = IEEE80211_MAX_DATA_LEN },
79         [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
80         [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
81         [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
82         [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
83                                                .len = NL80211_MAX_SUPP_RATES },
84         [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
85 };
86
87 /* message building helper */
88 static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
89                                    int flags, u8 cmd)
90 {
91         /* since there is no private header just add the generic one */
92         return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
93 }
94
95 /* netlink command implementations */
96
97 static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
98                               struct cfg80211_registered_device *dev)
99 {
100         void *hdr;
101
102         hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
103         if (!hdr)
104                 return -1;
105
106         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
107         NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
108         return genlmsg_end(msg, hdr);
109
110  nla_put_failure:
111         return genlmsg_cancel(msg, hdr);
112 }
113
114 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
115 {
116         int idx = 0;
117         int start = cb->args[0];
118         struct cfg80211_registered_device *dev;
119
120         mutex_lock(&cfg80211_drv_mutex);
121         list_for_each_entry(dev, &cfg80211_drv_list, list) {
122                 if (++idx < start)
123                         continue;
124                 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
125                                        cb->nlh->nlmsg_seq, NLM_F_MULTI,
126                                        dev) < 0)
127                         break;
128         }
129         mutex_unlock(&cfg80211_drv_mutex);
130
131         cb->args[0] = idx;
132
133         return skb->len;
134 }
135
136 static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
137 {
138         struct sk_buff *msg;
139         struct cfg80211_registered_device *dev;
140
141         dev = cfg80211_get_dev_from_info(info);
142         if (IS_ERR(dev))
143                 return PTR_ERR(dev);
144
145         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
146         if (!msg)
147                 goto out_err;
148
149         if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
150                 goto out_free;
151
152         cfg80211_put_dev(dev);
153
154         return genlmsg_unicast(msg, info->snd_pid);
155
156  out_free:
157         nlmsg_free(msg);
158  out_err:
159         cfg80211_put_dev(dev);
160         return -ENOBUFS;
161 }
162
163 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
164 {
165         struct cfg80211_registered_device *rdev;
166         int result;
167
168         if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
169                 return -EINVAL;
170
171         rdev = cfg80211_get_dev_from_info(info);
172         if (IS_ERR(rdev))
173                 return PTR_ERR(rdev);
174
175         result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
176
177         cfg80211_put_dev(rdev);
178         return result;
179 }
180
181
182 static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
183                               struct net_device *dev)
184 {
185         void *hdr;
186
187         hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
188         if (!hdr)
189                 return -1;
190
191         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
192         NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
193         /* TODO: interface type */
194         return genlmsg_end(msg, hdr);
195
196  nla_put_failure:
197         return genlmsg_cancel(msg, hdr);
198 }
199
200 static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
201 {
202         int wp_idx = 0;
203         int if_idx = 0;
204         int wp_start = cb->args[0];
205         int if_start = cb->args[1];
206         struct cfg80211_registered_device *dev;
207         struct wireless_dev *wdev;
208
209         mutex_lock(&cfg80211_drv_mutex);
210         list_for_each_entry(dev, &cfg80211_drv_list, list) {
211                 if (++wp_idx < wp_start)
212                         continue;
213                 if_idx = 0;
214
215                 mutex_lock(&dev->devlist_mtx);
216                 list_for_each_entry(wdev, &dev->netdev_list, list) {
217                         if (++if_idx < if_start)
218                                 continue;
219                         if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
220                                                cb->nlh->nlmsg_seq, NLM_F_MULTI,
221                                                wdev->netdev) < 0)
222                                 break;
223                 }
224                 mutex_unlock(&dev->devlist_mtx);
225         }
226         mutex_unlock(&cfg80211_drv_mutex);
227
228         cb->args[0] = wp_idx;
229         cb->args[1] = if_idx;
230
231         return skb->len;
232 }
233
234 static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
235 {
236         struct sk_buff *msg;
237         struct cfg80211_registered_device *dev;
238         struct net_device *netdev;
239         int err;
240
241         err = get_drv_dev_by_info_ifindex(info, &dev, &netdev);
242         if (err)
243                 return err;
244
245         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
246         if (!msg)
247                 goto out_err;
248
249         if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
250                 goto out_free;
251
252         dev_put(netdev);
253         cfg80211_put_dev(dev);
254
255         return genlmsg_unicast(msg, info->snd_pid);
256
257  out_free:
258         nlmsg_free(msg);
259  out_err:
260         dev_put(netdev);
261         cfg80211_put_dev(dev);
262         return -ENOBUFS;
263 }
264
265 static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
266 {
267         struct cfg80211_registered_device *drv;
268         int err, ifindex;
269         enum nl80211_iftype type;
270         struct net_device *dev;
271
272         if (info->attrs[NL80211_ATTR_IFTYPE]) {
273                 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
274                 if (type > NL80211_IFTYPE_MAX)
275                         return -EINVAL;
276         } else
277                 return -EINVAL;
278
279         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
280         if (err)
281                 return err;
282         ifindex = dev->ifindex;
283         dev_put(dev);
284
285         if (!drv->ops->change_virtual_intf) {
286                 err = -EOPNOTSUPP;
287                 goto unlock;
288         }
289
290         rtnl_lock();
291         err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
292         rtnl_unlock();
293
294  unlock:
295         cfg80211_put_dev(drv);
296         return err;
297 }
298
299 static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
300 {
301         struct cfg80211_registered_device *drv;
302         int err;
303         enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
304
305         if (!info->attrs[NL80211_ATTR_IFNAME])
306                 return -EINVAL;
307
308         if (info->attrs[NL80211_ATTR_IFTYPE]) {
309                 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
310                 if (type > NL80211_IFTYPE_MAX)
311                         return -EINVAL;
312         }
313
314         drv = cfg80211_get_dev_from_info(info);
315         if (IS_ERR(drv))
316                 return PTR_ERR(drv);
317
318         if (!drv->ops->add_virtual_intf) {
319                 err = -EOPNOTSUPP;
320                 goto unlock;
321         }
322
323         rtnl_lock();
324         err = drv->ops->add_virtual_intf(&drv->wiphy,
325                 nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
326         rtnl_unlock();
327
328  unlock:
329         cfg80211_put_dev(drv);
330         return err;
331 }
332
333 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
334 {
335         struct cfg80211_registered_device *drv;
336         int ifindex, err;
337         struct net_device *dev;
338
339         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
340         if (err)
341                 return err;
342         ifindex = dev->ifindex;
343         dev_put(dev);
344
345         if (!drv->ops->del_virtual_intf) {
346                 err = -EOPNOTSUPP;
347                 goto out;
348         }
349
350         rtnl_lock();
351         err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
352         rtnl_unlock();
353
354  out:
355         cfg80211_put_dev(drv);
356         return err;
357 }
358
359 struct get_key_cookie {
360         struct sk_buff *msg;
361         int error;
362 };
363
364 static void get_key_callback(void *c, struct key_params *params)
365 {
366         struct get_key_cookie *cookie = c;
367
368         if (params->key)
369                 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
370                         params->key_len, params->key);
371
372         if (params->seq)
373                 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
374                         params->seq_len, params->seq);
375
376         if (params->cipher)
377                 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
378                             params->cipher);
379
380         return;
381  nla_put_failure:
382         cookie->error = 1;
383 }
384
385 static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
386 {
387         struct cfg80211_registered_device *drv;
388         int err;
389         struct net_device *dev;
390         u8 key_idx = 0;
391         u8 *mac_addr = NULL;
392         struct get_key_cookie cookie = {
393                 .error = 0,
394         };
395         void *hdr;
396         struct sk_buff *msg;
397
398         if (info->attrs[NL80211_ATTR_KEY_IDX])
399                 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
400
401         if (key_idx > 3)
402                 return -EINVAL;
403
404         if (info->attrs[NL80211_ATTR_MAC])
405                 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
406
407         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
408         if (err)
409                 return err;
410
411         if (!drv->ops->get_key) {
412                 err = -EOPNOTSUPP;
413                 goto out;
414         }
415
416         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
417         if (!msg) {
418                 err = -ENOMEM;
419                 goto out;
420         }
421
422         hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
423                              NL80211_CMD_NEW_KEY);
424
425         if (IS_ERR(hdr)) {
426                 err = PTR_ERR(hdr);
427                 goto out;
428         }
429
430         cookie.msg = msg;
431
432         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
433         NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
434         if (mac_addr)
435                 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
436
437         rtnl_lock();
438         err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
439                                 &cookie, get_key_callback);
440         rtnl_unlock();
441
442         if (err)
443                 goto out;
444
445         if (cookie.error)
446                 goto nla_put_failure;
447
448         genlmsg_end(msg, hdr);
449         err = genlmsg_unicast(msg, info->snd_pid);
450         goto out;
451
452  nla_put_failure:
453         err = -ENOBUFS;
454         nlmsg_free(msg);
455  out:
456         cfg80211_put_dev(drv);
457         dev_put(dev);
458         return err;
459 }
460
461 static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
462 {
463         struct cfg80211_registered_device *drv;
464         int err;
465         struct net_device *dev;
466         u8 key_idx;
467
468         if (!info->attrs[NL80211_ATTR_KEY_IDX])
469                 return -EINVAL;
470
471         key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
472
473         if (key_idx > 3)
474                 return -EINVAL;
475
476         /* currently only support setting default key */
477         if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
478                 return -EINVAL;
479
480         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
481         if (err)
482                 return err;
483
484         if (!drv->ops->set_default_key) {
485                 err = -EOPNOTSUPP;
486                 goto out;
487         }
488
489         rtnl_lock();
490         err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
491         rtnl_unlock();
492
493  out:
494         cfg80211_put_dev(drv);
495         dev_put(dev);
496         return err;
497 }
498
499 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
500 {
501         struct cfg80211_registered_device *drv;
502         int err;
503         struct net_device *dev;
504         struct key_params params;
505         u8 key_idx = 0;
506         u8 *mac_addr = NULL;
507
508         memset(&params, 0, sizeof(params));
509
510         if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
511                 return -EINVAL;
512
513         if (info->attrs[NL80211_ATTR_KEY_DATA]) {
514                 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
515                 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
516         }
517
518         if (info->attrs[NL80211_ATTR_KEY_IDX])
519                 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
520
521         params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
522
523         if (info->attrs[NL80211_ATTR_MAC])
524                 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
525
526         if (key_idx > 3)
527                 return -EINVAL;
528
529         /*
530          * Disallow pairwise keys with non-zero index unless it's WEP
531          * (because current deployments use pairwise WEP keys with
532          * non-zero indizes but 802.11i clearly specifies to use zero)
533          */
534         if (mac_addr && key_idx &&
535             params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
536             params.cipher != WLAN_CIPHER_SUITE_WEP104)
537                 return -EINVAL;
538
539         /* TODO: add definitions for the lengths to linux/ieee80211.h */
540         switch (params.cipher) {
541         case WLAN_CIPHER_SUITE_WEP40:
542                 if (params.key_len != 5)
543                         return -EINVAL;
544                 break;
545         case WLAN_CIPHER_SUITE_TKIP:
546                 if (params.key_len != 32)
547                         return -EINVAL;
548                 break;
549         case WLAN_CIPHER_SUITE_CCMP:
550                 if (params.key_len != 16)
551                         return -EINVAL;
552                 break;
553         case WLAN_CIPHER_SUITE_WEP104:
554                 if (params.key_len != 13)
555                         return -EINVAL;
556                 break;
557         default:
558                 return -EINVAL;
559         }
560
561         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
562         if (err)
563                 return err;
564
565         if (!drv->ops->add_key) {
566                 err = -EOPNOTSUPP;
567                 goto out;
568         }
569
570         rtnl_lock();
571         err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
572         rtnl_unlock();
573
574  out:
575         cfg80211_put_dev(drv);
576         dev_put(dev);
577         return err;
578 }
579
580 static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
581 {
582         struct cfg80211_registered_device *drv;
583         int err;
584         struct net_device *dev;
585         u8 key_idx = 0;
586         u8 *mac_addr = NULL;
587
588         if (info->attrs[NL80211_ATTR_KEY_IDX])
589                 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
590
591         if (key_idx > 3)
592                 return -EINVAL;
593
594         if (info->attrs[NL80211_ATTR_MAC])
595                 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
596
597         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
598         if (err)
599                 return err;
600
601         if (!drv->ops->del_key) {
602                 err = -EOPNOTSUPP;
603                 goto out;
604         }
605
606         rtnl_lock();
607         err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
608         rtnl_unlock();
609
610  out:
611         cfg80211_put_dev(drv);
612         dev_put(dev);
613         return err;
614 }
615
616 static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
617 {
618         int (*call)(struct wiphy *wiphy, struct net_device *dev,
619                     struct beacon_parameters *info);
620         struct cfg80211_registered_device *drv;
621         int err;
622         struct net_device *dev;
623         struct beacon_parameters params;
624         int haveinfo = 0;
625
626         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
627         if (err)
628                 return err;
629
630         switch (info->genlhdr->cmd) {
631         case NL80211_CMD_NEW_BEACON:
632                 /* these are required for NEW_BEACON */
633                 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
634                     !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
635                     !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
636                         err = -EINVAL;
637                         goto out;
638                 }
639
640                 call = drv->ops->add_beacon;
641                 break;
642         case NL80211_CMD_SET_BEACON:
643                 call = drv->ops->set_beacon;
644                 break;
645         default:
646                 WARN_ON(1);
647                 err = -EOPNOTSUPP;
648                 goto out;
649         }
650
651         if (!call) {
652                 err = -EOPNOTSUPP;
653                 goto out;
654         }
655
656         memset(&params, 0, sizeof(params));
657
658         if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
659                 params.interval =
660                     nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
661                 haveinfo = 1;
662         }
663
664         if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
665                 params.dtim_period =
666                     nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
667                 haveinfo = 1;
668         }
669
670         if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
671                 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
672                 params.head_len =
673                     nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
674                 haveinfo = 1;
675         }
676
677         if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
678                 params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
679                 params.tail_len =
680                     nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
681                 haveinfo = 1;
682         }
683
684         if (!haveinfo) {
685                 err = -EINVAL;
686                 goto out;
687         }
688
689         rtnl_lock();
690         err = call(&drv->wiphy, dev, &params);
691         rtnl_unlock();
692
693  out:
694         cfg80211_put_dev(drv);
695         dev_put(dev);
696         return err;
697 }
698
699 static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
700 {
701         struct cfg80211_registered_device *drv;
702         int err;
703         struct net_device *dev;
704
705         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
706         if (err)
707                 return err;
708
709         if (!drv->ops->del_beacon) {
710                 err = -EOPNOTSUPP;
711                 goto out;
712         }
713
714         rtnl_lock();
715         err = drv->ops->del_beacon(&drv->wiphy, dev);
716         rtnl_unlock();
717
718  out:
719         cfg80211_put_dev(drv);
720         dev_put(dev);
721         return err;
722 }
723
724 static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
725         [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
726         [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
727         [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
728 };
729
730 static int parse_station_flags(struct nlattr *nla, u32 *staflags)
731 {
732         struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
733         int flag;
734
735         *staflags = 0;
736
737         if (!nla)
738                 return 0;
739
740         if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
741                              nla, sta_flags_policy))
742                 return -EINVAL;
743
744         *staflags = STATION_FLAG_CHANGED;
745
746         for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
747                 if (flags[flag])
748                         *staflags |= (1<<flag);
749
750         return 0;
751 }
752
753 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
754                                 int flags, struct net_device *dev,
755                                 u8 *mac_addr, struct station_stats *stats)
756 {
757         void *hdr;
758         struct nlattr *statsattr;
759
760         hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
761         if (!hdr)
762                 return -1;
763
764         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
765         NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
766
767         statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
768         if (!statsattr)
769                 goto nla_put_failure;
770         if (stats->filled & STATION_STAT_INACTIVE_TIME)
771                 NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
772                             stats->inactive_time);
773         if (stats->filled & STATION_STAT_RX_BYTES)
774                 NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
775                             stats->rx_bytes);
776         if (stats->filled & STATION_STAT_TX_BYTES)
777                 NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
778                             stats->tx_bytes);
779
780         nla_nest_end(msg, statsattr);
781
782         return genlmsg_end(msg, hdr);
783
784  nla_put_failure:
785         return genlmsg_cancel(msg, hdr);
786 }
787
788
789 static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
790 {
791         struct cfg80211_registered_device *drv;
792         int err;
793         struct net_device *dev;
794         struct station_stats stats;
795         struct sk_buff *msg;
796         u8 *mac_addr = NULL;
797
798         memset(&stats, 0, sizeof(stats));
799
800         if (!info->attrs[NL80211_ATTR_MAC])
801                 return -EINVAL;
802
803         mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
804
805         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
806         if (err)
807                 return err;
808
809         if (!drv->ops->get_station) {
810                 err = -EOPNOTSUPP;
811                 goto out;
812         }
813
814         rtnl_lock();
815         err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
816         rtnl_unlock();
817
818         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
819         if (!msg)
820                 goto out;
821
822         if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
823                                  dev, mac_addr, &stats) < 0)
824                 goto out_free;
825
826         err = genlmsg_unicast(msg, info->snd_pid);
827         goto out;
828
829  out_free:
830         nlmsg_free(msg);
831
832  out:
833         cfg80211_put_dev(drv);
834         dev_put(dev);
835         return err;
836 }
837
838 /*
839  * Get vlan interface making sure it is on the right wiphy.
840  */
841 static int get_vlan(struct nlattr *vlanattr,
842                     struct cfg80211_registered_device *rdev,
843                     struct net_device **vlan)
844 {
845         *vlan = NULL;
846
847         if (vlanattr) {
848                 *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
849                 if (!*vlan)
850                         return -ENODEV;
851                 if (!(*vlan)->ieee80211_ptr)
852                         return -EINVAL;
853                 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
854                         return -EINVAL;
855         }
856         return 0;
857 }
858
859 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
860 {
861         struct cfg80211_registered_device *drv;
862         int err;
863         struct net_device *dev;
864         struct station_parameters params;
865         u8 *mac_addr = NULL;
866
867         memset(&params, 0, sizeof(params));
868
869         params.listen_interval = -1;
870
871         if (info->attrs[NL80211_ATTR_STA_AID])
872                 return -EINVAL;
873
874         if (!info->attrs[NL80211_ATTR_MAC])
875                 return -EINVAL;
876
877         mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
878
879         if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
880                 params.supported_rates =
881                         nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
882                 params.supported_rates_len =
883                         nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
884         }
885
886         if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
887                 params.listen_interval =
888                     nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
889
890         if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
891                                 &params.station_flags))
892                 return -EINVAL;
893
894         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
895         if (err)
896                 return err;
897
898         err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
899         if (err)
900                 goto out;
901
902         if (!drv->ops->change_station) {
903                 err = -EOPNOTSUPP;
904                 goto out;
905         }
906
907         rtnl_lock();
908         err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
909         rtnl_unlock();
910
911  out:
912         if (params.vlan)
913                 dev_put(params.vlan);
914         cfg80211_put_dev(drv);
915         dev_put(dev);
916         return err;
917 }
918
919 static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
920 {
921         struct cfg80211_registered_device *drv;
922         int err;
923         struct net_device *dev;
924         struct station_parameters params;
925         u8 *mac_addr = NULL;
926
927         memset(&params, 0, sizeof(params));
928
929         if (!info->attrs[NL80211_ATTR_MAC])
930                 return -EINVAL;
931
932         if (!info->attrs[NL80211_ATTR_STA_AID])
933                 return -EINVAL;
934
935         if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
936                 return -EINVAL;
937
938         if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
939                 return -EINVAL;
940
941         mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
942         params.supported_rates =
943                 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
944         params.supported_rates_len =
945                 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
946         params.listen_interval =
947                 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
948         params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
949
950         if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
951                                 &params.station_flags))
952                 return -EINVAL;
953
954         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
955         if (err)
956                 return err;
957
958         err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
959         if (err)
960                 goto out;
961
962         if (!drv->ops->add_station) {
963                 err = -EOPNOTSUPP;
964                 goto out;
965         }
966
967         rtnl_lock();
968         err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
969         rtnl_unlock();
970
971  out:
972         if (params.vlan)
973                 dev_put(params.vlan);
974         cfg80211_put_dev(drv);
975         dev_put(dev);
976         return err;
977 }
978
979 static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
980 {
981         struct cfg80211_registered_device *drv;
982         int err;
983         struct net_device *dev;
984         u8 *mac_addr = NULL;
985
986         if (info->attrs[NL80211_ATTR_MAC])
987                 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
988
989         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
990         if (err)
991                 return err;
992
993         if (!drv->ops->del_station) {
994                 err = -EOPNOTSUPP;
995                 goto out;
996         }
997
998         rtnl_lock();
999         err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1000         rtnl_unlock();
1001
1002  out:
1003         cfg80211_put_dev(drv);
1004         dev_put(dev);
1005         return err;
1006 }
1007
1008 static struct genl_ops nl80211_ops[] = {
1009         {
1010                 .cmd = NL80211_CMD_GET_WIPHY,
1011                 .doit = nl80211_get_wiphy,
1012                 .dumpit = nl80211_dump_wiphy,
1013                 .policy = nl80211_policy,
1014                 /* can be retrieved by unprivileged users */
1015         },
1016         {
1017                 .cmd = NL80211_CMD_SET_WIPHY,
1018                 .doit = nl80211_set_wiphy,
1019                 .policy = nl80211_policy,
1020                 .flags = GENL_ADMIN_PERM,
1021         },
1022         {
1023                 .cmd = NL80211_CMD_GET_INTERFACE,
1024                 .doit = nl80211_get_interface,
1025                 .dumpit = nl80211_dump_interface,
1026                 .policy = nl80211_policy,
1027                 /* can be retrieved by unprivileged users */
1028         },
1029         {
1030                 .cmd = NL80211_CMD_SET_INTERFACE,
1031                 .doit = nl80211_set_interface,
1032                 .policy = nl80211_policy,
1033                 .flags = GENL_ADMIN_PERM,
1034         },
1035         {
1036                 .cmd = NL80211_CMD_NEW_INTERFACE,
1037                 .doit = nl80211_new_interface,
1038                 .policy = nl80211_policy,
1039                 .flags = GENL_ADMIN_PERM,
1040         },
1041         {
1042                 .cmd = NL80211_CMD_DEL_INTERFACE,
1043                 .doit = nl80211_del_interface,
1044                 .policy = nl80211_policy,
1045                 .flags = GENL_ADMIN_PERM,
1046         },
1047         {
1048                 .cmd = NL80211_CMD_GET_KEY,
1049                 .doit = nl80211_get_key,
1050                 .policy = nl80211_policy,
1051                 .flags = GENL_ADMIN_PERM,
1052         },
1053         {
1054                 .cmd = NL80211_CMD_SET_KEY,
1055                 .doit = nl80211_set_key,
1056                 .policy = nl80211_policy,
1057                 .flags = GENL_ADMIN_PERM,
1058         },
1059         {
1060                 .cmd = NL80211_CMD_NEW_KEY,
1061                 .doit = nl80211_new_key,
1062                 .policy = nl80211_policy,
1063                 .flags = GENL_ADMIN_PERM,
1064         },
1065         {
1066                 .cmd = NL80211_CMD_DEL_KEY,
1067                 .doit = nl80211_del_key,
1068                 .policy = nl80211_policy,
1069                 .flags = GENL_ADMIN_PERM,
1070         },
1071         {
1072                 .cmd = NL80211_CMD_SET_BEACON,
1073                 .policy = nl80211_policy,
1074                 .flags = GENL_ADMIN_PERM,
1075                 .doit = nl80211_addset_beacon,
1076         },
1077         {
1078                 .cmd = NL80211_CMD_NEW_BEACON,
1079                 .policy = nl80211_policy,
1080                 .flags = GENL_ADMIN_PERM,
1081                 .doit = nl80211_addset_beacon,
1082         },
1083         {
1084                 .cmd = NL80211_CMD_DEL_BEACON,
1085                 .policy = nl80211_policy,
1086                 .flags = GENL_ADMIN_PERM,
1087                 .doit = nl80211_del_beacon,
1088         },
1089         {
1090                 .cmd = NL80211_CMD_GET_STATION,
1091                 .doit = nl80211_get_station,
1092                 /* TODO: implement dumpit */
1093                 .policy = nl80211_policy,
1094                 .flags = GENL_ADMIN_PERM,
1095         },
1096         {
1097                 .cmd = NL80211_CMD_SET_STATION,
1098                 .doit = nl80211_set_station,
1099                 .policy = nl80211_policy,
1100                 .flags = GENL_ADMIN_PERM,
1101         },
1102         {
1103                 .cmd = NL80211_CMD_NEW_STATION,
1104                 .doit = nl80211_new_station,
1105                 .policy = nl80211_policy,
1106                 .flags = GENL_ADMIN_PERM,
1107         },
1108         {
1109                 .cmd = NL80211_CMD_DEL_STATION,
1110                 .doit = nl80211_del_station,
1111                 .policy = nl80211_policy,
1112                 .flags = GENL_ADMIN_PERM,
1113         },
1114 };
1115
1116 /* multicast groups */
1117 static struct genl_multicast_group nl80211_config_mcgrp = {
1118         .name = "config",
1119 };
1120
1121 /* notification functions */
1122
1123 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
1124 {
1125         struct sk_buff *msg;
1126
1127         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1128         if (!msg)
1129                 return;
1130
1131         if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
1132                 nlmsg_free(msg);
1133                 return;
1134         }
1135
1136         genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
1137 }
1138
1139 /* initialisation/exit functions */
1140
1141 int nl80211_init(void)
1142 {
1143         int err, i;
1144
1145         err = genl_register_family(&nl80211_fam);
1146         if (err)
1147                 return err;
1148
1149         for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
1150                 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
1151                 if (err)
1152                         goto err_out;
1153         }
1154
1155         err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
1156         if (err)
1157                 goto err_out;
1158
1159         return 0;
1160  err_out:
1161         genl_unregister_family(&nl80211_fam);
1162         return err;
1163 }
1164
1165 void nl80211_exit(void)
1166 {
1167         genl_unregister_family(&nl80211_fam);
1168 }