306ae019ea816e8b622e287dcf786fff1bd882e5
[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 };
80
81 /* message building helper */
82 static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
83                                    int flags, u8 cmd)
84 {
85         /* since there is no private header just add the generic one */
86         return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
87 }
88
89 /* netlink command implementations */
90
91 static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
92                               struct cfg80211_registered_device *dev)
93 {
94         void *hdr;
95
96         hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
97         if (!hdr)
98                 return -1;
99
100         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
101         NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
102         return genlmsg_end(msg, hdr);
103
104  nla_put_failure:
105         return genlmsg_cancel(msg, hdr);
106 }
107
108 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
109 {
110         int idx = 0;
111         int start = cb->args[0];
112         struct cfg80211_registered_device *dev;
113
114         mutex_lock(&cfg80211_drv_mutex);
115         list_for_each_entry(dev, &cfg80211_drv_list, list) {
116                 if (++idx < start)
117                         continue;
118                 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
119                                        cb->nlh->nlmsg_seq, NLM_F_MULTI,
120                                        dev) < 0)
121                         break;
122         }
123         mutex_unlock(&cfg80211_drv_mutex);
124
125         cb->args[0] = idx;
126
127         return skb->len;
128 }
129
130 static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
131 {
132         struct sk_buff *msg;
133         struct cfg80211_registered_device *dev;
134
135         dev = cfg80211_get_dev_from_info(info);
136         if (IS_ERR(dev))
137                 return PTR_ERR(dev);
138
139         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
140         if (!msg)
141                 goto out_err;
142
143         if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
144                 goto out_free;
145
146         cfg80211_put_dev(dev);
147
148         return genlmsg_unicast(msg, info->snd_pid);
149
150  out_free:
151         nlmsg_free(msg);
152  out_err:
153         cfg80211_put_dev(dev);
154         return -ENOBUFS;
155 }
156
157 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
158 {
159         struct cfg80211_registered_device *rdev;
160         int result;
161
162         if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
163                 return -EINVAL;
164
165         rdev = cfg80211_get_dev_from_info(info);
166         if (IS_ERR(rdev))
167                 return PTR_ERR(rdev);
168
169         result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
170
171         cfg80211_put_dev(rdev);
172         return result;
173 }
174
175
176 static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
177                               struct net_device *dev)
178 {
179         void *hdr;
180
181         hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
182         if (!hdr)
183                 return -1;
184
185         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
186         NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
187         /* TODO: interface type */
188         return genlmsg_end(msg, hdr);
189
190  nla_put_failure:
191         return genlmsg_cancel(msg, hdr);
192 }
193
194 static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
195 {
196         int wp_idx = 0;
197         int if_idx = 0;
198         int wp_start = cb->args[0];
199         int if_start = cb->args[1];
200         struct cfg80211_registered_device *dev;
201         struct wireless_dev *wdev;
202
203         mutex_lock(&cfg80211_drv_mutex);
204         list_for_each_entry(dev, &cfg80211_drv_list, list) {
205                 if (++wp_idx < wp_start)
206                         continue;
207                 if_idx = 0;
208
209                 mutex_lock(&dev->devlist_mtx);
210                 list_for_each_entry(wdev, &dev->netdev_list, list) {
211                         if (++if_idx < if_start)
212                                 continue;
213                         if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
214                                                cb->nlh->nlmsg_seq, NLM_F_MULTI,
215                                                wdev->netdev) < 0)
216                                 break;
217                 }
218                 mutex_unlock(&dev->devlist_mtx);
219         }
220         mutex_unlock(&cfg80211_drv_mutex);
221
222         cb->args[0] = wp_idx;
223         cb->args[1] = if_idx;
224
225         return skb->len;
226 }
227
228 static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
229 {
230         struct sk_buff *msg;
231         struct cfg80211_registered_device *dev;
232         struct net_device *netdev;
233         int err;
234
235         err = get_drv_dev_by_info_ifindex(info, &dev, &netdev);
236         if (err)
237                 return err;
238
239         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
240         if (!msg)
241                 goto out_err;
242
243         if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
244                 goto out_free;
245
246         dev_put(netdev);
247         cfg80211_put_dev(dev);
248
249         return genlmsg_unicast(msg, info->snd_pid);
250
251  out_free:
252         nlmsg_free(msg);
253  out_err:
254         dev_put(netdev);
255         cfg80211_put_dev(dev);
256         return -ENOBUFS;
257 }
258
259 static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
260 {
261         struct cfg80211_registered_device *drv;
262         int err, ifindex;
263         enum nl80211_iftype type;
264         struct net_device *dev;
265
266         if (info->attrs[NL80211_ATTR_IFTYPE]) {
267                 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
268                 if (type > NL80211_IFTYPE_MAX)
269                         return -EINVAL;
270         } else
271                 return -EINVAL;
272
273         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
274         if (err)
275                 return err;
276         ifindex = dev->ifindex;
277         dev_put(dev);
278
279         if (!drv->ops->change_virtual_intf) {
280                 err = -EOPNOTSUPP;
281                 goto unlock;
282         }
283
284         rtnl_lock();
285         err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
286         rtnl_unlock();
287
288  unlock:
289         cfg80211_put_dev(drv);
290         return err;
291 }
292
293 static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
294 {
295         struct cfg80211_registered_device *drv;
296         int err;
297         enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
298
299         if (!info->attrs[NL80211_ATTR_IFNAME])
300                 return -EINVAL;
301
302         if (info->attrs[NL80211_ATTR_IFTYPE]) {
303                 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
304                 if (type > NL80211_IFTYPE_MAX)
305                         return -EINVAL;
306         }
307
308         drv = cfg80211_get_dev_from_info(info);
309         if (IS_ERR(drv))
310                 return PTR_ERR(drv);
311
312         if (!drv->ops->add_virtual_intf) {
313                 err = -EOPNOTSUPP;
314                 goto unlock;
315         }
316
317         rtnl_lock();
318         err = drv->ops->add_virtual_intf(&drv->wiphy,
319                 nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
320         rtnl_unlock();
321
322  unlock:
323         cfg80211_put_dev(drv);
324         return err;
325 }
326
327 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
328 {
329         struct cfg80211_registered_device *drv;
330         int ifindex, err;
331         struct net_device *dev;
332
333         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
334         if (err)
335                 return err;
336         ifindex = dev->ifindex;
337         dev_put(dev);
338
339         if (!drv->ops->del_virtual_intf) {
340                 err = -EOPNOTSUPP;
341                 goto out;
342         }
343
344         rtnl_lock();
345         err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
346         rtnl_unlock();
347
348  out:
349         cfg80211_put_dev(drv);
350         return err;
351 }
352
353 struct get_key_cookie {
354         struct sk_buff *msg;
355         int error;
356 };
357
358 static void get_key_callback(void *c, struct key_params *params)
359 {
360         struct get_key_cookie *cookie = c;
361
362         if (params->key)
363                 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
364                         params->key_len, params->key);
365
366         if (params->seq)
367                 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
368                         params->seq_len, params->seq);
369
370         if (params->cipher)
371                 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
372                             params->cipher);
373
374         return;
375  nla_put_failure:
376         cookie->error = 1;
377 }
378
379 static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
380 {
381         struct cfg80211_registered_device *drv;
382         int err;
383         struct net_device *dev;
384         u8 key_idx = 0;
385         u8 *mac_addr = NULL;
386         struct get_key_cookie cookie = {
387                 .error = 0,
388         };
389         void *hdr;
390         struct sk_buff *msg;
391
392         if (info->attrs[NL80211_ATTR_KEY_IDX])
393                 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
394
395         if (key_idx > 3)
396                 return -EINVAL;
397
398         if (info->attrs[NL80211_ATTR_MAC])
399                 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
400
401         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
402         if (err)
403                 return err;
404
405         if (!drv->ops->get_key) {
406                 err = -EOPNOTSUPP;
407                 goto out;
408         }
409
410         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
411         if (!msg) {
412                 err = -ENOMEM;
413                 goto out;
414         }
415
416         hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
417                              NL80211_CMD_NEW_KEY);
418
419         if (IS_ERR(hdr)) {
420                 err = PTR_ERR(hdr);
421                 goto out;
422         }
423
424         cookie.msg = msg;
425
426         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
427         NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
428         if (mac_addr)
429                 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
430
431         rtnl_lock();
432         err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
433                                 &cookie, get_key_callback);
434         rtnl_unlock();
435
436         if (err)
437                 goto out;
438
439         if (cookie.error)
440                 goto nla_put_failure;
441
442         genlmsg_end(msg, hdr);
443         err = genlmsg_unicast(msg, info->snd_pid);
444         goto out;
445
446  nla_put_failure:
447         err = -ENOBUFS;
448         nlmsg_free(msg);
449  out:
450         cfg80211_put_dev(drv);
451         dev_put(dev);
452         return err;
453 }
454
455 static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
456 {
457         struct cfg80211_registered_device *drv;
458         int err;
459         struct net_device *dev;
460         u8 key_idx;
461
462         if (!info->attrs[NL80211_ATTR_KEY_IDX])
463                 return -EINVAL;
464
465         key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
466
467         if (key_idx > 3)
468                 return -EINVAL;
469
470         /* currently only support setting default key */
471         if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
472                 return -EINVAL;
473
474         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
475         if (err)
476                 return err;
477
478         if (!drv->ops->set_default_key) {
479                 err = -EOPNOTSUPP;
480                 goto out;
481         }
482
483         rtnl_lock();
484         err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
485         rtnl_unlock();
486
487  out:
488         cfg80211_put_dev(drv);
489         dev_put(dev);
490         return err;
491 }
492
493 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
494 {
495         struct cfg80211_registered_device *drv;
496         int err;
497         struct net_device *dev;
498         struct key_params params;
499         u8 key_idx = 0;
500         u8 *mac_addr = NULL;
501
502         memset(&params, 0, sizeof(params));
503
504         if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
505                 return -EINVAL;
506
507         if (info->attrs[NL80211_ATTR_KEY_DATA]) {
508                 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
509                 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
510         }
511
512         if (info->attrs[NL80211_ATTR_KEY_IDX])
513                 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
514
515         params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
516
517         if (info->attrs[NL80211_ATTR_MAC])
518                 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
519
520         if (key_idx > 3)
521                 return -EINVAL;
522
523         /*
524          * Disallow pairwise keys with non-zero index unless it's WEP
525          * (because current deployments use pairwise WEP keys with
526          * non-zero indizes but 802.11i clearly specifies to use zero)
527          */
528         if (mac_addr && key_idx &&
529             params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
530             params.cipher != WLAN_CIPHER_SUITE_WEP104)
531                 return -EINVAL;
532
533         /* TODO: add definitions for the lengths to linux/ieee80211.h */
534         switch (params.cipher) {
535         case WLAN_CIPHER_SUITE_WEP40:
536                 if (params.key_len != 5)
537                         return -EINVAL;
538                 break;
539         case WLAN_CIPHER_SUITE_TKIP:
540                 if (params.key_len != 32)
541                         return -EINVAL;
542                 break;
543         case WLAN_CIPHER_SUITE_CCMP:
544                 if (params.key_len != 16)
545                         return -EINVAL;
546                 break;
547         case WLAN_CIPHER_SUITE_WEP104:
548                 if (params.key_len != 13)
549                         return -EINVAL;
550                 break;
551         default:
552                 return -EINVAL;
553         }
554
555         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
556         if (err)
557                 return err;
558
559         if (!drv->ops->add_key) {
560                 err = -EOPNOTSUPP;
561                 goto out;
562         }
563
564         rtnl_lock();
565         err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
566         rtnl_unlock();
567
568  out:
569         cfg80211_put_dev(drv);
570         dev_put(dev);
571         return err;
572 }
573
574 static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
575 {
576         struct cfg80211_registered_device *drv;
577         int err;
578         struct net_device *dev;
579         u8 key_idx = 0;
580         u8 *mac_addr = NULL;
581
582         if (info->attrs[NL80211_ATTR_KEY_IDX])
583                 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
584
585         if (key_idx > 3)
586                 return -EINVAL;
587
588         if (info->attrs[NL80211_ATTR_MAC])
589                 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
590
591         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
592         if (err)
593                 return err;
594
595         if (!drv->ops->del_key) {
596                 err = -EOPNOTSUPP;
597                 goto out;
598         }
599
600         rtnl_lock();
601         err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
602         rtnl_unlock();
603
604  out:
605         cfg80211_put_dev(drv);
606         dev_put(dev);
607         return err;
608 }
609
610 static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
611 {
612         int (*call)(struct wiphy *wiphy, struct net_device *dev,
613                     struct beacon_parameters *info);
614         struct cfg80211_registered_device *drv;
615         int err;
616         struct net_device *dev;
617         struct beacon_parameters params;
618         int haveinfo = 0;
619
620         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
621         if (err)
622                 return err;
623
624         switch (info->genlhdr->cmd) {
625         case NL80211_CMD_NEW_BEACON:
626                 /* these are required for NEW_BEACON */
627                 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
628                     !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
629                     !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
630                         err = -EINVAL;
631                         goto out;
632                 }
633
634                 call = drv->ops->add_beacon;
635                 break;
636         case NL80211_CMD_SET_BEACON:
637                 call = drv->ops->set_beacon;
638                 break;
639         default:
640                 WARN_ON(1);
641                 err = -EOPNOTSUPP;
642                 goto out;
643         }
644
645         if (!call) {
646                 err = -EOPNOTSUPP;
647                 goto out;
648         }
649
650         memset(&params, 0, sizeof(params));
651
652         if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
653                 params.interval =
654                     nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
655                 haveinfo = 1;
656         }
657
658         if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
659                 params.dtim_period =
660                     nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
661                 haveinfo = 1;
662         }
663
664         if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
665                 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
666                 params.head_len =
667                     nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
668                 haveinfo = 1;
669         }
670
671         if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
672                 params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
673                 params.tail_len =
674                     nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
675                 haveinfo = 1;
676         }
677
678         if (!haveinfo) {
679                 err = -EINVAL;
680                 goto out;
681         }
682
683         rtnl_lock();
684         err = call(&drv->wiphy, dev, &params);
685         rtnl_unlock();
686
687  out:
688         cfg80211_put_dev(drv);
689         dev_put(dev);
690         return err;
691 }
692
693 static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
694 {
695         struct cfg80211_registered_device *drv;
696         int err;
697         struct net_device *dev;
698
699         err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
700         if (err)
701                 return err;
702
703         if (!drv->ops->del_beacon) {
704                 err = -EOPNOTSUPP;
705                 goto out;
706         }
707
708         rtnl_lock();
709         err = drv->ops->del_beacon(&drv->wiphy, dev);
710         rtnl_unlock();
711
712  out:
713         cfg80211_put_dev(drv);
714         dev_put(dev);
715         return err;
716 }
717
718 static struct genl_ops nl80211_ops[] = {
719         {
720                 .cmd = NL80211_CMD_GET_WIPHY,
721                 .doit = nl80211_get_wiphy,
722                 .dumpit = nl80211_dump_wiphy,
723                 .policy = nl80211_policy,
724                 /* can be retrieved by unprivileged users */
725         },
726         {
727                 .cmd = NL80211_CMD_SET_WIPHY,
728                 .doit = nl80211_set_wiphy,
729                 .policy = nl80211_policy,
730                 .flags = GENL_ADMIN_PERM,
731         },
732         {
733                 .cmd = NL80211_CMD_GET_INTERFACE,
734                 .doit = nl80211_get_interface,
735                 .dumpit = nl80211_dump_interface,
736                 .policy = nl80211_policy,
737                 /* can be retrieved by unprivileged users */
738         },
739         {
740                 .cmd = NL80211_CMD_SET_INTERFACE,
741                 .doit = nl80211_set_interface,
742                 .policy = nl80211_policy,
743                 .flags = GENL_ADMIN_PERM,
744         },
745         {
746                 .cmd = NL80211_CMD_NEW_INTERFACE,
747                 .doit = nl80211_new_interface,
748                 .policy = nl80211_policy,
749                 .flags = GENL_ADMIN_PERM,
750         },
751         {
752                 .cmd = NL80211_CMD_DEL_INTERFACE,
753                 .doit = nl80211_del_interface,
754                 .policy = nl80211_policy,
755                 .flags = GENL_ADMIN_PERM,
756         },
757         {
758                 .cmd = NL80211_CMD_GET_KEY,
759                 .doit = nl80211_get_key,
760                 .policy = nl80211_policy,
761                 .flags = GENL_ADMIN_PERM,
762         },
763         {
764                 .cmd = NL80211_CMD_SET_KEY,
765                 .doit = nl80211_set_key,
766                 .policy = nl80211_policy,
767                 .flags = GENL_ADMIN_PERM,
768         },
769         {
770                 .cmd = NL80211_CMD_NEW_KEY,
771                 .doit = nl80211_new_key,
772                 .policy = nl80211_policy,
773                 .flags = GENL_ADMIN_PERM,
774         },
775         {
776                 .cmd = NL80211_CMD_DEL_KEY,
777                 .doit = nl80211_del_key,
778                 .policy = nl80211_policy,
779                 .flags = GENL_ADMIN_PERM,
780         },
781         {
782                 .cmd = NL80211_CMD_SET_BEACON,
783                 .policy = nl80211_policy,
784                 .flags = GENL_ADMIN_PERM,
785                 .doit = nl80211_addset_beacon,
786         },
787         {
788                 .cmd = NL80211_CMD_NEW_BEACON,
789                 .policy = nl80211_policy,
790                 .flags = GENL_ADMIN_PERM,
791                 .doit = nl80211_addset_beacon,
792         },
793         {
794                 .cmd = NL80211_CMD_DEL_BEACON,
795                 .policy = nl80211_policy,
796                 .flags = GENL_ADMIN_PERM,
797                 .doit = nl80211_del_beacon,
798         },
799 };
800
801 /* multicast groups */
802 static struct genl_multicast_group nl80211_config_mcgrp = {
803         .name = "config",
804 };
805
806 /* notification functions */
807
808 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
809 {
810         struct sk_buff *msg;
811
812         msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
813         if (!msg)
814                 return;
815
816         if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
817                 nlmsg_free(msg);
818                 return;
819         }
820
821         genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
822 }
823
824 /* initialisation/exit functions */
825
826 int nl80211_init(void)
827 {
828         int err, i;
829
830         err = genl_register_family(&nl80211_fam);
831         if (err)
832                 return err;
833
834         for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
835                 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
836                 if (err)
837                         goto err_out;
838         }
839
840         err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
841         if (err)
842                 goto err_out;
843
844         return 0;
845  err_out:
846         genl_unregister_family(&nl80211_fam);
847         return err;
848 }
849
850 void nl80211_exit(void)
851 {
852         genl_unregister_family(&nl80211_fam);
853 }