Line data Source code
1 : /* $OpenBSD: ieee80211_proto.c,v 1.90 2018/09/11 10:23:40 krw 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 : * Copyright (c) 2008, 2009 Damien Bergamini
8 : * All rights reserved.
9 : *
10 : * Redistribution and use in source and binary forms, with or without
11 : * modification, are permitted provided that the following conditions
12 : * are met:
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : * 2. Redistributions in binary form must reproduce the above copyright
16 : * notice, this list of conditions and the following disclaimer in the
17 : * documentation and/or other materials provided with the distribution.
18 : * 3. The name of the author may not be used to endorse or promote products
19 : * derived from this software without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : */
32 :
33 : /*
34 : * IEEE 802.11 protocol support.
35 : */
36 :
37 : #include <sys/param.h>
38 : #include <sys/systm.h>
39 : #include <sys/mbuf.h>
40 : #include <sys/kernel.h>
41 : #include <sys/socket.h>
42 : #include <sys/sockio.h>
43 : #include <sys/endian.h>
44 : #include <sys/errno.h>
45 : #include <sys/sysctl.h>
46 :
47 : #include <net/if.h>
48 : #include <net/if_dl.h>
49 : #include <net/if_media.h>
50 : #include <net/if_llc.h>
51 :
52 : #include <netinet/in.h>
53 : #include <netinet/if_ether.h>
54 :
55 : #include <net80211/ieee80211_var.h>
56 : #include <net80211/ieee80211_priv.h>
57 :
58 : const char * const ieee80211_mgt_subtype_name[] = {
59 : "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
60 : "probe_req", "probe_resp", "reserved#6", "reserved#7",
61 : "beacon", "atim", "disassoc", "auth",
62 : "deauth", "action", "action_noack", "reserved#15"
63 : };
64 : const char * const ieee80211_state_name[IEEE80211_S_MAX] = {
65 : "INIT", /* IEEE80211_S_INIT */
66 : "SCAN", /* IEEE80211_S_SCAN */
67 : "AUTH", /* IEEE80211_S_AUTH */
68 : "ASSOC", /* IEEE80211_S_ASSOC */
69 : "RUN" /* IEEE80211_S_RUN */
70 : };
71 : const char * const ieee80211_phymode_name[] = {
72 : "auto", /* IEEE80211_MODE_AUTO */
73 : "11a", /* IEEE80211_MODE_11A */
74 : "11b", /* IEEE80211_MODE_11B */
75 : "11g", /* IEEE80211_MODE_11G */
76 : "11n", /* IEEE80211_MODE_11N */
77 : };
78 :
79 : void ieee80211_set_beacon_miss_threshold(struct ieee80211com *);
80 : int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
81 :
82 : void
83 0 : ieee80211_proto_attach(struct ifnet *ifp)
84 : {
85 0 : struct ieee80211com *ic = (void *)ifp;
86 :
87 0 : mq_init(&ic->ic_mgtq, IFQ_MAXLEN, IPL_NET);
88 0 : mq_init(&ic->ic_pwrsaveq, IFQ_MAXLEN, IPL_NET);
89 :
90 0 : ifp->if_hdrlen = sizeof(struct ieee80211_frame);
91 :
92 0 : ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
93 0 : ic->ic_fragthreshold = 2346; /* XXX not used yet */
94 0 : ic->ic_fixed_rate = -1; /* no fixed rate */
95 0 : ic->ic_fixed_mcs = -1; /* no fixed mcs */
96 0 : ic->ic_protmode = IEEE80211_PROT_CTSONLY;
97 :
98 : /* protocol state change handler */
99 0 : ic->ic_newstate = ieee80211_newstate;
100 :
101 : /* initialize management frame handlers */
102 0 : ic->ic_recv_mgmt = ieee80211_recv_mgmt;
103 0 : ic->ic_send_mgmt = ieee80211_send_mgmt;
104 0 : }
105 :
106 : void
107 0 : ieee80211_proto_detach(struct ifnet *ifp)
108 : {
109 0 : struct ieee80211com *ic = (void *)ifp;
110 :
111 0 : mq_purge(&ic->ic_mgtq);
112 0 : mq_purge(&ic->ic_pwrsaveq);
113 0 : }
114 :
115 : void
116 0 : ieee80211_print_essid(const u_int8_t *essid, int len)
117 : {
118 : int i;
119 : const u_int8_t *p;
120 :
121 0 : if (len > IEEE80211_NWID_LEN)
122 0 : len = IEEE80211_NWID_LEN;
123 : /* determine printable or not */
124 0 : for (i = 0, p = essid; i < len; i++, p++) {
125 0 : if (*p < ' ' || *p > 0x7e)
126 : break;
127 : }
128 0 : if (i == len) {
129 0 : printf("\"");
130 0 : for (i = 0, p = essid; i < len; i++, p++)
131 0 : printf("%c", *p);
132 0 : printf("\"");
133 0 : } else {
134 0 : printf("0x");
135 0 : for (i = 0, p = essid; i < len; i++, p++)
136 0 : printf("%02x", *p);
137 : }
138 0 : }
139 :
140 : #ifdef IEEE80211_DEBUG
141 : void
142 : ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi)
143 : {
144 : struct ieee80211_frame *wh;
145 : int i;
146 :
147 : wh = (struct ieee80211_frame *)buf;
148 : switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
149 : case IEEE80211_FC1_DIR_NODS:
150 : printf("NODS %s", ether_sprintf(wh->i_addr2));
151 : printf("->%s", ether_sprintf(wh->i_addr1));
152 : printf("(%s)", ether_sprintf(wh->i_addr3));
153 : break;
154 : case IEEE80211_FC1_DIR_TODS:
155 : printf("TODS %s", ether_sprintf(wh->i_addr2));
156 : printf("->%s", ether_sprintf(wh->i_addr3));
157 : printf("(%s)", ether_sprintf(wh->i_addr1));
158 : break;
159 : case IEEE80211_FC1_DIR_FROMDS:
160 : printf("FRDS %s", ether_sprintf(wh->i_addr3));
161 : printf("->%s", ether_sprintf(wh->i_addr1));
162 : printf("(%s)", ether_sprintf(wh->i_addr2));
163 : break;
164 : case IEEE80211_FC1_DIR_DSTODS:
165 : printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
166 : printf("->%s", ether_sprintf(wh->i_addr3));
167 : printf("(%s", ether_sprintf(wh->i_addr2));
168 : printf("->%s)", ether_sprintf(wh->i_addr1));
169 : break;
170 : }
171 : switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
172 : case IEEE80211_FC0_TYPE_DATA:
173 : printf(" data");
174 : break;
175 : case IEEE80211_FC0_TYPE_MGT:
176 : printf(" %s", ieee80211_mgt_subtype_name[
177 : (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
178 : >> IEEE80211_FC0_SUBTYPE_SHIFT]);
179 : break;
180 : default:
181 : printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
182 : break;
183 : }
184 : if (wh->i_fc[1] & IEEE80211_FC1_WEP)
185 : printf(" WEP");
186 : if (rate >= 0)
187 : printf(" %d%sM", rate / 2, (rate & 1) ? ".5" : "");
188 : if (rssi >= 0)
189 : printf(" +%d", rssi);
190 : printf("\n");
191 : if (len > 0) {
192 : for (i = 0; i < len; i++) {
193 : if ((i & 1) == 0)
194 : printf(" ");
195 : printf("%02x", buf[i]);
196 : }
197 : printf("\n");
198 : }
199 : }
200 : #endif
201 :
202 : int
203 0 : ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
204 : int flags)
205 : {
206 : #define RV(v) ((v) & IEEE80211_RATE_VAL)
207 : int i, j, ignore, error;
208 : int okrate, badrate, fixedrate;
209 : const struct ieee80211_rateset *srs;
210 : struct ieee80211_rateset *nrs;
211 : u_int8_t r;
212 :
213 : /*
214 : * If the fixed rate check was requested but no fixed rate has been
215 : * defined then just remove the check.
216 : */
217 0 : if ((flags & IEEE80211_F_DOFRATE) && ic->ic_fixed_rate == -1)
218 0 : flags &= ~IEEE80211_F_DOFRATE;
219 :
220 : error = 0;
221 : okrate = badrate = fixedrate = 0;
222 0 : srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
223 0 : nrs = &ni->ni_rates;
224 0 : for (i = 0; i < nrs->rs_nrates; ) {
225 : ignore = 0;
226 0 : if (flags & IEEE80211_F_DOSORT) {
227 : /*
228 : * Sort rates.
229 : */
230 0 : for (j = i + 1; j < nrs->rs_nrates; j++) {
231 0 : if (RV(nrs->rs_rates[i]) >
232 0 : RV(nrs->rs_rates[j])) {
233 : r = nrs->rs_rates[i];
234 0 : nrs->rs_rates[i] = nrs->rs_rates[j];
235 0 : nrs->rs_rates[j] = r;
236 0 : }
237 : }
238 : }
239 0 : r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
240 0 : badrate = r;
241 0 : if (flags & IEEE80211_F_DOFRATE) {
242 : /*
243 : * Check fixed rate is included.
244 : */
245 0 : if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
246 0 : fixedrate = r;
247 : }
248 0 : if (flags & IEEE80211_F_DONEGO) {
249 : /*
250 : * Check against supported rates.
251 : */
252 0 : for (j = 0; j < srs->rs_nrates; j++) {
253 0 : if (r == RV(srs->rs_rates[j])) {
254 : /*
255 : * Overwrite with the supported rate
256 : * value so any basic rate bit is set.
257 : * This insures that response we send
258 : * to stations have the necessary basic
259 : * rate bit set.
260 : */
261 0 : nrs->rs_rates[i] = srs->rs_rates[j];
262 0 : break;
263 : }
264 : }
265 0 : if (j == srs->rs_nrates) {
266 : /*
267 : * A rate in the node's rate set is not
268 : * supported. If this is a basic rate and we
269 : * are operating as an AP then this is an error.
270 : * Otherwise we just discard/ignore the rate.
271 : * Note that this is important for 11b stations
272 : * when they want to associate with an 11g AP.
273 : */
274 : #ifndef IEEE80211_STA_ONLY
275 0 : if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
276 0 : (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
277 0 : error++;
278 : #endif
279 : ignore++;
280 0 : }
281 : }
282 0 : if (flags & IEEE80211_F_DODEL) {
283 : /*
284 : * Delete unacceptable rates.
285 : */
286 0 : if (ignore) {
287 0 : nrs->rs_nrates--;
288 0 : for (j = i; j < nrs->rs_nrates; j++)
289 0 : nrs->rs_rates[j] = nrs->rs_rates[j + 1];
290 0 : nrs->rs_rates[j] = 0;
291 0 : continue;
292 : }
293 : }
294 0 : if (!ignore)
295 0 : okrate = nrs->rs_rates[i];
296 0 : i++;
297 : }
298 0 : if (okrate == 0 || error != 0 ||
299 0 : ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))
300 0 : return badrate | IEEE80211_RATE_BASIC;
301 : else
302 0 : return RV(okrate);
303 : #undef RV
304 0 : }
305 :
306 : /*
307 : * Reset 11g-related state.
308 : */
309 : void
310 0 : ieee80211_reset_erp(struct ieee80211com *ic)
311 : {
312 0 : ic->ic_flags &= ~IEEE80211_F_USEPROT;
313 :
314 0 : ieee80211_set_shortslottime(ic,
315 0 : ic->ic_curmode == IEEE80211_MODE_11A ||
316 0 : (ic->ic_curmode == IEEE80211_MODE_11N &&
317 0 : IEEE80211_IS_CHAN_5GHZ(ic->ic_ibss_chan))
318 : #ifndef IEEE80211_STA_ONLY
319 0 : ||
320 0 : ((ic->ic_curmode == IEEE80211_MODE_11G ||
321 0 : (ic->ic_curmode == IEEE80211_MODE_11N &&
322 0 : IEEE80211_IS_CHAN_2GHZ(ic->ic_ibss_chan))) &&
323 0 : ic->ic_opmode == IEEE80211_M_HOSTAP &&
324 0 : (ic->ic_caps & IEEE80211_C_SHSLOT))
325 : #endif
326 : );
327 :
328 0 : if (ic->ic_curmode == IEEE80211_MODE_11A ||
329 0 : (ic->ic_curmode == IEEE80211_MODE_11N &&
330 0 : IEEE80211_IS_CHAN_5GHZ(ic->ic_ibss_chan)) ||
331 0 : (ic->ic_caps & IEEE80211_C_SHPREAMBLE))
332 0 : ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
333 : else
334 0 : ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
335 0 : }
336 :
337 : /*
338 : * Set the short slot time state and notify the driver.
339 : */
340 : void
341 0 : ieee80211_set_shortslottime(struct ieee80211com *ic, int on)
342 : {
343 0 : if (on)
344 0 : ic->ic_flags |= IEEE80211_F_SHSLOT;
345 : else
346 0 : ic->ic_flags &= ~IEEE80211_F_SHSLOT;
347 :
348 : /* notify the driver */
349 0 : if (ic->ic_updateslot != NULL)
350 0 : ic->ic_updateslot(ic);
351 0 : }
352 :
353 : /*
354 : * This function is called by the 802.1X PACP machine (via an ioctl) when
355 : * the transmit key machine (4-Way Handshake for 802.11) should run.
356 : */
357 : int
358 0 : ieee80211_keyrun(struct ieee80211com *ic, u_int8_t *macaddr)
359 : {
360 0 : struct ieee80211_node *ni = ic->ic_bss;
361 : #ifndef IEEE80211_STA_ONLY
362 : struct ieee80211_pmk *pmk;
363 : #endif
364 :
365 : /* STA must be associated or AP must be ready */
366 0 : if (ic->ic_state != IEEE80211_S_RUN ||
367 0 : !(ic->ic_flags & IEEE80211_F_RSNON))
368 0 : return ENETDOWN;
369 :
370 0 : ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
371 : #ifndef IEEE80211_STA_ONLY
372 0 : if (ic->ic_opmode == IEEE80211_M_STA)
373 : #endif
374 0 : return 0; /* supplicant only, do nothing */
375 :
376 : #ifndef IEEE80211_STA_ONLY
377 : /* find the STA with which we must start the key exchange */
378 0 : if ((ni = ieee80211_find_node(ic, macaddr)) == NULL) {
379 : DPRINTF(("no node found for %s\n", ether_sprintf(macaddr)));
380 0 : return EINVAL;
381 : }
382 : /* check that the STA is in the correct state */
383 0 : if (ni->ni_state != IEEE80211_STA_ASSOC ||
384 0 : ni->ni_rsn_state != RSNA_AUTHENTICATION_2) {
385 : DPRINTF(("unexpected in state %d\n", ni->ni_rsn_state));
386 0 : return EINVAL;
387 : }
388 0 : ni->ni_rsn_state = RSNA_INITPMK;
389 :
390 : /* make sure a PMK is available for this STA, otherwise deauth it */
391 0 : if ((pmk = ieee80211_pmksa_find(ic, ni, NULL)) == NULL) {
392 : DPRINTF(("no PMK available for %s\n", ether_sprintf(macaddr)));
393 0 : IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
394 : IEEE80211_REASON_AUTH_LEAVE);
395 0 : ieee80211_node_leave(ic, ni);
396 0 : return EINVAL;
397 : }
398 0 : memcpy(ni->ni_pmk, pmk->pmk_key, IEEE80211_PMK_LEN);
399 0 : memcpy(ni->ni_pmkid, pmk->pmk_pmkid, IEEE80211_PMKID_LEN);
400 0 : ni->ni_flags |= IEEE80211_NODE_PMK;
401 :
402 : /* initiate key exchange (4-Way Handshake) with STA */
403 0 : return ieee80211_send_4way_msg1(ic, ni);
404 : #endif /* IEEE80211_STA_ONLY */
405 0 : }
406 :
407 : #ifndef IEEE80211_STA_ONLY
408 : /*
409 : * Initiate a group key handshake with a node.
410 : */
411 : static void
412 0 : ieee80211_node_gtk_rekey(void *arg, struct ieee80211_node *ni)
413 : {
414 0 : struct ieee80211com *ic = arg;
415 :
416 0 : if (ni->ni_state != IEEE80211_STA_ASSOC ||
417 0 : ni->ni_rsn_gstate != RSNA_IDLE)
418 0 : return;
419 :
420 : /* initiate a group key handshake with STA */
421 0 : ni->ni_flags |= IEEE80211_NODE_REKEY;
422 0 : if (ieee80211_send_group_msg1(ic, ni) != 0)
423 0 : ni->ni_flags &= ~IEEE80211_NODE_REKEY;
424 0 : }
425 :
426 : /*
427 : * This function is called in HostAP mode when the group key needs to be
428 : * changed.
429 : */
430 : void
431 0 : ieee80211_setkeys(struct ieee80211com *ic)
432 : {
433 : struct ieee80211_key *k;
434 : u_int8_t kid;
435 :
436 : /* Swap(GM, GN) */
437 0 : kid = (ic->ic_def_txkey == 1) ? 2 : 1;
438 0 : k = &ic->ic_nw_keys[kid];
439 0 : memset(k, 0, sizeof(*k));
440 0 : k->k_id = kid;
441 0 : k->k_cipher = ic->ic_bss->ni_rsngroupcipher;
442 0 : k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;
443 0 : k->k_len = ieee80211_cipher_keylen(k->k_cipher);
444 0 : arc4random_buf(k->k_key, k->k_len);
445 :
446 0 : if (ic->ic_caps & IEEE80211_C_MFP) {
447 : /* Swap(GM_igtk, GN_igtk) */
448 0 : kid = (ic->ic_igtk_kid == 4) ? 5 : 4;
449 0 : k = &ic->ic_nw_keys[kid];
450 0 : memset(k, 0, sizeof(*k));
451 0 : k->k_id = kid;
452 0 : k->k_cipher = ic->ic_bss->ni_rsngroupmgmtcipher;
453 0 : k->k_flags = IEEE80211_KEY_IGTK | IEEE80211_KEY_TX;
454 0 : k->k_len = 16;
455 0 : arc4random_buf(k->k_key, k->k_len);
456 0 : }
457 :
458 0 : ieee80211_iterate_nodes(ic, ieee80211_node_gtk_rekey, ic);
459 0 : }
460 :
461 : /*
462 : * The group key handshake has been completed with all associated stations.
463 : */
464 : void
465 0 : ieee80211_setkeysdone(struct ieee80211com *ic)
466 : {
467 : u_int8_t kid;
468 :
469 : /* install GTK */
470 0 : kid = (ic->ic_def_txkey == 1) ? 2 : 1;
471 0 : if ((*ic->ic_set_key)(ic, ic->ic_bss, &ic->ic_nw_keys[kid]) == 0)
472 0 : ic->ic_def_txkey = kid;
473 :
474 0 : if (ic->ic_caps & IEEE80211_C_MFP) {
475 : /* install IGTK */
476 0 : kid = (ic->ic_igtk_kid == 4) ? 5 : 4;
477 0 : if ((*ic->ic_set_key)(ic, ic->ic_bss,
478 0 : &ic->ic_nw_keys[kid]) == 0)
479 0 : ic->ic_igtk_kid = kid;
480 : }
481 0 : }
482 :
483 : /*
484 : * Group key lifetime has expired, update it.
485 : */
486 : void
487 0 : ieee80211_gtk_rekey_timeout(void *arg)
488 : {
489 0 : struct ieee80211com *ic = arg;
490 : int s;
491 :
492 0 : s = splnet();
493 0 : ieee80211_setkeys(ic);
494 0 : splx(s);
495 :
496 : /* re-schedule a GTK rekeying after 3600s */
497 0 : timeout_add_sec(&ic->ic_rsn_timeout, 3600);
498 0 : }
499 :
500 : void
501 0 : ieee80211_sa_query_timeout(void *arg)
502 : {
503 0 : struct ieee80211_node *ni = arg;
504 0 : struct ieee80211com *ic = ni->ni_ic;
505 : int s;
506 :
507 0 : s = splnet();
508 0 : if (++ni->ni_sa_query_count >= 3) {
509 0 : ni->ni_flags &= ~IEEE80211_NODE_SA_QUERY;
510 0 : ni->ni_flags |= IEEE80211_NODE_SA_QUERY_FAILED;
511 0 : } else /* retry SA Query Request */
512 0 : ieee80211_sa_query_request(ic, ni);
513 0 : splx(s);
514 0 : }
515 :
516 : /*
517 : * Request that a SA Query Request frame be sent to a specified peer STA
518 : * to which the STA is associated.
519 : */
520 : void
521 0 : ieee80211_sa_query_request(struct ieee80211com *ic, struct ieee80211_node *ni)
522 : {
523 : /* MLME-SAQuery.request */
524 :
525 0 : if (!(ni->ni_flags & IEEE80211_NODE_SA_QUERY)) {
526 0 : ni->ni_flags |= IEEE80211_NODE_SA_QUERY;
527 0 : ni->ni_flags &= ~IEEE80211_NODE_SA_QUERY_FAILED;
528 0 : ni->ni_sa_query_count = 0;
529 0 : }
530 : /* generate new Transaction Identifier */
531 0 : ni->ni_sa_query_trid++;
532 :
533 : /* send SA Query Request */
534 0 : IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_SA_QUERY,
535 : IEEE80211_ACTION_SA_QUERY_REQ, 0);
536 0 : timeout_add_msec(&ni->ni_sa_query_to, 10);
537 0 : }
538 : #endif /* IEEE80211_STA_ONLY */
539 :
540 : void
541 0 : ieee80211_ht_negotiate(struct ieee80211com *ic, struct ieee80211_node *ni)
542 : {
543 : int i;
544 :
545 0 : ni->ni_flags &= ~IEEE80211_NODE_HT;
546 :
547 : /* Check if we support HT. */
548 0 : if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) == 0)
549 0 : return;
550 :
551 : /* Check if HT support has been explicitly disabled. */
552 0 : if ((ic->ic_flags & IEEE80211_F_HTON) == 0)
553 0 : return;
554 :
555 : /*
556 : * Check if the peer supports HT.
557 : * Require at least one of the mandatory MCS.
558 : * MCS 0-7 are mandatory but some APs have particular MCS disabled.
559 : */
560 0 : if (!ieee80211_node_supports_ht(ni)) {
561 0 : ic->ic_stats.is_ht_nego_no_mandatory_mcs++;
562 0 : return;
563 : }
564 :
565 0 : if (ic->ic_opmode == IEEE80211_M_STA) {
566 : /* We must support the AP's basic MCS set. */
567 0 : for (i = 0; i < IEEE80211_HT_NUM_MCS; i++) {
568 0 : if (isset(ni->ni_basic_mcs, i) &&
569 0 : !isset(ic->ic_sup_mcs, i)) {
570 0 : ic->ic_stats.is_ht_nego_no_basic_mcs++;
571 0 : return;
572 : }
573 : }
574 : }
575 :
576 : /*
577 : * Don't allow group cipher (includes WEP) or TKIP
578 : * for pairwise encryption (see 802.11-2012 11.1.6).
579 : */
580 0 : if (ic->ic_flags & IEEE80211_F_WEPON) {
581 0 : ic->ic_stats.is_ht_nego_bad_crypto++;
582 0 : return;
583 : }
584 0 : if ((ic->ic_flags & IEEE80211_F_RSNON) &&
585 0 : (ni->ni_rsnciphers & IEEE80211_CIPHER_USEGROUP ||
586 0 : ni->ni_rsnciphers & IEEE80211_CIPHER_TKIP)) {
587 0 : ic->ic_stats.is_ht_nego_bad_crypto++;
588 0 : return;
589 : }
590 :
591 0 : ni->ni_flags |= IEEE80211_NODE_HT;
592 0 : }
593 :
594 : void
595 0 : ieee80211_tx_ba_timeout(void *arg)
596 : {
597 0 : struct ieee80211_tx_ba *ba = arg;
598 0 : struct ieee80211_node *ni = ba->ba_ni;
599 0 : struct ieee80211com *ic = ni->ni_ic;
600 : u_int8_t tid;
601 : int s;
602 :
603 0 : ic->ic_stats.is_ht_tx_ba_timeout++;
604 :
605 0 : s = splnet();
606 0 : if (ba->ba_state == IEEE80211_BA_REQUESTED) {
607 : /* MLME-ADDBA.confirm(TIMEOUT) */
608 0 : ba->ba_state = IEEE80211_BA_INIT;
609 :
610 0 : } else if (ba->ba_state == IEEE80211_BA_AGREED) {
611 : /* Block Ack inactivity timeout */
612 0 : tid = ((caddr_t)ba - (caddr_t)ni->ni_tx_ba) / sizeof(*ba);
613 0 : ieee80211_delba_request(ic, ni, IEEE80211_REASON_TIMEOUT,
614 : 1, tid);
615 0 : }
616 0 : splx(s);
617 0 : }
618 :
619 : void
620 0 : ieee80211_rx_ba_timeout(void *arg)
621 : {
622 0 : struct ieee80211_rx_ba *ba = arg;
623 0 : struct ieee80211_node *ni = ba->ba_ni;
624 0 : struct ieee80211com *ic = ni->ni_ic;
625 : u_int8_t tid;
626 : int s;
627 :
628 0 : ic->ic_stats.is_ht_rx_ba_timeout++;
629 :
630 0 : s = splnet();
631 :
632 : /* Block Ack inactivity timeout */
633 0 : tid = ((caddr_t)ba - (caddr_t)ni->ni_rx_ba) / sizeof(*ba);
634 0 : ieee80211_delba_request(ic, ni, IEEE80211_REASON_TIMEOUT, 0, tid);
635 :
636 0 : splx(s);
637 0 : }
638 :
639 : /*
640 : * Request initiation of Block Ack with the specified peer.
641 : */
642 : int
643 0 : ieee80211_addba_request(struct ieee80211com *ic, struct ieee80211_node *ni,
644 : u_int16_t ssn, u_int8_t tid)
645 : {
646 0 : struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];
647 :
648 : /* MLME-ADDBA.request */
649 :
650 : /* setup Block Ack */
651 0 : ba->ba_state = IEEE80211_BA_REQUESTED;
652 0 : ba->ba_token = ic->ic_dialog_token++;
653 0 : ba->ba_timeout_val = 0;
654 0 : timeout_set(&ba->ba_to, ieee80211_tx_ba_timeout, ba);
655 0 : ba->ba_winsize = IEEE80211_BA_MAX_WINSZ;
656 0 : ba->ba_winstart = ssn;
657 0 : ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
658 0 : ba->ba_params =
659 0 : (ba->ba_winsize << IEEE80211_ADDBA_BUFSZ_SHIFT) |
660 0 : (tid << IEEE80211_ADDBA_TID_SHIFT) | IEEE80211_ADDBA_AMSDU;
661 0 : if ((ic->ic_htcaps & IEEE80211_HTCAP_DELAYEDBA) == 0)
662 : /* immediate BA */
663 0 : ba->ba_params |= IEEE80211_ADDBA_BA_POLICY;
664 :
665 0 : timeout_add_sec(&ba->ba_to, 1); /* dot11ADDBAResponseTimeout */
666 0 : IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,
667 : IEEE80211_ACTION_ADDBA_REQ, tid);
668 0 : return 0;
669 : }
670 :
671 : /*
672 : * Request the deletion of Block Ack with a peer.
673 : */
674 : void
675 0 : ieee80211_delba_request(struct ieee80211com *ic, struct ieee80211_node *ni,
676 : u_int16_t reason, u_int8_t dir, u_int8_t tid)
677 : {
678 : /* MLME-DELBA.request */
679 :
680 : /* transmit a DELBA frame */
681 0 : IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,
682 : IEEE80211_ACTION_DELBA, reason << 16 | dir << 8 | tid);
683 0 : if (dir) {
684 : /* MLME-DELBA.confirm(Originator) */
685 0 : struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];
686 :
687 0 : if (ic->ic_ampdu_tx_stop != NULL)
688 0 : ic->ic_ampdu_tx_stop(ic, ni, tid);
689 :
690 0 : ba->ba_state = IEEE80211_BA_INIT;
691 : /* stop Block Ack inactivity timer */
692 0 : timeout_del(&ba->ba_to);
693 0 : } else {
694 : /* MLME-DELBA.confirm(Recipient) */
695 0 : struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
696 : int i;
697 :
698 0 : if (ic->ic_ampdu_rx_stop != NULL)
699 0 : ic->ic_ampdu_rx_stop(ic, ni, tid);
700 :
701 0 : ba->ba_state = IEEE80211_BA_INIT;
702 : /* stop Block Ack inactivity timer */
703 0 : timeout_del(&ba->ba_to);
704 0 : timeout_del(&ba->ba_gap_to);
705 :
706 0 : if (ba->ba_buf != NULL) {
707 : /* free all MSDUs stored in reordering buffer */
708 0 : for (i = 0; i < IEEE80211_BA_MAX_WINSZ; i++)
709 0 : m_freem(ba->ba_buf[i].m);
710 : /* free reordering buffer */
711 0 : free(ba->ba_buf, M_DEVBUF,
712 : IEEE80211_BA_MAX_WINSZ * sizeof(*ba->ba_buf));
713 0 : ba->ba_buf = NULL;
714 0 : }
715 : }
716 0 : }
717 :
718 : #ifndef IEEE80211_STA_ONLY
719 : void
720 0 : ieee80211_auth_open_confirm(struct ieee80211com *ic,
721 : struct ieee80211_node *ni, uint16_t seq)
722 : {
723 0 : struct ifnet *ifp = &ic->ic_if;
724 :
725 0 : IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
726 0 : if (ifp->if_flags & IFF_DEBUG)
727 0 : printf("%s: station %s %s authenticated (open)\n",
728 0 : ifp->if_xname,
729 0 : ether_sprintf((u_int8_t *)ni->ni_macaddr),
730 0 : ni->ni_state != IEEE80211_STA_CACHE ?
731 : "newly" : "already");
732 0 : ieee80211_node_newstate(ni, IEEE80211_STA_AUTH);
733 0 : }
734 : #endif
735 :
736 : void
737 0 : ieee80211_try_another_bss(struct ieee80211com *ic)
738 : {
739 : struct ieee80211_node *curbs, *selbs;
740 0 : struct ifnet *ifp = &ic->ic_if;
741 :
742 : /* Don't select our current AP again. */
743 0 : curbs = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
744 0 : if (curbs) {
745 0 : curbs->ni_fails++;
746 0 : ieee80211_node_newstate(curbs, IEEE80211_STA_CACHE);
747 0 : }
748 :
749 : /* Try a different AP from the same ESS if available. */
750 0 : if (ic->ic_caps & IEEE80211_C_SCANALLBAND) {
751 : /*
752 : * Make sure we will consider APs on all bands during
753 : * access point selection in ieee80211_node_choose_bss().
754 : * During multi-band scans, our previous AP may be trying
755 : * to steer us onto another band by denying authentication.
756 : */
757 0 : ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
758 0 : }
759 0 : selbs = ieee80211_node_choose_bss(ic, 0, NULL);
760 0 : if (selbs == NULL)
761 0 : return;
762 :
763 : /* Should not happen but seriously, don't try the same AP again. */
764 0 : if (memcmp(selbs->ni_macaddr, ic->ic_bss->ni_macaddr,
765 0 : IEEE80211_NWID_LEN) == 0)
766 0 : return;
767 :
768 0 : if (ifp->if_flags & IFF_DEBUG)
769 0 : printf("%s: trying AP %s on channel %d instead\n",
770 0 : ifp->if_xname, ether_sprintf(selbs->ni_macaddr),
771 0 : ieee80211_chan2ieee(ic, selbs->ni_chan));
772 :
773 : /* Triggers an AUTH->AUTH transition, avoiding another SCAN. */
774 0 : ieee80211_node_join_bss(ic, selbs);
775 0 : }
776 :
777 : void
778 0 : ieee80211_auth_open(struct ieee80211com *ic, const struct ieee80211_frame *wh,
779 : struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi, u_int16_t seq,
780 : u_int16_t status)
781 : {
782 0 : struct ifnet *ifp = &ic->ic_if;
783 0 : switch (ic->ic_opmode) {
784 : #ifndef IEEE80211_STA_ONLY
785 : case IEEE80211_M_IBSS:
786 0 : if (ic->ic_state != IEEE80211_S_RUN ||
787 0 : seq != IEEE80211_AUTH_OPEN_REQUEST) {
788 : DPRINTF(("discard auth from %s; state %u, seq %u\n",
789 : ether_sprintf((u_int8_t *)wh->i_addr2),
790 : ic->ic_state, seq));
791 0 : ic->ic_stats.is_rx_bad_auth++;
792 0 : return;
793 : }
794 0 : ieee80211_new_state(ic, IEEE80211_S_AUTH,
795 : wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
796 :
797 : /* In IBSS mode no (re)association frames are sent. */
798 0 : if (ic->ic_flags & IEEE80211_F_RSNON)
799 0 : ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
800 : break;
801 :
802 : case IEEE80211_M_AHDEMO:
803 : /* should not come here */
804 : break;
805 :
806 : case IEEE80211_M_HOSTAP:
807 0 : if (ic->ic_state != IEEE80211_S_RUN ||
808 0 : seq != IEEE80211_AUTH_OPEN_REQUEST) {
809 : DPRINTF(("discard auth from %s; state %u, seq %u\n",
810 : ether_sprintf((u_int8_t *)wh->i_addr2),
811 : ic->ic_state, seq));
812 0 : ic->ic_stats.is_rx_bad_auth++;
813 0 : return;
814 : }
815 0 : if (ni == ic->ic_bss) {
816 0 : ni = ieee80211_find_node(ic, wh->i_addr2);
817 0 : if (ni == NULL)
818 0 : ni = ieee80211_alloc_node(ic, wh->i_addr2);
819 0 : if (ni == NULL) {
820 0 : return;
821 : }
822 0 : IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
823 0 : ni->ni_rssi = rxi->rxi_rssi;
824 0 : ni->ni_rstamp = rxi->rxi_tstamp;
825 0 : ni->ni_chan = ic->ic_bss->ni_chan;
826 0 : }
827 :
828 : /*
829 : * Drivers may want to set up state before confirming.
830 : * In which case this returns EBUSY and the driver will
831 : * later call ieee80211_auth_open_confirm() by itself.
832 : */
833 0 : if (ic->ic_newauth && ic->ic_newauth(ic, ni,
834 0 : ni->ni_state != IEEE80211_STA_CACHE, seq) != 0)
835 : break;
836 0 : ieee80211_auth_open_confirm(ic, ni, seq);
837 0 : break;
838 : #endif /* IEEE80211_STA_ONLY */
839 :
840 : case IEEE80211_M_STA:
841 0 : if (ic->ic_state != IEEE80211_S_AUTH ||
842 0 : seq != IEEE80211_AUTH_OPEN_RESPONSE) {
843 0 : ic->ic_stats.is_rx_bad_auth++;
844 : DPRINTF(("discard auth from %s; state %u, seq %u\n",
845 : ether_sprintf((u_int8_t *)wh->i_addr2),
846 : ic->ic_state, seq));
847 0 : return;
848 : }
849 0 : if (ic->ic_flags & IEEE80211_F_RSNON) {
850 : /* XXX not here! */
851 0 : ic->ic_bss->ni_flags &= ~IEEE80211_NODE_TXRXPROT;
852 0 : ic->ic_bss->ni_port_valid = 0;
853 0 : ic->ic_bss->ni_replaycnt_ok = 0;
854 0 : (*ic->ic_delete_key)(ic, ic->ic_bss,
855 0 : &ic->ic_bss->ni_pairwise_key);
856 0 : }
857 0 : if (status != 0) {
858 0 : if (ifp->if_flags & IFF_DEBUG)
859 0 : printf("%s: open authentication failed "
860 0 : "(status %d) for %s\n", ifp->if_xname,
861 : status,
862 0 : ether_sprintf((u_int8_t *)wh->i_addr3));
863 0 : if (ni != ic->ic_bss)
864 0 : ni->ni_fails++;
865 : else
866 0 : ieee80211_try_another_bss(ic);
867 0 : ic->ic_stats.is_rx_auth_fail++;
868 0 : return;
869 : }
870 0 : ieee80211_new_state(ic, IEEE80211_S_ASSOC,
871 : wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
872 0 : break;
873 : default:
874 : break;
875 : }
876 0 : }
877 :
878 : void
879 0 : ieee80211_set_beacon_miss_threshold(struct ieee80211com *ic)
880 : {
881 0 : struct ifnet *ifp = &ic->ic_if;
882 :
883 : /*
884 : * Scale the missed beacon counter threshold to the AP's actual
885 : * beacon interval. Give the AP at least 700 ms to time out and
886 : * round up to ensure that at least one beacon may be missed.
887 : */
888 0 : int btimeout = MIN(7 * ic->ic_bss->ni_intval, 700);
889 0 : btimeout = MAX(btimeout, 2 * ic->ic_bss->ni_intval);
890 0 : if (ic->ic_bss->ni_intval > 0) /* don't crash if interval is bogus */
891 0 : ic->ic_bmissthres = btimeout / ic->ic_bss->ni_intval;
892 :
893 0 : if (ifp->if_flags & IFF_DEBUG)
894 0 : printf("%s: missed beacon threshold set to %d beacons, "
895 0 : "beacon interval is %u TU\n", ifp->if_xname,
896 0 : ic->ic_bmissthres, ic->ic_bss->ni_intval);
897 0 : }
898 :
899 : int
900 0 : ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
901 : int mgt)
902 : {
903 0 : struct ifnet *ifp = &ic->ic_if;
904 : struct ieee80211_node *ni;
905 : enum ieee80211_state ostate;
906 : u_int rate;
907 : #ifndef IEEE80211_STA_ONLY
908 : int s;
909 : #endif
910 :
911 0 : ostate = ic->ic_state;
912 0 : if (ifp->if_flags & IFF_DEBUG)
913 0 : printf("%s: %s -> %s\n", ifp->if_xname,
914 0 : ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
915 0 : ic->ic_state = nstate; /* state transition */
916 0 : ni = ic->ic_bss; /* NB: no reference held */
917 0 : ieee80211_set_link_state(ic, LINK_STATE_DOWN);
918 0 : ic->ic_xflags &= ~IEEE80211_F_TX_MGMT_ONLY;
919 0 : switch (nstate) {
920 : case IEEE80211_S_INIT:
921 : /*
922 : * If mgt = -1, driver is already partway down, so do
923 : * not send management frames.
924 : */
925 0 : switch (ostate) {
926 : case IEEE80211_S_INIT:
927 : break;
928 : case IEEE80211_S_RUN:
929 0 : if (mgt == -1)
930 : goto justcleanup;
931 0 : switch (ic->ic_opmode) {
932 : case IEEE80211_M_STA:
933 0 : IEEE80211_SEND_MGMT(ic, ni,
934 : IEEE80211_FC0_SUBTYPE_DISASSOC,
935 : IEEE80211_REASON_ASSOC_LEAVE);
936 0 : break;
937 : #ifndef IEEE80211_STA_ONLY
938 : case IEEE80211_M_HOSTAP:
939 0 : s = splnet();
940 0 : RBT_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
941 0 : if (ni->ni_state != IEEE80211_STA_ASSOC)
942 : continue;
943 0 : IEEE80211_SEND_MGMT(ic, ni,
944 : IEEE80211_FC0_SUBTYPE_DISASSOC,
945 : IEEE80211_REASON_ASSOC_LEAVE);
946 0 : }
947 0 : splx(s);
948 0 : break;
949 : #endif
950 : default:
951 : break;
952 : }
953 : /* FALLTHROUGH */
954 : case IEEE80211_S_ASSOC:
955 0 : if (mgt == -1)
956 : goto justcleanup;
957 0 : switch (ic->ic_opmode) {
958 : case IEEE80211_M_STA:
959 0 : IEEE80211_SEND_MGMT(ic, ni,
960 : IEEE80211_FC0_SUBTYPE_DEAUTH,
961 : IEEE80211_REASON_AUTH_LEAVE);
962 0 : break;
963 : #ifndef IEEE80211_STA_ONLY
964 : case IEEE80211_M_HOSTAP:
965 0 : s = splnet();
966 0 : RBT_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
967 0 : IEEE80211_SEND_MGMT(ic, ni,
968 : IEEE80211_FC0_SUBTYPE_DEAUTH,
969 : IEEE80211_REASON_AUTH_LEAVE);
970 : }
971 0 : splx(s);
972 0 : break;
973 : #endif
974 : default:
975 : break;
976 : }
977 : /* FALLTHROUGH */
978 : case IEEE80211_S_AUTH:
979 : case IEEE80211_S_SCAN:
980 : justcleanup:
981 : #ifndef IEEE80211_STA_ONLY
982 0 : if (ic->ic_opmode == IEEE80211_M_HOSTAP)
983 0 : timeout_del(&ic->ic_rsn_timeout);
984 : #endif
985 0 : timeout_del(&ic->ic_bgscan_timeout);
986 0 : ic->ic_bgscan_fail = 0;
987 0 : ic->ic_mgt_timer = 0;
988 0 : mq_purge(&ic->ic_mgtq);
989 0 : mq_purge(&ic->ic_pwrsaveq);
990 0 : ieee80211_free_allnodes(ic, 1);
991 0 : break;
992 : }
993 0 : ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
994 0 : if (ic->ic_flags & IEEE80211_F_RSNON)
995 0 : ieee80211_crypto_clear_groupkeys(ic);
996 : break;
997 : case IEEE80211_S_SCAN:
998 0 : ic->ic_flags &= ~IEEE80211_F_SIBSS;
999 : /* initialize bss for probe request */
1000 0 : IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);
1001 0 : IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);
1002 0 : ni->ni_rates = ic->ic_sup_rates[
1003 0 : ieee80211_chan2mode(ic, ni->ni_chan)];
1004 0 : ni->ni_associd = 0;
1005 0 : ni->ni_rstamp = 0;
1006 0 : ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
1007 0 : if (ic->ic_flags & IEEE80211_F_RSNON)
1008 0 : ieee80211_crypto_clear_groupkeys(ic);
1009 0 : switch (ostate) {
1010 : case IEEE80211_S_INIT:
1011 : #ifndef IEEE80211_STA_ONLY
1012 0 : if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1013 0 : ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1014 : /*
1015 : * AP operation and we already have a channel;
1016 : * bypass the scan and startup immediately.
1017 : */
1018 0 : ieee80211_create_ibss(ic, ic->ic_des_chan);
1019 0 : } else
1020 : #endif
1021 0 : ieee80211_begin_scan(ifp);
1022 : break;
1023 : case IEEE80211_S_SCAN:
1024 : /* scan next */
1025 0 : if (ic->ic_flags & IEEE80211_F_ASCAN) {
1026 0 : IEEE80211_SEND_MGMT(ic, ni,
1027 : IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
1028 0 : }
1029 : break;
1030 : case IEEE80211_S_RUN:
1031 : /* beacon miss */
1032 0 : if (ifp->if_flags & IFF_DEBUG) {
1033 : /* XXX bssid clobbered above */
1034 0 : printf("%s: no recent beacons from %s;"
1035 0 : " rescanning\n", ifp->if_xname,
1036 0 : ether_sprintf(ic->ic_bss->ni_bssid));
1037 0 : }
1038 0 : timeout_del(&ic->ic_bgscan_timeout);
1039 0 : ic->ic_bgscan_fail = 0;
1040 0 : ieee80211_free_allnodes(ic, 1);
1041 : /* FALLTHROUGH */
1042 : case IEEE80211_S_AUTH:
1043 : case IEEE80211_S_ASSOC:
1044 : /* timeout restart scan */
1045 0 : ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
1046 0 : if (ni != NULL)
1047 0 : ni->ni_fails++;
1048 0 : ieee80211_begin_scan(ifp);
1049 0 : break;
1050 : }
1051 : break;
1052 : case IEEE80211_S_AUTH:
1053 0 : ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
1054 0 : if (ic->ic_flags & IEEE80211_F_RSNON)
1055 0 : ieee80211_crypto_clear_groupkeys(ic);
1056 0 : switch (ostate) {
1057 : case IEEE80211_S_INIT:
1058 0 : if (ifp->if_flags & IFF_DEBUG)
1059 0 : printf("%s: invalid transition %s -> %s\n",
1060 0 : ifp->if_xname, ieee80211_state_name[ostate],
1061 0 : ieee80211_state_name[nstate]);
1062 : break;
1063 : case IEEE80211_S_SCAN:
1064 0 : IEEE80211_SEND_MGMT(ic, ni,
1065 : IEEE80211_FC0_SUBTYPE_AUTH, 1);
1066 0 : break;
1067 : case IEEE80211_S_AUTH:
1068 : case IEEE80211_S_ASSOC:
1069 0 : switch (mgt) {
1070 : case IEEE80211_FC0_SUBTYPE_AUTH:
1071 0 : if (ic->ic_opmode == IEEE80211_M_STA) {
1072 0 : IEEE80211_SEND_MGMT(ic, ni,
1073 : IEEE80211_FC0_SUBTYPE_AUTH,
1074 : IEEE80211_AUTH_OPEN_REQUEST);
1075 0 : }
1076 : break;
1077 : case IEEE80211_FC0_SUBTYPE_DEAUTH:
1078 : /* ignore and retry scan on timeout */
1079 : break;
1080 : }
1081 : break;
1082 : case IEEE80211_S_RUN:
1083 0 : timeout_del(&ic->ic_bgscan_timeout);
1084 0 : ic->ic_bgscan_fail = 0;
1085 0 : switch (mgt) {
1086 : case IEEE80211_FC0_SUBTYPE_AUTH:
1087 0 : IEEE80211_SEND_MGMT(ic, ni,
1088 : IEEE80211_FC0_SUBTYPE_AUTH, 2);
1089 0 : ic->ic_state = ostate; /* stay RUN */
1090 0 : break;
1091 : case IEEE80211_FC0_SUBTYPE_DEAUTH:
1092 : /* try to reauth */
1093 0 : IEEE80211_SEND_MGMT(ic, ni,
1094 : IEEE80211_FC0_SUBTYPE_AUTH, 1);
1095 0 : break;
1096 : }
1097 : break;
1098 : }
1099 : break;
1100 : case IEEE80211_S_ASSOC:
1101 0 : switch (ostate) {
1102 : case IEEE80211_S_INIT:
1103 : case IEEE80211_S_SCAN:
1104 : case IEEE80211_S_ASSOC:
1105 0 : if (ifp->if_flags & IFF_DEBUG)
1106 0 : printf("%s: invalid transition %s -> %s\n",
1107 0 : ifp->if_xname, ieee80211_state_name[ostate],
1108 0 : ieee80211_state_name[nstate]);
1109 : break;
1110 : case IEEE80211_S_AUTH:
1111 0 : IEEE80211_SEND_MGMT(ic, ni,
1112 : IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
1113 0 : break;
1114 : case IEEE80211_S_RUN:
1115 0 : IEEE80211_SEND_MGMT(ic, ni,
1116 : IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
1117 0 : break;
1118 : }
1119 : break;
1120 : case IEEE80211_S_RUN:
1121 0 : switch (ostate) {
1122 : case IEEE80211_S_INIT:
1123 0 : if (ic->ic_opmode == IEEE80211_M_MONITOR)
1124 : break;
1125 : case IEEE80211_S_AUTH:
1126 : case IEEE80211_S_RUN:
1127 0 : if (ifp->if_flags & IFF_DEBUG)
1128 0 : printf("%s: invalid transition %s -> %s\n",
1129 0 : ifp->if_xname, ieee80211_state_name[ostate],
1130 0 : ieee80211_state_name[nstate]);
1131 : break;
1132 : case IEEE80211_S_SCAN: /* adhoc/hostap mode */
1133 : case IEEE80211_S_ASSOC: /* infra mode */
1134 0 : if (ni->ni_txrate >= ni->ni_rates.rs_nrates)
1135 0 : panic("%s: bogus xmit rate %u setup",
1136 : __func__, ni->ni_txrate);
1137 0 : if (ifp->if_flags & IFF_DEBUG) {
1138 0 : printf("%s: %s with %s ssid ",
1139 0 : ifp->if_xname,
1140 0 : ic->ic_opmode == IEEE80211_M_STA ?
1141 : "associated" : "synchronized",
1142 0 : ether_sprintf(ni->ni_bssid));
1143 0 : ieee80211_print_essid(ic->ic_bss->ni_essid,
1144 0 : ni->ni_esslen);
1145 0 : rate = ni->ni_rates.rs_rates[ni->ni_txrate] &
1146 : IEEE80211_RATE_VAL;
1147 0 : printf(" channel %d",
1148 0 : ieee80211_chan2ieee(ic, ni->ni_chan));
1149 0 : if (ni->ni_flags & IEEE80211_NODE_HT)
1150 0 : printf(" start MCS %u", ni->ni_txmcs);
1151 : else
1152 0 : printf(" start %u%sMb",
1153 0 : rate / 2, (rate & 1) ? ".5" : "");
1154 0 : printf(" %s preamble %s slot time%s%s\n",
1155 0 : (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
1156 : "short" : "long",
1157 0 : (ic->ic_flags & IEEE80211_F_SHSLOT) ?
1158 : "short" : "long",
1159 0 : (ic->ic_flags & IEEE80211_F_USEPROT) ?
1160 : " protection enabled" : "",
1161 0 : (ni->ni_flags & IEEE80211_NODE_HT) ?
1162 : " HT enabled" : "");
1163 0 : }
1164 0 : if (!(ic->ic_flags & IEEE80211_F_RSNON)) {
1165 : /*
1166 : * NB: When RSN is enabled, we defer setting
1167 : * the link up until the port is valid.
1168 : */
1169 0 : ieee80211_set_link_state(ic, LINK_STATE_UP);
1170 0 : }
1171 0 : ic->ic_mgt_timer = 0;
1172 0 : ieee80211_set_beacon_miss_threshold(ic);
1173 0 : if_start(ifp);
1174 0 : break;
1175 : }
1176 : break;
1177 : }
1178 0 : return 0;
1179 : }
1180 :
1181 : void
1182 0 : ieee80211_set_link_state(struct ieee80211com *ic, int nstate)
1183 : {
1184 0 : struct ifnet *ifp = &ic->ic_if;
1185 :
1186 0 : switch (ic->ic_opmode) {
1187 : #ifndef IEEE80211_STA_ONLY
1188 : case IEEE80211_M_IBSS:
1189 : case IEEE80211_M_HOSTAP:
1190 : nstate = LINK_STATE_UNKNOWN;
1191 0 : break;
1192 : #endif
1193 : case IEEE80211_M_MONITOR:
1194 : nstate = LINK_STATE_DOWN;
1195 0 : break;
1196 : default:
1197 : break;
1198 : }
1199 0 : if (nstate != ifp->if_link_state) {
1200 0 : ifp->if_link_state = nstate;
1201 0 : if_link_state_change(ifp);
1202 0 : }
1203 0 : }
|