fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / include / net / iw_handler.h
index 5e70aed..10559e9 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * This file define the new driver API for Wireless Extensions
  *
- * Version :   5       4.12.02
+ * Version :   7       18.3.05
  *
  * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved.
  */
 
 #ifndef _IW_HANDLER_H
 /***************************** INCLUDES *****************************/
 
 #include <linux/wireless.h>            /* IOCTL user space API */
+#include <linux/if_ether.h>
 
 /***************************** VERSION *****************************/
 /*
  * will be needed...
  * I just plan to increment with each new version.
  */
-#define IW_HANDLER_VERSION     5
+#define IW_HANDLER_VERSION     7
 
 /*
  * Changes :
  * V4 to V5
  * --------
  *     - Add new spy support : struct iw_spy_data & prototypes
+ *
+ * V5 to V6
+ * --------
+ *     - Change the way we get to spy_data method for added safety
+ *     - Remove spy #ifdef, they are always on -> cleaner code
+ *     - Add IW_DESCR_FLAG_NOMAX flag for very large requests
+ *     - Start migrating get_wireless_stats to struct iw_handler_def
+ *
+ * V6 to V7
+ * --------
+ *     - Add struct ieee80211_device pointer in struct iw_public_data
+ *     - Remove (struct iw_point *)->pointer from events and streams
+ *     - Remove spy_offset from struct iw_handler_def
+ *     - Add "check" version of event macros for ieee802.11 stack
  */
 
 /**************************** CONSTANTS ****************************/
 
-/* Enable enhanced spy support. Disable to reduce footprint */
+/* Enhanced spy support available */
 #define IW_WIRELESS_SPY
 #define IW_WIRELESS_THRSPY
 
 #define IW_DESCR_FLAG_EVENT    0x0002  /* Generate an event on SET */
 #define IW_DESCR_FLAG_RESTRICT 0x0004  /* GET : request is ROOT only */
                                /* SET : Omit payload from generated iwevent */
+#define IW_DESCR_FLAG_NOMAX    0x0008  /* GET : no limit on request size */
 /* Driver level flags */
 #define IW_DESCR_FLAG_WAIT     0x0100  /* Wait for driver event */
 
@@ -286,6 +302,8 @@ struct iw_request_info
        __u16           flags;          /* More to come ;-) */
 };
 
+struct net_device;
+
 /*
  * This is how a function handling a Wireless Extension should look
  * like (both get and set, standard and private).
@@ -309,25 +327,24 @@ struct iw_handler_def
        __u16                   num_private_args;
 
        /* Array of handlers for standard ioctls
-        * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
+        * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
         */
-       iw_handler *            standard;
+       const iw_handler *      standard;
 
        /* Array of handlers for private ioctls
         * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
         */
-       iw_handler *            private;
+       const iw_handler *      private;
 
        /* Arguments of private handler. This one is just a list, so you
         * can put it in any order you want and should not leave holes...
         * We will automatically export that to user space... */
-       struct iw_priv_args *   private_args;
-
-       /* Driver enhanced spy support */
-       long                    spy_offset;     /* Spy data offset */
+       const struct iw_priv_args *     private_args;
 
-       /* In the long term, get_wireless_stats will move from
-        * 'struct net_device' to here, to minimise bloat. */
+       /* New location of get_wireless_stats, to de-bloat struct net_device.
+        * The old pointer in struct net_device will be gradually phased
+        * out, and drivers are encouraged to use this one... */
+       struct iw_statistics*   (*get_wireless_stats)(struct net_device *dev);
 };
 
 /* ---------------------- IOCTL DESCRIPTION ---------------------- */
@@ -374,18 +391,34 @@ struct iw_ioctl_description
  */
 struct iw_spy_data
 {
-#ifdef IW_WIRELESS_SPY
        /* --- Standard spy support --- */
        int                     spy_number;
        u_char                  spy_address[IW_MAX_SPY][ETH_ALEN];
        struct iw_quality       spy_stat[IW_MAX_SPY];
-#ifdef IW_WIRELESS_THRSPY
        /* --- Enhanced spy support (event) */
        struct iw_quality       spy_thr_low;    /* Low threshold */
        struct iw_quality       spy_thr_high;   /* High threshold */
        u_char                  spy_thr_under[IW_MAX_SPY];
-#endif /* IW_WIRELESS_THRSPY */
-#endif /* IW_WIRELESS_SPY */
+};
+
+/* --------------------- DEVICE WIRELESS DATA --------------------- */
+/*
+ * This is all the wireless data specific to a device instance that
+ * is managed by the core of Wireless Extensions or the 802.11 layer.
+ * We only keep pointer to those structures, so that a driver is free
+ * to share them between instances.
+ * This structure should be initialised before registering the device.
+ * Access to this data follow the same rules as any other struct net_device
+ * data (i.e. valid as long as struct net_device exist, same locking rules).
+ */
+/* Forward declaration */
+struct ieee80211_device;
+/* The struct */
+struct iw_public_data {
+       /* Driver enhanced spy support */
+       struct iw_spy_data *            spy_data;
+       /* Structure managed by the in-kernel IEEE 802.11 layer */
+       struct ieee80211_device *       ieee80211;
 };
 
 /**************************** PROTOTYPES ****************************/
@@ -400,9 +433,19 @@ struct iw_spy_data
 extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
                                 int length);
 
-/* Handle IOCTLs, called in net/code/dev.c */
+/* Handle IOCTLs, called in net/core/dev.c */
 extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
 
+/* Handle RtNetlink requests, called in net/core/rtnetlink.c */
+extern int wireless_rtnetlink_set(struct net_device *  dev,
+                                 char *                data,
+                                 int                   len);
+extern int wireless_rtnetlink_get(struct net_device *  dev,
+                                 char *                data,
+                                 int                   len,
+                                 char **               p_buf,
+                                 int *                 p_len);
+
 /* Second : functions that may be called by driver modules */
 
 /* Send a single event to user space */
@@ -455,7 +498,7 @@ iwe_stream_add_event(char * stream,         /* Stream of events */
                     int        event_len)      /* Real size of payload */
 {
        /* Check if it's possible */
-       if((stream + event_len) < ends) {
+       if(likely((stream + event_len) < ends)) {
                iwe->len = event_len;
                memcpy(stream, (char *) iwe, event_len);
                stream += event_len;
@@ -471,14 +514,17 @@ iwe_stream_add_event(char *       stream,         /* Stream of events */
 static inline char *
 iwe_stream_add_point(char *    stream,         /* Stream of events */
                     char *     ends,           /* End of stream */
-                    struct iw_event *iwe,      /* Payload */
-                    char *     extra)
+                    struct iw_event *iwe,      /* Payload length + flags */
+                    char *     extra)          /* More payload */
 {
        int     event_len = IW_EV_POINT_LEN + iwe->u.data.length;
        /* Check if it's possible */
-       if((stream + event_len) < ends) {
+       if(likely((stream + event_len) < ends)) {
                iwe->len = event_len;
-               memcpy(stream, (char *) iwe, IW_EV_POINT_LEN);
+               memcpy(stream, (char *) iwe, IW_EV_LCP_LEN);
+               memcpy(stream + IW_EV_LCP_LEN,
+                      ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
+                      IW_EV_POINT_LEN - IW_EV_LCP_LEN);
                memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
                stream += event_len;
        }
@@ -502,7 +548,7 @@ iwe_stream_add_value(char * event,          /* Event in the stream */
        event_len -= IW_EV_LCP_LEN;
 
        /* Check if it's possible */
-       if((value + event_len) < ends) {
+       if(likely((value + event_len) < ends)) {
                /* Add new value */
                memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
                value += event_len;
@@ -513,4 +559,85 @@ iwe_stream_add_value(char *        event,          /* Event in the stream */
        return value;
 }
 
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add an Wireless Event to a stream of events.
+ * Same as above, with explicit error check...
+ */
+static inline char *
+iwe_stream_check_add_event(char *      stream,         /* Stream of events */
+                          char *       ends,           /* End of stream */
+                          struct iw_event *iwe,        /* Payload */
+                          int          event_len,      /* Size of payload */
+                          int *        perr)           /* Error report */
+{
+       /* Check if it's possible, set error if not */
+       if(likely((stream + event_len) < ends)) {
+               iwe->len = event_len;
+               memcpy(stream, (char *) iwe, event_len);
+               stream += event_len;
+       } else
+               *perr = -E2BIG;
+       return stream;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add an short Wireless Event containing a pointer to a
+ * stream of events.
+ * Same as above, with explicit error check...
+ */
+static inline char *
+iwe_stream_check_add_point(char *      stream,         /* Stream of events */
+                          char *       ends,           /* End of stream */
+                          struct iw_event *iwe,        /* Payload length + flags */
+                          char *       extra,          /* More payload */
+                          int *        perr)           /* Error report */
+{
+       int     event_len = IW_EV_POINT_LEN + iwe->u.data.length;
+       /* Check if it's possible */
+       if(likely((stream + event_len) < ends)) {
+               iwe->len = event_len;
+               memcpy(stream, (char *) iwe, IW_EV_LCP_LEN);
+               memcpy(stream + IW_EV_LCP_LEN,
+                      ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
+                      IW_EV_POINT_LEN - IW_EV_LCP_LEN);
+               memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
+               stream += event_len;
+       } else
+               *perr = -E2BIG;
+       return stream;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add a value to a Wireless Event in a stream of events.
+ * Be careful, this one is tricky to use properly :
+ * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
+ * Same as above, with explicit error check...
+ */
+static inline char *
+iwe_stream_check_add_value(char *      event,          /* Event in the stream */
+                          char *       value,          /* Value in event */
+                          char *       ends,           /* End of stream */
+                          struct iw_event *iwe,        /* Payload */
+                          int          event_len,      /* Size of payload */
+                          int *        perr)           /* Error report */
+{
+       /* Don't duplicate LCP */
+       event_len -= IW_EV_LCP_LEN;
+
+       /* Check if it's possible */
+       if(likely((value + event_len) < ends)) {
+               /* Add new value */
+               memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
+               value += event_len;
+               /* Patch LCP */
+               iwe->len = value - event;
+               memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
+       } else
+               *perr = -E2BIG;
+       return value;
+}
+
 #endif /* _IW_HANDLER_H */