1 /* $OpenBSD: if_ieee80211subr.c,v 1.2 2004/01/26 03:35:36 fgsch Exp $ */
2 /* $NetBSD: if_ieee80211subr.c,v 1.43 2003/07/06 20:54:25 dyoung Exp $ */
3 /* $FreeBSD: src/sys/net/if_ieee80211subr.c,v 1.4 2003/01/21 08:55:59 alfred Exp $ */
4
5 /*-
6 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Atsushi Onoe.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 /*
42 * IEEE 802.11 generic handler
43 */
44
45 #include "bpfilter.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/mbuf.h>
50 #include <sys/malloc.h>
51 #include <sys/kernel.h>
52 #include <sys/socket.h>
53 #include <sys/ioctl.h>
54 #include <sys/errno.h>
55 #include <sys/device.h>
56 #include <sys/proc.h>
57
58 #include <machine/endian.h>
59
60 #include <dev/rndvar.h>
61 #include <crypto/arc4.h>
62
63 #include <net/if.h>
64 #include <net/if_dl.h>
65 #include <net/if_media.h>
66 #include <net/if_llc.h>
67 #include <netinet/in.h>
68 #include <netinet/if_ether.h>
69 #include <net/if_ieee80211.h>
70
71 #include <dev/ic/if_wi_ieee.h> /* XXX */
72
73 #if NBPFILTER > 0
74 #include <net/bpf.h>
75 #endif
76
77 #ifdef IEEE80211_DEBUG
78 int ieee80211_debug = 0;
79 #define DPRINTF(X) if (ieee80211_debug) printf X
80 #define DPRINTF2(X) if (ieee80211_debug>1) printf X
81 #else
82 #define DPRINTF(X)
83 #define DPRINTF2(X)
84 #endif
85
86 static int ieee80211_send_prreq(struct ieee80211com *,
87 struct ieee80211_node *, int, int);
88 static int ieee80211_send_prresp(struct ieee80211com *,
89 struct ieee80211_node *, int, int);
90 static int ieee80211_send_auth(struct ieee80211com *,
91 struct ieee80211_node *, int, int);
92 static int ieee80211_send_deauth(struct ieee80211com *,
93 struct ieee80211_node *, int, int);
94 static int ieee80211_send_asreq(struct ieee80211com *,
95 struct ieee80211_node *, int, int);
96 static int ieee80211_send_asresp(struct ieee80211com *,
97 struct ieee80211_node *, int, int);
98 static int ieee80211_send_disassoc(struct ieee80211com *,
99 struct ieee80211_node *, int, int);
100
101 static void ieee80211_recv_beacon(struct ieee80211com *,
102 struct mbuf *, int, u_int32_t);
103 static void ieee80211_recv_prreq(struct ieee80211com *,
104 struct mbuf *, int, u_int32_t);
105 static void ieee80211_recv_auth(struct ieee80211com *,
106 struct mbuf *, int, u_int32_t);
107 static void ieee80211_recv_asreq(struct ieee80211com *,
108 struct mbuf *, int, u_int32_t);
109 static void ieee80211_recv_asresp(struct ieee80211com *,
110 struct mbuf *, int, u_int32_t);
111 static void ieee80211_recv_disassoc(struct ieee80211com *,
112 struct mbuf *, int, u_int32_t);
113 static void ieee80211_recv_deauth(struct ieee80211com *,
114 struct mbuf *, int, u_int32_t);
115
116 static void ieee80211_recv_pspoll(struct ieee80211com *,
117 struct mbuf *, int, u_int32_t);
118
119 static void ieee80211_crc_init(void);
120 static u_int32_t ieee80211_crc_update(u_int32_t, u_int8_t *, int);
121
122 static const char *ieee80211_mgt_subtype_name[] = {
123 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
124 "probe_req", "probe_resp", "reserved#6", "reserved#7",
125 "beacon", "atim", "disassoc", "auth",
126 "deauth", "reserved#13", "reserved#14", "reserved#15"
127 };
128
129 void
ieee80211_ifattach(struct ifnet * ifp)130 ieee80211_ifattach(struct ifnet *ifp)
131 {
132 struct ieee80211com *ic = (void *)ifp;
133 int i, rate, mword;
134 struct ifmediareq imr;
135
136 bcopy(ic->ic_myaddr, ((struct arpcom *)ifp)->ac_enaddr,
137 ETHER_ADDR_LEN);
138 ether_ifattach(ifp);
139 #if NBPFILTER > 0
140 bpfattach(&ic->ic_rawbpf, ifp, DLT_IEEE802_11,
141 sizeof(struct ieee80211_frame_addr4));
142 #endif
143 ieee80211_crc_init();
144 memcpy(ic->ic_chan_active, ic->ic_chan_avail,
145 sizeof(ic->ic_chan_active));
146 if (isclr(ic->ic_chan_active, ic->ic_ibss_chan)) {
147 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
148 if (isset(ic->ic_chan_active, i)) {
149 ic->ic_ibss_chan = i;
150 break;
151 }
152 }
153 }
154 /* ic->ic_bss.ni_chan must always be a valid channel */
155 if (isclr(ic->ic_chan_active, ic->ic_bss.ni_chan))
156 ic->ic_bss.ni_chan = ic->ic_ibss_chan;
157
158 ic->ic_des_chan = IEEE80211_CHAN_ANY;
159 ic->ic_fixed_rate = -1;
160 if (ic->ic_lintval == 0)
161 ic->ic_lintval = 100; /* default sleep */
162 TAILQ_INIT(&ic->ic_node);
163 rate = 0;
164 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
165 if (ic->ic_sup_rates[i] != 0)
166 rate = (ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) / 2;
167 }
168 if (rate)
169 ifp->if_baudrate = IF_Mbps(rate);
170 ifp->if_hdrlen = sizeof(struct ieee80211_frame);
171
172 if (ic->ic_max_aid == 0)
173 ic->ic_max_aid = IEEE80211_MAX_AID;
174
175 /* initialize management frame handlers */
176 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_RESP
177 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_beacon;
178 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_BEACON
179 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_beacon;
180 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_REQ
181 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_prreq;
182 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_AUTH
183 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_auth;
184 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_REQ
185 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asreq;
186 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_REQ
187 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asreq;
188 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_RESP
189 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asresp;
190 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_RESP
191 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asresp;
192 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_DEAUTH
193 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_deauth;
194 ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_DISASSOC
195 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_disassoc;
196
197 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_REQ
198 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_prreq;
199 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_RESP
200 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_prresp;
201 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_AUTH
202 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_auth;
203 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_DEAUTH
204 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_deauth;
205 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_REQ
206 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asreq;
207 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_REQ
208 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asreq;
209 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_RESP
210 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asresp;
211 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_RESP
212 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asresp;
213 ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_DISASSOC
214 >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_disassoc;
215
216 #define ADD(s, o) ifmedia_add(&ic->ic_media, \
217 IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL)
218
219 ifmedia_init(&ic->ic_media, 0, ieee80211_media_change,
220 ieee80211_media_status);
221 ADD(IFM_AUTO, 0); /* infrastructure */
222 if (ic->ic_flags & IEEE80211_F_HASAHDEMO)
223 ADD(IFM_AUTO, IFM_IEEE80211_ADHOC | IFM_FLAG0);
224 if (ic->ic_flags & IEEE80211_F_HASHOSTAP)
225 ADD(IFM_AUTO, IFM_IEEE80211_HOSTAP);
226 if (ic->ic_flags & IEEE80211_F_HASIBSS)
227 ADD(IFM_AUTO, IFM_IEEE80211_ADHOC);
228 if (ic->ic_flags & IEEE80211_F_HASMONITOR)
229 ADD(IFM_AUTO, IFM_IEEE80211_MONITOR);
230
231 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
232 rate = ic->ic_sup_rates[i];
233 mword = ieee80211_rate2media(rate, ic->ic_phytype);
234 if (mword == 0)
235 continue;
236 ADD(mword, 0); /* infrastructure */
237 if (ic->ic_flags & IEEE80211_F_HASAHDEMO)
238 ADD(mword, IFM_IEEE80211_ADHOC | IFM_FLAG0);
239 if (ic->ic_flags & IEEE80211_F_HASHOSTAP)
240 ADD(mword, IFM_IEEE80211_HOSTAP);
241 if (ic->ic_flags & IEEE80211_F_HASIBSS)
242 ADD(mword, IFM_IEEE80211_ADHOC);
243 if (ic->ic_flags & IEEE80211_F_HASMONITOR)
244 ADD(mword, IFM_IEEE80211_MONITOR);
245 }
246 (*ic->ic_media.ifm_status)(ifp, &imr);
247 ifmedia_set(&ic->ic_media, imr.ifm_active);
248 #undef ADD
249 }
250
251 void
ieee80211_ifdetach(struct ifnet * ifp)252 ieee80211_ifdetach(struct ifnet *ifp)
253 {
254 struct ieee80211com *ic = (void *)ifp;
255 int s;
256
257 s = splnet();
258 IF_PURGE(&ic->ic_mgtq);
259 IF_PURGE(&ic->ic_pwrsaveq);
260 if (ic->ic_wep_ctx != NULL) {
261 free(ic->ic_wep_ctx, M_DEVBUF);
262 ic->ic_wep_ctx = NULL;
263 }
264 ieee80211_free_allnodes(ic);
265 ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY);
266 #if NBPFILTER > 0
267 bpfdetach(ifp);
268 #endif
269 ether_ifdetach(ifp);
270 splx(s);
271 }
272
273 void
ieee80211_input(struct ifnet * ifp,struct mbuf * m,int rssi,u_int32_t rstamp)274 ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp)
275 {
276 struct ieee80211com *ic = (void *)ifp;
277 struct ieee80211_node *ni;
278 struct ieee80211_frame *wh;
279 struct ether_header *eh;
280 void (*rh)(struct ieee80211com *, struct mbuf *, int, u_int);
281 struct mbuf *m1;
282 int error, len;
283 u_int8_t dir, subtype;
284 u_int8_t *bssid;
285 u_int16_t rxseq;
286
287 wh = mtod(m, struct ieee80211_frame *);
288 if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
289 IEEE80211_FC0_VERSION_0) {
290 if (ifp->if_flags & IFF_DEBUG)
291 printf("%s: receive packet with wrong version: %x\n",
292 ifp->if_xname, wh->i_fc[0]);
293 goto err;
294 }
295
296 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
297
298 if (ic->ic_state != IEEE80211_S_SCAN) {
299 switch (ic->ic_opmode) {
300 case IEEE80211_M_STA:
301 ni = &ic->ic_bss;
302 if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
303 DPRINTF2(("ieee80211_input: other bss %s\n",
304 ether_sprintf(wh->i_addr2)));
305 /* not interested in */
306 goto out;
307 }
308 break;
309 case IEEE80211_M_IBSS:
310 case IEEE80211_M_AHDEMO:
311 case IEEE80211_M_HOSTAP:
312 if (dir == IEEE80211_FC1_DIR_NODS)
313 bssid = wh->i_addr3;
314 else
315 bssid = wh->i_addr1;
316 if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss.ni_bssid) &&
317 !IEEE80211_ADDR_EQ(bssid, etherbroadcastaddr) &&
318 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
319 IEEE80211_FC0_TYPE_CTL) {
320 /* not interested in */
321 DPRINTF2(("ieee80211_input: other bss %s\n",
322 ether_sprintf(wh->i_addr3)));
323 goto out;
324 }
325 ni = ieee80211_find_node(ic, wh->i_addr2);
326 if (ni == NULL) {
327 DPRINTF2(("ieee80211_input: unknown src %s\n",
328 ether_sprintf(wh->i_addr2)));
329 ni = &ic->ic_bss; /* XXX allocate? */
330 }
331 break;
332 case IEEE80211_M_MONITOR:
333 goto out;
334 }
335 ni->ni_rssi = rssi;
336 ni->ni_rstamp = rstamp;
337 rxseq = ni->ni_rxseq;
338 ni->ni_rxseq =
339 letoh16(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
340 /* TODO: fragment */
341 if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
342 rxseq == ni->ni_rxseq) {
343 /* duplicate, silently discarded */
344 goto out;
345 }
346 ni->ni_inact = 0;
347 }
348
349 if (ic->ic_set_tim != NULL &&
350 (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT)
351 && ni->ni_pwrsave == 0) {
352 /* turn on power save mode */
353
354 if (ifp->if_flags & IFF_DEBUG)
355 printf("%s: power save mode on for %s\n",
356 ifp->if_xname, ether_sprintf(wh->i_addr2));
357
358 ni->ni_pwrsave = IEEE80211_PS_SLEEP;
359 }
360 if (ic->ic_set_tim != NULL &&
361 (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) == 0 &&
362 ni->ni_pwrsave != 0) {
363 /* turn off power save mode, dequeue stored packets */
364
365 ni->ni_pwrsave = 0;
366 if (ic->ic_set_tim)
367 ic->ic_set_tim(ic, ni->ni_associd, 0);
368
369 if (ifp->if_flags & IFF_DEBUG)
370 printf("%s: power save mode off for %s\n",
371 ifp->if_xname, ether_sprintf(wh->i_addr2));
372
373 while (!IF_IS_EMPTY(&ni->ni_savedq)) {
374 struct mbuf *m;
375 IF_DEQUEUE(&ni->ni_savedq, m);
376 IF_ENQUEUE(&ic->ic_pwrsaveq, m);
377 (*ifp->if_start)(ifp);
378 }
379 }
380
381 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
382 case IEEE80211_FC0_TYPE_DATA:
383 switch (ic->ic_opmode) {
384 case IEEE80211_M_STA:
385 if (dir != IEEE80211_FC1_DIR_FROMDS)
386 goto out;
387 if ((ifp->if_flags & IFF_SIMPLEX) &&
388 IEEE80211_IS_MULTICAST(wh->i_addr1) &&
389 IEEE80211_ADDR_EQ(wh->i_addr3,
390 ic->ic_myaddr)) {
391 /*
392 * In IEEE802.11 network, multicast packet
393 * sent from me is broadcasted from AP.
394 * It should be silently discarded for
395 * SIMPLEX interface.
396 */
397 goto out;
398 }
399 break;
400 case IEEE80211_M_IBSS:
401 case IEEE80211_M_AHDEMO:
402 if (dir != IEEE80211_FC1_DIR_NODS)
403 goto out;
404 break;
405 case IEEE80211_M_HOSTAP:
406 if (dir != IEEE80211_FC1_DIR_TODS)
407 goto out;
408 /* check if source STA is associated */
409 ni = ieee80211_find_node(ic, wh->i_addr2);
410 if (ni == NULL) {
411 DPRINTF(("ieee80211_input: "
412 "data from unknown src %s\n",
413 ether_sprintf(wh->i_addr2)));
414 if ((ni = ieee80211_alloc_node(ic, wh->i_addr2,
415 1)) != NULL) {
416 IEEE80211_SEND_MGMT(ic, ni,
417 IEEE80211_FC0_SUBTYPE_DEAUTH,
418 IEEE80211_REASON_NOT_AUTHED);
419 ieee80211_free_node(ic, ni);
420 }
421 goto err;
422 }
423 if (ni->ni_associd == 0) {
424 DPRINTF(("ieee80211_input: "
425 "data from unassoc src %s\n",
426 ether_sprintf(wh->i_addr2)));
427 IEEE80211_SEND_MGMT(ic, ni,
428 IEEE80211_FC0_SUBTYPE_DISASSOC,
429 IEEE80211_REASON_NOT_ASSOCED);
430 goto err;
431 }
432 break;
433 case IEEE80211_M_MONITOR:
434 /* Should never get here */
435 break;
436 }
437 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
438 if (ic->ic_flags & IEEE80211_F_WEPON) {
439 m = ieee80211_wep_crypt(ifp, m, 0);
440 if (m == NULL)
441 goto err;
442 wh = mtod(m, struct ieee80211_frame *);
443 } else
444 goto out;
445 }
446 /* copy to listener after decrypt */
447 #if NBPFILTER > 0
448 if (ic->ic_rawbpf)
449 bpf_mtap(ic->ic_rawbpf, m);
450 #endif
451 m = ieee80211_decap(ifp, m);
452 if (m == NULL)
453 goto err;
454 ifp->if_ipackets++;
455
456 /* perform as a bridge within the AP */
457 m1 = NULL;
458 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
459 eh = mtod(m, struct ether_header *);
460 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
461 m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
462 if (m1 == NULL)
463 ifp->if_oerrors++;
464 else
465 m1->m_flags |= M_MCAST;
466 } else {
467 ni = ieee80211_find_node(ic, eh->ether_dhost);
468 if (ni != NULL && ni->ni_associd != 0) {
469 m1 = m;
470 m = NULL;
471 }
472 }
473 if (m1 != NULL) {
474 len = m1->m_pkthdr.len;
475 IFQ_ENQUEUE(&ifp->if_snd, m1, NULL, error);
476 if (error)
477 ifp->if_oerrors++;
478 else {
479 if (m != NULL)
480 ifp->if_omcasts++;
481 ifp->if_obytes += len;
482 }
483 }
484 }
485 if (m != NULL) {
486 #if NBPFILTER > 0
487 /*
488 * If we forward packet into transmitter of the AP,
489 * we don't need to duplicate for DLT_EN10MB.
490 */
491 if (ifp->if_bpf && m1 == NULL)
492 bpf_mtap(ifp->if_bpf, m);
493 #endif
494 ether_input_mbuf(ifp, m);
495 }
496 return;
497
498 case IEEE80211_FC0_TYPE_MGT:
499 if (dir != IEEE80211_FC1_DIR_NODS)
500 goto err;
501 if (ic->ic_opmode == IEEE80211_M_AHDEMO)
502 goto out;
503 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
504
505 /* drop frames without interest */
506 if (ic->ic_state == IEEE80211_S_SCAN) {
507 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
508 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
509 goto out;
510 } else {
511 if (ic->ic_opmode != IEEE80211_M_IBSS &&
512 subtype == IEEE80211_FC0_SUBTYPE_BEACON)
513 goto out;
514 }
515
516 if (ifp->if_flags & IFF_DEBUG) {
517 /* avoid to print too many frames */
518 int doprint = 0;
519
520 switch (subtype) {
521 case IEEE80211_FC0_SUBTYPE_BEACON:
522 if (ic->ic_state == IEEE80211_S_SCAN)
523 doprint = 1;
524 break;
525 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
526 if (ic->ic_opmode == IEEE80211_M_IBSS)
527 doprint = 1;
528 break;
529 default:
530 doprint = 1;
531 break;
532 }
533 #ifdef IEEE80211_DEBUG
534 doprint += ieee80211_debug;
535 #endif
536 if (doprint)
537 printf("%s: received %s from %s rssi %d\n",
538 ifp->if_xname,
539 ieee80211_mgt_subtype_name[subtype
540 >> IEEE80211_FC0_SUBTYPE_SHIFT],
541 ether_sprintf(wh->i_addr2), rssi);
542 }
543 #if NBPFILTER > 0
544 if (ic->ic_rawbpf)
545 bpf_mtap(ic->ic_rawbpf, m);
546 #endif
547 rh = ic->ic_recv_mgmt[subtype >> IEEE80211_FC0_SUBTYPE_SHIFT];
548 if (rh != NULL)
549 (*rh)(ic, m, rssi, rstamp);
550 m_freem(m);
551 return;
552
553 case IEEE80211_FC0_TYPE_CTL:
554 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
555 goto out;
556 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
557 if (subtype == IEEE80211_FC0_SUBTYPE_PS_POLL) {
558 /* Dump out a single packet from the host */
559 if (ifp->if_flags & IFF_DEBUG)
560 printf("%s: got power save probe from %s\n",
561 ifp->if_xname,
562 ether_sprintf(wh->i_addr2));
563 ieee80211_recv_pspoll(ic, m, rssi, rstamp);
564 }
565 goto out;
566
567 default:
568 DPRINTF(("ieee80211_input: bad type %x\n", wh->i_fc[0]));
569 /* should not come here */
570 break;
571 }
572 err:
573 ifp->if_ierrors++;
574 out:
575 if (m != NULL) {
576 #if NBPFILTER > 0
577 if (ic->ic_rawbpf)
578 bpf_mtap(ic->ic_rawbpf, m);
579 #endif
580 m_freem(m);
581 }
582 }
583
584 int
ieee80211_mgmt_output(struct ifnet * ifp,struct ieee80211_node * ni,struct mbuf * m,int type)585 ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni,
586 struct mbuf *m, int type)
587 {
588 struct ieee80211com *ic = (void *)ifp;
589 struct ieee80211_frame *wh;
590
591 if (ni == NULL)
592 ni = &ic->ic_bss;
593 ni->ni_inact = 0;
594 M_PREPEND(m, IEEE80211_HEADER_LEN(ic), M_DONTWAIT);
595 if (m == NULL)
596 return (ENOMEM);
597 wh = mtod(m, struct ieee80211_frame *);
598 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
599 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
600 *(u_int16_t *)wh->i_dur = 0;
601 *(u_int16_t *)wh->i_seq =
602 htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
603 ni->ni_txseq++;
604 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
605 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
606 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
607
608 if (ifp->if_flags & IFF_DEBUG) {
609 /* avoid to print too many frames */
610 if (ic->ic_opmode == IEEE80211_M_IBSS ||
611 #ifdef IEEE80211_DEBUG
612 ieee80211_debug > 1 ||
613 #endif
614 (type & IEEE80211_FC0_SUBTYPE_MASK) !=
615 IEEE80211_FC0_SUBTYPE_PROBE_RESP)
616 printf("%s: sending %s to %s on channel %u\n",
617 ifp->if_xname,
618 ieee80211_mgt_subtype_name[
619 (type & IEEE80211_FC0_SUBTYPE_MASK)
620 >> IEEE80211_FC0_SUBTYPE_SHIFT],
621 ether_sprintf(ni->ni_macaddr),
622 ni->ni_chan);
623 }
624 IF_ENQUEUE(&ic->ic_mgtq, m);
625 ifp->if_timer = 1;
626 (*ifp->if_start)(ifp);
627 return (0);
628 }
629
630 struct mbuf *
ieee80211_encap(struct ifnet * ifp,struct mbuf * m)631 ieee80211_encap(struct ifnet *ifp, struct mbuf *m)
632 {
633 struct ieee80211com *ic = (void *)ifp;
634 struct ether_header eh;
635 struct ieee80211_frame *wh;
636 struct llc *llc;
637 struct ieee80211_node *ni;
638
639 if (m->m_len < sizeof(struct ether_header)) {
640 m = m_pullup(m, sizeof(struct ether_header));
641 if (m == NULL)
642 return (NULL);
643 }
644 memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
645
646 if (!IEEE80211_IS_MULTICAST(eh.ether_dhost) &&
647 (ic->ic_opmode == IEEE80211_M_IBSS ||
648 ic->ic_opmode == IEEE80211_M_HOSTAP)) {
649 ni = ieee80211_find_node(ic, eh.ether_dhost);
650 if (ni == NULL)
651 ni = &ic->ic_bss; /*XXX*/
652 } else
653 ni = &ic->ic_bss;
654 ni->ni_inact = 0;
655
656 m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
657 llc = mtod(m, struct llc *);
658 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
659 llc->llc_control = LLC_UI;
660 llc->llc_snap.org_code[0] = 0;
661 llc->llc_snap.org_code[1] = 0;
662 llc->llc_snap.org_code[2] = 0;
663 llc->llc_snap.ether_type = eh.ether_type;
664 M_PREPEND(m, IEEE80211_HEADER_LEN(ic), M_DONTWAIT);
665 if (m == NULL)
666 return (NULL);
667 wh = mtod(m, struct ieee80211_frame *);
668 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
669 *(u_int16_t *)wh->i_dur = 0;
670 *(u_int16_t *)wh->i_seq =
671 htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
672 ni->ni_txseq++;
673 switch (ic->ic_opmode) {
674 case IEEE80211_M_STA:
675 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
676 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
677 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
678 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
679 break;
680 case IEEE80211_M_IBSS:
681 case IEEE80211_M_AHDEMO:
682 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
683 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
684 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
685 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
686 break;
687 case IEEE80211_M_HOSTAP:
688 wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
689 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
690 IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
691 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
692 break;
693 case IEEE80211_M_MONITOR:
694 /* Should never get here! */
695 m_freem(m);
696 return (NULL);
697 }
698 return (m);
699 }
700
701 struct mbuf *
ieee80211_decap(struct ifnet * ifp,struct mbuf * m)702 ieee80211_decap(struct ifnet *ifp, struct mbuf *m)
703 {
704 struct ether_header *eh;
705 struct ieee80211_frame wh;
706 struct llc *llc;
707
708 if (m->m_len < sizeof(wh) + sizeof(*llc)) {
709 m = m_pullup(m, sizeof(wh) + sizeof(*llc));
710 if (m == NULL)
711 return (NULL);
712 }
713 memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
714 llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
715 if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
716 llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
717 llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
718 m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh));
719 llc = NULL;
720 } else {
721 m_adj(m, sizeof(wh) - sizeof(*eh));
722 }
723 eh = mtod(m, struct ether_header *);
724 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
725 case IEEE80211_FC1_DIR_NODS:
726 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
727 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
728 break;
729 case IEEE80211_FC1_DIR_TODS:
730 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
731 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
732 break;
733 case IEEE80211_FC1_DIR_FROMDS:
734 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
735 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
736 break;
737 case IEEE80211_FC1_DIR_DSTODS:
738 /* not yet supported */
739 DPRINTF(("ieee80211_decap: DS to DS\n"));
740 m_freem(m);
741 return (NULL);
742 }
743 if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
744 struct mbuf *n, *n0, **np;
745 caddr_t newdata;
746 int off, pktlen;
747
748 n0 = NULL;
749 np = &n0;
750 off = 0;
751 pktlen = m->m_pkthdr.len;
752 while (pktlen > off) {
753 if (n0 == NULL) {
754 MGETHDR(n, M_DONTWAIT, MT_DATA);
755 if (n == NULL) {
756 m_freem(m);
757 return (NULL);
758 }
759 M_MOVE_PKTHDR(n, m);
760 n->m_len = MHLEN;
761 } else {
762 MGET(n, M_DONTWAIT, MT_DATA);
763 if (n == NULL) {
764 m_freem(m);
765 m_freem(n0);
766 return (NULL);
767 }
768 n->m_len = MLEN;
769 }
770 if (pktlen - off >= MINCLSIZE) {
771 MCLGET(n, M_DONTWAIT);
772 if (n->m_flags & M_EXT)
773 n->m_len = n->m_ext.ext_size;
774 }
775 if (n0 == NULL) {
776 newdata =
777 (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
778 sizeof(*eh);
779 n->m_len -= newdata - n->m_data;
780 n->m_data = newdata;
781 }
782 if (n->m_len > pktlen - off)
783 n->m_len = pktlen - off;
784 m_copydata(m, off, n->m_len, mtod(n, caddr_t));
785 off += n->m_len;
786 *np = n;
787 np = &n->m_next;
788 }
789 m_freem(m);
790 m = n0;
791 }
792 if (llc != NULL) {
793 eh = mtod(m, struct ether_header *);
794 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
795 }
796 return (m);
797 }
798
799 int
ieee80211_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)800 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
801 {
802 struct ieee80211com *ic = (void *)ifp;
803 struct ifreq *ifr = (struct ifreq *)data;
804 int i, error = 0;
805 struct ieee80211_nwid nwid;
806 struct ieee80211_nwkey *nwkey;
807 struct ieee80211_power *power;
808 struct ieee80211_bssid *bssid;
809 struct ieee80211_channel *chan;
810 struct ieee80211_wepkey keys[IEEE80211_WEP_NKID];
811 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
813 };
814
815 switch (cmd) {
816 case SIOCSIFMEDIA:
817 case SIOCGIFMEDIA:
818 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
819 break;
820 case SIOCS80211NWID:
821 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0)
822 break;
823 if (nwid.i_len > IEEE80211_NWID_LEN) {
824 error = EINVAL;
825 break;
826 }
827 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
828 ic->ic_des_esslen = nwid.i_len;
829 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);
830 error = ENETRESET;
831 break;
832 case SIOCG80211NWID:
833 memset(&nwid, 0, sizeof(nwid));
834 switch (ic->ic_state) {
835 case IEEE80211_S_INIT:
836 case IEEE80211_S_SCAN:
837 nwid.i_len = ic->ic_des_esslen;
838 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len);
839 break;
840 default:
841 nwid.i_len = ic->ic_bss.ni_esslen;
842 memcpy(nwid.i_nwid, ic->ic_bss.ni_essid, nwid.i_len);
843 break;
844 }
845 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
846 break;
847 case SIOCS80211NWKEY:
848 nwkey = (struct ieee80211_nwkey *)data;
849 if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0 &&
850 nwkey->i_wepon != IEEE80211_NWKEY_OPEN) {
851 error = EINVAL;
852 break;
853 }
854 /* check and copy keys */
855 memset(keys, 0, sizeof(keys));
856 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
857 keys[i].wk_len = nwkey->i_key[i].i_keylen;
858 if ((keys[i].wk_len > 0 &&
859 keys[i].wk_len < IEEE80211_WEP_KEYLEN) ||
860 keys[i].wk_len > sizeof(keys[i].wk_key)) {
861 error = EINVAL;
862 break;
863 }
864 if (keys[i].wk_len <= 0)
865 continue;
866 if ((error = copyin(nwkey->i_key[i].i_keydat,
867 keys[i].wk_key, keys[i].wk_len)) != 0)
868 break;
869 }
870 if (error)
871 break;
872 i = nwkey->i_defkid - 1;
873 if (i < 0 || i >= IEEE80211_WEP_NKID ||
874 keys[i].wk_len == 0 ||
875 (keys[i].wk_len == -1 && ic->ic_nw_keys[i].wk_len == 0)) {
876 if (nwkey->i_wepon != IEEE80211_NWKEY_OPEN) {
877 error = EINVAL;
878 break;
879 }
880 } else
881 ic->ic_wep_txkey = i;
882 /* save the key */
883 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN)
884 ic->ic_flags &= ~IEEE80211_F_WEPON;
885 else
886 ic->ic_flags |= IEEE80211_F_WEPON;
887 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
888 if (keys[i].wk_len < 0)
889 continue;
890 ic->ic_nw_keys[i].wk_len = keys[i].wk_len;
891 memcpy(ic->ic_nw_keys[i].wk_key, keys[i].wk_key,
892 sizeof(keys[i].wk_key));
893 }
894 error = ENETRESET;
895 break;
896 case SIOCG80211NWKEY:
897 nwkey = (struct ieee80211_nwkey *)data;
898 if (ic->ic_flags & IEEE80211_F_WEPON)
899 nwkey->i_wepon = IEEE80211_NWKEY_WEP;
900 else
901 nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
902 nwkey->i_defkid = ic->ic_wep_txkey + 1;
903 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
904 if (nwkey->i_key[i].i_keydat == NULL)
905 continue;
906 /* do not show any keys to non-root user */
907 if ((error = suser(curproc, 0)) != 0)
908 break;
909 nwkey->i_key[i].i_keylen = ic->ic_nw_keys[i].wk_len;
910 if ((error = copyout(ic->ic_nw_keys[i].wk_key,
911 nwkey->i_key[i].i_keydat,
912 ic->ic_nw_keys[i].wk_len)) != 0)
913 break;
914 }
915 break;
916 case SIOCS80211POWER:
917 power = (struct ieee80211_power *)data;
918 ic->ic_lintval = power->i_maxsleep;
919 if (power->i_enabled != 0) {
920 if ((ic->ic_flags & IEEE80211_F_HASPMGT) == 0)
921 error = EINVAL;
922 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
923 ic->ic_flags |= IEEE80211_F_PMGTON;
924 error = ENETRESET;
925 }
926 } else {
927 if (ic->ic_flags & IEEE80211_F_PMGTON) {
928 ic->ic_flags &= ~IEEE80211_F_PMGTON;
929 error = ENETRESET;
930 }
931 }
932 break;
933 case SIOCG80211POWER:
934 power = (struct ieee80211_power *)data;
935 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;
936 power->i_maxsleep = ic->ic_lintval;
937 break;
938 case SIOCS80211BSSID:
939 bssid = (struct ieee80211_bssid *)data;
940 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr))
941 ic->ic_flags &= ~IEEE80211_F_DESBSSID;
942 else {
943 ic->ic_flags |= IEEE80211_F_DESBSSID;
944 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid);
945 }
946 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
947 break;
948 switch (ic->ic_state) {
949 case IEEE80211_S_INIT:
950 case IEEE80211_S_SCAN:
951 error = ENETRESET;
952 break;
953 default:
954 if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
955 !IEEE80211_ADDR_EQ(ic->ic_des_bssid,
956 ic->ic_bss.ni_bssid))
957 error = ENETRESET;
958 break;
959 }
960 break;
961 case SIOCG80211BSSID:
962 bssid = (struct ieee80211_bssid *)data;
963 switch (ic->ic_state) {
964 case IEEE80211_S_INIT:
965 case IEEE80211_S_SCAN:
966 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
967 IEEE80211_ADDR_COPY(bssid->i_bssid,
968 ic->ic_myaddr);
969 else if (ic->ic_flags & IEEE80211_F_DESBSSID)
970 IEEE80211_ADDR_COPY(bssid->i_bssid,
971 ic->ic_des_bssid);
972 else
973 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
974 break;
975 default:
976 IEEE80211_ADDR_COPY(bssid->i_bssid,
977 ic->ic_bss.ni_bssid);
978 break;
979 }
980 break;
981 case SIOCS80211CHANNEL:
982 chan = (struct ieee80211_channel *)data;
983 if (chan->i_channel == IEEE80211_CHAN_ANY)
984 ic->ic_des_chan = IEEE80211_CHAN_ANY;
985 else if (chan->i_channel > IEEE80211_CHAN_MAX ||
986 isclr(ic->ic_chan_active, chan->i_channel)) {
987 error = EINVAL;
988 break;
989 } else
990 ic->ic_ibss_chan = ic->ic_des_chan = chan->i_channel;
991 switch (ic->ic_state) {
992 case IEEE80211_S_INIT:
993 case IEEE80211_S_SCAN:
994 error = ENETRESET;
995 break;
996 default:
997 if (ic->ic_opmode == IEEE80211_M_STA) {
998 if (ic->ic_des_chan != IEEE80211_CHAN_ANY &&
999 ic->ic_bss.ni_chan != ic->ic_des_chan)
1000 error = ENETRESET;
1001 } else {
1002 if (ic->ic_bss.ni_chan != ic->ic_ibss_chan)
1003 error = ENETRESET;
1004 }
1005 break;
1006 }
1007 break;
1008 case SIOCG80211CHANNEL:
1009 chan = (struct ieee80211_channel *)data;
1010 chan->i_channel = ieee80211_get_channel(ic);
1011 break;
1012 case SIOCGWAVELAN:
1013 error = ieee80211_cfgget(ifp, cmd, data);
1014 break;
1015 case SIOCSWAVELAN:
1016 error = suser(curproc, 0);
1017 if (error)
1018 break;
1019 error = ieee80211_cfgset(ifp, cmd, data);
1020 break;
1021 default:
1022 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data);
1023 break;
1024 }
1025 return (error);
1026 }
1027
1028 void
ieee80211_print_essid(u_int8_t * essid,int len)1029 ieee80211_print_essid(u_int8_t *essid, int len)
1030 {
1031 int i;
1032 u_int8_t *p;
1033
1034 if (len > IEEE80211_NWID_LEN)
1035 len = IEEE80211_NWID_LEN;
1036 /* determine printable or not */
1037 for (i = 0, p = essid; i < len; i++, p++) {
1038 if (*p < ' ' || *p > 0x7e)
1039 break;
1040 }
1041 if (i == len) {
1042 printf("\"");
1043 for (i = 0, p = essid; i < len; i++, p++)
1044 printf("%c", *p);
1045 printf("\"");
1046 } else {
1047 printf("0x");
1048 for (i = 0, p = essid; i < len; i++, p++)
1049 printf("%02x", *p);
1050 }
1051 }
1052
1053 void
ieee80211_dump_pkt(u_int8_t * buf,int len,int rate,int rssi)1054 ieee80211_dump_pkt(u_int8_t *buf, int len, int rate, int rssi)
1055 {
1056 struct ieee80211_frame *wh;
1057 int i;
1058
1059 wh = (struct ieee80211_frame *)buf;
1060 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
1061 case IEEE80211_FC1_DIR_NODS:
1062 printf("NODS %s", ether_sprintf(wh->i_addr2));
1063 printf("->%s", ether_sprintf(wh->i_addr1));
1064 printf("(%s)", ether_sprintf(wh->i_addr3));
1065 break;
1066 case IEEE80211_FC1_DIR_TODS:
1067 printf("TODS %s", ether_sprintf(wh->i_addr2));
1068 printf("->%s", ether_sprintf(wh->i_addr3));
1069 printf("(%s)", ether_sprintf(wh->i_addr1));
1070 break;
1071 case IEEE80211_FC1_DIR_FROMDS:
1072 printf("FRDS %s", ether_sprintf(wh->i_addr3));
1073 printf("->%s", ether_sprintf(wh->i_addr1));
1074 printf("(%s)", ether_sprintf(wh->i_addr2));
1075 break;
1076 case IEEE80211_FC1_DIR_DSTODS:
1077 printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
1078 printf("->%s", ether_sprintf(wh->i_addr3));
1079 printf("(%s", ether_sprintf(wh->i_addr2));
1080 printf("->%s)", ether_sprintf(wh->i_addr1));
1081 break;
1082 }
1083 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1084 case IEEE80211_FC0_TYPE_DATA:
1085 printf(" data");
1086 break;
1087 case IEEE80211_FC0_TYPE_MGT:
1088 printf(" %s", ieee80211_mgt_subtype_name[
1089 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
1090 >> IEEE80211_FC0_SUBTYPE_SHIFT]);
1091 break;
1092 default:
1093 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
1094 break;
1095 }
1096 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
1097 printf(" WEP");
1098 if (rate >= 0)
1099 printf(" %dM", rate / 2);
1100 if (rssi >= 0)
1101 printf(" +%d", rssi);
1102 printf("\n");
1103 if (len > 0) {
1104 for (i = 0; i < len; i++) {
1105 if ((i & 1) == 0)
1106 printf(" ");
1107 printf("%02x", buf[i]);
1108 }
1109 printf("\n");
1110 }
1111 }
1112
1113 void
ieee80211_watchdog(struct ifnet * ifp)1114 ieee80211_watchdog(struct ifnet *ifp)
1115 {
1116 struct ieee80211com *ic = (void *)ifp;
1117 if (ic->ic_mgt_timer) {
1118 if (--ic->ic_mgt_timer == 0)
1119 ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
1120 }
1121 if (ic->ic_inact_timer) {
1122 if (--ic->ic_inact_timer == 0) {
1123 struct ieee80211_node *ni, *nextbs;
1124 for (ni = TAILQ_FIRST(&ic->ic_node); ni != NULL; ) {
1125 if (++ni->ni_inact <= IEEE80211_INACT_MAX) {
1126 ni = TAILQ_NEXT(ni, ni_list);
1127 continue;
1128 }
1129 if (ifp->if_flags & IFF_DEBUG)
1130 printf("%s: station %s deauthenticate"
1131 " (reason %d)\n",
1132 ifp->if_xname,
1133 ether_sprintf(ni->ni_macaddr),
1134 IEEE80211_REASON_AUTH_EXPIRE);
1135 nextbs = TAILQ_NEXT(ni, ni_list);
1136 IEEE80211_SEND_MGMT(ic, ni,
1137 IEEE80211_FC0_SUBTYPE_DEAUTH,
1138 IEEE80211_REASON_AUTH_EXPIRE);
1139 ieee80211_free_node(ic, ni);
1140 ni = nextbs;
1141 }
1142 if (!TAILQ_EMPTY(&ic->ic_node))
1143 ic->ic_inact_timer = IEEE80211_INACT_WAIT;
1144 }
1145 }
1146 if (ic->ic_mgt_timer != 0 || ic->ic_inact_timer != 0)
1147 ifp->if_timer = 1;
1148 }
1149
1150 static void
ieee80211_begin_scan(struct ifnet * ifp,struct ieee80211_node * ni)1151 ieee80211_begin_scan(struct ifnet *ifp, struct ieee80211_node *ni)
1152 {
1153 struct ieee80211com *ic = (void *)ifp;
1154 int i;
1155
1156 memcpy(ic->ic_chan_scan, ic->ic_chan_active,
1157 sizeof(ic->ic_chan_scan));
1158
1159 DPRINTF(("ieee80211_begin_scan: scanning"));
1160 for (i = 0; i < sizeof(ic->ic_chan_scan) * NBBY; i++) {
1161 if (!isset(ic->ic_chan_scan, i))
1162 continue;
1163 DPRINTF((" %d", i));
1164 ni->ni_chan = i;
1165 }
1166 DPRINTF(("\n"));
1167 clrbit(ic->ic_chan_scan, ni->ni_chan);
1168 ic->ic_flags |= IEEE80211_F_ASCAN;
1169 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
1170 }
1171
1172 void
ieee80211_next_scan(struct ifnet * ifp)1173 ieee80211_next_scan(struct ifnet *ifp)
1174 {
1175 struct ieee80211com *ic = (void *)ifp;
1176 int chan, s;
1177
1178 s = splnet();
1179
1180 chan = ic->ic_bss.ni_chan;
1181 for (;;) {
1182 chan = (chan + 1) % (IEEE80211_CHAN_MAX + 1);
1183 if (isset(ic->ic_chan_scan, chan))
1184 break;
1185 if (chan == ic->ic_bss.ni_chan) {
1186 DPRINTF(("ieee80211_next_scan: no chan available\n"));
1187 ieee80211_end_scan(ifp);
1188 splx(s);
1189 return;
1190 }
1191 }
1192 clrbit(ic->ic_chan_scan, chan);
1193 DPRINTF(("ieee80211_next_scan: chan %d->%d\n",
1194 ic->ic_bss.ni_chan, chan));
1195 ic->ic_bss.ni_chan = chan;
1196 ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
1197 splx(s);
1198 }
1199
1200 void
ieee80211_create_ibss(struct ieee80211com * ic)1201 ieee80211_create_ibss(struct ieee80211com *ic)
1202 {
1203 struct ifnet *ifp = &ic->ic_if;
1204 struct ieee80211_node *ni;
1205 int i;
1206
1207 ni = &ic->ic_bss;
1208 if (ifp->if_flags & IFF_DEBUG)
1209 printf("%s: creating ibss\n", ifp->if_xname);
1210 ic->ic_flags |= IEEE80211_F_SIBSS;
1211 ni->ni_nrate = 0;
1212 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
1213 if (ic->ic_sup_rates[i])
1214 ni->ni_rates[ni->ni_nrate++] =
1215 ic->ic_sup_rates[i];
1216 }
1217 IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
1218 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
1219 ni->ni_bssid[0] |= 0x02; /* local bit for IBSS */
1220 ni->ni_esslen = ic->ic_des_esslen;
1221 memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
1222 ni->ni_rssi = 0;
1223 ni->ni_rstamp = 0;
1224 memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
1225 ni->ni_intval = ic->ic_lintval;
1226 ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
1227 if (ic->ic_flags & IEEE80211_F_WEPON)
1228 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
1229 ni->ni_chan = ic->ic_ibss_chan;
1230 if (ic->ic_phytype == IEEE80211_T_FH) {
1231 ni->ni_fhdwell = 200; /* XXX */
1232 ni->ni_fhindex = 1;
1233 }
1234 ieee80211_new_state(ifp, IEEE80211_S_RUN, -1);
1235 }
1236
1237 int
ieee80211_match_bss(struct ieee80211com * ic,struct ieee80211_node * ni)1238 ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
1239 {
1240 struct ifnet *ifp = &ic->ic_if;
1241 u_int8_t rate;
1242 int fail;
1243
1244 fail = 0;
1245 if (isclr(ic->ic_chan_active, ni->ni_chan))
1246 fail |= 0x01;
1247 if (ic->ic_des_chan != IEEE80211_CHAN_ANY &&
1248 ni->ni_chan != ic->ic_des_chan)
1249 fail |= 0x01;
1250 if (ic->ic_opmode == IEEE80211_M_IBSS) {
1251 if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
1252 fail |= 0x02;
1253 } else {
1254 if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
1255 fail |= 0x02;
1256 }
1257 if (ic->ic_flags & IEEE80211_F_WEPON) {
1258 if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
1259 fail |= 0x04;
1260 } else {
1261 if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
1262 fail |= 0x04;
1263 }
1264 rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
1265 if (rate & IEEE80211_RATE_BASIC)
1266 fail |= 0x08;
1267 if (ic->ic_des_esslen != 0 &&
1268 (ni->ni_esslen != ic->ic_des_esslen ||
1269 memcmp(ni->ni_essid, ic->ic_des_essid,
1270 ic->ic_des_esslen) != 0))
1271 fail |= 0x10;
1272 if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
1273 !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
1274 fail |= 0x20;
1275 if (ifp->if_flags & IFF_DEBUG) {
1276 printf(" %c %s", fail ? '-' : '+',
1277 ether_sprintf(ni->ni_macaddr));
1278 printf(" %s%c", ether_sprintf(ni->ni_bssid),
1279 fail & 0x20 ? '!' : ' ');
1280 printf(" %3d%c", ni->ni_chan,
1281 fail & 0x01 ? '!' : ' ');
1282 printf(" %+4d", ni->ni_rssi);
1283 printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
1284 fail & 0x08 ? '!' : ' ');
1285 printf(" %4s%c",
1286 (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
1287 (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
1288 "????",
1289 fail & 0x02 ? '!' : ' ');
1290 printf(" %3s%c ",
1291 (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
1292 "wep" : "no",
1293 fail & 0x04 ? '!' : ' ');
1294 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
1295 printf("%s\n", fail & 0x10 ? "!" : "");
1296 }
1297 return (fail);
1298 }
1299
1300 void
ieee80211_end_scan(struct ifnet * ifp)1301 ieee80211_end_scan(struct ifnet *ifp)
1302 {
1303 struct ieee80211com *ic = (void *)ifp;
1304 struct ieee80211_node *ni, *nextbs, *selbs;
1305 void *p;
1306
1307 ni = TAILQ_FIRST(&ic->ic_node);
1308 if (ni == NULL) {
1309 DPRINTF(("ieee80211_end_scan: no scan candidate\n"));
1310 notfound:
1311 if (ic->ic_opmode == IEEE80211_M_IBSS &&
1312 (ic->ic_flags & IEEE80211_F_IBSSON) &&
1313 ic->ic_des_esslen != 0) {
1314 ieee80211_create_ibss(ic);
1315 return;
1316 }
1317 if (ic->ic_flags & IEEE80211_F_ASCAN) {
1318 if (ifp->if_flags & IFF_DEBUG)
1319 printf("%s: entering passive scan mode\n",
1320 ifp->if_xname);
1321 ic->ic_flags &= ~IEEE80211_F_ASCAN;
1322 }
1323 memcpy(ic->ic_chan_scan, ic->ic_chan_active,
1324 sizeof(ic->ic_chan_active));
1325 ieee80211_next_scan(ifp);
1326 return;
1327 }
1328 selbs = NULL;
1329 if (ifp->if_flags & IFF_DEBUG)
1330 printf("%s:\tmacaddr bssid chan rssi rate flag wep essid\n",
1331 ifp->if_xname);
1332 for (; ni != NULL; ni = nextbs) {
1333 nextbs = TAILQ_NEXT(ni, ni_list);
1334 if (ni->ni_fails) {
1335 /*
1336 * The configuration of the access points may change
1337 * during my scan. So delete the entry for the AP
1338 * and retry to associate if there is another beacon.
1339 */
1340 if (ni->ni_fails++ > 2)
1341 ieee80211_free_node(ic, ni);
1342 continue;
1343 }
1344 if (ieee80211_match_bss(ic, ni) == 0) {
1345 if (selbs == NULL || ni->ni_rssi > selbs->ni_rssi)
1346 selbs = ni;
1347 }
1348 }
1349 if (selbs == NULL)
1350 goto notfound;
1351 p = ic->ic_bss.ni_private;
1352 ic->ic_bss = *selbs;
1353 ic->ic_bss.ni_private = p;
1354 if (p != NULL && ic->ic_node_privlen)
1355 memcpy(p, selbs->ni_private, ic->ic_node_privlen);
1356 if (ic->ic_opmode == IEEE80211_M_IBSS) {
1357 ieee80211_fix_rate(ic, &ic->ic_bss, IEEE80211_F_DOFRATE |
1358 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1359 if (ic->ic_bss.ni_nrate == 0) {
1360 selbs->ni_fails++;
1361 goto notfound;
1362 }
1363 ieee80211_new_state(ifp, IEEE80211_S_RUN, -1);
1364 } else
1365 ieee80211_new_state(ifp, IEEE80211_S_AUTH, -1);
1366 }
1367
1368 int
ieee80211_get_rate(struct ieee80211com * ic)1369 ieee80211_get_rate(struct ieee80211com *ic)
1370 {
1371 int rate;
1372 if (ic->ic_fixed_rate == -1) {
1373 if (ic->ic_state == IEEE80211_S_RUN)
1374 rate = ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate];
1375 else
1376 rate = 0;
1377 } else
1378 rate = ic->ic_sup_rates[ic->ic_fixed_rate];
1379 return (rate & IEEE80211_RATE_VAL);
1380 }
1381
1382 int
ieee80211_get_channel(struct ieee80211com * ic)1383 ieee80211_get_channel(struct ieee80211com *ic)
1384 {
1385 switch (ic->ic_state) {
1386 case IEEE80211_S_INIT:
1387 if (ic->ic_opmode == IEEE80211_M_STA)
1388 return (ic->ic_des_chan);
1389 else
1390 return (ic->ic_ibss_chan);
1391 case IEEE80211_S_SCAN: /* XXX could be confusing if ic_des_chan is
1392 * set
1393 */
1394 default:
1395 return (ic->ic_bss.ni_chan);
1396 }
1397 }
1398
1399
1400 struct ieee80211_node *
ieee80211_alloc_node(struct ieee80211com * ic,u_int8_t * macaddr,int copy)1401 ieee80211_alloc_node(struct ieee80211com *ic, u_int8_t *macaddr, int copy)
1402 {
1403 struct ieee80211_node *ni;
1404 int hash;
1405 int s;
1406
1407 ni = malloc(sizeof(struct ieee80211_node) + ic->ic_node_privlen,
1408 M_DEVBUF, M_NOWAIT);
1409 if (ni == NULL)
1410 return (NULL);
1411 if (copy)
1412 memcpy(ni, &ic->ic_bss, sizeof(struct ieee80211_node));
1413 else
1414 memset(ni, 0, sizeof(struct ieee80211_node));
1415 IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
1416 if (ic->ic_node_privlen) {
1417 ni->ni_private = &ni[1];
1418 memset(ni->ni_private, 0, ic->ic_node_privlen);
1419 } else
1420 ni->ni_private = NULL;
1421
1422 hash = IEEE80211_NODE_HASH(macaddr);
1423 s = splnet();
1424 TAILQ_INSERT_TAIL(&ic->ic_node, ni, ni_list);
1425 LIST_INSERT_HEAD(&ic->ic_hash[hash], ni, ni_hash);
1426 splx(s);
1427 ic->ic_inact_timer = IEEE80211_INACT_WAIT;
1428 return (ni);
1429 }
1430
1431 struct ieee80211_node *
ieee80211_find_node(struct ieee80211com * ic,u_int8_t * macaddr)1432 ieee80211_find_node(struct ieee80211com *ic, u_int8_t *macaddr)
1433 {
1434 struct ieee80211_node *ni;
1435 int hash;
1436 int s;
1437
1438 hash = IEEE80211_NODE_HASH(macaddr);
1439 s = splnet();
1440 LIST_FOREACH(ni, &ic->ic_hash[hash], ni_hash) {
1441 if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr))
1442 break;
1443 }
1444 splx(s);
1445 return (ni);
1446 }
1447
1448 void
ieee80211_free_node(struct ieee80211com * ic,struct ieee80211_node * ni)1449 ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni)
1450 {
1451 int s;
1452
1453 s = splnet();
1454 if (ic->ic_node_free != NULL)
1455 (*ic->ic_node_free)(ic, ni);
1456 IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
1457 TAILQ_REMOVE(&ic->ic_node, ni, ni_list);
1458 LIST_REMOVE(ni, ni_hash);
1459 if (!IF_IS_EMPTY(&ni->ni_savedq)) {
1460 IF_PURGE(&ni->ni_savedq);
1461 if (ic->ic_set_tim)
1462 ic->ic_set_tim(ic, ni->ni_associd, 0);
1463 }
1464 splx(s);
1465 free(ni, M_DEVBUF);
1466 if (TAILQ_EMPTY(&ic->ic_node))
1467 ic->ic_inact_timer = 0;
1468 }
1469
1470 void
ieee80211_free_allnodes(struct ieee80211com * ic)1471 ieee80211_free_allnodes(struct ieee80211com *ic)
1472 {
1473 struct ieee80211_node *ni;
1474
1475 while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL)
1476 ieee80211_free_node(ic, ni);
1477 }
1478
1479 int
ieee80211_fix_rate(struct ieee80211com * ic,struct ieee80211_node * ni,int flags)1480 ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags)
1481 {
1482 int i, j, ignore, error;
1483 int okrate, badrate;
1484 u_int8_t r;
1485
1486 error = 0;
1487 okrate = badrate = 0;
1488 for (i = 0; i < ni->ni_nrate; ) {
1489 ignore = 0;
1490 if (flags & IEEE80211_F_DOSORT) {
1491 for (j = i + 1; j < ni->ni_nrate; j++) {
1492 if ((ni->ni_rates[i] & IEEE80211_RATE_VAL) >
1493 (ni->ni_rates[j] & IEEE80211_RATE_VAL)) {
1494 r = ni->ni_rates[i];
1495 ni->ni_rates[i] = ni->ni_rates[j];
1496 ni->ni_rates[j] = r;
1497 }
1498 }
1499 }
1500 r = ni->ni_rates[i] & IEEE80211_RATE_VAL;
1501 badrate = r;
1502 if (flags & IEEE80211_F_DOFRATE) {
1503 if (ic->ic_fixed_rate >= 0 &&
1504 r != (ic->ic_sup_rates[ic->ic_fixed_rate] &
1505 IEEE80211_RATE_VAL))
1506 ignore++;
1507 }
1508 if (flags & IEEE80211_F_DONEGO) {
1509 for (j = 0; j < IEEE80211_RATE_SIZE; j++) {
1510 if (r ==
1511 (ic->ic_sup_rates[j] & IEEE80211_RATE_VAL))
1512 break;
1513 }
1514 if (j == IEEE80211_RATE_SIZE) {
1515 if (ni->ni_rates[i] & IEEE80211_RATE_BASIC)
1516 error++;
1517 ignore++;
1518 }
1519 }
1520 if (flags & IEEE80211_F_DODEL) {
1521 if (ignore) {
1522 ni->ni_nrate--;
1523 for (j = i; j < ni->ni_nrate; j++)
1524 ni->ni_rates[j] = ni->ni_rates[j + 1];
1525 ni->ni_rates[j] = 0;
1526 continue;
1527 }
1528 }
1529 if (!ignore)
1530 okrate = ni->ni_rates[i];
1531 i++;
1532 }
1533 if (okrate == 0 || error != 0)
1534 return (badrate | IEEE80211_RATE_BASIC);
1535 return (okrate & IEEE80211_RATE_VAL);
1536 }
1537
1538 static u_int8_t *
ieee80211_add_rates(u_int8_t * frm,const u_int8_t rates[IEEE80211_RATE_SIZE])1539 ieee80211_add_rates(u_int8_t *frm, const u_int8_t rates[IEEE80211_RATE_SIZE])
1540 {
1541 int i, j;
1542
1543 *frm++ = IEEE80211_ELEMID_RATES;
1544 j = 0;
1545 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
1546 if (rates[i] != 0) {
1547 frm[1 + j] = rates[i];
1548 j++;
1549 }
1550 }
1551 *frm++ = j;
1552 return (frm + j);
1553 }
1554
1555 static u_int8_t *
ieee80211_add_ssid(u_int8_t * frm,const u_int8_t * ssid,u_int len)1556 ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
1557 {
1558 *frm++ = IEEE80211_ELEMID_SSID;
1559 *frm++ = len;
1560 memcpy(frm, ssid, len);
1561 return (frm + len);
1562 }
1563
1564 void
ieee80211_pwrsave(struct ieee80211com * ic,struct ieee80211_node * ni,struct mbuf * m)1565 ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni,
1566 struct mbuf *m)
1567 {
1568 /* Store the new packet on our queue, changing the TIM if necessary */
1569
1570 if (IF_IS_EMPTY(&ni->ni_savedq)) {
1571 ic->ic_set_tim(ic, ni->ni_associd, 1);
1572 }
1573 if (ni->ni_savedq.ifq_len >= IEEE80211_PS_MAX_QUEUE) {
1574 IF_DROP(&ni->ni_savedq);
1575 m_freem(m);
1576 if (ic->ic_if.if_flags & IFF_DEBUG)
1577 printf("%s: station %s power save queue overflow"
1578 " of size %d drops %d\n",
1579 ic->ic_if.if_xname,
1580 ether_sprintf(ni->ni_macaddr),
1581 IEEE80211_PS_MAX_QUEUE,
1582 ni->ni_savedq.ifq_drops);
1583 } else {
1584 IF_ENQUEUE(&ni->ni_savedq, m);
1585 }
1586 }
1587
1588 static int
ieee80211_send_prreq(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int dummy)1589 ieee80211_send_prreq(struct ieee80211com *ic, struct ieee80211_node *ni,
1590 int type, int dummy)
1591 {
1592 int ret;
1593 struct mbuf *m;
1594 u_int8_t *frm;
1595
1596 /*
1597 * prreq frame format
1598 * [tlv] ssid
1599 * [tlv] supported rates
1600 */
1601 MGETHDR(m, M_DONTWAIT, MT_DATA);
1602 if (m == NULL)
1603 return (ENOMEM);
1604 m->m_data += IEEE80211_HEADER_LEN(ic);
1605 frm = mtod(m, u_int8_t *);
1606 frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
1607 frm = ieee80211_add_rates(frm, ic->ic_sup_rates);
1608 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1609
1610 ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
1611 ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
1612 return (ret);
1613 }
1614
1615 static int
ieee80211_send_prresp(struct ieee80211com * ic,struct ieee80211_node * bs0,int type,int dummy)1616 ieee80211_send_prresp(struct ieee80211com *ic, struct ieee80211_node *bs0,
1617 int type, int dummy)
1618 {
1619 struct mbuf *m;
1620 u_int8_t *frm;
1621 struct ieee80211_node *ni = &ic->ic_bss;
1622 u_int16_t capinfo;
1623
1624 /*
1625 * probe response frame format
1626 * [8] time stamp
1627 * [2] beacon interval
1628 * [2] cabability information
1629 * [tlv] ssid
1630 * [tlv] supported rates
1631 * [tlv] parameter set (IBSS)
1632 */
1633 MGETHDR(m, M_DONTWAIT, MT_DATA);
1634 if (m == NULL)
1635 return (ENOMEM);
1636 m->m_data += IEEE80211_HEADER_LEN(ic);
1637 frm = mtod(m, u_int8_t *);
1638
1639 memset(frm, 0, 8); /* timestamp should be filled later */
1640 frm += 8;
1641 *(u_int16_t *)frm = htole16(ni->ni_intval);
1642 frm += 2;
1643 if (ic->ic_opmode == IEEE80211_M_IBSS)
1644 capinfo = IEEE80211_CAPINFO_IBSS;
1645 else
1646 capinfo = IEEE80211_CAPINFO_ESS;
1647 if (ic->ic_flags & IEEE80211_F_WEPON)
1648 capinfo |= IEEE80211_CAPINFO_PRIVACY;
1649 *(u_int16_t *)frm = htole16(capinfo);
1650 frm += 2;
1651
1652 frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
1653 frm = ieee80211_add_rates(frm, ni->ni_rates);
1654
1655 if (ic->ic_opmode == IEEE80211_M_IBSS) {
1656 *frm++ = IEEE80211_ELEMID_IBSSPARMS;
1657 *frm++ = 2;
1658 *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */
1659 } else { /* IEEE80211_M_HOSTAP */
1660 /* TODO: TIM */
1661 *frm++ = IEEE80211_ELEMID_TIM;
1662 *frm++ = 4; /* length */
1663 *frm++ = 0; /* DTIM count */
1664 *frm++ = 1; /* DTIM period */
1665 *frm++ = 0; /* bitmap control */
1666 *frm++ = 0; /* Partial Virtual Bitmap (variable length) */
1667 }
1668 /* TODO: check MHLEN limit */
1669 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1670
1671 return (ieee80211_mgmt_output(&ic->ic_if, bs0, m, type));
1672 }
1673
1674 static int
ieee80211_send_auth(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int seq)1675 ieee80211_send_auth(struct ieee80211com *ic, struct ieee80211_node *ni,
1676 int type, int seq)
1677 {
1678 struct mbuf *m;
1679 u_int16_t *frm;
1680 int ret;
1681
1682 MGETHDR(m, M_DONTWAIT, MT_DATA);
1683 if (m == NULL)
1684 return (ENOMEM);
1685 MH_ALIGN(m, 2 * 3);
1686 m->m_pkthdr.len = m->m_len = 6;
1687 frm = mtod(m, u_int16_t *);
1688 /* TODO: shared key auth */
1689 frm[0] = htole16(IEEE80211_AUTH_ALG_OPEN);
1690 frm[1] = htole16(seq);
1691 frm[2] = 0; /* status */
1692 ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
1693 if (ic->ic_opmode == IEEE80211_M_STA)
1694 ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
1695 return (ret);
1696 }
1697
1698 static int
ieee80211_send_deauth(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int reason)1699 ieee80211_send_deauth(struct ieee80211com *ic, struct ieee80211_node *ni,
1700 int type, int reason)
1701 {
1702 struct ifnet *ifp = &ic->ic_if;
1703 struct mbuf *m;
1704
1705 if (ifp->if_flags & IFF_DEBUG)
1706 printf("%s: station %s deauthenticate (reason %d)\n",
1707 ifp->if_xname, ether_sprintf(ni->ni_macaddr), reason);
1708 MGETHDR(m, M_DONTWAIT, MT_DATA);
1709 if (m == NULL)
1710 return (ENOMEM);
1711 MH_ALIGN(m, 2);
1712 m->m_pkthdr.len = m->m_len = 2;
1713 *mtod(m, u_int16_t *) = htole16(reason);
1714 return (ieee80211_mgmt_output(&ic->ic_if, ni, m, type));
1715 }
1716
1717 static int
ieee80211_send_asreq(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int dummy)1718 ieee80211_send_asreq(struct ieee80211com *ic, struct ieee80211_node *ni,
1719 int type, int dummy)
1720 {
1721 struct mbuf *m;
1722 u_int8_t *frm;
1723 u_int16_t capinfo;
1724 int ret;
1725
1726 /*
1727 * asreq frame format
1728 * [2] capability information
1729 * [2] listen interval
1730 * [6*] current AP address (reassoc only)
1731 * [tlv] ssid
1732 * [tlv] supported rates
1733 */
1734 MGETHDR(m, M_DONTWAIT, MT_DATA);
1735 if (m == NULL)
1736 return (ENOMEM);
1737 m->m_data += IEEE80211_HEADER_LEN(ic);
1738 frm = mtod(m, u_int8_t *);
1739
1740 capinfo = 0;
1741 if (ic->ic_opmode == IEEE80211_M_IBSS)
1742 capinfo |= IEEE80211_CAPINFO_IBSS;
1743 else /* IEEE80211_M_STA */
1744 capinfo |= IEEE80211_CAPINFO_ESS;
1745 if (ic->ic_flags & IEEE80211_F_WEPON)
1746 capinfo |= IEEE80211_CAPINFO_PRIVACY;
1747 *(u_int16_t *)frm = htole16(capinfo);
1748 frm += 2;
1749
1750 *(u_int16_t *)frm = htole16(ic->ic_lintval);
1751 frm += 2;
1752
1753 if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
1754 IEEE80211_ADDR_COPY(frm, ic->ic_bss.ni_bssid);
1755 frm += IEEE80211_ADDR_LEN;
1756 }
1757
1758 frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
1759 frm = ieee80211_add_rates(frm, ic->ic_sup_rates);
1760 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1761
1762 ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
1763 ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
1764 return (ret);
1765 }
1766
1767 static int
ieee80211_send_asresp(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int status)1768 ieee80211_send_asresp(struct ieee80211com *ic, struct ieee80211_node *ni,
1769 int type, int status)
1770 {
1771 struct mbuf *m;
1772 u_int8_t *frm;
1773 u_int16_t capinfo;
1774
1775 /*
1776 * asreq frame format
1777 * [2] capability information
1778 * [2] status
1779 * [2] association ID
1780 * [tlv] supported rates
1781 */
1782 MGETHDR(m, M_DONTWAIT, MT_DATA);
1783 if (m == NULL)
1784 return (ENOMEM);
1785 m->m_data += IEEE80211_HEADER_LEN(ic);
1786 frm = mtod(m, u_int8_t *);
1787
1788 capinfo = IEEE80211_CAPINFO_ESS;
1789 if (ic->ic_flags & IEEE80211_F_WEPON)
1790 capinfo |= IEEE80211_CAPINFO_PRIVACY;
1791 *(u_int16_t *)frm = htole16(capinfo);
1792 frm += 2;
1793
1794 *(u_int16_t *)frm = htole16(status);
1795 frm += 2;
1796
1797 if (status == IEEE80211_STATUS_SUCCESS && ni != NULL)
1798 *(u_int16_t *)frm = htole16(ni->ni_associd);
1799 else
1800 *(u_int16_t *)frm = htole16(0);
1801 frm += 2;
1802
1803 if (ni != NULL)
1804 frm = ieee80211_add_rates(frm, ni->ni_rates);
1805 else
1806 frm = ieee80211_add_rates(frm, ic->ic_bss.ni_rates);
1807 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1808
1809 return (ieee80211_mgmt_output(&ic->ic_if, ni, m, type));
1810 }
1811
1812 static int
ieee80211_send_disassoc(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int reason)1813 ieee80211_send_disassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
1814 int type, int reason)
1815 {
1816 struct ifnet *ifp = &ic->ic_if;
1817 struct mbuf *m;
1818
1819 if (ifp->if_flags & IFF_DEBUG)
1820 printf("%s: station %s disassociate (reason %d)\n",
1821 ifp->if_xname, ether_sprintf(ni->ni_macaddr), reason);
1822 MGETHDR(m, M_DONTWAIT, MT_DATA);
1823 if (m == NULL)
1824 return (ENOMEM);
1825 MH_ALIGN(m, 2);
1826 m->m_pkthdr.len = m->m_len = 2;
1827 *mtod(m, u_int16_t *) = htole16(reason);
1828 return (ieee80211_mgmt_output(&ic->ic_if, ni, m,
1829 IEEE80211_FC0_SUBTYPE_DISASSOC));
1830 }
1831
1832 /* Verify the existence and length of __elem or get out. */
1833 #define IEEE80211_VERIFY_ELEMENT(__subr_name, __wh, __elem, __maxlen) \
1834 do { \
1835 if (__elem == NULL) { \
1836 DPRINTF((#__subr_name ": no " #__elem "\n")); \
1837 return; \
1838 } \
1839 if (__elem[1] > __maxlen) { \
1840 DPRINTF((#__subr_name ": bad " #__elem \
1841 " len %d from %s\n", \
1842 __elem[1], ether_sprintf(__wh->i_addr2))); \
1843 return; \
1844 } \
1845 } while (0)
1846
1847 static void
ieee80211_recv_beacon(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)1848 ieee80211_recv_beacon(struct ieee80211com *ic, struct mbuf *m0, int rssi,
1849 u_int32_t rstamp)
1850 {
1851 struct ieee80211_frame *wh;
1852 struct ieee80211_node *ni;
1853 u_int8_t *frm, *efrm, *tstamp, *bintval, *capinfo, *ssid, *rates;
1854 u_int8_t chan, fhindex;
1855 u_int16_t fhdwell;
1856
1857 if (ic->ic_opmode != IEEE80211_M_IBSS &&
1858 ic->ic_state != IEEE80211_S_SCAN) {
1859 /* XXX: may be useful for background scan */
1860 return;
1861 }
1862
1863 wh = mtod(m0, struct ieee80211_frame *);
1864 frm = (u_int8_t *)&wh[1];
1865 efrm = mtod(m0, u_int8_t *) + m0->m_len;
1866 /*
1867 * beacon frame format
1868 * [8] time stamp
1869 * [2] beacon interval
1870 * [2] cabability information
1871 * [tlv] ssid
1872 * [tlv] supported rates
1873 * [tlv] parameter set (FH/DS)
1874 */
1875 tstamp = frm; frm += 8;
1876 bintval = frm; frm += 2;
1877 capinfo = frm; frm += 2;
1878 ssid = rates = NULL;
1879 chan = ic->ic_bss.ni_chan;
1880 fhdwell = 0;
1881 fhindex = 0;
1882 while (frm < efrm) {
1883 switch (*frm) {
1884 case IEEE80211_ELEMID_SSID:
1885 ssid = frm;
1886 break;
1887 case IEEE80211_ELEMID_RATES:
1888 rates = frm;
1889 break;
1890 case IEEE80211_ELEMID_FHPARMS:
1891 if (ic->ic_phytype == IEEE80211_T_FH) {
1892 fhdwell = (frm[3] << 8) | frm[2];
1893 chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
1894 fhindex = frm[6];
1895 }
1896 break;
1897 case IEEE80211_ELEMID_DSPARMS:
1898 if (ic->ic_phytype == IEEE80211_T_DS)
1899 chan = frm[2];
1900 break;
1901 }
1902 frm += frm[1] + 2;
1903 }
1904 IEEE80211_VERIFY_ELEMENT(ieee80211_recv_beacon, wh, rates,
1905 IEEE80211_RATE_SIZE);
1906 IEEE80211_VERIFY_ELEMENT(ieee80211_recv_beacon, wh, ssid,
1907 IEEE80211_NWID_LEN);
1908 ni = ieee80211_find_node(ic, wh->i_addr2);
1909 #ifdef IEEE80211_DEBUG
1910 if (ieee80211_debug &&
1911 (ieee80211_debug > 1 || ni == NULL ||
1912 ic->ic_state == IEEE80211_S_SCAN)) {
1913 int is_prresp = ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
1914 IEEE80211_FC0_SUBTYPE_PROBE_RESP);
1915 printf("ieee80211_recv_beacon: %s%s on chan %u (bss chan %u) ",
1916 (ni == NULL ? "new " : ""),
1917 is_prresp ? "probe response" : "beacon",
1918 chan, ic->ic_bss.ni_chan);
1919 ieee80211_print_essid(ssid + 2, ssid[1]);
1920 printf(" from %s\n", ether_sprintf(wh->i_addr2));
1921 }
1922 #endif
1923 if (ni == NULL) {
1924 if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 0)) == NULL)
1925 return;
1926 ni->ni_esslen = ssid[1];
1927 memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
1928 memcpy(ni->ni_essid, ssid + 2, ssid[1]);
1929 } else if (ssid[1] != 0) {
1930 ni->ni_esslen = ssid[1];
1931 memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
1932 memcpy(ni->ni_essid, ssid + 2, ssid[1]);
1933 }
1934 IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
1935 memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
1936 ni->ni_nrate = rates[1];
1937 memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
1938 ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT);
1939 ni->ni_rssi = rssi;
1940 ni->ni_rstamp = rstamp;
1941 memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
1942 ni->ni_intval = letoh16(*(u_int16_t *)bintval);
1943 ni->ni_capinfo = letoh16(*(u_int16_t *)capinfo);
1944 ni->ni_chan = chan;
1945 ni->ni_fhdwell = fhdwell;
1946 ni->ni_fhindex = fhindex;
1947 if (ic->ic_state == IEEE80211_S_SCAN &&
1948 (ic->ic_flags & IEEE80211_F_ASCAN) == 0)
1949 ieee80211_end_scan(&ic->ic_if);
1950 }
1951
1952 static void
ieee80211_recv_prreq(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)1953 ieee80211_recv_prreq(struct ieee80211com *ic, struct mbuf *m0, int rssi,
1954 u_int32_t rstamp)
1955 {
1956 struct ieee80211_frame *wh;
1957 struct ieee80211_node *ni;
1958 u_int8_t *frm, *efrm, *ssid, *rates;
1959 u_int8_t rate;
1960 int allocbs;
1961
1962 if (ic->ic_opmode == IEEE80211_M_STA)
1963 return;
1964 if (ic->ic_state != IEEE80211_S_RUN)
1965 return;
1966
1967 wh = mtod(m0, struct ieee80211_frame *);
1968 frm = (u_int8_t *)&wh[1];
1969 efrm = mtod(m0, u_int8_t *) + m0->m_len;
1970 /*
1971 * prreq frame format
1972 * [tlv] ssid
1973 * [tlv] supported rates
1974 */
1975 ssid = rates = NULL;
1976 while (frm < efrm) {
1977 switch (*frm) {
1978 case IEEE80211_ELEMID_SSID:
1979 ssid = frm;
1980 break;
1981 case IEEE80211_ELEMID_RATES:
1982 rates = frm;
1983 break;
1984 }
1985 frm += frm[1] + 2;
1986 }
1987 IEEE80211_VERIFY_ELEMENT(ieee80211_recv_prreq, wh, rates,
1988 IEEE80211_RATE_SIZE);
1989 IEEE80211_VERIFY_ELEMENT(ieee80211_recv_prreq, wh, ssid,
1990 IEEE80211_NWID_LEN);
1991 if (ssid[1] != 0 &&
1992 (ssid[1] != ic->ic_bss.ni_esslen ||
1993 memcmp(ssid + 2, ic->ic_bss.ni_essid, ic->ic_bss.ni_esslen) != 0)) {
1994 #ifdef IEEE80211_DEBUG
1995 if (ieee80211_debug) {
1996 printf("ieee80211_recv_prreq: ssid unmatch ");
1997 ieee80211_print_essid(ssid + 2, ssid[1]);
1998 printf(" from %s\n", ether_sprintf(wh->i_addr2));
1999 }
2000 #endif
2001 return;
2002 }
2003
2004 ni = ieee80211_find_node(ic, wh->i_addr2);
2005 if (ni == NULL) {
2006 if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 1)) == NULL)
2007 return;
2008 DPRINTF(("ieee80211_recv_prreq: new req from %s\n",
2009 ether_sprintf(wh->i_addr2)));
2010 allocbs = 1;
2011 } else
2012 allocbs = 0;
2013 memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
2014 ni->ni_nrate = rates[1];
2015 memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
2016 ni->ni_rssi = rssi;
2017 ni->ni_rstamp = rstamp;
2018 rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT |
2019 IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
2020 if (rate & IEEE80211_RATE_BASIC) {
2021 DPRINTF(("ieee80211_recv_prreq: rate negotiation failed: %s\n",
2022 ether_sprintf(wh->i_addr2)));
2023 } else {
2024 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP,
2025 0);
2026 }
2027 if (allocbs && (ic->ic_opmode == IEEE80211_M_HOSTAP))
2028 ieee80211_free_node(ic, ni);
2029 }
2030
2031 static void
ieee80211_recv_auth(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2032 ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2033 u_int32_t rstamp)
2034 {
2035 struct ifnet *ifp = &ic->ic_if;
2036 struct ieee80211_frame *wh;
2037 struct ieee80211_node *ni;
2038 u_int8_t *frm, *efrm;
2039 u_int16_t algo, seq, status;
2040 int allocbs;
2041
2042 wh = mtod(m0, struct ieee80211_frame *);
2043 frm = (u_int8_t *)&wh[1];
2044 efrm = mtod(m0, u_int8_t *) + m0->m_len;
2045 /*
2046 * auth frame format
2047 * [2] algorithm
2048 * [2] sequence
2049 * [2] status
2050 * [tlv*] challenge
2051 */
2052 if (frm + 6 > efrm) {
2053 DPRINTF(("ieee80211_recv_auth: too short from %s\n",
2054 ether_sprintf(wh->i_addr2)));
2055 return;
2056 }
2057 algo = letoh16(*(u_int16_t *)frm);
2058 seq = letoh16(*(u_int16_t *)(frm + 2));
2059 status = letoh16(*(u_int16_t *)(frm + 4));
2060 if (algo != IEEE80211_AUTH_ALG_OPEN) {
2061 /* TODO: shared key auth */
2062 DPRINTF(("ieee80211_recv_auth: unsupported auth %d from %s\n",
2063 algo, ether_sprintf(wh->i_addr2)));
2064 return;
2065 }
2066 switch (ic->ic_opmode) {
2067 case IEEE80211_M_IBSS:
2068 if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
2069 return;
2070 ieee80211_new_state(&ic->ic_if, IEEE80211_S_AUTH,
2071 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2072 break;
2073
2074 case IEEE80211_M_AHDEMO:
2075 case IEEE80211_M_MONITOR:
2076 /* should not come here */
2077 break;
2078
2079 case IEEE80211_M_HOSTAP:
2080 if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
2081 return;
2082 allocbs = 0;
2083 ni = ieee80211_find_node(ic, wh->i_addr2);
2084 if (ni == NULL) {
2085 ni = ieee80211_alloc_node(ic, wh->i_addr2, 0);
2086 if (ni == NULL)
2087 return;
2088 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss.ni_bssid);
2089 allocbs = 1;
2090 }
2091 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2);
2092 if (ifp->if_flags & IFF_DEBUG)
2093 printf("%s: station %s %s authenticated\n",
2094 ifp->if_xname,
2095 (allocbs ? "newly" : "already"),
2096 ether_sprintf(ni->ni_macaddr));
2097 break;
2098
2099 case IEEE80211_M_STA:
2100 if (ic->ic_state != IEEE80211_S_AUTH || seq != 2)
2101 return;
2102 if (status != 0) {
2103 printf("%s: authentication failed (reason %d) for %s\n",
2104 ic->ic_if.if_xname, status,
2105 ether_sprintf(wh->i_addr3));
2106 ni = ieee80211_find_node(ic, wh->i_addr2);
2107 if (ni != NULL)
2108 ni->ni_fails++;
2109 return;
2110 }
2111 ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC,
2112 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2113 break;
2114 }
2115 }
2116
2117 static void
ieee80211_recv_asreq(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2118 ieee80211_recv_asreq(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2119 u_int32_t rstamp)
2120 {
2121 struct ifnet *ifp = &ic->ic_if;
2122 struct ieee80211_frame *wh;
2123 struct ieee80211_node *ni = &ic->ic_bss;
2124 u_int8_t *frm, *efrm, *ssid, *rates;
2125 u_int16_t capinfo, bintval;
2126 int reassoc, resp, newassoc;
2127
2128 if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
2129 (ic->ic_state != IEEE80211_S_RUN))
2130 return;
2131
2132 wh = mtod(m0, struct ieee80211_frame *);
2133 frm = (u_int8_t *)&wh[1];
2134 efrm = mtod(m0, u_int8_t *) + m0->m_len;
2135 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2136 IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
2137 reassoc = 1;
2138 resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
2139 } else {
2140 reassoc = 0;
2141 resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
2142 }
2143 /*
2144 * asreq frame format
2145 * [2] capability information
2146 * [2] listen interval
2147 * [6*] current AP address (reassoc only)
2148 * [tlv] ssid
2149 * [tlv] supported rates
2150 */
2151 if (frm + (reassoc ? 10 : 4) > efrm) {
2152 DPRINTF(("ieee80211_recv_asreq: too short from %s\n",
2153 ether_sprintf(wh->i_addr2)));
2154 return;
2155 }
2156
2157 if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss.ni_bssid)) {
2158 DPRINTF(("ieee80211_recv_asreq: ignore other bss from %s\n",
2159 ether_sprintf(wh->i_addr2)));
2160 return;
2161 }
2162 capinfo = letoh16(*(u_int16_t *)frm); frm += 2;
2163 bintval = letoh16(*(u_int16_t *)frm); frm += 2;
2164 if (reassoc)
2165 frm += 6; /* ignore current AP info */
2166 ssid = rates = NULL;
2167 while (frm < efrm) {
2168 switch (*frm) {
2169 case IEEE80211_ELEMID_SSID:
2170 ssid = frm;
2171 break;
2172 case IEEE80211_ELEMID_RATES:
2173 rates = frm;
2174 break;
2175 }
2176 frm += frm[1] + 2;
2177 }
2178 IEEE80211_VERIFY_ELEMENT(ieee80211_recv_asreq, wh, rates,
2179 IEEE80211_RATE_SIZE);
2180 IEEE80211_VERIFY_ELEMENT(ieee80211_recv_asreq, wh, ssid,
2181 IEEE80211_NWID_LEN);
2182 if (ssid[1] != ic->ic_bss.ni_esslen ||
2183 memcmp(ssid + 2, ic->ic_bss.ni_essid, ssid[1]) != 0) {
2184 #ifdef IEEE80211_DEBUG
2185 if (ieee80211_debug) {
2186 printf("ieee80211_recv_asreq: ssid unmatch ");
2187 ieee80211_print_essid(ssid + 2, ssid[1]);
2188 printf(" from %s\n", ether_sprintf(wh->i_addr2));
2189 }
2190 #endif
2191 return;
2192 }
2193 ni = ieee80211_find_node(ic, wh->i_addr2);
2194 if (ni == NULL) {
2195 DPRINTF(("ieee80211_recv_asreq: not authenticated for %s\n",
2196 ether_sprintf(wh->i_addr2)));
2197 if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 1)) == NULL)
2198 return;
2199 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
2200 IEEE80211_REASON_ASSOC_NOT_AUTHED);
2201 ieee80211_free_node(ic, ni);
2202 return;
2203 }
2204 if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
2205 (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
2206 ((ic->ic_flags & IEEE80211_F_WEPON) ?
2207 IEEE80211_CAPINFO_PRIVACY : 0)) {
2208 DPRINTF(("ieee80211_recv_asreq: capability unmatch %x for %s\n",
2209 capinfo, ether_sprintf(wh->i_addr2)));
2210 IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
2211 ni->ni_associd = 0;
2212 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO);
2213 return;
2214 }
2215 memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
2216 ni->ni_nrate = rates[1];
2217 memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
2218 ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
2219 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
2220 if (ni->ni_nrate == 0) {
2221 DPRINTF(("ieee80211_recv_asreq: rate unmatch for %s\n",
2222 ether_sprintf(wh->i_addr2)));
2223 IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
2224 ni->ni_associd = 0;
2225 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE);
2226 return;
2227 }
2228 ni->ni_rssi = rssi;
2229 ni->ni_rstamp = rstamp;
2230 ni->ni_intval = bintval;
2231 ni->ni_capinfo = capinfo;
2232 ni->ni_chan = ic->ic_bss.ni_chan;
2233 ni->ni_fhdwell = ic->ic_bss.ni_fhdwell;
2234 ni->ni_fhindex = ic->ic_bss.ni_fhindex;
2235 if (ni->ni_associd == 0) {
2236 u_int16_t aid;
2237
2238 /*
2239 * It would be clever to search the bitmap more efficiently,
2240 * but this will do for now.
2241 */
2242 for (aid = 1; aid < ic->ic_max_aid; aid++) {
2243 if (!IEEE80211_AID_ISSET(aid, ic->ic_aid_bitmap))
2244 break;
2245 }
2246
2247 if (ic->ic_bss.ni_associd >= ic->ic_max_aid) {
2248 IEEE80211_SEND_MGMT(ic, ni, resp,
2249 IEEE80211_REASON_ASSOC_TOOMANY);
2250 return;
2251 } else {
2252 ni->ni_associd = aid | 0xc000;
2253 IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
2254 newassoc = 1;
2255 }
2256 } else
2257 newassoc = 0;
2258 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
2259 if (ifp->if_flags & IFF_DEBUG)
2260 printf("%s: station %s %s associated at aid %d\n",
2261 ifp->if_xname, (newassoc ? "newly" : "already"),
2262 ether_sprintf(ni->ni_macaddr),
2263 (ni->ni_associd & ~0xc000));
2264 }
2265
2266 static void
ieee80211_recv_asresp(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2267 ieee80211_recv_asresp(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2268 u_int32_t rstamp)
2269 {
2270 struct ifnet *ifp = &ic->ic_if;
2271 struct ieee80211_frame *wh;
2272 struct ieee80211_node *ni = &ic->ic_bss;
2273 u_int8_t *frm, *efrm, *rates;
2274 int status;
2275
2276 if (ic->ic_opmode != IEEE80211_M_STA ||
2277 ic->ic_state != IEEE80211_S_ASSOC)
2278 return;
2279
2280 wh = mtod(m0, struct ieee80211_frame *);
2281 frm = (u_int8_t *)&wh[1];
2282 efrm = mtod(m0, u_int8_t *) + m0->m_len;
2283 /*
2284 * asresp frame format
2285 * [2] capability information
2286 * [2] status
2287 * [2] association ID
2288 * [tlv] supported rates
2289 */
2290 if (frm + 6 > efrm) {
2291 DPRINTF(("ieee80211_recv_asresp: too short from %s\n",
2292 ether_sprintf(wh->i_addr2)));
2293 return;
2294 }
2295
2296 ni->ni_capinfo = letoh16(*(u_int16_t *)frm);
2297 frm += 2;
2298
2299 status = letoh16(*(u_int16_t *)frm);
2300 frm += 2;
2301 if (status != 0) {
2302 printf("%s: association failed (reason %d) for %s\n",
2303 ifp->if_xname, status, ether_sprintf(wh->i_addr3));
2304 ni = ieee80211_find_node(ic, wh->i_addr2);
2305 if (ni != NULL)
2306 ni->ni_fails++;
2307 return;
2308 }
2309 ni->ni_associd = letoh16(*(u_int16_t *)frm);
2310 frm += 2;
2311 rates = frm;
2312
2313 IEEE80211_VERIFY_ELEMENT(ieee80211_recv_asresp, wh, rates,
2314 IEEE80211_RATE_SIZE);
2315 memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
2316 ni->ni_nrate = rates[1];
2317 memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
2318 ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
2319 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
2320 if (ni->ni_nrate == 0)
2321 return;
2322 ieee80211_new_state(ifp, IEEE80211_S_RUN,
2323 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2324 }
2325
2326 static void
ieee80211_recv_disassoc(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2327 ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2328 u_int32_t rstamp)
2329 {
2330 struct ifnet *ifp = &ic->ic_if;
2331 struct ieee80211_frame *wh;
2332 struct ieee80211_node *ni;
2333 u_int8_t *frm, *efrm;
2334 u_int16_t reason;
2335
2336 wh = mtod(m0, struct ieee80211_frame *);
2337 frm = (u_int8_t *)&wh[1];
2338 efrm = mtod(m0, u_int8_t *) + m0->m_len;
2339 /*
2340 * disassoc frame format
2341 * [2] reason
2342 */
2343 if (frm + 2 > efrm) {
2344 DPRINTF(("ieee80211_recv_disassoc: too short from %s\n",
2345 ether_sprintf(wh->i_addr2)));
2346 return;
2347 }
2348 reason = letoh16(*(u_int16_t *)frm);
2349 switch (ic->ic_opmode) {
2350 case IEEE80211_M_STA:
2351 ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC,
2352 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2353 break;
2354 case IEEE80211_M_HOSTAP:
2355 if ((ni = ieee80211_find_node(ic, wh->i_addr2)) != NULL) {
2356 if (ifp->if_flags & IFF_DEBUG)
2357 printf("%s: station %s disassociated"
2358 " by peer (reason %d)\n", ifp->if_xname,
2359 ether_sprintf(ni->ni_macaddr), reason);
2360 IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
2361 ni->ni_associd = 0;
2362 }
2363 break;
2364 default:
2365 break;
2366 }
2367 }
2368
2369 static void
ieee80211_recv_deauth(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2370 ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2371 u_int32_t rstamp)
2372 {
2373 struct ifnet *ifp = &ic->ic_if;
2374 struct ieee80211_frame *wh;
2375 struct ieee80211_node *ni;
2376 u_int8_t *frm, *efrm;
2377 u_int16_t reason;
2378
2379 wh = mtod(m0, struct ieee80211_frame *);
2380 frm = (u_int8_t *)&wh[1];
2381 efrm = mtod(m0, u_int8_t *) + m0->m_len;
2382 /*
2383 * dauth frame format
2384 * [2] reason
2385 */
2386 if (frm + 2 > efrm) {
2387 DPRINTF(("ieee80211_recv_deauth: too short from %s\n",
2388 ether_sprintf(wh->i_addr2)));
2389 return;
2390 }
2391 reason = letoh16(*(u_int16_t *)frm);
2392 switch (ic->ic_opmode) {
2393 case IEEE80211_M_STA:
2394 ieee80211_new_state(&ic->ic_if, IEEE80211_S_AUTH,
2395 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2396 break;
2397 case IEEE80211_M_HOSTAP:
2398 if ((ni = ieee80211_find_node(ic, wh->i_addr2)) != NULL) {
2399 if (ifp->if_flags & IFF_DEBUG)
2400 printf("%s: station %s deauthenticated"
2401 " by peer (reason %d)\n", ifp->if_xname,
2402 ether_sprintf(ni->ni_macaddr), reason);
2403 ieee80211_free_node(ic, ni);
2404 }
2405 break;
2406 default:
2407 break;
2408 }
2409 }
2410
2411
2412 static void
ieee80211_recv_pspoll(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2413 ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2414 u_int32_t rstamp)
2415 {
2416 struct ifnet *ifp = &ic->ic_if;
2417 struct ieee80211_frame *wh;
2418 struct ieee80211_node *ni;
2419 struct mbuf *m;
2420 u_int16_t aid;
2421
2422 if (ic->ic_set_tim == NULL) /* No powersaving functionality */
2423 return;
2424
2425 wh = mtod(m0, struct ieee80211_frame *);
2426
2427 if ((ni = ieee80211_find_node(ic, wh->i_addr2)) == NULL) {
2428 if (ifp->if_flags & IFF_DEBUG)
2429 printf("%s: station %s sent bogus power save poll\n",
2430 ifp->if_xname, ether_sprintf(wh->i_addr2));
2431 return;
2432 }
2433
2434 memcpy(&aid, wh->i_dur, sizeof(wh->i_dur));
2435 if ((aid & 0xc000) != 0xc000) {
2436 if (ifp->if_flags & IFF_DEBUG)
2437 printf("%s: station %s sent bogus aid %x\n",
2438 ifp->if_xname, ether_sprintf(wh->i_addr2), aid);
2439 return;
2440 }
2441
2442 if (aid != ni->ni_associd) {
2443 if (ifp->if_flags & IFF_DEBUG)
2444 printf("%s: station %s aid %x doesn't match pspoll "
2445 "aid %x\n",
2446 ifp->if_xname, ether_sprintf(wh->i_addr2),
2447 ni->ni_associd, aid);
2448 return;
2449 }
2450
2451 /* Okay, take the first queued packet and put it out... */
2452
2453 IF_DEQUEUE(&ni->ni_savedq, m);
2454 if (m == NULL) {
2455 if (ifp->if_flags & IFF_DEBUG)
2456 printf("%s: station %s sent pspoll, "
2457 "but no packets are saved\n",
2458 ifp->if_xname, ether_sprintf(wh->i_addr2));
2459 return;
2460 }
2461 wh = mtod(m, struct ieee80211_frame *);
2462
2463 /*
2464 * If this is the last packet, turn off the TIM fields.
2465 * If there are more packets, set the more packets bit.
2466 */
2467
2468 if (IF_IS_EMPTY(&ni->ni_savedq)) {
2469 if (ic->ic_set_tim)
2470 ic->ic_set_tim(ic, ni->ni_associd, 0);
2471 } else {
2472 wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
2473 }
2474
2475 if (ifp->if_flags & IFF_DEBUG)
2476 printf("%s: enqueued power saving packet for station %s\n",
2477 ifp->if_xname, ether_sprintf(ni->ni_macaddr));
2478
2479 IF_ENQUEUE(&ic->ic_pwrsaveq, m);
2480 (*ifp->if_start)(ifp);
2481 }
2482
2483
2484 int
ieee80211_new_state(struct ifnet * ifp,enum ieee80211_state nstate,int mgt)2485 ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt)
2486 {
2487 struct ieee80211com *ic = (void *)ifp;
2488 struct ieee80211_node *ni = &ic->ic_bss;
2489 u_int8_t old_bssid[IEEE80211_ADDR_LEN];
2490 int i, error, ostate;
2491 #ifdef IEEE80211_DEBUG
2492 static const char *stname[] =
2493 { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
2494 #endif
2495
2496 ostate = ic->ic_state;
2497 DPRINTF(("ieee80211_new_state: %s -> %s\n",
2498 stname[ostate], stname[nstate]));
2499 if (ic->ic_newstate) {
2500 error = (*ic->ic_newstate)(ic->ic_softc, nstate);
2501 if (error == EINPROGRESS)
2502 return (0);
2503 if (error != 0)
2504 return (error);
2505 }
2506
2507 /* state transition */
2508 ic->ic_state = nstate;
2509 switch (nstate) {
2510 case IEEE80211_S_INIT:
2511 switch (ostate) {
2512 case IEEE80211_S_INIT:
2513 break;
2514 case IEEE80211_S_RUN:
2515 switch (ic->ic_opmode) {
2516 case IEEE80211_M_STA:
2517 IEEE80211_SEND_MGMT(ic, ni,
2518 IEEE80211_FC0_SUBTYPE_DISASSOC,
2519 IEEE80211_REASON_ASSOC_LEAVE);
2520 break;
2521 case IEEE80211_M_HOSTAP:
2522 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
2523 if (ni->ni_associd == 0)
2524 continue;
2525 IEEE80211_SEND_MGMT(ic, ni,
2526 IEEE80211_FC0_SUBTYPE_DISASSOC,
2527 IEEE80211_REASON_ASSOC_LEAVE);
2528 }
2529 break;
2530 default:
2531 break;
2532 }
2533 /* FALLTHRU */
2534 case IEEE80211_S_ASSOC:
2535 switch (ic->ic_opmode) {
2536 case IEEE80211_M_STA:
2537 IEEE80211_SEND_MGMT(ic, ni,
2538 IEEE80211_FC0_SUBTYPE_DEAUTH,
2539 IEEE80211_REASON_AUTH_LEAVE);
2540 break;
2541 case IEEE80211_M_HOSTAP:
2542 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
2543 IEEE80211_SEND_MGMT(ic, ni,
2544 IEEE80211_FC0_SUBTYPE_DEAUTH,
2545 IEEE80211_REASON_AUTH_LEAVE);
2546 }
2547 break;
2548 default:
2549 break;
2550 }
2551 /* FALLTHRU */
2552 case IEEE80211_S_AUTH:
2553 case IEEE80211_S_SCAN:
2554 ic->ic_mgt_timer = 0;
2555 IF_PURGE(&ic->ic_mgtq);
2556 IF_PURGE(&ic->ic_pwrsaveq);
2557 if (ic->ic_wep_ctx != NULL) {
2558 free(ic->ic_wep_ctx, M_DEVBUF);
2559 ic->ic_wep_ctx = NULL;
2560 }
2561 ieee80211_free_allnodes(ic);
2562 break;
2563 }
2564 break;
2565 case IEEE80211_S_SCAN:
2566 ic->ic_flags &= ~IEEE80211_F_SIBSS;
2567 ni = &ic->ic_bss;
2568 /* initialize bss for probe request */
2569 IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);
2570 IEEE80211_ADDR_COPY(old_bssid, ic->ic_bss.ni_bssid);
2571 IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);
2572 ni->ni_nrate = 0;
2573 memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
2574 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
2575 if (ic->ic_sup_rates[i] != 0)
2576 ni->ni_rates[ni->ni_nrate++] =
2577 ic->ic_sup_rates[i];
2578 }
2579 ni->ni_associd = 0;
2580 ni->ni_rstamp = 0;
2581 switch (ostate) {
2582 case IEEE80211_S_INIT:
2583 /* use lowest rate */
2584 ni->ni_txrate = 0;
2585 ieee80211_begin_scan(ifp, ni);
2586 break;
2587 case IEEE80211_S_SCAN:
2588 /* scan next */
2589 if (ic->ic_flags & IEEE80211_F_ASCAN) {
2590 IEEE80211_SEND_MGMT(ic, ni,
2591 IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
2592 }
2593 break;
2594 case IEEE80211_S_RUN:
2595 /* beacon miss */
2596 if (ifp->if_flags & IFF_DEBUG)
2597 printf("%s: no recent beacons from %s;"
2598 " rescanning\n",
2599 ifp->if_xname, ether_sprintf(old_bssid));
2600 ieee80211_free_allnodes(ic);
2601 /* FALLTHRU */
2602 case IEEE80211_S_AUTH:
2603 case IEEE80211_S_ASSOC:
2604 /* timeout restart scan */
2605 ni = ieee80211_find_node(ic, ic->ic_bss.ni_macaddr);
2606 if (ni != NULL)
2607 ni->ni_fails++;
2608 ieee80211_begin_scan(ifp, &ic->ic_bss);
2609 break;
2610 }
2611 break;
2612 case IEEE80211_S_AUTH:
2613 switch (ostate) {
2614 case IEEE80211_S_INIT:
2615 DPRINTF(("ieee80211_new_state: invalid transition\n"));
2616 break;
2617 case IEEE80211_S_SCAN:
2618 IEEE80211_SEND_MGMT(ic, ni,
2619 IEEE80211_FC0_SUBTYPE_AUTH, 1);
2620 break;
2621 case IEEE80211_S_AUTH:
2622 case IEEE80211_S_ASSOC:
2623 switch (mgt) {
2624 case IEEE80211_FC0_SUBTYPE_AUTH:
2625 /* ??? */
2626 IEEE80211_SEND_MGMT(ic, ni,
2627 IEEE80211_FC0_SUBTYPE_AUTH, 2);
2628 break;
2629 case IEEE80211_FC0_SUBTYPE_DEAUTH:
2630 /* ignore and retry scan on timeout */
2631 break;
2632 }
2633 break;
2634 case IEEE80211_S_RUN:
2635 switch (mgt) {
2636 case IEEE80211_FC0_SUBTYPE_AUTH:
2637 IEEE80211_SEND_MGMT(ic, ni,
2638 IEEE80211_FC0_SUBTYPE_AUTH, 2);
2639 ic->ic_state = ostate; /* stay RUN */
2640 break;
2641 case IEEE80211_FC0_SUBTYPE_DEAUTH:
2642 /* try to reauth */
2643 IEEE80211_SEND_MGMT(ic, ni,
2644 IEEE80211_FC0_SUBTYPE_AUTH, 1);
2645 break;
2646 }
2647 break;
2648 }
2649 break;
2650 case IEEE80211_S_ASSOC:
2651 switch (ostate) {
2652 case IEEE80211_S_INIT:
2653 case IEEE80211_S_SCAN:
2654 case IEEE80211_S_ASSOC:
2655 DPRINTF(("ieee80211_new_state: invalid transition\n"));
2656 break;
2657 case IEEE80211_S_AUTH:
2658 IEEE80211_SEND_MGMT(ic, ni,
2659 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
2660 break;
2661 case IEEE80211_S_RUN:
2662 IEEE80211_SEND_MGMT(ic, ni,
2663 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
2664 break;
2665 }
2666 break;
2667 case IEEE80211_S_RUN:
2668 switch (ostate) {
2669 case IEEE80211_S_INIT:
2670 case IEEE80211_S_AUTH:
2671 case IEEE80211_S_RUN:
2672 DPRINTF(("ieee80211_new_state: invalid transition\n"));
2673 break;
2674 case IEEE80211_S_SCAN: /* adhoc mode */
2675 case IEEE80211_S_ASSOC: /* infra mode */
2676 if (ifp->if_flags & IFF_DEBUG) {
2677 printf("%s: ", ifp->if_xname);
2678 if (ic->ic_opmode == IEEE80211_M_STA)
2679 printf("associated ");
2680 else
2681 printf("synchronized ");
2682 printf("with %s ssid ",
2683 ether_sprintf(ic->ic_bss.ni_bssid));
2684 ieee80211_print_essid(ic->ic_bss.ni_essid,
2685 ic->ic_bss.ni_esslen);
2686 printf(" channel %d\n", ic->ic_bss.ni_chan);
2687 }
2688 /* start with highest negotiated rate */
2689 ic->ic_bss.ni_txrate = ic->ic_bss.ni_nrate - 1;
2690 ic->ic_mgt_timer = 0;
2691 (*ifp->if_start)(ifp);
2692 break;
2693 }
2694 break;
2695 }
2696 return (0);
2697 }
2698
2699 struct mbuf *
ieee80211_wep_crypt(struct ifnet * ifp,struct mbuf * m0,int txflag)2700 ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
2701 {
2702 struct ieee80211com *ic = (void *)ifp;
2703 struct mbuf *m, *n, *n0;
2704 struct ieee80211_frame *wh;
2705 int i, left, len, moff, noff, kid;
2706 u_int32_t iv, crc;
2707 u_int8_t *ivp;
2708 void *ctx;
2709 u_int8_t keybuf[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
2710 u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
2711
2712 n0 = NULL;
2713 if ((ctx = ic->ic_wep_ctx) == NULL) {
2714 ctx = malloc(RC4STATE, M_DEVBUF, M_NOWAIT);
2715 if (ctx == NULL)
2716 goto fail;
2717 ic->ic_wep_ctx = ctx;
2718 }
2719 m = m0;
2720 left = m->m_pkthdr.len;
2721 MGET(n, M_DONTWAIT, m->m_type);
2722 n0 = n;
2723 if (n == NULL)
2724 goto fail;
2725 M_MOVE_PKTHDR(n, m);
2726 len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2727 if (txflag) {
2728 n->m_pkthdr.len += len;
2729 } else {
2730 n->m_pkthdr.len -= len;
2731 left -= len;
2732 }
2733 n->m_len = MHLEN;
2734 if (n->m_pkthdr.len >= MINCLSIZE) {
2735 MCLGET(n, M_DONTWAIT);
2736 if (n->m_flags & M_EXT)
2737 n->m_len = n->m_ext.ext_size;
2738 }
2739 len = sizeof(struct ieee80211_frame);
2740 memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
2741 wh = mtod(n, struct ieee80211_frame *);
2742 left -= len;
2743 moff = len;
2744 noff = len;
2745 if (txflag) {
2746 kid = ic->ic_wep_txkey;
2747 wh->i_fc[1] |= IEEE80211_FC1_WEP;
2748 if (!ic->ic_iv_flag) {
2749 ic->ic_iv = arc4random();
2750 ic->ic_iv_flag++;
2751 } else
2752 iv = ic->ic_iv + 1;
2753 /*
2754 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2755 * (B, 255, N) with 3 <= B < 8
2756 */
2757 if (iv >= 0x03ff00 &&
2758 (iv & 0xf8ff00) == 0x00ff00)
2759 iv += 0x000100;
2760 ic->ic_iv = iv + 1;
2761 /* put iv in little endian to prepare 802.11i */
2762 ivp = mtod(n, u_int8_t *) + noff;
2763 for (i = 0; i < IEEE80211_WEP_IVLEN; i++) {
2764 ivp[i] = iv & 0xff;
2765 iv >>= 8;
2766 }
2767 ivp[IEEE80211_WEP_IVLEN] = kid << 6; /* pad and keyid */
2768 noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
2769 } else {
2770 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
2771 ivp = mtod(m, u_int8_t *) + moff;
2772 kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
2773 moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
2774 }
2775 memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN);
2776 memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].wk_key,
2777 ic->ic_nw_keys[kid].wk_len);
2778 rc4_keysetup(ctx, keybuf,
2779 IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].wk_len);
2780
2781 /* encrypt with calculating CRC */
2782 crc = ~0;
2783 while (left > 0) {
2784 len = m->m_len - moff;
2785 if (len == 0) {
2786 m = m->m_next;
2787 moff = 0;
2788 continue;
2789 }
2790 if (len > n->m_len - noff) {
2791 len = n->m_len - noff;
2792 if (len == 0) {
2793 MGET(n->m_next, M_DONTWAIT, n->m_type);
2794 if (n->m_next == NULL)
2795 goto fail;
2796 n = n->m_next;
2797 n->m_len = MLEN;
2798 if (left >= MINCLSIZE) {
2799 MCLGET(n, M_DONTWAIT);
2800 if (n->m_flags & M_EXT)
2801 n->m_len = n->m_ext.ext_size;
2802 }
2803 noff = 0;
2804 continue;
2805 }
2806 }
2807 if (len > left)
2808 len = left;
2809 rc4_crypt(ctx, mtod(n, caddr_t) + noff,
2810 mtod(m, caddr_t) + moff, len);
2811 if (txflag)
2812 crc = ieee80211_crc_update(crc,
2813 mtod(m, u_int8_t *) + moff, len);
2814 else
2815 crc = ieee80211_crc_update(crc,
2816 mtod(n, u_int8_t *) + noff, len);
2817 left -= len;
2818 moff += len;
2819 noff += len;
2820 }
2821 crc = ~crc;
2822 if (txflag) {
2823 *(u_int32_t *)crcbuf = htole32(crc);
2824 if (n->m_len >= noff + sizeof(crcbuf))
2825 n->m_len = noff + sizeof(crcbuf);
2826 else {
2827 n->m_len = noff;
2828 MGET(n->m_next, M_DONTWAIT, n->m_type);
2829 if (n->m_next == NULL)
2830 goto fail;
2831 n = n->m_next;
2832 n->m_len = sizeof(crcbuf);
2833 noff = 0;
2834 }
2835 rc4_crypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
2836 sizeof(crcbuf));
2837 } else {
2838 n->m_len = noff;
2839 for (noff = 0; noff < sizeof(crcbuf); noff += len) {
2840 len = sizeof(crcbuf) - noff;
2841 if (len > m->m_len - moff)
2842 len = m->m_len - moff;
2843 if (len > 0)
2844 rc4_crypt(ctx, crcbuf + noff,
2845 mtod(m, caddr_t) + moff, len);
2846 m = m->m_next;
2847 moff = 0;
2848 }
2849 if (crc != letoh32(*(u_int32_t *)crcbuf)) {
2850 #ifdef IEEE80211_DEBUG
2851 if (ieee80211_debug) {
2852 printf("%s: decrypt CRC error\n",
2853 ifp->if_xname);
2854 if (ieee80211_debug > 1)
2855 ieee80211_dump_pkt(n0->m_data,
2856 n0->m_len, -1, -1);
2857 }
2858 #endif
2859 goto fail;
2860 }
2861 }
2862 m_freem(m0);
2863 return (n0);
2864
2865 fail:
2866 m_freem(m0);
2867 m_freem(n0);
2868 return (NULL);
2869 }
2870
2871 /*
2872 * CRC 32 -- routine from RFC 2083
2873 */
2874
2875 /* Table of CRCs of all 8-bit messages */
2876 static u_int32_t ieee80211_crc_table[256];
2877
2878 /* Make the table for a fast CRC. */
2879 static void
ieee80211_crc_init(void)2880 ieee80211_crc_init(void)
2881 {
2882 u_int32_t c;
2883 int n, k;
2884
2885 for (n = 0; n < 256; n++) {
2886 c = (u_int32_t)n;
2887 for (k = 0; k < 8; k++) {
2888 if (c & 1)
2889 c = 0xedb88320UL ^ (c >> 1);
2890 else
2891 c = c >> 1;
2892 }
2893 ieee80211_crc_table[n] = c;
2894 }
2895 }
2896
2897 /*
2898 * Update a running CRC with the bytes buf[0..len-1]--the CRC
2899 * should be initialized to all 1's, and the transmitted value
2900 * is the 1's complement of the final running CRC
2901 */
2902
2903 static u_int32_t
ieee80211_crc_update(u_int32_t crc,u_int8_t * buf,int len)2904 ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len)
2905 {
2906 u_int8_t *endbuf;
2907
2908 for (endbuf = buf + len; buf < endbuf; buf++)
2909 crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
2910 return (crc);
2911 }
2912
2913 int
ieee80211_media_change(struct ifnet * ifp)2914 ieee80211_media_change(struct ifnet *ifp)
2915 {
2916 struct ieee80211com *ic = (void *)ifp;
2917 struct ifmedia_entry *ime;
2918 enum ieee80211_opmode newmode;
2919 int i, rate, error = 0;
2920
2921 ime = ic->ic_media.ifm_cur;
2922 if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) {
2923 i = -1;
2924 } else {
2925 rate = ieee80211_media2rate(ime->ifm_media, ic->ic_phytype);
2926 if (rate == 0)
2927 return (EINVAL);
2928 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
2929 if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) == rate)
2930 break;
2931 }
2932 if (i == IEEE80211_RATE_SIZE)
2933 return (EINVAL);
2934 }
2935 if (ic->ic_fixed_rate != i) {
2936 ic->ic_fixed_rate = i;
2937 error = ENETRESET;
2938 }
2939
2940 if ((ime->ifm_media & IFM_IEEE80211_ADHOC) &&
2941 (ime->ifm_media & IFM_FLAG0))
2942 newmode = IEEE80211_M_AHDEMO;
2943 else if (ime->ifm_media & IFM_IEEE80211_ADHOC)
2944 newmode = IEEE80211_M_IBSS;
2945 else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
2946 newmode = IEEE80211_M_HOSTAP;
2947 else if (ime->ifm_media & IFM_IEEE80211_MONITOR)
2948 newmode = IEEE80211_M_MONITOR;
2949 else
2950 newmode = IEEE80211_M_STA;
2951 if (ic->ic_opmode != newmode) {
2952 ic->ic_opmode = newmode;
2953 error = ENETRESET;
2954 }
2955 if (error == ENETRESET) {
2956 if ((ifp->if_flags & IFF_UP) != 0)
2957 error = (*ifp->if_init)(ifp);
2958 else
2959 error = 0;
2960 }
2961 if (error == 0)
2962 ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);
2963
2964 return (error);
2965 }
2966
2967 void
ieee80211_media_status(struct ifnet * ifp,struct ifmediareq * imr)2968 ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2969 {
2970 struct ieee80211com *ic = (void *)ifp;
2971 int rate;
2972
2973 imr->ifm_status = IFM_AVALID;
2974 if (ic->ic_state == IEEE80211_S_RUN)
2975 imr->ifm_status |= IFM_ACTIVE;
2976 imr->ifm_active = IFM_IEEE80211;
2977 if (ic->ic_state == IEEE80211_S_RUN)
2978 rate = ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] &
2979 IEEE80211_RATE_VAL;
2980 else {
2981 if (ic->ic_fixed_rate == -1)
2982 rate = 0;
2983 else
2984 rate = ic->ic_sup_rates[ic->ic_fixed_rate] &
2985 IEEE80211_RATE_VAL;
2986 }
2987 imr->ifm_active |= ieee80211_rate2media(rate, ic->ic_phytype);
2988 switch (ic->ic_opmode) {
2989 case IEEE80211_M_AHDEMO:
2990 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
2991 break;
2992 case IEEE80211_M_HOSTAP:
2993 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
2994 break;
2995 case IEEE80211_M_IBSS:
2996 imr->ifm_active |= IFM_IEEE80211_ADHOC;
2997 break;
2998 case IEEE80211_M_MONITOR:
2999 imr->ifm_active |= IFM_IEEE80211_MONITOR;
3000 break;
3001 case IEEE80211_M_STA:
3002 break;
3003 }
3004 }
3005
3006 /*
3007 * convert IEEE80211 rate value to ifmedia subtype.
3008 * ieee80211 rate is in unit of 0.5Mbps.
3009 */
3010
3011 int
ieee80211_rate2media(int rate,enum ieee80211_phytype phytype)3012 ieee80211_rate2media(int rate, enum ieee80211_phytype phytype)
3013 {
3014 int mword;
3015
3016 mword = 0;
3017 switch (phytype) {
3018 case IEEE80211_T_FH:
3019 switch (rate & IEEE80211_RATE_VAL) {
3020 case 0:
3021 mword = IFM_AUTO;
3022 break;
3023 case 2:
3024 mword = IFM_IEEE80211_FH1;
3025 break;
3026 case 4:
3027 mword = IFM_IEEE80211_FH2;
3028 break;
3029 default:
3030 mword = IFM_NONE;
3031 break;
3032 }
3033 break;
3034
3035 case IEEE80211_T_DS:
3036 switch (rate & IEEE80211_RATE_VAL) {
3037 case 0:
3038 mword = IFM_AUTO;
3039 break;
3040 case 2:
3041 mword = IFM_IEEE80211_DS1;
3042 break;
3043 case 4:
3044 mword = IFM_IEEE80211_DS2;
3045 break;
3046 case 11:
3047 mword = IFM_IEEE80211_DS5;
3048 break;
3049 case 22:
3050 mword = IFM_IEEE80211_DS11;
3051 break;
3052 default:
3053 mword = IFM_NONE;
3054 break;
3055 }
3056 break;
3057
3058 default:
3059 mword = IFM_MANUAL;
3060 break;
3061 }
3062 return (mword);
3063 }
3064
3065 int
ieee80211_media2rate(int mword,enum ieee80211_phytype phytype)3066 ieee80211_media2rate(int mword, enum ieee80211_phytype phytype)
3067 {
3068 int rate;
3069
3070 rate = 0;
3071 switch (phytype) {
3072 case IEEE80211_T_FH:
3073 switch (IFM_SUBTYPE(mword)) {
3074 case IFM_IEEE80211_FH1:
3075 rate = 2;
3076 break;
3077 case IFM_IEEE80211_FH2:
3078 rate = 4;
3079 break;
3080 }
3081 break;
3082
3083 case IEEE80211_T_DS:
3084 switch (IFM_SUBTYPE(mword)) {
3085 case IFM_IEEE80211_DS1:
3086 rate = 2;
3087 break;
3088 case IFM_IEEE80211_DS2:
3089 rate = 4;
3090 break;
3091 case IFM_IEEE80211_DS5:
3092 rate = 11;
3093 break;
3094 case IFM_IEEE80211_DS11:
3095 rate = 22;
3096 break;
3097 }
3098 break;
3099
3100 default:
3101 break;
3102 }
3103 return (rate);
3104 }
3105
3106 /*
3107 * XXX
3108 * Wireless LAN specific configuration interface, which is compatible
3109 * with wiconfig(8).
3110 */
3111
3112 int
ieee80211_cfgget(struct ifnet * ifp,u_long cmd,caddr_t data)3113 ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data)
3114 {
3115 struct ieee80211com *ic = (void *)ifp;
3116 int i, j, error;
3117 struct ifreq *ifr = (struct ifreq *)data;
3118 struct wi_req wreq;
3119 struct wi_ltv_keys *keys;
3120 struct wi_apinfo *ap;
3121 struct ieee80211_node *ni;
3122 #ifdef WICACHE
3123 struct wi_sigcache wsc;
3124 #endif /* WICACHE */
3125
3126 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
3127 if (error)
3128 return (error);
3129 wreq.wi_len = 0;
3130 switch (wreq.wi_type) {
3131 case WI_RID_SERIALNO:
3132 /* nothing appropriate */
3133 break;
3134 case WI_RID_NODENAME:
3135 strlcpy((char *)&wreq.wi_val[1], hostname,
3136 sizeof(wreq.wi_val) - 1);
3137 wreq.wi_val[0] = htole16(strlen(hostname));
3138 wreq.wi_len = (1 + strlen(hostname) + 1) / 2;
3139 break;
3140 case WI_RID_CURRENT_SSID:
3141 if (ic->ic_state != IEEE80211_S_RUN) {
3142 wreq.wi_val[0] = 0;
3143 wreq.wi_len = 1;
3144 break;
3145 }
3146 wreq.wi_val[0] = htole16(ic->ic_bss.ni_esslen);
3147 memcpy(&wreq.wi_val[1], ic->ic_bss.ni_essid,
3148 ic->ic_bss.ni_esslen);
3149 wreq.wi_len = (1 + ic->ic_bss.ni_esslen + 1) / 2;
3150 break;
3151 case WI_RID_OWN_SSID:
3152 case WI_RID_DESIRED_SSID:
3153 wreq.wi_val[0] = htole16(ic->ic_des_esslen);
3154 memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen);
3155 wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2;
3156 break;
3157 case WI_RID_CURRENT_BSSID:
3158 if (ic->ic_state == IEEE80211_S_RUN)
3159 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss.ni_bssid);
3160 else
3161 memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN);
3162 wreq.wi_len = IEEE80211_ADDR_LEN / 2;
3163 break;
3164 case WI_RID_CHANNEL_LIST:
3165 memset(wreq.wi_val, 0, sizeof(wreq.wi_val));
3166 /*
3167 * Since channel 0 is not available for DS, channel 1
3168 * is assigned to LSB on WaveLAN.
3169 */
3170 if (ic->ic_phytype == IEEE80211_T_DS)
3171 i = 1;
3172 else
3173 i = 0;
3174 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
3175 if (isset(ic->ic_chan_active, i)) {
3176 setbit((u_int8_t *)wreq.wi_val, j);
3177 wreq.wi_len = j / 16 + 1;
3178 }
3179 }
3180 break;
3181 case WI_RID_OWN_CHNL:
3182 wreq.wi_val[0] = htole16(ic->ic_ibss_chan);
3183 wreq.wi_len = 1;
3184 break;
3185 case WI_RID_CURRENT_CHAN:
3186 wreq.wi_val[0] = htole16(ic->ic_bss.ni_chan);
3187 wreq.wi_len = 1;
3188 break;
3189 case WI_RID_COMMS_QUALITY:
3190 wreq.wi_val[0] = 0; /* quality */
3191 wreq.wi_val[1] = htole16(ic->ic_bss.ni_rssi); /* signal */
3192 wreq.wi_val[2] = 0; /* noise */
3193 wreq.wi_len = 3;
3194 break;
3195 case WI_RID_PROMISC:
3196 wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0);
3197 wreq.wi_len = 1;
3198 break;
3199 case WI_RID_PORTTYPE:
3200 wreq.wi_val[0] = htole16(ic->ic_opmode);
3201 wreq.wi_len = 1;
3202 break;
3203 case WI_RID_MAC_NODE:
3204 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr);
3205 wreq.wi_len = IEEE80211_ADDR_LEN / 2;
3206 break;
3207 case WI_RID_TX_RATE:
3208 if (ic->ic_fixed_rate == -1)
3209 wreq.wi_val[0] = 0; /* auto */
3210 else
3211 wreq.wi_val[0] = htole16(
3212 (ic->ic_sup_rates[ic->ic_fixed_rate] &
3213 IEEE80211_RATE_VAL) / 2);
3214 wreq.wi_len = 1;
3215 break;
3216 case WI_RID_CUR_TX_RATE:
3217 wreq.wi_val[0] = htole16(
3218 (ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] &
3219 IEEE80211_RATE_VAL) / 2);
3220 wreq.wi_len = 1;
3221 break;
3222 case WI_RID_RTS_THRESH:
3223 wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN); /* TODO: RTS */
3224 wreq.wi_len = 1;
3225 break;
3226 case WI_RID_CREATE_IBSS:
3227 wreq.wi_val[0] =
3228 htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0);
3229 wreq.wi_len = 1;
3230 break;
3231 case WI_RID_MICROWAVE_OVEN:
3232 wreq.wi_val[0] = 0; /* no ... not supported */
3233 wreq.wi_len = 1;
3234 break;
3235 case WI_RID_ROAMING_MODE:
3236 wreq.wi_val[0] = htole16(1); /* enabled ... not supported */
3237 wreq.wi_len = 1;
3238 break;
3239 case WI_RID_SYSTEM_SCALE:
3240 wreq.wi_val[0] = htole16(1); /* low density ... not supp */
3241 wreq.wi_len = 1;
3242 break;
3243 case WI_RID_PM_ENABLED:
3244 wreq.wi_val[0] =
3245 htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
3246 wreq.wi_len = 1;
3247 break;
3248 case WI_RID_MAX_SLEEP:
3249 wreq.wi_val[0] = htole16(ic->ic_lintval);
3250 wreq.wi_len = 1;
3251 break;
3252 case WI_RID_CUR_BEACON_INT:
3253 wreq.wi_val[0] = htole16(ic->ic_bss.ni_intval);
3254 wreq.wi_len = 1;
3255 break;
3256 case WI_RID_WEP_AVAIL:
3257 wreq.wi_val[0] =
3258 htole16((ic->ic_flags & IEEE80211_F_HASWEP) ? 1 : 0);
3259 wreq.wi_len = 1;
3260 break;
3261 case WI_RID_CNFAUTHMODE:
3262 wreq.wi_val[0] = htole16(1); /* TODO: open system only */
3263 wreq.wi_len = 1;
3264 break;
3265 case WI_RID_ENCRYPTION:
3266 wreq.wi_val[0] =
3267 htole16((ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0);
3268 wreq.wi_len = 1;
3269 break;
3270 case WI_RID_TX_CRYPT_KEY:
3271 wreq.wi_val[0] = htole16(ic->ic_wep_txkey);
3272 wreq.wi_len = 1;
3273 break;
3274 case WI_RID_DEFLT_CRYPT_KEYS:
3275 keys = (struct wi_ltv_keys *)&wreq;
3276 /* do not show keys to non-root user */
3277 error = suser(curproc, 0);
3278 if (error) {
3279 memset(keys, 0, sizeof(*keys));
3280 error = 0;
3281 break;
3282 }
3283 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
3284 keys->wi_keys[i].wi_keylen =
3285 htole16(ic->ic_nw_keys[i].wk_len);
3286 memcpy(keys->wi_keys[i].wi_keydat,
3287 ic->ic_nw_keys[i].wk_key, ic->ic_nw_keys[i].wk_len);
3288 }
3289 wreq.wi_len = sizeof(*keys) / 2;
3290 break;
3291 case WI_RID_MAX_DATALEN:
3292 wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN); /* TODO: frag */
3293 wreq.wi_len = 1;
3294 break;
3295 case WI_RID_IFACE_STATS:
3296 /* XXX: should be implemented in lower drivers */
3297 break;
3298 case WI_RID_READ_APS:
3299 if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
3300 for (i = 0; i < IEEE80211_PSCAN_WAIT; i++) {
3301 tsleep((caddr_t)ic, PWAIT | PCATCH, "i80211",
3302 hz);
3303 if (ic->ic_state != IEEE80211_S_SCAN ||
3304 (ic->ic_flags & IEEE80211_F_SCANAP) == 0 ||
3305 (ic->ic_flags & IEEE80211_F_ASCAN) == 0)
3306 break;
3307 }
3308 ic->ic_flags &= ~IEEE80211_F_SCANAP;
3309 memcpy(ic->ic_chan_active, ic->ic_chan_avail,
3310 sizeof(ic->ic_chan_active));
3311 }
3312 i = 0;
3313 ap = (void *)((char *)wreq.wi_val + sizeof(i));
3314 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
3315 if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1))
3316 break;
3317 memset(ap, 0, sizeof(*ap));
3318 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
3319 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr);
3320 ap->namelen = ic->ic_des_esslen;
3321 if (ic->ic_des_esslen)
3322 memcpy(ap->name, ic->ic_des_essid,
3323 ic->ic_des_esslen);
3324 } else {
3325 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid);
3326 ap->namelen = ni->ni_esslen;
3327 if (ni->ni_esslen)
3328 memcpy(ap->name, ni->ni_essid,
3329 ni->ni_esslen);
3330 }
3331 ap->channel = ni->ni_chan;
3332 ap->signal = ni->ni_rssi;
3333 ap->capinfo = ni->ni_capinfo;
3334 ap->interval = ni->ni_intval;
3335 for (j = 0; j < ni->ni_nrate; j++) {
3336 if (ni->ni_rates[j] & IEEE80211_RATE_BASIC) {
3337 ap->rate = (ni->ni_rates[j] &
3338 IEEE80211_RATE_VAL) * 5; /* XXX */
3339 }
3340 }
3341 i++;
3342 ap++;
3343 }
3344 memcpy(wreq.wi_val, &i, sizeof(i));
3345 wreq.wi_len = (sizeof(int) + sizeof(*ap) * i) / 2;
3346 break;
3347 #ifdef WICACHE
3348 case WI_RID_READ_CACHE:
3349 i = 0;
3350 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
3351 if (i == MAXWICACHE)
3352 break;
3353 IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr);
3354 memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc));
3355 wsc.signal = ni->ni_rssi;
3356 wsc.noise = 0;
3357 wsc.quality = 0;
3358 memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
3359 &wsc, sizeof(wsc));
3360 i++;
3361 }
3362 wreq.wi_len = sizeof(wsc) * i / 2;
3363 break;
3364 #endif /* WICACHE */
3365 case WI_RID_SCAN_APS:
3366 error = EINVAL;
3367 break;
3368 default:
3369 error = EINVAL;
3370 break;
3371 }
3372 if (error == 0) {
3373 wreq.wi_len++;
3374 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
3375 }
3376 return (error);
3377 }
3378
3379 int
ieee80211_cfgset(struct ifnet * ifp,u_long cmd,caddr_t data)3380 ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data)
3381 {
3382 struct ieee80211com *ic = (void *)ifp;
3383 int i, j, len, error;
3384 struct ifreq *ifr = (struct ifreq *)data;
3385 struct wi_ltv_keys *keys;
3386 struct wi_req wreq;
3387 u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)];
3388
3389 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
3390 if (error)
3391 return (error);
3392 if (wreq.wi_len-- < 1)
3393 return (EINVAL);
3394 switch (wreq.wi_type) {
3395 case WI_RID_SERIALNO:
3396 case WI_RID_NODENAME:
3397 return (EPERM);
3398 case WI_RID_CURRENT_SSID:
3399 return (EPERM);
3400 case WI_RID_OWN_SSID:
3401 case WI_RID_DESIRED_SSID:
3402 len = letoh16(wreq.wi_val[0]);
3403 if (wreq.wi_len < (1 + len + 1) / 2)
3404 return (EINVAL);
3405 if (len > IEEE80211_NWID_LEN)
3406 return (EINVAL);
3407 ic->ic_des_esslen = len;
3408 memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid));
3409 memcpy(ic->ic_des_essid, &wreq.wi_val[1], len);
3410 error = ENETRESET;
3411 break;
3412 case WI_RID_CURRENT_BSSID:
3413 return (EPERM);
3414 case WI_RID_OWN_CHNL:
3415 if (wreq.wi_len != 1)
3416 return (EINVAL);
3417 i = letoh16(wreq.wi_val[0]);
3418 if (i < 0 ||
3419 i > IEEE80211_CHAN_MAX ||
3420 isclr(ic->ic_chan_active, i))
3421 return (EINVAL);
3422 ic->ic_ibss_chan = i;
3423 if (ic->ic_flags & IEEE80211_F_SIBSS)
3424 error = ENETRESET;
3425 break;
3426 case WI_RID_CURRENT_CHAN:
3427 return (EPERM);
3428 case WI_RID_COMMS_QUALITY:
3429 return (EPERM);
3430 case WI_RID_PROMISC:
3431 if (wreq.wi_len != 1)
3432 return (EINVAL);
3433 if (ifp->if_flags & IFF_PROMISC) {
3434 if (wreq.wi_val[0] == 0) {
3435 ifp->if_flags &= ~IFF_PROMISC;
3436 error = ENETRESET;
3437 }
3438 } else {
3439 if (wreq.wi_val[0] != 0) {
3440 ifp->if_flags |= IFF_PROMISC;
3441 error = ENETRESET;
3442 }
3443 }
3444 break;
3445 case WI_RID_PORTTYPE:
3446 if (wreq.wi_len != 1)
3447 return (EINVAL);
3448 switch (letoh16(wreq.wi_val[0])) {
3449 case IEEE80211_M_STA:
3450 break;
3451 case IEEE80211_M_IBSS:
3452 if (!(ic->ic_flags & IEEE80211_F_HASIBSS))
3453 return (EINVAL);
3454 break;
3455 case IEEE80211_M_AHDEMO:
3456 if (ic->ic_phytype != IEEE80211_T_DS ||
3457 !(ic->ic_flags & IEEE80211_F_HASAHDEMO))
3458 return (EINVAL);
3459 break;
3460 case IEEE80211_M_HOSTAP:
3461 if (!(ic->ic_flags & IEEE80211_F_HASHOSTAP))
3462 return (EINVAL);
3463 break;
3464 default:
3465 return (EINVAL);
3466 }
3467 if (letoh16(wreq.wi_val[0]) != ic->ic_opmode) {
3468 ic->ic_opmode = letoh16(wreq.wi_val[0]);
3469 error = ENETRESET;
3470 }
3471 break;
3472 case WI_RID_MAC_NODE:
3473 if (wreq.wi_len != IEEE80211_ADDR_LEN / 2)
3474 return (EINVAL);
3475 IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val);
3476 /* if_init will copy lladdr into ic_myaddr */
3477 error = ENETRESET;
3478 break;
3479 case WI_RID_TX_RATE:
3480 if (wreq.wi_len != 1)
3481 return (EINVAL);
3482 if (wreq.wi_val[0] == 0) {
3483 /* auto */
3484 ic->ic_fixed_rate = -1;
3485 break;
3486 }
3487 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
3488 if (letoh16(wreq.wi_val[0]) ==
3489 (ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) / 2)
3490 break;
3491 }
3492 if (i == IEEE80211_RATE_SIZE)
3493 return (EINVAL);
3494 ic->ic_fixed_rate = i;
3495 error = ENETRESET;
3496 break;
3497 case WI_RID_CUR_TX_RATE:
3498 return (EPERM);
3499 case WI_RID_RTS_THRESH:
3500 if (wreq.wi_len != 1)
3501 return (EINVAL);
3502 if (letoh16(wreq.wi_val[0]) != IEEE80211_MAX_LEN)
3503 return (EINVAL); /* TODO: RTS */
3504 break;
3505 case WI_RID_CREATE_IBSS:
3506 if (wreq.wi_len != 1)
3507 return (EINVAL);
3508 if (wreq.wi_val[0] != 0) {
3509 if ((ic->ic_flags & IEEE80211_F_HASIBSS) == 0)
3510 return (EINVAL);
3511 if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) {
3512 ic->ic_flags |= IEEE80211_F_IBSSON;
3513 if (ic->ic_opmode == IEEE80211_M_IBSS &&
3514 ic->ic_state == IEEE80211_S_SCAN)
3515 error = ENETRESET;
3516 }
3517 } else {
3518 if (ic->ic_flags & IEEE80211_F_IBSSON) {
3519 ic->ic_flags &= ~IEEE80211_F_IBSSON;
3520 if (ic->ic_flags & IEEE80211_F_SIBSS) {
3521 ic->ic_flags &= ~IEEE80211_F_SIBSS;
3522 error = ENETRESET;
3523 }
3524 }
3525 }
3526 break;
3527 case WI_RID_MICROWAVE_OVEN:
3528 if (wreq.wi_len != 1)
3529 return (EINVAL);
3530 if (wreq.wi_val[0] != 0)
3531 return (EINVAL); /* not supported */
3532 break;
3533 case WI_RID_ROAMING_MODE:
3534 if (wreq.wi_len != 1)
3535 return EINVAL;
3536 if (letoh16(wreq.wi_val[0]) != 1)
3537 return (EINVAL); /* not supported */
3538 break;
3539 case WI_RID_SYSTEM_SCALE:
3540 if (wreq.wi_len != 1)
3541 return (EINVAL);
3542 if (letoh16(wreq.wi_val[0]) != 1)
3543 return (EINVAL); /* not supported */
3544 break;
3545 case WI_RID_PM_ENABLED:
3546 if (wreq.wi_len != 1)
3547 return (EINVAL);
3548 if (wreq.wi_val[0] != 0) {
3549 if ((ic->ic_flags & IEEE80211_F_HASPMGT) == 0)
3550 return (EINVAL);
3551 if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
3552 ic->ic_flags |= IEEE80211_F_PMGTON;
3553 error = ENETRESET;
3554 }
3555 } else {
3556 if (ic->ic_flags & IEEE80211_F_PMGTON) {
3557 ic->ic_flags &= ~IEEE80211_F_PMGTON;
3558 error = ENETRESET;
3559 }
3560 }
3561 break;
3562 case WI_RID_MAX_SLEEP:
3563 if (wreq.wi_len != 1)
3564 return (EINVAL);
3565 ic->ic_lintval = letoh16(wreq.wi_val[0]);
3566 if (ic->ic_flags & IEEE80211_F_PMGTON)
3567 error = ENETRESET;
3568 break;
3569 case WI_RID_CUR_BEACON_INT:
3570 return (EPERM);
3571 case WI_RID_WEP_AVAIL:
3572 return (EPERM);
3573 case WI_RID_CNFAUTHMODE:
3574 if (wreq.wi_len != 1)
3575 return (EINVAL);
3576 if (letoh16(wreq.wi_val[0]) != 1)
3577 return (EINVAL); /* TODO: shared key auth */
3578 break;
3579 case WI_RID_ENCRYPTION:
3580 if (wreq.wi_len != 1)
3581 return (EINVAL);
3582 if (wreq.wi_val[0] != 0) {
3583 if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0)
3584 return (EINVAL);
3585 if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) {
3586 ic->ic_flags |= IEEE80211_F_WEPON;
3587 error = ENETRESET;
3588 }
3589 } else {
3590 if (ic->ic_flags & IEEE80211_F_WEPON) {
3591 ic->ic_flags &= ~IEEE80211_F_WEPON;
3592 error = ENETRESET;
3593 }
3594 }
3595 break;
3596 case WI_RID_TX_CRYPT_KEY:
3597 if (wreq.wi_len != 1)
3598 return (EINVAL);
3599 i = letoh16(wreq.wi_val[0]);
3600 if (i >= IEEE80211_WEP_NKID)
3601 return (EINVAL);
3602 ic->ic_wep_txkey = i;
3603 break;
3604 case WI_RID_DEFLT_CRYPT_KEYS:
3605 if (wreq.wi_len != sizeof(struct wi_ltv_keys) / 2)
3606 return (EINVAL);
3607 keys = (struct wi_ltv_keys *)&wreq;
3608 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
3609 len = letoh16(keys->wi_keys[i].wi_keylen);
3610 if (len != 0 && len < IEEE80211_WEP_KEYLEN)
3611 return (EINVAL);
3612 if (len > sizeof(ic->ic_nw_keys[i].wk_key))
3613 return (EINVAL);
3614 }
3615 memset(ic->ic_nw_keys, 0, sizeof(ic->ic_nw_keys));
3616 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
3617 len = letoh16(keys->wi_keys[i].wi_keylen);
3618 ic->ic_nw_keys[i].wk_len = len;
3619 memcpy(ic->ic_nw_keys[i].wk_key,
3620 keys->wi_keys[i].wi_keydat, len);
3621 }
3622 error = ENETRESET;
3623 break;
3624 case WI_RID_MAX_DATALEN:
3625 if (wreq.wi_len != 1)
3626 return (EINVAL);
3627 len = letoh16(wreq.wi_val[0]);
3628 if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN)
3629 return (EINVAL);
3630 if (len != IEEE80211_MAX_LEN)
3631 return (EINVAL); /* TODO: fragment */
3632 break;
3633 case WI_RID_IFACE_STATS:
3634 error = EPERM;
3635 break;
3636 case WI_RID_SCAN_APS:
3637 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
3638 break;
3639 wreq.wi_len -= 2; /* XXX: tx rate? */
3640 /* FALLTHRU */
3641 case WI_RID_CHANNEL_LIST:
3642 memset(chanlist, 0, sizeof(chanlist));
3643 /*
3644 * Since channel 0 is not available for DS, channel 1
3645 * is assigned to LSB on WaveLAN.
3646 */
3647 if (ic->ic_phytype == IEEE80211_T_DS)
3648 i = 1;
3649 else
3650 i = 0;
3651 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
3652 if (j / 16 >= wreq.wi_len)
3653 break;
3654 if (isclr((u_int8_t *)wreq.wi_val, j))
3655 continue;
3656 if (isclr(ic->ic_chan_avail, i)) {
3657 if (wreq.wi_type == WI_RID_CHANNEL_LIST)
3658 error = EPERM;
3659 else
3660 continue;
3661 }
3662 setbit(chanlist, i);
3663 }
3664 if (error == EPERM && ic->ic_chancheck != NULL)
3665 error = (*ic->ic_chancheck)(ic->ic_softc, chanlist);
3666 if (error)
3667 return (error);
3668 memcpy(ic->ic_chan_active, chanlist,
3669 sizeof(ic->ic_chan_active));
3670 if (isclr(chanlist, ic->ic_ibss_chan)) {
3671 for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
3672 if (isset(chanlist, i)) {
3673 ic->ic_ibss_chan = i;
3674 break;
3675 }
3676 }
3677 if (isclr(chanlist, ic->ic_bss.ni_chan))
3678 ic->ic_bss.ni_chan = ic->ic_ibss_chan;
3679 if (wreq.wi_type == WI_RID_CHANNEL_LIST)
3680 error = ENETRESET;
3681 else {
3682 ic->ic_flags |= IEEE80211_F_SCANAP;
3683 error = ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
3684 }
3685 break;
3686 default:
3687 error = EINVAL;
3688 break;
3689 }
3690 return (error);
3691 }
3692