cfg80211/nl80211: station handling
[safe/jmp/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_get_station(struct sk_buff *skb, struct genl_info *info)
754 {
755         return -EOPNOTSUPP;
756 }
757
758 /*
759  * Get vlan interface making sure it is on the right wiphy.
760  */
761 static int get_vlan(struct nlattr *vlanattr,
762                     struct cfg80211_registered_device *rdev,
763                     struct net_device **vlan)
764 {
765         *vlan = NULL;
766
767         if (vlanattr) {
768                 *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
769                 if (!*vlan)
770                         return -ENODEV;
771                 if (!(*vlan)->ieee80211_ptr)
772                         return -EINVAL;
773                 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
774                         return -EINVAL;
775         }
776         return 0;
777 }
778
779 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
780 {
781         struct cfg80211_registered_device *drv;
782         int err;
783         struct net_device *dev;
784         struct station_parameters params;
785         u8 *mac_addr = NULL;
786
787         memset(&params, 0, sizeof(params));
788
789         params.listen_interval = -1;
790
791         if (info->attrs[NL80211_ATTR_STA_AID])
792                 return -EINVAL;
793
794         if (!info->attrs[NL80211_ATTR_MAC])
795                 return -EINVAL;
796
797         mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
798
799         if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
800                 params.supported_rates =
801                         nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
802                 params.supported_rates_len =
803                         nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
804         }
805
806         if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
807                 params.listen_interval =
808                     nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
809
810         if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
811                                 &params.station_flags))
812                 return -EINVAL;
813
814         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
815         if (err)
816                 return err;
817
818         err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
819         if (err)
820                 goto out;
821
822         if (!drv->ops->change_station) {
823                 err = -EOPNOTSUPP;
824                 goto out;
825         }
826
827         rtnl_lock();
828         err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
829         rtnl_unlock();
830
831  out:
832         if (params.vlan)
833                 dev_put(params.vlan);
834         cfg80211_put_dev(drv);
835         dev_put(dev);
836         return err;
837 }
838
839 static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
840 {
841         struct cfg80211_registered_device *drv;
842         int err;
843         struct net_device *dev;
844         struct station_parameters params;
845         u8 *mac_addr = NULL;
846
847         memset(&params, 0, sizeof(params));
848
849         if (!info->attrs[NL80211_ATTR_MAC])
850                 return -EINVAL;
851
852         if (!info->attrs[NL80211_ATTR_STA_AID])
853                 return -EINVAL;
854
855         if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
856                 return -EINVAL;
857
858         if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
859                 return -EINVAL;
860
861         mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
862         params.supported_rates =
863                 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
864         params.supported_rates_len =
865                 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
866         params.listen_interval =
867                 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
868         params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
869
870         if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
871                                 &params.station_flags))
872                 return -EINVAL;
873
874         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
875         if (err)
876                 return err;
877
878         err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
879         if (err)
880                 goto out;
881
882         if (!drv->ops->add_station) {
883                 err = -EOPNOTSUPP;
884                 goto out;
885         }
886
887         rtnl_lock();
888         err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
889         rtnl_unlock();
890
891  out:
892         if (params.vlan)
893                 dev_put(params.vlan);
894         cfg80211_put_dev(drv);
895         dev_put(dev);
896         return err;
897 }
898
899 static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
900 {
901         struct cfg80211_registered_device *drv;
902         int err;
903         struct net_device *dev;
904         u8 *mac_addr = NULL;
905
906         if (info->attrs[NL80211_ATTR_MAC])
907                 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
908
909         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
910         if (err)
911                 return err;
912
913         if (!drv->ops->del_station) {
914                 err = -EOPNOTSUPP;
915                 goto out;
916         }
917
918         rtnl_lock();
919         err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
920         rtnl_unlock();
921
922  out:
923         cfg80211_put_dev(drv);
924         dev_put(dev);
925         return err;
926 }
927
928 static struct genl_ops nl80211_ops[] = {
929         {
930                 .cmd = NL80211_CMD_GET_WIPHY,
931                 .doit = nl80211_get_wiphy,
932                 .dumpit = nl80211_dump_wiphy,
933                 .policy = nl80211_policy,
934                 /* can be retrieved by unprivileged users */
935         },
936         {
937                 .cmd = NL80211_CMD_SET_WIPHY,
938                 .doit = nl80211_set_wiphy,
939                 .policy = nl80211_policy,
940                 .flags = GENL_ADMIN_PERM,
941         },
942         {
943                 .cmd = NL80211_CMD_GET_INTERFACE,
944                 .doit = nl80211_get_interface,
945                 .dumpit = nl80211_dump_interface,
946                 .policy = nl80211_policy,
947                 /* can be retrieved by unprivileged users */
948         },
949         {
950                 .cmd = NL80211_CMD_SET_INTERFACE,
951                 .doit = nl80211_set_interface,
952                 .policy = nl80211_policy,
953                 .flags = GENL_ADMIN_PERM,
954         },
955         {
956                 .cmd = NL80211_CMD_NEW_INTERFACE,
957                 .doit = nl80211_new_interface,
958                 .policy = nl80211_policy,
959                 .flags = GENL_ADMIN_PERM,
960         },
961         {
962                 .cmd = NL80211_CMD_DEL_INTERFACE,
963                 .doit = nl80211_del_interface,
964                 .policy = nl80211_policy,
965                 .flags = GENL_ADMIN_PERM,
966         },
967         {
968                 .cmd = NL80211_CMD_GET_KEY,
969                 .doit = nl80211_get_key,
970                 .policy = nl80211_policy,
971                 .flags = GENL_ADMIN_PERM,
972         },
973         {
974                 .cmd = NL80211_CMD_SET_KEY,
975                 .doit = nl80211_set_key,
976                 .policy = nl80211_policy,
977                 .flags = GENL_ADMIN_PERM,
978         },
979         {
980                 .cmd = NL80211_CMD_NEW_KEY,
981                 .doit = nl80211_new_key,
982                 .policy = nl80211_policy,
983                 .flags = GENL_ADMIN_PERM,
984         },
985         {
986                 .cmd = NL80211_CMD_DEL_KEY,
987                 .doit = nl80211_del_key,
988                 .policy = nl80211_policy,
989                 .flags = GENL_ADMIN_PERM,
990         },
991         {
992                 .cmd = NL80211_CMD_SET_BEACON,
993                 .policy = nl80211_policy,
994                 .flags = GENL_ADMIN_PERM,
995                 .doit = nl80211_addset_beacon,
996         },
997         {
998                 .cmd = NL80211_CMD_NEW_BEACON,
999                 .policy = nl80211_policy,
1000                 .flags = GENL_ADMIN_PERM,
1001                 .doit = nl80211_addset_beacon,
1002         },
1003         {
1004                 .cmd = NL80211_CMD_DEL_BEACON,
1005                 .policy = nl80211_policy,
1006                 .flags = GENL_ADMIN_PERM,
1007                 .doit = nl80211_del_beacon,
1008         },
1009         {
1010                 .cmd = NL80211_CMD_GET_STATION,
1011                 .doit = nl80211_get_station,
1012                 /* TODO: implement dumpit */
1013                 .policy = nl80211_policy,
1014                 .flags = GENL_ADMIN_PERM,
1015         },
1016         {
1017                 .cmd = NL80211_CMD_SET_STATION,
1018                 .doit = nl80211_set_station,
1019                 .policy = nl80211_policy,
1020                 .flags = GENL_ADMIN_PERM,
1021         },
1022         {
1023                 .cmd = NL80211_CMD_NEW_STATION,
1024                 .doit = nl80211_new_station,
1025                 .policy = nl80211_policy,
1026                 .flags = GENL_ADMIN_PERM,
1027         },
1028         {
1029                 .cmd = NL80211_CMD_DEL_STATION,
1030                 .doit = nl80211_del_station,
1031                 .policy = nl80211_policy,
1032                 .flags = GENL_ADMIN_PERM,
1033         },
1034 };
1035
1036 /* multicast groups */
1037 static struct genl_multicast_group nl80211_config_mcgrp = {
1038         .name = "config",
1039 };
1040
1041 /* notification functions */
1042
1043 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
1044 {
1045         struct sk_buff *msg;
1046
1047         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1048         if (!msg)
1049                 return;
1050
1051         if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
1052                 nlmsg_free(msg);
1053                 return;
1054         }
1055
1056         genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
1057 }
1058
1059 /* initialisation/exit functions */
1060
1061 int nl80211_init(void)
1062 {
1063         int err, i;
1064
1065         err = genl_register_family(&nl80211_fam);
1066         if (err)
1067                 return err;
1068
1069         for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
1070                 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
1071                 if (err)
1072                         goto err_out;
1073         }
1074
1075         err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
1076         if (err)
1077                 goto err_out;
1078
1079         return 0;
1080  err_out:
1081         genl_unregister_family(&nl80211_fam);
1082         return err;
1083 }
1084
1085 void nl80211_exit(void)
1086 {
1087         genl_unregister_family(&nl80211_fam);
1088 }