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