Line data Source code
1 : /* $OpenBSD: ieee80211_output.c,v 1.122 2017/12/14 18:52:17 stsp Exp $ */
2 : /* $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $ */
3 :
4 : /*-
5 : * Copyright (c) 2001 Atsushi Onoe
6 : * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
7 : * Copyright (c) 2007-2009 Damien Bergamini
8 : * All rights reserved.
9 : *
10 : * Redistribution and use in source and binary forms, with or without
11 : * modification, are permitted provided that the following conditions
12 : * are met:
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : * 2. Redistributions in binary form must reproduce the above copyright
16 : * notice, this list of conditions and the following disclaimer in the
17 : * documentation and/or other materials provided with the distribution.
18 : * 3. The name of the author may not be used to endorse or promote products
19 : * derived from this software without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : */
32 :
33 : #include "bpfilter.h"
34 : #include "vlan.h"
35 :
36 : #include <sys/param.h>
37 : #include <sys/systm.h>
38 : #include <sys/mbuf.h>
39 : #include <sys/kernel.h>
40 : #include <sys/socket.h>
41 : #include <sys/sockio.h>
42 : #include <sys/endian.h>
43 : #include <sys/errno.h>
44 : #include <sys/sysctl.h>
45 :
46 : #include <net/if.h>
47 : #include <net/if_dl.h>
48 : #include <net/if_media.h>
49 : #include <net/if_llc.h>
50 : #include <net/bpf.h>
51 :
52 : #include <netinet/in.h>
53 : #include <netinet/if_ether.h>
54 : #include <netinet/ip.h>
55 : #ifdef INET6
56 : #include <netinet/ip6.h>
57 : #endif
58 :
59 : #if NVLAN > 0
60 : #include <net/if_vlan_var.h>
61 : #endif
62 :
63 : #include <net80211/ieee80211_var.h>
64 : #include <net80211/ieee80211_priv.h>
65 :
66 : int ieee80211_mgmt_output(struct ifnet *, struct ieee80211_node *,
67 : struct mbuf *, int);
68 : u_int8_t *ieee80211_add_rsn_body(u_int8_t *, struct ieee80211com *,
69 : const struct ieee80211_node *, int);
70 : struct mbuf *ieee80211_getmgmt(int, int, u_int);
71 : struct mbuf *ieee80211_get_probe_req(struct ieee80211com *,
72 : struct ieee80211_node *);
73 : #ifndef IEEE80211_STA_ONLY
74 : struct mbuf *ieee80211_get_probe_resp(struct ieee80211com *,
75 : struct ieee80211_node *);
76 : #endif
77 : struct mbuf *ieee80211_get_auth(struct ieee80211com *,
78 : struct ieee80211_node *, u_int16_t, u_int16_t);
79 : struct mbuf *ieee80211_get_deauth(struct ieee80211com *,
80 : struct ieee80211_node *, u_int16_t);
81 : struct mbuf *ieee80211_get_assoc_req(struct ieee80211com *,
82 : struct ieee80211_node *, int);
83 : #ifndef IEEE80211_STA_ONLY
84 : struct mbuf *ieee80211_get_assoc_resp(struct ieee80211com *,
85 : struct ieee80211_node *, u_int16_t);
86 : #endif
87 : struct mbuf *ieee80211_get_disassoc(struct ieee80211com *,
88 : struct ieee80211_node *, u_int16_t);
89 : struct mbuf *ieee80211_get_addba_req(struct ieee80211com *,
90 : struct ieee80211_node *, u_int8_t);
91 : struct mbuf *ieee80211_get_addba_resp(struct ieee80211com *,
92 : struct ieee80211_node *, u_int8_t, u_int8_t, u_int16_t);
93 : struct mbuf *ieee80211_get_delba(struct ieee80211com *,
94 : struct ieee80211_node *, u_int8_t, u_int8_t, u_int16_t);
95 : uint8_t *ieee80211_add_wme_info(uint8_t *, struct ieee80211com *);
96 : #ifndef IEEE80211_STA_ONLY
97 : uint8_t *ieee80211_add_wme_param(uint8_t *, struct ieee80211com *);
98 : #endif
99 : struct mbuf *ieee80211_get_sa_query(struct ieee80211com *,
100 : struct ieee80211_node *, u_int8_t);
101 : struct mbuf *ieee80211_get_action(struct ieee80211com *,
102 : struct ieee80211_node *, u_int8_t, u_int8_t, int);
103 :
104 : /*
105 : * IEEE 802.11 output routine. Normally this will directly call the
106 : * Ethernet output routine because 802.11 encapsulation is called
107 : * later by the driver. This function can be used to send raw frames
108 : * if the mbuf has been tagged with a 802.11 data link type.
109 : */
110 : int
111 0 : ieee80211_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
112 : struct rtentry *rt)
113 : {
114 : struct ieee80211_frame *wh;
115 : struct m_tag *mtag;
116 : int error = 0;
117 :
118 : /* Interface has to be up and running */
119 0 : if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
120 : (IFF_UP | IFF_RUNNING)) {
121 : error = ENETDOWN;
122 : goto bad;
123 : }
124 :
125 : /* Try to get the DLT from a mbuf tag */
126 0 : if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {
127 0 : struct ieee80211com *ic = (void *)ifp;
128 0 : u_int dlt = *(u_int *)(mtag + 1);
129 :
130 : /* Fallback to ethernet for non-802.11 linktypes */
131 0 : if (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO))
132 0 : goto fallback;
133 :
134 0 : if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min))
135 0 : return (EINVAL);
136 0 : wh = mtod(m, struct ieee80211_frame *);
137 0 : if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
138 : IEEE80211_FC0_VERSION_0)
139 0 : return (EINVAL);
140 0 : if (!(ic->ic_caps & IEEE80211_C_RAWCTL) &&
141 0 : (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
142 : IEEE80211_FC0_TYPE_CTL)
143 0 : return (EINVAL);
144 :
145 0 : return (if_enqueue(ifp, m));
146 : }
147 :
148 : fallback:
149 0 : return (ether_output(ifp, m, dst, rt));
150 :
151 : bad:
152 0 : m_freem(m);
153 0 : return (error);
154 0 : }
155 :
156 : /*
157 : * Send a management frame to the specified node. The node pointer
158 : * must have a reference as the pointer will be passed to the driver
159 : * and potentially held for a long time. If the frame is successfully
160 : * dispatched to the driver, then it is responsible for freeing the
161 : * reference (and potentially free'ing up any associated storage).
162 : */
163 : int
164 0 : ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni,
165 : struct mbuf *m, int type)
166 : {
167 0 : struct ieee80211com *ic = (void *)ifp;
168 : struct ieee80211_frame *wh;
169 :
170 0 : if (ni == NULL)
171 0 : panic("null node");
172 0 : ni->ni_inact = 0;
173 :
174 : /*
175 : * We want to pass the node down to the driver's start
176 : * routine. We could stick this in an m_tag and tack that
177 : * on to the mbuf. However that's rather expensive to do
178 : * for every frame so instead we stuff it in a special pkthdr
179 : * field.
180 : */
181 0 : M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
182 0 : if (m == NULL)
183 0 : return ENOMEM;
184 0 : m->m_pkthdr.ph_cookie = ni;
185 :
186 0 : wh = mtod(m, struct ieee80211_frame *);
187 0 : wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
188 0 : wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
189 0 : *(u_int16_t *)&wh->i_dur[0] = 0;
190 0 : *(u_int16_t *)&wh->i_seq[0] =
191 0 : htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
192 0 : ni->ni_txseq++;
193 0 : IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
194 0 : IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
195 0 : IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
196 :
197 : /* check if protection is required for this mgmt frame */
198 0 : if ((ic->ic_caps & IEEE80211_C_MFP) &&
199 0 : (type == IEEE80211_FC0_SUBTYPE_DISASSOC ||
200 0 : type == IEEE80211_FC0_SUBTYPE_DEAUTH ||
201 0 : type == IEEE80211_FC0_SUBTYPE_ACTION)) {
202 : /*
203 : * Hack: we should not set the Protected bit in outgoing
204 : * group management frames, however it is used as an
205 : * indication to the drivers that they must encrypt the
206 : * frame. Drivers should clear this bit from group
207 : * management frames (software crypto code will do it).
208 : * XXX could use an mbuf flag..
209 : */
210 0 : if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
211 0 : (ni->ni_flags & IEEE80211_NODE_TXMGMTPROT))
212 0 : wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
213 : }
214 :
215 0 : if (ifp->if_flags & IFF_DEBUG) {
216 : /* avoid to print too many frames */
217 : if (
218 : #ifndef IEEE80211_STA_ONLY
219 0 : ic->ic_opmode == IEEE80211_M_IBSS ||
220 : #endif
221 : #ifdef IEEE80211_DEBUG
222 : ieee80211_debug > 1 ||
223 : #endif
224 0 : (type & IEEE80211_FC0_SUBTYPE_MASK) !=
225 : IEEE80211_FC0_SUBTYPE_PROBE_RESP)
226 0 : printf("%s: sending %s to %s on channel %u mode %s\n",
227 0 : ifp->if_xname,
228 0 : ieee80211_mgt_subtype_name[
229 0 : (type & IEEE80211_FC0_SUBTYPE_MASK)
230 0 : >> IEEE80211_FC0_SUBTYPE_SHIFT],
231 0 : ether_sprintf(ni->ni_macaddr),
232 0 : ieee80211_chan2ieee(ic, ni->ni_chan),
233 0 : ieee80211_phymode_name[ic->ic_curmode]);
234 : }
235 :
236 : #ifndef IEEE80211_STA_ONLY
237 0 : if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
238 0 : ieee80211_pwrsave(ic, m, ni) != 0)
239 0 : return 0;
240 : #endif
241 0 : mq_enqueue(&ic->ic_mgtq, m);
242 0 : ifp->if_timer = 1;
243 0 : if_start(ifp);
244 0 : return 0;
245 0 : }
246 :
247 : /*-
248 : * EDCA tables are computed using the following formulas:
249 : *
250 : * 1) EDCATable (non-AP QSTA)
251 : *
252 : * AC CWmin CWmax AIFSN TXOP limit(ms)
253 : * -------------------------------------------------------------
254 : * AC_BK aCWmin aCWmax 7 0
255 : * AC_BE aCWmin aCWmax 3 0
256 : * AC_VI (aCWmin+1)/2-1 aCWmin 2 agn=3.008 b=6.016 others=0
257 : * AC_VO (aCWmin+1)/4-1 (aCWmin+1)/2-1 2 agn=1.504 b=3.264 others=0
258 : *
259 : * 2) QAPEDCATable (QAP)
260 : *
261 : * AC CWmin CWmax AIFSN TXOP limit(ms)
262 : * -------------------------------------------------------------
263 : * AC_BK aCWmin aCWmax 7 0
264 : * AC_BE aCWmin 4*(aCWmin+1)-1 3 0
265 : * AC_VI (aCWmin+1)/2-1 aCWmin 1 agn=3.008 b=6.016 others=0
266 : * AC_VO (aCWmin+1)/4-1 (aCWmin+1)/2-1 1 agn=1.504 b=3.264 others=0
267 : *
268 : * and the following aCWmin/aCWmax values:
269 : *
270 : * PHY aCWmin aCWmax
271 : * ---------------------------
272 : * 11A 15 1023
273 : * 11B 31 1023
274 : * 11G 15* 1023 (*) aCWmin(1)
275 : * 11N 15 1023
276 : */
277 : const struct ieee80211_edca_ac_params
278 : ieee80211_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC] = {
279 : [IEEE80211_MODE_11B] = {
280 : [EDCA_AC_BK] = { 5, 10, 7, 0 },
281 : [EDCA_AC_BE] = { 5, 10, 3, 0 },
282 : [EDCA_AC_VI] = { 4, 5, 2, 188 },
283 : [EDCA_AC_VO] = { 3, 4, 2, 102 }
284 : },
285 : [IEEE80211_MODE_11A] = {
286 : [EDCA_AC_BK] = { 4, 10, 7, 0 },
287 : [EDCA_AC_BE] = { 4, 10, 3, 0 },
288 : [EDCA_AC_VI] = { 3, 4, 2, 94 },
289 : [EDCA_AC_VO] = { 2, 3, 2, 47 }
290 : },
291 : [IEEE80211_MODE_11G] = {
292 : [EDCA_AC_BK] = { 4, 10, 7, 0 },
293 : [EDCA_AC_BE] = { 4, 10, 3, 0 },
294 : [EDCA_AC_VI] = { 3, 4, 2, 94 },
295 : [EDCA_AC_VO] = { 2, 3, 2, 47 }
296 : },
297 : [IEEE80211_MODE_11N] = {
298 : [EDCA_AC_BK] = { 4, 10, 7, 0 },
299 : [EDCA_AC_BE] = { 4, 10, 3, 0 },
300 : [EDCA_AC_VI] = { 3, 4, 2, 94 },
301 : [EDCA_AC_VO] = { 2, 3, 2, 47 }
302 : },
303 : };
304 :
305 : #ifndef IEEE80211_STA_ONLY
306 : const struct ieee80211_edca_ac_params
307 : ieee80211_qap_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC] = {
308 : [IEEE80211_MODE_11B] = {
309 : [EDCA_AC_BK] = { 5, 10, 7, 0 },
310 : [EDCA_AC_BE] = { 5, 7, 3, 0 },
311 : [EDCA_AC_VI] = { 4, 5, 1, 188 },
312 : [EDCA_AC_VO] = { 3, 4, 1, 102 }
313 : },
314 : [IEEE80211_MODE_11A] = {
315 : [EDCA_AC_BK] = { 4, 10, 7, 0 },
316 : [EDCA_AC_BE] = { 4, 6, 3, 0 },
317 : [EDCA_AC_VI] = { 3, 4, 1, 94 },
318 : [EDCA_AC_VO] = { 2, 3, 1, 47 }
319 : },
320 : [IEEE80211_MODE_11G] = {
321 : [EDCA_AC_BK] = { 4, 10, 7, 0 },
322 : [EDCA_AC_BE] = { 4, 6, 3, 0 },
323 : [EDCA_AC_VI] = { 3, 4, 1, 94 },
324 : [EDCA_AC_VO] = { 2, 3, 1, 47 }
325 : },
326 : [IEEE80211_MODE_11N] = {
327 : [EDCA_AC_BK] = { 4, 10, 7, 0 },
328 : [EDCA_AC_BE] = { 4, 6, 3, 0 },
329 : [EDCA_AC_VI] = { 3, 4, 1, 94 },
330 : [EDCA_AC_VO] = { 2, 3, 1, 47 }
331 : },
332 : };
333 : #endif /* IEEE80211_STA_ONLY */
334 :
335 : /*
336 : * Return the EDCA Access Category to be used for transmitting a frame with
337 : * user-priority `up'.
338 : */
339 : enum ieee80211_edca_ac
340 0 : ieee80211_up_to_ac(struct ieee80211com *ic, int up)
341 : {
342 : /* see Table 9-1 */
343 : static const enum ieee80211_edca_ac up_to_ac[] = {
344 : EDCA_AC_BE, /* BE */
345 : EDCA_AC_BK, /* BK */
346 : EDCA_AC_BK, /* -- */
347 : EDCA_AC_BE, /* EE */
348 : EDCA_AC_VI, /* CL */
349 : EDCA_AC_VI, /* VI */
350 : EDCA_AC_VO, /* VO */
351 : EDCA_AC_VO /* NC */
352 : };
353 : enum ieee80211_edca_ac ac;
354 :
355 0 : ac = (up <= 7) ? up_to_ac[up] : EDCA_AC_BE;
356 :
357 : #ifndef IEEE80211_STA_ONLY
358 0 : if (ic->ic_opmode == IEEE80211_M_HOSTAP)
359 0 : return ac;
360 : #endif
361 : /*
362 : * We do not support the admission control procedure defined in
363 : * IEEE Std 802.11-2012 section 9.19.4.2.3. The spec says that
364 : * non-AP QSTAs that don't support this procedure shall use EDCA
365 : * parameters of a lower priority AC that does not require
366 : * admission control.
367 : */
368 0 : while (ac != EDCA_AC_BK && ic->ic_edca_ac[ac].ac_acm) {
369 0 : switch (ac) {
370 : case EDCA_AC_BK:
371 : /* can't get there */
372 : break;
373 : case EDCA_AC_BE:
374 : /* BE shouldn't require admission control */
375 : ac = EDCA_AC_BK;
376 0 : break;
377 : case EDCA_AC_VI:
378 : ac = EDCA_AC_BE;
379 0 : break;
380 : case EDCA_AC_VO:
381 : ac = EDCA_AC_VI;
382 0 : break;
383 : }
384 : }
385 0 : return ac;
386 0 : }
387 :
388 : /*
389 : * Get mbuf's user-priority: if mbuf is not VLAN tagged, select user-priority
390 : * based on the DSCP (Differentiated Services Codepoint) field.
391 : */
392 : int
393 0 : ieee80211_classify(struct ieee80211com *ic, struct mbuf *m)
394 : {
395 : struct ether_header *eh;
396 : u_int8_t ds_field;
397 : #if NVLAN > 0
398 0 : if (m->m_flags & M_VLANTAG) /* use VLAN 802.1D user-priority */
399 0 : return EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
400 : #endif
401 0 : eh = mtod(m, struct ether_header *);
402 0 : if (eh->ether_type == htons(ETHERTYPE_IP)) {
403 0 : struct ip *ip = (struct ip *)&eh[1];
404 0 : if (ip->ip_v != 4)
405 0 : return 0;
406 0 : ds_field = ip->ip_tos;
407 0 : }
408 : #ifdef INET6
409 0 : else if (eh->ether_type == htons(ETHERTYPE_IPV6)) {
410 0 : struct ip6_hdr *ip6 = (struct ip6_hdr *)&eh[1];
411 : u_int32_t flowlabel;
412 :
413 0 : flowlabel = ntohl(ip6->ip6_flow);
414 0 : if ((flowlabel >> 28) != 6)
415 0 : return 0;
416 0 : ds_field = (flowlabel >> 20) & 0xff;
417 0 : }
418 : #endif /* INET6 */
419 : else /* neither IPv4 nor IPv6 */
420 0 : return 0;
421 :
422 : /*
423 : * Map Differentiated Services Codepoint field (see RFC2474).
424 : * Preserves backward compatibility with IP Precedence field.
425 : */
426 0 : switch (ds_field & 0xfc) {
427 : case IPTOS_PREC_PRIORITY:
428 0 : return 2;
429 : case IPTOS_PREC_IMMEDIATE:
430 0 : return 1;
431 : case IPTOS_PREC_FLASH:
432 0 : return 3;
433 : case IPTOS_PREC_FLASHOVERRIDE:
434 0 : return 4;
435 : case IPTOS_PREC_CRITIC_ECP:
436 0 : return 5;
437 : case IPTOS_PREC_INTERNETCONTROL:
438 0 : return 6;
439 : case IPTOS_PREC_NETCONTROL:
440 0 : return 7;
441 : }
442 0 : return 0; /* default to Best-Effort */
443 0 : }
444 :
445 : /*
446 : * Encapsulate an outbound data frame. The mbuf chain is updated and
447 : * a reference to the destination node is returned. If an error is
448 : * encountered NULL is returned and the node reference will also be NULL.
449 : *
450 : * NB: The caller is responsible for free'ing a returned node reference.
451 : * The convention is ic_bss is not reference counted; the caller must
452 : * maintain that.
453 : */
454 : struct mbuf *
455 0 : ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
456 : {
457 0 : struct ieee80211com *ic = (void *)ifp;
458 0 : struct ether_header eh;
459 : struct ieee80211_frame *wh;
460 : struct ieee80211_node *ni = NULL;
461 : struct llc *llc;
462 : struct m_tag *mtag;
463 : u_int8_t *addr;
464 : u_int dlt, hdrlen;
465 : int addqos, tid;
466 :
467 : /* Handle raw frames if mbuf is tagged as 802.11 */
468 0 : if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {
469 0 : dlt = *(u_int *)(mtag + 1);
470 :
471 0 : if (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO))
472 : goto fallback;
473 :
474 0 : wh = mtod(m, struct ieee80211_frame *);
475 0 : switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
476 : case IEEE80211_FC1_DIR_NODS:
477 : case IEEE80211_FC1_DIR_FROMDS:
478 0 : addr = wh->i_addr1;
479 0 : break;
480 : case IEEE80211_FC1_DIR_DSTODS:
481 : case IEEE80211_FC1_DIR_TODS:
482 0 : addr = wh->i_addr3;
483 0 : break;
484 : default:
485 : goto bad;
486 : }
487 :
488 0 : ni = ieee80211_find_txnode(ic, addr);
489 0 : if (ni == NULL)
490 0 : ni = ieee80211_ref_node(ic->ic_bss);
491 0 : if (ni == NULL) {
492 0 : printf("%s: no node for dst %s, "
493 0 : "discard raw tx frame\n", ifp->if_xname,
494 0 : ether_sprintf(addr));
495 0 : ic->ic_stats.is_tx_nonode++;
496 0 : goto bad;
497 : }
498 0 : ni->ni_inact = 0;
499 :
500 0 : *pni = ni;
501 0 : return (m);
502 : }
503 :
504 : fallback:
505 0 : if (m->m_len < sizeof(struct ether_header)) {
506 0 : m = m_pullup(m, sizeof(struct ether_header));
507 0 : if (m == NULL) {
508 0 : ic->ic_stats.is_tx_nombuf++;
509 0 : goto bad;
510 : }
511 : }
512 0 : memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
513 :
514 0 : ni = ieee80211_find_txnode(ic, eh.ether_dhost);
515 0 : if (ni == NULL) {
516 : DPRINTF(("no node for dst %s, discard frame\n",
517 : ether_sprintf(eh.ether_dhost)));
518 0 : ic->ic_stats.is_tx_nonode++;
519 0 : goto bad;
520 : }
521 :
522 0 : if ((ic->ic_flags & IEEE80211_F_RSNON) &&
523 0 : !ni->ni_port_valid &&
524 0 : eh.ether_type != htons(ETHERTYPE_PAE)) {
525 : DPRINTF(("port not valid: %s\n",
526 : ether_sprintf(eh.ether_dhost)));
527 0 : ic->ic_stats.is_tx_noauth++;
528 0 : goto bad;
529 : }
530 :
531 0 : if ((ic->ic_flags & IEEE80211_F_COUNTERM) &&
532 : ni->ni_rsncipher == IEEE80211_CIPHER_TKIP)
533 : /* XXX TKIP countermeasures! */;
534 :
535 0 : ni->ni_inact = 0;
536 :
537 0 : if ((ic->ic_flags & IEEE80211_F_QOS) &&
538 0 : (ni->ni_flags & IEEE80211_NODE_QOS) &&
539 : /* do not QoS-encapsulate EAPOL frames */
540 0 : eh.ether_type != htons(ETHERTYPE_PAE)) {
541 0 : tid = ieee80211_classify(ic, m);
542 : hdrlen = sizeof(struct ieee80211_qosframe);
543 : addqos = 1;
544 0 : } else {
545 : hdrlen = sizeof(struct ieee80211_frame);
546 : addqos = 0;
547 : }
548 0 : m_adj(m, sizeof(struct ether_header) - LLC_SNAPFRAMELEN);
549 0 : llc = mtod(m, struct llc *);
550 0 : llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
551 0 : llc->llc_control = LLC_UI;
552 0 : llc->llc_snap.org_code[0] = 0;
553 0 : llc->llc_snap.org_code[1] = 0;
554 0 : llc->llc_snap.org_code[2] = 0;
555 0 : llc->llc_snap.ether_type = eh.ether_type;
556 0 : M_PREPEND(m, hdrlen, M_DONTWAIT);
557 0 : if (m == NULL) {
558 0 : ic->ic_stats.is_tx_nombuf++;
559 0 : goto bad;
560 : }
561 0 : wh = mtod(m, struct ieee80211_frame *);
562 0 : wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
563 0 : *(u_int16_t *)&wh->i_dur[0] = 0;
564 0 : if (addqos) {
565 : struct ieee80211_qosframe *qwh =
566 0 : (struct ieee80211_qosframe *)wh;
567 0 : u_int16_t qos = tid;
568 :
569 0 : if (ic->ic_tid_noack & (1 << tid))
570 0 : qos |= IEEE80211_QOS_ACK_POLICY_NOACK;
571 0 : else if (ni->ni_tx_ba[tid].ba_state == IEEE80211_BA_AGREED)
572 0 : qos |= IEEE80211_QOS_ACK_POLICY_BA;
573 0 : qwh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS;
574 0 : *(u_int16_t *)qwh->i_qos = htole16(qos);
575 0 : *(u_int16_t *)qwh->i_seq =
576 0 : htole16(ni->ni_qos_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
577 0 : ni->ni_qos_txseqs[tid]++;
578 0 : } else {
579 0 : *(u_int16_t *)&wh->i_seq[0] =
580 0 : htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
581 0 : ni->ni_txseq++;
582 : }
583 0 : switch (ic->ic_opmode) {
584 : case IEEE80211_M_STA:
585 0 : wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
586 0 : IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
587 0 : IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
588 0 : IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
589 0 : break;
590 : #ifndef IEEE80211_STA_ONLY
591 : case IEEE80211_M_IBSS:
592 : case IEEE80211_M_AHDEMO:
593 0 : wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
594 0 : IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
595 0 : IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
596 0 : IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid);
597 0 : break;
598 : case IEEE80211_M_HOSTAP:
599 0 : wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
600 0 : IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
601 0 : IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
602 0 : IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
603 0 : break;
604 : #endif
605 : default:
606 : /* should not get there */
607 : goto bad;
608 : }
609 :
610 0 : if ((ic->ic_flags & IEEE80211_F_WEPON) ||
611 0 : ((ic->ic_flags & IEEE80211_F_RSNON) &&
612 0 : (ni->ni_flags & IEEE80211_NODE_TXPROT)))
613 0 : wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
614 :
615 : #ifndef IEEE80211_STA_ONLY
616 0 : if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
617 0 : ieee80211_pwrsave(ic, m, ni) != 0) {
618 0 : *pni = NULL;
619 0 : return NULL;
620 : }
621 : #endif
622 0 : *pni = ni;
623 0 : return m;
624 : bad:
625 0 : m_freem(m);
626 0 : if (ni != NULL)
627 0 : ieee80211_release_node(ic, ni);
628 0 : *pni = NULL;
629 0 : return NULL;
630 0 : }
631 :
632 : /*
633 : * Add a Capability Information field to a frame (see 7.3.1.4).
634 : */
635 : u_int8_t *
636 0 : ieee80211_add_capinfo(u_int8_t *frm, struct ieee80211com *ic,
637 : const struct ieee80211_node *ni)
638 : {
639 : u_int16_t capinfo;
640 :
641 : #ifndef IEEE80211_STA_ONLY
642 0 : if (ic->ic_opmode == IEEE80211_M_IBSS)
643 0 : capinfo = IEEE80211_CAPINFO_IBSS;
644 0 : else if (ic->ic_opmode == IEEE80211_M_HOSTAP)
645 0 : capinfo = IEEE80211_CAPINFO_ESS;
646 : else
647 : #endif
648 : capinfo = 0;
649 : #ifndef IEEE80211_STA_ONLY
650 0 : if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
651 0 : (ic->ic_flags & (IEEE80211_F_WEPON | IEEE80211_F_RSNON)))
652 0 : capinfo |= IEEE80211_CAPINFO_PRIVACY;
653 : #endif
654 : /* NB: some 11a AP's reject the request when short preamble is set */
655 0 : if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
656 0 : IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
657 0 : capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
658 0 : if (ic->ic_flags & IEEE80211_F_SHSLOT)
659 0 : capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
660 0 : LE_WRITE_2(frm, capinfo);
661 0 : return frm + 2;
662 : }
663 :
664 : /*
665 : * Add an SSID element to a frame (see 7.3.2.1).
666 : */
667 : u_int8_t *
668 0 : ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
669 : {
670 0 : *frm++ = IEEE80211_ELEMID_SSID;
671 0 : *frm++ = len;
672 0 : memcpy(frm, ssid, len);
673 0 : return frm + len;
674 : }
675 :
676 : /*
677 : * Add a supported rates element to a frame (see 7.3.2.2).
678 : */
679 : u_int8_t *
680 0 : ieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs)
681 : {
682 : int nrates;
683 :
684 0 : *frm++ = IEEE80211_ELEMID_RATES;
685 0 : nrates = min(rs->rs_nrates, IEEE80211_RATE_SIZE);
686 0 : *frm++ = nrates;
687 0 : memcpy(frm, rs->rs_rates, nrates);
688 0 : return frm + nrates;
689 : }
690 :
691 : #ifndef IEEE80211_STA_ONLY
692 : /*
693 : * Add a DS Parameter Set element to a frame (see 7.3.2.4).
694 : */
695 : u_int8_t *
696 0 : ieee80211_add_ds_params(u_int8_t *frm, struct ieee80211com *ic,
697 : const struct ieee80211_node *ni)
698 : {
699 0 : *frm++ = IEEE80211_ELEMID_DSPARMS;
700 0 : *frm++ = 1;
701 0 : *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);
702 0 : return frm;
703 : }
704 :
705 : /*
706 : * Add a TIM element to a frame (see 7.3.2.6 and Annex L).
707 : */
708 : u_int8_t *
709 0 : ieee80211_add_tim(u_int8_t *frm, struct ieee80211com *ic)
710 : {
711 : u_int i, offset = 0, len;
712 :
713 : /* find first non-zero octet in the virtual bit map */
714 0 : for (i = 0; i < ic->ic_tim_len && ic->ic_tim_bitmap[i] == 0; i++);
715 :
716 : /* clear the lsb as it is reserved for the broadcast indication bit */
717 0 : if (i < ic->ic_tim_len)
718 0 : offset = i & ~1;
719 :
720 : /* find last non-zero octet in the virtual bit map */
721 0 : for (i = ic->ic_tim_len - 1; i > 0 && ic->ic_tim_bitmap[i] == 0; i--);
722 :
723 0 : len = i - offset + 1;
724 :
725 0 : *frm++ = IEEE80211_ELEMID_TIM;
726 0 : *frm++ = len + 3; /* length */
727 0 : *frm++ = ic->ic_dtim_count; /* DTIM count */
728 0 : *frm++ = ic->ic_dtim_period; /* DTIM period */
729 :
730 : /* Bitmap Control */
731 0 : *frm = offset;
732 : /* set broadcast/multicast indication bit if necessary */
733 0 : if (ic->ic_dtim_count == 0 && ic->ic_tim_mcast_pending)
734 0 : *frm |= 0x01;
735 0 : frm++;
736 :
737 : /* Partial Virtual Bitmap */
738 0 : memcpy(frm, &ic->ic_tim_bitmap[offset], len);
739 0 : return frm + len;
740 : }
741 :
742 : /*
743 : * Add an IBSS Parameter Set element to a frame (see 7.3.2.7).
744 : */
745 : u_int8_t *
746 0 : ieee80211_add_ibss_params(u_int8_t *frm, const struct ieee80211_node *ni)
747 : {
748 0 : *frm++ = IEEE80211_ELEMID_IBSSPARMS;
749 0 : *frm++ = 2;
750 0 : LE_WRITE_2(frm, 0); /* TODO: ATIM window */
751 0 : return frm + 2;
752 : }
753 :
754 : /*
755 : * Add an EDCA Parameter Set element to a frame (see 7.3.2.29).
756 : */
757 : u_int8_t *
758 0 : ieee80211_add_edca_params(u_int8_t *frm, struct ieee80211com *ic)
759 : {
760 : const struct ieee80211_edca_ac_params *edca;
761 : int aci;
762 :
763 0 : *frm++ = IEEE80211_ELEMID_EDCAPARMS;
764 0 : *frm++ = 18; /* length */
765 0 : *frm++ = 0; /* QoS Info */
766 0 : *frm++ = 0; /* reserved */
767 :
768 : /* setup AC Parameter Records */
769 0 : edca = ieee80211_edca_table[ic->ic_curmode];
770 0 : for (aci = 0; aci < EDCA_NUM_AC; aci++) {
771 0 : const struct ieee80211_edca_ac_params *ac = &edca[aci];
772 :
773 0 : *frm++ = (aci << 5) | ((ac->ac_acm & 0x1) << 4) |
774 0 : (ac->ac_aifsn & 0xf);
775 0 : *frm++ = (ac->ac_ecwmax << 4) |
776 0 : (ac->ac_ecwmin & 0xf);
777 0 : LE_WRITE_2(frm, ac->ac_txoplimit); frm += 2;
778 : }
779 0 : return frm;
780 : }
781 :
782 : /*
783 : * Add an ERP element to a frame (see 7.3.2.13).
784 : */
785 : u_int8_t *
786 0 : ieee80211_add_erp(u_int8_t *frm, struct ieee80211com *ic)
787 : {
788 : u_int8_t erp;
789 0 : int nonerpsta = 0;
790 :
791 0 : *frm++ = IEEE80211_ELEMID_ERP;
792 0 : *frm++ = 1;
793 : erp = 0;
794 : /*
795 : * The NonERP_Present bit shall be set to 1 when a NonERP STA
796 : * is associated with the BSS.
797 : */
798 0 : ieee80211_iterate_nodes(ic, ieee80211_count_nonerpsta, &nonerpsta);
799 0 : if (nonerpsta != 0)
800 0 : erp |= IEEE80211_ERP_NON_ERP_PRESENT;
801 : /*
802 : * If one or more NonERP STAs are associated in the BSS, the
803 : * Use_Protection bit shall be set to 1 in transmitted ERP
804 : * Information Elements.
805 : */
806 0 : if (ic->ic_flags & IEEE80211_F_USEPROT)
807 0 : erp |= IEEE80211_ERP_USE_PROTECTION;
808 : /*
809 : * The Barker_Preamble_Mode bit shall be set to 1 by the ERP
810 : * Information Element sender if one or more associated NonERP
811 : * STAs are not short preamble capable.
812 : */
813 0 : if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE))
814 0 : erp |= IEEE80211_ERP_BARKER_MODE;
815 0 : *frm++ = erp;
816 0 : return frm;
817 0 : }
818 : #endif /* IEEE80211_STA_ONLY */
819 :
820 : /*
821 : * Add a QoS Capability element to a frame (see 7.3.2.35).
822 : */
823 : u_int8_t *
824 0 : ieee80211_add_qos_capability(u_int8_t *frm, struct ieee80211com *ic)
825 : {
826 0 : *frm++ = IEEE80211_ELEMID_QOS_CAP;
827 0 : *frm++ = 1;
828 0 : *frm++ = 0; /* QoS Info */
829 0 : return frm;
830 : }
831 :
832 : /*
833 : * Add a Wifi-Alliance WME (aka WMM) info element to a frame.
834 : * WME is a requirement for Wifi-Alliance compliance and some
835 : * 11n APs will not negotiate HT if this element is missing.
836 : */
837 : uint8_t *
838 0 : ieee80211_add_wme_info(uint8_t *frm, struct ieee80211com *ic)
839 : {
840 0 : *frm++ = IEEE80211_ELEMID_VENDOR;
841 0 : *frm++ = 7;
842 0 : memcpy(frm, MICROSOFT_OUI, 3); frm += 3;
843 0 : *frm++ = 2; /* OUI type */
844 0 : *frm++ = 0; /* OUI subtype */
845 0 : *frm++ = 1; /* version */
846 0 : *frm++ = 0; /* info */
847 :
848 0 : return frm;
849 : }
850 :
851 : #ifndef IEEE80211_STA_ONLY
852 : /*
853 : * Add a Wifi-Alliance WMM (aka WME) parameter element to a frame.
854 : */
855 : uint8_t *
856 0 : ieee80211_add_wme_param(uint8_t *frm, struct ieee80211com *ic)
857 : {
858 : const struct ieee80211_edca_ac_params *edca;
859 : int aci;
860 :
861 0 : *frm++ = IEEE80211_ELEMID_VENDOR;
862 0 : *frm++ = 24;
863 0 : memcpy(frm, MICROSOFT_OUI, 3); frm += 3;
864 0 : *frm++ = 2; /* OUI type */
865 0 : *frm++ = 1; /* OUI subtype */
866 0 : *frm++ = 1; /* version */
867 0 : *frm++ = 0; /* info */
868 0 : *frm++ = 0; /* reserved */
869 :
870 : /* setup AC Parameter Records */
871 0 : edca = ieee80211_edca_table[ic->ic_curmode];
872 0 : for (aci = 0; aci < EDCA_NUM_AC; aci++) {
873 0 : const struct ieee80211_edca_ac_params *ac = &edca[aci];
874 :
875 0 : *frm++ = (aci << 5) | ((ac->ac_acm & 0x1) << 4) |
876 0 : (ac->ac_aifsn & 0xf);
877 0 : *frm++ = (ac->ac_ecwmax << 4) |
878 0 : (ac->ac_ecwmin & 0xf);
879 0 : LE_WRITE_2(frm, ac->ac_txoplimit); frm += 2;
880 : }
881 :
882 0 : return frm;
883 : }
884 : #endif
885 :
886 : /*
887 : * Add an RSN element to a frame (see 802.11-2012 8.4.2.27)
888 : */
889 : u_int8_t *
890 0 : ieee80211_add_rsn_body(u_int8_t *frm, struct ieee80211com *ic,
891 : const struct ieee80211_node *ni, int wpa)
892 : {
893 0 : const u_int8_t *oui = wpa ? MICROSOFT_OUI : IEEE80211_OUI;
894 : u_int8_t *pcount;
895 : u_int16_t count;
896 :
897 : /* write Version field */
898 0 : LE_WRITE_2(frm, 1); frm += 2;
899 :
900 : /* write Group Data Cipher Suite field (see 802.11-2012 Table 8-99) */
901 0 : memcpy(frm, oui, 3); frm += 3;
902 0 : switch (ni->ni_rsngroupcipher) {
903 : case IEEE80211_CIPHER_WEP40:
904 0 : *frm++ = 1;
905 0 : break;
906 : case IEEE80211_CIPHER_TKIP:
907 0 : *frm++ = 2;
908 0 : break;
909 : case IEEE80211_CIPHER_CCMP:
910 0 : *frm++ = 4;
911 0 : break;
912 : case IEEE80211_CIPHER_WEP104:
913 0 : *frm++ = 5;
914 0 : break;
915 : default:
916 : /* can't get there */
917 0 : panic("invalid group data cipher!");
918 : }
919 :
920 0 : pcount = frm; frm += 2;
921 : count = 0;
922 : /* write Pairwise Cipher Suite List */
923 0 : if (ni->ni_rsnciphers & IEEE80211_CIPHER_USEGROUP) {
924 0 : memcpy(frm, oui, 3); frm += 3;
925 0 : *frm++ = 0;
926 : count++;
927 0 : }
928 0 : if (ni->ni_rsnciphers & IEEE80211_CIPHER_TKIP) {
929 0 : memcpy(frm, oui, 3); frm += 3;
930 0 : *frm++ = 2;
931 0 : count++;
932 0 : }
933 0 : if (ni->ni_rsnciphers & IEEE80211_CIPHER_CCMP) {
934 0 : memcpy(frm, oui, 3); frm += 3;
935 0 : *frm++ = 4;
936 0 : count++;
937 0 : }
938 : /* write Pairwise Cipher Suite Count field */
939 0 : LE_WRITE_2(pcount, count);
940 :
941 0 : pcount = frm; frm += 2;
942 : count = 0;
943 : /* write AKM Suite List (see Table 20dc) */
944 0 : if (ni->ni_rsnakms & IEEE80211_AKM_8021X) {
945 0 : memcpy(frm, oui, 3); frm += 3;
946 0 : *frm++ = 1;
947 : count++;
948 0 : }
949 0 : if (ni->ni_rsnakms & IEEE80211_AKM_PSK) {
950 0 : memcpy(frm, oui, 3); frm += 3;
951 0 : *frm++ = 2;
952 0 : count++;
953 0 : }
954 0 : if (!wpa && (ni->ni_rsnakms & IEEE80211_AKM_SHA256_8021X)) {
955 0 : memcpy(frm, oui, 3); frm += 3;
956 0 : *frm++ = 5;
957 0 : count++;
958 0 : }
959 0 : if (!wpa && (ni->ni_rsnakms & IEEE80211_AKM_SHA256_PSK)) {
960 0 : memcpy(frm, oui, 3); frm += 3;
961 0 : *frm++ = 6;
962 0 : count++;
963 0 : }
964 : /* write AKM Suite List Count field */
965 0 : LE_WRITE_2(pcount, count);
966 :
967 0 : if (wpa)
968 0 : return frm;
969 :
970 : /* write RSN Capabilities field */
971 0 : LE_WRITE_2(frm, ni->ni_rsncaps); frm += 2;
972 :
973 0 : if (ni->ni_flags & IEEE80211_NODE_PMKID) {
974 : /* write PMKID Count field */
975 0 : LE_WRITE_2(frm, 1); frm += 2;
976 : /* write PMKID List (only 1) */
977 0 : memcpy(frm, ni->ni_pmkid, IEEE80211_PMKID_LEN);
978 0 : frm += IEEE80211_PMKID_LEN;
979 0 : }
980 :
981 0 : if (!(ic->ic_caps & IEEE80211_C_MFP))
982 0 : return frm;
983 :
984 0 : if ((ni->ni_flags & IEEE80211_NODE_PMKID) == 0) {
985 : /* no PMKID (PMKID Count=0) */
986 0 : LE_WRITE_2(frm, 0); frm += 2;
987 0 : }
988 :
989 : /* write Group Integrity Cipher Suite field */
990 0 : memcpy(frm, oui, 3); frm += 3;
991 0 : switch (ic->ic_rsngroupmgmtcipher) {
992 : case IEEE80211_CIPHER_BIP:
993 0 : *frm++ = 6;
994 : break;
995 : default:
996 : /* can't get there */
997 0 : panic("invalid integrity group cipher!");
998 : }
999 0 : return frm;
1000 0 : }
1001 :
1002 : u_int8_t *
1003 0 : ieee80211_add_rsn(u_int8_t *frm, struct ieee80211com *ic,
1004 : const struct ieee80211_node *ni)
1005 : {
1006 : u_int8_t *plen;
1007 :
1008 0 : *frm++ = IEEE80211_ELEMID_RSN;
1009 0 : plen = frm++; /* length filled in later */
1010 0 : frm = ieee80211_add_rsn_body(frm, ic, ni, 0);
1011 :
1012 : /* write length field */
1013 0 : *plen = frm - plen - 1;
1014 0 : return frm;
1015 : }
1016 :
1017 : /*
1018 : * Add a vendor-specific WPA element to a frame.
1019 : * This is required for compatibility with Wi-Fi Alliance WPA.
1020 : */
1021 : u_int8_t *
1022 0 : ieee80211_add_wpa(u_int8_t *frm, struct ieee80211com *ic,
1023 : const struct ieee80211_node *ni)
1024 : {
1025 : u_int8_t *plen;
1026 :
1027 0 : *frm++ = IEEE80211_ELEMID_VENDOR;
1028 0 : plen = frm++; /* length filled in later */
1029 0 : memcpy(frm, MICROSOFT_OUI, 3); frm += 3;
1030 0 : *frm++ = 1; /* WPA */
1031 0 : frm = ieee80211_add_rsn_body(frm, ic, ni, 1);
1032 :
1033 : /* write length field */
1034 0 : *plen = frm - plen - 1;
1035 0 : return frm;
1036 : }
1037 :
1038 : /*
1039 : * Add an extended supported rates element to a frame (see 7.3.2.14).
1040 : */
1041 : u_int8_t *
1042 0 : ieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs)
1043 : {
1044 : int nrates;
1045 :
1046 0 : KASSERT(rs->rs_nrates > IEEE80211_RATE_SIZE);
1047 :
1048 0 : *frm++ = IEEE80211_ELEMID_XRATES;
1049 0 : nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;
1050 0 : *frm++ = nrates;
1051 0 : memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);
1052 0 : return frm + nrates;
1053 : }
1054 :
1055 : /*
1056 : * Add an HT Capabilities element to a frame (see 7.3.2.57).
1057 : */
1058 : u_int8_t *
1059 0 : ieee80211_add_htcaps(u_int8_t *frm, struct ieee80211com *ic)
1060 : {
1061 0 : *frm++ = IEEE80211_ELEMID_HTCAPS;
1062 0 : *frm++ = 26;
1063 0 : LE_WRITE_2(frm, ic->ic_htcaps); frm += 2;
1064 0 : *frm++ = ic->ic_ampdu_params;
1065 0 : memcpy(frm, ic->ic_sup_mcs, 10); frm += 10;
1066 0 : LE_WRITE_2(frm, (ic->ic_max_rxrate & IEEE80211_MCS_RX_RATE_HIGH));
1067 0 : frm += 2;
1068 0 : *frm++ = ic->ic_tx_mcs_set;
1069 0 : *frm++ = 0; /* reserved */
1070 0 : *frm++ = 0; /* reserved */
1071 0 : *frm++ = 0; /* reserved */
1072 0 : LE_WRITE_2(frm, ic->ic_htxcaps); frm += 2;
1073 0 : LE_WRITE_4(frm, ic->ic_txbfcaps); frm += 4;
1074 0 : *frm++ = ic->ic_aselcaps;
1075 0 : return frm;
1076 : }
1077 :
1078 : #ifndef IEEE80211_STA_ONLY
1079 : /*
1080 : * Add an HT Operation element to a frame (see 7.3.2.58).
1081 : */
1082 : u_int8_t *
1083 0 : ieee80211_add_htop(u_int8_t *frm, struct ieee80211com *ic)
1084 : {
1085 0 : *frm++ = IEEE80211_ELEMID_HTOP;
1086 0 : *frm++ = 22;
1087 0 : *frm++ = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
1088 0 : *frm++ = ic->ic_bss->ni_htop0;
1089 0 : LE_WRITE_2(frm, ic->ic_bss->ni_htop1); frm += 2;
1090 0 : LE_WRITE_2(frm, ic->ic_bss->ni_htop2); frm += 2;
1091 0 : memset(frm, 0, 16); frm += 16;
1092 0 : return frm;
1093 : }
1094 : #endif /* !IEEE80211_STA_ONLY */
1095 :
1096 : #ifndef IEEE80211_STA_ONLY
1097 : /*
1098 : * Add a Timeout Interval element to a frame (see 7.3.2.49).
1099 : */
1100 : u_int8_t *
1101 0 : ieee80211_add_tie(u_int8_t *frm, u_int8_t type, u_int32_t value)
1102 : {
1103 0 : *frm++ = IEEE80211_ELEMID_TIE;
1104 0 : *frm++ = 5; /* length */
1105 0 : *frm++ = type; /* Timeout Interval type */
1106 0 : LE_WRITE_4(frm, value);
1107 0 : return frm + 4;
1108 : }
1109 : #endif
1110 :
1111 : struct mbuf *
1112 0 : ieee80211_getmgmt(int flags, int type, u_int pktlen)
1113 : {
1114 : struct mbuf *m;
1115 :
1116 : /* reserve space for 802.11 header */
1117 0 : pktlen += sizeof(struct ieee80211_frame);
1118 :
1119 0 : if (pktlen > MCLBYTES)
1120 0 : panic("management frame too large: %u", pktlen);
1121 0 : MGETHDR(m, flags, type);
1122 0 : if (m == NULL)
1123 0 : return NULL;
1124 0 : if (pktlen > MHLEN) {
1125 0 : MCLGET(m, flags);
1126 0 : if (!(m->m_flags & M_EXT))
1127 0 : return m_free(m);
1128 : }
1129 0 : m->m_data += sizeof(struct ieee80211_frame);
1130 0 : return m;
1131 0 : }
1132 :
1133 : /*-
1134 : * Probe request frame format:
1135 : * [tlv] SSID
1136 : * [tlv] Supported rates
1137 : * [tlv] Extended Supported Rates (802.11g)
1138 : * [tlv] HT Capabilities (802.11n)
1139 : */
1140 : struct mbuf *
1141 0 : ieee80211_get_probe_req(struct ieee80211com *ic, struct ieee80211_node *ni)
1142 : {
1143 : const struct ieee80211_rateset *rs =
1144 0 : &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
1145 : struct mbuf *m;
1146 : u_int8_t *frm;
1147 :
1148 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
1149 0 : 2 + ic->ic_des_esslen +
1150 0 : 2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
1151 0 : ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
1152 0 : 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
1153 0 : ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 9 : 0));
1154 0 : if (m == NULL)
1155 0 : return NULL;
1156 :
1157 0 : frm = mtod(m, u_int8_t *);
1158 0 : frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
1159 0 : frm = ieee80211_add_rates(frm, rs);
1160 0 : if (rs->rs_nrates > IEEE80211_RATE_SIZE)
1161 0 : frm = ieee80211_add_xrates(frm, rs);
1162 0 : if (ic->ic_flags & IEEE80211_F_HTON) {
1163 0 : frm = ieee80211_add_htcaps(frm, ic);
1164 0 : frm = ieee80211_add_wme_info(frm, ic);
1165 0 : }
1166 :
1167 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1168 :
1169 0 : return m;
1170 0 : }
1171 :
1172 : #ifndef IEEE80211_STA_ONLY
1173 : /*-
1174 : * Probe response frame format:
1175 : * [8] Timestamp
1176 : * [2] Beacon interval
1177 : * [2] Capability
1178 : * [tlv] Service Set Identifier (SSID)
1179 : * [tlv] Supported rates
1180 : * [tlv] DS Parameter Set (802.11g)
1181 : * [tlv] ERP Information (802.11g)
1182 : * [tlv] Extended Supported Rates (802.11g)
1183 : * [tlv] RSN (802.11i)
1184 : * [tlv] EDCA Parameter Set (802.11e)
1185 : * [tlv] HT Capabilities (802.11n)
1186 : * [tlv] HT Operation (802.11n)
1187 : */
1188 : struct mbuf *
1189 0 : ieee80211_get_probe_resp(struct ieee80211com *ic, struct ieee80211_node *ni)
1190 : {
1191 0 : const struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
1192 : struct mbuf *m;
1193 : u_int8_t *frm;
1194 :
1195 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
1196 : 8 + 2 + 2 +
1197 0 : 2 + ni->ni_esslen +
1198 0 : 2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
1199 0 : 2 + 1 +
1200 0 : ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 + 2 : 0) +
1201 0 : ((ic->ic_curmode == IEEE80211_MODE_11G) ? 2 + 1 : 0) +
1202 0 : ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
1203 0 : 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
1204 0 : (((ic->ic_flags & IEEE80211_F_RSNON) &&
1205 0 : (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?
1206 0 : 2 + IEEE80211_RSNIE_MAXLEN : 0) +
1207 0 : ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0) +
1208 0 : (((ic->ic_flags & IEEE80211_F_RSNON) &&
1209 0 : (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?
1210 0 : 2 + IEEE80211_WPAIE_MAXLEN : 0) +
1211 0 : ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));
1212 0 : if (m == NULL)
1213 0 : return NULL;
1214 :
1215 0 : frm = mtod(m, u_int8_t *);
1216 0 : memset(frm, 0, 8); frm += 8; /* timestamp is set by hardware */
1217 0 : LE_WRITE_2(frm, ic->ic_bss->ni_intval); frm += 2;
1218 0 : frm = ieee80211_add_capinfo(frm, ic, ni);
1219 0 : frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,
1220 0 : ic->ic_bss->ni_esslen);
1221 0 : frm = ieee80211_add_rates(frm, rs);
1222 0 : frm = ieee80211_add_ds_params(frm, ic, ni);
1223 0 : if (ic->ic_opmode == IEEE80211_M_IBSS)
1224 0 : frm = ieee80211_add_ibss_params(frm, ni);
1225 0 : if (ic->ic_curmode == IEEE80211_MODE_11G)
1226 0 : frm = ieee80211_add_erp(frm, ic);
1227 0 : if (rs->rs_nrates > IEEE80211_RATE_SIZE)
1228 0 : frm = ieee80211_add_xrates(frm, rs);
1229 0 : if ((ic->ic_flags & IEEE80211_F_RSNON) &&
1230 0 : (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_RSN))
1231 0 : frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
1232 0 : if (ic->ic_flags & IEEE80211_F_QOS)
1233 0 : frm = ieee80211_add_edca_params(frm, ic);
1234 0 : if ((ic->ic_flags & IEEE80211_F_RSNON) &&
1235 0 : (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_WPA))
1236 0 : frm = ieee80211_add_wpa(frm, ic, ic->ic_bss);
1237 0 : if (ic->ic_flags & IEEE80211_F_HTON) {
1238 0 : frm = ieee80211_add_htcaps(frm, ic);
1239 0 : frm = ieee80211_add_htop(frm, ic);
1240 0 : frm = ieee80211_add_wme_param(frm, ic);
1241 0 : }
1242 :
1243 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1244 :
1245 0 : return m;
1246 0 : }
1247 : #endif /* IEEE80211_STA_ONLY */
1248 :
1249 : /*-
1250 : * Authentication frame format:
1251 : * [2] Authentication algorithm number
1252 : * [2] Authentication transaction sequence number
1253 : * [2] Status code
1254 : */
1255 : struct mbuf *
1256 0 : ieee80211_get_auth(struct ieee80211com *ic, struct ieee80211_node *ni,
1257 : u_int16_t status, u_int16_t seq)
1258 : {
1259 : struct mbuf *m;
1260 : u_int8_t *frm;
1261 :
1262 0 : MGETHDR(m, M_DONTWAIT, MT_DATA);
1263 0 : if (m == NULL)
1264 0 : return NULL;
1265 0 : MH_ALIGN(m, 2 * 3);
1266 0 : m->m_pkthdr.len = m->m_len = 2 * 3;
1267 :
1268 0 : frm = mtod(m, u_int8_t *);
1269 0 : LE_WRITE_2(frm, IEEE80211_AUTH_ALG_OPEN); frm += 2;
1270 0 : LE_WRITE_2(frm, seq); frm += 2;
1271 0 : LE_WRITE_2(frm, status);
1272 :
1273 0 : return m;
1274 0 : }
1275 :
1276 : /*-
1277 : * Deauthentication frame format:
1278 : * [2] Reason code
1279 : */
1280 : struct mbuf *
1281 0 : ieee80211_get_deauth(struct ieee80211com *ic, struct ieee80211_node *ni,
1282 : u_int16_t reason)
1283 : {
1284 : struct mbuf *m;
1285 :
1286 0 : MGETHDR(m, M_DONTWAIT, MT_DATA);
1287 0 : if (m == NULL)
1288 0 : return NULL;
1289 0 : MH_ALIGN(m, 2);
1290 :
1291 0 : m->m_pkthdr.len = m->m_len = 2;
1292 0 : *mtod(m, u_int16_t *) = htole16(reason);
1293 :
1294 0 : return m;
1295 0 : }
1296 :
1297 : /*-
1298 : * (Re)Association request frame format:
1299 : * [2] Capability information
1300 : * [2] Listen interval
1301 : * [6*] Current AP address (Reassociation only)
1302 : * [tlv] SSID
1303 : * [tlv] Supported rates
1304 : * [tlv] Extended Supported Rates (802.11g)
1305 : * [tlv] RSN (802.11i)
1306 : * [tlv] QoS Capability (802.11e)
1307 : * [tlv] HT Capabilities (802.11n)
1308 : */
1309 : struct mbuf *
1310 0 : ieee80211_get_assoc_req(struct ieee80211com *ic, struct ieee80211_node *ni,
1311 : int type)
1312 : {
1313 0 : const struct ieee80211_rateset *rs = &ni->ni_rates;
1314 : struct mbuf *m;
1315 : u_int8_t *frm;
1316 : u_int16_t capinfo;
1317 :
1318 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
1319 0 : 2 + 2 +
1320 0 : ((type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) ?
1321 0 : IEEE80211_ADDR_LEN : 0) +
1322 0 : 2 + ni->ni_esslen +
1323 0 : 2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
1324 0 : ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
1325 0 : 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
1326 0 : (((ic->ic_flags & IEEE80211_F_RSNON) &&
1327 0 : (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?
1328 0 : 2 + IEEE80211_RSNIE_MAXLEN : 0) +
1329 0 : ((ni->ni_flags & IEEE80211_NODE_QOS) ? 2 + 1 : 0) +
1330 0 : (((ic->ic_flags & IEEE80211_F_RSNON) &&
1331 0 : (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?
1332 0 : 2 + IEEE80211_WPAIE_MAXLEN : 0) +
1333 0 : ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 9 : 0));
1334 0 : if (m == NULL)
1335 0 : return NULL;
1336 :
1337 0 : frm = mtod(m, u_int8_t *);
1338 : capinfo = IEEE80211_CAPINFO_ESS;
1339 0 : if (ic->ic_flags & IEEE80211_F_WEPON)
1340 0 : capinfo |= IEEE80211_CAPINFO_PRIVACY;
1341 0 : if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
1342 0 : IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
1343 0 : capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
1344 0 : if (ic->ic_caps & IEEE80211_C_SHSLOT)
1345 0 : capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
1346 0 : LE_WRITE_2(frm, capinfo); frm += 2;
1347 0 : LE_WRITE_2(frm, ic->ic_lintval); frm += 2;
1348 0 : if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
1349 0 : IEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid);
1350 0 : frm += IEEE80211_ADDR_LEN;
1351 0 : }
1352 0 : frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
1353 0 : frm = ieee80211_add_rates(frm, rs);
1354 0 : if (rs->rs_nrates > IEEE80211_RATE_SIZE)
1355 0 : frm = ieee80211_add_xrates(frm, rs);
1356 0 : if ((ic->ic_flags & IEEE80211_F_RSNON) &&
1357 0 : (ni->ni_rsnprotos & IEEE80211_PROTO_RSN))
1358 0 : frm = ieee80211_add_rsn(frm, ic, ni);
1359 0 : if (ni->ni_flags & IEEE80211_NODE_QOS)
1360 0 : frm = ieee80211_add_qos_capability(frm, ic);
1361 0 : if ((ic->ic_flags & IEEE80211_F_RSNON) &&
1362 0 : (ni->ni_rsnprotos & IEEE80211_PROTO_WPA))
1363 0 : frm = ieee80211_add_wpa(frm, ic, ni);
1364 0 : if (ic->ic_flags & IEEE80211_F_HTON) {
1365 0 : frm = ieee80211_add_htcaps(frm, ic);
1366 0 : frm = ieee80211_add_wme_info(frm, ic);
1367 0 : }
1368 :
1369 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1370 :
1371 0 : return m;
1372 0 : }
1373 :
1374 : #ifndef IEEE80211_STA_ONLY
1375 : /*-
1376 : * (Re)Association response frame format:
1377 : * [2] Capability information
1378 : * [2] Status code
1379 : * [2] Association ID (AID)
1380 : * [tlv] Supported rates
1381 : * [tlv] Extended Supported Rates (802.11g)
1382 : * [tlv] EDCA Parameter Set (802.11e)
1383 : * [tlv] Timeout Interval (802.11w)
1384 : * [tlv] HT Capabilities (802.11n)
1385 : * [tlv] HT Operation (802.11n)
1386 : */
1387 : struct mbuf *
1388 0 : ieee80211_get_assoc_resp(struct ieee80211com *ic, struct ieee80211_node *ni,
1389 : u_int16_t status)
1390 : {
1391 0 : const struct ieee80211_rateset *rs = &ni->ni_rates;
1392 : struct mbuf *m;
1393 : u_int8_t *frm;
1394 :
1395 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
1396 : 2 + 2 + 2 +
1397 0 : 2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
1398 0 : ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
1399 0 : 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
1400 0 : ((ni->ni_flags & IEEE80211_NODE_QOS) ? 2 + 18 : 0) +
1401 0 : ((status == IEEE80211_STATUS_TRY_AGAIN_LATER) ? 2 + 7 : 0) +
1402 0 : ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));
1403 0 : if (m == NULL)
1404 0 : return NULL;
1405 :
1406 0 : frm = mtod(m, u_int8_t *);
1407 0 : frm = ieee80211_add_capinfo(frm, ic, ni);
1408 0 : LE_WRITE_2(frm, status); frm += 2;
1409 0 : if (status == IEEE80211_STATUS_SUCCESS)
1410 0 : LE_WRITE_2(frm, ni->ni_associd);
1411 : else
1412 0 : LE_WRITE_2(frm, 0);
1413 0 : frm += 2;
1414 0 : frm = ieee80211_add_rates(frm, rs);
1415 0 : if (rs->rs_nrates > IEEE80211_RATE_SIZE)
1416 0 : frm = ieee80211_add_xrates(frm, rs);
1417 0 : if (ni->ni_flags & IEEE80211_NODE_QOS)
1418 0 : frm = ieee80211_add_edca_params(frm, ic);
1419 0 : if ((ni->ni_flags & IEEE80211_NODE_MFP) &&
1420 : status == IEEE80211_STATUS_TRY_AGAIN_LATER) {
1421 : /* Association Comeback Time */
1422 0 : frm = ieee80211_add_tie(frm, 3, 1000 /* XXX */);
1423 0 : }
1424 0 : if (ic->ic_flags & IEEE80211_F_HTON) {
1425 0 : frm = ieee80211_add_htcaps(frm, ic);
1426 0 : frm = ieee80211_add_htop(frm, ic);
1427 0 : frm = ieee80211_add_wme_param(frm, ic);
1428 0 : }
1429 :
1430 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1431 :
1432 0 : return m;
1433 0 : }
1434 : #endif /* IEEE80211_STA_ONLY */
1435 :
1436 : /*-
1437 : * Disassociation frame format:
1438 : * [2] Reason code
1439 : */
1440 : struct mbuf *
1441 0 : ieee80211_get_disassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
1442 : u_int16_t reason)
1443 : {
1444 : struct mbuf *m;
1445 :
1446 0 : MGETHDR(m, M_DONTWAIT, MT_DATA);
1447 0 : if (m == NULL)
1448 0 : return NULL;
1449 0 : MH_ALIGN(m, 2);
1450 :
1451 0 : m->m_pkthdr.len = m->m_len = 2;
1452 0 : *mtod(m, u_int16_t *) = htole16(reason);
1453 :
1454 0 : return m;
1455 0 : }
1456 :
1457 : /*-
1458 : * ADDBA Request frame format:
1459 : * [1] Category
1460 : * [1] Action
1461 : * [1] Dialog Token
1462 : * [2] Block Ack Parameter Set
1463 : * [2] Block Ack Timeout Value
1464 : * [2] Block Ack Starting Sequence Control
1465 : */
1466 : struct mbuf *
1467 0 : ieee80211_get_addba_req(struct ieee80211com *ic, struct ieee80211_node *ni,
1468 : u_int8_t tid)
1469 : {
1470 0 : struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];
1471 : struct mbuf *m;
1472 : u_int8_t *frm;
1473 :
1474 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, 9);
1475 0 : if (m == NULL)
1476 0 : return m;
1477 :
1478 0 : frm = mtod(m, u_int8_t *);
1479 0 : *frm++ = IEEE80211_CATEG_BA;
1480 0 : *frm++ = IEEE80211_ACTION_ADDBA_REQ;
1481 0 : *frm++ = ba->ba_token;
1482 0 : LE_WRITE_2(frm, ba->ba_params); frm += 2;
1483 0 : LE_WRITE_2(frm, ba->ba_timeout_val / IEEE80211_DUR_TU); frm += 2;
1484 0 : LE_WRITE_2(frm, ba->ba_winstart); frm += 2;
1485 :
1486 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1487 :
1488 0 : return m;
1489 0 : }
1490 :
1491 : /*-
1492 : * ADDBA Response frame format:
1493 : * [1] Category
1494 : * [1] Action
1495 : * [1] Dialog Token
1496 : * [2] Status Code
1497 : * [2] Block Ack Parameter Set
1498 : * [2] Block Ack Timeout Value
1499 : */
1500 : struct mbuf *
1501 0 : ieee80211_get_addba_resp(struct ieee80211com *ic, struct ieee80211_node *ni,
1502 : u_int8_t tid, u_int8_t token, u_int16_t status)
1503 : {
1504 0 : struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
1505 : struct mbuf *m;
1506 : u_int8_t *frm;
1507 : u_int16_t params;
1508 :
1509 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, 9);
1510 0 : if (m == NULL)
1511 0 : return m;
1512 :
1513 0 : frm = mtod(m, u_int8_t *);
1514 0 : *frm++ = IEEE80211_CATEG_BA;
1515 0 : *frm++ = IEEE80211_ACTION_ADDBA_RESP;
1516 0 : *frm++ = token;
1517 0 : LE_WRITE_2(frm, status); frm += 2;
1518 0 : if (status == 0)
1519 0 : params = ba->ba_params;
1520 : else
1521 0 : params = tid << IEEE80211_ADDBA_TID_SHIFT;
1522 0 : LE_WRITE_2(frm, params); frm += 2;
1523 0 : if (status == 0)
1524 0 : LE_WRITE_2(frm, ba->ba_timeout_val / IEEE80211_DUR_TU);
1525 : else
1526 0 : LE_WRITE_2(frm, 0);
1527 0 : frm += 2;
1528 :
1529 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1530 :
1531 0 : return m;
1532 0 : }
1533 :
1534 : /*-
1535 : * DELBA frame format:
1536 : * [1] Category
1537 : * [1] Action
1538 : * [2] DELBA Parameter Set
1539 : * [2] Reason Code
1540 : */
1541 : struct mbuf *
1542 0 : ieee80211_get_delba(struct ieee80211com *ic, struct ieee80211_node *ni,
1543 : u_int8_t tid, u_int8_t dir, u_int16_t reason)
1544 : {
1545 : struct mbuf *m;
1546 : u_int8_t *frm;
1547 : u_int16_t params;
1548 :
1549 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, 6);
1550 0 : if (m == NULL)
1551 0 : return m;
1552 :
1553 0 : frm = mtod(m, u_int8_t *);
1554 0 : *frm++ = IEEE80211_CATEG_BA;
1555 0 : *frm++ = IEEE80211_ACTION_DELBA;
1556 0 : params = tid << 12;
1557 0 : if (dir)
1558 0 : params |= IEEE80211_DELBA_INITIATOR;
1559 0 : LE_WRITE_2(frm, params); frm += 2;
1560 0 : LE_WRITE_2(frm, reason); frm += 2;
1561 :
1562 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1563 :
1564 0 : return m;
1565 0 : }
1566 :
1567 : /*-
1568 : * SA Query Request/Reponse frame format:
1569 : * [1] Category
1570 : * [1] Action
1571 : * [16] Transaction Identifier
1572 : */
1573 : struct mbuf *
1574 0 : ieee80211_get_sa_query(struct ieee80211com *ic, struct ieee80211_node *ni,
1575 : u_int8_t action)
1576 : {
1577 : struct mbuf *m;
1578 : u_int8_t *frm;
1579 :
1580 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, 4);
1581 0 : if (m == NULL)
1582 0 : return NULL;
1583 :
1584 0 : frm = mtod(m, u_int8_t *);
1585 0 : *frm++ = IEEE80211_CATEG_SA_QUERY;
1586 0 : *frm++ = action; /* ACTION_SA_QUERY_REQ/RESP */
1587 0 : LE_WRITE_2(frm, ni->ni_sa_query_trid); frm += 2;
1588 :
1589 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1590 :
1591 0 : return m;
1592 0 : }
1593 :
1594 : struct mbuf *
1595 0 : ieee80211_get_action(struct ieee80211com *ic, struct ieee80211_node *ni,
1596 : u_int8_t categ, u_int8_t action, int arg)
1597 : {
1598 : struct mbuf *m = NULL;
1599 :
1600 0 : switch (categ) {
1601 : case IEEE80211_CATEG_BA:
1602 0 : switch (action) {
1603 : case IEEE80211_ACTION_ADDBA_REQ:
1604 0 : m = ieee80211_get_addba_req(ic, ni, arg & 0xffff);
1605 0 : break;
1606 : case IEEE80211_ACTION_ADDBA_RESP:
1607 0 : m = ieee80211_get_addba_resp(ic, ni, arg & 0xff,
1608 0 : arg >> 8, arg >> 16);
1609 0 : break;
1610 : case IEEE80211_ACTION_DELBA:
1611 0 : m = ieee80211_get_delba(ic, ni, arg & 0xff, arg >> 8,
1612 0 : arg >> 16);
1613 0 : break;
1614 : }
1615 : break;
1616 : case IEEE80211_CATEG_SA_QUERY:
1617 0 : switch (action) {
1618 : #ifndef IEEE80211_STA_ONLY
1619 : case IEEE80211_ACTION_SA_QUERY_REQ:
1620 : #endif
1621 : case IEEE80211_ACTION_SA_QUERY_RESP:
1622 0 : m = ieee80211_get_sa_query(ic, ni, action);
1623 0 : break;
1624 : }
1625 : break;
1626 : }
1627 0 : return m;
1628 : }
1629 :
1630 : /*
1631 : * Send a management frame. The node is for the destination (or ic_bss
1632 : * when in station mode). Nodes other than ic_bss have their reference
1633 : * count bumped to reflect our use for an indeterminant time.
1634 : */
1635 : int
1636 0 : ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
1637 : int type, int arg1, int arg2)
1638 : {
1639 : #define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0)
1640 0 : struct ifnet *ifp = &ic->ic_if;
1641 : struct mbuf *m;
1642 : int ret, timer;
1643 :
1644 0 : if (ni == NULL)
1645 0 : panic("null node");
1646 :
1647 : /*
1648 : * Hold a reference on the node so it doesn't go away until after
1649 : * the xmit is complete all the way in the driver. On error we
1650 : * will remove our reference.
1651 : */
1652 0 : ieee80211_ref_node(ni);
1653 : timer = 0;
1654 0 : switch (type) {
1655 : case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
1656 0 : if ((m = ieee80211_get_probe_req(ic, ni)) == NULL)
1657 0 : senderr(ENOMEM, is_tx_nombuf);
1658 :
1659 : timer = IEEE80211_TRANS_WAIT;
1660 0 : break;
1661 : #ifndef IEEE80211_STA_ONLY
1662 : case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
1663 0 : if ((m = ieee80211_get_probe_resp(ic, ni)) == NULL)
1664 0 : senderr(ENOMEM, is_tx_nombuf);
1665 : break;
1666 : #endif
1667 : case IEEE80211_FC0_SUBTYPE_AUTH:
1668 0 : m = ieee80211_get_auth(ic, ni, arg1 >> 16, arg1 & 0xffff);
1669 0 : if (m == NULL)
1670 0 : senderr(ENOMEM, is_tx_nombuf);
1671 :
1672 0 : if (ic->ic_opmode == IEEE80211_M_STA)
1673 0 : timer = IEEE80211_TRANS_WAIT;
1674 : break;
1675 :
1676 : case IEEE80211_FC0_SUBTYPE_DEAUTH:
1677 0 : if ((m = ieee80211_get_deauth(ic, ni, arg1)) == NULL)
1678 0 : senderr(ENOMEM, is_tx_nombuf);
1679 : #ifndef IEEE80211_STA_ONLY
1680 0 : if ((ifp->if_flags & IFF_DEBUG) &&
1681 0 : (ic->ic_opmode == IEEE80211_M_HOSTAP ||
1682 0 : ic->ic_opmode == IEEE80211_M_IBSS))
1683 0 : printf("%s: station %s deauthenticate (reason %d)\n",
1684 0 : ifp->if_xname, ether_sprintf(ni->ni_macaddr),
1685 : arg1);
1686 : #endif
1687 : break;
1688 :
1689 : case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
1690 : case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
1691 0 : if ((m = ieee80211_get_assoc_req(ic, ni, type)) == NULL)
1692 0 : senderr(ENOMEM, is_tx_nombuf);
1693 :
1694 : timer = IEEE80211_TRANS_WAIT;
1695 0 : break;
1696 : #ifndef IEEE80211_STA_ONLY
1697 : case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
1698 : case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
1699 0 : if ((m = ieee80211_get_assoc_resp(ic, ni, arg1)) == NULL)
1700 0 : senderr(ENOMEM, is_tx_nombuf);
1701 : break;
1702 : #endif
1703 : case IEEE80211_FC0_SUBTYPE_DISASSOC:
1704 0 : if ((m = ieee80211_get_disassoc(ic, ni, arg1)) == NULL)
1705 0 : senderr(ENOMEM, is_tx_nombuf);
1706 : #ifndef IEEE80211_STA_ONLY
1707 0 : if ((ifp->if_flags & IFF_DEBUG) &&
1708 0 : (ic->ic_opmode == IEEE80211_M_HOSTAP ||
1709 0 : ic->ic_opmode == IEEE80211_M_IBSS))
1710 0 : printf("%s: station %s disassociate (reason %d)\n",
1711 0 : ifp->if_xname, ether_sprintf(ni->ni_macaddr),
1712 : arg1);
1713 : #endif
1714 : break;
1715 :
1716 : case IEEE80211_FC0_SUBTYPE_ACTION:
1717 0 : m = ieee80211_get_action(ic, ni, arg1 >> 16, arg1 & 0xffff,
1718 : arg2);
1719 0 : if (m == NULL)
1720 0 : senderr(ENOMEM, is_tx_nombuf);
1721 : break;
1722 :
1723 : default:
1724 : DPRINTF(("invalid mgmt frame type %u\n", type));
1725 0 : senderr(EINVAL, is_tx_unknownmgt);
1726 : /* NOTREACHED */
1727 : }
1728 :
1729 0 : ret = ieee80211_mgmt_output(ifp, ni, m, type);
1730 0 : if (ret == 0) {
1731 0 : if (timer)
1732 0 : ic->ic_mgt_timer = timer;
1733 : } else {
1734 : bad:
1735 0 : ieee80211_release_node(ic, ni);
1736 : }
1737 0 : return ret;
1738 : #undef senderr
1739 : }
1740 :
1741 : /*
1742 : * Build a RTS (Request To Send) control frame (see 7.2.1.1).
1743 : */
1744 : struct mbuf *
1745 0 : ieee80211_get_rts(struct ieee80211com *ic, const struct ieee80211_frame *wh,
1746 : u_int16_t dur)
1747 : {
1748 : struct ieee80211_frame_rts *rts;
1749 : struct mbuf *m;
1750 :
1751 0 : MGETHDR(m, M_DONTWAIT, MT_DATA);
1752 0 : if (m == NULL)
1753 0 : return NULL;
1754 :
1755 0 : m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_rts);
1756 :
1757 0 : rts = mtod(m, struct ieee80211_frame_rts *);
1758 0 : rts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
1759 : IEEE80211_FC0_SUBTYPE_RTS;
1760 0 : rts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
1761 0 : *(u_int16_t *)rts->i_dur = htole16(dur);
1762 0 : IEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1);
1763 0 : IEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2);
1764 :
1765 0 : return m;
1766 0 : }
1767 :
1768 : /*
1769 : * Build a CTS-to-self (Clear To Send) control frame (see 7.2.1.2).
1770 : */
1771 : struct mbuf *
1772 0 : ieee80211_get_cts_to_self(struct ieee80211com *ic, u_int16_t dur)
1773 : {
1774 : struct ieee80211_frame_cts *cts;
1775 : struct mbuf *m;
1776 :
1777 0 : MGETHDR(m, M_DONTWAIT, MT_DATA);
1778 0 : if (m == NULL)
1779 0 : return NULL;
1780 :
1781 0 : m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_cts);
1782 :
1783 0 : cts = mtod(m, struct ieee80211_frame_cts *);
1784 0 : cts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
1785 : IEEE80211_FC0_SUBTYPE_CTS;
1786 0 : cts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
1787 0 : *(u_int16_t *)cts->i_dur = htole16(dur);
1788 0 : IEEE80211_ADDR_COPY(cts->i_ra, ic->ic_myaddr);
1789 :
1790 0 : return m;
1791 0 : }
1792 :
1793 : #ifndef IEEE80211_STA_ONLY
1794 : /*-
1795 : * Beacon frame format:
1796 : * [8] Timestamp
1797 : * [2] Beacon interval
1798 : * [2] Capability
1799 : * [tlv] Service Set Identifier (SSID)
1800 : * [tlv] Supported rates
1801 : * [tlv] DS Parameter Set (802.11g)
1802 : * [tlv] IBSS Parameter Set
1803 : * [tlv] Traffic Indication Map (TIM)
1804 : * [tlv] ERP Information (802.11g)
1805 : * [tlv] Extended Supported Rates (802.11g)
1806 : * [tlv] RSN (802.11i)
1807 : * [tlv] EDCA Parameter Set (802.11e)
1808 : * [tlv] HT Capabilities (802.11n)
1809 : * [tlv] HT Operation (802.11n)
1810 : */
1811 : struct mbuf *
1812 0 : ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni)
1813 : {
1814 0 : const struct ieee80211_rateset *rs = &ni->ni_rates;
1815 : struct ieee80211_frame *wh;
1816 : struct mbuf *m;
1817 : u_int8_t *frm;
1818 :
1819 0 : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
1820 : 8 + 2 + 2 +
1821 0 : 2 + ((ic->ic_flags & IEEE80211_F_HIDENWID) ? 0 : ni->ni_esslen) +
1822 0 : 2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
1823 0 : 2 + 1 +
1824 0 : 2 + ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 254) +
1825 0 : ((ic->ic_curmode == IEEE80211_MODE_11G) ? 2 + 1 : 0) +
1826 0 : ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
1827 0 : 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
1828 0 : (((ic->ic_flags & IEEE80211_F_RSNON) &&
1829 0 : (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?
1830 0 : 2 + IEEE80211_RSNIE_MAXLEN : 0) +
1831 0 : ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0) +
1832 0 : (((ic->ic_flags & IEEE80211_F_RSNON) &&
1833 0 : (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?
1834 0 : 2 + IEEE80211_WPAIE_MAXLEN : 0) +
1835 0 : ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));
1836 0 : if (m == NULL)
1837 0 : return NULL;
1838 :
1839 0 : M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
1840 0 : if (m == NULL)
1841 0 : return NULL;
1842 0 : wh = mtod(m, struct ieee80211_frame *);
1843 0 : wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
1844 : IEEE80211_FC0_SUBTYPE_BEACON;
1845 0 : wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
1846 0 : *(u_int16_t *)wh->i_dur = 0;
1847 0 : IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
1848 0 : IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
1849 0 : IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
1850 0 : *(u_int16_t *)wh->i_seq = 0;
1851 :
1852 0 : frm = (u_int8_t *)&wh[1];
1853 0 : memset(frm, 0, 8); frm += 8; /* timestamp is set by hardware */
1854 0 : LE_WRITE_2(frm, ni->ni_intval); frm += 2;
1855 0 : frm = ieee80211_add_capinfo(frm, ic, ni);
1856 0 : if (ic->ic_flags & IEEE80211_F_HIDENWID)
1857 0 : frm = ieee80211_add_ssid(frm, NULL, 0);
1858 : else
1859 0 : frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
1860 0 : frm = ieee80211_add_rates(frm, rs);
1861 0 : frm = ieee80211_add_ds_params(frm, ic, ni);
1862 0 : if (ic->ic_opmode == IEEE80211_M_IBSS)
1863 0 : frm = ieee80211_add_ibss_params(frm, ni);
1864 : else
1865 0 : frm = ieee80211_add_tim(frm, ic);
1866 0 : if (ic->ic_curmode == IEEE80211_MODE_11G)
1867 0 : frm = ieee80211_add_erp(frm, ic);
1868 0 : if (rs->rs_nrates > IEEE80211_RATE_SIZE)
1869 0 : frm = ieee80211_add_xrates(frm, rs);
1870 0 : if ((ic->ic_flags & IEEE80211_F_RSNON) &&
1871 0 : (ni->ni_rsnprotos & IEEE80211_PROTO_RSN))
1872 0 : frm = ieee80211_add_rsn(frm, ic, ni);
1873 0 : if (ic->ic_flags & IEEE80211_F_QOS)
1874 0 : frm = ieee80211_add_edca_params(frm, ic);
1875 0 : if ((ic->ic_flags & IEEE80211_F_RSNON) &&
1876 0 : (ni->ni_rsnprotos & IEEE80211_PROTO_WPA))
1877 0 : frm = ieee80211_add_wpa(frm, ic, ni);
1878 0 : if (ic->ic_flags & IEEE80211_F_HTON) {
1879 0 : frm = ieee80211_add_htcaps(frm, ic);
1880 0 : frm = ieee80211_add_htop(frm, ic);
1881 0 : frm = ieee80211_add_wme_param(frm, ic);
1882 0 : }
1883 :
1884 0 : m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1885 0 : m->m_pkthdr.ph_cookie = ni;
1886 :
1887 0 : return m;
1888 0 : }
1889 :
1890 : /*
1891 : * Check if an outgoing MSDU or management frame should be buffered into
1892 : * the AP for power management. Return 1 if the frame was buffered into
1893 : * the AP, or 0 if the frame shall be transmitted immediately.
1894 : */
1895 : int
1896 0 : ieee80211_pwrsave(struct ieee80211com *ic, struct mbuf *m,
1897 : struct ieee80211_node *ni)
1898 : {
1899 : const struct ieee80211_frame *wh;
1900 0 : int pssta = 0;
1901 :
1902 0 : KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP);
1903 0 : if (!(ic->ic_caps & IEEE80211_C_APPMGT))
1904 0 : return 0;
1905 :
1906 0 : wh = mtod(m, struct ieee80211_frame *);
1907 0 : if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1908 : /*
1909 : * Buffer group addressed MSDUs with the Order bit clear
1910 : * if any associated STAs are in PS mode.
1911 : */
1912 0 : ieee80211_iterate_nodes(ic, ieee80211_count_pssta, &pssta);
1913 0 : if ((wh->i_fc[1] & IEEE80211_FC1_ORDER) || pssta == 0)
1914 0 : return 0;
1915 0 : ic->ic_tim_mcast_pending = 1;
1916 0 : } else {
1917 : /*
1918 : * Buffer MSDUs, A-MSDUs or management frames destined for
1919 : * PS STAs.
1920 : */
1921 0 : if (ni->ni_pwrsave == IEEE80211_PS_AWAKE ||
1922 0 : (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
1923 : IEEE80211_FC0_TYPE_CTL)
1924 0 : return 0;
1925 0 : if (mq_empty(&ni->ni_savedq))
1926 0 : (*ic->ic_set_tim)(ic, ni->ni_associd, 1);
1927 : }
1928 : /* NB: ni == ic->ic_bss for broadcast/multicast */
1929 : /*
1930 : * Similar to ieee80211_mgmt_output, store the node in a
1931 : * special pkthdr field.
1932 : */
1933 0 : m->m_pkthdr.ph_cookie = ni;
1934 0 : mq_enqueue(&ni->ni_savedq, m);
1935 0 : return 1;
1936 0 : }
1937 : #endif /* IEEE80211_STA_ONLY */
|