1 /*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "opt_compat.h"
31
32 /*
33 * IEEE 802.11 ioctl support (FreeBSD-specific)
34 */
35
36 #include "opt_inet.h"
37 #include "opt_ipx.h"
38
39 #include <sys/endian.h>
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/priv.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/systm.h>
46
47 #include <net/if.h>
48 #include <net/if_dl.h>
49 #include <net/if_media.h>
50 #include <net/ethernet.h>
51
52 #ifdef INET
53 #include <netinet/in.h>
54 #include <netinet/if_ether.h>
55 #endif
56
57 #ifdef IPX
58 #include <netipx/ipx.h>
59 #include <netipx/ipx_if.h>
60 #endif
61
62 #include <net80211/ieee80211_var.h>
63 #include <net80211/ieee80211_ioctl.h>
64
65 #define IS_UP(_ic) \
66 (((_ic)->ic_ifp->if_flags & IFF_UP) && \
67 ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING))
68 #define IS_UP_AUTO(_ic) \
69 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
70 #define RESCAN 1
71
72 static struct ieee80211_channel *findchannel(struct ieee80211com *,
73 int ieee, int mode);
74
75 static int
76 cap2cipher(int flag)
77 {
78 switch (flag) {
79 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP;
80 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB;
81 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM;
82 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP;
83 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP;
84 }
85 return -1;
86 }
87
88 static int
89 ieee80211_ioctl_getkey(struct ieee80211com *ic, struct ieee80211req *ireq)
90 {
91 struct ieee80211_node *ni;
92 struct ieee80211req_key ik;
93 struct ieee80211_key *wk;
94 const struct ieee80211_cipher *cip;
95 u_int kid;
96 int error;
97
98 if (ireq->i_len != sizeof(ik))
99 return EINVAL;
100 error = copyin(ireq->i_data, &ik, sizeof(ik));
101 if (error)
102 return error;
103 kid = ik.ik_keyix;
104 if (kid == IEEE80211_KEYIX_NONE) {
105 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
106 if (ni == NULL)
107 return EINVAL; /* XXX */
108 wk = &ni->ni_ucastkey;
109 } else {
110 if (kid >= IEEE80211_WEP_NKID)
111 return EINVAL;
112 wk = &ic->ic_nw_keys[kid];
113 IEEE80211_ADDR_COPY(&ik.ik_macaddr, ic->ic_bss->ni_macaddr);
114 ni = NULL;
115 }
116 cip = wk->wk_cipher;
117 ik.ik_type = cip->ic_cipher;
118 ik.ik_keylen = wk->wk_keylen;
119 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
120 if (wk->wk_keyix == ic->ic_def_txkey)
121 ik.ik_flags |= IEEE80211_KEY_DEFAULT;
122 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
123 /* NB: only root can read key data */
124 ik.ik_keyrsc = wk->wk_keyrsc;
125 ik.ik_keytsc = wk->wk_keytsc;
126 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
127 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
128 memcpy(ik.ik_keydata+wk->wk_keylen,
129 wk->wk_key + IEEE80211_KEYBUF_SIZE,
130 IEEE80211_MICBUF_SIZE);
131 ik.ik_keylen += IEEE80211_MICBUF_SIZE;
132 }
133 } else {
134 ik.ik_keyrsc = 0;
135 ik.ik_keytsc = 0;
136 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
137 }
138 if (ni != NULL)
139 ieee80211_free_node(ni);
140 return copyout(&ik, ireq->i_data, sizeof(ik));
141 }
142
143 static int
144 ieee80211_ioctl_getchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
145 {
146
147 if (sizeof(ic->ic_chan_active) < ireq->i_len)
148 ireq->i_len = sizeof(ic->ic_chan_active);
149 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
150 }
151
152 static int
153 ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq)
154 {
155 int space;
156
157 space = __offsetof(struct ieee80211req_chaninfo,
158 ic_chans[ic->ic_nchans]);
159 if (space > ireq->i_len)
160 space = ireq->i_len;
161 /* XXX assumes compatible layout */
162 return copyout(&ic->ic_nchans, ireq->i_data, space);
163 }
164
165 static int
166 ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq, int req)
167 {
168 struct ieee80211_node *ni;
169 struct ieee80211req_wpaie2 wpaie;
170 int error;
171
172 if (ireq->i_len < IEEE80211_ADDR_LEN)
173 return EINVAL;
174 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN);
175 if (error != 0)
176 return error;
177 ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr);
178 if (ni == NULL)
179 return ENOENT; /* XXX */
180 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
181 if (ni->ni_wpa_ie != NULL) {
182 int ielen = ni->ni_wpa_ie[1] + 2;
183 if (ielen > sizeof(wpaie.wpa_ie))
184 ielen = sizeof(wpaie.wpa_ie);
185 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen);
186 }
187 if (req == IEEE80211_IOC_WPAIE2) {
188 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie));
189 if (ni->ni_rsn_ie != NULL) {
190 int ielen = ni->ni_rsn_ie[1] + 2;
191 if (ielen > sizeof(wpaie.rsn_ie))
192 ielen = sizeof(wpaie.rsn_ie);
193 memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen);
194 }
195 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2))
196 ireq->i_len = sizeof(struct ieee80211req_wpaie2);
197 } else {
198 /* compatibility op, may overwrite wpa ie */
199 /* XXX check ic_flags? */
200 if (ni->ni_rsn_ie != NULL) {
201 int ielen = ni->ni_rsn_ie[1] + 2;
202 if (ielen > sizeof(wpaie.wpa_ie))
203 ielen = sizeof(wpaie.wpa_ie);
204 memcpy(wpaie.wpa_ie, ni->ni_rsn_ie, ielen);
205 }
206 if (ireq->i_len > sizeof(struct ieee80211req_wpaie))
207 ireq->i_len = sizeof(struct ieee80211req_wpaie);
208 }
209 ieee80211_free_node(ni);
210 return copyout(&wpaie, ireq->i_data, ireq->i_len);
211 }
212
213 static int
214 ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
215 {
216 struct ieee80211_node *ni;
217 uint8_t macaddr[IEEE80211_ADDR_LEN];
218 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats);
219 int error;
220
221 if (ireq->i_len < off)
222 return EINVAL;
223 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
224 if (error != 0)
225 return error;
226 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
227 if (ni == NULL)
228 return EINVAL;
229 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats))
230 ireq->i_len = sizeof(struct ieee80211req_sta_stats);
231 /* NB: copy out only the statistics */
232 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off,
233 ireq->i_len - off);
234 ieee80211_free_node(ni);
235 return error;
236 }
237
238 static __inline uint8_t *
239 copyie(uint8_t *cp, const uint8_t *ie)
240 {
241 if (ie != NULL) {
242 memcpy(cp, ie, 2+ie[1]);
243 cp += 2+ie[1];
244 }
245 return cp;
246 }
247
248 #ifdef COMPAT_FREEBSD6
249 #define IEEE80211_IOC_SCAN_RESULTS_OLD 24
250
251 struct scan_result_old {
252 uint16_t isr_len; /* length (mult of 4) */
253 uint16_t isr_freq; /* MHz */
254 uint16_t isr_flags; /* channel flags */
255 uint8_t isr_noise;
256 uint8_t isr_rssi;
257 uint8_t isr_intval; /* beacon interval */
258 uint8_t isr_capinfo; /* capabilities */
259 uint8_t isr_erp; /* ERP element */
260 uint8_t isr_bssid[IEEE80211_ADDR_LEN];
261 uint8_t isr_nrates;
262 uint8_t isr_rates[IEEE80211_RATE_MAXSIZE];
263 uint8_t isr_ssid_len; /* SSID length */
264 uint8_t isr_ie_len; /* IE length */
265 uint8_t isr_pad[5];
266 /* variable length SSID followed by IE data */
267 };
268
269 struct oscanreq {
270 struct scan_result_old *sr;
271 size_t space;
272 };
273
274 static size_t
275 old_scan_space(const struct ieee80211_scan_entry *se, int *ielen)
276 {
277 size_t len;
278
279 *ielen = 0;
280 if (se->se_wpa_ie != NULL)
281 *ielen += 2+se->se_wpa_ie[1];
282 if (se->se_wme_ie != NULL)
283 *ielen += 2+se->se_wme_ie[1];
284 /*
285 * NB: ie's can be no more than 255 bytes and the max 802.11
286 * packet is <3Kbytes so we are sure this doesn't overflow
287 * 16-bits; if this is a concern we can drop the ie's.
288 */
289 len = sizeof(struct scan_result_old) + se->se_ssid[1] + *ielen;
290 return roundup(len, sizeof(uint32_t));
291 }
292
293 static void
294 old_get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
295 {
296 struct oscanreq *req = arg;
297 int ielen;
298
299 req->space += old_scan_space(se, &ielen);
300 }
301
302 static void
303 old_get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
304 {
305 struct oscanreq *req = arg;
306 struct scan_result_old *sr;
307 int ielen, len, nr, nxr;
308 uint8_t *cp;
309
310 len = old_scan_space(se, &ielen);
311 if (len > req->space)
312 return;
313
314 sr = req->sr;
315 memset(sr, 0, sizeof(*sr));
316 sr->isr_ssid_len = se->se_ssid[1];
317 /* NB: beware of overflow, isr_ie_len is 8 bits */
318 sr->isr_ie_len = (ielen > 255 ? 0 : ielen);
319 sr->isr_len = len;
320 sr->isr_freq = se->se_chan->ic_freq;
321 sr->isr_flags = se->se_chan->ic_flags;
322 sr->isr_rssi = se->se_rssi;
323 sr->isr_noise = se->se_noise;
324 sr->isr_intval = se->se_intval;
325 sr->isr_capinfo = se->se_capinfo;
326 sr->isr_erp = se->se_erp;
327 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
328 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
329 memcpy(sr->isr_rates, se->se_rates+2, nr);
330 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
331 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
332 sr->isr_nrates = nr + nxr;
333
334 cp = (uint8_t *)(sr+1);
335 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
336 cp += sr->isr_ssid_len;
337 if (sr->isr_ie_len) {
338 cp = copyie(cp, se->se_wpa_ie);
339 cp = copyie(cp, se->se_wme_ie);
340 }
341
342 req->space -= len;
343 req->sr = (struct scan_result_old *)(((uint8_t *)sr) + len);
344 }
345
346 static int
347 old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
348 {
349 struct oscanreq req;
350 int error;
351
352 if (ireq->i_len < sizeof(struct scan_result_old))
353 return EFAULT;
354
355 error = 0;
356 req.space = 0;
357 ieee80211_scan_iterate(ic, old_get_scan_space, &req);
358 if (req.space > ireq->i_len)
359 req.space = ireq->i_len;
360 if (req.space > 0) {
361 size_t space;
362 void *p;
363
364 space = req.space;
365 /* XXX M_WAITOK after driver lock released */
366 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
367 if (p == NULL)
368 return ENOMEM;
369 req.sr = p;
370 ieee80211_scan_iterate(ic, old_get_scan_result, &req);
371 ireq->i_len = space - req.space;
372 error = copyout(p, ireq->i_data, ireq->i_len);
373 FREE(p, M_TEMP);
374 } else
375 ireq->i_len = 0;
376
377 return error;
378 }
379 #endif /* COMPAT_FREEBSD6 */
380
381 struct scanreq {
382 struct ieee80211req_scan_result *sr;
383 size_t space;
384 };
385
386 static size_t
387 scan_space(const struct ieee80211_scan_entry *se, int *ielen)
388 {
389 size_t len;
390
391 *ielen = 0;
392 if (se->se_wpa_ie != NULL)
393 *ielen += 2+se->se_wpa_ie[1];
394 if (se->se_rsn_ie != NULL)
395 *ielen += 2+se->se_rsn_ie[1];
396 if (se->se_wme_ie != NULL)
397 *ielen += 2+se->se_wme_ie[1];
398 if (se->se_ath_ie != NULL)
399 *ielen += 2+se->se_ath_ie[1];
400 /*
401 * NB: ie's can be no more than 255 bytes and the max 802.11
402 * packet is <3Kbytes so we are sure this doesn't overflow
403 * 16-bits; if this is a concern we can drop the ie's.
404 */
405 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen;
406 return roundup(len, sizeof(uint32_t));
407 }
408
409 static void
410 get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
411 {
412 struct scanreq *req = arg;
413 int ielen;
414
415 req->space += scan_space(se, &ielen);
416 }
417
418 static void
419 get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
420 {
421 struct scanreq *req = arg;
422 struct ieee80211req_scan_result *sr;
423 int ielen, len, nr, nxr;
424 uint8_t *cp;
425
426 len = scan_space(se, &ielen);
427 if (len > req->space)
428 return;
429
430 sr = req->sr;
431 KASSERT(len <= 65535 && ielen <= 65535,
432 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen));
433 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result);
434 sr->isr_ie_len = ielen;
435 sr->isr_len = len;
436 sr->isr_freq = se->se_chan->ic_freq;
437 sr->isr_flags = se->se_chan->ic_flags;
438 sr->isr_rssi = se->se_rssi;
439 sr->isr_noise = se->se_noise;
440 sr->isr_intval = se->se_intval;
441 sr->isr_capinfo = se->se_capinfo;
442 sr->isr_erp = se->se_erp;
443 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
444 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
445 memcpy(sr->isr_rates, se->se_rates+2, nr);
446 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
447 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
448 sr->isr_nrates = nr + nxr;
449
450 sr->isr_ssid_len = se->se_ssid[1];
451 cp = ((uint8_t *)sr) + sr->isr_ie_off;
452 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
453
454 if (ielen) {
455 cp += sr->isr_ssid_len;
456 cp = copyie(cp, se->se_wpa_ie);
457 cp = copyie(cp, se->se_rsn_ie);
458 cp = copyie(cp, se->se_wme_ie);
459 cp = copyie(cp, se->se_ath_ie);
460 cp = copyie(cp, se->se_htcap_ie);
461 }
462
463 req->space -= len;
464 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
465 }
466
467 static int
468 ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
469 {
470 struct scanreq req;
471 int error;
472
473 if (ireq->i_len < sizeof(struct ieee80211req_scan_result))
474 return EFAULT;
475
476 error = 0;
477 req.space = 0;
478 ieee80211_scan_iterate(ic, get_scan_space, &req);
479 if (req.space > ireq->i_len)
480 req.space = ireq->i_len;
481 if (req.space > 0) {
482 size_t space;
483 void *p;
484
485 space = req.space;
486 /* XXX M_WAITOK after driver lock released */
487 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
488 if (p == NULL)
489 return ENOMEM;
490 req.sr = p;
491 ieee80211_scan_iterate(ic, get_scan_result, &req);
492 ireq->i_len = space - req.space;
493 error = copyout(p, ireq->i_data, ireq->i_len);
494 FREE(p, M_TEMP);
495 } else
496 ireq->i_len = 0;
497
498 return error;
499 }
500
501 struct stainforeq {
502 struct ieee80211com *ic;
503 struct ieee80211req_sta_info *si;
504 size_t space;
505 };
506
507 static size_t
508 sta_space(const struct ieee80211_node *ni, size_t *ielen)
509 {
510 *ielen = 0;
511 if (ni->ni_wpa_ie != NULL)
512 *ielen += 2+ni->ni_wpa_ie[1];
513 if (ni->ni_rsn_ie != NULL)
514 *ielen += 2+ni->ni_rsn_ie[1];
515 if (ni->ni_wme_ie != NULL)
516 *ielen += 2+ni->ni_wme_ie[1];
517 if (ni->ni_ath_ie != NULL)
518 *ielen += 2+ni->ni_ath_ie[1];
519 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
520 sizeof(uint32_t));
521 }
522
523 static void
524 get_sta_space(void *arg, struct ieee80211_node *ni)
525 {
526 struct stainforeq *req = arg;
527 struct ieee80211com *ic = ni->ni_ic;
528 size_t ielen;
529
530 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
531 ni->ni_associd == 0) /* only associated stations */
532 return;
533 req->space += sta_space(ni, &ielen);
534 }
535
536 static void
537 get_sta_info(void *arg, struct ieee80211_node *ni)
538 {
539 struct stainforeq *req = arg;
540 struct ieee80211com *ic = ni->ni_ic;
541 struct ieee80211req_sta_info *si;
542 size_t ielen, len;
543 uint8_t *cp;
544
545 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
546 ni->ni_associd == 0) /* only associated stations */
547 return;
548 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
549 return;
550 len = sta_space(ni, &ielen);
551 if (len > req->space)
552 return;
553 si = req->si;
554 si->isi_len = len;
555 si->isi_ie_off = sizeof(struct ieee80211req_sta_info);
556 si->isi_ie_len = ielen;
557 si->isi_freq = ni->ni_chan->ic_freq;
558 si->isi_flags = ni->ni_chan->ic_flags;
559 si->isi_state = ni->ni_flags;
560 si->isi_authmode = ni->ni_authmode;
561 ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise);
562 si->isi_noise = 0; /* XXX */
563 si->isi_capinfo = ni->ni_capinfo;
564 si->isi_erp = ni->ni_erp;
565 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr);
566 si->isi_nrates = ni->ni_rates.rs_nrates;
567 if (si->isi_nrates > 15)
568 si->isi_nrates = 15;
569 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
570 si->isi_txrate = ni->ni_txrate;
571 si->isi_ie_len = ielen;
572 si->isi_associd = ni->ni_associd;
573 si->isi_txpower = ni->ni_txpower;
574 si->isi_vlan = ni->ni_vlan;
575 if (ni->ni_flags & IEEE80211_NODE_QOS) {
576 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs));
577 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs));
578 } else {
579 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID];
580 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID];
581 }
582 /* NB: leave all cases in case we relax ni_associd == 0 check */
583 if (ieee80211_node_is_authorized(ni))
584 si->isi_inact = ic->ic_inact_run;
585 else if (ni->ni_associd != 0)
586 si->isi_inact = ic->ic_inact_auth;
587 else
588 si->isi_inact = ic->ic_inact_init;
589 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
590
591 if (ielen) {
592 cp = ((uint8_t *)si) + si->isi_ie_off;
593 cp = copyie(cp, ni->ni_wpa_ie);
594 cp = copyie(cp, ni->ni_rsn_ie);
595 cp = copyie(cp, ni->ni_wme_ie);
596 cp = copyie(cp, ni->ni_ath_ie);
597 }
598
599 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len);
600 req->space -= len;
601 }
602
603 static int
604 getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq,
605 struct ieee80211_node *ni, int off)
606 {
607 struct stainforeq req;
608 size_t space;
609 void *p;
610 int error;
611
612 error = 0;
613 req.space = 0;
614 if (ni == NULL)
615 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req);
616 else
617 get_sta_space(&req, ni);
618 if (req.space > ireq->i_len)
619 req.space = ireq->i_len;
620 if (req.space > 0) {
621 space = req.space;
622 /* XXX M_WAITOK after driver lock released */
623 MALLOC(p, void *, space, M_TEMP, M_NOWAIT);
624 if (p == NULL) {
625 error = ENOMEM;
626 goto bad;
627 }
628 req.si = p;
629 if (ni == NULL)
630 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
631 else
632 get_sta_info(&req, ni);
633 ireq->i_len = space - req.space;
634 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
635 FREE(p, M_TEMP);
636 } else
637 ireq->i_len = 0;
638 bad:
639 if (ni != NULL)
640 ieee80211_free_node(ni);
641 return error;
642 }
643
644 static int
645 ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
646 {
647 uint8_t macaddr[IEEE80211_ADDR_LEN];
648 const int off = __offsetof(struct ieee80211req_sta_req, info);
649 struct ieee80211_node *ni;
650 int error;
651
652 if (ireq->i_len < sizeof(struct ieee80211req_sta_req))
653 return EFAULT;
654 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
655 if (error != 0)
656 return error;
657 if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) {
658 ni = NULL;
659 } else {
660 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
661 if (ni == NULL)
662 return EINVAL;
663 }
664 return getstainfo_common(ic, ireq, ni, off);
665 }
666
667 #ifdef COMPAT_FREEBSD6
668 #define IEEE80211_IOC_STA_INFO_OLD 45
669
670 static int
671 old_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
672 {
673 if (ireq->i_len < sizeof(struct ieee80211req_sta_info))
674 return EFAULT;
675 return getstainfo_common(ic, ireq, NULL, 0);
676 }
677 #endif /* COMPAT_FREEBSD6 */
678
679 static int
680 ieee80211_ioctl_getstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq)
681 {
682 struct ieee80211_node *ni;
683 struct ieee80211req_sta_txpow txpow;
684 int error;
685
686 if (ireq->i_len != sizeof(txpow))
687 return EINVAL;
688 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
689 if (error != 0)
690 return error;
691 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr);
692 if (ni == NULL)
693 return EINVAL; /* XXX */
694 txpow.it_txpow = ni->ni_txpower;
695 error = copyout(&txpow, ireq->i_data, sizeof(txpow));
696 ieee80211_free_node(ni);
697 return error;
698 }
699
700 static int
701 ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
702 {
703 struct ieee80211_wme_state *wme = &ic->ic_wme;
704 struct wmeParams *wmep;
705 int ac;
706
707 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
708 return EINVAL;
709
710 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
711 if (ac >= WME_NUM_AC)
712 ac = WME_AC_BE;
713 if (ireq->i_len & IEEE80211_WMEPARAM_BSS)
714 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
715 else
716 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
717 switch (ireq->i_type) {
718 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
719 ireq->i_val = wmep->wmep_logcwmin;
720 break;
721 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
722 ireq->i_val = wmep->wmep_logcwmax;
723 break;
724 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
725 ireq->i_val = wmep->wmep_aifsn;
726 break;
727 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
728 ireq->i_val = wmep->wmep_txopLimit;
729 break;
730 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
731 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
732 ireq->i_val = wmep->wmep_acm;
733 break;
734 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
735 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
736 ireq->i_val = !wmep->wmep_noackPolicy;
737 break;
738 }
739 return 0;
740 }
741
742 static int
743 ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
744 {
745 const struct ieee80211_aclator *acl = ic->ic_acl;
746
747 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq));
748 }
749
750 /*
751 * Return the current ``state'' of an Atheros capbility.
752 * If associated in station mode report the negotiated
753 * setting. Otherwise report the current setting.
754 */
755 static int
756 getathcap(struct ieee80211com *ic, int cap)
757 {
758 if (ic->ic_opmode == IEEE80211_M_STA && ic->ic_state == IEEE80211_S_RUN)
759 return IEEE80211_ATH_CAP(ic, ic->ic_bss, cap) != 0;
760 else
761 return (ic->ic_flags & cap) != 0;
762 }
763
764 static int
765 ieee80211_ioctl_getcurchan(struct ieee80211com *ic, struct ieee80211req *ireq)
766 {
767 if (ireq->i_len != sizeof(struct ieee80211_channel))
768 return EINVAL;
769 return copyout(ic->ic_curchan, ireq->i_data, sizeof(*ic->ic_curchan));
770 }
771
772 /*
773 * When building the kernel with -O2 on the i386 architecture, gcc
774 * seems to want to inline this function into ieee80211_ioctl()
775 * (which is the only routine that calls it). When this happens,
776 * ieee80211_ioctl() ends up consuming an additional 2K of stack
777 * space. (Exactly why it needs so much is unclear.) The problem
778 * is that it's possible for ieee80211_ioctl() to invoke other
779 * routines (including driver init functions) which could then find
780 * themselves perilously close to exhausting the stack.
781 *
782 * To avoid this, we deliberately prevent gcc from inlining this
783 * routine. Another way to avoid this is to use less agressive
784 * optimization when compiling this file (i.e. -O instead of -O2)
785 * but special-casing the compilation of this one module in the
786 * build system would be awkward.
787 */
788 #ifdef __GNUC__
789 __attribute__ ((noinline))
790 #endif
791 static int
792 ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
793 {
794 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
795 int error = 0;
796 u_int kid, len, m;
797 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
798 char tmpssid[IEEE80211_NWID_LEN];
799
800 switch (ireq->i_type) {
801 case IEEE80211_IOC_SSID:
802 switch (ic->ic_state) {
803 case IEEE80211_S_INIT:
804 case IEEE80211_S_SCAN:
805 ireq->i_len = ic->ic_des_ssid[0].len;
806 memcpy(tmpssid, ic->ic_des_ssid[0].ssid, ireq->i_len);
807 break;
808 default:
809 ireq->i_len = ic->ic_bss->ni_esslen;
810 memcpy(tmpssid, ic->ic_bss->ni_essid,
811 ireq->i_len);
812 break;
813 }
814 error = copyout(tmpssid, ireq->i_data, ireq->i_len);
815 break;
816 case IEEE80211_IOC_NUMSSIDS:
817 ireq->i_val = 1;
818 break;
819 case IEEE80211_IOC_WEP:
820 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0)
821 ireq->i_val = IEEE80211_WEP_OFF;
822 else if (ic->ic_flags & IEEE80211_F_DROPUNENC)
823 ireq->i_val = IEEE80211_WEP_ON;
824 else
825 ireq->i_val = IEEE80211_WEP_MIXED;
826 break;
827 case IEEE80211_IOC_WEPKEY:
828 kid = (u_int) ireq->i_val;
829 if (kid >= IEEE80211_WEP_NKID)
830 return EINVAL;
831 len = (u_int) ic->ic_nw_keys[kid].wk_keylen;
832 /* NB: only root can read WEP keys */
833 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
834 bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len);
835 } else {
836 bzero(tmpkey, len);
837 }
838 ireq->i_len = len;
839 error = copyout(tmpkey, ireq->i_data, len);
840 break;
841 case IEEE80211_IOC_NUMWEPKEYS:
842 ireq->i_val = IEEE80211_WEP_NKID;
843 break;
844 case IEEE80211_IOC_WEPTXKEY:
845 ireq->i_val = ic->ic_def_txkey;
846 break;
847 case IEEE80211_IOC_AUTHMODE:
848 if (ic->ic_flags & IEEE80211_F_WPA)
849 ireq->i_val = IEEE80211_AUTH_WPA;
850 else
851 ireq->i_val = ic->ic_bss->ni_authmode;
852 break;
853 case IEEE80211_IOC_CHANNEL:
854 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan);
855 break;
856 case IEEE80211_IOC_POWERSAVE:
857 if (ic->ic_flags & IEEE80211_F_PMGTON)
858 ireq->i_val = IEEE80211_POWERSAVE_ON;
859 else
860 ireq->i_val = IEEE80211_POWERSAVE_OFF;
861 break;
862 case IEEE80211_IOC_POWERSAVESLEEP:
863 ireq->i_val = ic->ic_lintval;
864 break;
865 case IEEE80211_IOC_RTSTHRESHOLD:
866 ireq->i_val = ic->ic_rtsthreshold;
867 break;
868 case IEEE80211_IOC_PROTMODE:
869 ireq->i_val = ic->ic_protmode;
870 break;
871 case IEEE80211_IOC_TXPOWER:
872 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
873 return EINVAL;
874 ireq->i_val = ic->ic_txpowlimit;
875 break;
876 case IEEE80211_IOC_MCASTCIPHER:
877 ireq->i_val = rsn->rsn_mcastcipher;
878 break;
879 case IEEE80211_IOC_MCASTKEYLEN:
880 ireq->i_val = rsn->rsn_mcastkeylen;
881 break;
882 case IEEE80211_IOC_UCASTCIPHERS:
883 ireq->i_val = 0;
884 for (m = 0x1; m != 0; m <<= 1)
885 if (rsn->rsn_ucastcipherset & m)
886 ireq->i_val |= 1<<cap2cipher(m);
887 break;
888 case IEEE80211_IOC_UCASTCIPHER:
889 ireq->i_val = rsn->rsn_ucastcipher;
890 break;
891 case IEEE80211_IOC_UCASTKEYLEN:
892 ireq->i_val = rsn->rsn_ucastkeylen;
893 break;
894 case IEEE80211_IOC_KEYMGTALGS:
895 ireq->i_val = rsn->rsn_keymgmtset;
896 break;
897 case IEEE80211_IOC_RSNCAPS:
898 ireq->i_val = rsn->rsn_caps;
899 break;
900 case IEEE80211_IOC_WPA:
901 switch (ic->ic_flags & IEEE80211_F_WPA) {
902 case IEEE80211_F_WPA1:
903 ireq->i_val = 1;
904 break;
905 case IEEE80211_F_WPA2:
906 ireq->i_val = 2;
907 break;
908 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2:
909 ireq->i_val = 3;
910 break;
911 default:
912 ireq->i_val = 0;
913 break;
914 }
915 break;
916 case IEEE80211_IOC_CHANLIST:
917 error = ieee80211_ioctl_getchanlist(ic, ireq);
918 break;
919 case IEEE80211_IOC_ROAMING:
920 ireq->i_val = ic->ic_roaming;
921 break;
922 case IEEE80211_IOC_PRIVACY:
923 ireq->i_val = (ic->ic_flags & IEEE80211_F_PRIVACY) != 0;
924 break;
925 case IEEE80211_IOC_DROPUNENCRYPTED:
926 ireq->i_val = (ic->ic_flags & IEEE80211_F_DROPUNENC) != 0;
927 break;
928 case IEEE80211_IOC_COUNTERMEASURES:
929 ireq->i_val = (ic->ic_flags & IEEE80211_F_COUNTERM) != 0;
930 break;
931 case IEEE80211_IOC_DRIVER_CAPS:
932 ireq->i_val = ic->ic_caps>>16;
933 ireq->i_len = ic->ic_caps&0xffff;
934 break;
935 case IEEE80211_IOC_WME:
936 ireq->i_val = (ic->ic_flags & IEEE80211_F_WME) != 0;
937 break;
938 case IEEE80211_IOC_HIDESSID:
939 ireq->i_val = (ic->ic_flags & IEEE80211_F_HIDESSID) != 0;
940 break;
941 case IEEE80211_IOC_APBRIDGE:
942 ireq->i_val = (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0;
943 break;
944 case IEEE80211_IOC_OPTIE:
945 if (ic->ic_opt_ie == NULL)
946 return EINVAL;
947 /* NB: truncate, caller can check length */
948 if (ireq->i_len > ic->ic_opt_ie_len)
949 ireq->i_len = ic->ic_opt_ie_len;
950 error = copyout(ic->ic_opt_ie, ireq->i_data, ireq->i_len);
951 break;
952 case IEEE80211_IOC_WPAKEY:
953 error = ieee80211_ioctl_getkey(ic, ireq);
954 break;
955 case IEEE80211_IOC_CHANINFO:
956 error = ieee80211_ioctl_getchaninfo(ic, ireq);
957 break;
958 case IEEE80211_IOC_BSSID:
959 if (ireq->i_len != IEEE80211_ADDR_LEN)
960 return EINVAL;
961 error = copyout(ic->ic_state == IEEE80211_S_RUN ?
962 ic->ic_bss->ni_bssid :
963 ic->ic_des_bssid,
964 ireq->i_data, ireq->i_len);
965 break;
966 case IEEE80211_IOC_WPAIE:
967 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
968 break;
969 case IEEE80211_IOC_WPAIE2:
970 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
971 break;
972 #ifdef COMPAT_FREEBSD6
973 case IEEE80211_IOC_SCAN_RESULTS_OLD:
974 error = old_getscanresults(ic, ireq);
975 break;
976 #endif
977 case IEEE80211_IOC_SCAN_RESULTS:
978 error = ieee80211_ioctl_getscanresults(ic, ireq);
979 break;
980 case IEEE80211_IOC_STA_STATS:
981 error = ieee80211_ioctl_getstastats(ic, ireq);
982 break;
983 case IEEE80211_IOC_TXPOWMAX:
984 ireq->i_val = ic->ic_bss->ni_txpower;
985 break;
986 case IEEE80211_IOC_STA_TXPOW:
987 error = ieee80211_ioctl_getstatxpow(ic, ireq);
988 break;
989 #ifdef COMPAT_FREEBSD6
990 case IEEE80211_IOC_STA_INFO_OLD:
991 error = old_getstainfo(ic, ireq);
992 break;
993 #endif
994 case IEEE80211_IOC_STA_INFO:
995 error = ieee80211_ioctl_getstainfo(ic, ireq);
996 break;
997 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
998 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
999 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1000 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1001 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1002 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
1003 error = ieee80211_ioctl_getwmeparam(ic, ireq);
1004 break;
1005 case IEEE80211_IOC_DTIM_PERIOD:
1006 ireq->i_val = ic->ic_dtim_period;
1007 break;
1008 case IEEE80211_IOC_BEACON_INTERVAL:
1009 /* NB: get from ic_bss for station mode */
1010 ireq->i_val = ic->ic_bss->ni_intval;
1011 break;
1012 case IEEE80211_IOC_PUREG:
1013 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0;
1014 break;
1015 case IEEE80211_IOC_FF:
1016 ireq->i_val = getathcap(ic, IEEE80211_F_FF);
1017 break;
1018 case IEEE80211_IOC_TURBOP:
1019 ireq->i_val = getathcap(ic, IEEE80211_F_TURBOP);
1020 break;
1021 case IEEE80211_IOC_BGSCAN:
1022 ireq->i_val = (ic->ic_flags & IEEE80211_F_BGSCAN) != 0;
1023 break;
1024 case IEEE80211_IOC_BGSCAN_IDLE:
1025 ireq->i_val = ic->ic_bgscanidle*hz/1000; /* ms */
1026 break;
1027 case IEEE80211_IOC_BGSCAN_INTERVAL:
1028 ireq->i_val = ic->ic_bgscanintvl/hz; /* seconds */
1029 break;
1030 case IEEE80211_IOC_SCANVALID:
1031 ireq->i_val = ic->ic_scanvalid/hz; /* seconds */
1032 break;
1033 case IEEE80211_IOC_ROAM_RSSI_11A:
1034 ireq->i_val = ic->ic_roam.rssi11a;
1035 break;
1036 case IEEE80211_IOC_ROAM_RSSI_11B:
1037 ireq->i_val = ic->ic_roam.rssi11bOnly;
1038 break;
1039 case IEEE80211_IOC_ROAM_RSSI_11G:
1040 ireq->i_val = ic->ic_roam.rssi11b;
1041 break;
1042 case IEEE80211_IOC_ROAM_RATE_11A:
1043 ireq->i_val = ic->ic_roam.rate11a;
1044 break;
1045 case IEEE80211_IOC_ROAM_RATE_11B:
1046 ireq->i_val = ic->ic_roam.rate11bOnly;
1047 break;
1048 case IEEE80211_IOC_ROAM_RATE_11G:
1049 ireq->i_val = ic->ic_roam.rate11b;
1050 break;
1051 case IEEE80211_IOC_MCAST_RATE:
1052 ireq->i_val = ic->ic_mcast_rate;
1053 break;
1054 case IEEE80211_IOC_FRAGTHRESHOLD:
1055 ireq->i_val = ic->ic_fragthreshold;
1056 break;
1057 case IEEE80211_IOC_MACCMD:
1058 error = ieee80211_ioctl_getmaccmd(ic, ireq);
1059 break;
1060 case IEEE80211_IOC_BURST:
1061 ireq->i_val = (ic->ic_flags & IEEE80211_F_BURST) != 0;
1062 break;
1063 case IEEE80211_IOC_BMISSTHRESHOLD:
1064 ireq->i_val = ic->ic_bmissthreshold;
1065 break;
1066 case IEEE80211_IOC_CURCHAN:
1067 error = ieee80211_ioctl_getcurchan(ic, ireq);
1068 break;
1069 case IEEE80211_IOC_SHORTGI:
1070 ireq->i_val = 0;
1071 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI20)
1072 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20;
1073 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI40)
1074 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40;
1075 break;
1076 case IEEE80211_IOC_AMPDU:
1077 ireq->i_val = 0;
1078 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX)
1079 ireq->i_val |= 1;
1080 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_RX)
1081 ireq->i_val |= 2;
1082 break;
1083 case IEEE80211_IOC_AMPDU_LIMIT:
1084 ireq->i_val = ic->ic_ampdu_limit; /* XXX truncation? */
1085 break;
1086 case IEEE80211_IOC_AMPDU_DENSITY:
1087 ireq->i_val = ic->ic_ampdu_density;
1088 break;
1089 case IEEE80211_IOC_AMSDU:
1090 ireq->i_val = 0;
1091 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_TX)
1092 ireq->i_val |= 1;
1093 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_RX)
1094 ireq->i_val |= 2;
1095 break;
1096 case IEEE80211_IOC_AMSDU_LIMIT:
1097 ireq->i_val = ic->ic_amsdu_limit; /* XXX truncation? */
1098 break;
1099 case IEEE80211_IOC_PUREN:
1100 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_PUREN) != 0;
1101 break;
1102 case IEEE80211_IOC_DOTH:
1103 ireq->i_val = (ic->ic_flags & IEEE80211_F_DOTH) != 0;
1104 break;
1105 case IEEE80211_IOC_HTCOMPAT:
1106 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0;
1107 break;
1108 case IEEE80211_IOC_INACTIVITY:
1109 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_INACT) != 0;
1110 break;
1111 case IEEE80211_IOC_HTPROTMODE:
1112 ireq->i_val = ic->ic_htprotmode;
1113 break;
1114 case IEEE80211_IOC_HTCONF:
1115 if (ic->ic_flags_ext & IEEE80211_FEXT_HT) {
1116 ireq->i_val = 1;
1117 if (ic->ic_flags_ext & IEEE80211_FEXT_USEHT40)
1118 ireq->i_val |= 2;
1119 } else
1120 ireq->i_val = 0;
1121 break;
1122 default:
1123 error = EINVAL;
1124 break;
1125 }
1126 return error;
1127 }
1128
1129 static int
1130 ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq)
1131 {
1132 int error;
1133 void *ie, *oie;
1134
1135 /*
1136 * NB: Doing this for ap operation could be useful (e.g. for
1137 * WPA and/or WME) except that it typically is worthless
1138 * without being able to intervene when processing
1139 * association response frames--so disallow it for now.
1140 */
1141 if (ic->ic_opmode != IEEE80211_M_STA)
1142 return EINVAL;
1143 if (ireq->i_len > IEEE80211_MAX_OPT_IE)
1144 return EINVAL;
1145 /* NB: data.length is validated by the wireless extensions code */
1146 /* XXX M_WAITOK after driver lock released */
1147 if (ireq->i_len > 0) {
1148 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT);
1149 if (ie == NULL)
1150 return ENOMEM;
1151 error = copyin(ireq->i_data, ie, ireq->i_len);
1152 if (error) {
1153 FREE(ie, M_DEVBUF);
1154 return error;
1155 }
1156 } else {
1157 ie = NULL;
1158 ireq->i_len = 0;
1159 }
1160 /* XXX sanity check data? */
1161 oie = ic->ic_opt_ie;
1162 ic->ic_opt_ie = ie;
1163 ic->ic_opt_ie_len = ireq->i_len;
1164 if (oie != NULL)
1165 FREE(oie, M_DEVBUF);
1166 return 0;
1167 }
1168
1169 static int
1170 ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1171 {
1172 struct ieee80211req_key ik;
1173 struct ieee80211_node *ni;
1174 struct ieee80211_key *wk;
1175 uint16_t kid;
1176 int error;
1177
1178 if (ireq->i_len != sizeof(ik))
1179 return EINVAL;
1180 error = copyin(ireq->i_data, &ik, sizeof(ik));
1181 if (error)
1182 return error;
1183 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1184 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1185 if (ik.ik_keylen > sizeof(ik.ik_keydata))
1186 return E2BIG;
1187 kid = ik.ik_keyix;
1188 if (kid == IEEE80211_KEYIX_NONE) {
1189 /* XXX unicast keys currently must be tx/rx */
1190 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
1191 return EINVAL;
1192 if (ic->ic_opmode == IEEE80211_M_STA) {
1193 ni = ieee80211_ref_node(ic->ic_bss);
1194 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) {
1195 ieee80211_free_node(ni);
1196 return EADDRNOTAVAIL;
1197 }
1198 } else {
1199 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
1200 if (ni == NULL)
1201 return ENOENT;
1202 }
1203 wk = &ni->ni_ucastkey;
1204 } else {
1205 if (kid >= IEEE80211_WEP_NKID)
1206 return EINVAL;
1207 wk = &ic->ic_nw_keys[kid];
1208 /*
1209 * Global slots start off w/o any assigned key index.
1210 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1211 */
1212 if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
1213 wk->wk_keyix = kid;
1214 ni = NULL;
1215 }
1216 error = 0;
1217 ieee80211_key_update_begin(ic);
1218 if (ieee80211_crypto_newkey(ic, ik.ik_type, ik.ik_flags, wk)) {
1219 wk->wk_keylen = ik.ik_keylen;
1220 /* NB: MIC presence is implied by cipher type */
1221 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
1222 wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
1223 wk->wk_keyrsc = ik.ik_keyrsc;
1224 wk->wk_keytsc = 0; /* new key, reset */
1225 memset(wk->wk_key, 0, sizeof(wk->wk_key));
1226 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
1227 if (!ieee80211_crypto_setkey(ic, wk,
1228 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr))
1229 error = EIO;
1230 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
1231 ic->ic_def_txkey = kid;
1232 } else
1233 error = ENXIO;
1234 ieee80211_key_update_end(ic);
1235 if (ni != NULL)
1236 ieee80211_free_node(ni);
1237 return error;
1238 }
1239
1240 static int
1241 ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1242 {
1243 struct ieee80211req_del_key dk;
1244 int kid, error;
1245
1246 if (ireq->i_len != sizeof(dk))
1247 return EINVAL;
1248 error = copyin(ireq->i_data, &dk, sizeof(dk));
1249 if (error)
1250 return error;
1251 kid = dk.idk_keyix;
1252 /* XXX uint8_t -> uint16_t */
1253 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1254 struct ieee80211_node *ni;
1255
1256 if (ic->ic_opmode == IEEE80211_M_STA) {
1257 ni = ieee80211_ref_node(ic->ic_bss);
1258 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1259 ieee80211_free_node(ni);
1260 return EADDRNOTAVAIL;
1261 }
1262 } else {
1263 ni = ieee80211_find_node(&ic->ic_sta, dk.idk_macaddr);
1264 if (ni == NULL)
1265 return ENOENT;
1266 }
1267 /* XXX error return */
1268 ieee80211_node_delucastkey(ni);
1269 ieee80211_free_node(ni);
1270 } else {
1271 if (kid >= IEEE80211_WEP_NKID)
1272 return EINVAL;
1273 /* XXX error return */
1274 ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]);
1275 }
1276 return 0;
1277 }
1278
1279 static void
1280 domlme(void *arg, struct ieee80211_node *ni)
1281 {
1282 struct ieee80211com *ic = ni->ni_ic;
1283 struct ieee80211req_mlme *mlme = arg;
1284
1285 if (ni->ni_associd != 0) {
1286 IEEE80211_SEND_MGMT(ic, ni,
1287 mlme->im_op == IEEE80211_MLME_DEAUTH ?
1288 IEEE80211_FC0_SUBTYPE_DEAUTH :
1289 IEEE80211_FC0_SUBTYPE_DISASSOC,
1290 mlme->im_reason);
1291 }
1292 ieee80211_node_leave(ic, ni);
1293 }
1294
1295 struct scanlookup {
1296 const uint8_t *mac;
1297 int esslen;
1298 const uint8_t *essid;
1299 const struct ieee80211_scan_entry *se;
1300 };
1301
1302 /*
1303 * Match mac address and any ssid.
1304 */
1305 static void
1306 mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1307 {
1308 struct scanlookup *look = arg;
1309
1310 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1311 return;
1312 if (look->esslen != 0) {
1313 if (se->se_ssid[1] != look->esslen)
1314 return;
1315 if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1316 return;
1317 }
1318 look->se = se;
1319 }
1320
1321 static int
1322 ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq)
1323 {
1324 struct ieee80211req_mlme mlme;
1325 struct ieee80211_node *ni;
1326 int error;
1327
1328 if (ireq->i_len != sizeof(mlme))
1329 return EINVAL;
1330 error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1331 if (error)
1332 return error;
1333 switch (mlme.im_op) {
1334 case IEEE80211_MLME_ASSOC:
1335 /* XXX ibss/ahdemo */
1336 if (ic->ic_opmode == IEEE80211_M_STA) {
1337 struct scanlookup lookup;
1338
1339 lookup.se = NULL;
1340 lookup.mac = mlme.im_macaddr;
1341 /* XXX use revised api w/ explicit ssid */
1342 lookup.esslen = ic->ic_des_ssid[0].len;
1343 lookup.essid = ic->ic_des_ssid[0].ssid;
1344 ieee80211_scan_iterate(ic, mlmelookup, &lookup);
1345 if (lookup.se != NULL &&
1346 ieee80211_sta_join(ic, lookup.se))
1347 return 0;
1348 }
1349 return EINVAL;
1350 case IEEE80211_MLME_DISASSOC:
1351 case IEEE80211_MLME_DEAUTH:
1352 switch (ic->ic_opmode) {
1353 case IEEE80211_M_STA:
1354 /* XXX not quite right */
1355 ieee80211_new_state(ic, IEEE80211_S_INIT,
1356 mlme.im_reason);
1357 break;
1358 case IEEE80211_M_HOSTAP:
1359 /* NB: the broadcast address means do 'em all */
1360 if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) {
1361 if ((ni = ieee80211_find_node(&ic->ic_sta,
1362 mlme.im_macaddr)) == NULL)
1363 return EINVAL;
1364 domlme(&mlme, ni);
1365 ieee80211_free_node(ni);
1366 } else {
1367 ieee80211_iterate_nodes(&ic->ic_sta,
1368 domlme, &mlme);
1369 }
1370 break;
1371 default:
1372 return EINVAL;
1373 }
1374 break;
1375 case IEEE80211_MLME_AUTHORIZE:
1376 case IEEE80211_MLME_UNAUTHORIZE:
1377 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1378 return EINVAL;
1379 ni = ieee80211_find_node(&ic->ic_sta, mlme.im_macaddr);
1380 if (ni == NULL)
1381 return EINVAL;
1382 if (mlme.im_op == IEEE80211_MLME_AUTHORIZE)
1383 ieee80211_node_authorize(ni);
1384 else
1385 ieee80211_node_unauthorize(ni);
1386 ieee80211_free_node(ni);
1387 break;
1388 default:
1389 return EINVAL;
1390 }
1391 return 0;
1392 }
1393
1394 static int
1395 ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq)
1396 {
1397 uint8_t mac[IEEE80211_ADDR_LEN];
1398 const struct ieee80211_aclator *acl = ic->ic_acl;
1399 int error;
1400
1401 if (ireq->i_len != sizeof(mac))
1402 return EINVAL;
1403 error = copyin(ireq->i_data, mac, ireq->i_len);
1404 if (error)
1405 return error;
1406 if (acl == NULL) {
1407 acl = ieee80211_aclator_get("mac");
1408 if (acl == NULL || !acl->iac_attach(ic))
1409 return EINVAL;
1410 ic->ic_acl = acl;
1411 }
1412 if (ireq->i_type == IEEE80211_IOC_ADDMAC)
1413 acl->iac_add(ic, mac);
1414 else
1415 acl->iac_remove(ic, mac);
1416 return 0;
1417 }
1418
1419 static int
1420 ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
1421 {
1422 const struct ieee80211_aclator *acl = ic->ic_acl;
1423
1424 switch (ireq->i_val) {
1425 case IEEE80211_MACCMD_POLICY_OPEN:
1426 case IEEE80211_MACCMD_POLICY_ALLOW:
1427 case IEEE80211_MACCMD_POLICY_DENY:
1428 if (acl == NULL) {
1429 acl = ieee80211_aclator_get("mac");
1430 if (acl == NULL || !acl->iac_attach(ic))
1431 return EINVAL;
1432 ic->ic_acl = acl;
1433 }
1434 acl->iac_setpolicy(ic, ireq->i_val);
1435 break;
1436 case IEEE80211_MACCMD_FLUSH:
1437 if (acl != NULL)
1438 acl->iac_flush(ic);
1439 /* NB: silently ignore when not in use */
1440 break;
1441 case IEEE80211_MACCMD_DETACH:
1442 if (acl != NULL) {
1443 ic->ic_acl = NULL;
1444 acl->iac_detach(ic);
1445 }
1446 break;
1447 default:
1448 if (acl == NULL)
1449 return EINVAL;
1450 else
1451 return acl->iac_setioctl(ic, ireq);
1452 }
1453 return 0;
1454 }
1455
1456 static int
1457 ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
1458 {
1459 struct ieee80211req_chanlist list;
1460 u_char chanlist[IEEE80211_CHAN_BYTES];
1461 int i, j, nchan, error;
1462
1463 if (ireq->i_len != sizeof(list))
1464 return EINVAL;
1465 error = copyin(ireq->i_data, &list, sizeof(list));
1466 if (error)
1467 return error;
1468 memset(chanlist, 0, sizeof(chanlist));
1469 /*
1470 * Since channel 0 is not available for DS, channel 1
1471 * is assigned to LSB on WaveLAN.
1472 */
1473 if (ic->ic_phytype == IEEE80211_T_DS)
1474 i = 1;
1475 else
1476 i = 0;
1477 nchan = 0;
1478 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
1479 /*
1480 * NB: silently discard unavailable channels so users
1481 * can specify 1-255 to get all available channels.
1482 */
1483 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) {
1484 setbit(chanlist, i);
1485 nchan++;
1486 }
1487 }
1488 if (nchan == 0)
1489 return EINVAL;
1490 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1491 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1492 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1493 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
1494 return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0;
1495 }
1496
1497 static int
1498 ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
1499 {
1500 struct ieee80211_node *ni;
1501 uint8_t macaddr[IEEE80211_ADDR_LEN];
1502 int error;
1503
1504 /*
1505 * NB: we could copyin ieee80211req_sta_stats so apps
1506 * could make selective changes but that's overkill;
1507 * just clear all stats for now.
1508 */
1509 if (ireq->i_len < IEEE80211_ADDR_LEN)
1510 return EINVAL;
1511 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1512 if (error != 0)
1513 return error;
1514 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
1515 if (ni == NULL)
1516 return EINVAL; /* XXX */
1517 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats));
1518 ieee80211_free_node(ni);
1519 return 0;
1520 }
1521
1522 static int
1523 ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq)
1524 {
1525 struct ieee80211_node *ni;
1526 struct ieee80211req_sta_txpow txpow;
1527 int error;
1528
1529 if (ireq->i_len != sizeof(txpow))
1530 return EINVAL;
1531 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
1532 if (error != 0)
1533 return error;
1534 ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr);
1535 if (ni == NULL)
1536 return EINVAL; /* XXX */
1537 ni->ni_txpower = txpow.it_txpow;
1538 ieee80211_free_node(ni);
1539 return error;
1540 }
1541
1542 static int
1543 ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
1544 {
1545 struct ieee80211_wme_state *wme = &ic->ic_wme;
1546 struct wmeParams *wmep, *chanp;
1547 int isbss, ac;
1548
1549 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
1550 return EINVAL;
1551
1552 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
1553 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
1554 if (ac >= WME_NUM_AC)
1555 ac = WME_AC_BE;
1556 if (isbss) {
1557 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac];
1558 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
1559 } else {
1560 chanp = &wme->wme_chanParams.cap_wmeParams[ac];
1561 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
1562 }
1563 switch (ireq->i_type) {
1564 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
1565 if (isbss) {
1566 wmep->wmep_logcwmin = ireq->i_val;
1567 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1568 chanp->wmep_logcwmin = ireq->i_val;
1569 } else {
1570 wmep->wmep_logcwmin = chanp->wmep_logcwmin =
1571 ireq->i_val;
1572 }
1573 break;
1574 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
1575 if (isbss) {
1576 wmep->wmep_logcwmax = ireq->i_val;
1577 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1578 chanp->wmep_logcwmax = ireq->i_val;
1579 } else {
1580 wmep->wmep_logcwmax = chanp->wmep_logcwmax =
1581 ireq->i_val;
1582 }
1583 break;
1584 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1585 if (isbss) {
1586 wmep->wmep_aifsn = ireq->i_val;
1587 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1588 chanp->wmep_aifsn = ireq->i_val;
1589 } else {
1590 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
1591 }
1592 break;
1593 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1594 if (isbss) {
1595 wmep->wmep_txopLimit = ireq->i_val;
1596 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1597 chanp->wmep_txopLimit = ireq->i_val;
1598 } else {
1599 wmep->wmep_txopLimit = chanp->wmep_txopLimit =
1600 ireq->i_val;
1601 }
1602 break;
1603 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1604 wmep->wmep_acm = ireq->i_val;
1605 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1606 chanp->wmep_acm = ireq->i_val;
1607 break;
1608 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
1609 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy =
1610 (ireq->i_val) == 0;
1611 break;
1612 }
1613 ieee80211_wme_updateparams(ic);
1614 return 0;
1615 }
1616
1617 static int
1618 cipher2cap(int cipher)
1619 {
1620 switch (cipher) {
1621 case IEEE80211_CIPHER_WEP: return IEEE80211_C_WEP;
1622 case IEEE80211_CIPHER_AES_OCB: return IEEE80211_C_AES;
1623 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM;
1624 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP;
1625 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP;
1626 }
1627 return 0;
1628 }
1629
1630 static int
1631 find11gchannel(struct ieee80211com *ic, int start, int freq)
1632 {
1633 const struct ieee80211_channel *c;
1634 int i;
1635
1636 for (i = start+1; i < ic->ic_nchans; i++) {
1637 c = &ic->ic_channels[i];
1638 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1639 return 1;
1640 }
1641 /* NB: should not be needed but in case things are mis-sorted */
1642 for (i = 0; i < start; i++) {
1643 c = &ic->ic_channels[i];
1644 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1645 return 1;
1646 }
1647 return 0;
1648 }
1649
1650 static struct ieee80211_channel *
1651 findchannel(struct ieee80211com *ic, int ieee, int mode)
1652 {
1653 static const u_int chanflags[IEEE80211_MODE_MAX] = {
1654 0, /* IEEE80211_MODE_AUTO */
1655 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
1656 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
1657 IEEE80211_CHAN_G, /* IEEE80211_MODE_11G */
1658 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
1659 IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */
1660 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */
1661 IEEE80211_CHAN_STURBO, /* IEEE80211_MODE_STURBO_A */
1662 /* NB: handled specially below */
1663 IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA */
1664 IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG */
1665 };
1666 u_int modeflags;
1667 int i;
1668
1669 KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode));
1670 modeflags = chanflags[mode];
1671 KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO,
1672 ("no chanflags for mode %u", mode));
1673 for (i = 0; i < ic->ic_nchans; i++) {
1674 struct ieee80211_channel *c = &ic->ic_channels[i];
1675
1676 if (c->ic_ieee != ieee)
1677 continue;
1678 if (mode == IEEE80211_MODE_AUTO) {
1679 /* ignore turbo channels for autoselect */
1680 if (IEEE80211_IS_CHAN_TURBO(c))
1681 continue;
1682 /*
1683 * XXX special-case 11b/g channels so we
1684 * always select the g channel if both
1685 * are present.
1686 * XXX prefer HT to non-HT?
1687 */
1688 if (!IEEE80211_IS_CHAN_B(c) ||
1689 !find11gchannel(ic, i, c->ic_freq))
1690 return c;
1691 } else {
1692 /* must check HT specially */
1693 if ((mode == IEEE80211_MODE_11NA ||
1694 mode == IEEE80211_MODE_11NG) &&
1695 !IEEE80211_IS_CHAN_HT(c))
1696 continue;
1697 if ((c->ic_flags & modeflags) == modeflags)
1698 return c;
1699 }
1700 }
1701 return NULL;
1702 }
1703
1704 /*
1705 * Check the specified against any desired mode (aka netband).
1706 * This is only used (presently) when operating in hostap mode
1707 * to enforce consistency.
1708 */
1709 static int
1710 check_mode_consistency(const struct ieee80211_channel *c, int mode)
1711 {
1712 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
1713
1714 switch (mode) {
1715 case IEEE80211_MODE_11B:
1716 return (IEEE80211_IS_CHAN_B(c));
1717 case IEEE80211_MODE_11G:
1718 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
1719 case IEEE80211_MODE_11A:
1720 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
1721 case IEEE80211_MODE_STURBO_A:
1722 return (IEEE80211_IS_CHAN_STURBO(c));
1723 case IEEE80211_MODE_11NA:
1724 return (IEEE80211_IS_CHAN_HTA(c));
1725 case IEEE80211_MODE_11NG:
1726 return (IEEE80211_IS_CHAN_HTG(c));
1727 }
1728 return 1;
1729
1730 }
1731
1732 /*
1733 * Common code to set the current channel. If the device
1734 * is up and running this may result in an immediate channel
1735 * change or a kick of the state machine.
1736 */
1737 static int
1738 setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
1739 {
1740 int error;
1741
1742 if (c != IEEE80211_CHAN_ANYC) {
1743 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1744 !check_mode_consistency(c, ic->ic_des_mode))
1745 return EINVAL;
1746 if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan)
1747 return 0; /* NB: nothing to do */
1748 }
1749 ic->ic_des_chan = c;
1750
1751 error = 0;
1752 if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
1753 ic->ic_opmode == IEEE80211_M_WDS) &&
1754 ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1755 /*
1756 * Monitor and wds modes can switch directly.
1757 */
1758 ic->ic_curchan = ic->ic_des_chan;
1759 if (ic->ic_state == IEEE80211_S_RUN)
1760 ic->ic_set_channel(ic);
1761 } else {
1762 /*
1763 * Need to go through the state machine in case we
1764 * need to reassociate or the like. The state machine
1765 * will pickup the desired channel and avoid scanning.
1766 */
1767 if (IS_UP_AUTO(ic))
1768 error = ieee80211_init(ic, RESCAN);
1769 else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1770 /*
1771 * When not up+running and a real channel has
1772 * been specified fix the current channel so
1773 * there is immediate feedback; e.g. via ifconfig.
1774 */
1775 ic->ic_curchan = ic->ic_des_chan;
1776 }
1777 }
1778 return error;
1779 }
1780
1781 /*
1782 * Old api for setting the current channel; this is
1783 * deprecated because channel numbers are ambiguous.
1784 */
1785 static int
1786 ieee80211_ioctl_setchannel(struct ieee80211com *ic,
1787 const struct ieee80211req *ireq)
1788 {
1789 struct ieee80211_channel *c;
1790
1791 /* XXX 0xffff overflows 16-bit signed */
1792 if (ireq->i_val == 0 ||
1793 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
1794 c = IEEE80211_CHAN_ANYC;
1795 } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
1796 return EINVAL;
1797 } else {
1798 struct ieee80211_channel *c2;
1799
1800 c = findchannel(ic, ireq->i_val, ic->ic_des_mode);
1801 if (c == NULL) {
1802 c = findchannel(ic, ireq->i_val,
1803 IEEE80211_MODE_AUTO);
1804 if (c == NULL)
1805 return EINVAL;
1806 }
1807 /*
1808 * Fine tune channel selection based on desired mode:
1809 * if 11b is requested, find the 11b version of any
1810 * 11g channel returned,
1811 * if static turbo, find the turbo version of any
1812 * 11a channel return,
1813 * if 11na is requested, find the ht version of any
1814 * 11a channel returned,
1815 * if 11ng is requested, find the ht version of any
1816 * 11g channel returned,
1817 * otherwise we should be ok with what we've got.
1818 */
1819 switch (ic->ic_des_mode) {
1820 case IEEE80211_MODE_11B:
1821 if (IEEE80211_IS_CHAN_ANYG(c)) {
1822 c2 = findchannel(ic, ireq->i_val,
1823 IEEE80211_MODE_11B);
1824 /* NB: should not happen, =>'s 11g w/o 11b */
1825 if (c2 != NULL)
1826 c = c2;
1827 }
1828 break;
1829 case IEEE80211_MODE_TURBO_A:
1830 if (IEEE80211_IS_CHAN_A(c)) {
1831 c2 = findchannel(ic, ireq->i_val,
1832 IEEE80211_MODE_TURBO_A);
1833 if (c2 != NULL)
1834 c = c2;
1835 }
1836 break;
1837 case IEEE80211_MODE_11NA:
1838 if (IEEE80211_IS_CHAN_A(c)) {
1839 c2 = findchannel(ic, ireq->i_val,
1840 IEEE80211_MODE_11NA);
1841 if (c2 != NULL)
1842 c = c2;
1843 }
1844 break;
1845 case IEEE80211_MODE_11NG:
1846 if (IEEE80211_IS_CHAN_ANYG(c)) {
1847 c2 = findchannel(ic, ireq->i_val,
1848 IEEE80211_MODE_11NG);
1849 if (c2 != NULL)
1850 c = c2;
1851 }
1852 break;
1853 default: /* NB: no static turboG */
1854 break;
1855 }
1856 }
1857 return setcurchan(ic, c);
1858 }
1859
1860 /*
1861 * New/current api for setting the current channel; a complete
1862 * channel description is provide so there is no ambiguity in
1863 * identifying the channel.
1864 */
1865 static int
1866 ieee80211_ioctl_setcurchan(struct ieee80211com *ic,
1867 const struct ieee80211req *ireq)
1868 {
1869 struct ieee80211_channel chan, *c;
1870 int error;
1871
1872 if (ireq->i_len != sizeof(chan))
1873 return EINVAL;
1874 error = copyin(ireq->i_data, &chan, sizeof(chan));
1875 if (error != 0)
1876 return error;
1877 /* XXX 0xffff overflows 16-bit signed */
1878 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
1879 c = IEEE80211_CHAN_ANYC;
1880 } else {
1881 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
1882 if (c == NULL)
1883 return EINVAL;
1884 }
1885 return setcurchan(ic, c);
1886 }
1887
1888 static int
1889 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
1890 {
1891 static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
1892 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
1893 int error;
1894 const struct ieee80211_authenticator *auth;
1895 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
1896 char tmpssid[IEEE80211_NWID_LEN];
1897 uint8_t tmpbssid[IEEE80211_ADDR_LEN];
1898 struct ieee80211_key *k;
1899 int j, caps;
1900 u_int kid;
1901
1902 error = 0;
1903 switch (ireq->i_type) {
1904 case IEEE80211_IOC_SSID:
1905 if (ireq->i_val != 0 ||
1906 ireq->i_len > IEEE80211_NWID_LEN)
1907 return EINVAL;
1908 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
1909 if (error)
1910 break;
1911 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
1912 ic->ic_des_ssid[0].len = ireq->i_len;
1913 memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len);
1914 ic->ic_des_nssid = (ireq->i_len > 0);
1915 if (IS_UP_AUTO(ic))
1916 error = ieee80211_init(ic, RESCAN);
1917 break;
1918 case IEEE80211_IOC_WEP:
1919 switch (ireq->i_val) {
1920 case IEEE80211_WEP_OFF:
1921 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
1922 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1923 break;
1924 case IEEE80211_WEP_ON:
1925 ic->ic_flags |= IEEE80211_F_PRIVACY;
1926 ic->ic_flags |= IEEE80211_F_DROPUNENC;
1927 break;
1928 case IEEE80211_WEP_MIXED:
1929 ic->ic_flags |= IEEE80211_F_PRIVACY;
1930 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1931 break;
1932 }
1933 if (IS_UP_AUTO(ic))
1934 error = ieee80211_init(ic, RESCAN);
1935 break;
1936 case IEEE80211_IOC_WEPKEY:
1937 kid = (u_int) ireq->i_val;
1938 if (kid >= IEEE80211_WEP_NKID)
1939 return EINVAL;
1940 k = &ic->ic_nw_keys[kid];
1941 if (ireq->i_len == 0) {
1942 /* zero-len =>'s delete any existing key */
1943 (void) ieee80211_crypto_delkey(ic, k);
1944 break;
1945 }
1946 if (ireq->i_len > sizeof(tmpkey))
1947 return EINVAL;
1948 memset(tmpkey, 0, sizeof(tmpkey));
1949 error = copyin(ireq->i_data, tmpkey, ireq->i_len);
1950 if (error)
1951 break;
1952 ieee80211_key_update_begin(ic);
1953 k->wk_keyix = kid; /* NB: force fixed key id */
1954 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP,
1955 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
1956 k->wk_keylen = ireq->i_len;
1957 memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
1958 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr))
1959 error = EINVAL;
1960 } else
1961 error = EINVAL;
1962 ieee80211_key_update_end(ic);
1963 break;
1964 case IEEE80211_IOC_WEPTXKEY:
1965 kid = (u_int) ireq->i_val;
1966 if (kid >= IEEE80211_WEP_NKID &&
1967 (uint16_t) kid != IEEE80211_KEYIX_NONE)
1968 return EINVAL;
1969 ic->ic_def_txkey = kid;
1970 break;
1971 case IEEE80211_IOC_AUTHMODE:
1972 switch (ireq->i_val) {
1973 case IEEE80211_AUTH_WPA:
1974 case IEEE80211_AUTH_8021X: /* 802.1x */
1975 case IEEE80211_AUTH_OPEN: /* open */
1976 case IEEE80211_AUTH_SHARED: /* shared-key */
1977 case IEEE80211_AUTH_AUTO: /* auto */
1978 auth = ieee80211_authenticator_get(ireq->i_val);
1979 if (auth == NULL)
1980 return EINVAL;
1981 break;
1982 default:
1983 return EINVAL;
1984 }
1985 switch (ireq->i_val) {
1986 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */
1987 ic->ic_flags |= IEEE80211_F_PRIVACY;
1988 ireq->i_val = IEEE80211_AUTH_8021X;
1989 break;
1990 case IEEE80211_AUTH_OPEN: /* open */
1991 ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
1992 break;
1993 case IEEE80211_AUTH_SHARED: /* shared-key */
1994 case IEEE80211_AUTH_8021X: /* 802.1x */
1995 ic->ic_flags &= ~IEEE80211_F_WPA;
1996 /* both require a key so mark the PRIVACY capability */
1997 ic->ic_flags |= IEEE80211_F_PRIVACY;
1998 break;
1999 case IEEE80211_AUTH_AUTO: /* auto */
2000 ic->ic_flags &= ~IEEE80211_F_WPA;
2001 /* XXX PRIVACY handling? */
2002 /* XXX what's the right way to do this? */
2003 break;
2004 }
2005 /* NB: authenticator attach/detach happens on state change */
2006 ic->ic_bss->ni_authmode = ireq->i_val;
2007 /* XXX mixed/mode/usage? */
2008 ic->ic_auth = auth;
2009 if (IS_UP_AUTO(ic))
2010 error = ieee80211_init(ic, RESCAN);
2011 break;
2012 case IEEE80211_IOC_CHANNEL:
2013 error = ieee80211_ioctl_setchannel(ic, ireq);
2014 break;
2015 case IEEE80211_IOC_POWERSAVE:
2016 switch (ireq->i_val) {
2017 case IEEE80211_POWERSAVE_OFF:
2018 if (ic->ic_flags & IEEE80211_F_PMGTON) {
2019 ic->ic_flags &= ~IEEE80211_F_PMGTON;
2020 error = ENETRESET;
2021 }
2022 break;
2023 case IEEE80211_POWERSAVE_ON:
2024 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
2025 error = EINVAL;
2026 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
2027 ic->ic_flags |= IEEE80211_F_PMGTON;
2028 error = ENETRESET;
2029 }
2030 break;
2031 default:
2032 error = EINVAL;
2033 break;
2034 }
2035 if (error == ENETRESET) {
2036 /*
2037 * Switching in+out of power save mode
2038 * should not require a state change.
2039 */
2040 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2041 }
2042 break;
2043 case IEEE80211_IOC_POWERSAVESLEEP:
2044 if (ireq->i_val < 0)
2045 return EINVAL;
2046 ic->ic_lintval = ireq->i_val;
2047 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2048 break;
2049 case IEEE80211_IOC_RTSTHRESHOLD:
2050 if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
2051 ireq->i_val <= IEEE80211_RTS_MAX))
2052 return EINVAL;
2053 ic->ic_rtsthreshold = ireq->i_val;
2054 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2055 break;
2056 case IEEE80211_IOC_PROTMODE:
2057 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2058 return EINVAL;
2059 ic->ic_protmode = ireq->i_val;
2060 /* NB: if not operating in 11g this can wait */
2061 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2062 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2063 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2064 break;
2065 case IEEE80211_IOC_TXPOWER:
2066 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2067 return EINVAL;
2068 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
2069 ireq->i_val <= IEEE80211_TXPOWER_MAX))
2070 return EINVAL;
2071 ic->ic_txpowlimit = ireq->i_val;
2072 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2073 break;
2074 case IEEE80211_IOC_ROAMING:
2075 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2076 ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2077 return EINVAL;
2078 ic->ic_roaming = ireq->i_val;
2079 /* XXXX reset? */
2080 break;
2081 case IEEE80211_IOC_PRIVACY:
2082 if (ireq->i_val) {
2083 /* XXX check for key state? */
2084 ic->ic_flags |= IEEE80211_F_PRIVACY;
2085 } else
2086 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
2087 break;
2088 case IEEE80211_IOC_DROPUNENCRYPTED:
2089 if (ireq->i_val)
2090 ic->ic_flags |= IEEE80211_F_DROPUNENC;
2091 else
2092 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2093 break;
2094 case IEEE80211_IOC_WPAKEY:
2095 error = ieee80211_ioctl_setkey(ic, ireq);
2096 break;
2097 case IEEE80211_IOC_DELKEY:
2098 error = ieee80211_ioctl_delkey(ic, ireq);
2099 break;
2100 case IEEE80211_IOC_MLME:
2101 error = ieee80211_ioctl_setmlme(ic, ireq);
2102 break;
2103 case IEEE80211_IOC_OPTIE:
2104 error = ieee80211_ioctl_setoptie(ic, ireq);
2105 break;
2106 case IEEE80211_IOC_COUNTERMEASURES:
2107 if (ireq->i_val) {
2108 if ((ic->ic_flags & IEEE80211_F_WPA) == 0)
2109 return EINVAL;
2110 ic->ic_flags |= IEEE80211_F_COUNTERM;
2111 } else
2112 ic->ic_flags &= ~IEEE80211_F_COUNTERM;
2113 break;
2114 case IEEE80211_IOC_WPA:
2115 if (ireq->i_val > 3)
2116 return EINVAL;
2117 /* XXX verify ciphers available */
2118 ic->ic_flags &= ~IEEE80211_F_WPA;
2119 switch (ireq->i_val) {
2120 case 1:
2121 ic->ic_flags |= IEEE80211_F_WPA1;
2122 break;
2123 case 2:
2124 ic->ic_flags |= IEEE80211_F_WPA2;
2125 break;
2126 case 3:
2127 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2128 break;
2129 }
2130 error = ENETRESET;
2131 break;
2132 case IEEE80211_IOC_WME:
2133 if (ireq->i_val) {
2134 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
2135 return EINVAL;
2136 ic->ic_flags |= IEEE80211_F_WME;
2137 } else
2138 ic->ic_flags &= ~IEEE80211_F_WME;
2139 if (IS_UP_AUTO(ic))
2140 error = ieee80211_init(ic, 0);
2141 break;
2142 case IEEE80211_IOC_HIDESSID:
2143 if (ireq->i_val)
2144 ic->ic_flags |= IEEE80211_F_HIDESSID;
2145 else
2146 ic->ic_flags &= ~IEEE80211_F_HIDESSID;
2147 error = ENETRESET;
2148 break;
2149 case IEEE80211_IOC_APBRIDGE:
2150 if (ireq->i_val == 0)
2151 ic->ic_flags |= IEEE80211_F_NOBRIDGE;
2152 else
2153 ic->ic_flags &= ~IEEE80211_F_NOBRIDGE;
2154 break;
2155 case IEEE80211_IOC_MCASTCIPHER:
2156 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 &&
2157 !ieee80211_crypto_available(ireq->i_val))
2158 return EINVAL;
2159 rsn->rsn_mcastcipher = ireq->i_val;
2160 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2161 break;
2162 case IEEE80211_IOC_MCASTKEYLEN:
2163 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2164 return EINVAL;
2165 /* XXX no way to verify driver capability */
2166 rsn->rsn_mcastkeylen = ireq->i_val;
2167 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2168 break;
2169 case IEEE80211_IOC_UCASTCIPHERS:
2170 /*
2171 * Convert user-specified cipher set to the set
2172 * we can support (via hardware or software).
2173 * NB: this logic intentionally ignores unknown and
2174 * unsupported ciphers so folks can specify 0xff or
2175 * similar and get all available ciphers.
2176 */
2177 caps = 0;
2178 for (j = 1; j < 32; j++) /* NB: skip WEP */
2179 if ((ireq->i_val & (1<<j)) &&
2180 ((ic->ic_caps & cipher2cap(j)) ||
2181 ieee80211_crypto_available(j)))
2182 caps |= 1<<j;
2183 if (caps == 0) /* nothing available */
2184 return EINVAL;
2185 /* XXX verify ciphers ok for unicast use? */
2186 /* XXX disallow if running as it'll have no effect */
2187 rsn->rsn_ucastcipherset = caps;
2188 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2189 break;
2190 case IEEE80211_IOC_UCASTCIPHER:
2191 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0)
2192 return EINVAL;
2193 rsn->rsn_ucastcipher = ireq->i_val;
2194 break;
2195 case IEEE80211_IOC_UCASTKEYLEN:
2196 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2197 return EINVAL;
2198 /* XXX no way to verify driver capability */
2199 rsn->rsn_ucastkeylen = ireq->i_val;
2200 break;
2201 case IEEE80211_IOC_DRIVER_CAPS:
2202 /* NB: for testing */
2203 ic->ic_caps = (((uint16_t) ireq->i_val) << 16) |
2204 ((uint16_t) ireq->i_len);
2205 break;
2206 case IEEE80211_IOC_KEYMGTALGS:
2207 /* XXX check */
2208 rsn->rsn_keymgmtset = ireq->i_val;
2209 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2210 break;
2211 case IEEE80211_IOC_RSNCAPS:
2212 /* XXX check */
2213 rsn->rsn_caps = ireq->i_val;
2214 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2215 break;
2216 case IEEE80211_IOC_BSSID:
2217 if (ireq->i_len != sizeof(tmpbssid))
2218 return EINVAL;
2219 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2220 if (error)
2221 break;
2222 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid);
2223 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid))
2224 ic->ic_flags &= ~IEEE80211_F_DESBSSID;
2225 else
2226 ic->ic_flags |= IEEE80211_F_DESBSSID;
2227 if (IS_UP_AUTO(ic))
2228 error = ieee80211_init(ic, RESCAN);
2229 break;
2230 case IEEE80211_IOC_CHANLIST:
2231 error = ieee80211_ioctl_setchanlist(ic, ireq);
2232 break;
2233 case IEEE80211_IOC_SCAN_REQ:
2234 if (!IS_UP(ic))
2235 return EINVAL;
2236 (void) ieee80211_start_scan(ic,
2237 IEEE80211_SCAN_ACTIVE |
2238 IEEE80211_SCAN_NOPICK |
2239 IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,
2240 /* XXX use ioctl params */
2241 ic->ic_des_nssid, ic->ic_des_ssid);
2242 break;
2243 case IEEE80211_IOC_ADDMAC:
2244 case IEEE80211_IOC_DELMAC:
2245 error = ieee80211_ioctl_macmac(ic, ireq);
2246 break;
2247 case IEEE80211_IOC_MACCMD:
2248 error = ieee80211_ioctl_setmaccmd(ic, ireq);
2249 break;
2250 case IEEE80211_IOC_STA_STATS:
2251 error = ieee80211_ioctl_setstastats(ic, ireq);
2252 break;
2253 case IEEE80211_IOC_STA_TXPOW:
2254 error = ieee80211_ioctl_setstatxpow(ic, ireq);
2255 break;
2256 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
2257 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
2258 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
2259 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
2260 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
2261 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
2262 error = ieee80211_ioctl_setwmeparam(ic, ireq);
2263 break;
2264 case IEEE80211_IOC_DTIM_PERIOD:
2265 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2266 ic->ic_opmode != IEEE80211_M_IBSS)
2267 return EINVAL;
2268 if (IEEE80211_DTIM_MIN <= ireq->i_val &&
2269 ireq->i_val <= IEEE80211_DTIM_MAX) {
2270 ic->ic_dtim_period = ireq->i_val;
2271 error = ENETRESET; /* requires restart */
2272 } else
2273 error = EINVAL;
2274 break;
2275 case IEEE80211_IOC_BEACON_INTERVAL:
2276 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2277 ic->ic_opmode != IEEE80211_M_IBSS)
2278 return EINVAL;
2279 if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
2280 ireq->i_val <= IEEE80211_BINTVAL_MAX) {
2281 ic->ic_bintval = ireq->i_val;
2282 error = ENETRESET; /* requires restart */
2283 } else
2284 error = EINVAL;
2285 break;
2286 case IEEE80211_IOC_PUREG:
2287 if (ireq->i_val)
2288 ic->ic_flags |= IEEE80211_F_PUREG;
2289 else
2290 ic->ic_flags &= ~IEEE80211_F_PUREG;
2291 /* NB: reset only if we're operating on an 11g channel */
2292 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2293 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2294 error = ENETRESET;
2295 break;
2296 case IEEE80211_IOC_FF:
2297 if (ireq->i_val) {
2298 if ((ic->ic_caps & IEEE80211_C_FF) == 0)
2299 return EINVAL;
2300 ic->ic_flags |= IEEE80211_F_FF;
2301 } else
2302 ic->ic_flags &= ~IEEE80211_F_FF;
2303 error = ENETRESET;
2304 break;
2305 case IEEE80211_IOC_TURBOP:
2306 if (ireq->i_val) {
2307 if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0)
2308 return EINVAL;
2309 ic->ic_flags |= IEEE80211_F_TURBOP;
2310 } else
2311 ic->ic_flags &= ~IEEE80211_F_TURBOP;
2312 error = ENETRESET;
2313 break;
2314 case IEEE80211_IOC_BGSCAN:
2315 if (ireq->i_val) {
2316 if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0)
2317 return EINVAL;
2318 ic->ic_flags |= IEEE80211_F_BGSCAN;
2319 } else
2320 ic->ic_flags &= ~IEEE80211_F_BGSCAN;
2321 break;
2322 case IEEE80211_IOC_BGSCAN_IDLE:
2323 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
2324 ic->ic_bgscanidle = ireq->i_val*hz/1000;
2325 else
2326 error = EINVAL;
2327 break;
2328 case IEEE80211_IOC_BGSCAN_INTERVAL:
2329 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
2330 ic->ic_bgscanintvl = ireq->i_val*hz;
2331 else
2332 error = EINVAL;
2333 break;
2334 case IEEE80211_IOC_SCANVALID:
2335 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
2336 ic->ic_scanvalid = ireq->i_val*hz;
2337 else
2338 error = EINVAL;
2339 break;
2340 case IEEE80211_IOC_ROAM_RSSI_11A:
2341 ic->ic_roam.rssi11a = ireq->i_val;
2342 break;
2343 case IEEE80211_IOC_ROAM_RSSI_11B:
2344 ic->ic_roam.rssi11bOnly = ireq->i_val;
2345 break;
2346 case IEEE80211_IOC_ROAM_RSSI_11G:
2347 ic->ic_roam.rssi11b = ireq->i_val;
2348 break;
2349 case IEEE80211_IOC_ROAM_RATE_11A:
2350 ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL;
2351 break;
2352 case IEEE80211_IOC_ROAM_RATE_11B:
2353 ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL;
2354 break;
2355 case IEEE80211_IOC_ROAM_RATE_11G:
2356 ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL;
2357 break;
2358 case IEEE80211_IOC_MCAST_RATE:
2359 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL;
2360 break;
2361 case IEEE80211_IOC_FRAGTHRESHOLD:
2362 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 &&
2363 ireq->i_val != IEEE80211_FRAG_MAX)
2364 return EINVAL;
2365 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
2366 ireq->i_val <= IEEE80211_FRAG_MAX))
2367 return EINVAL;
2368 ic->ic_fragthreshold = ireq->i_val;
2369 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2370 break;
2371 case IEEE80211_IOC_BURST:
2372 if (ireq->i_val) {
2373 if ((ic->ic_caps & IEEE80211_C_BURST) == 0)
2374 return EINVAL;
2375 ic->ic_flags |= IEEE80211_F_BURST;
2376 } else
2377 ic->ic_flags &= ~IEEE80211_F_BURST;
2378 error = ENETRESET; /* XXX maybe not for station? */
2379 break;
2380 case IEEE80211_IOC_BMISSTHRESHOLD:
2381 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2382 ireq->i_val <= IEEE80211_HWBMISS_MAX))
2383 return EINVAL;
2384 ic->ic_bmissthreshold = ireq->i_val;
2385 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2386 break;
2387 case IEEE80211_IOC_CURCHAN:
2388 error = ieee80211_ioctl_setcurchan(ic, ireq);
2389 break;
2390 case IEEE80211_IOC_SHORTGI:
2391 if (ireq->i_val) {
2392 #define IEEE80211_HTCAP_SHORTGI \
2393 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2394 if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
2395 return EINVAL;
2396 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
2397 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20;
2398 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
2399 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40;
2400 #undef IEEE80211_HTCAP_SHORTGI
2401 } else
2402 ic->ic_flags_ext &=
2403 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40);
2404 /* XXX kick state machine? */
2405 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2406 break;
2407 case IEEE80211_IOC_AMPDU:
2408 if (ireq->i_val) {
2409 if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0)
2410 return EINVAL;
2411 if (ireq->i_val & 1)
2412 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX;
2413 if (ireq->i_val & 2)
2414 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX;
2415 } else
2416 ic->ic_flags_ext &=
2417 ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX);
2418 /* NB: reset only if we're operating on an 11n channel */
2419 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2420 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2421 error = ENETRESET;
2422 break;
2423 case IEEE80211_IOC_AMPDU_LIMIT:
2424 /* XXX validate */
2425 ic->ic_ampdu_limit = ireq->i_val;
2426 break;
2427 case IEEE80211_IOC_AMPDU_DENSITY:
2428 /* XXX validate */
2429 ic->ic_ampdu_density = ireq->i_val;
2430 break;
2431 case IEEE80211_IOC_AMSDU:
2432 if (ireq->i_val) {
2433 if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0)
2434 return EINVAL;
2435 if (ireq->i_val & 1)
2436 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
2437 if (ireq->i_val & 2)
2438 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
2439 } else
2440 ic->ic_flags_ext &=
2441 ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX);
2442 /* NB: reset only if we're operating on an 11n channel */
2443 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2444 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2445 error = ENETRESET;
2446 break;
2447 case IEEE80211_IOC_AMSDU_LIMIT:
2448 /* XXX validate */
2449 ic->ic_amsdu_limit = ireq->i_val; /* XXX truncation? */
2450 break;
2451 case IEEE80211_IOC_PUREN:
2452 if (ireq->i_val) {
2453 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2454 return EINVAL;
2455 ic->ic_flags_ext |= IEEE80211_FEXT_PUREN;
2456 } else
2457 ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN;
2458 /* NB: reset only if we're operating on an 11n channel */
2459 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2460 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2461 error = ENETRESET;
2462 break;
2463 case IEEE80211_IOC_DOTH:
2464 if (ireq->i_val) {
2465 #if 0
2466 /* XXX no capability */
2467 if ((ic->ic_caps & IEEE80211_C_DOTH) == 0)
2468 return EINVAL;
2469 #endif
2470 ic->ic_flags |= IEEE80211_F_DOTH;
2471 } else
2472 ic->ic_flags &= ~IEEE80211_F_DOTH;
2473 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2474 break;
2475 case IEEE80211_IOC_HTCOMPAT:
2476 if (ireq->i_val) {
2477 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2478 return EINVAL;
2479 ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT;
2480 } else
2481 ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT;
2482 /* NB: reset only if we're operating on an 11n channel */
2483 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2484 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2485 error = ENETRESET;
2486 break;
2487 case IEEE80211_IOC_INACTIVITY:
2488 if (ireq->i_val)
2489 ic->ic_flags_ext |= IEEE80211_FEXT_INACT;
2490 else
2491 ic->ic_flags_ext &= ~IEEE80211_FEXT_INACT;
2492 break;
2493 case IEEE80211_IOC_HTPROTMODE:
2494 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2495 return EINVAL;
2496 ic->ic_htprotmode = ireq->i_val ?
2497 IEEE80211_PROT_RTSCTS : IEEE80211_PROT_NONE;
2498 /* NB: if not operating in 11n this can wait */
2499 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2500 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2501 error = ERESTART;
2502 break;
2503 case IEEE80211_IOC_HTCONF:
2504 if (ireq->i_val & 1)
2505 ic->ic_flags_ext |= IEEE80211_FEXT_HT;
2506 else
2507 ic->ic_flags_ext &= ~IEEE80211_FEXT_HT;
2508 if (ireq->i_val & 2)
2509 ic->ic_flags_ext |= IEEE80211_FEXT_USEHT40;
2510 else
2511 ic->ic_flags_ext &= ~IEEE80211_FEXT_USEHT40;
2512 error = ENETRESET;
2513 break;
2514 default:
2515 error = EINVAL;
2516 break;
2517 }
2518 if (error == ENETRESET)
2519 error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0;
2520 return error;
2521 }
2522
2523 int
2524 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data)
2525 {
2526 struct ifnet *ifp = ic->ic_ifp;
2527 int error = 0;
2528 struct ifreq *ifr;
2529 struct ifaddr *ifa; /* XXX */
2530
2531 switch (cmd) {
2532 case SIOCSIFMEDIA:
2533 case SIOCGIFMEDIA:
2534 error = ifmedia_ioctl(ifp, (struct ifreq *) data,
2535 &ic->ic_media, cmd);
2536 break;
2537 case SIOCG80211:
2538 error = ieee80211_ioctl_get80211(ic, cmd,
2539 (struct ieee80211req *) data);
2540 break;
2541 case SIOCS80211:
2542 error = priv_check(curthread, PRIV_NET80211_MANAGE);
2543 if (error == 0)
2544 error = ieee80211_ioctl_set80211(ic, cmd,
2545 (struct ieee80211req *) data);
2546 break;
2547 case SIOCG80211STATS:
2548 ifr = (struct ifreq *)data;
2549 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
2550 break;
2551 case SIOCSIFMTU:
2552 ifr = (struct ifreq *)data;
2553 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
2554 ifr->ifr_mtu <= IEEE80211_MTU_MAX))
2555 error = EINVAL;
2556 else
2557 ifp->if_mtu = ifr->ifr_mtu;
2558 break;
2559 case SIOCSIFADDR:
2560 /*
2561 * XXX Handle this directly so we can supress if_init calls.
2562 * XXX This should be done in ether_ioctl but for the moment
2563 * XXX there are too many other parts of the system that
2564 * XXX set IFF_UP and so supress if_init being called when
2565 * XXX it should be.
2566 */
2567 ifa = (struct ifaddr *) data;
2568 switch (ifa->ifa_addr->sa_family) {
2569 #ifdef INET
2570 case AF_INET:
2571 if ((ifp->if_flags & IFF_UP) == 0) {
2572 ifp->if_flags |= IFF_UP;
2573 ifp->if_init(ifp->if_softc);
2574 }
2575 arp_ifinit(ifp, ifa);
2576 break;
2577 #endif
2578 #ifdef IPX
2579 /*
2580 * XXX - This code is probably wrong,
2581 * but has been copied many times.
2582 */
2583 case AF_IPX: {
2584 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
2585
2586 if (ipx_nullhost(*ina))
2587 ina->x_host = *(union ipx_host *)
2588 IF_LLADDR(ifp);
2589 else
2590 bcopy((caddr_t) ina->x_host.c_host,
2591 (caddr_t) IF_LLADDR(ifp),
2592 ETHER_ADDR_LEN);
2593 /* fall thru... */
2594 }
2595 #endif
2596 default:
2597 if ((ifp->if_flags & IFF_UP) == 0) {
2598 ifp->if_flags |= IFF_UP;
2599 ifp->if_init(ifp->if_softc);
2600 }
2601 break;
2602 }
2603 break;
2604 default:
2605 error = ether_ioctl(ifp, cmd, data);
2606 break;
2607 }
2608 return error;
2609 }
Cache object: b65afb5c6be7139a7b10bff62d1efcc0
|