]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - net/wireless/nl80211.c
p54: integrate parts of lmac_longbow.h and other parts of stlc45xx
[mirror_ubuntu-bionic-kernel.git] / net / wireless / nl80211.c
CommitLineData
55682965
JB
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"
b2e1b302 21#include "reg.h"
55682965
JB
22
23/* the netlink family */
24static struct genl_family nl80211_fam = {
25 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
26 .name = "nl80211", /* have users key off the name instead */
27 .hdrsize = 0, /* no private header */
28 .version = 1, /* no particular meaning now */
29 .maxattr = NL80211_ATTR_MAX,
30};
31
32/* internal helper: get drv and dev */
bba95fef 33static int get_drv_dev_by_info_ifindex(struct nlattr **attrs,
55682965
JB
34 struct cfg80211_registered_device **drv,
35 struct net_device **dev)
36{
37 int ifindex;
38
bba95fef 39 if (!attrs[NL80211_ATTR_IFINDEX])
55682965
JB
40 return -EINVAL;
41
bba95fef 42 ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
55682965
JB
43 *dev = dev_get_by_index(&init_net, ifindex);
44 if (!*dev)
45 return -ENODEV;
46
47 *drv = cfg80211_get_dev_from_ifindex(ifindex);
48 if (IS_ERR(*drv)) {
49 dev_put(*dev);
50 return PTR_ERR(*drv);
51 }
52
53 return 0;
54}
55
56/* policy for the attributes */
57static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
58 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
59 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
60 .len = BUS_ID_SIZE-1 },
61
62 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
63 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
64 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f
JB
65
66 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
67
68 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
69 .len = WLAN_MAX_KEY_LEN },
70 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
71 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
72 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
ed1b6cc7
JB
73
74 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
75 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
76 [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
77 .len = IEEE80211_MAX_DATA_LEN },
78 [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
79 .len = IEEE80211_MAX_DATA_LEN },
5727ef1b
JB
80 [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
81 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
82 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
83 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
84 .len = NL80211_MAX_SUPP_RATES },
2ec600d6 85 [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
5727ef1b 86 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
66f7ac50 87 [NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
2ec600d6
LCC
88 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
89 .len = IEEE80211_MAX_MESH_ID_LEN },
90 [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
9f1ba906 91
b2e1b302
LR
92 [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
93 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
94
9f1ba906
JM
95 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
96 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
97 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
36aedc90
JM
98
99 [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
100 .len = NL80211_HT_CAPABILITY_LEN },
55682965
JB
101};
102
103/* message building helper */
104static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
105 int flags, u8 cmd)
106{
107 /* since there is no private header just add the generic one */
108 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
109}
110
111/* netlink command implementations */
112
113static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
114 struct cfg80211_registered_device *dev)
115{
116 void *hdr;
ee688b00
JB
117 struct nlattr *nl_bands, *nl_band;
118 struct nlattr *nl_freqs, *nl_freq;
119 struct nlattr *nl_rates, *nl_rate;
f59ac048 120 struct nlattr *nl_modes;
ee688b00
JB
121 enum ieee80211_band band;
122 struct ieee80211_channel *chan;
123 struct ieee80211_rate *rate;
124 int i;
f59ac048 125 u16 ifmodes = dev->wiphy.interface_modes;
55682965
JB
126
127 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
128 if (!hdr)
129 return -1;
130
131 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
132 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
ee688b00 133
f59ac048
LR
134 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
135 if (!nl_modes)
136 goto nla_put_failure;
137
138 i = 0;
139 while (ifmodes) {
140 if (ifmodes & 1)
141 NLA_PUT_FLAG(msg, i);
142 ifmodes >>= 1;
143 i++;
144 }
145
146 nla_nest_end(msg, nl_modes);
147
ee688b00
JB
148 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
149 if (!nl_bands)
150 goto nla_put_failure;
151
152 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
153 if (!dev->wiphy.bands[band])
154 continue;
155
156 nl_band = nla_nest_start(msg, band);
157 if (!nl_band)
158 goto nla_put_failure;
159
d51626df
JB
160 /* add HT info */
161 if (dev->wiphy.bands[band]->ht_cap.ht_supported) {
162 NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET,
163 sizeof(dev->wiphy.bands[band]->ht_cap.mcs),
164 &dev->wiphy.bands[band]->ht_cap.mcs);
165 NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA,
166 dev->wiphy.bands[band]->ht_cap.cap);
167 NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
168 dev->wiphy.bands[band]->ht_cap.ampdu_factor);
169 NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
170 dev->wiphy.bands[band]->ht_cap.ampdu_density);
171 }
172
ee688b00
JB
173 /* add frequencies */
174 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
175 if (!nl_freqs)
176 goto nla_put_failure;
177
178 for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
179 nl_freq = nla_nest_start(msg, i);
180 if (!nl_freq)
181 goto nla_put_failure;
182
183 chan = &dev->wiphy.bands[band]->channels[i];
184 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
185 chan->center_freq);
186
187 if (chan->flags & IEEE80211_CHAN_DISABLED)
188 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
189 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
190 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
191 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
192 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
193 if (chan->flags & IEEE80211_CHAN_RADAR)
194 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
195
196 nla_nest_end(msg, nl_freq);
197 }
198
199 nla_nest_end(msg, nl_freqs);
200
201 /* add bitrates */
202 nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
203 if (!nl_rates)
204 goto nla_put_failure;
205
206 for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
207 nl_rate = nla_nest_start(msg, i);
208 if (!nl_rate)
209 goto nla_put_failure;
210
211 rate = &dev->wiphy.bands[band]->bitrates[i];
212 NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
213 rate->bitrate);
214 if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
215 NLA_PUT_FLAG(msg,
216 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
217
218 nla_nest_end(msg, nl_rate);
219 }
220
221 nla_nest_end(msg, nl_rates);
222
223 nla_nest_end(msg, nl_band);
224 }
225 nla_nest_end(msg, nl_bands);
226
55682965
JB
227 return genlmsg_end(msg, hdr);
228
229 nla_put_failure:
bc3ed28c
TG
230 genlmsg_cancel(msg, hdr);
231 return -EMSGSIZE;
55682965
JB
232}
233
234static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
235{
236 int idx = 0;
237 int start = cb->args[0];
238 struct cfg80211_registered_device *dev;
239
240 mutex_lock(&cfg80211_drv_mutex);
241 list_for_each_entry(dev, &cfg80211_drv_list, list) {
b4637271 242 if (++idx <= start)
55682965
JB
243 continue;
244 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
245 cb->nlh->nlmsg_seq, NLM_F_MULTI,
b4637271
JV
246 dev) < 0) {
247 idx--;
55682965 248 break;
b4637271 249 }
55682965
JB
250 }
251 mutex_unlock(&cfg80211_drv_mutex);
252
253 cb->args[0] = idx;
254
255 return skb->len;
256}
257
258static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
259{
260 struct sk_buff *msg;
261 struct cfg80211_registered_device *dev;
262
263 dev = cfg80211_get_dev_from_info(info);
264 if (IS_ERR(dev))
265 return PTR_ERR(dev);
266
267 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
268 if (!msg)
269 goto out_err;
270
271 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
272 goto out_free;
273
274 cfg80211_put_dev(dev);
275
276 return genlmsg_unicast(msg, info->snd_pid);
277
278 out_free:
279 nlmsg_free(msg);
280 out_err:
281 cfg80211_put_dev(dev);
282 return -ENOBUFS;
283}
284
285static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
286{
287 struct cfg80211_registered_device *rdev;
288 int result;
289
290 if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
291 return -EINVAL;
292
293 rdev = cfg80211_get_dev_from_info(info);
294 if (IS_ERR(rdev))
295 return PTR_ERR(rdev);
296
297 result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
298
299 cfg80211_put_dev(rdev);
300 return result;
301}
302
303
304static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
305 struct net_device *dev)
306{
307 void *hdr;
308
309 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
310 if (!hdr)
311 return -1;
312
313 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
314 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
60719ffd 315 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
55682965
JB
316 return genlmsg_end(msg, hdr);
317
318 nla_put_failure:
bc3ed28c
TG
319 genlmsg_cancel(msg, hdr);
320 return -EMSGSIZE;
55682965
JB
321}
322
323static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
324{
325 int wp_idx = 0;
326 int if_idx = 0;
327 int wp_start = cb->args[0];
328 int if_start = cb->args[1];
329 struct cfg80211_registered_device *dev;
330 struct wireless_dev *wdev;
331
332 mutex_lock(&cfg80211_drv_mutex);
333 list_for_each_entry(dev, &cfg80211_drv_list, list) {
bba95fef
JB
334 if (wp_idx < wp_start) {
335 wp_idx++;
55682965 336 continue;
bba95fef 337 }
55682965
JB
338 if_idx = 0;
339
340 mutex_lock(&dev->devlist_mtx);
341 list_for_each_entry(wdev, &dev->netdev_list, list) {
bba95fef
JB
342 if (if_idx < if_start) {
343 if_idx++;
55682965 344 continue;
bba95fef 345 }
55682965
JB
346 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
347 cb->nlh->nlmsg_seq, NLM_F_MULTI,
bba95fef
JB
348 wdev->netdev) < 0) {
349 mutex_unlock(&dev->devlist_mtx);
350 goto out;
351 }
352 if_idx++;
55682965
JB
353 }
354 mutex_unlock(&dev->devlist_mtx);
bba95fef
JB
355
356 wp_idx++;
55682965 357 }
bba95fef 358 out:
55682965
JB
359 mutex_unlock(&cfg80211_drv_mutex);
360
361 cb->args[0] = wp_idx;
362 cb->args[1] = if_idx;
363
364 return skb->len;
365}
366
367static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
368{
369 struct sk_buff *msg;
370 struct cfg80211_registered_device *dev;
371 struct net_device *netdev;
372 int err;
373
bba95fef 374 err = get_drv_dev_by_info_ifindex(info->attrs, &dev, &netdev);
55682965
JB
375 if (err)
376 return err;
377
378 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
379 if (!msg)
380 goto out_err;
381
382 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
383 goto out_free;
384
385 dev_put(netdev);
386 cfg80211_put_dev(dev);
387
388 return genlmsg_unicast(msg, info->snd_pid);
389
390 out_free:
391 nlmsg_free(msg);
392 out_err:
393 dev_put(netdev);
394 cfg80211_put_dev(dev);
395 return -ENOBUFS;
396}
397
66f7ac50
MW
398static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
399 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
400 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
401 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
402 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
403 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
404};
405
406static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
407{
408 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
409 int flag;
410
411 *mntrflags = 0;
412
413 if (!nla)
414 return -EINVAL;
415
416 if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
417 nla, mntr_flags_policy))
418 return -EINVAL;
419
420 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
421 if (flags[flag])
422 *mntrflags |= (1<<flag);
423
424 return 0;
425}
426
55682965
JB
427static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
428{
429 struct cfg80211_registered_device *drv;
2ec600d6 430 struct vif_params params;
55682965
JB
431 int err, ifindex;
432 enum nl80211_iftype type;
433 struct net_device *dev;
92ffe055 434 u32 _flags, *flags = NULL;
55682965 435
2ec600d6
LCC
436 memset(&params, 0, sizeof(params));
437
bba95fef 438 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
55682965
JB
439 if (err)
440 return err;
441 ifindex = dev->ifindex;
723b038d 442 type = dev->ieee80211_ptr->iftype;
55682965
JB
443 dev_put(dev);
444
723b038d
JB
445 err = -EINVAL;
446 if (info->attrs[NL80211_ATTR_IFTYPE]) {
447 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
448 if (type > NL80211_IFTYPE_MAX)
449 goto unlock;
450 }
451
f59ac048
LR
452 if (!drv->ops->change_virtual_intf ||
453 !(drv->wiphy.interface_modes & (1 << type))) {
55682965
JB
454 err = -EOPNOTSUPP;
455 goto unlock;
456 }
457
92ffe055
JB
458 if (info->attrs[NL80211_ATTR_MESH_ID]) {
459 if (type != NL80211_IFTYPE_MESH_POINT) {
460 err = -EINVAL;
461 goto unlock;
462 }
2ec600d6
LCC
463 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
464 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
465 }
466
92ffe055
JB
467 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
468 if (type != NL80211_IFTYPE_MONITOR) {
469 err = -EINVAL;
470 goto unlock;
471 }
472 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
473 &_flags);
474 if (!err)
475 flags = &_flags;
476 }
55682965 477 rtnl_lock();
66f7ac50 478 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
92ffe055 479 type, flags, &params);
60719ffd
JB
480
481 dev = __dev_get_by_index(&init_net, ifindex);
482 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type));
483
55682965
JB
484 rtnl_unlock();
485
486 unlock:
487 cfg80211_put_dev(drv);
488 return err;
489}
490
491static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
492{
493 struct cfg80211_registered_device *drv;
2ec600d6 494 struct vif_params params;
55682965
JB
495 int err;
496 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
66f7ac50 497 u32 flags;
55682965 498
2ec600d6
LCC
499 memset(&params, 0, sizeof(params));
500
55682965
JB
501 if (!info->attrs[NL80211_ATTR_IFNAME])
502 return -EINVAL;
503
504 if (info->attrs[NL80211_ATTR_IFTYPE]) {
505 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
506 if (type > NL80211_IFTYPE_MAX)
507 return -EINVAL;
508 }
509
510 drv = cfg80211_get_dev_from_info(info);
511 if (IS_ERR(drv))
512 return PTR_ERR(drv);
513
f59ac048
LR
514 if (!drv->ops->add_virtual_intf ||
515 !(drv->wiphy.interface_modes & (1 << type))) {
55682965
JB
516 err = -EOPNOTSUPP;
517 goto unlock;
518 }
519
2ec600d6
LCC
520 if (type == NL80211_IFTYPE_MESH_POINT &&
521 info->attrs[NL80211_ATTR_MESH_ID]) {
522 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
523 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
524 }
525
55682965 526 rtnl_lock();
66f7ac50
MW
527 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
528 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
529 &flags);
55682965 530 err = drv->ops->add_virtual_intf(&drv->wiphy,
66f7ac50 531 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
2ec600d6 532 type, err ? NULL : &flags, &params);
55682965
JB
533 rtnl_unlock();
534
2ec600d6 535
55682965
JB
536 unlock:
537 cfg80211_put_dev(drv);
538 return err;
539}
540
541static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
542{
543 struct cfg80211_registered_device *drv;
544 int ifindex, err;
545 struct net_device *dev;
546
bba95fef 547 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
55682965
JB
548 if (err)
549 return err;
550 ifindex = dev->ifindex;
551 dev_put(dev);
552
553 if (!drv->ops->del_virtual_intf) {
554 err = -EOPNOTSUPP;
555 goto out;
556 }
557
558 rtnl_lock();
559 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
560 rtnl_unlock();
561
562 out:
563 cfg80211_put_dev(drv);
564 return err;
565}
566
41ade00f
JB
567struct get_key_cookie {
568 struct sk_buff *msg;
569 int error;
570};
571
572static void get_key_callback(void *c, struct key_params *params)
573{
574 struct get_key_cookie *cookie = c;
575
576 if (params->key)
577 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
578 params->key_len, params->key);
579
580 if (params->seq)
581 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
582 params->seq_len, params->seq);
583
584 if (params->cipher)
585 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
586 params->cipher);
587
588 return;
589 nla_put_failure:
590 cookie->error = 1;
591}
592
593static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
594{
595 struct cfg80211_registered_device *drv;
596 int err;
597 struct net_device *dev;
598 u8 key_idx = 0;
599 u8 *mac_addr = NULL;
600 struct get_key_cookie cookie = {
601 .error = 0,
602 };
603 void *hdr;
604 struct sk_buff *msg;
605
606 if (info->attrs[NL80211_ATTR_KEY_IDX])
607 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
608
609 if (key_idx > 3)
610 return -EINVAL;
611
612 if (info->attrs[NL80211_ATTR_MAC])
613 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
614
bba95fef 615 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
41ade00f
JB
616 if (err)
617 return err;
618
619 if (!drv->ops->get_key) {
620 err = -EOPNOTSUPP;
621 goto out;
622 }
623
624 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
625 if (!msg) {
626 err = -ENOMEM;
627 goto out;
628 }
629
630 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
631 NL80211_CMD_NEW_KEY);
632
633 if (IS_ERR(hdr)) {
634 err = PTR_ERR(hdr);
635 goto out;
636 }
637
638 cookie.msg = msg;
639
640 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
641 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
642 if (mac_addr)
643 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
644
645 rtnl_lock();
646 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
647 &cookie, get_key_callback);
648 rtnl_unlock();
649
650 if (err)
651 goto out;
652
653 if (cookie.error)
654 goto nla_put_failure;
655
656 genlmsg_end(msg, hdr);
657 err = genlmsg_unicast(msg, info->snd_pid);
658 goto out;
659
660 nla_put_failure:
661 err = -ENOBUFS;
662 nlmsg_free(msg);
663 out:
664 cfg80211_put_dev(drv);
665 dev_put(dev);
666 return err;
667}
668
669static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
670{
671 struct cfg80211_registered_device *drv;
672 int err;
673 struct net_device *dev;
674 u8 key_idx;
675
676 if (!info->attrs[NL80211_ATTR_KEY_IDX])
677 return -EINVAL;
678
679 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
680
681 if (key_idx > 3)
682 return -EINVAL;
683
684 /* currently only support setting default key */
685 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
686 return -EINVAL;
687
bba95fef 688 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
41ade00f
JB
689 if (err)
690 return err;
691
692 if (!drv->ops->set_default_key) {
693 err = -EOPNOTSUPP;
694 goto out;
695 }
696
697 rtnl_lock();
698 err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
699 rtnl_unlock();
700
701 out:
702 cfg80211_put_dev(drv);
703 dev_put(dev);
704 return err;
705}
706
707static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
708{
709 struct cfg80211_registered_device *drv;
710 int err;
711 struct net_device *dev;
712 struct key_params params;
713 u8 key_idx = 0;
714 u8 *mac_addr = NULL;
715
716 memset(&params, 0, sizeof(params));
717
718 if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
719 return -EINVAL;
720
721 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
722 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
723 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
724 }
725
726 if (info->attrs[NL80211_ATTR_KEY_IDX])
727 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
728
729 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
730
731 if (info->attrs[NL80211_ATTR_MAC])
732 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
733
734 if (key_idx > 3)
735 return -EINVAL;
736
737 /*
738 * Disallow pairwise keys with non-zero index unless it's WEP
739 * (because current deployments use pairwise WEP keys with
740 * non-zero indizes but 802.11i clearly specifies to use zero)
741 */
742 if (mac_addr && key_idx &&
743 params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
744 params.cipher != WLAN_CIPHER_SUITE_WEP104)
745 return -EINVAL;
746
747 /* TODO: add definitions for the lengths to linux/ieee80211.h */
748 switch (params.cipher) {
749 case WLAN_CIPHER_SUITE_WEP40:
750 if (params.key_len != 5)
751 return -EINVAL;
752 break;
753 case WLAN_CIPHER_SUITE_TKIP:
754 if (params.key_len != 32)
755 return -EINVAL;
756 break;
757 case WLAN_CIPHER_SUITE_CCMP:
758 if (params.key_len != 16)
759 return -EINVAL;
760 break;
761 case WLAN_CIPHER_SUITE_WEP104:
762 if (params.key_len != 13)
763 return -EINVAL;
764 break;
765 default:
766 return -EINVAL;
767 }
768
bba95fef 769 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
41ade00f
JB
770 if (err)
771 return err;
772
773 if (!drv->ops->add_key) {
774 err = -EOPNOTSUPP;
775 goto out;
776 }
777
778 rtnl_lock();
779 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
780 rtnl_unlock();
781
782 out:
783 cfg80211_put_dev(drv);
784 dev_put(dev);
785 return err;
786}
787
788static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
789{
790 struct cfg80211_registered_device *drv;
791 int err;
792 struct net_device *dev;
793 u8 key_idx = 0;
794 u8 *mac_addr = NULL;
795
796 if (info->attrs[NL80211_ATTR_KEY_IDX])
797 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
798
799 if (key_idx > 3)
800 return -EINVAL;
801
802 if (info->attrs[NL80211_ATTR_MAC])
803 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
804
bba95fef 805 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
41ade00f
JB
806 if (err)
807 return err;
808
809 if (!drv->ops->del_key) {
810 err = -EOPNOTSUPP;
811 goto out;
812 }
813
814 rtnl_lock();
815 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
816 rtnl_unlock();
817
818 out:
819 cfg80211_put_dev(drv);
820 dev_put(dev);
821 return err;
822}
823
ed1b6cc7
JB
824static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
825{
826 int (*call)(struct wiphy *wiphy, struct net_device *dev,
827 struct beacon_parameters *info);
828 struct cfg80211_registered_device *drv;
829 int err;
830 struct net_device *dev;
831 struct beacon_parameters params;
832 int haveinfo = 0;
833
bba95fef 834 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
ed1b6cc7
JB
835 if (err)
836 return err;
837
838 switch (info->genlhdr->cmd) {
839 case NL80211_CMD_NEW_BEACON:
840 /* these are required for NEW_BEACON */
841 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
842 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
843 !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
844 err = -EINVAL;
845 goto out;
846 }
847
848 call = drv->ops->add_beacon;
849 break;
850 case NL80211_CMD_SET_BEACON:
851 call = drv->ops->set_beacon;
852 break;
853 default:
854 WARN_ON(1);
855 err = -EOPNOTSUPP;
856 goto out;
857 }
858
859 if (!call) {
860 err = -EOPNOTSUPP;
861 goto out;
862 }
863
864 memset(&params, 0, sizeof(params));
865
866 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
867 params.interval =
868 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
869 haveinfo = 1;
870 }
871
872 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
873 params.dtim_period =
874 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
875 haveinfo = 1;
876 }
877
878 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
879 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
880 params.head_len =
881 nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
882 haveinfo = 1;
883 }
884
885 if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
886 params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
887 params.tail_len =
888 nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
889 haveinfo = 1;
890 }
891
892 if (!haveinfo) {
893 err = -EINVAL;
894 goto out;
895 }
896
897 rtnl_lock();
898 err = call(&drv->wiphy, dev, &params);
899 rtnl_unlock();
900
901 out:
902 cfg80211_put_dev(drv);
903 dev_put(dev);
904 return err;
905}
906
907static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
908{
909 struct cfg80211_registered_device *drv;
910 int err;
911 struct net_device *dev;
912
bba95fef 913 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
ed1b6cc7
JB
914 if (err)
915 return err;
916
917 if (!drv->ops->del_beacon) {
918 err = -EOPNOTSUPP;
919 goto out;
920 }
921
922 rtnl_lock();
923 err = drv->ops->del_beacon(&drv->wiphy, dev);
924 rtnl_unlock();
925
926 out:
927 cfg80211_put_dev(drv);
928 dev_put(dev);
929 return err;
930}
931
5727ef1b
JB
932static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
933 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
934 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
935 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
936};
937
938static int parse_station_flags(struct nlattr *nla, u32 *staflags)
939{
940 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
941 int flag;
942
943 *staflags = 0;
944
945 if (!nla)
946 return 0;
947
948 if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
949 nla, sta_flags_policy))
950 return -EINVAL;
951
952 *staflags = STATION_FLAG_CHANGED;
953
954 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
955 if (flags[flag])
956 *staflags |= (1<<flag);
957
958 return 0;
959}
960
fd5b74dc
JB
961static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
962 int flags, struct net_device *dev,
2ec600d6 963 u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
964{
965 void *hdr;
2ec600d6 966 struct nlattr *sinfoattr;
fd5b74dc
JB
967
968 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
969 if (!hdr)
970 return -1;
971
972 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
973 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
974
2ec600d6
LCC
975 sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
976 if (!sinfoattr)
fd5b74dc 977 goto nla_put_failure;
2ec600d6
LCC
978 if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
979 NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
980 sinfo->inactive_time);
981 if (sinfo->filled & STATION_INFO_RX_BYTES)
982 NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
983 sinfo->rx_bytes);
984 if (sinfo->filled & STATION_INFO_TX_BYTES)
985 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
986 sinfo->tx_bytes);
987 if (sinfo->filled & STATION_INFO_LLID)
988 NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
989 sinfo->llid);
990 if (sinfo->filled & STATION_INFO_PLID)
991 NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
992 sinfo->plid);
993 if (sinfo->filled & STATION_INFO_PLINK_STATE)
994 NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
995 sinfo->plink_state);
996
997 nla_nest_end(msg, sinfoattr);
fd5b74dc
JB
998
999 return genlmsg_end(msg, hdr);
1000
1001 nla_put_failure:
bc3ed28c
TG
1002 genlmsg_cancel(msg, hdr);
1003 return -EMSGSIZE;
fd5b74dc
JB
1004}
1005
2ec600d6 1006static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 1007 struct netlink_callback *cb)
2ec600d6 1008{
2ec600d6
LCC
1009 struct station_info sinfo;
1010 struct cfg80211_registered_device *dev;
bba95fef 1011 struct net_device *netdev;
2ec600d6 1012 u8 mac_addr[ETH_ALEN];
bba95fef
JB
1013 int ifidx = cb->args[0];
1014 int sta_idx = cb->args[1];
2ec600d6 1015 int err;
2ec600d6 1016
bba95fef
JB
1017 if (!ifidx) {
1018 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1019 nl80211_fam.attrbuf, nl80211_fam.maxattr,
1020 nl80211_policy);
1021 if (err)
1022 return err;
2ec600d6 1023
bba95fef
JB
1024 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1025 return -EINVAL;
2ec600d6 1026
bba95fef
JB
1027 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1028 if (!ifidx)
1029 return -EINVAL;
2ec600d6 1030 }
2ec600d6 1031
bba95fef
JB
1032 netdev = dev_get_by_index(&init_net, ifidx);
1033 if (!netdev)
1034 return -ENODEV;
2ec600d6 1035
bba95fef
JB
1036 dev = cfg80211_get_dev_from_ifindex(ifidx);
1037 if (IS_ERR(dev)) {
1038 err = PTR_ERR(dev);
1039 goto out_put_netdev;
1040 }
1041
1042 if (!dev->ops->dump_station) {
1043 err = -ENOSYS;
1044 goto out_err;
1045 }
1046
1047 rtnl_lock();
1048
1049 while (1) {
1050 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
1051 mac_addr, &sinfo);
1052 if (err == -ENOENT)
1053 break;
1054 if (err)
1055 goto out_err_rtnl;
1056
1057 if (nl80211_send_station(skb,
1058 NETLINK_CB(cb->skb).pid,
1059 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1060 netdev, mac_addr,
1061 &sinfo) < 0)
1062 goto out;
1063
1064 sta_idx++;
1065 }
1066
1067
1068 out:
1069 cb->args[1] = sta_idx;
1070 err = skb->len;
1071 out_err_rtnl:
1072 rtnl_unlock();
1073 out_err:
1074 cfg80211_put_dev(dev);
1075 out_put_netdev:
1076 dev_put(netdev);
1077
1078 return err;
2ec600d6 1079}
fd5b74dc 1080
5727ef1b
JB
1081static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1082{
fd5b74dc
JB
1083 struct cfg80211_registered_device *drv;
1084 int err;
1085 struct net_device *dev;
2ec600d6 1086 struct station_info sinfo;
fd5b74dc
JB
1087 struct sk_buff *msg;
1088 u8 *mac_addr = NULL;
1089
2ec600d6 1090 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc
JB
1091
1092 if (!info->attrs[NL80211_ATTR_MAC])
1093 return -EINVAL;
1094
1095 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1096
bba95fef 1097 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
fd5b74dc
JB
1098 if (err)
1099 return err;
1100
1101 if (!drv->ops->get_station) {
1102 err = -EOPNOTSUPP;
1103 goto out;
1104 }
1105
1106 rtnl_lock();
2ec600d6 1107 err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
fd5b74dc
JB
1108 rtnl_unlock();
1109
2ec600d6
LCC
1110 if (err)
1111 goto out;
1112
fd5b74dc
JB
1113 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1114 if (!msg)
1115 goto out;
1116
1117 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
2ec600d6 1118 dev, mac_addr, &sinfo) < 0)
fd5b74dc
JB
1119 goto out_free;
1120
1121 err = genlmsg_unicast(msg, info->snd_pid);
1122 goto out;
1123
1124 out_free:
1125 nlmsg_free(msg);
1126
1127 out:
1128 cfg80211_put_dev(drv);
1129 dev_put(dev);
1130 return err;
5727ef1b
JB
1131}
1132
1133/*
1134 * Get vlan interface making sure it is on the right wiphy.
1135 */
1136static int get_vlan(struct nlattr *vlanattr,
1137 struct cfg80211_registered_device *rdev,
1138 struct net_device **vlan)
1139{
1140 *vlan = NULL;
1141
1142 if (vlanattr) {
1143 *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
1144 if (!*vlan)
1145 return -ENODEV;
1146 if (!(*vlan)->ieee80211_ptr)
1147 return -EINVAL;
1148 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
1149 return -EINVAL;
1150 }
1151 return 0;
1152}
1153
1154static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1155{
1156 struct cfg80211_registered_device *drv;
1157 int err;
1158 struct net_device *dev;
1159 struct station_parameters params;
1160 u8 *mac_addr = NULL;
1161
1162 memset(&params, 0, sizeof(params));
1163
1164 params.listen_interval = -1;
1165
1166 if (info->attrs[NL80211_ATTR_STA_AID])
1167 return -EINVAL;
1168
1169 if (!info->attrs[NL80211_ATTR_MAC])
1170 return -EINVAL;
1171
1172 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1173
1174 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
1175 params.supported_rates =
1176 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1177 params.supported_rates_len =
1178 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1179 }
1180
1181 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1182 params.listen_interval =
1183 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1184
36aedc90
JM
1185 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
1186 params.ht_capa =
1187 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
1188
5727ef1b
JB
1189 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1190 &params.station_flags))
1191 return -EINVAL;
1192
2ec600d6
LCC
1193 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
1194 params.plink_action =
1195 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
1196
bba95fef 1197 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
5727ef1b
JB
1198 if (err)
1199 return err;
1200
1201 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1202 if (err)
1203 goto out;
1204
1205 if (!drv->ops->change_station) {
1206 err = -EOPNOTSUPP;
1207 goto out;
1208 }
1209
1210 rtnl_lock();
1211 err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
1212 rtnl_unlock();
1213
1214 out:
1215 if (params.vlan)
1216 dev_put(params.vlan);
1217 cfg80211_put_dev(drv);
1218 dev_put(dev);
1219 return err;
1220}
1221
1222static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1223{
1224 struct cfg80211_registered_device *drv;
1225 int err;
1226 struct net_device *dev;
1227 struct station_parameters params;
1228 u8 *mac_addr = NULL;
1229
1230 memset(&params, 0, sizeof(params));
1231
1232 if (!info->attrs[NL80211_ATTR_MAC])
1233 return -EINVAL;
1234
1235 if (!info->attrs[NL80211_ATTR_STA_AID])
1236 return -EINVAL;
1237
1238 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1239 return -EINVAL;
1240
1241 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
1242 return -EINVAL;
1243
1244 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1245 params.supported_rates =
1246 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1247 params.supported_rates_len =
1248 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1249 params.listen_interval =
1250 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
16f2e85d 1251 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
36aedc90
JM
1252 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
1253 params.ht_capa =
1254 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b
JB
1255
1256 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1257 &params.station_flags))
1258 return -EINVAL;
1259
bba95fef 1260 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
5727ef1b
JB
1261 if (err)
1262 return err;
1263
1264 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1265 if (err)
1266 goto out;
1267
1268 if (!drv->ops->add_station) {
1269 err = -EOPNOTSUPP;
1270 goto out;
1271 }
1272
1273 rtnl_lock();
1274 err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
1275 rtnl_unlock();
1276
1277 out:
1278 if (params.vlan)
1279 dev_put(params.vlan);
1280 cfg80211_put_dev(drv);
1281 dev_put(dev);
1282 return err;
1283}
1284
1285static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1286{
1287 struct cfg80211_registered_device *drv;
1288 int err;
1289 struct net_device *dev;
1290 u8 *mac_addr = NULL;
1291
1292 if (info->attrs[NL80211_ATTR_MAC])
1293 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1294
bba95fef 1295 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
5727ef1b
JB
1296 if (err)
1297 return err;
1298
1299 if (!drv->ops->del_station) {
1300 err = -EOPNOTSUPP;
1301 goto out;
1302 }
1303
1304 rtnl_lock();
1305 err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1306 rtnl_unlock();
1307
1308 out:
1309 cfg80211_put_dev(drv);
1310 dev_put(dev);
1311 return err;
1312}
1313
2ec600d6
LCC
1314static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
1315 int flags, struct net_device *dev,
1316 u8 *dst, u8 *next_hop,
1317 struct mpath_info *pinfo)
1318{
1319 void *hdr;
1320 struct nlattr *pinfoattr;
1321
1322 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
1323 if (!hdr)
1324 return -1;
1325
1326 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1327 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
1328 NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
1329
1330 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
1331 if (!pinfoattr)
1332 goto nla_put_failure;
1333 if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
1334 NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
1335 pinfo->frame_qlen);
1336 if (pinfo->filled & MPATH_INFO_DSN)
1337 NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
1338 pinfo->dsn);
1339 if (pinfo->filled & MPATH_INFO_METRIC)
1340 NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
1341 pinfo->metric);
1342 if (pinfo->filled & MPATH_INFO_EXPTIME)
1343 NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
1344 pinfo->exptime);
1345 if (pinfo->filled & MPATH_INFO_FLAGS)
1346 NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
1347 pinfo->flags);
1348 if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
1349 NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
1350 pinfo->discovery_timeout);
1351 if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
1352 NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
1353 pinfo->discovery_retries);
1354
1355 nla_nest_end(msg, pinfoattr);
1356
1357 return genlmsg_end(msg, hdr);
1358
1359 nla_put_failure:
bc3ed28c
TG
1360 genlmsg_cancel(msg, hdr);
1361 return -EMSGSIZE;
2ec600d6
LCC
1362}
1363
1364static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 1365 struct netlink_callback *cb)
2ec600d6 1366{
2ec600d6
LCC
1367 struct mpath_info pinfo;
1368 struct cfg80211_registered_device *dev;
bba95fef 1369 struct net_device *netdev;
2ec600d6
LCC
1370 u8 dst[ETH_ALEN];
1371 u8 next_hop[ETH_ALEN];
bba95fef
JB
1372 int ifidx = cb->args[0];
1373 int path_idx = cb->args[1];
2ec600d6 1374 int err;
2ec600d6 1375
bba95fef
JB
1376 if (!ifidx) {
1377 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1378 nl80211_fam.attrbuf, nl80211_fam.maxattr,
1379 nl80211_policy);
1380 if (err)
1381 return err;
1382
1383 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1384 return -EINVAL;
1385
1386 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1387 if (!ifidx)
1388 return -EINVAL;
1389 }
1390
1391 netdev = dev_get_by_index(&init_net, ifidx);
1392 if (!netdev)
1393 return -ENODEV;
1394
1395 dev = cfg80211_get_dev_from_ifindex(ifidx);
1396 if (IS_ERR(dev)) {
1397 err = PTR_ERR(dev);
1398 goto out_put_netdev;
1399 }
1400
1401 if (!dev->ops->dump_mpath) {
1402 err = -ENOSYS;
1403 goto out_err;
1404 }
1405
1406 rtnl_lock();
1407
1408 while (1) {
1409 err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
1410 dst, next_hop, &pinfo);
1411 if (err == -ENOENT)
2ec600d6 1412 break;
bba95fef
JB
1413 if (err)
1414 goto out_err_rtnl;
2ec600d6 1415
bba95fef
JB
1416 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid,
1417 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1418 netdev, dst, next_hop,
1419 &pinfo) < 0)
1420 goto out;
2ec600d6 1421
bba95fef 1422 path_idx++;
2ec600d6 1423 }
2ec600d6 1424
2ec600d6 1425
bba95fef
JB
1426 out:
1427 cb->args[1] = path_idx;
1428 err = skb->len;
1429 out_err_rtnl:
1430 rtnl_unlock();
1431 out_err:
1432 cfg80211_put_dev(dev);
1433 out_put_netdev:
1434 dev_put(netdev);
1435
1436 return err;
2ec600d6
LCC
1437}
1438
1439static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
1440{
1441 struct cfg80211_registered_device *drv;
1442 int err;
1443 struct net_device *dev;
1444 struct mpath_info pinfo;
1445 struct sk_buff *msg;
1446 u8 *dst = NULL;
1447 u8 next_hop[ETH_ALEN];
1448
1449 memset(&pinfo, 0, sizeof(pinfo));
1450
1451 if (!info->attrs[NL80211_ATTR_MAC])
1452 return -EINVAL;
1453
1454 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1455
bba95fef 1456 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2ec600d6
LCC
1457 if (err)
1458 return err;
1459
1460 if (!drv->ops->get_mpath) {
1461 err = -EOPNOTSUPP;
1462 goto out;
1463 }
1464
1465 rtnl_lock();
1466 err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
1467 rtnl_unlock();
1468
1469 if (err)
1470 goto out;
1471
1472 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1473 if (!msg)
1474 goto out;
1475
1476 if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
1477 dev, dst, next_hop, &pinfo) < 0)
1478 goto out_free;
1479
1480 err = genlmsg_unicast(msg, info->snd_pid);
1481 goto out;
1482
1483 out_free:
1484 nlmsg_free(msg);
1485
1486 out:
1487 cfg80211_put_dev(drv);
1488 dev_put(dev);
1489 return err;
1490}
1491
1492static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
1493{
1494 struct cfg80211_registered_device *drv;
1495 int err;
1496 struct net_device *dev;
1497 u8 *dst = NULL;
1498 u8 *next_hop = NULL;
1499
1500 if (!info->attrs[NL80211_ATTR_MAC])
1501 return -EINVAL;
1502
1503 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
1504 return -EINVAL;
1505
1506 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1507 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1508
bba95fef 1509 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2ec600d6
LCC
1510 if (err)
1511 return err;
1512
1513 if (!drv->ops->change_mpath) {
1514 err = -EOPNOTSUPP;
1515 goto out;
1516 }
1517
1518 rtnl_lock();
1519 err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
1520 rtnl_unlock();
1521
1522 out:
1523 cfg80211_put_dev(drv);
1524 dev_put(dev);
1525 return err;
1526}
1527static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
1528{
1529 struct cfg80211_registered_device *drv;
1530 int err;
1531 struct net_device *dev;
1532 u8 *dst = NULL;
1533 u8 *next_hop = NULL;
1534
1535 if (!info->attrs[NL80211_ATTR_MAC])
1536 return -EINVAL;
1537
1538 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
1539 return -EINVAL;
1540
1541 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1542 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
1543
bba95fef 1544 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2ec600d6
LCC
1545 if (err)
1546 return err;
1547
1548 if (!drv->ops->add_mpath) {
1549 err = -EOPNOTSUPP;
1550 goto out;
1551 }
1552
1553 rtnl_lock();
1554 err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
1555 rtnl_unlock();
1556
1557 out:
1558 cfg80211_put_dev(drv);
1559 dev_put(dev);
1560 return err;
1561}
1562
1563static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
1564{
1565 struct cfg80211_registered_device *drv;
1566 int err;
1567 struct net_device *dev;
1568 u8 *dst = NULL;
1569
1570 if (info->attrs[NL80211_ATTR_MAC])
1571 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
1572
bba95fef 1573 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2ec600d6
LCC
1574 if (err)
1575 return err;
1576
1577 if (!drv->ops->del_mpath) {
1578 err = -EOPNOTSUPP;
1579 goto out;
1580 }
1581
1582 rtnl_lock();
1583 err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
1584 rtnl_unlock();
1585
1586 out:
1587 cfg80211_put_dev(drv);
1588 dev_put(dev);
1589 return err;
1590}
1591
9f1ba906
JM
1592static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
1593{
1594 struct cfg80211_registered_device *drv;
1595 int err;
1596 struct net_device *dev;
1597 struct bss_parameters params;
1598
1599 memset(&params, 0, sizeof(params));
1600 /* default to not changing parameters */
1601 params.use_cts_prot = -1;
1602 params.use_short_preamble = -1;
1603 params.use_short_slot_time = -1;
1604
1605 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
1606 params.use_cts_prot =
1607 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
1608 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
1609 params.use_short_preamble =
1610 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
1611 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
1612 params.use_short_slot_time =
1613 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
1614
1615 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
1616 if (err)
1617 return err;
1618
1619 if (!drv->ops->change_bss) {
1620 err = -EOPNOTSUPP;
1621 goto out;
1622 }
1623
1624 rtnl_lock();
1625 err = drv->ops->change_bss(&drv->wiphy, dev, &params);
1626 rtnl_unlock();
1627
1628 out:
1629 cfg80211_put_dev(drv);
1630 dev_put(dev);
1631 return err;
1632}
1633
b2e1b302
LR
1634static const struct nla_policy
1635 reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
1636 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
1637 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
1638 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
1639 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
1640 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
1641 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
1642};
1643
1644static int parse_reg_rule(struct nlattr *tb[],
1645 struct ieee80211_reg_rule *reg_rule)
1646{
1647 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
1648 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
1649
1650 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
1651 return -EINVAL;
1652 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
1653 return -EINVAL;
1654 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
1655 return -EINVAL;
1656 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
1657 return -EINVAL;
1658 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
1659 return -EINVAL;
1660
1661 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
1662
1663 freq_range->start_freq_khz =
1664 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
1665 freq_range->end_freq_khz =
1666 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
1667 freq_range->max_bandwidth_khz =
1668 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
1669
1670 power_rule->max_eirp =
1671 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
1672
1673 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
1674 power_rule->max_antenna_gain =
1675 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
1676
1677 return 0;
1678}
1679
1680static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
1681{
1682 int r;
1683 char *data = NULL;
1684
1685 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
1686 return -EINVAL;
1687
1688 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
1689
1690#ifdef CONFIG_WIRELESS_OLD_REGULATORY
1691 /* We ignore world regdom requests with the old regdom setup */
1692 if (is_world_regdom(data))
1693 return -EINVAL;
1694#endif
1695 mutex_lock(&cfg80211_drv_mutex);
1696 r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, NULL);
1697 mutex_unlock(&cfg80211_drv_mutex);
1698 return r;
1699}
1700
1701static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
1702{
1703 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
1704 struct nlattr *nl_reg_rule;
1705 char *alpha2 = NULL;
1706 int rem_reg_rules = 0, r = 0;
1707 u32 num_rules = 0, rule_idx = 0, size_of_regd;
1708 struct ieee80211_regdomain *rd = NULL;
1709
1710 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
1711 return -EINVAL;
1712
1713 if (!info->attrs[NL80211_ATTR_REG_RULES])
1714 return -EINVAL;
1715
1716 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
1717
1718 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1719 rem_reg_rules) {
1720 num_rules++;
1721 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
1722 goto bad_reg;
1723 }
1724
1725 if (!reg_is_valid_request(alpha2))
1726 return -EINVAL;
1727
1728 size_of_regd = sizeof(struct ieee80211_regdomain) +
1729 (num_rules * sizeof(struct ieee80211_reg_rule));
1730
1731 rd = kzalloc(size_of_regd, GFP_KERNEL);
1732 if (!rd)
1733 return -ENOMEM;
1734
1735 rd->n_reg_rules = num_rules;
1736 rd->alpha2[0] = alpha2[0];
1737 rd->alpha2[1] = alpha2[1];
1738
1739 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1740 rem_reg_rules) {
1741 nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
1742 nla_data(nl_reg_rule), nla_len(nl_reg_rule),
1743 reg_rule_policy);
1744 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
1745 if (r)
1746 goto bad_reg;
1747
1748 rule_idx++;
1749
1750 if (rule_idx > NL80211_MAX_SUPP_REG_RULES)
1751 goto bad_reg;
1752 }
1753
1754 BUG_ON(rule_idx != num_rules);
1755
1756 mutex_lock(&cfg80211_drv_mutex);
1757 r = set_regdom(rd);
1758 mutex_unlock(&cfg80211_drv_mutex);
1759 if (r)
1760 goto bad_reg;
1761
1762 return r;
1763
1764bad_reg:
1765 kfree(rd);
1766 return -EINVAL;
1767}
1768
55682965
JB
1769static struct genl_ops nl80211_ops[] = {
1770 {
1771 .cmd = NL80211_CMD_GET_WIPHY,
1772 .doit = nl80211_get_wiphy,
1773 .dumpit = nl80211_dump_wiphy,
1774 .policy = nl80211_policy,
1775 /* can be retrieved by unprivileged users */
1776 },
1777 {
1778 .cmd = NL80211_CMD_SET_WIPHY,
1779 .doit = nl80211_set_wiphy,
1780 .policy = nl80211_policy,
1781 .flags = GENL_ADMIN_PERM,
1782 },
1783 {
1784 .cmd = NL80211_CMD_GET_INTERFACE,
1785 .doit = nl80211_get_interface,
1786 .dumpit = nl80211_dump_interface,
1787 .policy = nl80211_policy,
1788 /* can be retrieved by unprivileged users */
1789 },
1790 {
1791 .cmd = NL80211_CMD_SET_INTERFACE,
1792 .doit = nl80211_set_interface,
1793 .policy = nl80211_policy,
1794 .flags = GENL_ADMIN_PERM,
1795 },
1796 {
1797 .cmd = NL80211_CMD_NEW_INTERFACE,
1798 .doit = nl80211_new_interface,
1799 .policy = nl80211_policy,
1800 .flags = GENL_ADMIN_PERM,
1801 },
1802 {
1803 .cmd = NL80211_CMD_DEL_INTERFACE,
1804 .doit = nl80211_del_interface,
1805 .policy = nl80211_policy,
41ade00f
JB
1806 .flags = GENL_ADMIN_PERM,
1807 },
1808 {
1809 .cmd = NL80211_CMD_GET_KEY,
1810 .doit = nl80211_get_key,
1811 .policy = nl80211_policy,
1812 .flags = GENL_ADMIN_PERM,
1813 },
1814 {
1815 .cmd = NL80211_CMD_SET_KEY,
1816 .doit = nl80211_set_key,
1817 .policy = nl80211_policy,
1818 .flags = GENL_ADMIN_PERM,
1819 },
1820 {
1821 .cmd = NL80211_CMD_NEW_KEY,
1822 .doit = nl80211_new_key,
1823 .policy = nl80211_policy,
1824 .flags = GENL_ADMIN_PERM,
1825 },
1826 {
1827 .cmd = NL80211_CMD_DEL_KEY,
1828 .doit = nl80211_del_key,
1829 .policy = nl80211_policy,
55682965
JB
1830 .flags = GENL_ADMIN_PERM,
1831 },
ed1b6cc7
JB
1832 {
1833 .cmd = NL80211_CMD_SET_BEACON,
1834 .policy = nl80211_policy,
1835 .flags = GENL_ADMIN_PERM,
1836 .doit = nl80211_addset_beacon,
1837 },
1838 {
1839 .cmd = NL80211_CMD_NEW_BEACON,
1840 .policy = nl80211_policy,
1841 .flags = GENL_ADMIN_PERM,
1842 .doit = nl80211_addset_beacon,
1843 },
1844 {
1845 .cmd = NL80211_CMD_DEL_BEACON,
1846 .policy = nl80211_policy,
1847 .flags = GENL_ADMIN_PERM,
1848 .doit = nl80211_del_beacon,
1849 },
5727ef1b
JB
1850 {
1851 .cmd = NL80211_CMD_GET_STATION,
1852 .doit = nl80211_get_station,
2ec600d6 1853 .dumpit = nl80211_dump_station,
5727ef1b
JB
1854 .policy = nl80211_policy,
1855 .flags = GENL_ADMIN_PERM,
1856 },
1857 {
1858 .cmd = NL80211_CMD_SET_STATION,
1859 .doit = nl80211_set_station,
1860 .policy = nl80211_policy,
1861 .flags = GENL_ADMIN_PERM,
1862 },
1863 {
1864 .cmd = NL80211_CMD_NEW_STATION,
1865 .doit = nl80211_new_station,
1866 .policy = nl80211_policy,
1867 .flags = GENL_ADMIN_PERM,
1868 },
1869 {
1870 .cmd = NL80211_CMD_DEL_STATION,
1871 .doit = nl80211_del_station,
1872 .policy = nl80211_policy,
2ec600d6
LCC
1873 .flags = GENL_ADMIN_PERM,
1874 },
1875 {
1876 .cmd = NL80211_CMD_GET_MPATH,
1877 .doit = nl80211_get_mpath,
1878 .dumpit = nl80211_dump_mpath,
1879 .policy = nl80211_policy,
1880 .flags = GENL_ADMIN_PERM,
1881 },
1882 {
1883 .cmd = NL80211_CMD_SET_MPATH,
1884 .doit = nl80211_set_mpath,
1885 .policy = nl80211_policy,
1886 .flags = GENL_ADMIN_PERM,
1887 },
1888 {
1889 .cmd = NL80211_CMD_NEW_MPATH,
1890 .doit = nl80211_new_mpath,
1891 .policy = nl80211_policy,
1892 .flags = GENL_ADMIN_PERM,
1893 },
1894 {
1895 .cmd = NL80211_CMD_DEL_MPATH,
1896 .doit = nl80211_del_mpath,
1897 .policy = nl80211_policy,
9f1ba906
JM
1898 .flags = GENL_ADMIN_PERM,
1899 },
1900 {
1901 .cmd = NL80211_CMD_SET_BSS,
1902 .doit = nl80211_set_bss,
1903 .policy = nl80211_policy,
b2e1b302
LR
1904 .flags = GENL_ADMIN_PERM,
1905 },
1906 {
1907 .cmd = NL80211_CMD_SET_REG,
1908 .doit = nl80211_set_reg,
1909 .policy = nl80211_policy,
1910 .flags = GENL_ADMIN_PERM,
1911 },
1912 {
1913 .cmd = NL80211_CMD_REQ_SET_REG,
1914 .doit = nl80211_req_set_reg,
1915 .policy = nl80211_policy,
5727ef1b
JB
1916 .flags = GENL_ADMIN_PERM,
1917 },
55682965
JB
1918};
1919
1920/* multicast groups */
1921static struct genl_multicast_group nl80211_config_mcgrp = {
1922 .name = "config",
1923};
1924
1925/* notification functions */
1926
1927void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
1928{
1929 struct sk_buff *msg;
1930
1931 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1932 if (!msg)
1933 return;
1934
1935 if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
1936 nlmsg_free(msg);
1937 return;
1938 }
1939
1940 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
1941}
1942
1943/* initialisation/exit functions */
1944
1945int nl80211_init(void)
1946{
1947 int err, i;
1948
1949 err = genl_register_family(&nl80211_fam);
1950 if (err)
1951 return err;
1952
1953 for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
1954 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
1955 if (err)
1956 goto err_out;
1957 }
1958
1959 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
1960 if (err)
1961 goto err_out;
1962
1963 return 0;
1964 err_out:
1965 genl_unregister_family(&nl80211_fam);
1966 return err;
1967}
1968
1969void nl80211_exit(void)
1970{
1971 genl_unregister_family(&nl80211_fam);
1972}