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 nlattr **attrs,
33 struct cfg80211_registered_device **drv,
34 struct net_device **dev)
38 if (!attrs[NL80211_ATTR_IFINDEX])
41 ifindex = nla_get_u32(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 },
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_PLINK_ACTION] = { .type = NLA_U8 },
85 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
86 [NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
87 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
88 .len = IEEE80211_MAX_MESH_ID_LEN },
89 [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
91 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
92 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
93 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
96 /* message building helper */
97 static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
100 /* since there is no private header just add the generic one */
101 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
104 /* netlink command implementations */
106 static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
107 struct cfg80211_registered_device *dev)
110 struct nlattr *nl_bands, *nl_band;
111 struct nlattr *nl_freqs, *nl_freq;
112 struct nlattr *nl_rates, *nl_rate;
113 enum ieee80211_band band;
114 struct ieee80211_channel *chan;
115 struct ieee80211_rate *rate;
118 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
122 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
123 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
125 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
127 goto nla_put_failure;
129 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
130 if (!dev->wiphy.bands[band])
133 nl_band = nla_nest_start(msg, band);
135 goto nla_put_failure;
137 /* add frequencies */
138 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
140 goto nla_put_failure;
142 for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
143 nl_freq = nla_nest_start(msg, i);
145 goto nla_put_failure;
147 chan = &dev->wiphy.bands[band]->channels[i];
148 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
151 if (chan->flags & IEEE80211_CHAN_DISABLED)
152 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
153 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
154 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
155 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
156 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
157 if (chan->flags & IEEE80211_CHAN_RADAR)
158 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
160 nla_nest_end(msg, nl_freq);
163 nla_nest_end(msg, nl_freqs);
166 nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
168 goto nla_put_failure;
170 for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
171 nl_rate = nla_nest_start(msg, i);
173 goto nla_put_failure;
175 rate = &dev->wiphy.bands[band]->bitrates[i];
176 NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
178 if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
180 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
182 nla_nest_end(msg, nl_rate);
185 nla_nest_end(msg, nl_rates);
187 nla_nest_end(msg, nl_band);
189 nla_nest_end(msg, nl_bands);
191 return genlmsg_end(msg, hdr);
194 genlmsg_cancel(msg, hdr);
198 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
201 int start = cb->args[0];
202 struct cfg80211_registered_device *dev;
204 mutex_lock(&cfg80211_drv_mutex);
205 list_for_each_entry(dev, &cfg80211_drv_list, list) {
208 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
209 cb->nlh->nlmsg_seq, NLM_F_MULTI,
215 mutex_unlock(&cfg80211_drv_mutex);
222 static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
225 struct cfg80211_registered_device *dev;
227 dev = cfg80211_get_dev_from_info(info);
231 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
235 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
238 cfg80211_put_dev(dev);
240 return genlmsg_unicast(msg, info->snd_pid);
245 cfg80211_put_dev(dev);
249 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
251 struct cfg80211_registered_device *rdev;
254 if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
257 rdev = cfg80211_get_dev_from_info(info);
259 return PTR_ERR(rdev);
261 result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
263 cfg80211_put_dev(rdev);
268 static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
269 struct net_device *dev)
273 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
277 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
278 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
279 /* TODO: interface type */
280 return genlmsg_end(msg, hdr);
283 genlmsg_cancel(msg, hdr);
287 static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
291 int wp_start = cb->args[0];
292 int if_start = cb->args[1];
293 struct cfg80211_registered_device *dev;
294 struct wireless_dev *wdev;
296 mutex_lock(&cfg80211_drv_mutex);
297 list_for_each_entry(dev, &cfg80211_drv_list, list) {
298 if (wp_idx < wp_start) {
304 mutex_lock(&dev->devlist_mtx);
305 list_for_each_entry(wdev, &dev->netdev_list, list) {
306 if (if_idx < if_start) {
310 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
311 cb->nlh->nlmsg_seq, NLM_F_MULTI,
313 mutex_unlock(&dev->devlist_mtx);
318 mutex_unlock(&dev->devlist_mtx);
323 mutex_unlock(&cfg80211_drv_mutex);
325 cb->args[0] = wp_idx;
326 cb->args[1] = if_idx;
331 static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
334 struct cfg80211_registered_device *dev;
335 struct net_device *netdev;
338 err = get_drv_dev_by_info_ifindex(info->attrs, &dev, &netdev);
342 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
346 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
350 cfg80211_put_dev(dev);
352 return genlmsg_unicast(msg, info->snd_pid);
358 cfg80211_put_dev(dev);
362 static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
363 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
364 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
365 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
366 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
367 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
370 static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
372 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
380 if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
381 nla, mntr_flags_policy))
384 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
386 *mntrflags |= (1<<flag);
391 static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
393 struct cfg80211_registered_device *drv;
394 struct vif_params params;
396 enum nl80211_iftype type;
397 struct net_device *dev;
400 memset(¶ms, 0, sizeof(params));
402 if (info->attrs[NL80211_ATTR_IFTYPE]) {
403 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
404 if (type > NL80211_IFTYPE_MAX)
409 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
412 ifindex = dev->ifindex;
415 if (!drv->ops->change_virtual_intf) {
420 if (type == NL80211_IFTYPE_MESH_POINT &&
421 info->attrs[NL80211_ATTR_MESH_ID]) {
422 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
423 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
427 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
428 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
430 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
431 type, err ? NULL : &flags, ¶ms);
435 cfg80211_put_dev(drv);
439 static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
441 struct cfg80211_registered_device *drv;
442 struct vif_params params;
444 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
447 memset(¶ms, 0, sizeof(params));
449 if (!info->attrs[NL80211_ATTR_IFNAME])
452 if (info->attrs[NL80211_ATTR_IFTYPE]) {
453 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
454 if (type > NL80211_IFTYPE_MAX)
458 drv = cfg80211_get_dev_from_info(info);
462 if (!drv->ops->add_virtual_intf) {
467 if (type == NL80211_IFTYPE_MESH_POINT &&
468 info->attrs[NL80211_ATTR_MESH_ID]) {
469 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
470 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
474 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
475 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
477 err = drv->ops->add_virtual_intf(&drv->wiphy,
478 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
479 type, err ? NULL : &flags, ¶ms);
484 cfg80211_put_dev(drv);
488 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
490 struct cfg80211_registered_device *drv;
492 struct net_device *dev;
494 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
497 ifindex = dev->ifindex;
500 if (!drv->ops->del_virtual_intf) {
506 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
510 cfg80211_put_dev(drv);
514 struct get_key_cookie {
519 static void get_key_callback(void *c, struct key_params *params)
521 struct get_key_cookie *cookie = c;
524 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
525 params->key_len, params->key);
528 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
529 params->seq_len, params->seq);
532 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
540 static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
542 struct cfg80211_registered_device *drv;
544 struct net_device *dev;
547 struct get_key_cookie cookie = {
553 if (info->attrs[NL80211_ATTR_KEY_IDX])
554 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
559 if (info->attrs[NL80211_ATTR_MAC])
560 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
562 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
566 if (!drv->ops->get_key) {
571 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
577 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
578 NL80211_CMD_NEW_KEY);
587 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
588 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
590 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
593 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
594 &cookie, get_key_callback);
601 goto nla_put_failure;
603 genlmsg_end(msg, hdr);
604 err = genlmsg_unicast(msg, info->snd_pid);
611 cfg80211_put_dev(drv);
616 static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
618 struct cfg80211_registered_device *drv;
620 struct net_device *dev;
623 if (!info->attrs[NL80211_ATTR_KEY_IDX])
626 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
631 /* currently only support setting default key */
632 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
635 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
639 if (!drv->ops->set_default_key) {
645 err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
649 cfg80211_put_dev(drv);
654 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
656 struct cfg80211_registered_device *drv;
658 struct net_device *dev;
659 struct key_params params;
663 memset(¶ms, 0, sizeof(params));
665 if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
668 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
669 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
670 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
673 if (info->attrs[NL80211_ATTR_KEY_IDX])
674 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
676 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
678 if (info->attrs[NL80211_ATTR_MAC])
679 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
685 * Disallow pairwise keys with non-zero index unless it's WEP
686 * (because current deployments use pairwise WEP keys with
687 * non-zero indizes but 802.11i clearly specifies to use zero)
689 if (mac_addr && key_idx &&
690 params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
691 params.cipher != WLAN_CIPHER_SUITE_WEP104)
694 /* TODO: add definitions for the lengths to linux/ieee80211.h */
695 switch (params.cipher) {
696 case WLAN_CIPHER_SUITE_WEP40:
697 if (params.key_len != 5)
700 case WLAN_CIPHER_SUITE_TKIP:
701 if (params.key_len != 32)
704 case WLAN_CIPHER_SUITE_CCMP:
705 if (params.key_len != 16)
708 case WLAN_CIPHER_SUITE_WEP104:
709 if (params.key_len != 13)
716 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
720 if (!drv->ops->add_key) {
726 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms);
730 cfg80211_put_dev(drv);
735 static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
737 struct cfg80211_registered_device *drv;
739 struct net_device *dev;
743 if (info->attrs[NL80211_ATTR_KEY_IDX])
744 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
749 if (info->attrs[NL80211_ATTR_MAC])
750 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
752 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
756 if (!drv->ops->del_key) {
762 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
766 cfg80211_put_dev(drv);
771 static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
773 int (*call)(struct wiphy *wiphy, struct net_device *dev,
774 struct beacon_parameters *info);
775 struct cfg80211_registered_device *drv;
777 struct net_device *dev;
778 struct beacon_parameters params;
781 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
785 switch (info->genlhdr->cmd) {
786 case NL80211_CMD_NEW_BEACON:
787 /* these are required for NEW_BEACON */
788 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
789 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
790 !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
795 call = drv->ops->add_beacon;
797 case NL80211_CMD_SET_BEACON:
798 call = drv->ops->set_beacon;
811 memset(¶ms, 0, sizeof(params));
813 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
815 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
819 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
821 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
825 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
826 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
828 nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
832 if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
833 params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
835 nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
845 err = call(&drv->wiphy, dev, ¶ms);
849 cfg80211_put_dev(drv);
854 static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
856 struct cfg80211_registered_device *drv;
858 struct net_device *dev;
860 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
864 if (!drv->ops->del_beacon) {
870 err = drv->ops->del_beacon(&drv->wiphy, dev);
874 cfg80211_put_dev(drv);
879 static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
880 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
881 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
882 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
885 static int parse_station_flags(struct nlattr *nla, u32 *staflags)
887 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
895 if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
896 nla, sta_flags_policy))
899 *staflags = STATION_FLAG_CHANGED;
901 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
903 *staflags |= (1<<flag);
908 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
909 int flags, struct net_device *dev,
910 u8 *mac_addr, struct station_info *sinfo)
913 struct nlattr *sinfoattr;
915 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
919 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
920 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
922 sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
924 goto nla_put_failure;
925 if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
926 NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
927 sinfo->inactive_time);
928 if (sinfo->filled & STATION_INFO_RX_BYTES)
929 NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
931 if (sinfo->filled & STATION_INFO_TX_BYTES)
932 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
934 if (sinfo->filled & STATION_INFO_LLID)
935 NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
937 if (sinfo->filled & STATION_INFO_PLID)
938 NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
940 if (sinfo->filled & STATION_INFO_PLINK_STATE)
941 NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
944 nla_nest_end(msg, sinfoattr);
946 return genlmsg_end(msg, hdr);
949 genlmsg_cancel(msg, hdr);
953 static int nl80211_dump_station(struct sk_buff *skb,
954 struct netlink_callback *cb)
956 struct station_info sinfo;
957 struct cfg80211_registered_device *dev;
958 struct net_device *netdev;
959 u8 mac_addr[ETH_ALEN];
960 int ifidx = cb->args[0];
961 int sta_idx = cb->args[1];
965 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
966 nl80211_fam.attrbuf, nl80211_fam.maxattr,
971 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
974 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
979 netdev = dev_get_by_index(&init_net, ifidx);
983 dev = cfg80211_get_dev_from_ifindex(ifidx);
989 if (!dev->ops->dump_station) {
997 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
1004 if (nl80211_send_station(skb,
1005 NETLINK_CB(cb->skb).pid,
1006 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1016 cb->args[1] = sta_idx;
1021 cfg80211_put_dev(dev);
1028 static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1030 struct cfg80211_registered_device *drv;
1032 struct net_device *dev;
1033 struct station_info sinfo;
1034 struct sk_buff *msg;
1035 u8 *mac_addr = NULL;
1037 memset(&sinfo, 0, sizeof(sinfo));
1039 if (!info->attrs[NL80211_ATTR_MAC])
1042 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1044 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1048 if (!drv->ops->get_station) {
1054 err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
1060 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1064 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
1065 dev, mac_addr, &sinfo) < 0)
1068 err = genlmsg_unicast(msg, info->snd_pid);
1075 cfg80211_put_dev(drv);
1081 * Get vlan interface making sure it is on the right wiphy.
1083 static int get_vlan(struct nlattr *vlanattr,
1084 struct cfg80211_registered_device *rdev,
1085 struct net_device **vlan)
1090 *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
1093 if (!(*vlan)->ieee80211_ptr)
1095 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
1101 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1103 struct cfg80211_registered_device *drv;
1105 struct net_device *dev;
1106 struct station_parameters params;
1107 u8 *mac_addr = NULL;
1109 memset(¶ms, 0, sizeof(params));
1111 params.listen_interval = -1;
1113 if (info->attrs[NL80211_ATTR_STA_AID])
1116 if (!info->attrs[NL80211_ATTR_MAC])
1119 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1121 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
1122 params.supported_rates =
1123 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1124 params.supported_rates_len =
1125 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1128 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1129 params.listen_interval =
1130 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1132 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1133 ¶ms.station_flags))
1136 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
1137 params.plink_action =
1138 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
1140 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1144 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan);
1148 if (!drv->ops->change_station) {
1154 err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms);
1159 dev_put(params.vlan);
1160 cfg80211_put_dev(drv);
1165 static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1167 struct cfg80211_registered_device *drv;
1169 struct net_device *dev;
1170 struct station_parameters params;
1171 u8 *mac_addr = NULL;
1173 memset(¶ms, 0, sizeof(params));
1175 if (!info->attrs[NL80211_ATTR_MAC])
1178 if (!info->attrs[NL80211_ATTR_STA_AID])
1181 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1184 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
1187 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1188 params.supported_rates =
1189 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1190 params.supported_rates_len =
1191 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1192 params.listen_interval =
1193 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1194 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
1196 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1197 ¶ms.station_flags))
1200 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1204 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan);
1208 if (!drv->ops->add_station) {
1214 err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms);
1219 dev_put(params.vlan);
1220 cfg80211_put_dev(drv);
1225 static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1227 struct cfg80211_registered_device *drv;
1229 struct net_device *dev;
1230 u8 *mac_addr = NULL;
1232 if (info->attrs[NL80211_ATTR_MAC])
1233 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1235 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1239 if (!drv->ops->del_station) {
1245 err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1249 cfg80211_put_dev(drv);
1254 static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
1255 int flags, struct net_device *dev,
1256 u8 *dst, u8 *next_hop,
1257 struct mpath_info *pinfo)
1260 struct nlattr *pinfoattr;
1262 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
1266 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1267 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
1268 NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
1270 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
1272 goto nla_put_failure;
1273 if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
1274 NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
1276 if (pinfo->filled & MPATH_INFO_DSN)
1277 NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
1279 if (pinfo->filled & MPATH_INFO_METRIC)
1280 NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
1282 if (pinfo->filled & MPATH_INFO_EXPTIME)
1283 NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
1285 if (pinfo->filled & MPATH_INFO_FLAGS)
1286 NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
1288 if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
1289 NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
1290 pinfo->discovery_timeout);
1291 if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
1292 NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
1293 pinfo->discovery_retries);
1295 nla_nest_end(msg, pinfoattr);
1297 return genlmsg_end(msg, hdr);
1300 genlmsg_cancel(msg, hdr);
1304 static int nl80211_dump_mpath(struct sk_buff *skb,
1305 struct netlink_callback *cb)
1307 struct mpath_info pinfo;
1308 struct cfg80211_registered_device *dev;
1309 struct net_device *netdev;
1311 u8 next_hop[ETH_ALEN];
1312 int ifidx = cb->args[0];
1313 int path_idx = cb->args[1];
1317 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1318 nl80211_fam.attrbuf, nl80211_fam.maxattr,
1323 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1326 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1331 netdev = dev_get_by_index(&init_net, ifidx);
1335 dev = cfg80211_get_dev_from_ifindex(ifidx);
1338 goto out_put_netdev;
1341 if (!dev->ops->dump_mpath) {
1349 err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
1350 dst, next_hop, &pinfo);
1356 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid,
1357 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1358 netdev, dst, next_hop,
1367 cb->args[1] = path_idx;
1372 cfg80211_put_dev(dev);
1379 static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1381 struct cfg80211_registered_device *drv;
1383 struct net_device *dev;
1384 struct mpath_info pinfo;
1385 struct sk_buff *msg;
1387 u8 next_hop[ETH_ALEN];
1389 memset(&pinfo, 0, sizeof(pinfo));
1391 if (!info->attrs[NL80211_ATTR_MAC])
1394 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1396 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1400 if (!drv->ops->get_mpath) {
1406 err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
1412 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1416 if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
1417 dev, dst, next_hop, &pinfo) < 0)
1420 err = genlmsg_unicast(msg, info->snd_pid);
1427 cfg80211_put_dev(drv);
1432 static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
1434 struct cfg80211_registered_device *drv;
1436 struct net_device *dev;
1438 u8 *next_hop = NULL;
1440 if (!info->attrs[NL80211_ATTR_MAC])
1443 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
1446 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1447 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1449 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1453 if (!drv->ops->change_mpath) {
1459 err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
1463 cfg80211_put_dev(drv);
1467 static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
1469 struct cfg80211_registered_device *drv;
1471 struct net_device *dev;
1473 u8 *next_hop = NULL;
1475 if (!info->attrs[NL80211_ATTR_MAC])
1478 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
1481 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1482 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1484 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1488 if (!drv->ops->add_mpath) {
1494 err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
1498 cfg80211_put_dev(drv);
1503 static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
1505 struct cfg80211_registered_device *drv;
1507 struct net_device *dev;
1510 if (info->attrs[NL80211_ATTR_MAC])
1511 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1513 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1517 if (!drv->ops->del_mpath) {
1523 err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
1527 cfg80211_put_dev(drv);
1532 static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
1534 struct cfg80211_registered_device *drv;
1536 struct net_device *dev;
1537 struct bss_parameters params;
1539 memset(¶ms, 0, sizeof(params));
1540 /* default to not changing parameters */
1541 params.use_cts_prot = -1;
1542 params.use_short_preamble = -1;
1543 params.use_short_slot_time = -1;
1545 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
1546 params.use_cts_prot =
1547 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
1548 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
1549 params.use_short_preamble =
1550 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
1551 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
1552 params.use_short_slot_time =
1553 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
1555 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1559 if (!drv->ops->change_bss) {
1565 err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms);
1569 cfg80211_put_dev(drv);
1574 static struct genl_ops nl80211_ops[] = {
1576 .cmd = NL80211_CMD_GET_WIPHY,
1577 .doit = nl80211_get_wiphy,
1578 .dumpit = nl80211_dump_wiphy,
1579 .policy = nl80211_policy,
1580 /* can be retrieved by unprivileged users */
1583 .cmd = NL80211_CMD_SET_WIPHY,
1584 .doit = nl80211_set_wiphy,
1585 .policy = nl80211_policy,
1586 .flags = GENL_ADMIN_PERM,
1589 .cmd = NL80211_CMD_GET_INTERFACE,
1590 .doit = nl80211_get_interface,
1591 .dumpit = nl80211_dump_interface,
1592 .policy = nl80211_policy,
1593 /* can be retrieved by unprivileged users */
1596 .cmd = NL80211_CMD_SET_INTERFACE,
1597 .doit = nl80211_set_interface,
1598 .policy = nl80211_policy,
1599 .flags = GENL_ADMIN_PERM,
1602 .cmd = NL80211_CMD_NEW_INTERFACE,
1603 .doit = nl80211_new_interface,
1604 .policy = nl80211_policy,
1605 .flags = GENL_ADMIN_PERM,
1608 .cmd = NL80211_CMD_DEL_INTERFACE,
1609 .doit = nl80211_del_interface,
1610 .policy = nl80211_policy,
1611 .flags = GENL_ADMIN_PERM,
1614 .cmd = NL80211_CMD_GET_KEY,
1615 .doit = nl80211_get_key,
1616 .policy = nl80211_policy,
1617 .flags = GENL_ADMIN_PERM,
1620 .cmd = NL80211_CMD_SET_KEY,
1621 .doit = nl80211_set_key,
1622 .policy = nl80211_policy,
1623 .flags = GENL_ADMIN_PERM,
1626 .cmd = NL80211_CMD_NEW_KEY,
1627 .doit = nl80211_new_key,
1628 .policy = nl80211_policy,
1629 .flags = GENL_ADMIN_PERM,
1632 .cmd = NL80211_CMD_DEL_KEY,
1633 .doit = nl80211_del_key,
1634 .policy = nl80211_policy,
1635 .flags = GENL_ADMIN_PERM,
1638 .cmd = NL80211_CMD_SET_BEACON,
1639 .policy = nl80211_policy,
1640 .flags = GENL_ADMIN_PERM,
1641 .doit = nl80211_addset_beacon,
1644 .cmd = NL80211_CMD_NEW_BEACON,
1645 .policy = nl80211_policy,
1646 .flags = GENL_ADMIN_PERM,
1647 .doit = nl80211_addset_beacon,
1650 .cmd = NL80211_CMD_DEL_BEACON,
1651 .policy = nl80211_policy,
1652 .flags = GENL_ADMIN_PERM,
1653 .doit = nl80211_del_beacon,
1656 .cmd = NL80211_CMD_GET_STATION,
1657 .doit = nl80211_get_station,
1658 .dumpit = nl80211_dump_station,
1659 .policy = nl80211_policy,
1660 .flags = GENL_ADMIN_PERM,
1663 .cmd = NL80211_CMD_SET_STATION,
1664 .doit = nl80211_set_station,
1665 .policy = nl80211_policy,
1666 .flags = GENL_ADMIN_PERM,
1669 .cmd = NL80211_CMD_NEW_STATION,
1670 .doit = nl80211_new_station,
1671 .policy = nl80211_policy,
1672 .flags = GENL_ADMIN_PERM,
1675 .cmd = NL80211_CMD_DEL_STATION,
1676 .doit = nl80211_del_station,
1677 .policy = nl80211_policy,
1678 .flags = GENL_ADMIN_PERM,
1681 .cmd = NL80211_CMD_GET_MPATH,
1682 .doit = nl80211_get_mpath,
1683 .dumpit = nl80211_dump_mpath,
1684 .policy = nl80211_policy,
1685 .flags = GENL_ADMIN_PERM,
1688 .cmd = NL80211_CMD_SET_MPATH,
1689 .doit = nl80211_set_mpath,
1690 .policy = nl80211_policy,
1691 .flags = GENL_ADMIN_PERM,
1694 .cmd = NL80211_CMD_NEW_MPATH,
1695 .doit = nl80211_new_mpath,
1696 .policy = nl80211_policy,
1697 .flags = GENL_ADMIN_PERM,
1700 .cmd = NL80211_CMD_DEL_MPATH,
1701 .doit = nl80211_del_mpath,
1702 .policy = nl80211_policy,
1703 .flags = GENL_ADMIN_PERM,
1706 .cmd = NL80211_CMD_SET_BSS,
1707 .doit = nl80211_set_bss,
1708 .policy = nl80211_policy,
1709 .flags = GENL_ADMIN_PERM,
1713 /* multicast groups */
1714 static struct genl_multicast_group nl80211_config_mcgrp = {
1718 /* notification functions */
1720 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
1722 struct sk_buff *msg;
1724 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1728 if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
1733 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
1736 /* initialisation/exit functions */
1738 int nl80211_init(void)
1742 err = genl_register_family(&nl80211_fam);
1746 for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
1747 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
1752 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
1758 genl_unregister_family(&nl80211_fam);
1762 void nl80211_exit(void)
1764 genl_unregister_family(&nl80211_fam);