2 * This is the new netlink-based wireless configuration interface.
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
8 #include <linux/module.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>
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,
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)
38 if (!info->attrs[NL80211_ATTR_IFINDEX])
41 ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
42 *dev = dev_get_by_index(&init_net, ifindex);
46 *drv = cfg80211_get_dev_from_ifindex(ifindex);
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 },
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 },
65 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
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 },
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 },
81 /* message building helper */
82 static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
85 /* since there is no private header just add the generic one */
86 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
89 /* netlink command implementations */
91 static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
92 struct cfg80211_registered_device *dev)
96 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
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);
105 return genlmsg_cancel(msg, hdr);
108 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
111 int start = cb->args[0];
112 struct cfg80211_registered_device *dev;
114 mutex_lock(&cfg80211_drv_mutex);
115 list_for_each_entry(dev, &cfg80211_drv_list, list) {
118 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
119 cb->nlh->nlmsg_seq, NLM_F_MULTI,
123 mutex_unlock(&cfg80211_drv_mutex);
130 static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
133 struct cfg80211_registered_device *dev;
135 dev = cfg80211_get_dev_from_info(info);
139 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
143 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
146 cfg80211_put_dev(dev);
148 return genlmsg_unicast(msg, info->snd_pid);
153 cfg80211_put_dev(dev);
157 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
159 struct cfg80211_registered_device *rdev;
162 if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
165 rdev = cfg80211_get_dev_from_info(info);
167 return PTR_ERR(rdev);
169 result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
171 cfg80211_put_dev(rdev);
176 static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
177 struct net_device *dev)
181 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
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);
191 return genlmsg_cancel(msg, hdr);
194 static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
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;
203 mutex_lock(&cfg80211_drv_mutex);
204 list_for_each_entry(dev, &cfg80211_drv_list, list) {
205 if (++wp_idx < wp_start)
209 mutex_lock(&dev->devlist_mtx);
210 list_for_each_entry(wdev, &dev->netdev_list, list) {
211 if (++if_idx < if_start)
213 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
214 cb->nlh->nlmsg_seq, NLM_F_MULTI,
218 mutex_unlock(&dev->devlist_mtx);
220 mutex_unlock(&cfg80211_drv_mutex);
222 cb->args[0] = wp_idx;
223 cb->args[1] = if_idx;
228 static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
231 struct cfg80211_registered_device *dev;
232 struct net_device *netdev;
235 err = get_drv_dev_by_info_ifindex(info, &dev, &netdev);
239 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
243 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
247 cfg80211_put_dev(dev);
249 return genlmsg_unicast(msg, info->snd_pid);
255 cfg80211_put_dev(dev);
259 static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
261 struct cfg80211_registered_device *drv;
263 enum nl80211_iftype type;
264 struct net_device *dev;
266 if (info->attrs[NL80211_ATTR_IFTYPE]) {
267 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
268 if (type > NL80211_IFTYPE_MAX)
273 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
276 ifindex = dev->ifindex;
279 if (!drv->ops->change_virtual_intf) {
285 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
289 cfg80211_put_dev(drv);
293 static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
295 struct cfg80211_registered_device *drv;
297 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
299 if (!info->attrs[NL80211_ATTR_IFNAME])
302 if (info->attrs[NL80211_ATTR_IFTYPE]) {
303 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
304 if (type > NL80211_IFTYPE_MAX)
308 drv = cfg80211_get_dev_from_info(info);
312 if (!drv->ops->add_virtual_intf) {
318 err = drv->ops->add_virtual_intf(&drv->wiphy,
319 nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
323 cfg80211_put_dev(drv);
327 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
329 struct cfg80211_registered_device *drv;
331 struct net_device *dev;
333 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
336 ifindex = dev->ifindex;
339 if (!drv->ops->del_virtual_intf) {
345 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
349 cfg80211_put_dev(drv);
353 struct get_key_cookie {
358 static void get_key_callback(void *c, struct key_params *params)
360 struct get_key_cookie *cookie = c;
363 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
364 params->key_len, params->key);
367 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
368 params->seq_len, params->seq);
371 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
379 static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
381 struct cfg80211_registered_device *drv;
383 struct net_device *dev;
386 struct get_key_cookie cookie = {
392 if (info->attrs[NL80211_ATTR_KEY_IDX])
393 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
398 if (info->attrs[NL80211_ATTR_MAC])
399 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
401 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
405 if (!drv->ops->get_key) {
410 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
416 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
417 NL80211_CMD_NEW_KEY);
426 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
427 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
429 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
432 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
433 &cookie, get_key_callback);
440 goto nla_put_failure;
442 genlmsg_end(msg, hdr);
443 err = genlmsg_unicast(msg, info->snd_pid);
450 cfg80211_put_dev(drv);
455 static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
457 struct cfg80211_registered_device *drv;
459 struct net_device *dev;
462 if (!info->attrs[NL80211_ATTR_KEY_IDX])
465 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
470 /* currently only support setting default key */
471 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
474 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
478 if (!drv->ops->set_default_key) {
484 err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
488 cfg80211_put_dev(drv);
493 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
495 struct cfg80211_registered_device *drv;
497 struct net_device *dev;
498 struct key_params params;
502 memset(¶ms, 0, sizeof(params));
504 if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
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]);
512 if (info->attrs[NL80211_ATTR_KEY_IDX])
513 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
515 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
517 if (info->attrs[NL80211_ATTR_MAC])
518 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
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)
528 if (mac_addr && key_idx &&
529 params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
530 params.cipher != WLAN_CIPHER_SUITE_WEP104)
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)
539 case WLAN_CIPHER_SUITE_TKIP:
540 if (params.key_len != 32)
543 case WLAN_CIPHER_SUITE_CCMP:
544 if (params.key_len != 16)
547 case WLAN_CIPHER_SUITE_WEP104:
548 if (params.key_len != 13)
555 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
559 if (!drv->ops->add_key) {
565 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms);
569 cfg80211_put_dev(drv);
574 static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
576 struct cfg80211_registered_device *drv;
578 struct net_device *dev;
582 if (info->attrs[NL80211_ATTR_KEY_IDX])
583 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
588 if (info->attrs[NL80211_ATTR_MAC])
589 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
591 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
595 if (!drv->ops->del_key) {
601 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
605 cfg80211_put_dev(drv);
610 static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
612 int (*call)(struct wiphy *wiphy, struct net_device *dev,
613 struct beacon_parameters *info);
614 struct cfg80211_registered_device *drv;
616 struct net_device *dev;
617 struct beacon_parameters params;
620 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
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]) {
634 call = drv->ops->add_beacon;
636 case NL80211_CMD_SET_BEACON:
637 call = drv->ops->set_beacon;
650 memset(¶ms, 0, sizeof(params));
652 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
654 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
658 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
660 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
664 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
665 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
667 nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
671 if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
672 params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
674 nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
684 err = call(&drv->wiphy, dev, ¶ms);
688 cfg80211_put_dev(drv);
693 static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
695 struct cfg80211_registered_device *drv;
697 struct net_device *dev;
699 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
703 if (!drv->ops->del_beacon) {
709 err = drv->ops->del_beacon(&drv->wiphy, dev);
713 cfg80211_put_dev(drv);
718 static struct genl_ops nl80211_ops[] = {
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 */
727 .cmd = NL80211_CMD_SET_WIPHY,
728 .doit = nl80211_set_wiphy,
729 .policy = nl80211_policy,
730 .flags = GENL_ADMIN_PERM,
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 */
740 .cmd = NL80211_CMD_SET_INTERFACE,
741 .doit = nl80211_set_interface,
742 .policy = nl80211_policy,
743 .flags = GENL_ADMIN_PERM,
746 .cmd = NL80211_CMD_NEW_INTERFACE,
747 .doit = nl80211_new_interface,
748 .policy = nl80211_policy,
749 .flags = GENL_ADMIN_PERM,
752 .cmd = NL80211_CMD_DEL_INTERFACE,
753 .doit = nl80211_del_interface,
754 .policy = nl80211_policy,
755 .flags = GENL_ADMIN_PERM,
758 .cmd = NL80211_CMD_GET_KEY,
759 .doit = nl80211_get_key,
760 .policy = nl80211_policy,
761 .flags = GENL_ADMIN_PERM,
764 .cmd = NL80211_CMD_SET_KEY,
765 .doit = nl80211_set_key,
766 .policy = nl80211_policy,
767 .flags = GENL_ADMIN_PERM,
770 .cmd = NL80211_CMD_NEW_KEY,
771 .doit = nl80211_new_key,
772 .policy = nl80211_policy,
773 .flags = GENL_ADMIN_PERM,
776 .cmd = NL80211_CMD_DEL_KEY,
777 .doit = nl80211_del_key,
778 .policy = nl80211_policy,
779 .flags = GENL_ADMIN_PERM,
782 .cmd = NL80211_CMD_SET_BEACON,
783 .policy = nl80211_policy,
784 .flags = GENL_ADMIN_PERM,
785 .doit = nl80211_addset_beacon,
788 .cmd = NL80211_CMD_NEW_BEACON,
789 .policy = nl80211_policy,
790 .flags = GENL_ADMIN_PERM,
791 .doit = nl80211_addset_beacon,
794 .cmd = NL80211_CMD_DEL_BEACON,
795 .policy = nl80211_policy,
796 .flags = GENL_ADMIN_PERM,
797 .doit = nl80211_del_beacon,
801 /* multicast groups */
802 static struct genl_multicast_group nl80211_config_mcgrp = {
806 /* notification functions */
808 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
812 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
816 if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
821 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
824 /* initialisation/exit functions */
826 int nl80211_init(void)
830 err = genl_register_family(&nl80211_fam);
834 for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
835 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
840 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
846 genl_unregister_family(&nl80211_fam);
850 void nl80211_exit(void)
852 genl_unregister_family(&nl80211_fam);