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