ieee80211_scan.c revision 188776
1/*- 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_scan.c 188776 2009-02-19 04:37:44Z sam $"); 28 29/* 30 * IEEE 802.11 scanning support. 31 */ 32#include "opt_wlan.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37 38#include <sys/socket.h> 39 40#include <net/if.h> 41#include <net/if_media.h> 42#include <net/ethernet.h> 43 44#include <net80211/ieee80211_var.h> 45 46#include <net/bpf.h> 47 48struct scan_state { 49 struct ieee80211_scan_state base; /* public state */ 50 51 u_int ss_iflags; /* flags used internally */ 52#define ISCAN_MINDWELL 0x0001 /* min dwell time reached */ 53#define ISCAN_DISCARD 0x0002 /* discard rx'd frames */ 54#define ISCAN_CANCEL 0x0004 /* cancel current scan */ 55#define ISCAN_START 0x0008 /* 1st time through next_scan */ 56 unsigned long ss_chanmindwell; /* min dwell on curchan */ 57 unsigned long ss_scanend; /* time scan must stop */ 58 u_int ss_duration; /* duration for next scan */ 59 struct callout ss_scan_timer; /* scan timer */ 60}; 61#define SCAN_PRIVATE(ss) ((struct scan_state *) ss) 62 63/* 64 * Amount of time to go off-channel during a background 65 * scan. This value should be large enough to catch most 66 * ap's but short enough that we can return on-channel 67 * before our listen interval expires. 68 * 69 * XXX tunable 70 * XXX check against configured listen interval 71 */ 72#define IEEE80211_SCAN_OFFCHANNEL msecs_to_ticks(150) 73 74/* 75 * Roaming-related defaults. RSSI thresholds are as returned by the 76 * driver (.5dBm). Transmit rate thresholds are IEEE rate codes (i.e 77 * .5M units) or MCS. 78 */ 79/* rssi thresholds */ 80#define ROAM_RSSI_11A_DEFAULT 14 /* 11a bss */ 81#define ROAM_RSSI_11B_DEFAULT 14 /* 11b bss */ 82#define ROAM_RSSI_11BONLY_DEFAULT 14 /* 11b-only bss */ 83/* transmit rate thresholds */ 84#define ROAM_RATE_11A_DEFAULT 2*12 /* 11a bss */ 85#define ROAM_RATE_11B_DEFAULT 2*5 /* 11b bss */ 86#define ROAM_RATE_11BONLY_DEFAULT 2*1 /* 11b-only bss */ 87#define ROAM_MCS_11N_DEFAULT (1 | IEEE80211_RATE_MCS) /* 11n bss */ 88 89static void scan_restart_pwrsav(void *); 90static void scan_curchan(struct ieee80211_scan_state *, unsigned long); 91static void scan_mindwell(struct ieee80211_scan_state *); 92static void scan_next(void *); 93 94MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state"); 95 96void 97ieee80211_scan_attach(struct ieee80211com *ic) 98{ 99 struct scan_state *ss; 100 101 ss = (struct scan_state *) malloc(sizeof(struct scan_state), 102 M_80211_SCAN, M_NOWAIT | M_ZERO); 103 if (ss == NULL) { 104 ic->ic_scan = NULL; 105 return; 106 } 107 callout_init_mtx(&ss->ss_scan_timer, IEEE80211_LOCK_OBJ(ic), 0); 108 ic->ic_scan = &ss->base; 109 110 ic->ic_scan_curchan = scan_curchan; 111 ic->ic_scan_mindwell = scan_mindwell; 112} 113 114void 115ieee80211_scan_detach(struct ieee80211com *ic) 116{ 117 struct ieee80211_scan_state *ss = ic->ic_scan; 118 119 if (ss != NULL) { 120 callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer); 121 if (ss->ss_ops != NULL) { 122 ss->ss_ops->scan_detach(ss); 123 ss->ss_ops = NULL; 124 } 125 ic->ic_flags &= ~IEEE80211_F_SCAN; 126 ic->ic_scan = NULL; 127 free(SCAN_PRIVATE(ss), M_80211_SCAN); 128 } 129} 130 131static const struct ieee80211_roamparam defroam[IEEE80211_MODE_MAX] = { 132 [IEEE80211_MODE_11A] = { .rssi = ROAM_RSSI_11A_DEFAULT, 133 .rate = ROAM_RATE_11A_DEFAULT }, 134 [IEEE80211_MODE_11G] = { .rssi = ROAM_RSSI_11B_DEFAULT, 135 .rate = ROAM_RATE_11B_DEFAULT }, 136 [IEEE80211_MODE_11B] = { .rssi = ROAM_RSSI_11BONLY_DEFAULT, 137 .rate = ROAM_RATE_11BONLY_DEFAULT }, 138 [IEEE80211_MODE_TURBO_A]= { .rssi = ROAM_RSSI_11A_DEFAULT, 139 .rate = ROAM_RATE_11A_DEFAULT }, 140 [IEEE80211_MODE_TURBO_G]= { .rssi = ROAM_RSSI_11A_DEFAULT, 141 .rate = ROAM_RATE_11A_DEFAULT }, 142 [IEEE80211_MODE_STURBO_A]={ .rssi = ROAM_RSSI_11A_DEFAULT, 143 .rate = ROAM_RATE_11A_DEFAULT }, 144 [IEEE80211_MODE_11NA] = { .rssi = ROAM_RSSI_11A_DEFAULT, 145 .rate = ROAM_MCS_11N_DEFAULT }, 146 [IEEE80211_MODE_11NG] = { .rssi = ROAM_RSSI_11B_DEFAULT, 147 .rate = ROAM_MCS_11N_DEFAULT }, 148}; 149 150void 151ieee80211_scan_vattach(struct ieee80211vap *vap) 152{ 153 vap->iv_bgscanidle = (IEEE80211_BGSCAN_IDLE_DEFAULT*1000)/hz; 154 vap->iv_bgscanintvl = IEEE80211_BGSCAN_INTVAL_DEFAULT*hz; 155 vap->iv_scanvalid = IEEE80211_SCAN_VALID_DEFAULT*hz; 156 157 vap->iv_roaming = IEEE80211_ROAMING_AUTO; 158 memcpy(vap->iv_roamparms, defroam, sizeof(defroam)); 159} 160 161void 162ieee80211_scan_vdetach(struct ieee80211vap *vap) 163{ 164 struct ieee80211com *ic = vap->iv_ic; 165 struct ieee80211_scan_state *ss; 166 167 IEEE80211_LOCK(ic); 168 ss = ic->ic_scan; 169 if (ss != NULL && ss->ss_vap == vap) { 170 if (ic->ic_flags & IEEE80211_F_SCAN) { 171 /* XXX callout_drain */ 172 callout_stop(&SCAN_PRIVATE(ss)->ss_scan_timer); 173 ic->ic_flags &= ~IEEE80211_F_SCAN; 174 } 175 if (ss->ss_ops != NULL) { 176 ss->ss_ops->scan_detach(ss); 177 ss->ss_ops = NULL; 178 } 179 ss->ss_vap = NULL; 180 } 181 IEEE80211_UNLOCK(ic); 182} 183 184/* 185 * Simple-minded scanner module support. 186 */ 187static const char *scan_modnames[IEEE80211_OPMODE_MAX] = { 188 "wlan_scan_sta", /* IEEE80211_M_IBSS */ 189 "wlan_scan_sta", /* IEEE80211_M_STA */ 190 "wlan_scan_wds", /* IEEE80211_M_WDS */ 191 "wlan_scan_sta", /* IEEE80211_M_AHDEMO */ 192 "wlan_scan_ap", /* IEEE80211_M_HOSTAP */ 193 "wlan_scan_monitor", /* IEEE80211_M_MONITOR */ 194}; 195static const struct ieee80211_scanner *scanners[IEEE80211_OPMODE_MAX]; 196 197const struct ieee80211_scanner * 198ieee80211_scanner_get(enum ieee80211_opmode mode) 199{ 200 if (mode >= IEEE80211_OPMODE_MAX) 201 return NULL; 202 if (scanners[mode] == NULL) 203 ieee80211_load_module(scan_modnames[mode]); 204 return scanners[mode]; 205} 206 207void 208ieee80211_scanner_register(enum ieee80211_opmode mode, 209 const struct ieee80211_scanner *scan) 210{ 211 if (mode >= IEEE80211_OPMODE_MAX) 212 return; 213 scanners[mode] = scan; 214} 215 216void 217ieee80211_scanner_unregister(enum ieee80211_opmode mode, 218 const struct ieee80211_scanner *scan) 219{ 220 if (mode >= IEEE80211_OPMODE_MAX) 221 return; 222 if (scanners[mode] == scan) 223 scanners[mode] = NULL; 224} 225 226void 227ieee80211_scanner_unregister_all(const struct ieee80211_scanner *scan) 228{ 229 int m; 230 231 for (m = 0; m < IEEE80211_OPMODE_MAX; m++) 232 if (scanners[m] == scan) 233 scanners[m] = NULL; 234} 235 236/* 237 * Update common scanner state to reflect the current 238 * operating mode. This is called when the state machine 239 * is transitioned to RUN state w/o scanning--e.g. when 240 * operating in monitor mode. The purpose of this is to 241 * ensure later callbacks find ss_ops set to properly 242 * reflect current operating mode. 243 */ 244static void 245scan_update_locked(struct ieee80211vap *vap, 246 const struct ieee80211_scanner *scan) 247{ 248 struct ieee80211com *ic = vap->iv_ic; 249 struct ieee80211_scan_state *ss = ic->ic_scan; 250 251 IEEE80211_LOCK_ASSERT(ic); 252 253#ifdef IEEE80211_DEBUG 254 if (ss->ss_vap != vap || ss->ss_ops != scan) { 255 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 256 "%s: current scanner is <%s:%s>, switch to <%s:%s>\n", 257 __func__, 258 ss->ss_vap != NULL ? 259 ss->ss_vap->iv_ifp->if_xname : "none", 260 ss->ss_vap != NULL ? 261 ieee80211_opmode_name[ss->ss_vap->iv_opmode] : "none", 262 vap->iv_ifp->if_xname, 263 ieee80211_opmode_name[vap->iv_opmode]); 264 } 265#endif 266 ss->ss_vap = vap; 267 if (ss->ss_ops != scan) { 268 /* 269 * Switch scanners; detach old, attach new. Special 270 * case where a single scan module implements multiple 271 * policies by using different scan ops but a common 272 * core. We assume if the old and new attach methods 273 * are identical then it's ok to just change ss_ops 274 * and not flush the internal state of the module. 275 */ 276 if (scan == NULL || ss->ss_ops == NULL || 277 ss->ss_ops->scan_attach != scan->scan_attach) { 278 if (ss->ss_ops != NULL) 279 ss->ss_ops->scan_detach(ss); 280 if (scan != NULL && !scan->scan_attach(ss)) { 281 /* XXX attach failure */ 282 /* XXX stat+msg */ 283 scan = NULL; 284 } 285 } 286 ss->ss_ops = scan; 287 } 288} 289 290static void 291change_channel(struct ieee80211com *ic, 292 struct ieee80211_channel *chan) 293{ 294 ic->ic_curchan = chan; 295 ic->ic_set_channel(ic); 296} 297 298static char 299channel_type(const struct ieee80211_channel *c) 300{ 301 if (IEEE80211_IS_CHAN_ST(c)) 302 return 'S'; 303 if (IEEE80211_IS_CHAN_108A(c)) 304 return 'T'; 305 if (IEEE80211_IS_CHAN_108G(c)) 306 return 'G'; 307 if (IEEE80211_IS_CHAN_HT(c)) 308 return 'n'; 309 if (IEEE80211_IS_CHAN_A(c)) 310 return 'a'; 311 if (IEEE80211_IS_CHAN_ANYG(c)) 312 return 'g'; 313 if (IEEE80211_IS_CHAN_B(c)) 314 return 'b'; 315 return 'f'; 316} 317 318void 319ieee80211_scan_dump_channels(const struct ieee80211_scan_state *ss) 320{ 321 struct ieee80211com *ic = ss->ss_vap->iv_ic; 322 const char *sep; 323 int i; 324 325 sep = ""; 326 for (i = ss->ss_next; i < ss->ss_last; i++) { 327 const struct ieee80211_channel *c = ss->ss_chans[i]; 328 329 printf("%s%u%c", sep, ieee80211_chan2ieee(ic, c), 330 channel_type(c)); 331 sep = ", "; 332 } 333} 334 335#ifdef IEEE80211_DEBUG 336static void 337scan_dump(struct ieee80211_scan_state *ss) 338{ 339 struct ieee80211vap *vap = ss->ss_vap; 340 341 if_printf(vap->iv_ifp, "scan set "); 342 ieee80211_scan_dump_channels(ss); 343 printf(" dwell min %lu max %lu\n", ss->ss_mindwell, ss->ss_maxdwell); 344} 345#endif /* IEEE80211_DEBUG */ 346 347/* 348 * Enable station power save mode and start/restart the scanning thread. 349 */ 350static void 351scan_restart_pwrsav(void *arg) 352{ 353 struct scan_state *ss = (struct scan_state *) arg; 354 struct ieee80211vap *vap = ss->base.ss_vap; 355 struct ieee80211com *ic = vap->iv_ic; 356 int ticksdelay; 357 358 ieee80211_sta_pwrsave(vap, 1); 359 /* 360 * Use an initial 1ms delay so the null 361 * data frame has a chance to go out. 362 * XXX 1ms is a lot, better to trigger scan 363 * on tx complete. 364 */ 365 ticksdelay = msecs_to_ticks(1); 366 if (ticksdelay < 1) 367 ticksdelay = 1; 368 ic->ic_scan_start(ic); /* notify driver */ 369 ss->ss_scanend = ticks + ticksdelay + ss->ss_duration; 370 ss->ss_iflags |= ISCAN_START; 371 callout_reset(&ss->ss_scan_timer, ticksdelay, scan_next, ss); 372} 373 374/* 375 * Start/restart scanning. If we're operating in station mode 376 * and associated notify the ap we're going into power save mode 377 * and schedule a callback to initiate the work (where there's a 378 * better context for doing the work). Otherwise, start the scan 379 * directly. 380 */ 381static int 382scan_restart(struct scan_state *ss, u_int duration) 383{ 384 struct ieee80211vap *vap = ss->base.ss_vap; 385 struct ieee80211com *ic = vap->iv_ic; 386 int defer = 0; 387 388 if (ss->base.ss_next == ss->base.ss_last) { 389 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 390 "%s: no channels to scan\n", __func__); 391 return 0; 392 } 393 if (vap->iv_opmode == IEEE80211_M_STA && 394 vap->iv_state == IEEE80211_S_RUN) { 395 if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) { 396 /* 397 * Initiate power save before going off-channel. 398 * Note that we cannot do this directly because 399 * of locking issues; instead we defer it to a 400 * tasklet. 401 */ 402 ss->ss_duration = duration; 403 defer = 1; 404 } 405 } 406 407 if (!defer) { 408 ic->ic_scan_start(ic); /* notify driver */ 409 ss->ss_scanend = ticks + duration; 410 ss->ss_iflags |= ISCAN_START; 411 callout_reset(&ss->ss_scan_timer, 0, scan_next, ss); 412 } else 413 scan_restart_pwrsav(ss); 414 return 1; 415} 416 417static void 418copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss, 419 int nssid, const struct ieee80211_scan_ssid ssids[]) 420{ 421 if (nssid > IEEE80211_SCAN_MAX_SSID) { 422 /* XXX printf */ 423 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 424 "%s: too many ssid %d, ignoring all of them\n", 425 __func__, nssid); 426 return; 427 } 428 memcpy(ss->ss_ssid, ssids, nssid * sizeof(ssids[0])); 429 ss->ss_nssid = nssid; 430} 431 432/* 433 * Start a scan unless one is already going. 434 */ 435static int 436start_scan_locked(const struct ieee80211_scanner *scan, 437 struct ieee80211vap *vap, int flags, u_int duration, 438 u_int mindwell, u_int maxdwell, 439 u_int nssid, const struct ieee80211_scan_ssid ssids[]) 440{ 441 struct ieee80211com *ic = vap->iv_ic; 442 struct ieee80211_scan_state *ss = ic->ic_scan; 443 444 IEEE80211_LOCK_ASSERT(ic); 445 446 if (ic->ic_flags & IEEE80211_F_CSAPENDING) { 447 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 448 "%s: scan inhibited by pending channel change\n", __func__); 449 } else if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { 450 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 451 "%s: %s scan, duration %u mindwell %u maxdwell %u, desired mode %s, %s%s%s%s%s%s\n" 452 , __func__ 453 , flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive" 454 , duration, mindwell, maxdwell 455 , ieee80211_phymode_name[vap->iv_des_mode] 456 , flags & IEEE80211_SCAN_FLUSH ? "flush" : "append" 457 , flags & IEEE80211_SCAN_NOPICK ? ", nopick" : "" 458 , flags & IEEE80211_SCAN_NOJOIN ? ", nojoin" : "" 459 , flags & IEEE80211_SCAN_NOBCAST ? ", nobcast" : "" 460 , flags & IEEE80211_SCAN_PICK1ST ? ", pick1st" : "" 461 , flags & IEEE80211_SCAN_ONCE ? ", once" : "" 462 ); 463 464 scan_update_locked(vap, scan); 465 if (ss->ss_ops != NULL) { 466 if ((flags & IEEE80211_SCAN_NOSSID) == 0) 467 copy_ssid(vap, ss, nssid, ssids); 468 469 /* NB: top 4 bits for internal use */ 470 ss->ss_flags = flags & 0xfff; 471 if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) 472 vap->iv_stats.is_scan_active++; 473 else 474 vap->iv_stats.is_scan_passive++; 475 if (flags & IEEE80211_SCAN_FLUSH) 476 ss->ss_ops->scan_flush(ss); 477 478 /* NB: flush frames rx'd before 1st channel change */ 479 SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; 480 ss->ss_next = 0; 481 ss->ss_mindwell = mindwell; 482 ss->ss_maxdwell = maxdwell; 483 ss->ss_ops->scan_start(ss, vap); 484#ifdef IEEE80211_DEBUG 485 if (ieee80211_msg_scan(vap)) 486 scan_dump(ss); 487#endif /* IEEE80211_DEBUG */ 488 if (scan_restart(SCAN_PRIVATE(ss), duration)) 489 ic->ic_flags |= IEEE80211_F_SCAN; 490 } 491 } else { 492 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 493 "%s: %s scan already in progress\n", __func__, 494 ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive"); 495 } 496 return (ic->ic_flags & IEEE80211_F_SCAN); 497} 498 499/* 500 * Start a scan unless one is already going. 501 */ 502int 503ieee80211_start_scan(struct ieee80211vap *vap, int flags, 504 u_int duration, u_int mindwell, u_int maxdwell, 505 u_int nssid, const struct ieee80211_scan_ssid ssids[]) 506{ 507 struct ieee80211com *ic = vap->iv_ic; 508 const struct ieee80211_scanner *scan; 509 int result; 510 511 scan = ieee80211_scanner_get(vap->iv_opmode); 512 if (scan == NULL) { 513 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 514 "%s: no scanner support for %s mode\n", 515 __func__, ieee80211_opmode_name[vap->iv_opmode]); 516 /* XXX stat */ 517 return 0; 518 } 519 520 IEEE80211_LOCK(ic); 521 result = start_scan_locked(scan, vap, flags, duration, 522 mindwell, maxdwell, nssid, ssids); 523 IEEE80211_UNLOCK(ic); 524 525 return result; 526} 527 528/* 529 * Check the scan cache for an ap/channel to use; if that 530 * fails then kick off a new scan. 531 */ 532int 533ieee80211_check_scan(struct ieee80211vap *vap, int flags, 534 u_int duration, u_int mindwell, u_int maxdwell, 535 u_int nssid, const struct ieee80211_scan_ssid ssids[]) 536{ 537 struct ieee80211com *ic = vap->iv_ic; 538 struct ieee80211_scan_state *ss = ic->ic_scan; 539 const struct ieee80211_scanner *scan; 540 int result; 541 542 scan = ieee80211_scanner_get(vap->iv_opmode); 543 if (scan == NULL) { 544 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 545 "%s: no scanner support for %s mode\n", 546 __func__, vap->iv_opmode); 547 /* XXX stat */ 548 return 0; 549 } 550 551 /* 552 * Check if there's a list of scan candidates already. 553 * XXX want more than the ap we're currently associated with 554 */ 555 556 IEEE80211_LOCK(ic); 557 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 558 "%s: %s scan, %s%s%s%s%s\n" 559 , __func__ 560 , flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive" 561 , flags & IEEE80211_SCAN_FLUSH ? "flush" : "append" 562 , flags & IEEE80211_SCAN_NOPICK ? ", nopick" : "" 563 , flags & IEEE80211_SCAN_NOJOIN ? ", nojoin" : "" 564 , flags & IEEE80211_SCAN_PICK1ST ? ", pick1st" : "" 565 , flags & IEEE80211_SCAN_ONCE ? ", once" : "" 566 ); 567 568 if (ss->ss_ops != scan) { 569 /* XXX re-use cache contents? e.g. adhoc<->sta */ 570 flags |= IEEE80211_SCAN_FLUSH; 571 } 572 scan_update_locked(vap, scan); 573 if (ss->ss_ops != NULL) { 574 /* XXX verify ss_ops matches vap->iv_opmode */ 575 if ((flags & IEEE80211_SCAN_NOSSID) == 0) { 576 /* 577 * Update the ssid list and mark flags so if 578 * we call start_scan it doesn't duplicate work. 579 */ 580 copy_ssid(vap, ss, nssid, ssids); 581 flags |= IEEE80211_SCAN_NOSSID; 582 } 583 if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 && 584 (flags & IEEE80211_SCAN_FLUSH) == 0 && 585 time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) { 586 /* 587 * We're not currently scanning and the cache is 588 * deemed hot enough to consult. Lock out others 589 * by marking IEEE80211_F_SCAN while we decide if 590 * something is already in the scan cache we can 591 * use. Also discard any frames that might come 592 * in while temporarily marked as scanning. 593 */ 594 SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; 595 ic->ic_flags |= IEEE80211_F_SCAN; 596 597 /* NB: need to use supplied flags in check */ 598 ss->ss_flags = flags & 0xff; 599 result = ss->ss_ops->scan_end(ss, vap); 600 601 ic->ic_flags &= ~IEEE80211_F_SCAN; 602 SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_DISCARD; 603 if (result) { 604 ieee80211_notify_scan_done(vap); 605 IEEE80211_UNLOCK(ic); 606 return 1; 607 } 608 } 609 } 610 result = start_scan_locked(scan, vap, flags, duration, 611 mindwell, maxdwell, nssid, ssids); 612 IEEE80211_UNLOCK(ic); 613 614 return result; 615} 616 617/* 618 * Check the scan cache for an ap/channel to use; if that fails 619 * then kick off a scan using the current settings. 620 */ 621int 622ieee80211_check_scan_current(struct ieee80211vap *vap) 623{ 624 return ieee80211_check_scan(vap, 625 IEEE80211_SCAN_ACTIVE, 626 IEEE80211_SCAN_FOREVER, 0, 0, 627 vap->iv_des_nssid, vap->iv_des_ssid); 628} 629 630/* 631 * Restart a previous scan. If the previous scan completed 632 * then we start again using the existing channel list. 633 */ 634int 635ieee80211_bg_scan(struct ieee80211vap *vap, int flags) 636{ 637 struct ieee80211com *ic = vap->iv_ic; 638 struct ieee80211_scan_state *ss = ic->ic_scan; 639 const struct ieee80211_scanner *scan; 640 641 scan = ieee80211_scanner_get(vap->iv_opmode); 642 if (scan == NULL) { 643 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 644 "%s: no scanner support for %s mode\n", 645 __func__, vap->iv_opmode); 646 /* XXX stat */ 647 return 0; 648 } 649 650 IEEE80211_LOCK(ic); 651 if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { 652 u_int duration; 653 /* 654 * Go off-channel for a fixed interval that is large 655 * enough to catch most ap's but short enough that 656 * we can return on-channel before our listen interval 657 * expires. 658 */ 659 duration = IEEE80211_SCAN_OFFCHANNEL; 660 661 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 662 "%s: %s scan, ticks %u duration %lu\n", __func__, 663 ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive", 664 ticks, duration); 665 666 scan_update_locked(vap, scan); 667 if (ss->ss_ops != NULL) { 668 ss->ss_vap = vap; 669 /* 670 * A background scan does not select a new sta; it 671 * just refreshes the scan cache. Also, indicate 672 * the scan logic should follow the beacon schedule: 673 * we go off-channel and scan for a while, then 674 * return to the bss channel to receive a beacon, 675 * then go off-channel again. All during this time 676 * we notify the ap we're in power save mode. When 677 * the scan is complete we leave power save mode. 678 * If any beacon indicates there are frames pending 679 * for us then we drop out of power save mode 680 * (and background scan) automatically by way of the 681 * usual sta power save logic. 682 */ 683 ss->ss_flags |= IEEE80211_SCAN_NOPICK 684 | IEEE80211_SCAN_BGSCAN 685 | flags 686 ; 687 /* if previous scan completed, restart */ 688 if (ss->ss_next >= ss->ss_last) { 689 if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) 690 vap->iv_stats.is_scan_active++; 691 else 692 vap->iv_stats.is_scan_passive++; 693 /* 694 * NB: beware of the scan cache being flushed; 695 * if the channel list is empty use the 696 * scan_start method to populate it. 697 */ 698 ss->ss_next = 0; 699 if (ss->ss_last != 0) 700 ss->ss_ops->scan_restart(ss, vap); 701 else { 702 ss->ss_ops->scan_start(ss, vap); 703#ifdef IEEE80211_DEBUG 704 if (ieee80211_msg_scan(vap)) 705 scan_dump(ss); 706#endif /* IEEE80211_DEBUG */ 707 } 708 } 709 /* NB: flush frames rx'd before 1st channel change */ 710 SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; 711 ss->ss_maxdwell = duration; 712 if (scan_restart(SCAN_PRIVATE(ss), duration)) { 713 ic->ic_flags |= IEEE80211_F_SCAN; 714 ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN; 715 } 716 } else { 717 /* XXX msg+stat */ 718 } 719 } else { 720 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 721 "%s: %s scan already in progress\n", __func__, 722 ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive"); 723 } 724 IEEE80211_UNLOCK(ic); 725 726 /* NB: racey, does it matter? */ 727 return (ic->ic_flags & IEEE80211_F_SCAN); 728} 729 730/* 731 * Cancel any scan currently going on for the specified vap. 732 */ 733void 734ieee80211_cancel_scan(struct ieee80211vap *vap) 735{ 736 struct ieee80211com *ic = vap->iv_ic; 737 struct ieee80211_scan_state *ss = ic->ic_scan; 738 739 IEEE80211_LOCK(ic); 740 if ((ic->ic_flags & IEEE80211_F_SCAN) && 741 ss->ss_vap == vap && 742 (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) { 743 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 744 "%s: cancel %s scan\n", __func__, 745 ss->ss_flags & IEEE80211_SCAN_ACTIVE ? 746 "active" : "passive"); 747 748 /* clear bg scan NOPICK and mark cancel request */ 749 ss->ss_flags &= ~IEEE80211_SCAN_NOPICK; 750 SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL; 751 /* force it to fire asap */ 752 callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 753 0, scan_next, ss); 754 } 755 IEEE80211_UNLOCK(ic); 756} 757 758/* 759 * Cancel any scan currently going on. 760 */ 761void 762ieee80211_cancel_anyscan(struct ieee80211vap *vap) 763{ 764 struct ieee80211com *ic = vap->iv_ic; 765 struct ieee80211_scan_state *ss = ic->ic_scan; 766 767 IEEE80211_LOCK(ic); 768 if ((ic->ic_flags & IEEE80211_F_SCAN) && 769 (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) { 770 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 771 "%s: cancel %s scan\n", __func__, 772 ss->ss_flags & IEEE80211_SCAN_ACTIVE ? 773 "active" : "passive"); 774 775 /* clear bg scan NOPICK and mark cancel request */ 776 ss->ss_flags &= ~IEEE80211_SCAN_NOPICK; 777 SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL; 778 /* force it to fire asap */ 779 callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 780 0, scan_next, ss); 781 } 782 IEEE80211_UNLOCK(ic); 783} 784 785/* 786 * Public access to scan_next for drivers that manage 787 * scanning themselves (e.g. for firmware-based devices). 788 */ 789void 790ieee80211_scan_next(struct ieee80211vap *vap) 791{ 792 struct ieee80211com *ic = vap->iv_ic; 793 struct ieee80211_scan_state *ss = ic->ic_scan; 794 795 callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 0, scan_next, ss); 796} 797 798/* 799 * Public access to scan_next for drivers that are not able to scan single 800 * channels (e.g. for firmware-based devices). 801 */ 802void 803ieee80211_scan_done(struct ieee80211vap *vap) 804{ 805 struct ieee80211com *ic = vap->iv_ic; 806 struct ieee80211_scan_state *ss; 807 808 IEEE80211_LOCK(ic); 809 ss = ic->ic_scan; 810 ss->ss_next = ss->ss_last; /* all channels are complete */ 811 scan_next(ss); 812 IEEE80211_UNLOCK(ic); 813} 814 815/* 816 * Probe the curent channel, if allowed, while scanning. 817 * If the channel is not marked passive-only then send 818 * a probe request immediately. Otherwise mark state and 819 * listen for beacons on the channel; if we receive something 820 * then we'll transmit a probe request. 821 */ 822void 823ieee80211_probe_curchan(struct ieee80211vap *vap, int force) 824{ 825 struct ieee80211com *ic = vap->iv_ic; 826 struct ieee80211_scan_state *ss = ic->ic_scan; 827 struct ifnet *ifp = vap->iv_ifp; 828 int i; 829 830 if ((ic->ic_curchan->ic_flags & IEEE80211_CHAN_PASSIVE) && !force) { 831 ic->ic_flags_ext |= IEEE80211_FEXT_PROBECHAN; 832 return; 833 } 834 /* 835 * Send directed probe requests followed by any 836 * broadcast probe request. 837 * XXX remove dependence on ic/vap->iv_bss 838 */ 839 for (i = 0; i < ss->ss_nssid; i++) 840 ieee80211_send_probereq(vap->iv_bss, 841 vap->iv_myaddr, ifp->if_broadcastaddr, 842 ifp->if_broadcastaddr, 843 ss->ss_ssid[i].ssid, ss->ss_ssid[i].len); 844 if ((ss->ss_flags & IEEE80211_SCAN_NOBCAST) == 0) 845 ieee80211_send_probereq(vap->iv_bss, 846 vap->iv_myaddr, ifp->if_broadcastaddr, 847 ifp->if_broadcastaddr, 848 "", 0); 849} 850 851/* 852 * Scan curchan. If this is an active scan and the channel 853 * is not marked passive then send probe request frame(s). 854 * Arrange for the channel change after maxdwell ticks. 855 */ 856static void 857scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) 858{ 859 struct ieee80211vap *vap = ss->ss_vap; 860 861 IEEE80211_LOCK_ASSERT(vap->iv_ic); 862 863 if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) 864 ieee80211_probe_curchan(vap, 0); 865 callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 866 maxdwell, scan_next, ss); 867} 868 869/* 870 * Handle mindwell requirements completed; initiate a channel 871 * change to the next channel asap. 872 */ 873static void 874scan_mindwell(struct ieee80211_scan_state *ss) 875{ 876 callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 0, scan_next, ss); 877} 878 879/* 880 * Switch to the next channel marked for scanning. 881 */ 882static void 883scan_next(void *arg) 884{ 885#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_START | ISCAN_DISCARD) 886 struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg; 887 struct ieee80211vap *vap = ss->ss_vap; 888 struct ieee80211com *ic = vap->iv_ic; 889 struct ieee80211_channel *chan; 890 unsigned long maxdwell, scanend; 891 int scandone; 892 893 IEEE80211_LOCK_ASSERT(ic); 894 895 if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) 896 return; 897again: 898 scandone = (ss->ss_next >= ss->ss_last) || 899 (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0; 900 scanend = SCAN_PRIVATE(ss)->ss_scanend; 901 if (!scandone && 902 (ss->ss_flags & IEEE80211_SCAN_GOTPICK) == 0 && 903 ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_START) || 904 time_before(ticks + ss->ss_mindwell, scanend))) { 905 chan = ss->ss_chans[ss->ss_next++]; 906 907 /* 908 * Watch for truncation due to the scan end time. 909 */ 910 if (time_after(ticks + ss->ss_maxdwell, scanend)) 911 maxdwell = scanend - ticks; 912 else 913 maxdwell = ss->ss_maxdwell; 914 915 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 916 "%s: chan %3d%c -> %3d%c [%s, dwell min %lu max %lu]\n", 917 __func__, 918 ieee80211_chan2ieee(ic, ic->ic_curchan), 919 channel_type(ic->ic_curchan), 920 ieee80211_chan2ieee(ic, chan), channel_type(chan), 921 (ss->ss_flags & IEEE80211_SCAN_ACTIVE) && 922 (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ? 923 "active" : "passive", 924 ss->ss_mindwell, maxdwell); 925 926 /* 927 * Potentially change channel and phy mode. 928 */ 929 change_channel(ic, chan); 930 931 /* 932 * Scan curchan. Drivers for "intelligent hardware" 933 * override ic_scan_curchan to tell the device to do 934 * the work. Otherwise we manage the work outselves; 935 * sending a probe request (as needed), and arming the 936 * timeout to switch channels after maxdwell ticks. 937 */ 938 ic->ic_scan_curchan(ss, maxdwell); 939 940 SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell; 941 /* clear mindwell lock and initial channel change flush */ 942 SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP; 943 } else { 944 ic->ic_scan_end(ic); /* notify driver */ 945 /* 946 * Record scan complete time. Note that we also do 947 * this when canceled so any background scan will 948 * not be restarted for a while. 949 */ 950 if (scandone) 951 ic->ic_lastscan = ticks; 952 /* return to the bss channel */ 953 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && 954 ic->ic_curchan != ic->ic_bsschan) 955 ieee80211_setcurchan(ic, ic->ic_bsschan); 956 /* clear internal flags and any indication of a pick */ 957 SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP; 958 ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK; 959 960 /* 961 * If not canceled and scan completed, do post-processing. 962 * If the callback function returns 0, then it wants to 963 * continue/restart scanning. Unfortunately we needed to 964 * notify the driver to end the scan above to avoid having 965 * rx frames alter the scan candidate list. 966 */ 967 if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 && 968 !ss->ss_ops->scan_end(ss, vap) && 969 (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 && 970 time_before(ticks + ss->ss_mindwell, scanend)) { 971 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 972 "%s: done, restart " 973 "[ticks %u, dwell min %lu scanend %lu]\n", 974 __func__, 975 ticks, ss->ss_mindwell, scanend); 976 ss->ss_next = 0; /* reset to begining */ 977 if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) 978 vap->iv_stats.is_scan_active++; 979 else 980 vap->iv_stats.is_scan_passive++; 981 982 ss->ss_ops->scan_restart(ss, vap); /* XXX? */ 983 ic->ic_scan_start(ic); /* notify driver */ 984 goto again; 985 } else { 986 /* past here, scandone is ``true'' if not in bg mode */ 987 if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0) 988 scandone = 1; 989 990 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 991 "%s: %s, " 992 "[ticks %u, dwell min %lu scanend %lu]\n", 993 __func__, scandone ? "done" : "stopped", 994 ticks, ss->ss_mindwell, scanend); 995 996 /* 997 * Clear the SCAN bit first in case frames are 998 * pending on the station power save queue. If 999 * we defer this then the dispatch of the frames 1000 * may generate a request to cancel scanning. 1001 */ 1002 ic->ic_flags &= ~IEEE80211_F_SCAN; 1003 /* 1004 * Drop out of power save mode when a scan has 1005 * completed. If this scan was prematurely terminated 1006 * because it is a background scan then don't notify 1007 * the ap; we'll either return to scanning after we 1008 * receive the beacon frame or we'll drop out of power 1009 * save mode because the beacon indicates we have frames 1010 * waiting for us. 1011 */ 1012 if (scandone) { 1013 ieee80211_sta_pwrsave(vap, 0); 1014 if (ss->ss_next >= ss->ss_last) { 1015 ieee80211_notify_scan_done(vap); 1016 ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN; 1017 } 1018 } 1019 SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_CANCEL; 1020 ss->ss_flags &= 1021 ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST); 1022 } 1023 } 1024#undef ISCAN_REP 1025} 1026 1027#ifdef IEEE80211_DEBUG 1028static void 1029dump_country(const uint8_t *ie) 1030{ 1031 const struct ieee80211_country_ie *cie = 1032 (const struct ieee80211_country_ie *) ie; 1033 int i, nbands, schan, nchan; 1034 1035 if (cie->len < 3) { 1036 printf(" <bogus country ie, len %d>", cie->len); 1037 return; 1038 } 1039 printf(" country [%c%c%c", cie->cc[0], cie->cc[1], cie->cc[2]); 1040 nbands = (cie->len - 3) / sizeof(cie->band[0]); 1041 for (i = 0; i < nbands; i++) { 1042 schan = cie->band[i].schan; 1043 nchan = cie->band[i].nchan; 1044 if (nchan != 1) 1045 printf(" %u-%u,%u", schan, schan + nchan-1, 1046 cie->band[i].maxtxpwr); 1047 else 1048 printf(" %u,%u", schan, cie->band[i].maxtxpwr); 1049 } 1050 printf("]"); 1051} 1052 1053static void 1054dump_probe_beacon(uint8_t subtype, int isnew, 1055 const uint8_t mac[IEEE80211_ADDR_LEN], 1056 const struct ieee80211_scanparams *sp, int rssi) 1057{ 1058 1059 printf("[%s] %s%s on chan %u (bss chan %u) ", 1060 ether_sprintf(mac), isnew ? "new " : "", 1061 ieee80211_mgt_subtype_name[subtype >> IEEE80211_FC0_SUBTYPE_SHIFT], 1062 sp->chan, sp->bchan); 1063 ieee80211_print_essid(sp->ssid + 2, sp->ssid[1]); 1064 printf(" rssi %d\n", rssi); 1065 1066 if (isnew) { 1067 printf("[%s] caps 0x%x bintval %u erp 0x%x", 1068 ether_sprintf(mac), sp->capinfo, sp->bintval, sp->erp); 1069 if (sp->country != NULL) 1070 dump_country(sp->country); 1071 printf("\n"); 1072 } 1073} 1074#endif /* IEEE80211_DEBUG */ 1075 1076/* 1077 * Process a beacon or probe response frame. 1078 */ 1079void 1080ieee80211_add_scan(struct ieee80211vap *vap, 1081 const struct ieee80211_scanparams *sp, 1082 const struct ieee80211_frame *wh, 1083 int subtype, int rssi, int noise, int rstamp) 1084{ 1085 struct ieee80211com *ic = vap->iv_ic; 1086 struct ieee80211_scan_state *ss = ic->ic_scan; 1087 1088 /* XXX locking */ 1089 /* 1090 * Frames received during startup are discarded to avoid 1091 * using scan state setup on the initial entry to the timer 1092 * callback. This can occur because the device may enable 1093 * rx prior to our doing the initial channel change in the 1094 * timer routine. 1095 */ 1096 if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_DISCARD) 1097 return; 1098#ifdef IEEE80211_DEBUG 1099 if (ieee80211_msg_scan(vap) && (ic->ic_flags & IEEE80211_F_SCAN)) 1100 dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi); 1101#endif 1102 if (ss->ss_ops != NULL && 1103 ss->ss_ops->scan_add(ss, sp, wh, subtype, rssi, noise, rstamp)) { 1104 /* 1105 * If we've reached the min dwell time terminate 1106 * the timer so we'll switch to the next channel. 1107 */ 1108 if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 && 1109 time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) { 1110 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 1111 "%s: chan %3d%c min dwell met (%u > %lu)\n", 1112 __func__, 1113 ieee80211_chan2ieee(ic, ic->ic_curchan), 1114 channel_type(ic->ic_curchan), 1115 ticks, SCAN_PRIVATE(ss)->ss_chanmindwell); 1116 SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_MINDWELL; 1117 /* 1118 * NB: trigger at next clock tick or wait for the 1119 * hardware. 1120 */ 1121 ic->ic_scan_mindwell(ss); 1122 } 1123 } 1124} 1125 1126/* 1127 * Timeout/age scan cache entries; called from sta timeout 1128 * timer (XXX should be self-contained). 1129 */ 1130void 1131ieee80211_scan_timeout(struct ieee80211com *ic) 1132{ 1133 struct ieee80211_scan_state *ss = ic->ic_scan; 1134 1135 if (ss->ss_ops != NULL) 1136 ss->ss_ops->scan_age(ss); 1137} 1138 1139/* 1140 * Mark a scan cache entry after a successful associate. 1141 */ 1142void 1143ieee80211_scan_assoc_success(struct ieee80211vap *vap, const uint8_t mac[]) 1144{ 1145 struct ieee80211_scan_state *ss = vap->iv_ic->ic_scan; 1146 1147 if (ss->ss_ops != NULL) { 1148 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_SCAN, 1149 mac, "%s", __func__); 1150 ss->ss_ops->scan_assoc_success(ss, mac); 1151 } 1152} 1153 1154/* 1155 * Demerit a scan cache entry after failing to associate. 1156 */ 1157void 1158ieee80211_scan_assoc_fail(struct ieee80211vap *vap, 1159 const uint8_t mac[], int reason) 1160{ 1161 struct ieee80211_scan_state *ss = vap->iv_ic->ic_scan; 1162 1163 if (ss->ss_ops != NULL) { 1164 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_SCAN, mac, 1165 "%s: reason %u", __func__, reason); 1166 ss->ss_ops->scan_assoc_fail(ss, mac, reason); 1167 } 1168} 1169 1170/* 1171 * Iterate over the contents of the scan cache. 1172 */ 1173void 1174ieee80211_scan_iterate(struct ieee80211vap *vap, 1175 ieee80211_scan_iter_func *f, void *arg) 1176{ 1177 struct ieee80211_scan_state *ss = vap->iv_ic->ic_scan; 1178 1179 if (ss->ss_ops != NULL) 1180 ss->ss_ops->scan_iterate(ss, f, arg); 1181} 1182 1183/* 1184 * Flush the contents of the scan cache. 1185 */ 1186void 1187ieee80211_scan_flush(struct ieee80211vap *vap) 1188{ 1189 struct ieee80211_scan_state *ss = vap->iv_ic->ic_scan; 1190 1191 if (ss->ss_ops != NULL && ss->ss_vap == vap) { 1192 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s\n", __func__); 1193 ss->ss_ops->scan_flush(ss); 1194 } 1195} 1196 1197/* 1198 * Check the scan cache for an ap/channel to use; if that 1199 * fails then kick off a new scan. 1200 */ 1201struct ieee80211_channel * 1202ieee80211_scan_pickchannel(struct ieee80211com *ic, int flags) 1203{ 1204 struct ieee80211_scan_state *ss = ic->ic_scan; 1205 1206 IEEE80211_LOCK_ASSERT(ic); 1207 1208 if (ss == NULL || ss->ss_ops == NULL || ss->ss_vap == NULL) { 1209 /* XXX printf? */ 1210 return NULL; 1211 } 1212 if (ss->ss_ops->scan_pickchan == NULL) { 1213 IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, 1214 "%s: scan module does not support picking a channel, " 1215 "opmode %s\n", __func__, ss->ss_vap->iv_opmode); 1216 return NULL; 1217 } 1218 return ss->ss_ops->scan_pickchan(ss, flags); 1219} 1220