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