ieee80211.c revision 1.20 1 /* $NetBSD: ieee80211.c,v 1.20 2004/07/16 02:36:58 dyoung Exp $ */
2 /*-
3 * Copyright (c) 2001 Atsushi Onoe
4 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/cdefs.h>
35 #ifdef __FreeBSD__
36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211.c,v 1.11 2004/04/02 20:19:20 sam Exp $");
37 #else
38 __KERNEL_RCSID(0, "$NetBSD: ieee80211.c,v 1.20 2004/07/16 02:36:58 dyoung Exp $");
39 #endif
40
41 /*
42 * IEEE 802.11 generic handler
43 */
44
45 #include "opt_inet.h"
46 #include "bpfilter.h"
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/mbuf.h>
51 #include <sys/malloc.h>
52 #include <sys/kernel.h>
53 #include <sys/socket.h>
54 #include <sys/sockio.h>
55 #include <sys/endian.h>
56 #include <sys/errno.h>
57 #ifdef __FreeBSD__
58 #include <sys/bus.h>
59 #endif
60 #include <sys/proc.h>
61 #include <sys/sysctl.h>
62
63 #ifdef __FreeBSD__
64 #include <machine/atomic.h>
65 #endif
66
67 #include <net/if.h>
68 #include <net/if_dl.h>
69 #include <net/if_media.h>
70 #include <net/if_arp.h>
71 #ifdef __FreeBSD__
72 #include <net/ethernet.h>
73 #else
74 #include <net/if_ether.h>
75 #endif
76 #include <net/if_llc.h>
77
78 #include <net80211/ieee80211_var.h>
79 #include <net80211/ieee80211_compat.h>
80
81 #include <net/bpf.h>
82
83 #ifdef INET
84 #include <netinet/in.h>
85 #ifdef __FreeBSD__
86 #include <netinet/if_ether.h>
87 #else
88 #include <net/if_ether.h>
89 #endif
90 #endif
91
92 #ifdef IEEE80211_DEBUG
93 int ieee80211_debug = 0;
94 #ifdef __NetBSD__
95 static int ieee80211_debug_nodenum;
96 #endif /* __NetBSD__ */
97
98 #ifdef __FreeBSD__
99 SYSCTL_INT(_debug, OID_AUTO, ieee80211, CTLFLAG_RW, &ieee80211_debug,
100 0, "IEEE 802.11 media debugging printfs");
101 #endif
102 #endif
103
104 int ieee80211_inact_max = IEEE80211_INACT_MAX;
105 static int ieee80211_inact_max_nodenum;
106
107 struct ieee80211com_head ieee80211com_head =
108 LIST_HEAD_INITIALIZER(ieee80211com_head);
109
110 static void ieee80211_set11gbasicrates(struct ieee80211_rateset *,
111 enum ieee80211_phymode);
112
113 static const char *ieee80211_phymode_name[] = {
114 "auto", /* IEEE80211_MODE_AUTO */
115 "11a", /* IEEE80211_MODE_11A */
116 "11b", /* IEEE80211_MODE_11B */
117 "11g", /* IEEE80211_MODE_11G */
118 "FH", /* IEEE80211_MODE_FH */
119 "turbo", /* IEEE80211_MODE_TURBO */
120 };
121
122 void
123 ieee80211_ifattach(struct ifnet *ifp)
124 {
125 struct ieee80211com *ic = (void *)ifp;
126 struct ieee80211_channel *c;
127 int i;
128
129 ether_ifattach(ifp, ic->ic_myaddr);
130 #if NBPFILTER > 0
131 bpfattach2(ifp, DLT_IEEE802_11,
132 sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf);
133 #endif
134 ieee80211_crypto_attach(ifp);
135
136 /*
137 * Fill in 802.11 available channel set, mark
138 * all available channels as active, and pick
139 * a default channel if not already specified.
140 */
141 memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
142 ic->ic_modecaps |= 1<<IEEE80211_MODE_AUTO;
143 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
144 c = &ic->ic_channels[i];
145 if (c->ic_flags) {
146 /*
147 * Verify driver passed us valid data.
148 */
149 if (i != ieee80211_chan2ieee(ic, c)) {
150 if_printf(ifp, "bad channel ignored; "
151 "freq %u flags %x number %u\n",
152 c->ic_freq, c->ic_flags, i);
153 c->ic_flags = 0; /* NB: remove */
154 continue;
155 }
156 setbit(ic->ic_chan_avail, i);
157 /*
158 * Identify mode capabilities.
159 */
160 if (IEEE80211_IS_CHAN_A(c))
161 ic->ic_modecaps |= 1<<IEEE80211_MODE_11A;
162 if (IEEE80211_IS_CHAN_B(c))
163 ic->ic_modecaps |= 1<<IEEE80211_MODE_11B;
164 if (IEEE80211_IS_CHAN_PUREG(c))
165 ic->ic_modecaps |= 1<<IEEE80211_MODE_11G;
166 if (IEEE80211_IS_CHAN_FHSS(c))
167 ic->ic_modecaps |= 1<<IEEE80211_MODE_FH;
168 if (IEEE80211_IS_CHAN_T(c))
169 ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO;
170 }
171 }
172 /* validate ic->ic_curmode */
173 if ((ic->ic_modecaps & (1<<ic->ic_curmode)) == 0)
174 ic->ic_curmode = IEEE80211_MODE_AUTO;
175 ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */
176
177 (void) ieee80211_setmode(ic, ic->ic_curmode);
178
179 if (ic->ic_lintval == 0)
180 ic->ic_lintval = 100; /* default sleep */
181 ic->ic_bmisstimeout = 7*ic->ic_lintval; /* default 7 beacons */
182
183 ieee80211_node_attach(ifp);
184 ieee80211_proto_attach(ifp);
185 }
186
187 void
188 ieee80211_ifdetach(struct ifnet *ifp)
189 {
190 struct ieee80211com *ic = (void *)ifp;
191
192 ieee80211_proto_detach(ifp);
193 ieee80211_crypto_detach(ifp);
194 ieee80211_node_detach(ifp);
195 #ifdef __FreeBSD__
196 ifmedia_removeall(&ic->ic_media);
197 #else
198 ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY);
199 #endif
200 #if NBPFILTER > 0
201 bpfdetach(ifp);
202 #endif
203 ether_ifdetach(ifp);
204 }
205
206 /*
207 * Convert MHz frequency to IEEE channel number.
208 */
209 u_int
210 ieee80211_mhz2ieee(u_int freq, u_int flags)
211 {
212 if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */
213 if (freq == 2484)
214 return 14;
215 if (freq < 2484)
216 return (freq - 2407) / 5;
217 else
218 return 15 + ((freq - 2512) / 20);
219 } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */
220 return (freq - 5000) / 5;
221 } else { /* either, guess */
222 if (freq == 2484)
223 return 14;
224 if (freq < 2484)
225 return (freq - 2407) / 5;
226 if (freq < 5000)
227 return 15 + ((freq - 2512) / 20);
228 return (freq - 5000) / 5;
229 }
230 }
231
232 /*
233 * Convert channel to IEEE channel number.
234 */
235 u_int
236 ieee80211_chan2ieee(struct ieee80211com *ic, struct ieee80211_channel *c)
237 {
238 if (ic->ic_channels <= c && c <= &ic->ic_channels[IEEE80211_CHAN_MAX])
239 return c - ic->ic_channels;
240 else if (c == IEEE80211_CHAN_ANYC)
241 return IEEE80211_CHAN_ANY;
242 else if (c != NULL) {
243 if_printf(&ic->ic_if, "invalid channel freq %u flags %x\n",
244 c->ic_freq, c->ic_flags);
245 return 0; /* XXX */
246 } else {
247 if_printf(&ic->ic_if, "invalid channel (NULL)\n");
248 return 0; /* XXX */
249 }
250 }
251
252 /*
253 * Convert IEEE channel number to MHz frequency.
254 */
255 u_int
256 ieee80211_ieee2mhz(u_int chan, u_int flags)
257 {
258 if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */
259 if (chan == 14)
260 return 2484;
261 if (chan < 14)
262 return 2407 + chan*5;
263 else
264 return 2512 + ((chan-15)*20);
265 } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */
266 return 5000 + (chan*5);
267 } else { /* either, guess */
268 if (chan == 14)
269 return 2484;
270 if (chan < 14) /* 0-13 */
271 return 2407 + chan*5;
272 if (chan < 27) /* 15-26 */
273 return 2512 + ((chan-15)*20);
274 return 5000 + (chan*5);
275 }
276 }
277
278 /*
279 * Setup the media data structures according to the channel and
280 * rate tables. This must be called by the driver after
281 * ieee80211_attach and before most anything else.
282 */
283 void
284 ieee80211_media_init(struct ifnet *ifp,
285 ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
286 {
287 #define ADD(_ic, _s, _o) \
288 ifmedia_add(&(_ic)->ic_media, \
289 IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)
290 struct ieee80211com *ic = (void *)ifp;
291 struct ifmediareq imr;
292 int i, j, mode, rate, maxrate, mword, mopt, r;
293 struct ieee80211_rateset *rs;
294 struct ieee80211_rateset allrates;
295
296 /*
297 * Do late attach work that must wait for any subclass
298 * (i.e. driver) work such as overriding methods.
299 */
300 ieee80211_node_lateattach(ifp);
301
302 /*
303 * Fill in media characteristics.
304 */
305 ifmedia_init(&ic->ic_media, 0, media_change, media_stat);
306 maxrate = 0;
307 memset(&allrates, 0, sizeof(allrates));
308 for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) {
309 static const u_int mopts[] = {
310 IFM_AUTO,
311 IFM_IEEE80211_11A,
312 IFM_IEEE80211_11B,
313 IFM_IEEE80211_11G,
314 IFM_IEEE80211_FH,
315 IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,
316 };
317 if ((ic->ic_modecaps & (1<<mode)) == 0)
318 continue;
319 mopt = mopts[mode];
320 ADD(ic, IFM_AUTO, mopt); /* e.g. 11a auto */
321 if (ic->ic_caps & IEEE80211_C_IBSS)
322 ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC);
323 if (ic->ic_caps & IEEE80211_C_HOSTAP)
324 ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);
325 if (ic->ic_caps & IEEE80211_C_AHDEMO)
326 ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0);
327 if (ic->ic_caps & IEEE80211_C_MONITOR)
328 ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);
329 if (mode == IEEE80211_MODE_AUTO)
330 continue;
331 if_printf(ifp, "%s rates: ", ieee80211_phymode_name[mode]);
332 rs = &ic->ic_sup_rates[mode];
333 for (i = 0; i < rs->rs_nrates; i++) {
334 rate = rs->rs_rates[i];
335 mword = ieee80211_rate2media(ic, rate, mode);
336 if (mword == 0)
337 continue;
338 printf("%s%d%sMbps", (i != 0 ? " " : ""),
339 (rate & IEEE80211_RATE_VAL) / 2,
340 ((rate & 0x1) != 0 ? ".5" : ""));
341 ADD(ic, mword, mopt);
342 if (ic->ic_caps & IEEE80211_C_IBSS)
343 ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC);
344 if (ic->ic_caps & IEEE80211_C_HOSTAP)
345 ADD(ic, mword, mopt | IFM_IEEE80211_HOSTAP);
346 if (ic->ic_caps & IEEE80211_C_AHDEMO)
347 ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0);
348 if (ic->ic_caps & IEEE80211_C_MONITOR)
349 ADD(ic, mword, mopt | IFM_IEEE80211_MONITOR);
350 /*
351 * Add rate to the collection of all rates.
352 */
353 r = rate & IEEE80211_RATE_VAL;
354 for (j = 0; j < allrates.rs_nrates; j++)
355 if (allrates.rs_rates[j] == r)
356 break;
357 if (j == allrates.rs_nrates) {
358 /* unique, add to the set */
359 allrates.rs_rates[j] = r;
360 allrates.rs_nrates++;
361 }
362 rate = (rate & IEEE80211_RATE_VAL) / 2;
363 if (rate > maxrate)
364 maxrate = rate;
365 }
366 printf("\n");
367 }
368 for (i = 0; i < allrates.rs_nrates; i++) {
369 mword = ieee80211_rate2media(ic, allrates.rs_rates[i],
370 IEEE80211_MODE_AUTO);
371 if (mword == 0)
372 continue;
373 mword = IFM_SUBTYPE(mword); /* remove media options */
374 ADD(ic, mword, 0);
375 if (ic->ic_caps & IEEE80211_C_IBSS)
376 ADD(ic, mword, IFM_IEEE80211_ADHOC);
377 if (ic->ic_caps & IEEE80211_C_HOSTAP)
378 ADD(ic, mword, IFM_IEEE80211_HOSTAP);
379 if (ic->ic_caps & IEEE80211_C_AHDEMO)
380 ADD(ic, mword, IFM_IEEE80211_ADHOC | IFM_FLAG0);
381 if (ic->ic_caps & IEEE80211_C_MONITOR)
382 ADD(ic, mword, IFM_IEEE80211_MONITOR);
383 }
384 ieee80211_media_status(ifp, &imr);
385 ifmedia_set(&ic->ic_media, imr.ifm_active);
386
387 if (maxrate)
388 ifp->if_baudrate = IF_Mbps(maxrate);
389
390 if (ic->ic_max_aid == 0)
391 ic->ic_max_aid = IEEE80211_MAX_AID;
392
393 #undef ADD
394 }
395
396 static int
397 findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate)
398 {
399 #define IEEERATE(_ic,_m,_i) \
400 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
401 int i, nrates = ic->ic_sup_rates[mode].rs_nrates;
402 for (i = 0; i < nrates; i++)
403 if (IEEERATE(ic, mode, i) == rate)
404 return i;
405 return -1;
406 #undef IEEERATE
407 }
408
409 /*
410 * Handle a media change request.
411 */
412 int
413 ieee80211_media_change(struct ifnet *ifp)
414 {
415 struct ieee80211com *ic = (void *)ifp;
416 struct ifmedia_entry *ime;
417 enum ieee80211_opmode newopmode;
418 enum ieee80211_phymode newphymode;
419 int i, j, newrate, error = 0;
420
421 ime = ic->ic_media.ifm_cur;
422 /*
423 * First, identify the phy mode.
424 */
425 switch (IFM_MODE(ime->ifm_media)) {
426 case IFM_IEEE80211_11A:
427 newphymode = IEEE80211_MODE_11A;
428 break;
429 case IFM_IEEE80211_11B:
430 newphymode = IEEE80211_MODE_11B;
431 break;
432 case IFM_IEEE80211_11G:
433 newphymode = IEEE80211_MODE_11G;
434 break;
435 case IFM_IEEE80211_FH:
436 newphymode = IEEE80211_MODE_FH;
437 break;
438 case IFM_AUTO:
439 newphymode = IEEE80211_MODE_AUTO;
440 break;
441 default:
442 return EINVAL;
443 }
444 /*
445 * Turbo mode is an ``option''. Eventually it
446 * needs to be applied to 11g too.
447 */
448 if (ime->ifm_media & IFM_IEEE80211_TURBO) {
449 if (newphymode != IEEE80211_MODE_11A)
450 return EINVAL;
451 newphymode = IEEE80211_MODE_TURBO;
452 }
453 /*
454 * Validate requested mode is available.
455 */
456 if ((ic->ic_modecaps & (1<<newphymode)) == 0)
457 return EINVAL;
458
459 /*
460 * Next, the fixed/variable rate.
461 */
462 i = -1;
463 if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) {
464 /*
465 * Convert media subtype to rate.
466 */
467 newrate = ieee80211_media2rate(ime->ifm_media);
468 if (newrate == 0)
469 return EINVAL;
470 /*
471 * Check the rate table for the specified/current phy.
472 */
473 if (newphymode == IEEE80211_MODE_AUTO) {
474 /*
475 * In autoselect mode search for the rate.
476 */
477 for (j = IEEE80211_MODE_11A;
478 j < IEEE80211_MODE_MAX; j++) {
479 if ((ic->ic_modecaps & (1<<j)) == 0)
480 continue;
481 i = findrate(ic, j, newrate);
482 if (i != -1) {
483 /* lock mode too */
484 newphymode = j;
485 break;
486 }
487 }
488 } else {
489 i = findrate(ic, newphymode, newrate);
490 }
491 if (i == -1) /* mode/rate mismatch */
492 return EINVAL;
493 }
494 /* NB: defer rate setting to later */
495
496 /*
497 * Deduce new operating mode but don't install it just yet.
498 */
499 if ((ime->ifm_media & (IFM_IEEE80211_ADHOC|IFM_FLAG0)) ==
500 (IFM_IEEE80211_ADHOC|IFM_FLAG0))
501 newopmode = IEEE80211_M_AHDEMO;
502 else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
503 newopmode = IEEE80211_M_HOSTAP;
504 else if (ime->ifm_media & IFM_IEEE80211_ADHOC)
505 newopmode = IEEE80211_M_IBSS;
506 else if (ime->ifm_media & IFM_IEEE80211_MONITOR)
507 newopmode = IEEE80211_M_MONITOR;
508 else
509 newopmode = IEEE80211_M_STA;
510
511 /*
512 * Autoselect doesn't make sense when operating as an AP.
513 * If no phy mode has been selected, pick one and lock it
514 * down so rate tables can be used in forming beacon frames
515 * and the like.
516 */
517 if (newopmode == IEEE80211_M_HOSTAP &&
518 newphymode == IEEE80211_MODE_AUTO) {
519 for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++)
520 if (ic->ic_modecaps & (1<<j)) {
521 newphymode = j;
522 break;
523 }
524 }
525
526 /*
527 * Handle phy mode change.
528 */
529 if (ic->ic_curmode != newphymode) { /* change phy mode */
530 error = ieee80211_setmode(ic, newphymode);
531 if (error != 0)
532 return error;
533 error = ENETRESET;
534 }
535
536 /*
537 * Committed to changes, install the rate setting.
538 */
539 if (ic->ic_fixed_rate != i) {
540 ic->ic_fixed_rate = i; /* set fixed tx rate */
541 error = ENETRESET;
542 }
543
544 /*
545 * Handle operating mode change.
546 */
547 if (ic->ic_opmode != newopmode) {
548 ic->ic_opmode = newopmode;
549 switch (newopmode) {
550 case IEEE80211_M_AHDEMO:
551 case IEEE80211_M_HOSTAP:
552 case IEEE80211_M_STA:
553 case IEEE80211_M_MONITOR:
554 ic->ic_flags &= ~IEEE80211_F_IBSSON;
555 break;
556 case IEEE80211_M_IBSS:
557 ic->ic_flags |= IEEE80211_F_IBSSON;
558 #ifdef notdef
559 if (ic->ic_curmode == IEEE80211_MODE_11G)
560 ieee80211_set11gbasicrates(
561 &ic->ic_sup_rates[newphymode],
562 IEEE80211_MODE_11B);
563 #endif
564 break;
565 }
566 error = ENETRESET;
567 }
568 #ifdef notdef
569 if (error == 0)
570 ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);
571 #endif
572 return error;
573 }
574
575 void
576 ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
577 {
578 struct ieee80211com *ic = (void *)ifp;
579 struct ieee80211_node *ni = NULL;
580
581 imr->ifm_status = IFM_AVALID;
582 imr->ifm_active = IFM_IEEE80211;
583 if (ic->ic_state == IEEE80211_S_RUN)
584 imr->ifm_status |= IFM_ACTIVE;
585 imr->ifm_active |= IFM_AUTO;
586 switch (ic->ic_opmode) {
587 case IEEE80211_M_STA:
588 ni = ic->ic_bss;
589 /* calculate rate subtype */
590 imr->ifm_active |= ieee80211_rate2media(ic,
591 ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode);
592 break;
593 case IEEE80211_M_IBSS:
594 imr->ifm_active |= IFM_IEEE80211_ADHOC;
595 break;
596 case IEEE80211_M_AHDEMO:
597 /* should not come here */
598 break;
599 case IEEE80211_M_HOSTAP:
600 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
601 break;
602 case IEEE80211_M_MONITOR:
603 imr->ifm_active |= IFM_IEEE80211_MONITOR;
604 break;
605 }
606 switch (ic->ic_curmode) {
607 case IEEE80211_MODE_11A:
608 imr->ifm_active |= IFM_IEEE80211_11A;
609 break;
610 case IEEE80211_MODE_11B:
611 imr->ifm_active |= IFM_IEEE80211_11B;
612 break;
613 case IEEE80211_MODE_11G:
614 imr->ifm_active |= IFM_IEEE80211_11G;
615 break;
616 case IEEE80211_MODE_FH:
617 imr->ifm_active |= IFM_IEEE80211_FH;
618 break;
619 case IEEE80211_MODE_TURBO:
620 imr->ifm_active |= IFM_IEEE80211_11A
621 | IFM_IEEE80211_TURBO;
622 break;
623 }
624 }
625
626 void
627 ieee80211_watchdog(struct ifnet *ifp)
628 {
629 struct ieee80211com *ic = (void *)ifp;
630
631 if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0)
632 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
633 if (ic->ic_inact_timer && --ic->ic_inact_timer == 0)
634 ieee80211_timeout_nodes(ic);
635
636 if (ic->ic_mgt_timer != 0 || ic->ic_inact_timer != 0)
637 ifp->if_timer = 1;
638 }
639
640 /*
641 * Mark the basic rates for the 11g rate table based on the
642 * operating mode. For real 11g we mark all the 11b rates
643 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only
644 * 11b rates. There's also a pseudo 11a-mode used to mark only
645 * the basic OFDM rates.
646 */
647 static void
648 ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode)
649 {
650 static const struct ieee80211_rateset basic[] = {
651 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */
652 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11B */
653 { 7, { 2, 4, 11, 22, 12, 24, 48 } },/* IEEE80211_MODE_11G */
654 { 0 }, /* IEEE80211_MODE_FH */
655 { 0 }, /* IEEE80211_MODE_TURBO */
656 };
657 int i, j;
658
659 for (i = 0; i < rs->rs_nrates; i++) {
660 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
661 for (j = 0; j < basic[mode].rs_nrates; j++)
662 if (basic[mode].rs_rates[j] == rs->rs_rates[i]) {
663 rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
664 break;
665 }
666 }
667 }
668
669 /*
670 * Set the current phy mode and recalculate the active channel
671 * set based on the available channels for this mode. Also
672 * select a new default/current channel if the current one is
673 * inappropriate for this mode.
674 */
675 int
676 ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode)
677 {
678 #define N(a) (sizeof(a) / sizeof(a[0]))
679 static const u_int chanflags[] = {
680 0, /* IEEE80211_MODE_AUTO */
681 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
682 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
683 IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */
684 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
685 IEEE80211_CHAN_T, /* IEEE80211_MODE_TURBO */
686 };
687 struct ieee80211_channel *c;
688 u_int modeflags;
689 int i;
690
691 /* validate new mode */
692 if ((ic->ic_modecaps & (1<<mode)) == 0) {
693 IEEE80211_DPRINTF(("%s: mode %u not supported (caps 0x%x)\n",
694 __func__, mode, ic->ic_modecaps));
695 return EINVAL;
696 }
697
698 /*
699 * Verify at least one channel is present in the available
700 * channel list before committing to the new mode.
701 */
702 IASSERT(mode < N(chanflags), ("Unexpected mode %u", mode));
703 modeflags = chanflags[mode];
704 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
705 c = &ic->ic_channels[i];
706 if (mode == IEEE80211_MODE_AUTO) {
707 /* ignore turbo channels for autoselect */
708 if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0)
709 break;
710 } else {
711 if ((c->ic_flags & modeflags) == modeflags)
712 break;
713 }
714 }
715 if (i > IEEE80211_CHAN_MAX) {
716 IEEE80211_DPRINTF(("%s: no channels found for mode %u\n",
717 __func__, mode));
718 return EINVAL;
719 }
720
721 /*
722 * Calculate the active channel set.
723 */
724 memset(ic->ic_chan_active, 0, sizeof(ic->ic_chan_active));
725 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
726 c = &ic->ic_channels[i];
727 if (mode == IEEE80211_MODE_AUTO) {
728 /* take anything but pure turbo channels */
729 if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0)
730 setbit(ic->ic_chan_active, i);
731 } else {
732 if ((c->ic_flags & modeflags) == modeflags)
733 setbit(ic->ic_chan_active, i);
734 }
735 }
736 /*
737 * If no current/default channel is setup or the current
738 * channel is wrong for the mode then pick the first
739 * available channel from the active list. This is likely
740 * not the right one.
741 */
742 if (ic->ic_ibss_chan == NULL ||
743 isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {
744 for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
745 if (isset(ic->ic_chan_active, i)) {
746 ic->ic_ibss_chan = &ic->ic_channels[i];
747 break;
748 }
749 IASSERT(ic->ic_ibss_chan != NULL &&
750 isset(ic->ic_chan_active,
751 ieee80211_chan2ieee(ic, ic->ic_ibss_chan)),
752 ("Bad IBSS channel %u\n",
753 ieee80211_chan2ieee(ic, ic->ic_ibss_chan)));
754 }
755
756 /*
757 * Set/reset state flags that influence beacon contents, etc.
758 *
759 * XXX what if we have stations already associated???
760 * XXX probably not right for autoselect?
761 */
762 if (ic->ic_caps & IEEE80211_C_SHPREAMBLE)
763 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
764 if (mode == IEEE80211_MODE_11G) {
765 if (ic->ic_caps & IEEE80211_C_SHSLOT)
766 ic->ic_flags |= IEEE80211_F_SHSLOT;
767 ieee80211_set11gbasicrates(&ic->ic_sup_rates[mode],
768 IEEE80211_MODE_11G);
769 } else {
770 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
771 }
772
773 ic->ic_curmode = mode;
774 return 0;
775 #undef N
776 }
777
778 /*
779 * Return the phy mode for with the specified channel so the
780 * caller can select a rate set. This is problematic and the
781 * work here assumes how things work elsewhere in this code.
782 *
783 * XXX never returns turbo modes -dcy
784 */
785 enum ieee80211_phymode
786 ieee80211_chan2mode(struct ieee80211com *ic, struct ieee80211_channel *chan)
787 {
788 /*
789 * NB: this assumes the channel would not be supplied to us
790 * unless it was already compatible with the current mode.
791 */
792 if (ic->ic_curmode != IEEE80211_MODE_AUTO ||
793 chan == IEEE80211_CHAN_ANYC)
794 return ic->ic_curmode;
795 /*
796 * In autoselect mode; deduce a mode based on the channel
797 * characteristics. We assume that turbo-only channels
798 * are not considered when the channel set is constructed.
799 */
800 if (IEEE80211_IS_CHAN_5GHZ(chan))
801 return IEEE80211_MODE_11A;
802 else if (IEEE80211_IS_CHAN_FHSS(chan))
803 return IEEE80211_MODE_FH;
804 else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))
805 return IEEE80211_MODE_11G;
806 else
807 return IEEE80211_MODE_11B;
808 }
809
810 /*
811 * convert IEEE80211 rate value to ifmedia subtype.
812 * ieee80211 rate is in unit of 0.5Mbps.
813 */
814 int
815 ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode mode)
816 {
817 #define N(a) (sizeof(a) / sizeof(a[0]))
818 static const struct {
819 u_int m; /* rate + mode */
820 u_int r; /* if_media rate */
821 } rates[] = {
822 { 2 | IFM_IEEE80211_FH, IFM_IEEE80211_FH1 },
823 { 4 | IFM_IEEE80211_FH, IFM_IEEE80211_FH2 },
824 { 2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 },
825 { 4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 },
826 { 11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 },
827 { 22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 },
828 { 44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 },
829 { 12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 },
830 { 18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 },
831 { 24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 },
832 { 36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 },
833 { 48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 },
834 { 72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 },
835 { 96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 },
836 { 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 },
837 { 2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 },
838 { 4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 },
839 { 11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 },
840 { 22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 },
841 { 12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 },
842 { 18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 },
843 { 24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 },
844 { 36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 },
845 { 48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 },
846 { 72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 },
847 { 96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 },
848 { 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 },
849 /* NB: OFDM72 doesn't realy exist so we don't handle it */
850 };
851 u_int mask, i;
852
853 mask = rate & IEEE80211_RATE_VAL;
854 switch (mode) {
855 case IEEE80211_MODE_11A:
856 case IEEE80211_MODE_TURBO:
857 mask |= IFM_IEEE80211_11A;
858 break;
859 case IEEE80211_MODE_11B:
860 mask |= IFM_IEEE80211_11B;
861 break;
862 case IEEE80211_MODE_FH:
863 mask |= IFM_IEEE80211_FH;
864 break;
865 case IEEE80211_MODE_AUTO:
866 /* NB: ic may be NULL for some drivers */
867 if (ic && ic->ic_phytype == IEEE80211_T_FH) {
868 mask |= IFM_IEEE80211_FH;
869 break;
870 }
871 /* NB: hack, 11g matches both 11b+11a rates */
872 /* fall thru... */
873 case IEEE80211_MODE_11G:
874 mask |= IFM_IEEE80211_11G;
875 break;
876 }
877 for (i = 0; i < N(rates); i++)
878 if (rates[i].m == mask)
879 return rates[i].r;
880 return IFM_AUTO;
881 #undef N
882 }
883
884 int
885 ieee80211_media2rate(int mword)
886 {
887 #define N(a) (sizeof(a) / sizeof(a[0]))
888 int i;
889 static const struct {
890 int subtype;
891 int rate;
892 } ieeerates[] = {
893 { IFM_AUTO, -1 },
894 { IFM_MANUAL, 0 },
895 { IFM_NONE, 0 },
896 { IFM_IEEE80211_FH1, 2 },
897 { IFM_IEEE80211_FH2, 4 },
898 { IFM_IEEE80211_DS1, 2 },
899 { IFM_IEEE80211_DS2, 4 },
900 { IFM_IEEE80211_DS5, 11 },
901 { IFM_IEEE80211_DS11, 22 },
902 { IFM_IEEE80211_DS22, 44 },
903 { IFM_IEEE80211_OFDM6, 12 },
904 { IFM_IEEE80211_OFDM9, 18 },
905 { IFM_IEEE80211_OFDM12, 24 },
906 { IFM_IEEE80211_OFDM18, 36 },
907 { IFM_IEEE80211_OFDM24, 48 },
908 { IFM_IEEE80211_OFDM36, 72 },
909 { IFM_IEEE80211_OFDM48, 96 },
910 { IFM_IEEE80211_OFDM54, 108 },
911 { IFM_IEEE80211_OFDM72, 144 },
912 };
913 for (i = 0; i < N(ieeerates); i++) {
914 if (ieeerates[i].subtype == IFM_SUBTYPE(mword))
915 return ieeerates[i].rate;
916 }
917 return 0;
918 #undef N
919 }
920
921 #ifdef __NetBSD__
922 /* TBD factor with sysctl_ath_verify. */
923 static int
924 sysctl_ieee80211_verify(SYSCTLFN_ARGS)
925 {
926 int error, t;
927 struct sysctlnode node;
928
929 node = *rnode;
930 t = *(int*)rnode->sysctl_data;
931 node.sysctl_data = &t;
932 error = sysctl_lookup(SYSCTLFN_CALL(&node));
933 if (error || newp == NULL)
934 return (error);
935
936 IEEE80211_DPRINTF(("%s: t = %d, nodenum = %d, rnodenum = %d\n",
937 __func__, t, node.sysctl_num, rnode->sysctl_num));
938
939 if (node.sysctl_num == ieee80211_inact_max_nodenum) {
940 if (t < 1)
941 return (EINVAL);
942 t = roundup(t, IEEE80211_INACT_WAIT) / IEEE80211_INACT_WAIT;
943 #ifdef IEEE80211_DEBUG
944 } else if (node.sysctl_num == ieee80211_debug_nodenum) {
945 if (t < 0 || t > 2)
946 return (EINVAL);
947 #endif /* IEEE80211_DEBUG */
948 } else
949 return (EINVAL);
950
951 *(int*)rnode->sysctl_data = t;
952
953 return (0);
954 }
955
956 /*
957 * Setup sysctl(3) MIB, net.ieee80211.*
958 *
959 * TBD condition CTLFLAG_PERMANENT on being an LKM or not
960 */
961 SYSCTL_SETUP(sysctl_ieee80211, "sysctl ieee80211 subtree setup")
962 {
963 int rc;
964 struct sysctlnode *cnode, *rnode;
965
966 if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
967 CTLFLAG_PERMANENT, CTLTYPE_NODE, "net", NULL,
968 NULL, 0, NULL, 0, CTL_NET, CTL_EOL)) != 0)
969 goto err;
970
971 if ((rc = sysctl_createv(clog, 0, &rnode, &rnode,
972 CTLFLAG_PERMANENT, CTLTYPE_NODE, "link",
973 "link-layer statistics and controls",
974 NULL, 0, NULL, 0, PF_LINK, CTL_EOL)) != 0)
975 goto err;
976
977 if ((rc = sysctl_createv(clog, 0, &rnode, &rnode,
978 CTLFLAG_PERMANENT, CTLTYPE_NODE, "ieee80211",
979 "IEEE 802.11 WLAN statistics and controls",
980 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
981 goto err;
982
983 #ifdef IEEE80211_DEBUG
984
985 /* control debugging printfs */
986 if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
987 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
988 "debug", SYSCTL_DESCR("Enable IEEE 802.11 debugging output"),
989 sysctl_ieee80211_verify, 0, &ieee80211_debug, 0,
990 CTL_CREATE, CTL_EOL)) != 0)
991 goto err;
992
993 ieee80211_debug_nodenum = cnode->sysctl_num;
994
995 #endif /* IEEE80211_DEBUG */
996
997 /* control inactivity timer */
998 if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
999 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
1000 "maxinact", SYSCTL_DESCR("Station inactivity timeout"),
1001 sysctl_ieee80211_verify, 0, &ieee80211_inact_max,
1002 0, CTL_CREATE, CTL_EOL)) != 0)
1003 goto err;
1004
1005 ieee80211_inact_max_nodenum = cnode->sysctl_num;
1006
1007 return;
1008 err:
1009 printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
1010 }
1011 #endif /* __NetBSD__ */
1012
1013 #ifdef __FreeBSD__
1014 /*
1015 * Module glue.
1016 *
1017 * NB: the module name is "wlan" for compatibility with NetBSD.
1018 */
1019
1020 static int
1021 ieee80211_modevent(module_t mod, int type, void *unused)
1022 {
1023 switch (type) {
1024 case MOD_LOAD:
1025 if (bootverbose)
1026 printf("wlan: <802.11 Link Layer>\n");
1027 return 0;
1028 case MOD_UNLOAD:
1029 return 0;
1030 }
1031 return EINVAL;
1032 }
1033
1034 static moduledata_t ieee80211_mod = {
1035 "wlan",
1036 ieee80211_modevent,
1037 0
1038 };
1039 DECLARE_MODULE(wlan, ieee80211_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
1040 MODULE_VERSION(wlan, 1);
1041 MODULE_DEPEND(wlan, rc4, 1, 1, 1);
1042 MODULE_DEPEND(wlan, ether, 1, 1, 1);
1043 #endif
1044