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.1.2.3 2002/02/07 15:12:37 ambrisko Exp $
28 * $DragonFly: src/sbin/ifconfig/ifieee80211.c,v 1.9 2005/11/06 12:21:42 swildner 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/route.h>
79 #include <netproto/802_11/ieee80211.h>
80 #include <netproto/802_11/ieee80211_crypto.h>
81 #include <netproto/802_11/ieee80211_ioctl.h>
94 static void set80211(int s, int type, int val, int len, u_int8_t *data);
95 static const char *get_string(const char *val, const char *sep,
96 u_int8_t *buf, int *lenp);
97 static void print_string(const u_int8_t *buf, int len);
100 set80211ssid(const char *val, int d __unused, int s,
101 const struct afswtch *rafp __unused)
109 if (len > 2 && isdigit(val[0]) && val[1] == ':') {
114 bzero(data, sizeof(data));
116 get_string(val, NULL, data, &len);
118 set80211(s, IEEE80211_IOC_SSID, ssid, len, data);
122 set80211stationname(const char *val, int d __unused, int s,
123 const struct afswtch *rafp __unused)
128 bzero(data, sizeof(data));
130 get_string(val, NULL, data, &len);
132 set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data);
136 set80211channel(const char *val, int d __unused, int s,
137 const struct afswtch *rafp __unused)
139 if (strcmp(val, "-") == 0)
140 set80211(s, IEEE80211_IOC_CHANNEL, IEEE80211_CHAN_ANY, 0, NULL);
142 set80211(s, IEEE80211_IOC_CHANNEL, atoi(val), 0, NULL);
146 set80211authmode(const char *val, int d __unused, int s,
147 const struct afswtch *rafp __unused)
151 if (strcasecmp(val, "none") == 0) {
152 mode = IEEE80211_AUTH_NONE;
153 } else if (strcasecmp(val, "open") == 0) {
154 mode = IEEE80211_AUTH_OPEN;
155 } else if (strcasecmp(val, "shared") == 0) {
156 mode = IEEE80211_AUTH_SHARED;
158 err(1, "unknown authmode");
161 set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL);
165 set80211powersavemode(const char *val, int d __unused, int s,
166 const struct afswtch *rafp __unused)
170 if (strcasecmp(val, "off") == 0) {
171 mode = IEEE80211_POWERSAVE_OFF;
172 } else if (strcasecmp(val, "on") == 0) {
173 mode = IEEE80211_POWERSAVE_ON;
174 } else if (strcasecmp(val, "cam") == 0) {
175 mode = IEEE80211_POWERSAVE_CAM;
176 } else if (strcasecmp(val, "psp") == 0) {
177 mode = IEEE80211_POWERSAVE_PSP;
178 } else if (strcasecmp(val, "psp-cam") == 0) {
179 mode = IEEE80211_POWERSAVE_PSP_CAM;
181 err(1, "unknown powersavemode");
184 set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL);
188 set80211powersave(const char *val __unused, int d, int s,
189 const struct afswtch *rafp __unused)
192 set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF,
195 set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON,
200 set80211powersavesleep(const char *val, int d __unused, int s,
201 const struct afswtch *rafp __unused)
203 set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL);
207 set80211wepmode(const char *val, int d __unused, int s,
208 const struct afswtch *rafp __unused)
212 if (strcasecmp(val, "off") == 0) {
213 mode = IEEE80211_WEP_OFF;
214 } else if (strcasecmp(val, "on") == 0) {
215 mode = IEEE80211_WEP_ON;
216 } else if (strcasecmp(val, "mixed") == 0) {
217 mode = IEEE80211_WEP_MIXED;
219 err(1, "unknown wep mode");
222 set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL);
226 set80211wep(const char *val __unused, int d, int s,
227 const struct afswtch *rafp __unused)
229 set80211(s, IEEE80211_IOC_WEP, d, 0, NULL);
233 set80211weptxkey(const char *val, int d __unused, int s,
234 const struct afswtch *rafp __unused)
236 set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL);
240 set80211wepkey(const char *val, int d __unused, int s,
241 const struct afswtch *rafp __unused)
245 u_int8_t data[IEEE80211_KEYBUF_SIZE];
247 if (isdigit(val[0]) && val[1] == ':') {
252 bzero(data, sizeof(data));
254 get_string(val, NULL, data, &len);
256 set80211(s, IEEE80211_IOC_WEPKEY, key, len, data);
260 * This function is purly a NetBSD compatability interface. The NetBSD
261 * iterface is too inflexable, but it's there so we'll support it since
262 * it's not all that hard.
265 set80211nwkey(const char *val, int d __unused, int s,
266 const struct afswtch *rafp __unused)
270 u_int8_t data[IEEE80211_KEYBUF_SIZE];
272 set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
274 if (isdigit(val[0]) && val[1] == ':') {
275 txkey = val[0]-'0'-1;
278 for (i = 0; i < 4; i++) {
279 bzero(data, sizeof(data));
281 val = get_string(val, ",", data, &len);
283 set80211(s, IEEE80211_IOC_WEPKEY, i, len, data);
286 bzero(data, sizeof(data));
288 get_string(val, NULL, data, &len);
291 set80211(s, IEEE80211_IOC_WEPKEY, 0, len, data);
293 bzero(data, sizeof(data));
294 for (i = 1; i < 4; i++)
295 set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data);
298 set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
302 set80211rtsthreshold(const char *val, int d __unused, int s,
303 const struct afswtch *rafp __unused)
305 set80211(s, IEEE80211_IOC_RTSTHRESHOLD, atoi(val), 0, NULL);
309 set80211protmode(const char *val, int d __unused, int s,
310 const struct afswtch *rafp __unused)
314 if (strcasecmp(val, "off") == 0) {
315 mode = IEEE80211_PROTMODE_OFF;
316 } else if (strcasecmp(val, "cts") == 0) {
317 mode = IEEE80211_PROTMODE_CTS;
318 } else if (strcasecmp(val, "rtscts") == 0) {
319 mode = IEEE80211_PROTMODE_RTSCTS;
321 err(1, "unknown protection mode");
324 set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL);
328 set80211txpower(const char *val, int d __unused, int s,
329 const struct afswtch *rafp __unused)
331 set80211(s, IEEE80211_IOC_TXPOWER, atoi(val), 0, NULL);
335 ieee80211_status (int s, struct rt_addrinfo *info __unused)
339 struct ieee80211req ireq;
343 memset(&ireq, 0, sizeof(ireq));
344 strncpy(ireq.i_name, name, sizeof(ireq.i_name));
347 ireq.i_type = IEEE80211_IOC_SSID;
349 if (ioctl(s, SIOCG80211, &ireq) < 0) {
350 /* If we can't get the SSID, the this isn't an 802.11 device. */
354 print_string(data, ireq.i_len);
356 ireq.i_type = IEEE80211_IOC_NUMSSIDS;
357 if (ioctl(s, SIOCG80211, &ireq) >= 0) {
360 ireq.i_type = IEEE80211_IOC_SSID;
361 for (ireq.i_val = 0; ireq.i_val < num; ireq.i_val++) {
362 if (ioctl(s, SIOCG80211, &ireq) >= 0 && ireq.i_len > 0) {
363 printf(" %d:", ireq.i_val + 1);
364 print_string(data, ireq.i_len);
369 ireq.i_type = IEEE80211_IOC_STATIONNAME;
370 if (ioctl(s, SIOCG80211, &ireq) != -1) {
371 printf("\tstationname ");
372 print_string(data, ireq.i_len);
376 ireq.i_type = IEEE80211_IOC_CHANNEL;
377 if (ioctl(s, SIOCG80211, &ireq) < 0) {
380 printf("\tchannel %d", ireq.i_val);
382 ireq.i_type = IEEE80211_IOC_AUTHMODE;
383 if (ioctl(s, SIOCG80211, &ireq) != -1) {
385 switch (ireq.i_val) {
386 case IEEE80211_AUTH_NONE:
389 case IEEE80211_AUTH_OPEN:
392 case IEEE80211_AUTH_SHARED:
401 ireq.i_type = IEEE80211_IOC_POWERSAVE;
402 if (ioctl(s, SIOCG80211, &ireq) != -1 &&
403 ireq.i_val != IEEE80211_POWERSAVE_NOSUP ) {
404 printf(" powersavemode");
405 switch (ireq.i_val) {
406 case IEEE80211_POWERSAVE_OFF:
409 case IEEE80211_POWERSAVE_CAM:
412 case IEEE80211_POWERSAVE_PSP:
415 case IEEE80211_POWERSAVE_PSP_CAM:
420 ireq.i_type = IEEE80211_IOC_POWERSAVESLEEP;
421 if (ioctl(s, SIOCG80211, &ireq) != -1) {
423 printf(" powersavesleep %d", ireq.i_val);
430 ireq.i_type = IEEE80211_IOC_RTSTHRESHOLD;
431 if (ioctl(s, SIOCG80211, &ireq) != -1) {
432 printf("%crtsthreshold %d", spacer, ireq.i_val);
436 ireq.i_type = IEEE80211_IOC_PROTMODE;
437 if (ioctl(s, SIOCG80211, &ireq) != -1) {
438 printf("%cprotmode", spacer);
439 switch (ireq.i_val) {
440 case IEEE80211_PROTMODE_OFF:
443 case IEEE80211_PROTMODE_CTS:
446 case IEEE80211_PROTMODE_RTSCTS:
456 ireq.i_type = IEEE80211_IOC_TXPOWER;
457 if (ioctl(s, SIOCG80211, &ireq) != -1) {
458 printf("%ctxpower %d", spacer, ireq.i_val);
465 ireq.i_type = IEEE80211_IOC_WEP;
466 if (ioctl(s, SIOCG80211, &ireq) != -1 &&
467 ireq.i_val != IEEE80211_WEP_NOSUP) {
469 switch (ireq.i_val) {
470 case IEEE80211_WEP_OFF:
473 case IEEE80211_WEP_ON:
476 case IEEE80211_WEP_MIXED:
485 * If we get here then we've got WEP support so we need
486 * to print WEP status.
489 ireq.i_type = IEEE80211_IOC_WEPTXKEY;
490 if (ioctl(s, SIOCG80211, &ireq) < 0) {
491 warn("WEP support, but no tx key!");
494 printf(" weptxkey %d", ireq.i_val+1);
496 ireq.i_type = IEEE80211_IOC_NUMWEPKEYS;
497 if (ioctl(s, SIOCG80211, &ireq) < 0) {
498 warn("WEP support, but no NUMWEPKEYS support!");
505 ireq.i_type = IEEE80211_IOC_WEPKEY;
507 for (i = 0; i < num; i++) {
509 if (ioctl(s, SIOCG80211, &ireq) < 0) {
510 warn("WEP support, but can get keys!");
513 if (ireq.i_len == 0 ||
514 ireq.i_len > IEEE80211_KEYBUF_SIZE)
516 printf("%cwepkey %d:%s", spacer, i+1,
517 ireq.i_len <= 5 ? "40-bit" :
518 ireq.i_len <= 13 ? "104-bit" : "128-bit");
531 set80211(int s, int type, int val, int len, u_int8_t *data)
533 struct ieee80211req ireq;
535 memset(&ireq, 0, sizeof(ireq));
536 strncpy(ireq.i_name, name, sizeof(ireq.i_name));
541 if (ioctl(s, SIOCS80211, &ireq) < 0)
542 err(1, "SIOCS80211");
546 get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
554 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
560 if (sep != NULL && strchr(sep, *val) != NULL) {
565 if (!isxdigit((u_char)val[0])) {
566 warnx("bad hexadecimal digits");
569 if (!isxdigit((u_char)val[1])) {
570 warnx("odd count hexadecimal digits");
574 if (p >= buf + len) {
576 warnx("hexadecimal digits too long");
578 warnx("string too long");
582 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
583 *p++ = (tohex((u_char)val[0]) << 4) |
584 tohex((u_char)val[1]);
591 /* The string "-" is treated as the empty string. */
592 if (!hexstr && len == 1 && buf[0] == '-')
595 memset(p, 0, *lenp - len);
601 print_string(const u_int8_t *buf, int len)
608 for (; i < len; i++) {
609 if (!isprint(buf[i]) && buf[i] != '\0')
615 if (hasspc || len == 0 || buf[0] == '\0')
616 printf("\"%.*s\"", len, buf);
618 printf("%.*s", len, buf);
621 for (i = 0; i < len; i++)
622 printf("%02x", buf[i]);