2 * Copyright 2001 The Aerospace Corporation. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of The Aerospace Corporation may not be used to endorse or
13 * promote products derived from this software.
15 * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: src/sbin/ifconfig/ifieee80211.c,v 1.18.2.10 2006/08/10 06:09:23 sam Exp $
28 * $DragonFly: src/sbin/ifconfig/ifieee80211.c,v 1.17 2006/12/08 14:25:07 sephe Exp $
32 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
33 * All rights reserved.
35 * This code is derived from software contributed to The NetBSD Foundation
36 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
37 * NASA Ames Research Center.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by the NetBSD
50 * Foundation, Inc. and its contributors.
51 * 4. Neither the name of The NetBSD Foundation nor the names of its
52 * contributors may be used to endorse or promote products derived
53 * from this software without specific prior written permission.
55 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
56 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
57 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
58 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
59 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65 * POSSIBILITY OF SUCH DAMAGE.
68 #include <sys/param.h>
69 #include <sys/ioctl.h>
70 #include <sys/socket.h>
71 #include <sys/sysctl.h>
74 #include <net/ethernet.h>
76 #include <net/if_dl.h>
77 #include <net/if_types.h>
78 #include <net/if_media.h>
79 #include <net/route.h>
81 #include <netproto/802_11/ieee80211.h>
82 #include <netproto/802_11/ieee80211_crypto.h>
83 #include <netproto/802_11/ieee80211_ioctl.h>
84 #include <netproto/802_11/ieee80211_ratectl.h>
99 static void set80211(int s
, int type
, int val
, int len
, u_int8_t
*data
);
100 static const char *get_string(const char *val
, const char *sep
,
101 u_int8_t
*buf
, int *lenp
);
102 static void print_string(const u_int8_t
*buf
, int len
);
105 isanyarg(const char *arg
)
107 return (strcmp(arg
, "-") == 0 ||
108 strcasecmp(arg
, "any") == 0 || strcasecmp(arg
, "off") == 0);
112 set80211ssid(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
116 u_int8_t data
[IEEE80211_NWID_LEN
];
120 if (len
> 2 && isdigit(val
[0]) && val
[1] == ':') {
125 bzero(data
, sizeof(data
));
127 if (get_string(val
, NULL
, data
, &len
) == NULL
)
130 set80211(s
, IEEE80211_IOC_SSID
, ssid
, len
, data
);
134 set80211stationname(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
139 bzero(data
, sizeof(data
));
141 get_string(val
, NULL
, data
, &len
);
143 set80211(s
, IEEE80211_IOC_STATIONNAME
, 0, len
, data
);
147 * Convert IEEE channel number to MHz frequency.
150 ieee80211_ieee2mhz(u_int chan
)
154 if (chan
< 14) /* 0-13 */
155 return 2407 + chan
*5;
156 if (chan
< 27) /* 15-26 */
157 return 2512 + ((chan
-15)*20);
158 return 5000 + (chan
*5);
162 * Convert MHz frequency to IEEE channel number.
165 ieee80211_mhz2ieee(u_int freq
)
170 return (freq
- 2407) / 5;
172 return 15 + ((freq
- 2512) / 20);
173 return (freq
- 5000) / 5;
177 set80211channel(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
179 if (!isanyarg(val
)) {
181 if (v
> 255) /* treat as frequency */
182 v
= ieee80211_mhz2ieee(v
);
183 set80211(s
, IEEE80211_IOC_CHANNEL
, v
, 0, NULL
);
185 set80211(s
, IEEE80211_IOC_CHANNEL
, IEEE80211_CHAN_ANY
, 0, NULL
);
189 set80211authmode(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
193 if (strcasecmp(val
, "none") == 0) {
194 mode
= IEEE80211_AUTH_NONE
;
195 } else if (strcasecmp(val
, "open") == 0) {
196 mode
= IEEE80211_AUTH_OPEN
;
197 } else if (strcasecmp(val
, "shared") == 0) {
198 mode
= IEEE80211_AUTH_SHARED
;
199 } else if (strcasecmp(val
, "8021x") == 0) {
200 mode
= IEEE80211_AUTH_8021X
;
201 } else if (strcasecmp(val
, "wpa") == 0) {
202 mode
= IEEE80211_AUTH_WPA
;
204 errx(1, "unknown authmode");
207 set80211(s
, IEEE80211_IOC_AUTHMODE
, mode
, 0, NULL
);
211 set80211powersavemode(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
215 if (strcasecmp(val
, "off") == 0) {
216 mode
= IEEE80211_POWERSAVE_OFF
;
217 } else if (strcasecmp(val
, "on") == 0) {
218 mode
= IEEE80211_POWERSAVE_ON
;
219 } else if (strcasecmp(val
, "cam") == 0) {
220 mode
= IEEE80211_POWERSAVE_CAM
;
221 } else if (strcasecmp(val
, "psp") == 0) {
222 mode
= IEEE80211_POWERSAVE_PSP
;
223 } else if (strcasecmp(val
, "psp-cam") == 0) {
224 mode
= IEEE80211_POWERSAVE_PSP_CAM
;
226 errx(1, "unknown powersavemode");
229 set80211(s
, IEEE80211_IOC_POWERSAVE
, mode
, 0, NULL
);
233 set80211powersave(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
236 set80211(s
, IEEE80211_IOC_POWERSAVE
, IEEE80211_POWERSAVE_OFF
,
239 set80211(s
, IEEE80211_IOC_POWERSAVE
, IEEE80211_POWERSAVE_ON
,
244 set80211powersavesleep(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
246 set80211(s
, IEEE80211_IOC_POWERSAVESLEEP
, atoi(val
), 0, NULL
);
250 set80211wepmode(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
254 if (strcasecmp(val
, "off") == 0) {
255 mode
= IEEE80211_WEP_OFF
;
256 } else if (strcasecmp(val
, "on") == 0) {
257 mode
= IEEE80211_WEP_ON
;
258 } else if (strcasecmp(val
, "mixed") == 0) {
259 mode
= IEEE80211_WEP_MIXED
;
261 errx(1, "unknown wep mode");
264 set80211(s
, IEEE80211_IOC_WEP
, mode
, 0, NULL
);
268 set80211wep(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
270 set80211(s
, IEEE80211_IOC_WEP
, d
, 0, NULL
);
274 isundefarg(const char *arg
)
276 return (strcmp(arg
, "-") == 0 || strncasecmp(arg
, "undef", 5) == 0);
280 set80211weptxkey(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
283 set80211(s
, IEEE80211_IOC_WEPTXKEY
, IEEE80211_KEYIX_NONE
, 0, NULL
);
285 set80211(s
, IEEE80211_IOC_WEPTXKEY
, atoi(val
)-1, 0, NULL
);
289 set80211wepkey(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
293 u_int8_t data
[IEEE80211_KEYBUF_SIZE
];
295 if (isdigit(val
[0]) && val
[1] == ':') {
300 bzero(data
, sizeof(data
));
302 get_string(val
, NULL
, data
, &len
);
304 set80211(s
, IEEE80211_IOC_WEPKEY
, key
, len
, data
);
308 * This function is purely a NetBSD compatability interface. The NetBSD
309 * interface is too inflexible, but it's there so we'll support it since
310 * it's not all that hard.
313 set80211nwkey(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
317 u_int8_t data
[IEEE80211_KEYBUF_SIZE
];
319 set80211(s
, IEEE80211_IOC_WEP
, IEEE80211_WEP_ON
, 0, NULL
);
321 if (isdigit(val
[0]) && val
[1] == ':') {
322 txkey
= val
[0]-'0'-1;
325 for (i
= 0; i
< 4; i
++) {
326 bzero(data
, sizeof(data
));
328 val
= get_string(val
, ",", data
, &len
);
332 set80211(s
, IEEE80211_IOC_WEPKEY
, i
, len
, data
);
335 bzero(data
, sizeof(data
));
337 get_string(val
, NULL
, data
, &len
);
340 set80211(s
, IEEE80211_IOC_WEPKEY
, 0, len
, data
);
342 bzero(data
, sizeof(data
));
343 for (i
= 1; i
< 4; i
++)
344 set80211(s
, IEEE80211_IOC_WEPKEY
, i
, 0, data
);
347 set80211(s
, IEEE80211_IOC_WEPTXKEY
, txkey
, 0, NULL
);
351 set80211rtsthreshold(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
353 set80211(s
, IEEE80211_IOC_RTSTHRESHOLD
,
354 isundefarg(val
) ? IEEE80211_RTS_MAX
: atoi(val
), 0, NULL
);
358 set80211protmode(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
362 if (strcasecmp(val
, "off") == 0) {
363 mode
= IEEE80211_PROTMODE_OFF
;
364 } else if (strcasecmp(val
, "cts") == 0) {
365 mode
= IEEE80211_PROTMODE_CTS
;
366 } else if (strcasecmp(val
, "rtscts") == 0) {
367 mode
= IEEE80211_PROTMODE_RTSCTS
;
369 errx(1, "unknown protection mode");
372 set80211(s
, IEEE80211_IOC_PROTMODE
, mode
, 0, NULL
);
376 set80211txpower(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
378 set80211(s
, IEEE80211_IOC_TXPOWER
, atoi(val
), 0, NULL
);
381 #define IEEE80211_ROAMING_DEVICE 0
382 #define IEEE80211_ROAMING_AUTO 1
383 #define IEEE80211_ROAMING_MANUAL 2
386 set80211roaming(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
390 if (strcasecmp(val
, "device") == 0) {
391 mode
= IEEE80211_ROAMING_DEVICE
;
392 } else if (strcasecmp(val
, "auto") == 0) {
393 mode
= IEEE80211_ROAMING_AUTO
;
394 } else if (strcasecmp(val
, "manual") == 0) {
395 mode
= IEEE80211_ROAMING_MANUAL
;
397 errx(1, "unknown roaming mode");
399 set80211(s
, IEEE80211_IOC_ROAMING
, mode
, 0, NULL
);
403 set80211wme(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
405 set80211(s
, IEEE80211_IOC_WME
, d
, 0, NULL
);
409 set80211hidessid(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
411 set80211(s
, IEEE80211_IOC_HIDESSID
, d
, 0, NULL
);
415 set80211apbridge(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
417 set80211(s
, IEEE80211_IOC_APBRIDGE
, d
, 0, NULL
);
421 set80211chanlist(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
423 struct ieee80211req_chanlist chanlist
;
424 #define MAXCHAN (sizeof(chanlist.ic_channels)*NBBY)
425 char *temp
, *cp
, *tp
;
427 temp
= malloc(strlen(val
) + 1);
429 errx(1, "malloc failed");
431 memset(&chanlist
, 0, sizeof(chanlist
));
436 tp
= strchr(cp
, ',');
439 switch (sscanf(cp
, "%u-%u", &first
, &last
)) {
442 errx(-1, "channel %u out of range, max %zu",
444 setbit(chanlist
.ic_channels
, first
);
448 errx(-1, "channel %u out of range, max %zu",
451 errx(-1, "channel %u out of range, max %zu",
454 errx(-1, "void channel range, %u > %u",
456 for (f
= first
; f
<= last
; f
++)
457 setbit(chanlist
.ic_channels
, f
);
468 set80211(s
, IEEE80211_IOC_CHANLIST
, 0,
469 sizeof(chanlist
), (uint8_t *) &chanlist
);
474 set80211bssid(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
477 if (!isanyarg(val
)) {
479 struct sockaddr_dl sdl
;
481 temp
= malloc(strlen(val
) + 2); /* ':' and '\0' */
483 errx(1, "malloc failed");
485 strcpy(temp
+ 1, val
);
486 sdl
.sdl_len
= sizeof(sdl
);
487 link_addr(temp
, &sdl
);
489 if (sdl
.sdl_alen
!= IEEE80211_ADDR_LEN
)
490 errx(1, "malformed link-level address");
491 set80211(s
, IEEE80211_IOC_BSSID
, 0,
492 IEEE80211_ADDR_LEN
, LLADDR(&sdl
));
494 uint8_t zerobssid
[IEEE80211_ADDR_LEN
];
495 memset(zerobssid
, 0, sizeof(zerobssid
));
496 set80211(s
, IEEE80211_IOC_BSSID
, 0,
497 IEEE80211_ADDR_LEN
, zerobssid
);
502 getac(const char *ac
)
504 if (strcasecmp(ac
, "ac_be") == 0 || strcasecmp(ac
, "be") == 0)
506 if (strcasecmp(ac
, "ac_bk") == 0 || strcasecmp(ac
, "bk") == 0)
508 if (strcasecmp(ac
, "ac_vi") == 0 || strcasecmp(ac
, "vi") == 0)
510 if (strcasecmp(ac
, "ac_vo") == 0 || strcasecmp(ac
, "vo") == 0)
512 errx(1, "unknown wme access class %s", ac
);
516 DECL_CMD_FUNC2(set80211cwmin
, ac
, val
)
518 set80211(s
, IEEE80211_IOC_WME_CWMIN
, atoi(val
), getac(ac
), NULL
);
522 DECL_CMD_FUNC2(set80211cwmax
, ac
, val
)
524 set80211(s
, IEEE80211_IOC_WME_CWMAX
, atoi(val
), getac(ac
), NULL
);
528 DECL_CMD_FUNC2(set80211aifs
, ac
, val
)
530 set80211(s
, IEEE80211_IOC_WME_AIFS
, atoi(val
), getac(ac
), NULL
);
534 DECL_CMD_FUNC2(set80211txoplimit
, ac
, val
)
536 set80211(s
, IEEE80211_IOC_WME_TXOPLIMIT
, atoi(val
), getac(ac
), NULL
);
540 DECL_CMD_FUNC(set80211acm
, ac
, d
)
542 set80211(s
, IEEE80211_IOC_WME_ACM
, 1, getac(ac
), NULL
);
545 DECL_CMD_FUNC(set80211noacm
, ac
, d
)
547 set80211(s
, IEEE80211_IOC_WME_ACM
, 0, getac(ac
), NULL
);
551 DECL_CMD_FUNC(set80211ackpolicy
, ac
, d
)
553 set80211(s
, IEEE80211_IOC_WME_ACKPOLICY
, 1, getac(ac
), NULL
);
556 DECL_CMD_FUNC(set80211noackpolicy
, ac
, d
)
558 set80211(s
, IEEE80211_IOC_WME_ACKPOLICY
, 0, getac(ac
), NULL
);
562 DECL_CMD_FUNC2(set80211bsscwmin
, ac
, val
)
564 set80211(s
, IEEE80211_IOC_WME_CWMIN
, atoi(val
),
565 getac(ac
)|IEEE80211_WMEPARAM_BSS
, NULL
);
569 DECL_CMD_FUNC2(set80211bsscwmax
, ac
, val
)
571 set80211(s
, IEEE80211_IOC_WME_CWMAX
, atoi(val
),
572 getac(ac
)|IEEE80211_WMEPARAM_BSS
, NULL
);
576 DECL_CMD_FUNC2(set80211bssaifs
, ac
, val
)
578 set80211(s
, IEEE80211_IOC_WME_AIFS
, atoi(val
),
579 getac(ac
)|IEEE80211_WMEPARAM_BSS
, NULL
);
583 DECL_CMD_FUNC2(set80211bsstxoplimit
, ac
, val
)
585 set80211(s
, IEEE80211_IOC_WME_TXOPLIMIT
, atoi(val
),
586 getac(ac
)|IEEE80211_WMEPARAM_BSS
, NULL
);
590 DECL_CMD_FUNC(set80211dtimperiod
, val
, d
)
592 set80211(s
, IEEE80211_IOC_DTIM_PERIOD
, atoi(val
), 0, NULL
);
596 DECL_CMD_FUNC(set80211bintval
, val
, d
)
598 set80211(s
, IEEE80211_IOC_BEACON_INTERVAL
, atoi(val
), 0, NULL
);
602 set80211macmac(int s
, int op
, const char *val
)
605 struct sockaddr_dl sdl
;
607 temp
= malloc(strlen(val
) + 2); /* ':' and '\0' */
609 errx(1, "malloc failed");
611 strcpy(temp
+ 1, val
);
612 sdl
.sdl_len
= sizeof(sdl
);
613 link_addr(temp
, &sdl
);
615 if (sdl
.sdl_alen
!= IEEE80211_ADDR_LEN
)
616 errx(1, "malformed link-level address");
617 set80211(s
, op
, 0, IEEE80211_ADDR_LEN
, LLADDR(&sdl
));
621 DECL_CMD_FUNC(set80211addmac
, val
, d
)
623 set80211macmac(s
, IEEE80211_IOC_ADDMAC
, val
);
627 DECL_CMD_FUNC(set80211delmac
, val
, d
)
629 set80211macmac(s
, IEEE80211_IOC_DELMAC
, val
);
633 DECL_CMD_FUNC(set80211kickmac
, val
, d
)
636 struct sockaddr_dl sdl
;
637 struct ieee80211req_mlme mlme
;
639 temp
= malloc(strlen(val
) + 2); /* ':' and '\0' */
641 errx(1, "malloc failed");
643 strcpy(temp
+ 1, val
);
644 sdl
.sdl_len
= sizeof(sdl
);
645 link_addr(temp
, &sdl
);
647 if (sdl
.sdl_alen
!= IEEE80211_ADDR_LEN
)
648 errx(1, "malformed link-level address");
649 memset(&mlme
, 0, sizeof(mlme
));
650 mlme
.im_op
= IEEE80211_MLME_DEAUTH
;
651 mlme
.im_reason
= IEEE80211_REASON_AUTH_EXPIRE
;
652 memcpy(mlme
.im_macaddr
, LLADDR(&sdl
), IEEE80211_ADDR_LEN
);
653 set80211(s
, IEEE80211_IOC_MLME
, 0, sizeof(mlme
), (u_int8_t
*) &mlme
);
657 DECL_CMD_FUNC(set80211maccmd
, val
, d
)
659 set80211(s
, IEEE80211_IOC_MACCMD
, d
, 0, NULL
);
663 set80211pureg(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
665 set80211(s
, IEEE80211_IOC_PUREG
, d
, 0, NULL
);
669 set80211burst(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
671 set80211(s
, IEEE80211_IOC_BURST
, d
, 0, NULL
);
675 set80211ratectl(const char *val
, int d
, int s
, const struct afswtch
*rafp
)
679 if (strcmp("onoe", val
) == 0)
680 ratectl
= IEEE80211_RATECTL_ONOE
;
681 else if (strcmp("amrr", val
) == 0)
682 ratectl
= IEEE80211_RATECTL_AMRR
;
684 errx(1, "unknown ratectl");
686 set80211(s
, IEEE80211_IOC_RATECTL
, ratectl
, 0, NULL
);
690 DECL_CMD_FUNC(set80211mcastrate
, val
, d
)
692 set80211(s
, IEEE80211_IOC_MCAST_RATE
, (int) 2*atof(val
), 0, NULL
);
696 DECL_CMD_FUNC(set80211fragthreshold
, val
, d
)
698 set80211(s
, IEEE80211_IOC_FRAGTHRESHOLD
,
699 isundefarg(val
) ? IEEE80211_FRAG_MAX
: atoi(val
), 0, NULL
);
703 DECL_CMD_FUNC(set80211bmissthreshold
, val
, d
)
705 set80211(s
, IEEE80211_IOC_BMISSTHRESHOLD
,
706 isundefarg(val
) ? IEEE80211_HWBMISS_MAX
: atoi(val
), 0, NULL
);
710 getmaxrate(uint8_t rates
[15], uint8_t nrates
)
714 for (i
= 0; i
< nrates
; i
++) {
715 int rate
= rates
[i
] & IEEE80211_RATE_VAL
;
725 static char capstring
[32];
726 char *cp
= capstring
;
728 if (capinfo
& IEEE80211_CAPINFO_ESS
)
730 if (capinfo
& IEEE80211_CAPINFO_IBSS
)
732 if (capinfo
& IEEE80211_CAPINFO_CF_POLLABLE
)
734 if (capinfo
& IEEE80211_CAPINFO_CF_POLLREQ
)
736 if (capinfo
& IEEE80211_CAPINFO_PRIVACY
)
738 if (capinfo
& IEEE80211_CAPINFO_SHORT_PREAMBLE
)
740 if (capinfo
& IEEE80211_CAPINFO_PBCC
)
742 if (capinfo
& IEEE80211_CAPINFO_CHNL_AGILITY
)
744 if (capinfo
& IEEE80211_CAPINFO_SHORT_SLOTTIME
)
746 if (capinfo
& IEEE80211_CAPINFO_RSN
)
748 if (capinfo
& IEEE80211_CAPINFO_DSSSOFDM
)
755 printie(const char* tag
, const uint8_t *ie
, size_t ielen
, int maxlen
)
759 maxlen
-= strlen(tag
)+2;
760 if (2*ielen
> maxlen
)
763 for (; ielen
> 0; ie
++, ielen
--) {
775 * Copy the ssid string contents into buf, truncating to fit. If the
776 * ssid is entirely printable then just copy intact. Otherwise convert
777 * to hexadecimal. If the result is truncated then replace the last
778 * three characters with "...".
781 copy_essid(char buf
[], size_t bufsize
, const u_int8_t
*essid
, size_t essid_len
)
787 if (essid_len
> bufsize
)
791 /* determine printable or not */
792 for (i
= 0, p
= essid
; i
< maxlen
; i
++, p
++) {
793 if (*p
< ' ' || *p
> 0x7e)
796 if (i
!= maxlen
) { /* not printable, print as hex */
799 strlcpy(buf
, "0x", bufsize
);
802 for (i
= 0; i
< maxlen
&& bufsize
>= 2; i
++) {
803 sprintf(&buf
[2+2*i
], "%02x", p
[i
]);
807 memcpy(&buf
[2+2*i
-3], "...", 3);
808 } else { /* printable, truncate as needed */
809 memcpy(buf
, essid
, maxlen
);
810 if (maxlen
!= essid_len
)
811 memcpy(&buf
[maxlen
-3], "...", 3);
816 /* unaligned little endian access */
817 #define LE_READ_4(p) \
819 ((((const u_int8_t *)(p))[0] ) | \
820 (((const u_int8_t *)(p))[1] << 8) | \
821 (((const u_int8_t *)(p))[2] << 16) | \
822 (((const u_int8_t *)(p))[3] << 24)))
825 iswpaoui(const u_int8_t
*frm
)
827 return frm
[1] > 3 && LE_READ_4(frm
+2) == ((WPA_OUI_TYPE
<<24)|WPA_OUI
);
831 iswmeoui(const u_int8_t
*frm
)
833 return frm
[1] > 3 && LE_READ_4(frm
+2) == ((WME_OUI_TYPE
<<24)|WME_OUI
);
837 isatherosoui(const u_int8_t
*frm
)
839 return frm
[1] > 3 && LE_READ_4(frm
+2) == ((ATH_OUI_TYPE
<<24)|ATH_OUI
);
843 printies(const u_int8_t
*vp
, int ielen
, int maxcols
)
847 case IEEE80211_ELEMID_VENDOR
:
849 printie(" WPA", vp
, 2+vp
[1], maxcols
);
850 else if (iswmeoui(vp
))
851 printie(" WME", vp
, 2+vp
[1], maxcols
);
852 else if (isatherosoui(vp
))
853 printie(" ATH", vp
, 2+vp
[1], maxcols
);
855 printie(" VEN", vp
, 2+vp
[1], maxcols
);
857 case IEEE80211_ELEMID_RSN
:
858 printie(" RSN", vp
, 2+vp
[1], maxcols
);
861 printie(" ???", vp
, 2+vp
[1], maxcols
);
872 uint8_t buf
[24*1024];
873 struct ieee80211req ireq
;
874 char ssid
[IEEE80211_NWID_LEN
+1];
878 (void) memset(&ireq
, 0, sizeof(ireq
));
879 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
880 ireq
.i_type
= IEEE80211_IOC_SCAN_RESULTS
;
882 ireq
.i_len
= sizeof(buf
);
883 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
884 errx(1, "unable to get scan results");
886 if (len
< sizeof(struct ieee80211req_scan_result
))
889 ssidmax
= verbose
? IEEE80211_NWID_LEN
: 14;
890 printf("%-*.*s %-17.17s %4s %4s %-5s %3s %4s\n"
891 , ssidmax
, ssidmax
, "SSID"
901 struct ieee80211req_scan_result
*sr
;
904 sr
= (struct ieee80211req_scan_result
*) cp
;
905 vp
= (u_int8_t
*)(sr
+1);
906 printf("%-*.*s %s %3d %3dM %2d:%-2d %3d %-4.4s"
908 , copy_essid(ssid
, ssidmax
, vp
, sr
->isr_ssid_len
)
910 , ether_ntoa((const struct ether_addr
*) sr
->isr_bssid
)
911 , ieee80211_mhz2ieee(sr
->isr_freq
)
912 , getmaxrate(sr
->isr_rates
, sr
->isr_nrates
)
913 , sr
->isr_rssi
, sr
->isr_noise
915 , getcaps(sr
->isr_capinfo
)
917 printies(vp
+ sr
->isr_ssid_len
, sr
->isr_ie_len
, 24);
919 cp
+= sr
->isr_len
, len
-= sr
->isr_len
;
920 } while (len
>= sizeof(struct ieee80211req_scan_result
));
923 #include <netproto/802_11/ieee80211_dragonfly.h>
928 struct ieee80211req ireq
;
931 sroute
= socket(PF_ROUTE
, SOCK_RAW
, 0);
933 perror("socket(PF_ROUTE,SOCK_RAW)");
936 (void) memset(&ireq
, 0, sizeof(ireq
));
937 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
938 ireq
.i_type
= IEEE80211_IOC_SCAN_REQ
;
939 /* NB: only root can trigger a scan so ignore errors */
940 if (ioctl(s
, SIOCS80211
, &ireq
) >= 0) {
942 struct if_announcemsghdr
*ifan
;
943 struct rt_msghdr
*rtm
;
946 if (read(sroute
, buf
, sizeof(buf
)) < 0) {
947 perror("read(PF_ROUTE)");
950 rtm
= (struct rt_msghdr
*) buf
;
951 if (rtm
->rtm_version
!= RTM_VERSION
)
953 ifan
= (struct if_announcemsghdr
*) rtm
;
954 } while (rtm
->rtm_type
!= RTM_IEEE80211
||
955 ifan
->ifan_what
!= RTM_IEEE80211_SCAN
);
961 DECL_CMD_FUNC(set80211scan
, val
, d
)
967 static enum ieee80211_opmode
get80211opmode(int s
);
973 struct ieee80211req_sta_req req
;
974 uint8_t buf
[24*1024];
976 enum ieee80211_opmode opmode
= get80211opmode(s
);
977 struct ieee80211req ireq
;
981 (void) memset(&ireq
, 0, sizeof(ireq
));
982 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
983 /* broadcast address =>'s get all stations */
984 (void) memset(u
.req
.is_u
.macaddr
, 0xff, IEEE80211_ADDR_LEN
);
985 if (opmode
== IEEE80211_M_STA
) {
987 * Get information about the associated AP.
989 ireq
.i_type
= IEEE80211_IOC_BSSID
;
990 ireq
.i_data
= u
.req
.is_u
.macaddr
;
991 ireq
.i_len
= IEEE80211_ADDR_LEN
;
992 (void) ioctl(s
, SIOCG80211
, &ireq
);
994 ireq
.i_type
= IEEE80211_IOC_STA_INFO
;
996 ireq
.i_len
= sizeof(u
);
997 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
998 errx(1, "unable to get station information");
1000 if (len
< sizeof(struct ieee80211req_sta_info
))
1003 printf("%-17.17s %4s %4s %4s %4s %4s %6s %6s %4s %3s\n"
1015 cp
= (uint8_t *) u
.req
.info
;
1017 struct ieee80211req_sta_info
*si
;
1020 si
= (struct ieee80211req_sta_info
*) cp
;
1021 if (si
->isi_len
< sizeof(*si
))
1023 vp
= (u_int8_t
*)(si
+1);
1024 printf("%s %4u %4d %3dM %4d %4d %6d %6d %-4.4s %3x"
1025 , ether_ntoa((const struct ether_addr
*) si
->isi_macaddr
)
1026 , IEEE80211_AID(si
->isi_associd
)
1027 , ieee80211_mhz2ieee(si
->isi_freq
)
1028 , (si
->isi_rates
[si
->isi_txrate
] & IEEE80211_RATE_VAL
)/2
1033 , getcaps(si
->isi_capinfo
)
1036 printies(vp
, si
->isi_ie_len
, 24);
1038 cp
+= si
->isi_len
, len
-= si
->isi_len
;
1039 } while (len
>= sizeof(struct ieee80211req_sta_info
));
1043 print_chaninfo(const struct ieee80211_channel
*c
)
1045 #define IEEE80211_IS_CHAN_PASSIVE(_c) \
1046 (((_c)->ic_flags & IEEE80211_CHAN_PASSIVE))
1050 if (IEEE80211_IS_CHAN_FHSS(c
))
1051 strlcat(buf
, " FHSS", sizeof(buf
));
1052 if (IEEE80211_IS_CHAN_A(c
))
1053 strlcat(buf
, " 11a", sizeof(buf
));
1054 /* XXX 11g schizophrenia */
1055 if (IEEE80211_IS_CHAN_G(c
) ||
1056 IEEE80211_IS_CHAN_PUREG(c
))
1057 strlcat(buf
, " 11g", sizeof(buf
));
1058 else if (IEEE80211_IS_CHAN_B(c
))
1059 strlcat(buf
, " 11b", sizeof(buf
));
1060 if (IEEE80211_IS_CHAN_T(c
))
1061 strlcat(buf
, " Turbo", sizeof(buf
));
1062 printf("Channel %3u : %u%c Mhz%-14.14s",
1063 ieee80211_mhz2ieee(c
->ic_freq
), c
->ic_freq
,
1064 IEEE80211_IS_CHAN_PASSIVE(c
) ? '*' : ' ', buf
);
1065 #undef IEEE80211_IS_CHAN_PASSIVE
1069 list_channels(int s
, int allchans
)
1071 struct ieee80211req ireq
;
1072 struct ieee80211req_chaninfo chans
;
1073 struct ieee80211req_chaninfo achans
;
1074 const struct ieee80211_channel
*c
;
1077 (void) memset(&ireq
, 0, sizeof(ireq
));
1078 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1079 ireq
.i_type
= IEEE80211_IOC_CHANINFO
;
1080 ireq
.i_data
= &chans
;
1081 ireq
.i_len
= sizeof(chans
);
1082 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1083 errx(1, "unable to get channel information");
1085 struct ieee80211req_chanlist active
;
1087 ireq
.i_type
= IEEE80211_IOC_CHANLIST
;
1088 ireq
.i_data
= &active
;
1089 ireq
.i_len
= sizeof(active
);
1090 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1091 errx(1, "unable to get active channel list");
1092 memset(&achans
, 0, sizeof(achans
));
1093 for (i
= 0; i
< chans
.ic_nchans
; i
++) {
1094 c
= &chans
.ic_chans
[i
];
1095 if (isset(active
.ic_channels
, ieee80211_mhz2ieee(c
->ic_freq
)) || allchans
)
1096 achans
.ic_chans
[achans
.ic_nchans
++] = *c
;
1100 half
= achans
.ic_nchans
/ 2;
1101 if (achans
.ic_nchans
% 2)
1103 for (i
= 0; i
< achans
.ic_nchans
/ 2; i
++) {
1104 print_chaninfo(&achans
.ic_chans
[i
]);
1105 print_chaninfo(&achans
.ic_chans
[half
+i
]);
1108 if (achans
.ic_nchans
% 2) {
1109 print_chaninfo(&achans
.ic_chans
[i
]);
1119 #define IEEE80211_C_BITS \
1120 "\020\1WEP\2TKIP\3AES\4AES_CCM\6CKIP\11IBSS\12PMGT\13HOSTAP\14AHDEMO" \
1121 "\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE\21MONITOR\22TKIPMIC\30WPA1" \
1122 "\31WPA2\32BURST\33WME"
1124 #define IEEE80211_CEXT_BITS "\020\1PBCC"
1127 list_capabilities(int s
)
1129 struct ieee80211req ireq
;
1130 uint32_t caps
, caps_ext
;
1132 memset(&ireq
, 0, sizeof(ireq
));
1135 strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1136 ireq
.i_data
= &caps_ext
;
1137 ireq
.i_len
= sizeof(caps_ext
);
1138 ireq
.i_type
= IEEE80211_IOC_DRIVER_CAPS
;
1139 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1140 errx(1, "unable to get driver capabilities");
1141 caps
= (((uint16_t)ireq
.i_val
) << 16) | ((uint16_t)ireq
.i_len
);
1142 printb(name
, caps
, IEEE80211_C_BITS
);
1144 printb(", ext", caps_ext
, IEEE80211_CEXT_BITS
);
1151 static const char *acnames
[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" };
1152 struct ieee80211req ireq
;
1155 (void) memset(&ireq
, 0, sizeof(ireq
));
1156 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1158 for (ac
= WME_AC_BE
; ac
<= WME_AC_VO
; ac
++) {
1160 if (ireq
.i_len
& IEEE80211_WMEPARAM_BSS
)
1161 printf("\t%s", " ");
1163 printf("\t%s", acnames
[ac
]);
1165 ireq
.i_len
= (ireq
.i_len
& IEEE80211_WMEPARAM_BSS
) | ac
;
1167 /* show WME BSS parameters */
1168 ireq
.i_type
= IEEE80211_IOC_WME_CWMIN
;
1169 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1170 printf(" cwmin %2u", ireq
.i_val
);
1171 ireq
.i_type
= IEEE80211_IOC_WME_CWMAX
;
1172 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1173 printf(" cwmax %2u", ireq
.i_val
);
1174 ireq
.i_type
= IEEE80211_IOC_WME_AIFS
;
1175 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1176 printf(" aifs %2u", ireq
.i_val
);
1177 ireq
.i_type
= IEEE80211_IOC_WME_TXOPLIMIT
;
1178 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1179 printf(" txopLimit %3u", ireq
.i_val
);
1180 ireq
.i_type
= IEEE80211_IOC_WME_ACM
;
1181 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1188 if ((ireq
.i_len
& IEEE80211_WMEPARAM_BSS
) == 0) {
1189 ireq
.i_type
= IEEE80211_IOC_WME_ACKPOLICY
;
1190 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1198 if ((ireq
.i_len
& IEEE80211_WMEPARAM_BSS
) == 0) {
1199 ireq
.i_len
|= IEEE80211_WMEPARAM_BSS
;
1202 ireq
.i_len
&= ~IEEE80211_WMEPARAM_BSS
;
1209 struct ieee80211req ireq
;
1210 struct ieee80211req_maclist
*acllist
;
1211 int i
, nacls
, policy
;
1214 (void) memset(&ireq
, 0, sizeof(ireq
));
1215 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
)); /* XXX ?? */
1216 ireq
.i_type
= IEEE80211_IOC_MACCMD
;
1217 ireq
.i_val
= IEEE80211_MACCMD_POLICY
;
1218 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1219 if (errno
== EINVAL
) {
1220 printf("No acl policy loaded\n");
1223 err(1, "unable to get mac policy");
1225 policy
= ireq
.i_val
;
1227 ireq
.i_val
= IEEE80211_MACCMD_LIST
;
1229 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1230 err(1, "unable to get mac acl list size");
1231 if (ireq
.i_len
== 0) /* NB: no acls */
1234 ireq
.i_data
= malloc(ireq
.i_len
);
1235 if (ireq
.i_data
== NULL
)
1236 err(1, "out of memory for acl list");
1238 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1239 err(1, "unable to get mac acl list");
1240 if (policy
== IEEE80211_MACCMD_POLICY_OPEN
) {
1242 printf("policy: open\n");
1244 } else if (policy
== IEEE80211_MACCMD_POLICY_ALLOW
) {
1246 printf("policy: allow\n");
1248 } else if (policy
== IEEE80211_MACCMD_POLICY_DENY
) {
1250 printf("policy: deny\n");
1253 printf("policy: unknown (%u)\n", policy
);
1256 nacls
= ireq
.i_len
/ sizeof(*acllist
);
1257 acllist
= (struct ieee80211req_maclist
*) ireq
.i_data
;
1258 for (i
= 0; i
< nacls
; i
++)
1259 printf("%c%s\n", c
, ether_ntoa(
1260 (const struct ether_addr
*) acllist
[i
].ml_macaddr
));
1264 DECL_CMD_FUNC(set80211list
, arg
, d
)
1266 #define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0)
1268 if (iseq(arg
, "sta"))
1270 else if (iseq(arg
, "scan") || iseq(arg
, "ap"))
1272 else if (iseq(arg
, "chan") || iseq(arg
, "freq"))
1273 list_channels(s
, 1);
1274 else if (iseq(arg
, "active"))
1275 list_channels(s
, 0);
1276 else if (iseq(arg
, "keys"))
1278 else if (iseq(arg
, "caps"))
1279 list_capabilities(s
);
1280 else if (iseq(arg
, "wme"))
1282 else if (iseq(arg
, "mac"))
1285 errx(1, "Don't know how to list %s for %s", arg
, name
);
1289 static enum ieee80211_opmode
1290 get80211opmode(int s
)
1292 struct ifmediareq ifmr
;
1294 (void) memset(&ifmr
, 0, sizeof(ifmr
));
1295 (void) strncpy(ifmr
.ifm_name
, name
, sizeof(ifmr
.ifm_name
));
1297 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
)&ifmr
) >= 0) {
1298 if (ifmr
.ifm_current
& IFM_IEEE80211_ADHOC
)
1299 return IEEE80211_M_IBSS
; /* XXX ahdemo */
1300 if (ifmr
.ifm_current
& IFM_IEEE80211_HOSTAP
)
1301 return IEEE80211_M_HOSTAP
;
1302 if (ifmr
.ifm_current
& IFM_IEEE80211_MONITOR
)
1303 return IEEE80211_M_MONITOR
;
1305 return IEEE80211_M_STA
;
1308 static const struct ieee80211_channel
*
1309 getchaninfo(int s
, int chan
)
1311 struct ieee80211req ireq
;
1312 static struct ieee80211req_chaninfo chans
;
1313 static struct ieee80211_channel undef
;
1314 const struct ieee80211_channel
*c
;
1317 (void) memset(&ireq
, 0, sizeof(ireq
));
1318 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1319 ireq
.i_type
= IEEE80211_IOC_CHANINFO
;
1320 ireq
.i_data
= &chans
;
1321 ireq
.i_len
= sizeof(chans
);
1322 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1323 errx(1, "unable to get channel information");
1324 freq
= ieee80211_ieee2mhz(chan
);
1325 for (i
= 0; i
< chans
.ic_nchans
; i
++) {
1326 c
= &chans
.ic_chans
[i
];
1327 if (c
->ic_freq
== freq
)
1335 printcipher(int s
, struct ieee80211req
*ireq
, int keylenop
)
1337 switch (ireq
->i_val
) {
1338 case IEEE80211_CIPHER_WEP
:
1339 ireq
->i_type
= keylenop
;
1340 if (ioctl(s
, SIOCG80211
, ireq
) != -1)
1342 ireq
->i_len
<= 5 ? "40" :
1343 ireq
->i_len
<= 13 ? "104" : "128");
1347 case IEEE80211_CIPHER_TKIP
:
1350 case IEEE80211_CIPHER_AES_OCB
:
1353 case IEEE80211_CIPHER_AES_CCM
:
1356 case IEEE80211_CIPHER_CKIP
:
1359 case IEEE80211_CIPHER_NONE
:
1363 printf("UNKNOWN (0x%x)", ireq
->i_val
);
1376 if (spacer
!= '\t') {
1380 col
= 8; /* 8-col tab */
1384 LINE_CHECK(const char *fmt
, ...)
1391 n
= vsnprintf(buf
+1, sizeof(buf
)-1, fmt
, ap
);
1404 printkey(const struct ieee80211req_key
*ik
)
1406 static const uint8_t zerodata
[IEEE80211_KEYBUF_SIZE
];
1407 int keylen
= ik
->ik_keylen
;
1410 printcontents
= printkeys
&&
1411 (memcmp(ik
->ik_keydata
, zerodata
, keylen
) != 0 || verbose
);
1414 switch (ik
->ik_type
) {
1415 case IEEE80211_CIPHER_WEP
:
1417 LINE_CHECK("wepkey %u:%s", ik
->ik_keyix
+1,
1418 keylen
<= 5 ? "40-bit" :
1419 keylen
<= 13 ? "104-bit" : "128-bit");
1421 case IEEE80211_CIPHER_TKIP
:
1423 keylen
-= 128/8; /* ignore MIC for now */
1424 LINE_CHECK("TKIP %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1426 case IEEE80211_CIPHER_AES_OCB
:
1427 LINE_CHECK("AES-OCB %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1429 case IEEE80211_CIPHER_AES_CCM
:
1430 LINE_CHECK("AES-CCM %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1432 case IEEE80211_CIPHER_CKIP
:
1433 LINE_CHECK("CKIP %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1435 case IEEE80211_CIPHER_NONE
:
1436 LINE_CHECK("NULL %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1439 LINE_CHECK("UNKNOWN (0x%x) %u:%u-bit",
1440 ik
->ik_type
, ik
->ik_keyix
+1, 8*keylen
);
1443 if (printcontents
) {
1447 for (i
= 0; i
< keylen
; i
++)
1448 printf("%02x", ik
->ik_keydata
[i
]);
1450 if (ik
->ik_type
!= IEEE80211_CIPHER_WEP
&&
1451 (ik
->ik_keyrsc
!= 0 || verbose
))
1452 printf(" rsc %ju", (uintmax_t)ik
->ik_keyrsc
);
1453 if (ik
->ik_type
!= IEEE80211_CIPHER_WEP
&&
1454 (ik
->ik_keytsc
!= 0 || verbose
))
1455 printf(" tsc %ju", (uintmax_t)ik
->ik_keytsc
);
1456 if (ik
->ik_flags
!= 0 && verbose
) {
1457 const char *sep
= " ";
1459 if (ik
->ik_flags
& IEEE80211_KEY_XMIT
)
1460 printf("%stx", sep
), sep
= "+";
1461 if (ik
->ik_flags
& IEEE80211_KEY_RECV
)
1462 printf("%srx", sep
), sep
= "+";
1463 if (ik
->ik_flags
& IEEE80211_KEY_DEFAULT
)
1464 printf("%sdef", sep
), sep
= "+";
1471 ieee80211_status(int s
)
1473 static const uint8_t zerobssid
[IEEE80211_ADDR_LEN
];
1474 enum ieee80211_opmode opmode
= get80211opmode(s
);
1475 int i
, num
, wpa
, wme
;
1476 struct ieee80211req ireq
;
1478 const struct ieee80211_channel
*c
;
1480 (void) memset(&ireq
, 0, sizeof(ireq
));
1481 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1482 ireq
.i_data
= &data
;
1484 wpa
= 0; /* unknown/not set */
1486 ireq
.i_type
= IEEE80211_IOC_SSID
;
1488 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1489 /* If we can't get the SSID, this isn't an 802.11 device. */
1493 ireq
.i_type
= IEEE80211_IOC_RATECTL
;
1494 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1497 switch (ireq
.i_val
) {
1498 case IEEE80211_RATECTL_ONOE
:
1499 printf("\tratectl: onoe");
1501 case IEEE80211_RATECTL_AMRR
:
1502 printf("\tratectl: amrr");
1506 printf("\tratectl: none");
1516 ireq
.i_type
= IEEE80211_IOC_NUMSSIDS
;
1517 if (ioctl(s
, SIOCG80211
, &ireq
) >= 0)
1521 ireq
.i_type
= IEEE80211_IOC_SSID
;
1522 for (ireq
.i_val
= 0; ireq
.i_val
< num
; ireq
.i_val
++) {
1523 if (ioctl(s
, SIOCG80211
, &ireq
) >= 0 && ireq
.i_len
> 0) {
1524 printf(" %d:", ireq
.i_val
+ 1);
1525 print_string(data
, ireq
.i_len
);
1529 print_string(data
, ireq
.i_len
);
1531 ireq
.i_type
= IEEE80211_IOC_CHANNEL
;
1532 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1534 c
= getchaninfo(s
, ireq
.i_val
);
1535 if (ireq
.i_val
!= -1) {
1536 printf(" channel %d", ireq
.i_val
);
1538 printf(" (%u)", c
->ic_freq
);
1540 printf(" channel UNDEF");
1542 ireq
.i_type
= IEEE80211_IOC_BSSID
;
1543 ireq
.i_len
= IEEE80211_ADDR_LEN
;
1544 if (ioctl(s
, SIOCG80211
, &ireq
) >= 0 &&
1545 (memcmp(ireq
.i_data
, zerobssid
, sizeof(zerobssid
)) != 0 || verbose
))
1546 printf(" bssid %s", ether_ntoa(ireq
.i_data
));
1548 ireq
.i_type
= IEEE80211_IOC_STATIONNAME
;
1549 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1550 printf("\n\tstationname ");
1551 print_string(data
, ireq
.i_len
);
1554 spacer
= ' '; /* force first break */
1557 ireq
.i_type
= IEEE80211_IOC_AUTHMODE
;
1558 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1559 switch (ireq
.i_val
) {
1560 case IEEE80211_AUTH_NONE
:
1561 LINE_CHECK("authmode NONE");
1563 case IEEE80211_AUTH_OPEN
:
1564 LINE_CHECK("authmode OPEN");
1566 case IEEE80211_AUTH_SHARED
:
1567 LINE_CHECK("authmode SHARED");
1569 case IEEE80211_AUTH_8021X
:
1570 LINE_CHECK("authmode 802.1x");
1572 case IEEE80211_AUTH_WPA
:
1573 ireq
.i_type
= IEEE80211_IOC_WPA
;
1574 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1577 wpa
= 1; /* default to WPA1 */
1580 LINE_CHECK("authmode WPA2/802.11i");
1583 LINE_CHECK("authmode WPA1+WPA2/802.11i");
1586 LINE_CHECK("authmode WPA");
1590 case IEEE80211_AUTH_AUTO
:
1591 LINE_CHECK("authmode AUTO");
1594 LINE_CHECK("authmode UNKNOWN (0x%x)",
1600 ireq
.i_type
= IEEE80211_IOC_WEP
;
1601 if (ioctl(s
, SIOCG80211
, &ireq
) != -1 &&
1602 ireq
.i_val
!= IEEE80211_WEP_NOSUP
) {
1603 int firstkey
, wepmode
;
1605 wepmode
= ireq
.i_val
;
1607 case IEEE80211_WEP_OFF
:
1608 LINE_CHECK("privacy OFF");
1610 case IEEE80211_WEP_ON
:
1611 LINE_CHECK("privacy ON");
1613 case IEEE80211_WEP_MIXED
:
1614 LINE_CHECK("privacy MIXED");
1617 LINE_CHECK("privacy UNKNOWN (0x%x)", wepmode
);
1622 * If we get here then we've got WEP support so we need
1623 * to print WEP status.
1626 ireq
.i_type
= IEEE80211_IOC_WEPTXKEY
;
1627 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1628 warn("WEP support, but no tx key!");
1631 if (ireq
.i_val
!= -1)
1632 LINE_CHECK("deftxkey %d", ireq
.i_val
+1);
1633 else if (wepmode
!= IEEE80211_WEP_OFF
|| verbose
)
1634 LINE_CHECK("deftxkey UNDEF");
1636 ireq
.i_type
= IEEE80211_IOC_NUMWEPKEYS
;
1637 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1638 warn("WEP support, but no NUMWEPKEYS support!");
1644 for (i
= 0; i
< num
; i
++) {
1645 struct ieee80211req_key ik
;
1647 memset(&ik
, 0, sizeof(ik
));
1649 ireq
.i_type
= IEEE80211_IOC_WPAKEY
;
1651 ireq
.i_len
= sizeof(ik
);
1652 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1653 warn("WEP support, but can get keys!");
1656 if (ik
.ik_keylen
!= 0) {
1665 ireq
.i_type
= IEEE80211_IOC_POWERSAVE
;
1666 if (ioctl(s
, SIOCG80211
, &ireq
) != -1 &&
1667 ireq
.i_val
!= IEEE80211_POWERSAVE_NOSUP
) {
1668 if (ireq
.i_val
!= IEEE80211_POWERSAVE_OFF
|| verbose
) {
1669 switch (ireq
.i_val
) {
1670 case IEEE80211_POWERSAVE_OFF
:
1671 LINE_CHECK("powersavemode OFF");
1673 case IEEE80211_POWERSAVE_CAM
:
1674 LINE_CHECK("powersavemode CAM");
1676 case IEEE80211_POWERSAVE_PSP
:
1677 LINE_CHECK("powersavemode PSP");
1679 case IEEE80211_POWERSAVE_PSP_CAM
:
1680 LINE_CHECK("powersavemode PSP-CAM");
1683 ireq
.i_type
= IEEE80211_IOC_POWERSAVESLEEP
;
1684 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1685 LINE_CHECK("powersavesleep %d", ireq
.i_val
);
1689 ireq
.i_type
= IEEE80211_IOC_TXPOWMAX
;
1690 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1691 LINE_CHECK("txpowmax %d", ireq
.i_val
);
1694 ireq
.i_type
= IEEE80211_IOC_TXPOWER
;
1695 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1696 LINE_CHECK("txpower %d", ireq
.i_val
);
1699 ireq
.i_type
= IEEE80211_IOC_RTSTHRESHOLD
;
1700 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1701 if (ireq
.i_val
!= IEEE80211_RTS_MAX
|| verbose
)
1702 LINE_CHECK("rtsthreshold %d", ireq
.i_val
);
1705 ireq
.i_type
= IEEE80211_IOC_MCAST_RATE
;
1706 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1707 if (ireq
.i_val
!= 2*1 || verbose
) {
1708 if (ireq
.i_val
== 11)
1709 LINE_CHECK("mcastrate 5.5");
1711 LINE_CHECK("mcastrate %d", ireq
.i_val
/2);
1715 ireq
.i_type
= IEEE80211_IOC_FRAGTHRESHOLD
;
1716 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1717 if (ireq
.i_val
!= IEEE80211_FRAG_MAX
|| verbose
)
1718 LINE_CHECK("fragthreshold %d", ireq
.i_val
);
1721 ireq
.i_type
= IEEE80211_IOC_BMISSTHRESHOLD
;
1722 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1723 if (ireq
.i_val
!= IEEE80211_HWBMISS_MAX
|| verbose
)
1724 LINE_CHECK("bmiss %d", ireq
.i_val
);
1727 if (IEEE80211_IS_CHAN_G(c
) || IEEE80211_IS_CHAN_PUREG(c
) || verbose
) {
1728 ireq
.i_type
= IEEE80211_IOC_PUREG
;
1729 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1731 LINE_CHECK("pureg");
1733 LINE_CHECK("-pureg");
1735 ireq
.i_type
= IEEE80211_IOC_PROTMODE
;
1736 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1737 switch (ireq
.i_val
) {
1738 case IEEE80211_PROTMODE_OFF
:
1739 LINE_CHECK("protmode OFF");
1741 case IEEE80211_PROTMODE_CTS
:
1742 LINE_CHECK("protmode CTS");
1744 case IEEE80211_PROTMODE_RTSCTS
:
1745 LINE_CHECK("protmode RTSCTS");
1748 LINE_CHECK("protmode UNKNOWN (0x%x)",
1755 ireq
.i_type
= IEEE80211_IOC_WME
;
1756 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1765 ireq
.i_type
= IEEE80211_IOC_BURST
;
1766 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1768 LINE_CHECK("burst");
1770 LINE_CHECK("-burst");
1773 if (opmode
== IEEE80211_M_HOSTAP
) {
1774 ireq
.i_type
= IEEE80211_IOC_HIDESSID
;
1775 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1777 LINE_CHECK("ssid HIDE");
1779 LINE_CHECK("ssid SHOW");
1782 ireq
.i_type
= IEEE80211_IOC_APBRIDGE
;
1783 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1785 LINE_CHECK("-apbridge");
1787 LINE_CHECK("apbridge");
1790 ireq
.i_type
= IEEE80211_IOC_DTIM_PERIOD
;
1791 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1792 LINE_CHECK("dtimperiod %u", ireq
.i_val
);
1794 ireq
.i_type
= IEEE80211_IOC_ROAMING
;
1795 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1796 if (ireq
.i_val
!= IEEE80211_ROAMING_AUTO
|| verbose
) {
1797 switch (ireq
.i_val
) {
1798 case IEEE80211_ROAMING_DEVICE
:
1799 LINE_CHECK("roaming DEVICE");
1801 case IEEE80211_ROAMING_AUTO
:
1802 LINE_CHECK("roaming AUTO");
1804 case IEEE80211_ROAMING_MANUAL
:
1805 LINE_CHECK("roaming MANUAL");
1808 LINE_CHECK("roaming UNKNOWN (0x%x)",
1815 ireq
.i_type
= IEEE80211_IOC_BEACON_INTERVAL
;
1816 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1818 LINE_CHECK("bintval %u", ireq
.i_val
);
1820 LINE_CHECK("bintval %u", ireq
.i_val
);
1823 if (wme
&& verbose
) {
1829 ireq
.i_type
= IEEE80211_IOC_COUNTERMEASURES
;
1830 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1832 LINE_CHECK("countermeasures");
1834 LINE_CHECK("-countermeasures");
1837 /* XXX not interesting with WPA done in user space */
1838 ireq
.i_type
= IEEE80211_IOC_KEYMGTALGS
;
1839 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1842 ireq
.i_type
= IEEE80211_IOC_MCASTCIPHER
;
1843 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1844 LINE_CHECK("mcastcipher ");
1845 printcipher(s
, &ireq
, IEEE80211_IOC_MCASTKEYLEN
);
1849 ireq
.i_type
= IEEE80211_IOC_UCASTCIPHER
;
1850 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1851 LINE_CHECK("ucastcipher ");
1852 printcipher(s
, &ireq
, IEEE80211_IOC_UCASTKEYLEN
);
1856 ireq
.i_type
= IEEE80211_IOC_RSNCAPS
;
1857 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1858 LINE_CHECK("RSN caps 0x%x", ireq
.i_val
);
1863 ireq
.i_type
= IEEE80211_IOC_UCASTCIPHERS
;
1864 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1876 set80211(int s
, int type
, int val
, int len
, u_int8_t
*data
)
1878 struct ieee80211req ireq
;
1880 (void) memset(&ireq
, 0, sizeof(ireq
));
1881 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1886 if (ioctl(s
, SIOCS80211
, &ireq
) < 0)
1887 err(1, "SIOCS80211");
1891 get_string(const char *val
, const char *sep
, u_int8_t
*buf
, int *lenp
)
1899 hexstr
= (val
[0] == '0' && tolower((u_char
)val
[1]) == 'x');
1905 if (sep
!= NULL
&& strchr(sep
, *val
) != NULL
) {
1910 if (!isxdigit((u_char
)val
[0])) {
1911 warnx("bad hexadecimal digits");
1914 if (!isxdigit((u_char
)val
[1])) {
1915 warnx("odd count hexadecimal digits");
1919 if (p
>= buf
+ len
) {
1921 warnx("hexadecimal digits too long");
1923 warnx("string too long");
1927 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
1928 *p
++ = (tohex((u_char
)val
[0]) << 4) |
1929 tohex((u_char
)val
[1]);
1937 memset(p
, 0, *lenp
- len
);
1938 /* The string "-" is treated as the empty string. */
1939 if (!hexstr
&& len
== 1 && buf
[0] == '-')
1946 print_string(const u_int8_t
*buf
, int len
)
1953 for (; i
< len
; i
++) {
1954 if (!isprint(buf
[i
]) && buf
[i
] != '\0')
1956 if (isspace(buf
[i
]))
1960 if (hasspc
|| len
== 0 || buf
[0] == '\0')
1961 printf("\"%.*s\"", len
, buf
);
1963 printf("%.*s", len
, buf
);
1966 for (i
= 0; i
< len
; i
++)
1967 printf("%02x", buf
[i
]);
1971 static struct cmd ieee80211_cmds
[] = {
1972 DEF_CMD_ARG("ssid", set80211ssid
),
1973 DEF_CMD_ARG("nwid", set80211ssid
),
1974 DEF_CMD_ARG("stationname", set80211stationname
),
1975 DEF_CMD_ARG("station", set80211stationname
), /* BSD/OS */
1976 DEF_CMD_ARG("channel", set80211channel
),
1977 DEF_CMD_ARG("authmode", set80211authmode
),
1978 DEF_CMD_ARG("powersavemode", set80211powersavemode
),
1979 DEF_CMD("powersave", 1, set80211powersave
),
1980 DEF_CMD("-powersave", 0, set80211powersave
),
1981 DEF_CMD_ARG("powersavesleep", set80211powersavesleep
),
1982 DEF_CMD_ARG("wepmode", set80211wepmode
),
1983 DEF_CMD("wep", 1, set80211wep
),
1984 DEF_CMD("-wep", 0, set80211wep
),
1985 DEF_CMD_ARG("deftxkey", set80211weptxkey
),
1986 DEF_CMD_ARG("weptxkey", set80211weptxkey
),
1987 DEF_CMD_ARG("wepkey", set80211wepkey
),
1988 DEF_CMD_ARG("nwkey", set80211nwkey
), /* NetBSD */
1989 DEF_CMD("-nwkey", 0, set80211wep
), /* NetBSD */
1990 DEF_CMD_ARG("rtsthreshold", set80211rtsthreshold
),
1991 DEF_CMD_ARG("protmode", set80211protmode
),
1992 DEF_CMD_ARG("txpower", set80211txpower
),
1993 DEF_CMD_ARG("roaming", set80211roaming
),
1994 DEF_CMD("wme", 1, set80211wme
),
1995 DEF_CMD("-wme", 0, set80211wme
),
1996 DEF_CMD("hidessid", 1, set80211hidessid
),
1997 DEF_CMD("-hidessid", 0, set80211hidessid
),
1998 DEF_CMD("apbridge", 1, set80211apbridge
),
1999 DEF_CMD("-apbridge", 0, set80211apbridge
),
2000 DEF_CMD_ARG("chanlist", set80211chanlist
),
2001 DEF_CMD_ARG("bssid", set80211bssid
),
2002 DEF_CMD_ARG("ap", set80211bssid
),
2003 DEF_CMD("scan", 0, set80211scan
),
2004 DEF_CMD_ARG("list", set80211list
),
2005 DEF_CMD_ARG2("cwmin", set80211cwmin
),
2006 DEF_CMD_ARG2("cwmax", set80211cwmax
),
2007 DEF_CMD_ARG2("aifs", set80211aifs
),
2008 DEF_CMD_ARG2("txoplimit", set80211txoplimit
),
2009 DEF_CMD_ARG("acm", set80211acm
),
2010 DEF_CMD_ARG("-acm", set80211noacm
),
2011 DEF_CMD_ARG("ack", set80211ackpolicy
),
2012 DEF_CMD_ARG("-ack", set80211noackpolicy
),
2013 DEF_CMD_ARG2("bss:cwmin", set80211bsscwmin
),
2014 DEF_CMD_ARG2("bss:cwmax", set80211bsscwmax
),
2015 DEF_CMD_ARG2("bss:aifs", set80211bssaifs
),
2016 DEF_CMD_ARG2("bss:txoplimit", set80211bsstxoplimit
),
2017 DEF_CMD_ARG("dtimperiod", set80211dtimperiod
),
2018 DEF_CMD_ARG("bintval", set80211bintval
),
2019 DEF_CMD("mac:open", IEEE80211_MACCMD_POLICY_OPEN
, set80211maccmd
),
2020 DEF_CMD("mac:allow", IEEE80211_MACCMD_POLICY_ALLOW
, set80211maccmd
),
2021 DEF_CMD("mac:deny", IEEE80211_MACCMD_POLICY_DENY
, set80211maccmd
),
2022 DEF_CMD("mac:flush", IEEE80211_MACCMD_FLUSH
, set80211maccmd
),
2023 DEF_CMD("mac:detach", IEEE80211_MACCMD_DETACH
, set80211maccmd
),
2024 DEF_CMD_ARG("mac:add", set80211addmac
),
2025 DEF_CMD_ARG("mac:del", set80211delmac
),
2026 DEF_CMD_ARG("mac:kick", set80211kickmac
),
2027 DEF_CMD("pureg", 1, set80211pureg
),
2028 DEF_CMD("-pureg", 0, set80211pureg
),
2029 DEF_CMD_ARG("mcastrate", set80211mcastrate
),
2030 DEF_CMD_ARG("fragthreshold", set80211fragthreshold
),
2031 DEF_CMD("burst", 1, set80211burst
),
2032 DEF_CMD("-burst", 0, set80211burst
),
2033 DEF_CMD_ARG("ratectl", set80211ratectl
),
2034 DEF_CMD_ARG("bmiss", set80211bmissthreshold
),
2035 DEF_CMD_ARG("bmissthreshold", set80211bmissthreshold
)
2037 static struct afswtch af_ieee80211
= {
2038 .af_name
= "af_ieee80211",
2040 .af_other_status
= ieee80211_status
,
2043 static __constructor
void
2044 ieee80211_ctor(void)
2046 #define N(a) (sizeof(a) / sizeof(a[0]))
2049 for (i
= 0; i
< N(ieee80211_cmds
); i
++)
2050 cmd_register(&ieee80211_cmds
[i
]);
2051 af_register(&af_ieee80211
);