Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wext-core.c
Go to the documentation of this file.
1 /*
2  * This file implement the Wireless Extensions core API.
3  *
4  * Authors : Jean Tourrilhes - HPL - <[email protected]>
5  * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
6  * Copyright 2009 Johannes Berg <[email protected]>
7  *
8  * (As all part of the Linux kernel, this file is GPL)
9  */
10 #include <linux/kernel.h>
11 #include <linux/netdevice.h>
12 #include <linux/rtnetlink.h>
13 #include <linux/slab.h>
14 #include <linux/wireless.h>
15 #include <linux/uaccess.h>
16 #include <linux/export.h>
17 #include <net/cfg80211.h>
18 #include <net/iw_handler.h>
19 #include <net/netlink.h>
20 #include <net/wext.h>
21 #include <net/net_namespace.h>
22 
23 typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *,
24  unsigned int, struct iw_request_info *,
25  iw_handler);
26 
27 
28 /*
29  * Meta-data about all the standard Wireless Extension request we
30  * know about.
31  */
32 static const struct iw_ioctl_description standard_ioctl[] = {
34  .header_type = IW_HEADER_TYPE_NULL,
35  },
37  .header_type = IW_HEADER_TYPE_CHAR,
38  .flags = IW_DESCR_FLAG_DUMP,
39  },
41  .header_type = IW_HEADER_TYPE_PARAM,
42  .flags = IW_DESCR_FLAG_EVENT,
43  },
45  .header_type = IW_HEADER_TYPE_PARAM,
46  .flags = IW_DESCR_FLAG_DUMP,
47  },
49  .header_type = IW_HEADER_TYPE_FREQ,
50  .flags = IW_DESCR_FLAG_EVENT,
51  },
53  .header_type = IW_HEADER_TYPE_FREQ,
54  .flags = IW_DESCR_FLAG_DUMP,
55  },
57  .header_type = IW_HEADER_TYPE_UINT,
58  .flags = IW_DESCR_FLAG_EVENT,
59  },
61  .header_type = IW_HEADER_TYPE_UINT,
62  .flags = IW_DESCR_FLAG_DUMP,
63  },
65  .header_type = IW_HEADER_TYPE_PARAM,
66  },
68  .header_type = IW_HEADER_TYPE_PARAM,
69  },
71  .header_type = IW_HEADER_TYPE_NULL,
72  },
74  .header_type = IW_HEADER_TYPE_POINT,
75  .token_size = 1,
76  .max_tokens = sizeof(struct iw_range),
77  .flags = IW_DESCR_FLAG_DUMP,
78  },
80  .header_type = IW_HEADER_TYPE_NULL,
81  },
82  [IW_IOCTL_IDX(SIOCGIWPRIV)] = { /* (handled directly by us) */
83  .header_type = IW_HEADER_TYPE_POINT,
84  .token_size = sizeof(struct iw_priv_args),
85  .max_tokens = 16,
86  .flags = IW_DESCR_FLAG_NOMAX,
87  },
89  .header_type = IW_HEADER_TYPE_NULL,
90  },
91  [IW_IOCTL_IDX(SIOCGIWSTATS)] = { /* (handled directly by us) */
92  .header_type = IW_HEADER_TYPE_POINT,
93  .token_size = 1,
94  .max_tokens = sizeof(struct iw_statistics),
95  .flags = IW_DESCR_FLAG_DUMP,
96  },
98  .header_type = IW_HEADER_TYPE_POINT,
99  .token_size = sizeof(struct sockaddr),
100  .max_tokens = IW_MAX_SPY,
101  },
102  [IW_IOCTL_IDX(SIOCGIWSPY)] = {
103  .header_type = IW_HEADER_TYPE_POINT,
104  .token_size = sizeof(struct sockaddr) +
105  sizeof(struct iw_quality),
106  .max_tokens = IW_MAX_SPY,
107  },
109  .header_type = IW_HEADER_TYPE_POINT,
110  .token_size = sizeof(struct iw_thrspy),
111  .min_tokens = 1,
112  .max_tokens = 1,
113  },
115  .header_type = IW_HEADER_TYPE_POINT,
116  .token_size = sizeof(struct iw_thrspy),
117  .min_tokens = 1,
118  .max_tokens = 1,
119  },
120  [IW_IOCTL_IDX(SIOCSIWAP)] = {
121  .header_type = IW_HEADER_TYPE_ADDR,
122  },
123  [IW_IOCTL_IDX(SIOCGIWAP)] = {
124  .header_type = IW_HEADER_TYPE_ADDR,
125  .flags = IW_DESCR_FLAG_DUMP,
126  },
128  .header_type = IW_HEADER_TYPE_POINT,
129  .token_size = 1,
130  .min_tokens = sizeof(struct iw_mlme),
131  .max_tokens = sizeof(struct iw_mlme),
132  },
133  [IW_IOCTL_IDX(SIOCGIWAPLIST)] = {
134  .header_type = IW_HEADER_TYPE_POINT,
135  .token_size = sizeof(struct sockaddr) +
136  sizeof(struct iw_quality),
137  .max_tokens = IW_MAX_AP,
138  .flags = IW_DESCR_FLAG_NOMAX,
139  },
141  .header_type = IW_HEADER_TYPE_POINT,
142  .token_size = 1,
143  .min_tokens = 0,
144  .max_tokens = sizeof(struct iw_scan_req),
145  },
146  [IW_IOCTL_IDX(SIOCGIWSCAN)] = {
147  .header_type = IW_HEADER_TYPE_POINT,
148  .token_size = 1,
149  .max_tokens = IW_SCAN_MAX_DATA,
150  .flags = IW_DESCR_FLAG_NOMAX,
151  },
153  .header_type = IW_HEADER_TYPE_POINT,
154  .token_size = 1,
155  .max_tokens = IW_ESSID_MAX_SIZE,
156  .flags = IW_DESCR_FLAG_EVENT,
157  },
159  .header_type = IW_HEADER_TYPE_POINT,
160  .token_size = 1,
161  .max_tokens = IW_ESSID_MAX_SIZE,
162  .flags = IW_DESCR_FLAG_DUMP,
163  },
165  .header_type = IW_HEADER_TYPE_POINT,
166  .token_size = 1,
167  .max_tokens = IW_ESSID_MAX_SIZE,
168  },
170  .header_type = IW_HEADER_TYPE_POINT,
171  .token_size = 1,
172  .max_tokens = IW_ESSID_MAX_SIZE,
173  },
175  .header_type = IW_HEADER_TYPE_PARAM,
176  },
178  .header_type = IW_HEADER_TYPE_PARAM,
179  },
180  [IW_IOCTL_IDX(SIOCSIWRTS)] = {
181  .header_type = IW_HEADER_TYPE_PARAM,
182  },
183  [IW_IOCTL_IDX(SIOCGIWRTS)] = {
184  .header_type = IW_HEADER_TYPE_PARAM,
185  },
187  .header_type = IW_HEADER_TYPE_PARAM,
188  },
190  .header_type = IW_HEADER_TYPE_PARAM,
191  },
193  .header_type = IW_HEADER_TYPE_PARAM,
194  },
196  .header_type = IW_HEADER_TYPE_PARAM,
197  },
199  .header_type = IW_HEADER_TYPE_PARAM,
200  },
202  .header_type = IW_HEADER_TYPE_PARAM,
203  },
205  .header_type = IW_HEADER_TYPE_POINT,
206  .token_size = 1,
207  .max_tokens = IW_ENCODING_TOKEN_MAX,
209  },
211  .header_type = IW_HEADER_TYPE_POINT,
212  .token_size = 1,
213  .max_tokens = IW_ENCODING_TOKEN_MAX,
215  },
217  .header_type = IW_HEADER_TYPE_PARAM,
218  },
220  .header_type = IW_HEADER_TYPE_PARAM,
221  },
223  .header_type = IW_HEADER_TYPE_POINT,
224  .token_size = 1,
225  .max_tokens = IW_GENERIC_IE_MAX,
226  },
228  .header_type = IW_HEADER_TYPE_POINT,
229  .token_size = 1,
230  .max_tokens = IW_GENERIC_IE_MAX,
231  },
233  .header_type = IW_HEADER_TYPE_PARAM,
234  },
236  .header_type = IW_HEADER_TYPE_PARAM,
237  },
239  .header_type = IW_HEADER_TYPE_POINT,
240  .token_size = 1,
241  .min_tokens = sizeof(struct iw_encode_ext),
242  .max_tokens = sizeof(struct iw_encode_ext) +
243  IW_ENCODING_TOKEN_MAX,
244  },
245  [IW_IOCTL_IDX(SIOCGIWENCODEEXT)] = {
246  .header_type = IW_HEADER_TYPE_POINT,
247  .token_size = 1,
248  .min_tokens = sizeof(struct iw_encode_ext),
249  .max_tokens = sizeof(struct iw_encode_ext) +
250  IW_ENCODING_TOKEN_MAX,
251  },
252  [IW_IOCTL_IDX(SIOCSIWPMKSA)] = {
253  .header_type = IW_HEADER_TYPE_POINT,
254  .token_size = 1,
255  .min_tokens = sizeof(struct iw_pmksa),
256  .max_tokens = sizeof(struct iw_pmksa),
257  },
258 };
259 static const unsigned int standard_ioctl_num = ARRAY_SIZE(standard_ioctl);
260 
261 /*
262  * Meta-data about all the additional standard Wireless Extension events
263  * we know about.
264  */
265 static const struct iw_ioctl_description standard_event[] = {
266  [IW_EVENT_IDX(IWEVTXDROP)] = {
268  },
269  [IW_EVENT_IDX(IWEVQUAL)] = {
270  .header_type = IW_HEADER_TYPE_QUAL,
271  },
272  [IW_EVENT_IDX(IWEVCUSTOM)] = {
273  .header_type = IW_HEADER_TYPE_POINT,
274  .token_size = 1,
275  .max_tokens = IW_CUSTOM_MAX,
276  },
278  .header_type = IW_HEADER_TYPE_ADDR,
279  },
281  .header_type = IW_HEADER_TYPE_ADDR,
282  },
283  [IW_EVENT_IDX(IWEVGENIE)] = {
284  .header_type = IW_HEADER_TYPE_POINT,
285  .token_size = 1,
286  .max_tokens = IW_GENERIC_IE_MAX,
287  },
289  .header_type = IW_HEADER_TYPE_POINT,
290  .token_size = 1,
291  .max_tokens = sizeof(struct iw_michaelmicfailure),
292  },
293  [IW_EVENT_IDX(IWEVASSOCREQIE)] = {
294  .header_type = IW_HEADER_TYPE_POINT,
295  .token_size = 1,
296  .max_tokens = IW_GENERIC_IE_MAX,
297  },
299  .header_type = IW_HEADER_TYPE_POINT,
300  .token_size = 1,
301  .max_tokens = IW_GENERIC_IE_MAX,
302  },
304  .header_type = IW_HEADER_TYPE_POINT,
305  .token_size = 1,
306  .max_tokens = sizeof(struct iw_pmkid_cand),
307  },
308 };
309 static const unsigned int standard_event_num = ARRAY_SIZE(standard_event);
310 
311 /* Size (in bytes) of various events */
312 static const int event_type_size[] = {
313  IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */
314  0,
315  IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
316  0,
317  IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */
318  IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */
319  IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */
320  0,
321  IW_EV_POINT_LEN, /* Without variable payload */
322  IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */
323  IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
324 };
325 
326 #ifdef CONFIG_COMPAT
327 static const int compat_event_type_size[] = {
328  IW_EV_COMPAT_LCP_LEN, /* IW_HEADER_TYPE_NULL */
329  0,
330  IW_EV_COMPAT_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
331  0,
332  IW_EV_COMPAT_UINT_LEN, /* IW_HEADER_TYPE_UINT */
333  IW_EV_COMPAT_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */
334  IW_EV_COMPAT_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */
335  0,
336  IW_EV_COMPAT_POINT_LEN, /* Without variable payload */
337  IW_EV_COMPAT_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */
338  IW_EV_COMPAT_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
339 };
340 #endif
341 
342 
343 /* IW event code */
344 
345 static int __net_init wext_pernet_init(struct net *net)
346 {
347  skb_queue_head_init(&net->wext_nlevents);
348  return 0;
349 }
350 
351 static void __net_exit wext_pernet_exit(struct net *net)
352 {
353  skb_queue_purge(&net->wext_nlevents);
354 }
355 
356 static struct pernet_operations wext_pernet_ops = {
357  .init = wext_pernet_init,
358  .exit = wext_pernet_exit,
359 };
360 
361 static int __init wireless_nlevent_init(void)
362 {
363  return register_pernet_subsys(&wext_pernet_ops);
364 }
365 
366 subsys_initcall(wireless_nlevent_init);
367 
368 /* Process events generated by the wireless layer or the driver. */
369 static void wireless_nlevent_process(struct work_struct *work)
370 {
371  struct sk_buff *skb;
372  struct net *net;
373 
374  rtnl_lock();
375 
376  for_each_net(net) {
377  while ((skb = skb_dequeue(&net->wext_nlevents)))
378  rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
379  GFP_KERNEL);
380  }
381 
382  rtnl_unlock();
383 }
384 
385 static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
386 
387 static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev,
388  struct sk_buff *skb)
389 {
390  struct ifinfomsg *r;
391  struct nlmsghdr *nlh;
392 
393  nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0);
394  if (!nlh)
395  return NULL;
396 
397  r = nlmsg_data(nlh);
398  r->ifi_family = AF_UNSPEC;
399  r->__ifi_pad = 0;
400  r->ifi_type = dev->type;
401  r->ifi_index = dev->ifindex;
402  r->ifi_flags = dev_get_flags(dev);
403  r->ifi_change = 0; /* Wireless changes don't affect those flags */
404 
405  if (nla_put_string(skb, IFLA_IFNAME, dev->name))
406  goto nla_put_failure;
407 
408  return nlh;
409  nla_put_failure:
410  nlmsg_cancel(skb, nlh);
411  return NULL;
412 }
413 
414 
415 /*
416  * Main event dispatcher. Called from other parts and drivers.
417  * Send the event on the appropriate channels.
418  * May be called from interrupt context.
419  */
420 void wireless_send_event(struct net_device * dev,
421  unsigned int cmd,
422  union iwreq_data * wrqu,
423  const char * extra)
424 {
425  const struct iw_ioctl_description * descr = NULL;
426  int extra_len = 0;
427  struct iw_event *event; /* Mallocated whole event */
428  int event_len; /* Its size */
429  int hdr_len; /* Size of the event header */
430  int wrqu_off = 0; /* Offset in wrqu */
431  /* Don't "optimise" the following variable, it will crash */
432  unsigned int cmd_index; /* *MUST* be unsigned */
433  struct sk_buff *skb;
434  struct nlmsghdr *nlh;
435  struct nlattr *nla;
436 #ifdef CONFIG_COMPAT
437  struct __compat_iw_event *compat_event;
438  struct compat_iw_point compat_wrqu;
439  struct sk_buff *compskb;
440 #endif
441 
442  /*
443  * Nothing in the kernel sends scan events with data, be safe.
444  * This is necessary because we cannot fix up scan event data
445  * for compat, due to being contained in 'extra', but normally
446  * applications are required to retrieve the scan data anyway
447  * and no data is included in the event, this codifies that
448  * practice.
449  */
450  if (WARN_ON(cmd == SIOCGIWSCAN && extra))
451  extra = NULL;
452 
453  /* Get the description of the Event */
454  if (cmd <= SIOCIWLAST) {
455  cmd_index = IW_IOCTL_IDX(cmd);
456  if (cmd_index < standard_ioctl_num)
457  descr = &(standard_ioctl[cmd_index]);
458  } else {
459  cmd_index = IW_EVENT_IDX(cmd);
460  if (cmd_index < standard_event_num)
461  descr = &(standard_event[cmd_index]);
462  }
463  /* Don't accept unknown events */
464  if (descr == NULL) {
465  /* Note : we don't return an error to the driver, because
466  * the driver would not know what to do about it. It can't
467  * return an error to the user, because the event is not
468  * initiated by a user request.
469  * The best the driver could do is to log an error message.
470  * We will do it ourselves instead...
471  */
472  netdev_err(dev, "(WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
473  cmd);
474  return;
475  }
476 
477  /* Check extra parameters and set extra_len */
478  if (descr->header_type == IW_HEADER_TYPE_POINT) {
479  /* Check if number of token fits within bounds */
480  if (wrqu->data.length > descr->max_tokens) {
481  netdev_err(dev, "(WE) : Wireless Event (cmd=0x%04X) too big (%d)\n",
482  cmd, wrqu->data.length);
483  return;
484  }
485  if (wrqu->data.length < descr->min_tokens) {
486  netdev_err(dev, "(WE) : Wireless Event (cmd=0x%04X) too small (%d)\n",
487  cmd, wrqu->data.length);
488  return;
489  }
490  /* Calculate extra_len - extra is NULL for restricted events */
491  if (extra != NULL)
492  extra_len = wrqu->data.length * descr->token_size;
493  /* Always at an offset in wrqu */
494  wrqu_off = IW_EV_POINT_OFF;
495  }
496 
497  /* Total length of the event */
498  hdr_len = event_type_size[descr->header_type];
499  event_len = hdr_len + extra_len;
500 
501  /*
502  * The problem for 64/32 bit.
503  *
504  * On 64-bit, a regular event is laid out as follows:
505  * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
506  * | event.len | event.cmd | p a d d i n g |
507  * | wrqu data ... (with the correct size) |
508  *
509  * This padding exists because we manipulate event->u,
510  * and 'event' is not packed.
511  *
512  * An iw_point event is laid out like this instead:
513  * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
514  * | event.len | event.cmd | p a d d i n g |
515  * | iwpnt.len | iwpnt.flg | p a d d i n g |
516  * | extra data ...
517  *
518  * The second padding exists because struct iw_point is extended,
519  * but this depends on the platform...
520  *
521  * On 32-bit, all the padding shouldn't be there.
522  */
523 
524  skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
525  if (!skb)
526  return;
527 
528  /* Send via the RtNetlink event channel */
529  nlh = rtnetlink_ifinfo_prep(dev, skb);
530  if (WARN_ON(!nlh)) {
531  kfree_skb(skb);
532  return;
533  }
534 
535  /* Add the wireless events in the netlink packet */
536  nla = nla_reserve(skb, IFLA_WIRELESS, event_len);
537  if (!nla) {
538  kfree_skb(skb);
539  return;
540  }
541  event = nla_data(nla);
542 
543  /* Fill event - first clear to avoid data leaking */
544  memset(event, 0, hdr_len);
545  event->len = event_len;
546  event->cmd = cmd;
547  memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
548  if (extra_len)
549  memcpy(((char *) event) + hdr_len, extra, extra_len);
550 
551  nlmsg_end(skb, nlh);
552 #ifdef CONFIG_COMPAT
553  hdr_len = compat_event_type_size[descr->header_type];
554  event_len = hdr_len + extra_len;
555 
556  compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
557  if (!compskb) {
558  kfree_skb(skb);
559  return;
560  }
561 
562  /* Send via the RtNetlink event channel */
563  nlh = rtnetlink_ifinfo_prep(dev, compskb);
564  if (WARN_ON(!nlh)) {
565  kfree_skb(skb);
566  kfree_skb(compskb);
567  return;
568  }
569 
570  /* Add the wireless events in the netlink packet */
571  nla = nla_reserve(compskb, IFLA_WIRELESS, event_len);
572  if (!nla) {
573  kfree_skb(skb);
574  kfree_skb(compskb);
575  return;
576  }
577  compat_event = nla_data(nla);
578 
579  compat_event->len = event_len;
580  compat_event->cmd = cmd;
581  if (descr->header_type == IW_HEADER_TYPE_POINT) {
582  compat_wrqu.length = wrqu->data.length;
583  compat_wrqu.flags = wrqu->data.flags;
584  memcpy(&compat_event->pointer,
585  ((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF,
586  hdr_len - IW_EV_COMPAT_LCP_LEN);
587  if (extra_len)
588  memcpy(((char *) compat_event) + hdr_len,
589  extra, extra_len);
590  } else {
591  /* extra_len must be zero, so no if (extra) needed */
592  memcpy(&compat_event->pointer, wrqu,
593  hdr_len - IW_EV_COMPAT_LCP_LEN);
594  }
595 
596  nlmsg_end(compskb, nlh);
597 
598  skb_shinfo(skb)->frag_list = compskb;
599 #endif
600  skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
601  schedule_work(&wireless_nlevent_work);
602 }
604 
605 
606 
607 /* IW handlers */
608 
610 {
611 #ifdef CONFIG_WIRELESS_EXT
612  if ((dev->wireless_handlers != NULL) &&
613  (dev->wireless_handlers->get_wireless_stats != NULL))
614  return dev->wireless_handlers->get_wireless_stats(dev);
615 #endif
616 
617 #ifdef CONFIG_CFG80211_WEXT
618  if (dev->ieee80211_ptr &&
619  dev->ieee80211_ptr->wiphy &&
620  dev->ieee80211_ptr->wiphy->wext &&
621  dev->ieee80211_ptr->wiphy->wext->get_wireless_stats)
622  return dev->ieee80211_ptr->wiphy->wext->get_wireless_stats(dev);
623 #endif
624 
625  /* not found */
626  return NULL;
627 }
628 
629 static int iw_handler_get_iwstats(struct net_device * dev,
630  struct iw_request_info * info,
631  union iwreq_data * wrqu,
632  char * extra)
633 {
634  /* Get stats from the driver */
635  struct iw_statistics *stats;
636 
637  stats = get_wireless_stats(dev);
638  if (stats) {
639  /* Copy statistics to extra */
640  memcpy(extra, stats, sizeof(struct iw_statistics));
641  wrqu->data.length = sizeof(struct iw_statistics);
642 
643  /* Check if we need to clear the updated flag */
644  if (wrqu->data.flags != 0)
645  stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
646  return 0;
647  } else
648  return -EOPNOTSUPP;
649 }
650 
651 static iw_handler get_handler(struct net_device *dev, unsigned int cmd)
652 {
653  /* Don't "optimise" the following variable, it will crash */
654  unsigned int index; /* *MUST* be unsigned */
655  const struct iw_handler_def *handlers = NULL;
656 
657 #ifdef CONFIG_CFG80211_WEXT
658  if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy)
659  handlers = dev->ieee80211_ptr->wiphy->wext;
660 #endif
661 #ifdef CONFIG_WIRELESS_EXT
662  if (dev->wireless_handlers)
663  handlers = dev->wireless_handlers;
664 #endif
665 
666  if (!handlers)
667  return NULL;
668 
669  /* Try as a standard command */
670  index = IW_IOCTL_IDX(cmd);
671  if (index < handlers->num_standard)
672  return handlers->standard[index];
673 
674 #ifdef CONFIG_WEXT_PRIV
675  /* Try as a private command */
676  index = cmd - SIOCIWFIRSTPRIV;
677  if (index < handlers->num_private)
678  return handlers->private[index];
679 #endif
680 
681  /* Not found */
682  return NULL;
683 }
684 
685 static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
686  const struct iw_ioctl_description *descr,
687  iw_handler handler, struct net_device *dev,
688  struct iw_request_info *info)
689 {
690  int err, extra_size, user_length = 0, essid_compat = 0;
691  char *extra;
692 
693  /* Calculate space needed by arguments. Always allocate
694  * for max space.
695  */
696  extra_size = descr->max_tokens * descr->token_size;
697 
698  /* Check need for ESSID compatibility for WE < 21 */
699  switch (cmd) {
700  case SIOCSIWESSID:
701  case SIOCGIWESSID:
702  case SIOCSIWNICKN:
703  case SIOCGIWNICKN:
704  if (iwp->length == descr->max_tokens + 1)
705  essid_compat = 1;
706  else if (IW_IS_SET(cmd) && (iwp->length != 0)) {
707  char essid[IW_ESSID_MAX_SIZE + 1];
708  unsigned int len;
709  len = iwp->length * descr->token_size;
710 
711  if (len > IW_ESSID_MAX_SIZE)
712  return -EFAULT;
713 
714  err = copy_from_user(essid, iwp->pointer, len);
715  if (err)
716  return -EFAULT;
717 
718  if (essid[iwp->length - 1] == '\0')
719  essid_compat = 1;
720  }
721  break;
722  default:
723  break;
724  }
725 
726  iwp->length -= essid_compat;
727 
728  /* Check what user space is giving us */
729  if (IW_IS_SET(cmd)) {
730  /* Check NULL pointer */
731  if (!iwp->pointer && iwp->length != 0)
732  return -EFAULT;
733  /* Check if number of token fits within bounds */
734  if (iwp->length > descr->max_tokens)
735  return -E2BIG;
736  if (iwp->length < descr->min_tokens)
737  return -EINVAL;
738  } else {
739  /* Check NULL pointer */
740  if (!iwp->pointer)
741  return -EFAULT;
742  /* Save user space buffer size for checking */
743  user_length = iwp->length;
744 
745  /* Don't check if user_length > max to allow forward
746  * compatibility. The test user_length < min is
747  * implied by the test at the end.
748  */
749 
750  /* Support for very large requests */
751  if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
752  (user_length > descr->max_tokens)) {
753  /* Allow userspace to GET more than max so
754  * we can support any size GET requests.
755  * There is still a limit : -ENOMEM.
756  */
757  extra_size = user_length * descr->token_size;
758 
759  /* Note : user_length is originally a __u16,
760  * and token_size is controlled by us,
761  * so extra_size won't get negative and
762  * won't overflow...
763  */
764  }
765  }
766 
767  /* kzalloc() ensures NULL-termination for essid_compat. */
768  extra = kzalloc(extra_size, GFP_KERNEL);
769  if (!extra)
770  return -ENOMEM;
771 
772  /* If it is a SET, get all the extra data in here */
773  if (IW_IS_SET(cmd) && (iwp->length != 0)) {
774  if (copy_from_user(extra, iwp->pointer,
775  iwp->length *
776  descr->token_size)) {
777  err = -EFAULT;
778  goto out;
779  }
780 
781  if (cmd == SIOCSIWENCODEEXT) {
782  struct iw_encode_ext *ee = (void *) extra;
783 
784  if (iwp->length < sizeof(*ee) + ee->key_len) {
785  err = -EFAULT;
786  goto out;
787  }
788  }
789  }
790 
791  if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) {
792  /*
793  * If this is a GET, but not NOMAX, it means that the extra
794  * data is not bounded by userspace, but by max_tokens. Thus
795  * set the length to max_tokens. This matches the extra data
796  * allocation.
797  * The driver should fill it with the number of tokens it
798  * provided, and it may check iwp->length rather than having
799  * knowledge of max_tokens. If the driver doesn't change the
800  * iwp->length, this ioctl just copies back max_token tokens
801  * filled with zeroes. Hopefully the driver isn't claiming
802  * them to be valid data.
803  */
804  iwp->length = descr->max_tokens;
805  }
806 
807  err = handler(dev, info, (union iwreq_data *) iwp, extra);
808 
809  iwp->length += essid_compat;
810 
811  /* If we have something to return to the user */
812  if (!err && IW_IS_GET(cmd)) {
813  /* Check if there is enough buffer up there */
814  if (user_length < iwp->length) {
815  err = -E2BIG;
816  goto out;
817  }
818 
819  if (copy_to_user(iwp->pointer, extra,
820  iwp->length *
821  descr->token_size)) {
822  err = -EFAULT;
823  goto out;
824  }
825  }
826 
827  /* Generate an event to notify listeners of the change */
828  if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
829  ((err == 0) || (err == -EIWCOMMIT))) {
830  union iwreq_data *data = (union iwreq_data *) iwp;
831 
832  if (descr->flags & IW_DESCR_FLAG_RESTRICT)
833  /* If the event is restricted, don't
834  * export the payload.
835  */
836  wireless_send_event(dev, cmd, data, NULL);
837  else
838  wireless_send_event(dev, cmd, data, extra);
839  }
840 
841 out:
842  kfree(extra);
843  return err;
844 }
845 
846 /*
847  * Call the commit handler in the driver
848  * (if exist and if conditions are right)
849  *
850  * Note : our current commit strategy is currently pretty dumb,
851  * but we will be able to improve on that...
852  * The goal is to try to agreagate as many changes as possible
853  * before doing the commit. Drivers that will define a commit handler
854  * are usually those that need a reset after changing parameters, so
855  * we want to minimise the number of reset.
856  * A cool idea is to use a timer : at each "set" command, we re-set the
857  * timer, when the timer eventually fires, we call the driver.
858  * Hopefully, more on that later.
859  *
860  * Also, I'm waiting to see how many people will complain about the
861  * netif_running(dev) test. I'm open on that one...
862  * Hopefully, the driver will remember to do a commit in "open()" ;-)
863  */
865 {
866 #ifdef CONFIG_WIRELESS_EXT
867  if ((netif_running(dev)) &&
868  (dev->wireless_handlers->standard[0] != NULL))
869  /* Call the commit handler on the driver */
870  return dev->wireless_handlers->standard[0](dev, NULL,
871  NULL, NULL);
872  else
873  return 0; /* Command completed successfully */
874 #else
875  /* cfg80211 has no commit */
876  return 0;
877 #endif
878 }
879 
880 /*
881  * Main IOCTl dispatcher.
882  * Check the type of IOCTL and call the appropriate wrapper...
883  */
884 static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
885  unsigned int cmd,
886  struct iw_request_info *info,
887  wext_ioctl_func standard,
888  wext_ioctl_func private)
889 {
890  struct iwreq *iwr = (struct iwreq *) ifr;
891  struct net_device *dev;
892  iw_handler handler;
893 
894  /* Permissions are already checked in dev_ioctl() before calling us.
895  * The copy_to/from_user() of ifr is also dealt with in there */
896 
897  /* Make sure the device exist */
898  if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)
899  return -ENODEV;
900 
901  /* A bunch of special cases, then the generic case...
902  * Note that 'cmd' is already filtered in dev_ioctl() with
903  * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
904  if (cmd == SIOCGIWSTATS)
905  return standard(dev, iwr, cmd, info,
906  &iw_handler_get_iwstats);
907 
908 #ifdef CONFIG_WEXT_PRIV
909  if (cmd == SIOCGIWPRIV && dev->wireless_handlers)
910  return standard(dev, iwr, cmd, info,
912 #endif
913 
914  /* Basic check */
915  if (!netif_device_present(dev))
916  return -ENODEV;
917 
918  /* New driver API : try to find the handler */
919  handler = get_handler(dev, cmd);
920  if (handler) {
921  /* Standard and private are not the same */
922  if (cmd < SIOCIWFIRSTPRIV)
923  return standard(dev, iwr, cmd, info, handler);
924  else if (private)
925  return private(dev, iwr, cmd, info, handler);
926  }
927  /* Old driver API : call driver ioctl handler */
928  if (dev->netdev_ops->ndo_do_ioctl)
929  return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
930  return -EOPNOTSUPP;
931 }
932 
933 /* If command is `set a parameter', or `get the encoding parameters',
934  * check if the user has the right to do it.
935  */
936 static int wext_permission_check(unsigned int cmd)
937 {
938  if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE ||
939  cmd == SIOCGIWENCODEEXT) &&
941  return -EPERM;
942 
943  return 0;
944 }
945 
946 /* entry point from dev ioctl */
947 static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
948  unsigned int cmd, struct iw_request_info *info,
949  wext_ioctl_func standard,
950  wext_ioctl_func private)
951 {
952  int ret = wext_permission_check(cmd);
953 
954  if (ret)
955  return ret;
956 
957  dev_load(net, ifr->ifr_name);
958  rtnl_lock();
959  ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private);
960  rtnl_unlock();
961 
962  return ret;
963 }
964 
965 /*
966  * Wrapper to call a standard Wireless Extension handler.
967  * We do various checks and also take care of moving data between
968  * user space and kernel space.
969  */
970 static int ioctl_standard_call(struct net_device * dev,
971  struct iwreq *iwr,
972  unsigned int cmd,
973  struct iw_request_info *info,
974  iw_handler handler)
975 {
976  const struct iw_ioctl_description * descr;
977  int ret = -EINVAL;
978 
979  /* Get the description of the IOCTL */
980  if (IW_IOCTL_IDX(cmd) >= standard_ioctl_num)
981  return -EOPNOTSUPP;
982  descr = &(standard_ioctl[IW_IOCTL_IDX(cmd)]);
983 
984  /* Check if we have a pointer to user space data or not */
985  if (descr->header_type != IW_HEADER_TYPE_POINT) {
986 
987  /* No extra arguments. Trivial to handle */
988  ret = handler(dev, info, &(iwr->u), NULL);
989 
990  /* Generate an event to notify listeners of the change */
991  if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
992  ((ret == 0) || (ret == -EIWCOMMIT)))
993  wireless_send_event(dev, cmd, &(iwr->u), NULL);
994  } else {
995  ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr,
996  handler, dev, info);
997  }
998 
999  /* Call commit handler if needed and defined */
1000  if (ret == -EIWCOMMIT)
1001  ret = call_commit_handler(dev);
1002 
1003  /* Here, we will generate the appropriate event if needed */
1004 
1005  return ret;
1006 }
1007 
1008 
1009 int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
1010  void __user *arg)
1011 {
1012  struct iw_request_info info = { .cmd = cmd, .flags = 0 };
1013  int ret;
1014 
1015  ret = wext_ioctl_dispatch(net, ifr, cmd, &info,
1016  ioctl_standard_call,
1018  if (ret >= 0 &&
1019  IW_IS_GET(cmd) &&
1020  copy_to_user(arg, ifr, sizeof(struct iwreq)))
1021  return -EFAULT;
1022 
1023  return ret;
1024 }
1025 
1026 #ifdef CONFIG_COMPAT
1027 static int compat_standard_call(struct net_device *dev,
1028  struct iwreq *iwr,
1029  unsigned int cmd,
1030  struct iw_request_info *info,
1031  iw_handler handler)
1032 {
1033  const struct iw_ioctl_description *descr;
1034  struct compat_iw_point *iwp_compat;
1035  struct iw_point iwp;
1036  int err;
1037 
1038  descr = standard_ioctl + IW_IOCTL_IDX(cmd);
1039 
1040  if (descr->header_type != IW_HEADER_TYPE_POINT)
1041  return ioctl_standard_call(dev, iwr, cmd, info, handler);
1042 
1043  iwp_compat = (struct compat_iw_point *) &iwr->u.data;
1044  iwp.pointer = compat_ptr(iwp_compat->pointer);
1045  iwp.length = iwp_compat->length;
1046  iwp.flags = iwp_compat->flags;
1047 
1048  err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info);
1049 
1050  iwp_compat->pointer = ptr_to_compat(iwp.pointer);
1051  iwp_compat->length = iwp.length;
1052  iwp_compat->flags = iwp.flags;
1053 
1054  return err;
1055 }
1056 
1057 int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
1058  unsigned long arg)
1059 {
1060  void __user *argp = (void __user *)arg;
1061  struct iw_request_info info;
1062  struct iwreq iwr;
1063  char *colon;
1064  int ret;
1065 
1066  if (copy_from_user(&iwr, argp, sizeof(struct iwreq)))
1067  return -EFAULT;
1068 
1069  iwr.ifr_name[IFNAMSIZ-1] = 0;
1070  colon = strchr(iwr.ifr_name, ':');
1071  if (colon)
1072  *colon = 0;
1073 
1074  info.cmd = cmd;
1076 
1077  ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, &info,
1078  compat_standard_call,
1080 
1081  if (ret >= 0 &&
1082  IW_IS_GET(cmd) &&
1083  copy_to_user(argp, &iwr, sizeof(struct iwreq)))
1084  return -EFAULT;
1085 
1086  return ret;
1087 }
1088 #endif