Deleted Added
full compact
ifieee80211.c (127831) ifieee80211.c (138593)
1/*
2 * Copyright 2001 The Aerospace Corporation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 10 unchanged lines hidden (view full) ---

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
25 * SUCH DAMAGE.
26 *
1/*
2 * Copyright 2001 The Aerospace Corporation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 10 unchanged lines hidden (view full) ---

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
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sbin/ifconfig/ifieee80211.c 127831 2004-04-04 07:28:58Z phk $
27 * $FreeBSD: head/sbin/ifconfig/ifieee80211.c 138593 2004-12-08 19:18:07Z sam $
28 */
29
30/*-
31 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
32 * All rights reserved.
33 *
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,

--- 33 unchanged lines hidden (view full) ---

69#include <sys/socket.h>
70#include <sys/sysctl.h>
71#include <sys/time.h>
72
73#include <net/ethernet.h>
74#include <net/if.h>
75#include <net/if_dl.h>
76#include <net/if_types.h>
28 */
29
30/*-
31 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
32 * All rights reserved.
33 *
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,

--- 33 unchanged lines hidden (view full) ---

69#include <sys/socket.h>
70#include <sys/sysctl.h>
71#include <sys/time.h>
72
73#include <net/ethernet.h>
74#include <net/if.h>
75#include <net/if_dl.h>
76#include <net/if_types.h>
77#include <net/if_media.h>
77#include <net/route.h>
78#include <net/route.h>
79
78#include <net80211/ieee80211.h>
79#include <net80211/ieee80211_crypto.h>
80#include <net80211/ieee80211_ioctl.h>
81
82#include <ctype.h>
83#include <err.h>
84#include <errno.h>
85#include <fcntl.h>

--- 4 unchanged lines hidden (view full) ---

90
91#include "ifconfig.h"
92
93static void set80211(int s, int type, int val, int len, u_int8_t *data);
94static const char *get_string(const char *val, const char *sep,
95 u_int8_t *buf, int *lenp);
96static void print_string(const u_int8_t *buf, int len);
97
80#include <net80211/ieee80211.h>
81#include <net80211/ieee80211_crypto.h>
82#include <net80211/ieee80211_ioctl.h>
83
84#include <ctype.h>
85#include <err.h>
86#include <errno.h>
87#include <fcntl.h>

--- 4 unchanged lines hidden (view full) ---

92
93#include "ifconfig.h"
94
95static void set80211(int s, int type, int val, int len, u_int8_t *data);
96static const char *get_string(const char *val, const char *sep,
97 u_int8_t *buf, int *lenp);
98static void print_string(const u_int8_t *buf, int len);
99
98void
100static int
101isanyarg(const char *arg)
102{
103 return (strcmp(arg, "-") == 0 ||
104 strcasecmp(arg, "any") == 0 || strcasecmp(arg, "off") == 0);
105}
106
107static void
99set80211ssid(const char *val, int d, int s, const struct afswtch *rafp)
100{
101 int ssid;
102 int len;
103 u_int8_t data[33];
104
105 ssid = 0;
106 len = strlen(val);

--- 4 unchanged lines hidden (view full) ---

111
112 bzero(data, sizeof(data));
113 len = sizeof(data);
114 get_string(val, NULL, data, &len);
115
116 set80211(s, IEEE80211_IOC_SSID, ssid, len, data);
117}
118
108set80211ssid(const char *val, int d, int s, const struct afswtch *rafp)
109{
110 int ssid;
111 int len;
112 u_int8_t data[33];
113
114 ssid = 0;
115 len = strlen(val);

--- 4 unchanged lines hidden (view full) ---

120
121 bzero(data, sizeof(data));
122 len = sizeof(data);
123 get_string(val, NULL, data, &len);
124
125 set80211(s, IEEE80211_IOC_SSID, ssid, len, data);
126}
127
119void
128static void
120set80211stationname(const char *val, int d, int s, const struct afswtch *rafp)
121{
122 int len;
123 u_int8_t data[33];
124
125 bzero(data, sizeof(data));
126 len = sizeof(data);
127 get_string(val, NULL, data, &len);
128
129 set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data);
130}
131
129set80211stationname(const char *val, int d, int s, const struct afswtch *rafp)
130{
131 int len;
132 u_int8_t data[33];
133
134 bzero(data, sizeof(data));
135 len = sizeof(data);
136 get_string(val, NULL, data, &len);
137
138 set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data);
139}
140
132void
141/*
142 * Convert IEEE channel number to MHz frequency.
143 */
144static u_int
145ieee80211_ieee2mhz(u_int chan)
146{
147 if (chan == 14)
148 return 2484;
149 if (chan < 14) /* 0-13 */
150 return 2407 + chan*5;
151 if (chan < 27) /* 15-26 */
152 return 2512 + ((chan-15)*20);
153 return 5000 + (chan*5);
154}
155
156/*
157 * Convert MHz frequency to IEEE channel number.
158 */
159static u_int
160ieee80211_mhz2ieee(u_int freq)
161{
162 if (freq == 2484)
163 return 14;
164 if (freq < 2484)
165 return (freq - 2407) / 5;
166 if (freq < 5000)
167 return 15 + ((freq - 2512) / 20);
168 return (freq - 5000) / 5;
169}
170
171static void
133set80211channel(const char *val, int d, int s, const struct afswtch *rafp)
134{
172set80211channel(const char *val, int d, int s, const struct afswtch *rafp)
173{
135 if (strcmp(val, "-") == 0)
174 if (!isanyarg(val)) {
175 int v = atoi(val);
176 if (v > 255) /* treat as frequency */
177 v = ieee80211_mhz2ieee(v);
178 set80211(s, IEEE80211_IOC_CHANNEL, v, 0, NULL);
179 } else
136 set80211(s, IEEE80211_IOC_CHANNEL, IEEE80211_CHAN_ANY, 0, NULL);
180 set80211(s, IEEE80211_IOC_CHANNEL, IEEE80211_CHAN_ANY, 0, NULL);
137 else
138 set80211(s, IEEE80211_IOC_CHANNEL, atoi(val), 0, NULL);
139}
140
181}
182
141void
183static void
142set80211authmode(const char *val, int d, int s, const struct afswtch *rafp)
143{
144 int mode;
145
146 if (strcasecmp(val, "none") == 0) {
147 mode = IEEE80211_AUTH_NONE;
148 } else if (strcasecmp(val, "open") == 0) {
149 mode = IEEE80211_AUTH_OPEN;
150 } else if (strcasecmp(val, "shared") == 0) {
151 mode = IEEE80211_AUTH_SHARED;
184set80211authmode(const char *val, int d, int s, const struct afswtch *rafp)
185{
186 int mode;
187
188 if (strcasecmp(val, "none") == 0) {
189 mode = IEEE80211_AUTH_NONE;
190 } else if (strcasecmp(val, "open") == 0) {
191 mode = IEEE80211_AUTH_OPEN;
192 } else if (strcasecmp(val, "shared") == 0) {
193 mode = IEEE80211_AUTH_SHARED;
194 } else if (strcasecmp(val, "8021x") == 0) {
195 mode = IEEE80211_AUTH_8021X;
196 } else if (strcasecmp(val, "wpa") == 0) {
197 mode = IEEE80211_AUTH_WPA;
152 } else {
153 err(1, "unknown authmode");
154 }
155
156 set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL);
157}
158
198 } else {
199 err(1, "unknown authmode");
200 }
201
202 set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL);
203}
204
159void
205static void
160set80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp)
161{
162 int mode;
163
164 if (strcasecmp(val, "off") == 0) {
165 mode = IEEE80211_POWERSAVE_OFF;
166 } else if (strcasecmp(val, "on") == 0) {
167 mode = IEEE80211_POWERSAVE_ON;

--- 5 unchanged lines hidden (view full) ---

173 mode = IEEE80211_POWERSAVE_PSP_CAM;
174 } else {
175 err(1, "unknown powersavemode");
176 }
177
178 set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL);
179}
180
206set80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp)
207{
208 int mode;
209
210 if (strcasecmp(val, "off") == 0) {
211 mode = IEEE80211_POWERSAVE_OFF;
212 } else if (strcasecmp(val, "on") == 0) {
213 mode = IEEE80211_POWERSAVE_ON;

--- 5 unchanged lines hidden (view full) ---

219 mode = IEEE80211_POWERSAVE_PSP_CAM;
220 } else {
221 err(1, "unknown powersavemode");
222 }
223
224 set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL);
225}
226
181void
227static void
182set80211powersave(const char *val, int d, int s, const struct afswtch *rafp)
183{
184 if (d == 0)
185 set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF,
186 0, NULL);
187 else
188 set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON,
189 0, NULL);
190}
191
228set80211powersave(const char *val, int d, int s, const struct afswtch *rafp)
229{
230 if (d == 0)
231 set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF,
232 0, NULL);
233 else
234 set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON,
235 0, NULL);
236}
237
192void
238static void
193set80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp)
194{
195 set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL);
196}
197
239set80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp)
240{
241 set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL);
242}
243
198void
244static void
199set80211wepmode(const char *val, int d, int s, const struct afswtch *rafp)
200{
201 int mode;
202
203 if (strcasecmp(val, "off") == 0) {
204 mode = IEEE80211_WEP_OFF;
205 } else if (strcasecmp(val, "on") == 0) {
206 mode = IEEE80211_WEP_ON;
207 } else if (strcasecmp(val, "mixed") == 0) {
208 mode = IEEE80211_WEP_MIXED;
209 } else {
210 err(1, "unknown wep mode");
211 }
212
213 set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL);
214}
215
245set80211wepmode(const char *val, int d, int s, const struct afswtch *rafp)
246{
247 int mode;
248
249 if (strcasecmp(val, "off") == 0) {
250 mode = IEEE80211_WEP_OFF;
251 } else if (strcasecmp(val, "on") == 0) {
252 mode = IEEE80211_WEP_ON;
253 } else if (strcasecmp(val, "mixed") == 0) {
254 mode = IEEE80211_WEP_MIXED;
255 } else {
256 err(1, "unknown wep mode");
257 }
258
259 set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL);
260}
261
216void
262static void
217set80211wep(const char *val, int d, int s, const struct afswtch *rafp)
218{
219 set80211(s, IEEE80211_IOC_WEP, d, 0, NULL);
220}
221
263set80211wep(const char *val, int d, int s, const struct afswtch *rafp)
264{
265 set80211(s, IEEE80211_IOC_WEP, d, 0, NULL);
266}
267
222void
268static void
223set80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp)
224{
225 set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL);
226}
227
269set80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp)
270{
271 set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL);
272}
273
228void
274static void
229set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp)
230{
231 int key = 0;
232 int len;
233 u_int8_t data[IEEE80211_KEYBUF_SIZE];
234
235 if (isdigit(val[0]) && val[1] == ':') {
236 key = atoi(val)-1;

--- 7 unchanged lines hidden (view full) ---

244 set80211(s, IEEE80211_IOC_WEPKEY, key, len, data);
245}
246
247/*
248 * This function is purly a NetBSD compatability interface. The NetBSD
249 * iterface is too inflexable, but it's there so we'll support it since
250 * it's not all that hard.
251 */
275set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp)
276{
277 int key = 0;
278 int len;
279 u_int8_t data[IEEE80211_KEYBUF_SIZE];
280
281 if (isdigit(val[0]) && val[1] == ':') {
282 key = atoi(val)-1;

--- 7 unchanged lines hidden (view full) ---

290 set80211(s, IEEE80211_IOC_WEPKEY, key, len, data);
291}
292
293/*
294 * This function is purly a NetBSD compatability interface. The NetBSD
295 * iterface is too inflexable, but it's there so we'll support it since
296 * it's not all that hard.
297 */
252void
298static void
253set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp)
254{
255 int txkey;
256 int i, len;
257 u_int8_t data[IEEE80211_KEYBUF_SIZE];
258
259 set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
260

--- 19 unchanged lines hidden (view full) ---

280 bzero(data, sizeof(data));
281 for (i = 1; i < 4; i++)
282 set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data);
283 }
284
285 set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
286}
287
299set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp)
300{
301 int txkey;
302 int i, len;
303 u_int8_t data[IEEE80211_KEYBUF_SIZE];
304
305 set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
306

--- 19 unchanged lines hidden (view full) ---

326 bzero(data, sizeof(data));
327 for (i = 1; i < 4; i++)
328 set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data);
329 }
330
331 set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
332}
333
288void
334static void
289set80211rtsthreshold(const char *val, int d, int s, const struct afswtch *rafp)
290{
291 set80211(s, IEEE80211_IOC_RTSTHRESHOLD, atoi(val), 0, NULL);
292}
293
335set80211rtsthreshold(const char *val, int d, int s, const struct afswtch *rafp)
336{
337 set80211(s, IEEE80211_IOC_RTSTHRESHOLD, atoi(val), 0, NULL);
338}
339
294void
340static void
295set80211protmode(const char *val, int d, int s, const struct afswtch *rafp)
296{
297 int mode;
298
299 if (strcasecmp(val, "off") == 0) {
300 mode = IEEE80211_PROTMODE_OFF;
301 } else if (strcasecmp(val, "cts") == 0) {
302 mode = IEEE80211_PROTMODE_CTS;
303 } else if (strcasecmp(val, "rtscts") == 0) {
304 mode = IEEE80211_PROTMODE_RTSCTS;
305 } else {
306 err(1, "unknown protection mode");
307 }
308
309 set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL);
310}
311
341set80211protmode(const char *val, int d, int s, const struct afswtch *rafp)
342{
343 int mode;
344
345 if (strcasecmp(val, "off") == 0) {
346 mode = IEEE80211_PROTMODE_OFF;
347 } else if (strcasecmp(val, "cts") == 0) {
348 mode = IEEE80211_PROTMODE_CTS;
349 } else if (strcasecmp(val, "rtscts") == 0) {
350 mode = IEEE80211_PROTMODE_RTSCTS;
351 } else {
352 err(1, "unknown protection mode");
353 }
354
355 set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL);
356}
357
312void
358static void
313set80211txpower(const char *val, int d, int s, const struct afswtch *rafp)
314{
315 set80211(s, IEEE80211_IOC_TXPOWER, atoi(val), 0, NULL);
316}
317
359set80211txpower(const char *val, int d, int s, const struct afswtch *rafp)
360{
361 set80211(s, IEEE80211_IOC_TXPOWER, atoi(val), 0, NULL);
362}
363
318void
319ieee80211_status (int s, struct rt_addrinfo *info __unused)
364#define IEEE80211_ROAMING_DEVICE 0
365#define IEEE80211_ROAMING_AUTO 1
366#define IEEE80211_ROAMING_MANUAL 2
367
368static void
369set80211roaming(const char *val, int d, int s, const struct afswtch *rafp)
320{
370{
321 int i;
322 int num;
323 struct ieee80211req ireq;
324 u_int8_t data[32];
325 char spacer;
371 int mode;
326
372
373 if (strcasecmp(val, "device") == 0) {
374 mode = IEEE80211_ROAMING_DEVICE;
375 } else if (strcasecmp(val, "auto") == 0) {
376 mode = IEEE80211_ROAMING_AUTO;
377 } else if (strcasecmp(val, "manual") == 0) {
378 mode = IEEE80211_ROAMING_MANUAL;
379 } else {
380 err(1, "unknown roaming mode");
381 }
382 set80211(s, IEEE80211_IOC_ROAMING, mode, 0, NULL);
383}
384
385static void
386set80211wme(const char *val, int d, int s, const struct afswtch *rafp)
387{
388 set80211(s, IEEE80211_IOC_WME, d, 0, NULL);
389}
390
391static void
392set80211hidessid(const char *val, int d, int s, const struct afswtch *rafp)
393{
394 set80211(s, IEEE80211_IOC_HIDESSID, d, 0, NULL);
395}
396
397static void
398set80211apbridge(const char *val, int d, int s, const struct afswtch *rafp)
399{
400 set80211(s, IEEE80211_IOC_APBRIDGE, d, 0, NULL);
401}
402
403static void
404set80211chanlist(const char *val, int d, int s, const struct afswtch *rafp)
405{
406 struct ieee80211req_chanlist chanlist;
407#define MAXCHAN (sizeof(chanlist.ic_channels)*NBBY)
408 char *temp, *cp, *tp;
409
410 temp = malloc(strlen(val) + 1);
411 if (temp == NULL)
412 errx(1, "malloc failed");
413 strcpy(temp, val);
414 memset(&chanlist, 0, sizeof(chanlist));
415 cp = temp;
416 for (;;) {
417 int first, last, f;
418
419 tp = strchr(cp, ',');
420 if (tp != NULL)
421 *tp++ = '\0';
422 switch (sscanf(cp, "%u-%u", &first, &last)) {
423 case 1:
424 if (first > MAXCHAN)
425 errx(-1, "channel %u out of range, max %u",
426 first, MAXCHAN);
427 setbit(chanlist.ic_channels, first);
428 break;
429 case 2:
430 if (first > MAXCHAN)
431 errx(-1, "channel %u out of range, max %u",
432 first, MAXCHAN);
433 if (last > MAXCHAN)
434 errx(-1, "channel %u out of range, max %u",
435 last, MAXCHAN);
436 if (first > last)
437 errx(-1, "void channel range, %u > %u",
438 first, last);
439 for (f = first; f <= last; f++)
440 setbit(chanlist.ic_channels, f);
441 break;
442 }
443 if (tp == NULL)
444 break;
445 while (isspace(*tp))
446 tp++;
447 if (!isdigit(*tp))
448 break;
449 cp = tp;
450 }
451 set80211(s, IEEE80211_IOC_CHANLIST, 0,
452 sizeof(chanlist), (uint8_t *) &chanlist);
453#undef MAXCHAN
454}
455
456static void
457set80211bssid(const char *val, int d, int s, const struct afswtch *rafp)
458{
459
460 if (!isanyarg(val)) {
461 char *temp;
462 struct sockaddr_dl sdl;
463
464 temp = malloc(strlen(val) + 1);
465 if (temp == NULL)
466 errx(1, "malloc failed");
467 temp[0] = ':';
468 strcpy(temp + 1, val);
469 sdl.sdl_len = sizeof(sdl);
470 link_addr(temp, &sdl);
471 free(temp);
472 if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
473 errx(1, "malformed link-level address");
474 set80211(s, IEEE80211_IOC_BSSID, 0,
475 IEEE80211_ADDR_LEN, LLADDR(&sdl));
476 } else {
477 uint8_t zerobssid[IEEE80211_ADDR_LEN];
478 memset(zerobssid, 0, sizeof(zerobssid));
479 set80211(s, IEEE80211_IOC_BSSID, 0,
480 IEEE80211_ADDR_LEN, zerobssid);
481 }
482}
483
484static int
485getac(const char *ac)
486{
487 if (strcasecmp(ac, "ac_be") == 0 || strcasecmp(ac, "be") == 0)
488 return WME_AC_BE;
489 if (strcasecmp(ac, "ac_bk") == 0 || strcasecmp(ac, "bk") == 0)
490 return WME_AC_BK;
491 if (strcasecmp(ac, "ac_vi") == 0 || strcasecmp(ac, "vi") == 0)
492 return WME_AC_VI;
493 if (strcasecmp(ac, "ac_vo") == 0 || strcasecmp(ac, "vo") == 0)
494 return WME_AC_VO;
495 errx(1, "unknown wme access class %s", ac);
496}
497
498static
499DECL_CMD_FUNC2(set80211cwmin, ac, val)
500{
501 set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac), NULL);
502}
503
504static
505DECL_CMD_FUNC2(set80211cwmax, ac, val)
506{
507 set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac), NULL);
508}
509
510static
511DECL_CMD_FUNC2(set80211aifs, ac, val)
512{
513 set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac), NULL);
514}
515
516static
517DECL_CMD_FUNC2(set80211txoplimit, ac, val)
518{
519 set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac), NULL);
520}
521
522static
523DECL_CMD_FUNC(set80211acm, val, d)
524{
525 set80211(s, IEEE80211_IOC_WME_ACM, d, WME_AC_BE, NULL);
526}
527
528static
529DECL_CMD_FUNC(set80211ackpolicy, val, d)
530{
531 set80211(s, IEEE80211_IOC_WME_ACKPOLICY, d, WME_AC_BE, NULL);
532}
533
534static
535DECL_CMD_FUNC2(set80211bsscwmin, ac, val)
536{
537 set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val),
538 getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
539}
540
541static
542DECL_CMD_FUNC2(set80211bsscwmax, ac, val)
543{
544 set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val),
545 getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
546}
547
548static
549DECL_CMD_FUNC2(set80211bssaifs, ac, val)
550{
551 set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val),
552 getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
553}
554
555static
556DECL_CMD_FUNC2(set80211bsstxoplimit, ac, val)
557{
558 set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val),
559 getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
560}
561
562static
563DECL_CMD_FUNC(set80211dtimperiod, val, d)
564{
565 set80211(s, IEEE80211_IOC_DTIM_PERIOD, atoi(val), 0, NULL);
566}
567
568static
569DECL_CMD_FUNC(set80211bintval, val, d)
570{
571 set80211(s, IEEE80211_IOC_BEACON_INTERVAL, atoi(val), 0, NULL);
572}
573
574static void
575set80211macmac(int s, int op, const char *val)
576{
577 char *temp;
578 struct sockaddr_dl sdl;
579
580 temp = malloc(strlen(val) + 1);
581 if (temp == NULL)
582 errx(1, "malloc failed");
583 temp[0] = ':';
584 strcpy(temp + 1, val);
585 sdl.sdl_len = sizeof(sdl);
586 link_addr(temp, &sdl);
587 free(temp);
588 if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
589 errx(1, "malformed link-level address");
590 set80211(s, op, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl));
591}
592
593static
594DECL_CMD_FUNC(set80211addmac, val, d)
595{
596 set80211macmac(s, IEEE80211_IOC_ADDMAC, val);
597}
598
599static
600DECL_CMD_FUNC(set80211delmac, val, d)
601{
602 set80211macmac(s, IEEE80211_IOC_DELMAC, val);
603}
604
605static
606DECL_CMD_FUNC(set80211maccmd, val, d)
607{
608 set80211(s, IEEE80211_IOC_MACCMD, d, 0, NULL);
609}
610
611static int
612getmaxrate(uint8_t rates[15], uint8_t nrates)
613{
614 int i, maxrate = -1;
615
616 for (i = 0; i < nrates; i++) {
617 int rate = rates[i] & IEEE80211_RATE_VAL;
618 if (rate > maxrate)
619 maxrate = rate;
620 }
621 return maxrate / 2;
622}
623
624static const char *
625getcaps(int capinfo)
626{
627 static char capstring[32];
628 char *cp = capstring;
629
630 if (capinfo & IEEE80211_CAPINFO_ESS)
631 *cp++ = 'E';
632 if (capinfo & IEEE80211_CAPINFO_IBSS)
633 *cp++ = 'I';
634 if (capinfo & IEEE80211_CAPINFO_CF_POLLABLE)
635 *cp++ = 'c';
636 if (capinfo & IEEE80211_CAPINFO_CF_POLLREQ)
637 *cp++ = 'C';
638 if (capinfo & IEEE80211_CAPINFO_PRIVACY)
639 *cp++ = 'P';
640 if (capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)
641 *cp++ = 'S';
642 if (capinfo & IEEE80211_CAPINFO_PBCC)
643 *cp++ = 'B';
644 if (capinfo & IEEE80211_CAPINFO_CHNL_AGILITY)
645 *cp++ = 'A';
646 if (capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)
647 *cp++ = 's';
648 if (capinfo & IEEE80211_CAPINFO_RSN)
649 *cp++ = 'R';
650 if (capinfo & IEEE80211_CAPINFO_DSSSOFDM)
651 *cp++ = 'D';
652 *cp = '\0';
653 return capstring;
654}
655
656static void
657printie(const char* tag, const uint8_t *ie, size_t ielen, int maxlen)
658{
659 printf("%s", tag);
660 if (verbose) {
661 maxlen -= strlen(tag)+2;
662 if (2*ielen > maxlen)
663 maxlen--;
664 printf("<");
665 for (; ielen > 0; ie++, ielen--) {
666 if (maxlen-- <= 0)
667 break;
668 printf("%02x", *ie);
669 }
670 if (ielen != 0)
671 printf("-");
672 printf(">");
673 }
674}
675
676/*
677 * Copy the ssid string contents into buf, truncating to fit. If the
678 * ssid is entirely printable then just copy intact. Otherwise convert
679 * to hexadecimal. If the result is truncated then replace the last
680 * three characters with "...".
681 */
682static size_t
683copy_essid(char buf[], size_t bufsize, const u_int8_t *essid, size_t essid_len)
684{
685 const u_int8_t *p;
686 size_t maxlen;
687 int i;
688
689 if (essid_len > bufsize)
690 maxlen = bufsize;
691 else
692 maxlen = essid_len;
693 /* determine printable or not */
694 for (i = 0, p = essid; i < maxlen; i++, p++) {
695 if (*p < ' ' || *p > 0x7e)
696 break;
697 }
698 if (i != maxlen) { /* not printable, print as hex */
699 if (bufsize < 3)
700 return 0;
701 strlcpy(buf, "0x", bufsize);
702 bufsize -= 2;
703 p = essid;
704 for (i = 0; i < maxlen && bufsize >= 2; i++) {
705 sprintf(&buf[2+2*i], "%02x", *p++);
706 bufsize -= 2;
707 }
708 maxlen = 2+2*i;
709 } else { /* printable, truncate as needed */
710 memcpy(buf, essid, maxlen);
711 }
712 if (maxlen != essid_len)
713 memcpy(buf+maxlen-3, "...", 3);
714 return maxlen;
715}
716
717/* unalligned little endian access */
718#define LE_READ_4(p) \
719 ((u_int32_t) \
720 ((((const u_int8_t *)(p))[0] ) | \
721 (((const u_int8_t *)(p))[1] << 8) | \
722 (((const u_int8_t *)(p))[2] << 16) | \
723 (((const u_int8_t *)(p))[3] << 24)))
724
725static int __inline
726iswpaoui(const u_int8_t *frm)
727{
728 return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
729}
730
731static int __inline
732iswmeoui(const u_int8_t *frm)
733{
734 return frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI);
735}
736
737static int __inline
738isatherosoui(const u_int8_t *frm)
739{
740 return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
741}
742
743static void
744printies(const u_int8_t *vp, int ielen, int maxcols)
745{
746 while (ielen > 0) {
747 switch (vp[0]) {
748 case IEEE80211_ELEMID_VENDOR:
749 if (iswpaoui(vp))
750 printie(" WPA", vp, 2+vp[1], maxcols);
751 else if (iswmeoui(vp))
752 printie(" WME", vp, 2+vp[1], maxcols);
753 else
754 printie(" VEN", vp, 2+vp[1], maxcols);
755 break;
756 case IEEE80211_ELEMID_RSN:
757 printie(" RSN", vp, 2+vp[1], maxcols);
758 break;
759 default:
760 printie(" ???", vp, 2+vp[1], maxcols);
761 break;
762 }
763 ielen -= 2+vp[1];
764 vp += 2+vp[1];
765 }
766}
767
768static void
769list_scan(int s)
770{
771 uint8_t buf[24*1024];
772 struct ieee80211req ireq;
773 char ssid[14];
774 uint8_t *cp;
775 int len;
776
327 (void) memset(&ireq, 0, sizeof(ireq));
328 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
777 (void) memset(&ireq, 0, sizeof(ireq));
778 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
779 ireq.i_type = IEEE80211_IOC_SCAN_RESULTS;
780 ireq.i_data = buf;
781 ireq.i_len = sizeof(buf);
782 if (ioctl(s, SIOCG80211, &ireq) < 0)
783 errx(1, "unable to get scan results");
784 len = ireq.i_len;
785 if (len < sizeof(struct ieee80211req_scan_result))
786 return;
787
788 printf("%-14.14s %-17.17s %4s %4s %-5s %3s %4s\n"
789 , "SSID"
790 , "BSSID"
791 , "CHAN"
792 , "RATE"
793 , "S:N"
794 , "INT"
795 , "CAPS"
796 );
797 cp = buf;
798 do {
799 struct ieee80211req_scan_result *sr;
800 uint8_t *vp;
801
802 sr = (struct ieee80211req_scan_result *) cp;
803 vp = (u_int8_t *)(sr+1);
804 printf("%-14.*s %s %3d %3dM %2d:%-2d %3d %-4.4s"
805 , copy_essid(ssid, sizeof(ssid), vp, sr->isr_ssid_len)
806 , ssid
807 , ether_ntoa((const struct ether_addr *) sr->isr_bssid)
808 , ieee80211_mhz2ieee(sr->isr_freq)
809 , getmaxrate(sr->isr_rates, sr->isr_nrates)
810 , sr->isr_rssi, sr->isr_noise
811 , sr->isr_intval
812 , getcaps(sr->isr_capinfo)
813 );
814 printies(vp + sr->isr_ssid_len, sr->isr_ie_len, 24);;
815 printf("\n");
816 cp += sr->isr_len, len -= sr->isr_len;
817 } while (len >= sizeof(struct ieee80211req_scan_result));
818}
819
820#include <net80211/ieee80211_freebsd.h>
821
822static void
823scan_and_wait(int s)
824{
825 struct ieee80211req ireq;
826 int sroute;
827
828 sroute = socket(PF_ROUTE, SOCK_RAW, 0);
829 if (sroute < 0) {
830 perror("socket(PF_ROUTE,SOCK_RAW)");
831 return;
832 }
833 (void) memset(&ireq, 0, sizeof(ireq));
834 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
835 ireq.i_type = IEEE80211_IOC_SCAN_REQ;
836 /* NB: only root can trigger a scan so ignore errors */
837 if (ioctl(s, SIOCS80211, &ireq) >= 0) {
838 char buf[2048];
839 struct if_announcemsghdr *ifan;
840 struct rt_msghdr *rtm;
841
842 do {
843 if (read(sroute, buf, sizeof(buf)) < 0) {
844 perror("read(PF_ROUTE)");
845 break;
846 }
847 rtm = (struct rt_msghdr *) buf;
848 if (rtm->rtm_version != RTM_VERSION)
849 break;
850 ifan = (struct if_announcemsghdr *) rtm;
851 } while (rtm->rtm_type != RTM_IEEE80211 ||
852 ifan->ifan_what != RTM_IEEE80211_SCAN);
853 }
854 close(sroute);
855}
856
857static
858DECL_CMD_FUNC(set80211scan, val, d)
859{
860 scan_and_wait(s);
861 list_scan(s);
862}
863
864static void
865list_stations(int s)
866{
867 uint8_t buf[24*1024];
868 struct ieee80211req ireq;
869 uint8_t *cp;
870 int len;
871
872 (void) memset(&ireq, 0, sizeof(ireq));
873 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
874 ireq.i_type = IEEE80211_IOC_STA_INFO;
875 ireq.i_data = buf;
876 ireq.i_len = sizeof(buf);
877 if (ioctl(s, SIOCG80211, &ireq) < 0)
878 errx(1, "unable to get station information");
879 len = ireq.i_len;
880 if (len < sizeof(struct ieee80211req_sta_info))
881 return;
882
883 printf("%-17.17s %4s %4s %4s %4s %4s %6s %6s %4s %3s\n"
884 , "ADDR"
885 , "AID"
886 , "CHAN"
887 , "RATE"
888 , "RSSI"
889 , "IDLE"
890 , "TXSEQ"
891 , "RXSEQ"
892 , "CAPS"
893 , "ERP"
894 );
895 cp = buf;
896 do {
897 struct ieee80211req_sta_info *si;
898 uint8_t *vp;
899
900 si = (struct ieee80211req_sta_info *) cp;
901 vp = (u_int8_t *)(si+1);
902 printf("%s %4u %4d %3dM %4d %4d %6d %6d %-4.4s %3x"
903 , ether_ntoa((const struct ether_addr*) si->isi_macaddr)
904 , IEEE80211_AID(si->isi_associd)
905 , ieee80211_mhz2ieee(si->isi_freq)
906 , (si->isi_rates[si->isi_txrate] & IEEE80211_RATE_VAL)/2
907 , si->isi_rssi
908 , si->isi_inact
909 , si->isi_txseqs[0]
910 , si->isi_rxseqs[0]
911 , getcaps(si->isi_capinfo)
912 , si->isi_erp
913 );
914 printies(vp, si->isi_ie_len, 24);
915 printf("\n");
916 cp += si->isi_len, len -= si->isi_len;
917 } while (len >= sizeof(struct ieee80211req_sta_info));
918}
919
920static void
921print_chaninfo(const struct ieee80211_channel *c)
922{
923#define IEEE80211_IS_CHAN_PASSIVE(_c) \
924 (((_c)->ic_flags & IEEE80211_CHAN_PASSIVE))
925 char buf[14];
926
927 buf[0] = '\0';
928 if (IEEE80211_IS_CHAN_FHSS(c))
929 strlcat(buf, " FHSS", sizeof(buf));
930 if (IEEE80211_IS_CHAN_A(c))
931 strlcat(buf, " 11a", sizeof(buf));
932 /* XXX 11g schizophrenia */
933 if (IEEE80211_IS_CHAN_G(c) ||
934 IEEE80211_IS_CHAN_PUREG(c))
935 strlcat(buf, " 11g", sizeof(buf));
936 else if (IEEE80211_IS_CHAN_B(c))
937 strlcat(buf, " 11b", sizeof(buf));
938 if (IEEE80211_IS_CHAN_T(c))
939 strlcat(buf, " Turbo", sizeof(buf));
940 printf("Channel %3u : %u%c Mhz%-14.14s",
941 ieee80211_mhz2ieee(c->ic_freq), c->ic_freq,
942 IEEE80211_IS_CHAN_PASSIVE(c) ? '*' : ' ', buf);
943#undef IEEE80211_IS_CHAN_PASSIVE
944}
945
946static void
947list_channels(int s, int allchans)
948{
949 struct ieee80211req ireq;
950 struct ieee80211req_chaninfo chans;
951 struct ieee80211req_chaninfo achans;
952 const struct ieee80211_channel *c;
953 int i, half;
954
955 (void) memset(&ireq, 0, sizeof(ireq));
956 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
957 ireq.i_type = IEEE80211_IOC_CHANINFO;
958 ireq.i_data = &chans;
959 ireq.i_len = sizeof(chans);
960 if (ioctl(s, SIOCG80211, &ireq) < 0)
961 errx(1, "unable to get channel information");
962 if (!allchans) {
963 struct ieee80211req_chanlist active;
964
965 ireq.i_type = IEEE80211_IOC_CHANLIST;
966 ireq.i_data = &active;
967 ireq.i_len = sizeof(active);
968 if (ioctl(s, SIOCG80211, &ireq) < 0)
969 errx(1, "unable to get active channel list");
970 memset(&achans, 0, sizeof(achans));
971 for (i = 0; i < chans.ic_nchans; i++) {
972 c = &chans.ic_chans[i];
973 if (isset(active.ic_channels, ieee80211_mhz2ieee(c->ic_freq)) || allchans)
974 achans.ic_chans[achans.ic_nchans++] = *c;
975 }
976 } else
977 achans = chans;
978 half = achans.ic_nchans / 2;
979 if (achans.ic_nchans % 2)
980 half++;
981 for (i = 0; i < achans.ic_nchans / 2; i++) {
982 print_chaninfo(&achans.ic_chans[i]);
983 print_chaninfo(&achans.ic_chans[half+i]);
984 printf("\n");
985 }
986 if (achans.ic_nchans % 2) {
987 print_chaninfo(&achans.ic_chans[i]);
988 printf("\n");
989 }
990}
991
992static void
993list_keys(int s)
994{
995}
996
997#define IEEE80211_C_BITS \
998"\020\1WEP\2TKIP\3AES\4AES_CCM\6CKIP\11IBSS\12PMGT\13HOSTAP\14AHDEMO" \
999"\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE\21MONITOR\22TKIPMIC\30WPA1" \
1000"\31WPA2\32BURST\33WME"
1001
1002static void
1003list_capabilities(int s)
1004{
1005 struct ieee80211req ireq;
1006 u_int32_t caps;
1007
1008 (void) memset(&ireq, 0, sizeof(ireq));
1009 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
1010 ireq.i_type = IEEE80211_IOC_DRIVER_CAPS;
1011 if (ioctl(s, SIOCG80211, &ireq) < 0)
1012 errx(1, "unable to get driver capabilities");
1013 caps = (((u_int16_t) ireq.i_val) << 16) | ((u_int16_t) ireq.i_len);
1014 printb(name, caps, IEEE80211_C_BITS);
1015 putchar('\n');
1016}
1017
1018static void
1019list_wme(int s)
1020{
1021 static const char *acnames[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" };
1022 struct ieee80211req ireq;
1023 int ac;
1024
1025 (void) memset(&ireq, 0, sizeof(ireq));
1026 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
1027 ireq.i_len = 0;
1028 for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++) {
1029again:
1030 if (ireq.i_len & IEEE80211_WMEPARAM_BSS)
1031 printf("\t%s", " ");
1032 else
1033 printf("\t%s", acnames[ac]);
1034
1035 ireq.i_len = (ireq.i_len & IEEE80211_WMEPARAM_BSS) | ac;
1036
1037 /* show WME BSS parameters */
1038 ireq.i_type = IEEE80211_IOC_WME_CWMIN;
1039 if (ioctl(s, SIOCG80211, &ireq) != -1)
1040 printf(" cwmin %2u", ireq.i_val);
1041 ireq.i_type = IEEE80211_IOC_WME_CWMAX;
1042 if (ioctl(s, SIOCG80211, &ireq) != -1)
1043 printf(" cwmax %2u", ireq.i_val);
1044 ireq.i_type = IEEE80211_IOC_WME_AIFS;
1045 if (ioctl(s, SIOCG80211, &ireq) != -1)
1046 printf(" aifs %2u", ireq.i_val);
1047 ireq.i_type = IEEE80211_IOC_WME_TXOPLIMIT;
1048 if (ioctl(s, SIOCG80211, &ireq) != -1)
1049 printf(" txopLimit %3u", ireq.i_val);
1050 ireq.i_type = IEEE80211_IOC_WME_ACM;
1051 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1052 if (ireq.i_val)
1053 printf(" acm");
1054 else if (verbose)
1055 printf(" -acm");
1056 }
1057 /* !BSS only */
1058 if ((ireq.i_len & IEEE80211_WMEPARAM_BSS) == 0) {
1059 ireq.i_type = IEEE80211_IOC_WME_ACKPOLICY;
1060 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1061 if (!ireq.i_val)
1062 printf(" -ack");
1063 else if (verbose)
1064 printf(" ack");
1065 }
1066 }
1067 printf("\n");
1068 if ((ireq.i_len & IEEE80211_WMEPARAM_BSS) == 0) {
1069 ireq.i_len |= IEEE80211_WMEPARAM_BSS;
1070 goto again;
1071 } else
1072 ireq.i_len &= ~IEEE80211_WMEPARAM_BSS;
1073 }
1074}
1075
1076static
1077DECL_CMD_FUNC(set80211list, arg, d)
1078{
1079#define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0)
1080
1081 if (iseq(arg, "sta"))
1082 list_stations(s);
1083 else if (iseq(arg, "scan") || iseq(arg, "ap"))
1084 list_scan(s);
1085 else if (iseq(arg, "chan") || iseq(arg, "freq"))
1086 list_channels(s, 1);
1087 else if (iseq(arg, "active"))
1088 list_channels(s, 0);
1089 else if (iseq(arg, "keys"))
1090 list_keys(s);
1091 else if (iseq(arg, "caps"))
1092 list_capabilities(s);
1093 else if (iseq(arg, "wme"))
1094 list_wme(s);
1095 else
1096 errx(1, "Don't know how to list %s for %s", arg, name);
1097#undef iseq
1098}
1099
1100static enum ieee80211_opmode
1101get80211opmode(int s)
1102{
1103 struct ifmediareq ifmr;
1104
1105 (void) memset(&ifmr, 0, sizeof(ifmr));
1106 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
1107
1108 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
1109 if (ifmr.ifm_current & IFM_IEEE80211_ADHOC)
1110 return IEEE80211_M_IBSS; /* XXX ahdemo */
1111 if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
1112 return IEEE80211_M_HOSTAP;
1113 if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
1114 return IEEE80211_M_MONITOR;
1115 }
1116 return IEEE80211_M_STA;
1117}
1118
1119static const struct ieee80211_channel *
1120getchaninfo(int s, int chan)
1121{
1122 struct ieee80211req ireq;
1123 static struct ieee80211req_chaninfo chans;
1124 static struct ieee80211_channel undef;
1125 const struct ieee80211_channel *c;
1126 int i, freq;
1127
1128 (void) memset(&ireq, 0, sizeof(ireq));
1129 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
1130 ireq.i_type = IEEE80211_IOC_CHANINFO;
1131 ireq.i_data = &chans;
1132 ireq.i_len = sizeof(chans);
1133 if (ioctl(s, SIOCG80211, &ireq) < 0)
1134 errx(1, "unable to get channel information");
1135 freq = ieee80211_ieee2mhz(chan);
1136 for (i = 0; i < chans.ic_nchans; i++) {
1137 c = &chans.ic_chans[i];
1138 if (c->ic_freq == freq)
1139 return c;
1140 }
1141 return &undef;
1142}
1143
1144#if 0
1145static void
1146printcipher(int s, struct ieee80211req *ireq, int keylenop)
1147{
1148 switch (ireq->i_val) {
1149 case IEEE80211_CIPHER_WEP:
1150 ireq->i_type = keylenop;
1151 if (ioctl(s, SIOCG80211, ireq) != -1)
1152 printf("WEP-%s",
1153 ireq->i_len <= 5 ? "40" :
1154 ireq->i_len <= 13 ? "104" : "128");
1155 else
1156 printf("WEP");
1157 break;
1158 case IEEE80211_CIPHER_TKIP:
1159 printf("TKIP");
1160 break;
1161 case IEEE80211_CIPHER_AES_OCB:
1162 printf("AES-OCB");
1163 break;
1164 case IEEE80211_CIPHER_AES_CCM:
1165 printf("AES-CCM");
1166 break;
1167 case IEEE80211_CIPHER_CKIP:
1168 printf("CKIP");
1169 break;
1170 case IEEE80211_CIPHER_NONE:
1171 printf("NONE");
1172 break;
1173 default:
1174 printf("UNKNOWN (0x%x)", ireq->i_val);
1175 break;
1176 }
1177}
1178#endif
1179
1180#define MAXCOL 78
1181int col;
1182char spacer;
1183
1184#define LINE_BREAK() do { \
1185 if (spacer != '\t') { \
1186 printf("\n"); \
1187 spacer = '\t'; \
1188 } \
1189 col = 8; /* 8-col tab */ \
1190} while (0)
1191#define LINE_CHECK(fmt, ...) do { \
1192 col += sizeof(fmt)-2; \
1193 if (col > MAXCOL) { \
1194 LINE_BREAK(); \
1195 col += sizeof(fmt)-2; \
1196 } \
1197 printf(fmt, __VA_ARGS__); \
1198 spacer = ' '; \
1199} while (0)
1200
1201static void
1202printkey(const struct ieee80211req_key *ik)
1203{
1204 static const uint8_t zerodata[IEEE80211_KEYBUF_SIZE];
1205 int keylen = ik->ik_keylen;
1206 int printcontents;
1207
1208 printcontents =
1209 (memcmp(ik->ik_keydata, zerodata, keylen) != 0 || verbose);
1210 if (printcontents)
1211 LINE_BREAK();
1212 switch (ik->ik_type) {
1213 case IEEE80211_CIPHER_WEP:
1214 /* compatibility */
1215 LINE_CHECK("%cwepkey %u:%s", spacer, ik->ik_keyix+1,
1216 keylen <= 5 ? "40-bit" :
1217 keylen <= 13 ? "104-bit" : "128-bit");
1218 break;
1219 case IEEE80211_CIPHER_TKIP:
1220 if (keylen > 128/8)
1221 keylen -= 128/8; /* ignore MIC for now */
1222 LINE_CHECK("%cTKIP %u:%u-bit",
1223 spacer, ik->ik_keyix+1, 8*keylen);
1224 break;
1225 case IEEE80211_CIPHER_AES_OCB:
1226 LINE_CHECK("%cAES-OCB %u:%u-bit",
1227 spacer, ik->ik_keyix+1, 8*keylen);
1228 break;
1229 case IEEE80211_CIPHER_AES_CCM:
1230 LINE_CHECK("%cAES-CCM %u:%u-bit",
1231 spacer, ik->ik_keyix+1, 8*keylen);
1232 break;
1233 case IEEE80211_CIPHER_CKIP:
1234 LINE_CHECK("%cCKIP %u:%u-bit",
1235 spacer, ik->ik_keyix+1, 8*keylen);
1236 break;
1237 case IEEE80211_CIPHER_NONE:
1238 LINE_CHECK("%cNULL %u:%u-bit",
1239 spacer, ik->ik_keyix+1, 8*keylen);
1240 break;
1241 default:
1242 LINE_CHECK("%cUNKNOWN (0x%x) %u:%u-bit", spacer,
1243 ik->ik_type, ik->ik_keyix+1, 8*keylen);
1244 break;
1245 }
1246 if (printcontents) {
1247 int i;
1248
1249 printf(" <");
1250 for (i = 0; i < keylen; i++)
1251 printf("%02x", ik->ik_keydata[i]);
1252 printf(">");
1253 if (ik->ik_type != IEEE80211_CIPHER_WEP &&
1254 (ik->ik_keyrsc != 0 || verbose))
1255 printf(" rsc %llu", ik->ik_keyrsc);
1256 if (ik->ik_type != IEEE80211_CIPHER_WEP &&
1257 (ik->ik_keytsc != 0 || verbose))
1258 printf(" tsc %llu", ik->ik_keytsc);
1259 if (ik->ik_flags != 0 && verbose) {
1260 const char *sep = " ";
1261
1262 if (ik->ik_flags & IEEE80211_KEY_XMIT)
1263 printf("%stx", sep), sep = "+";
1264 if (ik->ik_flags & IEEE80211_KEY_RECV)
1265 printf("%srx", sep), sep = "+";
1266 if (ik->ik_flags & IEEE80211_KEY_DEFAULT)
1267 printf("%sdef", sep), sep = "+";
1268 }
1269 LINE_BREAK();
1270 }
1271}
1272
1273static void
1274ieee80211_status(int s, const struct rt_addrinfo *info __unused)
1275{
1276 static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
1277 enum ieee80211_opmode opmode = get80211opmode(s);
1278 int i, num, wpa, wme;
1279 struct ieee80211req ireq;
1280 u_int8_t data[32];
1281 const struct ieee80211_channel *c;
1282
1283 (void) memset(&ireq, 0, sizeof(ireq));
1284 (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
329 ireq.i_data = &data;
330
1285 ireq.i_data = &data;
1286
1287 wpa = 0; /* unknown/not set */
1288
331 ireq.i_type = IEEE80211_IOC_SSID;
332 ireq.i_val = -1;
333 if (ioctl(s, SIOCG80211, &ireq) < 0) {
334 /* If we can't get the SSID, the this isn't an 802.11 device. */
335 return;
336 }
1289 ireq.i_type = IEEE80211_IOC_SSID;
1290 ireq.i_val = -1;
1291 if (ioctl(s, SIOCG80211, &ireq) < 0) {
1292 /* If we can't get the SSID, the this isn't an 802.11 device. */
1293 return;
1294 }
337 printf("\tssid ");
338 print_string(data, ireq.i_len);
339 num = 0;
340 ireq.i_type = IEEE80211_IOC_NUMSSIDS;
1295 num = 0;
1296 ireq.i_type = IEEE80211_IOC_NUMSSIDS;
341 if (ioctl(s, SIOCG80211, &ireq) >= 0) {
1297 if (ioctl(s, SIOCG80211, &ireq) >= 0)
342 num = ireq.i_val;
1298 num = ireq.i_val;
343 }
344 ireq.i_type = IEEE80211_IOC_SSID;
345 for (ireq.i_val = 0; ireq.i_val < num; ireq.i_val++) {
346 if (ioctl(s, SIOCG80211, &ireq) >= 0 && ireq.i_len > 0) {
347 printf(" %d:", ireq.i_val + 1);
348 print_string(data, ireq.i_len);
1299 printf("\tssid ");
1300 if (num > 1) {
1301 ireq.i_type = IEEE80211_IOC_SSID;
1302 for (ireq.i_val = 0; ireq.i_val < num; ireq.i_val++) {
1303 if (ioctl(s, SIOCG80211, &ireq) >= 0 && ireq.i_len > 0) {
1304 printf(" %d:", ireq.i_val + 1);
1305 print_string(data, ireq.i_len);
1306 }
349 }
1307 }
350 }
351 printf("\n");
1308 } else
1309 print_string(data, ireq.i_len);
352
1310
1311 ireq.i_type = IEEE80211_IOC_CHANNEL;
1312 if (ioctl(s, SIOCG80211, &ireq) < 0)
1313 goto end;
1314 c = getchaninfo(s, ireq.i_val);
1315 if (ireq.i_val != -1) {
1316 printf(" channel %d", ireq.i_val);
1317 if (verbose)
1318 printf(" (%u)", c->ic_freq);
1319 } else if (verbose)
1320 printf(" channel UNDEF");
1321
1322 ireq.i_type = IEEE80211_IOC_BSSID;
1323 ireq.i_len = IEEE80211_ADDR_LEN;
1324 if (ioctl(s, SIOCG80211, &ireq) >= 0 &&
1325 memcmp(ireq.i_data, zerobssid, sizeof(zerobssid)) != 0)
1326 printf(" bssid %s", ether_ntoa(ireq.i_data));
1327
353 ireq.i_type = IEEE80211_IOC_STATIONNAME;
354 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1328 ireq.i_type = IEEE80211_IOC_STATIONNAME;
1329 if (ioctl(s, SIOCG80211, &ireq) != -1) {
355 printf("\tstationname ");
1330 printf("\n\tstationname ");
356 print_string(data, ireq.i_len);
1331 print_string(data, ireq.i_len);
357 printf("\n");
358 }
359
1332 }
1333
360 ireq.i_type = IEEE80211_IOC_CHANNEL;
361 if (ioctl(s, SIOCG80211, &ireq) < 0) {
362 goto end;
363 }
364 printf("\tchannel %d", ireq.i_val);
1334 spacer = ' '; /* force first break */
1335 LINE_BREAK();
365
366 ireq.i_type = IEEE80211_IOC_AUTHMODE;
367 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1336
1337 ireq.i_type = IEEE80211_IOC_AUTHMODE;
1338 if (ioctl(s, SIOCG80211, &ireq) != -1) {
368 printf(" authmode");
369 switch (ireq.i_val) {
370 case IEEE80211_AUTH_NONE:
1339 switch (ireq.i_val) {
1340 case IEEE80211_AUTH_NONE:
371 printf(" NONE");
1341 LINE_CHECK("%cauthmode NONE", spacer);
372 break;
373 case IEEE80211_AUTH_OPEN:
1342 break;
1343 case IEEE80211_AUTH_OPEN:
374 printf(" OPEN");
1344 LINE_CHECK("%cauthmode OPEN", spacer);
375 break;
376 case IEEE80211_AUTH_SHARED:
1345 break;
1346 case IEEE80211_AUTH_SHARED:
377 printf(" SHARED");
1347 LINE_CHECK("%cauthmode SHARED", spacer);
378 break;
1348 break;
379 default:
380 printf(" UNKNOWN");
1349 case IEEE80211_AUTH_8021X:
1350 LINE_CHECK("%cauthmode 802.1x", spacer);
381 break;
1351 break;
382 }
383 }
384
385 ireq.i_type = IEEE80211_IOC_POWERSAVE;
386 if (ioctl(s, SIOCG80211, &ireq) != -1 &&
387 ireq.i_val != IEEE80211_POWERSAVE_NOSUP ) {
388 printf(" powersavemode");
389 switch (ireq.i_val) {
390 case IEEE80211_POWERSAVE_OFF:
391 printf(" OFF");
1352 case IEEE80211_AUTH_WPA:
1353 ireq.i_type = IEEE80211_IOC_WPA;
1354 if (ioctl(s, SIOCG80211, &ireq) != -1)
1355 wpa = ireq.i_val;
1356 if (!wpa)
1357 wpa = 1; /* default to WPA1 */
1358 switch (wpa) {
1359 case 2:
1360 LINE_CHECK("%cauthmode WPA2/802.11i",
1361 spacer);
1362 break;
1363 case 3:
1364 LINE_CHECK("%cauthmode WPA1+WPA2/802.11i",
1365 spacer);
1366 break;
1367 default:
1368 LINE_CHECK("%cauthmode WPA", spacer);
1369 break;
1370 }
392 break;
1371 break;
393 case IEEE80211_POWERSAVE_CAM:
394 printf(" CAM");
1372 case IEEE80211_AUTH_AUTO:
1373 LINE_CHECK("%cauthmode AUTO", spacer);
395 break;
1374 break;
396 case IEEE80211_POWERSAVE_PSP:
397 printf(" PSP");
398 break;
399 case IEEE80211_POWERSAVE_PSP_CAM:
400 printf(" PSP-CAM");
401 break;
402 }
403
404 ireq.i_type = IEEE80211_IOC_POWERSAVESLEEP;
405 if (ioctl(s, SIOCG80211, &ireq) != -1) {
406 if (ireq.i_val)
407 printf(" powersavesleep %d", ireq.i_val);
408 }
409 }
410
411 printf("\n");
412
413 spacer = '\t';
414 ireq.i_type = IEEE80211_IOC_RTSTHRESHOLD;
415 if (ioctl(s, SIOCG80211, &ireq) != -1) {
416 printf("%crtsthreshold %d", spacer, ireq.i_val);
417 spacer = ' ';
418 }
419
420 ireq.i_type = IEEE80211_IOC_PROTMODE;
421 if (ioctl(s, SIOCG80211, &ireq) != -1) {
422 printf("%cprotmode", spacer);
423 switch (ireq.i_val) {
424 case IEEE80211_PROTMODE_OFF:
425 printf(" OFF");
426 break;
427 case IEEE80211_PROTMODE_CTS:
428 printf(" CTS");
429 break;
430 case IEEE80211_PROTMODE_RTSCTS:
431 printf(" RTSCTS");
432 break;
433 default:
1375 default:
434 printf(" UNKNOWN");
1376 LINE_CHECK("%cauthmode UNKNOWN (0x%x)",
1377 spacer, ireq.i_val);
435 break;
436 }
1378 break;
1379 }
437 spacer = ' ';
438 }
439
1380 }
1381
440 ireq.i_type = IEEE80211_IOC_TXPOWER;
441 if (ioctl(s, SIOCG80211, &ireq) != -1) {
442 printf("%ctxpower %d", spacer, ireq.i_val);
443 spacer = ' ';
444 }
445
446 if (spacer != '\t')
447 printf("\n");
448
449 ireq.i_type = IEEE80211_IOC_WEP;
450 if (ioctl(s, SIOCG80211, &ireq) != -1 &&
451 ireq.i_val != IEEE80211_WEP_NOSUP) {
1382 ireq.i_type = IEEE80211_IOC_WEP;
1383 if (ioctl(s, SIOCG80211, &ireq) != -1 &&
1384 ireq.i_val != IEEE80211_WEP_NOSUP) {
452 printf("\twepmode");
1385 int firstkey;
1386
453 switch (ireq.i_val) {
454 case IEEE80211_WEP_OFF:
1387 switch (ireq.i_val) {
1388 case IEEE80211_WEP_OFF:
455 printf(" OFF");
1389 LINE_CHECK("%cprivacy OFF", spacer);
456 break;
457 case IEEE80211_WEP_ON:
1390 break;
1391 case IEEE80211_WEP_ON:
458 printf(" ON");
1392 LINE_CHECK("%cprivacy ON", spacer);
459 break;
460 case IEEE80211_WEP_MIXED:
1393 break;
1394 case IEEE80211_WEP_MIXED:
461 printf(" MIXED");
1395 LINE_CHECK("%cprivacy MIXED", spacer);
462 break;
463 default:
1396 break;
1397 default:
464 printf(" UNKNOWN");
1398 LINE_CHECK("%cprivacy UNKNOWN (0x%x)",
1399 spacer, ireq.i_val);
465 break;
466 }
467
468 /*
469 * If we get here then we've got WEP support so we need
470 * to print WEP status.
471 */
472
473 ireq.i_type = IEEE80211_IOC_WEPTXKEY;
474 if (ioctl(s, SIOCG80211, &ireq) < 0) {
475 warn("WEP support, but no tx key!");
476 goto end;
477 }
1400 break;
1401 }
1402
1403 /*
1404 * If we get here then we've got WEP support so we need
1405 * to print WEP status.
1406 */
1407
1408 ireq.i_type = IEEE80211_IOC_WEPTXKEY;
1409 if (ioctl(s, SIOCG80211, &ireq) < 0) {
1410 warn("WEP support, but no tx key!");
1411 goto end;
1412 }
478 printf(" weptxkey %d", ireq.i_val+1);
1413 if (ireq.i_val != -1)
1414 LINE_CHECK("%cdeftxkey %d", spacer, ireq.i_val+1);
1415 else if (verbose)
1416 LINE_CHECK("%cdeftxkey UNDEF", spacer);
479
480 ireq.i_type = IEEE80211_IOC_NUMWEPKEYS;
481 if (ioctl(s, SIOCG80211, &ireq) < 0) {
482 warn("WEP support, but no NUMWEPKEYS support!");
483 goto end;
484 }
485 num = ireq.i_val;
486
1417
1418 ireq.i_type = IEEE80211_IOC_NUMWEPKEYS;
1419 if (ioctl(s, SIOCG80211, &ireq) < 0) {
1420 warn("WEP support, but no NUMWEPKEYS support!");
1421 goto end;
1422 }
1423 num = ireq.i_val;
1424
487 printf("\n");
488
489 ireq.i_type = IEEE80211_IOC_WEPKEY;
490 spacer = '\t';
1425 firstkey = 1;
491 for (i = 0; i < num; i++) {
1426 for (i = 0; i < num; i++) {
492 ireq.i_val = i;
1427 struct ieee80211req_key ik;
1428
1429 memset(&ik, 0, sizeof(ik));
1430 ik.ik_keyix = i;
1431 ireq.i_type = IEEE80211_IOC_WPAKEY;
1432 ireq.i_data = &ik;
1433 ireq.i_len = sizeof(ik);
493 if (ioctl(s, SIOCG80211, &ireq) < 0) {
494 warn("WEP support, but can get keys!");
495 goto end;
496 }
1434 if (ioctl(s, SIOCG80211, &ireq) < 0) {
1435 warn("WEP support, but can get keys!");
1436 goto end;
1437 }
497 if (ireq.i_len == 0 ||
498 ireq.i_len > IEEE80211_KEYBUF_SIZE)
499 continue;
500 printf("%cwepkey %d:%s", spacer, i+1,
501 ireq.i_len <= 5 ? "40-bit" :
502 ireq.i_len <= 13 ? "104-bit" : "128-bit");
503 if (spacer == '\t')
1438 if (ik.ik_keylen != 0) {
1439 if (verbose)
1440 LINE_BREAK();
1441 printkey(&ik);
1442 firstkey = 0;
1443 }
1444 }
1445 }
1446
1447 ireq.i_type = IEEE80211_IOC_POWERSAVE;
1448 if (ioctl(s, SIOCG80211, &ireq) != -1 &&
1449 ireq.i_val != IEEE80211_POWERSAVE_NOSUP ) {
1450 if (ireq.i_val != IEEE80211_POWERSAVE_OFF || verbose) {
1451 switch (ireq.i_val) {
1452 case IEEE80211_POWERSAVE_OFF:
1453 LINE_CHECK("%cpowersavemode OFF",
1454 spacer);
1455 break;
1456 case IEEE80211_POWERSAVE_CAM:
1457 LINE_CHECK("%cpowersavemode CAM",
1458 spacer);
1459 break;
1460 case IEEE80211_POWERSAVE_PSP:
1461 LINE_CHECK("%cpowersavemode PSP",
1462 spacer);
1463 break;
1464 case IEEE80211_POWERSAVE_PSP_CAM:
1465 LINE_CHECK("%cpowersavemode PSP-CAM",
1466 spacer);
1467 break;
1468 }
1469 ireq.i_type = IEEE80211_IOC_POWERSAVESLEEP;
1470 if (ioctl(s, SIOCG80211, &ireq) != -1)
1471 LINE_CHECK("%cpowersavesleep %d",
1472 spacer, ireq.i_val);
1473 }
1474 }
1475
1476 ireq.i_type = IEEE80211_IOC_TXPOWMAX;
1477 if (ioctl(s, SIOCG80211, &ireq) != -1)
1478 LINE_CHECK("%ctxpowmax %d", spacer, ireq.i_val);
1479
1480 if (verbose) {
1481 ireq.i_type = IEEE80211_IOC_TXPOWER;
1482 if (ioctl(s, SIOCG80211, &ireq) != -1)
1483 LINE_CHECK("%ctxpower %d", spacer, ireq.i_val);
1484 }
1485
1486 ireq.i_type = IEEE80211_IOC_RTSTHRESHOLD;
1487 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1488 if (ireq.i_val != IEEE80211_RTS_MAX || verbose)
1489 LINE_CHECK("%crtsthreshold %d", spacer, ireq.i_val);
1490 }
1491
1492 if (IEEE80211_IS_CHAN_G(c) || IEEE80211_IS_CHAN_PUREG(c) || verbose) {
1493 ireq.i_type = IEEE80211_IOC_PROTMODE;
1494 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1495 switch (ireq.i_val) {
1496 case IEEE80211_PROTMODE_OFF:
1497 LINE_CHECK("%cprotmode OFF", spacer);
1498 break;
1499 case IEEE80211_PROTMODE_CTS:
1500 LINE_CHECK("%cprotmode CTS", spacer);
1501 break;
1502 case IEEE80211_PROTMODE_RTSCTS:
1503 LINE_CHECK("%cprotmode RTSCTS", spacer);
1504 break;
1505 default:
1506 LINE_CHECK("%cprotmode UNKNOWN (0x%x)",
1507 spacer, ireq.i_val);
1508 break;
1509 }
1510 }
1511 }
1512
1513 ireq.i_type = IEEE80211_IOC_WME;
1514 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1515 wme = ireq.i_val;
1516 if (wme)
1517 LINE_CHECK("%cwme", spacer);
1518 else if (verbose)
1519 LINE_CHECK("%c-wme", spacer);
1520 } else
1521 wme = 0;
1522
1523 if (opmode == IEEE80211_M_HOSTAP) {
1524 ireq.i_type = IEEE80211_IOC_HIDESSID;
1525 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1526 if (ireq.i_val)
1527 LINE_CHECK("%cssid HIDE", spacer);
1528 else if (verbose)
1529 LINE_CHECK("%cssid SHOW", spacer);
1530 }
1531
1532 ireq.i_type = IEEE80211_IOC_APBRIDGE;
1533 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1534 if (!ireq.i_val)
1535 LINE_CHECK("%c-apbridge", spacer);
1536 else if (verbose)
1537 LINE_CHECK("%capbridge", spacer);
1538 }
1539
1540 ireq.i_type = IEEE80211_IOC_DTIM_PERIOD;
1541 if (ioctl(s, SIOCG80211, &ireq) != -1)
1542 LINE_CHECK("%cdtimperiod %u", spacer, ireq.i_val);
1543 } else {
1544 ireq.i_type = IEEE80211_IOC_ROAMING;
1545 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1546 if (ireq.i_val != IEEE80211_ROAMING_AUTO || verbose) {
1547 switch (ireq.i_val) {
1548 case IEEE80211_ROAMING_DEVICE:
1549 LINE_CHECK("%croaming DEVICE", spacer);
1550 break;
1551 case IEEE80211_ROAMING_AUTO:
1552 LINE_CHECK("%croaming AUTO", spacer);
1553 break;
1554 case IEEE80211_ROAMING_MANUAL:
1555 LINE_CHECK("%croaming MANUAL", spacer);
1556 break;
1557 default:
1558 LINE_CHECK("%croaming UNKNOWN (0x%x)",
1559 spacer, ireq.i_val);
1560 break;
1561 }
1562 }
1563 }
1564 }
1565 ireq.i_type = IEEE80211_IOC_BEACON_INTERVAL;
1566 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1567 if (ireq.i_val)
1568 LINE_CHECK("%cbintval %u", spacer, ireq.i_val);
1569 else if (verbose)
1570 LINE_CHECK("%cbintval %u", spacer, ireq.i_val);
1571 }
1572
1573 if (wme && verbose) {
1574 LINE_BREAK();
1575 list_wme(s);
1576 }
1577
1578 if (wpa) {
1579 ireq.i_type = IEEE80211_IOC_COUNTERMEASURES;
1580 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1581 if (ireq.i_val)
1582 LINE_CHECK("%ccountermeasures", spacer);
1583 else if (verbose)
1584 LINE_CHECK("%c-countermeasures", spacer);
1585 }
1586#if 0
1587 /* XXX not interesting with WPA done in user space */
1588 ireq.i_type = IEEE80211_IOC_KEYMGTALGS;
1589 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1590 }
1591
1592 ireq.i_type = IEEE80211_IOC_MCASTCIPHER;
1593 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1594 printf("%cmcastcipher ", spacer);
1595 printcipher(s, &ireq, IEEE80211_IOC_MCASTKEYLEN);
1596 spacer = ' ';
1597 }
1598
1599 ireq.i_type = IEEE80211_IOC_UCASTCIPHER;
1600 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1601 printf("%cucastcipher ", spacer);
1602 printcipher(s, &ireq, IEEE80211_IOC_UCASTKEYLEN);
1603 }
1604
1605 if (wpa & 2) {
1606 ireq.i_type = IEEE80211_IOC_RSNCAPS;
1607 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1608 printf("%cRSN caps 0x%x", spacer, ireq.i_val);
504 spacer = ' ';
1609 spacer = ' ';
1610 }
505 }
1611 }
506 if (spacer == ' ')
507 printf("\n");
1612
1613 ireq.i_type = IEEE80211_IOC_UCASTCIPHERS;
1614 if (ioctl(s, SIOCG80211, &ireq) != -1) {
1615 }
1616#endif
1617 LINE_BREAK();
508 }
1618 }
1619 LINE_BREAK();
509
510end:
511 return;
512}
513
514static void
515set80211(int s, int type, int val, int len, u_int8_t *data)
516{

--- 85 unchanged lines hidden (view full) ---

602 printf("%.*s", len, buf);
603 } else {
604 printf("0x");
605 for (i = 0; i < len; i++)
606 printf("%02x", buf[i]);
607 }
608}
609
1620
1621end:
1622 return;
1623}
1624
1625static void
1626set80211(int s, int type, int val, int len, u_int8_t *data)
1627{

--- 85 unchanged lines hidden (view full) ---

1713 printf("%.*s", len, buf);
1714 } else {
1715 printf("0x");
1716 for (i = 0; i < len; i++)
1717 printf("%02x", buf[i]);
1718 }
1719}
1720
1721static struct cmd ieee80211_cmds[] = {
1722 DEF_CMD_ARG("ssid", set80211ssid),
1723 DEF_CMD_ARG("nwid", set80211ssid),
1724 DEF_CMD_ARG("stationname", set80211stationname),
1725 DEF_CMD_ARG("station", set80211stationname), /* BSD/OS */
1726 DEF_CMD_ARG("channel", set80211channel),
1727 DEF_CMD_ARG("authmode", set80211authmode),
1728 DEF_CMD_ARG("powersavemode", set80211powersavemode),
1729 DEF_CMD("powersave", 1, set80211powersave),
1730 DEF_CMD("-powersave", 0, set80211powersave),
1731 DEF_CMD_ARG("powersavesleep", set80211powersavesleep),
1732 DEF_CMD_ARG("wepmode", set80211wepmode),
1733 DEF_CMD("wep", 1, set80211wep),
1734 DEF_CMD("-wep", 0, set80211wep),
1735 DEF_CMD_ARG("weptxkey", set80211weptxkey),
1736 DEF_CMD_ARG("wepkey", set80211wepkey),
1737 DEF_CMD_ARG("nwkey", set80211nwkey), /* NetBSD */
1738 DEF_CMD("-nwkey", 0, set80211wep), /* NetBSD */
1739 DEF_CMD_ARG("rtsthreshold", set80211rtsthreshold),
1740 DEF_CMD_ARG("protmode", set80211protmode),
1741 DEF_CMD_ARG("txpower", set80211txpower),
1742 DEF_CMD_ARG("roaming", set80211roaming),
1743 DEF_CMD("wme", 1, set80211wme),
1744 DEF_CMD("-wme", 0, set80211wme),
1745 DEF_CMD("hidessid", 1, set80211hidessid),
1746 DEF_CMD("-hidessid", 0, set80211hidessid),
1747 DEF_CMD("apbridge", 1, set80211apbridge),
1748 DEF_CMD("-apbridge", 0, set80211apbridge),
1749 DEF_CMD_ARG("chanlist", set80211chanlist),
1750 DEF_CMD_ARG("bssid", set80211bssid),
1751 DEF_CMD_ARG("ap", set80211bssid),
1752 DEF_CMD("scan", 0, set80211scan),
1753 DEF_CMD_ARG("list", set80211list),
1754 DEF_CMD_ARG2("cwmin", set80211cwmin),
1755 DEF_CMD_ARG2("cwmax", set80211cwmax),
1756 DEF_CMD_ARG2("aifs", set80211aifs),
1757 DEF_CMD_ARG2("txoplimit", set80211txoplimit),
1758 DEF_CMD("acm", 1, set80211acm),
1759 DEF_CMD("-acm", 0, set80211acm),
1760 DEF_CMD("ack", 1, set80211ackpolicy),
1761 DEF_CMD("-ack", 0, set80211ackpolicy),
1762 DEF_CMD_ARG2("bss:cwmin", set80211bsscwmin),
1763 DEF_CMD_ARG2("bss:cwmax", set80211bsscwmax),
1764 DEF_CMD_ARG2("bss:aifs", set80211bssaifs),
1765 DEF_CMD_ARG2("bss:txoplimit", set80211bsstxoplimit),
1766 DEF_CMD_ARG("dtimperiod", set80211dtimperiod),
1767 DEF_CMD_ARG("bintval", set80211bintval),
1768 DEF_CMD("mac:open", IEEE80211_MACCMD_POLICY_OPEN, set80211maccmd),
1769 DEF_CMD("mac:allow", IEEE80211_MACCMD_POLICY_ALLOW, set80211maccmd),
1770 DEF_CMD("mac:deny", IEEE80211_MACCMD_POLICY_DENY, set80211maccmd),
1771 DEF_CMD("mac:flush", IEEE80211_MACCMD_FLUSH, set80211maccmd),
1772 DEF_CMD("mac:detach", IEEE80211_MACCMD_DETACH, set80211maccmd),
1773 DEF_CMD_ARG("mac:add", set80211addmac),
1774 DEF_CMD_ARG("mac:del", set80211delmac),
1775#if 0
1776 DEF_CMD_ARG("mac:kick", set80211kickmac),
1777#endif
1778};
1779static struct afswtch af_ieee80211 = {
1780 .af_name = "af_ieee80211",
1781 .af_af = AF_UNSPEC,
1782 .af_status = ieee80211_status,
1783};
1784
1785static __constructor void
1786ieee80211_ctor(void)
1787{
1788#define N(a) (sizeof(a) / sizeof(a[0]))
1789 int i;
1790
1791 for (i = 0; i < N(ieee80211_cmds); i++)
1792 cmd_register(&ieee80211_cmds[i]);
1793 af_register(&af_ieee80211);
1794#undef N
1795}