Deleted Added
full compact
ieee80211_proto.c (172058) ieee80211_proto.c (172211)
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2007 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2007 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_proto.c 172058 2007-09-05 21:31:32Z sam $");
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_proto.c 172211 2007-09-17 19:07:24Z sam $");
29
30/*
31 * IEEE 802.11 protocol support.
32 */
33
34#include "opt_inet.h"
35
36#include <sys/param.h>
37#include <sys/kernel.h>
38#include <sys/systm.h>
39
40#include <sys/socket.h>
41
42#include <net/if.h>
43#include <net/if_media.h>
44#include <net/ethernet.h> /* XXX for ether_sprintf */
45
46#include <net80211/ieee80211_var.h>
47
48/* XXX tunables */
49#define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */
50#define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */
51
52#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2)
53
54const char *ieee80211_mgt_subtype_name[] = {
55 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
56 "probe_req", "probe_resp", "reserved#6", "reserved#7",
57 "beacon", "atim", "disassoc", "auth",
58 "deauth", "reserved#13", "reserved#14", "reserved#15"
59};
60const char *ieee80211_ctl_subtype_name[] = {
61 "reserved#0", "reserved#1", "reserved#2", "reserved#3",
62 "reserved#3", "reserved#5", "reserved#6", "reserved#7",
63 "reserved#8", "reserved#9", "ps_poll", "rts",
64 "cts", "ack", "cf_end", "cf_end_ack"
65};
66const char *ieee80211_opmode_name[IEEE80211_OPMODE_MAX] = {
67 "IBSS", /* IEEE80211_M_IBSS */
68 "STA", /* IEEE80211_M_STA */
69 "#2",
70 "AHDEMO", /* IEEE80211_M_AHDEMO */
71 "#4", "#5",
72 "HOSTAP", /* IEEE80211_M_HOSTAP */
73 "#7",
74 "MONITOR" /* IEEE80211_M_MONITOR */
75};
76const char *ieee80211_state_name[IEEE80211_S_MAX] = {
77 "INIT", /* IEEE80211_S_INIT */
78 "SCAN", /* IEEE80211_S_SCAN */
79 "AUTH", /* IEEE80211_S_AUTH */
80 "ASSOC", /* IEEE80211_S_ASSOC */
81 "CAC", /* IEEE80211_S_CAC */
82 "RUN", /* IEEE80211_S_RUN */
83 "CSA", /* IEEE80211_S_CSA */
84 "SLEEP", /* IEEE80211_S_SLEEP */
85};
86const char *ieee80211_wme_acnames[] = {
87 "WME_AC_BE",
88 "WME_AC_BK",
89 "WME_AC_VI",
90 "WME_AC_VO",
91 "WME_UPSD",
92};
93
94static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
95
29
30/*
31 * IEEE 802.11 protocol support.
32 */
33
34#include "opt_inet.h"
35
36#include <sys/param.h>
37#include <sys/kernel.h>
38#include <sys/systm.h>
39
40#include <sys/socket.h>
41
42#include <net/if.h>
43#include <net/if_media.h>
44#include <net/ethernet.h> /* XXX for ether_sprintf */
45
46#include <net80211/ieee80211_var.h>
47
48/* XXX tunables */
49#define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */
50#define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */
51
52#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2)
53
54const char *ieee80211_mgt_subtype_name[] = {
55 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
56 "probe_req", "probe_resp", "reserved#6", "reserved#7",
57 "beacon", "atim", "disassoc", "auth",
58 "deauth", "reserved#13", "reserved#14", "reserved#15"
59};
60const char *ieee80211_ctl_subtype_name[] = {
61 "reserved#0", "reserved#1", "reserved#2", "reserved#3",
62 "reserved#3", "reserved#5", "reserved#6", "reserved#7",
63 "reserved#8", "reserved#9", "ps_poll", "rts",
64 "cts", "ack", "cf_end", "cf_end_ack"
65};
66const char *ieee80211_opmode_name[IEEE80211_OPMODE_MAX] = {
67 "IBSS", /* IEEE80211_M_IBSS */
68 "STA", /* IEEE80211_M_STA */
69 "#2",
70 "AHDEMO", /* IEEE80211_M_AHDEMO */
71 "#4", "#5",
72 "HOSTAP", /* IEEE80211_M_HOSTAP */
73 "#7",
74 "MONITOR" /* IEEE80211_M_MONITOR */
75};
76const char *ieee80211_state_name[IEEE80211_S_MAX] = {
77 "INIT", /* IEEE80211_S_INIT */
78 "SCAN", /* IEEE80211_S_SCAN */
79 "AUTH", /* IEEE80211_S_AUTH */
80 "ASSOC", /* IEEE80211_S_ASSOC */
81 "CAC", /* IEEE80211_S_CAC */
82 "RUN", /* IEEE80211_S_RUN */
83 "CSA", /* IEEE80211_S_CSA */
84 "SLEEP", /* IEEE80211_S_SLEEP */
85};
86const char *ieee80211_wme_acnames[] = {
87 "WME_AC_BE",
88 "WME_AC_BK",
89 "WME_AC_VI",
90 "WME_AC_VO",
91 "WME_UPSD",
92};
93
94static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
95
96static void
97null_update_beacon(struct ieee80211com *ic, int item)
98{
99}
100
96void
97ieee80211_proto_attach(struct ieee80211com *ic)
98{
99 struct ifnet *ifp = ic->ic_ifp;
100
101 /* XXX room for crypto */
102 ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4);
103
104 ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
105 ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT;
106 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
107 ic->ic_bmiss_max = IEEE80211_BMISS_MAX;
108 callout_init(&ic->ic_swbmiss, CALLOUT_MPSAFE);
109 callout_init(&ic->ic_mgtsend, CALLOUT_MPSAFE);
110 ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT;
111 ic->ic_protmode = IEEE80211_PROT_CTSONLY;
112 ic->ic_roaming = IEEE80211_ROAMING_AUTO;
113
114 ic->ic_wme.wme_hipri_switch_hysteresis =
115 AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
116
117 mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_xname, "mgmt send q", MTX_DEF);
118
119 /* protocol state change handler */
120 ic->ic_newstate = ieee80211_newstate;
101void
102ieee80211_proto_attach(struct ieee80211com *ic)
103{
104 struct ifnet *ifp = ic->ic_ifp;
105
106 /* XXX room for crypto */
107 ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4);
108
109 ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
110 ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT;
111 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
112 ic->ic_bmiss_max = IEEE80211_BMISS_MAX;
113 callout_init(&ic->ic_swbmiss, CALLOUT_MPSAFE);
114 callout_init(&ic->ic_mgtsend, CALLOUT_MPSAFE);
115 ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT;
116 ic->ic_protmode = IEEE80211_PROT_CTSONLY;
117 ic->ic_roaming = IEEE80211_ROAMING_AUTO;
118
119 ic->ic_wme.wme_hipri_switch_hysteresis =
120 AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
121
122 mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_xname, "mgmt send q", MTX_DEF);
123
124 /* protocol state change handler */
125 ic->ic_newstate = ieee80211_newstate;
126 ic->ic_update_beacon = null_update_beacon;
121
122 /* initialize management frame handlers */
123 ic->ic_recv_mgmt = ieee80211_recv_mgmt;
124 ic->ic_send_mgmt = ieee80211_send_mgmt;
125 ic->ic_raw_xmit = ieee80211_raw_xmit;
126}
127
128void
129ieee80211_proto_detach(struct ieee80211com *ic)
130{
131
132 /*
133 * This should not be needed as we detach when reseting
134 * the state but be conservative here since the
135 * authenticator may do things like spawn kernel threads.
136 */
137 if (ic->ic_auth->ia_detach)
138 ic->ic_auth->ia_detach(ic);
139
140 ieee80211_drain_ifq(&ic->ic_mgtq);
141 mtx_destroy(&ic->ic_mgtq.ifq_mtx);
142
143 /*
144 * Detach any ACL'ator.
145 */
146 if (ic->ic_acl != NULL)
147 ic->ic_acl->iac_detach(ic);
148}
149
150/*
151 * Simple-minded authenticator module support.
152 */
153
154#define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WPA+1)
155/* XXX well-known names */
156static const char *auth_modnames[IEEE80211_AUTH_MAX] = {
157 "wlan_internal", /* IEEE80211_AUTH_NONE */
158 "wlan_internal", /* IEEE80211_AUTH_OPEN */
159 "wlan_internal", /* IEEE80211_AUTH_SHARED */
160 "wlan_xauth", /* IEEE80211_AUTH_8021X */
161 "wlan_internal", /* IEEE80211_AUTH_AUTO */
162 "wlan_xauth", /* IEEE80211_AUTH_WPA */
163};
164static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX];
165
166static const struct ieee80211_authenticator auth_internal = {
167 .ia_name = "wlan_internal",
168 .ia_attach = NULL,
169 .ia_detach = NULL,
170 .ia_node_join = NULL,
171 .ia_node_leave = NULL,
172};
173
174/*
175 * Setup internal authenticators once; they are never unregistered.
176 */
177static void
178ieee80211_auth_setup(void)
179{
180 ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal);
181 ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal);
182 ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal);
183}
184SYSINIT(wlan_auth, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_auth_setup, NULL);
185
186const struct ieee80211_authenticator *
187ieee80211_authenticator_get(int auth)
188{
189 if (auth >= IEEE80211_AUTH_MAX)
190 return NULL;
191 if (authenticators[auth] == NULL)
192 ieee80211_load_module(auth_modnames[auth]);
193 return authenticators[auth];
194}
195
196void
197ieee80211_authenticator_register(int type,
198 const struct ieee80211_authenticator *auth)
199{
200 if (type >= IEEE80211_AUTH_MAX)
201 return;
202 authenticators[type] = auth;
203}
204
205void
206ieee80211_authenticator_unregister(int type)
207{
208
209 if (type >= IEEE80211_AUTH_MAX)
210 return;
211 authenticators[type] = NULL;
212}
213
214/*
215 * Very simple-minded ACL module support.
216 */
217/* XXX just one for now */
218static const struct ieee80211_aclator *acl = NULL;
219
220void
221ieee80211_aclator_register(const struct ieee80211_aclator *iac)
222{
223 printf("wlan: %s acl policy registered\n", iac->iac_name);
224 acl = iac;
225}
226
227void
228ieee80211_aclator_unregister(const struct ieee80211_aclator *iac)
229{
230 if (acl == iac)
231 acl = NULL;
232 printf("wlan: %s acl policy unregistered\n", iac->iac_name);
233}
234
235const struct ieee80211_aclator *
236ieee80211_aclator_get(const char *name)
237{
238 if (acl == NULL)
239 ieee80211_load_module("wlan_acl");
240 return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL;
241}
242
243void
244ieee80211_print_essid(const uint8_t *essid, int len)
245{
246 const uint8_t *p;
247 int i;
248
249 if (len > IEEE80211_NWID_LEN)
250 len = IEEE80211_NWID_LEN;
251 /* determine printable or not */
252 for (i = 0, p = essid; i < len; i++, p++) {
253 if (*p < ' ' || *p > 0x7e)
254 break;
255 }
256 if (i == len) {
257 printf("\"");
258 for (i = 0, p = essid; i < len; i++, p++)
259 printf("%c", *p);
260 printf("\"");
261 } else {
262 printf("0x");
263 for (i = 0, p = essid; i < len; i++, p++)
264 printf("%02x", *p);
265 }
266}
267
268void
269ieee80211_dump_pkt(struct ieee80211com *ic,
270 const uint8_t *buf, int len, int rate, int rssi)
271{
272 const struct ieee80211_frame *wh;
273 int i;
274
275 wh = (const struct ieee80211_frame *)buf;
276 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
277 case IEEE80211_FC1_DIR_NODS:
278 printf("NODS %s", ether_sprintf(wh->i_addr2));
279 printf("->%s", ether_sprintf(wh->i_addr1));
280 printf("(%s)", ether_sprintf(wh->i_addr3));
281 break;
282 case IEEE80211_FC1_DIR_TODS:
283 printf("TODS %s", ether_sprintf(wh->i_addr2));
284 printf("->%s", ether_sprintf(wh->i_addr3));
285 printf("(%s)", ether_sprintf(wh->i_addr1));
286 break;
287 case IEEE80211_FC1_DIR_FROMDS:
288 printf("FRDS %s", ether_sprintf(wh->i_addr3));
289 printf("->%s", ether_sprintf(wh->i_addr1));
290 printf("(%s)", ether_sprintf(wh->i_addr2));
291 break;
292 case IEEE80211_FC1_DIR_DSTODS:
293 printf("DSDS %s", ether_sprintf((const uint8_t *)&wh[1]));
294 printf("->%s", ether_sprintf(wh->i_addr3));
295 printf("(%s", ether_sprintf(wh->i_addr2));
296 printf("->%s)", ether_sprintf(wh->i_addr1));
297 break;
298 }
299 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
300 case IEEE80211_FC0_TYPE_DATA:
301 printf(" data");
302 break;
303 case IEEE80211_FC0_TYPE_MGT:
304 printf(" %s", ieee80211_mgt_subtype_name[
305 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
306 >> IEEE80211_FC0_SUBTYPE_SHIFT]);
307 break;
308 default:
309 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
310 break;
311 }
312 if (IEEE80211_QOS_HAS_SEQ(wh)) {
313 const struct ieee80211_qosframe *qwh =
314 (const struct ieee80211_qosframe *)buf;
315 printf(" QoS [TID %u%s]", qwh->i_qos[0] & IEEE80211_QOS_TID,
316 qwh->i_qos[0] & IEEE80211_QOS_ACKPOLICY ? " ACM" : "");
317 }
318 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
319 int off;
320
321 off = ieee80211_anyhdrspace(ic, wh);
322 printf(" WEP [IV %.02x %.02x %.02x",
323 buf[off+0], buf[off+1], buf[off+2]);
324 if (buf[off+IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)
325 printf(" %.02x %.02x %.02x",
326 buf[off+4], buf[off+5], buf[off+6]);
327 printf(" KID %u]", buf[off+IEEE80211_WEP_IVLEN] >> 6);
328 }
329 if (rate >= 0)
330 printf(" %dM", rate / 2);
331 if (rssi >= 0)
332 printf(" +%d", rssi);
333 printf("\n");
334 if (len > 0) {
335 for (i = 0; i < len; i++) {
336 if ((i & 1) == 0)
337 printf(" ");
338 printf("%02x", buf[i]);
339 }
340 printf("\n");
341 }
342}
343
344static __inline int
345findrix(const struct ieee80211_rateset *rs, int r)
346{
347 int i;
348
349 for (i = 0; i < rs->rs_nrates; i++)
350 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == r)
351 return i;
352 return -1;
353}
354
355int
356ieee80211_fix_rate(struct ieee80211_node *ni,
357 struct ieee80211_rateset *nrs, int flags)
358{
359#define RV(v) ((v) & IEEE80211_RATE_VAL)
360 struct ieee80211com *ic = ni->ni_ic;
361 int i, j, rix, error;
362 int okrate, badrate, fixedrate;
363 const struct ieee80211_rateset *srs;
364 uint8_t r;
365
366 error = 0;
367 okrate = badrate = 0;
368 fixedrate = IEEE80211_FIXED_RATE_NONE;
369 srs = ieee80211_get_suprates(ic, ni->ni_chan);
370 for (i = 0; i < nrs->rs_nrates; ) {
371 if (flags & IEEE80211_F_DOSORT) {
372 /*
373 * Sort rates.
374 */
375 for (j = i + 1; j < nrs->rs_nrates; j++) {
376 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) {
377 r = nrs->rs_rates[i];
378 nrs->rs_rates[i] = nrs->rs_rates[j];
379 nrs->rs_rates[j] = r;
380 }
381 }
382 }
383 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
384 badrate = r;
385 /*
386 * Check for fixed rate.
387 */
388 if (r == ic->ic_fixed_rate)
389 fixedrate = r;
390 /*
391 * Check against supported rates.
392 */
393 rix = findrix(srs, r);
394 if (flags & IEEE80211_F_DONEGO) {
395 if (rix < 0) {
396 /*
397 * A rate in the node's rate set is not
398 * supported. If this is a basic rate and we
399 * are operating as a STA then this is an error.
400 * Otherwise we just discard/ignore the rate.
401 */
402 if ((flags & IEEE80211_F_JOIN) &&
403 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
404 error++;
405 } else if ((flags & IEEE80211_F_JOIN) == 0) {
406 /*
407 * Overwrite with the supported rate
408 * value so any basic rate bit is set.
409 */
410 nrs->rs_rates[i] = srs->rs_rates[rix];
411 }
412 }
413 if ((flags & IEEE80211_F_DODEL) && rix < 0) {
414 /*
415 * Delete unacceptable rates.
416 */
417 nrs->rs_nrates--;
418 for (j = i; j < nrs->rs_nrates; j++)
419 nrs->rs_rates[j] = nrs->rs_rates[j + 1];
420 nrs->rs_rates[j] = 0;
421 continue;
422 }
423 if (rix >= 0)
424 okrate = nrs->rs_rates[i];
425 i++;
426 }
427 if (okrate == 0 || error != 0 ||
428 ((flags & IEEE80211_F_DOFRATE) && fixedrate != ic->ic_fixed_rate))
429 return badrate | IEEE80211_RATE_BASIC;
430 else
431 return RV(okrate);
432#undef RV
433}
434
435/*
436 * Reset 11g-related state.
437 */
438void
439ieee80211_reset_erp(struct ieee80211com *ic)
440{
441 ic->ic_flags &= ~IEEE80211_F_USEPROT;
442 ic->ic_nonerpsta = 0;
443 ic->ic_longslotsta = 0;
444 /*
445 * Short slot time is enabled only when operating in 11g
446 * and not in an IBSS. We must also honor whether or not
447 * the driver is capable of doing it.
448 */
449 ieee80211_set_shortslottime(ic,
450 IEEE80211_IS_CHAN_A(ic->ic_curchan) ||
451 IEEE80211_IS_CHAN_HT(ic->ic_curchan) ||
452 (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) &&
453 ic->ic_opmode == IEEE80211_M_HOSTAP &&
454 (ic->ic_caps & IEEE80211_C_SHSLOT)));
455 /*
456 * Set short preamble and ERP barker-preamble flags.
457 */
458 if (IEEE80211_IS_CHAN_A(ic->ic_curchan) ||
459 (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) {
460 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
461 ic->ic_flags &= ~IEEE80211_F_USEBARKER;
462 } else {
463 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
464 ic->ic_flags |= IEEE80211_F_USEBARKER;
465 }
466}
467
468/*
469 * Set the short slot time state and notify the driver.
470 */
471void
472ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff)
473{
474 if (onoff)
475 ic->ic_flags |= IEEE80211_F_SHSLOT;
476 else
477 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
478 /* notify driver */
479 if (ic->ic_updateslot != NULL)
480 ic->ic_updateslot(ic->ic_ifp);
481}
482
483/*
484 * Check if the specified rate set supports ERP.
485 * NB: the rate set is assumed to be sorted.
486 */
487int
488ieee80211_iserp_rateset(struct ieee80211com *ic, struct ieee80211_rateset *rs)
489{
490#define N(a) (sizeof(a) / sizeof(a[0]))
491 static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 };
492 int i, j;
493
494 if (rs->rs_nrates < N(rates))
495 return 0;
496 for (i = 0; i < N(rates); i++) {
497 for (j = 0; j < rs->rs_nrates; j++) {
498 int r = rs->rs_rates[j] & IEEE80211_RATE_VAL;
499 if (rates[i] == r)
500 goto next;
501 if (r > rates[i])
502 return 0;
503 }
504 return 0;
505 next:
506 ;
507 }
508 return 1;
509#undef N
510}
511
512/*
513 * Mark the basic rates for the 11g rate table based on the
514 * operating mode. For real 11g we mark all the 11b rates
515 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only
516 * 11b rates. There's also a pseudo 11a-mode used to mark only
517 * the basic OFDM rates.
518 */
519void
520ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode)
521{
522 static const struct ieee80211_rateset basic[IEEE80211_MODE_MAX] = {
523 { .rs_nrates = 0 }, /* IEEE80211_MODE_AUTO */
524 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */
525 { 2, { 2, 4 } }, /* IEEE80211_MODE_11B */
526 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G (mixed b/g) */
527 { .rs_nrates = 0 }, /* IEEE80211_MODE_FH */
528 /* IEEE80211_MODE_PUREG (not yet) */
529 { 7, { 2, 4, 11, 22, 12, 24, 48 } },
530 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11NA */
531 /* IEEE80211_MODE_11NG (mixed b/g) */
532 { 7, { 2, 4, 11, 22, 12, 24, 48 } },
533 };
534 int i, j;
535
536 for (i = 0; i < rs->rs_nrates; i++) {
537 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
538 for (j = 0; j < basic[mode].rs_nrates; j++)
539 if (basic[mode].rs_rates[j] == rs->rs_rates[i]) {
540 rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
541 break;
542 }
543 }
544}
545
546/*
547 * WME protocol support. The following parameters come from the spec.
548 */
549typedef struct phyParamType {
550 uint8_t aifsn;
551 uint8_t logcwmin;
552 uint8_t logcwmax;
553 uint16_t txopLimit;
554 uint8_t acm;
555} paramType;
556
557static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = {
558 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_AUTO */
559 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11A */
560 { 3, 5, 7, 0, 0 }, /* IEEE80211_MODE_11B */
561 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11G */
562 { 3, 5, 7, 0, 0 }, /* IEEE80211_MODE_FH */
563 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO_A */
564 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO_G */
565 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_STURBO_A */
566 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11NA */ /* XXXcheck*/
567 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11NG */ /* XXXcheck*/
568};
569static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = {
570 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_AUTO */
571 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */
572 { 7, 5, 10, 0, 0 }, /* IEEE80211_MODE_11B */
573 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11G */
574 { 7, 5, 10, 0, 0 }, /* IEEE80211_MODE_FH */
575 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_A */
576 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_G */
577 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_STURBO_A */
578 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NA */
579 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NG */
580};
581static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = {
582 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_AUTO */
583 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */
584 { 1, 4, 5, 188, 0 }, /* IEEE80211_MODE_11B */
585 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11G */
586 { 1, 4, 5, 188, 0 }, /* IEEE80211_MODE_FH */
587 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_A */
588 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_G */
589 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_STURBO_A */
590 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NA */
591 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NG */
592};
593static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = {
594 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_AUTO */
595 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */
596 { 1, 3, 4, 102, 0 }, /* IEEE80211_MODE_11B */
597 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11G */
598 { 1, 3, 4, 102, 0 }, /* IEEE80211_MODE_FH */
599 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_A */
600 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_G */
601 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_STURBO_A */
602 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NA */
603 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NG */
604};
605
606static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = {
607 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_AUTO */
608 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */
609 { 3, 5, 10, 0, 0 }, /* IEEE80211_MODE_11B */
610 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11G */
611 { 3, 5, 10, 0, 0 }, /* IEEE80211_MODE_FH */
612 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_A */
613 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_G */
614 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_STURBO_A */
615 { 1, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NA */
616 { 1, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NG */
617};
618static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = {
619 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_AUTO */
620 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */
621 { 2, 4, 5, 188, 0 }, /* IEEE80211_MODE_11B */
622 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11G */
623 { 2, 4, 5, 188, 0 }, /* IEEE80211_MODE_FH */
624 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_A */
625 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_G */
626 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_STURBO_A */
627 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NA */
628 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NG */
629};
630static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = {
631 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_AUTO */
632 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */
633 { 2, 3, 4, 102, 0 }, /* IEEE80211_MODE_11B */
634 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11G */
635 { 2, 3, 4, 102, 0 }, /* IEEE80211_MODE_FH */
636 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_A */
637 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_G */
638 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_STURBO_A */
639 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NA */
640 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NG */
641};
642
643void
644ieee80211_wme_initparams(struct ieee80211com *ic)
645{
646 struct ieee80211_wme_state *wme = &ic->ic_wme;
647 const paramType *pPhyParam, *pBssPhyParam;
648 struct wmeParams *wmep;
649 enum ieee80211_phymode mode;
650 int i;
651
652 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
653 return;
654
655 /*
656 * Select mode; we can be called early in which case we
657 * always use auto mode. We know we'll be called when
658 * entering the RUN state with bsschan setup properly
659 * so state will eventually get set correctly
660 */
661 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC)
662 mode = ieee80211_chan2mode(ic->ic_bsschan);
663 else
664 mode = IEEE80211_MODE_AUTO;
665 for (i = 0; i < WME_NUM_AC; i++) {
666 switch (i) {
667 case WME_AC_BK:
668 pPhyParam = &phyParamForAC_BK[mode];
669 pBssPhyParam = &phyParamForAC_BK[mode];
670 break;
671 case WME_AC_VI:
672 pPhyParam = &phyParamForAC_VI[mode];
673 pBssPhyParam = &bssPhyParamForAC_VI[mode];
674 break;
675 case WME_AC_VO:
676 pPhyParam = &phyParamForAC_VO[mode];
677 pBssPhyParam = &bssPhyParamForAC_VO[mode];
678 break;
679 case WME_AC_BE:
680 default:
681 pPhyParam = &phyParamForAC_BE[mode];
682 pBssPhyParam = &bssPhyParamForAC_BE[mode];
683 break;
684 }
685
686 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
687 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
688 wmep->wmep_acm = pPhyParam->acm;
689 wmep->wmep_aifsn = pPhyParam->aifsn;
690 wmep->wmep_logcwmin = pPhyParam->logcwmin;
691 wmep->wmep_logcwmax = pPhyParam->logcwmax;
692 wmep->wmep_txopLimit = pPhyParam->txopLimit;
693 } else {
694 wmep->wmep_acm = pBssPhyParam->acm;
695 wmep->wmep_aifsn = pBssPhyParam->aifsn;
696 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
697 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
698 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
699
700 }
701 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
702 "%s: %s chan [acm %u aifsn %u log2(cwmin) %u "
703 "log2(cwmax) %u txpoLimit %u]\n", __func__
704 , ieee80211_wme_acnames[i]
705 , wmep->wmep_acm
706 , wmep->wmep_aifsn
707 , wmep->wmep_logcwmin
708 , wmep->wmep_logcwmax
709 , wmep->wmep_txopLimit
710 );
711
712 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
713 wmep->wmep_acm = pBssPhyParam->acm;
714 wmep->wmep_aifsn = pBssPhyParam->aifsn;
715 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
716 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
717 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
718 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
719 "%s: %s bss [acm %u aifsn %u log2(cwmin) %u "
720 "log2(cwmax) %u txpoLimit %u]\n", __func__
721 , ieee80211_wme_acnames[i]
722 , wmep->wmep_acm
723 , wmep->wmep_aifsn
724 , wmep->wmep_logcwmin
725 , wmep->wmep_logcwmax
726 , wmep->wmep_txopLimit
727 );
728 }
729 /* NB: check ic_bss to avoid NULL deref on initial attach */
730 if (ic->ic_bss != NULL) {
731 /*
732 * Calculate agressive mode switching threshold based
733 * on beacon interval. This doesn't need locking since
734 * we're only called before entering the RUN state at
735 * which point we start sending beacon frames.
736 */
737 wme->wme_hipri_switch_thresh =
738 (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100;
739 ieee80211_wme_updateparams(ic);
740 }
741}
742
743/*
744 * Update WME parameters for ourself and the BSS.
745 */
746void
747ieee80211_wme_updateparams_locked(struct ieee80211com *ic)
748{
749 static const paramType phyParam[IEEE80211_MODE_MAX] = {
750 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_AUTO */
751 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11A */
752 { 2, 5, 10, 64, 0 }, /* IEEE80211_MODE_11B */
753 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11G */
754 { 2, 5, 10, 64, 0 }, /* IEEE80211_MODE_FH */
755 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_TURBO_A */
756 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_TURBO_G */
757 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_STURBO_A */
758 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11NA */ /*XXXcheck*/
759 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11NG */ /*XXXcheck*/
760 };
761 struct ieee80211_wme_state *wme = &ic->ic_wme;
762 const struct wmeParams *wmep;
763 struct wmeParams *chanp, *bssp;
764 enum ieee80211_phymode mode;
765 int i;
766
767 /* set up the channel access parameters for the physical device */
768 for (i = 0; i < WME_NUM_AC; i++) {
769 chanp = &wme->wme_chanParams.cap_wmeParams[i];
770 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
771 chanp->wmep_aifsn = wmep->wmep_aifsn;
772 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
773 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
774 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
775
776 chanp = &wme->wme_bssChanParams.cap_wmeParams[i];
777 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
778 chanp->wmep_aifsn = wmep->wmep_aifsn;
779 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
780 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
781 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
782 }
783
784 /*
785 * Select mode; we can be called early in which case we
786 * always use auto mode. We know we'll be called when
787 * entering the RUN state with bsschan setup properly
788 * so state will eventually get set correctly
789 */
790 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC)
791 mode = ieee80211_chan2mode(ic->ic_bsschan);
792 else
793 mode = IEEE80211_MODE_AUTO;
794
795 /*
796 * This implements agressive mode as found in certain
797 * vendors' AP's. When there is significant high
798 * priority (VI/VO) traffic in the BSS throttle back BE
799 * traffic by using conservative parameters. Otherwise
800 * BE uses agressive params to optimize performance of
801 * legacy/non-QoS traffic.
802 */
803 if ((ic->ic_opmode == IEEE80211_M_HOSTAP &&
804 (wme->wme_flags & WME_F_AGGRMODE) != 0) ||
805 (ic->ic_opmode == IEEE80211_M_STA &&
806 (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) ||
807 (ic->ic_flags & IEEE80211_F_WME) == 0) {
808 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
809 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
810
811 chanp->wmep_aifsn = bssp->wmep_aifsn = phyParam[mode].aifsn;
812 chanp->wmep_logcwmin = bssp->wmep_logcwmin =
813 phyParam[mode].logcwmin;
814 chanp->wmep_logcwmax = bssp->wmep_logcwmax =
815 phyParam[mode].logcwmax;
816 chanp->wmep_txopLimit = bssp->wmep_txopLimit =
817 (ic->ic_flags & IEEE80211_F_BURST) ?
818 phyParam[mode].txopLimit : 0;
819 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
820 "%s: %s [acm %u aifsn %u log2(cwmin) %u "
821 "log2(cwmax) %u txpoLimit %u]\n", __func__
822 , ieee80211_wme_acnames[WME_AC_BE]
823 , chanp->wmep_acm
824 , chanp->wmep_aifsn
825 , chanp->wmep_logcwmin
826 , chanp->wmep_logcwmax
827 , chanp->wmep_txopLimit
828 );
829 }
830
831 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
832 ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) != 0) {
833 static const uint8_t logCwMin[IEEE80211_MODE_MAX] = {
834 3, /* IEEE80211_MODE_AUTO */
835 3, /* IEEE80211_MODE_11A */
836 4, /* IEEE80211_MODE_11B */
837 3, /* IEEE80211_MODE_11G */
838 4, /* IEEE80211_MODE_FH */
839 3, /* IEEE80211_MODE_TURBO_A */
840 3, /* IEEE80211_MODE_TURBO_G */
841 3, /* IEEE80211_MODE_STURBO_A */
842 3, /* IEEE80211_MODE_11NA */
843 3, /* IEEE80211_MODE_11NG */
844 };
845 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
846 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
847
848 chanp->wmep_logcwmin = bssp->wmep_logcwmin = logCwMin[mode];
849 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
850 "%s: %s log2(cwmin) %u\n", __func__
851 , ieee80211_wme_acnames[WME_AC_BE]
852 , chanp->wmep_logcwmin
853 );
854 }
855 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX ibss? */
856 /*
857 * Arrange for a beacon update and bump the parameter
858 * set number so associated stations load the new values.
859 */
860 wme->wme_bssChanParams.cap_info =
861 (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT;
127
128 /* initialize management frame handlers */
129 ic->ic_recv_mgmt = ieee80211_recv_mgmt;
130 ic->ic_send_mgmt = ieee80211_send_mgmt;
131 ic->ic_raw_xmit = ieee80211_raw_xmit;
132}
133
134void
135ieee80211_proto_detach(struct ieee80211com *ic)
136{
137
138 /*
139 * This should not be needed as we detach when reseting
140 * the state but be conservative here since the
141 * authenticator may do things like spawn kernel threads.
142 */
143 if (ic->ic_auth->ia_detach)
144 ic->ic_auth->ia_detach(ic);
145
146 ieee80211_drain_ifq(&ic->ic_mgtq);
147 mtx_destroy(&ic->ic_mgtq.ifq_mtx);
148
149 /*
150 * Detach any ACL'ator.
151 */
152 if (ic->ic_acl != NULL)
153 ic->ic_acl->iac_detach(ic);
154}
155
156/*
157 * Simple-minded authenticator module support.
158 */
159
160#define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WPA+1)
161/* XXX well-known names */
162static const char *auth_modnames[IEEE80211_AUTH_MAX] = {
163 "wlan_internal", /* IEEE80211_AUTH_NONE */
164 "wlan_internal", /* IEEE80211_AUTH_OPEN */
165 "wlan_internal", /* IEEE80211_AUTH_SHARED */
166 "wlan_xauth", /* IEEE80211_AUTH_8021X */
167 "wlan_internal", /* IEEE80211_AUTH_AUTO */
168 "wlan_xauth", /* IEEE80211_AUTH_WPA */
169};
170static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX];
171
172static const struct ieee80211_authenticator auth_internal = {
173 .ia_name = "wlan_internal",
174 .ia_attach = NULL,
175 .ia_detach = NULL,
176 .ia_node_join = NULL,
177 .ia_node_leave = NULL,
178};
179
180/*
181 * Setup internal authenticators once; they are never unregistered.
182 */
183static void
184ieee80211_auth_setup(void)
185{
186 ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal);
187 ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal);
188 ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal);
189}
190SYSINIT(wlan_auth, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_auth_setup, NULL);
191
192const struct ieee80211_authenticator *
193ieee80211_authenticator_get(int auth)
194{
195 if (auth >= IEEE80211_AUTH_MAX)
196 return NULL;
197 if (authenticators[auth] == NULL)
198 ieee80211_load_module(auth_modnames[auth]);
199 return authenticators[auth];
200}
201
202void
203ieee80211_authenticator_register(int type,
204 const struct ieee80211_authenticator *auth)
205{
206 if (type >= IEEE80211_AUTH_MAX)
207 return;
208 authenticators[type] = auth;
209}
210
211void
212ieee80211_authenticator_unregister(int type)
213{
214
215 if (type >= IEEE80211_AUTH_MAX)
216 return;
217 authenticators[type] = NULL;
218}
219
220/*
221 * Very simple-minded ACL module support.
222 */
223/* XXX just one for now */
224static const struct ieee80211_aclator *acl = NULL;
225
226void
227ieee80211_aclator_register(const struct ieee80211_aclator *iac)
228{
229 printf("wlan: %s acl policy registered\n", iac->iac_name);
230 acl = iac;
231}
232
233void
234ieee80211_aclator_unregister(const struct ieee80211_aclator *iac)
235{
236 if (acl == iac)
237 acl = NULL;
238 printf("wlan: %s acl policy unregistered\n", iac->iac_name);
239}
240
241const struct ieee80211_aclator *
242ieee80211_aclator_get(const char *name)
243{
244 if (acl == NULL)
245 ieee80211_load_module("wlan_acl");
246 return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL;
247}
248
249void
250ieee80211_print_essid(const uint8_t *essid, int len)
251{
252 const uint8_t *p;
253 int i;
254
255 if (len > IEEE80211_NWID_LEN)
256 len = IEEE80211_NWID_LEN;
257 /* determine printable or not */
258 for (i = 0, p = essid; i < len; i++, p++) {
259 if (*p < ' ' || *p > 0x7e)
260 break;
261 }
262 if (i == len) {
263 printf("\"");
264 for (i = 0, p = essid; i < len; i++, p++)
265 printf("%c", *p);
266 printf("\"");
267 } else {
268 printf("0x");
269 for (i = 0, p = essid; i < len; i++, p++)
270 printf("%02x", *p);
271 }
272}
273
274void
275ieee80211_dump_pkt(struct ieee80211com *ic,
276 const uint8_t *buf, int len, int rate, int rssi)
277{
278 const struct ieee80211_frame *wh;
279 int i;
280
281 wh = (const struct ieee80211_frame *)buf;
282 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
283 case IEEE80211_FC1_DIR_NODS:
284 printf("NODS %s", ether_sprintf(wh->i_addr2));
285 printf("->%s", ether_sprintf(wh->i_addr1));
286 printf("(%s)", ether_sprintf(wh->i_addr3));
287 break;
288 case IEEE80211_FC1_DIR_TODS:
289 printf("TODS %s", ether_sprintf(wh->i_addr2));
290 printf("->%s", ether_sprintf(wh->i_addr3));
291 printf("(%s)", ether_sprintf(wh->i_addr1));
292 break;
293 case IEEE80211_FC1_DIR_FROMDS:
294 printf("FRDS %s", ether_sprintf(wh->i_addr3));
295 printf("->%s", ether_sprintf(wh->i_addr1));
296 printf("(%s)", ether_sprintf(wh->i_addr2));
297 break;
298 case IEEE80211_FC1_DIR_DSTODS:
299 printf("DSDS %s", ether_sprintf((const uint8_t *)&wh[1]));
300 printf("->%s", ether_sprintf(wh->i_addr3));
301 printf("(%s", ether_sprintf(wh->i_addr2));
302 printf("->%s)", ether_sprintf(wh->i_addr1));
303 break;
304 }
305 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
306 case IEEE80211_FC0_TYPE_DATA:
307 printf(" data");
308 break;
309 case IEEE80211_FC0_TYPE_MGT:
310 printf(" %s", ieee80211_mgt_subtype_name[
311 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
312 >> IEEE80211_FC0_SUBTYPE_SHIFT]);
313 break;
314 default:
315 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
316 break;
317 }
318 if (IEEE80211_QOS_HAS_SEQ(wh)) {
319 const struct ieee80211_qosframe *qwh =
320 (const struct ieee80211_qosframe *)buf;
321 printf(" QoS [TID %u%s]", qwh->i_qos[0] & IEEE80211_QOS_TID,
322 qwh->i_qos[0] & IEEE80211_QOS_ACKPOLICY ? " ACM" : "");
323 }
324 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
325 int off;
326
327 off = ieee80211_anyhdrspace(ic, wh);
328 printf(" WEP [IV %.02x %.02x %.02x",
329 buf[off+0], buf[off+1], buf[off+2]);
330 if (buf[off+IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)
331 printf(" %.02x %.02x %.02x",
332 buf[off+4], buf[off+5], buf[off+6]);
333 printf(" KID %u]", buf[off+IEEE80211_WEP_IVLEN] >> 6);
334 }
335 if (rate >= 0)
336 printf(" %dM", rate / 2);
337 if (rssi >= 0)
338 printf(" +%d", rssi);
339 printf("\n");
340 if (len > 0) {
341 for (i = 0; i < len; i++) {
342 if ((i & 1) == 0)
343 printf(" ");
344 printf("%02x", buf[i]);
345 }
346 printf("\n");
347 }
348}
349
350static __inline int
351findrix(const struct ieee80211_rateset *rs, int r)
352{
353 int i;
354
355 for (i = 0; i < rs->rs_nrates; i++)
356 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == r)
357 return i;
358 return -1;
359}
360
361int
362ieee80211_fix_rate(struct ieee80211_node *ni,
363 struct ieee80211_rateset *nrs, int flags)
364{
365#define RV(v) ((v) & IEEE80211_RATE_VAL)
366 struct ieee80211com *ic = ni->ni_ic;
367 int i, j, rix, error;
368 int okrate, badrate, fixedrate;
369 const struct ieee80211_rateset *srs;
370 uint8_t r;
371
372 error = 0;
373 okrate = badrate = 0;
374 fixedrate = IEEE80211_FIXED_RATE_NONE;
375 srs = ieee80211_get_suprates(ic, ni->ni_chan);
376 for (i = 0; i < nrs->rs_nrates; ) {
377 if (flags & IEEE80211_F_DOSORT) {
378 /*
379 * Sort rates.
380 */
381 for (j = i + 1; j < nrs->rs_nrates; j++) {
382 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) {
383 r = nrs->rs_rates[i];
384 nrs->rs_rates[i] = nrs->rs_rates[j];
385 nrs->rs_rates[j] = r;
386 }
387 }
388 }
389 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
390 badrate = r;
391 /*
392 * Check for fixed rate.
393 */
394 if (r == ic->ic_fixed_rate)
395 fixedrate = r;
396 /*
397 * Check against supported rates.
398 */
399 rix = findrix(srs, r);
400 if (flags & IEEE80211_F_DONEGO) {
401 if (rix < 0) {
402 /*
403 * A rate in the node's rate set is not
404 * supported. If this is a basic rate and we
405 * are operating as a STA then this is an error.
406 * Otherwise we just discard/ignore the rate.
407 */
408 if ((flags & IEEE80211_F_JOIN) &&
409 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
410 error++;
411 } else if ((flags & IEEE80211_F_JOIN) == 0) {
412 /*
413 * Overwrite with the supported rate
414 * value so any basic rate bit is set.
415 */
416 nrs->rs_rates[i] = srs->rs_rates[rix];
417 }
418 }
419 if ((flags & IEEE80211_F_DODEL) && rix < 0) {
420 /*
421 * Delete unacceptable rates.
422 */
423 nrs->rs_nrates--;
424 for (j = i; j < nrs->rs_nrates; j++)
425 nrs->rs_rates[j] = nrs->rs_rates[j + 1];
426 nrs->rs_rates[j] = 0;
427 continue;
428 }
429 if (rix >= 0)
430 okrate = nrs->rs_rates[i];
431 i++;
432 }
433 if (okrate == 0 || error != 0 ||
434 ((flags & IEEE80211_F_DOFRATE) && fixedrate != ic->ic_fixed_rate))
435 return badrate | IEEE80211_RATE_BASIC;
436 else
437 return RV(okrate);
438#undef RV
439}
440
441/*
442 * Reset 11g-related state.
443 */
444void
445ieee80211_reset_erp(struct ieee80211com *ic)
446{
447 ic->ic_flags &= ~IEEE80211_F_USEPROT;
448 ic->ic_nonerpsta = 0;
449 ic->ic_longslotsta = 0;
450 /*
451 * Short slot time is enabled only when operating in 11g
452 * and not in an IBSS. We must also honor whether or not
453 * the driver is capable of doing it.
454 */
455 ieee80211_set_shortslottime(ic,
456 IEEE80211_IS_CHAN_A(ic->ic_curchan) ||
457 IEEE80211_IS_CHAN_HT(ic->ic_curchan) ||
458 (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) &&
459 ic->ic_opmode == IEEE80211_M_HOSTAP &&
460 (ic->ic_caps & IEEE80211_C_SHSLOT)));
461 /*
462 * Set short preamble and ERP barker-preamble flags.
463 */
464 if (IEEE80211_IS_CHAN_A(ic->ic_curchan) ||
465 (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) {
466 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
467 ic->ic_flags &= ~IEEE80211_F_USEBARKER;
468 } else {
469 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
470 ic->ic_flags |= IEEE80211_F_USEBARKER;
471 }
472}
473
474/*
475 * Set the short slot time state and notify the driver.
476 */
477void
478ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff)
479{
480 if (onoff)
481 ic->ic_flags |= IEEE80211_F_SHSLOT;
482 else
483 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
484 /* notify driver */
485 if (ic->ic_updateslot != NULL)
486 ic->ic_updateslot(ic->ic_ifp);
487}
488
489/*
490 * Check if the specified rate set supports ERP.
491 * NB: the rate set is assumed to be sorted.
492 */
493int
494ieee80211_iserp_rateset(struct ieee80211com *ic, struct ieee80211_rateset *rs)
495{
496#define N(a) (sizeof(a) / sizeof(a[0]))
497 static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 };
498 int i, j;
499
500 if (rs->rs_nrates < N(rates))
501 return 0;
502 for (i = 0; i < N(rates); i++) {
503 for (j = 0; j < rs->rs_nrates; j++) {
504 int r = rs->rs_rates[j] & IEEE80211_RATE_VAL;
505 if (rates[i] == r)
506 goto next;
507 if (r > rates[i])
508 return 0;
509 }
510 return 0;
511 next:
512 ;
513 }
514 return 1;
515#undef N
516}
517
518/*
519 * Mark the basic rates for the 11g rate table based on the
520 * operating mode. For real 11g we mark all the 11b rates
521 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only
522 * 11b rates. There's also a pseudo 11a-mode used to mark only
523 * the basic OFDM rates.
524 */
525void
526ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode)
527{
528 static const struct ieee80211_rateset basic[IEEE80211_MODE_MAX] = {
529 { .rs_nrates = 0 }, /* IEEE80211_MODE_AUTO */
530 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */
531 { 2, { 2, 4 } }, /* IEEE80211_MODE_11B */
532 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G (mixed b/g) */
533 { .rs_nrates = 0 }, /* IEEE80211_MODE_FH */
534 /* IEEE80211_MODE_PUREG (not yet) */
535 { 7, { 2, 4, 11, 22, 12, 24, 48 } },
536 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11NA */
537 /* IEEE80211_MODE_11NG (mixed b/g) */
538 { 7, { 2, 4, 11, 22, 12, 24, 48 } },
539 };
540 int i, j;
541
542 for (i = 0; i < rs->rs_nrates; i++) {
543 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
544 for (j = 0; j < basic[mode].rs_nrates; j++)
545 if (basic[mode].rs_rates[j] == rs->rs_rates[i]) {
546 rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
547 break;
548 }
549 }
550}
551
552/*
553 * WME protocol support. The following parameters come from the spec.
554 */
555typedef struct phyParamType {
556 uint8_t aifsn;
557 uint8_t logcwmin;
558 uint8_t logcwmax;
559 uint16_t txopLimit;
560 uint8_t acm;
561} paramType;
562
563static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = {
564 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_AUTO */
565 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11A */
566 { 3, 5, 7, 0, 0 }, /* IEEE80211_MODE_11B */
567 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11G */
568 { 3, 5, 7, 0, 0 }, /* IEEE80211_MODE_FH */
569 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO_A */
570 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO_G */
571 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_STURBO_A */
572 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11NA */ /* XXXcheck*/
573 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11NG */ /* XXXcheck*/
574};
575static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = {
576 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_AUTO */
577 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */
578 { 7, 5, 10, 0, 0 }, /* IEEE80211_MODE_11B */
579 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11G */
580 { 7, 5, 10, 0, 0 }, /* IEEE80211_MODE_FH */
581 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_A */
582 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_G */
583 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_STURBO_A */
584 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NA */
585 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NG */
586};
587static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = {
588 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_AUTO */
589 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */
590 { 1, 4, 5, 188, 0 }, /* IEEE80211_MODE_11B */
591 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11G */
592 { 1, 4, 5, 188, 0 }, /* IEEE80211_MODE_FH */
593 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_A */
594 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_G */
595 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_STURBO_A */
596 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NA */
597 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NG */
598};
599static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = {
600 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_AUTO */
601 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */
602 { 1, 3, 4, 102, 0 }, /* IEEE80211_MODE_11B */
603 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11G */
604 { 1, 3, 4, 102, 0 }, /* IEEE80211_MODE_FH */
605 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_A */
606 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_G */
607 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_STURBO_A */
608 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NA */
609 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NG */
610};
611
612static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = {
613 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_AUTO */
614 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */
615 { 3, 5, 10, 0, 0 }, /* IEEE80211_MODE_11B */
616 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11G */
617 { 3, 5, 10, 0, 0 }, /* IEEE80211_MODE_FH */
618 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_A */
619 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_G */
620 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_STURBO_A */
621 { 1, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NA */
622 { 1, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NG */
623};
624static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = {
625 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_AUTO */
626 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */
627 { 2, 4, 5, 188, 0 }, /* IEEE80211_MODE_11B */
628 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11G */
629 { 2, 4, 5, 188, 0 }, /* IEEE80211_MODE_FH */
630 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_A */
631 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_G */
632 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_STURBO_A */
633 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NA */
634 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NG */
635};
636static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = {
637 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_AUTO */
638 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */
639 { 2, 3, 4, 102, 0 }, /* IEEE80211_MODE_11B */
640 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11G */
641 { 2, 3, 4, 102, 0 }, /* IEEE80211_MODE_FH */
642 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_A */
643 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_G */
644 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_STURBO_A */
645 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NA */
646 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NG */
647};
648
649void
650ieee80211_wme_initparams(struct ieee80211com *ic)
651{
652 struct ieee80211_wme_state *wme = &ic->ic_wme;
653 const paramType *pPhyParam, *pBssPhyParam;
654 struct wmeParams *wmep;
655 enum ieee80211_phymode mode;
656 int i;
657
658 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
659 return;
660
661 /*
662 * Select mode; we can be called early in which case we
663 * always use auto mode. We know we'll be called when
664 * entering the RUN state with bsschan setup properly
665 * so state will eventually get set correctly
666 */
667 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC)
668 mode = ieee80211_chan2mode(ic->ic_bsschan);
669 else
670 mode = IEEE80211_MODE_AUTO;
671 for (i = 0; i < WME_NUM_AC; i++) {
672 switch (i) {
673 case WME_AC_BK:
674 pPhyParam = &phyParamForAC_BK[mode];
675 pBssPhyParam = &phyParamForAC_BK[mode];
676 break;
677 case WME_AC_VI:
678 pPhyParam = &phyParamForAC_VI[mode];
679 pBssPhyParam = &bssPhyParamForAC_VI[mode];
680 break;
681 case WME_AC_VO:
682 pPhyParam = &phyParamForAC_VO[mode];
683 pBssPhyParam = &bssPhyParamForAC_VO[mode];
684 break;
685 case WME_AC_BE:
686 default:
687 pPhyParam = &phyParamForAC_BE[mode];
688 pBssPhyParam = &bssPhyParamForAC_BE[mode];
689 break;
690 }
691
692 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
693 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
694 wmep->wmep_acm = pPhyParam->acm;
695 wmep->wmep_aifsn = pPhyParam->aifsn;
696 wmep->wmep_logcwmin = pPhyParam->logcwmin;
697 wmep->wmep_logcwmax = pPhyParam->logcwmax;
698 wmep->wmep_txopLimit = pPhyParam->txopLimit;
699 } else {
700 wmep->wmep_acm = pBssPhyParam->acm;
701 wmep->wmep_aifsn = pBssPhyParam->aifsn;
702 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
703 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
704 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
705
706 }
707 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
708 "%s: %s chan [acm %u aifsn %u log2(cwmin) %u "
709 "log2(cwmax) %u txpoLimit %u]\n", __func__
710 , ieee80211_wme_acnames[i]
711 , wmep->wmep_acm
712 , wmep->wmep_aifsn
713 , wmep->wmep_logcwmin
714 , wmep->wmep_logcwmax
715 , wmep->wmep_txopLimit
716 );
717
718 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
719 wmep->wmep_acm = pBssPhyParam->acm;
720 wmep->wmep_aifsn = pBssPhyParam->aifsn;
721 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
722 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
723 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
724 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
725 "%s: %s bss [acm %u aifsn %u log2(cwmin) %u "
726 "log2(cwmax) %u txpoLimit %u]\n", __func__
727 , ieee80211_wme_acnames[i]
728 , wmep->wmep_acm
729 , wmep->wmep_aifsn
730 , wmep->wmep_logcwmin
731 , wmep->wmep_logcwmax
732 , wmep->wmep_txopLimit
733 );
734 }
735 /* NB: check ic_bss to avoid NULL deref on initial attach */
736 if (ic->ic_bss != NULL) {
737 /*
738 * Calculate agressive mode switching threshold based
739 * on beacon interval. This doesn't need locking since
740 * we're only called before entering the RUN state at
741 * which point we start sending beacon frames.
742 */
743 wme->wme_hipri_switch_thresh =
744 (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100;
745 ieee80211_wme_updateparams(ic);
746 }
747}
748
749/*
750 * Update WME parameters for ourself and the BSS.
751 */
752void
753ieee80211_wme_updateparams_locked(struct ieee80211com *ic)
754{
755 static const paramType phyParam[IEEE80211_MODE_MAX] = {
756 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_AUTO */
757 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11A */
758 { 2, 5, 10, 64, 0 }, /* IEEE80211_MODE_11B */
759 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11G */
760 { 2, 5, 10, 64, 0 }, /* IEEE80211_MODE_FH */
761 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_TURBO_A */
762 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_TURBO_G */
763 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_STURBO_A */
764 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11NA */ /*XXXcheck*/
765 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11NG */ /*XXXcheck*/
766 };
767 struct ieee80211_wme_state *wme = &ic->ic_wme;
768 const struct wmeParams *wmep;
769 struct wmeParams *chanp, *bssp;
770 enum ieee80211_phymode mode;
771 int i;
772
773 /* set up the channel access parameters for the physical device */
774 for (i = 0; i < WME_NUM_AC; i++) {
775 chanp = &wme->wme_chanParams.cap_wmeParams[i];
776 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
777 chanp->wmep_aifsn = wmep->wmep_aifsn;
778 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
779 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
780 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
781
782 chanp = &wme->wme_bssChanParams.cap_wmeParams[i];
783 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
784 chanp->wmep_aifsn = wmep->wmep_aifsn;
785 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
786 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
787 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
788 }
789
790 /*
791 * Select mode; we can be called early in which case we
792 * always use auto mode. We know we'll be called when
793 * entering the RUN state with bsschan setup properly
794 * so state will eventually get set correctly
795 */
796 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC)
797 mode = ieee80211_chan2mode(ic->ic_bsschan);
798 else
799 mode = IEEE80211_MODE_AUTO;
800
801 /*
802 * This implements agressive mode as found in certain
803 * vendors' AP's. When there is significant high
804 * priority (VI/VO) traffic in the BSS throttle back BE
805 * traffic by using conservative parameters. Otherwise
806 * BE uses agressive params to optimize performance of
807 * legacy/non-QoS traffic.
808 */
809 if ((ic->ic_opmode == IEEE80211_M_HOSTAP &&
810 (wme->wme_flags & WME_F_AGGRMODE) != 0) ||
811 (ic->ic_opmode == IEEE80211_M_STA &&
812 (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) ||
813 (ic->ic_flags & IEEE80211_F_WME) == 0) {
814 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
815 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
816
817 chanp->wmep_aifsn = bssp->wmep_aifsn = phyParam[mode].aifsn;
818 chanp->wmep_logcwmin = bssp->wmep_logcwmin =
819 phyParam[mode].logcwmin;
820 chanp->wmep_logcwmax = bssp->wmep_logcwmax =
821 phyParam[mode].logcwmax;
822 chanp->wmep_txopLimit = bssp->wmep_txopLimit =
823 (ic->ic_flags & IEEE80211_F_BURST) ?
824 phyParam[mode].txopLimit : 0;
825 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
826 "%s: %s [acm %u aifsn %u log2(cwmin) %u "
827 "log2(cwmax) %u txpoLimit %u]\n", __func__
828 , ieee80211_wme_acnames[WME_AC_BE]
829 , chanp->wmep_acm
830 , chanp->wmep_aifsn
831 , chanp->wmep_logcwmin
832 , chanp->wmep_logcwmax
833 , chanp->wmep_txopLimit
834 );
835 }
836
837 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
838 ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) != 0) {
839 static const uint8_t logCwMin[IEEE80211_MODE_MAX] = {
840 3, /* IEEE80211_MODE_AUTO */
841 3, /* IEEE80211_MODE_11A */
842 4, /* IEEE80211_MODE_11B */
843 3, /* IEEE80211_MODE_11G */
844 4, /* IEEE80211_MODE_FH */
845 3, /* IEEE80211_MODE_TURBO_A */
846 3, /* IEEE80211_MODE_TURBO_G */
847 3, /* IEEE80211_MODE_STURBO_A */
848 3, /* IEEE80211_MODE_11NA */
849 3, /* IEEE80211_MODE_11NG */
850 };
851 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
852 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
853
854 chanp->wmep_logcwmin = bssp->wmep_logcwmin = logCwMin[mode];
855 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
856 "%s: %s log2(cwmin) %u\n", __func__
857 , ieee80211_wme_acnames[WME_AC_BE]
858 , chanp->wmep_logcwmin
859 );
860 }
861 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX ibss? */
862 /*
863 * Arrange for a beacon update and bump the parameter
864 * set number so associated stations load the new values.
865 */
866 wme->wme_bssChanParams.cap_info =
867 (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT;
862 ic->ic_flags |= IEEE80211_F_WMEUPDATE;
868 ieee80211_beacon_notify(ic, IEEE80211_BEACON_WME);
863 }
864
865 wme->wme_update(ic);
866
867 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
868 "%s: WME params updated, cap_info 0x%x\n", __func__,
869 ic->ic_opmode == IEEE80211_M_STA ?
870 wme->wme_wmeChanParams.cap_info :
871 wme->wme_bssChanParams.cap_info);
872}
873
874void
875ieee80211_wme_updateparams(struct ieee80211com *ic)
876{
877
878 if (ic->ic_caps & IEEE80211_C_WME) {
879 IEEE80211_BEACON_LOCK(ic);
880 ieee80211_wme_updateparams_locked(ic);
881 IEEE80211_BEACON_UNLOCK(ic);
882 }
883}
884
885/*
886 * Start a device. If this is the first vap running on the
887 * underlying device then we first bring it up.
888 */
889int
890ieee80211_init(struct ieee80211com *ic, int forcescan)
891{
892
893 IEEE80211_DPRINTF(ic,
894 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
895 "%s\n", "start running");
896
897 /*
898 * Kick the 802.11 state machine as appropriate.
899 */
900 if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) {
901 if (ic->ic_opmode == IEEE80211_M_STA) {
902 /*
903 * Try to be intelligent about clocking the state
904 * machine. If we're currently in RUN state then
905 * we should be able to apply any new state/parameters
906 * simply by re-associating. Otherwise we need to
907 * re-scan to select an appropriate ap.
908 */
909 if (ic->ic_state != IEEE80211_S_RUN || forcescan)
910 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
911 else
912 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
913 } else {
914 /*
915 * For monitor+wds modes there's nothing to do but
916 * start running. Otherwise, if this is the first
917 * vap to be brought up, start a scan which may be
918 * preempted if the station is locked to a particular
919 * channel.
920 */
921 if (ic->ic_opmode == IEEE80211_M_MONITOR ||
922 ic->ic_opmode == IEEE80211_M_WDS) {
923 ic->ic_state = IEEE80211_S_INIT; /* XXX*/
924 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
925 } else
926 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
927 }
928 }
929 return 0;
930}
931
932/*
933 * Switch between turbo and non-turbo operating modes.
934 * Use the specified channel flags to locate the new
935 * channel, update 802.11 state, and then call back into
936 * the driver to effect the change.
937 */
938void
939ieee80211_dturbo_switch(struct ieee80211com *ic, int newflags)
940{
941 struct ieee80211_channel *chan;
942
943 chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags);
944 if (chan == NULL) { /* XXX should not happen */
945 IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
946 "%s: no channel with freq %u flags 0x%x\n",
947 __func__, ic->ic_bsschan->ic_freq, newflags);
948 return;
949 }
950
951 IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
952 "%s: %s -> %s (freq %u flags 0x%x)\n", __func__,
953 ieee80211_phymode_name[ieee80211_chan2mode(ic->ic_bsschan)],
954 ieee80211_phymode_name[ieee80211_chan2mode(chan)],
955 chan->ic_freq, chan->ic_flags);
956
957 ic->ic_bsschan = chan;
958 ic->ic_prevchan = ic->ic_curchan;
959 ic->ic_curchan = chan;
960 ic->ic_set_channel(ic);
961 /* NB: do not need to reset ERP state 'cuz we're in sta mode */
962}
963
964void
965ieee80211_beacon_miss(struct ieee80211com *ic)
966{
967
968 if (ic->ic_flags & IEEE80211_F_SCAN) {
969 /* XXX check ic_curchan != ic_bsschan? */
970 return;
971 }
972 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
973 "%s\n", "beacon miss");
974
975 /*
976 * Our handling is only meaningful for stations that are
977 * associated; any other conditions else will be handled
978 * through different means (e.g. the tx timeout on mgt frames).
979 */
980 if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN)
981 return;
982
983 if (++ic->ic_bmiss_count < ic->ic_bmiss_max) {
984 /*
985 * Send a directed probe req before falling back to a scan;
986 * if we receive a response ic_bmiss_count will be reset.
987 * Some cards mistakenly report beacon miss so this avoids
988 * the expensive scan if the ap is still there.
989 */
990 ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr,
991 ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid,
992 ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen,
993 ic->ic_opt_ie, ic->ic_opt_ie_len);
994 return;
995 }
996 ic->ic_bmiss_count = 0;
997 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
998 /*
999 * If we receive a beacon miss interrupt when using
1000 * dynamic turbo, attempt to switch modes before
1001 * reassociating.
1002 */
1003 if (IEEE80211_ATH_CAP(ic, ic->ic_bss, IEEE80211_NODE_TURBOP))
1004 ieee80211_dturbo_switch(ic,
1005 ic->ic_bsschan->ic_flags ^ IEEE80211_CHAN_TURBO);
1006 /*
1007 * Try to reassociate before scanning for a new ap.
1008 */
1009 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
1010 } else {
1011 /*
1012 * Somebody else is controlling state changes (e.g.
1013 * a user-mode app) don't do anything that would
1014 * confuse them; just drop into scan mode so they'll
1015 * notified of the state change and given control.
1016 */
1017 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
1018 }
1019}
1020
1021/*
1022 * Software beacon miss handling. Check if any beacons
1023 * were received in the last period. If not post a
1024 * beacon miss; otherwise reset the counter.
1025 */
1026static void
1027ieee80211_swbmiss(void *arg)
1028{
1029 struct ieee80211com *ic = arg;
1030
1031 if (ic->ic_swbmiss_count == 0) {
1032 ieee80211_beacon_miss(ic);
1033 if (ic->ic_bmiss_count == 0) /* don't re-arm timer */
1034 return;
1035 } else
1036 ic->ic_swbmiss_count = 0;
1037 callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period,
1038 ieee80211_swbmiss, ic);
1039}
1040
1041static void
1042sta_disassoc(void *arg, struct ieee80211_node *ni)
1043{
1044 struct ieee80211com *ic = arg;
1045
1046 if (ni->ni_associd != 0) {
1047 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
1048 IEEE80211_REASON_ASSOC_LEAVE);
1049 ieee80211_node_leave(ic, ni);
1050 }
1051}
1052
1053static void
1054sta_deauth(void *arg, struct ieee80211_node *ni)
1055{
1056 struct ieee80211com *ic = arg;
1057
1058 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
1059 IEEE80211_REASON_ASSOC_LEAVE);
1060}
1061
1062/*
1063 * Handle deauth with reason. We retry only for
1064 * the cases where we might succeed. Otherwise
1065 * we downgrade the ap and scan.
1066 */
1067static void
1068sta_authretry(struct ieee80211com *ic, struct ieee80211_node *ni, int reason)
1069{
1070 switch (reason) {
1071 case IEEE80211_STATUS_SUCCESS:
1072 case IEEE80211_STATUS_TIMEOUT:
1073 case IEEE80211_REASON_ASSOC_EXPIRE:
1074 case IEEE80211_REASON_NOT_AUTHED:
1075 case IEEE80211_REASON_NOT_ASSOCED:
1076 case IEEE80211_REASON_ASSOC_LEAVE:
1077 case IEEE80211_REASON_ASSOC_NOT_AUTHED:
1078 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 1);
1079 break;
1080 default:
1081 ieee80211_scan_assoc_fail(ic, ic->ic_bss->ni_macaddr, reason);
1082 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
1083 ieee80211_check_scan(ic,
1084 IEEE80211_SCAN_ACTIVE,
1085 IEEE80211_SCAN_FOREVER,
1086 ic->ic_des_nssid, ic->ic_des_ssid);
1087 break;
1088 }
1089}
1090
1091static int
1092ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1093{
1094 struct ifnet *ifp = ic->ic_ifp;
1095 struct ieee80211_node *ni;
1096 enum ieee80211_state ostate;
1097
1098 ostate = ic->ic_state;
1099 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__,
1100 ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
1101 ic->ic_state = nstate; /* state transition */
1102 callout_stop(&ic->ic_mgtsend); /* XXX callout_drain */
1103 if (ostate != IEEE80211_S_SCAN)
1104 ieee80211_cancel_scan(ic); /* background scan */
1105 ni = ic->ic_bss; /* NB: no reference held */
1106 if (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)
1107 callout_stop(&ic->ic_swbmiss);
1108 switch (nstate) {
1109 case IEEE80211_S_INIT:
1110 switch (ostate) {
1111 case IEEE80211_S_INIT:
1112 break;
1113 case IEEE80211_S_RUN:
1114 switch (ic->ic_opmode) {
1115 case IEEE80211_M_STA:
1116 IEEE80211_SEND_MGMT(ic, ni,
1117 IEEE80211_FC0_SUBTYPE_DISASSOC,
1118 IEEE80211_REASON_ASSOC_LEAVE);
1119 ieee80211_sta_leave(ic, ni);
1120 break;
1121 case IEEE80211_M_HOSTAP:
1122 ieee80211_iterate_nodes(&ic->ic_sta,
1123 sta_disassoc, ic);
1124 break;
1125 default:
1126 break;
1127 }
1128 break;
1129 case IEEE80211_S_ASSOC:
1130 switch (ic->ic_opmode) {
1131 case IEEE80211_M_STA:
1132 IEEE80211_SEND_MGMT(ic, ni,
1133 IEEE80211_FC0_SUBTYPE_DEAUTH,
1134 IEEE80211_REASON_AUTH_LEAVE);
1135 break;
1136 case IEEE80211_M_HOSTAP:
1137 ieee80211_iterate_nodes(&ic->ic_sta,
1138 sta_deauth, ic);
1139 break;
1140 default:
1141 break;
1142 }
1143 break;
1144 case IEEE80211_S_SCAN:
1145 ieee80211_cancel_scan(ic);
1146 break;
1147 case IEEE80211_S_AUTH:
1148 break;
1149 default:
1150 break;
1151 }
1152 if (ostate != IEEE80211_S_INIT) {
1153 /* NB: optimize INIT -> INIT case */
1154 ieee80211_drain_ifq(&ic->ic_mgtq);
1155 ieee80211_reset_bss(ic);
1156 ieee80211_scan_flush(ic);
1157 }
1158 if (ic->ic_auth->ia_detach != NULL)
1159 ic->ic_auth->ia_detach(ic);
1160 break;
1161 case IEEE80211_S_SCAN:
1162 switch (ostate) {
1163 case IEEE80211_S_INIT:
1164 createibss:
1165 if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
1166 ic->ic_opmode == IEEE80211_M_IBSS ||
1167 ic->ic_opmode == IEEE80211_M_AHDEMO) &&
1168 ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1169 /*
1170 * Already have a channel; bypass the
1171 * scan and startup immediately. Because
1172 * of this explicitly sync the scanner state.
1173 */
1174 ieee80211_scan_update(ic);
1175 ieee80211_create_ibss(ic, ic->ic_des_chan);
1176 } else {
1177 ieee80211_check_scan(ic,
1178 IEEE80211_SCAN_ACTIVE |
1179 IEEE80211_SCAN_FLUSH,
1180 IEEE80211_SCAN_FOREVER,
1181 ic->ic_des_nssid, ic->ic_des_ssid);
1182 }
1183 break;
1184 case IEEE80211_S_SCAN:
1185 case IEEE80211_S_AUTH:
1186 case IEEE80211_S_ASSOC:
1187 /*
1188 * These can happen either because of a timeout
1189 * on an assoc/auth response or because of a
1190 * change in state that requires a reset. For
1191 * the former we're called with a non-zero arg
1192 * that is the cause for the failure; pass this
1193 * to the scan code so it can update state.
1194 * Otherwise trigger a new scan unless we're in
1195 * manual roaming mode in which case an application
1196 * must issue an explicit scan request.
1197 */
1198 if (arg != 0)
1199 ieee80211_scan_assoc_fail(ic,
1200 ic->ic_bss->ni_macaddr, arg);
1201 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
1202 ieee80211_check_scan(ic,
1203 IEEE80211_SCAN_ACTIVE,
1204 IEEE80211_SCAN_FOREVER,
1205 ic->ic_des_nssid, ic->ic_des_ssid);
1206 break;
1207 case IEEE80211_S_RUN: /* beacon miss */
1208 if (ic->ic_opmode == IEEE80211_M_STA) {
1209 ieee80211_sta_leave(ic, ni);
1210 ic->ic_flags &= ~IEEE80211_F_SIBSS; /* XXX */
1211 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
1212 ieee80211_check_scan(ic,
1213 IEEE80211_SCAN_ACTIVE,
1214 IEEE80211_SCAN_FOREVER,
1215 ic->ic_des_nssid,
1216 ic->ic_des_ssid);
1217 } else {
1218 ieee80211_iterate_nodes(&ic->ic_sta,
1219 sta_disassoc, ic);
1220 goto createibss;
1221 }
1222 break;
1223 default:
1224 break;
1225 }
1226 break;
1227 case IEEE80211_S_AUTH:
1228 KASSERT(ic->ic_opmode == IEEE80211_M_STA,
1229 ("switch to %s state when operating in mode %u",
1230 ieee80211_state_name[nstate], ic->ic_opmode));
1231 switch (ostate) {
1232 case IEEE80211_S_INIT:
1233 case IEEE80211_S_SCAN:
1234 IEEE80211_SEND_MGMT(ic, ni,
1235 IEEE80211_FC0_SUBTYPE_AUTH, 1);
1236 break;
1237 case IEEE80211_S_AUTH:
1238 case IEEE80211_S_ASSOC:
1239 switch (arg & 0xff) {
1240 case IEEE80211_FC0_SUBTYPE_AUTH:
1241 /* ??? */
1242 IEEE80211_SEND_MGMT(ic, ni,
1243 IEEE80211_FC0_SUBTYPE_AUTH, 2);
1244 break;
1245 case IEEE80211_FC0_SUBTYPE_DEAUTH:
1246 sta_authretry(ic, ni, arg>>8);
1247 break;
1248 }
1249 break;
1250 case IEEE80211_S_RUN:
1251 switch (arg & 0xff) {
1252 case IEEE80211_FC0_SUBTYPE_AUTH:
1253 IEEE80211_SEND_MGMT(ic, ni,
1254 IEEE80211_FC0_SUBTYPE_AUTH, 2);
1255 ic->ic_state = ostate; /* stay RUN */
1256 break;
1257 case IEEE80211_FC0_SUBTYPE_DEAUTH:
1258 ieee80211_sta_leave(ic, ni);
1259 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
1260 /* try to reauth */
1261 IEEE80211_SEND_MGMT(ic, ni,
1262 IEEE80211_FC0_SUBTYPE_AUTH, 1);
1263 }
1264 break;
1265 }
1266 break;
1267 default:
1268 break;
1269 }
1270 break;
1271 case IEEE80211_S_ASSOC:
1272 KASSERT(ic->ic_opmode == IEEE80211_M_STA,
1273 ("switch to %s state when operating in mode %u",
1274 ieee80211_state_name[nstate], ic->ic_opmode));
1275 switch (ostate) {
1276 case IEEE80211_S_INIT:
1277 case IEEE80211_S_SCAN:
1278 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
1279 "%s: invalid transition\n", __func__);
1280 break;
1281 case IEEE80211_S_AUTH:
1282 case IEEE80211_S_ASSOC:
1283 IEEE80211_SEND_MGMT(ic, ni,
1284 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
1285 break;
1286 case IEEE80211_S_RUN:
1287 ieee80211_sta_leave(ic, ni);
1288 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
1289 IEEE80211_SEND_MGMT(ic, ni, arg ?
1290 IEEE80211_FC0_SUBTYPE_REASSOC_REQ :
1291 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
1292 }
1293 break;
1294 default:
1295 break;
1296 }
1297 break;
1298 case IEEE80211_S_RUN:
1299 if (ic->ic_flags & IEEE80211_F_WPA) {
1300 /* XXX validate prerequisites */
1301 }
1302 switch (ostate) {
1303 case IEEE80211_S_INIT:
1304 if (ic->ic_opmode == IEEE80211_M_MONITOR ||
1305 ic->ic_opmode == IEEE80211_M_WDS ||
1306 ic->ic_opmode == IEEE80211_M_HOSTAP) {
1307 /*
1308 * Already have a channel; bypass the
1309 * scan and startup immediately. Because
1310 * of this explicitly sync the scanner state.
1311 */
1312 ieee80211_scan_update(ic);
1313 ieee80211_create_ibss(ic, ic->ic_curchan);
1314 break;
1315 }
1316 /* fall thru... */
1317 case IEEE80211_S_AUTH:
1318 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
1319 "%s: invalid transition\n", __func__);
1320 /* fall thru... */
1321 case IEEE80211_S_RUN:
1322 break;
1323 case IEEE80211_S_SCAN: /* adhoc/hostap mode */
1324 case IEEE80211_S_ASSOC: /* infra mode */
1325 KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates,
1326 ("%s: bogus xmit rate %u setup\n", __func__,
1327 ni->ni_txrate));
1328#ifdef IEEE80211_DEBUG
1329 if (ieee80211_msg_debug(ic)) {
1330 if (ic->ic_opmode == IEEE80211_M_STA)
1331 if_printf(ifp, "associated ");
1332 else
1333 if_printf(ifp, "synchronized ");
1334 printf("with %s ssid ",
1335 ether_sprintf(ni->ni_bssid));
1336 ieee80211_print_essid(ic->ic_bss->ni_essid,
1337 ni->ni_esslen);
1338 printf(" channel %d start %uMb\n",
1339 ieee80211_chan2ieee(ic, ic->ic_curchan),
1340 IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
1341 }
1342#endif
1343 if (ic->ic_opmode == IEEE80211_M_STA) {
1344 ieee80211_scan_assoc_success(ic,
1345 ni->ni_macaddr);
1346 ieee80211_notify_node_join(ic, ni,
1347 arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
1348 }
1349 if_start(ifp); /* XXX not authorized yet */
1350 break;
1351 default:
1352 break;
1353 }
1354 if (ostate != IEEE80211_S_RUN &&
1355 ic->ic_opmode == IEEE80211_M_STA &&
1356 (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)) {
1357 /*
1358 * Start s/w beacon miss timer for devices w/o
1359 * hardware support. We fudge a bit here since
1360 * we're doing this in software.
1361 */
1362 ic->ic_swbmiss_period = IEEE80211_TU_TO_TICKS(
1363 2 * ic->ic_bmissthreshold * ni->ni_intval);
1364 ic->ic_swbmiss_count = 0;
1365 callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period,
1366 ieee80211_swbmiss, ic);
1367 }
1368 /*
1369 * Start/stop the authenticator when operating as an
1370 * AP. We delay until here to allow configuration to
1371 * happen out of order.
1372 */
1373 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */
1374 ic->ic_auth->ia_attach != NULL) {
1375 /* XXX check failure */
1376 ic->ic_auth->ia_attach(ic);
1377 } else if (ic->ic_auth->ia_detach != NULL) {
1378 ic->ic_auth->ia_detach(ic);
1379 }
1380 /*
1381 * When 802.1x is not in use mark the port authorized
1382 * at this point so traffic can flow.
1383 */
1384 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
1385 ieee80211_node_authorize(ni);
1386 /*
1387 * Enable inactivity processing.
1388 * XXX
1389 */
1390 callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
1391 ieee80211_node_timeout, ic);
1392 break;
1393 default:
1394 break;
1395 }
1396 return 0;
1397}
869 }
870
871 wme->wme_update(ic);
872
873 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
874 "%s: WME params updated, cap_info 0x%x\n", __func__,
875 ic->ic_opmode == IEEE80211_M_STA ?
876 wme->wme_wmeChanParams.cap_info :
877 wme->wme_bssChanParams.cap_info);
878}
879
880void
881ieee80211_wme_updateparams(struct ieee80211com *ic)
882{
883
884 if (ic->ic_caps & IEEE80211_C_WME) {
885 IEEE80211_BEACON_LOCK(ic);
886 ieee80211_wme_updateparams_locked(ic);
887 IEEE80211_BEACON_UNLOCK(ic);
888 }
889}
890
891/*
892 * Start a device. If this is the first vap running on the
893 * underlying device then we first bring it up.
894 */
895int
896ieee80211_init(struct ieee80211com *ic, int forcescan)
897{
898
899 IEEE80211_DPRINTF(ic,
900 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
901 "%s\n", "start running");
902
903 /*
904 * Kick the 802.11 state machine as appropriate.
905 */
906 if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) {
907 if (ic->ic_opmode == IEEE80211_M_STA) {
908 /*
909 * Try to be intelligent about clocking the state
910 * machine. If we're currently in RUN state then
911 * we should be able to apply any new state/parameters
912 * simply by re-associating. Otherwise we need to
913 * re-scan to select an appropriate ap.
914 */
915 if (ic->ic_state != IEEE80211_S_RUN || forcescan)
916 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
917 else
918 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
919 } else {
920 /*
921 * For monitor+wds modes there's nothing to do but
922 * start running. Otherwise, if this is the first
923 * vap to be brought up, start a scan which may be
924 * preempted if the station is locked to a particular
925 * channel.
926 */
927 if (ic->ic_opmode == IEEE80211_M_MONITOR ||
928 ic->ic_opmode == IEEE80211_M_WDS) {
929 ic->ic_state = IEEE80211_S_INIT; /* XXX*/
930 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
931 } else
932 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
933 }
934 }
935 return 0;
936}
937
938/*
939 * Switch between turbo and non-turbo operating modes.
940 * Use the specified channel flags to locate the new
941 * channel, update 802.11 state, and then call back into
942 * the driver to effect the change.
943 */
944void
945ieee80211_dturbo_switch(struct ieee80211com *ic, int newflags)
946{
947 struct ieee80211_channel *chan;
948
949 chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags);
950 if (chan == NULL) { /* XXX should not happen */
951 IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
952 "%s: no channel with freq %u flags 0x%x\n",
953 __func__, ic->ic_bsschan->ic_freq, newflags);
954 return;
955 }
956
957 IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
958 "%s: %s -> %s (freq %u flags 0x%x)\n", __func__,
959 ieee80211_phymode_name[ieee80211_chan2mode(ic->ic_bsschan)],
960 ieee80211_phymode_name[ieee80211_chan2mode(chan)],
961 chan->ic_freq, chan->ic_flags);
962
963 ic->ic_bsschan = chan;
964 ic->ic_prevchan = ic->ic_curchan;
965 ic->ic_curchan = chan;
966 ic->ic_set_channel(ic);
967 /* NB: do not need to reset ERP state 'cuz we're in sta mode */
968}
969
970void
971ieee80211_beacon_miss(struct ieee80211com *ic)
972{
973
974 if (ic->ic_flags & IEEE80211_F_SCAN) {
975 /* XXX check ic_curchan != ic_bsschan? */
976 return;
977 }
978 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
979 "%s\n", "beacon miss");
980
981 /*
982 * Our handling is only meaningful for stations that are
983 * associated; any other conditions else will be handled
984 * through different means (e.g. the tx timeout on mgt frames).
985 */
986 if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN)
987 return;
988
989 if (++ic->ic_bmiss_count < ic->ic_bmiss_max) {
990 /*
991 * Send a directed probe req before falling back to a scan;
992 * if we receive a response ic_bmiss_count will be reset.
993 * Some cards mistakenly report beacon miss so this avoids
994 * the expensive scan if the ap is still there.
995 */
996 ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr,
997 ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid,
998 ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen,
999 ic->ic_opt_ie, ic->ic_opt_ie_len);
1000 return;
1001 }
1002 ic->ic_bmiss_count = 0;
1003 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
1004 /*
1005 * If we receive a beacon miss interrupt when using
1006 * dynamic turbo, attempt to switch modes before
1007 * reassociating.
1008 */
1009 if (IEEE80211_ATH_CAP(ic, ic->ic_bss, IEEE80211_NODE_TURBOP))
1010 ieee80211_dturbo_switch(ic,
1011 ic->ic_bsschan->ic_flags ^ IEEE80211_CHAN_TURBO);
1012 /*
1013 * Try to reassociate before scanning for a new ap.
1014 */
1015 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
1016 } else {
1017 /*
1018 * Somebody else is controlling state changes (e.g.
1019 * a user-mode app) don't do anything that would
1020 * confuse them; just drop into scan mode so they'll
1021 * notified of the state change and given control.
1022 */
1023 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
1024 }
1025}
1026
1027/*
1028 * Software beacon miss handling. Check if any beacons
1029 * were received in the last period. If not post a
1030 * beacon miss; otherwise reset the counter.
1031 */
1032static void
1033ieee80211_swbmiss(void *arg)
1034{
1035 struct ieee80211com *ic = arg;
1036
1037 if (ic->ic_swbmiss_count == 0) {
1038 ieee80211_beacon_miss(ic);
1039 if (ic->ic_bmiss_count == 0) /* don't re-arm timer */
1040 return;
1041 } else
1042 ic->ic_swbmiss_count = 0;
1043 callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period,
1044 ieee80211_swbmiss, ic);
1045}
1046
1047static void
1048sta_disassoc(void *arg, struct ieee80211_node *ni)
1049{
1050 struct ieee80211com *ic = arg;
1051
1052 if (ni->ni_associd != 0) {
1053 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
1054 IEEE80211_REASON_ASSOC_LEAVE);
1055 ieee80211_node_leave(ic, ni);
1056 }
1057}
1058
1059static void
1060sta_deauth(void *arg, struct ieee80211_node *ni)
1061{
1062 struct ieee80211com *ic = arg;
1063
1064 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
1065 IEEE80211_REASON_ASSOC_LEAVE);
1066}
1067
1068/*
1069 * Handle deauth with reason. We retry only for
1070 * the cases where we might succeed. Otherwise
1071 * we downgrade the ap and scan.
1072 */
1073static void
1074sta_authretry(struct ieee80211com *ic, struct ieee80211_node *ni, int reason)
1075{
1076 switch (reason) {
1077 case IEEE80211_STATUS_SUCCESS:
1078 case IEEE80211_STATUS_TIMEOUT:
1079 case IEEE80211_REASON_ASSOC_EXPIRE:
1080 case IEEE80211_REASON_NOT_AUTHED:
1081 case IEEE80211_REASON_NOT_ASSOCED:
1082 case IEEE80211_REASON_ASSOC_LEAVE:
1083 case IEEE80211_REASON_ASSOC_NOT_AUTHED:
1084 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 1);
1085 break;
1086 default:
1087 ieee80211_scan_assoc_fail(ic, ic->ic_bss->ni_macaddr, reason);
1088 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
1089 ieee80211_check_scan(ic,
1090 IEEE80211_SCAN_ACTIVE,
1091 IEEE80211_SCAN_FOREVER,
1092 ic->ic_des_nssid, ic->ic_des_ssid);
1093 break;
1094 }
1095}
1096
1097static int
1098ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1099{
1100 struct ifnet *ifp = ic->ic_ifp;
1101 struct ieee80211_node *ni;
1102 enum ieee80211_state ostate;
1103
1104 ostate = ic->ic_state;
1105 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__,
1106 ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
1107 ic->ic_state = nstate; /* state transition */
1108 callout_stop(&ic->ic_mgtsend); /* XXX callout_drain */
1109 if (ostate != IEEE80211_S_SCAN)
1110 ieee80211_cancel_scan(ic); /* background scan */
1111 ni = ic->ic_bss; /* NB: no reference held */
1112 if (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)
1113 callout_stop(&ic->ic_swbmiss);
1114 switch (nstate) {
1115 case IEEE80211_S_INIT:
1116 switch (ostate) {
1117 case IEEE80211_S_INIT:
1118 break;
1119 case IEEE80211_S_RUN:
1120 switch (ic->ic_opmode) {
1121 case IEEE80211_M_STA:
1122 IEEE80211_SEND_MGMT(ic, ni,
1123 IEEE80211_FC0_SUBTYPE_DISASSOC,
1124 IEEE80211_REASON_ASSOC_LEAVE);
1125 ieee80211_sta_leave(ic, ni);
1126 break;
1127 case IEEE80211_M_HOSTAP:
1128 ieee80211_iterate_nodes(&ic->ic_sta,
1129 sta_disassoc, ic);
1130 break;
1131 default:
1132 break;
1133 }
1134 break;
1135 case IEEE80211_S_ASSOC:
1136 switch (ic->ic_opmode) {
1137 case IEEE80211_M_STA:
1138 IEEE80211_SEND_MGMT(ic, ni,
1139 IEEE80211_FC0_SUBTYPE_DEAUTH,
1140 IEEE80211_REASON_AUTH_LEAVE);
1141 break;
1142 case IEEE80211_M_HOSTAP:
1143 ieee80211_iterate_nodes(&ic->ic_sta,
1144 sta_deauth, ic);
1145 break;
1146 default:
1147 break;
1148 }
1149 break;
1150 case IEEE80211_S_SCAN:
1151 ieee80211_cancel_scan(ic);
1152 break;
1153 case IEEE80211_S_AUTH:
1154 break;
1155 default:
1156 break;
1157 }
1158 if (ostate != IEEE80211_S_INIT) {
1159 /* NB: optimize INIT -> INIT case */
1160 ieee80211_drain_ifq(&ic->ic_mgtq);
1161 ieee80211_reset_bss(ic);
1162 ieee80211_scan_flush(ic);
1163 }
1164 if (ic->ic_auth->ia_detach != NULL)
1165 ic->ic_auth->ia_detach(ic);
1166 break;
1167 case IEEE80211_S_SCAN:
1168 switch (ostate) {
1169 case IEEE80211_S_INIT:
1170 createibss:
1171 if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
1172 ic->ic_opmode == IEEE80211_M_IBSS ||
1173 ic->ic_opmode == IEEE80211_M_AHDEMO) &&
1174 ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1175 /*
1176 * Already have a channel; bypass the
1177 * scan and startup immediately. Because
1178 * of this explicitly sync the scanner state.
1179 */
1180 ieee80211_scan_update(ic);
1181 ieee80211_create_ibss(ic, ic->ic_des_chan);
1182 } else {
1183 ieee80211_check_scan(ic,
1184 IEEE80211_SCAN_ACTIVE |
1185 IEEE80211_SCAN_FLUSH,
1186 IEEE80211_SCAN_FOREVER,
1187 ic->ic_des_nssid, ic->ic_des_ssid);
1188 }
1189 break;
1190 case IEEE80211_S_SCAN:
1191 case IEEE80211_S_AUTH:
1192 case IEEE80211_S_ASSOC:
1193 /*
1194 * These can happen either because of a timeout
1195 * on an assoc/auth response or because of a
1196 * change in state that requires a reset. For
1197 * the former we're called with a non-zero arg
1198 * that is the cause for the failure; pass this
1199 * to the scan code so it can update state.
1200 * Otherwise trigger a new scan unless we're in
1201 * manual roaming mode in which case an application
1202 * must issue an explicit scan request.
1203 */
1204 if (arg != 0)
1205 ieee80211_scan_assoc_fail(ic,
1206 ic->ic_bss->ni_macaddr, arg);
1207 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
1208 ieee80211_check_scan(ic,
1209 IEEE80211_SCAN_ACTIVE,
1210 IEEE80211_SCAN_FOREVER,
1211 ic->ic_des_nssid, ic->ic_des_ssid);
1212 break;
1213 case IEEE80211_S_RUN: /* beacon miss */
1214 if (ic->ic_opmode == IEEE80211_M_STA) {
1215 ieee80211_sta_leave(ic, ni);
1216 ic->ic_flags &= ~IEEE80211_F_SIBSS; /* XXX */
1217 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
1218 ieee80211_check_scan(ic,
1219 IEEE80211_SCAN_ACTIVE,
1220 IEEE80211_SCAN_FOREVER,
1221 ic->ic_des_nssid,
1222 ic->ic_des_ssid);
1223 } else {
1224 ieee80211_iterate_nodes(&ic->ic_sta,
1225 sta_disassoc, ic);
1226 goto createibss;
1227 }
1228 break;
1229 default:
1230 break;
1231 }
1232 break;
1233 case IEEE80211_S_AUTH:
1234 KASSERT(ic->ic_opmode == IEEE80211_M_STA,
1235 ("switch to %s state when operating in mode %u",
1236 ieee80211_state_name[nstate], ic->ic_opmode));
1237 switch (ostate) {
1238 case IEEE80211_S_INIT:
1239 case IEEE80211_S_SCAN:
1240 IEEE80211_SEND_MGMT(ic, ni,
1241 IEEE80211_FC0_SUBTYPE_AUTH, 1);
1242 break;
1243 case IEEE80211_S_AUTH:
1244 case IEEE80211_S_ASSOC:
1245 switch (arg & 0xff) {
1246 case IEEE80211_FC0_SUBTYPE_AUTH:
1247 /* ??? */
1248 IEEE80211_SEND_MGMT(ic, ni,
1249 IEEE80211_FC0_SUBTYPE_AUTH, 2);
1250 break;
1251 case IEEE80211_FC0_SUBTYPE_DEAUTH:
1252 sta_authretry(ic, ni, arg>>8);
1253 break;
1254 }
1255 break;
1256 case IEEE80211_S_RUN:
1257 switch (arg & 0xff) {
1258 case IEEE80211_FC0_SUBTYPE_AUTH:
1259 IEEE80211_SEND_MGMT(ic, ni,
1260 IEEE80211_FC0_SUBTYPE_AUTH, 2);
1261 ic->ic_state = ostate; /* stay RUN */
1262 break;
1263 case IEEE80211_FC0_SUBTYPE_DEAUTH:
1264 ieee80211_sta_leave(ic, ni);
1265 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
1266 /* try to reauth */
1267 IEEE80211_SEND_MGMT(ic, ni,
1268 IEEE80211_FC0_SUBTYPE_AUTH, 1);
1269 }
1270 break;
1271 }
1272 break;
1273 default:
1274 break;
1275 }
1276 break;
1277 case IEEE80211_S_ASSOC:
1278 KASSERT(ic->ic_opmode == IEEE80211_M_STA,
1279 ("switch to %s state when operating in mode %u",
1280 ieee80211_state_name[nstate], ic->ic_opmode));
1281 switch (ostate) {
1282 case IEEE80211_S_INIT:
1283 case IEEE80211_S_SCAN:
1284 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
1285 "%s: invalid transition\n", __func__);
1286 break;
1287 case IEEE80211_S_AUTH:
1288 case IEEE80211_S_ASSOC:
1289 IEEE80211_SEND_MGMT(ic, ni,
1290 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
1291 break;
1292 case IEEE80211_S_RUN:
1293 ieee80211_sta_leave(ic, ni);
1294 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
1295 IEEE80211_SEND_MGMT(ic, ni, arg ?
1296 IEEE80211_FC0_SUBTYPE_REASSOC_REQ :
1297 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
1298 }
1299 break;
1300 default:
1301 break;
1302 }
1303 break;
1304 case IEEE80211_S_RUN:
1305 if (ic->ic_flags & IEEE80211_F_WPA) {
1306 /* XXX validate prerequisites */
1307 }
1308 switch (ostate) {
1309 case IEEE80211_S_INIT:
1310 if (ic->ic_opmode == IEEE80211_M_MONITOR ||
1311 ic->ic_opmode == IEEE80211_M_WDS ||
1312 ic->ic_opmode == IEEE80211_M_HOSTAP) {
1313 /*
1314 * Already have a channel; bypass the
1315 * scan and startup immediately. Because
1316 * of this explicitly sync the scanner state.
1317 */
1318 ieee80211_scan_update(ic);
1319 ieee80211_create_ibss(ic, ic->ic_curchan);
1320 break;
1321 }
1322 /* fall thru... */
1323 case IEEE80211_S_AUTH:
1324 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
1325 "%s: invalid transition\n", __func__);
1326 /* fall thru... */
1327 case IEEE80211_S_RUN:
1328 break;
1329 case IEEE80211_S_SCAN: /* adhoc/hostap mode */
1330 case IEEE80211_S_ASSOC: /* infra mode */
1331 KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates,
1332 ("%s: bogus xmit rate %u setup\n", __func__,
1333 ni->ni_txrate));
1334#ifdef IEEE80211_DEBUG
1335 if (ieee80211_msg_debug(ic)) {
1336 if (ic->ic_opmode == IEEE80211_M_STA)
1337 if_printf(ifp, "associated ");
1338 else
1339 if_printf(ifp, "synchronized ");
1340 printf("with %s ssid ",
1341 ether_sprintf(ni->ni_bssid));
1342 ieee80211_print_essid(ic->ic_bss->ni_essid,
1343 ni->ni_esslen);
1344 printf(" channel %d start %uMb\n",
1345 ieee80211_chan2ieee(ic, ic->ic_curchan),
1346 IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
1347 }
1348#endif
1349 if (ic->ic_opmode == IEEE80211_M_STA) {
1350 ieee80211_scan_assoc_success(ic,
1351 ni->ni_macaddr);
1352 ieee80211_notify_node_join(ic, ni,
1353 arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
1354 }
1355 if_start(ifp); /* XXX not authorized yet */
1356 break;
1357 default:
1358 break;
1359 }
1360 if (ostate != IEEE80211_S_RUN &&
1361 ic->ic_opmode == IEEE80211_M_STA &&
1362 (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)) {
1363 /*
1364 * Start s/w beacon miss timer for devices w/o
1365 * hardware support. We fudge a bit here since
1366 * we're doing this in software.
1367 */
1368 ic->ic_swbmiss_period = IEEE80211_TU_TO_TICKS(
1369 2 * ic->ic_bmissthreshold * ni->ni_intval);
1370 ic->ic_swbmiss_count = 0;
1371 callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period,
1372 ieee80211_swbmiss, ic);
1373 }
1374 /*
1375 * Start/stop the authenticator when operating as an
1376 * AP. We delay until here to allow configuration to
1377 * happen out of order.
1378 */
1379 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */
1380 ic->ic_auth->ia_attach != NULL) {
1381 /* XXX check failure */
1382 ic->ic_auth->ia_attach(ic);
1383 } else if (ic->ic_auth->ia_detach != NULL) {
1384 ic->ic_auth->ia_detach(ic);
1385 }
1386 /*
1387 * When 802.1x is not in use mark the port authorized
1388 * at this point so traffic can flow.
1389 */
1390 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
1391 ieee80211_node_authorize(ni);
1392 /*
1393 * Enable inactivity processing.
1394 * XXX
1395 */
1396 callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
1397 ieee80211_node_timeout, ic);
1398 break;
1399 default:
1400 break;
1401 }
1402 return 0;
1403}