ifieee80211.c revision 149029
177218Sphk/* 277218Sphk * Copyright 2001 The Aerospace Corporation. All rights reserved. 377218Sphk * 477218Sphk * Redistribution and use in source and binary forms, with or without 577218Sphk * modification, are permitted provided that the following conditions 677218Sphk * are met: 777218Sphk * 1. Redistributions of source code must retain the above copyright 877218Sphk * notice, this list of conditions and the following disclaimer. 977218Sphk * 2. Redistributions in binary form must reproduce the above copyright 1077218Sphk * notice, this list of conditions and the following disclaimer in the 1177218Sphk * documentation and/or other materials provided with the distribution. 1291454Sbrooks * 3. The name of The Aerospace Corporation may not be used to endorse or 1391454Sbrooks * promote products derived from this software. 1477218Sphk * 1577218Sphk * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND 1677218Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1777218Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1877218Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE 1977218Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2077218Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2177218Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2277218Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2377218Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2477218Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2577218Sphk * SUCH DAMAGE. 2677218Sphk * 2777218Sphk * $FreeBSD: head/sbin/ifconfig/ifieee80211.c 149029 2005-08-13 17:38:09Z sam $ 2877218Sphk */ 2977218Sphk 3077218Sphk/*- 3177218Sphk * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc. 3277218Sphk * All rights reserved. 3377218Sphk * 3477218Sphk * This code is derived from software contributed to The NetBSD Foundation 3577218Sphk * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 3677218Sphk * NASA Ames Research Center. 3777218Sphk * 3877218Sphk * Redistribution and use in source and binary forms, with or without 3977218Sphk * modification, are permitted provided that the following conditions 4077218Sphk * are met: 4177218Sphk * 1. Redistributions of source code must retain the above copyright 4277218Sphk * notice, this list of conditions and the following disclaimer. 4377218Sphk * 2. Redistributions in binary form must reproduce the above copyright 4477218Sphk * notice, this list of conditions and the following disclaimer in the 4577218Sphk * documentation and/or other materials provided with the distribution. 4677218Sphk * 3. All advertising materials mentioning features or use of this software 4777218Sphk * must display the following acknowledgement: 4877218Sphk * This product includes software developed by the NetBSD 4977218Sphk * Foundation, Inc. and its contributors. 5077218Sphk * 4. Neither the name of The NetBSD Foundation nor the names of its 5177218Sphk * contributors may be used to endorse or promote products derived 5277218Sphk * from this software without specific prior written permission. 5377218Sphk * 5477218Sphk * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 5577218Sphk * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 5677218Sphk * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 5777218Sphk * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 5877218Sphk * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5977218Sphk * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 6077218Sphk * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 6177218Sphk * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 6277218Sphk * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 6377218Sphk * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6477218Sphk * POSSIBILITY OF SUCH DAMAGE. 6577218Sphk */ 6677218Sphk 6777218Sphk#include <sys/param.h> 6877218Sphk#include <sys/ioctl.h> 6977218Sphk#include <sys/socket.h> 7077218Sphk#include <sys/sysctl.h> 7177218Sphk#include <sys/time.h> 7277218Sphk 7377218Sphk#include <net/ethernet.h> 7477218Sphk#include <net/if.h> 7577218Sphk#include <net/if_dl.h> 7677218Sphk#include <net/if_types.h> 77138593Ssam#include <net/if_media.h> 7877218Sphk#include <net/route.h> 79138593Ssam 80116957Ssam#include <net80211/ieee80211.h> 8177218Sphk#include <net80211/ieee80211_crypto.h> 8277218Sphk#include <net80211/ieee80211_ioctl.h> 8377218Sphk 8477218Sphk#include <ctype.h> 8577218Sphk#include <err.h> 86146873Sjhb#include <errno.h> 8777218Sphk#include <fcntl.h> 8877218Sphk#include <inttypes.h> 8977218Sphk#include <stdio.h> 9077218Sphk#include <stdlib.h> 91155931Ssam#include <string.h> 92173275Ssam#include <unistd.h> 9377218Sphk 9477218Sphk#include "ifconfig.h" 95178354Ssam 9677218Sphkstatic void set80211(int s, int type, int val, int len, u_int8_t *data); 97178354Ssamstatic const char *get_string(const char *val, const char *sep, 98178354Ssam u_int8_t *buf, int *lenp); 99178354Ssamstatic void print_string(const u_int8_t *buf, int len); 100178354Ssam 101178354Ssamstatic int 102178354Ssamisanyarg(const char *arg) 103178354Ssam{ 104178354Ssam return (strcmp(arg, "-") == 0 || 105178354Ssam strcasecmp(arg, "any") == 0 || strcasecmp(arg, "off") == 0); 106178354Ssam} 107178354Ssam 108178354Ssamstatic void 109178354Ssamset80211ssid(const char *val, int d, int s, const struct afswtch *rafp) 110178354Ssam{ 111178354Ssam int ssid; 112178354Ssam int len; 113178354Ssam u_int8_t data[33]; 114178354Ssam 115183261Ssam ssid = 0; 116183261Ssam len = strlen(val); 117183261Ssam if (len > 2 && isdigit(val[0]) && val[1] == ':') { 118183261Ssam ssid = atoi(val)-1; 119183261Ssam val += 2; 120178354Ssam } 121178354Ssam 122173275Ssam bzero(data, sizeof(data)); 123173275Ssam len = sizeof(data); 124173275Ssam get_string(val, NULL, data, &len); 125173275Ssam 126173275Ssam set80211(s, IEEE80211_IOC_SSID, ssid, len, data); 127173275Ssam} 128173275Ssam 129173275Ssamstatic void 130178354Ssamset80211stationname(const char *val, int d, int s, const struct afswtch *rafp) 131178354Ssam{ 132178354Ssam int len; 133173275Ssam u_int8_t data[33]; 134173275Ssam 135178354Ssam bzero(data, sizeof(data)); 136173275Ssam len = sizeof(data); 137173275Ssam get_string(val, NULL, data, &len); 138173275Ssam 13977218Sphk set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data); 14077218Sphk} 14177218Sphk 142178354Ssam/* 143178354Ssam * Convert IEEE channel number to MHz frequency. 144178354Ssam */ 145178354Ssamstatic u_int 146178354Ssamieee80211_ieee2mhz(u_int chan) 14777218Sphk{ 148170531Ssam if (chan == 14) 149178354Ssam return 2484; 150178354Ssam if (chan < 14) /* 0-13 */ 151178354Ssam return 2407 + chan*5; 152178354Ssam if (chan < 27) /* 15-26 */ 153178354Ssam return 2512 + ((chan-15)*20); 154178354Ssam return 5000 + (chan*5); 155173275Ssam} 156173275Ssam 157178354Ssam/* 158173275Ssam * Convert MHz frequency to IEEE channel number. 159173275Ssam */ 160170531Ssamstatic u_int 161173275Ssamieee80211_mhz2ieee(u_int freq) 162173275Ssam{ 163173275Ssam if (freq == 2484) 164173275Ssam return 14; 165173275Ssam if (freq < 2484) 166173275Ssam return (freq - 2407) / 5; 167173275Ssam if (freq < 5000) 168173275Ssam return 15 + ((freq - 2512) / 20); 169173275Ssam return (freq - 5000) / 5; 170173275Ssam} 171170531Ssam 172170531Ssamstatic void 173170531Ssamset80211channel(const char *val, int d, int s, const struct afswtch *rafp) 174170531Ssam{ 175170531Ssam if (!isanyarg(val)) { 176170531Ssam int v = atoi(val); 177170531Ssam if (v > 255) /* treat as frequency */ 178170531Ssam v = ieee80211_mhz2ieee(v); 179170531Ssam set80211(s, IEEE80211_IOC_CHANNEL, v, 0, NULL); 180173275Ssam } else 181170531Ssam set80211(s, IEEE80211_IOC_CHANNEL, IEEE80211_CHAN_ANY, 0, NULL); 182170531Ssam} 183173275Ssam 184170531Ssamstatic void 185170531Ssamset80211authmode(const char *val, int d, int s, const struct afswtch *rafp) 186178354Ssam{ 187178354Ssam int mode; 188178354Ssam 189178354Ssam if (strcasecmp(val, "none") == 0) { 190178354Ssam mode = IEEE80211_AUTH_NONE; 191178354Ssam } else if (strcasecmp(val, "open") == 0) { 192178354Ssam mode = IEEE80211_AUTH_OPEN; 193181198Ssam } else if (strcasecmp(val, "shared") == 0) { 194178354Ssam mode = IEEE80211_AUTH_SHARED; 195178354Ssam } else if (strcasecmp(val, "8021x") == 0) { 196178354Ssam mode = IEEE80211_AUTH_8021X; 197178354Ssam } else if (strcasecmp(val, "wpa") == 0) { 198170531Ssam mode = IEEE80211_AUTH_WPA; 199170531Ssam } else { 200170531Ssam err(1, "unknown authmode"); 201170531Ssam } 202170531Ssam 203170531Ssam set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL); 204170531Ssam} 205138593Ssam 206170531Ssamstatic void 207170531Ssamset80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp) 208170531Ssam{ 209170531Ssam int mode; 210170531Ssam 211170531Ssam if (strcasecmp(val, "off") == 0) { 212170531Ssam mode = IEEE80211_POWERSAVE_OFF; 213170531Ssam } else if (strcasecmp(val, "on") == 0) { 214170531Ssam mode = IEEE80211_POWERSAVE_ON; 215170531Ssam } else if (strcasecmp(val, "cam") == 0) { 216170531Ssam mode = IEEE80211_POWERSAVE_CAM; 217170531Ssam } else if (strcasecmp(val, "psp") == 0) { 218170531Ssam mode = IEEE80211_POWERSAVE_PSP; 219170531Ssam } else if (strcasecmp(val, "psp-cam") == 0) { 220170531Ssam mode = IEEE80211_POWERSAVE_PSP_CAM; 221170531Ssam } else { 222170531Ssam err(1, "unknown powersavemode"); 223170531Ssam } 224170531Ssam 225170531Ssam set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL); 226170531Ssam} 227170531Ssam 228170531Ssamstatic void 229170531Ssamset80211powersave(const char *val, int d, int s, const struct afswtch *rafp) 230170531Ssam{ 231170531Ssam if (d == 0) 232170531Ssam set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF, 233170531Ssam 0, NULL); 234170531Ssam else 235170531Ssam set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON, 236170531Ssam 0, NULL); 237170531Ssam} 238170531Ssam 239170531Ssamstatic void 240170531Ssamset80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp) 241170531Ssam{ 242170531Ssam set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL); 243170531Ssam} 244170531Ssam 245170531Ssamstatic void 246170531Ssamset80211wepmode(const char *val, int d, int s, const struct afswtch *rafp) 247170531Ssam{ 248170531Ssam int mode; 249170531Ssam 250170531Ssam if (strcasecmp(val, "off") == 0) { 251170531Ssam mode = IEEE80211_WEP_OFF; 252170531Ssam } else if (strcasecmp(val, "on") == 0) { 253170531Ssam mode = IEEE80211_WEP_ON; 254170531Ssam } else if (strcasecmp(val, "mixed") == 0) { 255170531Ssam mode = IEEE80211_WEP_MIXED; 256170531Ssam } else { 257170531Ssam err(1, "unknown wep mode"); 258170531Ssam } 259170531Ssam 260170531Ssam set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL); 261170531Ssam} 262173275Ssam 263170531Ssamstatic void 264170531Ssamset80211wep(const char *val, int d, int s, const struct afswtch *rafp) 265173275Ssam{ 266173275Ssam set80211(s, IEEE80211_IOC_WEP, d, 0, NULL); 267173275Ssam} 268173275Ssam 269173275Ssamstatic int 270173275Ssamisundefarg(const char *arg) 271170531Ssam{ 272173275Ssam return (strcmp(arg, "-") == 0 || strncasecmp(arg, "undef", 5) == 0); 273170531Ssam} 274170531Ssam 275173275Ssamstatic void 276173275Ssamset80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp) 277173275Ssam{ 278173275Ssam if (isundefarg(val)) 279173275Ssam set80211(s, IEEE80211_IOC_WEPTXKEY, IEEE80211_KEYIX_NONE, 0, NULL); 280173275Ssam else 281170531Ssam set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL); 282170531Ssam} 283170531Ssam 284170531Ssamstatic void 285170531Ssamset80211wepkey(const char *val, int d, int s, const struct afswtch *rafp) 286170531Ssam{ 287170531Ssam int key = 0; 288170531Ssam int len; 289170531Ssam u_int8_t data[IEEE80211_KEYBUF_SIZE]; 290170531Ssam 291170531Ssam if (isdigit(val[0]) && val[1] == ':') { 292170531Ssam key = atoi(val)-1; 293170531Ssam val += 2; 294170531Ssam } 295170531Ssam 296170531Ssam bzero(data, sizeof(data)); 297170531Ssam len = sizeof(data); 298170531Ssam get_string(val, NULL, data, &len); 299170531Ssam 300170531Ssam set80211(s, IEEE80211_IOC_WEPKEY, key, len, data); 301170531Ssam} 302170531Ssam 303170531Ssam/* 304170531Ssam * This function is purely a NetBSD compatability interface. The NetBSD 305170531Ssam * interface is too inflexible, but it's there so we'll support it since 306170531Ssam * it's not all that hard. 307170531Ssam */ 308170531Ssamstatic void 309170531Ssamset80211nwkey(const char *val, int d, int s, const struct afswtch *rafp) 310170531Ssam{ 311170531Ssam int txkey; 312170531Ssam int i, len; 313170531Ssam u_int8_t data[IEEE80211_KEYBUF_SIZE]; 314170531Ssam 315170531Ssam set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL); 316170531Ssam 317170531Ssam if (isdigit(val[0]) && val[1] == ':') { 318170531Ssam txkey = val[0]-'0'-1; 319170531Ssam val += 2; 320170531Ssam 321170531Ssam for (i = 0; i < 4; i++) { 322173275Ssam bzero(data, sizeof(data)); 323170531Ssam len = sizeof(data); 324170531Ssam val = get_string(val, ",", data, &len); 325173275Ssam 326173275Ssam set80211(s, IEEE80211_IOC_WEPKEY, i, len, data); 327173275Ssam } 328173275Ssam } else { 329173275Ssam bzero(data, sizeof(data)); 330173275Ssam len = sizeof(data); 331173275Ssam get_string(val, NULL, data, &len); 332173275Ssam txkey = 0; 333173275Ssam 334173275Ssam set80211(s, IEEE80211_IOC_WEPKEY, 0, len, data); 335173275Ssam 336173275Ssam bzero(data, sizeof(data)); 337173275Ssam for (i = 1; i < 4; i++) 338173275Ssam set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data); 339173275Ssam } 340173275Ssam 341173275Ssam set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL); 342178354Ssam} 343178354Ssam 344178354Ssamstatic void 345178354Ssamset80211rtsthreshold(const char *val, int d, int s, const struct afswtch *rafp) 346178354Ssam{ 347178354Ssam set80211(s, IEEE80211_IOC_RTSTHRESHOLD, 348178354Ssam isundefarg(val) ? IEEE80211_RTS_MAX : atoi(val), 0, NULL); 349178354Ssam} 350178354Ssam 351178354Ssamstatic void 352178354Ssamset80211protmode(const char *val, int d, int s, const struct afswtch *rafp) 353178354Ssam{ 354178354Ssam int mode; 355178354Ssam 356178354Ssam if (strcasecmp(val, "off") == 0) { 357178354Ssam mode = IEEE80211_PROTMODE_OFF; 358178354Ssam } else if (strcasecmp(val, "cts") == 0) { 359178354Ssam mode = IEEE80211_PROTMODE_CTS; 360178354Ssam } else if (strcasecmp(val, "rtscts") == 0) { 361178354Ssam mode = IEEE80211_PROTMODE_RTSCTS; 362178354Ssam } else { 363178354Ssam err(1, "unknown protection mode"); 364178354Ssam } 365178354Ssam 366178354Ssam set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL); 367178354Ssam} 368178354Ssam 369178354Ssamstatic void 370178354Ssamset80211txpower(const char *val, int d, int s, const struct afswtch *rafp) 371178354Ssam{ 372178354Ssam set80211(s, IEEE80211_IOC_TXPOWER, atoi(val), 0, NULL); 373178354Ssam} 374178354Ssam 375178354Ssam#define IEEE80211_ROAMING_DEVICE 0 376178354Ssam#define IEEE80211_ROAMING_AUTO 1 377178354Ssam#define IEEE80211_ROAMING_MANUAL 2 378178354Ssam 379178354Ssamstatic void 380178354Ssamset80211roaming(const char *val, int d, int s, const struct afswtch *rafp) 381178354Ssam{ 382178354Ssam int mode; 383178354Ssam 384178354Ssam if (strcasecmp(val, "device") == 0) { 385178354Ssam mode = IEEE80211_ROAMING_DEVICE; 386178354Ssam } else if (strcasecmp(val, "auto") == 0) { 387178354Ssam mode = IEEE80211_ROAMING_AUTO; 388178354Ssam } else if (strcasecmp(val, "manual") == 0) { 389178354Ssam mode = IEEE80211_ROAMING_MANUAL; 390178354Ssam } else { 391178354Ssam err(1, "unknown roaming mode"); 392178354Ssam } 393178354Ssam set80211(s, IEEE80211_IOC_ROAMING, mode, 0, NULL); 394178354Ssam} 395178354Ssam 396178354Ssamstatic void 397178354Ssamset80211wme(const char *val, int d, int s, const struct afswtch *rafp) 398178354Ssam{ 399178354Ssam set80211(s, IEEE80211_IOC_WME, d, 0, NULL); 400178354Ssam} 401178354Ssam 402178354Ssamstatic void 403178354Ssamset80211hidessid(const char *val, int d, int s, const struct afswtch *rafp) 404178354Ssam{ 405178354Ssam set80211(s, IEEE80211_IOC_HIDESSID, d, 0, NULL); 406178354Ssam} 407178354Ssam 408178354Ssamstatic void 409178354Ssamset80211apbridge(const char *val, int d, int s, const struct afswtch *rafp) 410178354Ssam{ 411178354Ssam set80211(s, IEEE80211_IOC_APBRIDGE, d, 0, NULL); 412178354Ssam} 413178354Ssam 414178354Ssamstatic void 415178354Ssamset80211chanlist(const char *val, int d, int s, const struct afswtch *rafp) 416178354Ssam{ 417178354Ssam struct ieee80211req_chanlist chanlist; 418178354Ssam#define MAXCHAN (sizeof(chanlist.ic_channels)*NBBY) 419178354Ssam char *temp, *cp, *tp; 420178354Ssam 421178354Ssam temp = malloc(strlen(val) + 1); 422178354Ssam if (temp == NULL) 423178354Ssam errx(1, "malloc failed"); 424178354Ssam strcpy(temp, val); 425178354Ssam memset(&chanlist, 0, sizeof(chanlist)); 426178354Ssam cp = temp; 427178354Ssam for (;;) { 428186102Ssam int first, last, f; 429178354Ssam 430178354Ssam tp = strchr(cp, ','); 431178354Ssam if (tp != NULL) 432178354Ssam *tp++ = '\0'; 433178354Ssam switch (sscanf(cp, "%u-%u", &first, &last)) { 434178354Ssam case 1: 435178354Ssam if (first > MAXCHAN) 436178354Ssam errx(-1, "channel %u out of range, max %zu", 437178354Ssam first, MAXCHAN); 438178354Ssam setbit(chanlist.ic_channels, first); 439178354Ssam break; 440178354Ssam case 2: 441178354Ssam if (first > MAXCHAN) 442178354Ssam errx(-1, "channel %u out of range, max %zu", 443178354Ssam first, MAXCHAN); 444178354Ssam if (last > MAXCHAN) 445178354Ssam errx(-1, "channel %u out of range, max %zu", 446178354Ssam last, MAXCHAN); 447178354Ssam if (first > last) 448178354Ssam errx(-1, "void channel range, %u > %u", 449178354Ssam first, last); 450178354Ssam for (f = first; f <= last; f++) 451178354Ssam setbit(chanlist.ic_channels, f); 452178354Ssam break; 453178354Ssam } 454178354Ssam if (tp == NULL) 455178354Ssam break; 456178354Ssam while (isspace(*tp)) 457178354Ssam tp++; 458178354Ssam if (!isdigit(*tp)) 459186102Ssam break; 460178354Ssam cp = tp; 461178354Ssam } 462178354Ssam set80211(s, IEEE80211_IOC_CHANLIST, 0, 463178354Ssam sizeof(chanlist), (uint8_t *) &chanlist); 464178354Ssam#undef MAXCHAN 465178354Ssam} 466178354Ssam 467178354Ssamstatic void 468178354Ssamset80211bssid(const char *val, int d, int s, const struct afswtch *rafp) 469178354Ssam{ 470178354Ssam 471178354Ssam if (!isanyarg(val)) { 472178354Ssam char *temp; 473178354Ssam struct sockaddr_dl sdl; 474178354Ssam 475178354Ssam temp = malloc(strlen(val) + 1); 476178354Ssam if (temp == NULL) 477178354Ssam errx(1, "malloc failed"); 478178354Ssam temp[0] = ':'; 479178354Ssam strcpy(temp + 1, val); 480178354Ssam sdl.sdl_len = sizeof(sdl); 481178354Ssam link_addr(temp, &sdl); 482178354Ssam free(temp); 483178354Ssam if (sdl.sdl_alen != IEEE80211_ADDR_LEN) 484178354Ssam errx(1, "malformed link-level address"); 485178354Ssam set80211(s, IEEE80211_IOC_BSSID, 0, 486178354Ssam IEEE80211_ADDR_LEN, LLADDR(&sdl)); 487178354Ssam } else { 488178354Ssam uint8_t zerobssid[IEEE80211_ADDR_LEN]; 489178354Ssam memset(zerobssid, 0, sizeof(zerobssid)); 490178354Ssam set80211(s, IEEE80211_IOC_BSSID, 0, 491178354Ssam IEEE80211_ADDR_LEN, zerobssid); 492178354Ssam } 493178354Ssam} 494178354Ssam 495170531Ssamstatic int 496170531Ssamgetac(const char *ac) 497170531Ssam{ 498170531Ssam if (strcasecmp(ac, "ac_be") == 0 || strcasecmp(ac, "be") == 0) 499170531Ssam return WME_AC_BE; 500170531Ssam if (strcasecmp(ac, "ac_bk") == 0 || strcasecmp(ac, "bk") == 0) 501170531Ssam return WME_AC_BK; 502170531Ssam if (strcasecmp(ac, "ac_vi") == 0 || strcasecmp(ac, "vi") == 0) 503170531Ssam return WME_AC_VI; 504138593Ssam if (strcasecmp(ac, "ac_vo") == 0 || strcasecmp(ac, "vo") == 0) 505138593Ssam return WME_AC_VO; 506173275Ssam errx(1, "unknown wme access class %s", ac); 507173275Ssam} 508138593Ssam 509138593Ssamstatic 510138593SsamDECL_CMD_FUNC2(set80211cwmin, ac, val) 51177218Sphk{ 51277218Sphk set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac), NULL); 51377218Sphk} 51477218Sphk 515151883Sbrooksstatic 51677218SphkDECL_CMD_FUNC2(set80211cwmax, ac, val) 51777218Sphk{ 518121827Sbrooks set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac), NULL); 519178354Ssam} 52088748Sambrisko 52188748Sambriskostatic 52288748SambriskoDECL_CMD_FUNC2(set80211aifs, ac, val) 52377218Sphk{ 52477218Sphk set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac), NULL); 52577218Sphk} 526151883Sbrooks 527151883Sbrooksstatic 52877218SphkDECL_CMD_FUNC2(set80211txoplimit, ac, val) 52977218Sphk{ 53077218Sphk set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac), NULL); 53177218Sphk} 532138593Ssam 53377218Sphkstatic 53477218SphkDECL_CMD_FUNC(set80211acm, ac, d) 53577218Sphk{ 53677218Sphk set80211(s, IEEE80211_IOC_WME_ACM, 1, getac(ac), NULL); 53777218Sphk} 53877218Sphkstatic 53977218SphkDECL_CMD_FUNC(set80211noacm, ac, d) 54077218Sphk{ 54177218Sphk set80211(s, IEEE80211_IOC_WME_ACM, 0, getac(ac), NULL); 54277218Sphk} 54377218Sphk 54477218Sphkstatic 545138593SsamDECL_CMD_FUNC(set80211ackpolicy, ac, d) 546170531Ssam{ 547170531Ssam set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 1, getac(ac), NULL); 548170531Ssam} 549170531Ssamstatic 550170531SsamDECL_CMD_FUNC(set80211noackpolicy, ac, d) 551170531Ssam{ 552170531Ssam set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 0, getac(ac), NULL); 553170531Ssam} 554170531Ssam 555170531Ssamstatic 556170531SsamDECL_CMD_FUNC2(set80211bsscwmin, ac, val) 557170531Ssam{ 558173275Ssam set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), 559138593Ssam getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); 560170531Ssam} 561170531Ssam 562170531Ssamstatic 563138593SsamDECL_CMD_FUNC2(set80211bsscwmax, ac, val) 564170531Ssam{ 565166015Ssam set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), 566170531Ssam getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); 567170531Ssam} 568170531Ssam 569170531Ssamstatic 570170531SsamDECL_CMD_FUNC2(set80211bssaifs, ac, val) 571170531Ssam{ 572170531Ssam set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), 573170531Ssam getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); 574170531Ssam} 575170531Ssam 576170531Ssamstatic 577170531SsamDECL_CMD_FUNC2(set80211bsstxoplimit, ac, val) 578170531Ssam{ 579170531Ssam set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), 580170531Ssam getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); 581170531Ssam} 582170531Ssam 583170531Ssamstatic 584170531SsamDECL_CMD_FUNC(set80211dtimperiod, val, d) 585170531Ssam{ 586170531Ssam set80211(s, IEEE80211_IOC_DTIM_PERIOD, atoi(val), 0, NULL); 587170531Ssam} 588170531Ssam 589170531Ssamstatic 590170531SsamDECL_CMD_FUNC(set80211bintval, val, d) 591170531Ssam{ 592170531Ssam set80211(s, IEEE80211_IOC_BEACON_INTERVAL, atoi(val), 0, NULL); 593170531Ssam} 594170531Ssam 595170531Ssamstatic void 596170531Ssamset80211macmac(int s, int op, const char *val) 597170531Ssam{ 598170531Ssam char *temp; 599173275Ssam struct sockaddr_dl sdl; 600170531Ssam 601170531Ssam temp = malloc(strlen(val) + 1); 602170531Ssam if (temp == NULL) 603170531Ssam errx(1, "malloc failed"); 604170531Ssam temp[0] = ':'; 605170531Ssam strcpy(temp + 1, val); 606170531Ssam sdl.sdl_len = sizeof(sdl); 607170531Ssam link_addr(temp, &sdl); 608166015Ssam free(temp); 609170531Ssam if (sdl.sdl_alen != IEEE80211_ADDR_LEN) 610170531Ssam errx(1, "malformed link-level address"); 611170531Ssam set80211(s, op, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl)); 612170531Ssam} 613170531Ssam 614170531Ssamstatic 615170531SsamDECL_CMD_FUNC(set80211addmac, val, d) 616170531Ssam{ 617170531Ssam set80211macmac(s, IEEE80211_IOC_ADDMAC, val); 618170531Ssam} 619170531Ssam 620170531Ssamstatic 621170531SsamDECL_CMD_FUNC(set80211delmac, val, d) 622170531Ssam{ 623170531Ssam set80211macmac(s, IEEE80211_IOC_DELMAC, val); 624170531Ssam} 625170531Ssam 626170531Ssamstatic 627173275SsamDECL_CMD_FUNC(set80211kickmac, val, d) 628170531Ssam{ 629165570Ssam char *temp; 630170531Ssam struct sockaddr_dl sdl; 631170531Ssam struct ieee80211req_mlme mlme; 632170531Ssam 633170531Ssam temp = malloc(strlen(val) + 1); 634170531Ssam if (temp == NULL) 635170531Ssam errx(1, "malloc failed"); 636170531Ssam temp[0] = ':'; 637170531Ssam strcpy(temp + 1, val); 638170531Ssam sdl.sdl_len = sizeof(sdl); 639170531Ssam link_addr(temp, &sdl); 640170531Ssam free(temp); 641170531Ssam if (sdl.sdl_alen != IEEE80211_ADDR_LEN) 642170531Ssam errx(1, "malformed link-level address"); 643170531Ssam memset(&mlme, 0, sizeof(mlme)); 644170531Ssam mlme.im_op = IEEE80211_MLME_DEAUTH; 645170531Ssam mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE; 646170531Ssam memcpy(mlme.im_macaddr, LLADDR(&sdl), IEEE80211_ADDR_LEN); 647170531Ssam set80211(s, IEEE80211_IOC_MLME, 0, sizeof(mlme), (u_int8_t *) &mlme); 648170531Ssam} 649173275Ssam 650173275Ssamstatic 651173275SsamDECL_CMD_FUNC(set80211maccmd, val, d) 652173275Ssam{ 653173275Ssam set80211(s, IEEE80211_IOC_MACCMD, d, 0, NULL); 654173275Ssam} 655173275Ssam 656173275Ssamstatic void 657173275Ssamset80211pureg(const char *val, int d, int s, const struct afswtch *rafp) 658173275Ssam{ 659173275Ssam set80211(s, IEEE80211_IOC_PUREG, d, 0, NULL); 660173275Ssam} 661170531Ssam 662170531Ssamstatic 663170531SsamDECL_CMD_FUNC(set80211fragthreshold, val, d) 664138593Ssam{ 665138593Ssam set80211(s, IEEE80211_IOC_FRAGTHRESHOLD, 666138593Ssam isundefarg(val) ? IEEE80211_FRAG_MAX : atoi(val), 0, NULL); 66777218Sphk} 66877218Sphk 669170531Ssamstatic int 670170531Ssamgetmaxrate(uint8_t rates[15], uint8_t nrates) 671170531Ssam{ 672138593Ssam int i, maxrate = -1; 673173275Ssam 674179958Sthompsa for (i = 0; i < nrates; i++) { 675170531Ssam int rate = rates[i] & IEEE80211_RATE_VAL; 676170531Ssam if (rate > maxrate) 677179958Sthompsa maxrate = rate; 678181722Sthompsa } 679181722Sthompsa return maxrate / 2; 680181722Sthompsa} 681181722Sthompsa 682173275Ssamstatic const char * 683170531Ssamgetcaps(int capinfo) 684170531Ssam{ 685170531Ssam static char capstring[32]; 686170531Ssam char *cp = capstring; 687170531Ssam 688170531Ssam if (capinfo & IEEE80211_CAPINFO_ESS) 689170531Ssam *cp++ = 'E'; 690170531Ssam if (capinfo & IEEE80211_CAPINFO_IBSS) 691170531Ssam *cp++ = 'I'; 69277218Sphk if (capinfo & IEEE80211_CAPINFO_CF_POLLABLE) 69377218Sphk *cp++ = 'c'; 694138593Ssam if (capinfo & IEEE80211_CAPINFO_CF_POLLREQ) 695178354Ssam *cp++ = 'C'; 696178354Ssam if (capinfo & IEEE80211_CAPINFO_PRIVACY) 697178354Ssam *cp++ = 'P'; 698178354Ssam if (capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) 699178354Ssam *cp++ = 'S'; 700178354Ssam if (capinfo & IEEE80211_CAPINFO_PBCC) 701178354Ssam *cp++ = 'B'; 702178354Ssam if (capinfo & IEEE80211_CAPINFO_CHNL_AGILITY) 703178354Ssam *cp++ = 'A'; 704178354Ssam if (capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) 705178354Ssam *cp++ = 's'; 706178354Ssam if (capinfo & IEEE80211_CAPINFO_RSN) 707178354Ssam *cp++ = 'R'; 708178354Ssam if (capinfo & IEEE80211_CAPINFO_DSSSOFDM) 709178354Ssam *cp++ = 'D'; 710178354Ssam *cp = '\0'; 711178354Ssam return capstring; 712178354Ssam} 713178354Ssam 714178354Ssamstatic void 71577218Sphkprintie(const char* tag, const uint8_t *ie, size_t ielen, int maxlen) 71677218Sphk{ 71777218Sphk printf("%s", tag); 71877218Sphk if (verbose) { 71991454Sbrooks maxlen -= strlen(tag)+2; 72077218Sphk if (2*ielen > maxlen) 72191454Sbrooks maxlen--; 72277218Sphk printf("<"); 72391454Sbrooks for (; ielen > 0; ie++, ielen--) { 72477218Sphk if (maxlen-- <= 0) 725138593Ssam break; 726138593Ssam printf("%02x", *ie); 727138593Ssam } 728138593Ssam if (ielen != 0) 72977218Sphk printf("-"); 730150708Sru printf(">"); 73177218Sphk } 73277218Sphk} 73377218Sphk 73477218Sphk/* 73577218Sphk * Copy the ssid string contents into buf, truncating to fit. If the 736138593Ssam * ssid is entirely printable then just copy intact. Otherwise convert 73777218Sphk * to hexadecimal. If the result is truncated then replace the last 73877218Sphk * three characters with "...". 73977218Sphk */ 74077218Sphkstatic int 74191454Sbrookscopy_essid(char buf[], size_t bufsize, const u_int8_t *essid, size_t essid_len) 74277218Sphk{ 74391454Sbrooks const u_int8_t *p; 74477218Sphk size_t maxlen; 74591454Sbrooks int i; 74677218Sphk 74791454Sbrooks if (essid_len > bufsize) 74877218Sphk maxlen = bufsize; 74991454Sbrooks else 75077218Sphk maxlen = essid_len; 75177218Sphk /* determine printable or not */ 752150708Sru for (i = 0, p = essid; i < maxlen; i++, p++) { 75377218Sphk if (*p < ' ' || *p > 0x7e) 75477218Sphk break; 75577218Sphk } 75677218Sphk if (i != maxlen) { /* not printable, print as hex */ 75777218Sphk if (bufsize < 3) 758138593Ssam return 0; 75977218Sphk strlcpy(buf, "0x", bufsize); 76077218Sphk bufsize -= 2; 76177218Sphk p = essid; 76277218Sphk for (i = 0; i < maxlen && bufsize >= 2; i++) { 76377218Sphk sprintf(&buf[2+2*i], "%02x", p[i]); 76477218Sphk bufsize -= 2; 76577218Sphk } 76677218Sphk if (i != essid_len) 76777218Sphk memcpy(&buf[2+2*i-3], "...", 3); 76877218Sphk } else { /* printable, truncate as needed */ 769138593Ssam memcpy(buf, essid, maxlen); 77077218Sphk if (maxlen != essid_len) 77177218Sphk memcpy(&buf[maxlen-3], "...", 3); 77277218Sphk } 77377218Sphk return maxlen; 77477218Sphk} 775138593Ssam 77677218Sphk/* unaligned little endian access */ 77777218Sphk#define LE_READ_4(p) \ 77877218Sphk ((u_int32_t) \ 77977218Sphk ((((const u_int8_t *)(p))[0] ) | \ 78091454Sbrooks (((const u_int8_t *)(p))[1] << 8) | \ 78177218Sphk (((const u_int8_t *)(p))[2] << 16) | \ 78291454Sbrooks (((const u_int8_t *)(p))[3] << 24))) 78377218Sphk 78491454Sbrooksstatic int __inline 78577218Sphkiswpaoui(const u_int8_t *frm) 78677218Sphk{ 787150708Sru return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); 78877218Sphk} 78977218Sphk 79077218Sphkstatic int __inline 79177218Sphkiswmeoui(const u_int8_t *frm) 79277218Sphk{ 793138593Ssam return frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI); 79477218Sphk} 79577218Sphk 79677218Sphkstatic int __inline 79777218Sphkisatherosoui(const u_int8_t *frm) 79877218Sphk{ 799139493Ssam return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI); 800139493Ssam} 801139493Ssam 802139493Ssamstatic void 803139493Ssamprinties(const u_int8_t *vp, int ielen, int maxcols) 804139493Ssam{ 805138593Ssam while (ielen > 0) { 80677218Sphk switch (vp[0]) { 80777218Sphk case IEEE80211_ELEMID_VENDOR: 808139493Ssam if (iswpaoui(vp)) 809139493Ssam printie(" WPA", vp, 2+vp[1], maxcols); 810139493Ssam else if (iswmeoui(vp)) 811139493Ssam printie(" WME", vp, 2+vp[1], maxcols); 81277218Sphk else if (isatherosoui(vp)) 81377218Sphk printie(" ATH", vp, 2+vp[1], maxcols); 814138593Ssam else 81577218Sphk printie(" VEN", vp, 2+vp[1], maxcols); 81677218Sphk break; 81777218Sphk case IEEE80211_ELEMID_RSN: 81877218Sphk printie(" RSN", vp, 2+vp[1], maxcols); 819120178Ssam break; 82077218Sphk default: 821178354Ssam printie(" ???", vp, 2+vp[1], maxcols); 82277218Sphk break; 82377218Sphk } 82477218Sphk ielen -= 2+vp[1]; 82577218Sphk vp += 2+vp[1]; 82677218Sphk } 82777218Sphk} 82877218Sphk 82977218Sphkstatic void 83077218Sphklist_scan(int s) 83177218Sphk{ 83277218Sphk uint8_t buf[24*1024]; 83377218Sphk struct ieee80211req ireq; 834148686Sstefanf char ssid[14]; 835148686Sstefanf uint8_t *cp; 83677218Sphk int len; 83777218Sphk 838138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 83977218Sphk (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 84077218Sphk ireq.i_type = IEEE80211_IOC_SCAN_RESULTS; 84177218Sphk ireq.i_data = buf; 84277218Sphk ireq.i_len = sizeof(buf); 843120178Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 84477218Sphk errx(1, "unable to get scan results"); 84577218Sphk len = ireq.i_len; 84677218Sphk if (len < sizeof(struct ieee80211req_scan_result)) 847178354Ssam return; 84877218Sphk 84977218Sphk printf("%-14.14s %-17.17s %4s %4s %-5s %3s %4s\n" 85077218Sphk , "SSID" 85191454Sbrooks , "BSSID" 85277218Sphk , "CHAN" 85377218Sphk , "RATE" 85477218Sphk , "S:N" 855151827Sbrooks , "INT" 856151827Sbrooks , "CAPS" 85777218Sphk ); 85877218Sphk cp = buf; 85977218Sphk do { 86077218Sphk struct ieee80211req_scan_result *sr; 86177218Sphk uint8_t *vp; 86277218Sphk 86377218Sphk sr = (struct ieee80211req_scan_result *) cp; 86477218Sphk vp = (u_int8_t *)(sr+1); 86577218Sphk printf("%-14.*s %s %3d %3dM %2d:%-2d %3d %-4.4s" 86677218Sphk , copy_essid(ssid, sizeof(ssid), vp, sr->isr_ssid_len) 86777218Sphk , ssid 86877218Sphk , ether_ntoa((const struct ether_addr *) sr->isr_bssid) 86991454Sbrooks , ieee80211_mhz2ieee(sr->isr_freq) 87077218Sphk , getmaxrate(sr->isr_rates, sr->isr_nrates) 87177218Sphk , sr->isr_rssi, sr->isr_noise 87277218Sphk , sr->isr_intval 87377218Sphk , getcaps(sr->isr_capinfo) 87477218Sphk ); 87577218Sphk printies(vp + sr->isr_ssid_len, sr->isr_ie_len, 24);; 876138593Ssam printf("\n"); 877127649Ssam cp += sr->isr_len, len -= sr->isr_len; 878127649Ssam } while (len >= sizeof(struct ieee80211req_scan_result)); 879148416Ssam} 880148416Ssam 881127649Ssam#include <net80211/ieee80211_freebsd.h> 882127649Ssam 883138593Ssamstatic void 884127649Ssamscan_and_wait(int s) 885127649Ssam{ 886127649Ssam struct ieee80211req ireq; 887127649Ssam int sroute; 888127649Ssam 889127649Ssam sroute = socket(PF_ROUTE, SOCK_RAW, 0); 890127649Ssam if (sroute < 0) { 891127649Ssam perror("socket(PF_ROUTE,SOCK_RAW)"); 892173275Ssam return; 893127649Ssam } 894127649Ssam (void) memset(&ireq, 0, sizeof(ireq)); 895150708Sru (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 896127649Ssam ireq.i_type = IEEE80211_IOC_SCAN_REQ; 897127649Ssam /* NB: only root can trigger a scan so ignore errors */ 898127649Ssam if (ioctl(s, SIOCS80211, &ireq) >= 0) { 899127649Ssam char buf[2048]; 900127649Ssam struct if_announcemsghdr *ifan; 901138593Ssam struct rt_msghdr *rtm; 902173275Ssam 903173275Ssam do { 904173275Ssam if (read(sroute, buf, sizeof(buf)) < 0) { 905173275Ssam perror("read(PF_ROUTE)"); 906173275Ssam break; 907173275Ssam } 908173275Ssam rtm = (struct rt_msghdr *) buf; 909173275Ssam if (rtm->rtm_version != RTM_VERSION) 910173275Ssam break; 911173275Ssam ifan = (struct if_announcemsghdr *) rtm; 912173275Ssam } while (rtm->rtm_type != RTM_IEEE80211 || 913173275Ssam ifan->ifan_what != RTM_IEEE80211_SCAN); 914173275Ssam } 915173275Ssam close(sroute); 916173275Ssam} 917173275Ssam 918127649Ssamstatic 919127649SsamDECL_CMD_FUNC(set80211scan, val, d) 920173275Ssam{ 921173275Ssam scan_and_wait(s); 922173275Ssam list_scan(s); 923173275Ssam} 924173275Ssam 925173275Ssamstatic void 926173275Ssamlist_stations(int s) 927127649Ssam{ 928127649Ssam uint8_t buf[24*1024]; 929138593Ssam struct ieee80211req ireq; 930138593Ssam uint8_t *cp; 931138593Ssam int len; 932138593Ssam 933138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 934138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 93577218Sphk ireq.i_type = IEEE80211_IOC_STA_INFO; 936138593Ssam ireq.i_data = buf; 93777218Sphk ireq.i_len = sizeof(buf); 938138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 939138593Ssam errx(1, "unable to get station information"); 940138593Ssam len = ireq.i_len; 941138593Ssam if (len < sizeof(struct ieee80211req_sta_info)) 942138593Ssam return; 943138593Ssam 944138593Ssam printf("%-17.17s %4s %4s %4s %4s %4s %6s %6s %4s %3s\n" 945150708Sru , "ADDR" 946138593Ssam , "AID" 947138593Ssam , "CHAN" 948138593Ssam , "RATE" 949138593Ssam , "RSSI" 950138593Ssam , "IDLE" 951138593Ssam , "TXSEQ" 952138593Ssam , "RXSEQ" 953138593Ssam , "CAPS" 954138593Ssam , "ERP" 955138593Ssam ); 956138593Ssam cp = buf; 957138593Ssam do { 958138593Ssam struct ieee80211req_sta_info *si; 959138593Ssam uint8_t *vp; 960138593Ssam 961138593Ssam si = (struct ieee80211req_sta_info *) cp; 962138593Ssam vp = (u_int8_t *)(si+1); 963138593Ssam printf("%s %4u %4d %3dM %4d %4d %6d %6d %-4.4s %3x" 964138593Ssam , ether_ntoa((const struct ether_addr*) si->isi_macaddr) 965138593Ssam , IEEE80211_AID(si->isi_associd) 966138593Ssam , ieee80211_mhz2ieee(si->isi_freq) 967138593Ssam , (si->isi_rates[si->isi_txrate] & IEEE80211_RATE_VAL)/2 968138593Ssam , si->isi_rssi 969170531Ssam , si->isi_inact 970170531Ssam , si->isi_txseqs[0] 971170531Ssam , si->isi_rxseqs[0] 972170531Ssam , getcaps(si->isi_capinfo) 973170531Ssam , si->isi_erp 974170531Ssam ); 975170531Ssam printies(vp, si->isi_ie_len, 24); 976170531Ssam printf("\n"); 977170531Ssam cp += si->isi_len, len -= si->isi_len; 978170531Ssam } while (len >= sizeof(struct ieee80211req_sta_info)); 979170531Ssam} 980170531Ssam 981138593Ssamstatic void 982138593Ssamprint_chaninfo(const struct ieee80211_channel *c) 983138593Ssam{ 984138593Ssam#define IEEE80211_IS_CHAN_PASSIVE(_c) \ 985138593Ssam (((_c)->ic_flags & IEEE80211_CHAN_PASSIVE)) 986138593Ssam char buf[14]; 987138593Ssam 988138593Ssam buf[0] = '\0'; 989138593Ssam if (IEEE80211_IS_CHAN_FHSS(c)) 990138593Ssam strlcat(buf, " FHSS", sizeof(buf)); 991138593Ssam if (IEEE80211_IS_CHAN_A(c)) 992138593Ssam strlcat(buf, " 11a", sizeof(buf)); 993138593Ssam /* XXX 11g schizophrenia */ 994173275Ssam if (IEEE80211_IS_CHAN_G(c) || 995138593Ssam IEEE80211_IS_CHAN_PUREG(c)) 996138593Ssam strlcat(buf, " 11g", sizeof(buf)); 997138593Ssam else if (IEEE80211_IS_CHAN_B(c)) 998138593Ssam strlcat(buf, " 11b", sizeof(buf)); 999138593Ssam if (IEEE80211_IS_CHAN_T(c)) 1000138593Ssam strlcat(buf, " Turbo", sizeof(buf)); 1001138593Ssam printf("Channel %3u : %u%c Mhz%-14.14s", 1002146873Sjhb ieee80211_mhz2ieee(c->ic_freq), c->ic_freq, 1003138593Ssam IEEE80211_IS_CHAN_PASSIVE(c) ? '*' : ' ', buf); 1004138593Ssam#undef IEEE80211_IS_CHAN_PASSIVE 1005138593Ssam} 1006138593Ssam 1007138593Ssamstatic void 1008146873Sjhblist_channels(int s, int allchans) 1009138593Ssam{ 1010138593Ssam struct ieee80211req ireq; 1011146873Sjhb struct ieee80211req_chaninfo chans; 1012138593Ssam struct ieee80211req_chaninfo achans; 1013138593Ssam const struct ieee80211_channel *c; 1014138593Ssam int i, half; 1015138593Ssam 1016138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1017138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1018138593Ssam ireq.i_type = IEEE80211_IOC_CHANINFO; 1019138593Ssam ireq.i_data = &chans; 1020138593Ssam ireq.i_len = sizeof(chans); 1021138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1022173275Ssam errx(1, "unable to get channel information"); 1023173275Ssam if (!allchans) { 1024138593Ssam struct ieee80211req_chanlist active; 1025173275Ssam 1026138593Ssam ireq.i_type = IEEE80211_IOC_CHANLIST; 1027138593Ssam ireq.i_data = &active; 1028138593Ssam ireq.i_len = sizeof(active); 1029170531Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1030138593Ssam errx(1, "unable to get active channel list"); 1031138593Ssam memset(&achans, 0, sizeof(achans)); 1032138593Ssam for (i = 0; i < chans.ic_nchans; i++) { 1033138593Ssam c = &chans.ic_chans[i]; 1034138593Ssam if (isset(active.ic_channels, ieee80211_mhz2ieee(c->ic_freq)) || allchans) 1035138593Ssam achans.ic_chans[achans.ic_nchans++] = *c; 1036138593Ssam } 1037138593Ssam } else 1038138593Ssam achans = chans; 1039138593Ssam half = achans.ic_nchans / 2; 1040138593Ssam if (achans.ic_nchans % 2) 1041155702Ssam half++; 1042138593Ssam for (i = 0; i < achans.ic_nchans / 2; i++) { 1043138593Ssam print_chaninfo(&achans.ic_chans[i]); 1044138593Ssam print_chaninfo(&achans.ic_chans[half+i]); 1045138593Ssam printf("\n"); 1046138593Ssam } 1047138593Ssam if (achans.ic_nchans % 2) { 1048138593Ssam print_chaninfo(&achans.ic_chans[i]); 1049138593Ssam printf("\n"); 1050138593Ssam } 1051138593Ssam} 1052138593Ssam 1053138593Ssamstatic void 1054138593Ssamlist_keys(int s) 1055138593Ssam{ 1056138593Ssam} 1057138593Ssam 1058138593Ssam#define IEEE80211_C_BITS \ 1059138593Ssam"\020\1WEP\2TKIP\3AES\4AES_CCM\6CKIP\11IBSS\12PMGT\13HOSTAP\14AHDEMO" \ 1060138593Ssam"\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE\21MONITOR\22TKIPMIC\30WPA1" \ 1061138593Ssam"\31WPA2\32BURST\33WME" 1062138593Ssam 1063138593Ssamstatic void 1064138593Ssamlist_capabilities(int s) 1065138593Ssam{ 1066138593Ssam struct ieee80211req ireq; 1067138593Ssam u_int32_t caps; 1068138593Ssam 1069138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1070138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1071138593Ssam ireq.i_type = IEEE80211_IOC_DRIVER_CAPS; 1072138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1073138593Ssam errx(1, "unable to get driver capabilities"); 1074138593Ssam caps = (((u_int16_t) ireq.i_val) << 16) | ((u_int16_t) ireq.i_len); 1075138593Ssam printb(name, caps, IEEE80211_C_BITS); 1076138593Ssam putchar('\n'); 1077138593Ssam} 1078138593Ssam 1079138593Ssamstatic void 1080138593Ssamlist_wme(int s) 1081138593Ssam{ 1082138593Ssam static const char *acnames[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" }; 1083138593Ssam struct ieee80211req ireq; 1084138593Ssam int ac; 1085138593Ssam 1086138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1087138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1088138593Ssam ireq.i_len = 0; 1089138593Ssam for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++) { 1090138593Ssamagain: 1091138593Ssam if (ireq.i_len & IEEE80211_WMEPARAM_BSS) 1092138593Ssam printf("\t%s", " "); 1093138593Ssam else 1094138593Ssam printf("\t%s", acnames[ac]); 1095138593Ssam 1096138593Ssam ireq.i_len = (ireq.i_len & IEEE80211_WMEPARAM_BSS) | ac; 1097138593Ssam 1098138593Ssam /* show WME BSS parameters */ 1099138593Ssam ireq.i_type = IEEE80211_IOC_WME_CWMIN; 1100148621Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1101138593Ssam printf(" cwmin %2u", ireq.i_val); 1102148621Ssam ireq.i_type = IEEE80211_IOC_WME_CWMAX; 1103138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1104148621Ssam printf(" cwmax %2u", ireq.i_val); 1105148621Ssam ireq.i_type = IEEE80211_IOC_WME_AIFS; 1106148621Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1107148621Ssam printf(" aifs %2u", ireq.i_val); 1108148621Ssam ireq.i_type = IEEE80211_IOC_WME_TXOPLIMIT; 1109138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1110138593Ssam printf(" txopLimit %3u", ireq.i_val); 1111148621Ssam ireq.i_type = IEEE80211_IOC_WME_ACM; 1112138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1113148621Ssam if (ireq.i_val) 1114138593Ssam printf(" acm"); 1115148621Ssam else if (verbose) 1116148621Ssam printf(" -acm"); 1117148621Ssam } 1118148621Ssam /* !BSS only */ 1119148621Ssam if ((ireq.i_len & IEEE80211_WMEPARAM_BSS) == 0) { 1120138593Ssam ireq.i_type = IEEE80211_IOC_WME_ACKPOLICY; 1121138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1122138593Ssam if (!ireq.i_val) 1123138593Ssam printf(" -ack"); 1124138593Ssam else if (verbose) 1125138593Ssam printf(" ack"); 1126138593Ssam } 1127138593Ssam } 1128138593Ssam printf("\n"); 1129138593Ssam if ((ireq.i_len & IEEE80211_WMEPARAM_BSS) == 0) { 1130138593Ssam ireq.i_len |= IEEE80211_WMEPARAM_BSS; 1131138593Ssam goto again; 1132138593Ssam } else 1133138593Ssam ireq.i_len &= ~IEEE80211_WMEPARAM_BSS; 1134138593Ssam } 1135138593Ssam} 1136138593Ssam 1137138593Ssamstatic void 1138138593Ssamlist_mac(int s) 1139138593Ssam{ 1140138593Ssam struct ieee80211req ireq; 1141138593Ssam struct ieee80211req_maclist *acllist; 1142138593Ssam int i, nacls, policy; 1143138593Ssam char c; 1144138593Ssam 1145138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1146138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); /* XXX ?? */ 1147138593Ssam ireq.i_type = IEEE80211_IOC_MACCMD; 1148138593Ssam ireq.i_val = IEEE80211_MACCMD_POLICY; 1149138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) { 1150138593Ssam if (errno == EINVAL) { 1151138593Ssam printf("No acl policy loaded\n"); 1152138593Ssam return; 1153138593Ssam } 1154138593Ssam err(1, "unable to get mac policy"); 1155138593Ssam } 1156138593Ssam policy = ireq.i_val; 1157138593Ssam 1158138593Ssam ireq.i_val = IEEE80211_MACCMD_LIST; 1159138593Ssam ireq.i_len = 0; 1160138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1161138593Ssam err(1, "unable to get mac acl list size"); 1162138593Ssam if (ireq.i_len == 0) /* NB: no acls */ 1163138593Ssam return; 1164138593Ssam 1165138593Ssam ireq.i_data = malloc(ireq.i_len); 1166138593Ssam if (ireq.i_data == NULL) 1167155702Ssam err(1, "out of memory for acl list"); 1168138593Ssam 1169138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1170138593Ssam err(1, "unable to get mac acl list"); 1171138593Ssam if (policy == IEEE80211_MACCMD_POLICY_OPEN) { 1172138593Ssam if (verbose) 1173138593Ssam printf("policy: open\n"); 1174138593Ssam c = '*'; 1175138593Ssam } else if (policy == IEEE80211_MACCMD_POLICY_ALLOW) { 1176138593Ssam if (verbose) 1177138593Ssam printf("policy: allow\n"); 1178138593Ssam c = '+'; 1179138593Ssam } else if (policy == IEEE80211_MACCMD_POLICY_DENY) { 1180138593Ssam if (verbose) 1181138593Ssam printf("policy: deny\n"); 1182138593Ssam c = '-'; 1183138593Ssam } else { 1184138593Ssam printf("policy: unknown (%u)\n", policy); 1185138593Ssam c = '?'; 1186138593Ssam } 1187138593Ssam nacls = ireq.i_len / sizeof(*acllist); 1188138593Ssam acllist = (struct ieee80211req_maclist *) ireq.i_data; 1189138593Ssam for (i = 0; i < nacls; i++) 1190138593Ssam printf("%c%s\n", c, ether_ntoa( 1191138593Ssam (const struct ether_addr *) acllist[i].ml_macaddr)); 1192138593Ssam} 1193149029Ssam 1194149029Ssamstatic 1195149029SsamDECL_CMD_FUNC(set80211list, arg, d) 1196149029Ssam{ 1197149029Ssam#define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0) 1198149029Ssam 1199155702Ssam if (iseq(arg, "sta")) 1200149029Ssam list_stations(s); 1201149029Ssam else if (iseq(arg, "scan") || iseq(arg, "ap")) 1202149029Ssam list_scan(s); 1203149029Ssam else if (iseq(arg, "chan") || iseq(arg, "freq")) 1204149029Ssam list_channels(s, 1); 1205149029Ssam else if (iseq(arg, "active")) 1206149029Ssam list_channels(s, 0); 1207149029Ssam else if (iseq(arg, "keys")) 1208149029Ssam list_keys(s); 1209149029Ssam else if (iseq(arg, "caps")) 1210149029Ssam list_capabilities(s); 1211149029Ssam else if (iseq(arg, "wme")) 1212149029Ssam list_wme(s); 1213170531Ssam else if (iseq(arg, "mac")) 1214149029Ssam list_mac(s); 1215149029Ssam else 1216149029Ssam errx(1, "Don't know how to list %s for %s", arg, name); 1217138593Ssam#undef iseq 1218138593Ssam} 1219138593Ssam 1220138593Ssamstatic enum ieee80211_opmode 1221138593Ssamget80211opmode(int s) 1222147795Ssam{ 1223147795Ssam struct ifmediareq ifmr; 1224147795Ssam 1225147795Ssam (void) memset(&ifmr, 0, sizeof(ifmr)); 1226147795Ssam (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1227147795Ssam 1228153422Ssam if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { 1229170531Ssam if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) 1230153422Ssam return IEEE80211_M_IBSS; /* XXX ahdemo */ 1231170531Ssam if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) 1232153422Ssam return IEEE80211_M_HOSTAP; 1233153422Ssam if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) 1234148416Ssam return IEEE80211_M_MONITOR; 1235170531Ssam } 1236170531Ssam return IEEE80211_M_STA; 1237170531Ssam} 1238170531Ssam 1239170531Ssamstatic const struct ieee80211_channel * 1240170531Ssamgetchaninfo(int s, int chan) 1241170531Ssam{ 1242170531Ssam struct ieee80211req ireq; 1243170531Ssam static struct ieee80211req_chaninfo chans; 1244170531Ssam static struct ieee80211_channel undef; 1245170531Ssam const struct ieee80211_channel *c; 1246170531Ssam int i, freq; 1247170531Ssam 1248170531Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1249170531Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1250170531Ssam ireq.i_type = IEEE80211_IOC_CHANINFO; 1251170531Ssam ireq.i_data = &chans; 1252178354Ssam ireq.i_len = sizeof(chans); 1253178354Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1254178354Ssam errx(1, "unable to get channel information"); 1255178354Ssam freq = ieee80211_ieee2mhz(chan); 1256178354Ssam for (i = 0; i < chans.ic_nchans; i++) { 1257178354Ssam c = &chans.ic_chans[i]; 1258178354Ssam if (c->ic_freq == freq) 1259178354Ssam return c; 1260178354Ssam } 1261178354Ssam return &undef; 1262178354Ssam} 1263178354Ssam 1264170531Ssam#if 0 1265178354Ssamstatic void 1266178354Ssamprintcipher(int s, struct ieee80211req *ireq, int keylenop) 1267178354Ssam{ 1268178354Ssam switch (ireq->i_val) { 1269178354Ssam case IEEE80211_CIPHER_WEP: 1270178354Ssam ireq->i_type = keylenop; 1271178354Ssam if (ioctl(s, SIOCG80211, ireq) != -1) 1272178354Ssam printf("WEP-%s", 1273178354Ssam ireq->i_len <= 5 ? "40" : 1274178354Ssam ireq->i_len <= 13 ? "104" : "128"); 1275178354Ssam else 1276178354Ssam printf("WEP"); 1277178354Ssam break; 1278178354Ssam case IEEE80211_CIPHER_TKIP: 1279178354Ssam printf("TKIP"); 1280178354Ssam break; 1281178354Ssam case IEEE80211_CIPHER_AES_OCB: 1282178354Ssam printf("AES-OCB"); 1283178354Ssam break; 1284178354Ssam case IEEE80211_CIPHER_AES_CCM: 1285178354Ssam printf("AES-CCM"); 1286178354Ssam break; 1287178354Ssam case IEEE80211_CIPHER_CKIP: 1288178354Ssam printf("CKIP"); 1289178354Ssam break; 1290178354Ssam case IEEE80211_CIPHER_NONE: 1291178354Ssam printf("NONE"); 1292178354Ssam break; 1293178354Ssam default: 1294178354Ssam printf("UNKNOWN (0x%x)", ireq->i_val); 1295178354Ssam break; 1296178354Ssam } 1297178354Ssam} 1298178354Ssam#endif 1299178354Ssam 1300178354Ssam#define MAXCOL 78 1301178354Ssamint col; 1302178354Ssamchar spacer; 1303178354Ssam 1304178354Ssam#define LINE_BREAK() do { \ 1305178354Ssam if (spacer != '\t') { \ 1306178354Ssam printf("\n"); \ 1307178354Ssam spacer = '\t'; \ 1308178354Ssam } \ 1309170531Ssam col = 8; /* 8-col tab */ \ 1310170531Ssam} while (0) 1311178354Ssam#define LINE_CHECK(fmt, ...) do { \ 1312178354Ssam col += sizeof(fmt)-2; \ 1313178354Ssam if (col > MAXCOL) { \ 1314178354Ssam LINE_BREAK(); \ 1315178354Ssam col += sizeof(fmt)-2; \ 1316178354Ssam } \ 1317178354Ssam printf(fmt, __VA_ARGS__); \ 1318178354Ssam spacer = ' '; \ 1319178354Ssam} while (0) 1320178354Ssam 1321178354Ssamstatic void 1322178354Ssamprintkey(const struct ieee80211req_key *ik) 1323178354Ssam{ 1324178354Ssam static const uint8_t zerodata[IEEE80211_KEYBUF_SIZE]; 1325178354Ssam int keylen = ik->ik_keylen; 1326178354Ssam int printcontents; 1327178354Ssam 1328178354Ssam printcontents = printkeys && 1329178354Ssam (memcmp(ik->ik_keydata, zerodata, keylen) != 0 || verbose); 1330178354Ssam if (printcontents) 1331178354Ssam LINE_BREAK(); 1332178354Ssam switch (ik->ik_type) { 1333178354Ssam case IEEE80211_CIPHER_WEP: 1334178354Ssam /* compatibility */ 1335178354Ssam LINE_CHECK("%cwepkey %u:%s", spacer, ik->ik_keyix+1, 1336178354Ssam keylen <= 5 ? "40-bit" : 1337178354Ssam keylen <= 13 ? "104-bit" : "128-bit"); 1338178354Ssam break; 1339178354Ssam case IEEE80211_CIPHER_TKIP: 1340178354Ssam if (keylen > 128/8) 1341178354Ssam keylen -= 128/8; /* ignore MIC for now */ 1342178354Ssam LINE_CHECK("%cTKIP %u:%u-bit", 1343178354Ssam spacer, ik->ik_keyix+1, 8*keylen); 1344178354Ssam break; 1345178354Ssam case IEEE80211_CIPHER_AES_OCB: 1346178354Ssam LINE_CHECK("%cAES-OCB %u:%u-bit", 1347178354Ssam spacer, ik->ik_keyix+1, 8*keylen); 1348178354Ssam break; 1349178354Ssam case IEEE80211_CIPHER_AES_CCM: 1350178354Ssam LINE_CHECK("%cAES-CCM %u:%u-bit", 1351178354Ssam spacer, ik->ik_keyix+1, 8*keylen); 1352178354Ssam break; 1353178354Ssam case IEEE80211_CIPHER_CKIP: 1354178354Ssam LINE_CHECK("%cCKIP %u:%u-bit", 1355178354Ssam spacer, ik->ik_keyix+1, 8*keylen); 1356178354Ssam break; 1357178354Ssam case IEEE80211_CIPHER_NONE: 1358178354Ssam LINE_CHECK("%cNULL %u:%u-bit", 1359178354Ssam spacer, ik->ik_keyix+1, 8*keylen); 1360178354Ssam break; 1361178354Ssam default: 1362178354Ssam LINE_CHECK("%cUNKNOWN (0x%x) %u:%u-bit", spacer, 1363178354Ssam ik->ik_type, ik->ik_keyix+1, 8*keylen); 1364178354Ssam break; 1365178354Ssam } 1366178354Ssam if (printcontents) { 1367178354Ssam int i; 1368178354Ssam 1369178354Ssam printf(" <"); 1370178354Ssam for (i = 0; i < keylen; i++) 1371178354Ssam printf("%02x", ik->ik_keydata[i]); 1372178354Ssam printf(">"); 1373178354Ssam if (ik->ik_type != IEEE80211_CIPHER_WEP && 1374178354Ssam (ik->ik_keyrsc != 0 || verbose)) 1375178354Ssam printf(" rsc %ju", (uintmax_t)ik->ik_keyrsc); 1376178354Ssam if (ik->ik_type != IEEE80211_CIPHER_WEP && 1377178354Ssam (ik->ik_keytsc != 0 || verbose)) 1378178354Ssam printf(" tsc %ju", (uintmax_t)ik->ik_keytsc); 1379178354Ssam if (ik->ik_flags != 0 && verbose) { 1380178354Ssam const char *sep = " "; 1381178354Ssam 1382178354Ssam if (ik->ik_flags & IEEE80211_KEY_XMIT) 1383178354Ssam printf("%stx", sep), sep = "+"; 1384178354Ssam if (ik->ik_flags & IEEE80211_KEY_RECV) 1385178354Ssam printf("%srx", sep), sep = "+"; 1386178354Ssam if (ik->ik_flags & IEEE80211_KEY_DEFAULT) 1387178354Ssam printf("%sdef", sep), sep = "+"; 1388178354Ssam } 1389178354Ssam LINE_BREAK(); 1390178354Ssam } 1391178354Ssam} 1392178354Ssam 1393178354Ssamstatic void 1394178354Ssamieee80211_status(int s) 1395178354Ssam{ 1396178354Ssam static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; 1397178354Ssam enum ieee80211_opmode opmode = get80211opmode(s); 1398178354Ssam int i, num, wpa, wme; 1399178354Ssam struct ieee80211req ireq; 1400178354Ssam u_int8_t data[32]; 1401178354Ssam const struct ieee80211_channel *c; 1402178354Ssam 1403178354Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1404178354Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1405178354Ssam ireq.i_data = &data; 1406178354Ssam 1407178354Ssam wpa = 0; /* unknown/not set */ 1408178354Ssam 1409170531Ssam ireq.i_type = IEEE80211_IOC_SSID; 1410178354Ssam ireq.i_val = -1; 1411170531Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) { 1412178354Ssam /* If we can't get the SSID, this isn't an 802.11 device. */ 1413178354Ssam return; 1414178354Ssam } 1415178354Ssam num = 0; 1416178354Ssam ireq.i_type = IEEE80211_IOC_NUMSSIDS; 1417178354Ssam if (ioctl(s, SIOCG80211, &ireq) >= 0) 1418178354Ssam num = ireq.i_val; 1419178354Ssam printf("\tssid "); 1420178354Ssam if (num > 1) { 1421178354Ssam ireq.i_type = IEEE80211_IOC_SSID; 1422178354Ssam for (ireq.i_val = 0; ireq.i_val < num; ireq.i_val++) { 1423178354Ssam if (ioctl(s, SIOCG80211, &ireq) >= 0 && ireq.i_len > 0) { 1424178354Ssam printf(" %d:", ireq.i_val + 1); 1425178354Ssam print_string(data, ireq.i_len); 1426170531Ssam } 1427170531Ssam } 1428170531Ssam } else 1429178354Ssam print_string(data, ireq.i_len); 1430170531Ssam 1431178354Ssam ireq.i_type = IEEE80211_IOC_CHANNEL; 1432178354Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1433178354Ssam goto end; 1434178354Ssam c = getchaninfo(s, ireq.i_val); 1435178354Ssam if (ireq.i_val != -1) { 1436178354Ssam printf(" channel %d", ireq.i_val); 1437178354Ssam if (verbose) 1438178354Ssam printf(" (%u)", c->ic_freq); 1439178354Ssam } else if (verbose) 1440178354Ssam printf(" channel UNDEF"); 1441170531Ssam 1442170531Ssam ireq.i_type = IEEE80211_IOC_BSSID; 1443170531Ssam ireq.i_len = IEEE80211_ADDR_LEN; 1444178354Ssam if (ioctl(s, SIOCG80211, &ireq) >= 0 && 1445170531Ssam memcmp(ireq.i_data, zerobssid, sizeof(zerobssid)) != 0) 1446178354Ssam printf(" bssid %s", ether_ntoa(ireq.i_data)); 1447178354Ssam 1448178354Ssam ireq.i_type = IEEE80211_IOC_STATIONNAME; 1449178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1450178354Ssam printf("\n\tstationname "); 1451178354Ssam print_string(data, ireq.i_len); 1452178354Ssam } 1453178354Ssam 1454178354Ssam spacer = ' '; /* force first break */ 1455178354Ssam LINE_BREAK(); 1456170531Ssam 1457170531Ssam ireq.i_type = IEEE80211_IOC_AUTHMODE; 1458170531Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1459178354Ssam switch (ireq.i_val) { 1460170531Ssam case IEEE80211_AUTH_NONE: 1461178354Ssam LINE_CHECK("%cauthmode NONE", spacer); 1462178354Ssam break; 1463178354Ssam case IEEE80211_AUTH_OPEN: 1464178354Ssam LINE_CHECK("%cauthmode OPEN", spacer); 1465178354Ssam break; 1466178354Ssam case IEEE80211_AUTH_SHARED: 1467178354Ssam LINE_CHECK("%cauthmode SHARED", spacer); 1468178354Ssam break; 1469178354Ssam case IEEE80211_AUTH_8021X: 1470178354Ssam LINE_CHECK("%cauthmode 802.1x", spacer); 1471170531Ssam break; 1472170531Ssam case IEEE80211_AUTH_WPA: 1473170531Ssam ireq.i_type = IEEE80211_IOC_WPA; 1474178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1475170531Ssam wpa = ireq.i_val; 1476178354Ssam if (!wpa) 1477178354Ssam wpa = 1; /* default to WPA1 */ 1478178354Ssam switch (wpa) { 1479178354Ssam case 2: 1480178354Ssam LINE_CHECK("%cauthmode WPA2/802.11i", 1481178354Ssam spacer); 1482178354Ssam break; 1483178354Ssam case 3: 1484178354Ssam LINE_CHECK("%cauthmode WPA1+WPA2/802.11i", 1485178354Ssam spacer); 1486178354Ssam break; 1487178354Ssam default: 1488178354Ssam LINE_CHECK("%cauthmode WPA", spacer); 1489178354Ssam break; 1490178354Ssam } 1491178354Ssam break; 1492178354Ssam case IEEE80211_AUTH_AUTO: 1493178354Ssam LINE_CHECK("%cauthmode AUTO", spacer); 1494178354Ssam break; 1495178354Ssam default: 1496178354Ssam LINE_CHECK("%cauthmode UNKNOWN (0x%x)", 1497170531Ssam spacer, ireq.i_val); 1498170531Ssam break; 1499170531Ssam } 1500178354Ssam } 1501153354Ssam 1502178354Ssam ireq.i_type = IEEE80211_IOC_WEP; 1503178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1 && 1504178354Ssam ireq.i_val != IEEE80211_WEP_NOSUP) { 1505178354Ssam int firstkey, wepmode; 1506178354Ssam 1507178354Ssam wepmode = ireq.i_val; 1508178354Ssam switch (wepmode) { 1509178354Ssam case IEEE80211_WEP_OFF: 1510178354Ssam LINE_CHECK("%cprivacy OFF", spacer); 1511178354Ssam break; 1512153354Ssam case IEEE80211_WEP_ON: 1513178354Ssam LINE_CHECK("%cprivacy ON", spacer); 1514178354Ssam break; 1515178354Ssam case IEEE80211_WEP_MIXED: 1516178354Ssam LINE_CHECK("%cprivacy MIXED", spacer); 1517153354Ssam break; 1518153354Ssam default: 1519148416Ssam LINE_CHECK("%cprivacy UNKNOWN (0x%x)", 1520148416Ssam spacer, wepmode); 1521148416Ssam break; 1522148416Ssam } 1523148416Ssam 1524148416Ssam /* 1525160687Ssam * If we get here then we've got WEP support so we need 1526160687Ssam * to print WEP status. 1527160687Ssam */ 1528160687Ssam 1529160687Ssam ireq.i_type = IEEE80211_IOC_WEPTXKEY; 1530160687Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) { 1531160687Ssam warn("WEP support, but no tx key!"); 1532170531Ssam goto end; 1533170531Ssam } 1534170531Ssam if (ireq.i_val != -1) 1535170531Ssam LINE_CHECK("%cdeftxkey %d", spacer, ireq.i_val+1); 1536170531Ssam else if (wepmode != IEEE80211_WEP_OFF || verbose) 1537170531Ssam LINE_CHECK("%cdeftxkey UNDEF", spacer); 1538170531Ssam 1539170531Ssam ireq.i_type = IEEE80211_IOC_NUMWEPKEYS; 1540170531Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) { 1541170531Ssam warn("WEP support, but no NUMWEPKEYS support!"); 1542170531Ssam goto end; 1543170531Ssam } 1544173275Ssam num = ireq.i_val; 1545178354Ssam 1546178354Ssam firstkey = 1; 1547178354Ssam for (i = 0; i < num; i++) { 1548178354Ssam struct ieee80211req_key ik; 1549178354Ssam 1550178354Ssam memset(&ik, 0, sizeof(ik)); 1551173275Ssam ik.ik_keyix = i; 1552173275Ssam ireq.i_type = IEEE80211_IOC_WPAKEY; 1553173275Ssam ireq.i_data = &ik; 1554173275Ssam ireq.i_len = sizeof(ik); 1555173275Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) { 1556173275Ssam warn("WEP support, but can get keys!"); 1557173275Ssam goto end; 1558173275Ssam } 1559173275Ssam if (ik.ik_keylen != 0) { 1560173275Ssam if (verbose) 1561173275Ssam LINE_BREAK(); 1562173275Ssam printkey(&ik); 1563173275Ssam firstkey = 0; 1564173275Ssam } 1565173275Ssam } 1566173275Ssam } 1567173275Ssam 1568173275Ssam ireq.i_type = IEEE80211_IOC_POWERSAVE; 1569173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1 && 1570173275Ssam ireq.i_val != IEEE80211_POWERSAVE_NOSUP ) { 1571173275Ssam if (ireq.i_val != IEEE80211_POWERSAVE_OFF || verbose) { 1572173275Ssam switch (ireq.i_val) { 1573173275Ssam case IEEE80211_POWERSAVE_OFF: 1574173275Ssam LINE_CHECK("%cpowersavemode OFF", 1575173275Ssam spacer); 1576173275Ssam break; 1577173275Ssam case IEEE80211_POWERSAVE_CAM: 1578173275Ssam LINE_CHECK("%cpowersavemode CAM", 1579173275Ssam spacer); 1580173275Ssam break; 1581173275Ssam case IEEE80211_POWERSAVE_PSP: 1582173275Ssam LINE_CHECK("%cpowersavemode PSP", 1583173275Ssam spacer); 1584173275Ssam break; 1585173275Ssam case IEEE80211_POWERSAVE_PSP_CAM: 1586173275Ssam LINE_CHECK("%cpowersavemode PSP-CAM", 1587173275Ssam spacer); 1588173275Ssam break; 1589173275Ssam } 1590173275Ssam ireq.i_type = IEEE80211_IOC_POWERSAVESLEEP; 1591173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1592173275Ssam LINE_CHECK("%cpowersavesleep %d", 1593173275Ssam spacer, ireq.i_val); 1594173275Ssam } 1595173275Ssam } 1596173275Ssam 1597173275Ssam ireq.i_type = IEEE80211_IOC_TXPOWMAX; 1598173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1599173275Ssam LINE_CHECK("%ctxpowmax %d", spacer, ireq.i_val); 1600173275Ssam 1601173275Ssam if (verbose) { 1602173275Ssam ireq.i_type = IEEE80211_IOC_TXPOWER; 1603173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1604173275Ssam LINE_CHECK("%ctxpower %d", spacer, ireq.i_val); 1605173275Ssam } 1606183260Ssam 1607173275Ssam ireq.i_type = IEEE80211_IOC_RTSTHRESHOLD; 1608173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1609173275Ssam if (ireq.i_val != IEEE80211_RTS_MAX || verbose) 1610173275Ssam LINE_CHECK("%crtsthreshold %d", spacer, ireq.i_val); 1611173275Ssam } 1612173275Ssam 1613173275Ssam ireq.i_type = IEEE80211_IOC_FRAGTHRESHOLD; 1614173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1615173275Ssam if (ireq.i_val != IEEE80211_FRAG_MAX || verbose) 1616173275Ssam LINE_CHECK("%cfragthreshold %d", spacer, ireq.i_val); 1617173275Ssam } 1618173275Ssam 1619173275Ssam if (IEEE80211_IS_CHAN_G(c) || IEEE80211_IS_CHAN_PUREG(c) || verbose) { 1620173275Ssam ireq.i_type = IEEE80211_IOC_PUREG; 1621173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1622173275Ssam if (ireq.i_val) 1623173275Ssam LINE_CHECK("%cpureg", spacer); 1624173275Ssam else if (verbose) 1625173275Ssam LINE_CHECK("%c-pureg", spacer); 1626173275Ssam } 1627173275Ssam ireq.i_type = IEEE80211_IOC_PROTMODE; 1628173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1629173275Ssam switch (ireq.i_val) { 1630173275Ssam case IEEE80211_PROTMODE_OFF: 1631173275Ssam LINE_CHECK("%cprotmode OFF", spacer); 1632173275Ssam break; 1633173275Ssam case IEEE80211_PROTMODE_CTS: 1634173275Ssam LINE_CHECK("%cprotmode CTS", spacer); 1635173275Ssam break; 1636173275Ssam case IEEE80211_PROTMODE_RTSCTS: 1637173275Ssam LINE_CHECK("%cprotmode RTSCTS", spacer); 1638173275Ssam break; 1639173275Ssam default: 1640173275Ssam LINE_CHECK("%cprotmode UNKNOWN (0x%x)", 1641173275Ssam spacer, ireq.i_val); 1642173275Ssam break; 1643173275Ssam } 1644173275Ssam } 1645173275Ssam } 1646173275Ssam 1647173275Ssam ireq.i_type = IEEE80211_IOC_WME; 1648173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1649173275Ssam wme = ireq.i_val; 1650173275Ssam if (wme) 1651173275Ssam LINE_CHECK("%cwme", spacer); 1652173275Ssam else if (verbose) 1653173275Ssam LINE_CHECK("%c-wme", spacer); 1654173275Ssam } else 1655173275Ssam wme = 0; 1656173275Ssam 1657173275Ssam if (opmode == IEEE80211_M_HOSTAP) { 1658173275Ssam ireq.i_type = IEEE80211_IOC_HIDESSID; 1659173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1660173275Ssam if (ireq.i_val) 1661173275Ssam LINE_CHECK("%cssid HIDE", spacer); 1662173275Ssam else if (verbose) 1663173275Ssam LINE_CHECK("%cssid SHOW", spacer); 1664173275Ssam } 1665173275Ssam 1666173275Ssam ireq.i_type = IEEE80211_IOC_APBRIDGE; 1667173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1668173275Ssam if (!ireq.i_val) 1669173275Ssam LINE_CHECK("%c-apbridge", spacer); 1670173275Ssam else if (verbose) 1671173275Ssam LINE_CHECK("%capbridge", spacer); 1672173275Ssam } 1673173275Ssam 1674173275Ssam ireq.i_type = IEEE80211_IOC_DTIM_PERIOD; 1675173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1676173275Ssam LINE_CHECK("%cdtimperiod %u", spacer, ireq.i_val); 1677173275Ssam } else { 1678173275Ssam ireq.i_type = IEEE80211_IOC_ROAMING; 1679173275Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1680178354Ssam if (ireq.i_val != IEEE80211_ROAMING_AUTO || verbose) { 1681178354Ssam switch (ireq.i_val) { 1682178354Ssam case IEEE80211_ROAMING_DEVICE: 1683178354Ssam LINE_CHECK("%croaming DEVICE", spacer); 1684178354Ssam break; 1685178354Ssam case IEEE80211_ROAMING_AUTO: 1686173275Ssam LINE_CHECK("%croaming AUTO", spacer); 1687173275Ssam break; 1688173275Ssam case IEEE80211_ROAMING_MANUAL: 1689173275Ssam LINE_CHECK("%croaming MANUAL", spacer); 1690173275Ssam break; 1691173275Ssam default: 1692178354Ssam LINE_CHECK("%croaming UNKNOWN (0x%x)", 1693178354Ssam spacer, ireq.i_val); 1694178354Ssam break; 1695178354Ssam } 1696178354Ssam } 1697178354Ssam } 1698178354Ssam } 1699178354Ssam ireq.i_type = IEEE80211_IOC_BEACON_INTERVAL; 1700178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1701178354Ssam if (ireq.i_val) 1702178354Ssam LINE_CHECK("%cbintval %u", spacer, ireq.i_val); 1703183261Ssam else if (verbose) 1704183261Ssam LINE_CHECK("%cbintval %u", spacer, ireq.i_val); 1705183261Ssam } 1706183261Ssam 1707183261Ssam if (wme && verbose) { 1708183261Ssam LINE_BREAK(); 1709183261Ssam list_wme(s); 1710183261Ssam } 1711183261Ssam 1712183261Ssam if (wpa) { 1713183261Ssam ireq.i_type = IEEE80211_IOC_COUNTERMEASURES; 1714183261Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1715178354Ssam if (ireq.i_val) 1716178354Ssam LINE_CHECK("%ccountermeasures", spacer); 1717178354Ssam else if (verbose) 1718178354Ssam LINE_CHECK("%c-countermeasures", spacer); 1719178354Ssam } 1720178354Ssam#if 0 1721178354Ssam /* XXX not interesting with WPA done in user space */ 1722178354Ssam ireq.i_type = IEEE80211_IOC_KEYMGTALGS; 1723178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1724178354Ssam } 1725178354Ssam 1726178354Ssam ireq.i_type = IEEE80211_IOC_MCASTCIPHER; 1727178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1728178354Ssam printf("%cmcastcipher ", spacer); 1729178354Ssam printcipher(s, &ireq, IEEE80211_IOC_MCASTKEYLEN); 1730178354Ssam spacer = ' '; 1731178354Ssam } 1732178354Ssam 1733178354Ssam ireq.i_type = IEEE80211_IOC_UCASTCIPHER; 1734178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1735178354Ssam printf("%cucastcipher ", spacer); 1736178354Ssam printcipher(s, &ireq, IEEE80211_IOC_UCASTKEYLEN); 1737178354Ssam } 1738178354Ssam 1739178354Ssam if (wpa & 2) { 1740178354Ssam ireq.i_type = IEEE80211_IOC_RSNCAPS; 1741178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1742178354Ssam printf("%cRSN caps 0x%x", spacer, ireq.i_val); 1743178354Ssam spacer = ' '; 1744178354Ssam } 1745178354Ssam } 1746178354Ssam 1747178354Ssam ireq.i_type = IEEE80211_IOC_UCASTCIPHERS; 1748178354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1749178354Ssam } 1750178354Ssam#endif 1751178354Ssam LINE_BREAK(); 1752178354Ssam } 1753178354Ssam LINE_BREAK(); 1754178354Ssam 1755178354Ssamend: 1756178354Ssam return; 1757178354Ssam} 1758178354Ssam 1759178354Ssamstatic void 1760178354Ssamset80211(int s, int type, int val, int len, u_int8_t *data) 1761178354Ssam{ 1762178354Ssam struct ieee80211req ireq; 1763178354Ssam 1764178354Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1765178354Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1766178354Ssam ireq.i_type = type; 1767178354Ssam ireq.i_val = val; 1768178354Ssam ireq.i_len = len; 1769178354Ssam ireq.i_data = data; 1770178354Ssam if (ioctl(s, SIOCS80211, &ireq) < 0) 1771178354Ssam err(1, "SIOCS80211"); 1772178354Ssam} 1773186101Ssam 1774186101Ssamstatic const char * 1775186101Ssamget_string(const char *val, const char *sep, u_int8_t *buf, int *lenp) 1776186101Ssam{ 1777186101Ssam int len; 1778178354Ssam int hexstr; 1779186101Ssam u_int8_t *p; 1780186101Ssam 1781178354Ssam len = *lenp; 1782178354Ssam p = buf; 1783178354Ssam hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); 1784178354Ssam if (hexstr) 1785178354Ssam val += 2; 1786186101Ssam for (;;) { 1787186101Ssam if (*val == '\0') 1788178354Ssam break; 1789178354Ssam if (sep != NULL && strchr(sep, *val) != NULL) { 1790178354Ssam val++; 1791178354Ssam break; 1792178354Ssam } 1793178354Ssam if (hexstr) { 1794178354Ssam if (!isxdigit((u_char)val[0])) { 1795178354Ssam warnx("bad hexadecimal digits"); 1796178354Ssam return NULL; 1797178354Ssam } 1798178354Ssam if (!isxdigit((u_char)val[1])) { 1799178354Ssam warnx("odd count hexadecimal digits"); 1800178354Ssam return NULL; 1801178354Ssam } 1802178354Ssam } 1803178354Ssam if (p >= buf + len) { 1804178354Ssam if (hexstr) 1805178354Ssam warnx("hexadecimal digits too long"); 1806178354Ssam else 1807178354Ssam warnx("string too long"); 1808178354Ssam return NULL; 1809178354Ssam } 1810178354Ssam if (hexstr) { 1811178354Ssam#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) 1812178354Ssam *p++ = (tohex((u_char)val[0]) << 4) | 1813178354Ssam tohex((u_char)val[1]); 1814178354Ssam#undef tohex 1815178354Ssam val += 2; 1816178354Ssam } else 1817178354Ssam *p++ = *val++; 1818178354Ssam } 1819178354Ssam len = p - buf; 1820178354Ssam /* The string "-" is treated as the empty string. */ 1821178354Ssam if (!hexstr && len == 1 && buf[0] == '-') 1822178354Ssam len = 0; 1823178354Ssam if (len < *lenp) 1824178354Ssam memset(p, 0, *lenp - len); 1825178354Ssam *lenp = len; 1826178354Ssam return val; 1827178354Ssam} 1828178354Ssam 1829178354Ssamstatic void 1830178354Ssamprint_string(const u_int8_t *buf, int len) 1831178354Ssam{ 1832178354Ssam int i; 1833178354Ssam int hasspc; 1834178354Ssam 1835178354Ssam i = 0; 1836178354Ssam hasspc = 0; 1837178354Ssam for (; i < len; i++) { 1838178354Ssam if (!isprint(buf[i]) && buf[i] != '\0') 1839178354Ssam break; 1840178354Ssam if (isspace(buf[i])) 1841178354Ssam hasspc++; 1842178354Ssam } 1843178354Ssam if (i == len) { 1844178354Ssam if (hasspc || len == 0 || buf[0] == '\0') 1845178354Ssam printf("\"%.*s\"", len, buf); 1846178354Ssam else 1847178354Ssam printf("%.*s", len, buf); 1848178354Ssam } else { 1849178354Ssam printf("0x"); 1850178354Ssam for (i = 0; i < len; i++) 1851178354Ssam printf("%02x", buf[i]); 1852178354Ssam } 1853178354Ssam} 1854178354Ssam 1855178354Ssamstatic struct cmd ieee80211_cmds[] = { 1856178354Ssam DEF_CMD_ARG("ssid", set80211ssid), 1857178354Ssam DEF_CMD_ARG("nwid", set80211ssid), 1858178354Ssam DEF_CMD_ARG("stationname", set80211stationname), 1859178354Ssam DEF_CMD_ARG("station", set80211stationname), /* BSD/OS */ 1860178354Ssam DEF_CMD_ARG("channel", set80211channel), 1861178354Ssam DEF_CMD_ARG("authmode", set80211authmode), 1862178354Ssam DEF_CMD_ARG("powersavemode", set80211powersavemode), 1863178354Ssam DEF_CMD("powersave", 1, set80211powersave), 1864178354Ssam DEF_CMD("-powersave", 0, set80211powersave), 1865178354Ssam DEF_CMD_ARG("powersavesleep", set80211powersavesleep), 1866178354Ssam DEF_CMD_ARG("wepmode", set80211wepmode), 1867178354Ssam DEF_CMD("wep", 1, set80211wep), 1868178354Ssam DEF_CMD("-wep", 0, set80211wep), 1869178354Ssam DEF_CMD_ARG("deftxkey", set80211weptxkey), 1870178354Ssam DEF_CMD_ARG("weptxkey", set80211weptxkey), 1871178354Ssam DEF_CMD_ARG("wepkey", set80211wepkey), 1872178354Ssam DEF_CMD_ARG("nwkey", set80211nwkey), /* NetBSD */ 1873178354Ssam DEF_CMD("-nwkey", 0, set80211wep), /* NetBSD */ 1874178354Ssam DEF_CMD_ARG("rtsthreshold", set80211rtsthreshold), 1875178354Ssam DEF_CMD_ARG("protmode", set80211protmode), 1876178354Ssam DEF_CMD_ARG("txpower", set80211txpower), 1877178354Ssam DEF_CMD_ARG("roaming", set80211roaming), 1878178354Ssam DEF_CMD("wme", 1, set80211wme), 1879178354Ssam DEF_CMD("-wme", 0, set80211wme), 1880178354Ssam DEF_CMD("hidessid", 1, set80211hidessid), 1881178354Ssam DEF_CMD("-hidessid", 0, set80211hidessid), 1882178354Ssam DEF_CMD("apbridge", 1, set80211apbridge), 1883178354Ssam DEF_CMD("-apbridge", 0, set80211apbridge), 1884178354Ssam DEF_CMD_ARG("chanlist", set80211chanlist), 1885178354Ssam DEF_CMD_ARG("bssid", set80211bssid), 1886178354Ssam DEF_CMD_ARG("ap", set80211bssid), 1887178354Ssam DEF_CMD("scan", 0, set80211scan), 1888178354Ssam DEF_CMD_ARG("list", set80211list), 1889178354Ssam DEF_CMD_ARG2("cwmin", set80211cwmin), 1890178354Ssam DEF_CMD_ARG2("cwmax", set80211cwmax), 1891178354Ssam DEF_CMD_ARG2("aifs", set80211aifs), 1892178354Ssam DEF_CMD_ARG2("txoplimit", set80211txoplimit), 1893178354Ssam DEF_CMD_ARG("acm", set80211acm), 1894178354Ssam DEF_CMD_ARG("-acm", set80211noacm), 1895178354Ssam DEF_CMD_ARG("ack", set80211ackpolicy), 1896178354Ssam DEF_CMD_ARG("-ack", set80211noackpolicy), 1897178354Ssam DEF_CMD_ARG2("bss:cwmin", set80211bsscwmin), 1898178354Ssam DEF_CMD_ARG2("bss:cwmax", set80211bsscwmax), 1899178354Ssam DEF_CMD_ARG2("bss:aifs", set80211bssaifs), 1900178354Ssam DEF_CMD_ARG2("bss:txoplimit", set80211bsstxoplimit), 1901178354Ssam DEF_CMD_ARG("dtimperiod", set80211dtimperiod), 1902178354Ssam DEF_CMD_ARG("bintval", set80211bintval), 1903178354Ssam DEF_CMD("mac:open", IEEE80211_MACCMD_POLICY_OPEN, set80211maccmd), 1904178354Ssam DEF_CMD("mac:allow", IEEE80211_MACCMD_POLICY_ALLOW, set80211maccmd), 1905178354Ssam DEF_CMD("mac:deny", IEEE80211_MACCMD_POLICY_DENY, set80211maccmd), 1906178354Ssam DEF_CMD("mac:flush", IEEE80211_MACCMD_FLUSH, set80211maccmd), 1907178354Ssam DEF_CMD("mac:detach", IEEE80211_MACCMD_DETACH, set80211maccmd), 1908178354Ssam DEF_CMD_ARG("mac:add", set80211addmac), 1909178354Ssam DEF_CMD_ARG("mac:del", set80211delmac), 1910178354Ssam DEF_CMD_ARG("mac:kick", set80211kickmac), 1911178354Ssam DEF_CMD("pureg", 1, set80211pureg), 1912178354Ssam DEF_CMD("-pureg", 0, set80211pureg), 1913178354Ssam DEF_CMD_ARG("fragthreshold", set80211fragthreshold), 1914178354Ssam}; 1915178354Ssamstatic struct afswtch af_ieee80211 = { 1916178354Ssam .af_name = "af_ieee80211", 1917178354Ssam .af_af = AF_UNSPEC, 1918178354Ssam .af_other_status = ieee80211_status, 1919178354Ssam}; 1920178354Ssam 1921178354Ssamstatic __constructor void 1922178354Ssamieee80211_ctor(void) 1923178354Ssam{ 1924178354Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 1925178354Ssam int i; 1926178354Ssam 1927178354Ssam for (i = 0; i < N(ieee80211_cmds); i++) 1928178354Ssam cmd_register(&ieee80211_cmds[i]); 1929178354Ssam af_register(&af_ieee80211); 1930178354Ssam#undef N 1931178354Ssam} 1932178354Ssam