2
* This file define the new driver API for Wireless Extensions
6
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
7
* Copyright (c) 2001-2007 Jean Tourrilhes, All Rights Reserved.
13
/************************** DOCUMENTATION **************************/
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...
21
* The initial API also defines a specific handler in struct net_device
22
* to handle wireless statistics.
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
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.
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.
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).
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).
70
* The new driver API is defined below in this file. User space should
71
* not be aware of what's happening down there...
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
77
* The driver export the list of handlers in :
78
* # include/linux/netdevice.h (one place)
80
* The new driver API is available for WIRELESS_EXT >= 13.
81
* Good luck with migration to the new API ;-)
84
/* ---------------------- THE IMPLEMENTATION ---------------------- */
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.
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
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
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).
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).
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,
149
* And then adding the handler in the array like this :
150
* (iw_handler) mydriver_ioctl_setrate, // SIOCSIWRATE
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
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
167
* 5) For many Wireless Extensions, the GET operation return the current
168
* dynamic value, not the value that was set.
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.
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
193
* So many comments and so few code
194
* --------------------------------
195
* That's a feature. Comments won't bloat the resulting kernel binary.
198
/***************************** INCLUDES *****************************/
200
#include <linux/wireless.h> /* IOCTL user space API */
201
#include <linux/if_ether.h>
203
/***************************** VERSION *****************************/
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
208
* I just plan to increment with each new version.
210
#define IW_HANDLER_VERSION 8
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
223
* - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
227
* - Add new spy support : struct iw_spy_data & prototypes
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
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
245
* - Prevent leaking of kernel space in stream on 64 bits.
248
/**************************** CONSTANTS ****************************/
250
/* Enhanced spy support available */
251
#define IW_WIRELESS_SPY
252
#define IW_WIRELESS_THRSPY
254
/* Special error message for the driver to indicate that we
255
* should do a commit after return from the iw_handler */
256
#define EIWCOMMIT EINPROGRESS
258
/* Flags available in struct iw_request_info */
259
#define IW_REQUEST_FLAG_NONE 0x0000 /* No flag so far */
261
/* Type of headers we know about (basically union iwreq_data) */
262
#define IW_HEADER_TYPE_NULL 0 /* Not available */
263
#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
264
#define IW_HEADER_TYPE_UINT 4 /* __u32 */
265
#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
266
#define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */
267
#define IW_HEADER_TYPE_POINT 8 /* struct iw_point */
268
#define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */
269
#define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */
272
/* Most are not implemented. I just use them as a reminder of some
273
* cool features we might need one day ;-) */
274
#define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
275
/* Wrapper level flags */
276
#define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
277
#define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
278
#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
279
/* SET : Omit payload from generated iwevent */
280
#define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
281
/* Driver level flags */
282
#define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
284
/****************************** TYPES ******************************/
286
/* ----------------------- WIRELESS HANDLER ----------------------- */
288
* A wireless handler is just a standard function, that looks like the
290
* We also define there how a handler list look like... As the Wireless
291
* Extension space is quite dense, we use a simple array, which is faster
292
* (that's the perfect hash table ;-).
296
* Meta data about the request passed to the iw_handler.
297
* Most handlers can safely ignore what's in there.
298
* The 'cmd' field might come handy if you want to use the same handler
299
* for multiple command...
300
* This struct is also my long term insurance. I can add new fields here
301
* without breaking the prototype of iw_handler...
303
struct iw_request_info
305
__u16 cmd; /* Wireless Extension command */
306
__u16 flags; /* More to come ;-) */
312
* This is how a function handling a Wireless Extension should look
313
* like (both get and set, standard and private).
315
typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
316
union iwreq_data *wrqu, char *extra);
319
* This define all the handler that the driver export.
320
* As you need only one per driver type, please use a static const
321
* shared by all driver instances... Same for the members...
322
* This will be linked from net_device in <linux/netdevice.h>
324
struct iw_handler_def
326
/* Number of handlers defined (more precisely, index of the
327
* last defined handler + 1) */
330
/* Number of private arg description */
331
__u16 num_private_args;
333
/* Array of handlers for standard ioctls
334
* We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
336
const iw_handler * standard;
338
/* Array of handlers for private ioctls
339
* Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
341
const iw_handler * private;
343
/* Arguments of private handler. This one is just a list, so you
344
* can put it in any order you want and should not leave holes...
345
* We will automatically export that to user space... */
346
const struct iw_priv_args * private_args;
348
/* New location of get_wireless_stats, to de-bloat struct net_device.
349
* The old pointer in struct net_device will be gradually phased
350
* out, and drivers are encouraged to use this one... */
351
struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
354
/* ---------------------- IOCTL DESCRIPTION ---------------------- */
356
* One of the main goal of the new interface is to deal entirely with
357
* user space/kernel space memory move.
358
* For that, we need to know :
359
* o if iwreq is a pointer or contain the full data
360
* o what is the size of the data to copy
362
* For private IOCTLs, we use the same rules as used by iwpriv and
363
* defined in struct iw_priv_args.
365
* For standard IOCTLs, things are quite different and we need to
366
* use the stuctures below. Actually, this struct is also more
367
* efficient, but that's another story...
371
* Describe how a standard IOCTL looks like.
373
struct iw_ioctl_description
375
__u8 header_type; /* NULL, iw_point or other */
376
__u8 token_type; /* Future */
377
__u16 token_size; /* Granularity of payload */
378
__u16 min_tokens; /* Min acceptable token number */
379
__u16 max_tokens; /* Max acceptable token number */
380
__u32 flags; /* Special handling of the request */
383
/* Need to think of short header translation table. Later. */
385
/* --------------------- ENHANCED SPY SUPPORT --------------------- */
387
* In the old days, the driver was handling spy support all by itself.
388
* Now, the driver can delegate this task to Wireless Extensions.
389
* It needs to include this struct in its private part and use the
390
* standard spy iw_handler.
394
* Instance specific spy data, i.e. addresses spied and quality for them.
398
/* --- Standard spy support --- */
400
u_char spy_address[IW_MAX_SPY][ETH_ALEN];
401
struct iw_quality spy_stat[IW_MAX_SPY];
402
/* --- Enhanced spy support (event) */
403
struct iw_quality spy_thr_low; /* Low threshold */
404
struct iw_quality spy_thr_high; /* High threshold */
405
u_char spy_thr_under[IW_MAX_SPY];
408
/* --------------------- DEVICE WIRELESS DATA --------------------- */
410
* This is all the wireless data specific to a device instance that
411
* is managed by the core of Wireless Extensions or the 802.11 layer.
412
* We only keep pointer to those structures, so that a driver is free
413
* to share them between instances.
414
* This structure should be initialised before registering the device.
415
* Access to this data follow the same rules as any other struct net_device
416
* data (i.e. valid as long as struct net_device exist, same locking rules).
418
/* Forward declaration */
419
struct ieee80211_device;
421
struct iw_public_data {
422
/* Driver enhanced spy support */
423
struct iw_spy_data * spy_data;
424
/* Structure managed by the in-kernel IEEE 802.11 layer */
425
struct ieee80211_device * ieee80211;
428
/**************************** PROTOTYPES ****************************/
430
* Functions part of the Wireless Extensions (defined in net/core/wireless.c).
431
* Those may be called only within the kernel.
434
/* functions that may be called by driver modules */
436
/* Send a single event to user space */
437
extern void wireless_send_event(struct net_device * dev,
439
union iwreq_data * wrqu,
442
/* We may need a function to send a stream of events to user space.
443
* More on that later... */
445
/* Standard handler for SIOCSIWSPY */
446
extern int iw_handler_set_spy(struct net_device * dev,
447
struct iw_request_info * info,
448
union iwreq_data * wrqu,
450
/* Standard handler for SIOCGIWSPY */
451
extern int iw_handler_get_spy(struct net_device * dev,
452
struct iw_request_info * info,
453
union iwreq_data * wrqu,
455
/* Standard handler for SIOCSIWTHRSPY */
456
extern int iw_handler_set_thrspy(struct net_device * dev,
457
struct iw_request_info *info,
458
union iwreq_data * wrqu,
460
/* Standard handler for SIOCGIWTHRSPY */
461
extern int iw_handler_get_thrspy(struct net_device * dev,
462
struct iw_request_info *info,
463
union iwreq_data * wrqu,
465
/* Driver call to update spy records */
466
extern void wireless_spy_update(struct net_device * dev,
467
unsigned char * address,
468
struct iw_quality * wstats);
470
/************************* INLINE FUNTIONS *************************/
472
* Function that are so simple that it's more efficient inlining them
475
/*------------------------------------------------------------------*/
477
* Wrapper to add an Wireless Event to a stream of events.
480
iwe_stream_add_event(char * stream, /* Stream of events */
481
char * ends, /* End of stream */
482
struct iw_event *iwe, /* Payload */
483
int event_len) /* Real size of payload */
485
/* Check if it's possible */
486
if(likely((stream + event_len) < ends)) {
487
iwe->len = event_len;
488
/* Beware of alignement issues on 64 bits */
489
memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
490
memcpy(stream + IW_EV_LCP_LEN,
491
((char *) iwe) + IW_EV_LCP_LEN,
492
event_len - IW_EV_LCP_LEN);
498
/*------------------------------------------------------------------*/
500
* Wrapper to add an short Wireless Event containing a pointer to a
504
iwe_stream_add_point(char * stream, /* Stream of events */
505
char * ends, /* End of stream */
506
struct iw_event *iwe, /* Payload length + flags */
507
char * extra) /* More payload */
509
int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
510
/* Check if it's possible */
511
if(likely((stream + event_len) < ends)) {
512
iwe->len = event_len;
513
memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
514
memcpy(stream + IW_EV_LCP_LEN,
515
((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
516
IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
517
memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
523
/*------------------------------------------------------------------*/
525
* Wrapper to add a value to a Wireless Event in a stream of events.
526
* Be careful, this one is tricky to use properly :
527
* At the first run, you need to have (value = event + IW_EV_LCP_LEN).
530
iwe_stream_add_value(char * event, /* Event in the stream */
531
char * value, /* Value in event */
532
char * ends, /* End of stream */
533
struct iw_event *iwe, /* Payload */
534
int event_len) /* Real size of payload */
536
/* Don't duplicate LCP */
537
event_len -= IW_EV_LCP_LEN;
539
/* Check if it's possible */
540
if(likely((value + event_len) < ends)) {
542
memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
545
iwe->len = value - event;
546
memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
551
/*------------------------------------------------------------------*/
553
* Wrapper to add an Wireless Event to a stream of events.
554
* Same as above, with explicit error check...
557
iwe_stream_check_add_event(char * stream, /* Stream of events */
558
char * ends, /* End of stream */
559
struct iw_event *iwe, /* Payload */
560
int event_len, /* Size of payload */
561
int * perr) /* Error report */
563
/* Check if it's possible, set error if not */
564
if(likely((stream + event_len) < ends)) {
565
iwe->len = event_len;
566
/* Beware of alignement issues on 64 bits */
567
memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
568
memcpy(stream + IW_EV_LCP_LEN,
569
((char *) iwe) + IW_EV_LCP_LEN,
570
event_len - IW_EV_LCP_LEN);
577
/*------------------------------------------------------------------*/
579
* Wrapper to add an short Wireless Event containing a pointer to a
581
* Same as above, with explicit error check...
584
iwe_stream_check_add_point(char * stream, /* Stream of events */
585
char * ends, /* End of stream */
586
struct iw_event *iwe, /* Payload length + flags */
587
char * extra, /* More payload */
588
int * perr) /* Error report */
590
int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
591
/* Check if it's possible */
592
if(likely((stream + event_len) < ends)) {
593
iwe->len = event_len;
594
memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
595
memcpy(stream + IW_EV_LCP_LEN,
596
((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
597
IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
598
memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
605
/*------------------------------------------------------------------*/
607
* Wrapper to add a value to a Wireless Event in a stream of events.
608
* Be careful, this one is tricky to use properly :
609
* At the first run, you need to have (value = event + IW_EV_LCP_LEN).
610
* Same as above, with explicit error check...
613
iwe_stream_check_add_value(char * event, /* Event in the stream */
614
char * value, /* Value in event */
615
char * ends, /* End of stream */
616
struct iw_event *iwe, /* Payload */
617
int event_len, /* Size of payload */
618
int * perr) /* Error report */
620
/* Don't duplicate LCP */
621
event_len -= IW_EV_LCP_LEN;
623
/* Check if it's possible */
624
if(likely((value + event_len) < ends)) {
626
memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
629
iwe->len = value - event;
630
memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
636
#endif /* _IW_HANDLER_H */