1 /* $NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $ */ 2 /*- 3 * Copyright (c) 2001 Atsushi Onoe 4 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * Alternatively, this software may be distributed under the terms of the 19 * GNU General Public License ("GPL") version 2 as published by the Free 20 * Software Foundation. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 #ifdef __FreeBSD__ 36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.8 2004/04/02 20:22:25 sam Exp $"); 37 #else 38 __KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $"); 39 #endif 40 41 /* 42 * IEEE 802.11 protocol support. 43 */ 44 45 #include "opt_inet.h" 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/mbuf.h> 50 #include <sys/malloc.h> 51 #include <sys/kernel.h> 52 #include <sys/socket.h> 53 #include <sys/sockio.h> 54 #include <sys/endian.h> 55 #include <sys/errno.h> 56 #ifdef __FreeBSD__ 57 #include <sys/bus.h> 58 #endif 59 #include <sys/proc.h> 60 #include <sys/sysctl.h> 61 62 #ifdef __FreeBSD__ 63 #include <machine/atomic.h> 64 #endif 65 66 #include <net/if.h> 67 #include <net/if_dl.h> 68 #include <net/if_media.h> 69 #include <net/if_arp.h> 70 #ifdef __FreeBSD__ 71 #include <net/ethernet.h> 72 #else 73 #include <net/if_ether.h> 74 #endif 75 #include <net/if_llc.h> 76 77 #include <net80211/ieee80211_var.h> 78 #include <net80211/ieee80211_compat.h> 79 80 #include <net/bpf.h> 81 82 #ifdef INET 83 #include <netinet/in.h> 84 #ifdef __FreeBSD__ 85 #include <netinet/if_ether.h> 86 #else 87 #include <net/if_ether.h> 88 #endif 89 #endif 90 91 #define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) 92 93 const char *ieee80211_mgt_subtype_name[] = { 94 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp", 95 "probe_req", "probe_resp", "reserved#6", "reserved#7", 96 "beacon", "atim", "disassoc", "auth", 97 "deauth", "reserved#13", "reserved#14", "reserved#15" 98 }; 99 const char *ieee80211_state_name[IEEE80211_S_MAX] = { 100 "INIT", /* IEEE80211_S_INIT */ 101 "SCAN", /* IEEE80211_S_SCAN */ 102 "AUTH", /* IEEE80211_S_AUTH */ 103 "ASSOC", /* IEEE80211_S_ASSOC */ 104 "RUN" /* IEEE80211_S_RUN */ 105 }; 106 107 static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int); 108 109 void 110 ieee80211_proto_attach(struct ifnet *ifp) 111 { 112 struct ieee80211com *ic = (void *)ifp; 113 114 ifp->if_hdrlen = sizeof(struct ieee80211_frame); 115 116 #ifdef notdef 117 ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT; 118 #else 119 ic->ic_rtsthreshold = IEEE80211_RTS_MAX; 120 #endif 121 ic->ic_fragthreshold = 2346; /* XXX not used yet */ 122 ic->ic_fixed_rate = -1; /* no fixed rate */ 123 ic->ic_protmode = IEEE80211_PROT_CTSONLY; 124 125 #ifdef __FreeBSD__ 126 mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_xname, "mgmt send q", MTX_DEF); 127 #endif 128 129 /* protocol state change handler */ 130 ic->ic_newstate = ieee80211_newstate; 131 132 /* initialize management frame handlers */ 133 ic->ic_recv_mgmt = ieee80211_recv_mgmt; 134 ic->ic_send_mgmt = ieee80211_send_mgmt; 135 } 136 137 void 138 ieee80211_proto_detach(struct ifnet *ifp) 139 { 140 struct ieee80211com *ic = (void *)ifp; 141 142 #ifdef __FreeBSD__ 143 IF_DRAIN(&ic->ic_mgtq); 144 mtx_destroy(&ic->ic_mgtq.ifq_mtx); 145 #else 146 IF_PURGE(&ic->ic_mgtq); 147 IF_PURGE(&ic->ic_pwrsaveq); 148 #endif 149 } 150 151 void 152 ieee80211_print_essid(u_int8_t *essid, int len) 153 { 154 int i; 155 u_int8_t *p; 156 157 if (len > IEEE80211_NWID_LEN) 158 len = IEEE80211_NWID_LEN; 159 /* determine printable or not */ 160 for (i = 0, p = essid; i < len; i++, p++) { 161 if (*p < ' ' || *p > 0x7e) 162 break; 163 } 164 if (i == len) { 165 printf("\""); 166 for (i = 0, p = essid; i < len; i++, p++) 167 printf("%c", *p); 168 printf("\""); 169 } else { 170 printf("0x"); 171 for (i = 0, p = essid; i < len; i++, p++) 172 printf("%02x", *p); 173 } 174 } 175 176 void 177 ieee80211_dump_pkt(u_int8_t *buf, int len, int rate, int rssi) 178 { 179 struct ieee80211_frame *wh; 180 int i; 181 182 wh = (struct ieee80211_frame *)buf; 183 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 184 case IEEE80211_FC1_DIR_NODS: 185 printf("NODS %s", ether_sprintf(wh->i_addr2)); 186 printf("->%s", ether_sprintf(wh->i_addr1)); 187 printf("(%s)", ether_sprintf(wh->i_addr3)); 188 break; 189 case IEEE80211_FC1_DIR_TODS: 190 printf("TODS %s", ether_sprintf(wh->i_addr2)); 191 printf("->%s", ether_sprintf(wh->i_addr3)); 192 printf("(%s)", ether_sprintf(wh->i_addr1)); 193 break; 194 case IEEE80211_FC1_DIR_FROMDS: 195 printf("FRDS %s", ether_sprintf(wh->i_addr3)); 196 printf("->%s", ether_sprintf(wh->i_addr1)); 197 printf("(%s)", ether_sprintf(wh->i_addr2)); 198 break; 199 case IEEE80211_FC1_DIR_DSTODS: 200 printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1])); 201 printf("->%s", ether_sprintf(wh->i_addr3)); 202 printf("(%s", ether_sprintf(wh->i_addr2)); 203 printf("->%s)", ether_sprintf(wh->i_addr1)); 204 break; 205 } 206 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 207 case IEEE80211_FC0_TYPE_DATA: 208 printf(" data"); 209 break; 210 case IEEE80211_FC0_TYPE_MGT: 211 printf(" %s", ieee80211_mgt_subtype_name[ 212 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) 213 >> IEEE80211_FC0_SUBTYPE_SHIFT]); 214 break; 215 default: 216 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 217 break; 218 } 219 if (wh->i_fc[1] & IEEE80211_FC1_WEP) 220 printf(" WEP"); 221 if (rate >= 0) 222 printf(" %dM", rate / 2); 223 if (rssi >= 0) 224 printf(" +%d", rssi); 225 printf("\n"); 226 if (len > 0) { 227 for (i = 0; i < len; i++) { 228 if ((i & 1) == 0) 229 printf(" "); 230 printf("%02x", buf[i]); 231 } 232 printf("\n"); 233 } 234 } 235 236 int 237 ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags) 238 { 239 #define RV(v) ((v) & IEEE80211_RATE_VAL) 240 int i, j, ignore, error; 241 int okrate, badrate; 242 struct ieee80211_rateset *srs, *nrs; 243 u_int8_t r; 244 245 error = 0; 246 okrate = badrate = 0; 247 srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; 248 nrs = &ni->ni_rates; 249 for (i = 0; i < nrs->rs_nrates; ) { 250 ignore = 0; 251 if (flags & IEEE80211_F_DOSORT) { 252 /* 253 * Sort rates. 254 */ 255 for (j = i + 1; j < nrs->rs_nrates; j++) { 256 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) { 257 r = nrs->rs_rates[i]; 258 nrs->rs_rates[i] = nrs->rs_rates[j]; 259 nrs->rs_rates[j] = r; 260 } 261 } 262 } 263 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL; 264 badrate = r; 265 if (flags & IEEE80211_F_DOFRATE) { 266 /* 267 * Apply fixed rate constraint. Note that we do 268 * not apply the constraint to basic rates as 269 * otherwise we may not be able to associate if 270 * the rate set we submit to the AP is invalid 271 * (e.g. fix rate at 36Mb/s which is not a basic 272 * rate for 11a operation). 273 */ 274 if ((nrs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0 && 275 ic->ic_fixed_rate >= 0 && 276 r != RV(srs->rs_rates[ic->ic_fixed_rate])) 277 ignore++; 278 } 279 if (flags & IEEE80211_F_DONEGO) { 280 /* 281 * Check against supported rates. 282 */ 283 for (j = 0; j < srs->rs_nrates; j++) { 284 if (r == RV(srs->rs_rates[j])) { 285 /* 286 * Overwrite with the supported rate 287 * value so any basic rate bit is set. 288 * This insures that response we send 289 * to stations have the necessary basic 290 * rate bit set. 291 */ 292 nrs->rs_rates[i] = srs->rs_rates[j]; 293 break; 294 } 295 } 296 if (j == srs->rs_nrates) { 297 /* 298 * A rate in the node's rate set is not 299 * supported. If this is a basic rate and we 300 * are operating as an AP then this is an error. 301 * Otherwise we just discard/ignore the rate. 302 * Note that this is important for 11b stations 303 * when they want to associate with an 11g AP. 304 */ 305 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 306 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC)) 307 error++; 308 ignore++; 309 } 310 } 311 if (flags & IEEE80211_F_DODEL) { 312 /* 313 * Delete unacceptable rates. 314 */ 315 if (ignore) { 316 nrs->rs_nrates--; 317 for (j = i; j < nrs->rs_nrates; j++) 318 nrs->rs_rates[j] = nrs->rs_rates[j + 1]; 319 nrs->rs_rates[j] = 0; 320 continue; 321 } 322 } 323 if (!ignore) 324 okrate = nrs->rs_rates[i]; 325 i++; 326 } 327 if (okrate == 0 || error != 0) 328 return badrate | IEEE80211_RATE_BASIC; 329 else 330 return RV(okrate); 331 #undef RV 332 } 333 334 static int 335 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int mgt) 336 { 337 struct ifnet *ifp = &ic->ic_if; 338 struct ieee80211_node *ni; 339 enum ieee80211_state ostate; 340 ieee80211_node_critsec_decl(s); 341 342 ostate = ic->ic_state; 343 IEEE80211_DPRINTF(("%s: %s -> %s\n", __func__, 344 ieee80211_state_name[ostate], ieee80211_state_name[nstate])); 345 ic->ic_state = nstate; /* state transition */ 346 ni = ic->ic_bss; /* NB: no reference held */ 347 switch (nstate) { 348 case IEEE80211_S_INIT: 349 switch (ostate) { 350 case IEEE80211_S_INIT: 351 break; 352 case IEEE80211_S_RUN: 353 switch (ic->ic_opmode) { 354 case IEEE80211_M_STA: 355 IEEE80211_SEND_MGMT(ic, ni, 356 IEEE80211_FC0_SUBTYPE_DISASSOC, 357 IEEE80211_REASON_ASSOC_LEAVE); 358 break; 359 case IEEE80211_M_HOSTAP: 360 ieee80211_node_critsec_begin(ic, s); 361 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 362 if (ni->ni_associd == 0) 363 continue; 364 IEEE80211_SEND_MGMT(ic, ni, 365 IEEE80211_FC0_SUBTYPE_DISASSOC, 366 IEEE80211_REASON_ASSOC_LEAVE); 367 } 368 ieee80211_node_critsec_end(ic, s); 369 break; 370 default: 371 break; 372 } 373 /* FALLTHRU */ 374 case IEEE80211_S_ASSOC: 375 switch (ic->ic_opmode) { 376 case IEEE80211_M_STA: 377 IEEE80211_SEND_MGMT(ic, ni, 378 IEEE80211_FC0_SUBTYPE_DEAUTH, 379 IEEE80211_REASON_AUTH_LEAVE); 380 break; 381 case IEEE80211_M_HOSTAP: 382 ieee80211_node_critsec_begin(ic, s); 383 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 384 IEEE80211_SEND_MGMT(ic, ni, 385 IEEE80211_FC0_SUBTYPE_DEAUTH, 386 IEEE80211_REASON_AUTH_LEAVE); 387 } 388 ieee80211_node_critsec_end(ic, s); 389 break; 390 default: 391 break; 392 } 393 /* FALLTHRU */ 394 case IEEE80211_S_AUTH: 395 case IEEE80211_S_SCAN: 396 ic->ic_mgt_timer = 0; 397 #ifdef __FreeBSD__ 398 IF_DRAIN(&ic->ic_mgtq); 399 #else 400 IF_PURGE(&ic->ic_mgtq); 401 IF_PURGE(&ic->ic_pwrsaveq); 402 #endif 403 if (ic->ic_wep_ctx != NULL) { 404 free(ic->ic_wep_ctx, M_DEVBUF); 405 ic->ic_wep_ctx = NULL; 406 } 407 ieee80211_free_allnodes(ic); 408 break; 409 } 410 break; 411 case IEEE80211_S_SCAN: 412 ic->ic_flags &= ~IEEE80211_F_SIBSS; 413 /* initialize bss for probe request */ 414 IEEE80211_ADDR_COPY(ni->ni_macaddr, ifp->if_broadcastaddr); 415 IEEE80211_ADDR_COPY(ni->ni_bssid, ifp->if_broadcastaddr); 416 ni->ni_rates = ic->ic_sup_rates[ 417 ieee80211_chan2mode(ic, ni->ni_chan)]; 418 ni->ni_associd = 0; 419 ni->ni_rstamp = 0; 420 switch (ostate) { 421 case IEEE80211_S_INIT: 422 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 423 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 424 /* 425 * AP operation and we already have a channel; 426 * bypass the scan and startup immediately. 427 */ 428 ieee80211_create_ibss(ic, ic->ic_des_chan); 429 } else { 430 ieee80211_begin_scan(ifp); 431 } 432 break; 433 case IEEE80211_S_SCAN: 434 /* scan next */ 435 if (ic->ic_flags & IEEE80211_F_ASCAN) { 436 IEEE80211_SEND_MGMT(ic, ni, 437 IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0); 438 } 439 break; 440 case IEEE80211_S_RUN: 441 /* beacon miss */ 442 if (ifp->if_flags & IFF_DEBUG) { 443 /* XXX bssid clobbered above */ 444 if_printf(ifp, "no recent beacons from %s;" 445 " rescanning\n", 446 ether_sprintf(ic->ic_bss->ni_bssid)); 447 } 448 ieee80211_free_allnodes(ic); 449 /* FALLTHRU */ 450 case IEEE80211_S_AUTH: 451 case IEEE80211_S_ASSOC: 452 /* timeout restart scan */ 453 ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr); 454 if (ni != NULL) { 455 ni->ni_fails++; 456 ieee80211_unref_node(&ni); 457 } 458 ieee80211_begin_scan(ifp); 459 break; 460 } 461 break; 462 case IEEE80211_S_AUTH: 463 switch (ostate) { 464 case IEEE80211_S_INIT: 465 IEEE80211_DPRINTF(("%s: invalid transition\n", 466 __func__)); 467 break; 468 case IEEE80211_S_SCAN: 469 IEEE80211_SEND_MGMT(ic, ni, 470 IEEE80211_FC0_SUBTYPE_AUTH, 1); 471 break; 472 case IEEE80211_S_AUTH: 473 case IEEE80211_S_ASSOC: 474 switch (mgt) { 475 case IEEE80211_FC0_SUBTYPE_AUTH: 476 /* ??? */ 477 IEEE80211_SEND_MGMT(ic, ni, 478 IEEE80211_FC0_SUBTYPE_AUTH, 2); 479 break; 480 case IEEE80211_FC0_SUBTYPE_DEAUTH: 481 /* ignore and retry scan on timeout */ 482 break; 483 } 484 break; 485 case IEEE80211_S_RUN: 486 switch (mgt) { 487 case IEEE80211_FC0_SUBTYPE_AUTH: 488 IEEE80211_SEND_MGMT(ic, ni, 489 IEEE80211_FC0_SUBTYPE_AUTH, 2); 490 ic->ic_state = ostate; /* stay RUN */ 491 break; 492 case IEEE80211_FC0_SUBTYPE_DEAUTH: 493 /* try to reauth */ 494 IEEE80211_SEND_MGMT(ic, ni, 495 IEEE80211_FC0_SUBTYPE_AUTH, 1); 496 break; 497 } 498 break; 499 } 500 break; 501 case IEEE80211_S_ASSOC: 502 switch (ostate) { 503 case IEEE80211_S_INIT: 504 case IEEE80211_S_SCAN: 505 case IEEE80211_S_ASSOC: 506 IEEE80211_DPRINTF(("%s: invalid transition\n", 507 __func__)); 508 break; 509 case IEEE80211_S_AUTH: 510 IEEE80211_SEND_MGMT(ic, ni, 511 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 512 break; 513 case IEEE80211_S_RUN: 514 IEEE80211_SEND_MGMT(ic, ni, 515 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1); 516 break; 517 } 518 break; 519 case IEEE80211_S_RUN: 520 switch (ostate) { 521 case IEEE80211_S_INIT: 522 case IEEE80211_S_AUTH: 523 case IEEE80211_S_RUN: 524 IEEE80211_DPRINTF(("%s: invalid transition\n", 525 __func__)); 526 break; 527 case IEEE80211_S_SCAN: /* adhoc/hostap mode */ 528 case IEEE80211_S_ASSOC: /* infra mode */ 529 IASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates, 530 ("%s: bogus xmit rate %u setup\n", __func__, 531 ni->ni_txrate)); 532 if (ifp->if_flags & IFF_DEBUG) { 533 if_printf(ifp, " "); 534 if (ic->ic_opmode == IEEE80211_M_STA) 535 printf("associated "); 536 else 537 printf("synchronized "); 538 printf("with %s ssid ", 539 ether_sprintf(ni->ni_bssid)); 540 ieee80211_print_essid(ic->ic_bss->ni_essid, 541 ni->ni_esslen); 542 printf(" channel %d start %uMb\n", 543 ieee80211_chan2ieee(ic, ni->ni_chan), 544 IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate])); 545 } 546 ic->ic_mgt_timer = 0; 547 (*ifp->if_start)(ifp); 548 break; 549 } 550 break; 551 } 552 return 0; 553 } 554