The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net80211/ieee80211_ioctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 9985790a462851906fd45ef33d74304b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.