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