Deleted Added
full compact
ieee80211_input.c (117811) ieee80211_input.c (117817)
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * Alternatively, this software may be distributed under the terms of the
18 * GNU General Public License ("GPL") version 2 as published by the Free
19 * Software Foundation.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * Alternatively, this software may be distributed under the terms of the
18 * GNU General Public License ("GPL") version 2 as published by the Free
19 * Software Foundation.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_input.c 117811 2003-07-20 21:36:08Z sam $");
34__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_input.c 117817 2003-07-21 02:49:42Z sam $");
35
36#include "opt_inet.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/mbuf.h>
41#include <sys/malloc.h>
42#include <sys/kernel.h>
43#include <sys/socket.h>
44#include <sys/sockio.h>
45#include <sys/endian.h>
46#include <sys/errno.h>
47#include <sys/bus.h>
48#include <sys/proc.h>
49#include <sys/sysctl.h>
50
51#include <machine/atomic.h>
52
53#include <net/if.h>
54#include <net/if_dl.h>
55#include <net/if_media.h>
56#include <net/if_arp.h>
57#include <net/ethernet.h>
58#include <net/if_llc.h>
59
60#include <net80211/ieee80211_var.h>
61
62#include <net/bpf.h>
63
64#ifdef INET
65#include <netinet/in.h>
66#include <netinet/if_ether.h>
67#endif
68
69void
70ieee80211_input(struct ifnet *ifp, struct mbuf *m,
71 int rssi, u_int32_t rstamp, u_int rantenna)
72{
73 struct ieee80211com *ic = (void *)ifp;
74 struct ieee80211_node *ni = NULL;
75 struct ieee80211_frame *wh;
76 struct ether_header *eh;
77 struct mbuf *m1;
78 int len;
79 u_int8_t dir, subtype;
80 u_int8_t *bssid;
81 u_int16_t rxseq;
82
83 /* trim CRC here for WEP can find its own CRC at the end of packet. */
84 if (m->m_flags & M_HASFCS) {
85 m_adj(m, -IEEE80211_CRC_LEN);
86 m->m_flags &= ~M_HASFCS;
87 }
88
89 wh = mtod(m, struct ieee80211_frame *);
90 if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
91 IEEE80211_FC0_VERSION_0) {
92 if (ifp->if_flags & IFF_DEBUG)
93 if_printf(ifp, "receive packet with wrong version: %x\n",
94 wh->i_fc[0]);
95 goto err;
96 }
97
98 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
99
100 if (ic->ic_state != IEEE80211_S_SCAN) {
101 switch (ic->ic_opmode) {
102 case IEEE80211_M_STA:
103 ni = ieee80211_ref_node(ic->ic_bss);
104 if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
105 IEEE80211_DPRINTF2(("%s: discard frame from "
106 "bss %s\n", __func__,
107 ether_sprintf(wh->i_addr2)));
108 /* not interested in */
109 ieee80211_unref_node(&ni);
110 goto out;
111 }
112 break;
113 case IEEE80211_M_IBSS:
114 case IEEE80211_M_AHDEMO:
115 case IEEE80211_M_HOSTAP:
116 if (dir == IEEE80211_FC1_DIR_NODS)
117 bssid = wh->i_addr3;
118 else
119 bssid = wh->i_addr1;
120 if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) &&
121 !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) {
122 /* not interested in */
123 IEEE80211_DPRINTF2(("%s: other bss %s\n",
124 __func__, ether_sprintf(wh->i_addr3)));
125 goto out;
126 }
127 ni = ieee80211_find_node(ic, wh->i_addr2);
128 if (ni == NULL) {
129 IEEE80211_DPRINTF2(("%s: warning, unknown src "
130 "%s\n", __func__,
131 ether_sprintf(wh->i_addr2)));
132 /*
133 * NB: Node allocation is handled in the
134 * management handling routines. Just fake
135 * up a reference to the hosts's node to do
136 * the stuff below.
137 */
138 ni = ieee80211_ref_node(ic->ic_bss);
139 }
140 break;
35
36#include "opt_inet.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/mbuf.h>
41#include <sys/malloc.h>
42#include <sys/kernel.h>
43#include <sys/socket.h>
44#include <sys/sockio.h>
45#include <sys/endian.h>
46#include <sys/errno.h>
47#include <sys/bus.h>
48#include <sys/proc.h>
49#include <sys/sysctl.h>
50
51#include <machine/atomic.h>
52
53#include <net/if.h>
54#include <net/if_dl.h>
55#include <net/if_media.h>
56#include <net/if_arp.h>
57#include <net/ethernet.h>
58#include <net/if_llc.h>
59
60#include <net80211/ieee80211_var.h>
61
62#include <net/bpf.h>
63
64#ifdef INET
65#include <netinet/in.h>
66#include <netinet/if_ether.h>
67#endif
68
69void
70ieee80211_input(struct ifnet *ifp, struct mbuf *m,
71 int rssi, u_int32_t rstamp, u_int rantenna)
72{
73 struct ieee80211com *ic = (void *)ifp;
74 struct ieee80211_node *ni = NULL;
75 struct ieee80211_frame *wh;
76 struct ether_header *eh;
77 struct mbuf *m1;
78 int len;
79 u_int8_t dir, subtype;
80 u_int8_t *bssid;
81 u_int16_t rxseq;
82
83 /* trim CRC here for WEP can find its own CRC at the end of packet. */
84 if (m->m_flags & M_HASFCS) {
85 m_adj(m, -IEEE80211_CRC_LEN);
86 m->m_flags &= ~M_HASFCS;
87 }
88
89 wh = mtod(m, struct ieee80211_frame *);
90 if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
91 IEEE80211_FC0_VERSION_0) {
92 if (ifp->if_flags & IFF_DEBUG)
93 if_printf(ifp, "receive packet with wrong version: %x\n",
94 wh->i_fc[0]);
95 goto err;
96 }
97
98 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
99
100 if (ic->ic_state != IEEE80211_S_SCAN) {
101 switch (ic->ic_opmode) {
102 case IEEE80211_M_STA:
103 ni = ieee80211_ref_node(ic->ic_bss);
104 if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
105 IEEE80211_DPRINTF2(("%s: discard frame from "
106 "bss %s\n", __func__,
107 ether_sprintf(wh->i_addr2)));
108 /* not interested in */
109 ieee80211_unref_node(&ni);
110 goto out;
111 }
112 break;
113 case IEEE80211_M_IBSS:
114 case IEEE80211_M_AHDEMO:
115 case IEEE80211_M_HOSTAP:
116 if (dir == IEEE80211_FC1_DIR_NODS)
117 bssid = wh->i_addr3;
118 else
119 bssid = wh->i_addr1;
120 if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) &&
121 !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) {
122 /* not interested in */
123 IEEE80211_DPRINTF2(("%s: other bss %s\n",
124 __func__, ether_sprintf(wh->i_addr3)));
125 goto out;
126 }
127 ni = ieee80211_find_node(ic, wh->i_addr2);
128 if (ni == NULL) {
129 IEEE80211_DPRINTF2(("%s: warning, unknown src "
130 "%s\n", __func__,
131 ether_sprintf(wh->i_addr2)));
132 /*
133 * NB: Node allocation is handled in the
134 * management handling routines. Just fake
135 * up a reference to the hosts's node to do
136 * the stuff below.
137 */
138 ni = ieee80211_ref_node(ic->ic_bss);
139 }
140 break;
141 case IEEE80211_M_MONITOR:
142 /* NB: this should collect everything */
143 goto out;
141 default:
142 /* XXX catch bad values */
143 break;
144 }
145 ni->ni_rssi = rssi;
146 ni->ni_rstamp = rstamp;
147 ni->ni_rantenna = rantenna;
148 rxseq = ni->ni_rxseq;
149 ni->ni_rxseq =
150 le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
151 /* TODO: fragment */
152 if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
153 rxseq == ni->ni_rxseq) {
154 /* duplicate, silently discarded */
155 ieee80211_unref_node(&ni);
156 goto out;
157 }
158 ni->ni_inact = 0;
159 ieee80211_unref_node(&ni);
160 }
161
162 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
163 case IEEE80211_FC0_TYPE_DATA:
164 switch (ic->ic_opmode) {
165 case IEEE80211_M_STA:
166 if (dir != IEEE80211_FC1_DIR_FROMDS)
167 goto out;
168 if ((ifp->if_flags & IFF_SIMPLEX) &&
169 IEEE80211_IS_MULTICAST(wh->i_addr1) &&
170 IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {
171 /*
172 * In IEEE802.11 network, multicast packet
173 * sent from me is broadcasted from AP.
174 * It should be silently discarded for
175 * SIMPLEX interface.
176 */
177 goto out;
178 }
179 break;
180 case IEEE80211_M_IBSS:
181 case IEEE80211_M_AHDEMO:
182 if (dir != IEEE80211_FC1_DIR_NODS)
183 goto out;
184 break;
185 case IEEE80211_M_HOSTAP:
186 if (dir != IEEE80211_FC1_DIR_TODS)
187 goto out;
188 /* check if source STA is associated */
189 ni = ieee80211_find_node(ic, wh->i_addr2);
190 if (ni == NULL) {
191 IEEE80211_DPRINTF(("%s: data from unknown src "
192 "%s\n", __func__,
193 ether_sprintf(wh->i_addr2)));
194 ni = ieee80211_dup_bss(ic, wh->i_addr2);
195 if (ni != NULL) {
196 IEEE80211_SEND_MGMT(ic, ni,
197 IEEE80211_FC0_SUBTYPE_DEAUTH,
198 IEEE80211_REASON_NOT_AUTHED);
199 ieee80211_free_node(ic, ni);
200 }
201 goto err;
202 }
203 if (ni->ni_associd == 0) {
204 IEEE80211_DPRINTF(("ieee80211_input: "
205 "data from unassoc src %s\n",
206 ether_sprintf(wh->i_addr2)));
207 IEEE80211_SEND_MGMT(ic, ni,
208 IEEE80211_FC0_SUBTYPE_DISASSOC,
209 IEEE80211_REASON_NOT_ASSOCED);
210 ieee80211_unref_node(&ni);
211 goto err;
212 }
213 ieee80211_unref_node(&ni);
214 break;
144 default:
145 /* XXX catch bad values */
146 break;
147 }
148 ni->ni_rssi = rssi;
149 ni->ni_rstamp = rstamp;
150 ni->ni_rantenna = rantenna;
151 rxseq = ni->ni_rxseq;
152 ni->ni_rxseq =
153 le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
154 /* TODO: fragment */
155 if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
156 rxseq == ni->ni_rxseq) {
157 /* duplicate, silently discarded */
158 ieee80211_unref_node(&ni);
159 goto out;
160 }
161 ni->ni_inact = 0;
162 ieee80211_unref_node(&ni);
163 }
164
165 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
166 case IEEE80211_FC0_TYPE_DATA:
167 switch (ic->ic_opmode) {
168 case IEEE80211_M_STA:
169 if (dir != IEEE80211_FC1_DIR_FROMDS)
170 goto out;
171 if ((ifp->if_flags & IFF_SIMPLEX) &&
172 IEEE80211_IS_MULTICAST(wh->i_addr1) &&
173 IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {
174 /*
175 * In IEEE802.11 network, multicast packet
176 * sent from me is broadcasted from AP.
177 * It should be silently discarded for
178 * SIMPLEX interface.
179 */
180 goto out;
181 }
182 break;
183 case IEEE80211_M_IBSS:
184 case IEEE80211_M_AHDEMO:
185 if (dir != IEEE80211_FC1_DIR_NODS)
186 goto out;
187 break;
188 case IEEE80211_M_HOSTAP:
189 if (dir != IEEE80211_FC1_DIR_TODS)
190 goto out;
191 /* check if source STA is associated */
192 ni = ieee80211_find_node(ic, wh->i_addr2);
193 if (ni == NULL) {
194 IEEE80211_DPRINTF(("%s: data from unknown src "
195 "%s\n", __func__,
196 ether_sprintf(wh->i_addr2)));
197 ni = ieee80211_dup_bss(ic, wh->i_addr2);
198 if (ni != NULL) {
199 IEEE80211_SEND_MGMT(ic, ni,
200 IEEE80211_FC0_SUBTYPE_DEAUTH,
201 IEEE80211_REASON_NOT_AUTHED);
202 ieee80211_free_node(ic, ni);
203 }
204 goto err;
205 }
206 if (ni->ni_associd == 0) {
207 IEEE80211_DPRINTF(("ieee80211_input: "
208 "data from unassoc src %s\n",
209 ether_sprintf(wh->i_addr2)));
210 IEEE80211_SEND_MGMT(ic, ni,
211 IEEE80211_FC0_SUBTYPE_DISASSOC,
212 IEEE80211_REASON_NOT_ASSOCED);
213 ieee80211_unref_node(&ni);
214 goto err;
215 }
216 ieee80211_unref_node(&ni);
217 break;
218 case IEEE80211_M_MONITOR:
219 break;
215 }
216 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
217 if (ic->ic_flags & IEEE80211_F_WEPON) {
218 m = ieee80211_wep_crypt(ifp, m, 0);
219 if (m == NULL)
220 goto err;
221 wh = mtod(m, struct ieee80211_frame *);
222 } else
223 goto out;
224 }
225 /* copy to listener after decrypt */
226 if (ic->ic_rawbpf)
227 bpf_mtap(ic->ic_rawbpf, m);
228 m = ieee80211_decap(ifp, m);
229 if (m == NULL)
230 goto err;
231 ifp->if_ipackets++;
232
233 /* perform as a bridge within the AP */
234 m1 = NULL;
235 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
236 eh = mtod(m, struct ether_header *);
237 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
238 m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
239 if (m1 == NULL)
240 ifp->if_oerrors++;
241 else
242 m1->m_flags |= M_MCAST;
243 } else {
244 ni = ieee80211_find_node(ic, eh->ether_dhost);
245 if (ni != NULL) {
246 if (ni->ni_associd != 0) {
247 m1 = m;
248 m = NULL;
249 }
250 ieee80211_unref_node(&ni);
251 }
252 }
253 if (m1 != NULL) {
254#ifdef ALTQ
255 if (ALTQ_IS_ENABLED(&ifp->if_snd))
256 altq_etherclassify(&ifp->if_snd, m1,
257 &pktattr);
258#endif
259 len = m1->m_pkthdr.len;
260 IF_ENQUEUE(&ifp->if_snd, m1);
261 if (m != NULL)
262 ifp->if_omcasts++;
263 ifp->if_obytes += len;
264 }
265 }
266 if (m != NULL)
267 (*ifp->if_input)(ifp, m);
268 return;
269
270 case IEEE80211_FC0_TYPE_MGT:
271 if (dir != IEEE80211_FC1_DIR_NODS)
272 goto err;
273 if (ic->ic_opmode == IEEE80211_M_AHDEMO)
274 goto out;
275 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
276
277 /* drop frames without interest */
278 if (ic->ic_state == IEEE80211_S_SCAN) {
279 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
280 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
281 goto out;
282 } else {
283 if (ic->ic_opmode != IEEE80211_M_IBSS &&
284 subtype == IEEE80211_FC0_SUBTYPE_BEACON)
285 goto out;
286 }
287
288 if (ifp->if_flags & IFF_DEBUG) {
289 /* avoid to print too many frames */
290 int doprint = 0;
291
292 switch (subtype) {
293 case IEEE80211_FC0_SUBTYPE_BEACON:
294 if (ic->ic_state == IEEE80211_S_SCAN)
295 doprint = 1;
296 break;
297 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
298 if (ic->ic_opmode == IEEE80211_M_IBSS)
299 doprint = 1;
300 break;
301 default:
302 doprint = 1;
303 break;
304 }
305#ifdef IEEE80211_DEBUG
306 doprint += ieee80211_debug;
307#endif
308 if (doprint)
309 if_printf(ifp, "received %s from %s rssi %d\n",
310 ieee80211_mgt_subtype_name[subtype
311 >> IEEE80211_FC0_SUBTYPE_SHIFT],
312 ether_sprintf(wh->i_addr2), rssi);
313 }
314 if (ic->ic_rawbpf)
315 bpf_mtap(ic->ic_rawbpf, m);
316 (*ic->ic_recv_mgmt)(ic, m, subtype, rssi, rstamp, rantenna);
317 m_freem(m);
318 return;
319
320 case IEEE80211_FC0_TYPE_CTL:
321 default:
322 IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, wh->i_fc[0]));
323 /* should not come here */
324 break;
325 }
326 err:
327 ifp->if_ierrors++;
328 out:
329 if (m != NULL) {
330 if (ic->ic_rawbpf)
331 bpf_mtap(ic->ic_rawbpf, m);
332 m_freem(m);
333 }
334}
335
336struct mbuf *
337ieee80211_decap(struct ifnet *ifp, struct mbuf *m)
338{
339 struct ether_header *eh;
340 struct ieee80211_frame wh;
341 struct llc *llc;
342
343 if (m->m_len < sizeof(wh) + sizeof(*llc)) {
344 m = m_pullup(m, sizeof(wh) + sizeof(*llc));
345 if (m == NULL)
346 return NULL;
347 }
348 memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
349 llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
350 if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
351 llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
352 llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
353 m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh));
354 llc = NULL;
355 } else {
356 m_adj(m, sizeof(wh) - sizeof(*eh));
357 }
358 eh = mtod(m, struct ether_header *);
359 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
360 case IEEE80211_FC1_DIR_NODS:
361 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
362 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
363 break;
364 case IEEE80211_FC1_DIR_TODS:
365 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
366 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
367 break;
368 case IEEE80211_FC1_DIR_FROMDS:
369 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
370 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
371 break;
372 case IEEE80211_FC1_DIR_DSTODS:
373 /* not yet supported */
374 IEEE80211_DPRINTF(("%s: DS to DS\n", __func__));
375 m_freem(m);
376 return NULL;
377 }
378#ifdef ALIGNED_POINTER
379 if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
380 struct mbuf *n, *n0, **np;
381 caddr_t newdata;
382 int off, pktlen;
383
384 n0 = NULL;
385 np = &n0;
386 off = 0;
387 pktlen = m->m_pkthdr.len;
388 while (pktlen > off) {
389 if (n0 == NULL) {
390 MGETHDR(n, M_DONTWAIT, MT_DATA);
391 if (n == NULL) {
392 m_freem(m);
393 return NULL;
394 }
395 M_MOVE_PKTHDR(n, m);
396 n->m_len = MHLEN;
397 } else {
398 MGET(n, M_DONTWAIT, MT_DATA);
399 if (n == NULL) {
400 m_freem(m);
401 m_freem(n0);
402 return NULL;
403 }
404 n->m_len = MLEN;
405 }
406 if (pktlen - off >= MINCLSIZE) {
407 MCLGET(n, M_DONTWAIT);
408 if (n->m_flags & M_EXT)
409 n->m_len = n->m_ext.ext_size;
410 }
411 if (n0 == NULL) {
412 newdata =
413 (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
414 sizeof(*eh);
415 n->m_len -= newdata - n->m_data;
416 n->m_data = newdata;
417 }
418 if (n->m_len > pktlen - off)
419 n->m_len = pktlen - off;
420 m_copydata(m, off, n->m_len, mtod(n, caddr_t));
421 off += n->m_len;
422 *np = n;
423 np = &n->m_next;
424 }
425 m_freem(m);
426 m = n0;
427 }
428#endif /* ALIGNED_POINTER */
429 if (llc != NULL) {
430 eh = mtod(m, struct ether_header *);
431 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
432 }
433 return m;
434}
435
436/*
437 * Install received rate set information in the node's state block.
438 */
439static int
440ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
441 u_int8_t *rates, u_int8_t *xrates, int flags)
442{
443 struct ieee80211_rateset *rs = &ni->ni_rates;
444
445 memset(rs, 0, sizeof(*rs));
446 rs->rs_nrates = rates[1];
447 memcpy(rs->rs_rates, rates + 2, rs->rs_nrates);
448 if (xrates != NULL) {
449 u_int8_t nxrates;
450 /*
451 * Tack on 11g extended supported rate element.
452 */
453 nxrates = xrates[1];
454 if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
455 nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates;
456 IEEE80211_DPRINTF(("%s: extended rate set too large;"
457 " only using %u of %u rates\n",
458 __func__, nxrates, xrates[1]));
459 }
460 memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
461 rs->rs_nrates += nxrates;
462 }
463 return ieee80211_fix_rate(ic, ni, flags);
464}
465
466/* XXX statistics */
467/* Verify the existence and length of __elem or get out. */
468#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \
469 if ((__elem) == NULL) { \
470 IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n", \
471 __func__, ieee80211_mgt_subtype_name[subtype >> \
472 IEEE80211_FC0_SUBTYPE_SHIFT])); \
473 return; \
474 } \
475 if ((__elem)[1] > (__maxlen)) { \
476 IEEE80211_DPRINTF(("%s: bad " #__elem " len %d in %s " \
477 "frame from %s\n", __func__, (__elem)[1], \
478 ieee80211_mgt_subtype_name[subtype >> \
479 IEEE80211_FC0_SUBTYPE_SHIFT], \
480 ether_sprintf(wh->i_addr2))); \
481 return; \
482 } \
483} while (0)
484
485#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \
486 if ((_len) < (_minlen)) { \
487 IEEE80211_DPRINTF(("%s: %s frame too short from %s\n", \
488 __func__, \
489 ieee80211_mgt_subtype_name[subtype >> \
490 IEEE80211_FC0_SUBTYPE_SHIFT], \
491 ether_sprintf(wh->i_addr2))); \
492 return; \
493 } \
494} while (0)
495
496void
497ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, int subtype,
498 int rssi, u_int32_t rstamp, u_int rantenna)
499{
500#define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
501 struct ifnet *ifp = &ic->ic_if;
502 struct ieee80211_frame *wh;
503 struct ieee80211_node *ni;
504 u_int8_t *frm, *efrm;
505 u_int8_t *ssid, *rates, *xrates;
506 int reassoc, resp, newassoc, allocbs;
507
508 wh = mtod(m0, struct ieee80211_frame *);
509 frm = (u_int8_t *)&wh[1];
510 efrm = mtod(m0, u_int8_t *) + m0->m_len;
511 switch (subtype) {
512 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
513 case IEEE80211_FC0_SUBTYPE_BEACON: {
514 u_int8_t *tstamp, *bintval, *capinfo, *country;
515 u_int8_t chan, bchan, fhindex, erp;
516 u_int16_t fhdwell;
517
518 if (ic->ic_opmode != IEEE80211_M_IBSS &&
519 ic->ic_state != IEEE80211_S_SCAN) {
520 /* XXX: may be useful for background scan */
521 return;
522 }
523
524 /*
525 * beacon/probe response frame format
526 * [8] time stamp
527 * [2] beacon interval
528 * [2] capability information
529 * [tlv] ssid
530 * [tlv] supported rates
531 * [tlv] country information
532 * [tlv] parameter set (FH/DS)
533 * [tlv] erp information
534 * [tlv] extended supported rates
535 */
536 IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
537 tstamp = frm; frm += 8;
538 bintval = frm; frm += 2;
539 capinfo = frm; frm += 2;
540 ssid = rates = xrates = country = NULL;
541 bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
542 chan = bchan;
543 fhdwell = 0;
544 fhindex = 0;
545 erp = 0;
546 while (frm < efrm) {
547 switch (*frm) {
548 case IEEE80211_ELEMID_SSID:
549 ssid = frm;
550 break;
551 case IEEE80211_ELEMID_RATES:
552 rates = frm;
553 break;
554 case IEEE80211_ELEMID_COUNTRY:
555 country = frm;
556 break;
557 case IEEE80211_ELEMID_FHPARMS:
558 if (ic->ic_phytype == IEEE80211_T_FH) {
559 fhdwell = (frm[3] << 8) | frm[2];
560 chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
561 fhindex = frm[6];
562 }
563 break;
564 case IEEE80211_ELEMID_DSPARMS:
565 /*
566 * XXX hack this since depending on phytype
567 * is problematic for multi-mode devices.
568 */
569 if (ic->ic_phytype != IEEE80211_T_FH)
570 chan = frm[2];
571 break;
572 case IEEE80211_ELEMID_TIM:
573 break;
574 case IEEE80211_ELEMID_XRATES:
575 xrates = frm;
576 break;
577 case IEEE80211_ELEMID_ERP:
578 if (frm[1] != 1) {
579 IEEE80211_DPRINTF(("%s: invalid ERP "
580 "element; length %u, expecting "
581 "1\n", __func__, frm[1]));
582 break;
583 }
584 erp = frm[2];
585 break;
586 default:
587 IEEE80211_DPRINTF(("%s: element id %u/len %u "
588 "ignored\n", __func__, *frm, frm[1]));
589 break;
590 }
591 frm += frm[1] + 2;
592 }
593 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
594 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
595 if (
596#if IEEE80211_CHAN_MAX < 255
597 chan > IEEE80211_CHAN_MAX ||
598#endif
599 isclr(ic->ic_chan_active, chan)) {
600 IEEE80211_DPRINTF(("%s: ignore %s with invalid channel "
601 "%u\n", __func__,
602 ISPROBE(subtype) ? "probe response" : "beacon",
603 chan));
604 return;
605 }
606 if (chan != bchan) {
607 /*
608 * Frame was received on a channel different from the
609 * one indicated in the DS/FH params element id;
610 * silently discard it.
611 *
612 * NB: this can happen due to signal leakage.
613 */
614 IEEE80211_DPRINTF(("%s: ignore %s on channel %u marked "
615 "for channel %u\n", __func__,
616 ISPROBE(subtype) ? "probe response" : "beacon",
617 bchan, chan));
618 /* XXX statistic */
619 return;
620 }
621
622 /*
623 * Use mac and channel for lookup so we collect all
624 * potential AP's when scanning. Otherwise we may
625 * see the same AP on multiple channels and will only
626 * record the last one. We could filter APs here based
627 * on rssi, etc. but leave that to the end of the scan
628 * so we can keep the selection criteria in one spot.
629 * This may result in a bloat of the scanned AP list but
630 * it shouldn't be too much.
631 */
632 ni = ieee80211_lookup_node(ic, wh->i_addr2,
633 &ic->ic_channels[chan]);
634#ifdef IEEE80211_DEBUG
635 if (ieee80211_debug &&
636 (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) {
637 printf("%s: %s%s on chan %u (bss chan %u) ",
638 __func__, (ni == NULL ? "new " : ""),
639 ISPROBE(subtype) ? "probe response" : "beacon",
640 chan, bchan);
641 ieee80211_print_essid(ssid + 2, ssid[1]);
642 printf(" from %s\n", ether_sprintf(wh->i_addr2));
643 printf("%s: caps 0x%x bintval %u erp 0x%x\n",
644 __func__, le16toh(*(u_int16_t *)capinfo),
645 le16toh(*(u_int16_t *)bintval), erp);
646 if (country)
647 printf("%s: country info %*D\n",
648 __func__, country[1], country+2, " ");
649 }
650#endif
651 if (ni == NULL) {
652 ni = ieee80211_alloc_node(ic, wh->i_addr2);
653 if (ni == NULL)
654 return;
655 ni->ni_esslen = ssid[1];
656 memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
657 memcpy(ni->ni_essid, ssid + 2, ssid[1]);
658 } else if (ssid[1] != 0 && ISPROBE(subtype)) {
659 /*
660 * Update ESSID at probe response to adopt hidden AP by
661 * Lucent/Cisco, which announces null ESSID in beacon.
662 */
663 ni->ni_esslen = ssid[1];
664 memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
665 memcpy(ni->ni_essid, ssid + 2, ssid[1]);
666 }
667 IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
668 ni->ni_rssi = rssi;
669 ni->ni_rstamp = rstamp;
670 ni->ni_rantenna = rantenna;
671 memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
672 ni->ni_intval = le16toh(*(u_int16_t *)bintval);
673 ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo);
674 /* XXX validate channel # */
675 ni->ni_chan = &ic->ic_channels[chan];
676 ni->ni_fhdwell = fhdwell;
677 ni->ni_fhindex = fhindex;
678 ni->ni_erp = erp;
679 /* NB: must be after ni_chan is setup */
680 ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
681 ieee80211_unref_node(&ni);
682 break;
683 }
684
685 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: {
686 u_int8_t rate;
687
688 if (ic->ic_opmode == IEEE80211_M_STA)
689 return;
690 if (ic->ic_state != IEEE80211_S_RUN)
691 return;
692
693 /*
694 * prreq frame format
695 * [tlv] ssid
696 * [tlv] supported rates
697 * [tlv] extended supported rates
698 */
699 ssid = rates = xrates = NULL;
700 while (frm < efrm) {
701 switch (*frm) {
702 case IEEE80211_ELEMID_SSID:
703 ssid = frm;
704 break;
705 case IEEE80211_ELEMID_RATES:
706 rates = frm;
707 break;
708 case IEEE80211_ELEMID_XRATES:
709 xrates = frm;
710 break;
711 }
712 frm += frm[1] + 2;
713 }
714 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
715 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
716 if (ssid[1] != 0 &&
717 (ssid[1] != ic->ic_bss->ni_esslen ||
718 memcmp(ssid + 2, ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen) != 0)) {
719#ifdef IEEE80211_DEBUG
720 if (ieee80211_debug) {
721 printf("%s: ssid unmatch ", __func__);
722 ieee80211_print_essid(ssid + 2, ssid[1]);
723 printf(" from %s\n", ether_sprintf(wh->i_addr2));
724 }
725#endif
726 return;
727 }
728
729 ni = ieee80211_find_node(ic, wh->i_addr2);
730 if (ni == NULL) {
731 ni = ieee80211_dup_bss(ic, wh->i_addr2);
732 if (ni == NULL)
733 return;
734 IEEE80211_DPRINTF(("%s: new req from %s\n",
735 __func__, ether_sprintf(wh->i_addr2)));
736 allocbs = 1;
737 } else
738 allocbs = 0;
739 ni->ni_rssi = rssi;
740 ni->ni_rstamp = rstamp;
741 ni->ni_rantenna = rantenna;
742 rate = ieee80211_setup_rates(ic, ni, rates, xrates,
743 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
744 | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
745 if (rate & IEEE80211_RATE_BASIC) {
746 IEEE80211_DPRINTF(("%s: rate negotiation failed: %s\n",
747 __func__,ether_sprintf(wh->i_addr2)));
748 } else {
749 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP,
750 0);
751 }
752 if (allocbs && ic->ic_opmode == IEEE80211_M_HOSTAP)
753 ieee80211_free_node(ic, ni);
754 else
755 ieee80211_unref_node(&ni);
756 break;
757 }
758
759 case IEEE80211_FC0_SUBTYPE_AUTH: {
760 u_int16_t algo, seq, status;
761 /*
762 * auth frame format
763 * [2] algorithm
764 * [2] sequence
765 * [2] status
766 * [tlv*] challenge
767 */
768 IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
769 algo = le16toh(*(u_int16_t *)frm);
770 seq = le16toh(*(u_int16_t *)(frm + 2));
771 status = le16toh(*(u_int16_t *)(frm + 4));
772 if (algo != IEEE80211_AUTH_ALG_OPEN) {
773 /* TODO: shared key auth */
774 IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n",
775 __func__, algo, ether_sprintf(wh->i_addr2)));
776 return;
777 }
778 switch (ic->ic_opmode) {
779 case IEEE80211_M_IBSS:
780 if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
781 return;
782 ieee80211_new_state(ic, IEEE80211_S_AUTH,
783 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
784 break;
785
786 case IEEE80211_M_AHDEMO:
787 /* should not come here */
788 break;
789
790 case IEEE80211_M_HOSTAP:
791 if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
792 return;
793 allocbs = 0;
794 ni = ieee80211_find_node(ic, wh->i_addr2);
795 if (ni == NULL) {
796 ni = ieee80211_alloc_node(ic, wh->i_addr2);
797 if (ni == NULL)
798 return;
799 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
800 ni->ni_rssi = rssi;
801 ni->ni_rstamp = rstamp;
802 ni->ni_rantenna = rantenna;
803 ni->ni_chan = ic->ic_bss->ni_chan;
804 allocbs = 1;
805 }
806 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2);
807 if (ifp->if_flags & IFF_DEBUG)
808 if_printf(ifp, "station %s %s authenticated\n",
809 (allocbs ? "newly" : "already"),
810 ether_sprintf(ni->ni_macaddr));
811 ieee80211_unref_node(&ni);
812 break;
813
814 case IEEE80211_M_STA:
815 if (ic->ic_state != IEEE80211_S_AUTH || seq != 2)
816 return;
817 if (status != 0) {
818 if_printf(&ic->ic_if,
819 "authentication failed (reason %d) for %s\n",
820 status,
821 ether_sprintf(wh->i_addr3));
822 ni = ieee80211_find_node(ic, wh->i_addr2);
823 if (ni != NULL) {
824 ni->ni_fails++;
825 ieee80211_unref_node(&ni);
826 }
827 return;
828 }
829 ieee80211_new_state(ic, IEEE80211_S_ASSOC,
830 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
831 break;
220 }
221 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
222 if (ic->ic_flags & IEEE80211_F_WEPON) {
223 m = ieee80211_wep_crypt(ifp, m, 0);
224 if (m == NULL)
225 goto err;
226 wh = mtod(m, struct ieee80211_frame *);
227 } else
228 goto out;
229 }
230 /* copy to listener after decrypt */
231 if (ic->ic_rawbpf)
232 bpf_mtap(ic->ic_rawbpf, m);
233 m = ieee80211_decap(ifp, m);
234 if (m == NULL)
235 goto err;
236 ifp->if_ipackets++;
237
238 /* perform as a bridge within the AP */
239 m1 = NULL;
240 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
241 eh = mtod(m, struct ether_header *);
242 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
243 m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
244 if (m1 == NULL)
245 ifp->if_oerrors++;
246 else
247 m1->m_flags |= M_MCAST;
248 } else {
249 ni = ieee80211_find_node(ic, eh->ether_dhost);
250 if (ni != NULL) {
251 if (ni->ni_associd != 0) {
252 m1 = m;
253 m = NULL;
254 }
255 ieee80211_unref_node(&ni);
256 }
257 }
258 if (m1 != NULL) {
259#ifdef ALTQ
260 if (ALTQ_IS_ENABLED(&ifp->if_snd))
261 altq_etherclassify(&ifp->if_snd, m1,
262 &pktattr);
263#endif
264 len = m1->m_pkthdr.len;
265 IF_ENQUEUE(&ifp->if_snd, m1);
266 if (m != NULL)
267 ifp->if_omcasts++;
268 ifp->if_obytes += len;
269 }
270 }
271 if (m != NULL)
272 (*ifp->if_input)(ifp, m);
273 return;
274
275 case IEEE80211_FC0_TYPE_MGT:
276 if (dir != IEEE80211_FC1_DIR_NODS)
277 goto err;
278 if (ic->ic_opmode == IEEE80211_M_AHDEMO)
279 goto out;
280 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
281
282 /* drop frames without interest */
283 if (ic->ic_state == IEEE80211_S_SCAN) {
284 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
285 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
286 goto out;
287 } else {
288 if (ic->ic_opmode != IEEE80211_M_IBSS &&
289 subtype == IEEE80211_FC0_SUBTYPE_BEACON)
290 goto out;
291 }
292
293 if (ifp->if_flags & IFF_DEBUG) {
294 /* avoid to print too many frames */
295 int doprint = 0;
296
297 switch (subtype) {
298 case IEEE80211_FC0_SUBTYPE_BEACON:
299 if (ic->ic_state == IEEE80211_S_SCAN)
300 doprint = 1;
301 break;
302 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
303 if (ic->ic_opmode == IEEE80211_M_IBSS)
304 doprint = 1;
305 break;
306 default:
307 doprint = 1;
308 break;
309 }
310#ifdef IEEE80211_DEBUG
311 doprint += ieee80211_debug;
312#endif
313 if (doprint)
314 if_printf(ifp, "received %s from %s rssi %d\n",
315 ieee80211_mgt_subtype_name[subtype
316 >> IEEE80211_FC0_SUBTYPE_SHIFT],
317 ether_sprintf(wh->i_addr2), rssi);
318 }
319 if (ic->ic_rawbpf)
320 bpf_mtap(ic->ic_rawbpf, m);
321 (*ic->ic_recv_mgmt)(ic, m, subtype, rssi, rstamp, rantenna);
322 m_freem(m);
323 return;
324
325 case IEEE80211_FC0_TYPE_CTL:
326 default:
327 IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, wh->i_fc[0]));
328 /* should not come here */
329 break;
330 }
331 err:
332 ifp->if_ierrors++;
333 out:
334 if (m != NULL) {
335 if (ic->ic_rawbpf)
336 bpf_mtap(ic->ic_rawbpf, m);
337 m_freem(m);
338 }
339}
340
341struct mbuf *
342ieee80211_decap(struct ifnet *ifp, struct mbuf *m)
343{
344 struct ether_header *eh;
345 struct ieee80211_frame wh;
346 struct llc *llc;
347
348 if (m->m_len < sizeof(wh) + sizeof(*llc)) {
349 m = m_pullup(m, sizeof(wh) + sizeof(*llc));
350 if (m == NULL)
351 return NULL;
352 }
353 memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
354 llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
355 if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
356 llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
357 llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
358 m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh));
359 llc = NULL;
360 } else {
361 m_adj(m, sizeof(wh) - sizeof(*eh));
362 }
363 eh = mtod(m, struct ether_header *);
364 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
365 case IEEE80211_FC1_DIR_NODS:
366 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
367 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
368 break;
369 case IEEE80211_FC1_DIR_TODS:
370 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
371 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
372 break;
373 case IEEE80211_FC1_DIR_FROMDS:
374 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
375 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
376 break;
377 case IEEE80211_FC1_DIR_DSTODS:
378 /* not yet supported */
379 IEEE80211_DPRINTF(("%s: DS to DS\n", __func__));
380 m_freem(m);
381 return NULL;
382 }
383#ifdef ALIGNED_POINTER
384 if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
385 struct mbuf *n, *n0, **np;
386 caddr_t newdata;
387 int off, pktlen;
388
389 n0 = NULL;
390 np = &n0;
391 off = 0;
392 pktlen = m->m_pkthdr.len;
393 while (pktlen > off) {
394 if (n0 == NULL) {
395 MGETHDR(n, M_DONTWAIT, MT_DATA);
396 if (n == NULL) {
397 m_freem(m);
398 return NULL;
399 }
400 M_MOVE_PKTHDR(n, m);
401 n->m_len = MHLEN;
402 } else {
403 MGET(n, M_DONTWAIT, MT_DATA);
404 if (n == NULL) {
405 m_freem(m);
406 m_freem(n0);
407 return NULL;
408 }
409 n->m_len = MLEN;
410 }
411 if (pktlen - off >= MINCLSIZE) {
412 MCLGET(n, M_DONTWAIT);
413 if (n->m_flags & M_EXT)
414 n->m_len = n->m_ext.ext_size;
415 }
416 if (n0 == NULL) {
417 newdata =
418 (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
419 sizeof(*eh);
420 n->m_len -= newdata - n->m_data;
421 n->m_data = newdata;
422 }
423 if (n->m_len > pktlen - off)
424 n->m_len = pktlen - off;
425 m_copydata(m, off, n->m_len, mtod(n, caddr_t));
426 off += n->m_len;
427 *np = n;
428 np = &n->m_next;
429 }
430 m_freem(m);
431 m = n0;
432 }
433#endif /* ALIGNED_POINTER */
434 if (llc != NULL) {
435 eh = mtod(m, struct ether_header *);
436 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
437 }
438 return m;
439}
440
441/*
442 * Install received rate set information in the node's state block.
443 */
444static int
445ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
446 u_int8_t *rates, u_int8_t *xrates, int flags)
447{
448 struct ieee80211_rateset *rs = &ni->ni_rates;
449
450 memset(rs, 0, sizeof(*rs));
451 rs->rs_nrates = rates[1];
452 memcpy(rs->rs_rates, rates + 2, rs->rs_nrates);
453 if (xrates != NULL) {
454 u_int8_t nxrates;
455 /*
456 * Tack on 11g extended supported rate element.
457 */
458 nxrates = xrates[1];
459 if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
460 nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates;
461 IEEE80211_DPRINTF(("%s: extended rate set too large;"
462 " only using %u of %u rates\n",
463 __func__, nxrates, xrates[1]));
464 }
465 memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
466 rs->rs_nrates += nxrates;
467 }
468 return ieee80211_fix_rate(ic, ni, flags);
469}
470
471/* XXX statistics */
472/* Verify the existence and length of __elem or get out. */
473#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \
474 if ((__elem) == NULL) { \
475 IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n", \
476 __func__, ieee80211_mgt_subtype_name[subtype >> \
477 IEEE80211_FC0_SUBTYPE_SHIFT])); \
478 return; \
479 } \
480 if ((__elem)[1] > (__maxlen)) { \
481 IEEE80211_DPRINTF(("%s: bad " #__elem " len %d in %s " \
482 "frame from %s\n", __func__, (__elem)[1], \
483 ieee80211_mgt_subtype_name[subtype >> \
484 IEEE80211_FC0_SUBTYPE_SHIFT], \
485 ether_sprintf(wh->i_addr2))); \
486 return; \
487 } \
488} while (0)
489
490#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \
491 if ((_len) < (_minlen)) { \
492 IEEE80211_DPRINTF(("%s: %s frame too short from %s\n", \
493 __func__, \
494 ieee80211_mgt_subtype_name[subtype >> \
495 IEEE80211_FC0_SUBTYPE_SHIFT], \
496 ether_sprintf(wh->i_addr2))); \
497 return; \
498 } \
499} while (0)
500
501void
502ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, int subtype,
503 int rssi, u_int32_t rstamp, u_int rantenna)
504{
505#define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
506 struct ifnet *ifp = &ic->ic_if;
507 struct ieee80211_frame *wh;
508 struct ieee80211_node *ni;
509 u_int8_t *frm, *efrm;
510 u_int8_t *ssid, *rates, *xrates;
511 int reassoc, resp, newassoc, allocbs;
512
513 wh = mtod(m0, struct ieee80211_frame *);
514 frm = (u_int8_t *)&wh[1];
515 efrm = mtod(m0, u_int8_t *) + m0->m_len;
516 switch (subtype) {
517 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
518 case IEEE80211_FC0_SUBTYPE_BEACON: {
519 u_int8_t *tstamp, *bintval, *capinfo, *country;
520 u_int8_t chan, bchan, fhindex, erp;
521 u_int16_t fhdwell;
522
523 if (ic->ic_opmode != IEEE80211_M_IBSS &&
524 ic->ic_state != IEEE80211_S_SCAN) {
525 /* XXX: may be useful for background scan */
526 return;
527 }
528
529 /*
530 * beacon/probe response frame format
531 * [8] time stamp
532 * [2] beacon interval
533 * [2] capability information
534 * [tlv] ssid
535 * [tlv] supported rates
536 * [tlv] country information
537 * [tlv] parameter set (FH/DS)
538 * [tlv] erp information
539 * [tlv] extended supported rates
540 */
541 IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
542 tstamp = frm; frm += 8;
543 bintval = frm; frm += 2;
544 capinfo = frm; frm += 2;
545 ssid = rates = xrates = country = NULL;
546 bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
547 chan = bchan;
548 fhdwell = 0;
549 fhindex = 0;
550 erp = 0;
551 while (frm < efrm) {
552 switch (*frm) {
553 case IEEE80211_ELEMID_SSID:
554 ssid = frm;
555 break;
556 case IEEE80211_ELEMID_RATES:
557 rates = frm;
558 break;
559 case IEEE80211_ELEMID_COUNTRY:
560 country = frm;
561 break;
562 case IEEE80211_ELEMID_FHPARMS:
563 if (ic->ic_phytype == IEEE80211_T_FH) {
564 fhdwell = (frm[3] << 8) | frm[2];
565 chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
566 fhindex = frm[6];
567 }
568 break;
569 case IEEE80211_ELEMID_DSPARMS:
570 /*
571 * XXX hack this since depending on phytype
572 * is problematic for multi-mode devices.
573 */
574 if (ic->ic_phytype != IEEE80211_T_FH)
575 chan = frm[2];
576 break;
577 case IEEE80211_ELEMID_TIM:
578 break;
579 case IEEE80211_ELEMID_XRATES:
580 xrates = frm;
581 break;
582 case IEEE80211_ELEMID_ERP:
583 if (frm[1] != 1) {
584 IEEE80211_DPRINTF(("%s: invalid ERP "
585 "element; length %u, expecting "
586 "1\n", __func__, frm[1]));
587 break;
588 }
589 erp = frm[2];
590 break;
591 default:
592 IEEE80211_DPRINTF(("%s: element id %u/len %u "
593 "ignored\n", __func__, *frm, frm[1]));
594 break;
595 }
596 frm += frm[1] + 2;
597 }
598 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
599 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
600 if (
601#if IEEE80211_CHAN_MAX < 255
602 chan > IEEE80211_CHAN_MAX ||
603#endif
604 isclr(ic->ic_chan_active, chan)) {
605 IEEE80211_DPRINTF(("%s: ignore %s with invalid channel "
606 "%u\n", __func__,
607 ISPROBE(subtype) ? "probe response" : "beacon",
608 chan));
609 return;
610 }
611 if (chan != bchan) {
612 /*
613 * Frame was received on a channel different from the
614 * one indicated in the DS/FH params element id;
615 * silently discard it.
616 *
617 * NB: this can happen due to signal leakage.
618 */
619 IEEE80211_DPRINTF(("%s: ignore %s on channel %u marked "
620 "for channel %u\n", __func__,
621 ISPROBE(subtype) ? "probe response" : "beacon",
622 bchan, chan));
623 /* XXX statistic */
624 return;
625 }
626
627 /*
628 * Use mac and channel for lookup so we collect all
629 * potential AP's when scanning. Otherwise we may
630 * see the same AP on multiple channels and will only
631 * record the last one. We could filter APs here based
632 * on rssi, etc. but leave that to the end of the scan
633 * so we can keep the selection criteria in one spot.
634 * This may result in a bloat of the scanned AP list but
635 * it shouldn't be too much.
636 */
637 ni = ieee80211_lookup_node(ic, wh->i_addr2,
638 &ic->ic_channels[chan]);
639#ifdef IEEE80211_DEBUG
640 if (ieee80211_debug &&
641 (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) {
642 printf("%s: %s%s on chan %u (bss chan %u) ",
643 __func__, (ni == NULL ? "new " : ""),
644 ISPROBE(subtype) ? "probe response" : "beacon",
645 chan, bchan);
646 ieee80211_print_essid(ssid + 2, ssid[1]);
647 printf(" from %s\n", ether_sprintf(wh->i_addr2));
648 printf("%s: caps 0x%x bintval %u erp 0x%x\n",
649 __func__, le16toh(*(u_int16_t *)capinfo),
650 le16toh(*(u_int16_t *)bintval), erp);
651 if (country)
652 printf("%s: country info %*D\n",
653 __func__, country[1], country+2, " ");
654 }
655#endif
656 if (ni == NULL) {
657 ni = ieee80211_alloc_node(ic, wh->i_addr2);
658 if (ni == NULL)
659 return;
660 ni->ni_esslen = ssid[1];
661 memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
662 memcpy(ni->ni_essid, ssid + 2, ssid[1]);
663 } else if (ssid[1] != 0 && ISPROBE(subtype)) {
664 /*
665 * Update ESSID at probe response to adopt hidden AP by
666 * Lucent/Cisco, which announces null ESSID in beacon.
667 */
668 ni->ni_esslen = ssid[1];
669 memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
670 memcpy(ni->ni_essid, ssid + 2, ssid[1]);
671 }
672 IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
673 ni->ni_rssi = rssi;
674 ni->ni_rstamp = rstamp;
675 ni->ni_rantenna = rantenna;
676 memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
677 ni->ni_intval = le16toh(*(u_int16_t *)bintval);
678 ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo);
679 /* XXX validate channel # */
680 ni->ni_chan = &ic->ic_channels[chan];
681 ni->ni_fhdwell = fhdwell;
682 ni->ni_fhindex = fhindex;
683 ni->ni_erp = erp;
684 /* NB: must be after ni_chan is setup */
685 ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
686 ieee80211_unref_node(&ni);
687 break;
688 }
689
690 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: {
691 u_int8_t rate;
692
693 if (ic->ic_opmode == IEEE80211_M_STA)
694 return;
695 if (ic->ic_state != IEEE80211_S_RUN)
696 return;
697
698 /*
699 * prreq frame format
700 * [tlv] ssid
701 * [tlv] supported rates
702 * [tlv] extended supported rates
703 */
704 ssid = rates = xrates = NULL;
705 while (frm < efrm) {
706 switch (*frm) {
707 case IEEE80211_ELEMID_SSID:
708 ssid = frm;
709 break;
710 case IEEE80211_ELEMID_RATES:
711 rates = frm;
712 break;
713 case IEEE80211_ELEMID_XRATES:
714 xrates = frm;
715 break;
716 }
717 frm += frm[1] + 2;
718 }
719 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
720 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
721 if (ssid[1] != 0 &&
722 (ssid[1] != ic->ic_bss->ni_esslen ||
723 memcmp(ssid + 2, ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen) != 0)) {
724#ifdef IEEE80211_DEBUG
725 if (ieee80211_debug) {
726 printf("%s: ssid unmatch ", __func__);
727 ieee80211_print_essid(ssid + 2, ssid[1]);
728 printf(" from %s\n", ether_sprintf(wh->i_addr2));
729 }
730#endif
731 return;
732 }
733
734 ni = ieee80211_find_node(ic, wh->i_addr2);
735 if (ni == NULL) {
736 ni = ieee80211_dup_bss(ic, wh->i_addr2);
737 if (ni == NULL)
738 return;
739 IEEE80211_DPRINTF(("%s: new req from %s\n",
740 __func__, ether_sprintf(wh->i_addr2)));
741 allocbs = 1;
742 } else
743 allocbs = 0;
744 ni->ni_rssi = rssi;
745 ni->ni_rstamp = rstamp;
746 ni->ni_rantenna = rantenna;
747 rate = ieee80211_setup_rates(ic, ni, rates, xrates,
748 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
749 | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
750 if (rate & IEEE80211_RATE_BASIC) {
751 IEEE80211_DPRINTF(("%s: rate negotiation failed: %s\n",
752 __func__,ether_sprintf(wh->i_addr2)));
753 } else {
754 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP,
755 0);
756 }
757 if (allocbs && ic->ic_opmode == IEEE80211_M_HOSTAP)
758 ieee80211_free_node(ic, ni);
759 else
760 ieee80211_unref_node(&ni);
761 break;
762 }
763
764 case IEEE80211_FC0_SUBTYPE_AUTH: {
765 u_int16_t algo, seq, status;
766 /*
767 * auth frame format
768 * [2] algorithm
769 * [2] sequence
770 * [2] status
771 * [tlv*] challenge
772 */
773 IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
774 algo = le16toh(*(u_int16_t *)frm);
775 seq = le16toh(*(u_int16_t *)(frm + 2));
776 status = le16toh(*(u_int16_t *)(frm + 4));
777 if (algo != IEEE80211_AUTH_ALG_OPEN) {
778 /* TODO: shared key auth */
779 IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n",
780 __func__, algo, ether_sprintf(wh->i_addr2)));
781 return;
782 }
783 switch (ic->ic_opmode) {
784 case IEEE80211_M_IBSS:
785 if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
786 return;
787 ieee80211_new_state(ic, IEEE80211_S_AUTH,
788 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
789 break;
790
791 case IEEE80211_M_AHDEMO:
792 /* should not come here */
793 break;
794
795 case IEEE80211_M_HOSTAP:
796 if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
797 return;
798 allocbs = 0;
799 ni = ieee80211_find_node(ic, wh->i_addr2);
800 if (ni == NULL) {
801 ni = ieee80211_alloc_node(ic, wh->i_addr2);
802 if (ni == NULL)
803 return;
804 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
805 ni->ni_rssi = rssi;
806 ni->ni_rstamp = rstamp;
807 ni->ni_rantenna = rantenna;
808 ni->ni_chan = ic->ic_bss->ni_chan;
809 allocbs = 1;
810 }
811 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2);
812 if (ifp->if_flags & IFF_DEBUG)
813 if_printf(ifp, "station %s %s authenticated\n",
814 (allocbs ? "newly" : "already"),
815 ether_sprintf(ni->ni_macaddr));
816 ieee80211_unref_node(&ni);
817 break;
818
819 case IEEE80211_M_STA:
820 if (ic->ic_state != IEEE80211_S_AUTH || seq != 2)
821 return;
822 if (status != 0) {
823 if_printf(&ic->ic_if,
824 "authentication failed (reason %d) for %s\n",
825 status,
826 ether_sprintf(wh->i_addr3));
827 ni = ieee80211_find_node(ic, wh->i_addr2);
828 if (ni != NULL) {
829 ni->ni_fails++;
830 ieee80211_unref_node(&ni);
831 }
832 return;
833 }
834 ieee80211_new_state(ic, IEEE80211_S_ASSOC,
835 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
836 break;
837 case IEEE80211_M_MONITOR:
838 break;
832 }
833 break;
834 }
835
836 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
837 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: {
838 u_int16_t capinfo, bintval;
839
840 if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
841 (ic->ic_state != IEEE80211_S_RUN))
842 return;
843
844 if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
845 reassoc = 1;
846 resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
847 } else {
848 reassoc = 0;
849 resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
850 }
851 /*
852 * asreq frame format
853 * [2] capability information
854 * [2] listen interval
855 * [6*] current AP address (reassoc only)
856 * [tlv] ssid
857 * [tlv] supported rates
858 * [tlv] extended supported rates
859 */
860 IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
861 if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
862 IEEE80211_DPRINTF(("%s: ignore other bss from %s\n",
863 __func__, ether_sprintf(wh->i_addr2)));
864 return;
865 }
866 capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
867 bintval = le16toh(*(u_int16_t *)frm); frm += 2;
868 if (reassoc)
869 frm += 6; /* ignore current AP info */
870 ssid = rates = xrates = NULL;
871 while (frm < efrm) {
872 switch (*frm) {
873 case IEEE80211_ELEMID_SSID:
874 ssid = frm;
875 break;
876 case IEEE80211_ELEMID_RATES:
877 rates = frm;
878 break;
879 case IEEE80211_ELEMID_XRATES:
880 xrates = frm;
881 break;
882 }
883 frm += frm[1] + 2;
884 }
885 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
886 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
887 if (ssid[1] != ic->ic_bss->ni_esslen ||
888 memcmp(ssid + 2, ic->ic_bss->ni_essid, ssid[1]) != 0) {
889#ifdef IEEE80211_DEBUG
890 if (ieee80211_debug) {
891 printf("%s: ssid unmatch ", __func__);
892 ieee80211_print_essid(ssid + 2, ssid[1]);
893 printf(" from %s\n", ether_sprintf(wh->i_addr2));
894 }
895#endif
896 return;
897 }
898 ni = ieee80211_find_node(ic, wh->i_addr2);
899 if (ni == NULL) {
900 IEEE80211_DPRINTF(("%s: not authenticated for %s\n",
901 __func__, ether_sprintf(wh->i_addr2)));
902 ni = ieee80211_dup_bss(ic, wh->i_addr2);
903 if (ni == NULL)
904 return;
905 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
906 IEEE80211_REASON_ASSOC_NOT_AUTHED);
907 ieee80211_free_node(ic, ni);
908 return;
909 }
910 /* XXX per-node cipher suite */
911 /* XXX some stations use the privacy bit for handling APs
912 that suport both encrypted and unencrypted traffic */
913 if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
914 (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
915 ((ic->ic_flags & IEEE80211_F_WEPON) ?
916 IEEE80211_CAPINFO_PRIVACY : 0)) {
917 IEEE80211_DPRINTF(("%s: capability mismatch %x for %s\n",
918 __func__, capinfo, ether_sprintf(wh->i_addr2)));
919 ni->ni_associd = 0;
920 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO);
921 ieee80211_unref_node(&ni);
922 return;
923 }
924 ieee80211_setup_rates(ic, ni, rates, xrates,
925 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
926 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
927 if (ni->ni_rates.rs_nrates == 0) {
928 IEEE80211_DPRINTF(("%s: rate unmatch for %s\n",
929 __func__, ether_sprintf(wh->i_addr2)));
930 ni->ni_associd = 0;
931 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE);
932 ieee80211_unref_node(&ni);
933 return;
934 }
935 ni->ni_rssi = rssi;
936 ni->ni_rstamp = rstamp;
937 ni->ni_rantenna = rantenna;
938 ni->ni_intval = bintval;
939 ni->ni_capinfo = capinfo;
940 ni->ni_chan = ic->ic_bss->ni_chan;
941 ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
942 ni->ni_fhindex = ic->ic_bss->ni_fhindex;
943 if (ni->ni_associd == 0) {
944 /* XXX handle rollover at 2007 */
945 /* XXX guarantee uniqueness */
946 ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++;
947 newassoc = 1;
948 } else
949 newassoc = 0;
950 /* XXX for 11g must turn off short slot time if long
951 slot time sta associates */
952 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
953 if (ifp->if_flags & IFF_DEBUG)
954 if_printf(ifp, "station %s %s associated\n",
955 (newassoc ? "newly" : "already"),
956 ether_sprintf(ni->ni_macaddr));
957 /* give driver a chance to setup state like ni_txrate */
958 if (ic->ic_newassoc)
959 (*ic->ic_newassoc)(ic, ni, newassoc);
960 ieee80211_unref_node(&ni);
961 break;
962 }
963
964 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
965 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: {
966 u_int16_t status;
967
968 if (ic->ic_opmode != IEEE80211_M_STA ||
969 ic->ic_state != IEEE80211_S_ASSOC)
970 return;
971
972 /*
973 * asresp frame format
974 * [2] capability information
975 * [2] status
976 * [2] association ID
977 * [tlv] supported rates
978 * [tlv] extended supported rates
979 */
980 IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
981 ni = ic->ic_bss;
982 ni->ni_capinfo = le16toh(*(u_int16_t *)frm);
983 frm += 2;
984
985 status = le16toh(*(u_int16_t *)frm);
986 frm += 2;
987 if (status != 0) {
988 if_printf(ifp, "association failed (reason %d) for %s\n",
989 status, ether_sprintf(wh->i_addr3));
990 ni = ieee80211_find_node(ic, wh->i_addr2);
991 if (ni != NULL) {
992 ni->ni_fails++;
993 ieee80211_unref_node(&ni);
994 }
995 return;
996 }
997 ni->ni_associd = le16toh(*(u_int16_t *)frm);
998 frm += 2;
999
1000 rates = xrates = NULL;
1001 while (frm < efrm) {
1002 switch (*frm) {
1003 case IEEE80211_ELEMID_RATES:
1004 rates = frm;
1005 break;
1006 case IEEE80211_ELEMID_XRATES:
1007 xrates = frm;
1008 break;
1009 }
1010 frm += frm[1] + 2;
1011 }
1012
1013 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
1014 ieee80211_setup_rates(ic, ni, rates, xrates,
1015 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1016 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1017 if (ni->ni_rates.rs_nrates != 0)
1018 ieee80211_new_state(ic, IEEE80211_S_RUN,
1019 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1020 break;
1021 }
1022
1023 case IEEE80211_FC0_SUBTYPE_DEAUTH: {
1024 u_int16_t reason;
1025 /*
1026 * deauth frame format
1027 * [2] reason
1028 */
1029 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1030 reason = le16toh(*(u_int16_t *)frm);
1031 switch (ic->ic_opmode) {
1032 case IEEE80211_M_STA:
1033 ieee80211_new_state(ic, IEEE80211_S_AUTH,
1034 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1035 break;
1036 case IEEE80211_M_HOSTAP:
1037 ni = ieee80211_find_node(ic, wh->i_addr2);
1038 if (ni != NULL) {
1039 if (ifp->if_flags & IFF_DEBUG)
1040 if_printf(ifp, "station %s deauthenticated"
1041 " by peer (reason %d)\n",
1042 ether_sprintf(ni->ni_macaddr), reason);
1043 ieee80211_free_node(ic, ni);
1044 }
1045 break;
1046 default:
1047 break;
1048 }
1049 break;
1050 }
1051
1052 case IEEE80211_FC0_SUBTYPE_DISASSOC: {
1053 u_int16_t reason;
1054 /*
1055 * disassoc frame format
1056 * [2] reason
1057 */
1058 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1059 reason = le16toh(*(u_int16_t *)frm);
1060 switch (ic->ic_opmode) {
1061 case IEEE80211_M_STA:
1062 ieee80211_new_state(ic, IEEE80211_S_ASSOC,
1063 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1064 break;
1065 case IEEE80211_M_HOSTAP:
1066 ni = ieee80211_find_node(ic, wh->i_addr2);
1067 if (ni != NULL) {
1068 if (ifp->if_flags & IFF_DEBUG)
1069 if_printf(ifp, "station %s disassociated"
1070 " by peer (reason %d)\n",
1071 ether_sprintf(ni->ni_macaddr), reason);
1072 ni->ni_associd = 0;
1073 ieee80211_unref_node(&ni);
1074 }
1075 break;
1076 default:
1077 break;
1078 }
1079 break;
1080 }
1081 default:
1082 IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not "
1083 "handled\n", __func__, subtype));
1084 break;
1085 }
1086#undef ISPROBE
1087}
1088#undef IEEE80211_VERIFY_LENGTH
1089#undef IEEE80211_VERIFY_ELEMENT
839 }
840 break;
841 }
842
843 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
844 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: {
845 u_int16_t capinfo, bintval;
846
847 if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
848 (ic->ic_state != IEEE80211_S_RUN))
849 return;
850
851 if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
852 reassoc = 1;
853 resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
854 } else {
855 reassoc = 0;
856 resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
857 }
858 /*
859 * asreq frame format
860 * [2] capability information
861 * [2] listen interval
862 * [6*] current AP address (reassoc only)
863 * [tlv] ssid
864 * [tlv] supported rates
865 * [tlv] extended supported rates
866 */
867 IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
868 if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
869 IEEE80211_DPRINTF(("%s: ignore other bss from %s\n",
870 __func__, ether_sprintf(wh->i_addr2)));
871 return;
872 }
873 capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
874 bintval = le16toh(*(u_int16_t *)frm); frm += 2;
875 if (reassoc)
876 frm += 6; /* ignore current AP info */
877 ssid = rates = xrates = NULL;
878 while (frm < efrm) {
879 switch (*frm) {
880 case IEEE80211_ELEMID_SSID:
881 ssid = frm;
882 break;
883 case IEEE80211_ELEMID_RATES:
884 rates = frm;
885 break;
886 case IEEE80211_ELEMID_XRATES:
887 xrates = frm;
888 break;
889 }
890 frm += frm[1] + 2;
891 }
892 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
893 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
894 if (ssid[1] != ic->ic_bss->ni_esslen ||
895 memcmp(ssid + 2, ic->ic_bss->ni_essid, ssid[1]) != 0) {
896#ifdef IEEE80211_DEBUG
897 if (ieee80211_debug) {
898 printf("%s: ssid unmatch ", __func__);
899 ieee80211_print_essid(ssid + 2, ssid[1]);
900 printf(" from %s\n", ether_sprintf(wh->i_addr2));
901 }
902#endif
903 return;
904 }
905 ni = ieee80211_find_node(ic, wh->i_addr2);
906 if (ni == NULL) {
907 IEEE80211_DPRINTF(("%s: not authenticated for %s\n",
908 __func__, ether_sprintf(wh->i_addr2)));
909 ni = ieee80211_dup_bss(ic, wh->i_addr2);
910 if (ni == NULL)
911 return;
912 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
913 IEEE80211_REASON_ASSOC_NOT_AUTHED);
914 ieee80211_free_node(ic, ni);
915 return;
916 }
917 /* XXX per-node cipher suite */
918 /* XXX some stations use the privacy bit for handling APs
919 that suport both encrypted and unencrypted traffic */
920 if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
921 (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
922 ((ic->ic_flags & IEEE80211_F_WEPON) ?
923 IEEE80211_CAPINFO_PRIVACY : 0)) {
924 IEEE80211_DPRINTF(("%s: capability mismatch %x for %s\n",
925 __func__, capinfo, ether_sprintf(wh->i_addr2)));
926 ni->ni_associd = 0;
927 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO);
928 ieee80211_unref_node(&ni);
929 return;
930 }
931 ieee80211_setup_rates(ic, ni, rates, xrates,
932 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
933 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
934 if (ni->ni_rates.rs_nrates == 0) {
935 IEEE80211_DPRINTF(("%s: rate unmatch for %s\n",
936 __func__, ether_sprintf(wh->i_addr2)));
937 ni->ni_associd = 0;
938 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE);
939 ieee80211_unref_node(&ni);
940 return;
941 }
942 ni->ni_rssi = rssi;
943 ni->ni_rstamp = rstamp;
944 ni->ni_rantenna = rantenna;
945 ni->ni_intval = bintval;
946 ni->ni_capinfo = capinfo;
947 ni->ni_chan = ic->ic_bss->ni_chan;
948 ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
949 ni->ni_fhindex = ic->ic_bss->ni_fhindex;
950 if (ni->ni_associd == 0) {
951 /* XXX handle rollover at 2007 */
952 /* XXX guarantee uniqueness */
953 ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++;
954 newassoc = 1;
955 } else
956 newassoc = 0;
957 /* XXX for 11g must turn off short slot time if long
958 slot time sta associates */
959 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
960 if (ifp->if_flags & IFF_DEBUG)
961 if_printf(ifp, "station %s %s associated\n",
962 (newassoc ? "newly" : "already"),
963 ether_sprintf(ni->ni_macaddr));
964 /* give driver a chance to setup state like ni_txrate */
965 if (ic->ic_newassoc)
966 (*ic->ic_newassoc)(ic, ni, newassoc);
967 ieee80211_unref_node(&ni);
968 break;
969 }
970
971 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
972 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: {
973 u_int16_t status;
974
975 if (ic->ic_opmode != IEEE80211_M_STA ||
976 ic->ic_state != IEEE80211_S_ASSOC)
977 return;
978
979 /*
980 * asresp frame format
981 * [2] capability information
982 * [2] status
983 * [2] association ID
984 * [tlv] supported rates
985 * [tlv] extended supported rates
986 */
987 IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
988 ni = ic->ic_bss;
989 ni->ni_capinfo = le16toh(*(u_int16_t *)frm);
990 frm += 2;
991
992 status = le16toh(*(u_int16_t *)frm);
993 frm += 2;
994 if (status != 0) {
995 if_printf(ifp, "association failed (reason %d) for %s\n",
996 status, ether_sprintf(wh->i_addr3));
997 ni = ieee80211_find_node(ic, wh->i_addr2);
998 if (ni != NULL) {
999 ni->ni_fails++;
1000 ieee80211_unref_node(&ni);
1001 }
1002 return;
1003 }
1004 ni->ni_associd = le16toh(*(u_int16_t *)frm);
1005 frm += 2;
1006
1007 rates = xrates = NULL;
1008 while (frm < efrm) {
1009 switch (*frm) {
1010 case IEEE80211_ELEMID_RATES:
1011 rates = frm;
1012 break;
1013 case IEEE80211_ELEMID_XRATES:
1014 xrates = frm;
1015 break;
1016 }
1017 frm += frm[1] + 2;
1018 }
1019
1020 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
1021 ieee80211_setup_rates(ic, ni, rates, xrates,
1022 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1023 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1024 if (ni->ni_rates.rs_nrates != 0)
1025 ieee80211_new_state(ic, IEEE80211_S_RUN,
1026 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1027 break;
1028 }
1029
1030 case IEEE80211_FC0_SUBTYPE_DEAUTH: {
1031 u_int16_t reason;
1032 /*
1033 * deauth frame format
1034 * [2] reason
1035 */
1036 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1037 reason = le16toh(*(u_int16_t *)frm);
1038 switch (ic->ic_opmode) {
1039 case IEEE80211_M_STA:
1040 ieee80211_new_state(ic, IEEE80211_S_AUTH,
1041 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1042 break;
1043 case IEEE80211_M_HOSTAP:
1044 ni = ieee80211_find_node(ic, wh->i_addr2);
1045 if (ni != NULL) {
1046 if (ifp->if_flags & IFF_DEBUG)
1047 if_printf(ifp, "station %s deauthenticated"
1048 " by peer (reason %d)\n",
1049 ether_sprintf(ni->ni_macaddr), reason);
1050 ieee80211_free_node(ic, ni);
1051 }
1052 break;
1053 default:
1054 break;
1055 }
1056 break;
1057 }
1058
1059 case IEEE80211_FC0_SUBTYPE_DISASSOC: {
1060 u_int16_t reason;
1061 /*
1062 * disassoc frame format
1063 * [2] reason
1064 */
1065 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1066 reason = le16toh(*(u_int16_t *)frm);
1067 switch (ic->ic_opmode) {
1068 case IEEE80211_M_STA:
1069 ieee80211_new_state(ic, IEEE80211_S_ASSOC,
1070 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1071 break;
1072 case IEEE80211_M_HOSTAP:
1073 ni = ieee80211_find_node(ic, wh->i_addr2);
1074 if (ni != NULL) {
1075 if (ifp->if_flags & IFF_DEBUG)
1076 if_printf(ifp, "station %s disassociated"
1077 " by peer (reason %d)\n",
1078 ether_sprintf(ni->ni_macaddr), reason);
1079 ni->ni_associd = 0;
1080 ieee80211_unref_node(&ni);
1081 }
1082 break;
1083 default:
1084 break;
1085 }
1086 break;
1087 }
1088 default:
1089 IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not "
1090 "handled\n", __func__, subtype));
1091 break;
1092 }
1093#undef ISPROBE
1094}
1095#undef IEEE80211_VERIFY_LENGTH
1096#undef IEEE80211_VERIFY_ELEMENT