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