Bluetooth: Fix double L2CAP connection request
[safe/jmp/linux-2.6] / include / net / iw_handler.h
index 44edd48..51b9a37 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * This file define the new driver API for Wireless Extensions
  *
- * Version :   6       21.6.04
+ * Version :   8       16.3.07
  *
  * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 2001-2007 Jean Tourrilhes, All Rights Reserved.
  */
 
 #ifndef _IW_HANDLER_H
  * will be needed...
  * I just plan to increment with each new version.
  */
-#define IW_HANDLER_VERSION     6
+#define IW_HANDLER_VERSION     8
 
 /*
  * Changes :
  *     - 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
+ *
+ * V7 to V8
+ * ----------
+ *     - Prevent leaking of kernel space in stream on 64 bits.
  */
 
 /**************************** CONSTANTS ****************************/
 #define EIWCOMMIT      EINPROGRESS
 
 /* Flags available in struct iw_request_info */
-#define IW_REQUEST_FLAG_NONE   0x0000  /* No flag so far */
+#define IW_REQUEST_FLAG_COMPAT 0x0001  /* Compat ioctl call */
 
 /* Type of headers we know about (basically union iwreq_data) */
 #define IW_HEADER_TYPE_NULL    0       /* Not available */
@@ -320,7 +331,7 @@ 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]
         */
        const iw_handler *      standard;
 
@@ -334,9 +345,6 @@ struct iw_handler_def
         * We will automatically export that to user space... */
        const struct iw_priv_args *     private_args;
 
-       /* This field will be *removed* in the next version of WE */
-       long                    spy_offset;     /* DO NOT USE */
-
        /* 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... */
@@ -400,16 +408,21 @@ struct iw_spy_data
 /* --------------------- DEVICE WIRELESS DATA --------------------- */
 /*
  * This is all the wireless data specific to a device instance that
- * is managed by the core of Wireless Extensions.
+ * 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;
+       struct iw_spy_data *            spy_data;
+       /* Structure managed by the in-kernel IEEE 802.11 layer */
+       struct ieee80211_device *       ieee80211;
 };
 
 /**************************** PROTOTYPES ****************************/
@@ -424,9 +437,6 @@ struct iw_public_data {
 extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
                                 int length);
 
-/* Handle IOCTLs, called in net/code/dev.c */
-extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
-
 /* Second : functions that may be called by driver modules */
 
 /* Send a single event to user space */
@@ -468,20 +478,56 @@ extern void wireless_spy_update(struct net_device *       dev,
  * Function that are so simple that it's more efficient inlining them
  */
 
+static inline int iwe_stream_lcp_len(struct iw_request_info *info)
+{
+#ifdef CONFIG_COMPAT
+       if (info->flags & IW_REQUEST_FLAG_COMPAT)
+               return IW_EV_COMPAT_LCP_LEN;
+#endif
+       return IW_EV_LCP_LEN;
+}
+
+static inline int iwe_stream_point_len(struct iw_request_info *info)
+{
+#ifdef CONFIG_COMPAT
+       if (info->flags & IW_REQUEST_FLAG_COMPAT)
+               return IW_EV_COMPAT_POINT_LEN;
+#endif
+       return IW_EV_POINT_LEN;
+}
+
+static inline int iwe_stream_event_len_adjust(struct iw_request_info *info,
+                                             int event_len)
+{
+#ifdef CONFIG_COMPAT
+       if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+               event_len -= IW_EV_LCP_LEN;
+               event_len += IW_EV_COMPAT_LCP_LEN;
+       }
+#endif
+
+       return event_len;
+}
+
 /*------------------------------------------------------------------*/
 /*
  * Wrapper to add an Wireless Event to a stream of events.
  */
 static inline char *
-iwe_stream_add_event(char *    stream,         /* Stream of events */
-                    char *     ends,           /* End of stream */
-                    struct iw_event *iwe,      /* Payload */
-                    int        event_len)      /* Real size of payload */
+iwe_stream_add_event(struct iw_request_info *info, char *stream, char *ends,
+                    struct iw_event *iwe, int event_len)
 {
+       int lcp_len = iwe_stream_lcp_len(info);
+
+       event_len = iwe_stream_event_len_adjust(info, event_len);
+
        /* 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);
+               /* Beware of alignement issues on 64 bits */
+               memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
+               memcpy(stream + lcp_len, &iwe->u,
+                      event_len - lcp_len);
                stream += event_len;
        }
        return stream;
@@ -493,17 +539,21 @@ iwe_stream_add_event(char *       stream,         /* Stream of events */
  * 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)
+iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends,
+                    struct iw_event *iwe, char *extra)
 {
-       int     event_len = IW_EV_POINT_LEN + iwe->u.data.length;
+       int event_len = iwe_stream_point_len(info) + iwe->u.data.length;
+       int point_len = iwe_stream_point_len(info);
+       int lcp_len   = iwe_stream_lcp_len(info);
+
        /* 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 + IW_EV_POINT_LEN, extra, iwe->u.data.length);
+               memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
+               memcpy(stream + lcp_len,
+                      ((char *) &iwe->u) + IW_EV_POINT_OFF,
+                      IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
+               memcpy(stream + point_len, extra, iwe->u.data.length);
                stream += event_len;
        }
        return stream;
@@ -516,23 +566,22 @@ iwe_stream_add_point(char *       stream,         /* Stream of events */
  * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
  */
 static inline char *
-iwe_stream_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)      /* Real size of payload */
+iwe_stream_add_value(struct iw_request_info *info, char *event, char *value,
+                    char *ends, struct iw_event *iwe, int event_len)
 {
+       int lcp_len = iwe_stream_lcp_len(info);
+
        /* Don't duplicate LCP */
        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);
+               memcpy(value, &iwe->u, event_len);
                value += event_len;
                /* Patch LCP */
                iwe->len = value - event;
-               memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
+               memcpy(event, (char *) iwe, lcp_len);
        }
        return value;
 }