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 * $FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.8 2004/04/02 20:22:25 sam Exp $ 33 * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_proto.c,v 1.1 2004/07/26 16:30:17 joerg Exp $ 34 */ 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 <netproto/802_11/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 /* protocol state change handler */ 108 ic->ic_newstate = ieee80211_newstate; 109 110 /* initialize management frame handlers */ 111 ic->ic_recv_mgmt = ieee80211_recv_mgmt; 112 ic->ic_send_mgmt = ieee80211_send_mgmt; 113 } 114 115 void 116 ieee80211_proto_detach(struct ifnet *ifp) 117 { 118 struct ieee80211com *ic = (void *)ifp; 119 120 IF_DRAIN(&ic->ic_mgtq); 121 } 122 123 void 124 ieee80211_print_essid(uint8_t *essid, int len) 125 { 126 int i; 127 uint8_t *p; 128 129 if (len > IEEE80211_NWID_LEN) 130 len = IEEE80211_NWID_LEN; 131 /* determine printable or not */ 132 for (i = 0, p = essid; i < len; i++, p++) { 133 if (*p < ' ' || *p > 0x7e) 134 break; 135 } 136 if (i == len) { 137 printf("\""); 138 for (i = 0, p = essid; i < len; i++, p++) 139 printf("%c", *p); 140 printf("\""); 141 } else { 142 printf("0x"); 143 for (i = 0, p = essid; i < len; i++, p++) 144 printf("%02x", *p); 145 } 146 } 147 148 void 149 ieee80211_dump_pkt(uint8_t *buf, int len, int rate, int rssi) 150 { 151 struct ieee80211_frame *wh; 152 int i; 153 154 wh = (struct ieee80211_frame *)buf; 155 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 156 case IEEE80211_FC1_DIR_NODS: 157 printf("NODS %6D->%6D(%6D)", wh->i_addr2, ":", 158 wh->i_addr1, ":", wh->i_addr3, ":"); 159 break; 160 case IEEE80211_FC1_DIR_TODS: 161 printf("TODS %6D->%6D(%6D)", wh->i_addr2, ":", 162 wh->i_addr3, ":", wh->i_addr1, ":"); 163 break; 164 case IEEE80211_FC1_DIR_FROMDS: 165 printf("FRDS %6D->%6D(%6D)", wh->i_addr3, ":", 166 wh->i_addr1, ":", wh->i_addr2, ":"); 167 break; 168 case IEEE80211_FC1_DIR_DSTODS: 169 printf("DSDS %6D->%6D(%6D->%6D)", (uint8_t *)&wh[1], ":", 170 wh->i_addr3, ":", wh->i_addr2, ":", wh->i_addr1, ":"); 171 break; 172 } 173 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 174 case IEEE80211_FC0_TYPE_DATA: 175 printf(" data"); 176 break; 177 case IEEE80211_FC0_TYPE_MGT: 178 printf(" %s", ieee80211_mgt_subtype_name[ 179 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) 180 >> IEEE80211_FC0_SUBTYPE_SHIFT]); 181 break; 182 default: 183 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 184 break; 185 } 186 if (wh->i_fc[1] & IEEE80211_FC1_WEP) 187 printf(" WEP"); 188 if (rate >= 0) 189 printf(" %dM", rate / 2); 190 if (rssi >= 0) 191 printf(" +%d", rssi); 192 printf("\n"); 193 if (len > 0) { 194 for (i = 0; i < len; i++) { 195 if ((i & 1) == 0) 196 printf(" "); 197 printf("%02x", buf[i]); 198 } 199 printf("\n"); 200 } 201 } 202 203 int 204 ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags) 205 { 206 #define RV(v) ((v) & IEEE80211_RATE_VAL) 207 int i, j, ignore, error; 208 int okrate, badrate; 209 struct ieee80211_rateset *srs, *nrs; 210 uint8_t r; 211 212 error = 0; 213 okrate = badrate = 0; 214 srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; 215 nrs = &ni->ni_rates; 216 for (i = 0; i < nrs->rs_nrates; ) { 217 ignore = 0; 218 if (flags & IEEE80211_F_DOSORT) { 219 /* 220 * Sort rates. 221 */ 222 for (j = i + 1; j < nrs->rs_nrates; j++) { 223 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) { 224 r = nrs->rs_rates[i]; 225 nrs->rs_rates[i] = nrs->rs_rates[j]; 226 nrs->rs_rates[j] = r; 227 } 228 } 229 } 230 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL; 231 badrate = r; 232 if (flags & IEEE80211_F_DOFRATE) { 233 /* 234 * Apply fixed rate constraint. Note that we do 235 * not apply the constraint to basic rates as 236 * otherwise we may not be able to associate if 237 * the rate set we submit to the AP is invalid 238 * (e.g. fix rate at 36Mb/s which is not a basic 239 * rate for 11a operation). 240 */ 241 if ((nrs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0 && 242 ic->ic_fixed_rate >= 0 && 243 r != RV(srs->rs_rates[ic->ic_fixed_rate])) 244 ignore++; 245 } 246 if (flags & IEEE80211_F_DONEGO) { 247 /* 248 * Check against supported rates. 249 */ 250 for (j = 0; j < srs->rs_nrates; j++) { 251 if (r == RV(srs->rs_rates[j])) { 252 /* 253 * Overwrite with the supported rate 254 * value so any basic rate bit is set. 255 * This insures that response we send 256 * to stations have the necessary basic 257 * rate bit set. 258 */ 259 nrs->rs_rates[i] = srs->rs_rates[j]; 260 break; 261 } 262 } 263 if (j == srs->rs_nrates) { 264 /* 265 * A rate in the node's rate set is not 266 * supported. If this is a basic rate and we 267 * are operating as an AP then this is an error. 268 * Otherwise we just discard/ignore the rate. 269 * Note that this is important for 11b stations 270 * when they want to associate with an 11g AP. 271 */ 272 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 273 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC)) 274 error++; 275 ignore++; 276 } 277 } 278 if (flags & IEEE80211_F_DODEL) { 279 /* 280 * Delete unacceptable rates. 281 */ 282 if (ignore) { 283 nrs->rs_nrates--; 284 for (j = i; j < nrs->rs_nrates; j++) 285 nrs->rs_rates[j] = nrs->rs_rates[j + 1]; 286 nrs->rs_rates[j] = 0; 287 continue; 288 } 289 } 290 if (!ignore) 291 okrate = nrs->rs_rates[i]; 292 i++; 293 } 294 if (okrate == 0 || error != 0) 295 return badrate | IEEE80211_RATE_BASIC; 296 else 297 return RV(okrate); 298 #undef RV 299 } 300 301 static int 302 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int mgt) 303 { 304 struct ifnet *ifp = &ic->ic_if; 305 struct ieee80211_node *ni; 306 enum ieee80211_state ostate; 307 struct lwkt_tokref ilock; 308 309 ostate = ic->ic_state; 310 IEEE80211_DPRINTF(("%s: %s -> %s\n", __func__, 311 ieee80211_state_name[ostate], ieee80211_state_name[nstate])); 312 ic->ic_state = nstate; /* state transition */ 313 ni = ic->ic_bss; /* NB: no reference held */ 314 switch (nstate) { 315 case IEEE80211_S_INIT: 316 switch (ostate) { 317 case IEEE80211_S_INIT: 318 break; 319 case IEEE80211_S_RUN: 320 switch (ic->ic_opmode) { 321 case IEEE80211_M_STA: 322 IEEE80211_SEND_MGMT(ic, ni, 323 IEEE80211_FC0_SUBTYPE_DISASSOC, 324 IEEE80211_REASON_ASSOC_LEAVE); 325 break; 326 case IEEE80211_M_HOSTAP: 327 lwkt_gettoken(&ilock, &ic->ic_nodetoken); 328 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 329 if (ni->ni_associd == 0) 330 continue; 331 IEEE80211_SEND_MGMT(ic, ni, 332 IEEE80211_FC0_SUBTYPE_DISASSOC, 333 IEEE80211_REASON_ASSOC_LEAVE); 334 } 335 lwkt_reltoken(&ilock); 336 break; 337 default: 338 break; 339 } 340 /* FALLTHRU */ 341 case IEEE80211_S_ASSOC: 342 switch (ic->ic_opmode) { 343 case IEEE80211_M_STA: 344 IEEE80211_SEND_MGMT(ic, ni, 345 IEEE80211_FC0_SUBTYPE_DEAUTH, 346 IEEE80211_REASON_AUTH_LEAVE); 347 break; 348 case IEEE80211_M_HOSTAP: 349 lwkt_gettoken(&ilock, &ic->ic_nodetoken); 350 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 351 IEEE80211_SEND_MGMT(ic, ni, 352 IEEE80211_FC0_SUBTYPE_DEAUTH, 353 IEEE80211_REASON_AUTH_LEAVE); 354 } 355 lwkt_reltoken(&ilock); 356 break; 357 default: 358 break; 359 } 360 /* FALLTHRU */ 361 case IEEE80211_S_AUTH: 362 case IEEE80211_S_SCAN: 363 ic->ic_mgt_timer = 0; 364 IF_DRAIN(&ic->ic_mgtq); 365 if (ic->ic_wep_ctx != NULL) { 366 free(ic->ic_wep_ctx, M_DEVBUF); 367 ic->ic_wep_ctx = NULL; 368 } 369 ieee80211_free_allnodes(ic); 370 break; 371 } 372 break; 373 case IEEE80211_S_SCAN: 374 ic->ic_flags &= ~IEEE80211_F_SIBSS; 375 /* initialize bss for probe request */ 376 IEEE80211_ADDR_COPY(ni->ni_macaddr, ifp->if_broadcastaddr); 377 IEEE80211_ADDR_COPY(ni->ni_bssid, ifp->if_broadcastaddr); 378 ni->ni_rates = ic->ic_sup_rates[ 379 ieee80211_chan2mode(ic, ni->ni_chan)]; 380 ni->ni_associd = 0; 381 ni->ni_rstamp = 0; 382 switch (ostate) { 383 case IEEE80211_S_INIT: 384 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 385 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 386 /* 387 * AP operation and we already have a channel; 388 * bypass the scan and startup immediately. 389 */ 390 ieee80211_create_ibss(ic, ic->ic_des_chan); 391 } else { 392 ieee80211_begin_scan(ifp); 393 } 394 break; 395 case IEEE80211_S_SCAN: 396 /* scan next */ 397 if (ic->ic_flags & IEEE80211_F_ASCAN) { 398 IEEE80211_SEND_MGMT(ic, ni, 399 IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0); 400 } 401 break; 402 case IEEE80211_S_RUN: 403 /* beacon miss */ 404 if (ifp->if_flags & IFF_DEBUG) { 405 /* XXX bssid clobbered above */ 406 if_printf(ifp, "no recent beacons from %6D;" 407 " rescanning\n", 408 ic->ic_bss->ni_bssid, ":"); 409 } 410 ieee80211_free_allnodes(ic); 411 /* FALLTHRU */ 412 case IEEE80211_S_AUTH: 413 case IEEE80211_S_ASSOC: 414 /* timeout restart scan */ 415 ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr); 416 if (ni != NULL) { 417 ni->ni_fails++; 418 ieee80211_unref_node(&ni); 419 } 420 ieee80211_begin_scan(ifp); 421 break; 422 } 423 break; 424 case IEEE80211_S_AUTH: 425 switch (ostate) { 426 case IEEE80211_S_INIT: 427 IEEE80211_DPRINTF(("%s: invalid transition\n", 428 __func__)); 429 break; 430 case IEEE80211_S_SCAN: 431 IEEE80211_SEND_MGMT(ic, ni, 432 IEEE80211_FC0_SUBTYPE_AUTH, 1); 433 break; 434 case IEEE80211_S_AUTH: 435 case IEEE80211_S_ASSOC: 436 switch (mgt) { 437 case IEEE80211_FC0_SUBTYPE_AUTH: 438 /* ??? */ 439 IEEE80211_SEND_MGMT(ic, ni, 440 IEEE80211_FC0_SUBTYPE_AUTH, 2); 441 break; 442 case IEEE80211_FC0_SUBTYPE_DEAUTH: 443 /* ignore and retry scan on timeout */ 444 break; 445 } 446 break; 447 case IEEE80211_S_RUN: 448 switch (mgt) { 449 case IEEE80211_FC0_SUBTYPE_AUTH: 450 IEEE80211_SEND_MGMT(ic, ni, 451 IEEE80211_FC0_SUBTYPE_AUTH, 2); 452 ic->ic_state = ostate; /* stay RUN */ 453 break; 454 case IEEE80211_FC0_SUBTYPE_DEAUTH: 455 /* try to reauth */ 456 IEEE80211_SEND_MGMT(ic, ni, 457 IEEE80211_FC0_SUBTYPE_AUTH, 1); 458 break; 459 } 460 break; 461 } 462 break; 463 case IEEE80211_S_ASSOC: 464 switch (ostate) { 465 case IEEE80211_S_INIT: 466 case IEEE80211_S_SCAN: 467 case IEEE80211_S_ASSOC: 468 IEEE80211_DPRINTF(("%s: invalid transition\n", 469 __func__)); 470 break; 471 case IEEE80211_S_AUTH: 472 IEEE80211_SEND_MGMT(ic, ni, 473 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 474 break; 475 case IEEE80211_S_RUN: 476 IEEE80211_SEND_MGMT(ic, ni, 477 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1); 478 break; 479 } 480 break; 481 case IEEE80211_S_RUN: 482 switch (ostate) { 483 case IEEE80211_S_INIT: 484 case IEEE80211_S_AUTH: 485 case IEEE80211_S_RUN: 486 IEEE80211_DPRINTF(("%s: invalid transition\n", 487 __func__)); 488 break; 489 case IEEE80211_S_SCAN: /* adhoc/hostap mode */ 490 case IEEE80211_S_ASSOC: /* infra mode */ 491 KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates, 492 ("%s: bogus xmit rate %u setup\n", __func__, 493 ni->ni_txrate)); 494 if (ifp->if_flags & IFF_DEBUG) { 495 if_printf(ifp, " "); 496 if (ic->ic_opmode == IEEE80211_M_STA) 497 printf("associated "); 498 else 499 printf("synchronized "); 500 printf("with %6D ssid ", ni->ni_bssid, ":"); 501 ieee80211_print_essid(ic->ic_bss->ni_essid, 502 ni->ni_esslen); 503 printf(" channel %d start %uMb\n", 504 ieee80211_chan2ieee(ic, ni->ni_chan), 505 IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate])); 506 } 507 ic->ic_mgt_timer = 0; 508 (*ifp->if_start)(ifp); 509 break; 510 } 511 break; 512 } 513 return 0; 514 } 515