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