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