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 /*      $OpenBSD: ieee80211_ioctl.c,v 1.81 2022/03/07 08:13:13 stsp Exp $       */
    2 /*      $NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $      */
    3 
    4 /*-
    5  * Copyright (c) 2001 Atsushi Onoe
    6  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * IEEE 802.11 ioctl support
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/socket.h>
   39 #include <sys/sockio.h>
   40 #include <sys/systm.h>
   41 #include <sys/endian.h>
   42 #include <sys/tree.h>
   43 
   44 #include <net/if.h>
   45 #include <net/if_media.h>
   46 
   47 #include <netinet/in.h>
   48 #include <netinet/if_ether.h>
   49 
   50 #include <net80211/ieee80211_var.h>
   51 #include <net80211/ieee80211_crypto.h>
   52 #include <net80211/ieee80211_ioctl.h>
   53 
   54 void     ieee80211_node2req(struct ieee80211com *,
   55             const struct ieee80211_node *, struct ieee80211_nodereq *);
   56 void     ieee80211_req2node(struct ieee80211com *,
   57             const struct ieee80211_nodereq *, struct ieee80211_node *);
   58 
   59 void
   60 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni,
   61     struct ieee80211_nodereq *nr)
   62 {
   63         uint8_t rssi;
   64 
   65         memset(nr, 0, sizeof(*nr));
   66 
   67         strlcpy(nr->nr_ifname, ic->ic_if.if_xname, sizeof(nr->nr_ifname));
   68 
   69         /* Node address and name information */
   70         IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr);
   71         IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid);
   72         nr->nr_nwid_len = ni->ni_esslen;
   73         bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN);
   74 
   75         /* Channel and rates */
   76         nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan);
   77         if (ni->ni_chan != IEEE80211_CHAN_ANYC)
   78                 nr->nr_chan_flags = ni->ni_chan->ic_flags;
   79         if (ic->ic_curmode != IEEE80211_MODE_11N)
   80                 nr->nr_chan_flags &= ~IEEE80211_CHAN_HT;
   81         nr->nr_nrates = ni->ni_rates.rs_nrates;
   82         bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE);
   83 
   84         /* Node status information */
   85         rssi = (*ic->ic_node_getrssi)(ic, ni);
   86         if (ic->ic_max_rssi) {
   87                 /* Driver reports RSSI relative to ic_max_rssi. */
   88                 nr->nr_rssi = rssi;
   89         } else {
   90                 /*
   91                  * Driver reports RSSI value in dBm.
   92                  * Convert from unsigned to signed.
   93                  * Some drivers report a negative value, some don't.
   94                  * Reasonable range is -20dBm to -80dBm.
   95                  */
   96                 nr->nr_rssi = (rssi < 128) ? -rssi : rssi;
   97         }
   98         nr->nr_max_rssi = ic->ic_max_rssi;
   99         bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp));
  100         nr->nr_intval = ni->ni_intval;
  101         nr->nr_capinfo = ni->ni_capinfo;
  102         nr->nr_erp = ni->ni_erp;
  103         nr->nr_pwrsave = ni->ni_pwrsave;
  104         nr->nr_associd = ni->ni_associd;
  105         nr->nr_txseq = ni->ni_txseq;
  106         nr->nr_rxseq = ni->ni_rxseq;
  107         nr->nr_fails = ni->ni_fails;
  108         nr->nr_assoc_fail = ni->ni_assoc_fail; /* flag values are the same */
  109         nr->nr_inact = ni->ni_inact;
  110         nr->nr_txrate = ni->ni_txrate;
  111         nr->nr_state = ni->ni_state;
  112 
  113         /* RSN */
  114         nr->nr_rsnciphers = ni->ni_rsnciphers;
  115         nr->nr_rsnakms = 0;
  116         nr->nr_rsnprotos = 0;
  117         if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_RSN)
  118                 nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA2;
  119         if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_WPA)
  120                 nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA1;
  121         if (ni->ni_supported_rsnakms & IEEE80211_AKM_8021X)
  122                 nr->nr_rsnakms |= IEEE80211_WPA_AKM_8021X;
  123         if (ni->ni_supported_rsnakms & IEEE80211_AKM_PSK)
  124                 nr->nr_rsnakms |= IEEE80211_WPA_AKM_PSK;
  125         if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_8021X)
  126                 nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_8021X;
  127         if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_PSK)
  128                 nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_PSK;
  129 
  130         /* Node flags */
  131         nr->nr_flags = 0;
  132         if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0)
  133                 nr->nr_flags |= IEEE80211_NODEREQ_AP;
  134         if (ni == ic->ic_bss)
  135                 nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS;
  136 
  137         /* HT */
  138         nr->nr_htcaps = ni->ni_htcaps;
  139         memcpy(nr->nr_rxmcs, ni->ni_rxmcs, sizeof(nr->nr_rxmcs));
  140         nr->nr_max_rxrate = ni->ni_max_rxrate;
  141         nr->nr_tx_mcs_set = ni->ni_tx_mcs_set;
  142         if (ni->ni_flags & IEEE80211_NODE_HT)
  143                 nr->nr_flags |= IEEE80211_NODEREQ_HT;
  144 
  145         /* HT / VHT */
  146         nr->nr_txmcs = ni->ni_txmcs;
  147 
  148         /* VHT */
  149         nr->nr_vht_ss = ni->ni_vht_ss;
  150         if (ni->ni_flags & IEEE80211_NODE_VHT)
  151                 nr->nr_flags |= IEEE80211_NODEREQ_VHT;
  152 }
  153 
  154 void
  155 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr,
  156     struct ieee80211_node *ni)
  157 {
  158         /* Node address and name information */
  159         IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr);
  160         IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid);
  161         ni->ni_esslen = nr->nr_nwid_len;
  162         bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN);
  163 
  164         /* Rates */
  165         ni->ni_rates.rs_nrates = nr->nr_nrates;
  166         bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE);
  167 
  168         /* Node information */
  169         ni->ni_intval = nr->nr_intval;
  170         ni->ni_capinfo = nr->nr_capinfo;
  171         ni->ni_erp = nr->nr_erp;
  172         ni->ni_pwrsave = nr->nr_pwrsave;
  173         ni->ni_associd = nr->nr_associd;
  174         ni->ni_txseq = nr->nr_txseq;
  175         ni->ni_rxseq = nr->nr_rxseq;
  176         ni->ni_fails = nr->nr_fails;
  177         ni->ni_inact = nr->nr_inact;
  178         ni->ni_txrate = nr->nr_txrate;
  179         ni->ni_state = nr->nr_state;
  180 }
  181 
  182 void
  183 ieee80211_disable_wep(struct ieee80211com *ic)
  184 {
  185         struct ieee80211_key *k;
  186         int i;
  187         
  188         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
  189                 k = &ic->ic_nw_keys[i];
  190                 if (k->k_cipher != IEEE80211_CIPHER_NONE)
  191                         (*ic->ic_delete_key)(ic, NULL, k);
  192                 explicit_bzero(k, sizeof(*k));
  193         }
  194         ic->ic_flags &= ~IEEE80211_F_WEPON;
  195 }
  196 
  197 void
  198 ieee80211_disable_rsn(struct ieee80211com *ic)
  199 {
  200         ic->ic_flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON);
  201         explicit_bzero(ic->ic_psk, sizeof(ic->ic_psk));
  202         ic->ic_rsnprotos = 0;
  203         ic->ic_rsnakms = 0;
  204         ic->ic_rsngroupcipher = 0;
  205         ic->ic_rsnciphers = 0;
  206 }
  207 
  208 /* Keep in sync with ieee80211_node.c:ieee80211_ess_setnwkeys() */
  209 static int
  210 ieee80211_ioctl_setnwkeys(struct ieee80211com *ic,
  211     const struct ieee80211_nwkey *nwkey)
  212 {
  213         struct ieee80211_key *k;
  214         int error, i;
  215 
  216         if (!(ic->ic_caps & IEEE80211_C_WEP))
  217                 return ENODEV;
  218 
  219         if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) {
  220                 if (!(ic->ic_flags & IEEE80211_F_WEPON))
  221                         return 0;
  222                 ic->ic_flags &= ~IEEE80211_F_WEPON;
  223                 return ENETRESET;
  224         }
  225         if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID)
  226                 return EINVAL;
  227 
  228         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
  229                 if (nwkey->i_key[i].i_keylen == 0 ||
  230                     nwkey->i_key[i].i_keydat == NULL)
  231                         continue;       /* entry not set */
  232                 if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE)
  233                         return EINVAL;
  234 
  235                 /* map wep key to ieee80211_key */
  236                 k = &ic->ic_nw_keys[i];
  237                 if (k->k_cipher != IEEE80211_CIPHER_NONE)
  238                         (*ic->ic_delete_key)(ic, NULL, k);
  239                 memset(k, 0, sizeof(*k));
  240                 if (nwkey->i_key[i].i_keylen <= 5)
  241                         k->k_cipher = IEEE80211_CIPHER_WEP40;
  242                 else
  243                         k->k_cipher = IEEE80211_CIPHER_WEP104;
  244                 k->k_len = ieee80211_cipher_keylen(k->k_cipher);
  245                 k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;
  246                 error = copyin(nwkey->i_key[i].i_keydat, k->k_key, k->k_len);
  247                 if (error != 0)
  248                         return error;
  249                 error = (*ic->ic_set_key)(ic, NULL, k);
  250                 switch (error) {
  251                 case 0:
  252                 case EBUSY:
  253                         break;
  254                 default:
  255                         return error;
  256                 }
  257         }
  258 
  259         ic->ic_def_txkey = nwkey->i_defkid - 1;
  260         ic->ic_flags |= IEEE80211_F_WEPON;
  261         if (ic->ic_flags & IEEE80211_F_RSNON)
  262                 ieee80211_disable_rsn(ic);
  263 
  264         return ENETRESET;
  265 }
  266 
  267 static int
  268 ieee80211_ioctl_getnwkeys(struct ieee80211com *ic,
  269     struct ieee80211_nwkey *nwkey)
  270 {
  271         int i;
  272 
  273         if (ic->ic_flags & IEEE80211_F_WEPON)
  274                 nwkey->i_wepon = IEEE80211_NWKEY_WEP;
  275         else
  276                 nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
  277 
  278         nwkey->i_defkid = ic->ic_wep_txkey + 1;
  279 
  280         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
  281                 if (nwkey->i_key[i].i_keydat == NULL)
  282                         continue;
  283                 /* do not show any keys to userland */
  284                 return EPERM;
  285         }
  286         return 0;
  287 }
  288 
  289 /* Keep in sync with ieee80211_node.c:ieee80211_ess_setwpaparms() */
  290 static int
  291 ieee80211_ioctl_setwpaparms(struct ieee80211com *ic,
  292     const struct ieee80211_wpaparams *wpa)
  293 {
  294         if (!(ic->ic_caps & IEEE80211_C_RSN))
  295                 return ENODEV;
  296 
  297         if (!wpa->i_enabled) {
  298                 if (!(ic->ic_flags & IEEE80211_F_RSNON))
  299                         return 0;
  300                 ic->ic_flags &= ~IEEE80211_F_RSNON;
  301                 ic->ic_rsnprotos = 0;
  302                 ic->ic_rsnakms = 0;
  303                 ic->ic_rsngroupcipher = 0;
  304                 ic->ic_rsnciphers = 0;
  305                 return ENETRESET;
  306         }
  307 
  308         ic->ic_rsnprotos = 0;
  309         if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1)
  310                 ic->ic_rsnprotos |= IEEE80211_PROTO_WPA;
  311         if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2)
  312                 ic->ic_rsnprotos |= IEEE80211_PROTO_RSN;
  313         if (ic->ic_rsnprotos == 0)      /* set to default (RSN) */
  314                 ic->ic_rsnprotos = IEEE80211_PROTO_RSN;
  315 
  316         ic->ic_rsnakms = 0;
  317         if (wpa->i_akms & IEEE80211_WPA_AKM_PSK)
  318                 ic->ic_rsnakms |= IEEE80211_AKM_PSK;
  319         if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK)
  320                 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_PSK;
  321         if (wpa->i_akms & IEEE80211_WPA_AKM_8021X)
  322                 ic->ic_rsnakms |= IEEE80211_AKM_8021X;
  323         if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X)
  324                 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_8021X;
  325         if (ic->ic_rsnakms == 0)        /* set to default (PSK) */
  326                 ic->ic_rsnakms = IEEE80211_AKM_PSK;
  327 
  328         if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40)
  329                 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP40;
  330         else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP)
  331                 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP;
  332         else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP)
  333                 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;
  334         else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104)
  335                 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP104;
  336         else  { /* set to default */
  337                 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
  338                         ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP;
  339                 else
  340                         ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;
  341         }
  342 
  343         ic->ic_rsnciphers = 0;
  344         if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP)
  345                 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP;
  346         if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP)
  347                 ic->ic_rsnciphers |= IEEE80211_CIPHER_CCMP;
  348         if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP)
  349                 ic->ic_rsnciphers = IEEE80211_CIPHER_USEGROUP;
  350         if (ic->ic_rsnciphers == 0) { /* set to default (CCMP, TKIP if WPA1) */
  351                 ic->ic_rsnciphers = IEEE80211_CIPHER_CCMP;
  352                 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
  353                         ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP;
  354         }
  355 
  356         ic->ic_flags |= IEEE80211_F_RSNON;
  357 
  358         return ENETRESET;
  359 }
  360 
  361 static int
  362 ieee80211_ioctl_getwpaparms(struct ieee80211com *ic,
  363     struct ieee80211_wpaparams *wpa)
  364 {
  365         wpa->i_enabled = (ic->ic_flags & IEEE80211_F_RSNON) ? 1 : 0;
  366 
  367         wpa->i_protos = 0;
  368         if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
  369                 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1;
  370         if (ic->ic_rsnprotos & IEEE80211_PROTO_RSN)
  371                 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2;
  372 
  373         wpa->i_akms = 0;
  374         if (ic->ic_rsnakms & IEEE80211_AKM_PSK)
  375                 wpa->i_akms |= IEEE80211_WPA_AKM_PSK;
  376         if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_PSK)
  377                 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK;
  378         if (ic->ic_rsnakms & IEEE80211_AKM_8021X)
  379                 wpa->i_akms |= IEEE80211_WPA_AKM_8021X;
  380         if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_8021X)
  381                 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X;
  382 
  383         if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP40)
  384                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40;
  385         else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_TKIP)
  386                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP;
  387         else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_CCMP)
  388                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP;
  389         else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP104)
  390                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104;
  391         else
  392                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE;
  393 
  394         wpa->i_ciphers = 0;
  395         if (ic->ic_rsnciphers & IEEE80211_CIPHER_TKIP)
  396                 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP;
  397         if (ic->ic_rsnciphers & IEEE80211_CIPHER_CCMP)
  398                 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP;
  399         if (ic->ic_rsnciphers & IEEE80211_CIPHER_USEGROUP)
  400                 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP;
  401 
  402         return 0;
  403 }
  404 
  405 static void
  406 ieee80211_ess_getwpaparms(struct ieee80211_ess *ess,
  407     struct ieee80211_wpaparams *wpa)
  408 {
  409         wpa->i_enabled = (ess->flags & IEEE80211_F_RSNON) ? 1 : 0;
  410 
  411         wpa->i_protos = 0;
  412         if (ess->rsnprotos & IEEE80211_PROTO_WPA)
  413                 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1;
  414         if (ess->rsnprotos & IEEE80211_PROTO_RSN)
  415                 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2;
  416 
  417         wpa->i_akms = 0;
  418         if (ess->rsnakms & IEEE80211_AKM_PSK)
  419                 wpa->i_akms |= IEEE80211_WPA_AKM_PSK;
  420         if (ess->rsnakms & IEEE80211_AKM_SHA256_PSK)
  421                 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK;
  422         if (ess->rsnakms & IEEE80211_AKM_8021X)
  423                 wpa->i_akms |= IEEE80211_WPA_AKM_8021X;
  424         if (ess->rsnakms & IEEE80211_AKM_SHA256_8021X)
  425                 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X;
  426 
  427         if (ess->rsngroupcipher == IEEE80211_CIPHER_WEP40)
  428                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40;
  429         else if (ess->rsngroupcipher == IEEE80211_CIPHER_TKIP)
  430                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP;
  431         else if (ess->rsngroupcipher == IEEE80211_CIPHER_CCMP)
  432                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP;
  433         else if (ess->rsngroupcipher == IEEE80211_CIPHER_WEP104)
  434                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104;
  435         else
  436                 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE;
  437 
  438         wpa->i_ciphers = 0;
  439         if (ess->rsnciphers & IEEE80211_CIPHER_TKIP)
  440                 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP;
  441         if (ess->rsnciphers & IEEE80211_CIPHER_CCMP)
  442                 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP;
  443         if (ess->rsnciphers & IEEE80211_CIPHER_USEGROUP)
  444                 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP;
  445 }
  446 
  447 int
  448 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  449 {
  450         struct ieee80211com *ic = (void *)ifp;
  451         struct ifreq *ifr = (struct ifreq *)data;
  452         int i, error = 0;
  453         size_t len;
  454         struct ieee80211_nwid nwid;
  455         struct ieee80211_join join;
  456         struct ieee80211_joinreq_all *ja;
  457         struct ieee80211_ess *ess;
  458         struct ieee80211_wpapsk *psk;
  459         struct ieee80211_keyavail *ka;
  460         struct ieee80211_keyrun *kr;
  461         struct ieee80211_power *power;
  462         struct ieee80211_bssid *bssid;
  463         struct ieee80211chanreq *chanreq;
  464         struct ieee80211_channel *chan;
  465         struct ieee80211_txpower *txpower;
  466         static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
  467                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  468         };
  469         struct ieee80211_nodereq *nr, nrbuf;
  470         struct ieee80211_nodereq_all *na;
  471         struct ieee80211_node *ni;
  472         struct ieee80211_chaninfo chaninfo;
  473         struct ieee80211_chanreq_all *allchans;
  474         u_int32_t flags;
  475 
  476         switch (cmd) {
  477         case SIOCSIFMEDIA:
  478         case SIOCGIFMEDIA:
  479                 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
  480                 break;
  481         case SIOCS80211NWID:
  482                 if ((error = suser(curproc)) != 0)
  483                         break;
  484                 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0)
  485                         break;
  486                 if (nwid.i_len > IEEE80211_NWID_LEN) {
  487                         error = EINVAL;
  488                         break;
  489                 }
  490                 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
  491                 ic->ic_des_esslen = nwid.i_len;
  492                 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);
  493                 if (ic->ic_des_esslen > 0) {
  494                         /* 'nwid' disables auto-join magic */
  495                         ic->ic_flags &= ~IEEE80211_F_AUTO_JOIN;
  496                 } else if (!TAILQ_EMPTY(&ic->ic_ess)) {
  497                         /* '-nwid' re-enables auto-join */
  498                         ic->ic_flags |= IEEE80211_F_AUTO_JOIN;
  499                 }
  500                 /* disable WPA/WEP */
  501                 ieee80211_disable_rsn(ic);
  502                 ieee80211_disable_wep(ic);
  503                 error = ENETRESET;
  504                 break;
  505         case SIOCG80211NWID:
  506                 memset(&nwid, 0, sizeof(nwid));
  507                 switch (ic->ic_state) {
  508                 case IEEE80211_S_INIT:
  509                 case IEEE80211_S_SCAN:
  510                         nwid.i_len = ic->ic_des_esslen;
  511                         memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len);
  512                         break;
  513                 default:
  514                         nwid.i_len = ic->ic_bss->ni_esslen;
  515                         memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len);
  516                         break;
  517                 }
  518                 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
  519                 break;
  520         case SIOCS80211JOIN:
  521                 if ((error = suser(curproc)) != 0)
  522                         break;
  523                 if (ic->ic_opmode != IEEE80211_M_STA)
  524                         break;
  525                 if ((error = copyin(ifr->ifr_data, &join, sizeof(join))) != 0)
  526                         break;
  527                 if (join.i_len > IEEE80211_NWID_LEN) {
  528                         error = EINVAL;
  529                         break;
  530                 }
  531                 if (join.i_flags & IEEE80211_JOIN_DEL) {
  532                         int update_ic = 0;
  533                         if (ic->ic_des_esslen == join.i_len &&
  534                             memcmp(join.i_nwid, ic->ic_des_essid,
  535                             join.i_len) == 0)
  536                                 update_ic = 1;
  537                         if (join.i_flags & IEEE80211_JOIN_DEL_ALL && 
  538                             ieee80211_get_ess(ic, ic->ic_des_essid,
  539                             ic->ic_des_esslen) != NULL)
  540                                 update_ic = 1;
  541                         ieee80211_del_ess(ic, join.i_nwid, join.i_len,
  542                             join.i_flags & IEEE80211_JOIN_DEL_ALL ? 1 : 0);
  543                         if (update_ic == 1) {
  544                                 /* Unconfigure this essid */
  545                                 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
  546                                 ic->ic_des_esslen = 0;
  547                                 /* disable WPA/WEP */
  548                                 ieee80211_disable_rsn(ic);
  549                                 ieee80211_disable_wep(ic);
  550                                 error = ENETRESET;
  551                         }
  552                 } else {
  553                         if (ic->ic_des_esslen == join.i_len &&
  554                             memcmp(join.i_nwid, ic->ic_des_essid,
  555                             join.i_len) == 0) {
  556                                 struct ieee80211_node *ni;
  557 
  558                                 ieee80211_deselect_ess(ic);
  559                                 ni = ieee80211_find_node(ic,
  560                                     ic->ic_bss->ni_bssid);
  561                                 if (ni != NULL)
  562                                         ieee80211_free_node(ic, ni);
  563                                 error = ENETRESET;
  564                         }
  565                         /* save nwid for auto-join */
  566                         if (ieee80211_add_ess(ic, &join) == 0)
  567                                 ic->ic_flags |= IEEE80211_F_AUTO_JOIN;
  568                 }
  569                 break;
  570         case SIOCG80211JOIN:
  571                 memset(&join, 0, sizeof(join));
  572                 error = ENOENT;
  573                 if (ic->ic_bss == NULL)
  574                         break;
  575                 TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
  576                         if (memcmp(ess->essid, ic->ic_bss->ni_essid,
  577                             IEEE80211_NWID_LEN) == 0) {
  578                                 join.i_len = ic->ic_bss->ni_esslen;
  579                                 memcpy(join.i_nwid, ic->ic_bss->ni_essid,
  580                                     join.i_len);
  581                                 if (ic->ic_flags & IEEE80211_F_AUTO_JOIN)
  582                                         join.i_flags = IEEE80211_JOIN_FOUND;
  583                                 error = copyout(&join, ifr->ifr_data,
  584                                     sizeof(join));
  585                                 break;
  586                         }
  587                 }
  588                 break;
  589         case SIOCG80211JOINALL:
  590                 ja = (struct ieee80211_joinreq_all *)data;
  591                 ja->ja_nodes = len = 0;
  592                 TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
  593                         if (len + sizeof(ja->ja_node[0]) >= ja->ja_size) {
  594                                 error = E2BIG;
  595                                 break;
  596                         }
  597                         memset(&join, 0, sizeof(join));
  598                         join.i_len = ess->esslen;
  599                         memcpy(&join.i_nwid, ess->essid, join.i_len);
  600                         if (ess->flags & IEEE80211_F_RSNON)
  601                                 join.i_flags |= IEEE80211_JOIN_WPA;
  602                         if (ess->flags & IEEE80211_F_PSK)
  603                                 join.i_flags |= IEEE80211_JOIN_WPAPSK;
  604                         if (ess->flags & IEEE80211_JOIN_8021X)
  605                                 join.i_flags |= IEEE80211_JOIN_8021X;
  606                         if (ess->flags & IEEE80211_F_WEPON)
  607                                 join.i_flags |= IEEE80211_JOIN_NWKEY;
  608                         if (ess->flags & IEEE80211_JOIN_ANY)
  609                                 join.i_flags |= IEEE80211_JOIN_ANY;
  610                         ieee80211_ess_getwpaparms(ess, &join.i_wpaparams);
  611                         error = copyout(&join, &ja->ja_node[ja->ja_nodes],
  612                             sizeof(ja->ja_node[0]));
  613                         if (error)
  614                                 break;
  615                         len += sizeof(join);
  616                         ja->ja_nodes++;
  617                 }
  618                 break;
  619         case SIOCS80211NWKEY:
  620                 if ((error = suser(curproc)) != 0)
  621                         break;
  622                 error = ieee80211_ioctl_setnwkeys(ic, (void *)data);
  623                 break;
  624         case SIOCG80211NWKEY:
  625                 error = ieee80211_ioctl_getnwkeys(ic, (void *)data);
  626                 break;
  627         case SIOCS80211WPAPARMS:
  628                 if ((error = suser(curproc)) != 0)
  629                         break;
  630                 error = ieee80211_ioctl_setwpaparms(ic, (void *)data);
  631                 break;
  632         case SIOCG80211WPAPARMS:
  633                 error = ieee80211_ioctl_getwpaparms(ic, (void *)data);
  634                 break;
  635         case SIOCS80211WPAPSK:
  636                 if ((error = suser(curproc)) != 0)
  637                         break;
  638                 psk = (struct ieee80211_wpapsk *)data;
  639                 if (psk->i_enabled) {
  640                         ic->ic_flags |= IEEE80211_F_PSK;
  641                         memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk));
  642                         if (ic->ic_flags & IEEE80211_F_WEPON)
  643                                 ieee80211_disable_wep(ic);
  644                 } else {
  645                         ic->ic_flags &= ~IEEE80211_F_PSK;
  646                         memset(ic->ic_psk, 0, sizeof(ic->ic_psk));
  647                 }
  648                 error = ENETRESET;
  649                 break;
  650         case SIOCG80211WPAPSK:
  651                 psk = (struct ieee80211_wpapsk *)data;
  652                 if (ic->ic_flags & IEEE80211_F_PSK) {
  653                         /* do not show any keys to userland */
  654                         psk->i_enabled = 2;
  655                         memset(psk->i_psk, 0, sizeof(psk->i_psk));
  656                         break;  /* return ok but w/o key */
  657                 } else
  658                         psk->i_enabled = 0;
  659                 break;
  660         case SIOCS80211KEYAVAIL:
  661                 if ((error = suser(curproc)) != 0)
  662                         break;
  663                 ka = (struct ieee80211_keyavail *)data;
  664                 (void)ieee80211_pmksa_add(ic, IEEE80211_AKM_8021X,
  665                     ka->i_macaddr, ka->i_key, ka->i_lifetime);
  666                 break;
  667         case SIOCS80211KEYRUN:
  668                 if ((error = suser(curproc)) != 0)
  669                         break;
  670                 kr = (struct ieee80211_keyrun *)data;
  671                 error = ieee80211_keyrun(ic, kr->i_macaddr);
  672                 if (error == 0 && (ic->ic_flags & IEEE80211_F_WEPON))
  673                         ieee80211_disable_wep(ic);
  674                 break;
  675         case SIOCS80211POWER:
  676                 if ((error = suser(curproc)) != 0)
  677                         break;
  678                 power = (struct ieee80211_power *)data;
  679                 ic->ic_lintval = power->i_maxsleep;
  680                 if (power->i_enabled != 0) {
  681                         if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
  682                                 error = EINVAL;
  683                         else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
  684                                 ic->ic_flags |= IEEE80211_F_PMGTON;
  685                                 error = ENETRESET;
  686                         }
  687                 } else {
  688                         if (ic->ic_flags & IEEE80211_F_PMGTON) {
  689                                 ic->ic_flags &= ~IEEE80211_F_PMGTON;
  690                                 error = ENETRESET;
  691                         }
  692                 }
  693                 break;
  694         case SIOCG80211POWER:
  695                 power = (struct ieee80211_power *)data;
  696                 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;
  697                 power->i_maxsleep = ic->ic_lintval;
  698                 break;
  699         case SIOCS80211BSSID:
  700                 if ((error = suser(curproc)) != 0)
  701                         break;
  702                 bssid = (struct ieee80211_bssid *)data;
  703                 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr))
  704                         ic->ic_flags &= ~IEEE80211_F_DESBSSID;
  705                 else {
  706                         ic->ic_flags |= IEEE80211_F_DESBSSID;
  707                         IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid);
  708                 }
  709 #ifndef IEEE80211_STA_ONLY
  710                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
  711                         break;
  712 #endif
  713                 switch (ic->ic_state) {
  714                 case IEEE80211_S_INIT:
  715                 case IEEE80211_S_SCAN:
  716                         error = ENETRESET;
  717                         break;
  718                 default:
  719                         if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
  720                             !IEEE80211_ADDR_EQ(ic->ic_des_bssid,
  721                             ic->ic_bss->ni_bssid))
  722                                 error = ENETRESET;
  723                         break;
  724                 }
  725                 break;
  726         case SIOCG80211BSSID:
  727                 bssid = (struct ieee80211_bssid *)data;
  728                 switch (ic->ic_state) {
  729                 case IEEE80211_S_INIT:
  730                 case IEEE80211_S_SCAN:
  731 #ifndef IEEE80211_STA_ONLY
  732                         if (ic->ic_opmode == IEEE80211_M_HOSTAP)
  733                                 IEEE80211_ADDR_COPY(bssid->i_bssid,
  734                                     ic->ic_myaddr);
  735                         else
  736 #endif
  737                         if (ic->ic_flags & IEEE80211_F_DESBSSID)
  738                                 IEEE80211_ADDR_COPY(bssid->i_bssid,
  739                                     ic->ic_des_bssid);
  740                         else
  741                                 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
  742                         break;
  743                 default:
  744                         IEEE80211_ADDR_COPY(bssid->i_bssid,
  745                             ic->ic_bss->ni_bssid);
  746                         break;
  747                 }
  748                 break;
  749         case SIOCS80211CHANNEL:
  750                 if ((error = suser(curproc)) != 0)
  751                         break;
  752                 chanreq = (struct ieee80211chanreq *)data;
  753                 if (chanreq->i_channel == IEEE80211_CHAN_ANY)
  754                         ic->ic_des_chan = IEEE80211_CHAN_ANYC;
  755                 else if (chanreq->i_channel > IEEE80211_CHAN_MAX ||
  756                     isclr(ic->ic_chan_active, chanreq->i_channel)) {
  757                         error = EINVAL;
  758                         break;
  759                 } else
  760                         ic->ic_ibss_chan = ic->ic_des_chan =
  761                             &ic->ic_channels[chanreq->i_channel];
  762                 switch (ic->ic_state) {
  763                 case IEEE80211_S_INIT:
  764                 case IEEE80211_S_SCAN:
  765                         error = ENETRESET;
  766                         break;
  767                 default:
  768                         if (ic->ic_opmode == IEEE80211_M_STA) {
  769                                 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
  770                                     ic->ic_bss->ni_chan != ic->ic_des_chan)
  771                                         error = ENETRESET;
  772                         } else {
  773                                 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan)
  774                                         error = ENETRESET;
  775                         }
  776                         break;
  777                 }
  778                 break;
  779         case SIOCG80211CHANNEL:
  780                 chanreq = (struct ieee80211chanreq *)data;
  781                 switch (ic->ic_state) {
  782                 case IEEE80211_S_INIT:
  783                 case IEEE80211_S_SCAN:
  784                         if (ic->ic_opmode == IEEE80211_M_STA)
  785                                 chan = ic->ic_des_chan;
  786                         else
  787                                 chan = ic->ic_ibss_chan;
  788                         break;
  789                 default:
  790                         chan = ic->ic_bss->ni_chan;
  791                         break;
  792                 }
  793                 chanreq->i_channel = ieee80211_chan2ieee(ic, chan);
  794                 break;
  795         case SIOCG80211ALLCHANS:
  796                 allchans = (struct ieee80211_chanreq_all *)data;
  797                 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
  798                         chan = &ic->ic_channels[i];
  799                         chaninfo.ic_freq = chan->ic_freq;
  800                         chaninfo.ic_flags = 0;
  801                         if (chan->ic_flags & IEEE80211_CHAN_2GHZ)
  802                                 chaninfo.ic_flags |= IEEE80211_CHANINFO_2GHZ;
  803                         if (chan->ic_flags & IEEE80211_CHAN_5GHZ)
  804                                 chaninfo.ic_flags |= IEEE80211_CHANINFO_5GHZ;
  805                         if (chan->ic_flags & IEEE80211_CHAN_PASSIVE)
  806                                 chaninfo.ic_flags |= IEEE80211_CHANINFO_PASSIVE;
  807                         error = copyout(&chaninfo, &allchans->i_chans[i],
  808                             sizeof(chaninfo));
  809                         if (error)
  810                                 break;
  811                 }
  812                 break;
  813 #if 0
  814         case SIOCG80211ZSTATS:
  815 #endif
  816         case SIOCG80211STATS:
  817                 ifr = (struct ifreq *)data;
  818                 error = copyout(&ic->ic_stats, ifr->ifr_data,
  819                     sizeof(ic->ic_stats));
  820 #if 0
  821                 if (cmd == SIOCG80211ZSTATS)
  822                         memset(&ic->ic_stats, 0, sizeof(ic->ic_stats));
  823 #endif
  824                 break;
  825         case SIOCS80211TXPOWER:
  826                 if ((error = suser(curproc)) != 0)
  827                         break;
  828                 txpower = (struct ieee80211_txpower *)data;
  829                 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) {
  830                         error = EINVAL;
  831                         break;
  832                 }
  833                 if (!(IEEE80211_TXPOWER_MIN <= txpower->i_val &&
  834                         txpower->i_val <= IEEE80211_TXPOWER_MAX)) {
  835                         error = EINVAL;
  836                         break;
  837                 }
  838                 ic->ic_txpower = txpower->i_val;
  839                 error = ENETRESET;
  840                 break;
  841         case SIOCG80211TXPOWER:
  842                 txpower = (struct ieee80211_txpower *)data;
  843                 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
  844                         error = EINVAL;
  845                 else
  846                         txpower->i_val = ic->ic_txpower;
  847                 break;
  848         case SIOCSIFMTU:
  849                 ifr = (struct ifreq *)data;
  850                 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
  851                     ifr->ifr_mtu <= IEEE80211_MTU_MAX))
  852                         error = EINVAL;
  853                 else
  854                         ifp->if_mtu = ifr->ifr_mtu;
  855                 break;
  856         case SIOCS80211SCAN:
  857                 /* Disabled. SIOCG80211ALLNODES is enough. */
  858                 break;
  859         case SIOCG80211NODE:
  860                 nr = (struct ieee80211_nodereq *)data;
  861                 if (ic->ic_bss &&
  862                     IEEE80211_ADDR_EQ(nr->nr_macaddr, ic->ic_bss->ni_macaddr))
  863                         ni = ic->ic_bss;
  864                 else
  865                         ni = ieee80211_find_node(ic, nr->nr_macaddr);
  866                 if (ni == NULL) {
  867                         error = ENOENT;
  868                         break;
  869                 }
  870                 ieee80211_node2req(ic, ni, nr);
  871                 break;
  872         case SIOCS80211NODE:
  873                 if ((error = suser(curproc)) != 0)
  874                         break;
  875 #ifndef IEEE80211_STA_ONLY
  876                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  877                         error = EINVAL;
  878                         break;
  879                 }
  880 #endif
  881                 nr = (struct ieee80211_nodereq *)data;
  882 
  883                 ni = ieee80211_find_node(ic, nr->nr_macaddr);
  884                 if (ni == NULL)
  885                         ni = ieee80211_alloc_node(ic, nr->nr_macaddr);
  886                 if (ni == NULL) {
  887                         error = ENOENT;
  888                         break;
  889                 }
  890 
  891                 if (nr->nr_flags & IEEE80211_NODEREQ_COPY)
  892                         ieee80211_req2node(ic, nr, ni);
  893                 break;
  894 #ifndef IEEE80211_STA_ONLY
  895         case SIOCS80211DELNODE:
  896                 if ((error = suser(curproc)) != 0)
  897                         break;
  898                 nr = (struct ieee80211_nodereq *)data;
  899                 ni = ieee80211_find_node(ic, nr->nr_macaddr);
  900                 if (ni == NULL)
  901                         error = ENOENT;
  902                 else if (ni == ic->ic_bss)
  903                         error = EPERM;
  904                 else {
  905                         if (ni->ni_state == IEEE80211_STA_COLLECT)
  906                                 break;
  907 
  908                         /* Disassociate station. */
  909                         if (ni->ni_state == IEEE80211_STA_ASSOC)
  910                                 IEEE80211_SEND_MGMT(ic, ni,
  911                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
  912                                     IEEE80211_REASON_ASSOC_LEAVE);
  913 
  914                         /* Deauth station. */
  915                         if (ni->ni_state >= IEEE80211_STA_AUTH)
  916                                 IEEE80211_SEND_MGMT(ic, ni,
  917                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
  918                                     IEEE80211_REASON_AUTH_LEAVE);
  919 
  920                         ieee80211_node_leave(ic, ni);
  921                 }
  922                 break;
  923 #endif
  924         case SIOCG80211ALLNODES:
  925                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
  926                     (IFF_UP | IFF_RUNNING)) {
  927                         error = ENETDOWN;
  928                         break;
  929                 }
  930 
  931                 na = (struct ieee80211_nodereq_all *)data;
  932                 na->na_nodes = i = 0;
  933                 ni = RBT_MIN(ieee80211_tree, &ic->ic_tree);
  934                 while (ni && na->na_size >=
  935                     i + sizeof(struct ieee80211_nodereq)) {
  936                         ieee80211_node2req(ic, ni, &nrbuf);
  937                         error = copyout(&nrbuf, (caddr_t)na->na_node + i,
  938                             sizeof(struct ieee80211_nodereq));
  939                         if (error)
  940                                 break;
  941                         i += sizeof(struct ieee80211_nodereq);
  942                         na->na_nodes++;
  943                         ni = RBT_NEXT(ieee80211_tree, ni);
  944                 }
  945                 if (suser(curproc) == 0)
  946                         ieee80211_begin_bgscan(ifp);
  947                 break;
  948         case SIOCG80211FLAGS:
  949                 flags = ic->ic_userflags;
  950 #ifndef IEEE80211_STA_ONLY
  951                 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
  952 #endif
  953                         flags &= ~IEEE80211_F_HOSTAPMASK;
  954                 ifr->ifr_flags = flags;
  955                 break;
  956         case SIOCS80211FLAGS:
  957                 if ((error = suser(curproc)) != 0)
  958                         break;
  959                 flags = ifr->ifr_flags;
  960                 if (
  961 #ifndef IEEE80211_STA_ONLY
  962                     ic->ic_opmode != IEEE80211_M_HOSTAP &&
  963 #endif
  964                     (flags & IEEE80211_F_HOSTAPMASK)) {
  965                         error = EINVAL;
  966                         break;
  967                 }
  968                 ic->ic_userflags = flags;
  969                 error = ENETRESET;
  970                 break;
  971         case SIOCADDMULTI:
  972         case SIOCDELMULTI:
  973                 error = (cmd == SIOCADDMULTI) ?
  974                     ether_addmulti(ifr, &ic->ic_ac) :
  975                     ether_delmulti(ifr, &ic->ic_ac);
  976                 if (error == ENETRESET)
  977                         error = 0;
  978                 break;
  979         default:
  980                 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data);
  981         }
  982 
  983         return error;
  984 }

Cache object: 6eb3e507cbb6b9a5f0a55d8e9242e5ca


[ 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.