/* * Complete a scan of potential channels. */ void ieee80211_end_scan(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; struct ieee80211_node *ni, *nextbs, *selbs; if (ifp->if_flags & IFF_DEBUG) printf("%s: end %s scan\n", ifp->if_xname, (ic->ic_flags & IEEE80211_F_ASCAN) ? "active" : "passive"); if (ic->ic_scan_count) ic->ic_flags &= ~IEEE80211_F_ASCAN; ni = RB_MIN(ieee80211_tree, &ic->ic_tree); #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX off stack? */ u_char occupied[howmany(IEEE80211_CHAN_MAX, NBBY)]; int i, fail; /* * The passive scan to look for existing AP's completed, * select a channel to camp on. Identify the channels * that already have one or more AP's and try to locate * an unnoccupied one. If that fails, pick a random * channel from the active set. */ memset(occupied, 0, sizeof(occupied)); RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) setbit(occupied, ieee80211_chan2ieee(ic, ni->ni_chan)); for (i = 0; i < IEEE80211_CHAN_MAX; i++) if (isset(ic->ic_chan_active, i) && isclr(occupied, i)) break; if (i == IEEE80211_CHAN_MAX) { fail = arc4random() & 3; /* random 0-3 */ for (i = 0; i < IEEE80211_CHAN_MAX; i++) if (isset(ic->ic_chan_active, i) && fail-- == 0) break; } ieee80211_create_ibss(ic, &ic->ic_channels[i]); goto wakeup; } #endif if (ni == NULL) { DPRINTF(("no scan candidate\n")); notfound: #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_IBSS && (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen != 0) { ieee80211_create_ibss(ic, ic->ic_ibss_chan); goto wakeup; } #endif /* * Scan the next mode if nothing has been found. This * is necessary if the device supports different * incompatible modes in the same channel range, like * like 11b and "pure" 11G mode. This will loop * forever except for user-initiated scans. */ if (ieee80211_next_mode(ifp) == IEEE80211_MODE_AUTO) { if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST && ic->ic_scan_lock & IEEE80211_SCAN_RESUME) { ic->ic_scan_lock = IEEE80211_SCAN_LOCKED; /* Return from an user-initiated scan */ wakeup(&ic->ic_scan_lock); } else if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) goto wakeup; ic->ic_scan_count++; } /* * Reset the list of channels to scan and start again. */ ieee80211_next_scan(ifp); return; } selbs = NULL; for (; ni != NULL; ni = nextbs) { nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni); if (ni->ni_fails) { /* * The configuration of the access points may change * during my scan. So delete the entry for the AP * and retry to associate if there is another beacon. */ if (ni->ni_fails++ > 2) ieee80211_free_node(ic, ni); continue; } if (ieee80211_match_bss(ic, ni) == 0) { if (selbs == NULL) selbs = ni; else if (ni->ni_rssi > selbs->ni_rssi) selbs = ni; } } if (selbs == NULL) goto notfound; (*ic->ic_node_copy)(ic, ic->ic_bss, selbs); ni = ic->ic_bss; /* * Set the erp state (mostly the slot time) to deal with * the auto-select case; this should be redundant if the * mode is locked. */ ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan); ieee80211_reset_erp(ic); if (ic->ic_flags & IEEE80211_F_RSNON) ieee80211_choose_rsnparams(ic); else if (ic->ic_flags & IEEE80211_F_WEPON) ni->ni_rsncipher = IEEE80211_CIPHER_USEGROUP; ieee80211_node_newstate(selbs, IEEE80211_STA_BSS); #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_IBSS) { ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); if (ni->ni_rates.rs_nrates == 0) goto notfound; ieee80211_new_state(ic, IEEE80211_S_RUN, -1); } else #endif ieee80211_new_state(ic, IEEE80211_S_AUTH, -1); wakeup: if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) { /* Return from an user-initiated scan */ wakeup(&ic->ic_scan_lock); } ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED; }
/* * Complete a scan of potential channels. */ void Voodoo80211Device:: ieee80211_end_scan(struct ieee80211com *ic) { struct ieee80211_node *ni, *nextbs, *selbs; /* TODO if (ifp->if_flags & IFF_DEBUG) printf("%s: end %s scan\n", ifp->if_xname, (ic->ic_flags & IEEE80211_F_ASCAN) ? "active" : "passive"); */ if (ic->ic_scan_count) ic->ic_flags &= ~IEEE80211_F_ASCAN; ni = RB_MIN(ieee80211_tree, &ic->ic_tree); if (ni == NULL) { DPRINTF(("no scan candidate\n")); notfound: /* * Scan the next mode if nothing has been found. This * is necessary if the device supports different * incompatible modes in the same channel range, like * like 11b and "pure" 11G mode. This will loop * forever except for user-initiated scans. */ if (ieee80211_next_mode(ic) == IEEE80211_MODE_AUTO) { if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST && ic->ic_scan_lock & IEEE80211_SCAN_RESUME) { ic->ic_scan_lock = IEEE80211_SCAN_LOCKED; /* Return from an user-initiated scan */ wakeupOn(&ic->ic_scan_lock); // XXX: pvaibhav: do this here? fInterface->postMessage(APPLE80211_M_SCAN_DONE); } else if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) goto wakeup; ic->ic_scan_count++; } /* * Reset the list of channels to scan and start again. */ ieee80211_next_scan(ic); return; } selbs = NULL; for (; ni != NULL; ni = nextbs) { nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni); if (ni->ni_fails) { /* * The configuration of the access points may change * during my scan. So delete the entry for the AP * and retry to associate if there is another beacon. */ if (ni->ni_fails++ > 2) ieee80211_free_node(ic, ni); continue; } if (ieee80211_match_bss(ic, ni) == 0) { if (selbs == NULL) selbs = ni; else if (ni->ni_rssi > selbs->ni_rssi) selbs = ni; } } if (selbs == NULL) goto notfound; ieee80211_node_copy(ic, ic->ic_bss, selbs); ni = ic->ic_bss; /* * Set the erp state (mostly the slot time) to deal with * the auto-select case; this should be redundant if the * mode is locked. */ ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan); ieee80211_reset_erp(ic); if (ic->ic_flags & IEEE80211_F_RSNON) ieee80211_choose_rsnparams(ic); else if (ic->ic_flags & IEEE80211_F_WEPON) ni->ni_rsncipher = IEEE80211_CIPHER_USEGROUP; ieee80211_node_newstate(selbs, IEEE80211_STA_BSS); ieee80211_newstate(ic, IEEE80211_S_AUTH, -1); wakeup: if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) { /* Return from an user-initiated scan */ wakeupOn(&ic->ic_scan_lock); // XXX: pvaibhav: do this here? fInterface->postMessage(APPLE80211_M_SCAN_DONE); } ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED; }