root/net80211/ieee80211_ioctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ieee80211_node2req
  2. ieee80211_req2node
  3. ieee80211_ioctl

    1 /*      $OpenBSD: ieee80211_ioctl.c,v 1.19 2007/07/18 18:10:31 damien 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/proc.h>
   43 #include <sys/tree.h>
   44 
   45 #include <net/if.h>
   46 #include <net/if_arp.h>
   47 #include <net/if_media.h>
   48 
   49 #ifdef INET
   50 #include <netinet/in.h>
   51 #include <netinet/if_ether.h>
   52 #endif
   53 
   54 #include <net80211/ieee80211_var.h>
   55 #include <net80211/ieee80211_ioctl.h>
   56 
   57 void     ieee80211_node2req(struct ieee80211com *,
   58             const struct ieee80211_node *, struct ieee80211_nodereq *);
   59 void     ieee80211_req2node(struct ieee80211com *,
   60             const struct ieee80211_nodereq *, struct ieee80211_node *);
   61 
   62 void
   63 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni,
   64     struct ieee80211_nodereq *nr)
   65 {
   66         /* Node address and name information */
   67         IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr);
   68         IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid);
   69         nr->nr_nwid_len = ni->ni_esslen;
   70         bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN);
   71 
   72         /* Channel and rates */
   73         nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan);
   74         nr->nr_chan_flags = ni->ni_chan->ic_flags;
   75         nr->nr_nrates = ni->ni_rates.rs_nrates;
   76         bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE);
   77 
   78         /* Node status information */
   79         nr->nr_rssi = (*ic->ic_node_getrssi)(ic, ni);
   80         nr->nr_max_rssi = ic->ic_max_rssi;
   81         bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp));
   82         nr->nr_intval = ni->ni_intval;
   83         nr->nr_capinfo = ni->ni_capinfo;
   84         nr->nr_fhdwell = ni->ni_fhdwell;
   85         nr->nr_fhindex = ni->ni_fhindex;
   86         nr->nr_erp = ni->ni_erp;
   87         nr->nr_pwrsave = ni->ni_pwrsave;
   88         nr->nr_associd = ni->ni_associd;
   89         nr->nr_txseq = ni->ni_txseq;
   90         nr->nr_rxseq = ni->ni_rxseq;
   91         nr->nr_fails = ni->ni_fails;
   92         nr->nr_inact = ni->ni_inact;
   93         nr->nr_txrate = ni->ni_txrate;
   94         nr->nr_state = ni->ni_state;
   95 
   96         /* Node flags */
   97         nr->nr_flags = 0;
   98         if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0)
   99                 nr->nr_flags |= IEEE80211_NODEREQ_AP;
  100         if (ni == ic->ic_bss)
  101                 nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS;
  102 }
  103 
  104 void
  105 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr,
  106     struct ieee80211_node *ni)
  107 {
  108         /* Node address and name information */
  109         IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr);
  110         IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid);
  111         ni->ni_esslen = nr->nr_nwid_len;
  112         bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN);
  113 
  114         /* Rates */
  115         ni->ni_rates.rs_nrates = nr->nr_nrates;
  116         bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE);
  117 
  118         /* Node information */
  119         ni->ni_intval = nr->nr_intval;
  120         ni->ni_capinfo = nr->nr_capinfo;
  121         ni->ni_fhdwell = nr->nr_fhdwell;
  122         ni->ni_fhindex = nr->nr_fhindex;
  123         ni->ni_erp = nr->nr_erp;
  124         ni->ni_pwrsave = nr->nr_pwrsave;
  125         ni->ni_associd = nr->nr_associd;
  126         ni->ni_txseq = nr->nr_txseq;
  127         ni->ni_rxseq = nr->nr_rxseq;
  128         ni->ni_fails = nr->nr_fails;
  129         ni->ni_inact = nr->nr_inact;
  130         ni->ni_txrate = nr->nr_txrate;
  131         ni->ni_state = nr->nr_state;
  132 }
  133 
  134 int
  135 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  136 {
  137         struct ieee80211com *ic = (void *)ifp;
  138         struct ifreq *ifr = (struct ifreq *)data;
  139         int i, error = 0;
  140         struct ieee80211_nwid nwid;
  141         struct ieee80211_nwkey *nwkey;
  142         struct ieee80211_power *power;
  143         struct ieee80211_bssid *bssid;
  144         struct ieee80211chanreq *chanreq;
  145         struct ieee80211_channel *chan;
  146         struct ieee80211_txpower *txpower;
  147         struct ieee80211_key keys[IEEE80211_WEP_NKID];
  148         static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
  149                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  150         };
  151         struct ieee80211_nodereq *nr, nrbuf;
  152         struct ieee80211_nodereq_all *na;
  153         struct ieee80211_node *ni;
  154         u_int32_t flags;
  155 
  156         switch (cmd) {
  157         case SIOCSIFADDR:
  158         case SIOCGIFADDR:
  159                 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data);
  160                 break;
  161         case SIOCSIFMEDIA:
  162         case SIOCGIFMEDIA:
  163                 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
  164                 break;
  165         case SIOCS80211NWID:
  166                 if ((error = suser(curproc, 0)) != 0)
  167                         break;
  168                 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0)
  169                         break;
  170                 if (nwid.i_len > IEEE80211_NWID_LEN) {
  171                         error = EINVAL;
  172                         break;
  173                 }
  174                 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
  175                 ic->ic_des_esslen = nwid.i_len;
  176                 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);
  177                 error = ENETRESET;
  178                 break;
  179         case SIOCG80211NWID:
  180                 memset(&nwid, 0, sizeof(nwid));
  181                 switch (ic->ic_state) {
  182                 case IEEE80211_S_INIT:
  183                 case IEEE80211_S_SCAN:
  184                         nwid.i_len = ic->ic_des_esslen;
  185                         memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len);
  186                         break;
  187                 default:
  188                         nwid.i_len = ic->ic_bss->ni_esslen;
  189                         memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len);
  190                         break;
  191                 }
  192                 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
  193                 break;
  194         case SIOCS80211NWKEY:
  195                 if ((error = suser(curproc, 0)) != 0)
  196                         break;
  197                 nwkey = (struct ieee80211_nwkey *)data;
  198                 if ((ic->ic_caps & IEEE80211_C_WEP) == 0 &&
  199                     nwkey->i_wepon != IEEE80211_NWKEY_OPEN) {
  200                         error = EINVAL;
  201                         break;
  202                 }
  203                 /* check and copy keys */
  204                 memset(keys, 0, sizeof(keys));
  205                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
  206                         keys[i].k_len = nwkey->i_key[i].i_keylen;
  207                         /*
  208                          * Limit the maximal allowed key size to 
  209                          * IEEE80211_KEYBUF_SIZE bytes.
  210                          */
  211                         if (keys[i].k_len > sizeof(keys[i].k_key)) {
  212                                 error = EINVAL;
  213                                 break;
  214                         }
  215                         if (keys[i].k_len <= 0)
  216                                 continue;
  217                         if ((error = copyin(nwkey->i_key[i].i_keydat,
  218                             keys[i].k_key, keys[i].k_len)) != 0)
  219                                 break;
  220                 }
  221                 if (error)
  222                         break;
  223                 i = nwkey->i_defkid - 1;
  224                 if (i < 0 || i >= IEEE80211_WEP_NKID ||
  225                     keys[i].k_len == 0 ||
  226                     (keys[i].k_len == -1 && ic->ic_nw_keys[i].k_len == 0)) {
  227                         if (nwkey->i_wepon != IEEE80211_NWKEY_OPEN) {
  228                                 error = EINVAL;
  229                                 break;
  230                         }
  231                 } else
  232                         ic->ic_wep_txkey = i;
  233                 /* save the key */
  234                 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN)
  235                         ic->ic_flags &= ~IEEE80211_F_WEPON;
  236                 else
  237                         ic->ic_flags |= IEEE80211_F_WEPON;
  238                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
  239                         struct ieee80211_key *k = &ic->ic_nw_keys[i];
  240                         if (keys[i].k_len < 0)
  241                                 continue;
  242                         if (keys[i].k_len == 0)
  243                                 k->k_cipher = IEEE80211_CIPHER_NONE;
  244                         else if (keys[i].k_len <= 5)
  245                                 k->k_cipher = IEEE80211_CIPHER_WEP40;
  246                         else
  247                                 k->k_cipher = IEEE80211_CIPHER_WEP104;
  248                         k->k_len = keys[i].k_len;
  249                         memcpy(k->k_key, keys[i].k_key, sizeof(keys[i].k_key));
  250                 }
  251                 error = ENETRESET;
  252                 break;
  253         case SIOCG80211NWKEY:
  254                 nwkey = (struct ieee80211_nwkey *)data;
  255                 if (ic->ic_flags & IEEE80211_F_WEPON)
  256                         nwkey->i_wepon = IEEE80211_NWKEY_WEP;
  257                 else
  258                         nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
  259                 nwkey->i_defkid = ic->ic_wep_txkey + 1;
  260                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
  261                         if (nwkey->i_key[i].i_keydat == NULL)
  262                                 continue;
  263                         /* do not show any keys to non-root user */
  264                         if ((error = suser(curproc, 0)) != 0)
  265                                 break;
  266                         nwkey->i_key[i].i_keylen = ic->ic_nw_keys[i].k_len;
  267                         if ((error = copyout(ic->ic_nw_keys[i].k_key,
  268                             nwkey->i_key[i].i_keydat,
  269                             ic->ic_nw_keys[i].k_len)) != 0)
  270                                 break;
  271                 }
  272                 break;
  273         case SIOCS80211POWER:
  274                 if ((error = suser(curproc, 0)) != 0)
  275                         break;
  276                 power = (struct ieee80211_power *)data;
  277                 ic->ic_lintval = power->i_maxsleep;
  278                 if (power->i_enabled != 0) {
  279                         if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
  280                                 error = EINVAL;
  281                         else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
  282                                 ic->ic_flags |= IEEE80211_F_PMGTON;
  283                                 error = ENETRESET;
  284                         }
  285                 } else {
  286                         if (ic->ic_flags & IEEE80211_F_PMGTON) {
  287                                 ic->ic_flags &= ~IEEE80211_F_PMGTON;
  288                                 error = ENETRESET;
  289                         }
  290                 }
  291                 break;
  292         case SIOCG80211POWER:
  293                 power = (struct ieee80211_power *)data;
  294                 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;
  295                 power->i_maxsleep = ic->ic_lintval;
  296                 break;
  297         case SIOCS80211BSSID:
  298                 if ((error = suser(curproc, 0)) != 0)
  299                         break;
  300                 bssid = (struct ieee80211_bssid *)data;
  301                 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr))
  302                         ic->ic_flags &= ~IEEE80211_F_DESBSSID;
  303                 else {
  304                         ic->ic_flags |= IEEE80211_F_DESBSSID;
  305                         IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid);
  306                 }
  307                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
  308                         break;
  309                 switch (ic->ic_state) {
  310                 case IEEE80211_S_INIT:
  311                 case IEEE80211_S_SCAN:
  312                         error = ENETRESET;
  313                         break;
  314                 default:
  315                         if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
  316                             !IEEE80211_ADDR_EQ(ic->ic_des_bssid,
  317                             ic->ic_bss->ni_bssid))
  318                                 error = ENETRESET;
  319                         break;
  320                 }
  321                 break;
  322         case SIOCG80211BSSID:
  323                 bssid = (struct ieee80211_bssid *)data;
  324                 switch (ic->ic_state) {
  325                 case IEEE80211_S_INIT:
  326                 case IEEE80211_S_SCAN:
  327                         if (ic->ic_opmode == IEEE80211_M_HOSTAP)
  328                                 IEEE80211_ADDR_COPY(bssid->i_bssid,
  329                                     ic->ic_myaddr);
  330                         else if (ic->ic_flags & IEEE80211_F_DESBSSID)
  331                                 IEEE80211_ADDR_COPY(bssid->i_bssid,
  332                                     ic->ic_des_bssid);
  333                         else
  334                                 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
  335                         break;
  336                 default:
  337                         IEEE80211_ADDR_COPY(bssid->i_bssid,
  338                             ic->ic_bss->ni_bssid);
  339                         break;
  340                 }
  341                 break;
  342         case SIOCS80211CHANNEL:
  343                 if ((error = suser(curproc, 0)) != 0)
  344                         break;
  345                 chanreq = (struct ieee80211chanreq *)data;
  346                 if (chanreq->i_channel == IEEE80211_CHAN_ANY)
  347                         ic->ic_des_chan = IEEE80211_CHAN_ANYC;
  348                 else if (chanreq->i_channel > IEEE80211_CHAN_MAX ||
  349                     isclr(ic->ic_chan_active, chanreq->i_channel)) {
  350                         error = EINVAL;
  351                         break;
  352                 } else
  353                         ic->ic_ibss_chan = ic->ic_des_chan =
  354                             &ic->ic_channels[chanreq->i_channel];
  355                 switch (ic->ic_state) {
  356                 case IEEE80211_S_INIT:
  357                 case IEEE80211_S_SCAN:
  358                         error = ENETRESET;
  359                         break;
  360                 default:
  361                         if (ic->ic_opmode == IEEE80211_M_STA) {
  362                                 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
  363                                     ic->ic_bss->ni_chan != ic->ic_des_chan)
  364                                         error = ENETRESET;
  365                         } else {
  366                                 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan)
  367                                         error = ENETRESET;
  368                         }
  369                         break;
  370                 }
  371                 break;
  372         case SIOCG80211CHANNEL:
  373                 chanreq = (struct ieee80211chanreq *)data;
  374                 switch (ic->ic_state) {
  375                 case IEEE80211_S_INIT:
  376                 case IEEE80211_S_SCAN:
  377                         if (ic->ic_opmode == IEEE80211_M_STA)
  378                                 chan = ic->ic_des_chan;
  379                         else
  380                                 chan = ic->ic_ibss_chan;
  381                         break;
  382                 default:
  383                         chan = ic->ic_bss->ni_chan;
  384                         break;
  385                 }
  386                 chanreq->i_channel = ieee80211_chan2ieee(ic, chan);
  387                 break;
  388 #if 0
  389         case SIOCG80211ZSTATS:
  390 #endif
  391         case SIOCG80211STATS:
  392                 ifr = (struct ifreq *)data;
  393                 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
  394 #if 0
  395                 if (cmd == SIOCG80211ZSTATS)
  396                         memset(&ic->ic_stats, 0, sizeof(ic->ic_stats));
  397 #endif
  398                 break;
  399         case SIOCS80211TXPOWER:
  400                 if ((error = suser(curproc, 0)) != 0)
  401                         break;
  402                 txpower = (struct ieee80211_txpower *)data;
  403                 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) {
  404                         error = EINVAL;
  405                         break;
  406                 }
  407                 if (!(IEEE80211_TXPOWER_MIN < txpower->i_val &&
  408                         txpower->i_val < IEEE80211_TXPOWER_MAX)) {
  409                         error = EINVAL;
  410                         break;
  411                 }
  412                 ic->ic_txpower = txpower->i_val;
  413                 error = ENETRESET;
  414                 break;
  415         case SIOCG80211TXPOWER:
  416                 txpower = (struct ieee80211_txpower *)data;
  417                 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
  418                         error = EINVAL;
  419                 else
  420                         txpower->i_val = ic->ic_txpower;
  421                 break;
  422         case SIOCSIFMTU:
  423                 ifr = (struct ifreq *)data;
  424                 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
  425                     ifr->ifr_mtu <= IEEE80211_MTU_MAX))
  426                         error = EINVAL;
  427                 else
  428                         ifp->if_mtu = ifr->ifr_mtu;
  429                 break;
  430         case SIOCS80211SCAN:
  431                 if ((error = suser(curproc, 0)) != 0)
  432                         break;
  433                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
  434                         break;
  435                 if ((ifp->if_flags & IFF_UP) == 0) {
  436                         error = ENETDOWN;
  437                         break;
  438                 }
  439                 if ((ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) == 0) {
  440                         if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED)
  441                                 ic->ic_scan_lock |= IEEE80211_SCAN_RESUME;
  442                         ic->ic_scan_lock |= IEEE80211_SCAN_REQUEST;
  443                         if (ic->ic_state != IEEE80211_S_SCAN)
  444                                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
  445                 }
  446                 /* Let the userspace process wait for completion */
  447                 error = tsleep(&ic->ic_scan_lock, PCATCH, "80211scan",
  448                     hz * IEEE80211_SCAN_TIMEOUT);
  449                 break;
  450         case SIOCG80211NODE:
  451                 nr = (struct ieee80211_nodereq *)data;
  452                 ni = ieee80211_find_node(ic, nr->nr_macaddr);
  453                 if (ni == NULL) {
  454                         error = ENOENT;
  455                         break;
  456                 }
  457                 ieee80211_node2req(ic, ni, nr);
  458                 break;
  459         case SIOCS80211NODE:
  460                 if ((error = suser(curproc, 0)) != 0)
  461                         break;
  462                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  463                         error = EINVAL;
  464                         break;
  465                 }
  466                 nr = (struct ieee80211_nodereq *)data;
  467 
  468                 ni = ieee80211_find_node(ic, nr->nr_macaddr);
  469                 if (ni == NULL)
  470                         ni = ieee80211_alloc_node(ic, nr->nr_macaddr);
  471                 if (ni == NULL) {
  472                         error = ENOENT;
  473                         break;
  474                 }
  475 
  476                 if (nr->nr_flags & IEEE80211_NODEREQ_COPY)
  477                         ieee80211_req2node(ic, nr, ni);
  478                 break;
  479         case SIOCS80211DELNODE:
  480                 if ((error = suser(curproc, 0)) != 0)
  481                         break;
  482                 nr = (struct ieee80211_nodereq *)data;
  483                 ni = ieee80211_find_node(ic, nr->nr_macaddr);
  484                 if (ni == NULL)
  485                         error = ENOENT;
  486                 else if (ni == ic->ic_bss)
  487                         error = EPERM;
  488                 else {
  489                         if (ni->ni_state == IEEE80211_STA_COLLECT)
  490                                 break;
  491 
  492                         /* Disassociate station. */
  493                         if (ni->ni_state == IEEE80211_STA_ASSOC)
  494                                 IEEE80211_SEND_MGMT(ic, ni,
  495                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
  496                                     IEEE80211_REASON_ASSOC_LEAVE);
  497 
  498                         /* Deauth station. */
  499                         if (ni->ni_state >= IEEE80211_STA_AUTH)
  500                                 IEEE80211_SEND_MGMT(ic, ni,
  501                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
  502                                     IEEE80211_REASON_AUTH_LEAVE);
  503 
  504                         ieee80211_release_node(ic, ni);
  505                 }
  506                 break;
  507         case SIOCG80211ALLNODES:
  508                 na = (struct ieee80211_nodereq_all *)data;
  509                 na->na_nodes = i = 0;
  510                 ni = RB_MIN(ieee80211_tree, &ic->ic_tree);
  511                 while (ni && na->na_size >=
  512                     i + sizeof(struct ieee80211_nodereq)) {
  513                         ieee80211_node2req(ic, ni, &nrbuf);
  514                         error = copyout(&nrbuf, (caddr_t)na->na_node + i,
  515                             sizeof(struct ieee80211_nodereq));
  516                         if (error)
  517                                 break;
  518                         i += sizeof(struct ieee80211_nodereq);
  519                         na->na_nodes++;
  520                         ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);
  521                 }
  522                 break;
  523         case SIOCG80211FLAGS:
  524                 flags = ic->ic_flags;
  525                 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
  526                         flags &= ~IEEE80211_F_HOSTAPMASK;
  527                 ifr->ifr_flags = flags >> IEEE80211_F_USERSHIFT;
  528                 break;
  529         case SIOCS80211FLAGS:
  530                 if ((error = suser(curproc, 0)) != 0)
  531                         break;
  532                 flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
  533                 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
  534                     (flags & IEEE80211_F_HOSTAPMASK)) {
  535                         error = EINVAL;
  536                         break;
  537                 }
  538                 ic->ic_flags = (ic->ic_flags & ~IEEE80211_F_USERMASK) | flags;
  539                 error = ENETRESET;
  540                 break;
  541         default:
  542                 error = EINVAL;
  543                 break;
  544         }
  545         return error;
  546 }

/* [<][>][^][v][top][bottom][index][help] */