This source file includes following definitions.
- ieee80211_proto_attach
- ieee80211_proto_detach
- ieee80211_print_essid
- ieee80211_dump_pkt
- ieee80211_fix_rate
- ieee80211_reset_erp
- ieee80211_set_shortslottime
- ieee80211_newstate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include "bpfilter.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/mbuf.h>
41 #include <sys/kernel.h>
42 #include <sys/socket.h>
43 #include <sys/sockio.h>
44 #include <sys/endian.h>
45 #include <sys/errno.h>
46 #include <sys/proc.h>
47 #include <sys/sysctl.h>
48
49 #include <net/if.h>
50 #include <net/if_dl.h>
51 #include <net/if_media.h>
52 #include <net/if_arp.h>
53 #include <net/if_llc.h>
54
55 #if NBPFILTER > 0
56 #include <net/bpf.h>
57 #endif
58
59 #ifdef INET
60 #include <netinet/in.h>
61 #include <netinet/if_ether.h>
62 #endif
63
64 #include <net80211/ieee80211_var.h>
65
66 const char * const ieee80211_mgt_subtype_name[] = {
67 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
68 "probe_req", "probe_resp", "reserved#6", "reserved#7",
69 "beacon", "atim", "disassoc", "auth",
70 "deauth", "action", "action_noack", "reserved#15"
71 };
72 const char * const ieee80211_state_name[IEEE80211_S_MAX] = {
73 "INIT",
74 "SCAN",
75 "AUTH",
76 "ASSOC",
77 "RUN"
78 };
79 const char * const ieee80211_phymode_name[] = {
80 "auto",
81 "11a",
82 "11b",
83 "11g",
84 "fh",
85 "turbo",
86 };
87
88 int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
89
90 void
91 ieee80211_proto_attach(struct ifnet *ifp)
92 {
93 struct ieee80211com *ic = (void *)ifp;
94
95 ifp->if_hdrlen = sizeof(struct ieee80211_frame);
96
97 #ifdef notdef
98 ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
99 #else
100 ic->ic_rtsthreshold = IEEE80211_RTS_MAX;
101 #endif
102 ic->ic_fragthreshold = 2346;
103 ic->ic_fixed_rate = -1;
104 ic->ic_protmode = IEEE80211_PROT_CTSONLY;
105
106
107 ic->ic_newstate = ieee80211_newstate;
108
109
110 ic->ic_recv_mgmt = ieee80211_recv_mgmt;
111 ic->ic_send_mgmt = ieee80211_send_mgmt;
112
113
114 ic->ic_recv_eapol = ieee80211_recv_eapol;
115 }
116
117 void
118 ieee80211_proto_detach(struct ifnet *ifp)
119 {
120 struct ieee80211com *ic = (void *)ifp;
121
122 IF_PURGE(&ic->ic_mgtq);
123 IF_PURGE(&ic->ic_pwrsaveq);
124 }
125
126 void
127 ieee80211_print_essid(const u_int8_t *essid, int len)
128 {
129 int i;
130 const u_int8_t *p;
131
132 if (len > IEEE80211_NWID_LEN)
133 len = IEEE80211_NWID_LEN;
134
135 for (i = 0, p = essid; i < len; i++, p++) {
136 if (*p < ' ' || *p > 0x7e)
137 break;
138 }
139 if (i == len) {
140 printf("\"");
141 for (i = 0, p = essid; i < len; i++, p++)
142 printf("%c", *p);
143 printf("\"");
144 } else {
145 printf("0x");
146 for (i = 0, p = essid; i < len; i++, p++)
147 printf("%02x", *p);
148 }
149 }
150
151 void
152 ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi)
153 {
154 struct ieee80211_frame *wh;
155 int i;
156
157 wh = (struct ieee80211_frame *)buf;
158 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
159 case IEEE80211_FC1_DIR_NODS:
160 printf("NODS %s", ether_sprintf(wh->i_addr2));
161 printf("->%s", ether_sprintf(wh->i_addr1));
162 printf("(%s)", ether_sprintf(wh->i_addr3));
163 break;
164 case IEEE80211_FC1_DIR_TODS:
165 printf("TODS %s", ether_sprintf(wh->i_addr2));
166 printf("->%s", ether_sprintf(wh->i_addr3));
167 printf("(%s)", ether_sprintf(wh->i_addr1));
168 break;
169 case IEEE80211_FC1_DIR_FROMDS:
170 printf("FRDS %s", ether_sprintf(wh->i_addr3));
171 printf("->%s", ether_sprintf(wh->i_addr1));
172 printf("(%s)", ether_sprintf(wh->i_addr2));
173 break;
174 case IEEE80211_FC1_DIR_DSTODS:
175 printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
176 printf("->%s", ether_sprintf(wh->i_addr3));
177 printf("(%s", ether_sprintf(wh->i_addr2));
178 printf("->%s)", ether_sprintf(wh->i_addr1));
179 break;
180 }
181 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
182 case IEEE80211_FC0_TYPE_DATA:
183 printf(" data");
184 break;
185 case IEEE80211_FC0_TYPE_MGT:
186 printf(" %s", ieee80211_mgt_subtype_name[
187 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
188 >> IEEE80211_FC0_SUBTYPE_SHIFT]);
189 break;
190 default:
191 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
192 break;
193 }
194 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
195 printf(" WEP");
196 if (rate >= 0)
197 printf(" %d%sM", rate / 2, (rate & 1) ? ".5" : "");
198 if (rssi >= 0)
199 printf(" +%d", rssi);
200 printf("\n");
201 if (len > 0) {
202 for (i = 0; i < len; i++) {
203 if ((i & 1) == 0)
204 printf(" ");
205 printf("%02x", buf[i]);
206 }
207 printf("\n");
208 }
209 }
210
211 int
212 ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
213 int flags)
214 {
215 #define RV(v) ((v) & IEEE80211_RATE_VAL)
216 int i, j, ignore, error;
217 int okrate, badrate, fixedrate;
218 const struct ieee80211_rateset *srs;
219 struct ieee80211_rateset *nrs;
220 u_int8_t r;
221
222
223
224
225
226 if ((flags & IEEE80211_F_DOFRATE) && ic->ic_fixed_rate == -1)
227 flags &= ~IEEE80211_F_DOFRATE;
228
229 error = 0;
230 okrate = badrate = fixedrate = 0;
231 srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
232 nrs = &ni->ni_rates;
233 for (i = 0; i < nrs->rs_nrates; ) {
234 ignore = 0;
235 if (flags & IEEE80211_F_DOSORT) {
236
237
238
239 for (j = i + 1; j < nrs->rs_nrates; j++) {
240 if (RV(nrs->rs_rates[i]) >
241 RV(nrs->rs_rates[j])) {
242 r = nrs->rs_rates[i];
243 nrs->rs_rates[i] = nrs->rs_rates[j];
244 nrs->rs_rates[j] = r;
245 }
246 }
247 }
248 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
249 badrate = r;
250 if (flags & IEEE80211_F_DOFRATE) {
251
252
253
254 if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
255 fixedrate = r;
256 }
257 if (flags & IEEE80211_F_DONEGO) {
258
259
260
261 for (j = 0; j < srs->rs_nrates; j++) {
262 if (r == RV(srs->rs_rates[j])) {
263
264
265
266
267
268
269
270 nrs->rs_rates[i] = srs->rs_rates[j];
271 break;
272 }
273 }
274 if (j == srs->rs_nrates) {
275
276
277
278
279
280
281
282
283 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
284 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
285 error++;
286 ignore++;
287 }
288 }
289 if (flags & IEEE80211_F_DODEL) {
290
291
292
293 if (ignore) {
294 nrs->rs_nrates--;
295 for (j = i; j < nrs->rs_nrates; j++)
296 nrs->rs_rates[j] = nrs->rs_rates[j + 1];
297 nrs->rs_rates[j] = 0;
298 continue;
299 }
300 }
301 if (!ignore)
302 okrate = nrs->rs_rates[i];
303 i++;
304 }
305 if (okrate == 0 || error != 0 ||
306 ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))
307 return badrate | IEEE80211_RATE_BASIC;
308 else
309 return RV(okrate);
310 #undef RV
311 }
312
313
314
315
316 void
317 ieee80211_reset_erp(struct ieee80211com *ic)
318 {
319 ic->ic_flags &= ~IEEE80211_F_USEPROT;
320 ic->ic_nonerpsta = 0;
321 ic->ic_longslotsta = 0;
322
323
324
325
326
327
328
329 ieee80211_set_shortslottime(ic,
330 ic->ic_curmode == IEEE80211_MODE_11A ||
331 (ic->ic_curmode == IEEE80211_MODE_11G &&
332 ic->ic_opmode == IEEE80211_M_HOSTAP &&
333 (ic->ic_caps & IEEE80211_C_SHSLOT)));
334
335 if (ic->ic_curmode == IEEE80211_MODE_11A ||
336 (ic->ic_caps & IEEE80211_C_SHPREAMBLE))
337 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
338 else
339 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
340 }
341
342
343
344
345 void
346 ieee80211_set_shortslottime(struct ieee80211com *ic, int on)
347 {
348 if (on)
349 ic->ic_flags |= IEEE80211_F_SHSLOT;
350 else
351 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
352
353
354 if (ic->ic_updateslot != NULL)
355 ic->ic_updateslot(ic);
356 }
357
358 int
359 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
360 int mgt)
361 {
362 struct ifnet *ifp = &ic->ic_if;
363 struct ieee80211_node *ni;
364 enum ieee80211_state ostate;
365 u_int rate;
366 int s;
367
368 ostate = ic->ic_state;
369 IEEE80211_DPRINTF(("%s: %s -> %s\n", __func__,
370 ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
371 ic->ic_state = nstate;
372 ni = ic->ic_bss;
373 switch (nstate) {
374 case IEEE80211_S_INIT:
375 switch (ostate) {
376 case IEEE80211_S_INIT:
377 break;
378 case IEEE80211_S_RUN:
379 switch (ic->ic_opmode) {
380 case IEEE80211_M_STA:
381 IEEE80211_SEND_MGMT(ic, ni,
382 IEEE80211_FC0_SUBTYPE_DISASSOC,
383 IEEE80211_REASON_ASSOC_LEAVE);
384 break;
385 case IEEE80211_M_HOSTAP:
386 s = splnet();
387 RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
388 if (ni->ni_associd == 0)
389 continue;
390 IEEE80211_SEND_MGMT(ic, ni,
391 IEEE80211_FC0_SUBTYPE_DISASSOC,
392 IEEE80211_REASON_ASSOC_LEAVE);
393 }
394 splx(s);
395 break;
396 default:
397 break;
398 }
399
400 case IEEE80211_S_ASSOC:
401 switch (ic->ic_opmode) {
402 case IEEE80211_M_STA:
403 IEEE80211_SEND_MGMT(ic, ni,
404 IEEE80211_FC0_SUBTYPE_DEAUTH,
405 IEEE80211_REASON_AUTH_LEAVE);
406 break;
407 case IEEE80211_M_HOSTAP:
408 s = splnet();
409 RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
410 IEEE80211_SEND_MGMT(ic, ni,
411 IEEE80211_FC0_SUBTYPE_DEAUTH,
412 IEEE80211_REASON_AUTH_LEAVE);
413 }
414 splx(s);
415 break;
416 default:
417 break;
418 }
419
420 case IEEE80211_S_AUTH:
421 case IEEE80211_S_SCAN:
422 ic->ic_mgt_timer = 0;
423 IF_PURGE(&ic->ic_mgtq);
424 IF_PURGE(&ic->ic_pwrsaveq);
425 if (ic->ic_wep_ctx != NULL) {
426 free(ic->ic_wep_ctx, M_DEVBUF);
427 ic->ic_wep_ctx = NULL;
428 }
429 ieee80211_free_allnodes(ic);
430 break;
431 }
432 break;
433 case IEEE80211_S_SCAN:
434 ic->ic_flags &= ~IEEE80211_F_SIBSS;
435
436 IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);
437 IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);
438 ni->ni_rates = ic->ic_sup_rates[
439 ieee80211_chan2mode(ic, ni->ni_chan)];
440 ni->ni_associd = 0;
441 ni->ni_rstamp = 0;
442 switch (ostate) {
443 case IEEE80211_S_INIT:
444 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
445 ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
446
447
448
449
450 ieee80211_create_ibss(ic, ic->ic_des_chan);
451 } else {
452 ieee80211_begin_scan(ifp);
453 }
454 break;
455 case IEEE80211_S_SCAN:
456
457 if (ic->ic_flags & IEEE80211_F_ASCAN) {
458 IEEE80211_SEND_MGMT(ic, ni,
459 IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
460 }
461 break;
462 case IEEE80211_S_RUN:
463
464 if (ifp->if_flags & IFF_DEBUG) {
465
466 printf("%s: no recent beacons from %s;"
467 " rescanning\n", ifp->if_xname,
468 ether_sprintf(ic->ic_bss->ni_bssid));
469 }
470 ieee80211_free_allnodes(ic);
471
472 case IEEE80211_S_AUTH:
473 case IEEE80211_S_ASSOC:
474
475 ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
476 if (ni != NULL)
477 ni->ni_fails++;
478 ieee80211_begin_scan(ifp);
479 break;
480 }
481 break;
482 case IEEE80211_S_AUTH:
483 switch (ostate) {
484 case IEEE80211_S_INIT:
485 IEEE80211_DPRINTF(("%s: invalid transition\n",
486 __func__));
487 break;
488 case IEEE80211_S_SCAN:
489 IEEE80211_SEND_MGMT(ic, ni,
490 IEEE80211_FC0_SUBTYPE_AUTH, 1);
491 break;
492 case IEEE80211_S_AUTH:
493 case IEEE80211_S_ASSOC:
494 switch (mgt) {
495 case IEEE80211_FC0_SUBTYPE_AUTH:
496
497 IEEE80211_SEND_MGMT(ic, ni,
498 IEEE80211_FC0_SUBTYPE_AUTH, 2);
499 break;
500 case IEEE80211_FC0_SUBTYPE_DEAUTH:
501
502 break;
503 }
504 break;
505 case IEEE80211_S_RUN:
506 switch (mgt) {
507 case IEEE80211_FC0_SUBTYPE_AUTH:
508 IEEE80211_SEND_MGMT(ic, ni,
509 IEEE80211_FC0_SUBTYPE_AUTH, 2);
510 ic->ic_state = ostate;
511 break;
512 case IEEE80211_FC0_SUBTYPE_DEAUTH:
513
514 IEEE80211_SEND_MGMT(ic, ni,
515 IEEE80211_FC0_SUBTYPE_AUTH, 1);
516 break;
517 }
518 break;
519 }
520 break;
521 case IEEE80211_S_ASSOC:
522 switch (ostate) {
523 case IEEE80211_S_INIT:
524 case IEEE80211_S_SCAN:
525 case IEEE80211_S_ASSOC:
526 IEEE80211_DPRINTF(("%s: invalid transition\n",
527 __func__));
528 break;
529 case IEEE80211_S_AUTH:
530 IEEE80211_SEND_MGMT(ic, ni,
531 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
532 break;
533 case IEEE80211_S_RUN:
534 IEEE80211_SEND_MGMT(ic, ni,
535 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
536 break;
537 }
538 break;
539 case IEEE80211_S_RUN:
540 switch (ostate) {
541 case IEEE80211_S_INIT:
542 case IEEE80211_S_AUTH:
543 case IEEE80211_S_RUN:
544 IEEE80211_DPRINTF(("%s: invalid transition\n",
545 __func__));
546 break;
547 case IEEE80211_S_SCAN:
548 case IEEE80211_S_ASSOC:
549 if (ni->ni_txrate >= ni->ni_rates.rs_nrates)
550 panic("%s: bogus xmit rate %u setup\n",
551 __func__, ni->ni_txrate);
552 if (ifp->if_flags & IFF_DEBUG) {
553 printf("%s: %s with %s ssid ",
554 ifp->if_xname,
555 ic->ic_opmode == IEEE80211_M_STA ?
556 "associated" : "synchronized",
557 ether_sprintf(ni->ni_bssid));
558 ieee80211_print_essid(ic->ic_bss->ni_essid,
559 ni->ni_esslen);
560 rate = ni->ni_rates.rs_rates[ni->ni_txrate] &
561 IEEE80211_RATE_VAL;
562 printf(" channel %d start %u%sMb",
563 ieee80211_chan2ieee(ic, ni->ni_chan),
564 rate / 2, (rate & 1) ? ".5" : "");
565 printf(" %s preamble %s slot time%s\n",
566 (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
567 "short" : "long",
568 (ic->ic_flags & IEEE80211_F_SHSLOT) ?
569 "short" : "long",
570 (ic->ic_flags & IEEE80211_F_USEPROT) ?
571 " protection enabled" : "");
572 }
573 ic->ic_mgt_timer = 0;
574 (*ifp->if_start)(ifp);
575 break;
576 }
577 break;
578 }
579 return 0;
580 }