2 * This is the new netlink-based wireless configuration interface.
4 * Copyright 2006 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 <net/genetlink.h>
17 #include <net/cfg80211.h>
21 /* the netlink family */
22 static struct genl_family nl80211_fam = {
23 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
24 .name = "nl80211", /* have users key off the name instead */
25 .hdrsize = 0, /* no private header */
26 .version = 1, /* no particular meaning now */
27 .maxattr = NL80211_ATTR_MAX,
30 /* internal helper: validate an information element attribute */
31 static int check_information_element(struct nlattr *nla)
33 int len = nla_len(nla);
34 u8 *data = nla_data(nla);
38 /* 1 byte ID, 1 byte len, `len' bytes data */
39 elementlen = *(data+1) + 2;
43 return len ? -EINVAL : 0;
46 /* internal helper: get drv and dev */
47 static int get_drv_dev_by_info_ifindex(struct genl_info *info,
48 struct cfg80211_registered_device **drv,
49 struct net_device **dev)
53 if (!info->attrs[NL80211_ATTR_IFINDEX])
56 ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
57 *dev = dev_get_by_index(ifindex);
61 *drv = cfg80211_get_dev_from_ifindex(ifindex);
70 /* policy for the attributes */
71 static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
72 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
73 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
74 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
75 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
76 .len = BUS_ID_SIZE-1 },
77 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
78 [NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
79 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
80 .len = IEEE80211_MAX_SSID_LEN },
81 [NL80211_ATTR_CHANNEL] = { .type = NLA_U32 },
82 [NL80211_ATTR_PHYMODE] = { .type = NLA_U32 },
83 [NL80211_ATTR_CHANNEL_LIST] = { .type = NLA_NESTED },
84 [NL80211_ATTR_BSS_LIST] = { .type = NLA_NESTED },
85 [NL80211_ATTR_BSSTYPE] = { .type = NLA_U32 },
86 [NL80211_ATTR_BEACON_PERIOD] = { .type = NLA_U32 },
87 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
88 [NL80211_ATTR_TIMESTAMP] = { .type = NLA_U64 },
89 [NL80211_ATTR_IE] = { .type = NLA_BINARY, .len = NL80211_MAX_IE_LEN },
90 [NL80211_ATTR_AUTH_ALGORITHM] = { .type = NLA_U32 },
91 [NL80211_ATTR_TIMEOUT_TU] = { .type = NLA_U32 },
92 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U32 },
93 [NL80211_ATTR_ASSOCIATION_ID] = { .type = NLA_U16 },
94 [NL80211_ATTR_DEAUTHENTICATED] = { .type = NLA_FLAG },
95 [NL80211_ATTR_RX_SENSITIVITY] = { .type = NLA_U32 },
96 [NL80211_ATTR_TRANSMIT_POWER] = { .type = NLA_U32 },
97 [NL80211_ATTR_FRAG_THRESHOLD] = { .type = NLA_U32 },
98 [NL80211_ATTR_FLAG_SCAN_ACTIVE] = { .type = NLA_FLAG },
99 [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY },
100 [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY },
101 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
102 .len = WLAN_MAX_KEY_LEN },
103 [NL80211_ATTR_KEY_ID] = { .type = NLA_U32 },
104 [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
105 [NL80211_ATTR_MAC] = { .len = ETH_ALEN },
106 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
109 /* netlink command implementations */
111 #define CHECK_CMD(ptr, cmd) \
113 NLA_PUT_FLAG(msg, NL80211_CMD_##cmd);
115 static int nl80211_get_cmdlist(struct sk_buff *skb, struct genl_info *info)
117 struct cfg80211_registered_device *drv;
121 struct nlattr *start;
123 drv = cfg80211_get_dev_from_info(info);
127 hdr = nl80211msg_new(&msg, info->snd_pid, info->snd_seq, 0,
128 NL80211_CMD_NEW_CMDLIST);
134 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, drv->idx);
136 start = nla_nest_start(msg, NL80211_ATTR_CMDS);
138 goto nla_put_failure;
140 /* unconditionally allow some common commands we handle centrally
141 * or where we require the implementation */
142 NLA_PUT_FLAG(msg, NL80211_CMD_GET_CMDLIST);
143 NLA_PUT_FLAG(msg, NL80211_CMD_GET_WIPHYS);
144 NLA_PUT_FLAG(msg, NL80211_CMD_GET_INTERFACES);
145 NLA_PUT_FLAG(msg, NL80211_CMD_RENAME_WIPHY);
147 CHECK_CMD(add_virtual_intf, ADD_VIRTUAL_INTERFACE);
148 CHECK_CMD(del_virtual_intf, DEL_VIRTUAL_INTERFACE);
149 CHECK_CMD(associate, ASSOCIATE);
150 CHECK_CMD(disassociate, DISASSOCIATE);
151 CHECK_CMD(deauth, DEAUTH);
152 CHECK_CMD(initiate_scan, INITIATE_SCAN);
153 CHECK_CMD(get_association, GET_ASSOCIATION);
154 CHECK_CMD(get_auth_list, GET_AUTH_LIST);
155 CHECK_CMD(add_key, ADD_KEY);
156 CHECK_CMD(del_key, DEL_KEY);
158 nla_nest_end(msg, start);
160 genlmsg_end(msg, hdr);
162 err = genlmsg_unicast(msg, info->snd_pid);
169 cfg80211_put_dev(drv);
174 static int nl80211_get_wiphys(struct sk_buff *skb, struct genl_info *info)
178 struct nlattr *start, *indexstart;
179 struct cfg80211_registered_device *drv;
182 hdr = nl80211msg_new(&msg, info->snd_pid, info->snd_seq, 0,
183 NL80211_CMD_NEW_WIPHYS);
187 start = nla_nest_start(msg, NL80211_ATTR_WIPHY_LIST);
189 goto nla_outer_nest_failure;
191 mutex_lock(&cfg80211_drv_mutex);
192 list_for_each_entry(drv, &cfg80211_drv_list, list) {
193 indexstart = nla_nest_start(msg, idx++);
195 goto nla_put_failure;
196 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, drv->idx);
197 nla_nest_end(msg, indexstart);
199 mutex_unlock(&cfg80211_drv_mutex);
201 nla_nest_end(msg, start);
203 genlmsg_end(msg, hdr);
205 return genlmsg_unicast(msg, info->snd_pid);
208 mutex_unlock(&cfg80211_drv_mutex);
209 nla_outer_nest_failure:
214 static int addifidx(struct net_device *dev, struct sk_buff *skb, int *idx)
217 struct nlattr *start;
221 start = nla_nest_start(skb, *idx++);
223 goto nla_put_failure;
225 NLA_PUT_U32(skb, NL80211_ATTR_IFINDEX, dev->ifindex);
226 NLA_PUT_STRING(skb, NL80211_ATTR_IFNAME, dev->name);
228 nla_nest_end(skb, start);
236 static int nl80211_get_intfs(struct sk_buff *skb, struct genl_info *info)
238 struct cfg80211_registered_device *drv;
242 struct nlattr *start;
243 struct wireless_dev *wdev;
245 drv = cfg80211_get_dev_from_info(info);
249 hdr = nl80211msg_new(&msg, info->snd_pid, info->snd_seq, 0,
250 NL80211_CMD_NEW_INTERFACES);
256 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, drv->idx);
258 start = nla_nest_start(msg, NL80211_ATTR_INTERFACE_LIST);
266 mutex_lock(&drv->devlist_mtx);
267 list_for_each_entry(wdev, &drv->netdev_list, list) {
268 err = addifidx(wdev->netdev, msg, &array_idx);
272 mutex_unlock(&drv->devlist_mtx);
276 nla_nest_end(msg, start);
278 genlmsg_end(msg, hdr);
280 err = genlmsg_unicast(msg, info->snd_pid);
288 cfg80211_put_dev(drv);
292 static int nl80211_add_virt_intf(struct sk_buff *skb, struct genl_info *info)
294 struct cfg80211_registered_device *drv;
296 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
298 if (!info->attrs[NL80211_ATTR_IFNAME])
301 if (info->attrs[NL80211_ATTR_IFTYPE]) {
302 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
303 if (type > NL80211_IFTYPE_MAX)
307 drv = cfg80211_get_dev_from_info(info);
311 if (!drv->ops->add_virtual_intf) {
317 err = drv->ops->add_virtual_intf(&drv->wiphy,
318 nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
322 cfg80211_put_dev(drv);
326 static int nl80211_del_virt_intf(struct sk_buff *skb, struct genl_info *info)
328 struct cfg80211_registered_device *drv;
330 struct net_device *dev;
332 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
335 ifindex = dev->ifindex;
338 if (!drv->ops->del_virtual_intf) {
344 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
348 cfg80211_put_dev(drv);
352 static int nl80211_change_virt_intf(struct sk_buff *skb, struct genl_info *info)
354 struct cfg80211_registered_device *drv;
356 enum nl80211_iftype type;
357 struct net_device *dev;
359 if (info->attrs[NL80211_ATTR_IFTYPE]) {
360 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
361 if (type > NL80211_IFTYPE_MAX)
366 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
369 ifindex = dev->ifindex;
372 if (!drv->ops->change_virtual_intf) {
378 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
382 cfg80211_put_dev(drv);
386 static int nl80211_get_association(struct sk_buff *skb, struct genl_info *info)
388 struct cfg80211_registered_device *drv;
390 struct net_device *dev;
395 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
399 if (!drv->ops->get_association) {
405 err = drv->ops->get_association(&drv->wiphy, dev, bssid);
410 hdr = nl80211msg_new(&msg, info->snd_pid, info->snd_seq, 0,
411 NL80211_CMD_ASSOCIATION_CHANGED);
418 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
420 NLA_PUT(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid);
422 genlmsg_end(msg, hdr);
423 err = genlmsg_unicast(msg, info->snd_pid);
430 cfg80211_put_dev(drv);
435 static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
437 struct cfg80211_registered_device *drv;
439 struct net_device *dev;
440 struct association_params assoc_params;
442 memset(&assoc_params, 0, sizeof(assoc_params));
444 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
448 if (!drv->ops->associate) {
453 if (!info->attrs[NL80211_ATTR_SSID])
456 assoc_params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
457 assoc_params.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
459 if (info->attrs[NL80211_ATTR_BSSID])
460 assoc_params.bssid = nla_data(info->attrs[NL80211_ATTR_BSSID]);
462 if (info->attrs[NL80211_ATTR_IE]) {
463 err = check_information_element(info->attrs[NL80211_ATTR_IE]);
466 assoc_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
467 assoc_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
470 if (info->attrs[NL80211_ATTR_TIMEOUT_TU]) {
471 assoc_params.timeout =
472 nla_get_u32(info->attrs[NL80211_ATTR_TIMEOUT_TU]);
473 assoc_params.valid |= ASSOC_PARAMS_TIMEOUT;
477 err = drv->ops->associate(&drv->wiphy, dev, &assoc_params);
481 cfg80211_put_dev(drv);
486 static int nl80211_disassoc_deauth(struct sk_buff *skb, struct genl_info *info)
488 struct cfg80211_registered_device *drv;
490 struct net_device *dev;
491 int (*act)(struct wiphy *wiphy, struct net_device *dev);
493 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
497 switch (info->genlhdr->cmd) {
498 case NL80211_CMD_DISASSOCIATE:
499 act = drv->ops->disassociate;
501 case NL80211_CMD_DEAUTH:
502 act = drv->ops->deauth;
514 err = act(&drv->wiphy, dev);
517 cfg80211_put_dev(drv);
527 static int add_bssid(void *data, u8 *bssid)
529 struct add_cb_data *cb = data;
531 struct nlattr *start;
533 start = nla_nest_start(cb->skb, cb->idx++);
535 goto nla_put_failure;
537 NLA_PUT(cb->skb, NL80211_ATTR_BSSID, ETH_ALEN, bssid);
539 nla_nest_end(cb->skb, start);
546 static int nl80211_get_auth_list(struct sk_buff *skb, struct genl_info *info)
548 struct cfg80211_registered_device *drv;
549 struct net_device *dev;
553 struct nlattr *start;
554 struct add_cb_data cb;
556 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
560 if (!drv->ops->get_auth_list) {
565 hdr = nl80211msg_new(&msg, info->snd_pid, info->snd_seq, 0,
566 NL80211_CMD_NEW_AUTH_LIST);
572 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
574 start = nla_nest_start(msg, NL80211_ATTR_BSS_LIST);
583 err = drv->ops->get_auth_list(&drv->wiphy, dev, &cb, add_bssid);
588 nla_nest_end(msg, start);
590 genlmsg_end(msg, hdr);
592 err = genlmsg_unicast(msg, info->snd_pid);
600 cfg80211_put_dev(drv);
605 static int nl80211_initiate_scan(struct sk_buff *skb, struct genl_info *info)
607 struct cfg80211_registered_device *drv;
609 struct net_device *dev;
610 struct scan_params params;
611 struct scan_channel *channels = NULL;
614 if (info->attrs[NL80211_ATTR_PHYMODE])
615 params.phymode = nla_get_u32(info->attrs[NL80211_ATTR_PHYMODE]);
617 if (params.phymode > NL80211_PHYMODE_MAX)
620 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
624 if (!drv->ops->initiate_scan) {
629 params.active = nla_get_flag(info->attrs[NL80211_ATTR_FLAG_SCAN_ACTIVE]);
631 if (info->attrs[NL80211_ATTR_CHANNEL_LIST]) {
632 struct nlattr *attr = info->attrs[NL80211_ATTR_CHANNEL_LIST];
637 /* let's count first */
639 nla_for_each_attr(nla, nla_data(attr), nla_len(attr), rem)
643 /* assume we should actually scan all channels,
644 * scanning no channels make no sense */
649 if (count > NL80211_MAX_CHANNEL_LIST_ITEM) {
654 channels = kmalloc(count * sizeof(struct scan_channel),
656 tb = kmalloc((NL80211_ATTR_MAX+1) * sizeof(struct nlattr),
660 nla_for_each_attr(nla, nla_data(attr), nla_len(attr), rem) {
661 err = nla_parse(tb, NL80211_ATTR_MAX, nla_data(nla),
662 nla_len(nla), nl80211_policy);
664 if (err || !tb[NL80211_ATTR_CHANNEL]) {
671 channels[count].phymode = params.phymode;
673 if (tb[NL80211_ATTR_PHYMODE])
674 channels[count].phymode =
675 nla_get_u32(tb[NL80211_ATTR_PHYMODE]);
677 if (channels[count].phymode > NL80211_PHYMODE_MAX) {
684 channels[count].channel =
685 nla_get_u32(tb[NL80211_ATTR_CHANNEL]);
687 channels[count].active =
688 nla_get_flag(tb[NL80211_ATTR_FLAG_SCAN_ACTIVE]);
695 params.channels = channels;
696 params.n_channels = count;
699 err = drv->ops->initiate_scan(&drv->wiphy, dev, ¶ms);
704 cfg80211_put_dev(drv);
709 static int nl80211_rename_wiphy(struct sk_buff *skb, struct genl_info *info)
711 struct cfg80211_registered_device *rdev;
714 if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
717 rdev = cfg80211_get_dev_from_info(info);
719 return PTR_ERR(rdev);
721 result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
723 cfg80211_put_dev(rdev);
727 static int nl80211_key_cmd(struct sk_buff *skb, struct genl_info *info)
729 struct cfg80211_registered_device *drv;
731 struct net_device *dev;
732 struct key_params params;
733 int (*act)(struct wiphy *wiphy, struct net_device *dev,
734 struct key_params *params);
736 memset(¶ms, 0, sizeof(params));
738 if (!info->attrs[NL80211_ATTR_KEY_TYPE])
741 if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
744 params.key_type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
745 if (params.key_type > NL80211_KEYTYPE_MAX)
748 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
752 switch (info->genlhdr->cmd) {
753 case NL80211_CMD_ADD_KEY:
754 act = drv->ops->add_key;
757 case NL80211_CMD_DEL_KEY:
758 act = drv->ops->del_key;
770 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
771 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
772 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
775 if (info->attrs[NL80211_ATTR_KEY_ID]) {
776 params.key_id = nla_get_u32(info->attrs[NL80211_ATTR_KEY_ID]);
781 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
783 if (info->attrs[NL80211_ATTR_MAC]) {
784 params.macaddress = nla_data(info->attrs[NL80211_ATTR_MAC]);
786 params.macaddress = NULL;
790 err = act(&drv->wiphy, dev, ¶ms);
794 cfg80211_put_dev(drv);
799 static struct genl_ops nl80211_ops[] = {
801 .cmd = NL80211_CMD_RENAME_WIPHY,
802 .doit = nl80211_rename_wiphy,
803 .policy = nl80211_policy,
804 .flags = GENL_ADMIN_PERM,
807 .cmd = NL80211_CMD_GET_CMDLIST,
808 .doit = nl80211_get_cmdlist,
809 .policy = nl80211_policy,
810 /* can be retrieved by unprivileged users */
813 .cmd = NL80211_CMD_ADD_VIRTUAL_INTERFACE,
814 .doit = nl80211_add_virt_intf,
815 .policy = nl80211_policy,
816 .flags = GENL_ADMIN_PERM,
819 .cmd = NL80211_CMD_DEL_VIRTUAL_INTERFACE,
820 .doit = nl80211_del_virt_intf,
821 .policy = nl80211_policy,
822 .flags = GENL_ADMIN_PERM,
825 .cmd = NL80211_CMD_CHANGE_VIRTUAL_INTERFACE,
826 .doit = nl80211_change_virt_intf,
827 .policy = nl80211_policy,
828 .flags = GENL_ADMIN_PERM,
831 .cmd = NL80211_CMD_GET_WIPHYS,
832 .doit = nl80211_get_wiphys,
833 .policy = nl80211_policy,
834 /* can be retrieved by unprivileged users */
837 .cmd = NL80211_CMD_GET_INTERFACES,
838 .doit = nl80211_get_intfs,
839 .policy = nl80211_policy,
840 /* can be retrieved by unprivileged users */
843 .cmd = NL80211_CMD_INITIATE_SCAN,
844 .doit = nl80211_initiate_scan,
845 .policy = nl80211_policy,
846 .flags = GENL_ADMIN_PERM,
849 .cmd = NL80211_CMD_GET_ASSOCIATION,
850 .doit = nl80211_get_association,
851 .policy = nl80211_policy,
852 /* can be retrieved by unprivileged users */
855 .cmd = NL80211_CMD_ASSOCIATE,
856 .doit = nl80211_associate,
857 .policy = nl80211_policy,
858 .flags = GENL_ADMIN_PERM,
861 .cmd = NL80211_CMD_DISASSOCIATE,
862 .doit = nl80211_disassoc_deauth,
863 .policy = nl80211_policy,
864 .flags = GENL_ADMIN_PERM,
867 .cmd = NL80211_CMD_DEAUTH,
868 .doit = nl80211_disassoc_deauth,
869 .policy = nl80211_policy,
870 .flags = GENL_ADMIN_PERM,
873 .cmd = NL80211_CMD_GET_AUTH_LIST,
874 .doit = nl80211_get_auth_list,
875 .policy = nl80211_policy,
876 /* can be retrieved by unprivileged users */
880 .cmd = NL80211_CMD_AP_SET_BEACON,
881 .policy = nl80211_policy,
882 .flags = GENL_ADMIN_PERM,
885 .cmd = NL80211_CMD_AP_ADD_STA,
886 .policy = nl80211_policy,
887 .flags = GENL_ADMIN_PERM,
890 .cmd = NL80211_CMD_AP_UPDATE_STA,
891 .policy = nl80211_policy,
892 .flags = GENL_ADMIN_PERM,
895 .cmd = NL80211_CMD_AP_GET_STA_INFO,
896 .policy = nl80211_policy,
897 .flags = GENL_ADMIN_PERM,
900 .cmd = NL80211_CMD_AP_SET_RATESETS,
901 .policy = nl80211_policy,
902 .flags = GENL_ADMIN_PERM,
906 .cmd = NL80211_CMD_ADD_KEY,
907 .doit = nl80211_key_cmd,
908 .policy = nl80211_policy,
909 .flags = GENL_ADMIN_PERM,
912 .cmd = NL80211_CMD_DEL_KEY,
913 .doit = nl80211_key_cmd,
914 .policy = nl80211_policy,
915 .flags = GENL_ADMIN_PERM,
920 /* exported functions */
922 void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, int flags, u8 cmd)
924 /* since there is no private header just add the generic one */
925 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
927 EXPORT_SYMBOL_GPL(nl80211hdr_put);
929 void *nl80211msg_new(struct sk_buff **skb, u32 pid, u32 seq, int flags, u8 cmd)
933 *skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
935 return ERR_PTR(-ENOBUFS);
937 hdr = nl80211hdr_put(*skb, pid, seq, flags, cmd);
940 return ERR_PTR(-ENOBUFS);
945 EXPORT_SYMBOL_GPL(nl80211msg_new);
947 /* notification functions */
949 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
954 hdr = nl80211msg_new(&msg, 0, 0, 0, NL80211_CMD_WIPHY_NEWNAME);
958 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->idx);
959 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&rdev->wiphy));
961 genlmsg_end(msg, hdr);
962 genlmsg_multicast(msg, 0, NL80211_GROUP_CONFIG, GFP_KERNEL);
970 /* initialisation/exit functions */
972 int nl80211_init(void)
976 err = genl_register_family(&nl80211_fam);
980 for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
981 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
987 genl_unregister_family(&nl80211_fam);
991 void nl80211_exit(void)
993 genl_unregister_family(&nl80211_fam);