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