Deleted Added
full compact
ieee80211_ioctl.c (170360) ieee80211_ioctl.c (170530)
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 11 unchanged lines hidden (view full) ---

20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 11 unchanged lines hidden (view full) ---

20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 170360 2007-06-06 04:56:04Z sam $");
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 170530 2007-06-11 03:36:55Z sam $");
29
30#include "opt_compat.h"
31
32/*
33 * IEEE 802.11 ioctl support (FreeBSD-specific)
34 */
35
36#include "opt_inet.h"

--- 20 unchanged lines hidden (view full) ---

57#ifdef IPX
58#include <netipx/ipx.h>
59#include <netipx/ipx_if.h>
60#endif
61
62#include <net80211/ieee80211_var.h>
63#include <net80211/ieee80211_ioctl.h>
64
29
30#include "opt_compat.h"
31
32/*
33 * IEEE 802.11 ioctl support (FreeBSD-specific)
34 */
35
36#include "opt_inet.h"

--- 20 unchanged lines hidden (view full) ---

57#ifdef IPX
58#include <netipx/ipx.h>
59#include <netipx/ipx_if.h>
60#endif
61
62#include <net80211/ieee80211_var.h>
63#include <net80211/ieee80211_ioctl.h>
64
65#include <dev/wi/if_wavelan_ieee.h>
66
67#define IS_UP(_ic) \
68 (((_ic)->ic_ifp->if_flags & IFF_UP) && \
69 ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING))
70#define IS_UP_AUTO(_ic) \
71 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
65#define IS_UP(_ic) \
66 (((_ic)->ic_ifp->if_flags & IFF_UP) && \
67 ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING))
68#define IS_UP_AUTO(_ic) \
69 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
70#define RESCAN 1
72
71
73/*
74 * XXX
75 * Wireless LAN specific configuration interface, which is compatible
76 * with wicontrol(8).
77 */
72static struct ieee80211_channel *findchannel(struct ieee80211com *,
73 int ieee, int mode);
78
74
79struct wi_read_ap_args {
80 int i; /* result count */
81 struct wi_apinfo *ap; /* current entry in result buffer */
82 caddr_t max; /* result buffer bound */
83};
84
85static void
86wi_read_ap_result(void *arg, struct ieee80211_node *ni)
87{
88 struct ieee80211com *ic = ni->ni_ic;
89 struct wi_read_ap_args *sa = arg;
90 struct wi_apinfo *ap = sa->ap;
91 struct ieee80211_rateset *rs;
92 int j;
93
94 if ((caddr_t)(ap + 1) > sa->max)
95 return;
96 memset(ap, 0, sizeof(struct wi_apinfo));
97 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
98 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr);
99 ap->namelen = ic->ic_des_esslen;
100 if (ic->ic_des_esslen)
101 memcpy(ap->name, ic->ic_des_essid,
102 ic->ic_des_esslen);
103 } else {
104 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid);
105 ap->namelen = ni->ni_esslen;
106 if (ni->ni_esslen)
107 memcpy(ap->name, ni->ni_essid,
108 ni->ni_esslen);
109 }
110 ap->channel = ieee80211_chan2ieee(ic, ni->ni_chan);
111 ap->signal = ic->ic_node_getrssi(ni);
112 ap->capinfo = ni->ni_capinfo;
113 ap->interval = ni->ni_intval;
114 rs = &ni->ni_rates;
115 for (j = 0; j < rs->rs_nrates; j++) {
116 if (rs->rs_rates[j] & IEEE80211_RATE_BASIC) {
117 ap->rate = (rs->rs_rates[j] &
118 IEEE80211_RATE_VAL) * 5; /* XXX */
119 }
120 }
121 sa->i++;
122 sa->ap++;
123}
124
125struct wi_read_prism2_args {
126 int i; /* result count */
127 struct wi_scan_res *res;/* current entry in result buffer */
128 caddr_t max; /* result buffer bound */
129};
130
131static void
132wi_read_prism2_result(void *arg, struct ieee80211_node *ni)
133{
134 struct ieee80211com *ic = ni->ni_ic;
135 struct wi_read_prism2_args *sa = arg;
136 struct wi_scan_res *res = sa->res;
137
138 if ((caddr_t)(res + 1) > sa->max)
139 return;
140 res->wi_chan = ieee80211_chan2ieee(ic, ni->ni_chan);
141 res->wi_noise = 0;
142 res->wi_signal = ic->ic_node_getrssi(ni);
143 IEEE80211_ADDR_COPY(res->wi_bssid, ni->ni_bssid);
144 res->wi_interval = ni->ni_intval;
145 res->wi_capinfo = ni->ni_capinfo;
146 res->wi_ssid_len = ni->ni_esslen;
147 memcpy(res->wi_ssid, ni->ni_essid, IEEE80211_NWID_LEN);
148 /* NB: assumes wi_srates holds <= ni->ni_rates */
149 memcpy(res->wi_srates, ni->ni_rates.rs_rates,
150 sizeof(res->wi_srates));
151 if (ni->ni_rates.rs_nrates < 10)
152 res->wi_srates[ni->ni_rates.rs_nrates] = 0;
153 res->wi_rate = ni->ni_rates.rs_rates[ni->ni_txrate];
154 res->wi_rsvd = 0;
155
156 sa->i++;
157 sa->res++;
158}
159
160struct wi_read_sigcache_args {
161 int i; /* result count */
162 struct wi_sigcache *wsc;/* current entry in result buffer */
163 caddr_t max; /* result buffer bound */
164};
165
166static void
167wi_read_sigcache(void *arg, struct ieee80211_node *ni)
168{
169 struct ieee80211com *ic = ni->ni_ic;
170 struct wi_read_sigcache_args *sa = arg;
171 struct wi_sigcache *wsc = sa->wsc;
172
173 if ((caddr_t)(wsc + 1) > sa->max)
174 return;
175 memset(wsc, 0, sizeof(struct wi_sigcache));
176 IEEE80211_ADDR_COPY(wsc->macsrc, ni->ni_macaddr);
177 wsc->signal = ic->ic_node_getrssi(ni);
178
179 sa->wsc++;
180 sa->i++;
181}
182
183int
184ieee80211_cfgget(struct ieee80211com *ic, u_long cmd, caddr_t data)
185{
186 struct ifnet *ifp = ic->ic_ifp;
187 int i, j, error;
188 struct ifreq *ifr = (struct ifreq *)data;
189 struct wi_req wreq;
190 struct wi_ltv_keys *keys;
191
192 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
193 if (error)
194 return error;
195 wreq.wi_len = 0;
196 switch (wreq.wi_type) {
197 case WI_RID_SERIALNO:
198 /* nothing appropriate */
199 break;
200 case WI_RID_NODENAME:
201 strcpy((char *)&wreq.wi_val[1], hostname);
202 wreq.wi_val[0] = htole16(strlen(hostname));
203 wreq.wi_len = (1 + strlen(hostname) + 1) / 2;
204 break;
205 case WI_RID_CURRENT_SSID:
206 if (ic->ic_state != IEEE80211_S_RUN) {
207 wreq.wi_val[0] = 0;
208 wreq.wi_len = 1;
209 break;
210 }
211 wreq.wi_val[0] = htole16(ic->ic_bss->ni_esslen);
212 memcpy(&wreq.wi_val[1], ic->ic_bss->ni_essid,
213 ic->ic_bss->ni_esslen);
214 wreq.wi_len = (1 + ic->ic_bss->ni_esslen + 1) / 2;
215 break;
216 case WI_RID_OWN_SSID:
217 case WI_RID_DESIRED_SSID:
218 wreq.wi_val[0] = htole16(ic->ic_des_esslen);
219 memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen);
220 wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2;
221 break;
222 case WI_RID_CURRENT_BSSID:
223 if (ic->ic_state == IEEE80211_S_RUN)
224 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss->ni_bssid);
225 else
226 memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN);
227 wreq.wi_len = IEEE80211_ADDR_LEN / 2;
228 break;
229 case WI_RID_CHANNEL_LIST:
230 memset(wreq.wi_val, 0, sizeof(wreq.wi_val));
231 /*
232 * Since channel 0 is not available for DS, channel 1
233 * is assigned to LSB on WaveLAN.
234 */
235 if (ic->ic_phytype == IEEE80211_T_DS)
236 i = 1;
237 else
238 i = 0;
239 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++)
240 if (isset(ic->ic_chan_active, i)) {
241 setbit((u_int8_t *)wreq.wi_val, j);
242 wreq.wi_len = j / 16 + 1;
243 }
244 break;
245 case WI_RID_OWN_CHNL:
246 wreq.wi_val[0] = htole16(
247 ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
248 wreq.wi_len = 1;
249 break;
250 case WI_RID_CURRENT_CHAN:
251 wreq.wi_val[0] = htole16(
252 ieee80211_chan2ieee(ic, ic->ic_curchan));
253 wreq.wi_len = 1;
254 break;
255 case WI_RID_COMMS_QUALITY:
256 wreq.wi_val[0] = 0; /* quality */
257 wreq.wi_val[1] = htole16(ic->ic_node_getrssi(ic->ic_bss));
258 wreq.wi_val[2] = 0; /* noise */
259 wreq.wi_len = 3;
260 break;
261 case WI_RID_PROMISC:
262 wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0);
263 wreq.wi_len = 1;
264 break;
265 case WI_RID_PORTTYPE:
266 wreq.wi_val[0] = htole16(ic->ic_opmode);
267 wreq.wi_len = 1;
268 break;
269 case WI_RID_MAC_NODE:
270 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr);
271 wreq.wi_len = IEEE80211_ADDR_LEN / 2;
272 break;
273 case WI_RID_TX_RATE:
274 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
275 wreq.wi_val[0] = 0; /* auto */
276 else
277 wreq.wi_val[0] = htole16(
278 (ic->ic_sup_rates[ic->ic_curmode].rs_rates[ic->ic_fixed_rate] &
279 IEEE80211_RATE_VAL) / 2);
280 wreq.wi_len = 1;
281 break;
282 case WI_RID_CUR_TX_RATE:
283 wreq.wi_val[0] = htole16(
284 (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] &
285 IEEE80211_RATE_VAL) / 2);
286 wreq.wi_len = 1;
287 break;
288 case WI_RID_RTS_THRESH:
289 wreq.wi_val[0] = htole16(ic->ic_rtsthreshold);
290 wreq.wi_len = 1;
291 break;
292 case WI_RID_CREATE_IBSS:
293 wreq.wi_val[0] =
294 htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0);
295 wreq.wi_len = 1;
296 break;
297 case WI_RID_MICROWAVE_OVEN:
298 wreq.wi_val[0] = 0; /* no ... not supported */
299 wreq.wi_len = 1;
300 break;
301 case WI_RID_ROAMING_MODE:
302 wreq.wi_val[0] = htole16(ic->ic_roaming); /* XXX map */
303 wreq.wi_len = 1;
304 break;
305 case WI_RID_SYSTEM_SCALE:
306 wreq.wi_val[0] = htole16(1); /* low density ... not supp */
307 wreq.wi_len = 1;
308 break;
309 case WI_RID_PM_ENABLED:
310 wreq.wi_val[0] =
311 htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
312 wreq.wi_len = 1;
313 break;
314 case WI_RID_MAX_SLEEP:
315 wreq.wi_val[0] = htole16(ic->ic_lintval);
316 wreq.wi_len = 1;
317 break;
318 case WI_RID_CUR_BEACON_INT:
319 wreq.wi_val[0] = htole16(ic->ic_bss->ni_intval);
320 wreq.wi_len = 1;
321 break;
322 case WI_RID_WEP_AVAIL:
323 wreq.wi_val[0] = htole16(1); /* always available */
324 wreq.wi_len = 1;
325 break;
326 case WI_RID_CNFAUTHMODE:
327 wreq.wi_val[0] = htole16(1); /* TODO: open system only */
328 wreq.wi_len = 1;
329 break;
330 case WI_RID_ENCRYPTION:
331 wreq.wi_val[0] =
332 htole16((ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0);
333 wreq.wi_len = 1;
334 break;
335 case WI_RID_TX_CRYPT_KEY:
336 wreq.wi_val[0] = htole16(ic->ic_def_txkey);
337 wreq.wi_len = 1;
338 break;
339 case WI_RID_DEFLT_CRYPT_KEYS:
340 keys = (struct wi_ltv_keys *)&wreq;
341 /* do not show keys to non-root user */
342 error = priv_check(curthread, PRIV_NET80211_GETKEY);
343 if (error) {
344 memset(keys, 0, sizeof(*keys));
345 error = 0;
346 break;
347 }
348 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
349 keys->wi_keys[i].wi_keylen =
350 htole16(ic->ic_nw_keys[i].wk_keylen);
351 memcpy(keys->wi_keys[i].wi_keydat,
352 ic->ic_nw_keys[i].wk_key,
353 ic->ic_nw_keys[i].wk_keylen);
354 }
355 wreq.wi_len = sizeof(*keys) / 2;
356 break;
357 case WI_RID_MAX_DATALEN:
358 wreq.wi_val[0] = htole16(ic->ic_fragthreshold);
359 wreq.wi_len = 1;
360 break;
361 case WI_RID_IFACE_STATS:
362 /* XXX: should be implemented in lower drivers */
363 break;
364 case WI_RID_READ_APS:
365 /*
366 * Don't return results until active scan completes.
367 */
368 if ((ic->ic_flags & (IEEE80211_F_SCAN|IEEE80211_F_ASCAN)) == 0) {
369 struct wi_read_ap_args args;
370
371 args.i = 0;
372 args.ap = (void *)((char *)wreq.wi_val + sizeof(i));
373 args.max = (void *)(&wreq + 1);
374 ieee80211_iterate_nodes(&ic->ic_scan,
375 wi_read_ap_result, &args);
376 memcpy(wreq.wi_val, &args.i, sizeof(args.i));
377 wreq.wi_len = (sizeof(int) +
378 sizeof(struct wi_apinfo) * args.i) / 2;
379 } else
380 error = EINPROGRESS;
381 break;
382 case WI_RID_PRISM2:
383 /* NB: we lie so WI_RID_SCAN_RES can include rates */
384 wreq.wi_val[0] = 1;
385 wreq.wi_len = sizeof(u_int16_t) / 2;
386 break;
387 case WI_RID_SCAN_RES: /* compatibility interface */
388 if ((ic->ic_flags & (IEEE80211_F_SCAN|IEEE80211_F_ASCAN)) == 0) {
389 struct wi_read_prism2_args args;
390 struct wi_scan_p2_hdr *p2;
391
392 /* NB: use Prism2 format so we can include rate info */
393 p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
394 args.i = 0;
395 args.res = (void *)&p2[1];
396 args.max = (void *)(&wreq + 1);
397 ieee80211_iterate_nodes(&ic->ic_scan,
398 wi_read_prism2_result, &args);
399 p2->wi_rsvd = 0;
400 p2->wi_reason = args.i;
401 wreq.wi_len = (sizeof(*p2) +
402 sizeof(struct wi_scan_res) * args.i) / 2;
403 } else
404 error = EINPROGRESS;
405 break;
406 case WI_RID_READ_CACHE: {
407 struct wi_read_sigcache_args args;
408 args.i = 0;
409 args.wsc = (struct wi_sigcache *) wreq.wi_val;
410 args.max = (void *)(&wreq + 1);
411 ieee80211_iterate_nodes(&ic->ic_scan, wi_read_sigcache, &args);
412 wreq.wi_len = sizeof(struct wi_sigcache) * args.i / 2;
413 break;
414 }
415 default:
416 error = EINVAL;
417 break;
418 }
419 if (error == 0) {
420 wreq.wi_len++;
421 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
422 }
423 return error;
424}
425
426static int
75static int
427findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate)
428{
429#define IEEERATE(_ic,_m,_i) \
430 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
431 int i, nrates = ic->ic_sup_rates[mode].rs_nrates;
432 for (i = 0; i < nrates; i++)
433 if (IEEERATE(ic, mode, i) == rate)
434 return i;
435 return -1;
436#undef IEEERATE
437}
438
439/*
440 * Prepare to do a user-initiated scan for AP's. If no
441 * current/default channel is setup or the current channel
442 * is invalid then pick the first available channel from
443 * the active list as the place to start the scan.
444 */
445static int
446ieee80211_setupscan(struct ieee80211com *ic, const u_int8_t chanlist[])
447{
448
449 /*
450 * XXX don't permit a scan to be started unless we
451 * know the device is ready. For the moment this means
452 * the device is marked up as this is the required to
453 * initialize the hardware. It would be better to permit
454 * scanning prior to being up but that'll require some
455 * changes to the infrastructure.
456 */
457 if (!IS_UP(ic))
458 return EINVAL;
459 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
460 /*
461 * We force the state to INIT before calling ieee80211_new_state
462 * to get ieee80211_begin_scan called. We really want to scan w/o
463 * altering the current state but that's not possible right now.
464 */
465 /* XXX handle proberequest case */
466 ic->ic_state = IEEE80211_S_INIT; /* XXX bypass state machine */
467 return 0;
468}
469
470int
471ieee80211_cfgset(struct ieee80211com *ic, u_long cmd, caddr_t data)
472{
473 struct ifnet *ifp = ic->ic_ifp;
474 int i, j, len, error, rate;
475 struct ifreq *ifr = (struct ifreq *)data;
476 struct wi_ltv_keys *keys;
477 struct wi_req wreq;
478 u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)];
479
480 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
481 if (error)
482 return error;
483 len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0;
484 switch (wreq.wi_type) {
485 case WI_RID_SERIALNO:
486 case WI_RID_NODENAME:
487 return EPERM;
488 case WI_RID_CURRENT_SSID:
489 return EPERM;
490 case WI_RID_OWN_SSID:
491 case WI_RID_DESIRED_SSID:
492 if (le16toh(wreq.wi_val[0]) * 2 > len ||
493 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) {
494 error = ENOSPC;
495 break;
496 }
497 memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid));
498 ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2;
499 memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen);
500 error = ENETRESET;
501 break;
502 case WI_RID_CURRENT_BSSID:
503 return EPERM;
504 case WI_RID_OWN_CHNL:
505 if (len != 2)
506 return EINVAL;
507 i = le16toh(wreq.wi_val[0]);
508 if (i < 0 ||
509 i > IEEE80211_CHAN_MAX ||
510 isclr(ic->ic_chan_active, i))
511 return EINVAL;
512 ic->ic_ibss_chan = &ic->ic_channels[i];
513 if (ic->ic_opmode == IEEE80211_M_MONITOR)
514 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
515 else
516 error = ENETRESET;
517 break;
518 case WI_RID_CURRENT_CHAN:
519 return EPERM;
520 case WI_RID_COMMS_QUALITY:
521 return EPERM;
522 case WI_RID_PROMISC:
523 if (len != 2)
524 return EINVAL;
525 if (ifp->if_flags & IFF_PROMISC) {
526 if (wreq.wi_val[0] == 0) {
527 ifp->if_flags &= ~IFF_PROMISC;
528 error = ENETRESET;
529 }
530 } else {
531 if (wreq.wi_val[0] != 0) {
532 ifp->if_flags |= IFF_PROMISC;
533 error = ENETRESET;
534 }
535 }
536 break;
537 case WI_RID_PORTTYPE:
538 if (len != 2)
539 return EINVAL;
540 switch (le16toh(wreq.wi_val[0])) {
541 case IEEE80211_M_STA:
542 break;
543 case IEEE80211_M_IBSS:
544 if (!(ic->ic_caps & IEEE80211_C_IBSS))
545 return EINVAL;
546 break;
547 case IEEE80211_M_AHDEMO:
548 if (ic->ic_phytype != IEEE80211_T_DS ||
549 !(ic->ic_caps & IEEE80211_C_AHDEMO))
550 return EINVAL;
551 break;
552 case IEEE80211_M_HOSTAP:
553 if (!(ic->ic_caps & IEEE80211_C_HOSTAP))
554 return EINVAL;
555 break;
556 default:
557 return EINVAL;
558 }
559 if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) {
560 ic->ic_opmode = le16toh(wreq.wi_val[0]);
561 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
562 }
563 break;
564#if 0
565 case WI_RID_MAC_NODE:
566 if (len != IEEE80211_ADDR_LEN)
567 return EINVAL;
568 IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val);
569 /* if_init will copy lladdr into ic_myaddr */
570 error = ENETRESET;
571 break;
572#endif
573 case WI_RID_TX_RATE:
574 if (len != 2)
575 return EINVAL;
576 if (wreq.wi_val[0] == 0) {
577 /* auto */
578 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
579 break;
580 }
581 rate = 2 * le16toh(wreq.wi_val[0]);
582 if (ic->ic_curmode == IEEE80211_MODE_AUTO) {
583 /*
584 * In autoselect mode search for the rate. We take
585 * the first instance which may not be right, but we
586 * are limited by the interface. Note that we also
587 * lock the mode to insure the rate is meaningful
588 * when it is used.
589 */
590 for (j = IEEE80211_MODE_11A;
591 j < IEEE80211_MODE_MAX; j++) {
592 if (isclr(ic->ic_modecaps, j))
593 continue;
594 i = findrate(ic, j, rate);
595 if (i != -1) {
596 /* lock mode too */
597 ic->ic_curmode = j;
598 goto setrate;
599 }
600 }
601 } else {
602 i = findrate(ic, ic->ic_curmode, rate);
603 if (i != -1)
604 goto setrate;
605 }
606 return EINVAL;
607 setrate:
608 ic->ic_fixed_rate = i;
609 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
610 break;
611 case WI_RID_CUR_TX_RATE:
612 return EPERM;
613 case WI_RID_RTS_THRESH:
614 if (len != 2)
615 return EINVAL;
616 if (le16toh(wreq.wi_val[0]) != IEEE80211_MAX_LEN)
617 return EINVAL; /* TODO: RTS */
618 break;
619 case WI_RID_CREATE_IBSS:
620 if (len != 2)
621 return EINVAL;
622 if (wreq.wi_val[0] != 0) {
623 if ((ic->ic_caps & IEEE80211_C_IBSS) == 0)
624 return EINVAL;
625 if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) {
626 ic->ic_flags |= IEEE80211_F_IBSSON;
627 if (ic->ic_opmode == IEEE80211_M_IBSS &&
628 ic->ic_state == IEEE80211_S_SCAN)
629 error = IS_UP_AUTO(ic) ? ENETRESET : 0;
630 }
631 } else {
632 if (ic->ic_flags & IEEE80211_F_IBSSON) {
633 ic->ic_flags &= ~IEEE80211_F_IBSSON;
634 if (ic->ic_flags & IEEE80211_F_SIBSS) {
635 ic->ic_flags &= ~IEEE80211_F_SIBSS;
636 error = IS_UP_AUTO(ic) ? ENETRESET : 0;
637 }
638 }
639 }
640 break;
641 case WI_RID_MICROWAVE_OVEN:
642 if (len != 2)
643 return EINVAL;
644 if (wreq.wi_val[0] != 0)
645 return EINVAL; /* not supported */
646 break;
647 case WI_RID_ROAMING_MODE:
648 if (len != 2)
649 return EINVAL;
650 i = le16toh(wreq.wi_val[0]);
651 if (i > IEEE80211_ROAMING_MANUAL)
652 return EINVAL; /* not supported */
653 ic->ic_roaming = i;
654 break;
655 case WI_RID_SYSTEM_SCALE:
656 if (len != 2)
657 return EINVAL;
658 if (le16toh(wreq.wi_val[0]) != 1)
659 return EINVAL; /* not supported */
660 break;
661 case WI_RID_PM_ENABLED:
662 if (len != 2)
663 return EINVAL;
664 if (wreq.wi_val[0] != 0) {
665 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
666 return EINVAL;
667 if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
668 ic->ic_flags |= IEEE80211_F_PMGTON;
669 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
670 }
671 } else {
672 if (ic->ic_flags & IEEE80211_F_PMGTON) {
673 ic->ic_flags &= ~IEEE80211_F_PMGTON;
674 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
675 }
676 }
677 break;
678 case WI_RID_MAX_SLEEP:
679 if (len != 2)
680 return EINVAL;
681 ic->ic_lintval = le16toh(wreq.wi_val[0]);
682 if (ic->ic_flags & IEEE80211_F_PMGTON)
683 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
684 break;
685 case WI_RID_CUR_BEACON_INT:
686 return EPERM;
687 case WI_RID_WEP_AVAIL:
688 return EPERM;
689 case WI_RID_CNFAUTHMODE:
690 if (len != 2)
691 return EINVAL;
692 i = le16toh(wreq.wi_val[0]);
693 if (i > IEEE80211_AUTH_WPA)
694 return EINVAL;
695 ic->ic_bss->ni_authmode = i; /* XXX ENETRESET? */
696 error = ENETRESET;
697 break;
698 case WI_RID_ENCRYPTION:
699 if (len != 2)
700 return EINVAL;
701 if (wreq.wi_val[0] != 0) {
702 if ((ic->ic_caps & IEEE80211_C_WEP) == 0)
703 return EINVAL;
704 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
705 ic->ic_flags |= IEEE80211_F_PRIVACY;
706 error = ENETRESET;
707 }
708 } else {
709 if (ic->ic_flags & IEEE80211_F_PRIVACY) {
710 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
711 error = ENETRESET;
712 }
713 }
714 break;
715 case WI_RID_TX_CRYPT_KEY:
716 if (len != 2)
717 return EINVAL;
718 i = le16toh(wreq.wi_val[0]);
719 if (i >= IEEE80211_WEP_NKID)
720 return EINVAL;
721 ic->ic_def_txkey = i;
722 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
723 break;
724 case WI_RID_DEFLT_CRYPT_KEYS:
725 if (len != sizeof(struct wi_ltv_keys))
726 return EINVAL;
727 keys = (struct wi_ltv_keys *)&wreq;
728 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
729 len = le16toh(keys->wi_keys[i].wi_keylen);
730 if (len != 0 && len < IEEE80211_WEP_KEYLEN)
731 return EINVAL;
732 if (len > IEEE80211_KEYBUF_SIZE)
733 return EINVAL;
734 }
735 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
736 struct ieee80211_key *k = &ic->ic_nw_keys[i];
737
738 len = le16toh(keys->wi_keys[i].wi_keylen);
739 k->wk_keylen = len;
740 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
741 memset(k->wk_key, 0, sizeof(k->wk_key));
742 memcpy(k->wk_key, keys->wi_keys[i].wi_keydat, len);
743#if 0
744 k->wk_type = IEEE80211_CIPHER_WEP;
745#endif
746 }
747 error = ENETRESET;
748 break;
749 case WI_RID_MAX_DATALEN:
750 if (len != 2)
751 return EINVAL;
752 len = le16toh(wreq.wi_val[0]);
753 if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN)
754 return EINVAL;
755 ic->ic_fragthreshold = len;
756 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
757 break;
758 case WI_RID_IFACE_STATS:
759 error = EPERM;
760 break;
761 case WI_RID_SCAN_REQ: /* XXX wicontrol */
762 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
763 break;
764 error = ieee80211_setupscan(ic, ic->ic_chan_avail);
765 if (error == 0)
766 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
767 break;
768 case WI_RID_SCAN_APS:
769 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
770 break;
771 len--; /* XXX: tx rate? */
772 /* FALLTHRU */
773 case WI_RID_CHANNEL_LIST:
774 memset(chanlist, 0, sizeof(chanlist));
775 /*
776 * Since channel 0 is not available for DS, channel 1
777 * is assigned to LSB on WaveLAN.
778 */
779 if (ic->ic_phytype == IEEE80211_T_DS)
780 i = 1;
781 else
782 i = 0;
783 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
784 if ((j / 8) >= len)
785 break;
786 if (isclr((u_int8_t *)wreq.wi_val, j))
787 continue;
788 if (isclr(ic->ic_chan_active, i)) {
789 if (wreq.wi_type != WI_RID_CHANNEL_LIST)
790 continue;
791 if (isclr(ic->ic_chan_avail, i))
792 return EPERM;
793 }
794 setbit(chanlist, i);
795 }
796 error = ieee80211_setupscan(ic, chanlist);
797 if (wreq.wi_type == WI_RID_CHANNEL_LIST) {
798 /* NB: ignore error from ieee80211_setupscan */
799 error = ENETRESET;
800 } else if (error == 0)
801 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
802 break;
803 default:
804 error = EINVAL;
805 break;
806 }
807 if (error == ENETRESET && !IS_UP_AUTO(ic))
808 error = 0;
809 return error;
810}
811
812static int
813cap2cipher(int flag)
814{
815 switch (flag) {
816 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP;
817 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB;
818 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM;
819 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP;
820 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP;

--- 63 unchanged lines hidden (view full) ---

884 if (sizeof(ic->ic_chan_active) < ireq->i_len)
885 ireq->i_len = sizeof(ic->ic_chan_active);
886 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
887}
888
889static int
890ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq)
891{
76cap2cipher(int flag)
77{
78 switch (flag) {
79 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP;
80 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB;
81 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM;
82 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP;
83 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP;

--- 63 unchanged lines hidden (view full) ---

147 if (sizeof(ic->ic_chan_active) < ireq->i_len)
148 ireq->i_len = sizeof(ic->ic_chan_active);
149 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
150}
151
152static int
153ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq)
154{
892 struct ieee80211req_chaninfo chans; /* XXX off stack? */
893 int i, space;
155 int space;
894
156
895 /*
896 * Since channel 0 is not available for DS, channel 1
897 * is assigned to LSB on WaveLAN.
898 */
899 if (ic->ic_phytype == IEEE80211_T_DS)
900 i = 1;
901 else
902 i = 0;
903 memset(&chans, 0, sizeof(chans));
904 for (; i <= IEEE80211_CHAN_MAX; i++)
905 if (isset(ic->ic_chan_avail, i)) {
906 struct ieee80211_channel *c = &ic->ic_channels[i];
907 chans.ic_chans[chans.ic_nchans].ic_freq = c->ic_freq;
908 chans.ic_chans[chans.ic_nchans].ic_flags = c->ic_flags;
909 chans.ic_nchans++;
910 }
911 space = __offsetof(struct ieee80211req_chaninfo,
157 space = __offsetof(struct ieee80211req_chaninfo,
912 ic_chans[chans.ic_nchans]);
158 ic_chans[ic->ic_nchans]);
913 if (space > ireq->i_len)
914 space = ireq->i_len;
159 if (space > ireq->i_len)
160 space = ireq->i_len;
915 return copyout(&chans, ireq->i_data, space);
161 /* XXX assumes compatible layout */
162 return copyout(&ic->ic_nchans, ireq->i_data, space);
916}
917
918static int
163}
164
165static int
919ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq)
166ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq, int req)
920{
921 struct ieee80211_node *ni;
167{
168 struct ieee80211_node *ni;
922 struct ieee80211req_wpaie wpaie;
169 struct ieee80211req_wpaie2 wpaie;
923 int error;
924
925 if (ireq->i_len < IEEE80211_ADDR_LEN)
926 return EINVAL;
927 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN);
928 if (error != 0)
929 return error;
930 ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr);
931 if (ni == NULL)
170 int error;
171
172 if (ireq->i_len < IEEE80211_ADDR_LEN)
173 return EINVAL;
174 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN);
175 if (error != 0)
176 return error;
177 ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr);
178 if (ni == NULL)
932 return EINVAL; /* XXX */
179 return ENOENT; /* XXX */
933 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
934 if (ni->ni_wpa_ie != NULL) {
935 int ielen = ni->ni_wpa_ie[1] + 2;
936 if (ielen > sizeof(wpaie.wpa_ie))
937 ielen = sizeof(wpaie.wpa_ie);
938 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen);
939 }
180 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
181 if (ni->ni_wpa_ie != NULL) {
182 int ielen = ni->ni_wpa_ie[1] + 2;
183 if (ielen > sizeof(wpaie.wpa_ie))
184 ielen = sizeof(wpaie.wpa_ie);
185 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen);
186 }
187 if (req == IEEE80211_IOC_WPAIE2) {
188 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie));
189 if (ni->ni_rsn_ie != NULL) {
190 int ielen = ni->ni_rsn_ie[1] + 2;
191 if (ielen > sizeof(wpaie.rsn_ie))
192 ielen = sizeof(wpaie.rsn_ie);
193 memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen);
194 }
195 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2))
196 ireq->i_len = sizeof(struct ieee80211req_wpaie2);
197 } else {
198 /* compatibility op, may overwrite wpa ie */
199 /* XXX check ic_flags? */
200 if (ni->ni_rsn_ie != NULL) {
201 int ielen = ni->ni_rsn_ie[1] + 2;
202 if (ielen > sizeof(wpaie.wpa_ie))
203 ielen = sizeof(wpaie.wpa_ie);
204 memcpy(wpaie.wpa_ie, ni->ni_rsn_ie, ielen);
205 }
206 if (ireq->i_len > sizeof(struct ieee80211req_wpaie))
207 ireq->i_len = sizeof(struct ieee80211req_wpaie);
208 }
940 ieee80211_free_node(ni);
209 ieee80211_free_node(ni);
941 if (ireq->i_len > sizeof(wpaie))
942 ireq->i_len = sizeof(wpaie);
943 return copyout(&wpaie, ireq->i_data, ireq->i_len);
944}
945
946static int
947ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
948{
949 struct ieee80211_node *ni;
210 return copyout(&wpaie, ireq->i_data, ireq->i_len);
211}
212
213static int
214ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
215{
216 struct ieee80211_node *ni;
950 u_int8_t macaddr[IEEE80211_ADDR_LEN];
217 uint8_t macaddr[IEEE80211_ADDR_LEN];
951 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats);
952 int error;
953
954 if (ireq->i_len < off)
955 return EINVAL;
956 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
957 if (error != 0)
958 return error;
959 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
218 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats);
219 int error;
220
221 if (ireq->i_len < off)
222 return EINVAL;
223 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
224 if (error != 0)
225 return error;
226 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
960 if (ni == NULL) {
961 /* XXX special-case sta-mode until bss is node in ic_sta */
962 if (ic->ic_opmode != IEEE80211_M_STA)
963 return ENOENT;
964 ni = ieee80211_ref_node(ic->ic_bss);
965 }
227 if (ni == NULL)
228 return EINVAL;
966 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats))
967 ireq->i_len = sizeof(struct ieee80211req_sta_stats);
968 /* NB: copy out only the statistics */
229 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats))
230 ireq->i_len = sizeof(struct ieee80211req_sta_stats);
231 /* NB: copy out only the statistics */
969 error = copyout(&ni->ni_stats, (u_int8_t *) ireq->i_data + off,
232 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off,
970 ireq->i_len - off);
971 ieee80211_free_node(ni);
972 return error;
973}
974
233 ireq->i_len - off);
234 ieee80211_free_node(ni);
235 return error;
236}
237
238static __inline uint8_t *
239copyie(uint8_t *cp, const uint8_t *ie)
240{
241 if (ie != NULL) {
242 memcpy(cp, ie, 2+ie[1]);
243 cp += 2+ie[1];
244 }
245 return cp;
246}
247
975#ifdef COMPAT_FREEBSD6
976#define IEEE80211_IOC_SCAN_RESULTS_OLD 24
977
978struct scan_result_old {
248#ifdef COMPAT_FREEBSD6
249#define IEEE80211_IOC_SCAN_RESULTS_OLD 24
250
251struct scan_result_old {
979 u_int16_t isr_len; /* length (mult of 4) */
980 u_int16_t isr_freq; /* MHz */
981 u_int16_t isr_flags; /* channel flags */
982 u_int8_t isr_noise;
983 u_int8_t isr_rssi;
984 u_int8_t isr_intval; /* beacon interval */
985 u_int8_t isr_capinfo; /* capabilities */
986 u_int8_t isr_erp; /* ERP element */
987 u_int8_t isr_bssid[IEEE80211_ADDR_LEN];
988 u_int8_t isr_nrates;
989 u_int8_t isr_rates[IEEE80211_RATE_MAXSIZE];
990 u_int8_t isr_ssid_len; /* SSID length */
991 u_int8_t isr_ie_len; /* IE length */
992 u_int8_t isr_pad[5];
252 uint16_t isr_len; /* length (mult of 4) */
253 uint16_t isr_freq; /* MHz */
254 uint16_t isr_flags; /* channel flags */
255 uint8_t isr_noise;
256 uint8_t isr_rssi;
257 uint8_t isr_intval; /* beacon interval */
258 uint8_t isr_capinfo; /* capabilities */
259 uint8_t isr_erp; /* ERP element */
260 uint8_t isr_bssid[IEEE80211_ADDR_LEN];
261 uint8_t isr_nrates;
262 uint8_t isr_rates[IEEE80211_RATE_MAXSIZE];
263 uint8_t isr_ssid_len; /* SSID length */
264 uint8_t isr_ie_len; /* IE length */
265 uint8_t isr_pad[5];
993 /* variable length SSID followed by IE data */
994};
995
266 /* variable length SSID followed by IE data */
267};
268
269struct oscanreq {
270 struct scan_result_old *sr;
271 size_t space;
272};
273
274static size_t
275old_scan_space(const struct ieee80211_scan_entry *se, int *ielen)
276{
277 size_t len;
278
279 *ielen = 0;
280 if (se->se_wpa_ie != NULL)
281 *ielen += 2+se->se_wpa_ie[1];
282 if (se->se_wme_ie != NULL)
283 *ielen += 2+se->se_wme_ie[1];
284 /*
285 * NB: ie's can be no more than 255 bytes and the max 802.11
286 * packet is <3Kbytes so we are sure this doesn't overflow
287 * 16-bits; if this is a concern we can drop the ie's.
288 */
289 len = sizeof(struct scan_result_old) + se->se_ssid[1] + *ielen;
290 return roundup(len, sizeof(uint32_t));
291}
292
996static void
293static void
997old_get_scan_result(struct scan_result_old *sr,
998 const struct ieee80211_node *ni)
294old_get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
999{
295{
1000 struct ieee80211com *ic = ni->ni_ic;
1001 u_int ielen;
296 struct oscanreq *req = arg;
297 int ielen;
1002
298
299 req->space += old_scan_space(se, &ielen);
300}
301
302static void
303old_get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
304{
305 struct oscanreq *req = arg;
306 struct scan_result_old *sr;
307 int ielen, len, nr, nxr;
308 uint8_t *cp;
309
310 len = old_scan_space(se, &ielen);
311 if (len > req->space)
312 return;
313
314 sr = req->sr;
1003 memset(sr, 0, sizeof(*sr));
315 memset(sr, 0, sizeof(*sr));
1004 sr->isr_ssid_len = ni->ni_esslen;
1005 ielen = 0;
1006 if (ni->ni_wpa_ie != NULL)
1007 ielen += 2+ni->ni_wpa_ie[1];
1008 if (ni->ni_wme_ie != NULL)
1009 ielen += 2+ni->ni_wme_ie[1];
316 sr->isr_ssid_len = se->se_ssid[1];
1010 /* NB: beware of overflow, isr_ie_len is 8 bits */
1011 sr->isr_ie_len = (ielen > 255 ? 0 : ielen);
317 /* NB: beware of overflow, isr_ie_len is 8 bits */
318 sr->isr_ie_len = (ielen > 255 ? 0 : ielen);
1012 sr->isr_len = sizeof(*sr) + sr->isr_ssid_len + sr->isr_ie_len;
1013 sr->isr_len = roundup(sr->isr_len, sizeof(u_int32_t));
1014 if (ni->ni_chan != IEEE80211_CHAN_ANYC) {
1015 sr->isr_freq = ni->ni_chan->ic_freq;
1016 sr->isr_flags = ni->ni_chan->ic_flags;
319 sr->isr_len = len;
320 sr->isr_freq = se->se_chan->ic_freq;
321 sr->isr_flags = se->se_chan->ic_flags;
322 sr->isr_rssi = se->se_rssi;
323 sr->isr_noise = se->se_noise;
324 sr->isr_intval = se->se_intval;
325 sr->isr_capinfo = se->se_capinfo;
326 sr->isr_erp = se->se_erp;
327 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
328 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
329 memcpy(sr->isr_rates, se->se_rates+2, nr);
330 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
331 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
332 sr->isr_nrates = nr + nxr;
333
334 cp = (uint8_t *)(sr+1);
335 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
336 cp += sr->isr_ssid_len;
337 if (sr->isr_ie_len) {
338 cp = copyie(cp, se->se_wpa_ie);
339 cp = copyie(cp, se->se_wme_ie);
1017 }
340 }
1018 sr->isr_rssi = ic->ic_node_getrssi(ni);
1019 sr->isr_intval = ni->ni_intval;
1020 sr->isr_capinfo = ni->ni_capinfo;
1021 sr->isr_erp = ni->ni_erp;
1022 IEEE80211_ADDR_COPY(sr->isr_bssid, ni->ni_bssid);
1023 sr->isr_nrates = ni->ni_rates.rs_nrates;
1024 if (sr->isr_nrates > 15)
1025 sr->isr_nrates = 15;
1026 memcpy(sr->isr_rates, ni->ni_rates.rs_rates, sr->isr_nrates);
341
342 req->space -= len;
343 req->sr = (struct scan_result_old *)(((uint8_t *)sr) + len);
1027}
1028
1029static int
1030old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
1031{
344}
345
346static int
347old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
348{
1032 union {
1033 struct scan_result_old res;
1034 char data[512]; /* XXX shrink? */
1035 } u;
1036 struct scan_result_old *sr = &u.res;
1037 struct ieee80211_node_table *nt;
1038 struct ieee80211_node *ni;
1039 int error, space;
1040 u_int8_t *p, *cp;
349 struct oscanreq req;
350 int error;
1041
351
1042 p = ireq->i_data;
1043 space = ireq->i_len;
352 if (ireq->i_len < sizeof(struct scan_result_old))
353 return EFAULT;
354
1044 error = 0;
355 error = 0;
1045 /* XXX locking */
1046 nt = &ic->ic_scan;
1047 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
1048 /* NB: skip pre-scan node state */
1049 if (ni->ni_chan == IEEE80211_CHAN_ANYC)
1050 continue;
1051 old_get_scan_result(sr, ni);
1052 if (sr->isr_len > sizeof(u))
1053 continue; /* XXX */
1054 if (space < sr->isr_len)
1055 break;
1056 cp = (u_int8_t *)(sr+1);
1057 memcpy(cp, ni->ni_essid, ni->ni_esslen);
1058 cp += ni->ni_esslen;
1059 if (sr->isr_ie_len) {
1060 if (ni->ni_wpa_ie != NULL) {
1061 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]);
1062 cp += 2+ni->ni_wpa_ie[1];
1063 }
1064 if (ni->ni_wme_ie != NULL) {
1065 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]);
1066 cp += 2+ni->ni_wme_ie[1];
1067 }
1068 }
1069 error = copyout(sr, p, sr->isr_len);
1070 if (error)
1071 break;
1072 p += sr->isr_len;
1073 space -= sr->isr_len;
1074 }
1075 ireq->i_len -= space;
356 req.space = 0;
357 ieee80211_scan_iterate(ic, old_get_scan_space, &req);
358 if (req.space > ireq->i_len)
359 req.space = ireq->i_len;
360 if (req.space > 0) {
361 size_t space;
362 void *p;
363
364 space = req.space;
365 /* XXX M_WAITOK after driver lock released */
366 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
367 if (p == NULL)
368 return ENOMEM;
369 req.sr = p;
370 ieee80211_scan_iterate(ic, old_get_scan_result, &req);
371 ireq->i_len = space - req.space;
372 error = copyout(p, ireq->i_data, ireq->i_len);
373 FREE(p, M_TEMP);
374 } else
375 ireq->i_len = 0;
376
1076 return error;
1077}
1078#endif /* COMPAT_FREEBSD6 */
1079
377 return error;
378}
379#endif /* COMPAT_FREEBSD6 */
380
1080struct scanresultsreq {
381struct scanreq {
1081 struct ieee80211req_scan_result *sr;
382 struct ieee80211req_scan_result *sr;
1082 size_t space;
383 size_t space;
1083};
1084
1085static size_t
384};
385
386static size_t
1086scan_space(const struct ieee80211_node *ni, size_t *ielen)
387scan_space(const struct ieee80211_scan_entry *se, int *ielen)
1087{
1088 size_t len;
1089
1090 *ielen = 0;
388{
389 size_t len;
390
391 *ielen = 0;
1091 if (ni->ni_wpa_ie != NULL)
1092 *ielen += 2+ni->ni_wpa_ie[1];
1093 if (ni->ni_wme_ie != NULL)
1094 *ielen += 2+ni->ni_wme_ie[1];
392 if (se->se_wpa_ie != NULL)
393 *ielen += 2+se->se_wpa_ie[1];
394 if (se->se_rsn_ie != NULL)
395 *ielen += 2+se->se_rsn_ie[1];
396 if (se->se_wme_ie != NULL)
397 *ielen += 2+se->se_wme_ie[1];
398 if (se->se_ath_ie != NULL)
399 *ielen += 2+se->se_ath_ie[1];
1095 /*
1096 * NB: ie's can be no more than 255 bytes and the max 802.11
1097 * packet is <3Kbytes so we are sure this doesn't overflow
1098 * 16-bits; if this is a concern we can drop the ie's.
1099 */
400 /*
401 * NB: ie's can be no more than 255 bytes and the max 802.11
402 * packet is <3Kbytes so we are sure this doesn't overflow
403 * 16-bits; if this is a concern we can drop the ie's.
404 */
1100 len = sizeof(struct ieee80211req_scan_result) + ni->ni_esslen + *ielen;
1101 return roundup(len, sizeof(u_int32_t));
405 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen;
406 return roundup(len, sizeof(uint32_t));
1102}
1103
1104static void
407}
408
409static void
1105get_scan_space(void *arg, struct ieee80211_node *ni)
410get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
1106{
411{
1107 struct scanresultsreq *req = arg;
1108 size_t ielen;
412 struct scanreq *req = arg;
413 int ielen;
1109
414
1110 req->space += scan_space(ni, &ielen);
415 req->space += scan_space(se, &ielen);
1111}
1112
1113static void
416}
417
418static void
1114get_scan_result(void *arg, struct ieee80211_node *ni)
419get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
1115{
420{
1116 struct scanresultsreq *req = arg;
1117 struct ieee80211com *ic = ni->ni_ic;
421 struct scanreq *req = arg;
1118 struct ieee80211req_scan_result *sr;
422 struct ieee80211req_scan_result *sr;
1119 size_t ielen, len;
1120 u_int8_t *cp;
423 int ielen, len, nr, nxr;
424 uint8_t *cp;
1121
425
1122 len = scan_space(ni, &ielen);
426 len = scan_space(se, &ielen);
1123 if (len > req->space)
1124 return;
427 if (len > req->space)
428 return;
429
1125 sr = req->sr;
1126 KASSERT(len <= 65535 && ielen <= 65535,
430 sr = req->sr;
431 KASSERT(len <= 65535 && ielen <= 65535,
1127 ("len %zu ssid %u ie %zu", len, ni->ni_esslen, ielen));
1128 sr->isr_len = len;
1129 sr->isr_ssid_len = ni->ni_esslen;
432 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen));
433 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result);
1130 sr->isr_ie_len = ielen;
434 sr->isr_ie_len = ielen;
1131 if (ni->ni_chan != IEEE80211_CHAN_ANYC) {
1132 sr->isr_freq = ni->ni_chan->ic_freq;
1133 sr->isr_flags = ni->ni_chan->ic_flags;
435 sr->isr_len = len;
436 sr->isr_freq = se->se_chan->ic_freq;
437 sr->isr_flags = se->se_chan->ic_flags;
438 sr->isr_rssi = se->se_rssi;
439 sr->isr_noise = se->se_noise;
440 sr->isr_intval = se->se_intval;
441 sr->isr_capinfo = se->se_capinfo;
442 sr->isr_erp = se->se_erp;
443 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
444 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
445 memcpy(sr->isr_rates, se->se_rates+2, nr);
446 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
447 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
448 sr->isr_nrates = nr + nxr;
449
450 sr->isr_ssid_len = se->se_ssid[1];
451 cp = ((uint8_t *)sr) + sr->isr_ie_off;
452 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
453
454 if (ielen) {
455 cp += sr->isr_ssid_len;
456 cp = copyie(cp, se->se_wpa_ie);
457 cp = copyie(cp, se->se_rsn_ie);
458 cp = copyie(cp, se->se_wme_ie);
459 cp = copyie(cp, se->se_ath_ie);
460 cp = copyie(cp, se->se_htcap_ie);
1134 }
461 }
1135 /* XXX need to rev driver apis for signal data */
1136 sr->isr_rssi = (int8_t) ic->ic_node_getrssi(ni);
1137 sr->isr_intval = ni->ni_intval;
1138 sr->isr_capinfo = ni->ni_capinfo;
1139 sr->isr_erp = ni->ni_erp;
1140 IEEE80211_ADDR_COPY(sr->isr_bssid, ni->ni_bssid);
1141 sr->isr_nrates = ni->ni_rates.rs_nrates;
1142 if (sr->isr_nrates > 15)
1143 sr->isr_nrates = 15;
1144 memcpy(sr->isr_rates, ni->ni_rates.rs_rates, sr->isr_nrates);
1145 cp = (u_int8_t *)(sr+1);
1146 memcpy(cp, ni->ni_essid, ni->ni_esslen);
1147 cp += ni->ni_esslen;
1148 if (sr->isr_ie_len) {
1149 if (ni->ni_wpa_ie != NULL) {
1150 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]);
1151 cp += 2+ni->ni_wpa_ie[1];
1152 }
1153 if (ni->ni_wme_ie != NULL) {
1154 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]);
1155 cp += 2+ni->ni_wme_ie[1];
1156 }
1157 }
1158
462
1159 req->sr = (struct ieee80211req_scan_result *)(((u_int8_t *)sr) + len);
1160 req->space -= len;
463 req->space -= len;
464 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
1161}
1162
1163static int
1164ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
1165{
465}
466
467static int
468ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
469{
1166 struct scanresultsreq req;
470 struct scanreq req;
1167 int error;
1168
1169 if (ireq->i_len < sizeof(struct ieee80211req_scan_result))
1170 return EFAULT;
1171
1172 error = 0;
1173 req.space = 0;
471 int error;
472
473 if (ireq->i_len < sizeof(struct ieee80211req_scan_result))
474 return EFAULT;
475
476 error = 0;
477 req.space = 0;
1174 ieee80211_iterate_nodes(&ic->ic_scan, get_scan_space, &req);
478 ieee80211_scan_iterate(ic, get_scan_space, &req);
1175 if (req.space > ireq->i_len)
1176 req.space = ireq->i_len;
1177 if (req.space > 0) {
1178 size_t space;
1179 void *p;
1180
1181 space = req.space;
1182 /* XXX M_WAITOK after driver lock released */
1183 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
1184 if (p == NULL)
1185 return ENOMEM;
1186 req.sr = p;
479 if (req.space > ireq->i_len)
480 req.space = ireq->i_len;
481 if (req.space > 0) {
482 size_t space;
483 void *p;
484
485 space = req.space;
486 /* XXX M_WAITOK after driver lock released */
487 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
488 if (p == NULL)
489 return ENOMEM;
490 req.sr = p;
1187 ieee80211_iterate_nodes(&ic->ic_scan, get_scan_result, &req);
491 ieee80211_scan_iterate(ic, get_scan_result, &req);
1188 ireq->i_len = space - req.space;
1189 error = copyout(p, ireq->i_data, ireq->i_len);
1190 FREE(p, M_TEMP);
1191 } else
1192 ireq->i_len = 0;
1193
1194 return error;
1195}

--- 5 unchanged lines hidden (view full) ---

1201};
1202
1203static size_t
1204sta_space(const struct ieee80211_node *ni, size_t *ielen)
1205{
1206 *ielen = 0;
1207 if (ni->ni_wpa_ie != NULL)
1208 *ielen += 2+ni->ni_wpa_ie[1];
492 ireq->i_len = space - req.space;
493 error = copyout(p, ireq->i_data, ireq->i_len);
494 FREE(p, M_TEMP);
495 } else
496 ireq->i_len = 0;
497
498 return error;
499}

--- 5 unchanged lines hidden (view full) ---

505};
506
507static size_t
508sta_space(const struct ieee80211_node *ni, size_t *ielen)
509{
510 *ielen = 0;
511 if (ni->ni_wpa_ie != NULL)
512 *ielen += 2+ni->ni_wpa_ie[1];
513 if (ni->ni_rsn_ie != NULL)
514 *ielen += 2+ni->ni_rsn_ie[1];
1209 if (ni->ni_wme_ie != NULL)
1210 *ielen += 2+ni->ni_wme_ie[1];
515 if (ni->ni_wme_ie != NULL)
516 *ielen += 2+ni->ni_wme_ie[1];
517 if (ni->ni_ath_ie != NULL)
518 *ielen += 2+ni->ni_ath_ie[1];
1211 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
519 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
1212 sizeof(u_int32_t));
520 sizeof(uint32_t));
1213}
1214
1215static void
1216get_sta_space(void *arg, struct ieee80211_node *ni)
1217{
1218 struct stainforeq *req = arg;
1219 struct ieee80211com *ic = ni->ni_ic;
1220 size_t ielen;

--- 6 unchanged lines hidden (view full) ---

1227
1228static void
1229get_sta_info(void *arg, struct ieee80211_node *ni)
1230{
1231 struct stainforeq *req = arg;
1232 struct ieee80211com *ic = ni->ni_ic;
1233 struct ieee80211req_sta_info *si;
1234 size_t ielen, len;
521}
522
523static void
524get_sta_space(void *arg, struct ieee80211_node *ni)
525{
526 struct stainforeq *req = arg;
527 struct ieee80211com *ic = ni->ni_ic;
528 size_t ielen;

--- 6 unchanged lines hidden (view full) ---

535
536static void
537get_sta_info(void *arg, struct ieee80211_node *ni)
538{
539 struct stainforeq *req = arg;
540 struct ieee80211com *ic = ni->ni_ic;
541 struct ieee80211req_sta_info *si;
542 size_t ielen, len;
1235 u_int8_t *cp;
543 uint8_t *cp;
1236
1237 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1238 ni->ni_associd == 0) /* only associated stations */
1239 return;
1240 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
1241 return;
1242 len = sta_space(ni, &ielen);
1243 if (len > req->space)
1244 return;
1245 si = req->si;
544
545 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
546 ni->ni_associd == 0) /* only associated stations */
547 return;
548 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
549 return;
550 len = sta_space(ni, &ielen);
551 if (len > req->space)
552 return;
553 si = req->si;
1246 KASSERT(len <= 65535 && ielen <= 65535, ("len %zu ie %zu", len, ielen));
1247 si->isi_len = len;
554 si->isi_len = len;
555 si->isi_ie_off = sizeof(struct ieee80211req_sta_info);
1248 si->isi_ie_len = ielen;
1249 si->isi_freq = ni->ni_chan->ic_freq;
1250 si->isi_flags = ni->ni_chan->ic_flags;
1251 si->isi_state = ni->ni_flags;
1252 si->isi_authmode = ni->ni_authmode;
556 si->isi_ie_len = ielen;
557 si->isi_freq = ni->ni_chan->ic_freq;
558 si->isi_flags = ni->ni_chan->ic_flags;
559 si->isi_state = ni->ni_flags;
560 si->isi_authmode = ni->ni_authmode;
1253 si->isi_rssi = ic->ic_node_getrssi(ni);
561 ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise);
1254 si->isi_noise = 0; /* XXX */
1255 si->isi_capinfo = ni->ni_capinfo;
1256 si->isi_erp = ni->ni_erp;
1257 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr);
1258 si->isi_nrates = ni->ni_rates.rs_nrates;
1259 if (si->isi_nrates > 15)
1260 si->isi_nrates = 15;
1261 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
1262 si->isi_txrate = ni->ni_txrate;
562 si->isi_noise = 0; /* XXX */
563 si->isi_capinfo = ni->ni_capinfo;
564 si->isi_erp = ni->ni_erp;
565 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr);
566 si->isi_nrates = ni->ni_rates.rs_nrates;
567 if (si->isi_nrates > 15)
568 si->isi_nrates = 15;
569 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
570 si->isi_txrate = ni->ni_txrate;
571 si->isi_ie_len = ielen;
1263 si->isi_associd = ni->ni_associd;
1264 si->isi_txpower = ni->ni_txpower;
1265 si->isi_vlan = ni->ni_vlan;
1266 if (ni->ni_flags & IEEE80211_NODE_QOS) {
1267 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs));
1268 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs));
1269 } else {
1270 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID];
1271 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID];
1272 }
1273 /* NB: leave all cases in case we relax ni_associd == 0 check */
1274 if (ieee80211_node_is_authorized(ni))
1275 si->isi_inact = ic->ic_inact_run;
1276 else if (ni->ni_associd != 0)
1277 si->isi_inact = ic->ic_inact_auth;
1278 else
1279 si->isi_inact = ic->ic_inact_init;
1280 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
1281
572 si->isi_associd = ni->ni_associd;
573 si->isi_txpower = ni->ni_txpower;
574 si->isi_vlan = ni->ni_vlan;
575 if (ni->ni_flags & IEEE80211_NODE_QOS) {
576 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs));
577 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs));
578 } else {
579 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID];
580 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID];
581 }
582 /* NB: leave all cases in case we relax ni_associd == 0 check */
583 if (ieee80211_node_is_authorized(ni))
584 si->isi_inact = ic->ic_inact_run;
585 else if (ni->ni_associd != 0)
586 si->isi_inact = ic->ic_inact_auth;
587 else
588 si->isi_inact = ic->ic_inact_init;
589 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
590
1282 cp = (u_int8_t *)(si+1);
1283 if (ni->ni_wpa_ie != NULL) {
1284 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]);
1285 cp += 2+ni->ni_wpa_ie[1];
591 if (ielen) {
592 cp = ((uint8_t *)si) + si->isi_ie_off;
593 cp = copyie(cp, ni->ni_wpa_ie);
594 cp = copyie(cp, ni->ni_rsn_ie);
595 cp = copyie(cp, ni->ni_wme_ie);
596 cp = copyie(cp, ni->ni_ath_ie);
1286 }
597 }
1287 if (ni->ni_wme_ie != NULL) {
1288 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]);
1289 cp += 2+ni->ni_wme_ie[1];
1290 }
1291
598
1292 req->si = (struct ieee80211req_sta_info *)(((u_int8_t *)si) + len);
599 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len);
1293 req->space -= len;
1294}
1295
1296static int
1297getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq,
1298 struct ieee80211_node *ni, int off)
1299{
1300 struct stainforeq req;

--- 18 unchanged lines hidden (view full) ---

1319 goto bad;
1320 }
1321 req.si = p;
1322 if (ni == NULL)
1323 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
1324 else
1325 get_sta_info(&req, ni);
1326 ireq->i_len = space - req.space;
600 req->space -= len;
601}
602
603static int
604getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq,
605 struct ieee80211_node *ni, int off)
606{
607 struct stainforeq req;

--- 18 unchanged lines hidden (view full) ---

626 goto bad;
627 }
628 req.si = p;
629 if (ni == NULL)
630 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
631 else
632 get_sta_info(&req, ni);
633 ireq->i_len = space - req.space;
1327 error = copyout(p, (u_int8_t *) ireq->i_data+off, ireq->i_len);
634 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
1328 FREE(p, M_TEMP);
1329 } else
1330 ireq->i_len = 0;
1331bad:
1332 if (ni != NULL)
1333 ieee80211_free_node(ni);
1334 return error;
1335}
1336
1337static int
1338ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
1339{
635 FREE(p, M_TEMP);
636 } else
637 ireq->i_len = 0;
638bad:
639 if (ni != NULL)
640 ieee80211_free_node(ni);
641 return error;
642}
643
644static int
645ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
646{
1340 u_int8_t macaddr[IEEE80211_ADDR_LEN];
647 uint8_t macaddr[IEEE80211_ADDR_LEN];
1341 const int off = __offsetof(struct ieee80211req_sta_req, info);
1342 struct ieee80211_node *ni;
1343 int error;
1344
1345 if (ireq->i_len < sizeof(struct ieee80211req_sta_req))
1346 return EFAULT;
1347 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1348 if (error != 0)
1349 return error;
1350 if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) {
1351 ni = NULL;
1352 } else {
1353 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
648 const int off = __offsetof(struct ieee80211req_sta_req, info);
649 struct ieee80211_node *ni;
650 int error;
651
652 if (ireq->i_len < sizeof(struct ieee80211req_sta_req))
653 return EFAULT;
654 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
655 if (error != 0)
656 return error;
657 if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) {
658 ni = NULL;
659 } else {
660 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
1354 if (ni == NULL) {
1355 /* XXX special-case sta-mode until bss is in ic_sta */
1356 if (ic->ic_opmode != IEEE80211_M_STA)
1357 return EINVAL; /* XXX */
1358 ni = ieee80211_ref_node(ic->ic_bss);
1359 }
661 if (ni == NULL)
662 return EINVAL;
1360 }
1361 return getstainfo_common(ic, ireq, ni, off);
1362}
1363
1364#ifdef COMPAT_FREEBSD6
1365#define IEEE80211_IOC_STA_INFO_OLD 45
1366
1367static int

--- 72 unchanged lines hidden (view full) ---

1440ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
1441{
1442 const struct ieee80211_aclator *acl = ic->ic_acl;
1443
1444 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq));
1445}
1446
1447/*
663 }
664 return getstainfo_common(ic, ireq, ni, off);
665}
666
667#ifdef COMPAT_FREEBSD6
668#define IEEE80211_IOC_STA_INFO_OLD 45
669
670static int

--- 72 unchanged lines hidden (view full) ---

743ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
744{
745 const struct ieee80211_aclator *acl = ic->ic_acl;
746
747 return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq));
748}
749
750/*
751 * Return the current ``state'' of an Atheros capbility.
752 * If associated in station mode report the negotiated
753 * setting. Otherwise report the current setting.
754 */
755static int
756getathcap(struct ieee80211com *ic, int cap)
757{
758 if (ic->ic_opmode == IEEE80211_M_STA && ic->ic_state == IEEE80211_S_RUN)
759 return IEEE80211_ATH_CAP(ic, ic->ic_bss, cap) != 0;
760 else
761 return (ic->ic_flags & cap) != 0;
762}
763
764static int
765ieee80211_ioctl_getcurchan(struct ieee80211com *ic, struct ieee80211req *ireq)
766{
767 if (ireq->i_len != sizeof(struct ieee80211_channel))
768 return EINVAL;
769 return copyout(ic->ic_curchan, ireq->i_data, sizeof(*ic->ic_curchan));
770}
771
772/*
1448 * When building the kernel with -O2 on the i386 architecture, gcc
1449 * seems to want to inline this function into ieee80211_ioctl()
1450 * (which is the only routine that calls it). When this happens,
1451 * ieee80211_ioctl() ends up consuming an additional 2K of stack
1452 * space. (Exactly why it needs so much is unclear.) The problem
1453 * is that it's possible for ieee80211_ioctl() to invoke other
1454 * routines (including driver init functions) which could then find
1455 * themselves perilously close to exhausting the stack.

--- 8 unchanged lines hidden (view full) ---

1464__attribute__ ((noinline))
1465#endif
1466static int
1467ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
1468{
1469 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
1470 int error = 0;
1471 u_int kid, len, m;
773 * When building the kernel with -O2 on the i386 architecture, gcc
774 * seems to want to inline this function into ieee80211_ioctl()
775 * (which is the only routine that calls it). When this happens,
776 * ieee80211_ioctl() ends up consuming an additional 2K of stack
777 * space. (Exactly why it needs so much is unclear.) The problem
778 * is that it's possible for ieee80211_ioctl() to invoke other
779 * routines (including driver init functions) which could then find
780 * themselves perilously close to exhausting the stack.

--- 8 unchanged lines hidden (view full) ---

789__attribute__ ((noinline))
790#endif
791static int
792ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
793{
794 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
795 int error = 0;
796 u_int kid, len, m;
1472 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE];
797 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
1473 char tmpssid[IEEE80211_NWID_LEN];
1474
1475 switch (ireq->i_type) {
1476 case IEEE80211_IOC_SSID:
1477 switch (ic->ic_state) {
1478 case IEEE80211_S_INIT:
1479 case IEEE80211_S_SCAN:
798 char tmpssid[IEEE80211_NWID_LEN];
799
800 switch (ireq->i_type) {
801 case IEEE80211_IOC_SSID:
802 switch (ic->ic_state) {
803 case IEEE80211_S_INIT:
804 case IEEE80211_S_SCAN:
1480 ireq->i_len = ic->ic_des_esslen;
1481 memcpy(tmpssid, ic->ic_des_essid, ireq->i_len);
805 ireq->i_len = ic->ic_des_ssid[0].len;
806 memcpy(tmpssid, ic->ic_des_ssid[0].ssid, ireq->i_len);
1482 break;
1483 default:
1484 ireq->i_len = ic->ic_bss->ni_esslen;
1485 memcpy(tmpssid, ic->ic_bss->ni_essid,
1486 ireq->i_len);
1487 break;
1488 }
1489 error = copyout(tmpssid, ireq->i_data, ireq->i_len);

--- 144 unchanged lines hidden (view full) ---

1634 if (ireq->i_len != IEEE80211_ADDR_LEN)
1635 return EINVAL;
1636 error = copyout(ic->ic_state == IEEE80211_S_RUN ?
1637 ic->ic_bss->ni_bssid :
1638 ic->ic_des_bssid,
1639 ireq->i_data, ireq->i_len);
1640 break;
1641 case IEEE80211_IOC_WPAIE:
807 break;
808 default:
809 ireq->i_len = ic->ic_bss->ni_esslen;
810 memcpy(tmpssid, ic->ic_bss->ni_essid,
811 ireq->i_len);
812 break;
813 }
814 error = copyout(tmpssid, ireq->i_data, ireq->i_len);

--- 144 unchanged lines hidden (view full) ---

959 if (ireq->i_len != IEEE80211_ADDR_LEN)
960 return EINVAL;
961 error = copyout(ic->ic_state == IEEE80211_S_RUN ?
962 ic->ic_bss->ni_bssid :
963 ic->ic_des_bssid,
964 ireq->i_data, ireq->i_len);
965 break;
966 case IEEE80211_IOC_WPAIE:
1642 error = ieee80211_ioctl_getwpaie(ic, ireq);
967 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
1643 break;
968 break;
969 case IEEE80211_IOC_WPAIE2:
970 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
971 break;
1644#ifdef COMPAT_FREEBSD6
1645 case IEEE80211_IOC_SCAN_RESULTS_OLD:
1646 error = old_getscanresults(ic, ireq);
1647 break;
1648#endif
1649 case IEEE80211_IOC_SCAN_RESULTS:
1650 error = ieee80211_ioctl_getscanresults(ic, ireq);
1651 break;

--- 27 unchanged lines hidden (view full) ---

1679 break;
1680 case IEEE80211_IOC_BEACON_INTERVAL:
1681 /* NB: get from ic_bss for station mode */
1682 ireq->i_val = ic->ic_bss->ni_intval;
1683 break;
1684 case IEEE80211_IOC_PUREG:
1685 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0;
1686 break;
972#ifdef COMPAT_FREEBSD6
973 case IEEE80211_IOC_SCAN_RESULTS_OLD:
974 error = old_getscanresults(ic, ireq);
975 break;
976#endif
977 case IEEE80211_IOC_SCAN_RESULTS:
978 error = ieee80211_ioctl_getscanresults(ic, ireq);
979 break;

--- 27 unchanged lines hidden (view full) ---

1007 break;
1008 case IEEE80211_IOC_BEACON_INTERVAL:
1009 /* NB: get from ic_bss for station mode */
1010 ireq->i_val = ic->ic_bss->ni_intval;
1011 break;
1012 case IEEE80211_IOC_PUREG:
1013 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0;
1014 break;
1015 case IEEE80211_IOC_FF:
1016 ireq->i_val = getathcap(ic, IEEE80211_F_FF);
1017 break;
1018 case IEEE80211_IOC_TURBOP:
1019 ireq->i_val = getathcap(ic, IEEE80211_F_TURBOP);
1020 break;
1021 case IEEE80211_IOC_BGSCAN:
1022 ireq->i_val = (ic->ic_flags & IEEE80211_F_BGSCAN) != 0;
1023 break;
1024 case IEEE80211_IOC_BGSCAN_IDLE:
1025 ireq->i_val = ic->ic_bgscanidle*hz/1000; /* ms */
1026 break;
1027 case IEEE80211_IOC_BGSCAN_INTERVAL:
1028 ireq->i_val = ic->ic_bgscanintvl/hz; /* seconds */
1029 break;
1030 case IEEE80211_IOC_SCANVALID:
1031 ireq->i_val = ic->ic_scanvalid/hz; /* seconds */
1032 break;
1033 case IEEE80211_IOC_ROAM_RSSI_11A:
1034 ireq->i_val = ic->ic_roam.rssi11a;
1035 break;
1036 case IEEE80211_IOC_ROAM_RSSI_11B:
1037 ireq->i_val = ic->ic_roam.rssi11bOnly;
1038 break;
1039 case IEEE80211_IOC_ROAM_RSSI_11G:
1040 ireq->i_val = ic->ic_roam.rssi11b;
1041 break;
1042 case IEEE80211_IOC_ROAM_RATE_11A:
1043 ireq->i_val = ic->ic_roam.rate11a;
1044 break;
1045 case IEEE80211_IOC_ROAM_RATE_11B:
1046 ireq->i_val = ic->ic_roam.rate11bOnly;
1047 break;
1048 case IEEE80211_IOC_ROAM_RATE_11G:
1049 ireq->i_val = ic->ic_roam.rate11b;
1050 break;
1687 case IEEE80211_IOC_MCAST_RATE:
1688 ireq->i_val = ic->ic_mcast_rate;
1689 break;
1690 case IEEE80211_IOC_FRAGTHRESHOLD:
1691 ireq->i_val = ic->ic_fragthreshold;
1692 break;
1693 case IEEE80211_IOC_MACCMD:
1694 error = ieee80211_ioctl_getmaccmd(ic, ireq);
1695 break;
1696 case IEEE80211_IOC_BURST:
1697 ireq->i_val = (ic->ic_flags & IEEE80211_F_BURST) != 0;
1698 break;
1699 case IEEE80211_IOC_BMISSTHRESHOLD:
1700 ireq->i_val = ic->ic_bmissthreshold;
1701 break;
1051 case IEEE80211_IOC_MCAST_RATE:
1052 ireq->i_val = ic->ic_mcast_rate;
1053 break;
1054 case IEEE80211_IOC_FRAGTHRESHOLD:
1055 ireq->i_val = ic->ic_fragthreshold;
1056 break;
1057 case IEEE80211_IOC_MACCMD:
1058 error = ieee80211_ioctl_getmaccmd(ic, ireq);
1059 break;
1060 case IEEE80211_IOC_BURST:
1061 ireq->i_val = (ic->ic_flags & IEEE80211_F_BURST) != 0;
1062 break;
1063 case IEEE80211_IOC_BMISSTHRESHOLD:
1064 ireq->i_val = ic->ic_bmissthreshold;
1065 break;
1066 case IEEE80211_IOC_CURCHAN:
1067 error = ieee80211_ioctl_getcurchan(ic, ireq);
1068 break;
1069 case IEEE80211_IOC_SHORTGI:
1070 ireq->i_val = 0;
1071 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI20)
1072 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20;
1073 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI40)
1074 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40;
1075 break;
1076 case IEEE80211_IOC_AMPDU:
1077 ireq->i_val = 0;
1078 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX)
1079 ireq->i_val |= 1;
1080 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_RX)
1081 ireq->i_val |= 2;
1082 break;
1083 case IEEE80211_IOC_AMPDU_LIMIT:
1084 ireq->i_val = ic->ic_ampdu_limit; /* XXX truncation? */
1085 break;
1086 case IEEE80211_IOC_AMPDU_DENSITY:
1087 ireq->i_val = ic->ic_ampdu_density;
1088 break;
1089 case IEEE80211_IOC_AMSDU:
1090 ireq->i_val = 0;
1091 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_TX)
1092 ireq->i_val |= 1;
1093 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_RX)
1094 ireq->i_val |= 2;
1095 break;
1096 case IEEE80211_IOC_AMSDU_LIMIT:
1097 ireq->i_val = ic->ic_amsdu_limit; /* XXX truncation? */
1098 break;
1099 case IEEE80211_IOC_PUREN:
1100 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_PUREN) != 0;
1101 break;
1102 case IEEE80211_IOC_DOTH:
1103 ireq->i_val = (ic->ic_flags & IEEE80211_F_DOTH) != 0;
1104 break;
1105 case IEEE80211_IOC_HTCOMPAT:
1106 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0;
1107 break;
1702 default:
1703 error = EINVAL;
1704 break;
1705 }
1706 return error;
1707}
1708
1709static int

--- 7 unchanged lines hidden (view full) ---

1717 * WPA and/or WME) except that it typically is worthless
1718 * without being able to intervene when processing
1719 * association response frames--so disallow it for now.
1720 */
1721 if (ic->ic_opmode != IEEE80211_M_STA)
1722 return EINVAL;
1723 if (ireq->i_len > IEEE80211_MAX_OPT_IE)
1724 return EINVAL;
1108 default:
1109 error = EINVAL;
1110 break;
1111 }
1112 return error;
1113}
1114
1115static int

--- 7 unchanged lines hidden (view full) ---

1123 * WPA and/or WME) except that it typically is worthless
1124 * without being able to intervene when processing
1125 * association response frames--so disallow it for now.
1126 */
1127 if (ic->ic_opmode != IEEE80211_M_STA)
1128 return EINVAL;
1129 if (ireq->i_len > IEEE80211_MAX_OPT_IE)
1130 return EINVAL;
1131 /* NB: data.length is validated by the wireless extensions code */
1132 /* XXX M_WAITOK after driver lock released */
1725 if (ireq->i_len > 0) {
1726 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT);
1727 if (ie == NULL)
1728 return ENOMEM;
1729 error = copyin(ireq->i_data, ie, ireq->i_len);
1730 if (error) {
1731 FREE(ie, M_DEVBUF);
1732 return error;

--- 12 unchanged lines hidden (view full) ---

1745}
1746
1747static int
1748ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1749{
1750 struct ieee80211req_key ik;
1751 struct ieee80211_node *ni;
1752 struct ieee80211_key *wk;
1133 if (ireq->i_len > 0) {
1134 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT);
1135 if (ie == NULL)
1136 return ENOMEM;
1137 error = copyin(ireq->i_data, ie, ireq->i_len);
1138 if (error) {
1139 FREE(ie, M_DEVBUF);
1140 return error;

--- 12 unchanged lines hidden (view full) ---

1153}
1154
1155static int
1156ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1157{
1158 struct ieee80211req_key ik;
1159 struct ieee80211_node *ni;
1160 struct ieee80211_key *wk;
1753 u_int16_t kid;
1161 uint16_t kid;
1754 int error;
1755
1756 if (ireq->i_len != sizeof(ik))
1757 return EINVAL;
1758 error = copyin(ireq->i_data, &ik, sizeof(ik));
1759 if (error)
1760 return error;
1761 /* NB: cipher support is verified by ieee80211_crypt_newkey */

--- 60 unchanged lines hidden (view full) ---

1822 int kid, error;
1823
1824 if (ireq->i_len != sizeof(dk))
1825 return EINVAL;
1826 error = copyin(ireq->i_data, &dk, sizeof(dk));
1827 if (error)
1828 return error;
1829 kid = dk.idk_keyix;
1162 int error;
1163
1164 if (ireq->i_len != sizeof(ik))
1165 return EINVAL;
1166 error = copyin(ireq->i_data, &ik, sizeof(ik));
1167 if (error)
1168 return error;
1169 /* NB: cipher support is verified by ieee80211_crypt_newkey */

--- 60 unchanged lines hidden (view full) ---

1230 int kid, error;
1231
1232 if (ireq->i_len != sizeof(dk))
1233 return EINVAL;
1234 error = copyin(ireq->i_data, &dk, sizeof(dk));
1235 if (error)
1236 return error;
1237 kid = dk.idk_keyix;
1830 /* XXX u_int8_t -> u_int16_t */
1831 if (dk.idk_keyix == (u_int8_t) IEEE80211_KEYIX_NONE) {
1238 /* XXX uint8_t -> uint16_t */
1239 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1832 struct ieee80211_node *ni;
1833
1834 if (ic->ic_opmode == IEEE80211_M_STA) {
1835 ni = ieee80211_ref_node(ic->ic_bss);
1836 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1837 ieee80211_free_node(ni);
1838 return EADDRNOTAVAIL;
1839 }

--- 25 unchanged lines hidden (view full) ---

1865 mlme->im_op == IEEE80211_MLME_DEAUTH ?
1866 IEEE80211_FC0_SUBTYPE_DEAUTH :
1867 IEEE80211_FC0_SUBTYPE_DISASSOC,
1868 mlme->im_reason);
1869 }
1870 ieee80211_node_leave(ic, ni);
1871}
1872
1240 struct ieee80211_node *ni;
1241
1242 if (ic->ic_opmode == IEEE80211_M_STA) {
1243 ni = ieee80211_ref_node(ic->ic_bss);
1244 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1245 ieee80211_free_node(ni);
1246 return EADDRNOTAVAIL;
1247 }

--- 25 unchanged lines hidden (view full) ---

1273 mlme->im_op == IEEE80211_MLME_DEAUTH ?
1274 IEEE80211_FC0_SUBTYPE_DEAUTH :
1275 IEEE80211_FC0_SUBTYPE_DISASSOC,
1276 mlme->im_reason);
1277 }
1278 ieee80211_node_leave(ic, ni);
1279}
1280
1281struct scanlookup {
1282 const uint8_t *mac;
1283 int esslen;
1284 const uint8_t *essid;
1285 const struct ieee80211_scan_entry *se;
1286};
1287
1288/*
1289 * Match mac address and any ssid.
1290 */
1291static void
1292mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1293{
1294 struct scanlookup *look = arg;
1295
1296 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1297 return;
1298 if (look->esslen != 0) {
1299 if (se->se_ssid[1] != look->esslen)
1300 return;
1301 if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1302 return;
1303 }
1304 look->se = se;
1305}
1306
1873static int
1874ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq)
1875{
1876 struct ieee80211req_mlme mlme;
1877 struct ieee80211_node *ni;
1878 int error;
1879
1880 if (ireq->i_len != sizeof(mlme))
1881 return EINVAL;
1882 error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1883 if (error)
1884 return error;
1885 switch (mlme.im_op) {
1886 case IEEE80211_MLME_ASSOC:
1307static int
1308ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq)
1309{
1310 struct ieee80211req_mlme mlme;
1311 struct ieee80211_node *ni;
1312 int error;
1313
1314 if (ireq->i_len != sizeof(mlme))
1315 return EINVAL;
1316 error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1317 if (error)
1318 return error;
1319 switch (mlme.im_op) {
1320 case IEEE80211_MLME_ASSOC:
1887 if (ic->ic_opmode != IEEE80211_M_STA)
1888 return EINVAL;
1889 /* XXX must be in S_SCAN state? */
1321 /* XXX ibss/ahdemo */
1322 if (ic->ic_opmode == IEEE80211_M_STA) {
1323 struct scanlookup lookup;
1890
1324
1891 if (mlme.im_ssid_len != 0) {
1892 /*
1893 * Desired ssid specified; must match both bssid and
1894 * ssid to distinguish ap advertising multiple ssid's.
1895 */
1896 ni = ieee80211_find_node_with_ssid(&ic->ic_scan,
1897 mlme.im_macaddr,
1898 mlme.im_ssid_len, mlme.im_ssid);
1899 } else {
1900 /*
1901 * Normal case; just match bssid.
1902 */
1903 ni = ieee80211_find_node(&ic->ic_scan, mlme.im_macaddr);
1325 lookup.se = NULL;
1326 lookup.mac = mlme.im_macaddr;
1327 /* XXX use revised api w/ explicit ssid */
1328 lookup.esslen = ic->ic_des_ssid[0].len;
1329 lookup.essid = ic->ic_des_ssid[0].ssid;
1330 ieee80211_scan_iterate(ic, mlmelookup, &lookup);
1331 if (lookup.se != NULL &&
1332 ieee80211_sta_join(ic, lookup.se))
1333 return 0;
1904 }
1334 }
1905 if (ni == NULL)
1906 return EINVAL;
1907 if (!ieee80211_sta_join(ic, ni)) {
1908 ieee80211_free_node(ni);
1909 return EINVAL;
1910 }
1911 break;
1335 return EINVAL;
1912 case IEEE80211_MLME_DISASSOC:
1913 case IEEE80211_MLME_DEAUTH:
1914 switch (ic->ic_opmode) {
1915 case IEEE80211_M_STA:
1916 /* XXX not quite right */
1917 ieee80211_new_state(ic, IEEE80211_S_INIT,
1918 mlme.im_reason);
1919 break;

--- 31 unchanged lines hidden (view full) ---

1951 return EINVAL;
1952 }
1953 return 0;
1954}
1955
1956static int
1957ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq)
1958{
1336 case IEEE80211_MLME_DISASSOC:
1337 case IEEE80211_MLME_DEAUTH:
1338 switch (ic->ic_opmode) {
1339 case IEEE80211_M_STA:
1340 /* XXX not quite right */
1341 ieee80211_new_state(ic, IEEE80211_S_INIT,
1342 mlme.im_reason);
1343 break;

--- 31 unchanged lines hidden (view full) ---

1375 return EINVAL;
1376 }
1377 return 0;
1378}
1379
1380static int
1381ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq)
1382{
1959 u_int8_t mac[IEEE80211_ADDR_LEN];
1383 uint8_t mac[IEEE80211_ADDR_LEN];
1960 const struct ieee80211_aclator *acl = ic->ic_acl;
1961 int error;
1962
1963 if (ireq->i_len != sizeof(mac))
1964 return EINVAL;
1965 error = copyin(ireq->i_data, mac, ireq->i_len);
1966 if (error)
1967 return error;

--- 47 unchanged lines hidden (view full) ---

2015 return 0;
2016}
2017
2018static int
2019ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
2020{
2021 struct ieee80211req_chanlist list;
2022 u_char chanlist[IEEE80211_CHAN_BYTES];
1384 const struct ieee80211_aclator *acl = ic->ic_acl;
1385 int error;
1386
1387 if (ireq->i_len != sizeof(mac))
1388 return EINVAL;
1389 error = copyin(ireq->i_data, mac, ireq->i_len);
1390 if (error)
1391 return error;

--- 47 unchanged lines hidden (view full) ---

1439 return 0;
1440}
1441
1442static int
1443ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
1444{
1445 struct ieee80211req_chanlist list;
1446 u_char chanlist[IEEE80211_CHAN_BYTES];
2023 int i, j, error;
1447 int i, j, nchan, error;
2024
2025 if (ireq->i_len != sizeof(list))
2026 return EINVAL;
2027 error = copyin(ireq->i_data, &list, sizeof(list));
2028 if (error)
2029 return error;
2030 memset(chanlist, 0, sizeof(chanlist));
2031 /*
2032 * Since channel 0 is not available for DS, channel 1
2033 * is assigned to LSB on WaveLAN.
2034 */
2035 if (ic->ic_phytype == IEEE80211_T_DS)
2036 i = 1;
2037 else
2038 i = 0;
1448
1449 if (ireq->i_len != sizeof(list))
1450 return EINVAL;
1451 error = copyin(ireq->i_data, &list, sizeof(list));
1452 if (error)
1453 return error;
1454 memset(chanlist, 0, sizeof(chanlist));
1455 /*
1456 * Since channel 0 is not available for DS, channel 1
1457 * is assigned to LSB on WaveLAN.
1458 */
1459 if (ic->ic_phytype == IEEE80211_T_DS)
1460 i = 1;
1461 else
1462 i = 0;
1463 nchan = 0;
2039 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
2040 /*
2041 * NB: silently discard unavailable channels so users
2042 * can specify 1-255 to get all available channels.
2043 */
1464 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
1465 /*
1466 * NB: silently discard unavailable channels so users
1467 * can specify 1-255 to get all available channels.
1468 */
2044 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i))
1469 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) {
2045 setbit(chanlist, i);
1470 setbit(chanlist, i);
1471 nchan++;
1472 }
2046 }
1473 }
2047 if (ic->ic_ibss_chan == NULL ||
2048 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {
2049 for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
2050 if (isset(chanlist, i)) {
2051 ic->ic_ibss_chan = &ic->ic_channels[i];
2052 goto found;
2053 }
2054 return EINVAL; /* no active channels */
2055found:
2056 ;
2057 }
1474 if (nchan == 0)
1475 return EINVAL;
1476 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1477 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1478 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
2058 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
1479 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
2059 return IS_UP_AUTO(ic) ? ENETRESET : 0;
1480 return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0;
2060}
2061
2062static int
2063ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
2064{
2065 struct ieee80211_node *ni;
1481}
1482
1483static int
1484ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
1485{
1486 struct ieee80211_node *ni;
2066 u_int8_t macaddr[IEEE80211_ADDR_LEN];
1487 uint8_t macaddr[IEEE80211_ADDR_LEN];
2067 int error;
2068
2069 /*
2070 * NB: we could copyin ieee80211req_sta_stats so apps
2071 * could make selective changes but that's overkill;
2072 * just clear all stats for now.
2073 */
2074 if (ireq->i_len < IEEE80211_ADDR_LEN)

--- 113 unchanged lines hidden (view full) ---

2188 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM;
2189 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP;
2190 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP;
2191 }
2192 return 0;
2193}
2194
2195static int
1488 int error;
1489
1490 /*
1491 * NB: we could copyin ieee80211req_sta_stats so apps
1492 * could make selective changes but that's overkill;
1493 * just clear all stats for now.
1494 */
1495 if (ireq->i_len < IEEE80211_ADDR_LEN)

--- 113 unchanged lines hidden (view full) ---

1609 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM;
1610 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP;
1611 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP;
1612 }
1613 return 0;
1614}
1615
1616static int
1617find11gchannel(struct ieee80211com *ic, int start, int freq)
1618{
1619 const struct ieee80211_channel *c;
1620 int i;
1621
1622 for (i = start+1; i < ic->ic_nchans; i++) {
1623 c = &ic->ic_channels[i];
1624 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1625 return 1;
1626 }
1627 /* NB: should not be needed but in case things are mis-sorted */
1628 for (i = 0; i < start; i++) {
1629 c = &ic->ic_channels[i];
1630 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1631 return 1;
1632 }
1633 return 0;
1634}
1635
1636static struct ieee80211_channel *
1637findchannel(struct ieee80211com *ic, int ieee, int mode)
1638{
1639 static const u_int chanflags[IEEE80211_MODE_MAX] = {
1640 0, /* IEEE80211_MODE_AUTO */
1641 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
1642 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
1643 IEEE80211_CHAN_G, /* IEEE80211_MODE_11G */
1644 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
1645 IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */
1646 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */
1647 IEEE80211_CHAN_STURBO, /* IEEE80211_MODE_STURBO_A */
1648 /* NB: handled specially below */
1649 IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA */
1650 IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG */
1651 };
1652 u_int modeflags;
1653 int i;
1654
1655 KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode));
1656 modeflags = chanflags[mode];
1657 KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO,
1658 ("no chanflags for mode %u", mode));
1659 for (i = 0; i < ic->ic_nchans; i++) {
1660 struct ieee80211_channel *c = &ic->ic_channels[i];
1661
1662 if (c->ic_ieee != ieee)
1663 continue;
1664 if (mode == IEEE80211_MODE_AUTO) {
1665 /* ignore turbo channels for autoselect */
1666 if (IEEE80211_IS_CHAN_TURBO(c))
1667 continue;
1668 /*
1669 * XXX special-case 11b/g channels so we
1670 * always select the g channel if both
1671 * are present.
1672 * XXX prefer HT to non-HT?
1673 */
1674 if (!IEEE80211_IS_CHAN_B(c) ||
1675 !find11gchannel(ic, i, c->ic_freq))
1676 return c;
1677 } else {
1678 /* must check HT specially */
1679 if ((mode == IEEE80211_MODE_11NA ||
1680 mode == IEEE80211_MODE_11NG) &&
1681 !IEEE80211_IS_CHAN_HT(c))
1682 continue;
1683 if ((c->ic_flags & modeflags) == modeflags)
1684 return c;
1685 }
1686 }
1687 return NULL;
1688}
1689
1690/*
1691 * Check the specified against any desired mode (aka netband).
1692 * This is only used (presently) when operating in hostap mode
1693 * to enforce consistency.
1694 */
1695static int
1696check_mode_consistency(const struct ieee80211_channel *c, int mode)
1697{
1698 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
1699
1700 switch (mode) {
1701 case IEEE80211_MODE_11B:
1702 return (IEEE80211_IS_CHAN_B(c));
1703 case IEEE80211_MODE_11G:
1704 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
1705 case IEEE80211_MODE_11A:
1706 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
1707 case IEEE80211_MODE_STURBO_A:
1708 return (IEEE80211_IS_CHAN_STURBO(c));
1709 case IEEE80211_MODE_11NA:
1710 return (IEEE80211_IS_CHAN_HTA(c));
1711 case IEEE80211_MODE_11NG:
1712 return (IEEE80211_IS_CHAN_HTG(c));
1713 }
1714 return 1;
1715
1716}
1717
1718/*
1719 * Common code to set the current channel. If the device
1720 * is up and running this may result in an immediate channel
1721 * change or a kick of the state machine.
1722 */
1723static int
1724setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
1725{
1726 int error;
1727
1728 if (c != IEEE80211_CHAN_ANYC) {
1729 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1730 !check_mode_consistency(c, ic->ic_des_mode))
1731 return EINVAL;
1732 if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan)
1733 return 0; /* NB: nothing to do */
1734 }
1735 ic->ic_des_chan = c;
1736
1737 error = 0;
1738 if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
1739 ic->ic_opmode == IEEE80211_M_WDS) &&
1740 ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1741 /*
1742 * Monitor and wds modes can switch directly.
1743 */
1744 ic->ic_curchan = ic->ic_des_chan;
1745 if (ic->ic_state == IEEE80211_S_RUN)
1746 ic->ic_set_channel(ic);
1747 } else {
1748 /*
1749 * Need to go through the state machine in case we
1750 * need to reassociate or the like. The state machine
1751 * will pickup the desired channel and avoid scanning.
1752 */
1753 if (IS_UP_AUTO(ic))
1754 error = ieee80211_init(ic, RESCAN);
1755 else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1756 /*
1757 * When not up+running and a real channel has
1758 * been specified fix the current channel so
1759 * there is immediate feedback; e.g. via ifconfig.
1760 */
1761 ic->ic_curchan = ic->ic_des_chan;
1762 }
1763 }
1764 return error;
1765}
1766
1767/*
1768 * Old api for setting the current channel; this is
1769 * deprecated because channel numbers are ambiguous.
1770 */
1771static int
1772ieee80211_ioctl_setchannel(struct ieee80211com *ic,
1773 const struct ieee80211req *ireq)
1774{
1775 struct ieee80211_channel *c;
1776
1777 /* XXX 0xffff overflows 16-bit signed */
1778 if (ireq->i_val == 0 ||
1779 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
1780 c = IEEE80211_CHAN_ANYC;
1781 } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
1782 return EINVAL;
1783 } else {
1784 struct ieee80211_channel *c2;
1785
1786 c = findchannel(ic, ireq->i_val, ic->ic_des_mode);
1787 if (c == NULL) {
1788 c = findchannel(ic, ireq->i_val,
1789 IEEE80211_MODE_AUTO);
1790 if (c == NULL)
1791 return EINVAL;
1792 }
1793 /*
1794 * Fine tune channel selection based on desired mode:
1795 * if 11b is requested, find the 11b version of any
1796 * 11g channel returned,
1797 * if static turbo, find the turbo version of any
1798 * 11a channel return,
1799 * if 11na is requested, find the ht version of any
1800 * 11a channel returned,
1801 * if 11ng is requested, find the ht version of any
1802 * 11g channel returned,
1803 * otherwise we should be ok with what we've got.
1804 */
1805 switch (ic->ic_des_mode) {
1806 case IEEE80211_MODE_11B:
1807 if (IEEE80211_IS_CHAN_ANYG(c)) {
1808 c2 = findchannel(ic, ireq->i_val,
1809 IEEE80211_MODE_11B);
1810 /* NB: should not happen, =>'s 11g w/o 11b */
1811 if (c2 != NULL)
1812 c = c2;
1813 }
1814 break;
1815 case IEEE80211_MODE_TURBO_A:
1816 if (IEEE80211_IS_CHAN_A(c)) {
1817 c2 = findchannel(ic, ireq->i_val,
1818 IEEE80211_MODE_TURBO_A);
1819 if (c2 != NULL)
1820 c = c2;
1821 }
1822 break;
1823 case IEEE80211_MODE_11NA:
1824 if (IEEE80211_IS_CHAN_A(c)) {
1825 c2 = findchannel(ic, ireq->i_val,
1826 IEEE80211_MODE_11NA);
1827 if (c2 != NULL)
1828 c = c2;
1829 }
1830 break;
1831 case IEEE80211_MODE_11NG:
1832 if (IEEE80211_IS_CHAN_ANYG(c)) {
1833 c2 = findchannel(ic, ireq->i_val,
1834 IEEE80211_MODE_11NG);
1835 if (c2 != NULL)
1836 c = c2;
1837 }
1838 break;
1839 default: /* NB: no static turboG */
1840 break;
1841 }
1842 }
1843 return setcurchan(ic, c);
1844}
1845
1846/*
1847 * New/current api for setting the current channel; a complete
1848 * channel description is provide so there is no ambiguity in
1849 * identifying the channel.
1850 */
1851static int
1852ieee80211_ioctl_setcurchan(struct ieee80211com *ic,
1853 const struct ieee80211req *ireq)
1854{
1855 struct ieee80211_channel chan, *c;
1856 int error;
1857
1858 if (ireq->i_len != sizeof(chan))
1859 return EINVAL;
1860 error = copyin(ireq->i_data, &chan, sizeof(chan));
1861 if (error != 0)
1862 return error;
1863 /* XXX 0xffff overflows 16-bit signed */
1864 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
1865 c = IEEE80211_CHAN_ANYC;
1866 } else {
1867 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
1868 if (c == NULL)
1869 return EINVAL;
1870 }
1871 return setcurchan(ic, c);
1872}
1873
1874static int
2196ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
2197{
1875ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
1876{
2198 static const u_int8_t zerobssid[IEEE80211_ADDR_LEN];
1877 static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
2199 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
2200 int error;
2201 const struct ieee80211_authenticator *auth;
1878 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
1879 int error;
1880 const struct ieee80211_authenticator *auth;
2202 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE];
1881 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
2203 char tmpssid[IEEE80211_NWID_LEN];
1882 char tmpssid[IEEE80211_NWID_LEN];
2204 u_int8_t tmpbssid[IEEE80211_ADDR_LEN];
1883 uint8_t tmpbssid[IEEE80211_ADDR_LEN];
2205 struct ieee80211_key *k;
2206 int j, caps;
2207 u_int kid;
2208
2209 error = 0;
2210 switch (ireq->i_type) {
2211 case IEEE80211_IOC_SSID:
2212 if (ireq->i_val != 0 ||
2213 ireq->i_len > IEEE80211_NWID_LEN)
2214 return EINVAL;
2215 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
2216 if (error)
2217 break;
1884 struct ieee80211_key *k;
1885 int j, caps;
1886 u_int kid;
1887
1888 error = 0;
1889 switch (ireq->i_type) {
1890 case IEEE80211_IOC_SSID:
1891 if (ireq->i_val != 0 ||
1892 ireq->i_len > IEEE80211_NWID_LEN)
1893 return EINVAL;
1894 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
1895 if (error)
1896 break;
2218 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
2219 ic->ic_des_esslen = ireq->i_len;
2220 memcpy(ic->ic_des_essid, tmpssid, ireq->i_len);
2221 error = ENETRESET;
1897 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
1898 ic->ic_des_ssid[0].len = ireq->i_len;
1899 memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len);
1900 ic->ic_des_nssid = (ireq->i_len > 0);
1901 if (IS_UP_AUTO(ic))
1902 error = ieee80211_init(ic, RESCAN);
2222 break;
2223 case IEEE80211_IOC_WEP:
2224 switch (ireq->i_val) {
2225 case IEEE80211_WEP_OFF:
2226 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
2227 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2228 break;
2229 case IEEE80211_WEP_ON:
2230 ic->ic_flags |= IEEE80211_F_PRIVACY;
2231 ic->ic_flags |= IEEE80211_F_DROPUNENC;
2232 break;
2233 case IEEE80211_WEP_MIXED:
2234 ic->ic_flags |= IEEE80211_F_PRIVACY;
2235 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2236 break;
2237 }
1903 break;
1904 case IEEE80211_IOC_WEP:
1905 switch (ireq->i_val) {
1906 case IEEE80211_WEP_OFF:
1907 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
1908 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1909 break;
1910 case IEEE80211_WEP_ON:
1911 ic->ic_flags |= IEEE80211_F_PRIVACY;
1912 ic->ic_flags |= IEEE80211_F_DROPUNENC;
1913 break;
1914 case IEEE80211_WEP_MIXED:
1915 ic->ic_flags |= IEEE80211_F_PRIVACY;
1916 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1917 break;
1918 }
2238 error = ENETRESET;
1919 if (IS_UP_AUTO(ic))
1920 error = ieee80211_init(ic, RESCAN);
2239 break;
2240 case IEEE80211_IOC_WEPKEY:
2241 kid = (u_int) ireq->i_val;
2242 if (kid >= IEEE80211_WEP_NKID)
2243 return EINVAL;
2244 k = &ic->ic_nw_keys[kid];
2245 if (ireq->i_len == 0) {
2246 /* zero-len =>'s delete any existing key */

--- 12 unchanged lines hidden (view full) ---

2259 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
2260 k->wk_keylen = ireq->i_len;
2261 memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
2262 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr))
2263 error = EINVAL;
2264 } else
2265 error = EINVAL;
2266 ieee80211_key_update_end(ic);
1921 break;
1922 case IEEE80211_IOC_WEPKEY:
1923 kid = (u_int) ireq->i_val;
1924 if (kid >= IEEE80211_WEP_NKID)
1925 return EINVAL;
1926 k = &ic->ic_nw_keys[kid];
1927 if (ireq->i_len == 0) {
1928 /* zero-len =>'s delete any existing key */

--- 12 unchanged lines hidden (view full) ---

1941 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
1942 k->wk_keylen = ireq->i_len;
1943 memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
1944 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr))
1945 error = EINVAL;
1946 } else
1947 error = EINVAL;
1948 ieee80211_key_update_end(ic);
2267 if (!error) /* NB: for compatibility */
2268 error = ENETRESET;
2269 break;
2270 case IEEE80211_IOC_WEPTXKEY:
2271 kid = (u_int) ireq->i_val;
2272 if (kid >= IEEE80211_WEP_NKID &&
1949 break;
1950 case IEEE80211_IOC_WEPTXKEY:
1951 kid = (u_int) ireq->i_val;
1952 if (kid >= IEEE80211_WEP_NKID &&
2273 (u_int16_t) kid != IEEE80211_KEYIX_NONE)
1953 (uint16_t) kid != IEEE80211_KEYIX_NONE)
2274 return EINVAL;
2275 ic->ic_def_txkey = kid;
1954 return EINVAL;
1955 ic->ic_def_txkey = kid;
2276 error = ENETRESET; /* push to hardware */
2277 break;
2278 case IEEE80211_IOC_AUTHMODE:
2279 switch (ireq->i_val) {
2280 case IEEE80211_AUTH_WPA:
2281 case IEEE80211_AUTH_8021X: /* 802.1x */
2282 case IEEE80211_AUTH_OPEN: /* open */
2283 case IEEE80211_AUTH_SHARED: /* shared-key */
2284 case IEEE80211_AUTH_AUTO: /* auto */

--- 23 unchanged lines hidden (view full) ---

2308 /* XXX PRIVACY handling? */
2309 /* XXX what's the right way to do this? */
2310 break;
2311 }
2312 /* NB: authenticator attach/detach happens on state change */
2313 ic->ic_bss->ni_authmode = ireq->i_val;
2314 /* XXX mixed/mode/usage? */
2315 ic->ic_auth = auth;
1956 break;
1957 case IEEE80211_IOC_AUTHMODE:
1958 switch (ireq->i_val) {
1959 case IEEE80211_AUTH_WPA:
1960 case IEEE80211_AUTH_8021X: /* 802.1x */
1961 case IEEE80211_AUTH_OPEN: /* open */
1962 case IEEE80211_AUTH_SHARED: /* shared-key */
1963 case IEEE80211_AUTH_AUTO: /* auto */

--- 23 unchanged lines hidden (view full) ---

1987 /* XXX PRIVACY handling? */
1988 /* XXX what's the right way to do this? */
1989 break;
1990 }
1991 /* NB: authenticator attach/detach happens on state change */
1992 ic->ic_bss->ni_authmode = ireq->i_val;
1993 /* XXX mixed/mode/usage? */
1994 ic->ic_auth = auth;
2316 error = ENETRESET;
1995 if (IS_UP_AUTO(ic))
1996 error = ieee80211_init(ic, RESCAN);
2317 break;
2318 case IEEE80211_IOC_CHANNEL:
1997 break;
1998 case IEEE80211_IOC_CHANNEL:
2319 /* XXX 0xffff overflows 16-bit signed */
2320 if (ireq->i_val == 0 ||
2321 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY)
2322 ic->ic_des_chan = IEEE80211_CHAN_ANYC;
2323 else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX ||
2324 isclr(ic->ic_chan_active, ireq->i_val)) {
2325 return EINVAL;
2326 } else
2327 ic->ic_ibss_chan = ic->ic_des_chan =
2328 &ic->ic_channels[ireq->i_val];
2329 switch (ic->ic_state) {
2330 case IEEE80211_S_INIT:
2331 case IEEE80211_S_SCAN:
2332 error = ENETRESET;
2333 break;
2334 default:
2335 /*
2336 * If the desired channel has changed (to something
2337 * other than any) and we're not already scanning,
2338 * then kick the state machine.
2339 */
2340 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
2341 ic->ic_bss->ni_chan != ic->ic_des_chan &&
2342 (ic->ic_flags & IEEE80211_F_SCAN) == 0)
2343 error = ENETRESET;
2344 break;
2345 }
2346 if (error == ENETRESET &&
2347 ic->ic_opmode == IEEE80211_M_MONITOR) {
2348 if (IS_UP(ic)) {
2349 /*
2350 * Monitor mode can switch directly.
2351 */
2352 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
2353 ic->ic_curchan = ic->ic_des_chan;
2354 error = ic->ic_reset(ic->ic_ifp);
2355 } else
2356 error = 0;
2357 }
1999 error = ieee80211_ioctl_setchannel(ic, ireq);
2358 break;
2359 case IEEE80211_IOC_POWERSAVE:
2360 switch (ireq->i_val) {
2361 case IEEE80211_POWERSAVE_OFF:
2362 if (ic->ic_flags & IEEE80211_F_PMGTON) {
2363 ic->ic_flags &= ~IEEE80211_F_PMGTON;
2364 error = ENETRESET;
2365 }

--- 31 unchanged lines hidden (view full) ---

2397 ic->ic_rtsthreshold = ireq->i_val;
2398 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2399 break;
2400 case IEEE80211_IOC_PROTMODE:
2401 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2402 return EINVAL;
2403 ic->ic_protmode = ireq->i_val;
2404 /* NB: if not operating in 11g this can wait */
2000 break;
2001 case IEEE80211_IOC_POWERSAVE:
2002 switch (ireq->i_val) {
2003 case IEEE80211_POWERSAVE_OFF:
2004 if (ic->ic_flags & IEEE80211_F_PMGTON) {
2005 ic->ic_flags &= ~IEEE80211_F_PMGTON;
2006 error = ENETRESET;
2007 }

--- 31 unchanged lines hidden (view full) ---

2039 ic->ic_rtsthreshold = ireq->i_val;
2040 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2041 break;
2042 case IEEE80211_IOC_PROTMODE:
2043 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2044 return EINVAL;
2045 ic->ic_protmode = ireq->i_val;
2046 /* NB: if not operating in 11g this can wait */
2405 if (ic->ic_curmode == IEEE80211_MODE_11G)
2047 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2048 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2406 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2407 break;
2408 case IEEE80211_IOC_TXPOWER:
2409 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2410 return EINVAL;
2049 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2050 break;
2051 case IEEE80211_IOC_TXPOWER:
2052 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2053 return EINVAL;
2411 if (!(IEEE80211_TXPOWER_MIN < ireq->i_val &&
2412 ireq->i_val < IEEE80211_TXPOWER_MAX))
2054 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
2055 ireq->i_val <= IEEE80211_TXPOWER_MAX))
2413 return EINVAL;
2414 ic->ic_txpowlimit = ireq->i_val;
2415 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2416 break;
2417 case IEEE80211_IOC_ROAMING:
2418 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2419 ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2420 return EINVAL;

--- 44 unchanged lines hidden (view full) ---

2465 break;
2466 case 2:
2467 ic->ic_flags |= IEEE80211_F_WPA2;
2468 break;
2469 case 3:
2470 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2471 break;
2472 }
2056 return EINVAL;
2057 ic->ic_txpowlimit = ireq->i_val;
2058 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2059 break;
2060 case IEEE80211_IOC_ROAMING:
2061 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2062 ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2063 return EINVAL;

--- 44 unchanged lines hidden (view full) ---

2108 break;
2109 case 2:
2110 ic->ic_flags |= IEEE80211_F_WPA2;
2111 break;
2112 case 3:
2113 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2114 break;
2115 }
2473 error = ENETRESET; /* XXX? */
2116 error = ENETRESET;
2474 break;
2475 case IEEE80211_IOC_WME:
2476 if (ireq->i_val) {
2477 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
2478 return EINVAL;
2479 ic->ic_flags |= IEEE80211_F_WME;
2480 } else
2481 ic->ic_flags &= ~IEEE80211_F_WME;
2117 break;
2118 case IEEE80211_IOC_WME:
2119 if (ireq->i_val) {
2120 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
2121 return EINVAL;
2122 ic->ic_flags |= IEEE80211_F_WME;
2123 } else
2124 ic->ic_flags &= ~IEEE80211_F_WME;
2482 error = ENETRESET; /* XXX maybe not for station? */
2125 if (IS_UP_AUTO(ic))
2126 error = ieee80211_init(ic, 0);
2483 break;
2484 case IEEE80211_IOC_HIDESSID:
2485 if (ireq->i_val)
2486 ic->ic_flags |= IEEE80211_F_HIDESSID;
2487 else
2488 ic->ic_flags &= ~IEEE80211_F_HIDESSID;
2489 error = ENETRESET;
2490 break;

--- 46 unchanged lines hidden (view full) ---

2537 case IEEE80211_IOC_UCASTKEYLEN:
2538 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2539 return EINVAL;
2540 /* XXX no way to verify driver capability */
2541 rsn->rsn_ucastkeylen = ireq->i_val;
2542 break;
2543 case IEEE80211_IOC_DRIVER_CAPS:
2544 /* NB: for testing */
2127 break;
2128 case IEEE80211_IOC_HIDESSID:
2129 if (ireq->i_val)
2130 ic->ic_flags |= IEEE80211_F_HIDESSID;
2131 else
2132 ic->ic_flags &= ~IEEE80211_F_HIDESSID;
2133 error = ENETRESET;
2134 break;

--- 46 unchanged lines hidden (view full) ---

2181 case IEEE80211_IOC_UCASTKEYLEN:
2182 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2183 return EINVAL;
2184 /* XXX no way to verify driver capability */
2185 rsn->rsn_ucastkeylen = ireq->i_val;
2186 break;
2187 case IEEE80211_IOC_DRIVER_CAPS:
2188 /* NB: for testing */
2545 ic->ic_caps = (((u_int16_t) ireq->i_val) << 16) |
2546 ((u_int16_t) ireq->i_len);
2189 ic->ic_caps = (((uint16_t) ireq->i_val) << 16) |
2190 ((uint16_t) ireq->i_len);
2547 break;
2548 case IEEE80211_IOC_KEYMGTALGS:
2549 /* XXX check */
2550 rsn->rsn_keymgmtset = ireq->i_val;
2551 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2552 break;
2553 case IEEE80211_IOC_RSNCAPS:
2554 /* XXX check */

--- 6 unchanged lines hidden (view full) ---

2561 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2562 if (error)
2563 break;
2564 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid);
2565 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid))
2566 ic->ic_flags &= ~IEEE80211_F_DESBSSID;
2567 else
2568 ic->ic_flags |= IEEE80211_F_DESBSSID;
2191 break;
2192 case IEEE80211_IOC_KEYMGTALGS:
2193 /* XXX check */
2194 rsn->rsn_keymgmtset = ireq->i_val;
2195 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2196 break;
2197 case IEEE80211_IOC_RSNCAPS:
2198 /* XXX check */

--- 6 unchanged lines hidden (view full) ---

2205 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2206 if (error)
2207 break;
2208 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid);
2209 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid))
2210 ic->ic_flags &= ~IEEE80211_F_DESBSSID;
2211 else
2212 ic->ic_flags |= IEEE80211_F_DESBSSID;
2569 error = ENETRESET;
2213 if (IS_UP_AUTO(ic))
2214 error = ieee80211_init(ic, RESCAN);
2570 break;
2571 case IEEE80211_IOC_CHANLIST:
2572 error = ieee80211_ioctl_setchanlist(ic, ireq);
2573 break;
2574 case IEEE80211_IOC_SCAN_REQ:
2215 break;
2216 case IEEE80211_IOC_CHANLIST:
2217 error = ieee80211_ioctl_setchanlist(ic, ireq);
2218 break;
2219 case IEEE80211_IOC_SCAN_REQ:
2575 if (ic->ic_opmode == IEEE80211_M_HOSTAP) /* XXX ignore */
2576 break;
2577 error = ieee80211_setupscan(ic, ic->ic_chan_avail);
2578 if (error == 0) /* XXX background scan */
2579 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2220 if (!IS_UP(ic))
2221 return EINVAL;
2222 (void) ieee80211_start_scan(ic,
2223 IEEE80211_SCAN_ACTIVE |
2224 IEEE80211_SCAN_NOPICK |
2225 IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,
2226 /* XXX use ioctl params */
2227 ic->ic_des_nssid, ic->ic_des_ssid);
2580 break;
2581 case IEEE80211_IOC_ADDMAC:
2582 case IEEE80211_IOC_DELMAC:
2583 error = ieee80211_ioctl_macmac(ic, ireq);
2584 break;
2585 case IEEE80211_IOC_MACCMD:
2586 error = ieee80211_ioctl_setmaccmd(ic, ireq);
2587 break;

--- 34 unchanged lines hidden (view full) ---

2622 error = EINVAL;
2623 break;
2624 case IEEE80211_IOC_PUREG:
2625 if (ireq->i_val)
2626 ic->ic_flags |= IEEE80211_F_PUREG;
2627 else
2628 ic->ic_flags &= ~IEEE80211_F_PUREG;
2629 /* NB: reset only if we're operating on an 11g channel */
2228 break;
2229 case IEEE80211_IOC_ADDMAC:
2230 case IEEE80211_IOC_DELMAC:
2231 error = ieee80211_ioctl_macmac(ic, ireq);
2232 break;
2233 case IEEE80211_IOC_MACCMD:
2234 error = ieee80211_ioctl_setmaccmd(ic, ireq);
2235 break;

--- 34 unchanged lines hidden (view full) ---

2270 error = EINVAL;
2271 break;
2272 case IEEE80211_IOC_PUREG:
2273 if (ireq->i_val)
2274 ic->ic_flags |= IEEE80211_F_PUREG;
2275 else
2276 ic->ic_flags &= ~IEEE80211_F_PUREG;
2277 /* NB: reset only if we're operating on an 11g channel */
2630 if (ic->ic_curmode == IEEE80211_MODE_11G)
2278 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2279 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2631 error = ENETRESET;
2632 break;
2280 error = ENETRESET;
2281 break;
2282 case IEEE80211_IOC_FF:
2283 if (ireq->i_val) {
2284 if ((ic->ic_caps & IEEE80211_C_FF) == 0)
2285 return EINVAL;
2286 ic->ic_flags |= IEEE80211_F_FF;
2287 } else
2288 ic->ic_flags &= ~IEEE80211_F_FF;
2289 error = ENETRESET;
2290 break;
2291 case IEEE80211_IOC_TURBOP:
2292 if (ireq->i_val) {
2293 if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0)
2294 return EINVAL;
2295 ic->ic_flags |= IEEE80211_F_TURBOP;
2296 } else
2297 ic->ic_flags &= ~IEEE80211_F_TURBOP;
2298 error = ENETRESET;
2299 break;
2300 case IEEE80211_IOC_BGSCAN:
2301 if (ireq->i_val) {
2302 if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0)
2303 return EINVAL;
2304 ic->ic_flags |= IEEE80211_F_BGSCAN;
2305 } else
2306 ic->ic_flags &= ~IEEE80211_F_BGSCAN;
2307 break;
2308 case IEEE80211_IOC_BGSCAN_IDLE:
2309 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
2310 ic->ic_bgscanidle = ireq->i_val*hz/1000;
2311 else
2312 error = EINVAL;
2313 break;
2314 case IEEE80211_IOC_BGSCAN_INTERVAL:
2315 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
2316 ic->ic_bgscanintvl = ireq->i_val*hz;
2317 else
2318 error = EINVAL;
2319 break;
2320 case IEEE80211_IOC_SCANVALID:
2321 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
2322 ic->ic_scanvalid = ireq->i_val*hz;
2323 else
2324 error = EINVAL;
2325 break;
2326 case IEEE80211_IOC_ROAM_RSSI_11A:
2327 ic->ic_roam.rssi11a = ireq->i_val;
2328 break;
2329 case IEEE80211_IOC_ROAM_RSSI_11B:
2330 ic->ic_roam.rssi11bOnly = ireq->i_val;
2331 break;
2332 case IEEE80211_IOC_ROAM_RSSI_11G:
2333 ic->ic_roam.rssi11b = ireq->i_val;
2334 break;
2335 case IEEE80211_IOC_ROAM_RATE_11A:
2336 ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL;
2337 break;
2338 case IEEE80211_IOC_ROAM_RATE_11B:
2339 ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL;
2340 break;
2341 case IEEE80211_IOC_ROAM_RATE_11G:
2342 ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL;
2343 break;
2633 case IEEE80211_IOC_MCAST_RATE:
2634 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL;
2635 break;
2636 case IEEE80211_IOC_FRAGTHRESHOLD:
2637 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 &&
2638 ireq->i_val != IEEE80211_FRAG_MAX)
2639 return EINVAL;
2640 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&

--- 13 unchanged lines hidden (view full) ---

2654 break;
2655 case IEEE80211_IOC_BMISSTHRESHOLD:
2656 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2657 ireq->i_val <= IEEE80211_HWBMISS_MAX))
2658 return EINVAL;
2659 ic->ic_bmissthreshold = ireq->i_val;
2660 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2661 break;
2344 case IEEE80211_IOC_MCAST_RATE:
2345 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL;
2346 break;
2347 case IEEE80211_IOC_FRAGTHRESHOLD:
2348 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 &&
2349 ireq->i_val != IEEE80211_FRAG_MAX)
2350 return EINVAL;
2351 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&

--- 13 unchanged lines hidden (view full) ---

2365 break;
2366 case IEEE80211_IOC_BMISSTHRESHOLD:
2367 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2368 ireq->i_val <= IEEE80211_HWBMISS_MAX))
2369 return EINVAL;
2370 ic->ic_bmissthreshold = ireq->i_val;
2371 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2372 break;
2373 case IEEE80211_IOC_CURCHAN:
2374 error = ieee80211_ioctl_setcurchan(ic, ireq);
2375 break;
2376 case IEEE80211_IOC_SHORTGI:
2377 if (ireq->i_val) {
2378#define IEEE80211_HTCAP_SHORTGI \
2379 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2380 if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
2381 return EINVAL;
2382 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
2383 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20;
2384 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
2385 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40;
2386#undef IEEE80211_HTCAP_SHORTGI
2387 } else
2388 ic->ic_flags_ext &=
2389 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40);
2390 /* XXX kick state machine? */
2391 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2392 break;
2393 case IEEE80211_IOC_AMPDU:
2394 if (ireq->i_val) {
2395 if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0)
2396 return EINVAL;
2397 if (ireq->i_val & 1)
2398 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX;
2399 if (ireq->i_val & 2)
2400 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX;
2401 } else
2402 ic->ic_flags_ext &=
2403 ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX);
2404 /* NB: reset only if we're operating on an 11n channel */
2405 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2406 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2407 error = ENETRESET;
2408 break;
2409 case IEEE80211_IOC_AMPDU_LIMIT:
2410 /* XXX validate */
2411 ic->ic_ampdu_limit = ireq->i_val;
2412 break;
2413 case IEEE80211_IOC_AMPDU_DENSITY:
2414 /* XXX validate */
2415 ic->ic_ampdu_density = ireq->i_val;
2416 break;
2417 case IEEE80211_IOC_AMSDU:
2418 if (ireq->i_val) {
2419 if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0)
2420 return EINVAL;
2421 if (ireq->i_val & 1)
2422 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
2423 if (ireq->i_val & 2)
2424 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
2425 } else
2426 ic->ic_flags_ext &=
2427 ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX);
2428 /* NB: reset only if we're operating on an 11n channel */
2429 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2430 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2431 error = ENETRESET;
2432 break;
2433 case IEEE80211_IOC_AMSDU_LIMIT:
2434 /* XXX validate */
2435 ic->ic_amsdu_limit = ireq->i_val; /* XXX truncation? */
2436 break;
2437 case IEEE80211_IOC_PUREN:
2438 if (ireq->i_val) {
2439 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2440 return EINVAL;
2441 ic->ic_flags_ext |= IEEE80211_FEXT_PUREN;
2442 } else
2443 ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN;
2444 /* NB: reset only if we're operating on an 11n channel */
2445 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2446 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2447 error = ENETRESET;
2448 break;
2449 case IEEE80211_IOC_DOTH:
2450 if (ireq->i_val) {
2451#if 0
2452 /* XXX no capability */
2453 if ((ic->ic_caps & IEEE80211_C_DOTH) == 0)
2454 return EINVAL;
2455#endif
2456 ic->ic_flags |= IEEE80211_F_DOTH;
2457 } else
2458 ic->ic_flags &= ~IEEE80211_F_DOTH;
2459 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2460 break;
2461 case IEEE80211_IOC_HTCOMPAT:
2462 if (ireq->i_val) {
2463 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2464 return EINVAL;
2465 ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT;
2466 } else
2467 ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT;
2468 /* NB: reset only if we're operating on an 11n channel */
2469 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2470 IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2471 error = ENETRESET;
2472 break;
2662 default:
2663 error = EINVAL;
2664 break;
2665 }
2473 default:
2474 error = EINVAL;
2475 break;
2476 }
2666 if (error == ENETRESET && !IS_UP_AUTO(ic))
2667 error = 0;
2477 if (error == ENETRESET)
2478 error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0;
2668 return error;
2669}
2670
2671int
2672ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data)
2673{
2674 struct ifnet *ifp = ic->ic_ifp;
2675 int error = 0;

--- 11 unchanged lines hidden (view full) ---

2687 (struct ieee80211req *) data);
2688 break;
2689 case SIOCS80211:
2690 error = priv_check(curthread, PRIV_NET80211_MANAGE);
2691 if (error == 0)
2692 error = ieee80211_ioctl_set80211(ic, cmd,
2693 (struct ieee80211req *) data);
2694 break;
2479 return error;
2480}
2481
2482int
2483ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data)
2484{
2485 struct ifnet *ifp = ic->ic_ifp;
2486 int error = 0;

--- 11 unchanged lines hidden (view full) ---

2498 (struct ieee80211req *) data);
2499 break;
2500 case SIOCS80211:
2501 error = priv_check(curthread, PRIV_NET80211_MANAGE);
2502 if (error == 0)
2503 error = ieee80211_ioctl_set80211(ic, cmd,
2504 (struct ieee80211req *) data);
2505 break;
2695 case SIOCGIFGENERIC:
2696 error = ieee80211_cfgget(ic, cmd, data);
2697 break;
2698 case SIOCSIFGENERIC:
2699 error = priv_check(curthread, PRIV_NET80211_MANAGE);
2700 if (error)
2701 break;
2702 error = ieee80211_cfgset(ic, cmd, data);
2703 break;
2704 case SIOCG80211STATS:
2705 ifr = (struct ifreq *)data;
2706 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
2707 break;
2708 case SIOCSIFMTU:
2709 ifr = (struct ifreq *)data;
2710 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
2711 ifr->ifr_mtu <= IEEE80211_MTU_MAX))

--- 55 unchanged lines hidden ---
2506 case SIOCG80211STATS:
2507 ifr = (struct ifreq *)data;
2508 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
2509 break;
2510 case SIOCSIFMTU:
2511 ifr = (struct ifreq *)data;
2512 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
2513 ifr->ifr_mtu <= IEEE80211_MTU_MAX))

--- 55 unchanged lines hidden ---