]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.6.16-we20-6.patch
- converted to utf8
[packages/kernel.git] / linux-2.6.16-we20-6.patch
1 diff -u -p linux/include/linux/wireless.19.h linux/include/linux/wireless.h
2 --- linux/include/linux/wireless.19.h   2006-02-17 10:49:04.000000000 -0800
3 +++ linux/include/linux/wireless.h      2006-02-17 17:58:10.000000000 -0800
4 @@ -1,10 +1,10 @@
5  /*
6   * This file define a set of standard wireless extensions
7   *
8 - * Version :   19      18.3.05
9 + * Version :   20      17.2.06
10   *
11   * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
12 - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
13 + * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
14   */
15  
16  #ifndef _LINUX_WIRELESS_H
17 @@ -80,7 +80,7 @@
18   * (there is some stuff that will be added in the future...)
19   * I just plan to increment with each new version.
20   */
21 -#define WIRELESS_EXT   19
22 +#define WIRELESS_EXT   20
23  
24  /*
25   * Changes :
26 @@ -204,6 +204,10 @@
27   *     - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
28   *     - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
29   *     - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
30 + *
31 + * V19 to V20
32 + * ----------
33 + *     - RtNetlink requests support (SET/GET)
34   */
35  
36  /**************************** CONSTANTS ****************************/
37 diff -u -p linux/include/net/iw_handler.19.h linux/include/net/iw_handler.h
38 --- linux/include/net/iw_handler.19.h   2006-02-17 10:49:15.000000000 -0800
39 +++ linux/include/net/iw_handler.h      2006-02-17 18:01:36.000000000 -0800
40 @@ -4,7 +4,7 @@
41   * Version :   7       18.3.05
42   *
43   * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
44 - * Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved.
45 + * Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved.
46   */
47  
48  #ifndef _IW_HANDLER_H
49 @@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * 
50  /* Handle IOCTLs, called in net/core/dev.c */
51  extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
52  
53 +/* Handle RtNetlink requests, called in net/core/rtnetlink.c */
54 +extern int wireless_rtnetlink_set(struct net_device *  dev,
55 +                                 char *                data,
56 +                                 int                   len);
57 +extern int wireless_rtnetlink_get(struct net_device *  dev,
58 +                                 char *                data,
59 +                                 int                   len,
60 +                                 char **               p_buf,
61 +                                 int *                 p_len);
62 +
63  /* Second : functions that may be called by driver modules */
64  
65  /* Send a single event to user space */
66 diff -u -p linux/drivers/net/wireless/Kconfig.19 linux/drivers/net/wireless/Kconfig
67 --- linux/drivers/net/wireless/Kconfig.19       2006-02-21 13:11:34.000000000 -0800
68 +++ linux/drivers/net/wireless/Kconfig  2006-02-22 11:48:27.000000000 -0800
69 @@ -24,6 +24,15 @@ config NET_RADIO
70           the tools from
71           <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
72  
73 +config NET_WIRELESS_RTNETLINK
74 +       bool "Wireless Extension API over RtNetlink"
75 +       ---help---
76 +         Support the Wireless Extension API over the RtNetlink socket
77 +         in addition to the traditional ioctl interface (selected above).
78 +
79 +         For now, few tools use this facility, but it might grow in the
80 +         future. The only downside is that it adds 4.5 kB to your kernel.
81 +
82  # Note : the cards are obsolete (can't buy them anymore), but the drivers
83  # are not, as people are still using them...
84  comment "Obsolete Wireless cards support (pre-802.11)"
85 diff -u -p linux/net/core/rtnetlink.19.c linux/net/core/rtnetlink.c
86 --- linux/net/core/rtnetlink.19.c       2006-02-17 10:49:26.000000000 -0800
87 +++ linux/net/core/rtnetlink.c  2006-02-21 12:57:07.000000000 -0800
88 @@ -50,6 +50,10 @@
89  #include <net/sock.h>
90  #include <net/pkt_sched.h>
91  #include <net/netlink.h>
92 +#ifdef CONFIG_NET_WIRELESS_RTNETLINK
93 +#include <linux/wireless.h>
94 +#include <net/iw_handler.h>
95 +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
96  
97  DECLARE_MUTEX(rtnl_sem);
98  
99 @@ -410,6 +414,17 @@ static int do_setlink(struct sk_buff *sk
100                         goto out;
101         }
102  
103 +#ifdef CONFIG_NET_WIRELESS_RTNETLINK
104 +       if (ida[IFLA_WIRELESS - 1]) {
105 +
106 +               /* Call Wireless Extensions.
107 +                * Various stuff checked in there... */
108 +               err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
109 +               if (err)
110 +                       goto out;
111 +       }
112 +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
113 +
114         err = 0;
115  
116  out:
117 @@ -420,6 +435,83 @@ out:
118         return err;
119  }
120  
121 +#ifdef CONFIG_NET_WIRELESS_RTNETLINK
122 +static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
123 +{
124 +       struct ifinfomsg  *ifm = NLMSG_DATA(in_nlh);
125 +       struct rtattr    **ida = arg;
126 +       struct net_device *dev;
127 +       struct ifinfomsg *r;
128 +       struct nlmsghdr  *nlh;
129 +       int err = -ENOBUFS;
130 +       struct sk_buff *skb;
131 +       unsigned char    *b;
132 +       char *iw_buf = NULL;
133 +       int iw_buf_len = 0;
134 +
135 +       if (ifm->ifi_index >= 0)
136 +               dev = dev_get_by_index(ifm->ifi_index);
137 +       else
138 +               return -EINVAL;
139 +       if (!dev)
140 +               return -ENODEV;
141 +
142 +#ifdef CONFIG_NET_WIRELESS_RTNETLINK
143 +       if (ida[IFLA_WIRELESS - 1]) {
144 +
145 +               /* Call Wireless Extensions. We need to know the size before
146 +                * we can alloc. Various stuff checked in there... */
147 +               err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
148 +               if (err)
149 +                       goto out;
150 +       }
151 +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
152 +
153 +       /* Create a skb big enough to include all the data.
154 +        * Some requests are way bigger than 4k... Jean II */
155 +       skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
156 +                       GFP_KERNEL);
157 +       if (!skb)
158 +               goto out;
159 +       b = skb->tail;
160 +
161 +       /* Put in the message the usual good stuff */
162 +       nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
163 +                       RTM_NEWLINK, sizeof(*r));
164 +       r = NLMSG_DATA(nlh);
165 +       r->ifi_family = AF_UNSPEC;
166 +       r->__ifi_pad = 0;
167 +       r->ifi_type = dev->type;
168 +       r->ifi_index = dev->ifindex;
169 +       r->ifi_flags = dev->flags;
170 +       r->ifi_change = 0;
171 +
172 +       /* Put the wireless payload if it exist */
173 +       if(iw_buf != NULL)
174 +               RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
175 +                       iw_buf + IW_EV_POINT_OFF);
176 +
177 +       nlh->nlmsg_len = skb->tail - b;
178 +
179 +       /* Needed ? */
180 +       NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
181 +
182 +       err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
183 +       if (err > 0)
184 +               err = 0;
185 +out:
186 +       if(iw_buf != NULL)
187 +               kfree(iw_buf);
188 +       dev_put(dev);
189 +       return err;
190 +
191 +rtattr_failure:
192 +nlmsg_failure:
193 +       kfree_skb(skb);
194 +       goto out;
195 +}
196 +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
197 +
198  static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
199  {
200         int idx;
201 @@ -585,7 +677,11 @@ static void rtnetlink_rcv(struct sock *s
202  
203  static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
204  {
205 -       [RTM_GETLINK     - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
206 +       [RTM_GETLINK     - RTM_BASE] = {
207 +#ifdef CONFIG_NET_WIRELESS_RTNETLINK
208 +                                        .doit   = do_getlink,
209 +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
210 +                                        .dumpit = rtnetlink_dump_ifinfo },
211         [RTM_SETLINK     - RTM_BASE] = { .doit   = do_setlink            },
212         [RTM_GETADDR     - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
213         [RTM_GETROUTE    - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
214 diff -u -p linux/net/core/wireless.19.c linux/net/core/wireless.c
215 --- linux/net/core/wireless.19.c        2006-02-17 10:49:37.000000000 -0800
216 +++ linux/net/core/wireless.c   2006-02-22 11:46:52.000000000 -0800
217 @@ -2,7 +2,7 @@
218   * This file implement the Wireless Extensions APIs.
219   *
220   * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
221 - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
222 + * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
223   *
224   * (As all part of the Linux kernel, this file is GPL)
225   */
226 @@ -65,6 +65,9 @@
227   *     o Start deprecating dev->get_wireless_stats, output a warning
228   *     o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless
229   *     o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats)
230 + *
231 + * v8 - 17.02.06 - Jean II
232 + *     o RtNetlink requests support (SET/GET)
233   */
234  
235  /***************************** INCLUDES *****************************/
236 @@ -89,11 +92,13 @@
237  
238  /* Debugging stuff */
239  #undef WE_IOCTL_DEBUG          /* Debug IOCTL API */
240 +#undef WE_RTNETLINK_DEBUG      /* Debug RtNetlink API */
241  #undef WE_EVENT_DEBUG          /* Debug Event dispatcher */
242  #undef WE_SPY_DEBUG            /* Debug enhanced spy support */
243  
244  /* Options */
245 -#define WE_EVENT_NETLINK       /* Propagate events using rtnetlink */
246 +//CONFIG_NET_WIRELESS_RTNETLINK        /* Wireless requests over RtNetlink */
247 +#define WE_EVENT_RTNETLINK     /* Propagate events using RtNetlink */
248  #define WE_SET_EVENT           /* Generate an event on some set commands */
249  
250  /************************* GLOBAL VARIABLES *************************/
251 @@ -156,13 +161,18 @@ static const struct iw_ioctl_description
252                 .header_type    = IW_HEADER_TYPE_NULL,
253         },
254         [SIOCGIWPRIV    - SIOCIWFIRST] = { /* (handled directly by us) */
255 -               .header_type    = IW_HEADER_TYPE_NULL,
256 +               .header_type    = IW_HEADER_TYPE_POINT,
257 +               .token_size     = sizeof(struct iw_priv_args),
258 +               .max_tokens     = 16,
259 +               .flags          = IW_DESCR_FLAG_NOMAX,
260         },
261         [SIOCSIWSTATS   - SIOCIWFIRST] = {
262                 .header_type    = IW_HEADER_TYPE_NULL,
263         },
264         [SIOCGIWSTATS   - SIOCIWFIRST] = { /* (handled directly by us) */
265 -               .header_type    = IW_HEADER_TYPE_NULL,
266 +               .header_type    = IW_HEADER_TYPE_POINT,
267 +               .token_size     = 1,
268 +               .max_tokens     = sizeof(struct iw_statistics),
269                 .flags          = IW_DESCR_FLAG_DUMP,
270         },
271         [SIOCSIWSPY     - SIOCIWFIRST] = {
272 @@ -529,6 +539,70 @@ static inline int adjust_priv_size(__u16
273         return num * iw_priv_type_size[type];
274  }
275  
276 +/* ---------------------------------------------------------------- */
277 +/*
278 + * Standard Wireless Handler : get wireless stats
279 + *     Allow programatic access to /proc/net/wireless even if /proc
280 + *     doesn't exist... Also more efficient...
281 + */
282 +static int iw_handler_get_iwstats(struct net_device *          dev,
283 +                                 struct iw_request_info *      info,
284 +                                 union iwreq_data *            wrqu,
285 +                                 char *                        extra)
286 +{
287 +       /* Get stats from the driver */
288 +       struct iw_statistics *stats;
289 +
290 +       stats = get_wireless_stats(dev);
291 +       if (stats != (struct iw_statistics *) NULL) {
292 +
293 +               /* Copy statistics to extra */
294 +               memcpy(extra, stats, sizeof(struct iw_statistics));
295 +               wrqu->data.length = sizeof(struct iw_statistics);
296 +
297 +               /* Check if we need to clear the updated flag */
298 +               if(wrqu->data.flags != 0)
299 +                       stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
300 +               return 0;
301 +       } else
302 +               return -EOPNOTSUPP;
303 +}
304 +
305 +/* ---------------------------------------------------------------- */
306 +/*
307 + * Standard Wireless Handler : get iwpriv definitions
308 + * Export the driver private handler definition
309 + * They will be picked up by tools like iwpriv...
310 + */
311 +static int iw_handler_get_private(struct net_device *          dev,
312 +                                 struct iw_request_info *      info,
313 +                                 union iwreq_data *            wrqu,
314 +                                 char *                        extra)
315 +{
316 +       /* Check if the driver has something to export */
317 +       if((dev->wireless_handlers->num_private_args == 0) ||
318 +          (dev->wireless_handlers->private_args == NULL))
319 +               return -EOPNOTSUPP;
320 +
321 +       /* Check if there is enough buffer up there */
322 +       if(wrqu->data.length < dev->wireless_handlers->num_private_args) {
323 +               /* User space can't know in advance how large the buffer
324 +                * needs to be. Give it a hint, so that we can support
325 +                * any size buffer we want somewhat efficiently... */
326 +               wrqu->data.length = dev->wireless_handlers->num_private_args;
327 +               return -E2BIG;
328 +       }
329 +
330 +       /* Set the number of available ioctls. */
331 +       wrqu->data.length = dev->wireless_handlers->num_private_args;
332 +
333 +       /* Copy structure to the user buffer. */
334 +       memcpy(extra, dev->wireless_handlers->private_args,
335 +              sizeof(struct iw_priv_args) * wrqu->data.length);
336 +
337 +       return 0;
338 +}
339 +
340  
341  /******************** /proc/net/wireless SUPPORT ********************/
342  /*
343 @@ -630,81 +704,14 @@ int __init wireless_proc_init(void)
344  
345  /* ---------------------------------------------------------------- */
346  /*
347 - *     Allow programatic access to /proc/net/wireless even if /proc
348 - *     doesn't exist... Also more efficient...
349 - */
350 -static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
351 -{
352 -       /* Get stats from the driver */
353 -       struct iw_statistics *stats;
354 -
355 -       stats = get_wireless_stats(dev);
356 -       if (stats != (struct iw_statistics *) NULL) {
357 -               struct iwreq *  wrq = (struct iwreq *)ifr;
358 -
359 -               /* Copy statistics to the user buffer */
360 -               if(copy_to_user(wrq->u.data.pointer, stats,
361 -                               sizeof(struct iw_statistics)))
362 -                       return -EFAULT;
363 -
364 -               /* Check if we need to clear the updated flag */
365 -               if(wrq->u.data.flags != 0)
366 -                       stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
367 -               return 0;
368 -       } else
369 -               return -EOPNOTSUPP;
370 -}
371 -
372 -/* ---------------------------------------------------------------- */
373 -/*
374 - * Export the driver private handler definition
375 - * They will be picked up by tools like iwpriv...
376 - */
377 -static inline int ioctl_export_private(struct net_device *     dev,
378 -                                      struct ifreq *           ifr)
379 -{
380 -       struct iwreq *                          iwr = (struct iwreq *) ifr;
381 -
382 -       /* Check if the driver has something to export */
383 -       if((dev->wireless_handlers->num_private_args == 0) ||
384 -          (dev->wireless_handlers->private_args == NULL))
385 -               return -EOPNOTSUPP;
386 -
387 -       /* Check NULL pointer */
388 -       if(iwr->u.data.pointer == NULL)
389 -               return -EFAULT;
390 -
391 -       /* Check if there is enough buffer up there */
392 -       if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
393 -               /* User space can't know in advance how large the buffer
394 -                * needs to be. Give it a hint, so that we can support
395 -                * any size buffer we want somewhat efficiently... */
396 -               iwr->u.data.length = dev->wireless_handlers->num_private_args;
397 -               return -E2BIG;
398 -       }
399 -
400 -       /* Set the number of available ioctls. */
401 -       iwr->u.data.length = dev->wireless_handlers->num_private_args;
402 -
403 -       /* Copy structure to the user buffer. */
404 -       if (copy_to_user(iwr->u.data.pointer,
405 -                        dev->wireless_handlers->private_args,
406 -                        sizeof(struct iw_priv_args) * iwr->u.data.length))
407 -               return -EFAULT;
408 -
409 -       return 0;
410 -}
411 -
412 -/* ---------------------------------------------------------------- */
413 -/*
414   * Wrapper to call a standard Wireless Extension handler.
415   * We do various checks and also take care of moving data between
416   * user space and kernel space.
417   */
418 -static inline int ioctl_standard_call(struct net_device *      dev,
419 -                                     struct ifreq *            ifr,
420 -                                     unsigned int              cmd,
421 -                                     iw_handler                handler)
422 +static int ioctl_standard_call(struct net_device *     dev,
423 +                              struct ifreq *           ifr,
424 +                              unsigned int             cmd,
425 +                              iw_handler               handler)
426  {
427         struct iwreq *                          iwr = (struct iwreq *) ifr;
428         const struct iw_ioctl_description *     descr;
429 @@ -1048,14 +1055,20 @@ int wireless_process_ioctl(struct ifreq 
430         {
431                 case SIOCGIWSTATS:
432                         /* Get Wireless Stats */
433 -                       return dev_iwstats(dev, ifr);
434 +                       return ioctl_standard_call(dev,
435 +                                                  ifr,
436 +                                                  cmd,
437 +                                                  &iw_handler_get_iwstats);
438  
439                 case SIOCGIWPRIV:
440                         /* Check if we have some wireless handlers defined */
441                         if(dev->wireless_handlers != NULL) {
442                                 /* We export to user space the definition of
443                                  * the private handler ourselves */
444 -                               return ioctl_export_private(dev, ifr);
445 +                               return ioctl_standard_call(dev,
446 +                                                          ifr,
447 +                                                          cmd,
448 +                                                          &iw_handler_get_private);
449                         }
450                         // ## Fall-through for old API ##
451                 default:
452 @@ -1088,16 +1101,739 @@ int wireless_process_ioctl(struct ifreq 
453         return -EINVAL;
454  }
455  
456 +/********************** RTNETLINK REQUEST API **********************/
457 +/*
458 + * The alternate user space API to configure all those Wireless Extensions
459 + * is through RtNetlink.
460 + * This API support only the new driver API (iw_handler).
461 + *
462 + * This RtNetlink API use the same query/reply model as the ioctl API.
463 + * Maximum effort has been done to fit in the RtNetlink model, and
464 + * we support both RtNetlink Set and RtNelink Get operations.
465 + * On the other hand, we don't offer Dump operations because of the
466 + * following reasons :
467 + *     o Large number of parameters, most optional
468 + *     o Large size of some parameters (> 100 bytes)
469 + *     o Each parameters need to be extracted from hardware
470 + *     o Scan requests can take seconds and disable network activity.
471 + * Because of this high cost/overhead, we want to return only the
472 + * parameters the user application is really interested in.
473 + * We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag.
474 + *
475 + * The API uses the standard RtNetlink socket. When the RtNetlink code
476 + * find a IFLA_WIRELESS field in a RtNetlink SET_LINK request,
477 + * it calls here.
478 + */
479 +
480 +#ifdef CONFIG_NET_WIRELESS_RTNETLINK
481 +/* ---------------------------------------------------------------- */
482 +/*
483 + * Wrapper to call a standard Wireless Extension GET handler.
484 + * We do various checks and call the handler with the proper args.
485 + */
486 +static int rtnetlink_standard_get(struct net_device *  dev,
487 +                                 struct iw_event *     request,
488 +                                 int                   request_len,
489 +                                 iw_handler            handler,
490 +                                 char **               p_buf,
491 +                                 int *                 p_len)
492 +{
493 +       const struct iw_ioctl_description *     descr = NULL;
494 +       unsigned int                            cmd;
495 +       union iwreq_data *                      wrqu;
496 +       int                                     hdr_len;
497 +       struct iw_request_info                  info;
498 +       char *                                  buffer = NULL;
499 +       int                                     buffer_size = 0;
500 +       int                                     ret = -EINVAL;
501 +
502 +       /* Get the description of the Request */
503 +       cmd = request->cmd;
504 +       if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
505 +               return -EOPNOTSUPP;
506 +       descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
507 +
508 +#ifdef WE_RTNETLINK_DEBUG
509 +       printk(KERN_DEBUG "%s (WE.r) : Found standard handler for 0x%04X\n",
510 +              dev->name, cmd);
511 +       printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
512 +#endif /* WE_RTNETLINK_DEBUG */
513 +
514 +       /* Check if wrqu is complete */
515 +       hdr_len = event_type_size[descr->header_type];
516 +       if(request_len < hdr_len) {
517 +#ifdef WE_RTNETLINK_DEBUG
518 +               printk(KERN_DEBUG
519 +                      "%s (WE.r) : Wireless request too short (%d)\n",
520 +                      dev->name, request_len);
521 +#endif /* WE_RTNETLINK_DEBUG */
522 +               return -EINVAL;
523 +       }
524 +
525 +       /* Prepare the call */
526 +       info.cmd = cmd;
527 +       info.flags = 0;
528 +
529 +       /* Check if we have extra data in the reply or not */
530 +       if(descr->header_type != IW_HEADER_TYPE_POINT) {
531 +
532 +               /* Create the kernel buffer that we will return.
533 +                * It's at an offset to match the TYPE_POINT case... */
534 +               buffer_size = request_len + IW_EV_POINT_OFF;
535 +               buffer = kmalloc(buffer_size, GFP_KERNEL);
536 +               if (buffer == NULL) {
537 +                       return -ENOMEM;
538 +               }
539 +               /* Copy event data */
540 +               memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
541 +               /* Use our own copy of wrqu */
542 +               wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
543 +                                            + IW_EV_LCP_LEN);
544 +
545 +               /* No extra arguments. Trivial to handle */
546 +               ret = handler(dev, &info, wrqu, NULL);
547 +
548 +       } else {
549 +               union iwreq_data        wrqu_point;
550 +               char *                  extra = NULL;
551 +               int                     extra_size = 0;
552 +
553 +               /* Get a temp copy of wrqu (skip pointer) */
554 +               memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
555 +                      ((char *) request) + IW_EV_LCP_LEN,
556 +                      IW_EV_POINT_LEN - IW_EV_LCP_LEN);
557 +
558 +               /* Calculate space needed by arguments. Always allocate
559 +                * for max space. Easier, and won't last long... */
560 +               extra_size = descr->max_tokens * descr->token_size;
561 +               /* Support for very large requests */
562 +               if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
563 +                  (wrqu_point.data.length > descr->max_tokens))
564 +                       extra_size = (wrqu_point.data.length
565 +                                     * descr->token_size);
566 +               buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
567 +#ifdef WE_RTNETLINK_DEBUG
568 +               printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
569 +                      dev->name, extra_size, buffer_size);
570 +#endif /* WE_RTNETLINK_DEBUG */
571 +
572 +               /* Create the kernel buffer that we will return */
573 +               buffer = kmalloc(buffer_size, GFP_KERNEL);
574 +               if (buffer == NULL) {
575 +                       return -ENOMEM;
576 +               }
577 +
578 +               /* Put wrqu in the right place (just before extra).
579 +                * Leave space for IWE header and dummy pointer...
580 +                * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
581 +                */
582 +               memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
583 +                      ((char *) &wrqu_point) + IW_EV_POINT_OFF,
584 +                      IW_EV_POINT_LEN - IW_EV_LCP_LEN);
585 +               wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
586 +
587 +               /* Extra comes logically after that. Offset +12 bytes. */
588 +               extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
589 +
590 +               /* Call the handler */
591 +               ret = handler(dev, &info, wrqu, extra);
592 +
593 +               /* Calculate real returned length */
594 +               extra_size = (wrqu->data.length * descr->token_size);
595 +               /* Re-adjust reply size */
596 +               request->len = extra_size + IW_EV_POINT_LEN;
597 +
598 +               /* Put the iwe header where it should, i.e. scrap the
599 +                * dummy pointer. */
600 +               memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN);
601 +
602 +#ifdef WE_RTNETLINK_DEBUG
603 +               printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
604 +#endif /* WE_RTNETLINK_DEBUG */
605 +
606 +               /* Check if there is enough buffer up there */
607 +               if(wrqu_point.data.length < wrqu->data.length)
608 +                       ret = -E2BIG;
609 +       }
610 +
611 +       /* Return the buffer to the caller */
612 +       if (!ret) {
613 +               *p_buf = buffer;
614 +               *p_len = request->len;
615 +       } else {
616 +               /* Cleanup */
617 +               if(buffer)
618 +                       kfree(buffer);
619 +       }
620 +
621 +       return ret;
622 +}
623 +
624 +/* ---------------------------------------------------------------- */
625 +/*
626 + * Wrapper to call a standard Wireless Extension SET handler.
627 + * We do various checks and call the handler with the proper args.
628 + */
629 +static inline int rtnetlink_standard_set(struct net_device *   dev,
630 +                                        struct iw_event *      request,
631 +                                        int                    request_len,
632 +                                        iw_handler             handler)
633 +{
634 +       const struct iw_ioctl_description *     descr = NULL;
635 +       unsigned int                            cmd;
636 +       union iwreq_data *                      wrqu;
637 +       union iwreq_data                        wrqu_point;
638 +       int                                     hdr_len;
639 +       char *                                  extra = NULL;
640 +       int                                     extra_size = 0;
641 +       struct iw_request_info                  info;
642 +       int                                     ret = -EINVAL;
643 +
644 +       /* Get the description of the Request */
645 +       cmd = request->cmd;
646 +       if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
647 +               return -EOPNOTSUPP;
648 +       descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
649 +
650 +#ifdef WE_RTNETLINK_DEBUG
651 +       printk(KERN_DEBUG "%s (WE.r) : Found standard SET handler for 0x%04X\n",
652 +              dev->name, cmd);
653 +       printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
654 +#endif /* WE_RTNETLINK_DEBUG */
655 +
656 +       /* Extract fixed header from request. This is properly aligned. */
657 +       wrqu = &request->u;
658 +
659 +       /* Check if wrqu is complete */
660 +       hdr_len = event_type_size[descr->header_type];
661 +       if(request_len < hdr_len) {
662 +#ifdef WE_RTNETLINK_DEBUG
663 +               printk(KERN_DEBUG
664 +                      "%s (WE.r) : Wireless request too short (%d)\n",
665 +                      dev->name, request_len);
666 +#endif /* WE_RTNETLINK_DEBUG */
667 +               return -EINVAL;
668 +       }
669 +
670 +       /* Prepare the call */
671 +       info.cmd = cmd;
672 +       info.flags = 0;
673 +
674 +       /* Check if we have extra data in the request or not */
675 +       if(descr->header_type != IW_HEADER_TYPE_POINT) {
676 +
677 +               /* No extra arguments. Trivial to handle */
678 +               ret = handler(dev, &info, wrqu, NULL);
679 +
680 +       } else {
681 +               int     extra_len;
682 +
683 +               /* Put wrqu in the right place (skip pointer) */
684 +               memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
685 +                      wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN);
686 +               /* Don't forget about the event code... */
687 +               wrqu = &wrqu_point;
688 +
689 +               /* Check if number of token fits within bounds */
690 +               if(wrqu_point.data.length > descr->max_tokens)
691 +                       return -E2BIG;
692 +               if(wrqu_point.data.length < descr->min_tokens)
693 +                       return -EINVAL;
694 +
695 +               /* Real length of payload */
696 +               extra_len = wrqu_point.data.length * descr->token_size;
697 +
698 +               /* Check if request is self consistent */
699 +               if((request_len - hdr_len) < extra_len) {
700 +#ifdef WE_RTNETLINK_DEBUG
701 +                       printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n",
702 +                              dev->name, extra_size);
703 +#endif /* WE_RTNETLINK_DEBUG */
704 +                       return -EINVAL;
705 +               }
706 +
707 +#ifdef WE_RTNETLINK_DEBUG
708 +               printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n",
709 +                      dev->name, extra_size);
710 +#endif /* WE_RTNETLINK_DEBUG */
711 +
712 +               /* Always allocate for max space. Easier, and won't last
713 +                * long... */
714 +               extra_size = descr->max_tokens * descr->token_size;
715 +               extra = kmalloc(extra_size, GFP_KERNEL);
716 +               if (extra == NULL)
717 +                       return -ENOMEM;
718 +
719 +               /* Copy extra in aligned buffer */
720 +               memcpy(extra, ((char *) request) + hdr_len, extra_len);
721 +
722 +               /* Call the handler */
723 +               ret = handler(dev, &info, &wrqu_point, extra);
724 +       }
725 +
726 +#ifdef WE_SET_EVENT
727 +       /* Generate an event to notify listeners of the change */
728 +       if((descr->flags & IW_DESCR_FLAG_EVENT) &&
729 +          ((ret == 0) || (ret == -EIWCOMMIT))) {
730 +               if(descr->flags & IW_DESCR_FLAG_RESTRICT)
731 +                       /* If the event is restricted, don't
732 +                        * export the payload */
733 +                       wireless_send_event(dev, cmd, wrqu, NULL);
734 +               else
735 +                       wireless_send_event(dev, cmd, wrqu, extra);
736 +       }
737 +#endif /* WE_SET_EVENT */
738 +
739 +       /* Cleanup - I told you it wasn't that long ;-) */
740 +       if(extra)
741 +               kfree(extra);
742 +
743 +       /* Call commit handler if needed and defined */
744 +       if(ret == -EIWCOMMIT)
745 +               ret = call_commit_handler(dev);
746 +
747 +       return ret;
748 +}
749 +
750 +/* ---------------------------------------------------------------- */
751 +/*
752 + * Wrapper to call a private Wireless Extension GET handler.
753 + * Same as above...
754 + * It's not as nice and slimline as the standard wrapper. The cause
755 + * is struct iw_priv_args, which was not really designed for the
756 + * job we are going here.
757 + *
758 + * IMPORTANT : This function prevent to set and get data on the same
759 + * IOCTL and enforce the SET/GET convention. Not doing it would be
760 + * far too hairy...
761 + * If you need to set and get data at the same time, please don't use
762 + * a iw_handler but process it in your ioctl handler (i.e. use the
763 + * old driver API).
764 + */
765 +static inline int rtnetlink_private_get(struct net_device *    dev,
766 +                                       struct iw_event *       request,
767 +                                       int                     request_len,
768 +                                       iw_handler              handler,
769 +                                       char **                 p_buf,
770 +                                       int *                   p_len)
771 +{
772 +       const struct iw_priv_args *     descr = NULL;
773 +       unsigned int                    cmd;
774 +       union iwreq_data *              wrqu;
775 +       int                             hdr_len;
776 +       struct iw_request_info          info;
777 +       int                             extra_size = 0;
778 +       int                             i;
779 +       char *                          buffer = NULL;
780 +       int                             buffer_size = 0;
781 +       int                             ret = -EINVAL;
782 +
783 +       /* Get the description of the Request */
784 +       cmd = request->cmd;
785 +       for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
786 +               if(cmd == dev->wireless_handlers->private_args[i].cmd) {
787 +                       descr = &(dev->wireless_handlers->private_args[i]);
788 +                       break;
789 +               }
790 +       if(descr == NULL)
791 +               return -EOPNOTSUPP;
792 +
793 +#ifdef WE_RTNETLINK_DEBUG
794 +       printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n",
795 +              dev->name, cmd);
796 +       printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n",
797 +              dev->name, descr->name, descr->set_args, descr->get_args);
798 +#endif /* WE_RTNETLINK_DEBUG */
799 +
800 +       /* Compute the max size of the get arguments */
801 +       extra_size = get_priv_size(descr->get_args);
802 +
803 +       /* Does it fits in wrqu ? */
804 +       if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
805 +          (extra_size <= IFNAMSIZ)) {
806 +               hdr_len = extra_size;
807 +               extra_size = 0;
808 +       } else {
809 +               hdr_len = IW_EV_POINT_LEN;
810 +       }
811 +
812 +       /* Check if wrqu is complete */
813 +       if(request_len < hdr_len) {
814 +#ifdef WE_RTNETLINK_DEBUG
815 +               printk(KERN_DEBUG
816 +                      "%s (WE.r) : Wireless request too short (%d)\n",
817 +                      dev->name, request_len);
818 +#endif /* WE_RTNETLINK_DEBUG */
819 +               return -EINVAL;
820 +       }
821 +
822 +       /* Prepare the call */
823 +       info.cmd = cmd;
824 +       info.flags = 0;
825 +
826 +       /* Check if we have a pointer to user space data or not. */
827 +       if(extra_size == 0) {
828 +
829 +               /* Create the kernel buffer that we will return.
830 +                * It's at an offset to match the TYPE_POINT case... */
831 +               buffer_size = request_len + IW_EV_POINT_OFF;
832 +               buffer = kmalloc(buffer_size, GFP_KERNEL);
833 +               if (buffer == NULL) {
834 +                       return -ENOMEM;
835 +               }
836 +               /* Copy event data */
837 +               memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
838 +               /* Use our own copy of wrqu */
839 +               wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
840 +                                            + IW_EV_LCP_LEN);
841 +
842 +               /* No extra arguments. Trivial to handle */
843 +               ret = handler(dev, &info, wrqu, (char *) wrqu);
844 +
845 +       } else {
846 +               char *  extra;
847 +
848 +               /* Buffer for full reply */
849 +               buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
850 +
851 +#ifdef WE_RTNETLINK_DEBUG
852 +               printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
853 +                      dev->name, extra_size, buffer_size);
854 +#endif /* WE_RTNETLINK_DEBUG */
855 +
856 +               /* Create the kernel buffer that we will return */
857 +               buffer = kmalloc(buffer_size, GFP_KERNEL);
858 +               if (buffer == NULL) {
859 +                       return -ENOMEM;
860 +               }
861 +
862 +               /* Put wrqu in the right place (just before extra).
863 +                * Leave space for IWE header and dummy pointer...
864 +                * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
865 +                */
866 +               memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
867 +                      ((char *) request) + IW_EV_LCP_LEN,
868 +                      IW_EV_POINT_LEN - IW_EV_LCP_LEN);
869 +               wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
870 +
871 +               /* Extra comes logically after that. Offset +12 bytes. */
872 +               extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
873 +
874 +               /* Call the handler */
875 +               ret = handler(dev, &info, wrqu, extra);
876 +
877 +               /* Adjust for the actual length if it's variable,
878 +                * avoid leaking kernel bits outside. */
879 +               if (!(descr->get_args & IW_PRIV_SIZE_FIXED))
880 +                       extra_size = adjust_priv_size(descr->get_args, wrqu);
881 +               /* Re-adjust reply size */
882 +               request->len = extra_size + IW_EV_POINT_LEN;
883 +
884 +               /* Put the iwe header where it should, i.e. scrap the
885 +                * dummy pointer. */
886 +               memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN);
887 +
888 +#ifdef WE_RTNETLINK_DEBUG
889 +               printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
890 +#endif /* WE_RTNETLINK_DEBUG */
891 +       }
892 +
893 +       /* Return the buffer to the caller */
894 +       if (!ret) {
895 +               *p_buf = buffer;
896 +               *p_len = request->len;
897 +       } else {
898 +               /* Cleanup */
899 +               if(buffer)
900 +                       kfree(buffer);
901 +       }
902 +
903 +       return ret;
904 +}
905 +
906 +/* ---------------------------------------------------------------- */
907 +/*
908 + * Wrapper to call a private Wireless Extension SET handler.
909 + * Same as above...
910 + * It's not as nice and slimline as the standard wrapper. The cause
911 + * is struct iw_priv_args, which was not really designed for the
912 + * job we are going here.
913 + *
914 + * IMPORTANT : This function prevent to set and get data on the same
915 + * IOCTL and enforce the SET/GET convention. Not doing it would be
916 + * far too hairy...
917 + * If you need to set and get data at the same time, please don't use
918 + * a iw_handler but process it in your ioctl handler (i.e. use the
919 + * old driver API).
920 + */
921 +static inline int rtnetlink_private_set(struct net_device *    dev,
922 +                                       struct iw_event *       request,
923 +                                       int                     request_len,
924 +                                       iw_handler              handler)
925 +{
926 +       const struct iw_priv_args *     descr = NULL;
927 +       unsigned int                    cmd;
928 +       union iwreq_data *              wrqu;
929 +       union iwreq_data                wrqu_point;
930 +       int                             hdr_len;
931 +       char *                          extra = NULL;
932 +       int                             extra_size = 0;
933 +       int                             offset = 0;     /* For sub-ioctls */
934 +       struct iw_request_info          info;
935 +       int                             i;
936 +       int                             ret = -EINVAL;
937 +
938 +       /* Get the description of the Request */
939 +       cmd = request->cmd;
940 +       for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
941 +               if(cmd == dev->wireless_handlers->private_args[i].cmd) {
942 +                       descr = &(dev->wireless_handlers->private_args[i]);
943 +                       break;
944 +               }
945 +       if(descr == NULL)
946 +               return -EOPNOTSUPP;
947 +
948 +#ifdef WE_RTNETLINK_DEBUG
949 +       printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n",
950 +              ifr->ifr_name, cmd);
951 +       printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n",
952 +              dev->name, descr->name, descr->set_args, descr->get_args);
953 +#endif /* WE_RTNETLINK_DEBUG */
954 +
955 +       /* Compute the size of the set arguments */
956 +       /* Check for sub-ioctl handler */
957 +       if(descr->name[0] == '\0')
958 +               /* Reserve one int for sub-ioctl index */
959 +               offset = sizeof(__u32);
960 +
961 +       /* Size of set arguments */
962 +       extra_size = get_priv_size(descr->set_args);
963 +
964 +       /* Does it fits in wrqu ? */
965 +       if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
966 +          (extra_size <= IFNAMSIZ)) {
967 +               hdr_len = IW_EV_LCP_LEN + extra_size;
968 +               extra_size = 0;
969 +       } else {
970 +               hdr_len = IW_EV_POINT_LEN;
971 +       }
972 +
973 +       /* Extract fixed header from request. This is properly aligned. */
974 +       wrqu = &request->u;
975 +
976 +       /* Check if wrqu is complete */
977 +       if(request_len < hdr_len) {
978 +#ifdef WE_RTNETLINK_DEBUG
979 +               printk(KERN_DEBUG
980 +                      "%s (WE.r) : Wireless request too short (%d)\n",
981 +                      dev->name, request_len);
982 +#endif /* WE_RTNETLINK_DEBUG */
983 +               return -EINVAL;
984 +       }
985 +
986 +       /* Prepare the call */
987 +       info.cmd = cmd;
988 +       info.flags = 0;
989 +
990 +       /* Check if we have a pointer to user space data or not. */
991 +       if(extra_size == 0) {
992 +
993 +               /* No extra arguments. Trivial to handle */
994 +               ret = handler(dev, &info, wrqu, (char *) wrqu);
995 +
996 +       } else {
997 +               int     extra_len;
998 +
999 +               /* Put wrqu in the right place (skip pointer) */
1000 +               memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1001 +                      wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1002 +
1003 +               /* Does it fits within bounds ? */
1004 +               if(wrqu_point.data.length > (descr->set_args &
1005 +                                            IW_PRIV_SIZE_MASK))
1006 +                       return -E2BIG;
1007 +
1008 +               /* Real length of payload */
1009 +               extra_len = adjust_priv_size(descr->set_args, &wrqu_point);
1010 +
1011 +               /* Check if request is self consistent */
1012 +               if((request_len - hdr_len) < extra_len) {
1013 +#ifdef WE_RTNETLINK_DEBUG
1014 +                       printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n",
1015 +                              dev->name, extra_size);
1016 +#endif /* WE_RTNETLINK_DEBUG */
1017 +                       return -EINVAL;
1018 +               }
1019 +
1020 +#ifdef WE_RTNETLINK_DEBUG
1021 +               printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n",
1022 +                      dev->name, extra_size);
1023 +#endif /* WE_RTNETLINK_DEBUG */
1024 +
1025 +               /* Always allocate for max space. Easier, and won't last
1026 +                * long... */
1027 +               extra = kmalloc(extra_size, GFP_KERNEL);
1028 +               if (extra == NULL)
1029 +                       return -ENOMEM;
1030 +
1031 +               /* Copy extra in aligned buffer */
1032 +               memcpy(extra, ((char *) request) + hdr_len, extra_len);
1033 +
1034 +               /* Call the handler */
1035 +               ret = handler(dev, &info, &wrqu_point, extra);
1036 +
1037 +               /* Cleanup - I told you it wasn't that long ;-) */
1038 +               kfree(extra);
1039 +       }
1040 +
1041 +       /* Call commit handler if needed and defined */
1042 +       if(ret == -EIWCOMMIT)
1043 +               ret = call_commit_handler(dev);
1044 +
1045 +       return ret;
1046 +}
1047 +
1048 +/* ---------------------------------------------------------------- */
1049 +/*
1050 + * Main RtNetlink dispatcher. Called from the main networking code
1051 + * (do_getlink() in net/core/rtnetlink.c).
1052 + * Check the type of Request and call the appropriate wrapper...
1053 + */
1054 +int wireless_rtnetlink_get(struct net_device * dev,
1055 +                          char *               data,
1056 +                          int                  len,
1057 +                          char **              p_buf,
1058 +                          int *                p_len)
1059 +{
1060 +       struct iw_event *       request = (struct iw_event *) data;
1061 +       iw_handler              handler;
1062 +
1063 +       /* Check length */
1064 +       if(len < IW_EV_LCP_LEN) {
1065 +               printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
1066 +                      dev->name, len);
1067 +               return -EINVAL;
1068 +       }
1069 +
1070 +       /* ReCheck length (len may have padding) */
1071 +       if(request->len > len) {
1072 +               printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n",
1073 +                      dev->name, request->len, len);
1074 +               return -EINVAL;
1075 +       }
1076 +
1077 +       /* Only accept GET requests in here */
1078 +       if(!IW_IS_GET(request->cmd))
1079 +               return -EOPNOTSUPP;
1080 +
1081 +       /* Special cases */
1082 +       if(request->cmd == SIOCGIWSTATS)
1083 +               /* Get Wireless Stats */
1084 +               return rtnetlink_standard_get(dev,
1085 +                                             request,
1086 +                                             request->len,
1087 +                                             &iw_handler_get_iwstats,
1088 +                                             p_buf, p_len);
1089 +       if(request->cmd == SIOCGIWPRIV) {
1090 +               /* Check if we have some wireless handlers defined */
1091 +               if(dev->wireless_handlers == NULL)
1092 +                       return -EOPNOTSUPP;
1093 +               /* Get Wireless Stats */
1094 +               return rtnetlink_standard_get(dev,
1095 +                                             request,
1096 +                                             request->len,
1097 +                                             &iw_handler_get_private,
1098 +                                             p_buf, p_len);
1099 +       }
1100 +
1101 +       /* Basic check */
1102 +       if (!netif_device_present(dev))
1103 +               return -ENODEV;
1104 +
1105 +       /* Try to find the handler */
1106 +       handler = get_handler(dev, request->cmd);
1107 +       if(handler != NULL) {
1108 +               /* Standard and private are not the same */
1109 +               if(request->cmd < SIOCIWFIRSTPRIV)
1110 +                       return rtnetlink_standard_get(dev,
1111 +                                                     request,
1112 +                                                     request->len,
1113 +                                                     handler,
1114 +                                                     p_buf, p_len);
1115 +               else
1116 +                       return rtnetlink_private_get(dev,
1117 +                                                    request,
1118 +                                                    request->len,
1119 +                                                    handler,
1120 +                                                    p_buf, p_len);
1121 +       }
1122 +
1123 +       return -EOPNOTSUPP;
1124 +}
1125 +
1126 +/* ---------------------------------------------------------------- */
1127 +/*
1128 + * Main RtNetlink dispatcher. Called from the main networking code
1129 + * (do_setlink() in net/core/rtnetlink.c).
1130 + * Check the type of Request and call the appropriate wrapper...
1131 + */
1132 +int wireless_rtnetlink_set(struct net_device * dev,
1133 +                          char *               data,
1134 +                          int                  len)
1135 +{
1136 +       struct iw_event *       request = (struct iw_event *) data;
1137 +       iw_handler              handler;
1138 +
1139 +       /* Check length */
1140 +       if(len < IW_EV_LCP_LEN) {
1141 +               printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
1142 +                      dev->name, len);
1143 +               return -EINVAL;
1144 +       }
1145 +
1146 +       /* ReCheck length (len may have padding) */
1147 +       if(request->len > len) {
1148 +               printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n",
1149 +                      dev->name, request->len, len);
1150 +               return -EINVAL;
1151 +       }
1152 +
1153 +       /* Only accept SET requests in here */
1154 +       if(!IW_IS_SET(request->cmd))
1155 +               return -EOPNOTSUPP;
1156 +
1157 +       /* Basic check */
1158 +       if (!netif_device_present(dev))
1159 +               return -ENODEV;
1160 +
1161 +       /* New driver API : try to find the handler */
1162 +       handler = get_handler(dev, request->cmd);
1163 +       if(handler != NULL) {
1164 +               /* Standard and private are not the same */
1165 +               if(request->cmd < SIOCIWFIRSTPRIV)
1166 +                       return rtnetlink_standard_set(dev,
1167 +                                                     request,
1168 +                                                     request->len,
1169 +                                                     handler);
1170 +               else
1171 +                       return rtnetlink_private_set(dev,
1172 +                                                    request,
1173 +                                                    request->len,
1174 +                                                    handler);
1175 +       }
1176 +
1177 +       return -EOPNOTSUPP;
1178 +}
1179 +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
1180 +
1181 +
1182  /************************* EVENT PROCESSING *************************/
1183  /*
1184   * Process events generated by the wireless layer or the driver.
1185   * Most often, the event will be propagated through rtnetlink
1186   */
1187  
1188 -#ifdef WE_EVENT_NETLINK
1189 -/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here.
1190 - * It is declared in <linux/rtnetlink.h> */
1191 -
1192 +#ifdef WE_EVENT_RTNETLINK
1193  /* ---------------------------------------------------------------- */
1194  /*
1195   * Fill a rtnetlink message with our event data.
1196 @@ -1121,12 +1857,11 @@ static inline int rtnetlink_fill_iwinfo(
1197         r->__ifi_pad = 0;
1198         r->ifi_type = dev->type;
1199         r->ifi_index = dev->ifindex;
1200 -       r->ifi_flags = dev->flags;
1201 +       r->ifi_flags = dev_get_flags(dev);
1202         r->ifi_change = 0;      /* Wireless changes don't affect those flags */
1203  
1204         /* Add the wireless events in the netlink packet */
1205 -       RTA_PUT(skb, IFLA_WIRELESS,
1206 -               event_len, event);
1207 +       RTA_PUT(skb, IFLA_WIRELESS, event_len, event);
1208  
1209         nlh->nlmsg_len = skb->tail - b;
1210         return skb->len;
1211 @@ -1163,7 +1898,7 @@ static inline void rtmsg_iwinfo(struct n
1212         NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1213         netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
1214  }
1215 -#endif /* WE_EVENT_NETLINK */
1216 +#endif /* WE_EVENT_RTNETLINK */
1217  
1218  /* ---------------------------------------------------------------- */
1219  /*
1220 @@ -1255,10 +1990,10 @@ void wireless_send_event(struct net_devi
1221         if(extra != NULL)
1222                 memcpy(((char *) event) + hdr_len, extra, extra_len);
1223  
1224 -#ifdef WE_EVENT_NETLINK
1225 -       /* rtnetlink event channel */
1226 +#ifdef WE_EVENT_RTNETLINK
1227 +       /* Send via the RtNetlink event channel */
1228         rtmsg_iwinfo(dev, (char *) event, event_len);
1229 -#endif /* WE_EVENT_NETLINK */
1230 +#endif /* WE_EVENT_RTNETLINK */
1231  
1232         /* Cleanup */
1233         kfree(event);
This page took 0.137388 seconds and 3 git commands to generate.