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.20 2008/01/19 07:34:13 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
;
683 else if (strcmp("sample", val
) == 0)
684 ratectl
= IEEE80211_RATECTL_SAMPLE
;
686 errx(1, "unknown ratectl");
688 set80211(s
, IEEE80211_IOC_RATECTL
, ratectl
, 0, NULL
);
692 DECL_CMD_FUNC(set80211mcastrate
, val
, d
)
694 set80211(s
, IEEE80211_IOC_MCAST_RATE
, (int) 2*atof(val
), 0, NULL
);
698 DECL_CMD_FUNC(set80211fragthreshold
, val
, d
)
700 set80211(s
, IEEE80211_IOC_FRAGTHRESHOLD
,
701 isundefarg(val
) ? IEEE80211_FRAG_MAX
: atoi(val
), 0, NULL
);
705 DECL_CMD_FUNC(set80211bmissthreshold
, val
, d
)
707 set80211(s
, IEEE80211_IOC_BMISSTHRESHOLD
,
708 isundefarg(val
) ? IEEE80211_HWBMISS_MAX
: atoi(val
), 0, NULL
);
712 getmaxrate(uint8_t rates
[15], uint8_t nrates
)
716 for (i
= 0; i
< nrates
; i
++) {
717 int rate
= rates
[i
] & IEEE80211_RATE_VAL
;
727 static char capstring
[32];
728 char *cp
= capstring
;
730 if (capinfo
& IEEE80211_CAPINFO_ESS
)
732 if (capinfo
& IEEE80211_CAPINFO_IBSS
)
734 if (capinfo
& IEEE80211_CAPINFO_CF_POLLABLE
)
736 if (capinfo
& IEEE80211_CAPINFO_CF_POLLREQ
)
738 if (capinfo
& IEEE80211_CAPINFO_PRIVACY
)
740 if (capinfo
& IEEE80211_CAPINFO_SHORT_PREAMBLE
)
742 if (capinfo
& IEEE80211_CAPINFO_PBCC
)
744 if (capinfo
& IEEE80211_CAPINFO_CHNL_AGILITY
)
746 if (capinfo
& IEEE80211_CAPINFO_SHORT_SLOTTIME
)
748 if (capinfo
& IEEE80211_CAPINFO_RSN
)
750 if (capinfo
& IEEE80211_CAPINFO_DSSSOFDM
)
757 printie(const char* tag
, const uint8_t *ie
, size_t ielen
, int maxlen
)
761 maxlen
-= strlen(tag
)+2;
762 if (2*ielen
> maxlen
)
765 for (; ielen
> 0; ie
++, ielen
--) {
777 * Copy the ssid string contents into buf, truncating to fit. If the
778 * ssid is entirely printable then just copy intact. Otherwise convert
779 * to hexadecimal. If the result is truncated then replace the last
780 * three characters with "...".
783 copy_essid(char buf
[], size_t bufsize
, const u_int8_t
*essid
, size_t essid_len
)
789 if (essid_len
> bufsize
)
793 /* determine printable or not */
794 for (i
= 0, p
= essid
; i
< maxlen
; i
++, p
++) {
795 if (*p
< ' ' || *p
> 0x7e)
798 if (i
!= maxlen
) { /* not printable, print as hex */
801 strlcpy(buf
, "0x", bufsize
);
804 for (i
= 0; i
< maxlen
&& bufsize
>= 2; i
++) {
805 sprintf(&buf
[2+2*i
], "%02x", p
[i
]);
809 memcpy(&buf
[2+2*i
-3], "...", 3);
810 } else { /* printable, truncate as needed */
811 memcpy(buf
, essid
, maxlen
);
812 if (maxlen
!= essid_len
)
813 memcpy(&buf
[maxlen
-3], "...", 3);
818 /* unaligned little endian access */
819 #define LE_READ_4(p) \
821 ((((const u_int8_t *)(p))[0] ) | \
822 (((const u_int8_t *)(p))[1] << 8) | \
823 (((const u_int8_t *)(p))[2] << 16) | \
824 (((const u_int8_t *)(p))[3] << 24)))
827 iswpaoui(const u_int8_t
*frm
)
829 return frm
[1] > 3 && LE_READ_4(frm
+2) == ((WPA_OUI_TYPE
<<24)|WPA_OUI
);
833 iswmeoui(const u_int8_t
*frm
)
835 return frm
[1] > 3 && LE_READ_4(frm
+2) == ((WME_OUI_TYPE
<<24)|WME_OUI
);
839 isatherosoui(const u_int8_t
*frm
)
841 return frm
[1] > 3 && LE_READ_4(frm
+2) == ((ATH_OUI_TYPE
<<24)|ATH_OUI
);
845 printies(const u_int8_t
*vp
, int ielen
, int maxcols
)
849 case IEEE80211_ELEMID_VENDOR
:
851 printie(" WPA", vp
, 2+vp
[1], maxcols
);
852 else if (iswmeoui(vp
))
853 printie(" WME", vp
, 2+vp
[1], maxcols
);
854 else if (isatherosoui(vp
))
855 printie(" ATH", vp
, 2+vp
[1], maxcols
);
857 printie(" VEN", vp
, 2+vp
[1], maxcols
);
859 case IEEE80211_ELEMID_RSN
:
860 printie(" RSN", vp
, 2+vp
[1], maxcols
);
863 printie(" ???", vp
, 2+vp
[1], maxcols
);
874 uint8_t buf
[24*1024];
875 struct ieee80211req ireq
;
876 char ssid
[IEEE80211_NWID_LEN
+1];
880 (void) memset(&ireq
, 0, sizeof(ireq
));
881 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
882 ireq
.i_type
= IEEE80211_IOC_SCAN_RESULTS
;
884 ireq
.i_len
= sizeof(buf
);
885 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
886 errx(1, "unable to get scan results");
888 if (len
< sizeof(struct ieee80211req_scan_result
))
891 ssidmax
= verbose
? IEEE80211_NWID_LEN
: 14;
892 printf("%-*.*s %-17.17s %4s %4s %-5s %3s %4s\n"
893 , ssidmax
, ssidmax
, "SSID"
903 struct ieee80211req_scan_result
*sr
;
906 sr
= (struct ieee80211req_scan_result
*) cp
;
907 vp
= (u_int8_t
*)(sr
+1);
908 printf("%-*.*s %s %3d %3dM %2d:%-2d %3d %-4.4s"
910 , copy_essid(ssid
, ssidmax
, vp
, sr
->isr_ssid_len
)
912 , ether_ntoa((const struct ether_addr
*) sr
->isr_bssid
)
913 , ieee80211_mhz2ieee(sr
->isr_freq
)
914 , getmaxrate(sr
->isr_rates
, sr
->isr_nrates
)
915 , sr
->isr_rssi
, sr
->isr_noise
917 , getcaps(sr
->isr_capinfo2
)
919 printies(vp
+ sr
->isr_ssid_len
, sr
->isr_ie_len
, 24);
921 cp
+= sr
->isr_len
, len
-= sr
->isr_len
;
922 } while (len
>= sizeof(struct ieee80211req_scan_result
));
925 #include <netproto/802_11/ieee80211_dragonfly.h>
930 struct ieee80211req ireq
;
933 sroute
= socket(PF_ROUTE
, SOCK_RAW
, 0);
935 perror("socket(PF_ROUTE,SOCK_RAW)");
938 (void) memset(&ireq
, 0, sizeof(ireq
));
939 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
940 ireq
.i_type
= IEEE80211_IOC_SCAN_REQ
;
941 /* NB: only root can trigger a scan so ignore errors */
942 if (ioctl(s
, SIOCS80211
, &ireq
) >= 0) {
944 struct if_announcemsghdr
*ifan
;
945 struct rt_msghdr
*rtm
;
948 if (read(sroute
, buf
, sizeof(buf
)) < 0) {
949 perror("read(PF_ROUTE)");
952 rtm
= (struct rt_msghdr
*) buf
;
953 if (rtm
->rtm_version
!= RTM_VERSION
)
955 ifan
= (struct if_announcemsghdr
*) rtm
;
956 } while (rtm
->rtm_type
!= RTM_IEEE80211
||
957 ifan
->ifan_what
!= RTM_IEEE80211_SCAN
);
963 DECL_CMD_FUNC(set80211scan
, val
, d
)
969 static enum ieee80211_opmode
get80211opmode(int s
);
975 struct ieee80211req_sta_req req
;
976 uint8_t buf
[24*1024];
978 enum ieee80211_opmode opmode
= get80211opmode(s
);
979 struct ieee80211req ireq
;
983 (void) memset(&ireq
, 0, sizeof(ireq
));
984 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
985 /* broadcast address =>'s get all stations */
986 (void) memset(u
.req
.is_u
.macaddr
, 0xff, IEEE80211_ADDR_LEN
);
987 if (opmode
== IEEE80211_M_STA
) {
989 * Get information about the associated AP.
991 ireq
.i_type
= IEEE80211_IOC_BSSID
;
992 ireq
.i_data
= u
.req
.is_u
.macaddr
;
993 ireq
.i_len
= IEEE80211_ADDR_LEN
;
994 (void) ioctl(s
, SIOCG80211
, &ireq
);
996 ireq
.i_type
= IEEE80211_IOC_STA_INFO
;
998 ireq
.i_len
= sizeof(u
);
999 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1000 errx(1, "unable to get station information");
1002 if (len
< sizeof(struct ieee80211req_sta_info
))
1005 printf("%-17.17s %4s %4s %4s %4s %4s %6s %6s %4s %3s\n"
1017 cp
= (uint8_t *) u
.req
.info
;
1019 struct ieee80211req_sta_info
*si
;
1022 si
= (struct ieee80211req_sta_info
*) cp
;
1023 if (si
->isi_len
< sizeof(*si
))
1025 vp
= (u_int8_t
*)(si
+1);
1026 printf("%s %4u %4d %3dM %4d %4d %6d %6d %-4.4s %3x"
1027 , ether_ntoa((const struct ether_addr
*) si
->isi_macaddr
)
1028 , IEEE80211_AID(si
->isi_associd
)
1029 , ieee80211_mhz2ieee(si
->isi_freq
)
1030 , (si
->isi_rates
[si
->isi_txrate
] & IEEE80211_RATE_VAL
)/2
1035 , getcaps(si
->isi_capinfo2
)
1038 printies(vp
, si
->isi_ie_len
, 24);
1040 cp
+= si
->isi_len
, len
-= si
->isi_len
;
1041 } while (len
>= sizeof(struct ieee80211req_sta_info
));
1045 print_chaninfo(const struct ieee80211_channel
*c
)
1047 #define IEEE80211_IS_CHAN_PASSIVE(_c) \
1048 (((_c)->ic_flags & IEEE80211_CHAN_PASSIVE))
1052 if (IEEE80211_IS_CHAN_FHSS(c
))
1053 strlcat(buf
, " FHSS", sizeof(buf
));
1054 if (IEEE80211_IS_CHAN_A(c
))
1055 strlcat(buf
, " 11a", sizeof(buf
));
1056 /* XXX 11g schizophrenia */
1057 if (IEEE80211_IS_CHAN_G(c
) ||
1058 IEEE80211_IS_CHAN_PUREG(c
))
1059 strlcat(buf
, " 11g", sizeof(buf
));
1060 else if (IEEE80211_IS_CHAN_B(c
))
1061 strlcat(buf
, " 11b", sizeof(buf
));
1062 if (IEEE80211_IS_CHAN_T(c
))
1063 strlcat(buf
, " Turbo", sizeof(buf
));
1064 printf("Channel %3u : %u%c Mhz%-14.14s",
1065 ieee80211_mhz2ieee(c
->ic_freq
), c
->ic_freq
,
1066 IEEE80211_IS_CHAN_PASSIVE(c
) ? '*' : ' ', buf
);
1067 #undef IEEE80211_IS_CHAN_PASSIVE
1071 list_channels(int s
, int allchans
)
1073 struct ieee80211req ireq
;
1074 struct ieee80211req_chaninfo chans
;
1075 struct ieee80211req_chaninfo achans
;
1076 const struct ieee80211_channel
*c
;
1079 (void) memset(&ireq
, 0, sizeof(ireq
));
1080 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1081 ireq
.i_type
= IEEE80211_IOC_CHANINFO
;
1082 ireq
.i_data
= &chans
;
1083 ireq
.i_len
= sizeof(chans
);
1084 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1085 errx(1, "unable to get channel information");
1087 struct ieee80211req_chanlist active
;
1089 ireq
.i_type
= IEEE80211_IOC_CHANLIST
;
1090 ireq
.i_data
= &active
;
1091 ireq
.i_len
= sizeof(active
);
1092 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1093 errx(1, "unable to get active channel list");
1094 memset(&achans
, 0, sizeof(achans
));
1095 for (i
= 0; i
< chans
.ic_nchans
; i
++) {
1096 c
= &chans
.ic_chans
[i
];
1097 if (isset(active
.ic_channels
, ieee80211_mhz2ieee(c
->ic_freq
)) || allchans
)
1098 achans
.ic_chans
[achans
.ic_nchans
++] = *c
;
1102 half
= achans
.ic_nchans
/ 2;
1103 if (achans
.ic_nchans
% 2)
1105 for (i
= 0; i
< achans
.ic_nchans
/ 2; i
++) {
1106 print_chaninfo(&achans
.ic_chans
[i
]);
1107 print_chaninfo(&achans
.ic_chans
[half
+i
]);
1110 if (achans
.ic_nchans
% 2) {
1111 print_chaninfo(&achans
.ic_chans
[i
]);
1121 #define IEEE80211_C_BITS \
1122 "\020\1WEP\2TKIP\3AES\4AES_CCM\6CKIP\11IBSS\12PMGT\13HOSTAP\14AHDEMO" \
1123 "\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE\21MONITOR\22TKIPMIC\30WPA1" \
1124 "\31WPA2\32BURST\33WME"
1126 #define IEEE80211_CEXT_BITS "\020\1PBCC"
1129 list_capabilities(int s
)
1131 struct ieee80211req ireq
;
1132 uint32_t caps
, caps_ext
;
1134 memset(&ireq
, 0, sizeof(ireq
));
1137 strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1138 ireq
.i_data
= &caps_ext
;
1139 ireq
.i_len
= sizeof(caps_ext
);
1140 ireq
.i_type
= IEEE80211_IOC_DRIVER_CAPS
;
1141 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1142 errx(1, "unable to get driver capabilities");
1143 caps
= (((uint16_t)ireq
.i_val
) << 16) | ((uint16_t)ireq
.i_len
);
1144 printb(name
, caps
, IEEE80211_C_BITS
);
1146 printb(", ext", caps_ext
, IEEE80211_CEXT_BITS
);
1153 static const char *acnames
[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" };
1154 struct ieee80211req ireq
;
1157 (void) memset(&ireq
, 0, sizeof(ireq
));
1158 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1160 for (ac
= WME_AC_BE
; ac
<= WME_AC_VO
; ac
++) {
1162 if (ireq
.i_len
& IEEE80211_WMEPARAM_BSS
)
1163 printf("\t%s", " ");
1165 printf("\t%s", acnames
[ac
]);
1167 ireq
.i_len
= (ireq
.i_len
& IEEE80211_WMEPARAM_BSS
) | ac
;
1169 /* show WME BSS parameters */
1170 ireq
.i_type
= IEEE80211_IOC_WME_CWMIN
;
1171 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1172 printf(" cwmin %2u", ireq
.i_val
);
1173 ireq
.i_type
= IEEE80211_IOC_WME_CWMAX
;
1174 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1175 printf(" cwmax %2u", ireq
.i_val
);
1176 ireq
.i_type
= IEEE80211_IOC_WME_AIFS
;
1177 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1178 printf(" aifs %2u", ireq
.i_val
);
1179 ireq
.i_type
= IEEE80211_IOC_WME_TXOPLIMIT
;
1180 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1181 printf(" txopLimit %3u", ireq
.i_val
);
1182 ireq
.i_type
= IEEE80211_IOC_WME_ACM
;
1183 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1190 if ((ireq
.i_len
& IEEE80211_WMEPARAM_BSS
) == 0) {
1191 ireq
.i_type
= IEEE80211_IOC_WME_ACKPOLICY
;
1192 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1200 if ((ireq
.i_len
& IEEE80211_WMEPARAM_BSS
) == 0) {
1201 ireq
.i_len
|= IEEE80211_WMEPARAM_BSS
;
1204 ireq
.i_len
&= ~IEEE80211_WMEPARAM_BSS
;
1211 struct ieee80211req ireq
;
1212 struct ieee80211req_maclist
*acllist
;
1213 int i
, nacls
, policy
;
1216 (void) memset(&ireq
, 0, sizeof(ireq
));
1217 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
)); /* XXX ?? */
1218 ireq
.i_type
= IEEE80211_IOC_MACCMD
;
1219 ireq
.i_val
= IEEE80211_MACCMD_POLICY
;
1220 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1221 if (errno
== EINVAL
) {
1222 printf("No acl policy loaded\n");
1225 err(1, "unable to get mac policy");
1227 policy
= ireq
.i_val
;
1229 ireq
.i_val
= IEEE80211_MACCMD_LIST
;
1231 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1232 err(1, "unable to get mac acl list size");
1233 if (ireq
.i_len
== 0) /* NB: no acls */
1236 ireq
.i_data
= malloc(ireq
.i_len
);
1237 if (ireq
.i_data
== NULL
)
1238 err(1, "out of memory for acl list");
1240 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1241 err(1, "unable to get mac acl list");
1242 if (policy
== IEEE80211_MACCMD_POLICY_OPEN
) {
1244 printf("policy: open\n");
1246 } else if (policy
== IEEE80211_MACCMD_POLICY_ALLOW
) {
1248 printf("policy: allow\n");
1250 } else if (policy
== IEEE80211_MACCMD_POLICY_DENY
) {
1252 printf("policy: deny\n");
1255 printf("policy: unknown (%u)\n", policy
);
1258 nacls
= ireq
.i_len
/ sizeof(*acllist
);
1259 acllist
= (struct ieee80211req_maclist
*) ireq
.i_data
;
1260 for (i
= 0; i
< nacls
; i
++)
1261 printf("%c%s\n", c
, ether_ntoa(
1262 (const struct ether_addr
*) acllist
[i
].ml_macaddr
));
1266 DECL_CMD_FUNC(set80211list
, arg
, d
)
1268 #define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0)
1270 if (iseq(arg
, "sta"))
1272 else if (iseq(arg
, "scan") || iseq(arg
, "ap"))
1274 else if (iseq(arg
, "chan") || iseq(arg
, "freq"))
1275 list_channels(s
, 1);
1276 else if (iseq(arg
, "active"))
1277 list_channels(s
, 0);
1278 else if (iseq(arg
, "keys"))
1280 else if (iseq(arg
, "caps"))
1281 list_capabilities(s
);
1282 else if (iseq(arg
, "wme"))
1284 else if (iseq(arg
, "mac"))
1287 errx(1, "Don't know how to list %s for %s", arg
, name
);
1291 static enum ieee80211_opmode
1292 get80211opmode(int s
)
1294 struct ifmediareq ifmr
;
1296 (void) memset(&ifmr
, 0, sizeof(ifmr
));
1297 (void) strncpy(ifmr
.ifm_name
, name
, sizeof(ifmr
.ifm_name
));
1299 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
)&ifmr
) >= 0) {
1300 if (ifmr
.ifm_current
& IFM_IEEE80211_ADHOC
)
1301 return IEEE80211_M_IBSS
; /* XXX ahdemo */
1302 if (ifmr
.ifm_current
& IFM_IEEE80211_HOSTAP
)
1303 return IEEE80211_M_HOSTAP
;
1304 if (ifmr
.ifm_current
& IFM_IEEE80211_MONITOR
)
1305 return IEEE80211_M_MONITOR
;
1307 return IEEE80211_M_STA
;
1310 static const struct ieee80211_channel
*
1311 getchaninfo(int s
, int chan
)
1313 struct ieee80211req ireq
;
1314 static struct ieee80211req_chaninfo chans
;
1315 static struct ieee80211_channel undef
;
1316 const struct ieee80211_channel
*c
;
1319 (void) memset(&ireq
, 0, sizeof(ireq
));
1320 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1321 ireq
.i_type
= IEEE80211_IOC_CHANINFO
;
1322 ireq
.i_data
= &chans
;
1323 ireq
.i_len
= sizeof(chans
);
1324 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1325 errx(1, "unable to get channel information");
1326 freq
= ieee80211_ieee2mhz(chan
);
1327 for (i
= 0; i
< chans
.ic_nchans
; i
++) {
1328 c
= &chans
.ic_chans
[i
];
1329 if (c
->ic_freq
== freq
)
1337 printcipher(int s
, struct ieee80211req
*ireq
, int keylenop
)
1339 switch (ireq
->i_val
) {
1340 case IEEE80211_CIPHER_WEP
:
1341 ireq
->i_type
= keylenop
;
1342 if (ioctl(s
, SIOCG80211
, ireq
) != -1)
1344 ireq
->i_len
<= 5 ? "40" :
1345 ireq
->i_len
<= 13 ? "104" : "128");
1349 case IEEE80211_CIPHER_TKIP
:
1352 case IEEE80211_CIPHER_AES_OCB
:
1355 case IEEE80211_CIPHER_AES_CCM
:
1358 case IEEE80211_CIPHER_CKIP
:
1361 case IEEE80211_CIPHER_NONE
:
1365 printf("UNKNOWN (0x%x)", ireq
->i_val
);
1378 if (spacer
!= '\t') {
1382 col
= 8; /* 8-col tab */
1386 LINE_CHECK(const char *fmt
, ...)
1393 n
= vsnprintf(buf
+1, sizeof(buf
)-1, fmt
, ap
);
1406 printkey(const struct ieee80211req_key
*ik
)
1408 static const uint8_t zerodata
[IEEE80211_KEYBUF_SIZE
];
1409 int keylen
= ik
->ik_keylen
;
1412 printcontents
= printkeys
&&
1413 (memcmp(ik
->ik_keydata
, zerodata
, keylen
) != 0 || verbose
);
1416 switch (ik
->ik_type
) {
1417 case IEEE80211_CIPHER_WEP
:
1419 LINE_CHECK("wepkey %u:%s", ik
->ik_keyix
+1,
1420 keylen
<= 5 ? "40-bit" :
1421 keylen
<= 13 ? "104-bit" : "128-bit");
1423 case IEEE80211_CIPHER_TKIP
:
1425 keylen
-= 128/8; /* ignore MIC for now */
1426 LINE_CHECK("TKIP %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1428 case IEEE80211_CIPHER_AES_OCB
:
1429 LINE_CHECK("AES-OCB %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1431 case IEEE80211_CIPHER_AES_CCM
:
1432 LINE_CHECK("AES-CCM %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1434 case IEEE80211_CIPHER_CKIP
:
1435 LINE_CHECK("CKIP %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1437 case IEEE80211_CIPHER_NONE
:
1438 LINE_CHECK("NULL %u:%u-bit", ik
->ik_keyix
+1, 8*keylen
);
1441 LINE_CHECK("UNKNOWN (0x%x) %u:%u-bit",
1442 ik
->ik_type
, ik
->ik_keyix
+1, 8*keylen
);
1445 if (printcontents
) {
1449 for (i
= 0; i
< keylen
; i
++)
1450 printf("%02x", ik
->ik_keydata
[i
]);
1452 if (ik
->ik_type
!= IEEE80211_CIPHER_WEP
&&
1453 (ik
->ik_keyrsc
!= 0 || verbose
))
1454 printf(" rsc %ju", (uintmax_t)ik
->ik_keyrsc
);
1455 if (ik
->ik_type
!= IEEE80211_CIPHER_WEP
&&
1456 (ik
->ik_keytsc
!= 0 || verbose
))
1457 printf(" tsc %ju", (uintmax_t)ik
->ik_keytsc
);
1458 if (ik
->ik_flags
!= 0 && verbose
) {
1459 const char *sep
= " ";
1461 if (ik
->ik_flags
& IEEE80211_KEY_XMIT
)
1462 printf("%stx", sep
), sep
= "+";
1463 if (ik
->ik_flags
& IEEE80211_KEY_RECV
)
1464 printf("%srx", sep
), sep
= "+";
1465 if (ik
->ik_flags
& IEEE80211_KEY_DEFAULT
)
1466 printf("%sdef", sep
), sep
= "+";
1473 ieee80211_status(int s
)
1475 static const uint8_t zerobssid
[IEEE80211_ADDR_LEN
];
1476 enum ieee80211_opmode opmode
= get80211opmode(s
);
1477 int i
, num
, wpa
, wme
;
1478 struct ieee80211req ireq
;
1480 const struct ieee80211_channel
*c
;
1482 (void) memset(&ireq
, 0, sizeof(ireq
));
1483 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1484 ireq
.i_data
= &data
;
1486 wpa
= 0; /* unknown/not set */
1488 ireq
.i_type
= IEEE80211_IOC_SSID
;
1490 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1491 /* If we can't get the SSID, this isn't an 802.11 device. */
1495 ireq
.i_type
= IEEE80211_IOC_RATECTL
;
1496 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1499 switch (ireq
.i_val
) {
1500 case IEEE80211_RATECTL_ONOE
:
1501 printf("\tratectl: onoe");
1503 case IEEE80211_RATECTL_AMRR
:
1504 printf("\tratectl: amrr");
1506 case IEEE80211_RATECTL_SAMPLE
:
1507 printf("\tratectl: sample");
1511 printf("\tratectl: none");
1521 ireq
.i_type
= IEEE80211_IOC_NUMSSIDS
;
1522 if (ioctl(s
, SIOCG80211
, &ireq
) >= 0)
1526 ireq
.i_type
= IEEE80211_IOC_SSID
;
1527 for (ireq
.i_val
= 0; ireq
.i_val
< num
; ireq
.i_val
++) {
1528 if (ioctl(s
, SIOCG80211
, &ireq
) >= 0 && ireq
.i_len
> 0) {
1529 printf(" %d:", ireq
.i_val
+ 1);
1530 print_string(data
, ireq
.i_len
);
1534 print_string(data
, ireq
.i_len
);
1536 ireq
.i_type
= IEEE80211_IOC_CHANNEL
;
1537 if (ioctl(s
, SIOCG80211
, &ireq
) < 0)
1539 c
= getchaninfo(s
, ireq
.i_val
);
1540 if (ireq
.i_val
!= -1) {
1541 printf(" channel %d", ireq
.i_val
);
1543 printf(" (%u)", c
->ic_freq
);
1545 printf(" channel UNDEF");
1547 ireq
.i_type
= IEEE80211_IOC_BSSID
;
1548 ireq
.i_len
= IEEE80211_ADDR_LEN
;
1549 if (ioctl(s
, SIOCG80211
, &ireq
) >= 0 &&
1550 (memcmp(ireq
.i_data
, zerobssid
, sizeof(zerobssid
)) != 0 || verbose
))
1551 printf(" bssid %s", ether_ntoa(ireq
.i_data
));
1553 ireq
.i_type
= IEEE80211_IOC_STATIONNAME
;
1554 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1555 printf("\n\tstationname ");
1556 print_string(data
, ireq
.i_len
);
1559 spacer
= ' '; /* force first break */
1562 ireq
.i_type
= IEEE80211_IOC_AUTHMODE
;
1563 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1564 switch (ireq
.i_val
) {
1565 case IEEE80211_AUTH_NONE
:
1566 LINE_CHECK("authmode NONE");
1568 case IEEE80211_AUTH_OPEN
:
1569 LINE_CHECK("authmode OPEN");
1571 case IEEE80211_AUTH_SHARED
:
1572 LINE_CHECK("authmode SHARED");
1574 case IEEE80211_AUTH_8021X
:
1575 LINE_CHECK("authmode 802.1x");
1577 case IEEE80211_AUTH_WPA
:
1578 ireq
.i_type
= IEEE80211_IOC_WPA
;
1579 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1582 wpa
= 1; /* default to WPA1 */
1585 LINE_CHECK("authmode WPA2/802.11i");
1588 LINE_CHECK("authmode WPA1+WPA2/802.11i");
1591 LINE_CHECK("authmode WPA");
1595 case IEEE80211_AUTH_AUTO
:
1596 LINE_CHECK("authmode AUTO");
1599 LINE_CHECK("authmode UNKNOWN (0x%x)",
1605 ireq
.i_type
= IEEE80211_IOC_WEP
;
1606 if (ioctl(s
, SIOCG80211
, &ireq
) != -1 &&
1607 ireq
.i_val
!= IEEE80211_WEP_NOSUP
) {
1608 int firstkey
, wepmode
;
1610 wepmode
= ireq
.i_val
;
1612 case IEEE80211_WEP_OFF
:
1613 LINE_CHECK("privacy OFF");
1615 case IEEE80211_WEP_ON
:
1616 LINE_CHECK("privacy ON");
1618 case IEEE80211_WEP_MIXED
:
1619 LINE_CHECK("privacy MIXED");
1622 LINE_CHECK("privacy UNKNOWN (0x%x)", wepmode
);
1627 * If we get here then we've got WEP support so we need
1628 * to print WEP status.
1631 ireq
.i_type
= IEEE80211_IOC_WEPTXKEY
;
1632 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1633 warn("WEP support, but no tx key!");
1636 if (ireq
.i_val
!= -1)
1637 LINE_CHECK("deftxkey %d", ireq
.i_val
+1);
1638 else if (wepmode
!= IEEE80211_WEP_OFF
|| verbose
)
1639 LINE_CHECK("deftxkey UNDEF");
1641 ireq
.i_type
= IEEE80211_IOC_NUMWEPKEYS
;
1642 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1643 warn("WEP support, but no NUMWEPKEYS support!");
1649 for (i
= 0; i
< num
; i
++) {
1650 struct ieee80211req_key ik
;
1652 memset(&ik
, 0, sizeof(ik
));
1654 ireq
.i_type
= IEEE80211_IOC_WPAKEY
;
1656 ireq
.i_len
= sizeof(ik
);
1657 if (ioctl(s
, SIOCG80211
, &ireq
) < 0) {
1658 warn("WEP support, but can get keys!");
1661 if (ik
.ik_keylen
!= 0) {
1670 ireq
.i_type
= IEEE80211_IOC_POWERSAVE
;
1671 if (ioctl(s
, SIOCG80211
, &ireq
) != -1 &&
1672 ireq
.i_val
!= IEEE80211_POWERSAVE_NOSUP
) {
1673 if (ireq
.i_val
!= IEEE80211_POWERSAVE_OFF
|| verbose
) {
1674 switch (ireq
.i_val
) {
1675 case IEEE80211_POWERSAVE_OFF
:
1676 LINE_CHECK("powersavemode OFF");
1678 case IEEE80211_POWERSAVE_CAM
:
1679 LINE_CHECK("powersavemode CAM");
1681 case IEEE80211_POWERSAVE_PSP
:
1682 LINE_CHECK("powersavemode PSP");
1684 case IEEE80211_POWERSAVE_PSP_CAM
:
1685 LINE_CHECK("powersavemode PSP-CAM");
1688 ireq
.i_type
= IEEE80211_IOC_POWERSAVESLEEP
;
1689 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1690 LINE_CHECK("powersavesleep %d", ireq
.i_val
);
1694 ireq
.i_type
= IEEE80211_IOC_TXPOWMAX
;
1695 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1696 LINE_CHECK("txpowmax %d", ireq
.i_val
);
1699 ireq
.i_type
= IEEE80211_IOC_TXPOWER
;
1700 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1701 LINE_CHECK("txpower %d", ireq
.i_val
);
1704 ireq
.i_type
= IEEE80211_IOC_RTSTHRESHOLD
;
1705 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1706 if (ireq
.i_val
!= IEEE80211_RTS_MAX
|| verbose
)
1707 LINE_CHECK("rtsthreshold %d", ireq
.i_val
);
1710 ireq
.i_type
= IEEE80211_IOC_MCAST_RATE
;
1711 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1712 if (ireq
.i_val
!= 2*1 || verbose
) {
1713 if (ireq
.i_val
== 11)
1714 LINE_CHECK("mcastrate 5.5");
1716 LINE_CHECK("mcastrate %d", ireq
.i_val
/2);
1720 ireq
.i_type
= IEEE80211_IOC_FRAGTHRESHOLD
;
1721 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1722 if (ireq
.i_val
!= IEEE80211_FRAG_MAX
|| verbose
)
1723 LINE_CHECK("fragthreshold %d", ireq
.i_val
);
1726 ireq
.i_type
= IEEE80211_IOC_BMISSTHRESHOLD
;
1727 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1728 if (ireq
.i_val
!= IEEE80211_HWBMISS_MAX
|| verbose
)
1729 LINE_CHECK("bmiss %d", ireq
.i_val
);
1732 if (IEEE80211_IS_CHAN_G(c
) || IEEE80211_IS_CHAN_PUREG(c
) || verbose
) {
1733 ireq
.i_type
= IEEE80211_IOC_PUREG
;
1734 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1736 LINE_CHECK("pureg");
1738 LINE_CHECK("-pureg");
1740 ireq
.i_type
= IEEE80211_IOC_PROTMODE
;
1741 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1742 switch (ireq
.i_val
) {
1743 case IEEE80211_PROTMODE_OFF
:
1744 LINE_CHECK("protmode OFF");
1746 case IEEE80211_PROTMODE_CTS
:
1747 LINE_CHECK("protmode CTS");
1749 case IEEE80211_PROTMODE_RTSCTS
:
1750 LINE_CHECK("protmode RTSCTS");
1753 LINE_CHECK("protmode UNKNOWN (0x%x)",
1760 ireq
.i_type
= IEEE80211_IOC_WME
;
1761 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1770 ireq
.i_type
= IEEE80211_IOC_BURST
;
1771 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1773 LINE_CHECK("burst");
1775 LINE_CHECK("-burst");
1778 if (opmode
== IEEE80211_M_HOSTAP
) {
1779 ireq
.i_type
= IEEE80211_IOC_HIDESSID
;
1780 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1782 LINE_CHECK("ssid HIDE");
1784 LINE_CHECK("ssid SHOW");
1787 ireq
.i_type
= IEEE80211_IOC_APBRIDGE
;
1788 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1790 LINE_CHECK("-apbridge");
1792 LINE_CHECK("apbridge");
1795 ireq
.i_type
= IEEE80211_IOC_DTIM_PERIOD
;
1796 if (ioctl(s
, SIOCG80211
, &ireq
) != -1)
1797 LINE_CHECK("dtimperiod %u", ireq
.i_val
);
1799 ireq
.i_type
= IEEE80211_IOC_ROAMING
;
1800 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1801 if (ireq
.i_val
!= IEEE80211_ROAMING_AUTO
|| verbose
) {
1802 switch (ireq
.i_val
) {
1803 case IEEE80211_ROAMING_DEVICE
:
1804 LINE_CHECK("roaming DEVICE");
1806 case IEEE80211_ROAMING_AUTO
:
1807 LINE_CHECK("roaming AUTO");
1809 case IEEE80211_ROAMING_MANUAL
:
1810 LINE_CHECK("roaming MANUAL");
1813 LINE_CHECK("roaming UNKNOWN (0x%x)",
1820 ireq
.i_type
= IEEE80211_IOC_BEACON_INTERVAL
;
1821 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1823 LINE_CHECK("bintval %u", ireq
.i_val
);
1825 LINE_CHECK("bintval %u", ireq
.i_val
);
1828 if (wme
&& verbose
) {
1834 ireq
.i_type
= IEEE80211_IOC_COUNTERMEASURES
;
1835 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1837 LINE_CHECK("countermeasures");
1839 LINE_CHECK("-countermeasures");
1842 /* XXX not interesting with WPA done in user space */
1843 ireq
.i_type
= IEEE80211_IOC_KEYMGTALGS
;
1844 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1847 ireq
.i_type
= IEEE80211_IOC_MCASTCIPHER
;
1848 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1849 LINE_CHECK("mcastcipher ");
1850 printcipher(s
, &ireq
, IEEE80211_IOC_MCASTKEYLEN
);
1854 ireq
.i_type
= IEEE80211_IOC_UCASTCIPHER
;
1855 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1856 LINE_CHECK("ucastcipher ");
1857 printcipher(s
, &ireq
, IEEE80211_IOC_UCASTKEYLEN
);
1861 ireq
.i_type
= IEEE80211_IOC_RSNCAPS
;
1862 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1863 LINE_CHECK("RSN caps 0x%x", ireq
.i_val
);
1868 ireq
.i_type
= IEEE80211_IOC_UCASTCIPHERS
;
1869 if (ioctl(s
, SIOCG80211
, &ireq
) != -1) {
1881 set80211(int s
, int type
, int val
, int len
, u_int8_t
*data
)
1883 struct ieee80211req ireq
;
1885 (void) memset(&ireq
, 0, sizeof(ireq
));
1886 (void) strncpy(ireq
.i_name
, name
, sizeof(ireq
.i_name
));
1891 if (ioctl(s
, SIOCS80211
, &ireq
) < 0)
1892 err(1, "SIOCS80211");
1896 get_string(const char *val
, const char *sep
, u_int8_t
*buf
, int *lenp
)
1904 hexstr
= (val
[0] == '0' && tolower((u_char
)val
[1]) == 'x');
1910 if (sep
!= NULL
&& strchr(sep
, *val
) != NULL
) {
1915 if (!isxdigit((u_char
)val
[0])) {
1916 warnx("bad hexadecimal digits");
1919 if (!isxdigit((u_char
)val
[1])) {
1920 warnx("odd count hexadecimal digits");
1924 if (p
>= buf
+ len
) {
1926 warnx("hexadecimal digits too long");
1928 warnx("string too long");
1932 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
1933 *p
++ = (tohex((u_char
)val
[0]) << 4) |
1934 tohex((u_char
)val
[1]);
1942 memset(p
, 0, *lenp
- len
);
1943 /* The string "-" is treated as the empty string. */
1944 if (!hexstr
&& len
== 1 && buf
[0] == '-')
1951 print_string(const u_int8_t
*buf
, int len
)
1958 for (; i
< len
; i
++) {
1959 if (!isprint(buf
[i
]) && buf
[i
] != '\0')
1961 if (isspace(buf
[i
]))
1965 if (hasspc
|| len
== 0 || buf
[0] == '\0')
1966 printf("\"%.*s\"", len
, buf
);
1968 printf("%.*s", len
, buf
);
1971 for (i
= 0; i
< len
; i
++)
1972 printf("%02x", buf
[i
]);
1976 static struct cmd ieee80211_cmds
[] = {
1977 DEF_CMD_ARG("ssid", set80211ssid
),
1978 DEF_CMD_ARG("nwid", set80211ssid
),
1979 DEF_CMD_ARG("stationname", set80211stationname
),
1980 DEF_CMD_ARG("station", set80211stationname
), /* BSD/OS */
1981 DEF_CMD_ARG("channel", set80211channel
),
1982 DEF_CMD_ARG("authmode", set80211authmode
),
1983 DEF_CMD_ARG("powersavemode", set80211powersavemode
),
1984 DEF_CMD("powersave", 1, set80211powersave
),
1985 DEF_CMD("-powersave", 0, set80211powersave
),
1986 DEF_CMD_ARG("powersavesleep", set80211powersavesleep
),
1987 DEF_CMD_ARG("wepmode", set80211wepmode
),
1988 DEF_CMD("wep", 1, set80211wep
),
1989 DEF_CMD("-wep", 0, set80211wep
),
1990 DEF_CMD_ARG("deftxkey", set80211weptxkey
),
1991 DEF_CMD_ARG("weptxkey", set80211weptxkey
),
1992 DEF_CMD_ARG("wepkey", set80211wepkey
),
1993 DEF_CMD_ARG("nwkey", set80211nwkey
), /* NetBSD */
1994 DEF_CMD("-nwkey", 0, set80211wep
), /* NetBSD */
1995 DEF_CMD_ARG("rtsthreshold", set80211rtsthreshold
),
1996 DEF_CMD_ARG("protmode", set80211protmode
),
1997 DEF_CMD_ARG("txpower", set80211txpower
),
1998 DEF_CMD_ARG("roaming", set80211roaming
),
1999 DEF_CMD("wme", 1, set80211wme
),
2000 DEF_CMD("-wme", 0, set80211wme
),
2001 DEF_CMD("hidessid", 1, set80211hidessid
),
2002 DEF_CMD("-hidessid", 0, set80211hidessid
),
2003 DEF_CMD("apbridge", 1, set80211apbridge
),
2004 DEF_CMD("-apbridge", 0, set80211apbridge
),
2005 DEF_CMD_ARG("chanlist", set80211chanlist
),
2006 DEF_CMD_ARG("bssid", set80211bssid
),
2007 DEF_CMD_ARG("ap", set80211bssid
),
2008 DEF_CMD("scan", 0, set80211scan
),
2009 DEF_CMD_ARG("list", set80211list
),
2010 DEF_CMD_ARG2("cwmin", set80211cwmin
),
2011 DEF_CMD_ARG2("cwmax", set80211cwmax
),
2012 DEF_CMD_ARG2("aifs", set80211aifs
),
2013 DEF_CMD_ARG2("txoplimit", set80211txoplimit
),
2014 DEF_CMD_ARG("acm", set80211acm
),
2015 DEF_CMD_ARG("-acm", set80211noacm
),
2016 DEF_CMD_ARG("ack", set80211ackpolicy
),
2017 DEF_CMD_ARG("-ack", set80211noackpolicy
),
2018 DEF_CMD_ARG2("bss:cwmin", set80211bsscwmin
),
2019 DEF_CMD_ARG2("bss:cwmax", set80211bsscwmax
),
2020 DEF_CMD_ARG2("bss:aifs", set80211bssaifs
),
2021 DEF_CMD_ARG2("bss:txoplimit", set80211bsstxoplimit
),
2022 DEF_CMD_ARG("dtimperiod", set80211dtimperiod
),
2023 DEF_CMD_ARG("bintval", set80211bintval
),
2024 DEF_CMD("mac:open", IEEE80211_MACCMD_POLICY_OPEN
, set80211maccmd
),
2025 DEF_CMD("mac:allow", IEEE80211_MACCMD_POLICY_ALLOW
, set80211maccmd
),
2026 DEF_CMD("mac:deny", IEEE80211_MACCMD_POLICY_DENY
, set80211maccmd
),
2027 DEF_CMD("mac:flush", IEEE80211_MACCMD_FLUSH
, set80211maccmd
),
2028 DEF_CMD("mac:detach", IEEE80211_MACCMD_DETACH
, set80211maccmd
),
2029 DEF_CMD_ARG("mac:add", set80211addmac
),
2030 DEF_CMD_ARG("mac:del", set80211delmac
),
2031 DEF_CMD_ARG("mac:kick", set80211kickmac
),
2032 DEF_CMD("pureg", 1, set80211pureg
),
2033 DEF_CMD("-pureg", 0, set80211pureg
),
2034 DEF_CMD_ARG("mcastrate", set80211mcastrate
),
2035 DEF_CMD_ARG("fragthreshold", set80211fragthreshold
),
2036 DEF_CMD("burst", 1, set80211burst
),
2037 DEF_CMD("-burst", 0, set80211burst
),
2038 DEF_CMD_ARG("ratectl", set80211ratectl
),
2039 DEF_CMD_ARG("bmiss", set80211bmissthreshold
),
2040 DEF_CMD_ARG("bmissthreshold", set80211bmissthreshold
)
2042 static struct afswtch af_ieee80211
= {
2043 .af_name
= "af_ieee80211",
2045 .af_other_status
= ieee80211_status
,
2048 static __constructor
void
2049 ieee80211_ctor(void)
2051 #define N(a) (sizeof(a) / sizeof(a[0]))
2054 for (i
= 0; i
< N(ieee80211_cmds
); i
++)
2055 cmd_register(&ieee80211_cmds
[i
]);
2056 af_register(&af_ieee80211
);