home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / net / iw_handler.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  23.7 KB  |  644 lines

  1. /*
  2.  * This file define the new driver API for Wireless Extensions
  3.  *
  4.  * Version :    7    18.3.05
  5.  *
  6.  * Authors :    Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  7.  * Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved.
  8.  */
  9.  
  10. #ifndef _IW_HANDLER_H
  11. #define _IW_HANDLER_H
  12.  
  13. /************************** DOCUMENTATION **************************/
  14. /*
  15.  * Initial driver API (1996 -> onward) :
  16.  * -----------------------------------
  17.  * The initial API just sends the IOCTL request received from user space
  18.  * to the driver (via the driver ioctl handler). The driver has to
  19.  * handle all the rest...
  20.  *
  21.  * The initial API also defines a specific handler in struct net_device
  22.  * to handle wireless statistics.
  23.  *
  24.  * The initial APIs served us well and has proven a reasonably good design.
  25.  * However, there is a few shortcommings :
  26.  *    o No events, everything is a request to the driver.
  27.  *    o Large ioctl function in driver with gigantic switch statement
  28.  *      (i.e. spaghetti code).
  29.  *    o Driver has to mess up with copy_to/from_user, and in many cases
  30.  *      does it unproperly. Common mistakes are :
  31.  *        * buffer overflows (no checks or off by one checks)
  32.  *        * call copy_to/from_user with irq disabled
  33.  *    o The user space interface is tied to ioctl because of the use
  34.  *      copy_to/from_user.
  35.  *
  36.  * New driver API (2002 -> onward) :
  37.  * -------------------------------
  38.  * The new driver API is just a bunch of standard functions (handlers),
  39.  * each handling a specific Wireless Extension. The driver just export
  40.  * the list of handler it supports, and those will be called apropriately.
  41.  *
  42.  * I tried to keep the main advantage of the previous API (simplicity,
  43.  * efficiency and light weight), and also I provide a good dose of backward
  44.  * compatibility (most structures are the same, driver can use both API
  45.  * simultaneously, ...).
  46.  * Hopefully, I've also addressed the shortcomming of the initial API.
  47.  *
  48.  * The advantage of the new API are :
  49.  *    o Handling of Extensions in driver broken in small contained functions
  50.  *    o Tighter checks of ioctl before calling the driver
  51.  *    o Flexible commit strategy (at least, the start of it)
  52.  *    o Backward compatibility (can be mixed with old API)
  53.  *    o Driver doesn't have to worry about memory and user-space issues
  54.  * The last point is important for the following reasons :
  55.  *    o You are now able to call the new driver API from any API you
  56.  *        want (including from within other parts of the kernel).
  57.  *    o Common mistakes are avoided (buffer overflow, user space copy
  58.  *        with irq disabled and so on).
  59.  *
  60.  * The Drawback of the new API are :
  61.  *    o bloat (especially kernel)
  62.  *    o need to migrate existing drivers to new API
  63.  * My initial testing shows that the new API adds around 3kB to the kernel
  64.  * and save between 0 and 5kB from a typical driver.
  65.  * Also, as all structures and data types are unchanged, the migration is
  66.  * quite straightforward (but tedious).
  67.  *
  68.  * ---
  69.  *
  70.  * The new driver API is defined below in this file. User space should
  71.  * not be aware of what's happening down there...
  72.  *
  73.  * A new kernel wrapper is in charge of validating the IOCTLs and calling
  74.  * the appropriate driver handler. This is implemented in :
  75.  *    # net/core/wireless.c
  76.  *
  77.  * The driver export the list of handlers in :
  78.  *    # include/linux/netdevice.h (one place)
  79.  *
  80.  * The new driver API is available for WIRELESS_EXT >= 13.
  81.  * Good luck with migration to the new API ;-)
  82.  */
  83.  
  84. /* ---------------------- THE IMPLEMENTATION ---------------------- */
  85. /*
  86.  * Some of the choice I've made are pretty controversials. Defining an
  87.  * API is very much weighting compromises. This goes into some of the
  88.  * details and the thinking behind the implementation.
  89.  *
  90.  * Implementation goals :
  91.  * --------------------
  92.  * The implementation goals were as follow :
  93.  *    o Obvious : you should not need a PhD to understand what's happening,
  94.  *        the benefit is easier maintainance.
  95.  *    o Flexible : it should accommodate a wide variety of driver
  96.  *        implementations and be as flexible as the old API.
  97.  *    o Lean : it should be efficient memory wise to minimise the impact
  98.  *        on kernel footprint.
  99.  *    o Transparent to user space : the large number of user space
  100.  *        applications that use Wireless Extensions should not need
  101.  *        any modifications.
  102.  *
  103.  * Array of functions versus Struct of functions
  104.  * ---------------------------------------------
  105.  * 1) Having an array of functions allow the kernel code to access the
  106.  * handler in a single lookup, which is much more efficient (think hash
  107.  * table here).
  108.  * 2) The only drawback is that driver writer may put their handler in
  109.  * the wrong slot. This is trivial to test (I set the frequency, the
  110.  * bitrate changes). Once the handler is in the proper slot, it will be
  111.  * there forever, because the array is only extended at the end.
  112.  * 3) Backward/forward compatibility : adding new handler just require
  113.  * extending the array, so you can put newer driver in older kernel
  114.  * without having to patch the kernel code (and vice versa).
  115.  *
  116.  * All handler are of the same generic type
  117.  * ----------------------------------------
  118.  * That's a feature !!!
  119.  * 1) Having a generic handler allow to have generic code, which is more
  120.  * efficient. If each of the handler was individually typed I would need
  121.  * to add a big switch in the kernel (== more bloat). This solution is
  122.  * more scalable, adding new Wireless Extensions doesn't add new code.
  123.  * 2) You can use the same handler in different slots of the array. For
  124.  * hardware, it may be more efficient or logical to handle multiple
  125.  * Wireless Extensions with a single function, and the API allow you to
  126.  * do that. (An example would be a single record on the card to control
  127.  * both bitrate and frequency, the handler would read the old record,
  128.  * modify it according to info->cmd and rewrite it).
  129.  *
  130.  * Functions prototype uses union iwreq_data
  131.  * -----------------------------------------
  132.  * Some would have prefered functions defined this way :
  133.  *    static int mydriver_ioctl_setrate(struct net_device *dev, 
  134.  *                      long rate, int auto)
  135.  * 1) The kernel code doesn't "validate" the content of iwreq_data, and
  136.  * can't do it (different hardware may have different notion of what a
  137.  * valid frequency is), so we don't pretend that we do it.
  138.  * 2) The above form is not extendable. If I want to add a flag (for
  139.  * example to distinguish setting max rate and basic rate), I would
  140.  * break the prototype. Using iwreq_data is more flexible.
  141.  * 3) Also, the above form is not generic (see above).
  142.  * 4) I don't expect driver developper using the wrong field of the
  143.  * union (Doh !), so static typechecking doesn't add much value.
  144.  * 5) Lastly, you can skip the union by doing :
  145.  *    static int mydriver_ioctl_setrate(struct net_device *dev,
  146.  *                      struct iw_request_info *info,
  147.  *                      struct iw_param *rrq,
  148.  *                      char *extra)
  149.  * And then adding the handler in the array like this :
  150.  *        (iw_handler) mydriver_ioctl_setrate,             // SIOCSIWRATE
  151.  *
  152.  * Using functions and not a registry
  153.  * ----------------------------------
  154.  * Another implementation option would have been for every instance to
  155.  * define a registry (a struct containing all the Wireless Extensions)
  156.  * and only have a function to commit the registry to the hardware.
  157.  * 1) This approach can be emulated by the current code, but not
  158.  * vice versa.
  159.  * 2) Some drivers don't keep any configuration in the driver, for them
  160.  * adding such a registry would be a significant bloat.
  161.  * 3) The code to translate from Wireless Extension to native format is
  162.  * needed anyway, so it would not reduce significantely the amount of code.
  163.  * 4) The current approach only selectively translate Wireless Extensions
  164.  * to native format and only selectively set, whereas the registry approach
  165.  * would require to translate all WE and set all parameters for any single
  166.  * change.
  167.  * 5) For many Wireless Extensions, the GET operation return the current
  168.  * dynamic value, not the value that was set.
  169.  *
  170.  * This header is <net/iw_handler.h>
  171.  * ---------------------------------
  172.  * 1) This header is kernel space only and should not be exported to
  173.  * user space. Headers in "include/linux/" are exported, headers in
  174.  * "include/net/" are not.
  175.  *
  176.  * Mixed 32/64 bit issues
  177.  * ----------------------
  178.  * The Wireless Extensions are designed to be 64 bit clean, by using only
  179.  * datatypes with explicit storage size.
  180.  * There are some issues related to kernel and user space using different
  181.  * memory model, and in particular 64bit kernel with 32bit user space.
  182.  * The problem is related to struct iw_point, that contains a pointer
  183.  * that *may* need to be translated.
  184.  * This is quite messy. The new API doesn't solve this problem (it can't),
  185.  * but is a step in the right direction :
  186.  * 1) Meta data about each ioctl is easily available, so we know what type
  187.  * of translation is needed.
  188.  * 2) The move of data between kernel and user space is only done in a single
  189.  * place in the kernel, so adding specific hooks in there is possible.
  190.  * 3) In the long term, it allows to move away from using ioctl as the
  191.  * user space API.
  192.  *
  193.  * So many comments and so few code
  194.  * --------------------------------
  195.  * That's a feature. Comments won't bloat the resulting kernel binary.
  196.  */
  197.  
  198. /***************************** INCLUDES *****************************/
  199.  
  200. #include <linux/wireless.h>        /* IOCTL user space API */
  201. #include <linux/if_ether.h>
  202.  
  203. /***************************** VERSION *****************************/
  204. /*
  205.  * This constant is used to know which version of the driver API is
  206.  * available. Hopefully, this will be pretty stable and no changes
  207.  * will be needed...
  208.  * I just plan to increment with each new version.
  209.  */
  210. #define IW_HANDLER_VERSION    7
  211.  
  212. /*
  213.  * Changes :
  214.  *
  215.  * V2 to V3
  216.  * --------
  217.  *    - Move event definition in <linux/wireless.h>
  218.  *    - Add Wireless Event support :
  219.  *        o wireless_send_event() prototype
  220.  *        o iwe_stream_add_event/point() inline functions
  221.  * V3 to V4
  222.  * --------
  223.  *    - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
  224.  *
  225.  * V4 to V5
  226.  * --------
  227.  *    - Add new spy support : struct iw_spy_data & prototypes
  228.  *
  229.  * V5 to V6
  230.  * --------
  231.  *    - Change the way we get to spy_data method for added safety
  232.  *    - Remove spy #ifdef, they are always on -> cleaner code
  233.  *    - Add IW_DESCR_FLAG_NOMAX flag for very large requests
  234.  *    - Start migrating get_wireless_stats to struct iw_handler_def
  235.  *
  236.  * V6 to V7
  237.  * --------
  238.  *    - Add struct ieee80211_device pointer in struct iw_public_data
  239.  *    - Remove (struct iw_point *)->pointer from events and streams
  240.  *    - Remove spy_offset from struct iw_handler_def
  241.  *    - Add "check" version of event macros for ieee802.11 stack
  242.  */
  243.  
  244. /**************************** CONSTANTS ****************************/
  245.  
  246. /* Enhanced spy support available */
  247. #define IW_WIRELESS_SPY
  248. #define IW_WIRELESS_THRSPY
  249.  
  250. /* Special error message for the driver to indicate that we
  251.  * should do a commit after return from the iw_handler */
  252. #define EIWCOMMIT    EINPROGRESS
  253.  
  254. /* Flags available in struct iw_request_info */
  255. #define IW_REQUEST_FLAG_NONE    0x0000    /* No flag so far */
  256.  
  257. /* Type of headers we know about (basically union iwreq_data) */
  258. #define IW_HEADER_TYPE_NULL    0    /* Not available */
  259. #define IW_HEADER_TYPE_CHAR    2    /* char [IFNAMSIZ] */
  260. #define IW_HEADER_TYPE_UINT    4    /* __u32 */
  261. #define IW_HEADER_TYPE_FREQ    5    /* struct iw_freq */
  262. #define IW_HEADER_TYPE_ADDR    6    /* struct sockaddr */
  263. #define IW_HEADER_TYPE_POINT    8    /* struct iw_point */
  264. #define IW_HEADER_TYPE_PARAM    9    /* struct iw_param */
  265. #define IW_HEADER_TYPE_QUAL    10    /* struct iw_quality */
  266.  
  267. /* Handling flags */
  268. /* Most are not implemented. I just use them as a reminder of some
  269.  * cool features we might need one day ;-) */
  270. #define IW_DESCR_FLAG_NONE    0x0000    /* Obvious */
  271. /* Wrapper level flags */
  272. #define IW_DESCR_FLAG_DUMP    0x0001    /* Not part of the dump command */
  273. #define IW_DESCR_FLAG_EVENT    0x0002    /* Generate an event on SET */
  274. #define IW_DESCR_FLAG_RESTRICT    0x0004    /* GET : request is ROOT only */
  275.                 /* SET : Omit payload from generated iwevent */
  276. #define IW_DESCR_FLAG_NOMAX    0x0008    /* GET : no limit on request size */
  277. /* Driver level flags */
  278. #define IW_DESCR_FLAG_WAIT    0x0100    /* Wait for driver event */
  279.  
  280. /****************************** TYPES ******************************/
  281.  
  282. /* ----------------------- WIRELESS HANDLER ----------------------- */
  283. /*
  284.  * A wireless handler is just a standard function, that looks like the
  285.  * ioctl handler.
  286.  * We also define there how a handler list look like... As the Wireless
  287.  * Extension space is quite dense, we use a simple array, which is faster
  288.  * (that's the perfect hash table ;-).
  289.  */
  290.  
  291. /*
  292.  * Meta data about the request passed to the iw_handler.
  293.  * Most handlers can safely ignore what's in there.
  294.  * The 'cmd' field might come handy if you want to use the same handler
  295.  * for multiple command...
  296.  * This struct is also my long term insurance. I can add new fields here
  297.  * without breaking the prototype of iw_handler...
  298.  */
  299. struct iw_request_info
  300. {
  301.     __u16        cmd;        /* Wireless Extension command */
  302.     __u16        flags;        /* More to come ;-) */
  303. };
  304.  
  305. struct net_device;
  306.  
  307. /*
  308.  * This is how a function handling a Wireless Extension should look
  309.  * like (both get and set, standard and private).
  310.  */
  311. typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
  312.               union iwreq_data *wrqu, char *extra);
  313.  
  314. /*
  315.  * This define all the handler that the driver export.
  316.  * As you need only one per driver type, please use a static const
  317.  * shared by all driver instances... Same for the members...
  318.  * This will be linked from net_device in <linux/netdevice.h>
  319.  */
  320. struct iw_handler_def
  321. {
  322.     /* Number of handlers defined (more precisely, index of the
  323.      * last defined handler + 1) */
  324.     __u16            num_standard;
  325.     __u16            num_private;
  326.     /* Number of private arg description */
  327.     __u16            num_private_args;
  328.  
  329.     /* Array of handlers for standard ioctls
  330.      * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
  331.      */
  332.     const iw_handler *    standard;
  333.  
  334.     /* Array of handlers for private ioctls
  335.      * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
  336.      */
  337.     const iw_handler *    private;
  338.  
  339.     /* Arguments of private handler. This one is just a list, so you
  340.      * can put it in any order you want and should not leave holes...
  341.      * We will automatically export that to user space... */
  342.     const struct iw_priv_args *    private_args;
  343.  
  344.     /* New location of get_wireless_stats, to de-bloat struct net_device.
  345.      * The old pointer in struct net_device will be gradually phased
  346.      * out, and drivers are encouraged to use this one... */
  347.     struct iw_statistics*    (*get_wireless_stats)(struct net_device *dev);
  348. };
  349.  
  350. /* ---------------------- IOCTL DESCRIPTION ---------------------- */
  351. /*
  352.  * One of the main goal of the new interface is to deal entirely with
  353.  * user space/kernel space memory move.
  354.  * For that, we need to know :
  355.  *    o if iwreq is a pointer or contain the full data
  356.  *    o what is the size of the data to copy
  357.  *
  358.  * For private IOCTLs, we use the same rules as used by iwpriv and
  359.  * defined in struct iw_priv_args.
  360.  *
  361.  * For standard IOCTLs, things are quite different and we need to
  362.  * use the stuctures below. Actually, this struct is also more
  363.  * efficient, but that's another story...
  364.  */
  365.  
  366. /*
  367.  * Describe how a standard IOCTL looks like.
  368.  */
  369. struct iw_ioctl_description
  370. {
  371.     __u8    header_type;        /* NULL, iw_point or other */
  372.     __u8    token_type;        /* Future */
  373.     __u16    token_size;        /* Granularity of payload */
  374.     __u16    min_tokens;        /* Min acceptable token number */
  375.     __u16    max_tokens;        /* Max acceptable token number */
  376.     __u32    flags;            /* Special handling of the request */
  377. };
  378.  
  379. /* Need to think of short header translation table. Later. */
  380.  
  381. /* --------------------- ENHANCED SPY SUPPORT --------------------- */
  382. /*
  383.  * In the old days, the driver was handling spy support all by itself.
  384.  * Now, the driver can delegate this task to Wireless Extensions.
  385.  * It needs to include this struct in its private part and use the
  386.  * standard spy iw_handler.
  387.  */
  388.  
  389. /*
  390.  * Instance specific spy data, i.e. addresses spied and quality for them.
  391.  */
  392. struct iw_spy_data
  393. {
  394.     /* --- Standard spy support --- */
  395.     int            spy_number;
  396.     u_char            spy_address[IW_MAX_SPY][ETH_ALEN];
  397.     struct iw_quality    spy_stat[IW_MAX_SPY];
  398.     /* --- Enhanced spy support (event) */
  399.     struct iw_quality    spy_thr_low;    /* Low threshold */
  400.     struct iw_quality    spy_thr_high;    /* High threshold */
  401.     u_char            spy_thr_under[IW_MAX_SPY];
  402. };
  403.  
  404. /* --------------------- DEVICE WIRELESS DATA --------------------- */
  405. /*
  406.  * This is all the wireless data specific to a device instance that
  407.  * is managed by the core of Wireless Extensions or the 802.11 layer.
  408.  * We only keep pointer to those structures, so that a driver is free
  409.  * to share them between instances.
  410.  * This structure should be initialised before registering the device.
  411.  * Access to this data follow the same rules as any other struct net_device
  412.  * data (i.e. valid as long as struct net_device exist, same locking rules).
  413.  */
  414. /* Forward declaration */
  415. struct ieee80211_device;
  416. /* The struct */
  417. struct iw_public_data {
  418.     /* Driver enhanced spy support */
  419.     struct iw_spy_data *        spy_data;
  420.     /* Structure managed by the in-kernel IEEE 802.11 layer */
  421.     struct ieee80211_device *    ieee80211;
  422. };
  423.  
  424. /**************************** PROTOTYPES ****************************/
  425. /*
  426.  * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
  427.  * Those may be called only within the kernel.
  428.  */
  429.  
  430. /* First : function strictly used inside the kernel */
  431.  
  432. /* Handle /proc/net/wireless, called in net/code/dev.c */
  433. extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
  434.                  int length);
  435.  
  436. /* Handle IOCTLs, called in net/core/dev.c */
  437. extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
  438.  
  439. /* Handle RtNetlink requests, called in net/core/rtnetlink.c */
  440. extern int wireless_rtnetlink_set(struct net_device *    dev,
  441.                   char *        data,
  442.                   int            len);
  443. extern int wireless_rtnetlink_get(struct net_device *    dev,
  444.                   char *        data,
  445.                   int            len,
  446.                   char **        p_buf,
  447.                   int *            p_len);
  448.  
  449. /* Second : functions that may be called by driver modules */
  450.  
  451. /* Send a single event to user space */
  452. extern void wireless_send_event(struct net_device *    dev,
  453.                 unsigned int        cmd,
  454.                 union iwreq_data *    wrqu,
  455.                 char *            extra);
  456.  
  457. /* We may need a function to send a stream of events to user space.
  458.  * More on that later... */
  459.  
  460. /* Standard handler for SIOCSIWSPY */
  461. extern int iw_handler_set_spy(struct net_device *    dev,
  462.                   struct iw_request_info *    info,
  463.                   union iwreq_data *    wrqu,
  464.                   char *            extra);
  465. /* Standard handler for SIOCGIWSPY */
  466. extern int iw_handler_get_spy(struct net_device *    dev,
  467.                   struct iw_request_info *    info,
  468.                   union iwreq_data *    wrqu,
  469.                   char *            extra);
  470. /* Standard handler for SIOCSIWTHRSPY */
  471. extern int iw_handler_set_thrspy(struct net_device *    dev,
  472.                  struct iw_request_info *info,
  473.                  union iwreq_data *    wrqu,
  474.                  char *            extra);
  475. /* Standard handler for SIOCGIWTHRSPY */
  476. extern int iw_handler_get_thrspy(struct net_device *    dev,
  477.                  struct iw_request_info *info,
  478.                  union iwreq_data *    wrqu,
  479.                  char *            extra);
  480. /* Driver call to update spy records */
  481. extern void wireless_spy_update(struct net_device *    dev,
  482.                 unsigned char *        address,
  483.                 struct iw_quality *    wstats);
  484.  
  485. /************************* INLINE FUNTIONS *************************/
  486. /*
  487.  * Function that are so simple that it's more efficient inlining them
  488.  */
  489.  
  490. /*------------------------------------------------------------------*/
  491. /*
  492.  * Wrapper to add an Wireless Event to a stream of events.
  493.  */
  494. static inline char *
  495. iwe_stream_add_event(char *    stream,        /* Stream of events */
  496.              char *    ends,        /* End of stream */
  497.              struct iw_event *iwe,    /* Payload */
  498.              int    event_len)    /* Real size of payload */
  499. {
  500.     /* Check if it's possible */
  501.     if(likely((stream + event_len) < ends)) {
  502.         iwe->len = event_len;
  503.         memcpy(stream, (char *) iwe, event_len);
  504.         stream += event_len;
  505.     }
  506.     return stream;
  507. }
  508.  
  509. /*------------------------------------------------------------------*/
  510. /*
  511.  * Wrapper to add an short Wireless Event containing a pointer to a
  512.  * stream of events.
  513.  */
  514. static inline char *
  515. iwe_stream_add_point(char *    stream,        /* Stream of events */
  516.              char *    ends,        /* End of stream */
  517.              struct iw_event *iwe,    /* Payload length + flags */
  518.              char *    extra)        /* More payload */
  519. {
  520.     int    event_len = IW_EV_POINT_LEN + iwe->u.data.length;
  521.     /* Check if it's possible */
  522.     if(likely((stream + event_len) < ends)) {
  523.         iwe->len = event_len;
  524.         memcpy(stream, (char *) iwe, IW_EV_LCP_LEN);
  525.         memcpy(stream + IW_EV_LCP_LEN,
  526.                ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
  527.                IW_EV_POINT_LEN - IW_EV_LCP_LEN);
  528.         memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
  529.         stream += event_len;
  530.     }
  531.     return stream;
  532. }
  533.  
  534. /*------------------------------------------------------------------*/
  535. /*
  536.  * Wrapper to add a value to a Wireless Event in a stream of events.
  537.  * Be careful, this one is tricky to use properly :
  538.  * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
  539.  */
  540. static inline char *
  541. iwe_stream_add_value(char *    event,        /* Event in the stream */
  542.              char *    value,        /* Value in event */
  543.              char *    ends,        /* End of stream */
  544.              struct iw_event *iwe,    /* Payload */
  545.              int    event_len)    /* Real size of payload */
  546. {
  547.     /* Don't duplicate LCP */
  548.     event_len -= IW_EV_LCP_LEN;
  549.  
  550.     /* Check if it's possible */
  551.     if(likely((value + event_len) < ends)) {
  552.         /* Add new value */
  553.         memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
  554.         value += event_len;
  555.         /* Patch LCP */
  556.         iwe->len = value - event;
  557.         memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
  558.     }
  559.     return value;
  560. }
  561.  
  562. /*------------------------------------------------------------------*/
  563. /*
  564.  * Wrapper to add an Wireless Event to a stream of events.
  565.  * Same as above, with explicit error check...
  566.  */
  567. static inline char *
  568. iwe_stream_check_add_event(char *    stream,        /* Stream of events */
  569.                char *    ends,        /* End of stream */
  570.                struct iw_event *iwe,    /* Payload */
  571.                int        event_len,    /* Size of payload */
  572.                int *    perr)        /* Error report */
  573. {
  574.     /* Check if it's possible, set error if not */
  575.     if(likely((stream + event_len) < ends)) {
  576.         iwe->len = event_len;
  577.         memcpy(stream, (char *) iwe, event_len);
  578.         stream += event_len;
  579.     } else
  580.         *perr = -E2BIG;
  581.     return stream;
  582. }
  583.  
  584. /*------------------------------------------------------------------*/
  585. /*
  586.  * Wrapper to add an short Wireless Event containing a pointer to a
  587.  * stream of events.
  588.  * Same as above, with explicit error check...
  589.  */
  590. static inline char *
  591. iwe_stream_check_add_point(char *    stream,        /* Stream of events */
  592.                char *    ends,        /* End of stream */
  593.                struct iw_event *iwe,    /* Payload length + flags */
  594.                char *    extra,        /* More payload */
  595.                int *    perr)        /* Error report */
  596. {
  597.     int    event_len = IW_EV_POINT_LEN + iwe->u.data.length;
  598.     /* Check if it's possible */
  599.     if(likely((stream + event_len) < ends)) {
  600.         iwe->len = event_len;
  601.         memcpy(stream, (char *) iwe, IW_EV_LCP_LEN);
  602.         memcpy(stream + IW_EV_LCP_LEN,
  603.                ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
  604.                IW_EV_POINT_LEN - IW_EV_LCP_LEN);
  605.         memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
  606.         stream += event_len;
  607.     } else
  608.         *perr = -E2BIG;
  609.     return stream;
  610. }
  611.  
  612. /*------------------------------------------------------------------*/
  613. /*
  614.  * Wrapper to add a value to a Wireless Event in a stream of events.
  615.  * Be careful, this one is tricky to use properly :
  616.  * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
  617.  * Same as above, with explicit error check...
  618.  */
  619. static inline char *
  620. iwe_stream_check_add_value(char *    event,        /* Event in the stream */
  621.                char *    value,        /* Value in event */
  622.                char *    ends,        /* End of stream */
  623.                struct iw_event *iwe,    /* Payload */
  624.                int        event_len,    /* Size of payload */
  625.                int *    perr)        /* Error report */
  626. {
  627.     /* Don't duplicate LCP */
  628.     event_len -= IW_EV_LCP_LEN;
  629.  
  630.     /* Check if it's possible */
  631.     if(likely((value + event_len) < ends)) {
  632.         /* Add new value */
  633.         memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
  634.         value += event_len;
  635.         /* Patch LCP */
  636.         iwe->len = value - event;
  637.         memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
  638.     } else
  639.         *perr = -E2BIG;
  640.     return value;
  641. }
  642.  
  643. #endif    /* _IW_HANDLER_H */
  644.