|
|
1.1 ! root 1: /* ! 2: * The iPXE 802.11 MAC layer. ! 3: * ! 4: * Copyright (c) 2009 Joshua Oreman <[email protected]>. ! 5: * ! 6: * This program is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU General Public License as ! 8: * published by the Free Software Foundation; either version 2 of the ! 9: * License, or any later version. ! 10: * ! 11: * This program is distributed in the hope that it will be useful, but ! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU General Public License ! 17: * along with this program; if not, write to the Free Software ! 18: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 19: */ ! 20: ! 21: FILE_LICENCE ( GPL2_OR_LATER ); ! 22: ! 23: #include <string.h> ! 24: #include <byteswap.h> ! 25: #include <stdlib.h> ! 26: #include <unistd.h> ! 27: #include <errno.h> ! 28: #include <ipxe/settings.h> ! 29: #include <ipxe/if_arp.h> ! 30: #include <ipxe/ethernet.h> ! 31: #include <ipxe/ieee80211.h> ! 32: #include <ipxe/netdevice.h> ! 33: #include <ipxe/net80211.h> ! 34: #include <ipxe/sec80211.h> ! 35: #include <ipxe/timer.h> ! 36: #include <ipxe/nap.h> ! 37: #include <ipxe/errortab.h> ! 38: #include <ipxe/net80211_err.h> ! 39: ! 40: /** @file ! 41: * ! 42: * 802.11 device management ! 43: */ ! 44: ! 45: /** List of 802.11 devices */ ! 46: static struct list_head net80211_devices = LIST_HEAD_INIT ( net80211_devices ); ! 47: ! 48: /** Set of device operations that does nothing */ ! 49: static struct net80211_device_operations net80211_null_ops; ! 50: ! 51: /** Information associated with a received management packet ! 52: * ! 53: * This is used to keep beacon signal strengths in a parallel queue to ! 54: * the beacons themselves. ! 55: */ ! 56: struct net80211_rx_info { ! 57: int signal; ! 58: struct list_head list; ! 59: }; ! 60: ! 61: /** Context for a probe operation */ ! 62: struct net80211_probe_ctx { ! 63: /** 802.11 device to probe on */ ! 64: struct net80211_device *dev; ! 65: ! 66: /** Value of keep_mgmt before probe was started */ ! 67: int old_keep_mgmt; ! 68: ! 69: /** If scanning actively, pointer to probe packet to send */ ! 70: struct io_buffer *probe; ! 71: ! 72: /** If non-"", the ESSID to limit ourselves to */ ! 73: const char *essid; ! 74: ! 75: /** Time probe was started */ ! 76: u32 ticks_start; ! 77: ! 78: /** Time last useful beacon was received */ ! 79: u32 ticks_beacon; ! 80: ! 81: /** Time channel was last changed */ ! 82: u32 ticks_channel; ! 83: ! 84: /** Time to stay on each channel */ ! 85: u32 hop_time; ! 86: ! 87: /** Channels to hop by when changing channel */ ! 88: int hop_step; ! 89: ! 90: /** List of best beacons for each network found so far */ ! 91: struct list_head *beacons; ! 92: }; ! 93: ! 94: /** Context for the association task */ ! 95: struct net80211_assoc_ctx { ! 96: /** Next authentication method to try using */ ! 97: int method; ! 98: ! 99: /** Time (in ticks) of the last sent association-related packet */ ! 100: int last_packet; ! 101: ! 102: /** Number of times we have tried sending it */ ! 103: int times_tried; ! 104: }; ! 105: ! 106: /** ! 107: * Detect secure 802.11 network when security support is not available ! 108: * ! 109: * @return -ENOTSUP, always. ! 110: */ ! 111: __weak int sec80211_detect ( struct io_buffer *iob __unused, ! 112: enum net80211_security_proto *secprot __unused, ! 113: enum net80211_crypto_alg *crypt __unused ) { ! 114: return -ENOTSUP; ! 115: } ! 116: ! 117: /** ! 118: * @defgroup net80211_netdev Network device interface functions ! 119: * @{ ! 120: */ ! 121: static int net80211_netdev_open ( struct net_device *netdev ); ! 122: static void net80211_netdev_close ( struct net_device *netdev ); ! 123: static int net80211_netdev_transmit ( struct net_device *netdev, ! 124: struct io_buffer *iobuf ); ! 125: static void net80211_netdev_poll ( struct net_device *netdev ); ! 126: static void net80211_netdev_irq ( struct net_device *netdev, int enable ); ! 127: /** @} */ ! 128: ! 129: /** ! 130: * @defgroup net80211_linklayer 802.11 link-layer protocol functions ! 131: * @{ ! 132: */ ! 133: static int net80211_ll_push ( struct net_device *netdev, ! 134: struct io_buffer *iobuf, const void *ll_dest, ! 135: const void *ll_source, uint16_t net_proto ); ! 136: static int net80211_ll_pull ( struct net_device *netdev, ! 137: struct io_buffer *iobuf, const void **ll_dest, ! 138: const void **ll_source, uint16_t * net_proto ); ! 139: /** @} */ ! 140: ! 141: /** ! 142: * @defgroup net80211_help 802.11 helper functions ! 143: * @{ ! 144: */ ! 145: static void net80211_add_channels ( struct net80211_device *dev, int start, ! 146: int len, int txpower ); ! 147: static void net80211_filter_hw_channels ( struct net80211_device *dev ); ! 148: static void net80211_set_rtscts_rate ( struct net80211_device *dev ); ! 149: static int net80211_process_capab ( struct net80211_device *dev, ! 150: u16 capab ); ! 151: static int net80211_process_ie ( struct net80211_device *dev, ! 152: union ieee80211_ie *ie, void *ie_end ); ! 153: static union ieee80211_ie * ! 154: net80211_marshal_request_info ( struct net80211_device *dev, ! 155: union ieee80211_ie *ie ); ! 156: /** @} */ ! 157: ! 158: /** ! 159: * @defgroup net80211_assoc_ll 802.11 association handling functions ! 160: * @{ ! 161: */ ! 162: static void net80211_step_associate ( struct process *proc ); ! 163: static void net80211_handle_auth ( struct net80211_device *dev, ! 164: struct io_buffer *iob ); ! 165: static void net80211_handle_assoc_reply ( struct net80211_device *dev, ! 166: struct io_buffer *iob ); ! 167: static int net80211_send_disassoc ( struct net80211_device *dev, int reason, ! 168: int deauth ); ! 169: static void net80211_handle_mgmt ( struct net80211_device *dev, ! 170: struct io_buffer *iob, int signal ); ! 171: /** @} */ ! 172: ! 173: /** ! 174: * @defgroup net80211_frag 802.11 fragment handling functions ! 175: * @{ ! 176: */ ! 177: static void net80211_free_frags ( struct net80211_device *dev, int fcid ); ! 178: static struct io_buffer *net80211_accum_frags ( struct net80211_device *dev, ! 179: int fcid, int nfrags, int size ); ! 180: static void net80211_rx_frag ( struct net80211_device *dev, ! 181: struct io_buffer *iob, int signal ); ! 182: /** @} */ ! 183: ! 184: /** ! 185: * @defgroup net80211_settings 802.11 settings handlers ! 186: * @{ ! 187: */ ! 188: static int net80211_check_settings_update ( void ); ! 189: ! 190: /** 802.11 settings applicator ! 191: * ! 192: * When the SSID is changed, this will cause any open devices to ! 193: * re-associate; when the encryption key is changed, we similarly ! 194: * update their state. ! 195: */ ! 196: struct settings_applicator net80211_applicator __settings_applicator = { ! 197: .apply = net80211_check_settings_update, ! 198: }; ! 199: ! 200: /** The network name to associate with ! 201: * ! 202: * If this is blank, we scan for all networks and use the one with the ! 203: * greatest signal strength. ! 204: */ ! 205: struct setting net80211_ssid_setting __setting ( SETTING_NETDEV_EXTRA ) = { ! 206: .name = "ssid", ! 207: .description = "Wireless SSID", ! 208: .type = &setting_type_string, ! 209: .tag = NET80211_SETTING_TAG_SSID, ! 210: }; ! 211: ! 212: /** Whether to use active scanning ! 213: * ! 214: * In order to associate with a hidden SSID, it's necessary to use an ! 215: * active scan (send probe packets). If this setting is nonzero, an ! 216: * active scan on the 2.4GHz band will be used to associate. ! 217: */ ! 218: struct setting net80211_active_setting __setting ( SETTING_NETDEV_EXTRA ) = { ! 219: .name = "active-scan", ! 220: .description = "Actively scan for wireless networks", ! 221: .type = &setting_type_int8, ! 222: .tag = NET80211_SETTING_TAG_ACTIVE_SCAN, ! 223: }; ! 224: ! 225: /** The cryptographic key to use ! 226: * ! 227: * For hex WEP keys, as is common, this must be entered using the ! 228: * normal iPXE method for entering hex settings; an ASCII string of ! 229: * hex characters will not behave as expected. ! 230: */ ! 231: struct setting net80211_key_setting __setting ( SETTING_NETDEV_EXTRA ) = { ! 232: .name = "key", ! 233: .description = "Wireless encryption key", ! 234: .type = &setting_type_string, ! 235: .tag = NET80211_SETTING_TAG_KEY, ! 236: }; ! 237: ! 238: /** @} */ ! 239: ! 240: ! 241: /* ---------- net_device wrapper ---------- */ ! 242: ! 243: /** ! 244: * Open 802.11 device and start association ! 245: * ! 246: * @v netdev Wrapping network device ! 247: * @ret rc Return status code ! 248: * ! 249: * This sets up a default conservative set of channels for probing, ! 250: * and starts the auto-association task unless the @c ! 251: * NET80211_NO_ASSOC flag is set in the wrapped 802.11 device's @c ! 252: * state field. ! 253: */ ! 254: static int net80211_netdev_open ( struct net_device *netdev ) ! 255: { ! 256: struct net80211_device *dev = netdev->priv; ! 257: int rc = 0; ! 258: ! 259: if ( dev->op == &net80211_null_ops ) ! 260: return -EFAULT; ! 261: ! 262: if ( dev->op->open ) ! 263: rc = dev->op->open ( dev ); ! 264: ! 265: if ( rc < 0 ) ! 266: return rc; ! 267: ! 268: if ( ! ( dev->state & NET80211_NO_ASSOC ) ) ! 269: net80211_autoassociate ( dev ); ! 270: ! 271: return 0; ! 272: } ! 273: ! 274: /** ! 275: * Close 802.11 device ! 276: * ! 277: * @v netdev Wrapping network device. ! 278: * ! 279: * If the association task is running, this will stop it. ! 280: */ ! 281: static void net80211_netdev_close ( struct net_device *netdev ) ! 282: { ! 283: struct net80211_device *dev = netdev->priv; ! 284: ! 285: if ( dev->state & NET80211_WORKING ) ! 286: process_del ( &dev->proc_assoc ); ! 287: ! 288: /* Send disassociation frame to AP, to be polite */ ! 289: if ( dev->state & NET80211_ASSOCIATED ) ! 290: net80211_send_disassoc ( dev, IEEE80211_REASON_LEAVING, 0 ); ! 291: ! 292: if ( dev->handshaker && dev->handshaker->stop && ! 293: dev->handshaker->started ) ! 294: dev->handshaker->stop ( dev ); ! 295: ! 296: free ( dev->crypto ); ! 297: free ( dev->handshaker ); ! 298: dev->crypto = NULL; ! 299: dev->handshaker = NULL; ! 300: ! 301: netdev_link_down ( netdev ); ! 302: dev->state = 0; ! 303: ! 304: if ( dev->op->close ) ! 305: dev->op->close ( dev ); ! 306: } ! 307: ! 308: /** ! 309: * Transmit packet on 802.11 device ! 310: * ! 311: * @v netdev Wrapping network device ! 312: * @v iobuf I/O buffer ! 313: * @ret rc Return status code ! 314: * ! 315: * If encryption is enabled for the currently associated network, the ! 316: * packet will be encrypted prior to transmission. ! 317: */ ! 318: static int net80211_netdev_transmit ( struct net_device *netdev, ! 319: struct io_buffer *iobuf ) ! 320: { ! 321: struct net80211_device *dev = netdev->priv; ! 322: struct ieee80211_frame *hdr = iobuf->data; ! 323: int rc = -ENOSYS; ! 324: ! 325: if ( dev->crypto && ! ( hdr->fc & IEEE80211_FC_PROTECTED ) && ! 326: ( ( hdr->fc & IEEE80211_FC_TYPE ) == IEEE80211_TYPE_DATA ) ) { ! 327: struct io_buffer *niob = dev->crypto->encrypt ( dev->crypto, ! 328: iobuf ); ! 329: if ( ! niob ) ! 330: return -ENOMEM; /* only reason encryption could fail */ ! 331: ! 332: /* Free the non-encrypted iob */ ! 333: netdev_tx_complete ( netdev, iobuf ); ! 334: ! 335: /* Transmit the encrypted iob; the Protected flag is ! 336: set, so we won't recurse into here again */ ! 337: netdev_tx ( netdev, niob ); ! 338: ! 339: /* Don't transmit the freed packet */ ! 340: return 0; ! 341: } ! 342: ! 343: if ( dev->op->transmit ) ! 344: rc = dev->op->transmit ( dev, iobuf ); ! 345: ! 346: return rc; ! 347: } ! 348: ! 349: /** ! 350: * Poll 802.11 device for received packets and completed transmissions ! 351: * ! 352: * @v netdev Wrapping network device ! 353: */ ! 354: static void net80211_netdev_poll ( struct net_device *netdev ) ! 355: { ! 356: struct net80211_device *dev = netdev->priv; ! 357: ! 358: if ( dev->op->poll ) ! 359: dev->op->poll ( dev ); ! 360: } ! 361: ! 362: /** ! 363: * Enable or disable interrupts for 802.11 device ! 364: * ! 365: * @v netdev Wrapping network device ! 366: * @v enable Whether to enable interrupts ! 367: */ ! 368: static void net80211_netdev_irq ( struct net_device *netdev, int enable ) ! 369: { ! 370: struct net80211_device *dev = netdev->priv; ! 371: ! 372: if ( dev->op->irq ) ! 373: dev->op->irq ( dev, enable ); ! 374: } ! 375: ! 376: /** Network device operations for a wrapped 802.11 device */ ! 377: static struct net_device_operations net80211_netdev_ops = { ! 378: .open = net80211_netdev_open, ! 379: .close = net80211_netdev_close, ! 380: .transmit = net80211_netdev_transmit, ! 381: .poll = net80211_netdev_poll, ! 382: .irq = net80211_netdev_irq, ! 383: }; ! 384: ! 385: ! 386: /* ---------- 802.11 link-layer protocol ---------- */ ! 387: ! 388: /** 802.11 broadcast MAC address */ ! 389: static u8 net80211_ll_broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ! 390: ! 391: /** ! 392: * Determine whether a transmission rate uses ERP/OFDM ! 393: * ! 394: * @v rate Rate in 100 kbps units ! 395: * @ret is_erp TRUE if the rate is an ERP/OFDM rate ! 396: * ! 397: * 802.11b supports rates of 1.0, 2.0, 5.5, and 11.0 Mbps; any other ! 398: * rate than these on the 2.4GHz spectrum is an ERP (802.11g) rate. ! 399: */ ! 400: static inline int net80211_rate_is_erp ( u16 rate ) ! 401: { ! 402: if ( rate == 10 || rate == 20 || rate == 55 || rate == 110 ) ! 403: return 0; ! 404: return 1; ! 405: } ! 406: ! 407: ! 408: /** ! 409: * Calculate one frame's contribution to 802.11 duration field ! 410: * ! 411: * @v dev 802.11 device ! 412: * @v bytes Amount of data to calculate duration for ! 413: * @ret dur Duration field in microseconds ! 414: * ! 415: * To avoid multiple stations attempting to transmit at once, 802.11 ! 416: * provides that every packet shall include a duration field ! 417: * specifying a length of time for which the wireless medium will be ! 418: * reserved after it is transmitted. The duration is measured in ! 419: * microseconds and is calculated with respect to the current ! 420: * physical-layer parameters of the 802.11 device. ! 421: * ! 422: * For an unfragmented data or management frame, or the last fragment ! 423: * of a fragmented frame, the duration captures only the 10 data bytes ! 424: * of one ACK; call once with bytes = 10. ! 425: * ! 426: * For a fragment of a data or management rame that will be followed ! 427: * by more fragments, the duration captures an ACK, the following ! 428: * fragment, and its ACK; add the results of three calls, two with ! 429: * bytes = 10 and one with bytes set to the next fragment's size. ! 430: * ! 431: * For an RTS control frame, the duration captures the responding CTS, ! 432: * the frame being sent, and its ACK; add the results of three calls, ! 433: * two with bytes = 10 and one with bytes set to the next frame's size ! 434: * (assuming unfragmented). ! 435: * ! 436: * For a CTS-to-self control frame, the duration captures the frame ! 437: * being protected and its ACK; add the results of two calls, one with ! 438: * bytes = 10 and one with bytes set to the next frame's size. ! 439: * ! 440: * No other frame types are currently supported by iPXE. ! 441: */ ! 442: u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate ) ! 443: { ! 444: struct net80211_channel *chan = &dev->channels[dev->channel]; ! 445: u32 kbps = rate * 100; ! 446: ! 447: if ( chan->band == NET80211_BAND_5GHZ || net80211_rate_is_erp ( rate ) ) { ! 448: /* OFDM encoding (802.11a/g) */ ! 449: int bits_per_symbol = ( kbps * 4 ) / 1000; /* 4us/symbol */ ! 450: int bits = 22 + ( bytes << 3 ); /* 22-bit PLCP */ ! 451: int symbols = ( bits + bits_per_symbol - 1 ) / bits_per_symbol; ! 452: ! 453: return 16 + 20 + ( symbols * 4 ); /* 16us SIFS, 20us preamble */ ! 454: } else { ! 455: /* CCK encoding (802.11b) */ ! 456: int phy_time = 144 + 48; /* preamble + PLCP */ ! 457: int bits = bytes << 3; ! 458: int data_time = ( bits * 1000 + kbps - 1 ) / kbps; ! 459: ! 460: if ( dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE ) ! 461: phy_time >>= 1; ! 462: ! 463: return 10 + phy_time + data_time; /* 10us SIFS */ ! 464: } ! 465: } ! 466: ! 467: /** ! 468: * Add 802.11 link-layer header ! 469: * ! 470: * @v netdev Wrapping network device ! 471: * @v iobuf I/O buffer ! 472: * @v ll_dest Link-layer destination address ! 473: * @v ll_source Link-layer source address ! 474: * @v net_proto Network-layer protocol, in network byte order ! 475: * @ret rc Return status code ! 476: * ! 477: * This adds both the 802.11 frame header and the 802.2 LLC/SNAP ! 478: * header used on data packets. ! 479: * ! 480: * We also check here for state of the link that would make it invalid ! 481: * to send a data packet; every data packet must pass through here, ! 482: * and no non-data packet (e.g. management frame) should. ! 483: */ ! 484: static int net80211_ll_push ( struct net_device *netdev, ! 485: struct io_buffer *iobuf, const void *ll_dest, ! 486: const void *ll_source, uint16_t net_proto ) ! 487: { ! 488: struct net80211_device *dev = netdev->priv; ! 489: struct ieee80211_frame *hdr = iob_push ( iobuf, ! 490: IEEE80211_LLC_HEADER_LEN + ! 491: IEEE80211_TYP_FRAME_HEADER_LEN ); ! 492: struct ieee80211_llc_snap_header *lhdr = ! 493: ( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN; ! 494: ! 495: /* We can't send data packets if we're not associated. */ ! 496: if ( ! ( dev->state & NET80211_ASSOCIATED ) ) { ! 497: if ( dev->assoc_rc ) ! 498: return dev->assoc_rc; ! 499: return -ENETUNREACH; ! 500: } ! 501: ! 502: hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_DATA | ! 503: IEEE80211_STYPE_DATA | IEEE80211_FC_TODS; ! 504: ! 505: /* We don't send fragmented frames, so duration is the time ! 506: for an SIFS + 10-byte ACK. */ ! 507: hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] ); ! 508: ! 509: memcpy ( hdr->addr1, dev->bssid, ETH_ALEN ); ! 510: memcpy ( hdr->addr2, ll_source, ETH_ALEN ); ! 511: memcpy ( hdr->addr3, ll_dest, ETH_ALEN ); ! 512: ! 513: hdr->seq = IEEE80211_MAKESEQ ( ++dev->last_tx_seqnr, 0 ); ! 514: ! 515: lhdr->dsap = IEEE80211_LLC_DSAP; ! 516: lhdr->ssap = IEEE80211_LLC_SSAP; ! 517: lhdr->ctrl = IEEE80211_LLC_CTRL; ! 518: memset ( lhdr->oui, 0x00, 3 ); ! 519: lhdr->ethertype = net_proto; ! 520: ! 521: return 0; ! 522: } ! 523: ! 524: /** ! 525: * Remove 802.11 link-layer header ! 526: * ! 527: * @v netdev Wrapping network device ! 528: * @v iobuf I/O buffer ! 529: * @ret ll_dest Link-layer destination address ! 530: * @ret ll_source Link-layer source ! 531: * @ret net_proto Network-layer protocol, in network byte order ! 532: * @ret rc Return status code ! 533: * ! 534: * This expects and removes both the 802.11 frame header and the 802.2 ! 535: * LLC/SNAP header that are used on data packets. ! 536: */ ! 537: static int net80211_ll_pull ( struct net_device *netdev __unused, ! 538: struct io_buffer *iobuf, ! 539: const void **ll_dest, const void **ll_source, ! 540: uint16_t * net_proto ) ! 541: { ! 542: struct ieee80211_frame *hdr = iobuf->data; ! 543: struct ieee80211_llc_snap_header *lhdr = ! 544: ( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN; ! 545: ! 546: /* Bunch of sanity checks */ ! 547: if ( iob_len ( iobuf ) < IEEE80211_TYP_FRAME_HEADER_LEN + ! 548: IEEE80211_LLC_HEADER_LEN ) { ! 549: DBGC ( netdev->priv, "802.11 %p packet too short (%zd bytes)\n", ! 550: netdev->priv, iob_len ( iobuf ) ); ! 551: return -EINVAL_PKT_TOO_SHORT; ! 552: } ! 553: ! 554: if ( ( hdr->fc & IEEE80211_FC_VERSION ) != IEEE80211_THIS_VERSION ) { ! 555: DBGC ( netdev->priv, "802.11 %p packet invalid version %04x\n", ! 556: netdev->priv, hdr->fc & IEEE80211_FC_VERSION ); ! 557: return -EINVAL_PKT_VERSION; ! 558: } ! 559: ! 560: if ( ( hdr->fc & IEEE80211_FC_TYPE ) != IEEE80211_TYPE_DATA || ! 561: ( hdr->fc & IEEE80211_FC_SUBTYPE ) != IEEE80211_STYPE_DATA ) { ! 562: DBGC ( netdev->priv, "802.11 %p packet not data/data (fc=%04x)\n", ! 563: netdev->priv, hdr->fc ); ! 564: return -EINVAL_PKT_NOT_DATA; ! 565: } ! 566: ! 567: if ( ( hdr->fc & ( IEEE80211_FC_TODS | IEEE80211_FC_FROMDS ) ) != ! 568: IEEE80211_FC_FROMDS ) { ! 569: DBGC ( netdev->priv, "802.11 %p packet not from DS (fc=%04x)\n", ! 570: netdev->priv, hdr->fc ); ! 571: return -EINVAL_PKT_NOT_FROMDS; ! 572: } ! 573: ! 574: if ( lhdr->dsap != IEEE80211_LLC_DSAP || lhdr->ssap != IEEE80211_LLC_SSAP || ! 575: lhdr->ctrl != IEEE80211_LLC_CTRL || lhdr->oui[0] || lhdr->oui[1] || ! 576: lhdr->oui[2] ) { ! 577: DBGC ( netdev->priv, "802.11 %p LLC header is not plain EtherType " ! 578: "encapsulator: %02x->%02x [%02x] %02x:%02x:%02x %04x\n", ! 579: netdev->priv, lhdr->dsap, lhdr->ssap, lhdr->ctrl, ! 580: lhdr->oui[0], lhdr->oui[1], lhdr->oui[2], lhdr->ethertype ); ! 581: return -EINVAL_PKT_LLC_HEADER; ! 582: } ! 583: ! 584: iob_pull ( iobuf, sizeof ( *hdr ) + sizeof ( *lhdr ) ); ! 585: ! 586: *ll_dest = hdr->addr1; ! 587: *ll_source = hdr->addr3; ! 588: *net_proto = lhdr->ethertype; ! 589: return 0; ! 590: } ! 591: ! 592: /** 802.11 link-layer protocol */ ! 593: static struct ll_protocol net80211_ll_protocol __ll_protocol = { ! 594: .name = "802.11", ! 595: .push = net80211_ll_push, ! 596: .pull = net80211_ll_pull, ! 597: .init_addr = eth_init_addr, ! 598: .ntoa = eth_ntoa, ! 599: .mc_hash = eth_mc_hash, ! 600: .eth_addr = eth_eth_addr, ! 601: .ll_proto = htons ( ARPHRD_ETHER ), /* "encapsulated Ethernet" */ ! 602: .hw_addr_len = ETH_ALEN, ! 603: .ll_addr_len = ETH_ALEN, ! 604: .ll_header_len = IEEE80211_TYP_FRAME_HEADER_LEN + ! 605: IEEE80211_LLC_HEADER_LEN, ! 606: }; ! 607: ! 608: ! 609: /* ---------- 802.11 network management API ---------- */ ! 610: ! 611: /** ! 612: * Get 802.11 device from wrapping network device ! 613: * ! 614: * @v netdev Wrapping network device ! 615: * @ret dev 802.11 device wrapped by network device, or NULL ! 616: * ! 617: * Returns NULL if the network device does not wrap an 802.11 device. ! 618: */ ! 619: struct net80211_device * net80211_get ( struct net_device *netdev ) ! 620: { ! 621: struct net80211_device *dev; ! 622: ! 623: list_for_each_entry ( dev, &net80211_devices, list ) { ! 624: if ( netdev->priv == dev ) ! 625: return netdev->priv; ! 626: } ! 627: ! 628: return NULL; ! 629: } ! 630: ! 631: /** ! 632: * Set state of 802.11 device keeping management frames ! 633: * ! 634: * @v dev 802.11 device ! 635: * @v enable Whether to keep management frames ! 636: * @ret oldenab Whether management frames were enabled before this call ! 637: * ! 638: * If enable is TRUE, beacon, probe, and action frames will be kept ! 639: * and may be retrieved by calling net80211_mgmt_dequeue(). ! 640: */ ! 641: int net80211_keep_mgmt ( struct net80211_device *dev, int enable ) ! 642: { ! 643: int oldenab = dev->keep_mgmt; ! 644: ! 645: dev->keep_mgmt = enable; ! 646: return oldenab; ! 647: } ! 648: ! 649: /** ! 650: * Get 802.11 management frame ! 651: * ! 652: * @v dev 802.11 device ! 653: * @ret signal Signal strength of returned management frame ! 654: * @ret iob I/O buffer, or NULL if no management frame is queued ! 655: * ! 656: * Frames will only be returned by this function if ! 657: * net80211_keep_mgmt() has been previously called with enable set to ! 658: * TRUE. ! 659: * ! 660: * The calling function takes ownership of the returned I/O buffer. ! 661: */ ! 662: struct io_buffer * net80211_mgmt_dequeue ( struct net80211_device *dev, ! 663: int *signal ) ! 664: { ! 665: struct io_buffer *iobuf; ! 666: struct net80211_rx_info *rxi; ! 667: ! 668: list_for_each_entry ( rxi, &dev->mgmt_info_queue, list ) { ! 669: list_del ( &rxi->list ); ! 670: if ( signal ) ! 671: *signal = rxi->signal; ! 672: free ( rxi ); ! 673: ! 674: assert ( ! list_empty ( &dev->mgmt_queue ) ); ! 675: iobuf = list_first_entry ( &dev->mgmt_queue, struct io_buffer, ! 676: list ); ! 677: list_del ( &iobuf->list ); ! 678: return iobuf; ! 679: } ! 680: ! 681: return NULL; ! 682: } ! 683: ! 684: /** ! 685: * Transmit 802.11 management frame ! 686: * ! 687: * @v dev 802.11 device ! 688: * @v fc Frame Control flags for management frame ! 689: * @v dest Destination access point ! 690: * @v iob I/O buffer ! 691: * @ret rc Return status code ! 692: * ! 693: * The @a fc argument must contain at least an IEEE 802.11 management ! 694: * subtype number (e.g. IEEE80211_STYPE_PROBE_REQ). If it contains ! 695: * IEEE80211_FC_PROTECTED, the frame will be encrypted prior to ! 696: * transmission. ! 697: * ! 698: * It is required that @a iob have at least 24 bytes of headroom ! 699: * reserved before its data start. ! 700: */ ! 701: int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc, u8 dest[6], ! 702: struct io_buffer *iob ) ! 703: { ! 704: struct ieee80211_frame *hdr = iob_push ( iob, ! 705: IEEE80211_TYP_FRAME_HEADER_LEN ); ! 706: ! 707: hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_MGMT | ! 708: ( fc & ~IEEE80211_FC_PROTECTED ); ! 709: hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] ); ! 710: hdr->seq = IEEE80211_MAKESEQ ( ++dev->last_tx_seqnr, 0 ); ! 711: ! 712: memcpy ( hdr->addr1, dest, ETH_ALEN ); /* DA = RA */ ! 713: memcpy ( hdr->addr2, dev->netdev->ll_addr, ETH_ALEN ); /* SA = TA */ ! 714: memcpy ( hdr->addr3, dest, ETH_ALEN ); /* BSSID */ ! 715: ! 716: if ( fc & IEEE80211_FC_PROTECTED ) { ! 717: if ( ! dev->crypto ) ! 718: return -EINVAL_CRYPTO_REQUEST; ! 719: ! 720: struct io_buffer *eiob = dev->crypto->encrypt ( dev->crypto, ! 721: iob ); ! 722: free_iob ( iob ); ! 723: iob = eiob; ! 724: } ! 725: ! 726: return netdev_tx ( dev->netdev, iob ); ! 727: } ! 728: ! 729: ! 730: /* ---------- Driver API ---------- */ ! 731: ! 732: /** ! 733: * Allocate 802.11 device ! 734: * ! 735: * @v priv_size Size of driver-private allocation area ! 736: * @ret dev Newly allocated 802.11 device ! 737: * ! 738: * This function allocates a net_device with space in its private area ! 739: * for both the net80211_device it will wrap and the driver-private ! 740: * data space requested. It initializes the link-layer-specific parts ! 741: * of the net_device, and links the net80211_device to the net_device ! 742: * appropriately. ! 743: */ ! 744: struct net80211_device * net80211_alloc ( size_t priv_size ) ! 745: { ! 746: struct net80211_device *dev; ! 747: struct net_device *netdev = ! 748: alloc_netdev ( sizeof ( *dev ) + priv_size ); ! 749: ! 750: if ( ! netdev ) ! 751: return NULL; ! 752: ! 753: netdev->ll_protocol = &net80211_ll_protocol; ! 754: netdev->ll_broadcast = net80211_ll_broadcast; ! 755: netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN; ! 756: netdev_init ( netdev, &net80211_netdev_ops ); ! 757: ! 758: dev = netdev->priv; ! 759: dev->netdev = netdev; ! 760: dev->priv = ( u8 * ) dev + sizeof ( *dev ); ! 761: dev->op = &net80211_null_ops; ! 762: ! 763: process_init_stopped ( &dev->proc_assoc, net80211_step_associate, ! 764: &netdev->refcnt ); ! 765: INIT_LIST_HEAD ( &dev->mgmt_queue ); ! 766: INIT_LIST_HEAD ( &dev->mgmt_info_queue ); ! 767: ! 768: return dev; ! 769: } ! 770: ! 771: /** ! 772: * Register 802.11 device with network stack ! 773: * ! 774: * @v dev 802.11 device ! 775: * @v ops 802.11 device operations ! 776: * @v hw 802.11 hardware information ! 777: * ! 778: * This also registers the wrapping net_device with the higher network ! 779: * layers. ! 780: */ ! 781: int net80211_register ( struct net80211_device *dev, ! 782: struct net80211_device_operations *ops, ! 783: struct net80211_hw_info *hw ) ! 784: { ! 785: dev->op = ops; ! 786: dev->hw = malloc ( sizeof ( *hw ) ); ! 787: if ( ! dev->hw ) ! 788: return -ENOMEM; ! 789: ! 790: memcpy ( dev->hw, hw, sizeof ( *hw ) ); ! 791: memcpy ( dev->netdev->hw_addr, hw->hwaddr, ETH_ALEN ); ! 792: ! 793: /* Set some sensible channel defaults for driver's open() function */ ! 794: memcpy ( dev->channels, dev->hw->channels, ! 795: NET80211_MAX_CHANNELS * sizeof ( dev->channels[0] ) ); ! 796: dev->channel = 0; ! 797: ! 798: list_add_tail ( &dev->list, &net80211_devices ); ! 799: return register_netdev ( dev->netdev ); ! 800: } ! 801: ! 802: /** ! 803: * Unregister 802.11 device from network stack ! 804: * ! 805: * @v dev 802.11 device ! 806: * ! 807: * After this call, the device operations are cleared so that they ! 808: * will not be called. ! 809: */ ! 810: void net80211_unregister ( struct net80211_device *dev ) ! 811: { ! 812: unregister_netdev ( dev->netdev ); ! 813: list_del ( &dev->list ); ! 814: dev->op = &net80211_null_ops; ! 815: } ! 816: ! 817: /** ! 818: * Free 802.11 device ! 819: * ! 820: * @v dev 802.11 device ! 821: * ! 822: * The device should be unregistered before this function is called. ! 823: */ ! 824: void net80211_free ( struct net80211_device *dev ) ! 825: { ! 826: free ( dev->hw ); ! 827: rc80211_free ( dev->rctl ); ! 828: netdev_nullify ( dev->netdev ); ! 829: netdev_put ( dev->netdev ); ! 830: } ! 831: ! 832: ! 833: /* ---------- 802.11 network management workhorse code ---------- */ ! 834: ! 835: /** ! 836: * Set state of 802.11 device ! 837: * ! 838: * @v dev 802.11 device ! 839: * @v clear Bitmask of flags to clear ! 840: * @v set Bitmask of flags to set ! 841: * @v status Status or reason code for most recent operation ! 842: * ! 843: * If @a status represents a reason code, it should be OR'ed with ! 844: * NET80211_IS_REASON. ! 845: * ! 846: * Clearing authentication also clears association; clearing ! 847: * association also clears security handshaking state. Clearing ! 848: * association removes the link-up flag from the wrapping net_device, ! 849: * but setting it does not automatically set the flag; that is left to ! 850: * the judgment of higher-level code. ! 851: */ ! 852: static inline void net80211_set_state ( struct net80211_device *dev, ! 853: short clear, short set, ! 854: u16 status ) ! 855: { ! 856: /* The conditions in this function are deliberately formulated ! 857: to be decidable at compile-time in most cases. Since clear ! 858: and set are generally passed as constants, the body of this ! 859: function can be reduced down to a few statements by the ! 860: compiler. */ ! 861: ! 862: const int statmsk = NET80211_STATUS_MASK | NET80211_IS_REASON; ! 863: ! 864: if ( clear & NET80211_PROBED ) ! 865: clear |= NET80211_AUTHENTICATED; ! 866: ! 867: if ( clear & NET80211_AUTHENTICATED ) ! 868: clear |= NET80211_ASSOCIATED; ! 869: ! 870: if ( clear & NET80211_ASSOCIATED ) ! 871: clear |= NET80211_CRYPTO_SYNCED; ! 872: ! 873: dev->state = ( dev->state & ~clear ) | set; ! 874: dev->state = ( dev->state & ~statmsk ) | ( status & statmsk ); ! 875: ! 876: if ( clear & NET80211_ASSOCIATED ) ! 877: netdev_link_down ( dev->netdev ); ! 878: ! 879: if ( ( clear | set ) & NET80211_ASSOCIATED ) ! 880: dev->op->config ( dev, NET80211_CFG_ASSOC ); ! 881: ! 882: if ( status != 0 ) { ! 883: if ( status & NET80211_IS_REASON ) ! 884: dev->assoc_rc = -E80211_REASON ( status ); ! 885: else ! 886: dev->assoc_rc = -E80211_STATUS ( status ); ! 887: netdev_link_err ( dev->netdev, dev->assoc_rc ); ! 888: } ! 889: } ! 890: ! 891: /** ! 892: * Add channels to 802.11 device ! 893: * ! 894: * @v dev 802.11 device ! 895: * @v start First channel number to add ! 896: * @v len Number of channels to add ! 897: * @v txpower TX power (dBm) to allow on added channels ! 898: * ! 899: * To replace the current list of channels instead of adding to it, ! 900: * set the nr_channels field of the 802.11 device to 0 before calling ! 901: * this function. ! 902: */ ! 903: static void net80211_add_channels ( struct net80211_device *dev, int start, ! 904: int len, int txpower ) ! 905: { ! 906: int i, chan = start; ! 907: ! 908: for ( i = dev->nr_channels; len-- && i < NET80211_MAX_CHANNELS; i++ ) { ! 909: dev->channels[i].channel_nr = chan; ! 910: dev->channels[i].maxpower = txpower; ! 911: dev->channels[i].hw_value = 0; ! 912: ! 913: if ( chan >= 1 && chan <= 14 ) { ! 914: dev->channels[i].band = NET80211_BAND_2GHZ; ! 915: if ( chan == 14 ) ! 916: dev->channels[i].center_freq = 2484; ! 917: else ! 918: dev->channels[i].center_freq = 2407 + 5 * chan; ! 919: chan++; ! 920: } else { ! 921: dev->channels[i].band = NET80211_BAND_5GHZ; ! 922: dev->channels[i].center_freq = 5000 + 5 * chan; ! 923: chan += 4; ! 924: } ! 925: } ! 926: ! 927: dev->nr_channels = i; ! 928: } ! 929: ! 930: /** ! 931: * Filter 802.11 device channels for hardware capabilities ! 932: * ! 933: * @v dev 802.11 device ! 934: * ! 935: * Hardware may support fewer channels than regulatory restrictions ! 936: * allow; this function filters out channels in dev->channels that are ! 937: * not supported by the hardware list in dev->hwinfo. It also copies ! 938: * over the net80211_channel::hw_value and limits maximum TX power ! 939: * appropriately. ! 940: * ! 941: * Channels are matched based on center frequency, ignoring band and ! 942: * channel number. ! 943: * ! 944: * If the driver specifies no supported channels, the effect will be ! 945: * as though all were supported. ! 946: */ ! 947: static void net80211_filter_hw_channels ( struct net80211_device *dev ) ! 948: { ! 949: int delta = 0, i = 0; ! 950: int old_freq = dev->channels[dev->channel].center_freq; ! 951: struct net80211_channel *chan, *hwchan; ! 952: ! 953: if ( ! dev->hw->nr_channels ) ! 954: return; ! 955: ! 956: dev->channel = 0; ! 957: for ( chan = dev->channels; chan < dev->channels + dev->nr_channels; ! 958: chan++, i++ ) { ! 959: int ok = 0; ! 960: for ( hwchan = dev->hw->channels; ! 961: hwchan < dev->hw->channels + dev->hw->nr_channels; ! 962: hwchan++ ) { ! 963: if ( hwchan->center_freq == chan->center_freq ) { ! 964: ok = 1; ! 965: break; ! 966: } ! 967: } ! 968: ! 969: if ( ! ok ) ! 970: delta++; ! 971: else { ! 972: chan->hw_value = hwchan->hw_value; ! 973: if ( hwchan->maxpower != 0 && ! 974: chan->maxpower > hwchan->maxpower ) ! 975: chan->maxpower = hwchan->maxpower; ! 976: if ( old_freq == chan->center_freq ) ! 977: dev->channel = i - delta; ! 978: if ( delta ) ! 979: chan[-delta] = *chan; ! 980: } ! 981: } ! 982: ! 983: dev->nr_channels -= delta; ! 984: ! 985: if ( dev->channels[dev->channel].center_freq != old_freq ) ! 986: dev->op->config ( dev, NET80211_CFG_CHANNEL ); ! 987: } ! 988: ! 989: /** ! 990: * Update 802.11 device state to reflect received capabilities field ! 991: * ! 992: * @v dev 802.11 device ! 993: * @v capab Capabilities field in beacon, probe, or association frame ! 994: * @ret rc Return status code ! 995: */ ! 996: static int net80211_process_capab ( struct net80211_device *dev, ! 997: u16 capab ) ! 998: { ! 999: u16 old_phy = dev->phy_flags; ! 1000: ! 1001: if ( ( capab & ( IEEE80211_CAPAB_MANAGED | IEEE80211_CAPAB_ADHOC ) ) != ! 1002: IEEE80211_CAPAB_MANAGED ) { ! 1003: DBGC ( dev, "802.11 %p cannot handle IBSS network\n", dev ); ! 1004: return -ENOSYS; ! 1005: } ! 1006: ! 1007: dev->phy_flags &= ~( NET80211_PHY_USE_SHORT_PREAMBLE | ! 1008: NET80211_PHY_USE_SHORT_SLOT ); ! 1009: ! 1010: if ( capab & IEEE80211_CAPAB_SHORT_PMBL ) ! 1011: dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE; ! 1012: ! 1013: if ( capab & IEEE80211_CAPAB_SHORT_SLOT ) ! 1014: dev->phy_flags |= NET80211_PHY_USE_SHORT_SLOT; ! 1015: ! 1016: if ( old_phy != dev->phy_flags ) ! 1017: dev->op->config ( dev, NET80211_CFG_PHY_PARAMS ); ! 1018: ! 1019: return 0; ! 1020: } ! 1021: ! 1022: /** ! 1023: * Update 802.11 device state to reflect received information elements ! 1024: * ! 1025: * @v dev 802.11 device ! 1026: * @v ie Pointer to first information element ! 1027: * @v ie_end Pointer to tail of packet I/O buffer ! 1028: * @ret rc Return status code ! 1029: */ ! 1030: static int net80211_process_ie ( struct net80211_device *dev, ! 1031: union ieee80211_ie *ie, void *ie_end ) ! 1032: { ! 1033: u16 old_rate = dev->rates[dev->rate]; ! 1034: u16 old_phy = dev->phy_flags; ! 1035: int have_rates = 0, i; ! 1036: int ds_channel = 0; ! 1037: int changed = 0; ! 1038: int band = dev->channels[dev->channel].band; ! 1039: ! 1040: if ( ! ieee80211_ie_bound ( ie, ie_end ) ) ! 1041: return 0; ! 1042: ! 1043: for ( ; ie; ie = ieee80211_next_ie ( ie, ie_end ) ) { ! 1044: switch ( ie->id ) { ! 1045: case IEEE80211_IE_SSID: ! 1046: if ( ie->len <= 32 ) { ! 1047: memcpy ( dev->essid, ie->ssid, ie->len ); ! 1048: dev->essid[ie->len] = 0; ! 1049: } ! 1050: break; ! 1051: ! 1052: case IEEE80211_IE_RATES: ! 1053: case IEEE80211_IE_EXT_RATES: ! 1054: if ( ! have_rates ) { ! 1055: dev->nr_rates = 0; ! 1056: dev->basic_rates = 0; ! 1057: have_rates = 1; ! 1058: } ! 1059: for ( i = 0; i < ie->len && ! 1060: dev->nr_rates < NET80211_MAX_RATES; i++ ) { ! 1061: u8 rid = ie->rates[i]; ! 1062: u16 rate = ( rid & 0x7f ) * 5; ! 1063: ! 1064: if ( rid & 0x80 ) ! 1065: dev->basic_rates |= ! 1066: ( 1 << dev->nr_rates ); ! 1067: ! 1068: dev->rates[dev->nr_rates++] = rate; ! 1069: } ! 1070: ! 1071: break; ! 1072: ! 1073: case IEEE80211_IE_DS_PARAM: ! 1074: if ( dev->channel < dev->nr_channels && ds_channel == ! 1075: dev->channels[dev->channel].channel_nr ) ! 1076: break; ! 1077: ds_channel = ie->ds_param.current_channel; ! 1078: net80211_change_channel ( dev, ds_channel ); ! 1079: break; ! 1080: ! 1081: case IEEE80211_IE_COUNTRY: ! 1082: dev->nr_channels = 0; ! 1083: ! 1084: DBGC ( dev, "802.11 %p setting country regulations " ! 1085: "for %c%c\n", dev, ie->country.name[0], ! 1086: ie->country.name[1] ); ! 1087: for ( i = 0; i < ( ie->len - 3 ) / 3; i++ ) { ! 1088: union ieee80211_ie_country_triplet *t = ! 1089: &ie->country.triplet[i]; ! 1090: if ( t->first > 200 ) { ! 1091: DBGC ( dev, "802.11 %p ignoring regulatory " ! 1092: "extension information\n", dev ); ! 1093: } else { ! 1094: net80211_add_channels ( dev, ! 1095: t->band.first_channel, ! 1096: t->band.nr_channels, ! 1097: t->band.max_txpower ); ! 1098: } ! 1099: } ! 1100: net80211_filter_hw_channels ( dev ); ! 1101: break; ! 1102: ! 1103: case IEEE80211_IE_ERP_INFO: ! 1104: dev->phy_flags &= ~( NET80211_PHY_USE_PROTECTION | ! 1105: NET80211_PHY_USE_SHORT_PREAMBLE ); ! 1106: if ( ie->erp_info & IEEE80211_ERP_USE_PROTECTION ) ! 1107: dev->phy_flags |= NET80211_PHY_USE_PROTECTION; ! 1108: if ( ! ( ie->erp_info & IEEE80211_ERP_BARKER_LONG ) ) ! 1109: dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE; ! 1110: break; ! 1111: } ! 1112: } ! 1113: ! 1114: if ( have_rates ) { ! 1115: /* Allow only those rates that are also supported by ! 1116: the hardware. */ ! 1117: int delta = 0, j; ! 1118: ! 1119: dev->rate = 0; ! 1120: for ( i = 0; i < dev->nr_rates; i++ ) { ! 1121: int ok = 0; ! 1122: for ( j = 0; j < dev->hw->nr_rates[band]; j++ ) { ! 1123: if ( dev->hw->rates[band][j] == dev->rates[i] ){ ! 1124: ok = 1; ! 1125: break; ! 1126: } ! 1127: } ! 1128: ! 1129: if ( ! ok ) ! 1130: delta++; ! 1131: else { ! 1132: dev->rates[i - delta] = dev->rates[i]; ! 1133: if ( old_rate == dev->rates[i] ) ! 1134: dev->rate = i - delta; ! 1135: } ! 1136: } ! 1137: ! 1138: dev->nr_rates -= delta; ! 1139: ! 1140: /* Sort available rates - sorted subclumps tend to already ! 1141: exist, so insertion sort works well. */ ! 1142: for ( i = 1; i < dev->nr_rates; i++ ) { ! 1143: u16 rate = dev->rates[i]; ! 1144: u32 tmp, br, mask; ! 1145: ! 1146: for ( j = i - 1; j >= 0 && dev->rates[j] >= rate; j-- ) ! 1147: dev->rates[j + 1] = dev->rates[j]; ! 1148: dev->rates[j + 1] = rate; ! 1149: ! 1150: /* Adjust basic_rates to match by rotating the ! 1151: bits from bit j+1 to bit i left one position. */ ! 1152: mask = ( ( 1 << i ) - 1 ) & ~( ( 1 << ( j + 1 ) ) - 1 ); ! 1153: br = dev->basic_rates; ! 1154: tmp = br & ( 1 << i ); ! 1155: br = ( br & ~( mask | tmp ) ) | ( ( br & mask ) << 1 ); ! 1156: br |= ( tmp >> ( i - j - 1 ) ); ! 1157: dev->basic_rates = br; ! 1158: } ! 1159: ! 1160: net80211_set_rtscts_rate ( dev ); ! 1161: ! 1162: if ( dev->rates[dev->rate] != old_rate ) ! 1163: changed |= NET80211_CFG_RATE; ! 1164: } ! 1165: ! 1166: if ( dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE ) ! 1167: dev->phy_flags &= ~NET80211_PHY_USE_SHORT_PREAMBLE; ! 1168: if ( dev->hw->flags & NET80211_HW_NO_SHORT_SLOT ) ! 1169: dev->phy_flags &= ~NET80211_PHY_USE_SHORT_SLOT; ! 1170: ! 1171: if ( old_phy != dev->phy_flags ) ! 1172: changed |= NET80211_CFG_PHY_PARAMS; ! 1173: ! 1174: if ( changed ) ! 1175: dev->op->config ( dev, changed ); ! 1176: ! 1177: return 0; ! 1178: } ! 1179: ! 1180: /** ! 1181: * Create information elements for outgoing probe or association packet ! 1182: * ! 1183: * @v dev 802.11 device ! 1184: * @v ie Pointer to start of information element area ! 1185: * @ret next_ie Pointer to first byte after added information elements ! 1186: */ ! 1187: static union ieee80211_ie * ! 1188: net80211_marshal_request_info ( struct net80211_device *dev, ! 1189: union ieee80211_ie *ie ) ! 1190: { ! 1191: int i; ! 1192: ! 1193: ie->id = IEEE80211_IE_SSID; ! 1194: ie->len = strlen ( dev->essid ); ! 1195: memcpy ( ie->ssid, dev->essid, ie->len ); ! 1196: ! 1197: ie = ieee80211_next_ie ( ie, NULL ); ! 1198: ! 1199: ie->id = IEEE80211_IE_RATES; ! 1200: ie->len = dev->nr_rates; ! 1201: if ( ie->len > 8 ) ! 1202: ie->len = 8; ! 1203: ! 1204: for ( i = 0; i < ie->len; i++ ) { ! 1205: ie->rates[i] = dev->rates[i] / 5; ! 1206: if ( dev->basic_rates & ( 1 << i ) ) ! 1207: ie->rates[i] |= 0x80; ! 1208: } ! 1209: ! 1210: ie = ieee80211_next_ie ( ie, NULL ); ! 1211: ! 1212: if ( dev->rsn_ie && dev->rsn_ie->id == IEEE80211_IE_RSN ) { ! 1213: memcpy ( ie, dev->rsn_ie, dev->rsn_ie->len + 2 ); ! 1214: ie = ieee80211_next_ie ( ie, NULL ); ! 1215: } ! 1216: ! 1217: if ( dev->nr_rates > 8 ) { ! 1218: /* 802.11 requires we use an Extended Basic Rates IE ! 1219: for the rates beyond the eighth. */ ! 1220: ! 1221: ie->id = IEEE80211_IE_EXT_RATES; ! 1222: ie->len = dev->nr_rates - 8; ! 1223: ! 1224: for ( ; i < dev->nr_rates; i++ ) { ! 1225: ie->rates[i - 8] = dev->rates[i] / 5; ! 1226: if ( dev->basic_rates & ( 1 << i ) ) ! 1227: ie->rates[i - 8] |= 0x80; ! 1228: } ! 1229: ! 1230: ie = ieee80211_next_ie ( ie, NULL ); ! 1231: } ! 1232: ! 1233: if ( dev->rsn_ie && dev->rsn_ie->id == IEEE80211_IE_VENDOR ) { ! 1234: memcpy ( ie, dev->rsn_ie, dev->rsn_ie->len + 2 ); ! 1235: ie = ieee80211_next_ie ( ie, NULL ); ! 1236: } ! 1237: ! 1238: return ie; ! 1239: } ! 1240: ! 1241: /** Seconds to wait after finding a network, to possibly find better APs for it ! 1242: * ! 1243: * This is used when a specific SSID to scan for is specified. ! 1244: */ ! 1245: #define NET80211_PROBE_GATHER 1 ! 1246: ! 1247: /** Seconds to wait after finding a network, to possibly find other networks ! 1248: * ! 1249: * This is used when an empty SSID is specified, to scan for all ! 1250: * networks. ! 1251: */ ! 1252: #define NET80211_PROBE_GATHER_ALL 2 ! 1253: ! 1254: /** Seconds to allow a probe to take if no network has been found */ ! 1255: #define NET80211_PROBE_TIMEOUT 6 ! 1256: ! 1257: /** ! 1258: * Begin probe of 802.11 networks ! 1259: * ! 1260: * @v dev 802.11 device ! 1261: * @v essid SSID to probe for, or "" to accept any (may not be NULL) ! 1262: * @v active Whether to use active scanning ! 1263: * @ret ctx Probe context ! 1264: * ! 1265: * Active scanning may only be used on channels 1-11 in the 2.4GHz ! 1266: * band, due to iPXE's lack of a complete regulatory database. If ! 1267: * active scanning is used, probe packets will be sent on each ! 1268: * channel; this can allow association with hidden-SSID networks if ! 1269: * the SSID is properly specified. ! 1270: * ! 1271: * A @c NULL return indicates an out-of-memory condition. ! 1272: * ! 1273: * The returned context must be periodically passed to ! 1274: * net80211_probe_step() until that function returns zero. ! 1275: */ ! 1276: struct net80211_probe_ctx * net80211_probe_start ( struct net80211_device *dev, ! 1277: const char *essid, ! 1278: int active ) ! 1279: { ! 1280: struct net80211_probe_ctx *ctx = zalloc ( sizeof ( *ctx ) ); ! 1281: ! 1282: if ( ! ctx ) ! 1283: return NULL; ! 1284: ! 1285: assert ( netdev_is_open ( dev->netdev ) ); ! 1286: ! 1287: ctx->dev = dev; ! 1288: ctx->old_keep_mgmt = net80211_keep_mgmt ( dev, 1 ); ! 1289: ctx->essid = essid; ! 1290: if ( dev->essid != ctx->essid ) ! 1291: strcpy ( dev->essid, ctx->essid ); ! 1292: ! 1293: if ( active ) { ! 1294: struct ieee80211_probe_req *probe_req; ! 1295: union ieee80211_ie *ie; ! 1296: ! 1297: ctx->probe = alloc_iob ( 128 ); ! 1298: iob_reserve ( ctx->probe, IEEE80211_TYP_FRAME_HEADER_LEN ); ! 1299: probe_req = ctx->probe->data; ! 1300: ! 1301: ie = net80211_marshal_request_info ( dev, ! 1302: probe_req->info_element ); ! 1303: ! 1304: iob_put ( ctx->probe, ( void * ) ie - ctx->probe->data ); ! 1305: } ! 1306: ! 1307: ctx->ticks_start = currticks(); ! 1308: ctx->ticks_beacon = 0; ! 1309: ctx->ticks_channel = currticks(); ! 1310: ctx->hop_time = ticks_per_sec() / ( active ? 2 : 6 ); ! 1311: ! 1312: /* ! 1313: * Channels on 2.4GHz overlap, and the most commonly used ! 1314: * are 1, 6, and 11. We'll get a result faster if we check ! 1315: * every 5 channels, but in order to hit all of them the ! 1316: * number of channels must be relatively prime to 5. If it's ! 1317: * not, tweak the hop. ! 1318: */ ! 1319: ctx->hop_step = 5; ! 1320: while ( dev->nr_channels % ctx->hop_step == 0 && ctx->hop_step > 1 ) ! 1321: ctx->hop_step--; ! 1322: ! 1323: ctx->beacons = malloc ( sizeof ( *ctx->beacons ) ); ! 1324: INIT_LIST_HEAD ( ctx->beacons ); ! 1325: ! 1326: dev->channel = 0; ! 1327: dev->op->config ( dev, NET80211_CFG_CHANNEL ); ! 1328: ! 1329: return ctx; ! 1330: } ! 1331: ! 1332: /** ! 1333: * Continue probe of 802.11 networks ! 1334: * ! 1335: * @v ctx Probe context returned by net80211_probe_start() ! 1336: * @ret rc Probe status ! 1337: * ! 1338: * The return code will be 0 if the probe is still going on (and this ! 1339: * function should be called again), a positive number if the probe ! 1340: * completed successfully, or a negative error code if the probe ! 1341: * failed for that reason. ! 1342: * ! 1343: * Whether the probe succeeded or failed, you must call ! 1344: * net80211_probe_finish_all() or net80211_probe_finish_best() ! 1345: * (depending on whether you want information on all networks or just ! 1346: * the best-signal one) in order to release the probe context. A ! 1347: * failed probe may still have acquired some valid data. ! 1348: */ ! 1349: int net80211_probe_step ( struct net80211_probe_ctx *ctx ) ! 1350: { ! 1351: struct net80211_device *dev = ctx->dev; ! 1352: u32 start_timeout = NET80211_PROBE_TIMEOUT * ticks_per_sec(); ! 1353: u32 gather_timeout = ticks_per_sec(); ! 1354: u32 now = currticks(); ! 1355: struct io_buffer *iob; ! 1356: int signal; ! 1357: int rc; ! 1358: char ssid[IEEE80211_MAX_SSID_LEN + 1]; ! 1359: ! 1360: gather_timeout *= ( ctx->essid[0] ? NET80211_PROBE_GATHER : ! 1361: NET80211_PROBE_GATHER_ALL ); ! 1362: ! 1363: /* Time out if necessary */ ! 1364: if ( now >= ctx->ticks_start + start_timeout ) ! 1365: return list_empty ( ctx->beacons ) ? -ETIMEDOUT : +1; ! 1366: ! 1367: if ( ctx->ticks_beacon > 0 && now >= ctx->ticks_start + gather_timeout ) ! 1368: return +1; ! 1369: ! 1370: /* Change channels if necessary */ ! 1371: if ( now >= ctx->ticks_channel + ctx->hop_time ) { ! 1372: dev->channel = ( dev->channel + ctx->hop_step ) ! 1373: % dev->nr_channels; ! 1374: dev->op->config ( dev, NET80211_CFG_CHANNEL ); ! 1375: udelay ( dev->hw->channel_change_time ); ! 1376: ! 1377: ctx->ticks_channel = now; ! 1378: ! 1379: if ( ctx->probe ) { ! 1380: struct io_buffer *siob = ctx->probe; /* to send */ ! 1381: ! 1382: /* make a copy for future use */ ! 1383: iob = alloc_iob ( siob->tail - siob->head ); ! 1384: iob_reserve ( iob, iob_headroom ( siob ) ); ! 1385: memcpy ( iob_put ( iob, iob_len ( siob ) ), ! 1386: siob->data, iob_len ( siob ) ); ! 1387: ! 1388: ctx->probe = iob; ! 1389: rc = net80211_tx_mgmt ( dev, IEEE80211_STYPE_PROBE_REQ, ! 1390: net80211_ll_broadcast, ! 1391: iob_disown ( siob ) ); ! 1392: if ( rc ) { ! 1393: DBGC ( dev, "802.11 %p send probe failed: " ! 1394: "%s\n", dev, strerror ( rc ) ); ! 1395: return rc; ! 1396: } ! 1397: } ! 1398: } ! 1399: ! 1400: /* Check for new management packets */ ! 1401: while ( ( iob = net80211_mgmt_dequeue ( dev, &signal ) ) != NULL ) { ! 1402: struct ieee80211_frame *hdr; ! 1403: struct ieee80211_beacon *beacon; ! 1404: union ieee80211_ie *ie; ! 1405: struct net80211_wlan *wlan; ! 1406: u16 type; ! 1407: ! 1408: hdr = iob->data; ! 1409: type = hdr->fc & IEEE80211_FC_SUBTYPE; ! 1410: beacon = ( struct ieee80211_beacon * ) hdr->data; ! 1411: ! 1412: if ( type != IEEE80211_STYPE_BEACON && ! 1413: type != IEEE80211_STYPE_PROBE_RESP ) { ! 1414: DBGC2 ( dev, "802.11 %p probe: non-beacon\n", dev ); ! 1415: goto drop; ! 1416: } ! 1417: ! 1418: if ( ( void * ) beacon->info_element >= iob->tail ) { ! 1419: DBGC ( dev, "802.11 %p probe: beacon with no IEs\n", ! 1420: dev ); ! 1421: goto drop; ! 1422: } ! 1423: ! 1424: ie = beacon->info_element; ! 1425: ! 1426: if ( ! ieee80211_ie_bound ( ie, iob->tail ) ) ! 1427: ie = NULL; ! 1428: ! 1429: while ( ie && ie->id != IEEE80211_IE_SSID ) ! 1430: ie = ieee80211_next_ie ( ie, iob->tail ); ! 1431: ! 1432: if ( ! ie ) { ! 1433: DBGC ( dev, "802.11 %p probe: beacon with no SSID\n", ! 1434: dev ); ! 1435: goto drop; ! 1436: } ! 1437: ! 1438: memcpy ( ssid, ie->ssid, ie->len ); ! 1439: ssid[ie->len] = 0; ! 1440: ! 1441: if ( ctx->essid[0] && strcmp ( ctx->essid, ssid ) != 0 ) { ! 1442: DBGC2 ( dev, "802.11 %p probe: beacon with wrong SSID " ! 1443: "(%s)\n", dev, ssid ); ! 1444: goto drop; ! 1445: } ! 1446: ! 1447: /* See if we've got an entry for this network */ ! 1448: list_for_each_entry ( wlan, ctx->beacons, list ) { ! 1449: if ( strcmp ( wlan->essid, ssid ) != 0 ) ! 1450: continue; ! 1451: ! 1452: if ( signal < wlan->signal ) { ! 1453: DBGC2 ( dev, "802.11 %p probe: beacon for %s " ! 1454: "(%s) with weaker signal %d\n", dev, ! 1455: ssid, eth_ntoa ( hdr->addr3 ), signal ); ! 1456: goto drop; ! 1457: } ! 1458: ! 1459: goto fill; ! 1460: } ! 1461: ! 1462: /* No entry yet - make one */ ! 1463: wlan = zalloc ( sizeof ( *wlan ) ); ! 1464: strcpy ( wlan->essid, ssid ); ! 1465: list_add_tail ( &wlan->list, ctx->beacons ); ! 1466: ! 1467: /* Whether we're using an old entry or a new one, fill ! 1468: it with new data. */ ! 1469: fill: ! 1470: memcpy ( wlan->bssid, hdr->addr3, ETH_ALEN ); ! 1471: wlan->signal = signal; ! 1472: wlan->channel = dev->channels[dev->channel].channel_nr; ! 1473: ! 1474: /* Copy this I/O buffer into a new wlan->beacon; the ! 1475: * iob we've got probably came from the device driver ! 1476: * and may have the full 2.4k allocation, which we ! 1477: * don't want to keep around wasting memory. ! 1478: */ ! 1479: free_iob ( wlan->beacon ); ! 1480: wlan->beacon = alloc_iob ( iob_len ( iob ) ); ! 1481: memcpy ( iob_put ( wlan->beacon, iob_len ( iob ) ), ! 1482: iob->data, iob_len ( iob ) ); ! 1483: ! 1484: if ( ( rc = sec80211_detect ( wlan->beacon, &wlan->handshaking, ! 1485: &wlan->crypto ) ) == -ENOTSUP ) { ! 1486: struct ieee80211_beacon *beacon = ! 1487: ( struct ieee80211_beacon * ) hdr->data; ! 1488: ! 1489: if ( beacon->capability & IEEE80211_CAPAB_PRIVACY ) { ! 1490: DBG ( "802.11 %p probe: secured network %s but " ! 1491: "encryption support not compiled in\n", ! 1492: dev, wlan->essid ); ! 1493: wlan->handshaking = NET80211_SECPROT_UNKNOWN; ! 1494: wlan->crypto = NET80211_CRYPT_UNKNOWN; ! 1495: } else { ! 1496: wlan->handshaking = NET80211_SECPROT_NONE; ! 1497: wlan->crypto = NET80211_CRYPT_NONE; ! 1498: } ! 1499: } else if ( rc != 0 ) { ! 1500: DBGC ( dev, "802.11 %p probe warning: network " ! 1501: "%s with unidentifiable security " ! 1502: "settings: %s\n", dev, wlan->essid, ! 1503: strerror ( rc ) ); ! 1504: } ! 1505: ! 1506: ctx->ticks_beacon = now; ! 1507: ! 1508: DBGC2 ( dev, "802.11 %p probe: good beacon for %s (%s)\n", ! 1509: dev, wlan->essid, eth_ntoa ( wlan->bssid ) ); ! 1510: ! 1511: drop: ! 1512: free_iob ( iob ); ! 1513: } ! 1514: ! 1515: return 0; ! 1516: } ! 1517: ! 1518: ! 1519: /** ! 1520: * Finish probe of 802.11 networks, returning best-signal network found ! 1521: * ! 1522: * @v ctx Probe context ! 1523: * @ret wlan Best-signal network found, or @c NULL if none were found ! 1524: * ! 1525: * If net80211_probe_start() was called with a particular SSID ! 1526: * parameter as filter, only a network with that SSID (matching ! 1527: * case-sensitively) can be returned from this function. ! 1528: */ ! 1529: struct net80211_wlan * ! 1530: net80211_probe_finish_best ( struct net80211_probe_ctx *ctx ) ! 1531: { ! 1532: struct net80211_wlan *best = NULL, *wlan; ! 1533: ! 1534: if ( ! ctx ) ! 1535: return NULL; ! 1536: ! 1537: list_for_each_entry ( wlan, ctx->beacons, list ) { ! 1538: if ( ! best || best->signal < wlan->signal ) ! 1539: best = wlan; ! 1540: } ! 1541: ! 1542: if ( best ) ! 1543: list_del ( &best->list ); ! 1544: else ! 1545: DBGC ( ctx->dev, "802.11 %p probe: found nothing for '%s'\n", ! 1546: ctx->dev, ctx->essid ); ! 1547: ! 1548: net80211_free_wlanlist ( ctx->beacons ); ! 1549: ! 1550: net80211_keep_mgmt ( ctx->dev, ctx->old_keep_mgmt ); ! 1551: ! 1552: if ( ctx->probe ) ! 1553: free_iob ( ctx->probe ); ! 1554: ! 1555: free ( ctx ); ! 1556: ! 1557: return best; ! 1558: } ! 1559: ! 1560: ! 1561: /** ! 1562: * Finish probe of 802.11 networks, returning all networks found ! 1563: * ! 1564: * @v ctx Probe context ! 1565: * @ret list List of net80211_wlan detailing networks found ! 1566: * ! 1567: * If net80211_probe_start() was called with a particular SSID ! 1568: * parameter as filter, this will always return either an empty or a ! 1569: * one-element list. ! 1570: */ ! 1571: struct list_head *net80211_probe_finish_all ( struct net80211_probe_ctx *ctx ) ! 1572: { ! 1573: struct list_head *beacons = ctx->beacons; ! 1574: ! 1575: if ( ! ctx ) ! 1576: return NULL; ! 1577: ! 1578: net80211_keep_mgmt ( ctx->dev, ctx->old_keep_mgmt ); ! 1579: ! 1580: if ( ctx->probe ) ! 1581: free_iob ( ctx->probe ); ! 1582: ! 1583: free ( ctx ); ! 1584: ! 1585: return beacons; ! 1586: } ! 1587: ! 1588: ! 1589: /** ! 1590: * Free WLAN structure ! 1591: * ! 1592: * @v wlan WLAN structure to free ! 1593: */ ! 1594: void net80211_free_wlan ( struct net80211_wlan *wlan ) ! 1595: { ! 1596: if ( wlan ) { ! 1597: free_iob ( wlan->beacon ); ! 1598: free ( wlan ); ! 1599: } ! 1600: } ! 1601: ! 1602: ! 1603: /** ! 1604: * Free list of WLAN structures ! 1605: * ! 1606: * @v list List of WLAN structures to free ! 1607: */ ! 1608: void net80211_free_wlanlist ( struct list_head *list ) ! 1609: { ! 1610: struct net80211_wlan *wlan, *tmp; ! 1611: ! 1612: if ( ! list ) ! 1613: return; ! 1614: ! 1615: list_for_each_entry_safe ( wlan, tmp, list, list ) { ! 1616: list_del ( &wlan->list ); ! 1617: net80211_free_wlan ( wlan ); ! 1618: } ! 1619: ! 1620: free ( list ); ! 1621: } ! 1622: ! 1623: ! 1624: /** Number of ticks to wait for replies to association management frames */ ! 1625: #define ASSOC_TIMEOUT TICKS_PER_SEC ! 1626: ! 1627: /** Number of times to try sending a particular association management frame */ ! 1628: #define ASSOC_RETRIES 2 ! 1629: ! 1630: /** ! 1631: * Step 802.11 association process ! 1632: * ! 1633: * @v proc Association process ! 1634: */ ! 1635: static void net80211_step_associate ( struct process *proc ) ! 1636: { ! 1637: struct net80211_device *dev = ! 1638: container_of ( proc, struct net80211_device, proc_assoc ); ! 1639: int rc = 0; ! 1640: int status = dev->state & NET80211_STATUS_MASK; ! 1641: ! 1642: /* ! 1643: * We use a sort of state machine implemented using bits in ! 1644: * the dev->state variable. At each call, we take the ! 1645: * logically first step that has not yet succeeded; either it ! 1646: * has not been tried yet, it's being retried, or it failed. ! 1647: * If it failed, we return an error indication; otherwise we ! 1648: * perform the step. If it succeeds, RX handling code will set ! 1649: * the appropriate status bit for us. ! 1650: * ! 1651: * Probe works a bit differently, since we have to step it ! 1652: * on every call instead of waiting for a packet to arrive ! 1653: * that will set the completion bit for us. ! 1654: */ ! 1655: ! 1656: /* If we're waiting for a reply, check for timeout condition */ ! 1657: if ( dev->state & NET80211_WAITING ) { ! 1658: /* Sanity check */ ! 1659: if ( ! dev->associating ) ! 1660: return; ! 1661: ! 1662: if ( currticks() - dev->ctx.assoc->last_packet > ASSOC_TIMEOUT ) { ! 1663: /* Timed out - fail if too many retries, or retry */ ! 1664: dev->ctx.assoc->times_tried++; ! 1665: if ( ++dev->ctx.assoc->times_tried > ASSOC_RETRIES ) { ! 1666: rc = -ETIMEDOUT; ! 1667: goto fail; ! 1668: } ! 1669: } else { ! 1670: /* Didn't time out - let it keep going */ ! 1671: return; ! 1672: } ! 1673: } else { ! 1674: if ( dev->state & NET80211_PROBED ) ! 1675: dev->ctx.assoc->times_tried = 0; ! 1676: } ! 1677: ! 1678: if ( ! ( dev->state & NET80211_PROBED ) ) { ! 1679: /* state: probe */ ! 1680: ! 1681: if ( ! dev->ctx.probe ) { ! 1682: /* start probe */ ! 1683: int active = fetch_intz_setting ( NULL, ! 1684: &net80211_active_setting ); ! 1685: int band = dev->hw->bands; ! 1686: ! 1687: if ( active ) ! 1688: band &= ~NET80211_BAND_BIT_5GHZ; ! 1689: ! 1690: rc = net80211_prepare_probe ( dev, band, active ); ! 1691: if ( rc ) ! 1692: goto fail; ! 1693: ! 1694: dev->ctx.probe = net80211_probe_start ( dev, dev->essid, ! 1695: active ); ! 1696: if ( ! dev->ctx.probe ) { ! 1697: dev->assoc_rc = -ENOMEM; ! 1698: goto fail; ! 1699: } ! 1700: } ! 1701: ! 1702: rc = net80211_probe_step ( dev->ctx.probe ); ! 1703: if ( ! rc ) { ! 1704: return; /* still going */ ! 1705: } ! 1706: ! 1707: dev->associating = net80211_probe_finish_best ( dev->ctx.probe ); ! 1708: dev->ctx.probe = NULL; ! 1709: if ( ! dev->associating ) { ! 1710: if ( rc > 0 ) /* "successful" probe found nothing */ ! 1711: rc = -ETIMEDOUT; ! 1712: goto fail; ! 1713: } ! 1714: ! 1715: /* If we probed using a broadcast SSID, record that ! 1716: fact for the settings applicator before we clobber ! 1717: it with the specific SSID we've chosen. */ ! 1718: if ( ! dev->essid[0] ) ! 1719: dev->state |= NET80211_AUTO_SSID; ! 1720: ! 1721: DBGC ( dev, "802.11 %p found network %s (%s)\n", dev, ! 1722: dev->associating->essid, ! 1723: eth_ntoa ( dev->associating->bssid ) ); ! 1724: ! 1725: dev->ctx.assoc = zalloc ( sizeof ( *dev->ctx.assoc ) ); ! 1726: if ( ! dev->ctx.assoc ) { ! 1727: rc = -ENOMEM; ! 1728: goto fail; ! 1729: } ! 1730: ! 1731: dev->state |= NET80211_PROBED; ! 1732: dev->ctx.assoc->method = IEEE80211_AUTH_OPEN_SYSTEM; ! 1733: ! 1734: return; ! 1735: } ! 1736: ! 1737: /* Record time of sending the packet we're about to send, for timeout */ ! 1738: dev->ctx.assoc->last_packet = currticks(); ! 1739: ! 1740: if ( ! ( dev->state & NET80211_AUTHENTICATED ) ) { ! 1741: /* state: prepare and authenticate */ ! 1742: ! 1743: if ( status != IEEE80211_STATUS_SUCCESS ) { ! 1744: /* we tried authenticating already, but failed */ ! 1745: int method = dev->ctx.assoc->method; ! 1746: ! 1747: if ( method == IEEE80211_AUTH_OPEN_SYSTEM && ! 1748: ( status == IEEE80211_STATUS_AUTH_CHALL_INVALID || ! 1749: status == IEEE80211_STATUS_AUTH_ALGO_UNSUPP ) ) { ! 1750: /* Maybe this network uses Shared Key? */ ! 1751: dev->ctx.assoc->method = ! 1752: IEEE80211_AUTH_SHARED_KEY; ! 1753: } else { ! 1754: goto fail; ! 1755: } ! 1756: } ! 1757: ! 1758: DBGC ( dev, "802.11 %p authenticating with method %d\n", dev, ! 1759: dev->ctx.assoc->method ); ! 1760: ! 1761: rc = net80211_prepare_assoc ( dev, dev->associating ); ! 1762: if ( rc ) ! 1763: goto fail; ! 1764: ! 1765: rc = net80211_send_auth ( dev, dev->associating, ! 1766: dev->ctx.assoc->method ); ! 1767: if ( rc ) ! 1768: goto fail; ! 1769: ! 1770: return; ! 1771: } ! 1772: ! 1773: if ( ! ( dev->state & NET80211_ASSOCIATED ) ) { ! 1774: /* state: associate */ ! 1775: ! 1776: if ( status != IEEE80211_STATUS_SUCCESS ) ! 1777: goto fail; ! 1778: ! 1779: DBGC ( dev, "802.11 %p associating\n", dev ); ! 1780: ! 1781: if ( dev->handshaker && dev->handshaker->start && ! 1782: ! dev->handshaker->started ) { ! 1783: rc = dev->handshaker->start ( dev ); ! 1784: if ( rc < 0 ) ! 1785: goto fail; ! 1786: dev->handshaker->started = 1; ! 1787: } ! 1788: ! 1789: rc = net80211_send_assoc ( dev, dev->associating ); ! 1790: if ( rc ) ! 1791: goto fail; ! 1792: ! 1793: return; ! 1794: } ! 1795: ! 1796: if ( ! ( dev->state & NET80211_CRYPTO_SYNCED ) ) { ! 1797: /* state: crypto sync */ ! 1798: DBGC ( dev, "802.11 %p security handshaking\n", dev ); ! 1799: ! 1800: if ( ! dev->handshaker || ! dev->handshaker->step ) { ! 1801: dev->state |= NET80211_CRYPTO_SYNCED; ! 1802: return; ! 1803: } ! 1804: ! 1805: rc = dev->handshaker->step ( dev ); ! 1806: ! 1807: if ( rc < 0 ) { ! 1808: /* Only record the returned error if we're ! 1809: still marked as associated, because an ! 1810: asynchronous error will have already been ! 1811: reported to net80211_deauthenticate() and ! 1812: assoc_rc thereby set. */ ! 1813: if ( dev->state & NET80211_ASSOCIATED ) ! 1814: dev->assoc_rc = rc; ! 1815: rc = 0; ! 1816: goto fail; ! 1817: } ! 1818: ! 1819: if ( rc > 0 ) { ! 1820: dev->assoc_rc = 0; ! 1821: dev->state |= NET80211_CRYPTO_SYNCED; ! 1822: } ! 1823: return; ! 1824: } ! 1825: ! 1826: /* state: done! */ ! 1827: netdev_link_up ( dev->netdev ); ! 1828: dev->assoc_rc = 0; ! 1829: dev->state &= ~NET80211_WORKING; ! 1830: ! 1831: free ( dev->ctx.assoc ); ! 1832: dev->ctx.assoc = NULL; ! 1833: ! 1834: net80211_free_wlan ( dev->associating ); ! 1835: dev->associating = NULL; ! 1836: ! 1837: dev->rctl = rc80211_init ( dev ); ! 1838: ! 1839: process_del ( proc ); ! 1840: ! 1841: DBGC ( dev, "802.11 %p associated with %s (%s)\n", dev, ! 1842: dev->essid, eth_ntoa ( dev->bssid ) ); ! 1843: ! 1844: return; ! 1845: ! 1846: fail: ! 1847: dev->state &= ~( NET80211_WORKING | NET80211_WAITING ); ! 1848: if ( rc ) ! 1849: dev->assoc_rc = rc; ! 1850: ! 1851: netdev_link_err ( dev->netdev, dev->assoc_rc ); ! 1852: ! 1853: /* We never reach here from the middle of a probe, so we don't ! 1854: need to worry about freeing dev->ctx.probe. */ ! 1855: ! 1856: if ( dev->state & NET80211_PROBED ) { ! 1857: free ( dev->ctx.assoc ); ! 1858: dev->ctx.assoc = NULL; ! 1859: } ! 1860: ! 1861: net80211_free_wlan ( dev->associating ); ! 1862: dev->associating = NULL; ! 1863: ! 1864: process_del ( proc ); ! 1865: ! 1866: DBGC ( dev, "802.11 %p association failed (state=%04x): " ! 1867: "%s\n", dev, dev->state, strerror ( dev->assoc_rc ) ); ! 1868: ! 1869: /* Try it again: */ ! 1870: net80211_autoassociate ( dev ); ! 1871: } ! 1872: ! 1873: /** ! 1874: * Check for 802.11 SSID or key updates ! 1875: * ! 1876: * This acts as a settings applicator; if the user changes netX/ssid, ! 1877: * and netX is currently open, the association task will be invoked ! 1878: * again. If the user changes the encryption key, the current security ! 1879: * handshaker will be asked to update its state to match; if that is ! 1880: * impossible without reassociation, we reassociate. ! 1881: */ ! 1882: static int net80211_check_settings_update ( void ) ! 1883: { ! 1884: struct net80211_device *dev; ! 1885: char ssid[IEEE80211_MAX_SSID_LEN + 1]; ! 1886: int key_reassoc; ! 1887: ! 1888: list_for_each_entry ( dev, &net80211_devices, list ) { ! 1889: if ( ! netdev_is_open ( dev->netdev ) ) ! 1890: continue; ! 1891: ! 1892: key_reassoc = 0; ! 1893: if ( dev->handshaker && dev->handshaker->change_key && ! 1894: dev->handshaker->change_key ( dev ) < 0 ) ! 1895: key_reassoc = 1; ! 1896: ! 1897: fetch_string_setting ( netdev_settings ( dev->netdev ), ! 1898: &net80211_ssid_setting, ssid, ! 1899: IEEE80211_MAX_SSID_LEN + 1 ); ! 1900: ! 1901: if ( key_reassoc || ! 1902: ( ! ( ! ssid[0] && ( dev->state & NET80211_AUTO_SSID ) ) && ! 1903: strcmp ( ssid, dev->essid ) != 0 ) ) { ! 1904: DBGC ( dev, "802.11 %p updating association: " ! 1905: "%s -> %s\n", dev, dev->essid, ssid ); ! 1906: net80211_autoassociate ( dev ); ! 1907: } ! 1908: } ! 1909: ! 1910: return 0; ! 1911: } ! 1912: ! 1913: /** ! 1914: * Start 802.11 association process ! 1915: * ! 1916: * @v dev 802.11 device ! 1917: * ! 1918: * If the association process is running, it will be restarted. ! 1919: */ ! 1920: void net80211_autoassociate ( struct net80211_device *dev ) ! 1921: { ! 1922: if ( ! ( dev->state & NET80211_WORKING ) ) { ! 1923: DBGC2 ( dev, "802.11 %p spawning association process\n", dev ); ! 1924: process_add ( &dev->proc_assoc ); ! 1925: } else { ! 1926: DBGC2 ( dev, "802.11 %p restarting association\n", dev ); ! 1927: } ! 1928: ! 1929: /* Clean up everything an earlier association process might ! 1930: have been in the middle of using */ ! 1931: if ( dev->associating ) ! 1932: net80211_free_wlan ( dev->associating ); ! 1933: ! 1934: if ( ! ( dev->state & NET80211_PROBED ) ) ! 1935: net80211_free_wlan ( ! 1936: net80211_probe_finish_best ( dev->ctx.probe ) ); ! 1937: else ! 1938: free ( dev->ctx.assoc ); ! 1939: ! 1940: /* Reset to a clean state */ ! 1941: fetch_string_setting ( netdev_settings ( dev->netdev ), ! 1942: &net80211_ssid_setting, dev->essid, ! 1943: IEEE80211_MAX_SSID_LEN + 1 ); ! 1944: dev->ctx.probe = NULL; ! 1945: dev->associating = NULL; ! 1946: dev->assoc_rc = 0; ! 1947: net80211_set_state ( dev, NET80211_PROBED, NET80211_WORKING, 0 ); ! 1948: } ! 1949: ! 1950: /** ! 1951: * Pick TX rate for RTS/CTS packets based on data rate ! 1952: * ! 1953: * @v dev 802.11 device ! 1954: * ! 1955: * The RTS/CTS rate is the fastest TX rate marked as "basic" that is ! 1956: * not faster than the data rate. ! 1957: */ ! 1958: static void net80211_set_rtscts_rate ( struct net80211_device *dev ) ! 1959: { ! 1960: u16 datarate = dev->rates[dev->rate]; ! 1961: u16 rtsrate = 0; ! 1962: int rts_idx = -1; ! 1963: int i; ! 1964: ! 1965: for ( i = 0; i < dev->nr_rates; i++ ) { ! 1966: u16 rate = dev->rates[i]; ! 1967: ! 1968: if ( ! ( dev->basic_rates & ( 1 << i ) ) || rate > datarate ) ! 1969: continue; ! 1970: ! 1971: if ( rate > rtsrate ) { ! 1972: rtsrate = rate; ! 1973: rts_idx = i; ! 1974: } ! 1975: } ! 1976: ! 1977: /* If this is in initialization, we might not have any basic ! 1978: rates; just use the first data rate in that case. */ ! 1979: if ( rts_idx < 0 ) ! 1980: rts_idx = 0; ! 1981: ! 1982: dev->rtscts_rate = rts_idx; ! 1983: } ! 1984: ! 1985: /** ! 1986: * Set data transmission rate for 802.11 device ! 1987: * ! 1988: * @v dev 802.11 device ! 1989: * @v rate Rate to set, as index into @c dev->rates array ! 1990: */ ! 1991: void net80211_set_rate_idx ( struct net80211_device *dev, int rate ) ! 1992: { ! 1993: assert ( netdev_is_open ( dev->netdev ) ); ! 1994: ! 1995: if ( rate >= 0 && rate < dev->nr_rates && rate != dev->rate ) { ! 1996: DBGC2 ( dev, "802.11 %p changing rate from %d->%d Mbps\n", ! 1997: dev, dev->rates[dev->rate] / 10, ! 1998: dev->rates[rate] / 10 ); ! 1999: ! 2000: dev->rate = rate; ! 2001: net80211_set_rtscts_rate ( dev ); ! 2002: dev->op->config ( dev, NET80211_CFG_RATE ); ! 2003: } ! 2004: } ! 2005: ! 2006: /** ! 2007: * Configure 802.11 device to transmit on a certain channel ! 2008: * ! 2009: * @v dev 802.11 device ! 2010: * @v channel Channel number (1-11 for 2.4GHz) to transmit on ! 2011: */ ! 2012: int net80211_change_channel ( struct net80211_device *dev, int channel ) ! 2013: { ! 2014: int i, oldchan = dev->channel; ! 2015: ! 2016: assert ( netdev_is_open ( dev->netdev ) ); ! 2017: ! 2018: for ( i = 0; i < dev->nr_channels; i++ ) { ! 2019: if ( dev->channels[i].channel_nr == channel ) { ! 2020: dev->channel = i; ! 2021: break; ! 2022: } ! 2023: } ! 2024: ! 2025: if ( i == dev->nr_channels ) ! 2026: return -ENOENT; ! 2027: ! 2028: if ( i != oldchan ) ! 2029: return dev->op->config ( dev, NET80211_CFG_CHANNEL ); ! 2030: ! 2031: return 0; ! 2032: } ! 2033: ! 2034: /** ! 2035: * Prepare 802.11 device channel and rate set for scanning ! 2036: * ! 2037: * @v dev 802.11 device ! 2038: * @v band RF band(s) on which to prepare for scanning ! 2039: * @v active Whether the scanning will be active ! 2040: * @ret rc Return status code ! 2041: */ ! 2042: int net80211_prepare_probe ( struct net80211_device *dev, int band, ! 2043: int active ) ! 2044: { ! 2045: assert ( netdev_is_open ( dev->netdev ) ); ! 2046: ! 2047: if ( active && ( band & NET80211_BAND_BIT_5GHZ ) ) { ! 2048: DBGC ( dev, "802.11 %p cannot perform active scanning on " ! 2049: "5GHz band\n", dev ); ! 2050: return -EINVAL_ACTIVE_SCAN; ! 2051: } ! 2052: ! 2053: if ( band == 0 ) { ! 2054: /* This can happen for a 5GHz-only card with 5GHz ! 2055: scanning masked out by an active request. */ ! 2056: DBGC ( dev, "802.11 %p asked to prepare for scanning nothing\n", ! 2057: dev ); ! 2058: return -EINVAL_ACTIVE_SCAN; ! 2059: } ! 2060: ! 2061: dev->nr_channels = 0; ! 2062: ! 2063: if ( active ) ! 2064: net80211_add_channels ( dev, 1, 11, NET80211_REG_TXPOWER ); ! 2065: else { ! 2066: if ( band & NET80211_BAND_BIT_2GHZ ) ! 2067: net80211_add_channels ( dev, 1, 14, ! 2068: NET80211_REG_TXPOWER ); ! 2069: if ( band & NET80211_BAND_BIT_5GHZ ) ! 2070: net80211_add_channels ( dev, 36, 8, ! 2071: NET80211_REG_TXPOWER ); ! 2072: } ! 2073: ! 2074: net80211_filter_hw_channels ( dev ); ! 2075: ! 2076: /* Use channel 1 for now */ ! 2077: dev->channel = 0; ! 2078: dev->op->config ( dev, NET80211_CFG_CHANNEL ); ! 2079: ! 2080: /* Always do active probes at lowest (presumably first) speed */ ! 2081: dev->rate = 0; ! 2082: dev->nr_rates = 1; ! 2083: dev->rates[0] = dev->hw->rates[dev->channels[0].band][0]; ! 2084: dev->op->config ( dev, NET80211_CFG_RATE ); ! 2085: ! 2086: return 0; ! 2087: } ! 2088: ! 2089: /** ! 2090: * Prepare 802.11 device channel and rate set for communication ! 2091: * ! 2092: * @v dev 802.11 device ! 2093: * @v wlan WLAN to prepare for communication with ! 2094: * @ret rc Return status code ! 2095: */ ! 2096: int net80211_prepare_assoc ( struct net80211_device *dev, ! 2097: struct net80211_wlan *wlan ) ! 2098: { ! 2099: struct ieee80211_frame *hdr = wlan->beacon->data; ! 2100: struct ieee80211_beacon *beacon = ! 2101: ( struct ieee80211_beacon * ) hdr->data; ! 2102: struct net80211_handshaker *handshaker; ! 2103: int rc; ! 2104: ! 2105: assert ( netdev_is_open ( dev->netdev ) ); ! 2106: ! 2107: net80211_set_state ( dev, NET80211_ASSOCIATED, 0, 0 ); ! 2108: memcpy ( dev->bssid, wlan->bssid, ETH_ALEN ); ! 2109: strcpy ( dev->essid, wlan->essid ); ! 2110: ! 2111: free ( dev->rsn_ie ); ! 2112: dev->rsn_ie = NULL; ! 2113: ! 2114: dev->last_beacon_timestamp = beacon->timestamp; ! 2115: dev->tx_beacon_interval = 1024 * beacon->beacon_interval; ! 2116: ! 2117: /* Barring an IE that tells us the channel outright, assume ! 2118: the channel we heard this AP best on is the channel it's ! 2119: communicating on. */ ! 2120: net80211_change_channel ( dev, wlan->channel ); ! 2121: ! 2122: rc = net80211_process_capab ( dev, beacon->capability ); ! 2123: if ( rc ) ! 2124: return rc; ! 2125: ! 2126: rc = net80211_process_ie ( dev, beacon->info_element, ! 2127: wlan->beacon->tail ); ! 2128: if ( rc ) ! 2129: return rc; ! 2130: ! 2131: /* Associate at the lowest rate so we know it'll get through */ ! 2132: dev->rate = 0; ! 2133: dev->op->config ( dev, NET80211_CFG_RATE ); ! 2134: ! 2135: /* Free old handshaker and crypto, if they exist */ ! 2136: if ( dev->handshaker && dev->handshaker->stop && ! 2137: dev->handshaker->started ) ! 2138: dev->handshaker->stop ( dev ); ! 2139: free ( dev->handshaker ); ! 2140: dev->handshaker = NULL; ! 2141: free ( dev->crypto ); ! 2142: free ( dev->gcrypto ); ! 2143: dev->crypto = dev->gcrypto = NULL; ! 2144: ! 2145: /* Find new security handshaker to use */ ! 2146: for_each_table_entry ( handshaker, NET80211_HANDSHAKERS ) { ! 2147: if ( handshaker->protocol == wlan->handshaking ) { ! 2148: dev->handshaker = zalloc ( sizeof ( *handshaker ) + ! 2149: handshaker->priv_len ); ! 2150: if ( ! dev->handshaker ) ! 2151: return -ENOMEM; ! 2152: ! 2153: memcpy ( dev->handshaker, handshaker, ! 2154: sizeof ( *handshaker ) ); ! 2155: dev->handshaker->priv = ( ( void * ) dev->handshaker + ! 2156: sizeof ( *handshaker ) ); ! 2157: break; ! 2158: } ! 2159: } ! 2160: ! 2161: if ( ( wlan->handshaking != NET80211_SECPROT_NONE ) && ! 2162: ! dev->handshaker ) { ! 2163: DBGC ( dev, "802.11 %p no support for handshaking scheme %d\n", ! 2164: dev, wlan->handshaking ); ! 2165: return -( ENOTSUP | ( wlan->handshaking << 8 ) ); ! 2166: } ! 2167: ! 2168: /* Initialize security handshaker */ ! 2169: if ( dev->handshaker ) { ! 2170: rc = dev->handshaker->init ( dev ); ! 2171: if ( rc < 0 ) ! 2172: return rc; ! 2173: } ! 2174: ! 2175: return 0; ! 2176: } ! 2177: ! 2178: /** ! 2179: * Send 802.11 initial authentication frame ! 2180: * ! 2181: * @v dev 802.11 device ! 2182: * @v wlan WLAN to authenticate with ! 2183: * @v method Authentication method ! 2184: * @ret rc Return status code ! 2185: * ! 2186: * @a method may be 0 for Open System authentication or 1 for Shared ! 2187: * Key authentication. Open System provides no security in association ! 2188: * whatsoever, relying on encryption for confidentiality, but Shared ! 2189: * Key actively introduces security problems and is very rarely used. ! 2190: */ ! 2191: int net80211_send_auth ( struct net80211_device *dev, ! 2192: struct net80211_wlan *wlan, int method ) ! 2193: { ! 2194: struct io_buffer *iob = alloc_iob ( 64 ); ! 2195: struct ieee80211_auth *auth; ! 2196: ! 2197: net80211_set_state ( dev, 0, NET80211_WAITING, 0 ); ! 2198: iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN ); ! 2199: auth = iob_put ( iob, sizeof ( *auth ) ); ! 2200: auth->algorithm = method; ! 2201: auth->tx_seq = 1; ! 2202: auth->status = 0; ! 2203: ! 2204: return net80211_tx_mgmt ( dev, IEEE80211_STYPE_AUTH, wlan->bssid, iob ); ! 2205: } ! 2206: ! 2207: /** ! 2208: * Handle receipt of 802.11 authentication frame ! 2209: * ! 2210: * @v dev 802.11 device ! 2211: * @v iob I/O buffer ! 2212: * ! 2213: * If the authentication method being used is Shared Key, and the ! 2214: * frame that was received included challenge text, the frame is ! 2215: * encrypted using the cryptosystem currently in effect and sent back ! 2216: * to the AP to complete the authentication. ! 2217: */ ! 2218: static void net80211_handle_auth ( struct net80211_device *dev, ! 2219: struct io_buffer *iob ) ! 2220: { ! 2221: struct ieee80211_frame *hdr = iob->data; ! 2222: struct ieee80211_auth *auth = ! 2223: ( struct ieee80211_auth * ) hdr->data; ! 2224: ! 2225: if ( auth->tx_seq & 1 ) { ! 2226: DBGC ( dev, "802.11 %p authentication received improperly " ! 2227: "directed frame (seq. %d)\n", dev, auth->tx_seq ); ! 2228: net80211_set_state ( dev, NET80211_WAITING, 0, ! 2229: IEEE80211_STATUS_FAILURE ); ! 2230: return; ! 2231: } ! 2232: ! 2233: if ( auth->status != IEEE80211_STATUS_SUCCESS ) { ! 2234: DBGC ( dev, "802.11 %p authentication failed: status %d\n", ! 2235: dev, auth->status ); ! 2236: net80211_set_state ( dev, NET80211_WAITING, 0, ! 2237: auth->status ); ! 2238: return; ! 2239: } ! 2240: ! 2241: if ( auth->algorithm == IEEE80211_AUTH_SHARED_KEY && ! dev->crypto ) { ! 2242: DBGC ( dev, "802.11 %p can't perform shared-key authentication " ! 2243: "without a cryptosystem\n", dev ); ! 2244: net80211_set_state ( dev, NET80211_WAITING, 0, ! 2245: IEEE80211_STATUS_FAILURE ); ! 2246: return; ! 2247: } ! 2248: ! 2249: if ( auth->algorithm == IEEE80211_AUTH_SHARED_KEY && ! 2250: auth->tx_seq == 2 ) { ! 2251: /* Since the iob we got is going to be freed as soon ! 2252: as we return, we can do some in-place ! 2253: modification. */ ! 2254: auth->tx_seq = 3; ! 2255: auth->status = 0; ! 2256: ! 2257: memcpy ( hdr->addr2, hdr->addr1, ETH_ALEN ); ! 2258: memcpy ( hdr->addr1, hdr->addr3, ETH_ALEN ); ! 2259: ! 2260: netdev_tx ( dev->netdev, ! 2261: dev->crypto->encrypt ( dev->crypto, iob ) ); ! 2262: return; ! 2263: } ! 2264: ! 2265: net80211_set_state ( dev, NET80211_WAITING, NET80211_AUTHENTICATED, ! 2266: IEEE80211_STATUS_SUCCESS ); ! 2267: ! 2268: return; ! 2269: } ! 2270: ! 2271: /** ! 2272: * Send 802.11 association frame ! 2273: * ! 2274: * @v dev 802.11 device ! 2275: * @v wlan WLAN to associate with ! 2276: * @ret rc Return status code ! 2277: */ ! 2278: int net80211_send_assoc ( struct net80211_device *dev, ! 2279: struct net80211_wlan *wlan ) ! 2280: { ! 2281: struct io_buffer *iob = alloc_iob ( 128 ); ! 2282: struct ieee80211_assoc_req *assoc; ! 2283: union ieee80211_ie *ie; ! 2284: ! 2285: net80211_set_state ( dev, 0, NET80211_WAITING, 0 ); ! 2286: ! 2287: iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN ); ! 2288: assoc = iob->data; ! 2289: ! 2290: assoc->capability = IEEE80211_CAPAB_MANAGED; ! 2291: if ( ! ( dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE ) ) ! 2292: assoc->capability |= IEEE80211_CAPAB_SHORT_PMBL; ! 2293: if ( ! ( dev->hw->flags & NET80211_HW_NO_SHORT_SLOT ) ) ! 2294: assoc->capability |= IEEE80211_CAPAB_SHORT_SLOT; ! 2295: if ( wlan->crypto ) ! 2296: assoc->capability |= IEEE80211_CAPAB_PRIVACY; ! 2297: ! 2298: assoc->listen_interval = 1; ! 2299: ! 2300: ie = net80211_marshal_request_info ( dev, assoc->info_element ); ! 2301: ! 2302: DBGP ( "802.11 %p about to send association request:\n", dev ); ! 2303: DBGP_HD ( iob->data, ( void * ) ie - iob->data ); ! 2304: ! 2305: iob_put ( iob, ( void * ) ie - iob->data ); ! 2306: ! 2307: return net80211_tx_mgmt ( dev, IEEE80211_STYPE_ASSOC_REQ, ! 2308: wlan->bssid, iob ); ! 2309: } ! 2310: ! 2311: /** ! 2312: * Handle receipt of 802.11 association reply frame ! 2313: * ! 2314: * @v dev 802.11 device ! 2315: * @v iob I/O buffer ! 2316: */ ! 2317: static void net80211_handle_assoc_reply ( struct net80211_device *dev, ! 2318: struct io_buffer *iob ) ! 2319: { ! 2320: struct ieee80211_frame *hdr = iob->data; ! 2321: struct ieee80211_assoc_resp *assoc = ! 2322: ( struct ieee80211_assoc_resp * ) hdr->data; ! 2323: ! 2324: net80211_process_capab ( dev, assoc->capability ); ! 2325: net80211_process_ie ( dev, assoc->info_element, iob->tail ); ! 2326: ! 2327: if ( assoc->status != IEEE80211_STATUS_SUCCESS ) { ! 2328: DBGC ( dev, "802.11 %p association failed: status %d\n", ! 2329: dev, assoc->status ); ! 2330: net80211_set_state ( dev, NET80211_WAITING, 0, ! 2331: assoc->status ); ! 2332: return; ! 2333: } ! 2334: ! 2335: /* ESSID was filled before the association request was sent */ ! 2336: memcpy ( dev->bssid, hdr->addr3, ETH_ALEN ); ! 2337: dev->aid = assoc->aid; ! 2338: ! 2339: net80211_set_state ( dev, NET80211_WAITING, NET80211_ASSOCIATED, ! 2340: IEEE80211_STATUS_SUCCESS ); ! 2341: } ! 2342: ! 2343: ! 2344: /** ! 2345: * Send 802.11 disassociation frame ! 2346: * ! 2347: * @v dev 802.11 device ! 2348: * @v reason Reason for disassociation ! 2349: * @v deauth If TRUE, send deauthentication instead of disassociation ! 2350: * @ret rc Return status code ! 2351: */ ! 2352: static int net80211_send_disassoc ( struct net80211_device *dev, int reason, ! 2353: int deauth ) ! 2354: { ! 2355: struct io_buffer *iob = alloc_iob ( 64 ); ! 2356: struct ieee80211_disassoc *disassoc; ! 2357: ! 2358: if ( ! ( dev->state & NET80211_ASSOCIATED ) ) ! 2359: return -EINVAL; ! 2360: ! 2361: net80211_set_state ( dev, NET80211_ASSOCIATED, 0, 0 ); ! 2362: iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN ); ! 2363: disassoc = iob_put ( iob, sizeof ( *disassoc ) ); ! 2364: disassoc->reason = reason; ! 2365: ! 2366: return net80211_tx_mgmt ( dev, deauth ? IEEE80211_STYPE_DEAUTH : ! 2367: IEEE80211_STYPE_DISASSOC, dev->bssid, iob ); ! 2368: } ! 2369: ! 2370: ! 2371: /** ! 2372: * Deauthenticate from current network and try again ! 2373: * ! 2374: * @v dev 802.11 device ! 2375: * @v rc Return status code indicating reason ! 2376: * ! 2377: * The deauthentication will be sent using an 802.11 "unspecified ! 2378: * reason", as is common, but @a rc will be set as a link-up ! 2379: * error to aid the user in debugging. ! 2380: */ ! 2381: void net80211_deauthenticate ( struct net80211_device *dev, int rc ) ! 2382: { ! 2383: net80211_send_disassoc ( dev, IEEE80211_REASON_UNSPECIFIED, 1 ); ! 2384: dev->assoc_rc = rc; ! 2385: netdev_link_err ( dev->netdev, rc ); ! 2386: ! 2387: net80211_autoassociate ( dev ); ! 2388: } ! 2389: ! 2390: ! 2391: /** Smoothing factor (1-7) for link quality calculation */ ! 2392: #define LQ_SMOOTH 7 ! 2393: ! 2394: /** ! 2395: * Update link quality information based on received beacon ! 2396: * ! 2397: * @v dev 802.11 device ! 2398: * @v iob I/O buffer containing beacon ! 2399: * @ret rc Return status code ! 2400: */ ! 2401: static void net80211_update_link_quality ( struct net80211_device *dev, ! 2402: struct io_buffer *iob ) ! 2403: { ! 2404: struct ieee80211_frame *hdr = iob->data; ! 2405: struct ieee80211_beacon *beacon; ! 2406: u32 dt, rxi; ! 2407: ! 2408: if ( ! ( dev->state & NET80211_ASSOCIATED ) ) ! 2409: return; ! 2410: ! 2411: beacon = ( struct ieee80211_beacon * ) hdr->data; ! 2412: dt = ( u32 ) ( beacon->timestamp - dev->last_beacon_timestamp ); ! 2413: rxi = dev->rx_beacon_interval; ! 2414: ! 2415: rxi = ( LQ_SMOOTH * rxi ) + ( ( 8 - LQ_SMOOTH ) * dt ); ! 2416: dev->rx_beacon_interval = rxi >> 3; ! 2417: ! 2418: dev->last_beacon_timestamp = beacon->timestamp; ! 2419: } ! 2420: ! 2421: ! 2422: /** ! 2423: * Handle receipt of 802.11 management frame ! 2424: * ! 2425: * @v dev 802.11 device ! 2426: * @v iob I/O buffer ! 2427: * @v signal Signal strength of received frame ! 2428: */ ! 2429: static void net80211_handle_mgmt ( struct net80211_device *dev, ! 2430: struct io_buffer *iob, int signal ) ! 2431: { ! 2432: struct ieee80211_frame *hdr = iob->data; ! 2433: struct ieee80211_disassoc *disassoc; ! 2434: u16 stype = hdr->fc & IEEE80211_FC_SUBTYPE; ! 2435: int keep = 0; ! 2436: int is_deauth = ( stype == IEEE80211_STYPE_DEAUTH ); ! 2437: ! 2438: if ( ( hdr->fc & IEEE80211_FC_TYPE ) != IEEE80211_TYPE_MGMT ) { ! 2439: free_iob ( iob ); ! 2440: return; /* only handle management frames */ ! 2441: } ! 2442: ! 2443: switch ( stype ) { ! 2444: /* We reconnect on deauthentication and disassociation. */ ! 2445: case IEEE80211_STYPE_DEAUTH: ! 2446: case IEEE80211_STYPE_DISASSOC: ! 2447: disassoc = ( struct ieee80211_disassoc * ) hdr->data; ! 2448: net80211_set_state ( dev, is_deauth ? NET80211_AUTHENTICATED : ! 2449: NET80211_ASSOCIATED, 0, ! 2450: NET80211_IS_REASON | disassoc->reason ); ! 2451: DBGC ( dev, "802.11 %p %s: reason %d\n", ! 2452: dev, is_deauth ? "deauthenticated" : "disassociated", ! 2453: disassoc->reason ); ! 2454: ! 2455: /* Try to reassociate, in case it's transient. */ ! 2456: net80211_autoassociate ( dev ); ! 2457: ! 2458: break; ! 2459: ! 2460: /* We handle authentication and association. */ ! 2461: case IEEE80211_STYPE_AUTH: ! 2462: if ( ! ( dev->state & NET80211_AUTHENTICATED ) ) ! 2463: net80211_handle_auth ( dev, iob ); ! 2464: break; ! 2465: ! 2466: case IEEE80211_STYPE_ASSOC_RESP: ! 2467: case IEEE80211_STYPE_REASSOC_RESP: ! 2468: if ( ! ( dev->state & NET80211_ASSOCIATED ) ) ! 2469: net80211_handle_assoc_reply ( dev, iob ); ! 2470: break; ! 2471: ! 2472: /* We pass probes and beacons onto network scanning ! 2473: code. Pass actions for future extensibility. */ ! 2474: case IEEE80211_STYPE_BEACON: ! 2475: net80211_update_link_quality ( dev, iob ); ! 2476: /* fall through */ ! 2477: case IEEE80211_STYPE_PROBE_RESP: ! 2478: case IEEE80211_STYPE_ACTION: ! 2479: if ( dev->keep_mgmt ) { ! 2480: struct net80211_rx_info *rxinf; ! 2481: rxinf = zalloc ( sizeof ( *rxinf ) ); ! 2482: if ( ! rxinf ) { ! 2483: DBGC ( dev, "802.11 %p out of memory\n", dev ); ! 2484: break; ! 2485: } ! 2486: rxinf->signal = signal; ! 2487: list_add_tail ( &iob->list, &dev->mgmt_queue ); ! 2488: list_add_tail ( &rxinf->list, &dev->mgmt_info_queue ); ! 2489: keep = 1; ! 2490: } ! 2491: break; ! 2492: ! 2493: case IEEE80211_STYPE_PROBE_REQ: ! 2494: /* Some nodes send these broadcast. Ignore them. */ ! 2495: break; ! 2496: ! 2497: case IEEE80211_STYPE_ASSOC_REQ: ! 2498: case IEEE80211_STYPE_REASSOC_REQ: ! 2499: /* We should never receive these, only send them. */ ! 2500: DBGC ( dev, "802.11 %p received strange management request " ! 2501: "(%04x)\n", dev, stype ); ! 2502: break; ! 2503: ! 2504: default: ! 2505: DBGC ( dev, "802.11 %p received unimplemented management " ! 2506: "packet (%04x)\n", dev, stype ); ! 2507: break; ! 2508: } ! 2509: ! 2510: if ( ! keep ) ! 2511: free_iob ( iob ); ! 2512: } ! 2513: ! 2514: /* ---------- Packet handling functions ---------- */ ! 2515: ! 2516: /** ! 2517: * Free buffers used by 802.11 fragment cache entry ! 2518: * ! 2519: * @v dev 802.11 device ! 2520: * @v fcid Fragment cache entry index ! 2521: * ! 2522: * After this function, the referenced entry will be marked unused. ! 2523: */ ! 2524: static void net80211_free_frags ( struct net80211_device *dev, int fcid ) ! 2525: { ! 2526: int j; ! 2527: struct net80211_frag_cache *frag = &dev->frags[fcid]; ! 2528: ! 2529: for ( j = 0; j < 16; j++ ) { ! 2530: if ( frag->iob[j] ) { ! 2531: free_iob ( frag->iob[j] ); ! 2532: frag->iob[j] = NULL; ! 2533: } ! 2534: } ! 2535: ! 2536: frag->seqnr = 0; ! 2537: frag->start_ticks = 0; ! 2538: frag->in_use = 0; ! 2539: } ! 2540: ! 2541: /** ! 2542: * Accumulate 802.11 fragments into one I/O buffer ! 2543: * ! 2544: * @v dev 802.11 device ! 2545: * @v fcid Fragment cache entry index ! 2546: * @v nfrags Number of fragments received ! 2547: * @v size Sum of sizes of all fragments, including headers ! 2548: * @ret iob I/O buffer containing reassembled packet ! 2549: * ! 2550: * This function does not free the fragment buffers. ! 2551: */ ! 2552: static struct io_buffer *net80211_accum_frags ( struct net80211_device *dev, ! 2553: int fcid, int nfrags, int size ) ! 2554: { ! 2555: struct net80211_frag_cache *frag = &dev->frags[fcid]; ! 2556: int hdrsize = IEEE80211_TYP_FRAME_HEADER_LEN; ! 2557: int nsize = size - hdrsize * ( nfrags - 1 ); ! 2558: int i; ! 2559: ! 2560: struct io_buffer *niob = alloc_iob ( nsize ); ! 2561: struct ieee80211_frame *hdr; ! 2562: ! 2563: /* Add the header from the first one... */ ! 2564: memcpy ( iob_put ( niob, hdrsize ), frag->iob[0]->data, hdrsize ); ! 2565: ! 2566: /* ... and all the data from all of them. */ ! 2567: for ( i = 0; i < nfrags; i++ ) { ! 2568: int len = iob_len ( frag->iob[i] ) - hdrsize; ! 2569: memcpy ( iob_put ( niob, len ), ! 2570: frag->iob[i]->data + hdrsize, len ); ! 2571: } ! 2572: ! 2573: /* Turn off the fragment bit. */ ! 2574: hdr = niob->data; ! 2575: hdr->fc &= ~IEEE80211_FC_MORE_FRAG; ! 2576: ! 2577: return niob; ! 2578: } ! 2579: ! 2580: /** ! 2581: * Handle receipt of 802.11 fragment ! 2582: * ! 2583: * @v dev 802.11 device ! 2584: * @v iob I/O buffer containing fragment ! 2585: * @v signal Signal strength with which fragment was received ! 2586: */ ! 2587: static void net80211_rx_frag ( struct net80211_device *dev, ! 2588: struct io_buffer *iob, int signal ) ! 2589: { ! 2590: struct ieee80211_frame *hdr = iob->data; ! 2591: int fragnr = IEEE80211_FRAG ( hdr->seq ); ! 2592: ! 2593: if ( fragnr == 0 && ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) { ! 2594: /* start a frag cache entry */ ! 2595: int i, newest = -1; ! 2596: u32 curr_ticks = currticks(), newest_ticks = 0; ! 2597: u32 timeout = ticks_per_sec() * NET80211_FRAG_TIMEOUT; ! 2598: ! 2599: for ( i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++ ) { ! 2600: if ( dev->frags[i].in_use == 0 ) ! 2601: break; ! 2602: ! 2603: if ( dev->frags[i].start_ticks + timeout >= ! 2604: curr_ticks ) { ! 2605: net80211_free_frags ( dev, i ); ! 2606: break; ! 2607: } ! 2608: ! 2609: if ( dev->frags[i].start_ticks > newest_ticks ) { ! 2610: newest = i; ! 2611: newest_ticks = dev->frags[i].start_ticks; ! 2612: } ! 2613: } ! 2614: ! 2615: /* If we're being sent more concurrent fragmented ! 2616: packets than we can handle, drop the newest so the ! 2617: older ones have time to complete. */ ! 2618: if ( i == NET80211_NR_CONCURRENT_FRAGS ) { ! 2619: i = newest; ! 2620: net80211_free_frags ( dev, i ); ! 2621: } ! 2622: ! 2623: dev->frags[i].in_use = 1; ! 2624: dev->frags[i].seqnr = IEEE80211_SEQNR ( hdr->seq ); ! 2625: dev->frags[i].start_ticks = currticks(); ! 2626: dev->frags[i].iob[0] = iob; ! 2627: return; ! 2628: } else { ! 2629: int i; ! 2630: for ( i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++ ) { ! 2631: if ( dev->frags[i].in_use && dev->frags[i].seqnr == ! 2632: IEEE80211_SEQNR ( hdr->seq ) ) ! 2633: break; ! 2634: } ! 2635: if ( i == NET80211_NR_CONCURRENT_FRAGS ) { ! 2636: /* Drop non-first not-in-cache fragments */ ! 2637: DBGC ( dev, "802.11 %p dropped fragment fc=%04x " ! 2638: "seq=%04x\n", dev, hdr->fc, hdr->seq ); ! 2639: free_iob ( iob ); ! 2640: return; ! 2641: } ! 2642: ! 2643: dev->frags[i].iob[fragnr] = iob; ! 2644: ! 2645: if ( ! ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) { ! 2646: int j, size = 0; ! 2647: for ( j = 0; j < fragnr; j++ ) { ! 2648: size += iob_len ( dev->frags[i].iob[j] ); ! 2649: if ( dev->frags[i].iob[j] == NULL ) ! 2650: break; ! 2651: } ! 2652: if ( j == fragnr ) { ! 2653: /* We've got everything */ ! 2654: struct io_buffer *niob = ! 2655: net80211_accum_frags ( dev, i, fragnr, ! 2656: size ); ! 2657: net80211_free_frags ( dev, i ); ! 2658: net80211_rx ( dev, niob, signal, 0 ); ! 2659: } else { ! 2660: DBGC ( dev, "802.11 %p dropping fragmented " ! 2661: "packet due to out-of-order arrival, " ! 2662: "fc=%04x seq=%04x\n", dev, hdr->fc, ! 2663: hdr->seq ); ! 2664: net80211_free_frags ( dev, i ); ! 2665: } ! 2666: } ! 2667: } ! 2668: } ! 2669: ! 2670: /** ! 2671: * Handle receipt of 802.11 frame ! 2672: * ! 2673: * @v dev 802.11 device ! 2674: * @v iob I/O buffer ! 2675: * @v signal Received signal strength ! 2676: * @v rate Bitrate at which frame was received, in 100 kbps units ! 2677: * ! 2678: * If the rate or signal is unknown, 0 should be passed. ! 2679: */ ! 2680: void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob, ! 2681: int signal, u16 rate ) ! 2682: { ! 2683: struct ieee80211_frame *hdr = iob->data; ! 2684: u16 type = hdr->fc & IEEE80211_FC_TYPE; ! 2685: if ( ( hdr->fc & IEEE80211_FC_VERSION ) != IEEE80211_THIS_VERSION ) ! 2686: goto drop; /* drop invalid-version packets */ ! 2687: ! 2688: if ( type == IEEE80211_TYPE_CTRL ) ! 2689: goto drop; /* we don't handle control packets, ! 2690: the hardware does */ ! 2691: ! 2692: if ( dev->last_rx_seq == hdr->seq ) ! 2693: goto drop; /* avoid duplicate packet */ ! 2694: dev->last_rx_seq = hdr->seq; ! 2695: ! 2696: if ( dev->hw->flags & NET80211_HW_RX_HAS_FCS ) { ! 2697: /* discard the FCS */ ! 2698: iob_unput ( iob, 4 ); ! 2699: } ! 2700: ! 2701: /* Only decrypt packets from our BSSID, to avoid spurious errors */ ! 2702: if ( ( hdr->fc & IEEE80211_FC_PROTECTED ) && ! 2703: ! memcmp ( hdr->addr2, dev->bssid, ETH_ALEN ) ) { ! 2704: /* Decrypt packet; record and drop if it fails */ ! 2705: struct io_buffer *niob; ! 2706: struct net80211_crypto *crypto = dev->crypto; ! 2707: ! 2708: if ( ! dev->crypto ) { ! 2709: DBGC ( dev, "802.11 %p cannot decrypt packet " ! 2710: "without a cryptosystem\n", dev ); ! 2711: goto drop_crypt; ! 2712: } ! 2713: ! 2714: if ( ( hdr->addr1[0] & 1 ) && dev->gcrypto ) { ! 2715: /* Use group decryption if needed */ ! 2716: crypto = dev->gcrypto; ! 2717: } ! 2718: ! 2719: niob = crypto->decrypt ( crypto, iob ); ! 2720: if ( ! niob ) { ! 2721: DBGC ( dev, "802.11 %p decryption error\n", dev ); ! 2722: goto drop_crypt; ! 2723: } ! 2724: free_iob ( iob ); ! 2725: iob = niob; ! 2726: hdr = iob->data; ! 2727: } ! 2728: ! 2729: dev->last_signal = signal; ! 2730: ! 2731: /* Fragments go into the frag cache or get dropped. */ ! 2732: if ( IEEE80211_FRAG ( hdr->seq ) != 0 ! 2733: || ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) { ! 2734: net80211_rx_frag ( dev, iob, signal ); ! 2735: return; ! 2736: } ! 2737: ! 2738: /* Management frames get handled, enqueued, or dropped. */ ! 2739: if ( type == IEEE80211_TYPE_MGMT ) { ! 2740: net80211_handle_mgmt ( dev, iob, signal ); ! 2741: return; ! 2742: } ! 2743: ! 2744: /* Data frames get dropped or sent to the net_device. */ ! 2745: if ( ( hdr->fc & IEEE80211_FC_SUBTYPE ) != IEEE80211_STYPE_DATA ) ! 2746: goto drop; /* drop QoS, CFP, or null data packets */ ! 2747: ! 2748: /* Update rate-control algorithm */ ! 2749: if ( dev->rctl ) ! 2750: rc80211_update_rx ( dev, hdr->fc & IEEE80211_FC_RETRY, rate ); ! 2751: ! 2752: /* Pass packet onward */ ! 2753: if ( dev->state & NET80211_ASSOCIATED ) { ! 2754: netdev_rx ( dev->netdev, iob ); ! 2755: return; ! 2756: } ! 2757: ! 2758: /* No association? Drop it. */ ! 2759: goto drop; ! 2760: ! 2761: drop_crypt: ! 2762: netdev_rx_err ( dev->netdev, NULL, EINVAL_CRYPTO_REQUEST ); ! 2763: drop: ! 2764: DBGC2 ( dev, "802.11 %p dropped packet fc=%04x seq=%04x\n", dev, ! 2765: hdr->fc, hdr->seq ); ! 2766: free_iob ( iob ); ! 2767: return; ! 2768: } ! 2769: ! 2770: /** Indicate an error in receiving a packet ! 2771: * ! 2772: * @v dev 802.11 device ! 2773: * @v iob I/O buffer with received packet, or NULL ! 2774: * @v rc Error code ! 2775: * ! 2776: * This logs the error with the wrapping net_device, and frees iob if ! 2777: * it is passed. ! 2778: */ ! 2779: void net80211_rx_err ( struct net80211_device *dev, ! 2780: struct io_buffer *iob, int rc ) ! 2781: { ! 2782: netdev_rx_err ( dev->netdev, iob, rc ); ! 2783: } ! 2784: ! 2785: /** Indicate the completed transmission of a packet ! 2786: * ! 2787: * @v dev 802.11 device ! 2788: * @v iob I/O buffer of transmitted packet ! 2789: * @v retries Number of times this packet was retransmitted ! 2790: * @v rc Error code, or 0 for success ! 2791: * ! 2792: * This logs an error with the wrapping net_device if one occurred, ! 2793: * and removes and frees the I/O buffer from its TX queue. The ! 2794: * provided retry information is used to tune our transmission rate. ! 2795: * ! 2796: * If the packet did not need to be retransmitted because it was ! 2797: * properly ACKed the first time, @a retries should be 0. ! 2798: */ ! 2799: void net80211_tx_complete ( struct net80211_device *dev, ! 2800: struct io_buffer *iob, int retries, int rc ) ! 2801: { ! 2802: /* Update rate-control algorithm */ ! 2803: if ( dev->rctl ) ! 2804: rc80211_update_tx ( dev, retries, rc ); ! 2805: ! 2806: /* Pass completion onward */ ! 2807: netdev_tx_complete_err ( dev->netdev, iob, rc ); ! 2808: } ! 2809: ! 2810: /** Common 802.11 errors */ ! 2811: struct errortab common_wireless_errors[] __errortab = { ! 2812: __einfo_errortab ( EINFO_EINVAL_CRYPTO_REQUEST ), ! 2813: __einfo_errortab ( EINFO_ECONNRESET_UNSPECIFIED ), ! 2814: __einfo_errortab ( EINFO_ECONNRESET_INACTIVITY ), ! 2815: __einfo_errortab ( EINFO_ECONNRESET_4WAY_TIMEOUT ), ! 2816: __einfo_errortab ( EINFO_ECONNRESET_8021X_FAILURE ), ! 2817: __einfo_errortab ( EINFO_ECONNREFUSED_FAILURE ), ! 2818: __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_DENIED ), ! 2819: __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP ), ! 2820: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.