| 1 |
|
| 2 | |
| 3 | * This file define the new driver API for Wireless Extensions
|
| 4 | *
|
| 5 | * Version : 8 16.3.07
|
| 6 | *
|
| 7 | * Authors : Jean Tourrilhes - HPL - <[email protected]>
|
| 8 | * Copyright (c) 2001-2007 Jean Tourrilhes, All Rights Reserved.
|
| 9 |
|
| 10 |
|
| 11 | #ifndef _IW_HANDLER_H
|
| 12 | #define _IW_HANDLER_H
|
| 13 |
|
| 14 |
|
| 15 | |
| 16 | * Initial driver API (1996 -> onward) :
|
| 17 | * -----------------------------------
|
| 18 | * The initial API just sends the IOCTL request received from user space
|
| 19 | * to the driver (via the driver ioctl handler). The driver has to
|
| 20 | * handle all the rest...
|
| 21 | *
|
| 22 | * The initial API also defines a specific handler in struct net_device
|
| 23 | * to handle wireless statistics.
|
| 24 | *
|
| 25 | * The initial APIs served us well and has proven a reasonably good design.
|
| 26 | * However, there are a few shortcomings :
|
| 27 | * o No events, everything is a request to the driver.
|
| 28 | * o Large ioctl function in driver with gigantic switch statement
|
| 29 | * (i.e. spaghetti code).
|
| 30 | * o Driver has to mess up with copy_to/from_user, and in many cases
|
| 31 | * does it unproperly. Common mistakes are :
|
| 32 | * * buffer overflows (no checks or off by one checks)
|
| 33 | * * call copy_to/from_user with irq disabled
|
| 34 | * o The user space interface is tied to ioctl because of the use
|
| 35 | * copy_to/from_user.
|
| 36 | *
|
| 37 | * New driver API (2002 -> onward) :
|
| 38 | * -------------------------------
|
| 39 | * The new driver API is just a bunch of standard functions (handlers),
|
| 40 | * each handling a specific Wireless Extension. The driver just export
|
| 41 | * the list of handler it supports, and those will be called appropriately.
|
| 42 | *
|
| 43 | * I tried to keep the main advantage of the previous API (simplicity,
|
| 44 | * efficiency and light weight), and also I provide a good dose of backward
|
| 45 | * compatibility (most structures are the same, driver can use both API
|
| 46 | * simultaneously, ...).
|
| 47 | * Hopefully, I've also addressed the shortcoming of the initial API.
|
| 48 | *
|
| 49 | * The advantage of the new API are :
|
| 50 | * o Handling of Extensions in driver broken in small contained functions
|
| 51 | * o Tighter checks of ioctl before calling the driver
|
| 52 | * o Flexible commit strategy (at least, the start of it)
|
| 53 | * o Backward compatibility (can be mixed with old API)
|
| 54 | * o Driver doesn't have to worry about memory and user-space issues
|
| 55 | * The last point is important for the following reasons :
|
| 56 | * o You are now able to call the new driver API from any API you
|
| 57 | * want (including from within other parts of the kernel).
|
| 58 | * o Common mistakes are avoided (buffer overflow, user space copy
|
| 59 | * with irq disabled and so on).
|
| 60 | *
|
| 61 | * The Drawback of the new API are :
|
| 62 | * o bloat (especially kernel)
|
| 63 | * o need to migrate existing drivers to new API
|
| 64 | * My initial testing shows that the new API adds around 3kB to the kernel
|
| 65 | * and save between 0 and 5kB from a typical driver.
|
| 66 | * Also, as all structures and data types are unchanged, the migration is
|
| 67 | * quite straightforward (but tedious).
|
| 68 | *
|
| 69 | * ---
|
| 70 | *
|
| 71 | * The new driver API is defined below in this file. User space should
|
| 72 | * not be aware of what's happening down there...
|
| 73 | *
|
| 74 | * A new kernel wrapper is in charge of validating the IOCTLs and calling
|
| 75 | * the appropriate driver handler. This is implemented in :
|
| 76 | * # net/core/wireless.c
|
| 77 | *
|
| 78 | * The driver export the list of handlers in :
|
| 79 | * # include/linux/netdevice.h (one place)
|
| 80 | *
|
| 81 | * The new driver API is available for WIRELESS_EXT >= 13.
|
| 82 | * Good luck with migration to the new API ;-)
|
| 83 |
|
| 84 |
|
| 85 |
|
| 86 | |
| 87 | * Some of the choice I've made are pretty controversial. Defining an
|
| 88 | * API is very much weighting compromises. This goes into some of the
|
| 89 | * details and the thinking behind the implementation.
|
| 90 | *
|
| 91 | * Implementation goals :
|
| 92 | * --------------------
|
| 93 | * The implementation goals were as follow :
|
| 94 | * o Obvious : you should not need a PhD to understand what's happening,
|
| 95 | * the benefit is easier maintenance.
|
| 96 | * o Flexible : it should accommodate a wide variety of driver
|
| 97 | * implementations and be as flexible as the old API.
|
| 98 | * o Lean : it should be efficient memory wise to minimise the impact
|
| 99 | * on kernel footprint.
|
| 100 | * o Transparent to user space : the large number of user space
|
| 101 | * applications that use Wireless Extensions should not need
|
| 102 | * any modifications.
|
| 103 | *
|
| 104 | * Array of functions versus Struct of functions
|
| 105 | * ---------------------------------------------
|
| 106 | * 1) Having an array of functions allow the kernel code to access the
|
| 107 | * handler in a single lookup, which is much more efficient (think hash
|
| 108 | * table here).
|
| 109 | * 2) The only drawback is that driver writer may put their handler in
|
| 110 | * the wrong slot. This is trivial to test (I set the frequency, the
|
| 111 | * bitrate changes). Once the handler is in the proper slot, it will be
|
| 112 | * there forever, because the array is only extended at the end.
|
| 113 | * 3) Backward/forward compatibility : adding new handler just require
|
| 114 | * extending the array, so you can put newer driver in older kernel
|
| 115 | * without having to patch the kernel code (and vice versa).
|
| 116 | *
|
| 117 | * All handler are of the same generic type
|
| 118 | * ----------------------------------------
|
| 119 | * That's a feature !!!
|
| 120 | * 1) Having a generic handler allow to have generic code, which is more
|
| 121 | * efficient. If each of the handler was individually typed I would need
|
| 122 | * to add a big switch in the kernel (== more bloat). This solution is
|
| 123 | * more scalable, adding new Wireless Extensions doesn't add new code.
|
| 124 | * 2) You can use the same handler in different slots of the array. For
|
| 125 | * hardware, it may be more efficient or logical to handle multiple
|
| 126 | * Wireless Extensions with a single function, and the API allow you to
|
| 127 | * do that. (An example would be a single record on the card to control
|
| 128 | * both bitrate and frequency, the handler would read the old record,
|
| 129 | * modify it according to info->cmd and rewrite it).
|
| 130 | *
|
| 131 | * Functions prototype uses union iwreq_data
|
| 132 | * -----------------------------------------
|
| 133 | * Some would have preferred functions defined this way :
|
| 134 | * static int mydriver_ioctl_setrate(struct net_device *dev,
|
| 135 | * long rate, int auto)
|
| 136 | * 1) The kernel code doesn't "validate" the content of iwreq_data, and
|
| 137 | * can't do it (different hardware may have different notion of what a
|
| 138 | * valid frequency is), so we don't pretend that we do it.
|
| 139 | * 2) The above form is not extendable. If I want to add a flag (for
|
| 140 | * example to distinguish setting max rate and basic rate), I would
|
| 141 | * break the prototype. Using iwreq_data is more flexible.
|
| 142 | * 3) Also, the above form is not generic (see above).
|
| 143 | * 4) I don't expect driver developer using the wrong field of the
|
| 144 | * union (Doh !), so static typechecking doesn't add much value.
|
| 145 | * 5) Lastly, you can skip the union by doing :
|
| 146 | * static int mydriver_ioctl_setrate(struct net_device *dev,
|
| 147 | * struct iw_request_info *info,
|
| 148 | * struct iw_param *rrq,
|
| 149 | * char *extra)
|
| 150 | * And then adding the handler in the array like this :
|
| 151 | * (iw_handler) mydriver_ioctl_setrate, // SIOCSIWRATE
|
| 152 | *
|
| 153 | * Using functions and not a registry
|
| 154 | * ----------------------------------
|
| 155 | * Another implementation option would have been for every instance to
|
| 156 | * define a registry (a struct containing all the Wireless Extensions)
|
| 157 | * and only have a function to commit the registry to the hardware.
|
| 158 | * 1) This approach can be emulated by the current code, but not
|
| 159 | * vice versa.
|
| 160 | * 2) Some drivers don't keep any configuration in the driver, for them
|
| 161 | * adding such a registry would be a significant bloat.
|
| 162 | * 3) The code to translate from Wireless Extension to native format is
|
| 163 | * needed anyway, so it would not reduce significantely the amount of code.
|
| 164 | * 4) The current approach only selectively translate Wireless Extensions
|
| 165 | * to native format and only selectively set, whereas the registry approach
|
| 166 | * would require to translate all WE and set all parameters for any single
|
| 167 | * change.
|
| 168 | * 5) For many Wireless Extensions, the GET operation return the current
|
| 169 | * dynamic value, not the value that was set.
|
| 170 | *
|
| 171 | * This header is <net/iw_handler.h>
|
| 172 | * ---------------------------------
|
| 173 | * 1) This header is kernel space only and should not be exported to
|
| 174 | * user space. Headers in "include/linux/" are exported, headers in
|
| 175 | * "include/net/" are not.
|
| 176 | *
|
| 177 | * Mixed 32/64 bit issues
|
| 178 | * ----------------------
|
| 179 | * The Wireless Extensions are designed to be 64 bit clean, by using only
|
| 180 | * datatypes with explicit storage size.
|
| 181 | * There are some issues related to kernel and user space using different
|
| 182 | * memory model, and in particular 64bit kernel with 32bit user space.
|
| 183 | * The problem is related to struct iw_point, that contains a pointer
|
| 184 | * that *may* need to be translated.
|
| 185 | * This is quite messy. The new API doesn't solve this problem (it can't),
|
| 186 | * but is a step in the right direction :
|
| 187 | * 1) Meta data about each ioctl is easily available, so we know what type
|
| 188 | * of translation is needed.
|
| 189 | * 2) The move of data between kernel and user space is only done in a single
|
| 190 | * place in the kernel, so adding specific hooks in there is possible.
|
| 191 | * 3) In the long term, it allows to move away from using ioctl as the
|
| 192 | * user space API.
|
| 193 | *
|
| 194 | * So many comments and so few code
|
| 195 | * --------------------------------
|
| 196 | * That's a feature. Comments won't bloat the resulting kernel binary.
|
| 197 |
|
| 198 |
|
| 199 |
|
| 200 |
|
| 201 | #include <linux/wireless.h>
|
| 202 | #include <linux/if_ether.h>
|
| 203 |
|
| 204 |
|
| 205 | |
| 206 | * This constant is used to know which version of the driver API is
|
| 207 | * available. Hopefully, this will be pretty stable and no changes
|
| 208 | * will be needed...
|
| 209 | * I just plan to increment with each new version.
|
| 210 |
|
| 211 | #define IW_HANDLER_VERSION 8
|
| 212 |
|
| 213 | |
| 214 | * Changes :
|
| 215 | *
|
| 216 | * V2 to V3
|
| 217 | * --------
|
| 218 | * - Move event definition in <linux/wireless.h>
|
| 219 | * - Add Wireless Event support :
|
| 220 | * o wireless_send_event() prototype
|
| 221 | * o iwe_stream_add_event/point() inline functions
|
| 222 | * V3 to V4
|
| 223 | * --------
|
| 224 | * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
|
| 225 | *
|
| 226 | * V4 to V5
|
| 227 | * --------
|
| 228 | * - Add new spy support : struct iw_spy_data & prototypes
|
| 229 | *
|
| 230 | * V5 to V6
|
| 231 | * --------
|
| 232 | * - Change the way we get to spy_data method for added safety
|
| 233 | * - Remove spy #ifdef, they are always on -> cleaner code
|
| 234 | * - Add IW_DESCR_FLAG_NOMAX flag for very large requests
|
| 235 | * - Start migrating get_wireless_stats to struct iw_handler_def
|
| 236 | *
|
| 237 | * V6 to V7
|
| 238 | * --------
|
| 239 | * - Add struct ieee80211_device pointer in struct iw_public_data
|
| 240 | * - Remove (struct iw_point *)->pointer from events and streams
|
| 241 | * - Remove spy_offset from struct iw_handler_def
|
| 242 | * - Add "check" version of event macros for ieee802.11 stack
|
| 243 | *
|
| 244 | * V7 to V8
|
| 245 | * ----------
|
| 246 | * - Prevent leaking of kernel space in stream on 64 bits.
|
| 247 |
|
| 248 |
|
| 249 |
|
| 250 |
|
| 251 |
|
| 252 | #define IW_WIRELESS_SPY
|
| 253 | #define IW_WIRELESS_THRSPY
|
| 254 |
|
| 255 | |
| 256 | * should do a commit after return from the iw_handler
|
| 257 | #define EIWCOMMIT EINPROGRESS
|
| 258 |
|
| 259 |
|
| 260 | #define IW_REQUEST_FLAG_COMPAT 0x0001
|
| 261 |
|
| 262 |
|
| 263 | #define IW_HEADER_TYPE_NULL 0
|
| 264 | #define IW_HEADER_TYPE_CHAR 2
|
| 265 | #define IW_HEADER_TYPE_UINT 4
|
| 266 | #define IW_HEADER_TYPE_FREQ 5
|
| 267 | #define IW_HEADER_TYPE_ADDR 6
|
| 268 | #define IW_HEADER_TYPE_POINT 8
|
| 269 | #define IW_HEADER_TYPE_PARAM 9
|
| 270 | #define IW_HEADER_TYPE_QUAL 10
|
| 271 |
|
| 272 |
|
| 273 | |
| 274 | * cool features we might need one day ;-)
|
| 275 | #define IW_DESCR_FLAG_NONE 0x0000
|
| 276 |
|
| 277 | #define IW_DESCR_FLAG_DUMP 0x0001
|
| 278 | #define IW_DESCR_FLAG_EVENT 0x0002
|
| 279 | #define IW_DESCR_FLAG_RESTRICT 0x0004
|
| 280 |
|
| 281 | #define IW_DESCR_FLAG_NOMAX 0x0008
|
| 282 |
|
| 283 |
|
| 284 |
|
| 285 |
|
| 286 | |
| 287 | * A wireless handler is just a standard function, that looks like the
|
| 288 | * ioctl handler.
|
| 289 | * We also define there how a handler list look like... As the Wireless
|
| 290 | * Extension space is quite dense, we use a simple array, which is faster
|
| 291 | * (that's the perfect hash table ;-).
|
| 292 |
|
| 293 |
|
| 294 | |
| 295 | * Meta data about the request passed to the iw_handler.
|
| 296 | * Most handlers can safely ignore what's in there.
|
| 297 | * The 'cmd' field might come handy if you want to use the same handler
|
| 298 | * for multiple command...
|
| 299 | * This struct is also my long term insurance. I can add new fields here
|
| 300 | * without breaking the prototype of iw_handler...
|
| 301 |
|
| 302 | struct iw_request_info {
|
| 303 | __u16 cmd;
|
| 304 | __u16 flags;
|
| 305 | };
|
| 306 |
|
| 307 | struct net_device;
|
| 308 |
|
| 309 | |
| 310 | * This is how a function handling a Wireless Extension should look
|
| 311 | * like (both get and set, standard and private).
|
| 312 |
|
| 313 | typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
|
| 314 | union iwreq_data *wrqu, char *extra);
|
| 315 |
|
| 316 | |
| 317 | * This define all the handler that the driver export.
|
| 318 | * As you need only one per driver type, please use a static const
|
| 319 | * shared by all driver instances... Same for the members...
|
| 320 | * This will be linked from net_device in <linux/netdevice.h>
|
| 321 |
|
| 322 | struct iw_handler_def {
|
| 323 |
|
| 324 | |
| 325 | * We will call dev->wireless_handlers->standard[ioctl - SIOCIWFIRST]
|
| 326 |
|
| 327 | const iw_handler * standard;
|
| 328 | |
| 329 | * last defined handler + 1)
|
| 330 | __u16 num_standard;
|
| 331 |
|
| 332 | #ifdef CONFIG_WEXT_PRIV
|
| 333 | __u16 num_private;
|
| 334 |
|
| 335 | __u16 num_private_args;
|
| 336 | |
| 337 | * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
|
| 338 |
|
| 339 | const iw_handler * private;
|
| 340 |
|
| 341 | |
| 342 | * can put it in any order you want and should not leave holes...
|
| 343 | * We will automatically export that to user space...
|
| 344 | const struct iw_priv_args * private_args;
|
| 345 | #endif
|
| 346 |
|
| 347 | |
| 348 | * The old pointer in struct net_device will be gradually phased
|
| 349 | * out, and drivers are encouraged to use this one...
|
| 350 | struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
|
| 351 | };
|
| 352 |
|
| 353 |
|
| 354 | |
| 355 | * One of the main goal of the new interface is to deal entirely with
|
| 356 | * user space/kernel space memory move.
|
| 357 | * For that, we need to know :
|
| 358 | * o if iwreq is a pointer or contain the full data
|
| 359 | * o what is the size of the data to copy
|
| 360 | *
|
| 361 | * For private IOCTLs, we use the same rules as used by iwpriv and
|
| 362 | * defined in struct iw_priv_args.
|
| 363 | *
|
| 364 | * For standard IOCTLs, things are quite different and we need to
|
| 365 | * use the structures below. Actually, this struct is also more
|
| 366 | * efficient, but that's another story...
|
| 367 |
|
| 368 |
|
| 369 | |
| 370 | * Describe how a standard IOCTL looks like.
|
| 371 |
|
| 372 | struct iw_ioctl_description {
|
| 373 | __u8 header_type;
|
| 374 | __u8 flags;
|
| 375 | __u16 token_size;
|
| 376 | __u16 min_tokens;
|
| 377 | __u16 max_tokens;
|
| 378 | };
|
| 379 |
|
| 380 |
|
| 381 |
|
| 382 |
|
| 383 | |
| 384 | * In the old days, the driver was handling spy support all by itself.
|
| 385 | * Now, the driver can delegate this task to Wireless Extensions.
|
| 386 | * It needs to include this struct in its private part and use the
|
| 387 | * standard spy iw_handler.
|
| 388 |
|
| 389 |
|
| 390 | |
| 391 | * Instance specific spy data, i.e. addresses spied and quality for them.
|
| 392 |
|
| 393 | struct iw_spy_data {
|
| 394 |
|
| 395 | int spy_number;
|
| 396 | u_char spy_address[IW_MAX_SPY][ETH_ALEN];
|
| 397 | struct iw_quality spy_stat[IW_MAX_SPY];
|
| 398 |
|
| 399 | struct iw_quality spy_thr_low;
|
| 400 | struct iw_quality spy_thr_high;
|
| 401 | u_char spy_thr_under[IW_MAX_SPY];
|
| 402 | };
|
| 403 |
|
| 404 |
|
| 405 | |
| 406 | * Functions part of the Wireless Extensions (defined in net/wireless/wext-core.c).
|
| 407 | * Those may be called by driver modules.
|
| 408 |
|
| 409 |
|
| 410 |
|
| 411 | void wireless_send_event(struct net_device *dev, unsigned int cmd,
|
| 412 | union iwreq_data *wrqu, const char *extra);
|
| 413 | #ifdef CONFIG_WEXT_CORE
|
| 414 |
|
| 415 | void wireless_nlevent_flush(void);
|
| 416 | #else
|
| 417 | static inline void wireless_nlevent_flush(void) {}
|
| 418 | #endif
|
| 419 |
|
| 420 | |
| 421 | * More on that later...
|
| 422 |
|
| 423 |
|
| 424 | |
| 425 | * Function that are so simple that it's more efficient inlining them
|
| 426 |
|
| 427 |
|
| 428 | static inline int iwe_stream_lcp_len(struct iw_request_info *info)
|
| 429 | {
|
| 430 | #ifdef CONFIG_COMPAT
|
| 431 | if (info->flags & IW_REQUEST_FLAG_COMPAT)
|
| 432 | return IW_EV_COMPAT_LCP_LEN;
|
| 433 | #endif
|
| 434 | return IW_EV_LCP_LEN;
|
| 435 | }
|
| 436 |
|
| 437 | static inline int iwe_stream_point_len(struct iw_request_info *info)
|
| 438 | {
|
| 439 | #ifdef CONFIG_COMPAT
|
| 440 | if (info->flags & IW_REQUEST_FLAG_COMPAT)
|
| 441 | return IW_EV_COMPAT_POINT_LEN;
|
| 442 | #endif
|
| 443 | return IW_EV_POINT_LEN;
|
| 444 | }
|
| 445 |
|
| 446 | static inline int iwe_stream_event_len_adjust(struct iw_request_info *info,
|
| 447 | int event_len)
|
| 448 | {
|
| 449 | #ifdef CONFIG_COMPAT
|
| 450 | if (info->flags & IW_REQUEST_FLAG_COMPAT) {
|
| 451 | event_len -= IW_EV_LCP_LEN;
|
| 452 | event_len += IW_EV_COMPAT_LCP_LEN;
|
| 453 | }
|
| 454 | #endif
|
| 455 |
|
| 456 | return event_len;
|
| 457 | }
|
| 458 |
|
| 459 |
|
| 460 | |
| 461 | * Wrapper to add an Wireless Event to a stream of events.
|
| 462 |
|
| 463 | char *iwe_stream_add_event(struct iw_request_info *info, char *stream,
|
| 464 | char *ends, struct iw_event *iwe, int event_len);
|
| 465 |
|
| 466 | static inline char *
|
| 467 | iwe_stream_add_event_check(struct iw_request_info *info, char *stream,
|
| 468 | char *ends, struct iw_event *iwe, int event_len)
|
| 469 | {
|
| 470 | char *res = iwe_stream_add_event(info, stream, ends, iwe, event_len);
|
| 471 |
|
| 472 | if (res == stream)
|
| 473 | return ERR_PTR(-E2BIG);
|
| 474 | return res;
|
| 475 | }
|
| 476 |
|
| 477 |
|
| 478 | |
| 479 | * Wrapper to add an short Wireless Event containing a pointer to a
|
| 480 | * stream of events.
|
| 481 |
|
| 482 | char *iwe_stream_add_point(struct iw_request_info *info, char *stream,
|
| 483 | char *ends, struct iw_event *iwe, char *extra);
|
| 484 |
|
| 485 | static inline char *
|
| 486 | iwe_stream_add_point_check(struct iw_request_info *info, char *stream,
|
| 487 | char *ends, struct iw_event *iwe, char *extra)
|
| 488 | {
|
| 489 | char *res = iwe_stream_add_point(info, stream, ends, iwe, extra);
|
| 490 |
|
| 491 | if (res == stream)
|
| 492 | return ERR_PTR(-E2BIG);
|
| 493 | return res;
|
| 494 | }
|
| 495 |
|
| 496 |
|
| 497 | |
| 498 | * Wrapper to add a value to a Wireless Event in a stream of events.
|
| 499 | * Be careful, this one is tricky to use properly :
|
| 500 | * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
|
| 501 |
|
| 502 | char *iwe_stream_add_value(struct iw_request_info *info, char *event,
|
| 503 | char *value, char *ends, struct iw_event *iwe,
|
| 504 | int event_len);
|
| 505 |
|
| 506 | #endif
|