📄 ieee80211softmac_assoc.c
字号:
*/ if (rssi < net->stats.rssi) { best = net; rssi = best->stats.rssi; } } } /* if we unlock here, we might get interrupted and the `best' * pointer could go stale */ if (best) { found = ieee80211softmac_create_network(mac, best); /* if found is still NULL, then we got -ENOMEM somewhere */ if (found) ieee80211softmac_add_network(mac, found); } spin_unlock_irqrestore(&mac->ieee->lock, flags); } if (!found) { if (mac->associnfo.scan_retry > 0) { mac->associnfo.scan_retry--; /* We know of no such network. Let's scan. * NB: this also happens if we had no memory to copy the network info... * Maybe we can hope to have more memory after scanning finishes ;) */ dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n"); ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); if (ieee80211softmac_start_scan(mac)) { dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); } goto out; } else { mac->associnfo.associating = 0; mac->associnfo.associated = 0; dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); /* reset the retry counter for the next user request since we * break out and don't reschedule ourselves after this point. */ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); goto out; } } /* reset the retry counter for the next user request since we * now found a net and will try to associate to it, but not * schedule this function again. */ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; mac->associnfo.bssvalid = 1; memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); /* copy the ESSID for displaying it */ mac->associnfo.associate_essid.len = found->essid.len; memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); /* we found a network! authenticate (if necessary) and associate to it. */ if (found->authenticating) { dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n"); if(!mac->associnfo.assoc_wait) { mac->associnfo.assoc_wait = 1; ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); } goto out; } if (!found->authenticated && !found->authenticating) { /* This relies on the fact that _auth_req only queues the work, * otherwise adding the notification would be racy. */ if (!ieee80211softmac_auth_req(mac, found)) { if(!mac->associnfo.assoc_wait) { dprintk(KERN_INFO PFX "Cannot associate without being authenticated, requested authentication\n"); mac->associnfo.assoc_wait = 1; ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); } } else { printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n"); mac->associnfo.assoc_wait = 0; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); } goto out; } /* finally! now we can start associating */ mac->associnfo.assoc_wait = 0; ieee80211softmac_assoc(mac, found);out: mutex_unlock(&mac->associnfo.mutex);}/* call this to do whatever is necessary when we're associated */static voidieee80211softmac_associated(struct ieee80211softmac_device *mac, struct ieee80211_assoc_response * resp, struct ieee80211softmac_network *net){ u16 cap = le16_to_cpu(resp->capability); u8 erp_value = net->erp_value; mac->associnfo.associating = 0; mac->bssinfo.supported_rates = net->supported_rates; ieee80211softmac_recalc_txrates(mac); mac->associnfo.associated = 1; mac->associnfo.short_preamble_available = (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0; ieee80211softmac_process_erp(mac, erp_value); if (mac->set_bssid_filter) mac->set_bssid_filter(mac->dev, net->bssid); memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN); netif_carrier_on(mac->dev); mac->association_id = le16_to_cpup(&resp->aid);}/* received frame handling functions */intieee80211softmac_handle_assoc_response(struct net_device * dev, struct ieee80211_assoc_response * resp, struct ieee80211_network * _ieee80211_network){ /* NOTE: the network parameter has to be mostly ignored by * this code because it is the ieee80211's pointer * to the struct, not ours (we made a copy) */ struct ieee80211softmac_device *mac = ieee80211_priv(dev); u16 status = le16_to_cpup(&resp->status); struct ieee80211softmac_network *network = NULL; unsigned long flags; DECLARE_MAC_BUF(mac2); if (unlikely(!mac->running)) return -ENODEV; spin_lock_irqsave(&mac->lock, flags); if (!mac->associnfo.associating) { /* we race against the timeout function, so make sure * only one of us can do work */ spin_unlock_irqrestore(&mac->lock, flags); return 0; } network = ieee80211softmac_get_network_by_bssid_locked(mac, resp->header.addr3); /* someone sending us things without us knowing him? Ignore. */ if (!network) { dprintk(KERN_INFO PFX "Received unrequested assocation response from %s\n", print_mac(mac2, resp->header.addr3)); spin_unlock_irqrestore(&mac->lock, flags); return 0; } /* now that we know it was for us, we can cancel the timeout */ cancel_delayed_work(&mac->associnfo.timeout); /* if the association response included an ERP IE, update our saved * copy */ if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE) network->erp_value = _ieee80211_network->erp_value; switch (status) { case 0: dprintk(KERN_INFO PFX "associated!\n"); ieee80211softmac_associated(mac, resp, network); ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, network); break; case WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH: if (!network->auth_desynced_once) { /* there seem to be a few rare cases where our view of * the world is obscured, or buggy APs that don't DEAUTH * us properly. So we handle that, but allow it only once. */ printkl(KERN_INFO PFX "We were not authenticated during association, retrying...\n"); network->authenticated = 0; /* we don't want to do this more than once ... */ network->auth_desynced_once = 1; queue_delayed_work(mac->wq, &mac->associnfo.work, 0); break; } default: dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); mac->associnfo.associating = 0; mac->associnfo.bssvalid = 0; mac->associnfo.associated = 0; ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); } spin_unlock_irqrestore(&mac->lock, flags); return 0;}voidieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac){ unsigned long flags; spin_lock_irqsave(&mac->lock, flags); mac->associnfo.associating = 1; queue_delayed_work(mac->wq, &mac->associnfo.work, 0); spin_unlock_irqrestore(&mac->lock, flags);}intieee80211softmac_handle_disassoc(struct net_device * dev, struct ieee80211_disassoc *disassoc){ struct ieee80211softmac_device *mac = ieee80211_priv(dev); if (unlikely(!mac->running)) return -ENODEV; if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) return 0; if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) return 0; dprintk(KERN_INFO PFX "got disassoc frame\n"); ieee80211softmac_disassoc(mac); ieee80211softmac_try_reassoc(mac); return 0;}intieee80211softmac_handle_reassoc_req(struct net_device * dev, struct ieee80211_reassoc_request * resp){ struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct ieee80211softmac_network *network; if (unlikely(!mac->running)) return -ENODEV; network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); if (!network) { dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); return 0; } queue_delayed_work(mac->wq, &mac->associnfo.work, 0); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -