1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2001 Atsushi Onoe 8 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * Alternatively, this software may be distributed under the terms of the 23 * GNU General Public License ("GPL") version 2 as published by the Free 24 * Software Foundation. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Node management routines 40 */ 41 42 #include "net80211_impl.h" 43 44 static ieee80211_node_t *ieee80211_node_alloc(ieee80211com_t *); 45 static void ieee80211_node_cleanup(ieee80211_node_t *); 46 static void ieee80211_node_free(ieee80211_node_t *); 47 static uint8_t ieee80211_node_getrssi(const ieee80211_node_t *); 48 static void ieee80211_setup_node(ieee80211com_t *, ieee80211_node_table_t *, 49 ieee80211_node_t *, const uint8_t *); 50 static void ieee80211_node_reclaim(ieee80211_node_table_t *, 51 ieee80211_node_t *); 52 static void ieee80211_free_node_locked(ieee80211_node_t *); 53 static void ieee80211_free_allnodes(ieee80211_node_table_t *); 54 static void ieee80211_node_leave(ieee80211com_t *, ieee80211_node_t *); 55 static void ieee80211_timeout_scan_candidates(ieee80211_node_table_t *); 56 static void ieee80211_timeout_stations(ieee80211_node_table_t *); 57 static void ieee80211_node_table_init(ieee80211com_t *, 58 ieee80211_node_table_t *, const char *, int, int, 59 void (*timeout)(ieee80211_node_table_t *)); 60 static void ieee80211_node_table_cleanup(ieee80211_node_table_t *); 61 62 /* 63 * association failures before ignored 64 * The failure may be caused by the response frame is lost for 65 * environmental reason. So Try associate more than once before 66 * ignore the node 67 */ 68 #define IEEE80211_STA_FAILS_MAX 2 69 70 /* 71 * Initialize node database management callbacks for the interface. 72 * This function is called by ieee80211_attach(). These callback 73 * functions may be overridden in special circumstances, as long as 74 * as this is done after calling ieee80211_attach() and prior to any 75 * other call which may allocate a node 76 */ 77 void 78 ieee80211_node_attach(ieee80211com_t *ic) 79 { 80 struct ieee80211_impl *im = ic->ic_private; 81 82 ic->ic_node_alloc = ieee80211_node_alloc; 83 ic->ic_node_free = ieee80211_node_free; 84 ic->ic_node_cleanup = ieee80211_node_cleanup; 85 ic->ic_node_getrssi = ieee80211_node_getrssi; 86 87 /* default station inactivity timer setings */ 88 im->im_inact_init = IEEE80211_INACT_INIT; 89 im->im_inact_assoc = IEEE80211_INACT_ASSOC; 90 im->im_inact_run = IEEE80211_INACT_RUN; 91 im->im_inact_probe = IEEE80211_INACT_PROBE; 92 } 93 94 /* 95 * Initialize node databases and the ic_bss node element. 96 */ 97 void 98 ieee80211_node_lateattach(ieee80211com_t *ic) 99 { 100 /* 101 * Calculate ic_tim_bitmap size in bytes 102 * IEEE80211_AID_MAX defines maximum bits in ic_tim_bitmap 103 */ 104 ic->ic_tim_len = howmany(IEEE80211_AID_MAX, 8) * sizeof (uint8_t); 105 106 ieee80211_node_table_init(ic, &ic->ic_sta, "station", 107 IEEE80211_INACT_INIT, IEEE80211_WEP_NKID, 108 ieee80211_timeout_stations); 109 ieee80211_node_table_init(ic, &ic->ic_scan, "scan", 110 IEEE80211_INACT_SCAN, 0, ieee80211_timeout_scan_candidates); 111 112 ieee80211_reset_bss(ic); 113 } 114 115 /* 116 * Destroy all node databases and is usually called during device detach 117 */ 118 void 119 ieee80211_node_detach(ieee80211com_t *ic) 120 { 121 /* Node Detach */ 122 if (ic->ic_bss != NULL) { 123 ieee80211_free_node(ic->ic_bss); 124 ic->ic_bss = NULL; 125 } 126 ieee80211_node_table_cleanup(&ic->ic_scan); 127 ieee80211_node_table_cleanup(&ic->ic_sta); 128 } 129 130 /* 131 * Increase a node's reference count 132 * 133 * Return pointer to the node 134 */ 135 ieee80211_node_t * 136 ieee80211_ref_node(ieee80211_node_t *in) 137 { 138 ieee80211_node_incref(in); 139 return (in); 140 } 141 142 /* 143 * Dexrease a node's reference count 144 */ 145 void 146 ieee80211_unref_node(ieee80211_node_t **in) 147 { 148 ieee80211_node_decref(*in); 149 *in = NULL; /* guard against use */ 150 } 151 152 /* 153 * Mark ports authorized for data traffic. This function is usually 154 * used by 802.1x authenticator. 155 */ 156 void 157 ieee80211_node_authorize(ieee80211_node_t *in) 158 { 159 ieee80211_impl_t *im = in->in_ic->ic_private; 160 161 in->in_flags |= IEEE80211_NODE_AUTH; 162 in->in_inact_reload = im->im_inact_run; 163 in->in_inact = in->in_inact_reload; 164 } 165 166 /* 167 * Mark ports unauthorized for data traffic. This function is usually 168 * used by 802.1x authenticator. 169 */ 170 void 171 ieee80211_node_unauthorize(ieee80211_node_t *in) 172 { 173 in->in_flags &= ~IEEE80211_NODE_AUTH; 174 } 175 176 /* 177 * Set/change the channel. The rate set is also updated as 178 * to insure a consistent view by drivers. 179 */ 180 static void 181 ieee80211_node_setchan(ieee80211com_t *ic, ieee80211_node_t *in, 182 struct ieee80211_channel *chan) 183 { 184 if (chan == IEEE80211_CHAN_ANYC) 185 chan = ic->ic_curchan; 186 in->in_chan = chan; 187 in->in_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, chan)]; 188 } 189 190 /* 191 * Initialize the channel set to scan based on the available channels 192 * and the current PHY mode. 193 */ 194 static void 195 ieee80211_reset_scan(ieee80211com_t *ic) 196 { 197 ieee80211_impl_t *im = ic->ic_private; 198 199 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 200 (void) memset(im->im_chan_scan, 0, sizeof (im->im_chan_scan)); 201 ieee80211_setbit(im->im_chan_scan, 202 ieee80211_chan2ieee(ic, ic->ic_des_chan)); 203 } else { 204 bcopy(ic->ic_chan_active, im->im_chan_scan, 205 sizeof (ic->ic_chan_active)); 206 } 207 ieee80211_dbg(IEEE80211_MSG_SCAN, "ieee80211_reset_scan(): " 208 "start chan %u\n", ieee80211_chan2ieee(ic, ic->ic_curchan)); 209 } 210 211 /* 212 * Begin an active scan. Initialize the node cache. The scan 213 * begins on the next radio channel by calling ieee80211_next_scan(). 214 * The actual scanning is not automated. The driver itself 215 * only handles setting the radio frequency and stepping through 216 * the channels. 217 */ 218 void 219 ieee80211_begin_scan(ieee80211com_t *ic, boolean_t reset) 220 { 221 IEEE80211_LOCK(ic); 222 223 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 224 ic->ic_flags |= IEEE80211_F_ASCAN; 225 ieee80211_dbg(IEEE80211_MSG_SCAN, 226 "begin %s scan in %s mode on channel %u\n", 227 (ic->ic_flags & IEEE80211_F_ASCAN) ? "active" : "passive", 228 ieee80211_phymode_name[ic->ic_curmode], 229 ieee80211_chan2ieee(ic, ic->ic_curchan)); 230 231 /* 232 * Clear scan state and flush any previously seen AP's. 233 */ 234 ieee80211_reset_scan(ic); 235 if (reset) 236 ieee80211_free_allnodes(&ic->ic_scan); 237 238 ic->ic_flags |= IEEE80211_F_SCAN; 239 IEEE80211_UNLOCK(ic); 240 241 /* Scan the next channel. */ 242 ieee80211_next_scan(ic); 243 } 244 245 /* 246 * Switch to the next channel marked for scanning. 247 * A driver is expected to first call ieee80211_begin_scan(), 248 * to initialize the node cache, then set the radio channel 249 * on the device. And then after a certain time has elapsed, 250 * call ieee80211_next_scan() to move to the next channel. 251 * Typically, a timeout routine is used to automate this process. 252 */ 253 void 254 ieee80211_next_scan(ieee80211com_t *ic) 255 { 256 ieee80211_impl_t *im = ic->ic_private; 257 struct ieee80211_channel *chan; 258 259 IEEE80211_LOCK(ic); 260 /* 261 * Insure any previous mgt frame timeouts don't fire. 262 * This assumes the driver does the right thing in 263 * flushing anything queued in the driver and below. 264 */ 265 im->im_mgt_timer = 0; 266 267 chan = ic->ic_curchan; 268 do { 269 if (++chan > &ic->ic_sup_channels[IEEE80211_CHAN_MAX]) 270 chan = &ic->ic_sup_channels[0]; 271 if (ieee80211_isset(im->im_chan_scan, 272 ieee80211_chan2ieee(ic, chan))) { 273 ieee80211_clrbit(im->im_chan_scan, 274 ieee80211_chan2ieee(ic, chan)); 275 ieee80211_dbg(IEEE80211_MSG_SCAN, 276 "ieee80211_next_scan: chan %d->%d\n", 277 ieee80211_chan2ieee(ic, ic->ic_curchan), 278 ieee80211_chan2ieee(ic, chan)); 279 ic->ic_curchan = chan; 280 /* 281 * drivers should do this as needed, 282 * for now maintain compatibility 283 */ 284 ic->ic_bss->in_rates = 285 ic->ic_sup_rates[ieee80211_chan2mode(ic, chan)]; 286 IEEE80211_UNLOCK(ic); 287 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 288 return; 289 } 290 } while (chan != ic->ic_curchan); 291 IEEE80211_UNLOCK(ic); 292 ieee80211_end_scan(ic); 293 } 294 295 /* 296 * Copy useful state from node obss into nbss. 297 */ 298 static void 299 ieee80211_copy_bss(ieee80211_node_t *nbss, const ieee80211_node_t *obss) 300 { 301 /* propagate useful state */ 302 nbss->in_authmode = obss->in_authmode; 303 nbss->in_txpower = obss->in_txpower; 304 nbss->in_vlan = obss->in_vlan; 305 } 306 307 /* 308 * Setup the net80211 specific portion of an interface's softc, ic, 309 * for use in IBSS mode 310 */ 311 void 312 ieee80211_create_ibss(ieee80211com_t *ic, struct ieee80211_channel *chan) 313 { 314 ieee80211_impl_t *im = ic->ic_private; 315 ieee80211_node_table_t *nt; 316 ieee80211_node_t *in; 317 318 IEEE80211_LOCK_ASSERT(ic); 319 ieee80211_dbg(IEEE80211_MSG_SCAN, "ieee80211_create_ibss: " 320 "creating ibss\n"); 321 322 /* 323 * Create the station/neighbor table. Note that for adhoc 324 * mode we make the initial inactivity timer longer since 325 * we create nodes only through discovery and they typically 326 * are long-lived associations. 327 */ 328 nt = &ic->ic_sta; 329 IEEE80211_NODE_LOCK(nt); 330 nt->nt_name = "neighbor"; 331 nt->nt_inact_init = im->im_inact_run; 332 IEEE80211_NODE_UNLOCK(nt); 333 334 in = ieee80211_alloc_node(ic, &ic->ic_sta, ic->ic_macaddr); 335 if (in == NULL) { 336 ieee80211_err("ieee80211_create_ibss(): alloc node failed\n"); 337 return; 338 } 339 IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_macaddr); 340 in->in_esslen = ic->ic_des_esslen; 341 (void) memcpy(in->in_essid, ic->ic_des_essid, in->in_esslen); 342 ieee80211_copy_bss(in, ic->ic_bss); 343 in->in_intval = ic->ic_bintval; 344 if (ic->ic_flags & IEEE80211_F_PRIVACY) 345 in->in_capinfo |= IEEE80211_CAPINFO_PRIVACY; 346 if (ic->ic_phytype == IEEE80211_T_FH) { 347 in->in_fhdwell = 200; 348 in->in_fhindex = 1; 349 } 350 switch (ic->ic_opmode) { 351 case IEEE80211_M_IBSS: 352 ic->ic_flags |= IEEE80211_F_SIBSS; 353 in->in_capinfo |= IEEE80211_CAPINFO_IBSS; 354 if (ic->ic_flags & IEEE80211_F_DESBSSID) 355 IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_des_bssid); 356 else 357 in->in_bssid[0] |= 0x02; /* local bit for IBSS */ 358 break; 359 case IEEE80211_M_AHDEMO: 360 if (ic->ic_flags & IEEE80211_F_DESBSSID) 361 IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_des_bssid); 362 else 363 (void) memset(in->in_bssid, 0, IEEE80211_ADDR_LEN); 364 break; 365 default: 366 ieee80211_err("ieee80211_create_ibss(): " 367 "wrong opmode %u to creat IBSS, abort\n", 368 ic->ic_opmode); 369 ieee80211_free_node(in); 370 return; 371 } 372 373 /* 374 * Fix the channel and related attributes. 375 */ 376 ieee80211_node_setchan(ic, in, chan); 377 ic->ic_curchan = chan; 378 ic->ic_curmode = ieee80211_chan2mode(ic, chan); 379 /* 380 * Do mode-specific rate setup. 381 */ 382 ieee80211_setbasicrates(&in->in_rates, ic->ic_curmode); 383 IEEE80211_UNLOCK(ic); 384 ieee80211_sta_join(ic, ieee80211_ref_node(in)); 385 IEEE80211_LOCK(ic); 386 } 387 388 void 389 ieee80211_reset_bss(ieee80211com_t *ic) 390 { 391 ieee80211_node_t *in; 392 ieee80211_node_t *obss; 393 394 ieee80211_node_table_reset(&ic->ic_sta); 395 ieee80211_reset_erp(ic); 396 397 in = ieee80211_alloc_node(ic, &ic->ic_scan, ic->ic_macaddr); 398 ASSERT(in != NULL); 399 obss = ic->ic_bss; 400 ic->ic_bss = ieee80211_ref_node(in); 401 if (obss != NULL) { 402 ieee80211_copy_bss(in, obss); 403 in->in_intval = ic->ic_bintval; 404 ieee80211_free_node(obss); 405 } 406 } 407 408 static int 409 ieee80211_match_bss(ieee80211com_t *ic, ieee80211_node_t *in) 410 { 411 uint8_t rate; 412 int fail; 413 414 fail = 0; 415 if (ieee80211_isclr(ic->ic_chan_active, 416 ieee80211_chan2ieee(ic, in->in_chan))) { 417 fail |= IEEE80211_BADCHAN; 418 } 419 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 420 in->in_chan != ic->ic_des_chan) { 421 fail |= IEEE80211_BADCHAN; 422 } 423 if (ic->ic_opmode == IEEE80211_M_IBSS) { 424 if (!(in->in_capinfo & IEEE80211_CAPINFO_IBSS)) 425 fail |= IEEE80211_BADOPMODE; 426 } else { 427 if (!(in->in_capinfo & IEEE80211_CAPINFO_ESS)) 428 fail |= IEEE80211_BADOPMODE; 429 } 430 if (ic->ic_flags & IEEE80211_F_PRIVACY) { 431 if (!(in->in_capinfo & IEEE80211_CAPINFO_PRIVACY)) 432 fail |= IEEE80211_BADPRIVACY; 433 } else { 434 if (in->in_capinfo & IEEE80211_CAPINFO_PRIVACY) 435 fail |= IEEE80211_BADPRIVACY; 436 } 437 rate = ieee80211_fix_rate(in, IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE); 438 if (rate & IEEE80211_RATE_BASIC) 439 fail |= IEEE80211_BADRATE; 440 if (ic->ic_des_esslen != 0 && 441 (in->in_esslen != ic->ic_des_esslen || 442 memcmp(in->in_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0)) { 443 fail |= IEEE80211_BADESSID; 444 } 445 if ((ic->ic_flags & IEEE80211_F_DESBSSID) && 446 !IEEE80211_ADDR_EQ(ic->ic_des_bssid, in->in_bssid)) { 447 fail |= IEEE80211_BADBSSID; 448 } 449 if (in->in_fails >= IEEE80211_STA_FAILS_MAX) 450 fail |= IEEE80211_NODEFAIL; 451 452 return (fail); 453 } 454 455 #define IEEE80211_MAXRATE(_rs) \ 456 ((_rs).ir_rates[(_rs).ir_nrates - 1] & IEEE80211_RATE_VAL) 457 458 /* 459 * Compare the capabilities of node a with node b and decide which is 460 * more desirable (return b if b is considered better than a). Note 461 * that we assume compatibility/usability has already been checked 462 * so we don't need to (e.g. validate whether privacy is supported). 463 * Used to select the best scan candidate for association in a BSS. 464 * 465 * Return desired node 466 */ 467 static ieee80211_node_t * 468 ieee80211_node_compare(ieee80211com_t *ic, ieee80211_node_t *a, 469 ieee80211_node_t *b) 470 { 471 uint8_t maxa; 472 uint8_t maxb; 473 uint8_t rssia; 474 uint8_t rssib; 475 476 /* privacy support preferred */ 477 if ((a->in_capinfo & IEEE80211_CAPINFO_PRIVACY) && 478 !(b->in_capinfo & IEEE80211_CAPINFO_PRIVACY)) { 479 return (a); 480 } 481 if (!(a->in_capinfo & IEEE80211_CAPINFO_PRIVACY) && 482 (b->in_capinfo & IEEE80211_CAPINFO_PRIVACY)) { 483 return (b); 484 } 485 486 /* compare count of previous failures */ 487 if (b->in_fails != a->in_fails) 488 return ((a->in_fails > b->in_fails) ? b : a); 489 490 rssia = ic->ic_node_getrssi(a); 491 rssib = ic->ic_node_getrssi(b); 492 if (ABS(rssib - rssia) < IEEE80211_RSSI_CMP_THRESHOLD) { 493 /* best/max rate preferred if signal level close enough */ 494 maxa = IEEE80211_MAXRATE(a->in_rates); 495 maxb = IEEE80211_MAXRATE(b->in_rates); 496 if (maxa != maxb) 497 return ((maxb > maxa) ? b : a); 498 /* for now just prefer 5Ghz band to all other bands */ 499 if (IEEE80211_IS_CHAN_5GHZ(a->in_chan) && 500 !IEEE80211_IS_CHAN_5GHZ(b->in_chan)) { 501 return (a); 502 } 503 if (!IEEE80211_IS_CHAN_5GHZ(a->in_chan) && 504 IEEE80211_IS_CHAN_5GHZ(b->in_chan)) { 505 return (b); 506 } 507 } 508 /* all things being equal, compare signal level */ 509 return ((rssib > rssia) ? b : a); 510 } 511 512 /* 513 * Mark an ongoing scan stopped. 514 */ 515 void 516 ieee80211_cancel_scan(ieee80211com_t *ic) 517 { 518 IEEE80211_LOCK(ic); 519 ieee80211_dbg(IEEE80211_MSG_SCAN, "ieee80211_cancel_scan()" 520 "end %s scan\n", 521 (ic->ic_flags & IEEE80211_F_ASCAN) ? "active" : "passive"); 522 ic->ic_flags &= ~(IEEE80211_F_SCAN | IEEE80211_F_ASCAN); 523 cv_broadcast(&((ieee80211_impl_t *)ic->ic_private)->im_scan_cv); 524 IEEE80211_UNLOCK(ic); 525 } 526 527 /* 528 * Complete a scan of potential channels. It is called by 529 * ieee80211_next_scan() when the state machine has performed 530 * a full cycle of scaning on all available radio channels. 531 * ieee80211_end_scan() will inspect the node cache for suitable 532 * APs found during scaning, and associate with one, should 533 * the parameters of the node match those of the configuration 534 * requested from userland. 535 */ 536 void 537 ieee80211_end_scan(ieee80211com_t *ic) 538 { 539 ieee80211_node_table_t *nt = &ic->ic_scan; 540 ieee80211_node_t *in; 541 ieee80211_node_t *selbs; 542 543 ieee80211_cancel_scan(ic); 544 /* notify SCAN done */ 545 ieee80211_notify(ic, EVENT_SCAN_RESULTS); 546 IEEE80211_LOCK(ic); 547 548 /* 549 * Automatic sequencing; look for a candidate and 550 * if found join the network. 551 */ 552 /* NB: unlocked read should be ok */ 553 in = list_head(&nt->nt_node); 554 if (in == NULL && (ic->ic_flags & IEEE80211_F_WPA) == 0) { 555 ieee80211_dbg(IEEE80211_MSG_SCAN, "ieee80211_end_scan: " 556 "no scan candidate\n"); 557 notfound: 558 if (ic->ic_opmode == IEEE80211_M_IBSS && 559 (ic->ic_flags & IEEE80211_F_IBSSON) && 560 ic->ic_des_esslen != 0) { 561 ieee80211_create_ibss(ic, ic->ic_ibss_chan); 562 IEEE80211_UNLOCK(ic); 563 return; 564 } 565 566 /* 567 * Reset the list of channels to scan and start again. 568 */ 569 ieee80211_reset_scan(ic); 570 ic->ic_flags |= IEEE80211_F_SCAN | IEEE80211_F_ASCAN; 571 IEEE80211_UNLOCK(ic); 572 573 ieee80211_next_scan(ic); 574 return; 575 } 576 577 if (ic->ic_flags & IEEE80211_F_SCANONLY || 578 ic->ic_flags & IEEE80211_F_WPA) { /* scan only */ 579 ic->ic_flags &= ~IEEE80211_F_SCANONLY; 580 IEEE80211_UNLOCK(ic); 581 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 582 return; 583 } 584 585 selbs = NULL; 586 IEEE80211_NODE_LOCK(nt); 587 while (in != NULL) { 588 if (in->in_fails >= IEEE80211_STA_FAILS_MAX) { 589 ieee80211_node_t *tmpin = in; 590 591 /* 592 * The configuration of the access points may change 593 * during my scan. So delete the entry for the AP 594 * and retry to associate if there is another beacon. 595 */ 596 in = list_next(&nt->nt_node, tmpin); 597 ieee80211_node_reclaim(nt, tmpin); 598 continue; 599 } 600 /* 601 * It's possible at some special moments, the in_chan will 602 * be none. Need to skip the null node. 603 */ 604 if (in->in_chan == IEEE80211_CHAN_ANYC) { 605 in = list_next(&nt->nt_node, in); 606 continue; 607 } 608 if (ieee80211_match_bss(ic, in) == 0) { 609 if (selbs == NULL) 610 selbs = in; 611 else 612 selbs = ieee80211_node_compare(ic, selbs, in); 613 } 614 in = list_next(&nt->nt_node, in); 615 } 616 if (selbs != NULL) /* grab ref while dropping lock */ 617 (void) ieee80211_ref_node(selbs); 618 IEEE80211_NODE_UNLOCK(nt); 619 if (selbs == NULL) 620 goto notfound; 621 IEEE80211_UNLOCK(ic); 622 ieee80211_sta_join(ic, selbs); 623 } 624 625 626 /* 627 * Handle 802.11 ad hoc network merge. The convention, set by the 628 * Wireless Ethernet Compatibility Alliance (WECA), is that an 802.11 629 * station will change its BSSID to match the "oldest" 802.11 ad hoc 630 * network, on the same channel, that has the station's desired SSID. 631 * The "oldest" 802.11 network sends beacons with the greatest TSF 632 * timestamp. 633 * The caller is assumed to validate TSF's before attempting a merge. 634 * 635 * Return B_TRUE if the BSSID changed, B_FALSE otherwise. 636 */ 637 boolean_t 638 ieee80211_ibss_merge(ieee80211_node_t *in) 639 { 640 ieee80211com_t *ic = in->in_ic; 641 642 if (in == ic->ic_bss || 643 IEEE80211_ADDR_EQ(in->in_bssid, ic->ic_bss->in_bssid)) { 644 /* unchanged, nothing to do */ 645 return (B_FALSE); 646 } 647 if (ieee80211_match_bss(ic, in) != 0) { /* capabilities mismatch */ 648 ieee80211_dbg(IEEE80211_MSG_ASSOC, "ieee80211_ibss_merge: " 649 " merge failed, capabilities mismatch\n"); 650 return (B_FALSE); 651 } 652 ieee80211_dbg(IEEE80211_MSG_ASSOC, "ieee80211_ibss_merge: " 653 "new bssid %s: %s preamble, %s slot time%s\n", 654 ieee80211_macaddr_sprintf(in->in_bssid), 655 (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long", 656 (ic->ic_flags & IEEE80211_F_SHSLOT) ? "short" : "long", 657 (ic->ic_flags&IEEE80211_F_USEPROT) ? ", protection" : ""); 658 ieee80211_sta_join(ic, ieee80211_ref_node(in)); 659 return (B_TRUE); 660 } 661 662 /* 663 * Join the specified IBSS/BSS network. The node is assumed to 664 * be passed in with a held reference. 665 */ 666 void 667 ieee80211_sta_join(ieee80211com_t *ic, ieee80211_node_t *selbs) 668 { 669 ieee80211_impl_t *im = ic->ic_private; 670 ieee80211_node_t *obss; 671 672 IEEE80211_LOCK(ic); 673 if (ic->ic_opmode == IEEE80211_M_IBSS) { 674 ieee80211_node_table_t *nt; 675 676 /* 677 * Delete unusable rates; we've already checked 678 * that the negotiated rate set is acceptable. 679 */ 680 (void) ieee80211_fix_rate(selbs, IEEE80211_F_DODEL); 681 /* 682 * Fillin the neighbor table 683 */ 684 nt = &ic->ic_sta; 685 IEEE80211_NODE_LOCK(nt); 686 nt->nt_name = "neighbor"; 687 nt->nt_inact_init = im->im_inact_run; 688 IEEE80211_NODE_UNLOCK(nt); 689 } 690 691 /* 692 * Committed to selbs, setup state. 693 */ 694 obss = ic->ic_bss; 695 ic->ic_bss = selbs; /* caller assumed to bump refcnt */ 696 if (obss != NULL) { 697 ieee80211_copy_bss(selbs, obss); 698 ieee80211_free_node(obss); 699 } 700 ic->ic_curmode = ieee80211_chan2mode(ic, selbs->in_chan); 701 ic->ic_curchan = selbs->in_chan; 702 ic->ic_phytype = selbs->in_phytype; 703 /* 704 * Set the erp state (mostly the slot time) to deal with 705 * the auto-select case; this should be redundant if the 706 * mode is locked. 707 */ 708 ieee80211_reset_erp(ic); 709 710 IEEE80211_UNLOCK(ic); 711 if (ic->ic_opmode == IEEE80211_M_STA) 712 ieee80211_new_state(ic, IEEE80211_S_AUTH, -1); 713 else 714 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 715 } 716 717 /* 718 * Leave the specified IBSS/BSS network. The node is assumed to 719 * be passed in with a held reference. 720 */ 721 void 722 ieee80211_sta_leave(ieee80211com_t *ic, ieee80211_node_t *in) 723 { 724 IEEE80211_LOCK(ic); 725 ic->ic_node_cleanup(in); 726 ieee80211_notify_node_leave(ic, in); 727 IEEE80211_UNLOCK(ic); 728 } 729 730 /* 731 * Allocate a node. This is the default callback function for 732 * ic_node_alloc. This function may be overridden by the driver 733 * to allocate device specific node structure. 734 */ 735 /* ARGSUSED */ 736 static ieee80211_node_t * 737 ieee80211_node_alloc(ieee80211com_t *ic) 738 { 739 return (kmem_zalloc(sizeof (ieee80211_node_t), KM_SLEEP)); 740 } 741 742 /* 743 * Cleanup a node, free any memory associated with the node. 744 * This is the default callback function for ic_node_cleanup 745 * and may be overridden by the driver. 746 */ 747 static void 748 ieee80211_node_cleanup(ieee80211_node_t *in) 749 { 750 in->in_associd = 0; 751 in->in_rssi = 0; 752 in->in_rstamp = 0; 753 if (in->in_challenge != NULL) { 754 kmem_free(in->in_challenge, IEEE80211_CHALLENGE_LEN); 755 in->in_challenge = NULL; 756 } 757 if (in->in_rxfrag != NULL) { 758 freemsg(in->in_rxfrag); 759 in->in_rxfrag = NULL; 760 } 761 } 762 763 /* 764 * Free a node. This is the default callback function for ic_node_free 765 * and may be overridden by the driver to free memory used by device 766 * specific node structure 767 */ 768 static void 769 ieee80211_node_free(ieee80211_node_t *in) 770 { 771 ieee80211com_t *ic = in->in_ic; 772 773 ic->ic_node_cleanup(in); 774 if (in->in_wpa_ie != NULL) 775 ieee80211_free(in->in_wpa_ie); 776 kmem_free(in, sizeof (ieee80211_node_t)); 777 } 778 779 /* 780 * Get a node current RSSI value. This is the default callback function 781 * for ic_node_getrssi and may be overridden by the driver to provide 782 * device specific RSSI calculation algorithm. 783 */ 784 static uint8_t 785 ieee80211_node_getrssi(const ieee80211_node_t *in) 786 { 787 return (in->in_rssi); 788 } 789 790 /* Free fragment if not needed anymore */ 791 static void 792 node_cleanfrag(ieee80211_node_t *in) 793 { 794 clock_t ticks; 795 796 ticks = ddi_get_lbolt(); 797 if (in->in_rxfrag != NULL && ticks > (in->in_rxfragstamp + hz)) { 798 freemsg(in->in_rxfrag); 799 in->in_rxfrag = NULL; 800 } 801 } 802 803 /* 804 * Setup a node. Initialize the node with specified macaddr. Associate 805 * with the interface softc, ic, and add it to the specified node 806 * database. 807 */ 808 static void 809 ieee80211_setup_node(ieee80211com_t *ic, ieee80211_node_table_t *nt, 810 ieee80211_node_t *in, const uint8_t *macaddr) 811 { 812 int32_t hash; 813 814 ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_setup_node(): " 815 "%p<%s> in %s table\n", in, 816 ieee80211_macaddr_sprintf(macaddr), 817 (nt != NULL) ? nt->nt_name : "NULL"); 818 819 in->in_ic = ic; 820 IEEE80211_ADDR_COPY(in->in_macaddr, macaddr); 821 hash = ieee80211_node_hash(macaddr); 822 ieee80211_node_initref(in); /* mark referenced */ 823 in->in_authmode = IEEE80211_AUTH_OPEN; 824 in->in_txpower = ic->ic_txpowlimit; /* max power */ 825 in->in_chan = IEEE80211_CHAN_ANYC; 826 in->in_inact_reload = IEEE80211_INACT_INIT; 827 in->in_inact = in->in_inact_reload; 828 ieee80211_crypto_resetkey(ic, &in->in_ucastkey, IEEE80211_KEYIX_NONE); 829 830 if (nt != NULL) { 831 IEEE80211_NODE_LOCK(nt); 832 list_insert_tail(&nt->nt_node, in); 833 list_insert_tail(&nt->nt_hash[hash], in); 834 in->in_table = nt; 835 in->in_inact_reload = nt->nt_inact_init; 836 IEEE80211_NODE_UNLOCK(nt); 837 } 838 } 839 840 /* 841 * Allocates and initialize a node with specified MAC address. 842 * Associate the node with the interface ic. If the allocation 843 * is successful, the node structure is initialized by 844 * ieee80211_setup_node(); otherwise, NULL is returned 845 */ 846 ieee80211_node_t * 847 ieee80211_alloc_node(ieee80211com_t *ic, ieee80211_node_table_t *nt, 848 const uint8_t *macaddr) 849 { 850 ieee80211_node_t *in; 851 852 in = ic->ic_node_alloc(ic); 853 if (in != NULL) 854 ieee80211_setup_node(ic, nt, in, macaddr); 855 return (in); 856 } 857 858 /* 859 * Craft a temporary node suitable for sending a management frame 860 * to the specified station. We craft only as much state as we 861 * need to do the work since the node will be immediately reclaimed 862 * once the send completes. 863 */ 864 ieee80211_node_t * 865 ieee80211_tmp_node(ieee80211com_t *ic, const uint8_t *macaddr) 866 { 867 ieee80211_node_t *in; 868 869 in = ic->ic_node_alloc(ic); 870 if (in != NULL) { 871 ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_tmp_node: " 872 "%p<%s>\n", in, ieee80211_macaddr_sprintf(macaddr)); 873 874 IEEE80211_ADDR_COPY(in->in_macaddr, macaddr); 875 IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_bss->in_bssid); 876 ieee80211_node_initref(in); /* mark referenced */ 877 in->in_txpower = ic->ic_bss->in_txpower; 878 /* NB: required by ieee80211_fix_rate */ 879 ieee80211_node_setchan(ic, in, ic->ic_bss->in_chan); 880 ieee80211_crypto_resetkey(ic, &in->in_ucastkey, 881 IEEE80211_KEYIX_NONE); 882 883 in->in_table = NULL; /* NB: pedantic */ 884 in->in_ic = ic; 885 } 886 887 return (in); 888 } 889 890 /* 891 * ieee80211_dup_bss() is similar to ieee80211_alloc_node(), 892 * but is instead used to create a node database entry for 893 * the specified BSSID. If the allocation is successful, the 894 * node is initialized, otherwise, NULL is returned. 895 */ 896 ieee80211_node_t * 897 ieee80211_dup_bss(ieee80211_node_table_t *nt, const uint8_t *macaddr) 898 { 899 ieee80211com_t *ic = nt->nt_ic; 900 ieee80211_node_t *in; 901 902 in = ieee80211_alloc_node(ic, nt, macaddr); 903 if (in != NULL) { 904 /* 905 * Inherit from ic_bss. 906 */ 907 ieee80211_copy_bss(in, ic->ic_bss); 908 IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_bss->in_bssid); 909 ieee80211_node_setchan(ic, in, ic->ic_bss->in_chan); 910 } 911 912 return (in); 913 } 914 915 /* 916 * Iterate through the node table, searching for a node entry which 917 * matches macaddr. If the entry is found, its reference count is 918 * incremented, and a pointer to the node is returned; otherwise, 919 * NULL will be returned. 920 * The node table lock is acquired by the caller. 921 */ 922 static ieee80211_node_t * 923 ieee80211_find_node_locked(ieee80211_node_table_t *nt, const uint8_t *macaddr) 924 { 925 ieee80211_node_t *in; 926 int hash; 927 928 ASSERT(IEEE80211_NODE_IS_LOCKED(nt)); 929 930 hash = ieee80211_node_hash(macaddr); 931 in = list_head(&nt->nt_hash[hash]); 932 while (in != NULL) { 933 if (IEEE80211_ADDR_EQ(in->in_macaddr, macaddr)) 934 return (ieee80211_ref_node(in)); /* mark referenced */ 935 in = list_next(&nt->nt_hash[hash], in); 936 } 937 return (NULL); 938 } 939 940 /* 941 * Iterate through the node table, searching for a node entry 942 * which match specified mac address. 943 * Return NULL if no matching node found. 944 */ 945 ieee80211_node_t * 946 ieee80211_find_node(ieee80211_node_table_t *nt, const uint8_t *macaddr) 947 { 948 ieee80211_node_t *in; 949 950 IEEE80211_NODE_LOCK(nt); 951 in = ieee80211_find_node_locked(nt, macaddr); 952 IEEE80211_NODE_UNLOCK(nt); 953 return (in); 954 } 955 956 /* 957 * Like find but search based on the ssid too. 958 */ 959 ieee80211_node_t * 960 ieee80211_find_node_with_ssid(ieee80211_node_table_t *nt, 961 const uint8_t *macaddr, uint32_t ssidlen, const uint8_t *ssid) 962 { 963 ieee80211_node_t *in; 964 int hash; 965 966 IEEE80211_NODE_LOCK(nt); 967 968 hash = ieee80211_node_hash(macaddr); 969 in = list_head(&nt->nt_hash[hash]); 970 while (in != NULL) { 971 if (IEEE80211_ADDR_EQ(in->in_macaddr, macaddr) && 972 in->in_esslen == ssidlen && 973 memcmp(in->in_essid, ssid, ssidlen) == 0) 974 break; 975 in = list_next(&nt->nt_hash[hash], in); 976 } 977 if (in != NULL) { 978 (void) ieee80211_ref_node(in); /* mark referenced */ 979 } 980 IEEE80211_NODE_UNLOCK(nt); 981 982 return (in); 983 } 984 985 /* 986 * Fake up a node; this handles node discovery in adhoc mode. 987 * Note that for the driver's benefit we treat this like an 988 * association so the driver has an opportunity to setup it's 989 * private state. 990 */ 991 ieee80211_node_t * 992 ieee80211_fakeup_adhoc_node(ieee80211_node_table_t *nt, const uint8_t *macaddr) 993 { 994 ieee80211com_t *ic = nt->nt_ic; 995 ieee80211_node_t *in; 996 997 ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_fakeup_adhoc_node: " 998 "mac<%s>\n", ieee80211_macaddr_sprintf(macaddr)); 999 in = ieee80211_dup_bss(nt, macaddr); 1000 if (in != NULL) { 1001 /* no rate negotiation; just dup */ 1002 in->in_rates = ic->ic_bss->in_rates; 1003 if (ic->ic_node_newassoc != NULL) 1004 ic->ic_node_newassoc(in, 1); 1005 ieee80211_node_authorize(in); 1006 } 1007 return (in); 1008 } 1009 1010 static void 1011 ieee80211_saveie(uint8_t **iep, const uint8_t *ie) 1012 { 1013 uint_t ielen = ie[1]+2; 1014 /* 1015 * Record information element for later use. 1016 */ 1017 if (*iep == NULL || (*iep)[1] != ie[1]) { 1018 if (*iep != NULL) 1019 ieee80211_free(*iep); 1020 *iep = ieee80211_malloc(ielen); 1021 } 1022 if (*iep != NULL) 1023 (void) memcpy(*iep, ie, ielen); 1024 } 1025 1026 static void 1027 saveie(uint8_t **iep, const uint8_t *ie) 1028 { 1029 if (ie == NULL) { 1030 if (*iep != NULL) 1031 ieee80211_free(*iep); 1032 *iep = NULL; 1033 } 1034 else 1035 ieee80211_saveie(iep, ie); 1036 } 1037 1038 /* 1039 * Process a beacon or probe response frame. 1040 */ 1041 void 1042 ieee80211_add_scan(ieee80211com_t *ic, const struct ieee80211_scanparams *sp, 1043 const struct ieee80211_frame *wh, int subtype, int rssi, int rstamp) 1044 { 1045 ieee80211_node_table_t *nt = &ic->ic_scan; 1046 ieee80211_node_t *in; 1047 boolean_t newnode = B_FALSE; 1048 1049 in = ieee80211_find_node(nt, wh->i_addr3); 1050 if (in == NULL) { 1051 /* 1052 * Create a new entry. 1053 */ 1054 in = ieee80211_alloc_node(ic, nt, wh->i_addr3); 1055 if (in == NULL) { 1056 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_add_scan: " 1057 "alloc node failed\n"); 1058 return; 1059 } 1060 /* 1061 * inherit from ic_bss. 1062 */ 1063 ieee80211_copy_bss(in, ic->ic_bss); 1064 ieee80211_node_setchan(ic, in, ic->ic_curchan); 1065 newnode = B_TRUE; 1066 } 1067 1068 /* ap beaconing multiple ssid w/ same bssid */ 1069 1070 /* 1071 * sp->ssid[0] - element ID 1072 * sp->ssid[1] - length 1073 * sp->ssid[2]... - ssid 1074 */ 1075 if (sp->ssid[1] != 0 && 1076 subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP || 1077 in->in_esslen == 0) { 1078 in->in_esslen = sp->ssid[1]; 1079 bzero(in->in_essid, sizeof (in->in_essid)); 1080 bcopy(sp->ssid + 2, in->in_essid, sp->ssid[1]); 1081 } 1082 IEEE80211_ADDR_COPY(in->in_bssid, wh->i_addr3); 1083 in->in_rssi = (uint8_t)rssi; 1084 in->in_rstamp = rstamp; 1085 bcopy(sp->tstamp, in->in_tstamp.data, sizeof (in->in_tstamp)); 1086 in->in_intval = sp->bintval; 1087 in->in_capinfo = sp->capinfo; 1088 in->in_chan = &ic->ic_sup_channels[sp->chan]; 1089 in->in_phytype = sp->phytype; 1090 in->in_fhdwell = sp->fhdwell; 1091 in->in_fhindex = sp->fhindex; 1092 in->in_erp = sp->erp; 1093 if (sp->tim != NULL) { 1094 struct ieee80211_tim_ie *ie; 1095 1096 ie = (struct ieee80211_tim_ie *)sp->tim; 1097 in->in_dtim_count = ie->tim_count; 1098 in->in_dtim_period = ie->tim_period; 1099 } 1100 /* 1101 * Record the byte offset from the mac header to 1102 * the start of the TIM information element for 1103 * use by hardware and/or to speedup software 1104 * processing of beacon frames. 1105 */ 1106 in->in_tim_off = sp->timoff; 1107 /* 1108 * Record optional information elements that might be 1109 * used by applications or drivers. 1110 */ 1111 saveie(&in->in_wpa_ie, sp->wpa); 1112 1113 /* NB: must be after in_chan is setup */ 1114 (void) ieee80211_setup_rates(in, sp->rates, sp->xrates, 1115 IEEE80211_F_DOSORT); 1116 1117 if (!newnode) 1118 ieee80211_free_node(in); 1119 } 1120 1121 /* 1122 * Initialize/update an ad-hoc node with contents from a received 1123 * beacon frame. 1124 */ 1125 void 1126 ieee80211_init_neighbor(ieee80211_node_t *in, const struct ieee80211_frame *wh, 1127 const struct ieee80211_scanparams *sp) 1128 { 1129 in->in_esslen = sp->ssid[1]; 1130 (void) memcpy(in->in_essid, sp->ssid + 2, sp->ssid[1]); 1131 IEEE80211_ADDR_COPY(in->in_bssid, wh->i_addr3); 1132 (void) memcpy(in->in_tstamp.data, sp->tstamp, sizeof (in->in_tstamp)); 1133 in->in_intval = sp->bintval; 1134 in->in_capinfo = sp->capinfo; 1135 in->in_chan = in->in_ic->ic_curchan; 1136 in->in_fhdwell = sp->fhdwell; 1137 in->in_fhindex = sp->fhindex; 1138 in->in_erp = sp->erp; 1139 in->in_tim_off = sp->timoff; 1140 1141 /* NB: must be after in_chan is setup */ 1142 (void) ieee80211_setup_rates(in, sp->rates, sp->xrates, 1143 IEEE80211_F_DOSORT); 1144 } 1145 1146 /* 1147 * Do node discovery in adhoc mode on receipt of a beacon 1148 * or probe response frame. Note that for the driver's 1149 * benefit we we treat this like an association so the 1150 * driver has an opportuinty to setup it's private state. 1151 */ 1152 ieee80211_node_t * 1153 ieee80211_add_neighbor(ieee80211com_t *ic, const struct ieee80211_frame *wh, 1154 const struct ieee80211_scanparams *sp) 1155 { 1156 ieee80211_node_t *in; 1157 1158 in = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2); 1159 if (in != NULL) { 1160 ieee80211_init_neighbor(in, wh, sp); 1161 if (ic->ic_node_newassoc != NULL) 1162 ic->ic_node_newassoc(in, 1); 1163 } 1164 return (in); 1165 } 1166 1167 #define IEEE80211_IS_CTL(wh) \ 1168 ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) 1169 1170 /* 1171 * Locate the node for sender, track state, and then pass the 1172 * (referenced) node up to the 802.11 layer for its use. We 1173 * are required to pass some node so we fall back to ic_bss 1174 * when this frame is from an unknown sender. The 802.11 layer 1175 * knows this means the sender wasn't in the node table and 1176 * acts accordingly. 1177 */ 1178 ieee80211_node_t * 1179 ieee80211_find_rxnode(ieee80211com_t *ic, const struct ieee80211_frame *wh) 1180 { 1181 ieee80211_node_table_t *nt; 1182 ieee80211_node_t *in; 1183 1184 /* may want scanned nodes in the neighbor table for adhoc */ 1185 if (ic->ic_opmode == IEEE80211_M_STA || 1186 (ic->ic_flags & IEEE80211_F_SCAN)) { 1187 nt = &ic->ic_scan; 1188 } else { 1189 nt = &ic->ic_sta; 1190 } 1191 1192 IEEE80211_NODE_LOCK(nt); 1193 if (IEEE80211_IS_CTL(wh)) 1194 in = ieee80211_find_node_locked(nt, wh->i_addr1); 1195 else 1196 in = ieee80211_find_node_locked(nt, wh->i_addr2); 1197 IEEE80211_NODE_UNLOCK(nt); 1198 1199 if (in == NULL) 1200 in = ieee80211_ref_node(ic->ic_bss); 1201 1202 return (in); 1203 } 1204 1205 /* 1206 * Return a reference to the appropriate node for sending 1207 * a data frame. This handles node discovery in adhoc networks. 1208 */ 1209 ieee80211_node_t * 1210 ieee80211_find_txnode(ieee80211com_t *ic, const uint8_t *daddr) 1211 { 1212 ieee80211_node_table_t *nt = &ic->ic_sta; 1213 ieee80211_node_t *in; 1214 1215 /* 1216 * The destination address should be in the node table 1217 * unless this is a multicast/broadcast frame. We can 1218 * also optimize station mode operation, all frames go 1219 * to the bss node. 1220 */ 1221 IEEE80211_NODE_LOCK(nt); 1222 if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(daddr)) 1223 in = ieee80211_ref_node(ic->ic_bss); 1224 else 1225 in = ieee80211_find_node_locked(nt, daddr); 1226 IEEE80211_NODE_UNLOCK(nt); 1227 1228 if (in == NULL) { 1229 if (ic->ic_opmode == IEEE80211_M_IBSS) { 1230 /* 1231 * In adhoc mode cons up a node for the destination. 1232 * Note that we need an additional reference for the 1233 * caller to be consistent with 1234 * ieee80211_find_node_locked 1235 * can't hold lock across ieee80211_dup_bss 'cuz of 1236 * recursive locking 1237 */ 1238 in = ieee80211_fakeup_adhoc_node(nt, daddr); 1239 if (in != NULL) 1240 (void) ieee80211_ref_node(in); 1241 } else { 1242 ieee80211_dbg(IEEE80211_MSG_OUTPUT, 1243 "ieee80211_find_txnode: " 1244 "[%s] no node, discard frame\n", 1245 ieee80211_macaddr_sprintf(daddr)); 1246 } 1247 } 1248 return (in); 1249 } 1250 1251 /* 1252 * Remove a node from the node database entries and free memory 1253 * associated with the node. The node table lock is acquired by 1254 * the caller. 1255 */ 1256 static void 1257 ieee80211_free_node_locked(ieee80211_node_t *in) 1258 { 1259 ieee80211com_t *ic = in->in_ic; 1260 ieee80211_node_table_t *nt = in->in_table; 1261 int32_t hash; 1262 1263 if (nt != NULL) { 1264 hash = ieee80211_node_hash(in->in_macaddr); 1265 list_remove(&nt->nt_hash[hash], in); 1266 list_remove(&nt->nt_node, in); 1267 } 1268 ic->ic_node_free(in); 1269 } 1270 1271 /* 1272 * Remove a node from the node database entries and free any 1273 * memory associated with the node. 1274 * This method can be overridden in ieee80211_attach() 1275 */ 1276 void 1277 ieee80211_free_node(ieee80211_node_t *in) 1278 { 1279 ieee80211_node_table_t *nt = in->in_table; 1280 1281 if (nt != NULL) 1282 IEEE80211_NODE_LOCK(nt); 1283 if (ieee80211_node_decref_nv(in) == 0) 1284 ieee80211_free_node_locked(in); 1285 if (nt != NULL) 1286 IEEE80211_NODE_UNLOCK(nt); 1287 } 1288 1289 /* 1290 * Reclaim a node. If this is the last reference count then 1291 * do the normal free work. Otherwise remove it from the node 1292 * table and mark it gone by clearing the back-reference. 1293 */ 1294 static void 1295 ieee80211_node_reclaim(ieee80211_node_table_t *nt, ieee80211_node_t *in) 1296 { 1297 int32_t hash; 1298 1299 IEEE80211_NODE_LOCK_ASSERT(nt); 1300 ieee80211_dbg(IEEE80211_MSG_NODE, "node_reclaim: " 1301 " remove %p<%s> from %s table, refcnt %d\n", 1302 in, ieee80211_macaddr_sprintf(in->in_macaddr), nt->nt_name, 1303 ieee80211_node_refcnt(in)); 1304 1305 if (ieee80211_node_decref_nv(in) != 0) { 1306 /* 1307 * Clear any entry in the unicast key mapping table. 1308 * We need to do it here so rx lookups don't find it 1309 * in the mapping table even if it's not in the hash 1310 * table. We cannot depend on the mapping table entry 1311 * being cleared because the node may not be free'd. 1312 */ 1313 hash = ieee80211_node_hash(in->in_macaddr); 1314 list_remove(&nt->nt_hash[hash], in); 1315 list_remove(&nt->nt_node, in); 1316 in->in_table = NULL; 1317 } else { 1318 ieee80211_free_node_locked(in); 1319 } 1320 } 1321 1322 /* 1323 * Iterate through the node list and reclaim all node in the node table. 1324 * The node table lock is acquired by the caller 1325 */ 1326 static void 1327 ieee80211_free_allnodes_locked(ieee80211_node_table_t *nt) 1328 { 1329 ieee80211_node_t *in; 1330 1331 ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_free_allnodes_locked(): " 1332 "free all nodes in %s table\n", nt->nt_name); 1333 1334 in = list_head(&nt->nt_node); 1335 while (in != NULL) { 1336 ieee80211_node_reclaim(nt, in); 1337 in = list_head(&nt->nt_node); 1338 } 1339 ieee80211_reset_erp(nt->nt_ic); 1340 } 1341 1342 /* 1343 * Iterate through the node list, calling ieee80211_node_reclaim() for 1344 * all nodes associated with the interface. 1345 */ 1346 static void 1347 ieee80211_free_allnodes(ieee80211_node_table_t *nt) 1348 { 1349 IEEE80211_NODE_LOCK(nt); 1350 ieee80211_free_allnodes_locked(nt); 1351 IEEE80211_NODE_UNLOCK(nt); 1352 } 1353 1354 /* 1355 * Timeout entries in the scan cache. This is the timeout callback 1356 * function of node table ic_scan which is called when the inactivity 1357 * timer expires. 1358 */ 1359 static void 1360 ieee80211_timeout_scan_candidates(ieee80211_node_table_t *nt) 1361 { 1362 ieee80211com_t *ic = nt->nt_ic; 1363 ieee80211_node_t *in; 1364 1365 IEEE80211_NODE_LOCK(nt); 1366 in = ic->ic_bss; 1367 node_cleanfrag(in); /* Free fragment if not needed */ 1368 nt->nt_inact_timer = IEEE80211_INACT_WAIT; 1369 IEEE80211_NODE_UNLOCK(nt); 1370 } 1371 1372 /* 1373 * Timeout inactive stations and do related housekeeping. 1374 * Note that we cannot hold the node lock while sending a 1375 * frame as this would lead to a LOR. Instead we use a 1376 * generation number to mark nodes that we've scanned and 1377 * drop the lock and restart a scan if we have to time out 1378 * a node. Since we are single-threaded by virtue of 1379 * controlling the inactivity timer we can be sure this will 1380 * process each node only once. 1381 */ 1382 static void 1383 ieee80211_timeout_stations(ieee80211_node_table_t *nt) 1384 { 1385 ieee80211com_t *ic = nt->nt_ic; 1386 ieee80211_impl_t *im = ic->ic_private; 1387 ieee80211_node_t *in = NULL; 1388 uint32_t gen; 1389 boolean_t isadhoc; 1390 1391 IEEE80211_LOCK_ASSERT(ic); 1392 isadhoc = (ic->ic_opmode == IEEE80211_M_IBSS || 1393 ic->ic_opmode == IEEE80211_M_AHDEMO); 1394 IEEE80211_SCAN_LOCK(nt); 1395 gen = ++nt->nt_scangen; 1396 restart: 1397 IEEE80211_NODE_LOCK(nt); 1398 for (in = list_head(&nt->nt_node); in != NULL; 1399 in = list_next(&nt->nt_node, in)) { 1400 if (in->in_scangen == gen) /* previously handled */ 1401 continue; 1402 in->in_scangen = gen; 1403 node_cleanfrag(in); /* free fragment if not needed */ 1404 1405 /* 1406 * Special case ourself; we may be idle for extended periods 1407 * of time and regardless reclaiming our state is wrong. 1408 */ 1409 if (in == ic->ic_bss) 1410 continue; 1411 in->in_inact--; 1412 if (in->in_associd != 0 || isadhoc) { 1413 /* 1414 * Probe the station before time it out. We 1415 * send a null data frame which may not be 1416 * uinversally supported by drivers (need it 1417 * for ps-poll support so it should be...). 1418 */ 1419 if (0 < in->in_inact && 1420 in->in_inact <= im->im_inact_probe) { 1421 ieee80211_dbg(IEEE80211_MSG_NODE, "net80211: " 1422 "probe station due to inactivity\n"); 1423 IEEE80211_NODE_UNLOCK(nt); 1424 IEEE80211_UNLOCK(ic); 1425 (void) ieee80211_send_nulldata(in); 1426 IEEE80211_LOCK(ic); 1427 goto restart; 1428 } 1429 } 1430 if (in->in_inact <= 0) { 1431 ieee80211_dbg(IEEE80211_MSG_NODE, "net80211: " 1432 "station timed out due to inact (refcnt %u)\n", 1433 ieee80211_node_refcnt(in)); 1434 /* 1435 * Send a deauthenticate frame and drop the station. 1436 * This is somewhat complicated due to reference counts 1437 * and locking. At this point a station will typically 1438 * have a reference count of 1. ieee80211_node_leave 1439 * will do a "free" of the node which will drop the 1440 * reference count. But in the meantime a reference 1441 * wil be held by the deauth frame. The actual reclaim 1442 * of the node will happen either after the tx is 1443 * completed or by ieee80211_node_leave. 1444 * 1445 * Separately we must drop the node lock before sending 1446 * in case the driver takes a lock, as this will result 1447 * in LOR between the node lock and the driver lock. 1448 */ 1449 IEEE80211_NODE_UNLOCK(nt); 1450 if (in->in_associd != 0) { 1451 IEEE80211_UNLOCK(ic); 1452 IEEE80211_SEND_MGMT(ic, in, 1453 IEEE80211_FC0_SUBTYPE_DEAUTH, 1454 IEEE80211_REASON_AUTH_EXPIRE); 1455 IEEE80211_LOCK(ic); 1456 } 1457 ieee80211_node_leave(ic, in); 1458 goto restart; 1459 } 1460 } 1461 IEEE80211_NODE_UNLOCK(nt); 1462 1463 IEEE80211_SCAN_UNLOCK(nt); 1464 1465 nt->nt_inact_timer = IEEE80211_INACT_WAIT; 1466 } 1467 1468 /* 1469 * Call the user-defined call back function for all nodes in 1470 * the node cache. The callback is invoked with the user-supplied 1471 * value and a pointer to the current node. 1472 */ 1473 void 1474 ieee80211_iterate_nodes(ieee80211_node_table_t *nt, ieee80211_iter_func *f, 1475 void *arg) 1476 { 1477 ieee80211_node_t *in; 1478 1479 IEEE80211_NODE_LOCK(nt); 1480 in = list_head(&nt->nt_node); 1481 while (in != NULL) { 1482 if (in->in_chan == IEEE80211_CHAN_ANYC) { 1483 in = list_next(&nt->nt_node, in); 1484 continue; 1485 } 1486 (void) ieee80211_ref_node(in); 1487 IEEE80211_NODE_UNLOCK(nt); 1488 (*f)(arg, in); 1489 ieee80211_free_node(in); 1490 IEEE80211_NODE_LOCK(nt); 1491 in = list_next(&nt->nt_node, in); 1492 } 1493 IEEE80211_NODE_UNLOCK(nt); 1494 } 1495 1496 /* 1497 * Handle bookkeeping for station deauthentication/disassociation 1498 * when operating as an ap. 1499 */ 1500 static void 1501 ieee80211_node_leave(ieee80211com_t *ic, ieee80211_node_t *in) 1502 { 1503 ieee80211_node_table_t *nt = in->in_table; 1504 1505 ASSERT(ic->ic_opmode == IEEE80211_M_IBSS); 1506 1507 /* 1508 * Remove the node from any table it's recorded in and 1509 * drop the caller's reference. Removal from the table 1510 * is important to insure the node is not reprocessed 1511 * for inactivity. 1512 */ 1513 if (nt != NULL) { 1514 IEEE80211_NODE_LOCK(nt); 1515 ieee80211_node_reclaim(nt, in); 1516 IEEE80211_NODE_UNLOCK(nt); 1517 } else { 1518 ieee80211_free_node(in); 1519 } 1520 } 1521 1522 /* 1523 * Initialize a node table with specified name, inactivity timer value 1524 * and callback inactivity timeout function. Associate the node table 1525 * with interface softc, ic. 1526 */ 1527 static void 1528 ieee80211_node_table_init(ieee80211com_t *ic, ieee80211_node_table_t *nt, 1529 const char *name, int inact, int keyixmax, 1530 void (*timeout)(ieee80211_node_table_t *)) 1531 { 1532 int i; 1533 1534 ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_node_table_init():" 1535 "%s table, inact %d\n", name, inact); 1536 1537 nt->nt_ic = ic; 1538 nt->nt_name = name; 1539 nt->nt_inact_timer = 0; 1540 nt->nt_inact_init = inact; 1541 nt->nt_timeout = timeout; 1542 nt->nt_keyixmax = keyixmax; 1543 nt->nt_scangen = 1; 1544 mutex_init(&nt->nt_scanlock, NULL, MUTEX_DRIVER, NULL); 1545 mutex_init(&nt->nt_nodelock, NULL, MUTEX_DRIVER, NULL); 1546 1547 list_create(&nt->nt_node, sizeof (ieee80211_node_t), 1548 offsetof(ieee80211_node_t, in_node)); 1549 for (i = 0; i < IEEE80211_NODE_HASHSIZE; i++) { 1550 list_create(&nt->nt_hash[i], sizeof (ieee80211_node_t), 1551 offsetof(ieee80211_node_t, in_hash)); 1552 } 1553 } 1554 1555 /* 1556 * Reset a node table. Clean its inactivity timer and call 1557 * ieee80211_free_allnodes_locked() to free all nodes in the 1558 * node table. 1559 */ 1560 void 1561 ieee80211_node_table_reset(ieee80211_node_table_t *nt) 1562 { 1563 ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_node_table_reset(): " 1564 "%s table\n", nt->nt_name); 1565 1566 IEEE80211_NODE_LOCK(nt); 1567 nt->nt_inact_timer = 0; 1568 ieee80211_free_allnodes_locked(nt); 1569 IEEE80211_NODE_UNLOCK(nt); 1570 } 1571 1572 /* 1573 * Destroy a node table. Free all nodes in the node table. 1574 * This function is usually called by node detach function. 1575 */ 1576 static void 1577 ieee80211_node_table_cleanup(ieee80211_node_table_t *nt) 1578 { 1579 ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_node_table_cleanup(): " 1580 "%s table\n", nt->nt_name); 1581 1582 IEEE80211_NODE_LOCK(nt); 1583 ieee80211_free_allnodes_locked(nt); 1584 IEEE80211_NODE_UNLOCK(nt); 1585 mutex_destroy(&nt->nt_nodelock); 1586 mutex_destroy(&nt->nt_scanlock); 1587 } 1588