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