Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * This file define the new driver API for Wireless Extensions
0004  *
0005  * Version :    8   16.3.07
0006  *
0007  * Authors :    Jean Tourrilhes - HPL - <jt@hpl.hp.com>
0008  * Copyright (c) 2001-2007 Jean Tourrilhes, All Rights Reserved.
0009  */
0010 
0011 #ifndef _IW_HANDLER_H
0012 #define _IW_HANDLER_H
0013 
0014 /************************** DOCUMENTATION **************************/
0015 /*
0016  * Initial driver API (1996 -> onward) :
0017  * -----------------------------------
0018  * The initial API just sends the IOCTL request received from user space
0019  * to the driver (via the driver ioctl handler). The driver has to
0020  * handle all the rest...
0021  *
0022  * The initial API also defines a specific handler in struct net_device
0023  * to handle wireless statistics.
0024  *
0025  * The initial APIs served us well and has proven a reasonably good design.
0026  * However, there is a few shortcommings :
0027  *  o No events, everything is a request to the driver.
0028  *  o Large ioctl function in driver with gigantic switch statement
0029  *    (i.e. spaghetti code).
0030  *  o Driver has to mess up with copy_to/from_user, and in many cases
0031  *    does it unproperly. Common mistakes are :
0032  *      * buffer overflows (no checks or off by one checks)
0033  *      * call copy_to/from_user with irq disabled
0034  *  o The user space interface is tied to ioctl because of the use
0035  *    copy_to/from_user.
0036  *
0037  * New driver API (2002 -> onward) :
0038  * -------------------------------
0039  * The new driver API is just a bunch of standard functions (handlers),
0040  * each handling a specific Wireless Extension. The driver just export
0041  * the list of handler it supports, and those will be called apropriately.
0042  *
0043  * I tried to keep the main advantage of the previous API (simplicity,
0044  * efficiency and light weight), and also I provide a good dose of backward
0045  * compatibility (most structures are the same, driver can use both API
0046  * simultaneously, ...).
0047  * Hopefully, I've also addressed the shortcomming of the initial API.
0048  *
0049  * The advantage of the new API are :
0050  *  o Handling of Extensions in driver broken in small contained functions
0051  *  o Tighter checks of ioctl before calling the driver
0052  *  o Flexible commit strategy (at least, the start of it)
0053  *  o Backward compatibility (can be mixed with old API)
0054  *  o Driver doesn't have to worry about memory and user-space issues
0055  * The last point is important for the following reasons :
0056  *  o You are now able to call the new driver API from any API you
0057  *      want (including from within other parts of the kernel).
0058  *  o Common mistakes are avoided (buffer overflow, user space copy
0059  *      with irq disabled and so on).
0060  *
0061  * The Drawback of the new API are :
0062  *  o bloat (especially kernel)
0063  *  o need to migrate existing drivers to new API
0064  * My initial testing shows that the new API adds around 3kB to the kernel
0065  * and save between 0 and 5kB from a typical driver.
0066  * Also, as all structures and data types are unchanged, the migration is
0067  * quite straightforward (but tedious).
0068  *
0069  * ---
0070  *
0071  * The new driver API is defined below in this file. User space should
0072  * not be aware of what's happening down there...
0073  *
0074  * A new kernel wrapper is in charge of validating the IOCTLs and calling
0075  * the appropriate driver handler. This is implemented in :
0076  *  # net/core/wireless.c
0077  *
0078  * The driver export the list of handlers in :
0079  *  # include/linux/netdevice.h (one place)
0080  *
0081  * The new driver API is available for WIRELESS_EXT >= 13.
0082  * Good luck with migration to the new API ;-)
0083  */
0084 
0085 /* ---------------------- THE IMPLEMENTATION ---------------------- */
0086 /*
0087  * Some of the choice I've made are pretty controversials. Defining an
0088  * API is very much weighting compromises. This goes into some of the
0089  * details and the thinking behind the implementation.
0090  *
0091  * Implementation goals :
0092  * --------------------
0093  * The implementation goals were as follow :
0094  *  o Obvious : you should not need a PhD to understand what's happening,
0095  *      the benefit is easier maintenance.
0096  *  o Flexible : it should accommodate a wide variety of driver
0097  *      implementations and be as flexible as the old API.
0098  *  o Lean : it should be efficient memory wise to minimise the impact
0099  *      on kernel footprint.
0100  *  o Transparent to user space : the large number of user space
0101  *      applications that use Wireless Extensions should not need
0102  *      any modifications.
0103  *
0104  * Array of functions versus Struct of functions
0105  * ---------------------------------------------
0106  * 1) Having an array of functions allow the kernel code to access the
0107  * handler in a single lookup, which is much more efficient (think hash
0108  * table here).
0109  * 2) The only drawback is that driver writer may put their handler in
0110  * the wrong slot. This is trivial to test (I set the frequency, the
0111  * bitrate changes). Once the handler is in the proper slot, it will be
0112  * there forever, because the array is only extended at the end.
0113  * 3) Backward/forward compatibility : adding new handler just require
0114  * extending the array, so you can put newer driver in older kernel
0115  * without having to patch the kernel code (and vice versa).
0116  *
0117  * All handler are of the same generic type
0118  * ----------------------------------------
0119  * That's a feature !!!
0120  * 1) Having a generic handler allow to have generic code, which is more
0121  * efficient. If each of the handler was individually typed I would need
0122  * to add a big switch in the kernel (== more bloat). This solution is
0123  * more scalable, adding new Wireless Extensions doesn't add new code.
0124  * 2) You can use the same handler in different slots of the array. For
0125  * hardware, it may be more efficient or logical to handle multiple
0126  * Wireless Extensions with a single function, and the API allow you to
0127  * do that. (An example would be a single record on the card to control
0128  * both bitrate and frequency, the handler would read the old record,
0129  * modify it according to info->cmd and rewrite it).
0130  *
0131  * Functions prototype uses union iwreq_data
0132  * -----------------------------------------
0133  * Some would have preferred functions defined this way :
0134  *  static int mydriver_ioctl_setrate(struct net_device *dev, 
0135  *                    long rate, int auto)
0136  * 1) The kernel code doesn't "validate" the content of iwreq_data, and
0137  * can't do it (different hardware may have different notion of what a
0138  * valid frequency is), so we don't pretend that we do it.
0139  * 2) The above form is not extendable. If I want to add a flag (for
0140  * example to distinguish setting max rate and basic rate), I would
0141  * break the prototype. Using iwreq_data is more flexible.
0142  * 3) Also, the above form is not generic (see above).
0143  * 4) I don't expect driver developper using the wrong field of the
0144  * union (Doh !), so static typechecking doesn't add much value.
0145  * 5) Lastly, you can skip the union by doing :
0146  *  static int mydriver_ioctl_setrate(struct net_device *dev,
0147  *                    struct iw_request_info *info,
0148  *                    struct iw_param *rrq,
0149  *                    char *extra)
0150  * And then adding the handler in the array like this :
0151  *        (iw_handler) mydriver_ioctl_setrate,             // SIOCSIWRATE
0152  *
0153  * Using functions and not a registry
0154  * ----------------------------------
0155  * Another implementation option would have been for every instance to
0156  * define a registry (a struct containing all the Wireless Extensions)
0157  * and only have a function to commit the registry to the hardware.
0158  * 1) This approach can be emulated by the current code, but not
0159  * vice versa.
0160  * 2) Some drivers don't keep any configuration in the driver, for them
0161  * adding such a registry would be a significant bloat.
0162  * 3) The code to translate from Wireless Extension to native format is
0163  * needed anyway, so it would not reduce significantely the amount of code.
0164  * 4) The current approach only selectively translate Wireless Extensions
0165  * to native format and only selectively set, whereas the registry approach
0166  * would require to translate all WE and set all parameters for any single
0167  * change.
0168  * 5) For many Wireless Extensions, the GET operation return the current
0169  * dynamic value, not the value that was set.
0170  *
0171  * This header is <net/iw_handler.h>
0172  * ---------------------------------
0173  * 1) This header is kernel space only and should not be exported to
0174  * user space. Headers in "include/linux/" are exported, headers in
0175  * "include/net/" are not.
0176  *
0177  * Mixed 32/64 bit issues
0178  * ----------------------
0179  * The Wireless Extensions are designed to be 64 bit clean, by using only
0180  * datatypes with explicit storage size.
0181  * There are some issues related to kernel and user space using different
0182  * memory model, and in particular 64bit kernel with 32bit user space.
0183  * The problem is related to struct iw_point, that contains a pointer
0184  * that *may* need to be translated.
0185  * This is quite messy. The new API doesn't solve this problem (it can't),
0186  * but is a step in the right direction :
0187  * 1) Meta data about each ioctl is easily available, so we know what type
0188  * of translation is needed.
0189  * 2) The move of data between kernel and user space is only done in a single
0190  * place in the kernel, so adding specific hooks in there is possible.
0191  * 3) In the long term, it allows to move away from using ioctl as the
0192  * user space API.
0193  *
0194  * So many comments and so few code
0195  * --------------------------------
0196  * That's a feature. Comments won't bloat the resulting kernel binary.
0197  */
0198 
0199 /***************************** INCLUDES *****************************/
0200 
0201 #include <linux/wireless.h>     /* IOCTL user space API */
0202 #include <linux/if_ether.h>
0203 
0204 /***************************** VERSION *****************************/
0205 /*
0206  * This constant is used to know which version of the driver API is
0207  * available. Hopefully, this will be pretty stable and no changes
0208  * will be needed...
0209  * I just plan to increment with each new version.
0210  */
0211 #define IW_HANDLER_VERSION  8
0212 
0213 /*
0214  * Changes :
0215  *
0216  * V2 to V3
0217  * --------
0218  *  - Move event definition in <linux/wireless.h>
0219  *  - Add Wireless Event support :
0220  *      o wireless_send_event() prototype
0221  *      o iwe_stream_add_event/point() inline functions
0222  * V3 to V4
0223  * --------
0224  *  - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
0225  *
0226  * V4 to V5
0227  * --------
0228  *  - Add new spy support : struct iw_spy_data & prototypes
0229  *
0230  * V5 to V6
0231  * --------
0232  *  - Change the way we get to spy_data method for added safety
0233  *  - Remove spy #ifdef, they are always on -> cleaner code
0234  *  - Add IW_DESCR_FLAG_NOMAX flag for very large requests
0235  *  - Start migrating get_wireless_stats to struct iw_handler_def
0236  *
0237  * V6 to V7
0238  * --------
0239  *  - Add struct ieee80211_device pointer in struct iw_public_data
0240  *  - Remove (struct iw_point *)->pointer from events and streams
0241  *  - Remove spy_offset from struct iw_handler_def
0242  *  - Add "check" version of event macros for ieee802.11 stack
0243  *
0244  * V7 to V8
0245  * ----------
0246  *  - Prevent leaking of kernel space in stream on 64 bits.
0247  */
0248 
0249 /**************************** CONSTANTS ****************************/
0250 
0251 /* Enhanced spy support available */
0252 #define IW_WIRELESS_SPY
0253 #define IW_WIRELESS_THRSPY
0254 
0255 /* Special error message for the driver to indicate that we
0256  * should do a commit after return from the iw_handler */
0257 #define EIWCOMMIT   EINPROGRESS
0258 
0259 /* Flags available in struct iw_request_info */
0260 #define IW_REQUEST_FLAG_COMPAT  0x0001  /* Compat ioctl call */
0261 
0262 /* Type of headers we know about (basically union iwreq_data) */
0263 #define IW_HEADER_TYPE_NULL 0   /* Not available */
0264 #define IW_HEADER_TYPE_CHAR 2   /* char [IFNAMSIZ] */
0265 #define IW_HEADER_TYPE_UINT 4   /* __u32 */
0266 #define IW_HEADER_TYPE_FREQ 5   /* struct iw_freq */
0267 #define IW_HEADER_TYPE_ADDR 6   /* struct sockaddr */
0268 #define IW_HEADER_TYPE_POINT    8   /* struct iw_point */
0269 #define IW_HEADER_TYPE_PARAM    9   /* struct iw_param */
0270 #define IW_HEADER_TYPE_QUAL 10  /* struct iw_quality */
0271 
0272 /* Handling flags */
0273 /* Most are not implemented. I just use them as a reminder of some
0274  * cool features we might need one day ;-) */
0275 #define IW_DESCR_FLAG_NONE  0x0000  /* Obvious */
0276 /* Wrapper level flags */
0277 #define IW_DESCR_FLAG_DUMP  0x0001  /* Not part of the dump command */
0278 #define IW_DESCR_FLAG_EVENT 0x0002  /* Generate an event on SET */
0279 #define IW_DESCR_FLAG_RESTRICT  0x0004  /* GET : request is ROOT only */
0280                 /* SET : Omit payload from generated iwevent */
0281 #define IW_DESCR_FLAG_NOMAX 0x0008  /* GET : no limit on request size */
0282 /* Driver level flags */
0283 #define IW_DESCR_FLAG_WAIT  0x0100  /* Wait for driver event */
0284 
0285 /****************************** TYPES ******************************/
0286 
0287 /* ----------------------- WIRELESS HANDLER ----------------------- */
0288 /*
0289  * A wireless handler is just a standard function, that looks like the
0290  * ioctl handler.
0291  * We also define there how a handler list look like... As the Wireless
0292  * Extension space is quite dense, we use a simple array, which is faster
0293  * (that's the perfect hash table ;-).
0294  */
0295 
0296 /*
0297  * Meta data about the request passed to the iw_handler.
0298  * Most handlers can safely ignore what's in there.
0299  * The 'cmd' field might come handy if you want to use the same handler
0300  * for multiple command...
0301  * This struct is also my long term insurance. I can add new fields here
0302  * without breaking the prototype of iw_handler...
0303  */
0304 struct iw_request_info {
0305     __u16       cmd;        /* Wireless Extension command */
0306     __u16       flags;      /* More to come ;-) */
0307 };
0308 
0309 struct net_device;
0310 
0311 /*
0312  * This is how a function handling a Wireless Extension should look
0313  * like (both get and set, standard and private).
0314  */
0315 typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
0316               union iwreq_data *wrqu, char *extra);
0317 
0318 /*
0319  * This define all the handler that the driver export.
0320  * As you need only one per driver type, please use a static const
0321  * shared by all driver instances... Same for the members...
0322  * This will be linked from net_device in <linux/netdevice.h>
0323  */
0324 struct iw_handler_def {
0325 
0326     /* Array of handlers for standard ioctls
0327      * We will call dev->wireless_handlers->standard[ioctl - SIOCIWFIRST]
0328      */
0329     const iw_handler *  standard;
0330     /* Number of handlers defined (more precisely, index of the
0331      * last defined handler + 1) */
0332     __u16           num_standard;
0333 
0334 #ifdef CONFIG_WEXT_PRIV
0335     __u16           num_private;
0336     /* Number of private arg description */
0337     __u16           num_private_args;
0338     /* Array of handlers for private ioctls
0339      * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
0340      */
0341     const iw_handler *  private;
0342 
0343     /* Arguments of private handler. This one is just a list, so you
0344      * can put it in any order you want and should not leave holes...
0345      * We will automatically export that to user space... */
0346     const struct iw_priv_args * private_args;
0347 #endif
0348 
0349     /* New location of get_wireless_stats, to de-bloat struct net_device.
0350      * The old pointer in struct net_device will be gradually phased
0351      * out, and drivers are encouraged to use this one... */
0352     struct iw_statistics*   (*get_wireless_stats)(struct net_device *dev);
0353 };
0354 
0355 /* ---------------------- IOCTL DESCRIPTION ---------------------- */
0356 /*
0357  * One of the main goal of the new interface is to deal entirely with
0358  * user space/kernel space memory move.
0359  * For that, we need to know :
0360  *  o if iwreq is a pointer or contain the full data
0361  *  o what is the size of the data to copy
0362  *
0363  * For private IOCTLs, we use the same rules as used by iwpriv and
0364  * defined in struct iw_priv_args.
0365  *
0366  * For standard IOCTLs, things are quite different and we need to
0367  * use the structures below. Actually, this struct is also more
0368  * efficient, but that's another story...
0369  */
0370 
0371 /*
0372  * Describe how a standard IOCTL looks like.
0373  */
0374 struct iw_ioctl_description {
0375     __u8    header_type;        /* NULL, iw_point or other */
0376     __u8    token_type;     /* Future */
0377     __u16   token_size;     /* Granularity of payload */
0378     __u16   min_tokens;     /* Min acceptable token number */
0379     __u16   max_tokens;     /* Max acceptable token number */
0380     __u32   flags;          /* Special handling of the request */
0381 };
0382 
0383 /* Need to think of short header translation table. Later. */
0384 
0385 /* --------------------- ENHANCED SPY SUPPORT --------------------- */
0386 /*
0387  * In the old days, the driver was handling spy support all by itself.
0388  * Now, the driver can delegate this task to Wireless Extensions.
0389  * It needs to include this struct in its private part and use the
0390  * standard spy iw_handler.
0391  */
0392 
0393 /*
0394  * Instance specific spy data, i.e. addresses spied and quality for them.
0395  */
0396 struct iw_spy_data {
0397     /* --- Standard spy support --- */
0398     int         spy_number;
0399     u_char          spy_address[IW_MAX_SPY][ETH_ALEN];
0400     struct iw_quality   spy_stat[IW_MAX_SPY];
0401     /* --- Enhanced spy support (event) */
0402     struct iw_quality   spy_thr_low;    /* Low threshold */
0403     struct iw_quality   spy_thr_high;   /* High threshold */
0404     u_char          spy_thr_under[IW_MAX_SPY];
0405 };
0406 
0407 /* --------------------- DEVICE WIRELESS DATA --------------------- */
0408 /*
0409  * This is all the wireless data specific to a device instance that
0410  * is managed by the core of Wireless Extensions or the 802.11 layer.
0411  * We only keep pointer to those structures, so that a driver is free
0412  * to share them between instances.
0413  * This structure should be initialised before registering the device.
0414  * Access to this data follow the same rules as any other struct net_device
0415  * data (i.e. valid as long as struct net_device exist, same locking rules).
0416  */
0417 /* Forward declaration */
0418 struct libipw_device;
0419 /* The struct */
0420 struct iw_public_data {
0421     /* Driver enhanced spy support */
0422     struct iw_spy_data *        spy_data;
0423     /* Legacy structure managed by the ipw2x00-specific IEEE 802.11 layer */
0424     struct libipw_device *      libipw;
0425 };
0426 
0427 /**************************** PROTOTYPES ****************************/
0428 /*
0429  * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
0430  * Those may be called only within the kernel.
0431  */
0432 
0433 /* First : function strictly used inside the kernel */
0434 
0435 /* Handle /proc/net/wireless, called in net/code/dev.c */
0436 int dev_get_wireless_info(char *buffer, char **start, off_t offset, int length);
0437 
0438 /* Second : functions that may be called by driver modules */
0439 
0440 /* Send a single event to user space */
0441 void wireless_send_event(struct net_device *dev, unsigned int cmd,
0442              union iwreq_data *wrqu, const char *extra);
0443 #ifdef CONFIG_WEXT_CORE
0444 /* flush all previous wext events - if work is done from netdev notifiers */
0445 void wireless_nlevent_flush(void);
0446 #else
0447 static inline void wireless_nlevent_flush(void) {}
0448 #endif
0449 
0450 /* We may need a function to send a stream of events to user space.
0451  * More on that later... */
0452 
0453 /* Standard handler for SIOCSIWSPY */
0454 int iw_handler_set_spy(struct net_device *dev, struct iw_request_info *info,
0455                union iwreq_data *wrqu, char *extra);
0456 /* Standard handler for SIOCGIWSPY */
0457 int iw_handler_get_spy(struct net_device *dev, struct iw_request_info *info,
0458                union iwreq_data *wrqu, char *extra);
0459 /* Standard handler for SIOCSIWTHRSPY */
0460 int iw_handler_set_thrspy(struct net_device *dev, struct iw_request_info *info,
0461               union iwreq_data *wrqu, char *extra);
0462 /* Standard handler for SIOCGIWTHRSPY */
0463 int iw_handler_get_thrspy(struct net_device *dev, struct iw_request_info *info,
0464               union iwreq_data *wrqu, char *extra);
0465 /* Driver call to update spy records */
0466 void wireless_spy_update(struct net_device *dev, unsigned char *address,
0467              struct iw_quality *wstats);
0468 
0469 /************************* INLINE FUNTIONS *************************/
0470 /*
0471  * Function that are so simple that it's more efficient inlining them
0472  */
0473 
0474 static inline int iwe_stream_lcp_len(struct iw_request_info *info)
0475 {
0476 #ifdef CONFIG_COMPAT
0477     if (info->flags & IW_REQUEST_FLAG_COMPAT)
0478         return IW_EV_COMPAT_LCP_LEN;
0479 #endif
0480     return IW_EV_LCP_LEN;
0481 }
0482 
0483 static inline int iwe_stream_point_len(struct iw_request_info *info)
0484 {
0485 #ifdef CONFIG_COMPAT
0486     if (info->flags & IW_REQUEST_FLAG_COMPAT)
0487         return IW_EV_COMPAT_POINT_LEN;
0488 #endif
0489     return IW_EV_POINT_LEN;
0490 }
0491 
0492 static inline int iwe_stream_event_len_adjust(struct iw_request_info *info,
0493                           int event_len)
0494 {
0495 #ifdef CONFIG_COMPAT
0496     if (info->flags & IW_REQUEST_FLAG_COMPAT) {
0497         event_len -= IW_EV_LCP_LEN;
0498         event_len += IW_EV_COMPAT_LCP_LEN;
0499     }
0500 #endif
0501 
0502     return event_len;
0503 }
0504 
0505 /*------------------------------------------------------------------*/
0506 /*
0507  * Wrapper to add an Wireless Event to a stream of events.
0508  */
0509 char *iwe_stream_add_event(struct iw_request_info *info, char *stream,
0510                char *ends, struct iw_event *iwe, int event_len);
0511 
0512 static inline char *
0513 iwe_stream_add_event_check(struct iw_request_info *info, char *stream,
0514                char *ends, struct iw_event *iwe, int event_len)
0515 {
0516     char *res = iwe_stream_add_event(info, stream, ends, iwe, event_len);
0517 
0518     if (res == stream)
0519         return ERR_PTR(-E2BIG);
0520     return res;
0521 }
0522 
0523 /*------------------------------------------------------------------*/
0524 /*
0525  * Wrapper to add an short Wireless Event containing a pointer to a
0526  * stream of events.
0527  */
0528 char *iwe_stream_add_point(struct iw_request_info *info, char *stream,
0529                char *ends, struct iw_event *iwe, char *extra);
0530 
0531 static inline char *
0532 iwe_stream_add_point_check(struct iw_request_info *info, char *stream,
0533                char *ends, struct iw_event *iwe, char *extra)
0534 {
0535     char *res = iwe_stream_add_point(info, stream, ends, iwe, extra);
0536 
0537     if (res == stream)
0538         return ERR_PTR(-E2BIG);
0539     return res;
0540 }
0541 
0542 /*------------------------------------------------------------------*/
0543 /*
0544  * Wrapper to add a value to a Wireless Event in a stream of events.
0545  * Be careful, this one is tricky to use properly :
0546  * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
0547  */
0548 char *iwe_stream_add_value(struct iw_request_info *info, char *event,
0549                char *value, char *ends, struct iw_event *iwe,
0550                int event_len);
0551 
0552 #endif  /* _IW_HANDLER_H */