Annotation of sys/net80211/ieee80211_proto.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ieee80211_proto.c,v 1.20 2007/07/28 11:24:06 damien Exp $ */
! 2: /* $NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 2001 Atsushi Onoe
! 6: * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. The name of the author may not be used to endorse or promote products
! 18: * derived from this software without specific prior written permission.
! 19: *
! 20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 30: */
! 31:
! 32: /*
! 33: * IEEE 802.11 protocol support.
! 34: */
! 35:
! 36: #include "bpfilter.h"
! 37:
! 38: #include <sys/param.h>
! 39: #include <sys/systm.h>
! 40: #include <sys/mbuf.h>
! 41: #include <sys/kernel.h>
! 42: #include <sys/socket.h>
! 43: #include <sys/sockio.h>
! 44: #include <sys/endian.h>
! 45: #include <sys/errno.h>
! 46: #include <sys/proc.h>
! 47: #include <sys/sysctl.h>
! 48:
! 49: #include <net/if.h>
! 50: #include <net/if_dl.h>
! 51: #include <net/if_media.h>
! 52: #include <net/if_arp.h>
! 53: #include <net/if_llc.h>
! 54:
! 55: #if NBPFILTER > 0
! 56: #include <net/bpf.h>
! 57: #endif
! 58:
! 59: #ifdef INET
! 60: #include <netinet/in.h>
! 61: #include <netinet/if_ether.h>
! 62: #endif
! 63:
! 64: #include <net80211/ieee80211_var.h>
! 65:
! 66: const char * const ieee80211_mgt_subtype_name[] = {
! 67: "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
! 68: "probe_req", "probe_resp", "reserved#6", "reserved#7",
! 69: "beacon", "atim", "disassoc", "auth",
! 70: "deauth", "action", "action_noack", "reserved#15"
! 71: };
! 72: const char * const ieee80211_state_name[IEEE80211_S_MAX] = {
! 73: "INIT", /* IEEE80211_S_INIT */
! 74: "SCAN", /* IEEE80211_S_SCAN */
! 75: "AUTH", /* IEEE80211_S_AUTH */
! 76: "ASSOC", /* IEEE80211_S_ASSOC */
! 77: "RUN" /* IEEE80211_S_RUN */
! 78: };
! 79: const char * const ieee80211_phymode_name[] = {
! 80: "auto", /* IEEE80211_MODE_AUTO */
! 81: "11a", /* IEEE80211_MODE_11A */
! 82: "11b", /* IEEE80211_MODE_11B */
! 83: "11g", /* IEEE80211_MODE_11G */
! 84: "fh", /* IEEE80211_MODE_FH */
! 85: "turbo", /* IEEE80211_MODE_TURBO */
! 86: };
! 87:
! 88: int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
! 89:
! 90: void
! 91: ieee80211_proto_attach(struct ifnet *ifp)
! 92: {
! 93: struct ieee80211com *ic = (void *)ifp;
! 94:
! 95: ifp->if_hdrlen = sizeof(struct ieee80211_frame);
! 96:
! 97: #ifdef notdef
! 98: ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
! 99: #else
! 100: ic->ic_rtsthreshold = IEEE80211_RTS_MAX;
! 101: #endif
! 102: ic->ic_fragthreshold = 2346; /* XXX not used yet */
! 103: ic->ic_fixed_rate = -1; /* no fixed rate */
! 104: ic->ic_protmode = IEEE80211_PROT_CTSONLY;
! 105:
! 106: /* protocol state change handler */
! 107: ic->ic_newstate = ieee80211_newstate;
! 108:
! 109: /* initialize management frame handlers */
! 110: ic->ic_recv_mgmt = ieee80211_recv_mgmt;
! 111: ic->ic_send_mgmt = ieee80211_send_mgmt;
! 112:
! 113: /* initialize EAPOL frame handler */
! 114: ic->ic_recv_eapol = ieee80211_recv_eapol;
! 115: }
! 116:
! 117: void
! 118: ieee80211_proto_detach(struct ifnet *ifp)
! 119: {
! 120: struct ieee80211com *ic = (void *)ifp;
! 121:
! 122: IF_PURGE(&ic->ic_mgtq);
! 123: IF_PURGE(&ic->ic_pwrsaveq);
! 124: }
! 125:
! 126: void
! 127: ieee80211_print_essid(const u_int8_t *essid, int len)
! 128: {
! 129: int i;
! 130: const 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(const 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(" %d%sM", rate / 2, (rate & 1) ? ".5" : "");
! 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,
! 213: int flags)
! 214: {
! 215: #define RV(v) ((v) & IEEE80211_RATE_VAL)
! 216: int i, j, ignore, error;
! 217: int okrate, badrate, fixedrate;
! 218: const struct ieee80211_rateset *srs;
! 219: struct ieee80211_rateset *nrs;
! 220: u_int8_t r;
! 221:
! 222: /*
! 223: * If the fixed rate check was requested but no fixed rate has been
! 224: * defined then just remove the check.
! 225: */
! 226: if ((flags & IEEE80211_F_DOFRATE) && ic->ic_fixed_rate == -1)
! 227: flags &= ~IEEE80211_F_DOFRATE;
! 228:
! 229: error = 0;
! 230: okrate = badrate = fixedrate = 0;
! 231: srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
! 232: nrs = &ni->ni_rates;
! 233: for (i = 0; i < nrs->rs_nrates; ) {
! 234: ignore = 0;
! 235: if (flags & IEEE80211_F_DOSORT) {
! 236: /*
! 237: * Sort rates.
! 238: */
! 239: for (j = i + 1; j < nrs->rs_nrates; j++) {
! 240: if (RV(nrs->rs_rates[i]) >
! 241: RV(nrs->rs_rates[j])) {
! 242: r = nrs->rs_rates[i];
! 243: nrs->rs_rates[i] = nrs->rs_rates[j];
! 244: nrs->rs_rates[j] = r;
! 245: }
! 246: }
! 247: }
! 248: r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
! 249: badrate = r;
! 250: if (flags & IEEE80211_F_DOFRATE) {
! 251: /*
! 252: * Check fixed rate is included.
! 253: */
! 254: if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
! 255: fixedrate = r;
! 256: }
! 257: if (flags & IEEE80211_F_DONEGO) {
! 258: /*
! 259: * Check against supported rates.
! 260: */
! 261: for (j = 0; j < srs->rs_nrates; j++) {
! 262: if (r == RV(srs->rs_rates[j])) {
! 263: /*
! 264: * Overwrite with the supported rate
! 265: * value so any basic rate bit is set.
! 266: * This insures that response we send
! 267: * to stations have the necessary basic
! 268: * rate bit set.
! 269: */
! 270: nrs->rs_rates[i] = srs->rs_rates[j];
! 271: break;
! 272: }
! 273: }
! 274: if (j == srs->rs_nrates) {
! 275: /*
! 276: * A rate in the node's rate set is not
! 277: * supported. If this is a basic rate and we
! 278: * are operating as an AP then this is an error.
! 279: * Otherwise we just discard/ignore the rate.
! 280: * Note that this is important for 11b stations
! 281: * when they want to associate with an 11g AP.
! 282: */
! 283: if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
! 284: (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
! 285: error++;
! 286: ignore++;
! 287: }
! 288: }
! 289: if (flags & IEEE80211_F_DODEL) {
! 290: /*
! 291: * Delete unacceptable rates.
! 292: */
! 293: if (ignore) {
! 294: nrs->rs_nrates--;
! 295: for (j = i; j < nrs->rs_nrates; j++)
! 296: nrs->rs_rates[j] = nrs->rs_rates[j + 1];
! 297: nrs->rs_rates[j] = 0;
! 298: continue;
! 299: }
! 300: }
! 301: if (!ignore)
! 302: okrate = nrs->rs_rates[i];
! 303: i++;
! 304: }
! 305: if (okrate == 0 || error != 0 ||
! 306: ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))
! 307: return badrate | IEEE80211_RATE_BASIC;
! 308: else
! 309: return RV(okrate);
! 310: #undef RV
! 311: }
! 312:
! 313: /*
! 314: * Reset 11g-related state.
! 315: */
! 316: void
! 317: ieee80211_reset_erp(struct ieee80211com *ic)
! 318: {
! 319: ic->ic_flags &= ~IEEE80211_F_USEPROT;
! 320: ic->ic_nonerpsta = 0;
! 321: ic->ic_longslotsta = 0;
! 322:
! 323: /*
! 324: * Enable short slot time iff:
! 325: * - we're operating in 802.11a or
! 326: * - we're operating in 802.11g and we're not in IBSS mode and
! 327: * the device supports short slot time
! 328: */
! 329: ieee80211_set_shortslottime(ic,
! 330: ic->ic_curmode == IEEE80211_MODE_11A ||
! 331: (ic->ic_curmode == IEEE80211_MODE_11G &&
! 332: ic->ic_opmode == IEEE80211_M_HOSTAP &&
! 333: (ic->ic_caps & IEEE80211_C_SHSLOT)));
! 334:
! 335: if (ic->ic_curmode == IEEE80211_MODE_11A ||
! 336: (ic->ic_caps & IEEE80211_C_SHPREAMBLE))
! 337: ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
! 338: else
! 339: ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
! 340: }
! 341:
! 342: /*
! 343: * Set the short slot time state and notify the driver.
! 344: */
! 345: void
! 346: ieee80211_set_shortslottime(struct ieee80211com *ic, int on)
! 347: {
! 348: if (on)
! 349: ic->ic_flags |= IEEE80211_F_SHSLOT;
! 350: else
! 351: ic->ic_flags &= ~IEEE80211_F_SHSLOT;
! 352:
! 353: /* notify the driver */
! 354: if (ic->ic_updateslot != NULL)
! 355: ic->ic_updateslot(ic);
! 356: }
! 357:
! 358: int
! 359: ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
! 360: int mgt)
! 361: {
! 362: struct ifnet *ifp = &ic->ic_if;
! 363: struct ieee80211_node *ni;
! 364: enum ieee80211_state ostate;
! 365: u_int rate;
! 366: int s;
! 367:
! 368: ostate = ic->ic_state;
! 369: IEEE80211_DPRINTF(("%s: %s -> %s\n", __func__,
! 370: ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
! 371: ic->ic_state = nstate; /* state transition */
! 372: ni = ic->ic_bss; /* NB: no reference held */
! 373: switch (nstate) {
! 374: case IEEE80211_S_INIT:
! 375: switch (ostate) {
! 376: case IEEE80211_S_INIT:
! 377: break;
! 378: case IEEE80211_S_RUN:
! 379: switch (ic->ic_opmode) {
! 380: case IEEE80211_M_STA:
! 381: IEEE80211_SEND_MGMT(ic, ni,
! 382: IEEE80211_FC0_SUBTYPE_DISASSOC,
! 383: IEEE80211_REASON_ASSOC_LEAVE);
! 384: break;
! 385: case IEEE80211_M_HOSTAP:
! 386: s = splnet();
! 387: RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
! 388: if (ni->ni_associd == 0)
! 389: continue;
! 390: IEEE80211_SEND_MGMT(ic, ni,
! 391: IEEE80211_FC0_SUBTYPE_DISASSOC,
! 392: IEEE80211_REASON_ASSOC_LEAVE);
! 393: }
! 394: splx(s);
! 395: break;
! 396: default:
! 397: break;
! 398: }
! 399: /* FALLTHROUGH */
! 400: case IEEE80211_S_ASSOC:
! 401: switch (ic->ic_opmode) {
! 402: case IEEE80211_M_STA:
! 403: IEEE80211_SEND_MGMT(ic, ni,
! 404: IEEE80211_FC0_SUBTYPE_DEAUTH,
! 405: IEEE80211_REASON_AUTH_LEAVE);
! 406: break;
! 407: case IEEE80211_M_HOSTAP:
! 408: s = splnet();
! 409: RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
! 410: IEEE80211_SEND_MGMT(ic, ni,
! 411: IEEE80211_FC0_SUBTYPE_DEAUTH,
! 412: IEEE80211_REASON_AUTH_LEAVE);
! 413: }
! 414: splx(s);
! 415: break;
! 416: default:
! 417: break;
! 418: }
! 419: /* FALLTHROUGH */
! 420: case IEEE80211_S_AUTH:
! 421: case IEEE80211_S_SCAN:
! 422: ic->ic_mgt_timer = 0;
! 423: IF_PURGE(&ic->ic_mgtq);
! 424: IF_PURGE(&ic->ic_pwrsaveq);
! 425: if (ic->ic_wep_ctx != NULL) {
! 426: free(ic->ic_wep_ctx, M_DEVBUF);
! 427: ic->ic_wep_ctx = NULL;
! 428: }
! 429: ieee80211_free_allnodes(ic);
! 430: break;
! 431: }
! 432: break;
! 433: case IEEE80211_S_SCAN:
! 434: ic->ic_flags &= ~IEEE80211_F_SIBSS;
! 435: /* initialize bss for probe request */
! 436: IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);
! 437: IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);
! 438: ni->ni_rates = ic->ic_sup_rates[
! 439: ieee80211_chan2mode(ic, ni->ni_chan)];
! 440: ni->ni_associd = 0;
! 441: ni->ni_rstamp = 0;
! 442: switch (ostate) {
! 443: case IEEE80211_S_INIT:
! 444: if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
! 445: ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
! 446: /*
! 447: * AP operation and we already have a channel;
! 448: * bypass the scan and startup immediately.
! 449: */
! 450: ieee80211_create_ibss(ic, ic->ic_des_chan);
! 451: } else {
! 452: ieee80211_begin_scan(ifp);
! 453: }
! 454: break;
! 455: case IEEE80211_S_SCAN:
! 456: /* scan next */
! 457: if (ic->ic_flags & IEEE80211_F_ASCAN) {
! 458: IEEE80211_SEND_MGMT(ic, ni,
! 459: IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
! 460: }
! 461: break;
! 462: case IEEE80211_S_RUN:
! 463: /* beacon miss */
! 464: if (ifp->if_flags & IFF_DEBUG) {
! 465: /* XXX bssid clobbered above */
! 466: printf("%s: no recent beacons from %s;"
! 467: " rescanning\n", ifp->if_xname,
! 468: ether_sprintf(ic->ic_bss->ni_bssid));
! 469: }
! 470: ieee80211_free_allnodes(ic);
! 471: /* FALLTHROUGH */
! 472: case IEEE80211_S_AUTH:
! 473: case IEEE80211_S_ASSOC:
! 474: /* timeout restart scan */
! 475: ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
! 476: if (ni != NULL)
! 477: ni->ni_fails++;
! 478: ieee80211_begin_scan(ifp);
! 479: break;
! 480: }
! 481: break;
! 482: case IEEE80211_S_AUTH:
! 483: switch (ostate) {
! 484: case IEEE80211_S_INIT:
! 485: IEEE80211_DPRINTF(("%s: invalid transition\n",
! 486: __func__));
! 487: break;
! 488: case IEEE80211_S_SCAN:
! 489: IEEE80211_SEND_MGMT(ic, ni,
! 490: IEEE80211_FC0_SUBTYPE_AUTH, 1);
! 491: break;
! 492: case IEEE80211_S_AUTH:
! 493: case IEEE80211_S_ASSOC:
! 494: switch (mgt) {
! 495: case IEEE80211_FC0_SUBTYPE_AUTH:
! 496: /* ??? */
! 497: IEEE80211_SEND_MGMT(ic, ni,
! 498: IEEE80211_FC0_SUBTYPE_AUTH, 2);
! 499: break;
! 500: case IEEE80211_FC0_SUBTYPE_DEAUTH:
! 501: /* ignore and retry scan on timeout */
! 502: break;
! 503: }
! 504: break;
! 505: case IEEE80211_S_RUN:
! 506: switch (mgt) {
! 507: case IEEE80211_FC0_SUBTYPE_AUTH:
! 508: IEEE80211_SEND_MGMT(ic, ni,
! 509: IEEE80211_FC0_SUBTYPE_AUTH, 2);
! 510: ic->ic_state = ostate; /* stay RUN */
! 511: break;
! 512: case IEEE80211_FC0_SUBTYPE_DEAUTH:
! 513: /* try to reauth */
! 514: IEEE80211_SEND_MGMT(ic, ni,
! 515: IEEE80211_FC0_SUBTYPE_AUTH, 1);
! 516: break;
! 517: }
! 518: break;
! 519: }
! 520: break;
! 521: case IEEE80211_S_ASSOC:
! 522: switch (ostate) {
! 523: case IEEE80211_S_INIT:
! 524: case IEEE80211_S_SCAN:
! 525: case IEEE80211_S_ASSOC:
! 526: IEEE80211_DPRINTF(("%s: invalid transition\n",
! 527: __func__));
! 528: break;
! 529: case IEEE80211_S_AUTH:
! 530: IEEE80211_SEND_MGMT(ic, ni,
! 531: IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
! 532: break;
! 533: case IEEE80211_S_RUN:
! 534: IEEE80211_SEND_MGMT(ic, ni,
! 535: IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
! 536: break;
! 537: }
! 538: break;
! 539: case IEEE80211_S_RUN:
! 540: switch (ostate) {
! 541: case IEEE80211_S_INIT:
! 542: case IEEE80211_S_AUTH:
! 543: case IEEE80211_S_RUN:
! 544: IEEE80211_DPRINTF(("%s: invalid transition\n",
! 545: __func__));
! 546: break;
! 547: case IEEE80211_S_SCAN: /* adhoc/hostap mode */
! 548: case IEEE80211_S_ASSOC: /* infra mode */
! 549: if (ni->ni_txrate >= ni->ni_rates.rs_nrates)
! 550: panic("%s: bogus xmit rate %u setup\n",
! 551: __func__, ni->ni_txrate);
! 552: if (ifp->if_flags & IFF_DEBUG) {
! 553: printf("%s: %s with %s ssid ",
! 554: ifp->if_xname,
! 555: ic->ic_opmode == IEEE80211_M_STA ?
! 556: "associated" : "synchronized",
! 557: ether_sprintf(ni->ni_bssid));
! 558: ieee80211_print_essid(ic->ic_bss->ni_essid,
! 559: ni->ni_esslen);
! 560: rate = ni->ni_rates.rs_rates[ni->ni_txrate] &
! 561: IEEE80211_RATE_VAL;
! 562: printf(" channel %d start %u%sMb",
! 563: ieee80211_chan2ieee(ic, ni->ni_chan),
! 564: rate / 2, (rate & 1) ? ".5" : "");
! 565: printf(" %s preamble %s slot time%s\n",
! 566: (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
! 567: "short" : "long",
! 568: (ic->ic_flags & IEEE80211_F_SHSLOT) ?
! 569: "short" : "long",
! 570: (ic->ic_flags & IEEE80211_F_USEPROT) ?
! 571: " protection enabled" : "");
! 572: }
! 573: ic->ic_mgt_timer = 0;
! 574: (*ifp->if_start)(ifp);
! 575: break;
! 576: }
! 577: break;
! 578: }
! 579: return 0;
! 580: }
CVSweb