Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.32-rc1 1772 lines 51 kB view raw
1/* 2 * This file implement the Wireless Extensions APIs. 3 * 4 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> 5 * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. 6 * 7 * (As all part of the Linux kernel, this file is GPL) 8 */ 9 10/************************** DOCUMENTATION **************************/ 11/* 12 * API definition : 13 * -------------- 14 * See <linux/wireless.h> for details of the APIs and the rest. 15 * 16 * History : 17 * ------- 18 * 19 * v1 - 5.12.01 - Jean II 20 * o Created this file. 21 * 22 * v2 - 13.12.01 - Jean II 23 * o Move /proc/net/wireless stuff from net/core/dev.c to here 24 * o Make Wireless Extension IOCTLs go through here 25 * o Added iw_handler handling ;-) 26 * o Added standard ioctl description 27 * o Initial dumb commit strategy based on orinoco.c 28 * 29 * v3 - 19.12.01 - Jean II 30 * o Make sure we don't go out of standard_ioctl[] in ioctl_standard_call 31 * o Add event dispatcher function 32 * o Add event description 33 * o Propagate events as rtnetlink IFLA_WIRELESS option 34 * o Generate event on selected SET requests 35 * 36 * v4 - 18.04.02 - Jean II 37 * o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1 38 * 39 * v5 - 21.06.02 - Jean II 40 * o Add IW_PRIV_TYPE_ADDR in priv_type_size (+cleanup) 41 * o Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes 42 * o Add IWEVCUSTOM for driver specific event/scanning token 43 * o Turn on WE_STRICT_WRITE by default + kernel warning 44 * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num) 45 * o Fix off-by-one in test (extra_size <= IFNAMSIZ) 46 * 47 * v6 - 9.01.03 - Jean II 48 * o Add common spy support : iw_handler_set_spy(), wireless_spy_update() 49 * o Add enhanced spy support : iw_handler_set_thrspy() and event. 50 * o Add WIRELESS_EXT version display in /proc/net/wireless 51 * 52 * v6 - 18.06.04 - Jean II 53 * o Change get_spydata() method for added safety 54 * o Remove spy #ifdef, they are always on -> cleaner code 55 * o Allow any size GET request if user specifies length > max 56 * and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV 57 * o Start migrating get_wireless_stats to struct iw_handler_def 58 * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus 59 * Based on patch from Pavel Roskin <proski@gnu.org> : 60 * o Fix kernel data leak to user space in private handler handling 61 * 62 * v7 - 18.3.05 - Jean II 63 * o Remove (struct iw_point *)->pointer from events and streams 64 * o Remove spy_offset from struct iw_handler_def 65 * o Start deprecating dev->get_wireless_stats, output a warning 66 * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless 67 * o Don't lose INVALID/DBM flags when clearing UPDATED flags (iwstats) 68 * 69 * v8 - 17.02.06 - Jean II 70 * o RtNetlink requests support (SET/GET) 71 * 72 * v8b - 03.08.06 - Herbert Xu 73 * o Fix Wireless Event locking issues. 74 * 75 * v9 - 14.3.06 - Jean II 76 * o Change length in ESSID and NICK to strlen() instead of strlen()+1 77 * o Make standard_ioctl_num and standard_event_num unsigned 78 * o Remove (struct net_device *)->get_wireless_stats() 79 * 80 * v10 - 16.3.07 - Jean II 81 * o Prevent leaking of kernel space in stream on 64 bits. 82 */ 83 84/***************************** INCLUDES *****************************/ 85 86#include <linux/module.h> 87#include <linux/types.h> /* off_t */ 88#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ 89#include <linux/proc_fs.h> 90#include <linux/rtnetlink.h> /* rtnetlink stuff */ 91#include <linux/seq_file.h> 92#include <linux/init.h> /* for __init */ 93#include <linux/if_arp.h> /* ARPHRD_ETHER */ 94#include <linux/etherdevice.h> /* compare_ether_addr */ 95#include <linux/interrupt.h> 96#include <net/net_namespace.h> 97 98#include <linux/wireless.h> /* Pretty obvious */ 99#include <net/iw_handler.h> /* New driver API */ 100#include <net/netlink.h> 101#include <net/wext.h> 102 103#include <asm/uaccess.h> /* copy_to_user() */ 104 105/************************* GLOBAL VARIABLES *************************/ 106/* 107 * You should not use global variables, because of re-entrancy. 108 * On our case, it's only const, so it's OK... 109 */ 110/* 111 * Meta-data about all the standard Wireless Extension request we 112 * know about. 113 */ 114static const struct iw_ioctl_description standard_ioctl[] = { 115 [SIOCSIWCOMMIT - SIOCIWFIRST] = { 116 .header_type = IW_HEADER_TYPE_NULL, 117 }, 118 [SIOCGIWNAME - SIOCIWFIRST] = { 119 .header_type = IW_HEADER_TYPE_CHAR, 120 .flags = IW_DESCR_FLAG_DUMP, 121 }, 122 [SIOCSIWNWID - SIOCIWFIRST] = { 123 .header_type = IW_HEADER_TYPE_PARAM, 124 .flags = IW_DESCR_FLAG_EVENT, 125 }, 126 [SIOCGIWNWID - SIOCIWFIRST] = { 127 .header_type = IW_HEADER_TYPE_PARAM, 128 .flags = IW_DESCR_FLAG_DUMP, 129 }, 130 [SIOCSIWFREQ - SIOCIWFIRST] = { 131 .header_type = IW_HEADER_TYPE_FREQ, 132 .flags = IW_DESCR_FLAG_EVENT, 133 }, 134 [SIOCGIWFREQ - SIOCIWFIRST] = { 135 .header_type = IW_HEADER_TYPE_FREQ, 136 .flags = IW_DESCR_FLAG_DUMP, 137 }, 138 [SIOCSIWMODE - SIOCIWFIRST] = { 139 .header_type = IW_HEADER_TYPE_UINT, 140 .flags = IW_DESCR_FLAG_EVENT, 141 }, 142 [SIOCGIWMODE - SIOCIWFIRST] = { 143 .header_type = IW_HEADER_TYPE_UINT, 144 .flags = IW_DESCR_FLAG_DUMP, 145 }, 146 [SIOCSIWSENS - SIOCIWFIRST] = { 147 .header_type = IW_HEADER_TYPE_PARAM, 148 }, 149 [SIOCGIWSENS - SIOCIWFIRST] = { 150 .header_type = IW_HEADER_TYPE_PARAM, 151 }, 152 [SIOCSIWRANGE - SIOCIWFIRST] = { 153 .header_type = IW_HEADER_TYPE_NULL, 154 }, 155 [SIOCGIWRANGE - SIOCIWFIRST] = { 156 .header_type = IW_HEADER_TYPE_POINT, 157 .token_size = 1, 158 .max_tokens = sizeof(struct iw_range), 159 .flags = IW_DESCR_FLAG_DUMP, 160 }, 161 [SIOCSIWPRIV - SIOCIWFIRST] = { 162 .header_type = IW_HEADER_TYPE_NULL, 163 }, 164 [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ 165 .header_type = IW_HEADER_TYPE_POINT, 166 .token_size = sizeof(struct iw_priv_args), 167 .max_tokens = 16, 168 .flags = IW_DESCR_FLAG_NOMAX, 169 }, 170 [SIOCSIWSTATS - SIOCIWFIRST] = { 171 .header_type = IW_HEADER_TYPE_NULL, 172 }, 173 [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ 174 .header_type = IW_HEADER_TYPE_POINT, 175 .token_size = 1, 176 .max_tokens = sizeof(struct iw_statistics), 177 .flags = IW_DESCR_FLAG_DUMP, 178 }, 179 [SIOCSIWSPY - SIOCIWFIRST] = { 180 .header_type = IW_HEADER_TYPE_POINT, 181 .token_size = sizeof(struct sockaddr), 182 .max_tokens = IW_MAX_SPY, 183 }, 184 [SIOCGIWSPY - SIOCIWFIRST] = { 185 .header_type = IW_HEADER_TYPE_POINT, 186 .token_size = sizeof(struct sockaddr) + 187 sizeof(struct iw_quality), 188 .max_tokens = IW_MAX_SPY, 189 }, 190 [SIOCSIWTHRSPY - SIOCIWFIRST] = { 191 .header_type = IW_HEADER_TYPE_POINT, 192 .token_size = sizeof(struct iw_thrspy), 193 .min_tokens = 1, 194 .max_tokens = 1, 195 }, 196 [SIOCGIWTHRSPY - SIOCIWFIRST] = { 197 .header_type = IW_HEADER_TYPE_POINT, 198 .token_size = sizeof(struct iw_thrspy), 199 .min_tokens = 1, 200 .max_tokens = 1, 201 }, 202 [SIOCSIWAP - SIOCIWFIRST] = { 203 .header_type = IW_HEADER_TYPE_ADDR, 204 }, 205 [SIOCGIWAP - SIOCIWFIRST] = { 206 .header_type = IW_HEADER_TYPE_ADDR, 207 .flags = IW_DESCR_FLAG_DUMP, 208 }, 209 [SIOCSIWMLME - SIOCIWFIRST] = { 210 .header_type = IW_HEADER_TYPE_POINT, 211 .token_size = 1, 212 .min_tokens = sizeof(struct iw_mlme), 213 .max_tokens = sizeof(struct iw_mlme), 214 }, 215 [SIOCGIWAPLIST - SIOCIWFIRST] = { 216 .header_type = IW_HEADER_TYPE_POINT, 217 .token_size = sizeof(struct sockaddr) + 218 sizeof(struct iw_quality), 219 .max_tokens = IW_MAX_AP, 220 .flags = IW_DESCR_FLAG_NOMAX, 221 }, 222 [SIOCSIWSCAN - SIOCIWFIRST] = { 223 .header_type = IW_HEADER_TYPE_POINT, 224 .token_size = 1, 225 .min_tokens = 0, 226 .max_tokens = sizeof(struct iw_scan_req), 227 }, 228 [SIOCGIWSCAN - SIOCIWFIRST] = { 229 .header_type = IW_HEADER_TYPE_POINT, 230 .token_size = 1, 231 .max_tokens = IW_SCAN_MAX_DATA, 232 .flags = IW_DESCR_FLAG_NOMAX, 233 }, 234 [SIOCSIWESSID - SIOCIWFIRST] = { 235 .header_type = IW_HEADER_TYPE_POINT, 236 .token_size = 1, 237 .max_tokens = IW_ESSID_MAX_SIZE, 238 .flags = IW_DESCR_FLAG_EVENT, 239 }, 240 [SIOCGIWESSID - SIOCIWFIRST] = { 241 .header_type = IW_HEADER_TYPE_POINT, 242 .token_size = 1, 243 .max_tokens = IW_ESSID_MAX_SIZE, 244 .flags = IW_DESCR_FLAG_DUMP, 245 }, 246 [SIOCSIWNICKN - SIOCIWFIRST] = { 247 .header_type = IW_HEADER_TYPE_POINT, 248 .token_size = 1, 249 .max_tokens = IW_ESSID_MAX_SIZE, 250 }, 251 [SIOCGIWNICKN - SIOCIWFIRST] = { 252 .header_type = IW_HEADER_TYPE_POINT, 253 .token_size = 1, 254 .max_tokens = IW_ESSID_MAX_SIZE, 255 }, 256 [SIOCSIWRATE - SIOCIWFIRST] = { 257 .header_type = IW_HEADER_TYPE_PARAM, 258 }, 259 [SIOCGIWRATE - SIOCIWFIRST] = { 260 .header_type = IW_HEADER_TYPE_PARAM, 261 }, 262 [SIOCSIWRTS - SIOCIWFIRST] = { 263 .header_type = IW_HEADER_TYPE_PARAM, 264 }, 265 [SIOCGIWRTS - SIOCIWFIRST] = { 266 .header_type = IW_HEADER_TYPE_PARAM, 267 }, 268 [SIOCSIWFRAG - SIOCIWFIRST] = { 269 .header_type = IW_HEADER_TYPE_PARAM, 270 }, 271 [SIOCGIWFRAG - SIOCIWFIRST] = { 272 .header_type = IW_HEADER_TYPE_PARAM, 273 }, 274 [SIOCSIWTXPOW - SIOCIWFIRST] = { 275 .header_type = IW_HEADER_TYPE_PARAM, 276 }, 277 [SIOCGIWTXPOW - SIOCIWFIRST] = { 278 .header_type = IW_HEADER_TYPE_PARAM, 279 }, 280 [SIOCSIWRETRY - SIOCIWFIRST] = { 281 .header_type = IW_HEADER_TYPE_PARAM, 282 }, 283 [SIOCGIWRETRY - SIOCIWFIRST] = { 284 .header_type = IW_HEADER_TYPE_PARAM, 285 }, 286 [SIOCSIWENCODE - SIOCIWFIRST] = { 287 .header_type = IW_HEADER_TYPE_POINT, 288 .token_size = 1, 289 .max_tokens = IW_ENCODING_TOKEN_MAX, 290 .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, 291 }, 292 [SIOCGIWENCODE - SIOCIWFIRST] = { 293 .header_type = IW_HEADER_TYPE_POINT, 294 .token_size = 1, 295 .max_tokens = IW_ENCODING_TOKEN_MAX, 296 .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, 297 }, 298 [SIOCSIWPOWER - SIOCIWFIRST] = { 299 .header_type = IW_HEADER_TYPE_PARAM, 300 }, 301 [SIOCGIWPOWER - SIOCIWFIRST] = { 302 .header_type = IW_HEADER_TYPE_PARAM, 303 }, 304 [SIOCSIWGENIE - SIOCIWFIRST] = { 305 .header_type = IW_HEADER_TYPE_POINT, 306 .token_size = 1, 307 .max_tokens = IW_GENERIC_IE_MAX, 308 }, 309 [SIOCGIWGENIE - SIOCIWFIRST] = { 310 .header_type = IW_HEADER_TYPE_POINT, 311 .token_size = 1, 312 .max_tokens = IW_GENERIC_IE_MAX, 313 }, 314 [SIOCSIWAUTH - SIOCIWFIRST] = { 315 .header_type = IW_HEADER_TYPE_PARAM, 316 }, 317 [SIOCGIWAUTH - SIOCIWFIRST] = { 318 .header_type = IW_HEADER_TYPE_PARAM, 319 }, 320 [SIOCSIWENCODEEXT - SIOCIWFIRST] = { 321 .header_type = IW_HEADER_TYPE_POINT, 322 .token_size = 1, 323 .min_tokens = sizeof(struct iw_encode_ext), 324 .max_tokens = sizeof(struct iw_encode_ext) + 325 IW_ENCODING_TOKEN_MAX, 326 }, 327 [SIOCGIWENCODEEXT - SIOCIWFIRST] = { 328 .header_type = IW_HEADER_TYPE_POINT, 329 .token_size = 1, 330 .min_tokens = sizeof(struct iw_encode_ext), 331 .max_tokens = sizeof(struct iw_encode_ext) + 332 IW_ENCODING_TOKEN_MAX, 333 }, 334 [SIOCSIWPMKSA - SIOCIWFIRST] = { 335 .header_type = IW_HEADER_TYPE_POINT, 336 .token_size = 1, 337 .min_tokens = sizeof(struct iw_pmksa), 338 .max_tokens = sizeof(struct iw_pmksa), 339 }, 340}; 341static const unsigned standard_ioctl_num = ARRAY_SIZE(standard_ioctl); 342 343/* 344 * Meta-data about all the additional standard Wireless Extension events 345 * we know about. 346 */ 347static const struct iw_ioctl_description standard_event[] = { 348 [IWEVTXDROP - IWEVFIRST] = { 349 .header_type = IW_HEADER_TYPE_ADDR, 350 }, 351 [IWEVQUAL - IWEVFIRST] = { 352 .header_type = IW_HEADER_TYPE_QUAL, 353 }, 354 [IWEVCUSTOM - IWEVFIRST] = { 355 .header_type = IW_HEADER_TYPE_POINT, 356 .token_size = 1, 357 .max_tokens = IW_CUSTOM_MAX, 358 }, 359 [IWEVREGISTERED - IWEVFIRST] = { 360 .header_type = IW_HEADER_TYPE_ADDR, 361 }, 362 [IWEVEXPIRED - IWEVFIRST] = { 363 .header_type = IW_HEADER_TYPE_ADDR, 364 }, 365 [IWEVGENIE - IWEVFIRST] = { 366 .header_type = IW_HEADER_TYPE_POINT, 367 .token_size = 1, 368 .max_tokens = IW_GENERIC_IE_MAX, 369 }, 370 [IWEVMICHAELMICFAILURE - IWEVFIRST] = { 371 .header_type = IW_HEADER_TYPE_POINT, 372 .token_size = 1, 373 .max_tokens = sizeof(struct iw_michaelmicfailure), 374 }, 375 [IWEVASSOCREQIE - IWEVFIRST] = { 376 .header_type = IW_HEADER_TYPE_POINT, 377 .token_size = 1, 378 .max_tokens = IW_GENERIC_IE_MAX, 379 }, 380 [IWEVASSOCRESPIE - IWEVFIRST] = { 381 .header_type = IW_HEADER_TYPE_POINT, 382 .token_size = 1, 383 .max_tokens = IW_GENERIC_IE_MAX, 384 }, 385 [IWEVPMKIDCAND - IWEVFIRST] = { 386 .header_type = IW_HEADER_TYPE_POINT, 387 .token_size = 1, 388 .max_tokens = sizeof(struct iw_pmkid_cand), 389 }, 390}; 391static const unsigned standard_event_num = ARRAY_SIZE(standard_event); 392 393/* Size (in bytes) of the various private data types */ 394static const char iw_priv_type_size[] = { 395 0, /* IW_PRIV_TYPE_NONE */ 396 1, /* IW_PRIV_TYPE_BYTE */ 397 1, /* IW_PRIV_TYPE_CHAR */ 398 0, /* Not defined */ 399 sizeof(__u32), /* IW_PRIV_TYPE_INT */ 400 sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ 401 sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ 402 0, /* Not defined */ 403}; 404 405/* Size (in bytes) of various events */ 406static const int event_type_size[] = { 407 IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */ 408 0, 409 IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */ 410 0, 411 IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */ 412 IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */ 413 IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */ 414 0, 415 IW_EV_POINT_LEN, /* Without variable payload */ 416 IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */ 417 IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ 418}; 419 420#ifdef CONFIG_COMPAT 421static const int compat_event_type_size[] = { 422 IW_EV_COMPAT_LCP_LEN, /* IW_HEADER_TYPE_NULL */ 423 0, 424 IW_EV_COMPAT_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */ 425 0, 426 IW_EV_COMPAT_UINT_LEN, /* IW_HEADER_TYPE_UINT */ 427 IW_EV_COMPAT_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */ 428 IW_EV_COMPAT_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */ 429 0, 430 IW_EV_COMPAT_POINT_LEN, /* Without variable payload */ 431 IW_EV_COMPAT_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */ 432 IW_EV_COMPAT_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ 433}; 434#endif 435 436/************************ COMMON SUBROUTINES ************************/ 437/* 438 * Stuff that may be used in various place or doesn't fit in one 439 * of the section below. 440 */ 441 442/* ---------------------------------------------------------------- */ 443/* 444 * Return the driver handler associated with a specific Wireless Extension. 445 */ 446static iw_handler get_handler(struct net_device *dev, unsigned int cmd) 447{ 448 /* Don't "optimise" the following variable, it will crash */ 449 unsigned int index; /* *MUST* be unsigned */ 450 451 /* Check if we have some wireless handlers defined */ 452 if (dev->wireless_handlers == NULL) 453 return NULL; 454 455 /* Try as a standard command */ 456 index = cmd - SIOCIWFIRST; 457 if (index < dev->wireless_handlers->num_standard) 458 return dev->wireless_handlers->standard[index]; 459 460 /* Try as a private command */ 461 index = cmd - SIOCIWFIRSTPRIV; 462 if (index < dev->wireless_handlers->num_private) 463 return dev->wireless_handlers->private[index]; 464 465 /* Not found */ 466 return NULL; 467} 468 469/* ---------------------------------------------------------------- */ 470/* 471 * Get statistics out of the driver 472 */ 473static struct iw_statistics *get_wireless_stats(struct net_device *dev) 474{ 475 /* New location */ 476 if ((dev->wireless_handlers != NULL) && 477 (dev->wireless_handlers->get_wireless_stats != NULL)) 478 return dev->wireless_handlers->get_wireless_stats(dev); 479 480 /* Not found */ 481 return NULL; 482} 483 484/* ---------------------------------------------------------------- */ 485/* 486 * Call the commit handler in the driver 487 * (if exist and if conditions are right) 488 * 489 * Note : our current commit strategy is currently pretty dumb, 490 * but we will be able to improve on that... 491 * The goal is to try to agreagate as many changes as possible 492 * before doing the commit. Drivers that will define a commit handler 493 * are usually those that need a reset after changing parameters, so 494 * we want to minimise the number of reset. 495 * A cool idea is to use a timer : at each "set" command, we re-set the 496 * timer, when the timer eventually fires, we call the driver. 497 * Hopefully, more on that later. 498 * 499 * Also, I'm waiting to see how many people will complain about the 500 * netif_running(dev) test. I'm open on that one... 501 * Hopefully, the driver will remember to do a commit in "open()" ;-) 502 */ 503static int call_commit_handler(struct net_device *dev) 504{ 505 if ((netif_running(dev)) && 506 (dev->wireless_handlers->standard[0] != NULL)) 507 /* Call the commit handler on the driver */ 508 return dev->wireless_handlers->standard[0](dev, NULL, 509 NULL, NULL); 510 else 511 return 0; /* Command completed successfully */ 512} 513 514/* ---------------------------------------------------------------- */ 515/* 516 * Calculate size of private arguments 517 */ 518static int get_priv_size(__u16 args) 519{ 520 int num = args & IW_PRIV_SIZE_MASK; 521 int type = (args & IW_PRIV_TYPE_MASK) >> 12; 522 523 return num * iw_priv_type_size[type]; 524} 525 526/* ---------------------------------------------------------------- */ 527/* 528 * Re-calculate the size of private arguments 529 */ 530static int adjust_priv_size(__u16 args, struct iw_point *iwp) 531{ 532 int num = iwp->length; 533 int max = args & IW_PRIV_SIZE_MASK; 534 int type = (args & IW_PRIV_TYPE_MASK) >> 12; 535 536 /* Make sure the driver doesn't goof up */ 537 if (max < num) 538 num = max; 539 540 return num * iw_priv_type_size[type]; 541} 542 543/* ---------------------------------------------------------------- */ 544/* 545 * Standard Wireless Handler : get wireless stats 546 * Allow programatic access to /proc/net/wireless even if /proc 547 * doesn't exist... Also more efficient... 548 */ 549static int iw_handler_get_iwstats(struct net_device * dev, 550 struct iw_request_info * info, 551 union iwreq_data * wrqu, 552 char * extra) 553{ 554 /* Get stats from the driver */ 555 struct iw_statistics *stats; 556 557 stats = get_wireless_stats(dev); 558 if (stats) { 559 /* Copy statistics to extra */ 560 memcpy(extra, stats, sizeof(struct iw_statistics)); 561 wrqu->data.length = sizeof(struct iw_statistics); 562 563 /* Check if we need to clear the updated flag */ 564 if (wrqu->data.flags != 0) 565 stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; 566 return 0; 567 } else 568 return -EOPNOTSUPP; 569} 570 571/* ---------------------------------------------------------------- */ 572/* 573 * Standard Wireless Handler : get iwpriv definitions 574 * Export the driver private handler definition 575 * They will be picked up by tools like iwpriv... 576 */ 577static int iw_handler_get_private(struct net_device * dev, 578 struct iw_request_info * info, 579 union iwreq_data * wrqu, 580 char * extra) 581{ 582 /* Check if the driver has something to export */ 583 if ((dev->wireless_handlers->num_private_args == 0) || 584 (dev->wireless_handlers->private_args == NULL)) 585 return -EOPNOTSUPP; 586 587 /* Check if there is enough buffer up there */ 588 if (wrqu->data.length < dev->wireless_handlers->num_private_args) { 589 /* User space can't know in advance how large the buffer 590 * needs to be. Give it a hint, so that we can support 591 * any size buffer we want somewhat efficiently... */ 592 wrqu->data.length = dev->wireless_handlers->num_private_args; 593 return -E2BIG; 594 } 595 596 /* Set the number of available ioctls. */ 597 wrqu->data.length = dev->wireless_handlers->num_private_args; 598 599 /* Copy structure to the user buffer. */ 600 memcpy(extra, dev->wireless_handlers->private_args, 601 sizeof(struct iw_priv_args) * wrqu->data.length); 602 603 return 0; 604} 605 606 607/******************** /proc/net/wireless SUPPORT ********************/ 608/* 609 * The /proc/net/wireless file is a human readable user-space interface 610 * exporting various wireless specific statistics from the wireless devices. 611 * This is the most popular part of the Wireless Extensions ;-) 612 * 613 * This interface is a pure clone of /proc/net/dev (in net/core/dev.c). 614 * The content of the file is basically the content of "struct iw_statistics". 615 */ 616 617#ifdef CONFIG_PROC_FS 618 619/* ---------------------------------------------------------------- */ 620/* 621 * Print one entry (line) of /proc/net/wireless 622 */ 623static void wireless_seq_printf_stats(struct seq_file *seq, 624 struct net_device *dev) 625{ 626 /* Get stats from the driver */ 627 struct iw_statistics *stats = get_wireless_stats(dev); 628 static struct iw_statistics nullstats = {}; 629 630 /* show device if it's wireless regardless of current stats */ 631 if (!stats && dev->wireless_handlers) 632 stats = &nullstats; 633 634 if (stats) { 635 seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d " 636 "%6d %6d %6d\n", 637 dev->name, stats->status, stats->qual.qual, 638 stats->qual.updated & IW_QUAL_QUAL_UPDATED 639 ? '.' : ' ', 640 ((__s32) stats->qual.level) - 641 ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0), 642 stats->qual.updated & IW_QUAL_LEVEL_UPDATED 643 ? '.' : ' ', 644 ((__s32) stats->qual.noise) - 645 ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0), 646 stats->qual.updated & IW_QUAL_NOISE_UPDATED 647 ? '.' : ' ', 648 stats->discard.nwid, stats->discard.code, 649 stats->discard.fragment, stats->discard.retries, 650 stats->discard.misc, stats->miss.beacon); 651 652 if (stats != &nullstats) 653 stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; 654 } 655} 656 657/* ---------------------------------------------------------------- */ 658/* 659 * Print info for /proc/net/wireless (print all entries) 660 */ 661static int wireless_dev_seq_show(struct seq_file *seq, void *v) 662{ 663 might_sleep(); 664 665 if (v == SEQ_START_TOKEN) 666 seq_printf(seq, "Inter-| sta-| Quality | Discarded " 667 "packets | Missed | WE\n" 668 " face | tus | link level noise | nwid " 669 "crypt frag retry misc | beacon | %d\n", 670 WIRELESS_EXT); 671 else 672 wireless_seq_printf_stats(seq, v); 673 return 0; 674} 675 676static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) 677{ 678 struct net *net = seq_file_net(seq); 679 loff_t off; 680 struct net_device *dev; 681 682 rtnl_lock(); 683 if (!*pos) 684 return SEQ_START_TOKEN; 685 686 off = 1; 687 for_each_netdev(net, dev) 688 if (off++ == *pos) 689 return dev; 690 return NULL; 691} 692 693static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 694{ 695 struct net *net = seq_file_net(seq); 696 697 ++*pos; 698 699 return v == SEQ_START_TOKEN ? 700 first_net_device(net) : next_net_device(v); 701} 702 703static void wireless_dev_seq_stop(struct seq_file *seq, void *v) 704{ 705 rtnl_unlock(); 706} 707 708static const struct seq_operations wireless_seq_ops = { 709 .start = wireless_dev_seq_start, 710 .next = wireless_dev_seq_next, 711 .stop = wireless_dev_seq_stop, 712 .show = wireless_dev_seq_show, 713}; 714 715static int seq_open_wireless(struct inode *inode, struct file *file) 716{ 717 return seq_open_net(inode, file, &wireless_seq_ops, 718 sizeof(struct seq_net_private)); 719} 720 721static const struct file_operations wireless_seq_fops = { 722 .owner = THIS_MODULE, 723 .open = seq_open_wireless, 724 .read = seq_read, 725 .llseek = seq_lseek, 726 .release = seq_release_net, 727}; 728 729int wext_proc_init(struct net *net) 730{ 731 /* Create /proc/net/wireless entry */ 732 if (!proc_net_fops_create(net, "wireless", S_IRUGO, &wireless_seq_fops)) 733 return -ENOMEM; 734 735 return 0; 736} 737 738void wext_proc_exit(struct net *net) 739{ 740 proc_net_remove(net, "wireless"); 741} 742#endif /* CONFIG_PROC_FS */ 743 744/************************** IOCTL SUPPORT **************************/ 745/* 746 * The original user space API to configure all those Wireless Extensions 747 * is through IOCTLs. 748 * In there, we check if we need to call the new driver API (iw_handler) 749 * or just call the driver ioctl handler. 750 */ 751 752/* ---------------------------------------------------------------- */ 753static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, 754 const struct iw_ioctl_description *descr, 755 iw_handler handler, struct net_device *dev, 756 struct iw_request_info *info) 757{ 758 int err, extra_size, user_length = 0, essid_compat = 0; 759 char *extra; 760 761 /* Calculate space needed by arguments. Always allocate 762 * for max space. 763 */ 764 extra_size = descr->max_tokens * descr->token_size; 765 766 /* Check need for ESSID compatibility for WE < 21 */ 767 switch (cmd) { 768 case SIOCSIWESSID: 769 case SIOCGIWESSID: 770 case SIOCSIWNICKN: 771 case SIOCGIWNICKN: 772 if (iwp->length == descr->max_tokens + 1) 773 essid_compat = 1; 774 else if (IW_IS_SET(cmd) && (iwp->length != 0)) { 775 char essid[IW_ESSID_MAX_SIZE + 1]; 776 777 err = copy_from_user(essid, iwp->pointer, 778 iwp->length * 779 descr->token_size); 780 if (err) 781 return -EFAULT; 782 783 if (essid[iwp->length - 1] == '\0') 784 essid_compat = 1; 785 } 786 break; 787 default: 788 break; 789 } 790 791 iwp->length -= essid_compat; 792 793 /* Check what user space is giving us */ 794 if (IW_IS_SET(cmd)) { 795 /* Check NULL pointer */ 796 if (!iwp->pointer && iwp->length != 0) 797 return -EFAULT; 798 /* Check if number of token fits within bounds */ 799 if (iwp->length > descr->max_tokens) 800 return -E2BIG; 801 if (iwp->length < descr->min_tokens) 802 return -EINVAL; 803 } else { 804 /* Check NULL pointer */ 805 if (!iwp->pointer) 806 return -EFAULT; 807 /* Save user space buffer size for checking */ 808 user_length = iwp->length; 809 810 /* Don't check if user_length > max to allow forward 811 * compatibility. The test user_length < min is 812 * implied by the test at the end. 813 */ 814 815 /* Support for very large requests */ 816 if ((descr->flags & IW_DESCR_FLAG_NOMAX) && 817 (user_length > descr->max_tokens)) { 818 /* Allow userspace to GET more than max so 819 * we can support any size GET requests. 820 * There is still a limit : -ENOMEM. 821 */ 822 extra_size = user_length * descr->token_size; 823 824 /* Note : user_length is originally a __u16, 825 * and token_size is controlled by us, 826 * so extra_size won't get negative and 827 * won't overflow... 828 */ 829 } 830 } 831 832 /* kzalloc() ensures NULL-termination for essid_compat. */ 833 extra = kzalloc(extra_size, GFP_KERNEL); 834 if (!extra) 835 return -ENOMEM; 836 837 /* If it is a SET, get all the extra data in here */ 838 if (IW_IS_SET(cmd) && (iwp->length != 0)) { 839 if (copy_from_user(extra, iwp->pointer, 840 iwp->length * 841 descr->token_size)) { 842 err = -EFAULT; 843 goto out; 844 } 845 846 if (cmd == SIOCSIWENCODEEXT) { 847 struct iw_encode_ext *ee = (void *) extra; 848 849 if (iwp->length < sizeof(*ee) + ee->key_len) 850 return -EFAULT; 851 } 852 } 853 854 err = handler(dev, info, (union iwreq_data *) iwp, extra); 855 856 iwp->length += essid_compat; 857 858 /* If we have something to return to the user */ 859 if (!err && IW_IS_GET(cmd)) { 860 /* Check if there is enough buffer up there */ 861 if (user_length < iwp->length) { 862 err = -E2BIG; 863 goto out; 864 } 865 866 if (copy_to_user(iwp->pointer, extra, 867 iwp->length * 868 descr->token_size)) { 869 err = -EFAULT; 870 goto out; 871 } 872 } 873 874 /* Generate an event to notify listeners of the change */ 875 if ((descr->flags & IW_DESCR_FLAG_EVENT) && err == -EIWCOMMIT) { 876 union iwreq_data *data = (union iwreq_data *) iwp; 877 878 if (descr->flags & IW_DESCR_FLAG_RESTRICT) 879 /* If the event is restricted, don't 880 * export the payload. 881 */ 882 wireless_send_event(dev, cmd, data, NULL); 883 else 884 wireless_send_event(dev, cmd, data, extra); 885 } 886 887out: 888 kfree(extra); 889 return err; 890} 891 892/* 893 * Wrapper to call a standard Wireless Extension handler. 894 * We do various checks and also take care of moving data between 895 * user space and kernel space. 896 */ 897static int ioctl_standard_call(struct net_device * dev, 898 struct iwreq *iwr, 899 unsigned int cmd, 900 struct iw_request_info *info, 901 iw_handler handler) 902{ 903 const struct iw_ioctl_description * descr; 904 int ret = -EINVAL; 905 906 /* Get the description of the IOCTL */ 907 if ((cmd - SIOCIWFIRST) >= standard_ioctl_num) 908 return -EOPNOTSUPP; 909 descr = &(standard_ioctl[cmd - SIOCIWFIRST]); 910 911 /* Check if we have a pointer to user space data or not */ 912 if (descr->header_type != IW_HEADER_TYPE_POINT) { 913 914 /* No extra arguments. Trivial to handle */ 915 ret = handler(dev, info, &(iwr->u), NULL); 916 917 /* Generate an event to notify listeners of the change */ 918 if ((descr->flags & IW_DESCR_FLAG_EVENT) && 919 ((ret == 0) || (ret == -EIWCOMMIT))) 920 wireless_send_event(dev, cmd, &(iwr->u), NULL); 921 } else { 922 ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr, 923 handler, dev, info); 924 } 925 926 /* Call commit handler if needed and defined */ 927 if (ret == -EIWCOMMIT) 928 ret = call_commit_handler(dev); 929 930 /* Here, we will generate the appropriate event if needed */ 931 932 return ret; 933} 934 935/* ---------------------------------------------------------------- */ 936/* 937 * Wrapper to call a private Wireless Extension handler. 938 * We do various checks and also take care of moving data between 939 * user space and kernel space. 940 * It's not as nice and slimline as the standard wrapper. The cause 941 * is struct iw_priv_args, which was not really designed for the 942 * job we are going here. 943 * 944 * IMPORTANT : This function prevent to set and get data on the same 945 * IOCTL and enforce the SET/GET convention. Not doing it would be 946 * far too hairy... 947 * If you need to set and get data at the same time, please don't use 948 * a iw_handler but process it in your ioctl handler (i.e. use the 949 * old driver API). 950 */ 951static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, 952 const struct iw_priv_args **descrp) 953{ 954 const struct iw_priv_args *descr; 955 int i, extra_size; 956 957 descr = NULL; 958 for (i = 0; i < dev->wireless_handlers->num_private_args; i++) { 959 if (cmd == dev->wireless_handlers->private_args[i].cmd) { 960 descr = &dev->wireless_handlers->private_args[i]; 961 break; 962 } 963 } 964 965 extra_size = 0; 966 if (descr) { 967 if (IW_IS_SET(cmd)) { 968 int offset = 0; /* For sub-ioctls */ 969 /* Check for sub-ioctl handler */ 970 if (descr->name[0] == '\0') 971 /* Reserve one int for sub-ioctl index */ 972 offset = sizeof(__u32); 973 974 /* Size of set arguments */ 975 extra_size = get_priv_size(descr->set_args); 976 977 /* Does it fits in iwr ? */ 978 if ((descr->set_args & IW_PRIV_SIZE_FIXED) && 979 ((extra_size + offset) <= IFNAMSIZ)) 980 extra_size = 0; 981 } else { 982 /* Size of get arguments */ 983 extra_size = get_priv_size(descr->get_args); 984 985 /* Does it fits in iwr ? */ 986 if ((descr->get_args & IW_PRIV_SIZE_FIXED) && 987 (extra_size <= IFNAMSIZ)) 988 extra_size = 0; 989 } 990 } 991 *descrp = descr; 992 return extra_size; 993} 994 995static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, 996 const struct iw_priv_args *descr, 997 iw_handler handler, struct net_device *dev, 998 struct iw_request_info *info, int extra_size) 999{ 1000 char *extra; 1001 int err; 1002 1003 /* Check what user space is giving us */ 1004 if (IW_IS_SET(cmd)) { 1005 if (!iwp->pointer && iwp->length != 0) 1006 return -EFAULT; 1007 1008 if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK)) 1009 return -E2BIG; 1010 } else if (!iwp->pointer) 1011 return -EFAULT; 1012 1013 extra = kmalloc(extra_size, GFP_KERNEL); 1014 if (!extra) 1015 return -ENOMEM; 1016 1017 /* If it is a SET, get all the extra data in here */ 1018 if (IW_IS_SET(cmd) && (iwp->length != 0)) { 1019 if (copy_from_user(extra, iwp->pointer, extra_size)) { 1020 err = -EFAULT; 1021 goto out; 1022 } 1023 } 1024 1025 /* Call the handler */ 1026 err = handler(dev, info, (union iwreq_data *) iwp, extra); 1027 1028 /* If we have something to return to the user */ 1029 if (!err && IW_IS_GET(cmd)) { 1030 /* Adjust for the actual length if it's variable, 1031 * avoid leaking kernel bits outside. 1032 */ 1033 if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) 1034 extra_size = adjust_priv_size(descr->get_args, iwp); 1035 1036 if (copy_to_user(iwp->pointer, extra, extra_size)) 1037 err = -EFAULT; 1038 } 1039 1040out: 1041 kfree(extra); 1042 return err; 1043} 1044 1045static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, 1046 unsigned int cmd, struct iw_request_info *info, 1047 iw_handler handler) 1048{ 1049 int extra_size = 0, ret = -EINVAL; 1050 const struct iw_priv_args *descr; 1051 1052 extra_size = get_priv_descr_and_size(dev, cmd, &descr); 1053 1054 /* Check if we have a pointer to user space data or not. */ 1055 if (extra_size == 0) { 1056 /* No extra arguments. Trivial to handle */ 1057 ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); 1058 } else { 1059 ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, 1060 handler, dev, info, extra_size); 1061 } 1062 1063 /* Call commit handler if needed and defined */ 1064 if (ret == -EIWCOMMIT) 1065 ret = call_commit_handler(dev); 1066 1067 return ret; 1068} 1069 1070/* ---------------------------------------------------------------- */ 1071typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, 1072 unsigned int, struct iw_request_info *, 1073 iw_handler); 1074 1075/* 1076 * Main IOCTl dispatcher. 1077 * Check the type of IOCTL and call the appropriate wrapper... 1078 */ 1079static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, 1080 unsigned int cmd, 1081 struct iw_request_info *info, 1082 wext_ioctl_func standard, 1083 wext_ioctl_func private) 1084{ 1085 struct iwreq *iwr = (struct iwreq *) ifr; 1086 struct net_device *dev; 1087 iw_handler handler; 1088 1089 /* Permissions are already checked in dev_ioctl() before calling us. 1090 * The copy_to/from_user() of ifr is also dealt with in there */ 1091 1092 /* Make sure the device exist */ 1093 if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL) 1094 return -ENODEV; 1095 1096 /* A bunch of special cases, then the generic case... 1097 * Note that 'cmd' is already filtered in dev_ioctl() with 1098 * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ 1099 if (cmd == SIOCGIWSTATS) 1100 return standard(dev, iwr, cmd, info, 1101 &iw_handler_get_iwstats); 1102 1103 if (cmd == SIOCGIWPRIV && dev->wireless_handlers) 1104 return standard(dev, iwr, cmd, info, 1105 &iw_handler_get_private); 1106 1107 /* Basic check */ 1108 if (!netif_device_present(dev)) 1109 return -ENODEV; 1110 1111 /* New driver API : try to find the handler */ 1112 handler = get_handler(dev, cmd); 1113 if (handler) { 1114 /* Standard and private are not the same */ 1115 if (cmd < SIOCIWFIRSTPRIV) 1116 return standard(dev, iwr, cmd, info, handler); 1117 else 1118 return private(dev, iwr, cmd, info, handler); 1119 } 1120 /* Old driver API : call driver ioctl handler */ 1121 if (dev->netdev_ops->ndo_do_ioctl) 1122 return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); 1123 return -EOPNOTSUPP; 1124} 1125 1126/* If command is `set a parameter', or `get the encoding parameters', 1127 * check if the user has the right to do it. 1128 */ 1129static int wext_permission_check(unsigned int cmd) 1130{ 1131 if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE || cmd == SIOCGIWENCODEEXT) 1132 && !capable(CAP_NET_ADMIN)) 1133 return -EPERM; 1134 1135 return 0; 1136} 1137 1138/* entry point from dev ioctl */ 1139static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, 1140 unsigned int cmd, struct iw_request_info *info, 1141 wext_ioctl_func standard, 1142 wext_ioctl_func private) 1143{ 1144 int ret = wext_permission_check(cmd); 1145 1146 if (ret) 1147 return ret; 1148 1149 dev_load(net, ifr->ifr_name); 1150 rtnl_lock(); 1151 ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private); 1152 rtnl_unlock(); 1153 1154 return ret; 1155} 1156 1157int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, 1158 void __user *arg) 1159{ 1160 struct iw_request_info info = { .cmd = cmd, .flags = 0 }; 1161 int ret; 1162 1163 ret = wext_ioctl_dispatch(net, ifr, cmd, &info, 1164 ioctl_standard_call, 1165 ioctl_private_call); 1166 if (ret >= 0 && 1167 IW_IS_GET(cmd) && 1168 copy_to_user(arg, ifr, sizeof(struct iwreq))) 1169 return -EFAULT; 1170 1171 return ret; 1172} 1173 1174#ifdef CONFIG_COMPAT 1175static int compat_standard_call(struct net_device *dev, 1176 struct iwreq *iwr, 1177 unsigned int cmd, 1178 struct iw_request_info *info, 1179 iw_handler handler) 1180{ 1181 const struct iw_ioctl_description *descr; 1182 struct compat_iw_point *iwp_compat; 1183 struct iw_point iwp; 1184 int err; 1185 1186 descr = standard_ioctl + (cmd - SIOCIWFIRST); 1187 1188 if (descr->header_type != IW_HEADER_TYPE_POINT) 1189 return ioctl_standard_call(dev, iwr, cmd, info, handler); 1190 1191 iwp_compat = (struct compat_iw_point *) &iwr->u.data; 1192 iwp.pointer = compat_ptr(iwp_compat->pointer); 1193 iwp.length = iwp_compat->length; 1194 iwp.flags = iwp_compat->flags; 1195 1196 err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info); 1197 1198 iwp_compat->pointer = ptr_to_compat(iwp.pointer); 1199 iwp_compat->length = iwp.length; 1200 iwp_compat->flags = iwp.flags; 1201 1202 return err; 1203} 1204 1205static int compat_private_call(struct net_device *dev, struct iwreq *iwr, 1206 unsigned int cmd, struct iw_request_info *info, 1207 iw_handler handler) 1208{ 1209 const struct iw_priv_args *descr; 1210 int ret, extra_size; 1211 1212 extra_size = get_priv_descr_and_size(dev, cmd, &descr); 1213 1214 /* Check if we have a pointer to user space data or not. */ 1215 if (extra_size == 0) { 1216 /* No extra arguments. Trivial to handle */ 1217 ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); 1218 } else { 1219 struct compat_iw_point *iwp_compat; 1220 struct iw_point iwp; 1221 1222 iwp_compat = (struct compat_iw_point *) &iwr->u.data; 1223 iwp.pointer = compat_ptr(iwp_compat->pointer); 1224 iwp.length = iwp_compat->length; 1225 iwp.flags = iwp_compat->flags; 1226 1227 ret = ioctl_private_iw_point(&iwp, cmd, descr, 1228 handler, dev, info, extra_size); 1229 1230 iwp_compat->pointer = ptr_to_compat(iwp.pointer); 1231 iwp_compat->length = iwp.length; 1232 iwp_compat->flags = iwp.flags; 1233 } 1234 1235 /* Call commit handler if needed and defined */ 1236 if (ret == -EIWCOMMIT) 1237 ret = call_commit_handler(dev); 1238 1239 return ret; 1240} 1241 1242int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, 1243 unsigned long arg) 1244{ 1245 void __user *argp = (void __user *)arg; 1246 struct iw_request_info info; 1247 struct iwreq iwr; 1248 char *colon; 1249 int ret; 1250 1251 if (copy_from_user(&iwr, argp, sizeof(struct iwreq))) 1252 return -EFAULT; 1253 1254 iwr.ifr_name[IFNAMSIZ-1] = 0; 1255 colon = strchr(iwr.ifr_name, ':'); 1256 if (colon) 1257 *colon = 0; 1258 1259 info.cmd = cmd; 1260 info.flags = IW_REQUEST_FLAG_COMPAT; 1261 1262 ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, &info, 1263 compat_standard_call, 1264 compat_private_call); 1265 1266 if (ret >= 0 && 1267 IW_IS_GET(cmd) && 1268 copy_to_user(argp, &iwr, sizeof(struct iwreq))) 1269 return -EFAULT; 1270 1271 return ret; 1272} 1273#endif 1274 1275static int __net_init wext_pernet_init(struct net *net) 1276{ 1277 skb_queue_head_init(&net->wext_nlevents); 1278 return 0; 1279} 1280 1281static void __net_exit wext_pernet_exit(struct net *net) 1282{ 1283 skb_queue_purge(&net->wext_nlevents); 1284} 1285 1286static struct pernet_operations wext_pernet_ops = { 1287 .init = wext_pernet_init, 1288 .exit = wext_pernet_exit, 1289}; 1290 1291static int __init wireless_nlevent_init(void) 1292{ 1293 return register_pernet_subsys(&wext_pernet_ops); 1294} 1295 1296subsys_initcall(wireless_nlevent_init); 1297 1298/* Process events generated by the wireless layer or the driver. */ 1299static void wireless_nlevent_process(struct work_struct *work) 1300{ 1301 struct sk_buff *skb; 1302 struct net *net; 1303 1304 rtnl_lock(); 1305 1306 for_each_net(net) { 1307 while ((skb = skb_dequeue(&net->wext_nlevents))) 1308 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, 1309 GFP_KERNEL); 1310 } 1311 1312 rtnl_unlock(); 1313} 1314 1315static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process); 1316 1317static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev, 1318 struct sk_buff *skb) 1319{ 1320 struct ifinfomsg *r; 1321 struct nlmsghdr *nlh; 1322 1323 nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0); 1324 if (!nlh) 1325 return NULL; 1326 1327 r = nlmsg_data(nlh); 1328 r->ifi_family = AF_UNSPEC; 1329 r->__ifi_pad = 0; 1330 r->ifi_type = dev->type; 1331 r->ifi_index = dev->ifindex; 1332 r->ifi_flags = dev_get_flags(dev); 1333 r->ifi_change = 0; /* Wireless changes don't affect those flags */ 1334 1335 NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); 1336 1337 return nlh; 1338 nla_put_failure: 1339 nlmsg_cancel(skb, nlh); 1340 return NULL; 1341} 1342 1343 1344/* 1345 * Main event dispatcher. Called from other parts and drivers. 1346 * Send the event on the appropriate channels. 1347 * May be called from interrupt context. 1348 */ 1349void wireless_send_event(struct net_device * dev, 1350 unsigned int cmd, 1351 union iwreq_data * wrqu, 1352 const char * extra) 1353{ 1354 const struct iw_ioctl_description * descr = NULL; 1355 int extra_len = 0; 1356 struct iw_event *event; /* Mallocated whole event */ 1357 int event_len; /* Its size */ 1358 int hdr_len; /* Size of the event header */ 1359 int wrqu_off = 0; /* Offset in wrqu */ 1360 /* Don't "optimise" the following variable, it will crash */ 1361 unsigned cmd_index; /* *MUST* be unsigned */ 1362 struct sk_buff *skb; 1363 struct nlmsghdr *nlh; 1364 struct nlattr *nla; 1365#ifdef CONFIG_COMPAT 1366 struct __compat_iw_event *compat_event; 1367 struct compat_iw_point compat_wrqu; 1368 struct sk_buff *compskb; 1369#endif 1370 1371 /* 1372 * Nothing in the kernel sends scan events with data, be safe. 1373 * This is necessary because we cannot fix up scan event data 1374 * for compat, due to being contained in 'extra', but normally 1375 * applications are required to retrieve the scan data anyway 1376 * and no data is included in the event, this codifies that 1377 * practice. 1378 */ 1379 if (WARN_ON(cmd == SIOCGIWSCAN && extra)) 1380 extra = NULL; 1381 1382 /* Get the description of the Event */ 1383 if (cmd <= SIOCIWLAST) { 1384 cmd_index = cmd - SIOCIWFIRST; 1385 if (cmd_index < standard_ioctl_num) 1386 descr = &(standard_ioctl[cmd_index]); 1387 } else { 1388 cmd_index = cmd - IWEVFIRST; 1389 if (cmd_index < standard_event_num) 1390 descr = &(standard_event[cmd_index]); 1391 } 1392 /* Don't accept unknown events */ 1393 if (descr == NULL) { 1394 /* Note : we don't return an error to the driver, because 1395 * the driver would not know what to do about it. It can't 1396 * return an error to the user, because the event is not 1397 * initiated by a user request. 1398 * The best the driver could do is to log an error message. 1399 * We will do it ourselves instead... 1400 */ 1401 printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n", 1402 dev->name, cmd); 1403 return; 1404 } 1405 1406 /* Check extra parameters and set extra_len */ 1407 if (descr->header_type == IW_HEADER_TYPE_POINT) { 1408 /* Check if number of token fits within bounds */ 1409 if (wrqu->data.length > descr->max_tokens) { 1410 printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length); 1411 return; 1412 } 1413 if (wrqu->data.length < descr->min_tokens) { 1414 printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length); 1415 return; 1416 } 1417 /* Calculate extra_len - extra is NULL for restricted events */ 1418 if (extra != NULL) 1419 extra_len = wrqu->data.length * descr->token_size; 1420 /* Always at an offset in wrqu */ 1421 wrqu_off = IW_EV_POINT_OFF; 1422 } 1423 1424 /* Total length of the event */ 1425 hdr_len = event_type_size[descr->header_type]; 1426 event_len = hdr_len + extra_len; 1427 1428 /* 1429 * The problem for 64/32 bit. 1430 * 1431 * On 64-bit, a regular event is laid out as follows: 1432 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 1433 * | event.len | event.cmd | p a d d i n g | 1434 * | wrqu data ... (with the correct size) | 1435 * 1436 * This padding exists because we manipulate event->u, 1437 * and 'event' is not packed. 1438 * 1439 * An iw_point event is laid out like this instead: 1440 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 1441 * | event.len | event.cmd | p a d d i n g | 1442 * | iwpnt.len | iwpnt.flg | p a d d i n g | 1443 * | extra data ... 1444 * 1445 * The second padding exists because struct iw_point is extended, 1446 * but this depends on the platform... 1447 * 1448 * On 32-bit, all the padding shouldn't be there. 1449 */ 1450 1451 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1452 if (!skb) 1453 return; 1454 1455 /* Send via the RtNetlink event channel */ 1456 nlh = rtnetlink_ifinfo_prep(dev, skb); 1457 if (WARN_ON(!nlh)) { 1458 kfree_skb(skb); 1459 return; 1460 } 1461 1462 /* Add the wireless events in the netlink packet */ 1463 nla = nla_reserve(skb, IFLA_WIRELESS, event_len); 1464 if (!nla) { 1465 kfree_skb(skb); 1466 return; 1467 } 1468 event = nla_data(nla); 1469 1470 /* Fill event - first clear to avoid data leaking */ 1471 memset(event, 0, hdr_len); 1472 event->len = event_len; 1473 event->cmd = cmd; 1474 memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN); 1475 if (extra_len) 1476 memcpy(((char *) event) + hdr_len, extra, extra_len); 1477 1478 nlmsg_end(skb, nlh); 1479#ifdef CONFIG_COMPAT 1480 hdr_len = compat_event_type_size[descr->header_type]; 1481 event_len = hdr_len + extra_len; 1482 1483 compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1484 if (!compskb) { 1485 kfree_skb(skb); 1486 return; 1487 } 1488 1489 /* Send via the RtNetlink event channel */ 1490 nlh = rtnetlink_ifinfo_prep(dev, compskb); 1491 if (WARN_ON(!nlh)) { 1492 kfree_skb(skb); 1493 kfree_skb(compskb); 1494 return; 1495 } 1496 1497 /* Add the wireless events in the netlink packet */ 1498 nla = nla_reserve(compskb, IFLA_WIRELESS, event_len); 1499 if (!nla) { 1500 kfree_skb(skb); 1501 kfree_skb(compskb); 1502 return; 1503 } 1504 compat_event = nla_data(nla); 1505 1506 compat_event->len = event_len; 1507 compat_event->cmd = cmd; 1508 if (descr->header_type == IW_HEADER_TYPE_POINT) { 1509 compat_wrqu.length = wrqu->data.length; 1510 compat_wrqu.flags = wrqu->data.flags; 1511 memcpy(&compat_event->pointer, 1512 ((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF, 1513 hdr_len - IW_EV_COMPAT_LCP_LEN); 1514 if (extra_len) 1515 memcpy(((char *) compat_event) + hdr_len, 1516 extra, extra_len); 1517 } else { 1518 /* extra_len must be zero, so no if (extra) needed */ 1519 memcpy(&compat_event->pointer, wrqu, 1520 hdr_len - IW_EV_COMPAT_LCP_LEN); 1521 } 1522 1523 nlmsg_end(compskb, nlh); 1524 1525 skb_shinfo(skb)->frag_list = compskb; 1526#endif 1527 skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); 1528 schedule_work(&wireless_nlevent_work); 1529} 1530EXPORT_SYMBOL(wireless_send_event); 1531 1532/********************** ENHANCED IWSPY SUPPORT **********************/ 1533/* 1534 * In the old days, the driver was handling spy support all by itself. 1535 * Now, the driver can delegate this task to Wireless Extensions. 1536 * It needs to use those standard spy iw_handler in struct iw_handler_def, 1537 * push data to us via wireless_spy_update() and include struct iw_spy_data 1538 * in its private part (and export it in net_device->wireless_data->spy_data). 1539 * One of the main advantage of centralising spy support here is that 1540 * it becomes much easier to improve and extend it without having to touch 1541 * the drivers. One example is the addition of the Spy-Threshold events. 1542 */ 1543 1544/* ---------------------------------------------------------------- */ 1545/* 1546 * Return the pointer to the spy data in the driver. 1547 * Because this is called on the Rx path via wireless_spy_update(), 1548 * we want it to be efficient... 1549 */ 1550static inline struct iw_spy_data *get_spydata(struct net_device *dev) 1551{ 1552 /* This is the new way */ 1553 if (dev->wireless_data) 1554 return dev->wireless_data->spy_data; 1555 return NULL; 1556} 1557 1558/*------------------------------------------------------------------*/ 1559/* 1560 * Standard Wireless Handler : set Spy List 1561 */ 1562int iw_handler_set_spy(struct net_device * dev, 1563 struct iw_request_info * info, 1564 union iwreq_data * wrqu, 1565 char * extra) 1566{ 1567 struct iw_spy_data * spydata = get_spydata(dev); 1568 struct sockaddr * address = (struct sockaddr *) extra; 1569 1570 /* Make sure driver is not buggy or using the old API */ 1571 if (!spydata) 1572 return -EOPNOTSUPP; 1573 1574 /* Disable spy collection while we copy the addresses. 1575 * While we copy addresses, any call to wireless_spy_update() 1576 * will NOP. This is OK, as anyway the addresses are changing. */ 1577 spydata->spy_number = 0; 1578 1579 /* We want to operate without locking, because wireless_spy_update() 1580 * most likely will happen in the interrupt handler, and therefore 1581 * have its own locking constraints and needs performance. 1582 * The rtnl_lock() make sure we don't race with the other iw_handlers. 1583 * This make sure wireless_spy_update() "see" that the spy list 1584 * is temporarily disabled. */ 1585 smp_wmb(); 1586 1587 /* Are there are addresses to copy? */ 1588 if (wrqu->data.length > 0) { 1589 int i; 1590 1591 /* Copy addresses */ 1592 for (i = 0; i < wrqu->data.length; i++) 1593 memcpy(spydata->spy_address[i], address[i].sa_data, 1594 ETH_ALEN); 1595 /* Reset stats */ 1596 memset(spydata->spy_stat, 0, 1597 sizeof(struct iw_quality) * IW_MAX_SPY); 1598 } 1599 1600 /* Make sure above is updated before re-enabling */ 1601 smp_wmb(); 1602 1603 /* Enable addresses */ 1604 spydata->spy_number = wrqu->data.length; 1605 1606 return 0; 1607} 1608EXPORT_SYMBOL(iw_handler_set_spy); 1609 1610/*------------------------------------------------------------------*/ 1611/* 1612 * Standard Wireless Handler : get Spy List 1613 */ 1614int iw_handler_get_spy(struct net_device * dev, 1615 struct iw_request_info * info, 1616 union iwreq_data * wrqu, 1617 char * extra) 1618{ 1619 struct iw_spy_data * spydata = get_spydata(dev); 1620 struct sockaddr * address = (struct sockaddr *) extra; 1621 int i; 1622 1623 /* Make sure driver is not buggy or using the old API */ 1624 if (!spydata) 1625 return -EOPNOTSUPP; 1626 1627 wrqu->data.length = spydata->spy_number; 1628 1629 /* Copy addresses. */ 1630 for (i = 0; i < spydata->spy_number; i++) { 1631 memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN); 1632 address[i].sa_family = AF_UNIX; 1633 } 1634 /* Copy stats to the user buffer (just after). */ 1635 if (spydata->spy_number > 0) 1636 memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number), 1637 spydata->spy_stat, 1638 sizeof(struct iw_quality) * spydata->spy_number); 1639 /* Reset updated flags. */ 1640 for (i = 0; i < spydata->spy_number; i++) 1641 spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED; 1642 return 0; 1643} 1644EXPORT_SYMBOL(iw_handler_get_spy); 1645 1646/*------------------------------------------------------------------*/ 1647/* 1648 * Standard Wireless Handler : set spy threshold 1649 */ 1650int iw_handler_set_thrspy(struct net_device * dev, 1651 struct iw_request_info *info, 1652 union iwreq_data * wrqu, 1653 char * extra) 1654{ 1655 struct iw_spy_data * spydata = get_spydata(dev); 1656 struct iw_thrspy * threshold = (struct iw_thrspy *) extra; 1657 1658 /* Make sure driver is not buggy or using the old API */ 1659 if (!spydata) 1660 return -EOPNOTSUPP; 1661 1662 /* Just do it */ 1663 memcpy(&(spydata->spy_thr_low), &(threshold->low), 1664 2 * sizeof(struct iw_quality)); 1665 1666 /* Clear flag */ 1667 memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under)); 1668 1669 return 0; 1670} 1671EXPORT_SYMBOL(iw_handler_set_thrspy); 1672 1673/*------------------------------------------------------------------*/ 1674/* 1675 * Standard Wireless Handler : get spy threshold 1676 */ 1677int iw_handler_get_thrspy(struct net_device * dev, 1678 struct iw_request_info *info, 1679 union iwreq_data * wrqu, 1680 char * extra) 1681{ 1682 struct iw_spy_data * spydata = get_spydata(dev); 1683 struct iw_thrspy * threshold = (struct iw_thrspy *) extra; 1684 1685 /* Make sure driver is not buggy or using the old API */ 1686 if (!spydata) 1687 return -EOPNOTSUPP; 1688 1689 /* Just do it */ 1690 memcpy(&(threshold->low), &(spydata->spy_thr_low), 1691 2 * sizeof(struct iw_quality)); 1692 1693 return 0; 1694} 1695EXPORT_SYMBOL(iw_handler_get_thrspy); 1696 1697/*------------------------------------------------------------------*/ 1698/* 1699 * Prepare and send a Spy Threshold event 1700 */ 1701static void iw_send_thrspy_event(struct net_device * dev, 1702 struct iw_spy_data * spydata, 1703 unsigned char * address, 1704 struct iw_quality * wstats) 1705{ 1706 union iwreq_data wrqu; 1707 struct iw_thrspy threshold; 1708 1709 /* Init */ 1710 wrqu.data.length = 1; 1711 wrqu.data.flags = 0; 1712 /* Copy address */ 1713 memcpy(threshold.addr.sa_data, address, ETH_ALEN); 1714 threshold.addr.sa_family = ARPHRD_ETHER; 1715 /* Copy stats */ 1716 memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality)); 1717 /* Copy also thresholds */ 1718 memcpy(&(threshold.low), &(spydata->spy_thr_low), 1719 2 * sizeof(struct iw_quality)); 1720 1721 /* Send event to user space */ 1722 wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); 1723} 1724 1725/* ---------------------------------------------------------------- */ 1726/* 1727 * Call for the driver to update the spy data. 1728 * For now, the spy data is a simple array. As the size of the array is 1729 * small, this is good enough. If we wanted to support larger number of 1730 * spy addresses, we should use something more efficient... 1731 */ 1732void wireless_spy_update(struct net_device * dev, 1733 unsigned char * address, 1734 struct iw_quality * wstats) 1735{ 1736 struct iw_spy_data * spydata = get_spydata(dev); 1737 int i; 1738 int match = -1; 1739 1740 /* Make sure driver is not buggy or using the old API */ 1741 if (!spydata) 1742 return; 1743 1744 /* Update all records that match */ 1745 for (i = 0; i < spydata->spy_number; i++) 1746 if (!compare_ether_addr(address, spydata->spy_address[i])) { 1747 memcpy(&(spydata->spy_stat[i]), wstats, 1748 sizeof(struct iw_quality)); 1749 match = i; 1750 } 1751 1752 /* Generate an event if we cross the spy threshold. 1753 * To avoid event storms, we have a simple hysteresis : we generate 1754 * event only when we go under the low threshold or above the 1755 * high threshold. */ 1756 if (match >= 0) { 1757 if (spydata->spy_thr_under[match]) { 1758 if (wstats->level > spydata->spy_thr_high.level) { 1759 spydata->spy_thr_under[match] = 0; 1760 iw_send_thrspy_event(dev, spydata, 1761 address, wstats); 1762 } 1763 } else { 1764 if (wstats->level < spydata->spy_thr_low.level) { 1765 spydata->spy_thr_under[match] = 1; 1766 iw_send_thrspy_event(dev, spydata, 1767 address, wstats); 1768 } 1769 } 1770 } 1771} 1772EXPORT_SYMBOL(wireless_spy_update);