[BACK]Return to ieee80211_ioctl.c CVS log [TXT][DIR] Up to [local] / sys / net80211

Annotation of sys/net80211/ieee80211_ioctl.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb