2 * Copyright (c) 1997, 1998, 1999
3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: src/usr.sbin/wicontrol/wicontrol.c,v 1.37 2003/09/29 06:32:11 imp Exp $
33 * $DragonFly: src/usr.sbin/wicontrol/wicontrol.c,v 1.6 2004/07/28 10:38:33 joerg Exp $
36 #include <sys/param.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
39 #include <sys/socket.h>
42 #include <net/if_var.h>
43 #include <net/ethernet.h>
45 #include <netproto/802_11/ieee80211.h>
46 #include <netproto/802_11/ieee80211_ioctl.h>
47 #include <netproto/802_11/if_wavelan_ieee.h>
57 static int wi_getval(const char *, struct wi_req
*);
58 static int wi_getvalmaybe(const char *, struct wi_req
*);
59 static void wi_setval(const char *, struct wi_req
*);
60 static void wi_printstr(struct wi_req
*);
61 static void wi_setstr(const char *, int, char *);
62 static void wi_setbytes(const char *, int, char *, int);
63 static void wi_setword(const char *, int, int);
64 static void wi_sethex(const char *, int, char *);
65 static void wi_printwords(struct wi_req
*);
66 static void wi_printbool(struct wi_req
*);
67 static void wi_printhex(struct wi_req
*);
68 static void wi_printaps(struct wi_req
*);
69 static void wi_dumpinfo(const char *);
70 static void wi_dumpstats(const char *);
71 static void wi_setkeys(const char *, char *, int);
72 static void wi_printkeys(struct wi_req
*);
73 static void wi_printaplist(const char *);
74 static int wi_hex2int(char);
75 static void wi_str2key(char *, struct wi_key
*);
76 static void wi_readcache(const char *);
77 static void usage(const char *);
82 _wi_getval(const char *iface
, struct wi_req
*wreq
)
88 bzero((char *)&ifr
, sizeof(ifr
));
90 strlcpy(ifr
.ifr_name
, iface
, sizeof(ifr
.ifr_name
));
91 ifr
.ifr_data
= (caddr_t
)wreq
;
93 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
96 retval
= ioctl(s
, SIOCGWAVELAN
, &ifr
);
103 wi_getval(const char *iface
, struct wi_req
*wreq
)
105 if (_wi_getval(iface
, wreq
) == -1) {
106 if (errno
!= EINPROGRESS
)
107 err(1, "SIOCGWAVELAN");
114 wi_getvalmaybe(const char *iface
, struct wi_req
*wreq
)
116 if (_wi_getval(iface
, wreq
) == -1) {
117 if (errno
!= EINPROGRESS
&& errno
!= EINVAL
)
118 err(1, "SIOCGWAVELAN");
125 wi_setval(const char *iface
, struct wi_req
*wreq
)
130 bzero((char *)&ifr
, sizeof(ifr
));
132 strlcpy(ifr
.ifr_name
, iface
, sizeof(ifr
.ifr_name
));
133 ifr
.ifr_data
= (caddr_t
)wreq
;
135 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
140 if (ioctl(s
, SIOCSWAVELAN
, &ifr
) == -1)
141 err(1, "SIOCSWAVELAN");
149 wi_printstr(struct wi_req
*wreq
)
154 if (wreq
->wi_type
== WI_RID_SERIALNO
) {
155 ptr
= (char *)&wreq
->wi_val
;
156 for (i
= 0; i
< (wreq
->wi_len
- 1) * 2; i
++) {
161 ptr
= (char *)&wreq
->wi_val
[1];
162 for (i
= 0; i
< wreq
->wi_val
[0]; i
++) {
169 printf("[ %s ]", ptr
);
175 wi_setstr(const char *iface
, int code
, char *str
)
180 errx(1, "must specify interface name");
183 errx(1, "must specify string");
185 bzero((char *)&wreq
, sizeof(wreq
));
187 if (strlen(str
) > 30)
188 errx(1, "string too long");
192 wreq
.wi_val
[0] = strlen(str
);
193 bcopy(str
, (char *)&wreq
.wi_val
[1], strlen(str
));
195 wi_setval(iface
, &wreq
);
201 wi_setbytes(const char *iface
, int code
, char *bytes
, int len
)
206 errx(1, "must specify interface name");
208 bzero((char *)&wreq
, sizeof(wreq
));
211 wreq
.wi_len
= (len
/ 2) + 1;
212 bcopy(bytes
, (char *)&wreq
.wi_val
[0], len
);
214 wi_setval(iface
, &wreq
);
220 wi_setword(const char *iface
, int code
, int word
)
224 bzero((char *)&wreq
, sizeof(wreq
));
228 wreq
.wi_val
[0] = word
;
230 wi_setval(iface
, &wreq
);
236 wi_sethex(const char *iface
, int code
, char *str
)
238 struct ether_addr
*addr
;
241 errx(1, "must specify address");
243 addr
= ether_aton(str
);
246 errx(1, "badly formatted address");
248 wi_setbytes(iface
, code
, (char *)addr
, ETHER_ADDR_LEN
);
256 if (c
>= '0' && c
<= '9')
258 if (c
>= 'A' && c
<= 'F')
259 return (c
- 'A' + 10);
260 if (c
>= 'a' && c
<= 'f')
261 return (c
- 'a' + 10);
267 wi_str2key(char *s
, struct wi_key
*k
)
272 /* Is this a hex string? */
273 if (s
[0] == '0' && (s
[1] == 'x' || s
[1] == 'X')) {
274 /* Yes, convert to int. */
276 p
= (char *)&k
->wi_keydat
[0];
277 for (i
= 2; s
[i
] != '\0' && s
[i
+ 1] != '\0'; i
+= 2) {
278 *p
++ = (wi_hex2int(s
[i
]) << 4) + wi_hex2int(s
[i
+ 1]);
282 errx(1, "hex strings must be of even length");
285 /* No, just copy it in. */
286 bcopy(s
, k
->wi_keydat
, strlen(s
));
287 k
->wi_keylen
= strlen(s
);
294 wi_setkeys(const char *iface
, char *key
, int idx
)
298 struct wi_ltv_keys
*keys
;
302 bzero((char *)&wreq
, sizeof(wreq
));
303 wreq
.wi_len
= WI_MAX_DATALEN
;
304 wreq
.wi_type
= WI_RID_WEP_AVAIL
;
306 if (wi_getval(iface
, &wreq
) == 0)
307 has_wep
= wreq
.wi_val
[0];
311 errx(1, "no WEP option available on this card");
313 bzero((char *)&wreq
, sizeof(wreq
));
314 wreq
.wi_len
= WI_MAX_DATALEN
;
315 wreq
.wi_type
= WI_RID_DEFLT_CRYPT_KEYS
;
317 if (wi_getval(iface
, &wreq
) == -1)
318 errx(1, "Cannot get default key index");
319 keys
= (struct wi_ltv_keys
*)&wreq
;
321 keylen
= strlen(key
);
322 if (key
[0] == '0' && (key
[1] == 'x' || key
[1] == 'X')) {
323 if (keylen
!= 2 && keylen
!= 12 && keylen
!= 28) {
324 errx(1, "encryption key must be 0, 10, or 26 "
328 if (keylen
!= 0 && keylen
!= 5 && keylen
!= 13) {
329 errx(1, "encryption key must be 0, 5, or 13 "
335 errx(1, "only 4 encryption keys available");
337 k
= &keys
->wi_keys
[idx
];
340 wreq
.wi_len
= (sizeof(struct wi_ltv_keys
) / 2) + 1;
341 wreq
.wi_type
= WI_RID_DEFLT_CRYPT_KEYS
;
342 wi_setval(iface
, &wreq
);
348 wi_printkeys(struct wi_req
*wreq
)
353 struct wi_ltv_keys
*keys
;
356 keys
= (struct wi_ltv_keys
*)wreq
;
358 for (i
= 0; i
< 4; i
++) {
359 k
= &keys
->wi_keys
[i
];
360 ptr
= (char *)k
->wi_keydat
;
362 for (j
= 0; j
< k
->wi_keylen
; j
++) {
363 if (!isprint(ptr
[j
])) {
370 printf("[ %s ]", ptr
);
373 for (j
= 0; j
< k
->wi_keylen
; j
++) {
374 printf("%02x", ptr
[j
] & 0xFF);
385 wi_printwords(struct wi_req
*wreq
)
390 for (i
= 0; i
< wreq
->wi_len
- 1; i
++)
391 printf("%d ", wreq
->wi_val
[i
]);
398 wi_printswords(struct wi_req
*wreq
)
403 for (i
= 0; i
< wreq
->wi_len
- 1; i
++)
404 printf("%d ", ((int16_t *) wreq
->wi_val
)[i
]);
411 wi_printhexwords(struct wi_req
*wreq
)
416 for (i
= 0; i
< wreq
->wi_len
- 1; i
++)
417 printf("%x ", wreq
->wi_val
[i
]);
424 wi_printbool(struct wi_req
*wreq
)
435 wi_printhex(struct wi_req
*wreq
)
440 c
= (unsigned char *)&wreq
->wi_val
;
443 for (i
= 0; i
< (wreq
->wi_len
- 1) * 2; i
++) {
444 printf("%02x", c
[i
]);
445 if (i
< ((wreq
->wi_len
- 1) * 2) - 1)
454 wi_printaplist(const char *iface
)
456 int prism2
, len
, i
= 0, j
, r
;
458 struct wi_scan_p2_hdr
*wi_p2_h
;
459 struct wi_scan_res
*res
;
462 printf("Available APs:\n");
464 /* first determine if this is a prism2 card or not */
465 wreq
.wi_len
= WI_MAX_DATALEN
;
466 wreq
.wi_type
= WI_RID_PRISM2
;
468 if (wi_getval(iface
, &wreq
) == 0)
469 prism2
= wreq
.wi_val
[0];
473 /* send out a scan request */
474 wreq
.wi_len
= prism2
? 3 : 1;
475 wreq
.wi_type
= WI_RID_SCAN_REQ
;
478 wreq
.wi_val
[0] = 0x3FFF;
479 wreq
.wi_val
[1] = 0x000F;
482 wi_setval(iface
, &wreq
);
486 * sleep for 100 milliseconds so there's enough time for the card to
487 * respond... prism2's take a little longer.
489 usleep(prism2
? 500000 : 100000);
491 /* get the scan results */
492 wreq
.wi_len
= WI_MAX_DATALEN
;
493 wreq
.wi_type
= WI_RID_SCAN_RES
;
494 } while (wi_getval(iface
, &wreq
) == -1 && errno
== EINPROGRESS
);
497 wi_p2_h
= (struct wi_scan_p2_hdr
*)wreq
.wi_val
;
499 /* if the reason is 0, this info is invalid */
500 if (wi_p2_h
->wi_reason
== 0)
506 len
= prism2
? WI_PRISM2_RES_SIZE
: WI_WAVELAN_RES_SIZE
;
509 int nstations
= ((wreq
.wi_len
* 2) - i
) / len
;
510 if (nstations
== 0) {
511 printf("No stations\n");
514 printf("%d station%s:\n", nstations
, nstations
== 1 ? "" : "s");
515 printf("%-16.16s BSSID Chan SN S N Intrvl Capinfo\n", "SSID");
517 for (; i
< (wreq
.wi_len
* 2) - len
; i
+= len
) {
518 res
= (struct wi_scan_res
*)((char *)wreq
.wi_val
+ i
);
520 res
->wi_ssid
[res
->wi_ssid_len
] = '\0';
522 printf("%-16.16s [ %02x:%02x:%02x:%02x:%02x:%02x ] [ %-2d ] "
523 "[ %2d %2d %2d ] %3d ", res
->wi_ssid
,
524 res
->wi_bssid
[0], res
->wi_bssid
[1], res
->wi_bssid
[2],
525 res
->wi_bssid
[3], res
->wi_bssid
[4], res
->wi_bssid
[5],
526 res
->wi_chan
, res
->wi_signal
- res
->wi_noise
,
527 res
->wi_signal
, res
->wi_noise
, res
->wi_interval
);
529 if (!quiet
&& res
->wi_capinfo
) {
531 if (res
->wi_capinfo
& WI_CAPINFO_ESS
)
533 if (res
->wi_capinfo
& WI_CAPINFO_IBSS
)
535 if (res
->wi_capinfo
& IEEE80211_CAPINFO_CF_POLLABLE
)
537 if (res
->wi_capinfo
& IEEE80211_CAPINFO_CF_POLLREQ
)
539 if (res
->wi_capinfo
& WI_CAPINFO_PRIV
)
541 if (res
->wi_capinfo
& IEEE80211_CAPINFO_SHORT_PREAMBLE
)
543 if (res
->wi_capinfo
& IEEE80211_CAPINFO_PBCC
)
545 if (res
->wi_capinfo
& IEEE80211_CAPINFO_CHNL_AGILITY
)
547 if (res
->wi_capinfo
& IEEE80211_CAPINFO_SHORT_SLOTTIME
)
549 if (res
->wi_capinfo
& IEEE80211_CAPINFO_DSSSOFDM
)
554 if (prism2
&& res
->wi_srates
[0] != 0) {
555 printf("\n%16s [ ", "");
556 for (j
= 0; j
< 10 && res
->wi_srates
[j
] != 0; j
++) {
557 r
= res
->wi_srates
[j
] & IEEE80211_RATE_VAL
;
559 printf("%d.%d", r
/ 2, (r
% 2) * 5);
562 printf("%s ", res
->wi_srates
[j
] & IEEE80211_RATE_BASIC
? "b" : "");
570 #define WI_STRING 0x01
572 #define WI_WORDS 0x03
573 #define WI_HEXBYTES 0x04
574 #define WI_KEYSTRUCT 0x05
575 #define WI_SWORDS 0x06
576 #define WI_HEXWORDS 0x07
577 #define WI_REGDOMS 0x08
585 static struct wi_table wi_table
[] = {
586 { WI_RID_SERIALNO
, WI_STRING
, "NIC serial number:\t\t\t" },
587 { WI_RID_NODENAME
, WI_STRING
, "Station name:\t\t\t\t" },
588 { WI_RID_OWN_SSID
, WI_STRING
, "SSID for IBSS creation:\t\t\t" },
589 { WI_RID_CURRENT_SSID
, WI_STRING
, "Current netname (SSID):\t\t\t" },
590 { WI_RID_DESIRED_SSID
, WI_STRING
, "Desired netname (SSID):\t\t\t" },
591 { WI_RID_CURRENT_BSSID
, WI_HEXBYTES
, "Current BSSID:\t\t\t\t" },
592 { WI_RID_CHANNEL_LIST
, WI_HEXWORDS
, "Channel list:\t\t\t\t" },
593 { WI_RID_OWN_CHNL
, WI_WORDS
, "IBSS channel:\t\t\t\t" },
594 { WI_RID_CURRENT_CHAN
, WI_WORDS
, "Current channel:\t\t\t" },
595 { WI_RID_COMMS_QUALITY
, WI_WORDS
, "Comms quality/signal/noise:\t\t" },
596 { WI_RID_DBM_COMMS_QUAL
, WI_SWORDS
, "dBm Coms Quality:\t\t\t" },
597 { WI_RID_PROMISC
, WI_BOOL
, "Promiscuous mode:\t\t\t" },
598 { WI_RID_PROCFRAME
, WI_BOOL
, "Process 802.11b Frame:\t\t\t" },
599 { WI_RID_PRISM2
, WI_WORDS
, "Intersil-Prism2 based card:\t\t" },
600 { WI_RID_PORTTYPE
, WI_WORDS
, "Port type (1=BSS, 3=ad-hoc):\t\t"},
601 { WI_RID_MAC_NODE
, WI_HEXBYTES
, "MAC address:\t\t\t\t"},
602 { WI_RID_TX_RATE
, WI_WORDS
, "TX rate (selection):\t\t\t"},
603 { WI_RID_CUR_TX_RATE
, WI_WORDS
, "TX rate (actual speed):\t\t\t"},
604 { WI_RID_RTS_THRESH
, WI_WORDS
, "RTS/CTS handshake threshold:\t\t"},
605 { WI_RID_CREATE_IBSS
, WI_BOOL
, "Create IBSS:\t\t\t\t" },
606 { WI_RID_SYSTEM_SCALE
, WI_WORDS
, "Access point density:\t\t\t" },
607 { WI_RID_PM_ENABLED
, WI_WORDS
, "Power Mgmt (1=on, 0=off):\t\t" },
608 { WI_RID_MAX_SLEEP
, WI_WORDS
, "Max sleep time:\t\t\t\t" },
609 { WI_RID_PRI_IDENTITY
, WI_WORDS
, "PRI Identity:\t\t\t\t" },
610 { WI_RID_STA_IDENTITY
, WI_WORDS
, "STA Identity:\t\t\t\t" } ,
611 { WI_RID_CARD_ID
, WI_HEXWORDS
, "Card ID register:\t\t\t" },
612 { WI_RID_TEMP_TYPE
, WI_WORDS
, "Temperature Range:\t\t\t" },
614 { WI_RID_PRI_SUP_RANGE
, WI_WORDS
, "PRI Sup Range:\t\t\t\t" },
615 { WI_RID_CIF_ACT_RANGE
, WI_WORDS
, "CFI Act Sup Range:\t\t\t" },
616 { WI_RID_STA_SUP_RANGE
, WI_WORDS
, "STA Sup Range:\t\t\t\t" } ,
617 { WI_RID_MFI_ACT_RANGE
, WI_WORDS
, "MFI Act Sup Range:\t\t\t" } ,
622 static struct wi_table wi_crypt_table
[] = {
623 { WI_RID_ENCRYPTION
, WI_BOOL
, "WEP encryption:\t\t\t\t" },
624 { WI_RID_TX_CRYPT_KEY
, WI_WORDS
, "TX encryption key:\t\t\t" },
625 { WI_RID_DEFLT_CRYPT_KEYS
, WI_KEYSTRUCT
, "Encryption keys:\t\t\t" },
630 wi_dumpinfo(const char *iface
)
636 bzero((char *)&wreq
, sizeof(wreq
));
638 wreq
.wi_len
= WI_MAX_DATALEN
;
639 wreq
.wi_type
= WI_RID_WEP_AVAIL
;
641 if (wi_getval(iface
, &wreq
) == 0)
642 has_wep
= wreq
.wi_val
[0];
648 for (i
= 0; w
[i
].wi_type
; i
++) {
649 bzero((char *)&wreq
, sizeof(wreq
));
651 wreq
.wi_len
= WI_MAX_DATALEN
;
652 wreq
.wi_type
= w
[i
].wi_code
;
654 if (wi_getvalmaybe(iface
, &wreq
) == -1)
656 printf("%s", w
[i
].wi_str
);
657 switch(w
[i
].wi_type
) {
662 wi_printwords(&wreq
);
665 wi_printswords(&wreq
);
668 wi_printhexwords(&wreq
);
684 for (i
= 0; w
[i
].wi_type
; i
++) {
685 bzero((char *)&wreq
, sizeof(wreq
));
687 wreq
.wi_len
= WI_MAX_DATALEN
;
688 wreq
.wi_type
= w
[i
].wi_code
;
690 if (wi_getval(iface
, &wreq
) == -1)
692 printf("%s", w
[i
].wi_str
);
693 switch(w
[i
].wi_type
) {
698 if (wreq
.wi_type
== WI_RID_TX_CRYPT_KEY
)
700 wi_printwords(&wreq
);
719 wi_printaplist(iface
);
725 wi_dumpstats(const char *iface
)
728 struct wi_counters
*c
;
731 errx(1, "must specify interface name");
733 bzero((char *)&wreq
, sizeof(wreq
));
734 wreq
.wi_len
= WI_MAX_DATALEN
;
735 wreq
.wi_type
= WI_RID_IFACE_STATS
;
737 if (wi_getval(iface
, &wreq
) == -1)
738 errx(1, "Cannot get interface stats");
740 c
= (struct wi_counters
*)&wreq
.wi_val
;
742 printf("Transmitted unicast frames:\t\t%d\n",
743 c
->wi_tx_unicast_frames
);
744 printf("Transmitted multicast frames:\t\t%d\n",
745 c
->wi_tx_multicast_frames
);
746 printf("Transmitted fragments:\t\t\t%d\n",
748 printf("Transmitted unicast octets:\t\t%d\n",
749 c
->wi_tx_unicast_octets
);
750 printf("Transmitted multicast octets:\t\t%d\n",
751 c
->wi_tx_multicast_octets
);
752 printf("Single transmit retries:\t\t%d\n",
753 c
->wi_tx_single_retries
);
754 printf("Multiple transmit retries:\t\t%d\n",
755 c
->wi_tx_multi_retries
);
756 printf("Transmit retry limit exceeded:\t\t%d\n",
757 c
->wi_tx_retry_limit
);
758 printf("Transmit discards:\t\t\t%d\n",
760 printf("Transmit discards due to wrong SA:\t%d\n",
761 c
->wi_tx_discards_wrong_sa
);
762 printf("Received unicast frames:\t\t%d\n",
763 c
->wi_rx_unicast_frames
);
764 printf("Received multicast frames:\t\t%d\n",
765 c
->wi_rx_multicast_frames
);
766 printf("Received fragments:\t\t\t%d\n",
768 printf("Received unicast octets:\t\t%d\n",
769 c
->wi_rx_unicast_octets
);
770 printf("Received multicast octets:\t\t%d\n",
771 c
->wi_rx_multicast_octets
);
772 printf("Receive FCS errors:\t\t\t%d\n",
773 c
->wi_rx_fcs_errors
);
774 printf("Receive discards due to no buffer:\t%d\n",
775 c
->wi_rx_discards_nobuf
);
776 printf("Can't decrypt WEP frame:\t\t%d\n",
777 c
->wi_rx_WEP_cant_decrypt
);
778 printf("Received message fragments:\t\t%d\n",
779 c
->wi_rx_msg_in_msg_frags
);
780 printf("Received message bad fragments:\t\t%d\n",
781 c
->wi_rx_msg_in_bad_msg_frags
);
789 fprintf(stderr
, "usage: %s -i iface\n", p
);
790 fprintf(stderr
, "\t%s -i iface -o\n", p
);
791 fprintf(stderr
, "\t%s -i iface -l\n", p
);
792 fprintf(stderr
, "\t%s -i iface -L\n", p
);
793 fprintf(stderr
, "\t%s -i iface -t tx rate\n", p
);
794 fprintf(stderr
, "\t%s -i iface -n network name\n", p
);
795 fprintf(stderr
, "\t%s -i iface -s station name\n", p
);
796 fprintf(stderr
, "\t%s -i iface -c 0|1\n", p
);
797 fprintf(stderr
, "\t%s -i iface -q SSID\n", p
);
798 fprintf(stderr
, "\t%s -i iface -p port type\n", p
);
799 fprintf(stderr
, "\t%s -i iface -a access point density\n", p
);
800 fprintf(stderr
, "\t%s -i iface -m mac address\n", p
);
801 fprintf(stderr
, "\t%s -i iface -d max data length\n", p
);
802 fprintf(stderr
, "\t%s -i iface -e 0|1\n", p
);
803 fprintf(stderr
, "\t%s -i iface -k encryption key [-v 1|2|3|4]\n", p
);
804 fprintf(stderr
, "\t%s -i iface -r RTS threshold\n", p
);
805 fprintf(stderr
, "\t%s -i iface -f frequency\n", p
);
806 fprintf(stderr
, "\t%s -i iface -F 0|1\n", p
);
807 fprintf(stderr
, "\t%s -i iface -P 0|1\n", p
);
808 fprintf(stderr
, "\t%s -i iface -S max sleep duration\n", p
);
809 fprintf(stderr
, "\t%s -i iface -T 1|2|3|4\n", p
);
811 fprintf(stderr
, "\t%s -i iface -Z zero out signal cache\n", p
);
812 fprintf(stderr
, "\t%s -i iface -C print signal cache\n", p
);
819 wi_printaps(struct wi_req
*wreq
)
824 nstations
= *(int *)wreq
->wi_val
;
825 printf("%d station%s:\n", nstations
, nstations
== 1 ? "" : "s");
826 w
= (struct wi_apinfo
*)(((char *)&wreq
->wi_val
) + sizeof(int));
827 for ( i
= 0; i
< nstations
; i
++, w
++) {
828 printf("ap[%d]:\n", i
);
830 static const char *scanm
[] = {
832 "Firmware initiated",
833 "Inquiry request from host"
835 printf("\tScanReason:\t\t\t[ %s ]\n",
836 scanm
[w
->scanreason
- 1]);
838 printf("\tnetname (SSID):\t\t\t[ ");
839 for (j
= 0; j
< w
->namelen
; j
++) {
840 printf("%c", w
->name
[j
]);
843 printf("\tBSSID:\t\t\t\t[ %02x:%02x:%02x:%02x:%02x:%02x ]\n",
844 w
->bssid
[0]&0xff, w
->bssid
[1]&0xff,
845 w
->bssid
[2]&0xff, w
->bssid
[3]&0xff,
846 w
->bssid
[4]&0xff, w
->bssid
[5]&0xff);
847 printf("\tChannel:\t\t\t[ %d ]\n", w
->channel
);
848 printf("\tQuality/Signal/Noise [signal]:\t[ %d / %d / %d ]\n"
849 "\t [dBm]:\t[ %d / %d / %d ]\n",
850 w
->quality
, w
->signal
, w
->noise
,
851 w
->quality
, w
->signal
- 149, w
->noise
- 149);
852 printf("\tBSS Beacon Interval [msec]:\t[ %d ]\n", w
->interval
);
853 printf("\tCapinfo:\t\t\t[ ");
854 if (w
->capinfo
& IEEE80211_CAPINFO_ESS
)
856 if (w
->capinfo
& IEEE80211_CAPINFO_PRIVACY
)
863 wi_dumpstations(const char *iface
)
868 errx(1, "must specify interface name");
870 bzero((char *)&wreq
, sizeof(wreq
));
871 wreq
.wi_len
= WI_MAX_DATALEN
;
872 wreq
.wi_type
= WI_RID_READ_APS
;
874 if (wi_getval(iface
, &wreq
) == -1)
875 errx(1, "Cannot get stations");
880 wi_readcache(const char *iface
)
884 struct wi_sigcache
*sc
;
889 errx(1, "must specify interface name");
891 bzero((char *)&wreq
, sizeof(wreq
));
892 wreq
.wi_len
= WI_MAX_DATALEN
;
893 wreq
.wi_type
= WI_RID_READ_CACHE
;
894 if (wi_getval(iface
, &wreq
) == -1)
895 errx(1, "Cannot read signal cache");
897 wi_sigitems
= (int *) &wreq
.wi_val
;
898 pt
= ((char *) &wreq
.wi_val
);
900 sc
= (struct wi_sigcache
*) pt
;
902 for (i
= 0; i
< *wi_sigitems
; i
++) {
903 printf("[%d/%d]:", i
+1, *wi_sigitems
);
904 printf(" %02x:%02x:%02x:%02x:%02x:%02x,",
911 printf(" %d.%d.%d.%d,",((sc
->ipsrc
>> 0) & 0xff),
912 ((sc
->ipsrc
>> 8) & 0xff),
913 ((sc
->ipsrc
>> 16) & 0xff),
914 ((sc
->ipsrc
>> 24) & 0xff));
915 printf(" sig: %d, noise: %d, qual: %d\n",
926 dep(const char *flag
, const char *opt
)
928 warnx("warning: flag %s deprecated, migrate to ifconfig %s", flag
,
933 main(int argc
, char *argv
[])
936 const char *iface
= NULL
;
941 /* Get the interface name */
943 ch
= getopt(argc
, argv
, "i:");
947 if (argc
> 1 && *argv
[1] != '-') {
958 while((ch
= getopt(argc
, argv
,
959 "a:c:d:e:f:hi:k:lm:n:op:q:r:s:t:v:CF:LP:QS:T")) != -1) {
970 dep("c", "mediaopt");
971 wi_setword(iface
, WI_RID_CREATE_IBSS
, atoi(optarg
));
975 wi_setword(iface
, WI_RID_MAX_DATALEN
, atoi(optarg
));
980 wi_setword(iface
, WI_RID_ENCRYPTION
, atoi(optarg
));
985 wi_setword(iface
, WI_RID_OWN_CHNL
, atoi(optarg
));
989 wi_setword(iface
, WI_RID_PROCFRAME
, atoi(optarg
));
1000 wi_dumpstations(iface
);
1004 dep("p", "mediaopt");
1005 wi_setword(iface
, WI_RID_PORTTYPE
, atoi(optarg
));
1009 wi_setword(iface
, WI_RID_RTS_THRESH
, atoi(optarg
));
1013 dep("t", "mediaopt");
1014 wi_setword(iface
, WI_RID_TX_RATE
, atoi(optarg
));
1019 wi_setstr(iface
, WI_RID_DESIRED_SSID
, optarg
);
1023 dep("s", "stationname");
1024 wi_setstr(iface
, WI_RID_NODENAME
, optarg
);
1028 wi_sethex(iface
, WI_RID_MAC_NODE
, optarg
);
1036 wi_setstr(iface
, WI_RID_OWN_SSID
, optarg
);
1040 dep("S", "powersleep");
1041 wi_setword(iface
, WI_RID_MAX_SLEEP
, atoi(optarg
));
1045 dep("T", "weptxkey");
1047 WI_RID_TX_CRYPT_KEY
, atoi(optarg
) - 1);
1051 dep("P", "powersave");
1052 wi_setword(iface
, WI_RID_PM_ENABLED
, atoi(optarg
));
1056 wi_setword(iface
, WI_RID_SYSTEM_SCALE
, atoi(optarg
));
1060 modifier
= atoi(optarg
);
1074 wi_setkeys(iface
, key
, modifier
);
1079 wi_printaplist(iface
);