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