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