ieee80211_ioctl.c revision 1.60.18.7 1 /* $NetBSD: ieee80211_ioctl.c,v 1.60.18.7 2018/08/15 17:07:02 phil Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 *
6 * Copyright (c) 2001 Atsushi Onoe
7 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
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 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 #if __FreeBSD__
33 __FBSDID("$FreeBSD$");
34 #endif
35
36 /*
37 * IEEE 802.11 ioctl support (FreeBSD-specific)
38 */
39
40 #include "opt_inet.h"
41 #include "opt_wlan.h"
42
43 #include <sys/endian.h>
44 #include <sys/param.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #if __FreeBSD__
48 #include <sys/priv.h>
49 #endif
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 #include <sys/systm.h>
53
54 #include <net/if.h>
55 #if __FreeBSD__
56 #include <net/if_var.h>
57 #endif
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #if __FreeBSD__
61 #include <net/ethernet.h>
62 #endif
63 #if __NetBSD__
64 #include <net/if_ether.h>
65 #endif
66
67 #ifdef INET
68 #include <netinet/in.h>
69 #if __FreeBSD__
70 #include <netinet/if_ether.h>
71 #endif
72 #if __NetBSD__
73 #include <netinet/if_inarp.h>
74 #endif
75 #endif
76
77 #include <net80211/ieee80211_var.h>
78 #include <net80211/ieee80211_ioctl.h>
79 #include <net80211/ieee80211_regdomain.h>
80 #include <net80211/ieee80211_input.h>
81
82 #ifdef __NetBSD__
83 #undef KASSERT
84 #define KASSERT(__cond, __complaint) FBSDKASSERT(__cond, __complaint)
85 #endif
86
87 #define IS_UP_AUTO(_vap) \
88 (IFNET_IS_UP_RUNNING((_vap)->iv_ifp) && \
89 (_vap)->iv_roaming == IEEE80211_ROAMING_AUTO)
90
91 static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
92 static struct ieee80211_channel *findchannel(struct ieee80211com *,
93 int ieee, int mode);
94 static int ieee80211_scanreq(struct ieee80211vap *,
95 struct ieee80211_scan_req *);
96
97 static int
98 ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
99 {
100 struct ieee80211com *ic = vap->iv_ic;
101 struct ieee80211_node *ni;
102 struct ieee80211req_key ik;
103 struct ieee80211_key *wk;
104 const struct ieee80211_cipher *cip;
105 u_int kid;
106 int error;
107
108 if (ireq->i_len != sizeof(ik))
109 return EINVAL;
110 error = copyin(ireq->i_data, &ik, sizeof(ik));
111 if (error)
112 return error;
113 kid = ik.ik_keyix;
114 if (kid == IEEE80211_KEYIX_NONE) {
115 ni = ieee80211_find_vap_node(&ic->ic_sta, vap, ik.ik_macaddr);
116 if (ni == NULL)
117 return ENOENT;
118 wk = &ni->ni_ucastkey;
119 } else {
120 if (kid >= IEEE80211_WEP_NKID)
121 return EINVAL;
122 wk = &vap->iv_nw_keys[kid];
123 IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr);
124 ni = NULL;
125 }
126 cip = wk->wk_cipher;
127 ik.ik_type = cip->ic_cipher;
128 ik.ik_keylen = wk->wk_keylen;
129 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
130 if (wk->wk_keyix == vap->iv_def_txkey)
131 ik.ik_flags |= IEEE80211_KEY_DEFAULT;
132 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
133 /* NB: only root can read key data */
134 ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID];
135 ik.ik_keytsc = wk->wk_keytsc;
136 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
137 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
138 memcpy(ik.ik_keydata+wk->wk_keylen,
139 wk->wk_key + IEEE80211_KEYBUF_SIZE,
140 IEEE80211_MICBUF_SIZE);
141 ik.ik_keylen += IEEE80211_MICBUF_SIZE;
142 }
143 } else {
144 ik.ik_keyrsc = 0;
145 ik.ik_keytsc = 0;
146 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
147 }
148 if (ni != NULL)
149 ieee80211_free_node(ni);
150 return copyout(&ik, ireq->i_data, sizeof(ik));
151 }
152
153 static int
154 ieee80211_ioctl_getchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
155 {
156 struct ieee80211com *ic = vap->iv_ic;
157
158 if (sizeof(ic->ic_chan_active) < ireq->i_len)
159 ireq->i_len = sizeof(ic->ic_chan_active);
160 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
161 }
162
163 static int
164 ieee80211_ioctl_getchaninfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
165 {
166 struct ieee80211com *ic = vap->iv_ic;
167 uint32_t space;
168
169 space = __offsetof(struct ieee80211req_chaninfo,
170 ic_chans[ic->ic_nchans]);
171 if (space > ireq->i_len)
172 space = ireq->i_len;
173 /* XXX assumes compatible layout */
174 return copyout(&ic->ic_nchans, ireq->i_data, space);
175 }
176
177 static int
178 ieee80211_ioctl_getwpaie(struct ieee80211vap *vap,
179 struct ieee80211req *ireq, int req)
180 {
181 struct ieee80211_node *ni;
182 struct ieee80211req_wpaie2 *wpaie;
183 int error;
184
185 if (ireq->i_len < IEEE80211_ADDR_LEN)
186 return EINVAL;
187 wpaie = IEEE80211_MALLOC(sizeof(*wpaie), M_TEMP,
188 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
189 if (wpaie == NULL)
190 return ENOMEM;
191 error = copyin(ireq->i_data, wpaie->wpa_macaddr, IEEE80211_ADDR_LEN);
192 if (error != 0)
193 goto bad;
194 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie->wpa_macaddr);
195 if (ni == NULL) {
196 error = ENOENT;
197 goto bad;
198 }
199 if (ni->ni_ies.wpa_ie != NULL) {
200 int ielen = ni->ni_ies.wpa_ie[1] + 2;
201 if (ielen > sizeof(wpaie->wpa_ie))
202 ielen = sizeof(wpaie->wpa_ie);
203 memcpy(wpaie->wpa_ie, ni->ni_ies.wpa_ie, ielen);
204 }
205 if (req == IEEE80211_IOC_WPAIE2) {
206 if (ni->ni_ies.rsn_ie != NULL) {
207 int ielen = ni->ni_ies.rsn_ie[1] + 2;
208 if (ielen > sizeof(wpaie->rsn_ie))
209 ielen = sizeof(wpaie->rsn_ie);
210 memcpy(wpaie->rsn_ie, ni->ni_ies.rsn_ie, ielen);
211 }
212 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2))
213 ireq->i_len = sizeof(struct ieee80211req_wpaie2);
214 } else {
215 /* compatibility op, may overwrite wpa ie */
216 /* XXX check ic_flags? */
217 if (ni->ni_ies.rsn_ie != NULL) {
218 int ielen = ni->ni_ies.rsn_ie[1] + 2;
219 if (ielen > sizeof(wpaie->wpa_ie))
220 ielen = sizeof(wpaie->wpa_ie);
221 memcpy(wpaie->wpa_ie, ni->ni_ies.rsn_ie, ielen);
222 }
223 if (ireq->i_len > sizeof(struct ieee80211req_wpaie))
224 ireq->i_len = sizeof(struct ieee80211req_wpaie);
225 }
226 ieee80211_free_node(ni);
227 error = copyout(wpaie, ireq->i_data, ireq->i_len);
228 bad:
229 IEEE80211_FREE(wpaie, M_TEMP);
230 return error;
231 }
232
233 static int
234 ieee80211_ioctl_getstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
235 {
236 struct ieee80211_node *ni;
237 uint8_t macaddr[IEEE80211_ADDR_LEN];
238 const size_t off = __offsetof(struct ieee80211req_sta_stats, is_stats);
239 int error;
240
241 if (ireq->i_len < off)
242 return EINVAL;
243 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
244 if (error != 0)
245 return error;
246 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
247 if (ni == NULL)
248 return ENOENT;
249 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats))
250 ireq->i_len = sizeof(struct ieee80211req_sta_stats);
251 /* NB: copy out only the statistics */
252 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off,
253 ireq->i_len - off);
254 ieee80211_free_node(ni);
255 return error;
256 }
257
258 struct scanreq {
259 struct ieee80211req_scan_result *sr;
260 size_t space;
261 };
262
263 static size_t
264 scan_space(const struct ieee80211_scan_entry *se, int *ielen)
265 {
266 size_t len;
267
268 *ielen = se->se_ies.len;
269 /*
270 * NB: ie's can be no more than 255 bytes and the max 802.11
271 * packet is <3Kbytes so we are sure this doesn't overflow
272 * 16-bits; if this is a concern we can drop the ie's.
273 */
274 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] +
275 se->se_meshid[1] + *ielen;
276 return roundup(len, sizeof(uint32_t));
277 }
278
279 static void
280 get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
281 {
282 struct scanreq *req = arg;
283 int ielen;
284
285 req->space += scan_space(se, &ielen);
286 }
287
288 static void
289 get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
290 {
291 struct scanreq *req = arg;
292 struct ieee80211req_scan_result *sr;
293 int ielen, len, nr, nxr;
294 uint8_t *cp;
295
296 len = scan_space(se, &ielen);
297 if (len > req->space)
298 return;
299
300 sr = req->sr;
301 KASSERT(len <= 65535 && ielen <= 65535,
302 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen));
303 sr->isr_len = len;
304 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result);
305 sr->isr_ie_len = ielen;
306 sr->isr_freq = se->se_chan->ic_freq;
307 sr->isr_flags = se->se_chan->ic_flags;
308 sr->isr_rssi = se->se_rssi;
309 sr->isr_noise = se->se_noise;
310 sr->isr_intval = se->se_intval;
311 sr->isr_capinfo = se->se_capinfo;
312 sr->isr_erp = se->se_erp;
313 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
314 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
315 memcpy(sr->isr_rates, se->se_rates+2, nr);
316 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
317 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
318 sr->isr_nrates = nr + nxr;
319
320 /* copy SSID */
321 sr->isr_ssid_len = se->se_ssid[1];
322 cp = ((uint8_t *)sr) + sr->isr_ie_off;
323 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
324
325 /* copy mesh id */
326 cp += sr->isr_ssid_len;
327 sr->isr_meshid_len = se->se_meshid[1];
328 memcpy(cp, se->se_meshid+2, sr->isr_meshid_len);
329 cp += sr->isr_meshid_len;
330
331 if (ielen)
332 memcpy(cp, se->se_ies.data, ielen);
333
334 req->space -= len;
335 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
336 }
337
338 static int
339 ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
340 struct ieee80211req *ireq)
341 {
342 struct scanreq req;
343 int error;
344
345 if (ireq->i_len < sizeof(struct scanreq))
346 return EFAULT;
347
348 error = 0;
349 req.space = 0;
350 ieee80211_scan_iterate(vap, get_scan_space, &req);
351 if (req.space > ireq->i_len)
352 req.space = ireq->i_len;
353 if (req.space > 0) {
354 uint32_t space;
355 void *p;
356
357 space = req.space;
358 /* XXX M_WAITOK after driver lock released */
359 p = IEEE80211_MALLOC(space, M_TEMP,
360 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
361 if (p == NULL)
362 return ENOMEM;
363 req.sr = p;
364 ieee80211_scan_iterate(vap, get_scan_result, &req);
365 ireq->i_len = space - req.space;
366 error = copyout(p, ireq->i_data, ireq->i_len);
367 IEEE80211_FREE(p, M_TEMP);
368 } else
369 ireq->i_len = 0;
370
371 return error;
372 }
373
374 #ifdef OLD_IEEE80211_IOC_SCAN_RESULTS
375 /* Code to get the old version of scan results, for NetBSD 8.0 and earlier. */
376
377 static size_t
378 old_scan_space(const struct ieee80211_scan_entry *se, int *ielen)
379 {
380 size_t len;
381
382 *ielen = se->se_ies.len;
383 /*
384 * NB: ie's can be no more than 255 bytes and the max 802.11
385 * packet is <3Kbytes so we are sure this doesn't overflow
386 * 16-bits; if this is a concern we can drop the ie's.
387 */
388 len = sizeof(struct old_ieee80211req_scan_result) + se->se_ssid[1] +
389 se->se_meshid[1] + *ielen;
390 return roundup(len, sizeof(uint32_t));
391 }
392
393 static void
394 old_get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
395 {
396 struct scanreq *req = arg;
397 int ielen;
398
399 req->space += old_scan_space(se, &ielen);
400 }
401
402 static void
403 old_get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
404 {
405 struct scanreq *req = arg;
406 struct old_ieee80211req_scan_result *sr;
407 int ielen, len, nr, nxr;
408 uint8_t *cp;
409
410 len = old_scan_space(se, &ielen);
411 if (len > req->space)
412 return;
413
414 sr = (struct old_ieee80211req_scan_result *)req->sr;
415 KASSERT(len <= 65535 && ielen <= 65535,
416 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen));
417 sr->isr_len = len;
418 sr->isr_ie_len = ielen;
419 sr->isr_freq = se->se_chan->ic_freq;
420 sr->isr_flags = se->se_chan->ic_flags;
421 sr->isr_rssi = se->se_rssi;
422 sr->isr_noise = se->se_noise;
423 sr->isr_intval = se->se_intval;
424 sr->isr_capinfo = se->se_capinfo;
425 sr->isr_erp = se->se_erp;
426 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
427 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
428 memcpy(sr->isr_rates, se->se_rates+2, nr);
429 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
430 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
431 sr->isr_nrates = nr + nxr;
432 if (sr->isr_nrates > 15)
433 sr->isr_nrates = 15;
434
435 printf ("old_get_scan_results: ssid=%.*s\n", se->se_ssid[1], &se->se_ssid[2]);
436
437 /* copy SSID */
438 sr->isr_ssid_len = se->se_ssid[1];
439 cp = ((uint8_t *)sr) + sizeof(struct old_ieee80211req_scan_result);
440 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
441
442 if (ielen)
443 memcpy(cp+sr->isr_ssid_len, se->se_ies.data, ielen);
444
445 req->space -= len;
446 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
447 }
448
449 static int
450 old_ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
451 struct ieee80211req *ireq)
452 {
453 struct scanreq req;
454 int error;
455
456 if (ireq->i_len < sizeof(struct scanreq))
457 return EFAULT;
458
459 error = 0;
460 req.space = 0;
461 ieee80211_scan_iterate(vap, old_get_scan_space, &req);
462 if (req.space > ireq->i_len)
463 req.space = ireq->i_len;
464 if (req.space > 0) {
465 uint32_t space;
466 void *p;
467
468 space = req.space;
469 /* XXX M_WAITOK after driver lock released */
470 p = IEEE80211_MALLOC(space, M_TEMP,
471 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
472 if (p == NULL)
473 return ENOMEM;
474 req.sr = p;
475 ieee80211_scan_iterate(vap, old_get_scan_result, &req);
476 ireq->i_len = space - req.space;
477 error = copyout(p, ireq->i_data, ireq->i_len);
478 IEEE80211_FREE(p, M_TEMP);
479 } else
480 ireq->i_len = 0;
481
482 return error;
483 }
484
485 #endif
486
487 struct stainforeq {
488 struct ieee80211req_sta_info *si;
489 size_t space;
490 };
491
492 static size_t
493 sta_space(const struct ieee80211_node *ni, size_t *ielen)
494 {
495 *ielen = ni->ni_ies.len;
496 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
497 sizeof(uint32_t));
498 }
499
500 static void
501 get_sta_space(void *arg, struct ieee80211_node *ni)
502 {
503 struct stainforeq *req = arg;
504 size_t ielen;
505
506 if (ni->ni_vap->iv_opmode == IEEE80211_M_HOSTAP &&
507 ni->ni_associd == 0) /* only associated stations */
508 return;
509 req->space += sta_space(ni, &ielen);
510 }
511
512 static void
513 get_sta_info(void *arg, struct ieee80211_node *ni)
514 {
515 struct stainforeq *req = arg;
516 struct ieee80211vap *vap = ni->ni_vap;
517 struct ieee80211req_sta_info *si;
518 size_t ielen, len;
519 uint8_t *cp;
520
521 if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
522 ni->ni_associd == 0) /* only associated stations */
523 return;
524 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
525 return;
526 len = sta_space(ni, &ielen);
527 if (len > req->space)
528 return;
529 si = req->si;
530 si->isi_len = len;
531 si->isi_ie_off = sizeof(struct ieee80211req_sta_info);
532 si->isi_ie_len = ielen;
533 si->isi_freq = ni->ni_chan->ic_freq;
534 si->isi_flags = ni->ni_chan->ic_flags;
535 si->isi_state = ni->ni_flags;
536 si->isi_authmode = ni->ni_authmode;
537 vap->iv_ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise);
538 vap->iv_ic->ic_node_getmimoinfo(ni, &si->isi_mimo);
539 si->isi_capinfo = ni->ni_capinfo;
540 si->isi_erp = ni->ni_erp;
541 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr);
542 si->isi_nrates = ni->ni_rates.rs_nrates;
543 if (si->isi_nrates > 15)
544 si->isi_nrates = 15;
545 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
546 si->isi_txrate = ni->ni_txrate;
547 if (si->isi_txrate & IEEE80211_RATE_MCS) {
548 const struct ieee80211_mcs_rates *mcs =
549 &ieee80211_htrates[ni->ni_txrate &~ IEEE80211_RATE_MCS];
550 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
551 if (ni->ni_flags & IEEE80211_NODE_SGI40)
552 si->isi_txmbps = mcs->ht40_rate_800ns;
553 else
554 si->isi_txmbps = mcs->ht40_rate_400ns;
555 } else {
556 if (ni->ni_flags & IEEE80211_NODE_SGI20)
557 si->isi_txmbps = mcs->ht20_rate_800ns;
558 else
559 si->isi_txmbps = mcs->ht20_rate_400ns;
560 }
561 } else
562 si->isi_txmbps = si->isi_txrate;
563 si->isi_associd = ni->ni_associd;
564 si->isi_txpower = ni->ni_txpower;
565 si->isi_vlan = ni->ni_vlan;
566 if (ni->ni_flags & IEEE80211_NODE_QOS) {
567 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs));
568 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs));
569 } else {
570 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID];
571 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID];
572 }
573 /* NB: leave all cases in case we relax ni_associd == 0 check */
574 if (ieee80211_node_is_authorized(ni))
575 si->isi_inact = vap->iv_inact_run;
576 else if (ni->ni_associd != 0 ||
577 (vap->iv_opmode == IEEE80211_M_WDS &&
578 (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY)))
579 si->isi_inact = vap->iv_inact_auth;
580 else
581 si->isi_inact = vap->iv_inact_init;
582 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
583 si->isi_localid = ni->ni_mllid;
584 si->isi_peerid = ni->ni_mlpid;
585 si->isi_peerstate = ni->ni_mlstate;
586
587 if (ielen) {
588 cp = ((uint8_t *)si) + si->isi_ie_off;
589 memcpy(cp, ni->ni_ies.data, ielen);
590 }
591
592 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len);
593 req->space -= len;
594 }
595
596 static int
597 getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
598 struct ieee80211_node *ni, size_t off)
599 {
600 struct ieee80211com *ic = vap->iv_ic;
601 struct stainforeq req;
602 size_t space;
603 void *p;
604 int error;
605
606 error = 0;
607 req.space = 0;
608 if (ni == NULL) {
609 ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_sta_space,
610 &req);
611 } else
612 get_sta_space(&req, ni);
613 if (req.space > ireq->i_len)
614 req.space = ireq->i_len;
615 if (req.space > 0) {
616 space = req.space;
617 /* XXX M_WAITOK after driver lock released */
618 p = IEEE80211_MALLOC(space, M_TEMP,
619 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
620 if (p == NULL) {
621 error = ENOMEM;
622 goto bad;
623 }
624 req.si = p;
625 if (ni == NULL) {
626 ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
627 get_sta_info, &req);
628 } else
629 get_sta_info(&req, ni);
630 ireq->i_len = space - req.space;
631 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
632 IEEE80211_FREE(p, M_TEMP);
633 } else
634 ireq->i_len = 0;
635 bad:
636 if (ni != NULL)
637 ieee80211_free_node(ni);
638 return error;
639 }
640
641 static int
642 ieee80211_ioctl_getstainfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
643 {
644 uint8_t macaddr[IEEE80211_ADDR_LEN];
645 const size_t off = __offsetof(struct ieee80211req_sta_req, info);
646 struct ieee80211_node *ni;
647 int error;
648
649 if (ireq->i_len < sizeof(struct ieee80211req_sta_req))
650 return EFAULT;
651 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
652 if (error != 0)
653 return error;
654 if (IEEE80211_ADDR_EQ(macaddr, vap->iv_ifp->if_broadcastaddr)) {
655 ni = NULL;
656 } else {
657 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
658 if (ni == NULL)
659 return ENOENT;
660 }
661 return getstainfo_common(vap, ireq, ni, off);
662 }
663
664 static int
665 ieee80211_ioctl_getstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
666 {
667 struct ieee80211_node *ni;
668 struct ieee80211req_sta_txpow txpow;
669 int error;
670
671 if (ireq->i_len != sizeof(txpow))
672 return EINVAL;
673 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
674 if (error != 0)
675 return error;
676 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr);
677 if (ni == NULL)
678 return ENOENT;
679 txpow.it_txpow = ni->ni_txpower;
680 error = copyout(&txpow, ireq->i_data, sizeof(txpow));
681 ieee80211_free_node(ni);
682 return error;
683 }
684
685 static int
686 ieee80211_ioctl_getwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
687 {
688 struct ieee80211com *ic = vap->iv_ic;
689 struct ieee80211_wme_state *wme = &ic->ic_wme;
690 struct wmeParams *wmep;
691 int ac;
692
693 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
694 return EINVAL;
695
696 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
697 if (ac >= WME_NUM_AC)
698 ac = WME_AC_BE;
699 if (ireq->i_len & IEEE80211_WMEPARAM_BSS)
700 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
701 else
702 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
703 switch (ireq->i_type) {
704 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
705 ireq->i_val = wmep->wmep_logcwmin;
706 break;
707 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
708 ireq->i_val = wmep->wmep_logcwmax;
709 break;
710 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
711 ireq->i_val = wmep->wmep_aifsn;
712 break;
713 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
714 ireq->i_val = wmep->wmep_txopLimit;
715 break;
716 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
717 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
718 ireq->i_val = wmep->wmep_acm;
719 break;
720 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
721 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
722 ireq->i_val = !wmep->wmep_noackPolicy;
723 break;
724 }
725 return 0;
726 }
727
728 static int
729 ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
730 {
731 const struct ieee80211_aclator *acl = vap->iv_acl;
732
733 return (acl == NULL ? EINVAL : acl->iac_getioctl(vap, ireq));
734 }
735
736 static int
737 ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq)
738 {
739 struct ieee80211com *ic = vap->iv_ic;
740 struct ieee80211_channel *c;
741
742 if (ireq->i_len != sizeof(struct ieee80211_channel))
743 return EINVAL;
744 /*
745 * vap's may have different operating channels when HT is
746 * in use. When in RUN state report the vap-specific channel.
747 * Otherwise return curchan.
748 */
749 if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)
750 c = vap->iv_bss->ni_chan;
751 else
752 c = ic->ic_curchan;
753 return copyout(c, ireq->i_data, sizeof(*c));
754 }
755
756 static int
757 getappie(const struct ieee80211_appie *aie, struct ieee80211req *ireq)
758 {
759 if (aie == NULL)
760 return EINVAL;
761 /* NB: truncate, caller can check length */
762 if (ireq->i_len > aie->ie_len)
763 ireq->i_len = aie->ie_len;
764 return copyout(aie->ie_data, ireq->i_data, ireq->i_len);
765 }
766
767 static int
768 ieee80211_ioctl_getappie(struct ieee80211vap *vap, struct ieee80211req *ireq)
769 {
770 uint8_t fc0;
771
772 fc0 = ireq->i_val & 0xff;
773 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
774 return EINVAL;
775 /* NB: could check iv_opmode and reject but hardly worth the effort */
776 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) {
777 case IEEE80211_FC0_SUBTYPE_BEACON:
778 return getappie(vap->iv_appie_beacon, ireq);
779 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
780 return getappie(vap->iv_appie_proberesp, ireq);
781 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
782 return getappie(vap->iv_appie_assocresp, ireq);
783 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
784 return getappie(vap->iv_appie_probereq, ireq);
785 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
786 return getappie(vap->iv_appie_assocreq, ireq);
787 case IEEE80211_FC0_SUBTYPE_BEACON|IEEE80211_FC0_SUBTYPE_PROBE_RESP:
788 return getappie(vap->iv_appie_wpa, ireq);
789 }
790 return EINVAL;
791 }
792
793 static int
794 ieee80211_ioctl_getregdomain(struct ieee80211vap *vap,
795 const struct ieee80211req *ireq)
796 {
797 struct ieee80211com *ic = vap->iv_ic;
798
799 if (ireq->i_len != sizeof(ic->ic_regdomain))
800 return EINVAL;
801 return copyout(&ic->ic_regdomain, ireq->i_data,
802 sizeof(ic->ic_regdomain));
803 }
804
805 static int
806 ieee80211_ioctl_getroam(struct ieee80211vap *vap,
807 const struct ieee80211req *ireq)
808 {
809 size_t len = ireq->i_len;
810 /* NB: accept short requests for backwards compat */
811 if (len > sizeof(vap->iv_roamparms))
812 len = sizeof(vap->iv_roamparms);
813 return copyout(vap->iv_roamparms, ireq->i_data, len);
814 }
815
816 static int
817 ieee80211_ioctl_gettxparams(struct ieee80211vap *vap,
818 const struct ieee80211req *ireq)
819 {
820 size_t len = ireq->i_len;
821 /* NB: accept short requests for backwards compat */
822 if (len > sizeof(vap->iv_txparms))
823 len = sizeof(vap->iv_txparms);
824 return copyout(vap->iv_txparms, ireq->i_data, len);
825 }
826
827 static int
828 ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
829 const struct ieee80211req *ireq)
830 {
831 struct ieee80211_devcaps_req *dc;
832 struct ieee80211req_chaninfo *ci;
833 int maxchans, error;
834
835 maxchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_devcaps_req)) /
836 sizeof(struct ieee80211_channel));
837 /* NB: require 1 so we know ic_nchans is accessible */
838 if (maxchans < 1)
839 return EINVAL;
840 /* constrain max request size, 2K channels is ~24Kbytes */
841 if (maxchans > 2048)
842 maxchans = 2048;
843 dc = (struct ieee80211_devcaps_req *)
844 IEEE80211_MALLOC(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP,
845 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
846 if (dc == NULL)
847 return ENOMEM;
848 dc->dc_drivercaps = ic->ic_caps;
849 dc->dc_cryptocaps = ic->ic_cryptocaps;
850 dc->dc_htcaps = ic->ic_htcaps;
851 dc->dc_vhtcaps = ic->ic_vhtcaps;
852 ci = &dc->dc_chaninfo;
853 ic->ic_getradiocaps(ic, maxchans, &ci->ic_nchans, ci->ic_chans);
854 KASSERT(ci->ic_nchans <= maxchans,
855 ("nchans %d maxchans %d", ci->ic_nchans, maxchans));
856 ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
857 error = copyout(dc, ireq->i_data, IEEE80211_DEVCAPS_SPACE(dc));
858 IEEE80211_FREE(dc, M_TEMP);
859 return error;
860 }
861
862 static int
863 ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
864 {
865 struct ieee80211_node *ni;
866 struct ieee80211req_sta_vlan vlan;
867 int error;
868
869 if (ireq->i_len != sizeof(vlan))
870 return EINVAL;
871 error = copyin(ireq->i_data, &vlan, sizeof(vlan));
872 if (error != 0)
873 return error;
874 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) {
875 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
876 vlan.sv_macaddr);
877 if (ni == NULL)
878 return ENOENT;
879 } else
880 ni = ieee80211_ref_node(vap->iv_bss);
881 vlan.sv_vlan = ni->ni_vlan;
882 error = copyout(&vlan, ireq->i_data, sizeof(vlan));
883 ieee80211_free_node(ni);
884 return error;
885 }
886
887 /*
888 * Dummy ioctl get handler so the linker set is defined.
889 */
890 static __unused int
891 dummy_ioctl_get(struct ieee80211vap *vap, struct ieee80211req *ireq)
892 {
893 return ENOSYS;
894 }
895 IEEE80211_IOCTL_GET(dummy, dummy_ioctl_get);
896
897 static int
898 ieee80211_ioctl_getdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
899 {
900 int error;
901 #if notyet
902 ieee80211_ioctl_getfunc * const *get;
903
904 SET_FOREACH(get, ieee80211_ioctl_getset) {
905 error = (*get)(vap, ireq);
906 if (error != ENOSYS)
907 return error;
908 }
909 #else
910 printf ("ieee80211_ioctl_getdefault called\n");
911 error = dummy_ioctl_get(vap, ireq);
912 #endif
913 return error;
914 }
915
916 static int
917 ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
918 struct ieee80211req *ireq)
919 {
920 #define MS(_v, _f) (((_v) & _f) >> _f##_S)
921 struct ieee80211com *ic = vap->iv_ic;
922 u_int kid, len;
923 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
924 char tmpssid[IEEE80211_NWID_LEN];
925 int error = 0;
926
927 switch (ireq->i_type) {
928 case IEEE80211_IOC_SSID:
929 switch (vap->iv_state) {
930 case IEEE80211_S_INIT:
931 case IEEE80211_S_SCAN:
932 ireq->i_len = vap->iv_des_ssid[0].len;
933 memcpy(tmpssid, vap->iv_des_ssid[0].ssid, ireq->i_len);
934 break;
935 default:
936 ireq->i_len = vap->iv_bss->ni_esslen;
937 memcpy(tmpssid, vap->iv_bss->ni_essid, ireq->i_len);
938 break;
939 }
940 error = copyout(tmpssid, ireq->i_data, ireq->i_len);
941 break;
942 case IEEE80211_IOC_NUMSSIDS:
943 ireq->i_val = 1;
944 break;
945 case IEEE80211_IOC_WEP:
946 if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0)
947 ireq->i_val = IEEE80211_WEP_OFF;
948 else if (vap->iv_flags & IEEE80211_F_DROPUNENC)
949 ireq->i_val = IEEE80211_WEP_ON;
950 else
951 ireq->i_val = IEEE80211_WEP_MIXED;
952 break;
953 case IEEE80211_IOC_WEPKEY:
954 kid = (u_int) ireq->i_val;
955 if (kid >= IEEE80211_WEP_NKID)
956 return EINVAL;
957 len = (u_int) vap->iv_nw_keys[kid].wk_keylen;
958 /* NB: only root can read WEP keys */
959 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
960 bcopy(vap->iv_nw_keys[kid].wk_key, tmpkey, len);
961 } else {
962 bzero(tmpkey, len);
963 }
964 ireq->i_len = len;
965 error = copyout(tmpkey, ireq->i_data, len);
966 break;
967 case IEEE80211_IOC_NUMWEPKEYS:
968 ireq->i_val = IEEE80211_WEP_NKID;
969 break;
970 case IEEE80211_IOC_WEPTXKEY:
971 ireq->i_val = vap->iv_def_txkey;
972 break;
973 case IEEE80211_IOC_AUTHMODE:
974 if (vap->iv_flags & IEEE80211_F_WPA)
975 ireq->i_val = IEEE80211_AUTH_WPA;
976 else
977 ireq->i_val = vap->iv_bss->ni_authmode;
978 break;
979 case IEEE80211_IOC_CHANNEL:
980 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan);
981 break;
982 case IEEE80211_IOC_POWERSAVE:
983 if (vap->iv_flags & IEEE80211_F_PMGTON)
984 ireq->i_val = IEEE80211_POWERSAVE_ON;
985 else
986 ireq->i_val = IEEE80211_POWERSAVE_OFF;
987 break;
988 case IEEE80211_IOC_POWERSAVESLEEP:
989 ireq->i_val = ic->ic_lintval;
990 break;
991 case IEEE80211_IOC_RTSTHRESHOLD:
992 ireq->i_val = vap->iv_rtsthreshold;
993 break;
994 case IEEE80211_IOC_PROTMODE:
995 ireq->i_val = ic->ic_protmode;
996 break;
997 case IEEE80211_IOC_TXPOWER:
998 /*
999 * Tx power limit is the min of max regulatory
1000 * power, any user-set limit, and the max the
1001 * radio can do.
1002 *
1003 * TODO: methodize this
1004 */
1005 ireq->i_val = 2*ic->ic_curchan->ic_maxregpower;
1006 if (ireq->i_val > ic->ic_txpowlimit)
1007 ireq->i_val = ic->ic_txpowlimit;
1008 if (ireq->i_val > ic->ic_curchan->ic_maxpower)
1009 ireq->i_val = ic->ic_curchan->ic_maxpower;
1010 break;
1011 case IEEE80211_IOC_WPA:
1012 switch (vap->iv_flags & IEEE80211_F_WPA) {
1013 case IEEE80211_F_WPA1:
1014 ireq->i_val = 1;
1015 break;
1016 case IEEE80211_F_WPA2:
1017 ireq->i_val = 2;
1018 break;
1019 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2:
1020 ireq->i_val = 3;
1021 break;
1022 default:
1023 ireq->i_val = 0;
1024 break;
1025 }
1026 break;
1027 case IEEE80211_IOC_CHANLIST:
1028 error = ieee80211_ioctl_getchanlist(vap, ireq);
1029 break;
1030 case IEEE80211_IOC_ROAMING:
1031 ireq->i_val = vap->iv_roaming;
1032 break;
1033 case IEEE80211_IOC_PRIVACY:
1034 ireq->i_val = (vap->iv_flags & IEEE80211_F_PRIVACY) != 0;
1035 break;
1036 case IEEE80211_IOC_DROPUNENCRYPTED:
1037 ireq->i_val = (vap->iv_flags & IEEE80211_F_DROPUNENC) != 0;
1038 break;
1039 case IEEE80211_IOC_COUNTERMEASURES:
1040 ireq->i_val = (vap->iv_flags & IEEE80211_F_COUNTERM) != 0;
1041 break;
1042 case IEEE80211_IOC_WME:
1043 ireq->i_val = (vap->iv_flags & IEEE80211_F_WME) != 0;
1044 break;
1045 case IEEE80211_IOC_HIDESSID:
1046 ireq->i_val = (vap->iv_flags & IEEE80211_F_HIDESSID) != 0;
1047 break;
1048 case IEEE80211_IOC_APBRIDGE:
1049 ireq->i_val = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0;
1050 break;
1051 case IEEE80211_IOC_WPAKEY:
1052 error = ieee80211_ioctl_getkey(vap, ireq);
1053 break;
1054 case IEEE80211_IOC_CHANINFO:
1055 error = ieee80211_ioctl_getchaninfo(vap, ireq);
1056 break;
1057 case IEEE80211_IOC_BSSID:
1058 if (ireq->i_len != IEEE80211_ADDR_LEN)
1059 return EINVAL;
1060 if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) {
1061 error = copyout(vap->iv_opmode == IEEE80211_M_WDS ?
1062 vap->iv_bss->ni_macaddr : vap->iv_bss->ni_bssid,
1063 ireq->i_data, ireq->i_len);
1064 } else
1065 error = copyout(vap->iv_des_bssid, ireq->i_data,
1066 ireq->i_len);
1067 break;
1068 case IEEE80211_IOC_WPAIE:
1069 case IEEE80211_IOC_WPAIE2:
1070 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type);
1071 break;
1072 #ifdef OLD_IEEE80211_IOC_SCAN_RESULTS
1073 case OLD_IEEE80211_IOC_SCAN_RESULTS:
1074 error = old_ieee80211_ioctl_getscanresults(vap, ireq);
1075 break;
1076 #endif
1077 case IEEE80211_IOC_SCAN_RESULTS:
1078 error = ieee80211_ioctl_getscanresults(vap, ireq);
1079 break;
1080 case IEEE80211_IOC_STA_STATS:
1081 error = ieee80211_ioctl_getstastats(vap, ireq);
1082 break;
1083 case IEEE80211_IOC_TXPOWMAX:
1084 ireq->i_val = vap->iv_bss->ni_txpower;
1085 break;
1086 case IEEE80211_IOC_STA_TXPOW:
1087 error = ieee80211_ioctl_getstatxpow(vap, ireq);
1088 break;
1089 case IEEE80211_IOC_STA_INFO:
1090 error = ieee80211_ioctl_getstainfo(vap, ireq);
1091 break;
1092 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
1093 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
1094 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1095 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1096 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1097 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only) */
1098 error = ieee80211_ioctl_getwmeparam(vap, ireq);
1099 break;
1100 case IEEE80211_IOC_DTIM_PERIOD:
1101 ireq->i_val = vap->iv_dtim_period;
1102 break;
1103 case IEEE80211_IOC_BEACON_INTERVAL:
1104 /* NB: get from ic_bss for station mode */
1105 ireq->i_val = vap->iv_bss->ni_intval;
1106 break;
1107 case IEEE80211_IOC_PUREG:
1108 ireq->i_val = (vap->iv_flags & IEEE80211_F_PUREG) != 0;
1109 break;
1110 case IEEE80211_IOC_QUIET:
1111 ireq->i_val = vap->iv_quiet;
1112 break;
1113 case IEEE80211_IOC_QUIET_COUNT:
1114 ireq->i_val = vap->iv_quiet_count;
1115 break;
1116 case IEEE80211_IOC_QUIET_PERIOD:
1117 ireq->i_val = vap->iv_quiet_period;
1118 break;
1119 case IEEE80211_IOC_QUIET_DUR:
1120 ireq->i_val = vap->iv_quiet_duration;
1121 break;
1122 case IEEE80211_IOC_QUIET_OFFSET:
1123 ireq->i_val = vap->iv_quiet_offset;
1124 break;
1125 case IEEE80211_IOC_BGSCAN:
1126 ireq->i_val = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0;
1127 break;
1128 case IEEE80211_IOC_BGSCAN_IDLE:
1129 ireq->i_val = vap->iv_bgscanidle*hz/1000; /* ms */
1130 break;
1131 case IEEE80211_IOC_BGSCAN_INTERVAL:
1132 ireq->i_val = vap->iv_bgscanintvl/hz; /* seconds */
1133 break;
1134 case IEEE80211_IOC_SCANVALID:
1135 ireq->i_val = vap->iv_scanvalid/hz; /* seconds */
1136 break;
1137 case IEEE80211_IOC_FRAGTHRESHOLD:
1138 ireq->i_val = vap->iv_fragthreshold;
1139 break;
1140 case IEEE80211_IOC_MACCMD:
1141 error = ieee80211_ioctl_getmaccmd(vap, ireq);
1142 break;
1143 case IEEE80211_IOC_BURST:
1144 ireq->i_val = (vap->iv_flags & IEEE80211_F_BURST) != 0;
1145 break;
1146 case IEEE80211_IOC_BMISSTHRESHOLD:
1147 ireq->i_val = vap->iv_bmissthreshold;
1148 break;
1149 case IEEE80211_IOC_CURCHAN:
1150 error = ieee80211_ioctl_getcurchan(vap, ireq);
1151 break;
1152 case IEEE80211_IOC_SHORTGI:
1153 ireq->i_val = 0;
1154 if (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20)
1155 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20;
1156 if (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40)
1157 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40;
1158 break;
1159 case IEEE80211_IOC_AMPDU:
1160 ireq->i_val = 0;
1161 if (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_TX)
1162 ireq->i_val |= 1;
1163 if (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_RX)
1164 ireq->i_val |= 2;
1165 break;
1166 case IEEE80211_IOC_AMPDU_LIMIT:
1167 /* XXX TODO: make this a per-node thing; and leave this as global */
1168 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
1169 ireq->i_val = vap->iv_ampdu_rxmax;
1170 else if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)
1171 /*
1172 * XXX TODO: this isn't completely correct, as we've
1173 * negotiated the higher of the two.
1174 */
1175 ireq->i_val = MS(vap->iv_bss->ni_htparam,
1176 IEEE80211_HTCAP_MAXRXAMPDU);
1177 else
1178 ireq->i_val = vap->iv_ampdu_limit;
1179 break;
1180 case IEEE80211_IOC_AMPDU_DENSITY:
1181 /* XXX TODO: make this a per-node thing; and leave this as global */
1182 if (vap->iv_opmode == IEEE80211_M_STA &&
1183 (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP))
1184 /*
1185 * XXX TODO: this isn't completely correct, as we've
1186 * negotiated the higher of the two.
1187 */
1188 ireq->i_val = MS(vap->iv_bss->ni_htparam,
1189 IEEE80211_HTCAP_MPDUDENSITY);
1190 else
1191 ireq->i_val = vap->iv_ampdu_density;
1192 break;
1193 case IEEE80211_IOC_AMSDU:
1194 ireq->i_val = 0;
1195 if (vap->iv_flags_ht & IEEE80211_FHT_AMSDU_TX)
1196 ireq->i_val |= 1;
1197 if (vap->iv_flags_ht & IEEE80211_FHT_AMSDU_RX)
1198 ireq->i_val |= 2;
1199 break;
1200 case IEEE80211_IOC_AMSDU_LIMIT:
1201 ireq->i_val = vap->iv_amsdu_limit; /* XXX truncation? */
1202 break;
1203 case IEEE80211_IOC_PUREN:
1204 ireq->i_val = (vap->iv_flags_ht & IEEE80211_FHT_PUREN) != 0;
1205 break;
1206 case IEEE80211_IOC_DOTH:
1207 ireq->i_val = (vap->iv_flags & IEEE80211_F_DOTH) != 0;
1208 break;
1209 case IEEE80211_IOC_REGDOMAIN:
1210 error = ieee80211_ioctl_getregdomain(vap, ireq);
1211 break;
1212 case IEEE80211_IOC_ROAM:
1213 error = ieee80211_ioctl_getroam(vap, ireq);
1214 break;
1215 case IEEE80211_IOC_TXPARAMS:
1216 error = ieee80211_ioctl_gettxparams(vap, ireq);
1217 break;
1218 case IEEE80211_IOC_HTCOMPAT:
1219 ireq->i_val = (vap->iv_flags_ht & IEEE80211_FHT_HTCOMPAT) != 0;
1220 break;
1221 case IEEE80211_IOC_DWDS:
1222 ireq->i_val = (vap->iv_flags & IEEE80211_F_DWDS) != 0;
1223 break;
1224 case IEEE80211_IOC_INACTIVITY:
1225 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_INACT) != 0;
1226 break;
1227 case IEEE80211_IOC_APPIE:
1228 error = ieee80211_ioctl_getappie(vap, ireq);
1229 break;
1230 case IEEE80211_IOC_WPS:
1231 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_WPS) != 0;
1232 break;
1233 case IEEE80211_IOC_TSN:
1234 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_TSN) != 0;
1235 break;
1236 case IEEE80211_IOC_DFS:
1237 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DFS) != 0;
1238 break;
1239 case IEEE80211_IOC_DOTD:
1240 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DOTD) != 0;
1241 break;
1242 case IEEE80211_IOC_DEVCAPS:
1243 error = ieee80211_ioctl_getdevcaps(ic, ireq);
1244 break;
1245 case IEEE80211_IOC_HTPROTMODE:
1246 ireq->i_val = ic->ic_htprotmode;
1247 break;
1248 case IEEE80211_IOC_HTCONF:
1249 if (vap->iv_flags_ht & IEEE80211_FHT_HT) {
1250 ireq->i_val = 1;
1251 if (vap->iv_flags_ht & IEEE80211_FHT_USEHT40)
1252 ireq->i_val |= 2;
1253 } else
1254 ireq->i_val = 0;
1255 break;
1256 case IEEE80211_IOC_STA_VLAN:
1257 error = ieee80211_ioctl_getstavlan(vap, ireq);
1258 break;
1259 case IEEE80211_IOC_SMPS:
1260 if (vap->iv_opmode == IEEE80211_M_STA &&
1261 (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) {
1262 if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_RTS)
1263 ireq->i_val = IEEE80211_HTCAP_SMPS_DYNAMIC;
1264 else if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_PS)
1265 ireq->i_val = IEEE80211_HTCAP_SMPS_ENA;
1266 else
1267 ireq->i_val = IEEE80211_HTCAP_SMPS_OFF;
1268 } else
1269 ireq->i_val = vap->iv_htcaps & IEEE80211_HTCAP_SMPS;
1270 break;
1271 case IEEE80211_IOC_RIFS:
1272 if (vap->iv_opmode == IEEE80211_M_STA &&
1273 (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP))
1274 ireq->i_val =
1275 (vap->iv_bss->ni_flags & IEEE80211_NODE_RIFS) != 0;
1276 else
1277 ireq->i_val =
1278 (vap->iv_flags_ht & IEEE80211_FHT_RIFS) != 0;
1279 break;
1280 case IEEE80211_IOC_STBC:
1281 ireq->i_val = 0;
1282 if (vap->iv_flags_ht & IEEE80211_FHT_STBC_TX)
1283 ireq->i_val |= 1;
1284 if (vap->iv_flags_ht & IEEE80211_FHT_STBC_RX)
1285 ireq->i_val |= 2;
1286 break;
1287 case IEEE80211_IOC_LDPC:
1288 ireq->i_val = 0;
1289 if (vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX)
1290 ireq->i_val |= 1;
1291 if (vap->iv_flags_ht & IEEE80211_FHT_LDPC_RX)
1292 ireq->i_val |= 2;
1293 break;
1294
1295 /* VHT */
1296 case IEEE80211_IOC_VHTCONF:
1297 ireq->i_val = 0;
1298 if (vap->iv_flags_vht & IEEE80211_FVHT_VHT)
1299 ireq->i_val |= 1;
1300 if (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT40)
1301 ireq->i_val |= 2;
1302 if (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80)
1303 ireq->i_val |= 4;
1304 if (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80P80)
1305 ireq->i_val |= 8;
1306 if (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT160)
1307 ireq->i_val |= 16;
1308 break;
1309
1310 default:
1311 error = ieee80211_ioctl_getdefault(vap, ireq);
1312 break;
1313 }
1314 return error;
1315 #undef MS
1316 }
1317
1318 static int
1319 ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
1320 {
1321 struct ieee80211req_key ik;
1322 struct ieee80211_node *ni;
1323 struct ieee80211_key *wk;
1324 uint16_t kid;
1325 int error, i;
1326
1327 if (ireq->i_len != sizeof(ik))
1328 return EINVAL;
1329 error = copyin(ireq->i_data, &ik, sizeof(ik));
1330 if (error)
1331 return error;
1332 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1333 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1334 if (ik.ik_keylen > sizeof(ik.ik_keydata))
1335 return E2BIG;
1336 kid = ik.ik_keyix;
1337 if (kid == IEEE80211_KEYIX_NONE) {
1338 /* XXX unicast keys currently must be tx/rx */
1339 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
1340 return EINVAL;
1341 if (vap->iv_opmode == IEEE80211_M_STA) {
1342 ni = ieee80211_ref_node(vap->iv_bss);
1343 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) {
1344 ieee80211_free_node(ni);
1345 return EADDRNOTAVAIL;
1346 }
1347 } else {
1348 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
1349 ik.ik_macaddr);
1350 if (ni == NULL)
1351 return ENOENT;
1352 }
1353 wk = &ni->ni_ucastkey;
1354 } else {
1355 if (kid >= IEEE80211_WEP_NKID)
1356 return EINVAL;
1357 wk = &vap->iv_nw_keys[kid];
1358 /*
1359 * Global slots start off w/o any assigned key index.
1360 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1361 */
1362 if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
1363 wk->wk_keyix = kid;
1364 ni = NULL;
1365 }
1366 error = 0;
1367 ieee80211_key_update_begin(vap);
1368 if (ieee80211_crypto_newkey(vap, ik.ik_type, ik.ik_flags, wk)) {
1369 wk->wk_keylen = ik.ik_keylen;
1370 /* NB: MIC presence is implied by cipher type */
1371 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
1372 wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
1373 for (i = 0; i < IEEE80211_TID_SIZE; i++)
1374 wk->wk_keyrsc[i] = ik.ik_keyrsc;
1375 wk->wk_keytsc = 0; /* new key, reset */
1376 memset(wk->wk_key, 0, sizeof(wk->wk_key));
1377 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
1378 IEEE80211_ADDR_COPY(wk->wk_macaddr,
1379 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr);
1380 if (!ieee80211_crypto_setkey(vap, wk))
1381 error = EIO;
1382 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
1383 /*
1384 * Inform the driver that this is the default
1385 * transmit key. Now, ideally we'd just set
1386 * a flag in the key update that would
1387 * say "yes, we're the default key", but
1388 * that currently isn't the way the ioctl ->
1389 * key interface works.
1390 */
1391 ieee80211_crypto_set_deftxkey(vap, kid);
1392 } else
1393 error = ENXIO;
1394 ieee80211_key_update_end(vap);
1395 if (ni != NULL)
1396 ieee80211_free_node(ni);
1397 return error;
1398 }
1399
1400 static int
1401 ieee80211_ioctl_delkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
1402 {
1403 struct ieee80211req_del_key dk;
1404 int kid, error;
1405
1406 if (ireq->i_len != sizeof(dk))
1407 return EINVAL;
1408 error = copyin(ireq->i_data, &dk, sizeof(dk));
1409 if (error)
1410 return error;
1411 kid = dk.idk_keyix;
1412 /* XXX uint8_t -> uint16_t */
1413 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1414 struct ieee80211_node *ni;
1415
1416 if (vap->iv_opmode == IEEE80211_M_STA) {
1417 ni = ieee80211_ref_node(vap->iv_bss);
1418 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1419 ieee80211_free_node(ni);
1420 return EADDRNOTAVAIL;
1421 }
1422 } else {
1423 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
1424 dk.idk_macaddr);
1425 if (ni == NULL)
1426 return ENOENT;
1427 }
1428 /* XXX error return */
1429 ieee80211_node_delucastkey(ni);
1430 ieee80211_free_node(ni);
1431 } else {
1432 if (kid >= IEEE80211_WEP_NKID)
1433 return EINVAL;
1434 /* XXX error return */
1435 ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[kid]);
1436 }
1437 return 0;
1438 }
1439
1440 struct mlmeop {
1441 struct ieee80211vap *vap;
1442 int op;
1443 int reason;
1444 };
1445
1446 static void
1447 mlmedebug(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
1448 int op, int reason)
1449 {
1450 #ifdef IEEE80211_DEBUG
1451 static const struct {
1452 int mask;
1453 const char *opstr;
1454 } ops[] = {
1455 { 0, "op#0" },
1456 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1457 IEEE80211_MSG_ASSOC, "assoc" },
1458 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1459 IEEE80211_MSG_ASSOC, "disassoc" },
1460 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1461 IEEE80211_MSG_AUTH, "deauth" },
1462 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1463 IEEE80211_MSG_AUTH, "authorize" },
1464 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1465 IEEE80211_MSG_AUTH, "unauthorize" },
1466 };
1467
1468 if (op == IEEE80211_MLME_AUTH) {
1469 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_IOCTL |
1470 IEEE80211_MSG_STATE | IEEE80211_MSG_AUTH, mac,
1471 "station authenticate %s via MLME (reason: %d (%s))",
1472 reason == IEEE80211_STATUS_SUCCESS ? "ACCEPT" : "REJECT",
1473 reason, ieee80211_reason_to_string(reason));
1474 } else if (!(IEEE80211_MLME_ASSOC <= op && op <= IEEE80211_MLME_AUTH)) {
1475 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY, mac,
1476 "unknown MLME request %d (reason: %d (%s))", op, reason,
1477 ieee80211_reason_to_string(reason));
1478 } else if (reason == IEEE80211_STATUS_SUCCESS) {
1479 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac,
1480 "station %s via MLME", ops[op].opstr);
1481 } else {
1482 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac,
1483 "station %s via MLME (reason: %d (%s))", ops[op].opstr,
1484 reason, ieee80211_reason_to_string(reason));
1485 }
1486 #endif /* IEEE80211_DEBUG */
1487 }
1488
1489 static void
1490 domlme(void *arg, struct ieee80211_node *ni)
1491 {
1492 struct mlmeop *mop = arg;
1493 struct ieee80211vap *vap = ni->ni_vap;
1494
1495 if (vap != mop->vap)
1496 return;
1497 /*
1498 * NB: if ni_associd is zero then the node is already cleaned
1499 * up and we don't need to do this (we're safely holding a
1500 * reference but should otherwise not modify it's state).
1501 */
1502 if (ni->ni_associd == 0)
1503 return;
1504 mlmedebug(vap, ni->ni_macaddr, mop->op, mop->reason);
1505 if (mop->op == IEEE80211_MLME_DEAUTH) {
1506 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
1507 mop->reason);
1508 } else {
1509 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
1510 mop->reason);
1511 }
1512 ieee80211_node_leave(ni);
1513 }
1514
1515 static int
1516 setmlme_dropsta(struct ieee80211vap *vap,
1517 const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
1518 {
1519 struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
1520 struct ieee80211_node *ni;
1521 int error = 0;
1522
1523 /* NB: the broadcast address means do 'em all */
1524 if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) {
1525 IEEE80211_NODE_LOCK(nt);
1526 ni = ieee80211_find_node_locked(nt, mac);
1527 IEEE80211_NODE_UNLOCK(nt);
1528 /*
1529 * Don't do the node update inside the node
1530 * table lock. This unfortunately causes LORs
1531 * with drivers and their TX paths.
1532 */
1533 if (ni != NULL) {
1534 domlme(mlmeop, ni);
1535 ieee80211_free_node(ni);
1536 } else
1537 error = ENOENT;
1538 } else {
1539 ieee80211_iterate_nodes(nt, domlme, mlmeop);
1540 }
1541 return error;
1542 }
1543
1544 static int
1545 setmlme_common(struct ieee80211vap *vap, int op,
1546 const uint8_t mac[IEEE80211_ADDR_LEN], int reason)
1547 {
1548 struct ieee80211com *ic = vap->iv_ic;
1549 struct ieee80211_node_table *nt = &ic->ic_sta;
1550 struct ieee80211_node *ni;
1551 struct mlmeop mlmeop;
1552 int error;
1553
1554 error = 0;
1555 switch (op) {
1556 case IEEE80211_MLME_DISASSOC:
1557 case IEEE80211_MLME_DEAUTH:
1558 switch (vap->iv_opmode) {
1559 case IEEE80211_M_STA:
1560 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason);
1561 /* XXX not quite right */
1562 ieee80211_new_state(vap, IEEE80211_S_INIT, reason);
1563 break;
1564 case IEEE80211_M_HOSTAP:
1565 mlmeop.vap = vap;
1566 mlmeop.op = op;
1567 mlmeop.reason = reason;
1568 error = setmlme_dropsta(vap, mac, &mlmeop);
1569 break;
1570 case IEEE80211_M_WDS:
1571 /* XXX user app should send raw frame? */
1572 if (op != IEEE80211_MLME_DEAUTH) {
1573 error = EINVAL;
1574 break;
1575 }
1576 #if 0
1577 /* XXX accept any address, simplifies user code */
1578 if (!IEEE80211_ADDR_EQ(mac, vap->iv_bss->ni_macaddr)) {
1579 error = EINVAL;
1580 break;
1581 }
1582 #endif
1583 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason);
1584 ni = ieee80211_ref_node(vap->iv_bss);
1585 IEEE80211_SEND_MGMT(ni,
1586 IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
1587 ieee80211_free_node(ni);
1588 break;
1589 case IEEE80211_M_MBSS:
1590 IEEE80211_NODE_LOCK(nt);
1591 ni = ieee80211_find_node_locked(nt, mac);
1592 /*
1593 * Don't do the node update inside the node
1594 * table lock. This unfortunately causes LORs
1595 * with drivers and their TX paths.
1596 */
1597 IEEE80211_NODE_UNLOCK(nt);
1598 if (ni != NULL) {
1599 ieee80211_node_leave(ni);
1600 ieee80211_free_node(ni);
1601 } else {
1602 error = ENOENT;
1603 }
1604 break;
1605 default:
1606 error = EINVAL;
1607 break;
1608 }
1609 break;
1610 case IEEE80211_MLME_AUTHORIZE:
1611 case IEEE80211_MLME_UNAUTHORIZE:
1612 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
1613 vap->iv_opmode != IEEE80211_M_WDS) {
1614 error = EINVAL;
1615 break;
1616 }
1617 IEEE80211_NODE_LOCK(nt);
1618 ni = ieee80211_find_vap_node_locked(nt, vap, mac);
1619 /*
1620 * Don't do the node update inside the node
1621 * table lock. This unfortunately causes LORs
1622 * with drivers and their TX paths.
1623 */
1624 IEEE80211_NODE_UNLOCK(nt);
1625 if (ni != NULL) {
1626 mlmedebug(vap, mac, op, reason);
1627 if (op == IEEE80211_MLME_AUTHORIZE)
1628 ieee80211_node_authorize(ni);
1629 else
1630 ieee80211_node_unauthorize(ni);
1631 ieee80211_free_node(ni);
1632 } else
1633 error = ENOENT;
1634 break;
1635 case IEEE80211_MLME_AUTH:
1636 if (vap->iv_opmode != IEEE80211_M_HOSTAP) {
1637 error = EINVAL;
1638 break;
1639 }
1640 IEEE80211_NODE_LOCK(nt);
1641 ni = ieee80211_find_vap_node_locked(nt, vap, mac);
1642 /*
1643 * Don't do the node update inside the node
1644 * table lock. This unfortunately causes LORs
1645 * with drivers and their TX paths.
1646 */
1647 IEEE80211_NODE_UNLOCK(nt);
1648 if (ni != NULL) {
1649 mlmedebug(vap, mac, op, reason);
1650 if (reason == IEEE80211_STATUS_SUCCESS) {
1651 IEEE80211_SEND_MGMT(ni,
1652 IEEE80211_FC0_SUBTYPE_AUTH, 2);
1653 /*
1654 * For shared key auth, just continue the
1655 * exchange. Otherwise when 802.1x is not in
1656 * use mark the port authorized at this point
1657 * so traffic can flow.
1658 */
1659 if (ni->ni_authmode != IEEE80211_AUTH_8021X &&
1660 ni->ni_challenge == NULL)
1661 ieee80211_node_authorize(ni);
1662 } else {
1663 vap->iv_stats.is_rx_acl++;
1664 ieee80211_send_error(ni, ni->ni_macaddr,
1665 IEEE80211_FC0_SUBTYPE_AUTH, 2|(reason<<16));
1666 ieee80211_node_leave(ni);
1667 }
1668 ieee80211_free_node(ni);
1669 } else
1670 error = ENOENT;
1671 break;
1672 default:
1673 error = EINVAL;
1674 break;
1675 }
1676 return error;
1677 }
1678
1679 struct scanlookup {
1680 const uint8_t *mac;
1681 int esslen;
1682 const uint8_t *essid;
1683 const struct ieee80211_scan_entry *se;
1684 };
1685
1686 /*
1687 * Match mac address and any ssid.
1688 */
1689 static void
1690 mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1691 {
1692 struct scanlookup *look = arg;
1693
1694 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1695 return;
1696 if (look->esslen != 0) {
1697 if (se->se_ssid[1] != look->esslen)
1698 return;
1699 if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1700 return;
1701 }
1702 look->se = se;
1703 }
1704
1705 static int
1706 setmlme_assoc_sta(struct ieee80211vap *vap,
1707 const uint8_t mac[IEEE80211_ADDR_LEN], int ssid_len,
1708 const uint8_t ssid[IEEE80211_NWID_LEN])
1709 {
1710 struct scanlookup lookup;
1711
1712 KASSERT(vap->iv_opmode == IEEE80211_M_STA,
1713 ("expected opmode STA not %s",
1714 ieee80211_opmode_name[vap->iv_opmode]));
1715
1716 /* NB: this is racey if roaming is !manual */
1717 lookup.se = NULL;
1718 lookup.mac = mac;
1719 lookup.esslen = ssid_len;
1720 lookup.essid = ssid;
1721 ieee80211_scan_iterate(vap, mlmelookup, &lookup);
1722 if (lookup.se == NULL)
1723 return ENOENT;
1724 mlmedebug(vap, mac, IEEE80211_MLME_ASSOC, 0);
1725 if (!ieee80211_sta_join(vap, lookup.se->se_chan, lookup.se))
1726 return EIO; /* XXX unique but could be better */
1727 return 0;
1728 }
1729
1730 static int
1731 setmlme_assoc_adhoc(struct ieee80211vap *vap,
1732 const uint8_t mac[IEEE80211_ADDR_LEN], int ssid_len,
1733 const uint8_t ssid[IEEE80211_NWID_LEN])
1734 {
1735 struct ieee80211_scan_req *sr;
1736 int error;
1737
1738 KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||
1739 vap->iv_opmode == IEEE80211_M_AHDEMO,
1740 ("expected opmode IBSS or AHDEMO not %s",
1741 ieee80211_opmode_name[vap->iv_opmode]));
1742
1743 if (ssid_len == 0)
1744 return EINVAL;
1745
1746 sr = IEEE80211_MALLOC(sizeof(*sr), M_TEMP,
1747 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
1748 if (sr == NULL)
1749 return ENOMEM;
1750
1751 /* NB: IEEE80211_IOC_SSID call missing for ap_scan=2. */
1752 memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
1753 vap->iv_des_ssid[0].len = ssid_len;
1754 memcpy(vap->iv_des_ssid[0].ssid, ssid, ssid_len);
1755 vap->iv_des_nssid = 1;
1756
1757 sr->sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE;
1758 sr->sr_duration = IEEE80211_IOC_SCAN_FOREVER;
1759 memcpy(sr->sr_ssid[0].ssid, ssid, ssid_len);
1760 sr->sr_ssid[0].len = ssid_len;
1761 sr->sr_nssid = 1;
1762
1763 error = ieee80211_scanreq(vap, sr);
1764
1765 IEEE80211_FREE(sr, M_TEMP);
1766 return error;
1767 }
1768
1769 static int
1770 ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq)
1771 {
1772 struct ieee80211req_mlme mlme;
1773 int error;
1774
1775 if (ireq->i_len != sizeof(mlme))
1776 return EINVAL;
1777 error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1778 if (error)
1779 return error;
1780 if (vap->iv_opmode == IEEE80211_M_STA &&
1781 mlme.im_op == IEEE80211_MLME_ASSOC)
1782 return setmlme_assoc_sta(vap, mlme.im_macaddr,
1783 vap->iv_des_ssid[0].len, vap->iv_des_ssid[0].ssid);
1784 else if ((vap->iv_opmode == IEEE80211_M_IBSS ||
1785 vap->iv_opmode == IEEE80211_M_AHDEMO) &&
1786 mlme.im_op == IEEE80211_MLME_ASSOC)
1787 return setmlme_assoc_adhoc(vap, mlme.im_macaddr,
1788 mlme.im_ssid_len, mlme.im_ssid);
1789 else
1790 return setmlme_common(vap, mlme.im_op,
1791 mlme.im_macaddr, mlme.im_reason);
1792 }
1793
1794 static int
1795 ieee80211_ioctl_macmac(struct ieee80211vap *vap, struct ieee80211req *ireq)
1796 {
1797 uint8_t mac[IEEE80211_ADDR_LEN];
1798 const struct ieee80211_aclator *acl = vap->iv_acl;
1799 int error;
1800
1801 if (ireq->i_len != sizeof(mac))
1802 return EINVAL;
1803 error = copyin(ireq->i_data, mac, ireq->i_len);
1804 if (error)
1805 return error;
1806 if (acl == NULL) {
1807 acl = ieee80211_aclator_get("mac");
1808 if (acl == NULL || !acl->iac_attach(vap))
1809 return EINVAL;
1810 vap->iv_acl = acl;
1811 }
1812 if (ireq->i_type == IEEE80211_IOC_ADDMAC)
1813 acl->iac_add(vap, mac);
1814 else
1815 acl->iac_remove(vap, mac);
1816 return 0;
1817 }
1818
1819 static int
1820 ieee80211_ioctl_setmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
1821 {
1822 const struct ieee80211_aclator *acl = vap->iv_acl;
1823
1824 switch (ireq->i_val) {
1825 case IEEE80211_MACCMD_POLICY_OPEN:
1826 case IEEE80211_MACCMD_POLICY_ALLOW:
1827 case IEEE80211_MACCMD_POLICY_DENY:
1828 case IEEE80211_MACCMD_POLICY_RADIUS:
1829 if (acl == NULL) {
1830 acl = ieee80211_aclator_get("mac");
1831 if (acl == NULL || !acl->iac_attach(vap))
1832 return EINVAL;
1833 vap->iv_acl = acl;
1834 }
1835 acl->iac_setpolicy(vap, ireq->i_val);
1836 break;
1837 case IEEE80211_MACCMD_FLUSH:
1838 if (acl != NULL)
1839 acl->iac_flush(vap);
1840 /* NB: silently ignore when not in use */
1841 break;
1842 case IEEE80211_MACCMD_DETACH:
1843 if (acl != NULL) {
1844 vap->iv_acl = NULL;
1845 acl->iac_detach(vap);
1846 }
1847 break;
1848 default:
1849 if (acl == NULL)
1850 return EINVAL;
1851 else
1852 return acl->iac_setioctl(vap, ireq);
1853 }
1854 return 0;
1855 }
1856
1857 static int
1858 ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
1859 {
1860 struct ieee80211com *ic = vap->iv_ic;
1861 uint8_t *chanlist, *list;
1862 int i, nchan, maxchan, error;
1863
1864 if (ireq->i_len > sizeof(ic->ic_chan_active))
1865 ireq->i_len = sizeof(ic->ic_chan_active);
1866 list = IEEE80211_MALLOC(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP,
1867 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
1868 if (list == NULL)
1869 return ENOMEM;
1870 error = copyin(ireq->i_data, list, ireq->i_len);
1871 if (error) {
1872 IEEE80211_FREE(list, M_TEMP);
1873 return error;
1874 }
1875 nchan = 0;
1876 chanlist = list + ireq->i_len; /* NB: zero'd already */
1877 maxchan = ireq->i_len * NBBY;
1878 for (i = 0; i < ic->ic_nchans; i++) {
1879 const struct ieee80211_channel *c = &ic->ic_channels[i];
1880 /*
1881 * Calculate the intersection of the user list and the
1882 * available channels so users can do things like specify
1883 * 1-255 to get all available channels.
1884 */
1885 if (c->ic_ieee < maxchan && isset(list, c->ic_ieee)) {
1886 setbit(chanlist, c->ic_ieee);
1887 nchan++;
1888 }
1889 }
1890 if (nchan == 0) {
1891 IEEE80211_FREE(list, M_TEMP);
1892 return EINVAL;
1893 }
1894 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1895 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1896 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1897 memcpy(ic->ic_chan_active, chanlist, IEEE80211_CHAN_BYTES);
1898 ieee80211_scan_flush(vap);
1899 IEEE80211_FREE(list, M_TEMP);
1900 return ENETRESET;
1901 }
1902
1903 static int
1904 ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
1905 {
1906 struct ieee80211_node *ni;
1907 uint8_t macaddr[IEEE80211_ADDR_LEN];
1908 int error;
1909
1910 /*
1911 * NB: we could copyin ieee80211req_sta_stats so apps
1912 * could make selective changes but that's overkill;
1913 * just clear all stats for now.
1914 */
1915 if (ireq->i_len < IEEE80211_ADDR_LEN)
1916 return EINVAL;
1917 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1918 if (error != 0)
1919 return error;
1920 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
1921 if (ni == NULL)
1922 return ENOENT;
1923 /* XXX require ni_vap == vap? */
1924 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats));
1925 ieee80211_free_node(ni);
1926 return 0;
1927 }
1928
1929 static int
1930 ieee80211_ioctl_setstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
1931 {
1932 struct ieee80211_node *ni;
1933 struct ieee80211req_sta_txpow txpow;
1934 int error;
1935
1936 if (ireq->i_len != sizeof(txpow))
1937 return EINVAL;
1938 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
1939 if (error != 0)
1940 return error;
1941 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr);
1942 if (ni == NULL)
1943 return ENOENT;
1944 ni->ni_txpower = txpow.it_txpow;
1945 ieee80211_free_node(ni);
1946 return error;
1947 }
1948
1949 static int
1950 ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
1951 {
1952 struct ieee80211com *ic = vap->iv_ic;
1953 struct ieee80211_wme_state *wme = &ic->ic_wme;
1954 struct wmeParams *wmep, *chanp;
1955 int isbss, ac, aggrmode;
1956
1957 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
1958 return EOPNOTSUPP;
1959
1960 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
1961 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
1962 aggrmode = (wme->wme_flags & WME_F_AGGRMODE);
1963 if (ac >= WME_NUM_AC)
1964 ac = WME_AC_BE;
1965 if (isbss) {
1966 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac];
1967 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
1968 } else {
1969 chanp = &wme->wme_chanParams.cap_wmeParams[ac];
1970 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
1971 }
1972 switch (ireq->i_type) {
1973 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
1974 wmep->wmep_logcwmin = ireq->i_val;
1975 if (!isbss || !aggrmode)
1976 chanp->wmep_logcwmin = ireq->i_val;
1977 break;
1978 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
1979 wmep->wmep_logcwmax = ireq->i_val;
1980 if (!isbss || !aggrmode)
1981 chanp->wmep_logcwmax = ireq->i_val;
1982 break;
1983 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1984 wmep->wmep_aifsn = ireq->i_val;
1985 if (!isbss || !aggrmode)
1986 chanp->wmep_aifsn = ireq->i_val;
1987 break;
1988 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1989 wmep->wmep_txopLimit = ireq->i_val;
1990 if (!isbss || !aggrmode)
1991 chanp->wmep_txopLimit = ireq->i_val;
1992 break;
1993 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1994 wmep->wmep_acm = ireq->i_val;
1995 if (!aggrmode)
1996 chanp->wmep_acm = ireq->i_val;
1997 break;
1998 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
1999 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy =
2000 (ireq->i_val) == 0;
2001 break;
2002 }
2003 ieee80211_wme_updateparams(vap);
2004 return 0;
2005 }
2006
2007 static int
2008 find11gchannel(struct ieee80211com *ic, int start, int freq)
2009 {
2010 const struct ieee80211_channel *c;
2011 int i;
2012
2013 for (i = start+1; i < ic->ic_nchans; i++) {
2014 c = &ic->ic_channels[i];
2015 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
2016 return 1;
2017 }
2018 /* NB: should not be needed but in case things are mis-sorted */
2019 for (i = 0; i < start; i++) {
2020 c = &ic->ic_channels[i];
2021 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
2022 return 1;
2023 }
2024 return 0;
2025 }
2026
2027 static struct ieee80211_channel *
2028 findchannel(struct ieee80211com *ic, int ieee, int mode)
2029 {
2030 static const u_int chanflags[IEEE80211_MODE_MAX] = {
2031 [IEEE80211_MODE_AUTO] = 0,
2032 [IEEE80211_MODE_11A] = IEEE80211_CHAN_A,
2033 [IEEE80211_MODE_11B] = IEEE80211_CHAN_B,
2034 [IEEE80211_MODE_11G] = IEEE80211_CHAN_G,
2035 [IEEE80211_MODE_FH] = IEEE80211_CHAN_FHSS,
2036 [IEEE80211_MODE_TURBO_A] = IEEE80211_CHAN_108A,
2037 [IEEE80211_MODE_TURBO_G] = IEEE80211_CHAN_108G,
2038 [IEEE80211_MODE_STURBO_A] = IEEE80211_CHAN_STURBO,
2039 [IEEE80211_MODE_HALF] = IEEE80211_CHAN_HALF,
2040 [IEEE80211_MODE_QUARTER] = IEEE80211_CHAN_QUARTER,
2041 /* NB: handled specially below */
2042 [IEEE80211_MODE_11NA] = IEEE80211_CHAN_A,
2043 [IEEE80211_MODE_11NG] = IEEE80211_CHAN_G,
2044 [IEEE80211_MODE_VHT_5GHZ] = IEEE80211_CHAN_A,
2045 [IEEE80211_MODE_VHT_2GHZ] = IEEE80211_CHAN_G,
2046 };
2047 u_int modeflags;
2048 int i;
2049
2050 modeflags = chanflags[mode];
2051 for (i = 0; i < ic->ic_nchans; i++) {
2052 struct ieee80211_channel *c = &ic->ic_channels[i];
2053
2054 if (c->ic_ieee != ieee)
2055 continue;
2056 if (mode == IEEE80211_MODE_AUTO) {
2057 /* ignore turbo channels for autoselect */
2058 if (IEEE80211_IS_CHAN_TURBO(c))
2059 continue;
2060 /*
2061 * XXX special-case 11b/g channels so we
2062 * always select the g channel if both
2063 * are present.
2064 * XXX prefer HT to non-HT?
2065 */
2066 if (!IEEE80211_IS_CHAN_B(c) ||
2067 !find11gchannel(ic, i, c->ic_freq))
2068 return c;
2069 } else {
2070 /* must check VHT specifically */
2071 if ((mode == IEEE80211_MODE_VHT_5GHZ ||
2072 mode == IEEE80211_MODE_VHT_2GHZ) &&
2073 !IEEE80211_IS_CHAN_VHT(c))
2074 continue;
2075
2076 /*
2077 * Must check HT specially - only match on HT,
2078 * not HT+VHT channels
2079 */
2080 if ((mode == IEEE80211_MODE_11NA ||
2081 mode == IEEE80211_MODE_11NG) &&
2082 !IEEE80211_IS_CHAN_HT(c))
2083 continue;
2084
2085 if ((mode == IEEE80211_MODE_11NA ||
2086 mode == IEEE80211_MODE_11NG) &&
2087 IEEE80211_IS_CHAN_VHT(c))
2088 continue;
2089
2090 /* Check that the modeflags above match */
2091 if ((c->ic_flags & modeflags) == modeflags)
2092 return c;
2093 }
2094 }
2095 return NULL;
2096 }
2097
2098 /*
2099 * Check the specified against any desired mode (aka netband).
2100 * This is only used (presently) when operating in hostap mode
2101 * to enforce consistency.
2102 */
2103 static int
2104 check_mode_consistency(const struct ieee80211_channel *c, int mode)
2105 {
2106 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
2107
2108 switch (mode) {
2109 case IEEE80211_MODE_11B:
2110 return (IEEE80211_IS_CHAN_B(c));
2111 case IEEE80211_MODE_11G:
2112 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
2113 case IEEE80211_MODE_11A:
2114 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
2115 case IEEE80211_MODE_STURBO_A:
2116 return (IEEE80211_IS_CHAN_STURBO(c));
2117 case IEEE80211_MODE_11NA:
2118 return (IEEE80211_IS_CHAN_HTA(c));
2119 case IEEE80211_MODE_11NG:
2120 return (IEEE80211_IS_CHAN_HTG(c));
2121 }
2122 return 1;
2123
2124 }
2125
2126 /*
2127 * Common code to set the current channel. If the device
2128 * is up and running this may result in an immediate channel
2129 * change or a kick of the state machine.
2130 */
2131 static int
2132 setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c)
2133 {
2134 struct ieee80211com *ic = vap->iv_ic;
2135 int error;
2136
2137 if (c != IEEE80211_CHAN_ANYC) {
2138 if (IEEE80211_IS_CHAN_RADAR(c))
2139 return EBUSY; /* XXX better code? */
2140 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
2141 if (IEEE80211_IS_CHAN_NOHOSTAP(c))
2142 return EINVAL;
2143 if (!check_mode_consistency(c, vap->iv_des_mode))
2144 return EINVAL;
2145 } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
2146 if (IEEE80211_IS_CHAN_NOADHOC(c))
2147 return EINVAL;
2148 }
2149 if ((vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) &&
2150 vap->iv_bss->ni_chan == c)
2151 return 0; /* NB: nothing to do */
2152 }
2153 vap->iv_des_chan = c;
2154
2155 error = 0;
2156 if (vap->iv_opmode == IEEE80211_M_MONITOR &&
2157 vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
2158 /*
2159 * Monitor mode can switch directly.
2160 */
2161 if (IFNET_IS_UP_RUNNING(vap->iv_ifp)) {
2162 /* XXX need state machine for other vap's to follow */
2163 ieee80211_setcurchan(ic, vap->iv_des_chan);
2164 vap->iv_bss->ni_chan = ic->ic_curchan;
2165 } else {
2166 ic->ic_curchan = vap->iv_des_chan;
2167 ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
2168 }
2169 } else {
2170 /*
2171 * Need to go through the state machine in case we
2172 * need to reassociate or the like. The state machine
2173 * will pickup the desired channel and avoid scanning.
2174 */
2175 if (IS_UP_AUTO(vap))
2176 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
2177 else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
2178 /*
2179 * When not up+running and a real channel has
2180 * been specified fix the current channel so
2181 * there is immediate feedback; e.g. via ifconfig.
2182 */
2183 ic->ic_curchan = vap->iv_des_chan;
2184 ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
2185 }
2186 }
2187 return error;
2188 }
2189
2190 /*
2191 * Old api for setting the current channel; this is
2192 * deprecated because channel numbers are ambiguous.
2193 */
2194 static int
2195 ieee80211_ioctl_setchannel(struct ieee80211vap *vap,
2196 const struct ieee80211req *ireq)
2197 {
2198 struct ieee80211com *ic = vap->iv_ic;
2199 struct ieee80211_channel *c;
2200
2201 /* XXX 0xffff overflows 16-bit signed */
2202 if (ireq->i_val == 0 ||
2203 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
2204 c = IEEE80211_CHAN_ANYC;
2205 } else {
2206 struct ieee80211_channel *c2;
2207
2208 c = findchannel(ic, ireq->i_val, vap->iv_des_mode);
2209 if (c == NULL) {
2210 c = findchannel(ic, ireq->i_val,
2211 IEEE80211_MODE_AUTO);
2212 if (c == NULL)
2213 return EINVAL;
2214 }
2215
2216 /*
2217 * Fine tune channel selection based on desired mode:
2218 * if 11b is requested, find the 11b version of any
2219 * 11g channel returned,
2220 * if static turbo, find the turbo version of any
2221 * 11a channel return,
2222 * if 11na is requested, find the ht version of any
2223 * 11a channel returned,
2224 * if 11ng is requested, find the ht version of any
2225 * 11g channel returned,
2226 * if 11ac is requested, find the 11ac version
2227 * of any 11a/11na channel returned,
2228 * (TBD) 11acg (2GHz VHT)
2229 * otherwise we should be ok with what we've got.
2230 */
2231 switch (vap->iv_des_mode) {
2232 case IEEE80211_MODE_11B:
2233 if (IEEE80211_IS_CHAN_ANYG(c)) {
2234 c2 = findchannel(ic, ireq->i_val,
2235 IEEE80211_MODE_11B);
2236 /* NB: should not happen, =>'s 11g w/o 11b */
2237 if (c2 != NULL)
2238 c = c2;
2239 }
2240 break;
2241 case IEEE80211_MODE_TURBO_A:
2242 if (IEEE80211_IS_CHAN_A(c)) {
2243 c2 = findchannel(ic, ireq->i_val,
2244 IEEE80211_MODE_TURBO_A);
2245 if (c2 != NULL)
2246 c = c2;
2247 }
2248 break;
2249 case IEEE80211_MODE_11NA:
2250 if (IEEE80211_IS_CHAN_A(c)) {
2251 c2 = findchannel(ic, ireq->i_val,
2252 IEEE80211_MODE_11NA);
2253 if (c2 != NULL)
2254 c = c2;
2255 }
2256 break;
2257 case IEEE80211_MODE_11NG:
2258 if (IEEE80211_IS_CHAN_ANYG(c)) {
2259 c2 = findchannel(ic, ireq->i_val,
2260 IEEE80211_MODE_11NG);
2261 if (c2 != NULL)
2262 c = c2;
2263 }
2264 break;
2265 case IEEE80211_MODE_VHT_2GHZ:
2266 printf("%s: TBD\n", __func__);
2267 break;
2268 case IEEE80211_MODE_VHT_5GHZ:
2269 if (IEEE80211_IS_CHAN_A(c)) {
2270 c2 = findchannel(ic, ireq->i_val,
2271 IEEE80211_MODE_VHT_5GHZ);
2272 if (c2 != NULL)
2273 c = c2;
2274 }
2275 break;
2276 default: /* NB: no static turboG */
2277 break;
2278 }
2279 }
2280 return setcurchan(vap, c);
2281 }
2282
2283 /*
2284 * New/current api for setting the current channel; a complete
2285 * channel description is provide so there is no ambiguity in
2286 * identifying the channel.
2287 */
2288 static int
2289 ieee80211_ioctl_setcurchan(struct ieee80211vap *vap,
2290 const struct ieee80211req *ireq)
2291 {
2292 struct ieee80211com *ic = vap->iv_ic;
2293 struct ieee80211_channel chan, *c;
2294 int error;
2295
2296 if (ireq->i_len != sizeof(chan))
2297 return EINVAL;
2298 error = copyin(ireq->i_data, &chan, sizeof(chan));
2299 if (error != 0)
2300 return error;
2301
2302 /* XXX 0xffff overflows 16-bit signed */
2303 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
2304 c = IEEE80211_CHAN_ANYC;
2305 } else {
2306 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
2307 if (c == NULL)
2308 return EINVAL;
2309 }
2310 return setcurchan(vap, c);
2311 }
2312
2313 static int
2314 ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
2315 const struct ieee80211req *ireq)
2316 {
2317 struct ieee80211_regdomain_req *reg;
2318 int nchans, error;
2319
2320 nchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_regdomain_req)) /
2321 sizeof(struct ieee80211_channel));
2322 if (!(1 <= nchans && nchans <= IEEE80211_CHAN_MAX)) {
2323 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2324 "%s: bad # chans, i_len %d nchans %d\n", __func__,
2325 ireq->i_len, nchans);
2326 return EINVAL;
2327 }
2328 reg = (struct ieee80211_regdomain_req *)
2329 IEEE80211_MALLOC(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP,
2330 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
2331 if (reg == NULL) {
2332 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2333 "%s: no memory, nchans %d\n", __func__, nchans);
2334 return ENOMEM;
2335 }
2336 error = copyin(ireq->i_data, reg, IEEE80211_REGDOMAIN_SIZE(nchans));
2337 if (error == 0) {
2338 /* NB: validate inline channel count against storage size */
2339 if (reg->chaninfo.ic_nchans != nchans) {
2340 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2341 "%s: chan cnt mismatch, %d != %d\n", __func__,
2342 reg->chaninfo.ic_nchans, nchans);
2343 error = EINVAL;
2344 } else
2345 error = ieee80211_setregdomain(vap, reg);
2346 }
2347 IEEE80211_FREE(reg, M_TEMP);
2348
2349 return (error == 0 ? ENETRESET : error);
2350 }
2351
2352 static int
2353 ieee80211_ioctl_setroam(struct ieee80211vap *vap,
2354 const struct ieee80211req *ireq)
2355 {
2356 if (ireq->i_len != sizeof(vap->iv_roamparms))
2357 return EINVAL;
2358 /* XXX validate params */
2359 /* XXX? ENETRESET to push to device? */
2360 return copyin(ireq->i_data, vap->iv_roamparms,
2361 sizeof(vap->iv_roamparms));
2362 }
2363
2364 static int
2365 checkrate(const struct ieee80211_rateset *rs, int rate)
2366 {
2367 int i;
2368
2369 if (rate == IEEE80211_FIXED_RATE_NONE)
2370 return 1;
2371 for (i = 0; i < rs->rs_nrates; i++)
2372 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate)
2373 return 1;
2374 return 0;
2375 }
2376
2377 static int
2378 checkmcs(const struct ieee80211_htrateset *rs, int mcs)
2379 {
2380 int rate_val = IEEE80211_RV(mcs);
2381 int i;
2382
2383 if (mcs == IEEE80211_FIXED_RATE_NONE)
2384 return 1;
2385 if ((mcs & IEEE80211_RATE_MCS) == 0) /* MCS always have 0x80 set */
2386 return 0;
2387 for (i = 0; i < rs->rs_nrates; i++)
2388 if (IEEE80211_RV(rs->rs_rates[i]) == rate_val)
2389 return 1;
2390 return 0;
2391 }
2392
2393 static int
2394 ieee80211_ioctl_settxparams(struct ieee80211vap *vap,
2395 const struct ieee80211req *ireq)
2396 {
2397 struct ieee80211com *ic = vap->iv_ic;
2398 struct ieee80211_txparams_req parms; /* XXX stack use? */
2399 struct ieee80211_txparam *src, *dst;
2400 const struct ieee80211_htrateset *rs_ht;
2401 const struct ieee80211_rateset *rs;
2402 int error, mode, changed, is11n, nmodes;
2403
2404 /* NB: accept short requests for backwards compat */
2405 if (ireq->i_len > sizeof(parms))
2406 return EINVAL;
2407 error = copyin(ireq->i_data, &parms, ireq->i_len);
2408 if (error != 0)
2409 return error;
2410 nmodes = ireq->i_len / sizeof(struct ieee80211_txparam);
2411 changed = 0;
2412 /* validate parameters and check if anything changed */
2413 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) {
2414 if (isclr(ic->ic_modecaps, mode))
2415 continue;
2416 src = &parms.params[mode];
2417 dst = &vap->iv_txparms[mode];
2418 rs = &ic->ic_sup_rates[mode]; /* NB: 11n maps to legacy */
2419 rs_ht = &ic->ic_sup_htrates;
2420 is11n = (mode == IEEE80211_MODE_11NA ||
2421 mode == IEEE80211_MODE_11NG);
2422 if (src->ucastrate != dst->ucastrate) {
2423 if (!checkrate(rs, src->ucastrate) &&
2424 (!is11n || !checkmcs(rs_ht, src->ucastrate)))
2425 return EINVAL;
2426 changed++;
2427 }
2428 if (src->mcastrate != dst->mcastrate) {
2429 if (!checkrate(rs, src->mcastrate) &&
2430 (!is11n || !checkmcs(rs_ht, src->mcastrate)))
2431 return EINVAL;
2432 changed++;
2433 }
2434 if (src->mgmtrate != dst->mgmtrate) {
2435 if (!checkrate(rs, src->mgmtrate) &&
2436 (!is11n || !checkmcs(rs_ht, src->mgmtrate)))
2437 return EINVAL;
2438 changed++;
2439 }
2440 if (src->maxretry != dst->maxretry) /* NB: no bounds */
2441 changed++;
2442 }
2443 if (changed) {
2444 /*
2445 * Copy new parameters in place and notify the
2446 * driver so it can push state to the device.
2447 */
2448 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) {
2449 if (isset(ic->ic_modecaps, mode))
2450 vap->iv_txparms[mode] = parms.params[mode];
2451 }
2452 /* XXX could be more intelligent,
2453 e.g. don't reset if setting not being used */
2454 return ENETRESET;
2455 }
2456 return 0;
2457 }
2458
2459 /*
2460 * Application Information Element support.
2461 */
2462 static int
2463 setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
2464 {
2465 struct ieee80211_appie *app = *aie;
2466 struct ieee80211_appie *napp;
2467 int error;
2468
2469 if (ireq->i_len == 0) { /* delete any existing ie */
2470 if (app != NULL) {
2471 *aie = NULL; /* XXX racey */
2472 IEEE80211_FREE(app, M_80211_NODE_IE);
2473 }
2474 return 0;
2475 }
2476 if (!(2 <= ireq->i_len && ireq->i_len <= IEEE80211_MAX_APPIE))
2477 return EINVAL;
2478 /*
2479 * Allocate a new appie structure and copy in the user data.
2480 * When done swap in the new structure. Note that we do not
2481 * guard against users holding a ref to the old structure;
2482 * this must be handled outside this code.
2483 *
2484 * XXX bad bad bad
2485 */
2486 napp = (struct ieee80211_appie *) IEEE80211_MALLOC(
2487 sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE,
2488 IEEE80211_M_NOWAIT);
2489 if (napp == NULL)
2490 return ENOMEM;
2491 /* XXX holding ic lock */
2492 error = copyin(ireq->i_data, napp->ie_data, ireq->i_len);
2493 if (error) {
2494 IEEE80211_FREE(napp, M_80211_NODE_IE);
2495 return error;
2496 }
2497 napp->ie_len = ireq->i_len;
2498 *aie = napp;
2499 if (app != NULL)
2500 IEEE80211_FREE(app, M_80211_NODE_IE);
2501 return 0;
2502 }
2503
2504 static void
2505 setwparsnie(struct ieee80211vap *vap, uint8_t *ie, int space)
2506 {
2507 /* validate data is present as best we can */
2508 if (space == 0 || 2+ie[1] > space)
2509 return;
2510 if (ie[0] == IEEE80211_ELEMID_VENDOR)
2511 vap->iv_wpa_ie = ie;
2512 else if (ie[0] == IEEE80211_ELEMID_RSN)
2513 vap->iv_rsn_ie = ie;
2514 }
2515
2516 static int
2517 ieee80211_ioctl_setappie_locked(struct ieee80211vap *vap,
2518 const struct ieee80211req *ireq, int fc0)
2519 {
2520 int error;
2521
2522 IEEE80211_LOCK_ASSERT(vap->iv_ic);
2523
2524 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) {
2525 case IEEE80211_FC0_SUBTYPE_BEACON:
2526 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2527 vap->iv_opmode != IEEE80211_M_IBSS) {
2528 error = EINVAL;
2529 break;
2530 }
2531 error = setappie(&vap->iv_appie_beacon, ireq);
2532 if (error == 0)
2533 ieee80211_beacon_notify(vap, IEEE80211_BEACON_APPIE);
2534 break;
2535 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
2536 error = setappie(&vap->iv_appie_proberesp, ireq);
2537 break;
2538 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
2539 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
2540 error = setappie(&vap->iv_appie_assocresp, ireq);
2541 else
2542 error = EINVAL;
2543 break;
2544 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
2545 error = setappie(&vap->iv_appie_probereq, ireq);
2546 break;
2547 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
2548 if (vap->iv_opmode == IEEE80211_M_STA)
2549 error = setappie(&vap->iv_appie_assocreq, ireq);
2550 else
2551 error = EINVAL;
2552 break;
2553 case (IEEE80211_APPIE_WPA & IEEE80211_FC0_SUBTYPE_MASK):
2554 error = setappie(&vap->iv_appie_wpa, ireq);
2555 if (error == 0) {
2556 /*
2557 * Must split single blob of data into separate
2558 * WPA and RSN ie's because they go in different
2559 * locations in the mgt frames.
2560 * XXX use IEEE80211_IOC_WPA2 so user code does split
2561 */
2562 vap->iv_wpa_ie = NULL;
2563 vap->iv_rsn_ie = NULL;
2564 if (vap->iv_appie_wpa != NULL) {
2565 struct ieee80211_appie *appie =
2566 vap->iv_appie_wpa;
2567 uint8_t *data = appie->ie_data;
2568
2569 /* XXX ie length validate is painful, cheat */
2570 setwparsnie(vap, data, appie->ie_len);
2571 setwparsnie(vap, data + 2 + data[1],
2572 appie->ie_len - (2 + data[1]));
2573 }
2574 if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
2575 vap->iv_opmode == IEEE80211_M_IBSS) {
2576 /*
2577 * Must rebuild beacon frame as the update
2578 * mechanism doesn't handle WPA/RSN ie's.
2579 * Could extend it but it doesn't normally
2580 * change; this is just to deal with hostapd
2581 * plumbing the ie after the interface is up.
2582 */
2583 error = ENETRESET;
2584 }
2585 }
2586 break;
2587 default:
2588 error = EINVAL;
2589 break;
2590 }
2591 return error;
2592 }
2593
2594 static int
2595 ieee80211_ioctl_setappie(struct ieee80211vap *vap,
2596 const struct ieee80211req *ireq)
2597 {
2598 struct ieee80211com *ic = vap->iv_ic;
2599 int error;
2600 uint8_t fc0;
2601
2602 fc0 = ireq->i_val & 0xff;
2603 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
2604 return EINVAL;
2605 /* NB: could check iv_opmode and reject but hardly worth the effort */
2606 IEEE80211_LOCK(ic);
2607 error = ieee80211_ioctl_setappie_locked(vap, ireq, fc0);
2608 IEEE80211_UNLOCK(ic);
2609 return error;
2610 }
2611
2612 static int
2613 ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq)
2614 {
2615 struct ieee80211com *ic = vap->iv_ic;
2616 struct ieee80211_chanswitch_req csr;
2617 struct ieee80211_channel *c;
2618 int error;
2619
2620 if (ireq->i_len != sizeof(csr))
2621 return EINVAL;
2622 error = copyin(ireq->i_data, &csr, sizeof(csr));
2623 if (error != 0)
2624 return error;
2625 /* XXX adhoc mode not supported */
2626 if (vap->iv_opmode != IEEE80211_M_HOSTAP ||
2627 (vap->iv_flags & IEEE80211_F_DOTH) == 0)
2628 return EOPNOTSUPP;
2629 c = ieee80211_find_channel(ic,
2630 csr.csa_chan.ic_freq, csr.csa_chan.ic_flags);
2631 if (c == NULL)
2632 return ENOENT;
2633 IEEE80211_LOCK(ic);
2634 if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0)
2635 ieee80211_csa_startswitch(ic, c, csr.csa_mode, csr.csa_count);
2636 else if (csr.csa_count == 0)
2637 ieee80211_csa_cancelswitch(ic);
2638 else
2639 error = EBUSY;
2640 IEEE80211_UNLOCK(ic);
2641 return error;
2642 }
2643
2644 static int
2645 ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr)
2646 {
2647 #define IEEE80211_IOC_SCAN_FLAGS \
2648 (IEEE80211_IOC_SCAN_NOPICK | IEEE80211_IOC_SCAN_ACTIVE | \
2649 IEEE80211_IOC_SCAN_PICK1ST | IEEE80211_IOC_SCAN_BGSCAN | \
2650 IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOBCAST | \
2651 IEEE80211_IOC_SCAN_NOJOIN | IEEE80211_IOC_SCAN_FLUSH | \
2652 IEEE80211_IOC_SCAN_CHECK)
2653 struct ieee80211com *ic = vap->iv_ic;
2654 int error, i;
2655
2656 /* convert duration */
2657 if (sr->sr_duration == IEEE80211_IOC_SCAN_FOREVER)
2658 sr->sr_duration = IEEE80211_SCAN_FOREVER;
2659 else {
2660 if (sr->sr_duration < IEEE80211_IOC_SCAN_DURATION_MIN ||
2661 sr->sr_duration > IEEE80211_IOC_SCAN_DURATION_MAX)
2662 return EINVAL;
2663 sr->sr_duration = msecs_to_ticks(sr->sr_duration);
2664 if (sr->sr_duration < 1)
2665 sr->sr_duration = 1;
2666 }
2667 /* convert min/max channel dwell */
2668 if (sr->sr_mindwell != 0) {
2669 sr->sr_mindwell = msecs_to_ticks(sr->sr_mindwell);
2670 if (sr->sr_mindwell < 1)
2671 sr->sr_mindwell = 1;
2672 }
2673 if (sr->sr_maxdwell != 0) {
2674 sr->sr_maxdwell = msecs_to_ticks(sr->sr_maxdwell);
2675 if (sr->sr_maxdwell < 1)
2676 sr->sr_maxdwell = 1;
2677 }
2678 /* NB: silently reduce ssid count to what is supported */
2679 if (sr->sr_nssid > IEEE80211_SCAN_MAX_SSID)
2680 sr->sr_nssid = IEEE80211_SCAN_MAX_SSID;
2681 for (i = 0; i < sr->sr_nssid; i++)
2682 if (sr->sr_ssid[i].len > IEEE80211_NWID_LEN)
2683 return EINVAL;
2684 /* cleanse flags just in case, could reject if invalid flags */
2685 sr->sr_flags &= IEEE80211_IOC_SCAN_FLAGS;
2686 /*
2687 * Add an implicit NOPICK if the vap is not marked UP. This
2688 * allows applications to scan without joining a bss (or picking
2689 * a channel and setting up a bss) and without forcing manual
2690 * roaming mode--you just need to mark the parent device UP.
2691 */
2692 if ((vap->iv_ifp->if_flags & IFF_UP) == 0)
2693 sr->sr_flags |= IEEE80211_IOC_SCAN_NOPICK;
2694
2695 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
2696 "%s: flags 0x%x%s duration 0x%x mindwell %u maxdwell %u nssid %d\n",
2697 __func__, sr->sr_flags,
2698 (vap->iv_ifp->if_flags & IFF_UP) == 0 ? " (!IFF_UP)" : "",
2699 sr->sr_duration, sr->sr_mindwell, sr->sr_maxdwell, sr->sr_nssid);
2700 /*
2701 * If we are in INIT state then the driver has never had a chance
2702 * to setup hardware state to do a scan; we must use the state
2703 * machine to get us up to the SCAN state but once we reach SCAN
2704 * state we then want to use the supplied params. Stash the
2705 * parameters in the vap and mark IEEE80211_FEXT_SCANREQ; the
2706 * state machines will recognize this and use the stashed params
2707 * to issue the scan request.
2708 *
2709 * Otherwise just invoke the scan machinery directly.
2710 */
2711 IEEE80211_LOCK(ic);
2712 if (ic->ic_nrunning == 0) {
2713 IEEE80211_UNLOCK(ic);
2714 return ENXIO;
2715 }
2716
2717 if (vap->iv_state == IEEE80211_S_INIT) {
2718 /* NB: clobbers previous settings */
2719 vap->iv_scanreq_flags = sr->sr_flags;
2720 vap->iv_scanreq_duration = sr->sr_duration;
2721 vap->iv_scanreq_nssid = sr->sr_nssid;
2722 for (i = 0; i < sr->sr_nssid; i++) {
2723 vap->iv_scanreq_ssid[i].len = sr->sr_ssid[i].len;
2724 memcpy(vap->iv_scanreq_ssid[i].ssid,
2725 sr->sr_ssid[i].ssid, sr->sr_ssid[i].len);
2726 }
2727 vap->iv_flags_ext |= IEEE80211_FEXT_SCANREQ;
2728 IEEE80211_UNLOCK(ic);
2729 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
2730 } else {
2731 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
2732 IEEE80211_UNLOCK(ic);
2733 if (sr->sr_flags & IEEE80211_IOC_SCAN_CHECK) {
2734 error = ieee80211_check_scan(vap, sr->sr_flags,
2735 sr->sr_duration, sr->sr_mindwell, sr->sr_maxdwell,
2736 sr->sr_nssid,
2737 /* NB: cheat, we assume structures are compatible */
2738 (const struct ieee80211_scan_ssid *) &sr->sr_ssid[0]);
2739 } else {
2740 error = ieee80211_start_scan(vap, sr->sr_flags,
2741 sr->sr_duration, sr->sr_mindwell, sr->sr_maxdwell,
2742 sr->sr_nssid,
2743 /* NB: cheat, we assume structures are compatible */
2744 (const struct ieee80211_scan_ssid *) &sr->sr_ssid[0]);
2745 }
2746 if (error == 0)
2747 return EINPROGRESS;
2748 }
2749 return 0;
2750 #undef IEEE80211_IOC_SCAN_FLAGS
2751 }
2752
2753 static int
2754 ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq)
2755 {
2756 struct ieee80211_scan_req *sr;
2757 int error;
2758
2759 if (ireq->i_len != sizeof(*sr))
2760 return EINVAL;
2761 sr = IEEE80211_MALLOC(sizeof(*sr), M_TEMP,
2762 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
2763 if (sr == NULL)
2764 return ENOMEM;
2765 error = copyin(ireq->i_data, sr, sizeof(*sr));
2766 if (error != 0)
2767 goto bad;
2768 error = ieee80211_scanreq(vap, sr);
2769 bad:
2770 IEEE80211_FREE(sr, M_TEMP);
2771 return error;
2772 }
2773
2774 static int
2775 ieee80211_ioctl_setstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
2776 {
2777 struct ieee80211_node *ni;
2778 struct ieee80211req_sta_vlan vlan;
2779 int error;
2780
2781 if (ireq->i_len != sizeof(vlan))
2782 return EINVAL;
2783 error = copyin(ireq->i_data, &vlan, sizeof(vlan));
2784 if (error != 0)
2785 return error;
2786 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) {
2787 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
2788 vlan.sv_macaddr);
2789 if (ni == NULL)
2790 return ENOENT;
2791 } else
2792 ni = ieee80211_ref_node(vap->iv_bss);
2793 ni->ni_vlan = vlan.sv_vlan;
2794 ieee80211_free_node(ni);
2795 return error;
2796 }
2797
2798 static int
2799 isvap11g(const struct ieee80211vap *vap)
2800 {
2801 const struct ieee80211_node *bss = vap->iv_bss;
2802 return bss->ni_chan != IEEE80211_CHAN_ANYC &&
2803 IEEE80211_IS_CHAN_ANYG(bss->ni_chan);
2804 }
2805
2806 static int
2807 isvapht(const struct ieee80211vap *vap)
2808 {
2809 const struct ieee80211_node *bss = vap->iv_bss;
2810 return bss->ni_chan != IEEE80211_CHAN_ANYC &&
2811 IEEE80211_IS_CHAN_HT(bss->ni_chan);
2812 }
2813
2814 /*
2815 * Dummy ioctl set handler so the linker set is defined.
2816 */
2817 static __unused int
2818 dummy_ioctl_set(struct ieee80211vap *vap, struct ieee80211req *ireq)
2819 {
2820 return ENOSYS;
2821 }
2822 IEEE80211_IOCTL_SET(dummy, dummy_ioctl_set);
2823
2824 static int
2825 ieee80211_ioctl_setdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
2826 {
2827 #ifdef notyet
2828 ieee80211_ioctl_setfunc * const *set;
2829 int error;
2830
2831 SET_FOREACH(set, ieee80211_ioctl_setset) {
2832 error = (*set)(vap, ireq);
2833 if (error != ENOSYS)
2834 return error;
2835 }
2836 #else
2837 printf ("ieee80211_ioctl_setdefault called\n");
2838 #endif
2839 return EINVAL;
2840 }
2841
2842 static int
2843 ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq)
2844 {
2845 struct ieee80211com *ic = vap->iv_ic;
2846 int error;
2847 const struct ieee80211_authenticator *auth;
2848 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
2849 char tmpssid[IEEE80211_NWID_LEN];
2850 uint8_t tmpbssid[IEEE80211_ADDR_LEN];
2851 struct ieee80211_key *k;
2852 u_int kid;
2853 uint32_t flags;
2854
2855 error = 0;
2856 switch (ireq->i_type) {
2857 case IEEE80211_IOC_SSID:
2858 if (ireq->i_val != 0 ||
2859 ireq->i_len > IEEE80211_NWID_LEN)
2860 return EINVAL;
2861 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
2862 if (error)
2863 break;
2864 memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
2865 vap->iv_des_ssid[0].len = ireq->i_len;
2866 memcpy(vap->iv_des_ssid[0].ssid, tmpssid, ireq->i_len);
2867 vap->iv_des_nssid = (ireq->i_len > 0);
2868 error = ENETRESET;
2869 break;
2870 case IEEE80211_IOC_WEP:
2871 switch (ireq->i_val) {
2872 case IEEE80211_WEP_OFF:
2873 vap->iv_flags &= ~IEEE80211_F_PRIVACY;
2874 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2875 break;
2876 case IEEE80211_WEP_ON:
2877 vap->iv_flags |= IEEE80211_F_PRIVACY;
2878 vap->iv_flags |= IEEE80211_F_DROPUNENC;
2879 break;
2880 case IEEE80211_WEP_MIXED:
2881 vap->iv_flags |= IEEE80211_F_PRIVACY;
2882 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2883 break;
2884 }
2885 error = ENETRESET;
2886 break;
2887 case IEEE80211_IOC_WEPKEY:
2888 kid = (u_int) ireq->i_val;
2889 if (kid >= IEEE80211_WEP_NKID)
2890 return EINVAL;
2891 k = &vap->iv_nw_keys[kid];
2892 if (ireq->i_len == 0) {
2893 /* zero-len =>'s delete any existing key */
2894 (void) ieee80211_crypto_delkey(vap, k);
2895 break;
2896 }
2897 if (ireq->i_len > sizeof(tmpkey))
2898 return EINVAL;
2899 memset(tmpkey, 0, sizeof(tmpkey));
2900 error = copyin(ireq->i_data, tmpkey, ireq->i_len);
2901 if (error)
2902 break;
2903 ieee80211_key_update_begin(vap);
2904 k->wk_keyix = kid; /* NB: force fixed key id */
2905 if (ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP,
2906 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
2907 k->wk_keylen = ireq->i_len;
2908 memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
2909 IEEE80211_ADDR_COPY(k->wk_macaddr, vap->iv_myaddr);
2910 if (!ieee80211_crypto_setkey(vap, k))
2911 error = EINVAL;
2912 } else
2913 error = EINVAL;
2914 ieee80211_key_update_end(vap);
2915 break;
2916 case IEEE80211_IOC_WEPTXKEY:
2917 kid = (u_int) ireq->i_val;
2918 if (kid >= IEEE80211_WEP_NKID &&
2919 (uint16_t) kid != IEEE80211_KEYIX_NONE)
2920 return EINVAL;
2921 /*
2922 * Firmware devices may need to be told about an explicit
2923 * key index here, versus just inferring it from the
2924 * key set / change. Since we may also need to pause
2925 * things like transmit before the key is updated,
2926 * give the driver a chance to flush things by tying
2927 * into key update begin/end.
2928 */
2929 ieee80211_key_update_begin(vap);
2930 ieee80211_crypto_set_deftxkey(vap, kid);
2931 ieee80211_key_update_end(vap);
2932 break;
2933 case IEEE80211_IOC_AUTHMODE:
2934 switch (ireq->i_val) {
2935 case IEEE80211_AUTH_WPA:
2936 case IEEE80211_AUTH_8021X: /* 802.1x */
2937 case IEEE80211_AUTH_OPEN: /* open */
2938 case IEEE80211_AUTH_SHARED: /* shared-key */
2939 case IEEE80211_AUTH_AUTO: /* auto */
2940 auth = ieee80211_authenticator_get(ireq->i_val);
2941 if (auth == NULL)
2942 return EINVAL;
2943 break;
2944 default:
2945 return EINVAL;
2946 }
2947 switch (ireq->i_val) {
2948 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */
2949 vap->iv_flags |= IEEE80211_F_PRIVACY;
2950 ireq->i_val = IEEE80211_AUTH_8021X;
2951 break;
2952 case IEEE80211_AUTH_OPEN: /* open */
2953 vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
2954 break;
2955 case IEEE80211_AUTH_SHARED: /* shared-key */
2956 case IEEE80211_AUTH_8021X: /* 802.1x */
2957 vap->iv_flags &= ~IEEE80211_F_WPA;
2958 /* both require a key so mark the PRIVACY capability */
2959 vap->iv_flags |= IEEE80211_F_PRIVACY;
2960 break;
2961 case IEEE80211_AUTH_AUTO: /* auto */
2962 vap->iv_flags &= ~IEEE80211_F_WPA;
2963 /* XXX PRIVACY handling? */
2964 /* XXX what's the right way to do this? */
2965 break;
2966 }
2967 /* NB: authenticator attach/detach happens on state change */
2968 vap->iv_bss->ni_authmode = ireq->i_val;
2969 /* XXX mixed/mode/usage? */
2970 vap->iv_auth = auth;
2971 error = ENETRESET;
2972 break;
2973 case IEEE80211_IOC_CHANNEL:
2974 error = ieee80211_ioctl_setchannel(vap, ireq);
2975 break;
2976 case IEEE80211_IOC_POWERSAVE:
2977 switch (ireq->i_val) {
2978 case IEEE80211_POWERSAVE_OFF:
2979 if (vap->iv_flags & IEEE80211_F_PMGTON) {
2980 ieee80211_syncflag(vap, -IEEE80211_F_PMGTON);
2981 error = ERESTART;
2982 }
2983 break;
2984 case IEEE80211_POWERSAVE_ON:
2985 if ((vap->iv_caps & IEEE80211_C_PMGT) == 0)
2986 error = EOPNOTSUPP;
2987 else if ((vap->iv_flags & IEEE80211_F_PMGTON) == 0) {
2988 ieee80211_syncflag(vap, IEEE80211_F_PMGTON);
2989 error = ERESTART;
2990 }
2991 break;
2992 default:
2993 error = EINVAL;
2994 break;
2995 }
2996 break;
2997 case IEEE80211_IOC_POWERSAVESLEEP:
2998 if (ireq->i_val < 0)
2999 return EINVAL;
3000 ic->ic_lintval = ireq->i_val;
3001 error = ERESTART;
3002 break;
3003 case IEEE80211_IOC_RTSTHRESHOLD:
3004 if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
3005 ireq->i_val <= IEEE80211_RTS_MAX))
3006 return EINVAL;
3007 vap->iv_rtsthreshold = ireq->i_val;
3008 error = ERESTART;
3009 break;
3010 case IEEE80211_IOC_PROTMODE:
3011 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
3012 return EINVAL;
3013 ic->ic_protmode = (enum ieee80211_protmode)ireq->i_val;
3014 /* NB: if not operating in 11g this can wait */
3015 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
3016 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
3017 error = ERESTART;
3018 break;
3019 case IEEE80211_IOC_TXPOWER:
3020 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
3021 return EOPNOTSUPP;
3022 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
3023 ireq->i_val <= IEEE80211_TXPOWER_MAX))
3024 return EINVAL;
3025 ic->ic_txpowlimit = ireq->i_val;
3026 error = ERESTART;
3027 break;
3028 case IEEE80211_IOC_ROAMING:
3029 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
3030 ireq->i_val <= IEEE80211_ROAMING_MANUAL))
3031 return EINVAL;
3032 vap->iv_roaming = (enum ieee80211_roamingmode)ireq->i_val;
3033 /* XXXX reset? */
3034 break;
3035 case IEEE80211_IOC_PRIVACY:
3036 if (ireq->i_val) {
3037 /* XXX check for key state? */
3038 vap->iv_flags |= IEEE80211_F_PRIVACY;
3039 } else
3040 vap->iv_flags &= ~IEEE80211_F_PRIVACY;
3041 /* XXX ERESTART? */
3042 break;
3043 case IEEE80211_IOC_DROPUNENCRYPTED:
3044 if (ireq->i_val)
3045 vap->iv_flags |= IEEE80211_F_DROPUNENC;
3046 else
3047 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
3048 /* XXX ERESTART? */
3049 break;
3050 case IEEE80211_IOC_WPAKEY:
3051 error = ieee80211_ioctl_setkey(vap, ireq);
3052 break;
3053 case IEEE80211_IOC_DELKEY:
3054 error = ieee80211_ioctl_delkey(vap, ireq);
3055 break;
3056 case IEEE80211_IOC_MLME:
3057 error = ieee80211_ioctl_setmlme(vap, ireq);
3058 break;
3059 case IEEE80211_IOC_COUNTERMEASURES:
3060 if (ireq->i_val) {
3061 if ((vap->iv_flags & IEEE80211_F_WPA) == 0)
3062 return EOPNOTSUPP;
3063 vap->iv_flags |= IEEE80211_F_COUNTERM;
3064 } else
3065 vap->iv_flags &= ~IEEE80211_F_COUNTERM;
3066 /* XXX ERESTART? */
3067 break;
3068 case IEEE80211_IOC_WPA:
3069 if (ireq->i_val > 3)
3070 return EINVAL;
3071 /* XXX verify ciphers available */
3072 flags = vap->iv_flags & ~IEEE80211_F_WPA;
3073 switch (ireq->i_val) {
3074 case 0:
3075 /* wpa_supplicant calls this to clear the WPA config */
3076 break;
3077 case 1:
3078 if (!(vap->iv_caps & IEEE80211_C_WPA1))
3079 return EOPNOTSUPP;
3080 flags |= IEEE80211_F_WPA1;
3081 break;
3082 case 2:
3083 if (!(vap->iv_caps & IEEE80211_C_WPA2))
3084 return EOPNOTSUPP;
3085 flags |= IEEE80211_F_WPA2;
3086 break;
3087 case 3:
3088 if ((vap->iv_caps & IEEE80211_C_WPA) != IEEE80211_C_WPA)
3089 return EOPNOTSUPP;
3090 flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
3091 break;
3092 default: /* Can't set any -> error */
3093 return EOPNOTSUPP;
3094 }
3095 vap->iv_flags = flags;
3096 error = ERESTART; /* NB: can change beacon frame */
3097 break;
3098 case IEEE80211_IOC_WME:
3099 if (ireq->i_val) {
3100 if ((vap->iv_caps & IEEE80211_C_WME) == 0)
3101 return EOPNOTSUPP;
3102 ieee80211_syncflag(vap, IEEE80211_F_WME);
3103 } else
3104 ieee80211_syncflag(vap, -IEEE80211_F_WME);
3105 error = ERESTART; /* NB: can change beacon frame */
3106 break;
3107 case IEEE80211_IOC_HIDESSID:
3108 if (ireq->i_val)
3109 vap->iv_flags |= IEEE80211_F_HIDESSID;
3110 else
3111 vap->iv_flags &= ~IEEE80211_F_HIDESSID;
3112 error = ERESTART; /* XXX ENETRESET? */
3113 break;
3114 case IEEE80211_IOC_APBRIDGE:
3115 if (ireq->i_val == 0)
3116 vap->iv_flags |= IEEE80211_F_NOBRIDGE;
3117 else
3118 vap->iv_flags &= ~IEEE80211_F_NOBRIDGE;
3119 break;
3120 case IEEE80211_IOC_BSSID:
3121 if (ireq->i_len != sizeof(tmpbssid))
3122 return EINVAL;
3123 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
3124 if (error)
3125 break;
3126 IEEE80211_ADDR_COPY(vap->iv_des_bssid, tmpbssid);
3127 if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zerobssid))
3128 vap->iv_flags &= ~IEEE80211_F_DESBSSID;
3129 else
3130 vap->iv_flags |= IEEE80211_F_DESBSSID;
3131 error = ENETRESET;
3132 break;
3133 case IEEE80211_IOC_CHANLIST:
3134 error = ieee80211_ioctl_setchanlist(vap, ireq);
3135 break;
3136 #ifdef OLD_IEEE80211_IOC_SCAN_REQ
3137 case OLD_IEEE80211_IOC_SCAN_REQ:
3138 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
3139 "%s: active scan request\n", __func__);
3140 printf ("old scan req\n");
3141 /*
3142 * If we are in INIT state then the driver has never
3143 * had a chance to setup hardware state to do a scan;
3144 * use the state machine to get us up the SCAN state.
3145 * Otherwise just invoke the scan machinery to start
3146 * a one-time scan.
3147 */
3148 if (vap->iv_state == IEEE80211_S_INIT)
3149 { printf ("calling new_state\n");
3150 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
3151 }
3152 else
3153 { printf("calling _start_scan()\n");
3154 (void) ieee80211_start_scan(vap,
3155 IEEE80211_SCAN_ACTIVE |
3156 IEEE80211_SCAN_NOPICK |
3157 IEEE80211_SCAN_ONCE,
3158 IEEE80211_SCAN_FOREVER, 0, 0,
3159 /* XXX use ioctl params */
3160 vap->iv_des_nssid, vap->iv_des_ssid);
3161 }
3162 break;
3163 #endif /* OLD_IEEE80211_IOC_SCAN_REQ */
3164 case IEEE80211_IOC_SCAN_REQ:
3165 error = ieee80211_ioctl_scanreq(vap, ireq);
3166 break;
3167 case IEEE80211_IOC_SCAN_CANCEL:
3168 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
3169 "%s: cancel scan\n", __func__);
3170 #if __NetBSD__
3171 /* Bug in FreeBSD? */
3172 IEEE80211_LOCK(ic);
3173 #endif
3174 ieee80211_cancel_scan(vap);
3175 #if __NetBSD__
3176 IEEE80211_UNLOCK(ic);
3177 #endif
3178 break;
3179 case IEEE80211_IOC_HTCONF:
3180 if (ireq->i_val & 1)
3181 ieee80211_syncflag_ht(vap, IEEE80211_FHT_HT);
3182 else
3183 ieee80211_syncflag_ht(vap, -IEEE80211_FHT_HT);
3184 if (ireq->i_val & 2)
3185 ieee80211_syncflag_ht(vap, IEEE80211_FHT_USEHT40);
3186 else
3187 ieee80211_syncflag_ht(vap, -IEEE80211_FHT_USEHT40);
3188 error = ENETRESET;
3189 break;
3190 case IEEE80211_IOC_ADDMAC:
3191 case IEEE80211_IOC_DELMAC:
3192 error = ieee80211_ioctl_macmac(vap, ireq);
3193 break;
3194 case IEEE80211_IOC_MACCMD:
3195 error = ieee80211_ioctl_setmaccmd(vap, ireq);
3196 break;
3197 case IEEE80211_IOC_STA_STATS:
3198 error = ieee80211_ioctl_setstastats(vap, ireq);
3199 break;
3200 case IEEE80211_IOC_STA_TXPOW:
3201 error = ieee80211_ioctl_setstatxpow(vap, ireq);
3202 break;
3203 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
3204 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
3205 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
3206 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
3207 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
3208 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only) */
3209 error = ieee80211_ioctl_setwmeparam(vap, ireq);
3210 break;
3211 case IEEE80211_IOC_DTIM_PERIOD:
3212 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
3213 vap->iv_opmode != IEEE80211_M_MBSS &&
3214 vap->iv_opmode != IEEE80211_M_IBSS)
3215 return EINVAL;
3216 if (IEEE80211_DTIM_MIN <= ireq->i_val &&
3217 ireq->i_val <= IEEE80211_DTIM_MAX) {
3218 vap->iv_dtim_period = ireq->i_val;
3219 error = ENETRESET; /* requires restart */
3220 } else
3221 error = EINVAL;
3222 break;
3223 case IEEE80211_IOC_BEACON_INTERVAL:
3224 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
3225 vap->iv_opmode != IEEE80211_M_MBSS &&
3226 vap->iv_opmode != IEEE80211_M_IBSS)
3227 return EINVAL;
3228 if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
3229 ireq->i_val <= IEEE80211_BINTVAL_MAX) {
3230 ic->ic_bintval = ireq->i_val;
3231 error = ENETRESET; /* requires restart */
3232 } else
3233 error = EINVAL;
3234 break;
3235 case IEEE80211_IOC_PUREG:
3236 if (ireq->i_val)
3237 vap->iv_flags |= IEEE80211_F_PUREG;
3238 else
3239 vap->iv_flags &= ~IEEE80211_F_PUREG;
3240 /* NB: reset only if we're operating on an 11g channel */
3241 if (isvap11g(vap))
3242 error = ENETRESET;
3243 break;
3244 case IEEE80211_IOC_QUIET:
3245 vap->iv_quiet= ireq->i_val;
3246 break;
3247 case IEEE80211_IOC_QUIET_COUNT:
3248 vap->iv_quiet_count=ireq->i_val;
3249 break;
3250 case IEEE80211_IOC_QUIET_PERIOD:
3251 vap->iv_quiet_period=ireq->i_val;
3252 break;
3253 case IEEE80211_IOC_QUIET_OFFSET:
3254 vap->iv_quiet_offset=ireq->i_val;
3255 break;
3256 case IEEE80211_IOC_QUIET_DUR:
3257 if(ireq->i_val < vap->iv_bss->ni_intval)
3258 vap->iv_quiet_duration = ireq->i_val;
3259 else
3260 error = EINVAL;
3261 break;
3262 case IEEE80211_IOC_BGSCAN:
3263 if (ireq->i_val) {
3264 if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0)
3265 return EOPNOTSUPP;
3266 vap->iv_flags |= IEEE80211_F_BGSCAN;
3267 } else
3268 vap->iv_flags &= ~IEEE80211_F_BGSCAN;
3269 break;
3270 case IEEE80211_IOC_BGSCAN_IDLE:
3271 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
3272 vap->iv_bgscanidle = ireq->i_val*hz/1000;
3273 else
3274 error = EINVAL;
3275 break;
3276 case IEEE80211_IOC_BGSCAN_INTERVAL:
3277 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
3278 vap->iv_bgscanintvl = ireq->i_val*hz;
3279 else
3280 error = EINVAL;
3281 break;
3282 case IEEE80211_IOC_SCANVALID:
3283 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
3284 vap->iv_scanvalid = ireq->i_val*hz;
3285 else
3286 error = EINVAL;
3287 break;
3288 case IEEE80211_IOC_FRAGTHRESHOLD:
3289 if ((vap->iv_caps & IEEE80211_C_TXFRAG) == 0 &&
3290 ireq->i_val != IEEE80211_FRAG_MAX)
3291 return EOPNOTSUPP;
3292 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
3293 ireq->i_val <= IEEE80211_FRAG_MAX))
3294 return EINVAL;
3295 vap->iv_fragthreshold = ireq->i_val;
3296 error = ERESTART;
3297 break;
3298 case IEEE80211_IOC_BURST:
3299 if (ireq->i_val) {
3300 if ((vap->iv_caps & IEEE80211_C_BURST) == 0)
3301 return EOPNOTSUPP;
3302 ieee80211_syncflag(vap, IEEE80211_F_BURST);
3303 } else
3304 ieee80211_syncflag(vap, -IEEE80211_F_BURST);
3305 error = ERESTART;
3306 break;
3307 case IEEE80211_IOC_BMISSTHRESHOLD:
3308 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
3309 ireq->i_val <= IEEE80211_HWBMISS_MAX))
3310 return EINVAL;
3311 vap->iv_bmissthreshold = ireq->i_val;
3312 error = ERESTART;
3313 break;
3314 case IEEE80211_IOC_CURCHAN:
3315 error = ieee80211_ioctl_setcurchan(vap, ireq);
3316 break;
3317 case IEEE80211_IOC_SHORTGI:
3318 if (ireq->i_val) {
3319 #define IEEE80211_HTCAP_SHORTGI \
3320 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
3321 if (((ireq->i_val ^ vap->iv_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
3322 return EINVAL;
3323 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
3324 vap->iv_flags_ht |= IEEE80211_FHT_SHORTGI20;
3325 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
3326 vap->iv_flags_ht |= IEEE80211_FHT_SHORTGI40;
3327 #undef IEEE80211_HTCAP_SHORTGI
3328 } else
3329 vap->iv_flags_ht &=
3330 ~(IEEE80211_FHT_SHORTGI20 | IEEE80211_FHT_SHORTGI40);
3331 error = ERESTART;
3332 break;
3333 case IEEE80211_IOC_AMPDU:
3334 if (ireq->i_val && (vap->iv_htcaps & IEEE80211_HTC_AMPDU) == 0)
3335 return EINVAL;
3336 if (ireq->i_val & 1)
3337 vap->iv_flags_ht |= IEEE80211_FHT_AMPDU_TX;
3338 else
3339 vap->iv_flags_ht &= ~IEEE80211_FHT_AMPDU_TX;
3340 if (ireq->i_val & 2)
3341 vap->iv_flags_ht |= IEEE80211_FHT_AMPDU_RX;
3342 else
3343 vap->iv_flags_ht &= ~IEEE80211_FHT_AMPDU_RX;
3344 /* NB: reset only if we're operating on an 11n channel */
3345 if (isvapht(vap))
3346 error = ERESTART;
3347 break;
3348 case IEEE80211_IOC_AMPDU_LIMIT:
3349 /* XXX TODO: figure out ampdu_limit versus ampdu_rxmax */
3350 if (!(IEEE80211_HTCAP_MAXRXAMPDU_8K <= ireq->i_val &&
3351 ireq->i_val <= IEEE80211_HTCAP_MAXRXAMPDU_64K))
3352 return EINVAL;
3353 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
3354 vap->iv_ampdu_rxmax = ireq->i_val;
3355 else
3356 vap->iv_ampdu_limit = ireq->i_val;
3357 error = ERESTART;
3358 break;
3359 case IEEE80211_IOC_AMPDU_DENSITY:
3360 if (!(IEEE80211_HTCAP_MPDUDENSITY_NA <= ireq->i_val &&
3361 ireq->i_val <= IEEE80211_HTCAP_MPDUDENSITY_16))
3362 return EINVAL;
3363 vap->iv_ampdu_density = ireq->i_val;
3364 error = ERESTART;
3365 break;
3366 case IEEE80211_IOC_AMSDU:
3367 if (ireq->i_val && (vap->iv_htcaps & IEEE80211_HTC_AMSDU) == 0)
3368 return EINVAL;
3369 if (ireq->i_val & 1)
3370 vap->iv_flags_ht |= IEEE80211_FHT_AMSDU_TX;
3371 else
3372 vap->iv_flags_ht &= ~IEEE80211_FHT_AMSDU_TX;
3373 if (ireq->i_val & 2)
3374 vap->iv_flags_ht |= IEEE80211_FHT_AMSDU_RX;
3375 else
3376 vap->iv_flags_ht &= ~IEEE80211_FHT_AMSDU_RX;
3377 /* NB: reset only if we're operating on an 11n channel */
3378 if (isvapht(vap))
3379 error = ERESTART;
3380 break;
3381 case IEEE80211_IOC_AMSDU_LIMIT:
3382 /* XXX validate */
3383 vap->iv_amsdu_limit = ireq->i_val; /* XXX truncation? */
3384 break;
3385 case IEEE80211_IOC_PUREN:
3386 if (ireq->i_val) {
3387 if ((vap->iv_flags_ht & IEEE80211_FHT_HT) == 0)
3388 return EINVAL;
3389 vap->iv_flags_ht |= IEEE80211_FHT_PUREN;
3390 } else
3391 vap->iv_flags_ht &= ~IEEE80211_FHT_PUREN;
3392 /* NB: reset only if we're operating on an 11n channel */
3393 if (isvapht(vap))
3394 error = ERESTART;
3395 break;
3396 case IEEE80211_IOC_DOTH:
3397 if (ireq->i_val) {
3398 #if 0
3399 /* XXX no capability */
3400 if ((vap->iv_caps & IEEE80211_C_DOTH) == 0)
3401 return EOPNOTSUPP;
3402 #endif
3403 vap->iv_flags |= IEEE80211_F_DOTH;
3404 } else
3405 vap->iv_flags &= ~IEEE80211_F_DOTH;
3406 error = ENETRESET;
3407 break;
3408 case IEEE80211_IOC_REGDOMAIN:
3409 error = ieee80211_ioctl_setregdomain(vap, ireq);
3410 break;
3411 case IEEE80211_IOC_ROAM:
3412 error = ieee80211_ioctl_setroam(vap, ireq);
3413 break;
3414 case IEEE80211_IOC_TXPARAMS:
3415 error = ieee80211_ioctl_settxparams(vap, ireq);
3416 break;
3417 case IEEE80211_IOC_HTCOMPAT:
3418 if (ireq->i_val) {
3419 if ((vap->iv_flags_ht & IEEE80211_FHT_HT) == 0)
3420 return EOPNOTSUPP;
3421 vap->iv_flags_ht |= IEEE80211_FHT_HTCOMPAT;
3422 } else
3423 vap->iv_flags_ht &= ~IEEE80211_FHT_HTCOMPAT;
3424 /* NB: reset only if we're operating on an 11n channel */
3425 if (isvapht(vap))
3426 error = ERESTART;
3427 break;
3428 case IEEE80211_IOC_DWDS:
3429 if (ireq->i_val) {
3430 /* NB: DWDS only makes sense for WDS-capable devices */
3431 if ((ic->ic_caps & IEEE80211_C_WDS) == 0)
3432 return EOPNOTSUPP;
3433 /* NB: DWDS is used only with ap+sta vaps */
3434 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
3435 vap->iv_opmode != IEEE80211_M_STA)
3436 return EINVAL;
3437 vap->iv_flags |= IEEE80211_F_DWDS;
3438 if (vap->iv_opmode == IEEE80211_M_STA)
3439 vap->iv_flags_ext |= IEEE80211_FEXT_4ADDR;
3440 } else {
3441 vap->iv_flags &= ~IEEE80211_F_DWDS;
3442 if (vap->iv_opmode == IEEE80211_M_STA)
3443 vap->iv_flags_ext &= ~IEEE80211_FEXT_4ADDR;
3444 }
3445 break;
3446 case IEEE80211_IOC_INACTIVITY:
3447 if (ireq->i_val)
3448 vap->iv_flags_ext |= IEEE80211_FEXT_INACT;
3449 else
3450 vap->iv_flags_ext &= ~IEEE80211_FEXT_INACT;
3451 break;
3452 case IEEE80211_IOC_APPIE:
3453 error = ieee80211_ioctl_setappie(vap, ireq);
3454 break;
3455 case IEEE80211_IOC_WPS:
3456 if (ireq->i_val) {
3457 if ((vap->iv_caps & IEEE80211_C_WPA) == 0)
3458 return EOPNOTSUPP;
3459 vap->iv_flags_ext |= IEEE80211_FEXT_WPS;
3460 } else
3461 vap->iv_flags_ext &= ~IEEE80211_FEXT_WPS;
3462 break;
3463 case IEEE80211_IOC_TSN:
3464 if (ireq->i_val) {
3465 if ((vap->iv_caps & IEEE80211_C_WPA) == 0)
3466 return EOPNOTSUPP;
3467 vap->iv_flags_ext |= IEEE80211_FEXT_TSN;
3468 } else
3469 vap->iv_flags_ext &= ~IEEE80211_FEXT_TSN;
3470 break;
3471 case IEEE80211_IOC_CHANSWITCH:
3472 error = ieee80211_ioctl_chanswitch(vap, ireq);
3473 break;
3474 case IEEE80211_IOC_DFS:
3475 if (ireq->i_val) {
3476 if ((vap->iv_caps & IEEE80211_C_DFS) == 0)
3477 return EOPNOTSUPP;
3478 /* NB: DFS requires 11h support */
3479 if ((vap->iv_flags & IEEE80211_F_DOTH) == 0)
3480 return EINVAL;
3481 vap->iv_flags_ext |= IEEE80211_FEXT_DFS;
3482 } else
3483 vap->iv_flags_ext &= ~IEEE80211_FEXT_DFS;
3484 break;
3485 case IEEE80211_IOC_DOTD:
3486 if (ireq->i_val)
3487 vap->iv_flags_ext |= IEEE80211_FEXT_DOTD;
3488 else
3489 vap->iv_flags_ext &= ~IEEE80211_FEXT_DOTD;
3490 if (vap->iv_opmode == IEEE80211_M_STA)
3491 error = ENETRESET;
3492 break;
3493 case IEEE80211_IOC_HTPROTMODE:
3494 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
3495 return EINVAL;
3496 ic->ic_htprotmode = ireq->i_val ?
3497 IEEE80211_PROT_RTSCTS : IEEE80211_PROT_NONE;
3498 /* NB: if not operating in 11n this can wait */
3499 if (isvapht(vap))
3500 error = ERESTART;
3501 break;
3502 case IEEE80211_IOC_STA_VLAN:
3503 error = ieee80211_ioctl_setstavlan(vap, ireq);
3504 break;
3505 case IEEE80211_IOC_SMPS:
3506 if ((ireq->i_val &~ IEEE80211_HTCAP_SMPS) != 0 ||
3507 ireq->i_val == 0x0008) /* value of 2 is reserved */
3508 return EINVAL;
3509 if (ireq->i_val != IEEE80211_HTCAP_SMPS_OFF &&
3510 (vap->iv_htcaps & IEEE80211_HTC_SMPS) == 0)
3511 return EOPNOTSUPP;
3512 vap->iv_htcaps = (vap->iv_htcaps &~ IEEE80211_HTCAP_SMPS) |
3513 ireq->i_val;
3514 /* NB: if not operating in 11n this can wait */
3515 if (isvapht(vap))
3516 error = ERESTART;
3517 break;
3518 case IEEE80211_IOC_RIFS:
3519 if (ireq->i_val != 0) {
3520 if ((vap->iv_htcaps & IEEE80211_HTC_RIFS) == 0)
3521 return EOPNOTSUPP;
3522 vap->iv_flags_ht |= IEEE80211_FHT_RIFS;
3523 } else
3524 vap->iv_flags_ht &= ~IEEE80211_FHT_RIFS;
3525 /* NB: if not operating in 11n this can wait */
3526 if (isvapht(vap))
3527 error = ERESTART;
3528 break;
3529 case IEEE80211_IOC_STBC:
3530 /* Check if we can do STBC TX/RX before changing the setting */
3531 if ((ireq->i_val & 1) &&
3532 ((vap->iv_htcaps & IEEE80211_HTCAP_TXSTBC) == 0))
3533 return EOPNOTSUPP;
3534 if ((ireq->i_val & 2) &&
3535 ((vap->iv_htcaps & IEEE80211_HTCAP_RXSTBC) == 0))
3536 return EOPNOTSUPP;
3537
3538 /* TX */
3539 if (ireq->i_val & 1)
3540 vap->iv_flags_ht |= IEEE80211_FHT_STBC_TX;
3541 else
3542 vap->iv_flags_ht &= ~IEEE80211_FHT_STBC_TX;
3543
3544 /* RX */
3545 if (ireq->i_val & 2)
3546 vap->iv_flags_ht |= IEEE80211_FHT_STBC_RX;
3547 else
3548 vap->iv_flags_ht &= ~IEEE80211_FHT_STBC_RX;
3549
3550 /* NB: reset only if we're operating on an 11n channel */
3551 if (isvapht(vap))
3552 error = ERESTART;
3553 break;
3554 case IEEE80211_IOC_LDPC:
3555 /* Check if we can do LDPC TX/RX before changing the setting */
3556 if ((ireq->i_val & 1) &&
3557 (vap->iv_htcaps & IEEE80211_HTC_TXLDPC) == 0)
3558 return EOPNOTSUPP;
3559 if ((ireq->i_val & 2) &&
3560 (vap->iv_htcaps & IEEE80211_HTCAP_LDPC) == 0)
3561 return EOPNOTSUPP;
3562
3563 /* TX */
3564 if (ireq->i_val & 1)
3565 vap->iv_flags_ht |= IEEE80211_FHT_LDPC_TX;
3566 else
3567 vap->iv_flags_ht &= ~IEEE80211_FHT_LDPC_TX;
3568
3569 /* RX */
3570 if (ireq->i_val & 2)
3571 vap->iv_flags_ht |= IEEE80211_FHT_LDPC_RX;
3572 else
3573 vap->iv_flags_ht &= ~IEEE80211_FHT_LDPC_RX;
3574
3575 /* NB: reset only if we're operating on an 11n channel */
3576 if (isvapht(vap))
3577 error = ERESTART;
3578 break;
3579
3580 /* VHT */
3581 case IEEE80211_IOC_VHTCONF:
3582 if (ireq->i_val & 1)
3583 ieee80211_syncflag_vht(vap, IEEE80211_FVHT_VHT);
3584 else
3585 ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_VHT);
3586
3587 if (ireq->i_val & 2)
3588 ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT40);
3589 else
3590 ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT40);
3591
3592 if (ireq->i_val & 4)
3593 ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT80);
3594 else
3595 ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT80);
3596
3597 if (ireq->i_val & 8)
3598 ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT80P80);
3599 else
3600 ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT80P80);
3601
3602 if (ireq->i_val & 16)
3603 ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT160);
3604 else
3605 ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT160);
3606
3607 error = ENETRESET;
3608 break;
3609
3610 default:
3611 error = ieee80211_ioctl_setdefault(vap, ireq);
3612 break;
3613 }
3614 /*
3615 * The convention is that ENETRESET means an operation
3616 * requires a complete re-initialization of the device (e.g.
3617 * changing something that affects the association state).
3618 * ERESTART means the request may be handled with only a
3619 * reload of the hardware state. We hand ERESTART requests
3620 * to the iv_reset callback so the driver can decide. If
3621 * a device does not fillin iv_reset then it defaults to one
3622 * that returns ENETRESET. Otherwise a driver may return
3623 * ENETRESET (in which case a full reset will be done) or
3624 * 0 to mean there's no need to do anything (e.g. when the
3625 * change has no effect on the driver/device).
3626 */
3627 if (error == ERESTART)
3628 error = IFNET_IS_UP_RUNNING(vap->iv_ifp) ?
3629 vap->iv_reset(vap, ireq->i_type) : 0;
3630 if (error == ENETRESET) {
3631 /* XXX need to re-think AUTO handling */
3632 if (IS_UP_AUTO(vap))
3633 #if __FreeBSD__
3634 ieee80211_init(vap);
3635 #elif __NetBSD__
3636 /* arg is a vap in 802.11 code */
3637 ieee80211_init((struct ifnet *)vap);
3638 #endif
3639 error = 0;
3640 }
3641 return error;
3642 }
3643
3644 int
3645 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
3646 {
3647 struct ieee80211vap *vap = ifp->if_softc;
3648 struct ieee80211com *ic = vap->iv_ic;
3649 int error = 0, wait = 0;
3650 struct ifreq *ifr;
3651 struct ifaddr *ifa; /* XXX */
3652 #if __NetBSD__
3653 struct ieee80211_nwid nwid;
3654 // struct ieee80211_nwkey *nwkey;
3655 struct ieee80211_power *power;
3656 struct ieee80211chanreq *chanreq;
3657 struct ieee80211_bssid *bssid;
3658 struct ieee80211_channel *chan;
3659 struct ieee80211req ireq;
3660
3661 ifr = (struct ifreq *)data;
3662 #endif
3663
3664 switch (cmd) {
3665 case SIOCSIFFLAGS:
3666 IEEE80211_LOCK(ic);
3667 if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_PROMISC) {
3668 printf (" promisc mode\n");
3669 /*
3670 * Enable promiscuous mode when:
3671 * 1. Interface is not a member of bridge, or
3672 * 2. Requested by user, or
3673 * 3. In monitor (or adhoc-demo) mode.
3674 */
3675 if (ifp->if_bridge == NULL ||
3676 (ifp->if_flags & IFF_PPROMISC) != 0 ||
3677 vap->iv_opmode == IEEE80211_M_MONITOR ||
3678 (vap->iv_opmode == IEEE80211_M_AHDEMO &&
3679 (vap->iv_caps & IEEE80211_C_TDMA) == 0)) {
3680 ieee80211_promisc(vap,
3681 ifp->if_flags & IFF_PROMISC);
3682 vap->iv_ifflags ^= IFF_PROMISC;
3683 }
3684 }
3685 if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_ALLMULTI) {
3686 printf (" allmulti\n");
3687 ieee80211_allmulti(vap, ifp->if_flags & IFF_ALLMULTI);
3688 vap->iv_ifflags ^= IFF_ALLMULTI;
3689 }
3690 if (ifp->if_flags & IFF_UP) {
3691 printf (" up flag\n");
3692 /*
3693 * Bring ourself up unless we're already operational.
3694 * If we're the first vap and the parent is not up
3695 * then it will automatically be brought up as a
3696 * side-effect of bringing ourself up.
3697 */
3698 if (vap->iv_state == IEEE80211_S_INIT) {
3699 if (ic->ic_nrunning == 0)
3700 wait = 1;
3701 printf ("Should call start_locked ...\n");
3702 wait = 0;
3703 // ieee80211_start_locked(vap);
3704 }
3705 #if __FreeBSD__
3706 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
3707 #elif __NetBSD__
3708 } else if (ifp->if_flags & IFF_RUNNING) {
3709 #endif
3710 /*
3711 * Stop ourself. If we are the last vap to be
3712 * marked down the parent will also be taken down.
3713 */
3714 if (ic->ic_nrunning == 1)
3715 wait = 1;
3716 ieee80211_stop_locked(vap);
3717 }
3718 IEEE80211_UNLOCK(ic);
3719 /* Wait for parent ioctl handler if it was queued */
3720 if (wait) {
3721 ieee80211_waitfor_parent(ic);
3722
3723 /*
3724 * Check if the MAC address was changed
3725 * via SIOCSIFLLADDR ioctl.
3726 */
3727 if_addr_rlock(ifp);
3728 if ((ifp->if_flags & IFF_UP) == 0 &&
3729 !IEEE80211_ADDR_EQ(vap->iv_myaddr, IF_LLADDR(ifp))) {
3730 IEEE80211_ADDR_COPY(vap->iv_myaddr,
3731 IF_LLADDR(ifp));
3732 printf ("vap->iv_myaddr changed in ioctl to %s\n",
3733 ether_sprintf(vap->iv_myaddr));
3734 }
3735
3736 if_addr_runlock(ifp);
3737 }
3738 break;
3739 case SIOCADDMULTI:
3740 case SIOCDELMULTI:
3741 ieee80211_runtask(ic, &ic->ic_mcast_task);
3742 break;
3743 #ifdef OSIOCSIFMEDIA
3744 case OSIOCSIFMEDIA:
3745 #endif
3746 case SIOCSIFMEDIA:
3747 case SIOCGIFMEDIA:
3748 ifr = (struct ifreq *)data;
3749 error = ifmedia_ioctl(ifp, ifr, &vap->iv_media, cmd);
3750 break;
3751 case SIOCG80211:
3752 error = ieee80211_ioctl_get80211(vap, cmd,
3753 (struct ieee80211req *) data);
3754 break;
3755 case SIOCS80211:
3756 error = priv_check(curthread, PRIV_NET80211_MANAGE);
3757 if (error == 0)
3758 error = ieee80211_ioctl_set80211(vap, cmd,
3759 (struct ieee80211req *) data);
3760 break;
3761 #ifdef SIOCG80211ZSTATS
3762 case SIOCG80211ZSTATS:
3763 #endif
3764 case SIOCG80211STATS:
3765 ifr = (struct ifreq *)data;
3766 #if __FreeBSD__
3767 copyout(&vap->iv_stats, ifr_data_get_ptr(ifr),
3768 sizeof (vap->iv_stats));
3769 #elif__NetBSD__
3770 copyout(&vap->iv_stats, ifr->ifr_buf,
3771 sizeof (vap->iv_stats) <= ifr->ifr_buflen
3772 ? sizeof (vap->iv_stats) : ifr->ifr_buflen);
3773 #endif
3774 break;
3775 case SIOCSIFMTU:
3776 ifr = (struct ifreq *)data;
3777 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
3778 ifr->ifr_mtu <= IEEE80211_MTU_MAX))
3779 error = EINVAL;
3780 else
3781 ifp->if_mtu = ifr->ifr_mtu;
3782 break;
3783 case SIOCSIFADDR:
3784 /*
3785 * XXX Handle this directly so we can suppress if_init calls.
3786 * XXX This should be done in ether_ioctl but for the moment
3787 * XXX there are too many other parts of the system that
3788 * XXX set IFF_UP and so suppress if_init being called when
3789 * XXX it should be.
3790 */
3791 ifa = (struct ifaddr *) data;
3792 switch (ifa->ifa_addr->sa_family) {
3793 #ifdef INET
3794 case AF_INET:
3795 if ((ifp->if_flags & IFF_UP) == 0) {
3796 ifp->if_flags |= IFF_UP;
3797 #if __FreeBSD__
3798 ifp->if_init(ifp->if_softc);
3799 #elif __NetBSD__
3800 ifp->if_init(ifp);
3801 #endif
3802 }
3803 arp_ifinit(ifp, ifa);
3804 break;
3805 #endif
3806 default:
3807 if ((ifp->if_flags & IFF_UP) == 0) {
3808 ifp->if_flags |= IFF_UP;
3809 #if __FreeBSD__
3810 ifp->if_init(ifp->if_softc);
3811 #elif __NetBSD__
3812 ifp->if_init(ifp);
3813 #endif
3814 }
3815 break;
3816 }
3817 break;
3818 #if __NetBSD__
3819 case SIOCS80211NWID:
3820 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0)
3821 break;
3822 if (nwid.i_len > IEEE80211_NWID_LEN) {
3823 error = EINVAL;
3824 break;
3825 }
3826 memset(vap->iv_des_ssid, 0, IEEE80211_NWID_LEN);
3827 vap->iv_des_ssid[0].len = nwid.i_len;
3828 memcpy(vap->iv_des_ssid[0].ssid, nwid.i_nwid, nwid.i_len);
3829 error = ENETRESET;
3830 break;
3831 case SIOCG80211NWID:
3832 memset(&nwid, 0, sizeof(nwid));
3833 switch (vap->iv_state) {
3834 case IEEE80211_S_INIT:
3835 case IEEE80211_S_SCAN:
3836 nwid.i_len = vap->iv_des_ssid[0].len;
3837 memcpy(nwid.i_nwid, vap->iv_des_ssid[0].ssid,
3838 nwid.i_len);
3839 break;
3840 default:
3841 nwid.i_len = vap->iv_bss->ni_esslen;
3842 memcpy(nwid.i_nwid, vap->iv_bss->ni_essid, nwid.i_len);
3843 break;
3844 }
3845 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
3846 break;
3847 case SIOCS80211NWKEY:
3848 case SIOCG80211NWKEY:
3849 printf ("NetBSD NWKEY ioctl\n"); // NNN
3850 error = ENOTTY;
3851 break;
3852 case SIOCS80211POWER:
3853 power = (struct ieee80211_power *)data;
3854 ic->ic_lintval = power->i_maxsleep;
3855 if (power->i_enabled != 0) {
3856 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
3857 error = EINVAL;
3858 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
3859 ic->ic_flags |= IEEE80211_F_PMGTON;
3860 error = ENETRESET;
3861 }
3862 } else {
3863 if (ic->ic_flags & IEEE80211_F_PMGTON) {
3864 ic->ic_flags &= ~IEEE80211_F_PMGTON;
3865 error = ENETRESET;
3866 }
3867 }
3868 break;
3869 case SIOCG80211POWER:
3870 power = (struct ieee80211_power *)data;
3871 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;
3872 power->i_maxsleep = ic->ic_lintval;
3873 break;
3874 case SIOCS80211BSSID:
3875 bssid = (struct ieee80211_bssid *)data;
3876 IEEE80211_ADDR_COPY(vap->iv_des_bssid, bssid->i_bssid);
3877 if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zerobssid))
3878 vap->iv_flags &= ~IEEE80211_F_DESBSSID;
3879 else
3880 vap->iv_flags |= IEEE80211_F_DESBSSID;
3881 error = ENETRESET;
3882 break;
3883 case SIOCG80211BSSID:
3884 bssid = (struct ieee80211_bssid *)data;
3885 switch (vap->iv_state) {
3886 case IEEE80211_S_RUN:
3887 case IEEE80211_S_SLEEP:
3888 IEEE80211_ADDR_COPY(bssid->i_bssid,
3889 vap->iv_opmode == IEEE80211_M_WDS ?
3890 vap->iv_bss->ni_macaddr : vap->iv_bss->ni_bssid);
3891 break;
3892 case IEEE80211_S_INIT:
3893 case IEEE80211_S_SCAN:
3894 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
3895 IEEE80211_ADDR_COPY(bssid->i_bssid,
3896 vap->iv_myaddr);
3897 else if (vap->iv_flags & IEEE80211_F_DESBSSID)
3898 IEEE80211_ADDR_COPY(bssid->i_bssid,
3899 vap->iv_des_bssid);
3900 else
3901 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
3902
3903 break;
3904 default:
3905 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
3906 }
3907 break;
3908 case SIOCS80211CHANNEL:
3909 /* Use deprecated ieee80211_ioctl_setchannel code. NNN? */
3910 chanreq = (struct ieee80211chanreq *)data;
3911 ireq.i_val = chanreq->i_channel;
3912 error = ieee80211_ioctl_setchannel(vap, &ireq);
3913 break;
3914 case SIOCG80211CHANNEL:
3915 chanreq = (struct ieee80211chanreq *)data;
3916 switch (vap->iv_state) {
3917 case IEEE80211_S_INIT:
3918 case IEEE80211_S_SCAN:
3919 if (vap->iv_opmode == IEEE80211_M_STA)
3920 chan = vap->iv_des_chan;
3921 else
3922 chan = ic->ic_bsschan; // NNN ibss chan?
3923 break;
3924 default:
3925 chan = ic->ic_curchan;
3926 break;
3927 }
3928 chanreq->i_channel = ieee80211_chan2ieee(ic, chan);
3929 break;
3930 #endif
3931 default:
3932 /*
3933 * Pass unknown ioctls first to the driver, and if it
3934 * returns ENOTTY, then to the generic Ethernet handler.
3935 */
3936 if (ic->ic_ioctl != NULL &&
3937 (error = ic->ic_ioctl(ic, cmd, data)) != ENOTTY)
3938 break;
3939 error = ether_ioctl(ifp, cmd, data);
3940 if (error == ENOTTY) {
3941 printf ("ieee80211_ioctl: cmd is 0x%lx. ('%c', %ld)\n",
3942 cmd, (char) ((cmd>>8) & 0xff), cmd & 0xff );
3943 printf ("Unknown 802.11 IOCTL.\n"); /* NNN */
3944 }
3945 break;
3946 }
3947 return (error);
3948 }
3949