Functions | |
| static void | net80211_step_associate (struct process *proc) |
| Step 802.11 association process. | |
| static void | net80211_handle_auth (struct net80211_device *dev, struct io_buffer *iob) |
| Handle receipt of 802.11 authentication frame. | |
| static void | net80211_handle_assoc_reply (struct net80211_device *dev, struct io_buffer *iob) |
| Handle receipt of 802.11 association reply frame. | |
| static int | net80211_send_disassoc (struct net80211_device *dev, int reason, int deauth) |
| Send 802.11 disassociation frame. | |
| static void | net80211_handle_mgmt (struct net80211_device *dev, struct io_buffer *iob, int signal) |
| Handle receipt of 802.11 management frame. | |
| static void net80211_step_associate | ( | struct process * | proc | ) | [static] |
Step 802.11 association process.
| proc | Association process |
Definition at line 1657 of file net80211.c.
References net80211_device::assoc, net80211_device::assoc_rc, ASSOC_RETRIES, ASSOC_TIMEOUT, net80211_device::associating, net80211_hw_info::bands, net80211_device::bssid, net80211_wlan::bssid, container_of, net80211_device::ctx, currticks(), DBGC, ENOMEM, net80211_wlan::essid, net80211_device::essid, eth_ntoa(), ETIMEDOUT, fetch_intz_setting(), free(), net80211_device::handshaker, net80211_device::hw, IEEE80211_AUTH_OPEN_SYSTEM, IEEE80211_AUTH_SHARED_KEY, IEEE80211_STATUS_AUTH_ALGO_UNSUPP, IEEE80211_STATUS_AUTH_CHALL_INVALID, IEEE80211_STATUS_SUCCESS, net80211_assoc_ctx::last_packet, net80211_assoc_ctx::method, NET80211_ASSOCIATED, NET80211_AUTHENTICATED, NET80211_AUTO_SSID, net80211_autoassociate(), NET80211_BAND_BIT_5GHZ, NET80211_CRYPTO_SYNCED, net80211_free_wlan(), net80211_prepare_assoc(), net80211_prepare_probe(), net80211_probe_finish_best(), net80211_probe_start(), net80211_probe_step(), NET80211_PROBED, net80211_send_assoc(), net80211_send_auth(), NET80211_STATUS_MASK, NET80211_WAITING, NET80211_WORKING, net80211_device::netdev, netdev_link_err(), netdev_link_up(), NULL, net80211_device::probe, net80211_device::proc_assoc, process_del(), rc80211_init(), net80211_device::rctl, net80211_handshaker::start, net80211_handshaker::started, net80211_device::state, net80211_handshaker::step, strerror(), net80211_assoc_ctx::times_tried, and zalloc().
Referenced by net80211_alloc().
01658 { 01659 struct net80211_device *dev = 01660 container_of ( proc, struct net80211_device, proc_assoc ); 01661 int rc = 0; 01662 int status = dev->state & NET80211_STATUS_MASK; 01663 01664 /* 01665 * We use a sort of state machine implemented using bits in 01666 * the dev->state variable. At each call, we take the 01667 * logically first step that has not yet succeeded; either it 01668 * has not been tried yet, it's being retried, or it failed. 01669 * If it failed, we return an error indication; otherwise we 01670 * perform the step. If it succeeds, RX handling code will set 01671 * the appropriate status bit for us. 01672 * 01673 * Probe works a bit differently, since we have to step it 01674 * on every call instead of waiting for a packet to arrive 01675 * that will set the completion bit for us. 01676 */ 01677 01678 /* If we're waiting for a reply, check for timeout condition */ 01679 if ( dev->state & NET80211_WAITING ) { 01680 /* Sanity check */ 01681 if ( ! dev->associating ) 01682 return; 01683 01684 if ( currticks() - dev->ctx.assoc->last_packet > ASSOC_TIMEOUT ) { 01685 /* Timed out - fail if too many retries, or retry */ 01686 dev->ctx.assoc->times_tried++; 01687 if ( ++dev->ctx.assoc->times_tried > ASSOC_RETRIES ) { 01688 rc = -ETIMEDOUT; 01689 goto fail; 01690 } 01691 } else { 01692 /* Didn't time out - let it keep going */ 01693 return; 01694 } 01695 } else { 01696 if ( dev->state & NET80211_PROBED ) 01697 dev->ctx.assoc->times_tried = 0; 01698 } 01699 01700 if ( ! ( dev->state & NET80211_PROBED ) ) { 01701 /* state: probe */ 01702 01703 if ( ! dev->ctx.probe ) { 01704 /* start probe */ 01705 int active = fetch_intz_setting ( NULL, 01706 &net80211_active_setting ); 01707 int band = dev->hw->bands; 01708 01709 if ( active ) 01710 band &= ~NET80211_BAND_BIT_5GHZ; 01711 01712 rc = net80211_prepare_probe ( dev, band, active ); 01713 if ( rc ) 01714 goto fail; 01715 01716 dev->ctx.probe = net80211_probe_start ( dev, dev->essid, 01717 active ); 01718 if ( ! dev->ctx.probe ) { 01719 dev->assoc_rc = -ENOMEM; 01720 goto fail; 01721 } 01722 } 01723 01724 rc = net80211_probe_step ( dev->ctx.probe ); 01725 if ( ! rc ) { 01726 return; /* still going */ 01727 } 01728 01729 dev->associating = net80211_probe_finish_best ( dev->ctx.probe ); 01730 dev->ctx.probe = NULL; 01731 if ( ! dev->associating ) { 01732 if ( rc > 0 ) /* "successful" probe found nothing */ 01733 rc = -ETIMEDOUT; 01734 goto fail; 01735 } 01736 01737 /* If we probed using a broadcast SSID, record that 01738 fact for the settings applicator before we clobber 01739 it with the specific SSID we've chosen. */ 01740 if ( ! dev->essid[0] ) 01741 dev->state |= NET80211_AUTO_SSID; 01742 01743 DBGC ( dev, "802.11 %p found network %s (%s)\n", dev, 01744 dev->associating->essid, 01745 eth_ntoa ( dev->associating->bssid ) ); 01746 01747 dev->ctx.assoc = zalloc ( sizeof ( *dev->ctx.assoc ) ); 01748 if ( ! dev->ctx.assoc ) { 01749 rc = -ENOMEM; 01750 goto fail; 01751 } 01752 01753 dev->state |= NET80211_PROBED; 01754 dev->ctx.assoc->method = IEEE80211_AUTH_OPEN_SYSTEM; 01755 01756 return; 01757 } 01758 01759 /* Record time of sending the packet we're about to send, for timeout */ 01760 dev->ctx.assoc->last_packet = currticks(); 01761 01762 if ( ! ( dev->state & NET80211_AUTHENTICATED ) ) { 01763 /* state: prepare and authenticate */ 01764 01765 if ( status != IEEE80211_STATUS_SUCCESS ) { 01766 /* we tried authenticating already, but failed */ 01767 int method = dev->ctx.assoc->method; 01768 01769 if ( method == IEEE80211_AUTH_OPEN_SYSTEM && 01770 ( status == IEEE80211_STATUS_AUTH_CHALL_INVALID || 01771 status == IEEE80211_STATUS_AUTH_ALGO_UNSUPP ) ) { 01772 /* Maybe this network uses Shared Key? */ 01773 dev->ctx.assoc->method = 01774 IEEE80211_AUTH_SHARED_KEY; 01775 } else { 01776 goto fail; 01777 } 01778 } 01779 01780 DBGC ( dev, "802.11 %p authenticating with method %d\n", dev, 01781 dev->ctx.assoc->method ); 01782 01783 rc = net80211_prepare_assoc ( dev, dev->associating ); 01784 if ( rc ) 01785 goto fail; 01786 01787 rc = net80211_send_auth ( dev, dev->associating, 01788 dev->ctx.assoc->method ); 01789 if ( rc ) 01790 goto fail; 01791 01792 return; 01793 } 01794 01795 if ( ! ( dev->state & NET80211_ASSOCIATED ) ) { 01796 /* state: associate */ 01797 01798 if ( status != IEEE80211_STATUS_SUCCESS ) 01799 goto fail; 01800 01801 DBGC ( dev, "802.11 %p associating\n", dev ); 01802 01803 if ( dev->handshaker && dev->handshaker->start && 01804 ! dev->handshaker->started ) { 01805 rc = dev->handshaker->start ( dev ); 01806 if ( rc < 0 ) 01807 goto fail; 01808 dev->handshaker->started = 1; 01809 } 01810 01811 rc = net80211_send_assoc ( dev, dev->associating ); 01812 if ( rc ) 01813 goto fail; 01814 01815 return; 01816 } 01817 01818 if ( ! ( dev->state & NET80211_CRYPTO_SYNCED ) ) { 01819 /* state: crypto sync */ 01820 DBGC ( dev, "802.11 %p security handshaking\n", dev ); 01821 01822 if ( ! dev->handshaker || ! dev->handshaker->step ) { 01823 dev->state |= NET80211_CRYPTO_SYNCED; 01824 return; 01825 } 01826 01827 rc = dev->handshaker->step ( dev ); 01828 01829 if ( rc < 0 ) { 01830 /* Only record the returned error if we're 01831 still marked as associated, because an 01832 asynchronous error will have already been 01833 reported to net80211_deauthenticate() and 01834 assoc_rc thereby set. */ 01835 if ( dev->state & NET80211_ASSOCIATED ) 01836 dev->assoc_rc = rc; 01837 rc = 0; 01838 goto fail; 01839 } 01840 01841 if ( rc > 0 ) { 01842 dev->assoc_rc = 0; 01843 dev->state |= NET80211_CRYPTO_SYNCED; 01844 } 01845 return; 01846 } 01847 01848 /* state: done! */ 01849 netdev_link_up ( dev->netdev ); 01850 dev->assoc_rc = 0; 01851 dev->state &= ~NET80211_WORKING; 01852 01853 free ( dev->ctx.assoc ); 01854 dev->ctx.assoc = NULL; 01855 01856 net80211_free_wlan ( dev->associating ); 01857 dev->associating = NULL; 01858 01859 dev->rctl = rc80211_init ( dev ); 01860 01861 process_del ( proc ); 01862 01863 DBGC ( dev, "802.11 %p associated with %s (%s)\n", dev, 01864 dev->essid, eth_ntoa ( dev->bssid ) ); 01865 01866 return; 01867 01868 fail: 01869 dev->state &= ~( NET80211_WORKING | NET80211_WAITING ); 01870 if ( rc ) 01871 dev->assoc_rc = rc; 01872 01873 netdev_link_err ( dev->netdev, dev->assoc_rc ); 01874 01875 /* We never reach here from the middle of a probe, so we don't 01876 need to worry about freeing dev->ctx.probe. */ 01877 01878 if ( dev->state & NET80211_PROBED ) { 01879 free ( dev->ctx.assoc ); 01880 dev->ctx.assoc = NULL; 01881 } 01882 01883 net80211_free_wlan ( dev->associating ); 01884 dev->associating = NULL; 01885 01886 process_del ( proc ); 01887 01888 DBGC ( dev, "802.11 %p association failed (state=%04x): " 01889 "%s\n", dev, dev->state, strerror ( dev->assoc_rc ) ); 01890 01891 /* Try it again: */ 01892 net80211_autoassociate ( dev ); 01893 }
| static void net80211_handle_auth | ( | struct net80211_device * | dev, | |
| struct io_buffer * | iob | |||
| ) | [static] |
Handle receipt of 802.11 authentication frame.
| dev | 802.11 device | |
| iob | I/O buffer |
Definition at line 2240 of file net80211.c.
References ieee80211_frame::addr1, ieee80211_frame::addr2, ieee80211_frame::addr3, ieee80211_auth::algorithm, net80211_device::crypto, ieee80211_frame::data, io_buffer::data, DBGC, net80211_crypto::encrypt, ETH_ALEN, IEEE80211_AUTH_SHARED_KEY, IEEE80211_STATUS_FAILURE, IEEE80211_STATUS_SUCCESS, memcpy, NET80211_AUTHENTICATED, net80211_set_state(), NET80211_WAITING, net80211_device::netdev, netdev_tx(), ieee80211_auth::status, and ieee80211_auth::tx_seq.
Referenced by net80211_handle_mgmt().
02242 { 02243 struct ieee80211_frame *hdr = iob->data; 02244 struct ieee80211_auth *auth = 02245 ( struct ieee80211_auth * ) hdr->data; 02246 02247 if ( auth->tx_seq & 1 ) { 02248 DBGC ( dev, "802.11 %p authentication received improperly " 02249 "directed frame (seq. %d)\n", dev, auth->tx_seq ); 02250 net80211_set_state ( dev, NET80211_WAITING, 0, 02251 IEEE80211_STATUS_FAILURE ); 02252 return; 02253 } 02254 02255 if ( auth->status != IEEE80211_STATUS_SUCCESS ) { 02256 DBGC ( dev, "802.11 %p authentication failed: status %d\n", 02257 dev, auth->status ); 02258 net80211_set_state ( dev, NET80211_WAITING, 0, 02259 auth->status ); 02260 return; 02261 } 02262 02263 if ( auth->algorithm == IEEE80211_AUTH_SHARED_KEY && ! dev->crypto ) { 02264 DBGC ( dev, "802.11 %p can't perform shared-key authentication " 02265 "without a cryptosystem\n", dev ); 02266 net80211_set_state ( dev, NET80211_WAITING, 0, 02267 IEEE80211_STATUS_FAILURE ); 02268 return; 02269 } 02270 02271 if ( auth->algorithm == IEEE80211_AUTH_SHARED_KEY && 02272 auth->tx_seq == 2 ) { 02273 /* Since the iob we got is going to be freed as soon 02274 as we return, we can do some in-place 02275 modification. */ 02276 auth->tx_seq = 3; 02277 auth->status = 0; 02278 02279 memcpy ( hdr->addr2, hdr->addr1, ETH_ALEN ); 02280 memcpy ( hdr->addr1, hdr->addr3, ETH_ALEN ); 02281 02282 netdev_tx ( dev->netdev, 02283 dev->crypto->encrypt ( dev->crypto, iob ) ); 02284 return; 02285 } 02286 02287 net80211_set_state ( dev, NET80211_WAITING, NET80211_AUTHENTICATED, 02288 IEEE80211_STATUS_SUCCESS ); 02289 02290 return; 02291 }
| static void net80211_handle_assoc_reply | ( | struct net80211_device * | dev, | |
| struct io_buffer * | iob | |||
| ) | [static] |
Handle receipt of 802.11 association reply frame.
| dev | 802.11 device | |
| iob | I/O buffer |
Definition at line 2339 of file net80211.c.
References ieee80211_frame::addr3, net80211_device::aid, net80211_device::bssid, ieee80211_frame::data, io_buffer::data, DBGC, ETH_ALEN, ieee80211_assoc_resp, IEEE80211_STATUS_SUCCESS, memcpy, NET80211_ASSOCIATED, net80211_process_capab(), net80211_process_ie(), net80211_set_state(), NET80211_WAITING, and io_buffer::tail.
Referenced by net80211_handle_mgmt().
02341 { 02342 struct ieee80211_frame *hdr = iob->data; 02343 struct ieee80211_assoc_resp *assoc = 02344 ( struct ieee80211_assoc_resp * ) hdr->data; 02345 02346 net80211_process_capab ( dev, assoc->capability ); 02347 net80211_process_ie ( dev, assoc->info_element, iob->tail ); 02348 02349 if ( assoc->status != IEEE80211_STATUS_SUCCESS ) { 02350 DBGC ( dev, "802.11 %p association failed: status %d\n", 02351 dev, assoc->status ); 02352 net80211_set_state ( dev, NET80211_WAITING, 0, 02353 assoc->status ); 02354 return; 02355 } 02356 02357 /* ESSID was filled before the association request was sent */ 02358 memcpy ( dev->bssid, hdr->addr3, ETH_ALEN ); 02359 dev->aid = assoc->aid; 02360 02361 net80211_set_state ( dev, NET80211_WAITING, NET80211_ASSOCIATED, 02362 IEEE80211_STATUS_SUCCESS ); 02363 }
| static int net80211_send_disassoc | ( | struct net80211_device * | dev, | |
| int | reason, | |||
| int | deauth | |||
| ) | [static] |
Send 802.11 disassociation frame.
| dev | 802.11 device | |
| reason | Reason for disassociation | |
| deauth | If TRUE, send deauthentication instead of disassociation |
| rc | Return status code |
Definition at line 2374 of file net80211.c.
References alloc_iob(), net80211_device::bssid, EINVAL, ieee80211_disassoc, IEEE80211_STYPE_DEAUTH, IEEE80211_STYPE_DISASSOC, IEEE80211_TYP_FRAME_HEADER_LEN, iob_put, iob_reserve, NET80211_ASSOCIATED, net80211_set_state(), net80211_tx_mgmt(), and net80211_device::state.
Referenced by net80211_deauthenticate(), and net80211_netdev_close().
02376 { 02377 struct io_buffer *iob = alloc_iob ( 64 ); 02378 struct ieee80211_disassoc *disassoc; 02379 02380 if ( ! ( dev->state & NET80211_ASSOCIATED ) ) 02381 return -EINVAL; 02382 02383 net80211_set_state ( dev, NET80211_ASSOCIATED, 0, 0 ); 02384 iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN ); 02385 disassoc = iob_put ( iob, sizeof ( *disassoc ) ); 02386 disassoc->reason = reason; 02387 02388 return net80211_tx_mgmt ( dev, deauth ? IEEE80211_STYPE_DEAUTH : 02389 IEEE80211_STYPE_DISASSOC, dev->bssid, iob ); 02390 }
| static void net80211_handle_mgmt | ( | struct net80211_device * | dev, | |
| struct io_buffer * | iob, | |||
| int | signal | |||
| ) | [static] |
Handle receipt of 802.11 management frame.
| dev | 802.11 device | |
| iob | I/O buffer | |
| signal | Signal strength of received frame |
Definition at line 2451 of file net80211.c.
References ieee80211_frame::data, io_buffer::data, DBGC, ieee80211_frame::fc, free_iob(), ieee80211_disassoc, IEEE80211_FC_SUBTYPE, IEEE80211_FC_TYPE, IEEE80211_STYPE_ACTION, IEEE80211_STYPE_ASSOC_REQ, IEEE80211_STYPE_ASSOC_RESP, IEEE80211_STYPE_AUTH, IEEE80211_STYPE_BEACON, IEEE80211_STYPE_DEAUTH, IEEE80211_STYPE_DISASSOC, IEEE80211_STYPE_PROBE_REQ, IEEE80211_STYPE_PROBE_RESP, IEEE80211_STYPE_REASSOC_REQ, IEEE80211_STYPE_REASSOC_RESP, IEEE80211_TYPE_MGMT, net80211_device::keep_mgmt, net80211_rx_info::list, io_buffer::list, list_add_tail, net80211_device::mgmt_info_queue, net80211_device::mgmt_queue, NET80211_ASSOCIATED, NET80211_AUTHENTICATED, net80211_autoassociate(), net80211_handle_assoc_reply(), net80211_handle_auth(), NET80211_IS_REASON, net80211_set_state(), net80211_update_link_quality(), net80211_rx_info::signal, net80211_device::state, u16, and zalloc().
Referenced by net80211_rx().
02453 { 02454 struct ieee80211_frame *hdr = iob->data; 02455 struct ieee80211_disassoc *disassoc; 02456 u16 stype = hdr->fc & IEEE80211_FC_SUBTYPE; 02457 int keep = 0; 02458 int is_deauth = ( stype == IEEE80211_STYPE_DEAUTH ); 02459 02460 if ( ( hdr->fc & IEEE80211_FC_TYPE ) != IEEE80211_TYPE_MGMT ) { 02461 free_iob ( iob ); 02462 return; /* only handle management frames */ 02463 } 02464 02465 switch ( stype ) { 02466 /* We reconnect on deauthentication and disassociation. */ 02467 case IEEE80211_STYPE_DEAUTH: 02468 case IEEE80211_STYPE_DISASSOC: 02469 disassoc = ( struct ieee80211_disassoc * ) hdr->data; 02470 net80211_set_state ( dev, is_deauth ? NET80211_AUTHENTICATED : 02471 NET80211_ASSOCIATED, 0, 02472 NET80211_IS_REASON | disassoc->reason ); 02473 DBGC ( dev, "802.11 %p %s: reason %d\n", 02474 dev, is_deauth ? "deauthenticated" : "disassociated", 02475 disassoc->reason ); 02476 02477 /* Try to reassociate, in case it's transient. */ 02478 net80211_autoassociate ( dev ); 02479 02480 break; 02481 02482 /* We handle authentication and association. */ 02483 case IEEE80211_STYPE_AUTH: 02484 if ( ! ( dev->state & NET80211_AUTHENTICATED ) ) 02485 net80211_handle_auth ( dev, iob ); 02486 break; 02487 02488 case IEEE80211_STYPE_ASSOC_RESP: 02489 case IEEE80211_STYPE_REASSOC_RESP: 02490 if ( ! ( dev->state & NET80211_ASSOCIATED ) ) 02491 net80211_handle_assoc_reply ( dev, iob ); 02492 break; 02493 02494 /* We pass probes and beacons onto network scanning 02495 code. Pass actions for future extensibility. */ 02496 case IEEE80211_STYPE_BEACON: 02497 net80211_update_link_quality ( dev, iob ); 02498 /* fall through */ 02499 case IEEE80211_STYPE_PROBE_RESP: 02500 case IEEE80211_STYPE_ACTION: 02501 if ( dev->keep_mgmt ) { 02502 struct net80211_rx_info *rxinf; 02503 rxinf = zalloc ( sizeof ( *rxinf ) ); 02504 if ( ! rxinf ) { 02505 DBGC ( dev, "802.11 %p out of memory\n", dev ); 02506 break; 02507 } 02508 rxinf->signal = signal; 02509 list_add_tail ( &iob->list, &dev->mgmt_queue ); 02510 list_add_tail ( &rxinf->list, &dev->mgmt_info_queue ); 02511 keep = 1; 02512 } 02513 break; 02514 02515 case IEEE80211_STYPE_PROBE_REQ: 02516 /* Some nodes send these broadcast. Ignore them. */ 02517 break; 02518 02519 case IEEE80211_STYPE_ASSOC_REQ: 02520 case IEEE80211_STYPE_REASSOC_REQ: 02521 /* We should never receive these, only send them. */ 02522 DBGC ( dev, "802.11 %p received strange management request " 02523 "(%04x)\n", dev, stype ); 02524 break; 02525 02526 default: 02527 DBGC ( dev, "802.11 %p received unimplemented management " 02528 "packet (%04x)\n", dev, stype ); 02529 break; 02530 } 02531 02532 if ( ! keep ) 02533 free_iob ( iob ); 02534 }
1.5.7.1