Home | History | Annotate | Line # | Download | only in ifconfig
ieee80211.c revision 1.7
      1  1.7  christos /*	$NetBSD: ieee80211.c,v 1.7 2006/08/26 18:14:28 christos Exp $	*/
      2  1.1   thorpej 
      3  1.1   thorpej /*
      4  1.1   thorpej  * Copyright (c) 1983, 1993
      5  1.1   thorpej  *      The Regents of the University of California.  All rights reserved.
      6  1.1   thorpej  *
      7  1.1   thorpej  * Redistribution and use in source and binary forms, with or without
      8  1.1   thorpej  * modification, are permitted provided that the following conditions
      9  1.1   thorpej  * are met:
     10  1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     11  1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     12  1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     14  1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     15  1.1   thorpej  * 3. Neither the name of the University nor the names of its contributors
     16  1.1   thorpej  *    may be used to endorse or promote products derived from this software
     17  1.1   thorpej  *    without specific prior written permission.
     18  1.1   thorpej  *
     19  1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  1.1   thorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  1.1   thorpej  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  1.1   thorpej  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  1.1   thorpej  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  1.1   thorpej  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  1.1   thorpej  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  1.1   thorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  1.1   thorpej  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  1.1   thorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  1.1   thorpej  * SUCH DAMAGE.
     30  1.1   thorpej  */
     31  1.1   thorpej 
     32  1.1   thorpej #include <sys/cdefs.h>
     33  1.1   thorpej #ifndef lint
     34  1.7  christos __RCSID("$NetBSD: ieee80211.c,v 1.7 2006/08/26 18:14:28 christos Exp $");
     35  1.1   thorpej #endif /* not lint */
     36  1.1   thorpej 
     37  1.1   thorpej #include <sys/param.h>
     38  1.1   thorpej #include <sys/ioctl.h>
     39  1.1   thorpej #include <sys/socket.h>
     40  1.1   thorpej 
     41  1.1   thorpej #include <net/if.h>
     42  1.1   thorpej #include <net/if_ether.h>
     43  1.5    rpaulo #include <net/if_media.h>
     44  1.1   thorpej #include <net80211/ieee80211.h>
     45  1.1   thorpej #include <net80211/ieee80211_ioctl.h>
     46  1.1   thorpej 
     47  1.1   thorpej #include <ctype.h>
     48  1.1   thorpej #include <err.h>
     49  1.1   thorpej #include <netdb.h>
     50  1.1   thorpej #include <string.h>
     51  1.1   thorpej #include <stdlib.h>
     52  1.1   thorpej #include <stdio.h>
     53  1.7  christos #include <util.h>
     54  1.1   thorpej 
     55  1.1   thorpej #include "extern.h"
     56  1.1   thorpej #include "ieee80211.h"
     57  1.1   thorpej 
     58  1.5    rpaulo static void set80211(int, int, int, uint8_t *);
     59  1.5    rpaulo 
     60  1.5    rpaulo static void
     61  1.5    rpaulo set80211(int type, int val, int len, u_int8_t *data)
     62  1.5    rpaulo {
     63  1.5    rpaulo 	struct ieee80211req	ireq;
     64  1.5    rpaulo 
     65  1.5    rpaulo 	(void) memset(&ireq, 0, sizeof(ireq));
     66  1.6      elad 	estrlcpy(ireq.i_name, name, sizeof(ireq.i_name));
     67  1.5    rpaulo 	ireq.i_type = type;
     68  1.5    rpaulo 	ireq.i_val = val;
     69  1.5    rpaulo 	ireq.i_len = len;
     70  1.5    rpaulo 	ireq.i_data = data;
     71  1.5    rpaulo 	if (ioctl(s, SIOCS80211, &ireq) < 0)
     72  1.5    rpaulo 		err(1, "SIOCS80211");
     73  1.5    rpaulo }
     74  1.5    rpaulo 
     75  1.5    rpaulo void
     76  1.5    rpaulo sethidessid(const char *val, int d)
     77  1.5    rpaulo {
     78  1.5    rpaulo 	set80211(IEEE80211_IOC_HIDESSID, d, 0, NULL);
     79  1.5    rpaulo }
     80  1.5    rpaulo 
     81  1.5    rpaulo void
     82  1.5    rpaulo setapbridge(const char *val, int d)
     83  1.5    rpaulo {
     84  1.5    rpaulo 	set80211(IEEE80211_IOC_APBRIDGE, d, 0, NULL);
     85  1.5    rpaulo }
     86  1.5    rpaulo 
     87  1.5    rpaulo static enum ieee80211_opmode
     88  1.5    rpaulo get80211opmode(void)
     89  1.5    rpaulo {
     90  1.5    rpaulo 	struct ifmediareq ifmr;
     91  1.5    rpaulo 
     92  1.5    rpaulo 	(void) memset(&ifmr, 0, sizeof(ifmr));
     93  1.6      elad 	estrlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
     94  1.5    rpaulo 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
     95  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_ADHOC)
     96  1.5    rpaulo 			return IEEE80211_M_IBSS;        /* XXX ahdemo */
     97  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
     98  1.5    rpaulo 			return IEEE80211_M_HOSTAP;
     99  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
    100  1.5    rpaulo 			return IEEE80211_M_MONITOR;
    101  1.5    rpaulo 	}
    102  1.5    rpaulo 
    103  1.5    rpaulo 	return IEEE80211_M_STA;
    104  1.5    rpaulo }
    105  1.5    rpaulo 
    106  1.1   thorpej void
    107  1.1   thorpej setifnwid(const char *val, int d)
    108  1.1   thorpej {
    109  1.1   thorpej 	struct ieee80211_nwid nwid;
    110  1.1   thorpej 	int len;
    111  1.1   thorpej 
    112  1.1   thorpej 	len = sizeof(nwid.i_nwid);
    113  1.1   thorpej 	if (get_string(val, NULL, nwid.i_nwid, &len) == NULL)
    114  1.1   thorpej 		return;
    115  1.1   thorpej 	nwid.i_len = len;
    116  1.6      elad 	estrlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    117  1.1   thorpej 	ifr.ifr_data = (void *)&nwid;
    118  1.1   thorpej 	if (ioctl(s, SIOCS80211NWID, &ifr) == -1)
    119  1.1   thorpej 		warn("SIOCS80211NWID");
    120  1.1   thorpej }
    121  1.1   thorpej 
    122  1.1   thorpej void
    123  1.1   thorpej setifbssid(const char *val, int d)
    124  1.1   thorpej {
    125  1.1   thorpej 	struct ieee80211_bssid bssid;
    126  1.1   thorpej 	struct ether_addr *ea;
    127  1.1   thorpej 
    128  1.1   thorpej 	if (d != 0) {
    129  1.1   thorpej 		/* no BSSID is especially desired */
    130  1.1   thorpej 		memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid));
    131  1.1   thorpej 	} else {
    132  1.1   thorpej 		ea = ether_aton(val);
    133  1.1   thorpej 		if (ea == NULL) {
    134  1.1   thorpej 			warnx("malformed BSSID: %s", val);
    135  1.1   thorpej 			return;
    136  1.1   thorpej 		}
    137  1.1   thorpej 		memcpy(&bssid.i_bssid, ea->ether_addr_octet,
    138  1.1   thorpej 		    sizeof(bssid.i_bssid));
    139  1.1   thorpej 	}
    140  1.6      elad 	estrlcpy(bssid.i_name, name, sizeof(bssid.i_name));
    141  1.1   thorpej 	if (ioctl(s, SIOCS80211BSSID, &bssid) == -1)
    142  1.1   thorpej 		warn("SIOCS80211BSSID");
    143  1.1   thorpej }
    144  1.1   thorpej 
    145  1.1   thorpej void
    146  1.1   thorpej setifchan(const char *val, int d)
    147  1.1   thorpej {
    148  1.1   thorpej 	struct ieee80211chanreq channel;
    149  1.1   thorpej 	int chan;
    150  1.1   thorpej 
    151  1.1   thorpej 	if (d != 0)
    152  1.1   thorpej 		chan = IEEE80211_CHAN_ANY;
    153  1.1   thorpej 	else {
    154  1.1   thorpej 		chan = atoi(val);
    155  1.1   thorpej 		if (chan < 0 || chan > 0xffff) {
    156  1.1   thorpej 			warnx("invalid channel: %s", val);
    157  1.1   thorpej 			return;
    158  1.1   thorpej 		}
    159  1.1   thorpej 	}
    160  1.1   thorpej 
    161  1.6      elad 	estrlcpy(channel.i_name, name, sizeof(channel.i_name));
    162  1.1   thorpej 	channel.i_channel = (u_int16_t) chan;
    163  1.1   thorpej 	if (ioctl(s, SIOCS80211CHANNEL, &channel) == -1)
    164  1.1   thorpej 		warn("SIOCS80211CHANNEL");
    165  1.1   thorpej }
    166  1.1   thorpej 
    167  1.1   thorpej void
    168  1.1   thorpej setifnwkey(const char *val, int d)
    169  1.1   thorpej {
    170  1.1   thorpej 	struct ieee80211_nwkey nwkey;
    171  1.1   thorpej 	int i;
    172  1.1   thorpej 	u_int8_t keybuf[IEEE80211_WEP_NKID][16];
    173  1.1   thorpej 
    174  1.1   thorpej 	nwkey.i_wepon = IEEE80211_NWKEY_WEP;
    175  1.1   thorpej 	nwkey.i_defkid = 1;
    176  1.1   thorpej 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    177  1.1   thorpej 		nwkey.i_key[i].i_keylen = sizeof(keybuf[i]);
    178  1.1   thorpej 		nwkey.i_key[i].i_keydat = keybuf[i];
    179  1.1   thorpej 	}
    180  1.1   thorpej 	if (d != 0) {
    181  1.1   thorpej 		/* disable WEP encryption */
    182  1.1   thorpej 		nwkey.i_wepon = 0;
    183  1.1   thorpej 		i = 0;
    184  1.1   thorpej 	} else if (strcasecmp("persist", val) == 0) {
    185  1.1   thorpej 		/* use all values from persistent memory */
    186  1.1   thorpej 		nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST;
    187  1.1   thorpej 		nwkey.i_defkid = 0;
    188  1.1   thorpej 		for (i = 0; i < IEEE80211_WEP_NKID; i++)
    189  1.1   thorpej 			nwkey.i_key[i].i_keylen = -1;
    190  1.1   thorpej 	} else if (strncasecmp("persist:", val, 8) == 0) {
    191  1.1   thorpej 		val += 8;
    192  1.1   thorpej 		/* program keys in persistent memory */
    193  1.1   thorpej 		nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST;
    194  1.1   thorpej 		goto set_nwkey;
    195  1.1   thorpej 	} else {
    196  1.1   thorpej   set_nwkey:
    197  1.1   thorpej 		if (isdigit((unsigned char)val[0]) && val[1] == ':') {
    198  1.1   thorpej 			/* specifying a full set of four keys */
    199  1.1   thorpej 			nwkey.i_defkid = val[0] - '0';
    200  1.1   thorpej 			val += 2;
    201  1.1   thorpej 			for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    202  1.1   thorpej 				val = get_string(val, ",", keybuf[i],
    203  1.1   thorpej 				    &nwkey.i_key[i].i_keylen);
    204  1.1   thorpej 				if (val == NULL)
    205  1.1   thorpej 					return;
    206  1.1   thorpej 			}
    207  1.1   thorpej 			if (*val != '\0') {
    208  1.1   thorpej 				warnx("SIOCS80211NWKEY: too many keys.");
    209  1.1   thorpej 				return;
    210  1.1   thorpej 			}
    211  1.1   thorpej 		} else {
    212  1.1   thorpej 			val = get_string(val, NULL, keybuf[0],
    213  1.1   thorpej 			    &nwkey.i_key[0].i_keylen);
    214  1.1   thorpej 			if (val == NULL)
    215  1.1   thorpej 				return;
    216  1.1   thorpej 			i = 1;
    217  1.1   thorpej 		}
    218  1.1   thorpej 	}
    219  1.1   thorpej 	for (; i < IEEE80211_WEP_NKID; i++)
    220  1.1   thorpej 		nwkey.i_key[i].i_keylen = 0;
    221  1.6      elad 	estrlcpy(nwkey.i_name, name, sizeof(nwkey.i_name));
    222  1.1   thorpej 	if (ioctl(s, SIOCS80211NWKEY, &nwkey) == -1)
    223  1.1   thorpej 		warn("SIOCS80211NWKEY");
    224  1.1   thorpej }
    225  1.1   thorpej 
    226  1.1   thorpej void
    227  1.1   thorpej setifpowersave(const char *val, int d)
    228  1.1   thorpej {
    229  1.1   thorpej 	struct ieee80211_power power;
    230  1.1   thorpej 
    231  1.6      elad 	estrlcpy(power.i_name, name, sizeof(power.i_name));
    232  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1) {
    233  1.1   thorpej 		warn("SIOCG80211POWER");
    234  1.1   thorpej 		return;
    235  1.1   thorpej 	}
    236  1.1   thorpej 
    237  1.1   thorpej 	power.i_enabled = d;
    238  1.1   thorpej 	if (ioctl(s, SIOCS80211POWER, &power) == -1)
    239  1.1   thorpej 		warn("SIOCS80211POWER");
    240  1.1   thorpej }
    241  1.1   thorpej 
    242  1.1   thorpej void
    243  1.1   thorpej setifpowersavesleep(const char *val, int d)
    244  1.1   thorpej {
    245  1.1   thorpej 	struct ieee80211_power power;
    246  1.1   thorpej 
    247  1.6      elad 	estrlcpy(power.i_name, name, sizeof(power.i_name));
    248  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1) {
    249  1.1   thorpej 		warn("SIOCG80211POWER");
    250  1.1   thorpej 		return;
    251  1.1   thorpej 	}
    252  1.1   thorpej 
    253  1.1   thorpej 	power.i_maxsleep = atoi(val);
    254  1.1   thorpej 	if (ioctl(s, SIOCS80211POWER, &power) == -1)
    255  1.1   thorpej 		warn("SIOCS80211POWER");
    256  1.1   thorpej }
    257  1.1   thorpej 
    258  1.1   thorpej void
    259  1.1   thorpej ieee80211_statistics(void)
    260  1.1   thorpej {
    261  1.1   thorpej 	struct ieee80211_stats stats;
    262  1.1   thorpej 
    263  1.1   thorpej 	memset(&ifr, 0, sizeof(ifr));
    264  1.3    dyoung 	ifr.ifr_buflen = sizeof(stats);
    265  1.3    dyoung 	ifr.ifr_buf = (caddr_t)&stats;
    266  1.6      elad 	estrlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    267  1.1   thorpej 	if (ioctl(s, (zflag) ? SIOCG80211ZSTATS : SIOCG80211STATS,
    268  1.1   thorpej 	    (caddr_t)&ifr) == -1)
    269  1.1   thorpej 		return;
    270  1.2    dyoung #define	STAT_PRINT(_member, _desc)	\
    271  1.2    dyoung 	printf("\t" _desc ": %" PRIu32 "\n", stats._member)
    272  1.1   thorpej 
    273  1.2    dyoung 	STAT_PRINT(is_rx_badversion, "rx frame with bad version");
    274  1.2    dyoung 	STAT_PRINT(is_rx_tooshort, "rx frame too short");
    275  1.2    dyoung 	STAT_PRINT(is_rx_wrongbss, "rx from wrong bssid");
    276  1.2    dyoung 	STAT_PRINT(is_rx_dup, "rx discard 'cuz dup");
    277  1.2    dyoung 	STAT_PRINT(is_rx_wrongdir, "rx w/ wrong direction");
    278  1.2    dyoung 	STAT_PRINT(is_rx_mcastecho, "rx discard 'cuz mcast echo");
    279  1.2    dyoung 	STAT_PRINT(is_rx_notassoc, "rx discard 'cuz sta !assoc");
    280  1.2    dyoung 	STAT_PRINT(is_rx_noprivacy, "rx w/ wep but privacy off");
    281  1.2    dyoung 	STAT_PRINT(is_rx_unencrypted, "rx w/o wep and privacy on");
    282  1.2    dyoung 	STAT_PRINT(is_rx_wepfail, "rx wep processing failed");
    283  1.2    dyoung 	STAT_PRINT(is_rx_decap, "rx decapsulation failed");
    284  1.2    dyoung 	STAT_PRINT(is_rx_mgtdiscard, "rx discard mgt frames");
    285  1.2    dyoung 	STAT_PRINT(is_rx_ctl, "rx discard ctrl frames");
    286  1.2    dyoung 	STAT_PRINT(is_rx_beacon, "rx beacon frames");
    287  1.2    dyoung 	STAT_PRINT(is_rx_rstoobig, "rx rate set truncated");
    288  1.2    dyoung 	STAT_PRINT(is_rx_elem_missing, "rx required element missin");
    289  1.2    dyoung 	STAT_PRINT(is_rx_elem_toobig, "rx element too big");
    290  1.2    dyoung 	STAT_PRINT(is_rx_elem_toosmall, "rx element too small");
    291  1.2    dyoung 	STAT_PRINT(is_rx_elem_unknown, "rx element unknown");
    292  1.2    dyoung 	STAT_PRINT(is_rx_badchan, "rx frame w/ invalid chan");
    293  1.2    dyoung 	STAT_PRINT(is_rx_chanmismatch, "rx frame chan mismatch");
    294  1.2    dyoung 	STAT_PRINT(is_rx_nodealloc, "rx frame dropped");
    295  1.2    dyoung 	STAT_PRINT(is_rx_ssidmismatch, "rx frame ssid mismatch ");
    296  1.2    dyoung 	STAT_PRINT(is_rx_auth_unsupported, "rx w/ unsupported auth alg");
    297  1.2    dyoung 	STAT_PRINT(is_rx_auth_fail, "rx sta auth failure");
    298  1.2    dyoung 	STAT_PRINT(is_rx_auth_countermeasures, "rx auth discard 'cuz CM");
    299  1.2    dyoung 	STAT_PRINT(is_rx_assoc_bss, "rx assoc from wrong bssid");
    300  1.2    dyoung 	STAT_PRINT(is_rx_assoc_notauth, "rx assoc w/o auth");
    301  1.2    dyoung 	STAT_PRINT(is_rx_assoc_capmismatch, "rx assoc w/ cap mismatch");
    302  1.2    dyoung 	STAT_PRINT(is_rx_assoc_norate, "rx assoc w/ no rate match");
    303  1.2    dyoung 	STAT_PRINT(is_rx_assoc_badwpaie, "rx assoc w/ bad WPA IE");
    304  1.2    dyoung 	STAT_PRINT(is_rx_deauth, "rx deauthentication");
    305  1.2    dyoung 	STAT_PRINT(is_rx_disassoc, "rx disassociation");
    306  1.2    dyoung 	STAT_PRINT(is_rx_badsubtype, "rx frame w/ unknown subtyp");
    307  1.2    dyoung 	STAT_PRINT(is_rx_nobuf, "rx failed for lack of buf");
    308  1.2    dyoung 	STAT_PRINT(is_rx_decryptcrc, "rx decrypt failed on crc");
    309  1.2    dyoung 	STAT_PRINT(is_rx_ahdemo_mgt, "rx discard ahdemo mgt fram");
    310  1.2    dyoung 	STAT_PRINT(is_rx_bad_auth, "rx bad auth request");
    311  1.2    dyoung 	STAT_PRINT(is_rx_unauth, "rx on unauthorized port");
    312  1.2    dyoung 	STAT_PRINT(is_rx_badkeyid, "rx w/ incorrect keyid");
    313  1.2    dyoung 	STAT_PRINT(is_rx_ccmpreplay, "rx seq# violation (CCMP)");
    314  1.2    dyoung 	STAT_PRINT(is_rx_ccmpformat, "rx format bad (CCMP)");
    315  1.2    dyoung 	STAT_PRINT(is_rx_ccmpmic, "rx MIC check failed (CCMP)");
    316  1.2    dyoung 	STAT_PRINT(is_rx_tkipreplay, "rx seq# violation (TKIP)");
    317  1.2    dyoung 	STAT_PRINT(is_rx_tkipformat, "rx format bad (TKIP)");
    318  1.2    dyoung 	STAT_PRINT(is_rx_tkipmic, "rx MIC check failed (TKIP)");
    319  1.2    dyoung 	STAT_PRINT(is_rx_tkipicv, "rx ICV check failed (TKIP)");
    320  1.2    dyoung 	STAT_PRINT(is_rx_badcipher, "rx failed 'cuz key type");
    321  1.2    dyoung 	STAT_PRINT(is_rx_nocipherctx, "rx failed 'cuz key !setup");
    322  1.2    dyoung 	STAT_PRINT(is_rx_acl, "rx discard 'cuz acl policy");
    323  1.2    dyoung 
    324  1.2    dyoung 	STAT_PRINT(is_tx_nobuf, "tx failed for lack of buf");
    325  1.2    dyoung 	STAT_PRINT(is_tx_nonode, "tx failed for no node");
    326  1.2    dyoung 	STAT_PRINT(is_tx_unknownmgt, "tx of unknown mgt frame");
    327  1.2    dyoung 	STAT_PRINT(is_tx_badcipher, "tx failed 'cuz key type");
    328  1.2    dyoung 	STAT_PRINT(is_tx_nodefkey, "tx failed 'cuz no defkey");
    329  1.2    dyoung 	STAT_PRINT(is_tx_noheadroom, "tx failed 'cuz no space");
    330  1.2    dyoung 
    331  1.2    dyoung 	STAT_PRINT(is_scan_active, "active scans started");
    332  1.2    dyoung 	STAT_PRINT(is_scan_passive, "passive scans started");
    333  1.2    dyoung 	STAT_PRINT(is_node_timeout, "nodes timed out inactivity");
    334  1.2    dyoung 	STAT_PRINT(is_crypto_nomem, "no memory for crypto ctx");
    335  1.2    dyoung 	STAT_PRINT(is_crypto_tkip, "tkip crypto done in s/w");
    336  1.2    dyoung 	STAT_PRINT(is_crypto_tkipenmic, "tkip en-MIC done in s/w");
    337  1.2    dyoung 	STAT_PRINT(is_crypto_tkipdemic, "tkip de-MIC done in s/w");
    338  1.2    dyoung 	STAT_PRINT(is_crypto_tkipcm, "tkip counter measures");
    339  1.2    dyoung 	STAT_PRINT(is_crypto_ccmp, "ccmp crypto done in s/w");
    340  1.2    dyoung 	STAT_PRINT(is_crypto_wep, "wep crypto done in s/w");
    341  1.2    dyoung 	STAT_PRINT(is_crypto_setkey_cipher, "cipher rejected key");
    342  1.2    dyoung 	STAT_PRINT(is_crypto_setkey_nokey, "no key index for setkey");
    343  1.2    dyoung 	STAT_PRINT(is_crypto_delkey, "driver key delete failed");
    344  1.2    dyoung 	STAT_PRINT(is_crypto_badcipher, "unknown cipher");
    345  1.2    dyoung 	STAT_PRINT(is_crypto_nocipher, "cipher not available");
    346  1.2    dyoung 	STAT_PRINT(is_crypto_attachfail, "cipher attach failed");
    347  1.2    dyoung 	STAT_PRINT(is_crypto_swfallback, "cipher fallback to s/w");
    348  1.2    dyoung 	STAT_PRINT(is_crypto_keyfail, "driver key alloc failed");
    349  1.2    dyoung 	STAT_PRINT(is_crypto_enmicfail, "en-MIC failed");
    350  1.2    dyoung 	STAT_PRINT(is_ibss_capmismatch, "merge failed-cap mismatch");
    351  1.2    dyoung 	STAT_PRINT(is_ibss_norate, "merge failed-rate mismatch");
    352  1.2    dyoung 	STAT_PRINT(is_ps_unassoc, "ps-poll for unassoc. sta");
    353  1.2    dyoung 	STAT_PRINT(is_ps_badaid, "ps-poll w/ incorrect aid");
    354  1.2    dyoung 	STAT_PRINT(is_ps_qempty, "ps-poll w/ nothing to send");
    355  1.1   thorpej }
    356  1.1   thorpej 
    357  1.1   thorpej void
    358  1.1   thorpej ieee80211_status(void)
    359  1.1   thorpej {
    360  1.1   thorpej 	int i, nwkey_verbose;
    361  1.1   thorpej 	struct ieee80211_nwid nwid;
    362  1.1   thorpej 	struct ieee80211_nwkey nwkey;
    363  1.1   thorpej 	struct ieee80211_power power;
    364  1.1   thorpej 	u_int8_t keybuf[IEEE80211_WEP_NKID][16];
    365  1.1   thorpej 	struct ieee80211_bssid bssid;
    366  1.1   thorpej 	struct ieee80211chanreq channel;
    367  1.5    rpaulo 	struct ieee80211req ireq;
    368  1.1   thorpej 	struct ether_addr ea;
    369  1.1   thorpej 	static const u_int8_t zero_macaddr[IEEE80211_ADDR_LEN];
    370  1.5    rpaulo 	enum ieee80211_opmode opmode = get80211opmode();
    371  1.5    rpaulo 	extern int vflag;
    372  1.1   thorpej 
    373  1.1   thorpej 	memset(&ifr, 0, sizeof(ifr));
    374  1.1   thorpej 	ifr.ifr_data = (void *)&nwid;
    375  1.6      elad 	estrlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    376  1.1   thorpej 	if (ioctl(s, SIOCG80211NWID, &ifr) == -1)
    377  1.1   thorpej 		return;
    378  1.1   thorpej 	if (nwid.i_len > IEEE80211_NWID_LEN) {
    379  1.1   thorpej 		warnx("SIOCG80211NWID: wrong length of nwid (%d)", nwid.i_len);
    380  1.1   thorpej 		return;
    381  1.1   thorpej 	}
    382  1.1   thorpej 	printf("\tssid ");
    383  1.1   thorpej 	print_string(nwid.i_nwid, nwid.i_len);
    384  1.5    rpaulo 
    385  1.5    rpaulo 	if (opmode == IEEE80211_M_HOSTAP) {
    386  1.6      elad 		estrlcpy(ireq.i_name, name, sizeof(ireq.i_name));
    387  1.5    rpaulo 		ireq.i_type = IEEE80211_IOC_HIDESSID;
    388  1.5    rpaulo 		if (ioctl(s, SIOCG80211, &ireq) != -1) {
    389  1.5    rpaulo                         if (ireq.i_val)
    390  1.5    rpaulo                                 printf(" [hidden]");
    391  1.5    rpaulo                         else if (vflag)
    392  1.5    rpaulo                                 printf(" [shown]");
    393  1.5    rpaulo                 }
    394  1.5    rpaulo 
    395  1.5    rpaulo 		ireq.i_type = IEEE80211_IOC_APBRIDGE;
    396  1.5    rpaulo 		if (ioctl(s, SIOCG80211, &ireq) != -1) {
    397  1.5    rpaulo 			if (ireq.i_val)
    398  1.5    rpaulo 				printf(" apbridge");
    399  1.5    rpaulo 			else if (vflag)
    400  1.5    rpaulo 				printf(" -apbridge");
    401  1.5    rpaulo 		}
    402  1.5    rpaulo         }
    403  1.5    rpaulo 
    404  1.1   thorpej 	memset(&nwkey, 0, sizeof(nwkey));
    405  1.6      elad 	estrlcpy(nwkey.i_name, name, sizeof(nwkey.i_name));
    406  1.1   thorpej 	/* show nwkey only when WEP is enabled */
    407  1.1   thorpej 	if (ioctl(s, SIOCG80211NWKEY, &nwkey) == -1 ||
    408  1.1   thorpej 	    nwkey.i_wepon == 0) {
    409  1.1   thorpej 		printf("\n");
    410  1.1   thorpej 		goto skip_wep;
    411  1.1   thorpej 	}
    412  1.1   thorpej 
    413  1.1   thorpej 	printf(" nwkey ");
    414  1.1   thorpej 	/* try to retrieve WEP keys */
    415  1.1   thorpej 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    416  1.1   thorpej 		nwkey.i_key[i].i_keydat = keybuf[i];
    417  1.1   thorpej 		nwkey.i_key[i].i_keylen = sizeof(keybuf[i]);
    418  1.1   thorpej 	}
    419  1.1   thorpej 	if (ioctl(s, SIOCG80211NWKEY, &nwkey) == -1) {
    420  1.1   thorpej 		printf("*****");
    421  1.1   thorpej 	} else {
    422  1.1   thorpej 		nwkey_verbose = 0;
    423  1.1   thorpej 		/* check to see non default key or multiple keys defined */
    424  1.1   thorpej 		if (nwkey.i_defkid != 1) {
    425  1.1   thorpej 			nwkey_verbose = 1;
    426  1.1   thorpej 		} else {
    427  1.1   thorpej 			for (i = 1; i < IEEE80211_WEP_NKID; i++) {
    428  1.1   thorpej 				if (nwkey.i_key[i].i_keylen != 0) {
    429  1.1   thorpej 					nwkey_verbose = 1;
    430  1.1   thorpej 					break;
    431  1.1   thorpej 				}
    432  1.1   thorpej 			}
    433  1.1   thorpej 		}
    434  1.1   thorpej 		/* check extra ambiguity with keywords */
    435  1.1   thorpej 		if (!nwkey_verbose) {
    436  1.1   thorpej 			if (nwkey.i_key[0].i_keylen >= 2 &&
    437  1.1   thorpej 			    isdigit(nwkey.i_key[0].i_keydat[0]) &&
    438  1.1   thorpej 			    nwkey.i_key[0].i_keydat[1] == ':')
    439  1.1   thorpej 				nwkey_verbose = 1;
    440  1.1   thorpej 			else if (nwkey.i_key[0].i_keylen >= 7 &&
    441  1.4  christos 			    strncasecmp("persist",
    442  1.4  christos 			    (const char *)nwkey.i_key[0].i_keydat, 7) == 0)
    443  1.1   thorpej 				nwkey_verbose = 1;
    444  1.1   thorpej 		}
    445  1.1   thorpej 		if (nwkey_verbose)
    446  1.1   thorpej 			printf("%d:", nwkey.i_defkid);
    447  1.1   thorpej 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    448  1.1   thorpej 			if (i > 0)
    449  1.1   thorpej 				printf(",");
    450  1.1   thorpej 			if (nwkey.i_key[i].i_keylen < 0)
    451  1.1   thorpej 				printf("persist");
    452  1.1   thorpej 			else
    453  1.1   thorpej 				print_string(nwkey.i_key[i].i_keydat,
    454  1.1   thorpej 				    nwkey.i_key[i].i_keylen);
    455  1.1   thorpej 			if (!nwkey_verbose)
    456  1.1   thorpej 				break;
    457  1.1   thorpej 		}
    458  1.1   thorpej 	}
    459  1.1   thorpej 	printf("\n");
    460  1.1   thorpej 
    461  1.1   thorpej  skip_wep:
    462  1.6      elad 	estrlcpy(power.i_name, name, sizeof(power.i_name));
    463  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1)
    464  1.1   thorpej 		goto skip_power;
    465  1.1   thorpej 	printf("\tpowersave ");
    466  1.1   thorpej 	if (power.i_enabled)
    467  1.1   thorpej 		printf("on (%dms sleep)", power.i_maxsleep);
    468  1.1   thorpej 	else
    469  1.1   thorpej 		printf("off");
    470  1.1   thorpej 	printf("\n");
    471  1.1   thorpej 
    472  1.1   thorpej  skip_power:
    473  1.6      elad 	estrlcpy(bssid.i_name, name, sizeof(bssid.i_name));
    474  1.1   thorpej 	if (ioctl(s, SIOCG80211BSSID, &bssid) == -1)
    475  1.1   thorpej 		return;
    476  1.6      elad 	estrlcpy(channel.i_name, name, sizeof(channel.i_name));
    477  1.1   thorpej 	if (ioctl(s, SIOCG80211CHANNEL, &channel) == -1)
    478  1.1   thorpej 		return;
    479  1.1   thorpej 	if (memcmp(bssid.i_bssid, zero_macaddr, IEEE80211_ADDR_LEN) == 0) {
    480  1.1   thorpej 		if (channel.i_channel != (u_int16_t)-1)
    481  1.1   thorpej 			printf("\tchan %d\n", channel.i_channel);
    482  1.1   thorpej 	} else {
    483  1.1   thorpej 		memcpy(ea.ether_addr_octet, bssid.i_bssid,
    484  1.1   thorpej 		    sizeof(ea.ether_addr_octet));
    485  1.1   thorpej 		printf("\tbssid %s", ether_ntoa(&ea));
    486  1.1   thorpej 		if (channel.i_channel != IEEE80211_CHAN_ANY)
    487  1.1   thorpej 			printf(" chan %d", channel.i_channel);
    488  1.1   thorpej 		printf("\n");
    489  1.1   thorpej 	}
    490  1.1   thorpej }
    491