ifieee80211.c revision 153422
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 153422 2005-12-14 19:44:39Z 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> 81120178Ssam#include <net80211/ieee80211_crypto.h> 82116957Ssam#include <net80211/ieee80211_ioctl.h> 8377218Sphk 8477218Sphk#include <ctype.h> 8577218Sphk#include <err.h> 8677218Sphk#include <errno.h> 8777218Sphk#include <fcntl.h> 88146873Sjhb#include <inttypes.h> 8977218Sphk#include <stdio.h> 9077218Sphk#include <stdlib.h> 9177218Sphk#include <string.h> 9277218Sphk#include <unistd.h> 9377218Sphk 9477218Sphk#include "ifconfig.h" 9577218Sphk 9677218Sphkstatic void set80211(int s, int type, int val, int len, u_int8_t *data); 9777218Sphkstatic const char *get_string(const char *val, const char *sep, 9877218Sphk u_int8_t *buf, int *lenp); 9977218Sphkstatic void print_string(const u_int8_t *buf, int len); 10077218Sphk 101138593Ssamstatic int 102138593Ssamisanyarg(const char *arg) 103138593Ssam{ 104138593Ssam return (strcmp(arg, "-") == 0 || 105138593Ssam strcasecmp(arg, "any") == 0 || strcasecmp(arg, "off") == 0); 106138593Ssam} 107138593Ssam 108138593Ssamstatic void 10977218Sphkset80211ssid(const char *val, int d, int s, const struct afswtch *rafp) 11077218Sphk{ 11177218Sphk int ssid; 11277218Sphk int len; 113151883Sbrooks u_int8_t data[IEEE80211_NWID_LEN]; 11477218Sphk 11577218Sphk ssid = 0; 116121827Sbrooks len = strlen(val); 11788748Sambrisko if (len > 2 && isdigit(val[0]) && val[1] == ':') { 11888748Sambrisko ssid = atoi(val)-1; 11988748Sambrisko val += 2; 12088748Sambrisko } 12177218Sphk 12277218Sphk bzero(data, sizeof(data)); 12377218Sphk len = sizeof(data); 124151883Sbrooks if (get_string(val, NULL, data, &len) == NULL) 125151883Sbrooks exit(1); 12677218Sphk 12777218Sphk set80211(s, IEEE80211_IOC_SSID, ssid, len, data); 12877218Sphk} 12977218Sphk 130138593Ssamstatic void 13177218Sphkset80211stationname(const char *val, int d, int s, const struct afswtch *rafp) 13277218Sphk{ 13377218Sphk int len; 13477218Sphk u_int8_t data[33]; 13577218Sphk 13677218Sphk bzero(data, sizeof(data)); 13777218Sphk len = sizeof(data); 13877218Sphk get_string(val, NULL, data, &len); 13977218Sphk 14077218Sphk set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data); 14177218Sphk} 14277218Sphk 143138593Ssam/* 144138593Ssam * Convert IEEE channel number to MHz frequency. 145138593Ssam */ 146138593Ssamstatic u_int 147138593Ssamieee80211_ieee2mhz(u_int chan) 148138593Ssam{ 149138593Ssam if (chan == 14) 150138593Ssam return 2484; 151138593Ssam if (chan < 14) /* 0-13 */ 152138593Ssam return 2407 + chan*5; 153138593Ssam if (chan < 27) /* 15-26 */ 154138593Ssam return 2512 + ((chan-15)*20); 155138593Ssam return 5000 + (chan*5); 156138593Ssam} 157138593Ssam 158138593Ssam/* 159138593Ssam * Convert MHz frequency to IEEE channel number. 160138593Ssam */ 161138593Ssamstatic u_int 162138593Ssamieee80211_mhz2ieee(u_int freq) 163138593Ssam{ 164138593Ssam if (freq == 2484) 165138593Ssam return 14; 166138593Ssam if (freq < 2484) 167138593Ssam return (freq - 2407) / 5; 168138593Ssam if (freq < 5000) 169138593Ssam return 15 + ((freq - 2512) / 20); 170138593Ssam return (freq - 5000) / 5; 171138593Ssam} 172138593Ssam 173138593Ssamstatic void 17477218Sphkset80211channel(const char *val, int d, int s, const struct afswtch *rafp) 17577218Sphk{ 176138593Ssam if (!isanyarg(val)) { 177138593Ssam int v = atoi(val); 178138593Ssam if (v > 255) /* treat as frequency */ 179138593Ssam v = ieee80211_mhz2ieee(v); 180138593Ssam set80211(s, IEEE80211_IOC_CHANNEL, v, 0, NULL); 181138593Ssam } else 182116957Ssam set80211(s, IEEE80211_IOC_CHANNEL, IEEE80211_CHAN_ANY, 0, NULL); 18377218Sphk} 18477218Sphk 185138593Ssamstatic void 18677218Sphkset80211authmode(const char *val, int d, int s, const struct afswtch *rafp) 18777218Sphk{ 18877218Sphk int mode; 18977218Sphk 19091454Sbrooks if (strcasecmp(val, "none") == 0) { 19177218Sphk mode = IEEE80211_AUTH_NONE; 19291454Sbrooks } else if (strcasecmp(val, "open") == 0) { 19377218Sphk mode = IEEE80211_AUTH_OPEN; 19491454Sbrooks } else if (strcasecmp(val, "shared") == 0) { 19577218Sphk mode = IEEE80211_AUTH_SHARED; 196138593Ssam } else if (strcasecmp(val, "8021x") == 0) { 197138593Ssam mode = IEEE80211_AUTH_8021X; 198138593Ssam } else if (strcasecmp(val, "wpa") == 0) { 199138593Ssam mode = IEEE80211_AUTH_WPA; 20077218Sphk } else { 201150708Sru errx(1, "unknown authmode"); 20277218Sphk } 20377218Sphk 20477218Sphk set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL); 20577218Sphk} 20677218Sphk 207138593Ssamstatic void 20877218Sphkset80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp) 20977218Sphk{ 21077218Sphk int mode; 21177218Sphk 21291454Sbrooks if (strcasecmp(val, "off") == 0) { 21377218Sphk mode = IEEE80211_POWERSAVE_OFF; 21491454Sbrooks } else if (strcasecmp(val, "on") == 0) { 21577218Sphk mode = IEEE80211_POWERSAVE_ON; 21691454Sbrooks } else if (strcasecmp(val, "cam") == 0) { 21777218Sphk mode = IEEE80211_POWERSAVE_CAM; 21891454Sbrooks } else if (strcasecmp(val, "psp") == 0) { 21977218Sphk mode = IEEE80211_POWERSAVE_PSP; 22091454Sbrooks } else if (strcasecmp(val, "psp-cam") == 0) { 22177218Sphk mode = IEEE80211_POWERSAVE_PSP_CAM; 22277218Sphk } else { 223150708Sru errx(1, "unknown powersavemode"); 22477218Sphk } 22577218Sphk 22677218Sphk set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL); 22777218Sphk} 22877218Sphk 229138593Ssamstatic void 23077218Sphkset80211powersave(const char *val, int d, int s, const struct afswtch *rafp) 23177218Sphk{ 23277218Sphk if (d == 0) 23377218Sphk set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF, 23477218Sphk 0, NULL); 23577218Sphk else 23677218Sphk set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON, 23777218Sphk 0, NULL); 23877218Sphk} 23977218Sphk 240138593Ssamstatic void 24177218Sphkset80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp) 24277218Sphk{ 24377218Sphk set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL); 24477218Sphk} 24577218Sphk 246138593Ssamstatic void 24777218Sphkset80211wepmode(const char *val, int d, int s, const struct afswtch *rafp) 24877218Sphk{ 24977218Sphk int mode; 25077218Sphk 25191454Sbrooks if (strcasecmp(val, "off") == 0) { 25277218Sphk mode = IEEE80211_WEP_OFF; 25391454Sbrooks } else if (strcasecmp(val, "on") == 0) { 25477218Sphk mode = IEEE80211_WEP_ON; 25591454Sbrooks } else if (strcasecmp(val, "mixed") == 0) { 25677218Sphk mode = IEEE80211_WEP_MIXED; 25777218Sphk } else { 258150708Sru errx(1, "unknown wep mode"); 25977218Sphk } 26077218Sphk 26177218Sphk set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL); 26277218Sphk} 26377218Sphk 264138593Ssamstatic void 26577218Sphkset80211wep(const char *val, int d, int s, const struct afswtch *rafp) 26677218Sphk{ 26777218Sphk set80211(s, IEEE80211_IOC_WEP, d, 0, NULL); 26877218Sphk} 26977218Sphk 270139493Ssamstatic int 271139493Ssamisundefarg(const char *arg) 272139493Ssam{ 273139493Ssam return (strcmp(arg, "-") == 0 || strncasecmp(arg, "undef", 5) == 0); 274139493Ssam} 275139493Ssam 276138593Ssamstatic void 27777218Sphkset80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp) 27877218Sphk{ 279139493Ssam if (isundefarg(val)) 280139493Ssam set80211(s, IEEE80211_IOC_WEPTXKEY, IEEE80211_KEYIX_NONE, 0, NULL); 281139493Ssam else 282139493Ssam set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL); 28377218Sphk} 28477218Sphk 285138593Ssamstatic void 28677218Sphkset80211wepkey(const char *val, int d, int s, const struct afswtch *rafp) 28777218Sphk{ 28877218Sphk int key = 0; 28977218Sphk int len; 290120178Ssam u_int8_t data[IEEE80211_KEYBUF_SIZE]; 29177218Sphk 29291454Sbrooks if (isdigit(val[0]) && val[1] == ':') { 29377218Sphk key = atoi(val)-1; 29477218Sphk val += 2; 29577218Sphk } 29677218Sphk 29777218Sphk bzero(data, sizeof(data)); 29877218Sphk len = sizeof(data); 29977218Sphk get_string(val, NULL, data, &len); 30077218Sphk 30177218Sphk set80211(s, IEEE80211_IOC_WEPKEY, key, len, data); 30277218Sphk} 30377218Sphk 30477218Sphk/* 305148686Sstefanf * This function is purely a NetBSD compatability interface. The NetBSD 306148686Sstefanf * interface is too inflexible, but it's there so we'll support it since 30777218Sphk * it's not all that hard. 30877218Sphk */ 309138593Ssamstatic void 31077218Sphkset80211nwkey(const char *val, int d, int s, const struct afswtch *rafp) 31177218Sphk{ 31277218Sphk int txkey; 31377218Sphk int i, len; 314120178Ssam u_int8_t data[IEEE80211_KEYBUF_SIZE]; 31577218Sphk 31677218Sphk set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL); 31777218Sphk 31891454Sbrooks if (isdigit(val[0]) && val[1] == ':') { 31977218Sphk txkey = val[0]-'0'-1; 32077218Sphk val += 2; 32177218Sphk 32291454Sbrooks for (i = 0; i < 4; i++) { 32377218Sphk bzero(data, sizeof(data)); 32477218Sphk len = sizeof(data); 32577218Sphk val = get_string(val, ",", data, &len); 326151827Sbrooks if (val == NULL) 327151827Sbrooks exit(1); 32877218Sphk 32977218Sphk set80211(s, IEEE80211_IOC_WEPKEY, i, len, data); 33077218Sphk } 33177218Sphk } else { 33277218Sphk bzero(data, sizeof(data)); 33377218Sphk len = sizeof(data); 33477218Sphk get_string(val, NULL, data, &len); 33577218Sphk txkey = 0; 33677218Sphk 33777218Sphk set80211(s, IEEE80211_IOC_WEPKEY, 0, len, data); 33877218Sphk 33977218Sphk bzero(data, sizeof(data)); 34091454Sbrooks for (i = 1; i < 4; i++) 34177218Sphk set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data); 34277218Sphk } 34377218Sphk 34477218Sphk set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL); 34577218Sphk} 34677218Sphk 347138593Ssamstatic void 348127649Ssamset80211rtsthreshold(const char *val, int d, int s, const struct afswtch *rafp) 349127649Ssam{ 350148416Ssam set80211(s, IEEE80211_IOC_RTSTHRESHOLD, 351148416Ssam isundefarg(val) ? IEEE80211_RTS_MAX : atoi(val), 0, NULL); 352127649Ssam} 353127649Ssam 354138593Ssamstatic void 355127649Ssamset80211protmode(const char *val, int d, int s, const struct afswtch *rafp) 356127649Ssam{ 357127649Ssam int mode; 358127649Ssam 359127649Ssam if (strcasecmp(val, "off") == 0) { 360127649Ssam mode = IEEE80211_PROTMODE_OFF; 361127649Ssam } else if (strcasecmp(val, "cts") == 0) { 362127649Ssam mode = IEEE80211_PROTMODE_CTS; 363127649Ssam } else if (strcasecmp(val, "rtscts") == 0) { 364127649Ssam mode = IEEE80211_PROTMODE_RTSCTS; 365127649Ssam } else { 366150708Sru errx(1, "unknown protection mode"); 367127649Ssam } 368127649Ssam 369127649Ssam set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL); 370127649Ssam} 371127649Ssam 372138593Ssamstatic void 373127649Ssamset80211txpower(const char *val, int d, int s, const struct afswtch *rafp) 374127649Ssam{ 375127649Ssam set80211(s, IEEE80211_IOC_TXPOWER, atoi(val), 0, NULL); 376127649Ssam} 377127649Ssam 378138593Ssam#define IEEE80211_ROAMING_DEVICE 0 379138593Ssam#define IEEE80211_ROAMING_AUTO 1 380138593Ssam#define IEEE80211_ROAMING_MANUAL 2 381138593Ssam 382138593Ssamstatic void 383138593Ssamset80211roaming(const char *val, int d, int s, const struct afswtch *rafp) 38477218Sphk{ 385138593Ssam int mode; 38677218Sphk 387138593Ssam if (strcasecmp(val, "device") == 0) { 388138593Ssam mode = IEEE80211_ROAMING_DEVICE; 389138593Ssam } else if (strcasecmp(val, "auto") == 0) { 390138593Ssam mode = IEEE80211_ROAMING_AUTO; 391138593Ssam } else if (strcasecmp(val, "manual") == 0) { 392138593Ssam mode = IEEE80211_ROAMING_MANUAL; 393138593Ssam } else { 394150708Sru errx(1, "unknown roaming mode"); 395138593Ssam } 396138593Ssam set80211(s, IEEE80211_IOC_ROAMING, mode, 0, NULL); 397138593Ssam} 398138593Ssam 399138593Ssamstatic void 400138593Ssamset80211wme(const char *val, int d, int s, const struct afswtch *rafp) 401138593Ssam{ 402138593Ssam set80211(s, IEEE80211_IOC_WME, d, 0, NULL); 403138593Ssam} 404138593Ssam 405138593Ssamstatic void 406138593Ssamset80211hidessid(const char *val, int d, int s, const struct afswtch *rafp) 407138593Ssam{ 408138593Ssam set80211(s, IEEE80211_IOC_HIDESSID, d, 0, NULL); 409138593Ssam} 410138593Ssam 411138593Ssamstatic void 412138593Ssamset80211apbridge(const char *val, int d, int s, const struct afswtch *rafp) 413138593Ssam{ 414138593Ssam set80211(s, IEEE80211_IOC_APBRIDGE, d, 0, NULL); 415138593Ssam} 416138593Ssam 417138593Ssamstatic void 418138593Ssamset80211chanlist(const char *val, int d, int s, const struct afswtch *rafp) 419138593Ssam{ 420138593Ssam struct ieee80211req_chanlist chanlist; 421138593Ssam#define MAXCHAN (sizeof(chanlist.ic_channels)*NBBY) 422138593Ssam char *temp, *cp, *tp; 423138593Ssam 424138593Ssam temp = malloc(strlen(val) + 1); 425138593Ssam if (temp == NULL) 426138593Ssam errx(1, "malloc failed"); 427138593Ssam strcpy(temp, val); 428138593Ssam memset(&chanlist, 0, sizeof(chanlist)); 429138593Ssam cp = temp; 430138593Ssam for (;;) { 431138593Ssam int first, last, f; 432138593Ssam 433138593Ssam tp = strchr(cp, ','); 434138593Ssam if (tp != NULL) 435138593Ssam *tp++ = '\0'; 436138593Ssam switch (sscanf(cp, "%u-%u", &first, &last)) { 437138593Ssam case 1: 438138593Ssam if (first > MAXCHAN) 439146873Sjhb errx(-1, "channel %u out of range, max %zu", 440138593Ssam first, MAXCHAN); 441138593Ssam setbit(chanlist.ic_channels, first); 442138593Ssam break; 443138593Ssam case 2: 444138593Ssam if (first > MAXCHAN) 445146873Sjhb errx(-1, "channel %u out of range, max %zu", 446138593Ssam first, MAXCHAN); 447138593Ssam if (last > MAXCHAN) 448146873Sjhb errx(-1, "channel %u out of range, max %zu", 449138593Ssam last, MAXCHAN); 450138593Ssam if (first > last) 451138593Ssam errx(-1, "void channel range, %u > %u", 452138593Ssam first, last); 453138593Ssam for (f = first; f <= last; f++) 454138593Ssam setbit(chanlist.ic_channels, f); 455138593Ssam break; 456138593Ssam } 457138593Ssam if (tp == NULL) 458138593Ssam break; 459138593Ssam while (isspace(*tp)) 460138593Ssam tp++; 461138593Ssam if (!isdigit(*tp)) 462138593Ssam break; 463138593Ssam cp = tp; 464138593Ssam } 465138593Ssam set80211(s, IEEE80211_IOC_CHANLIST, 0, 466138593Ssam sizeof(chanlist), (uint8_t *) &chanlist); 467138593Ssam#undef MAXCHAN 468138593Ssam} 469138593Ssam 470138593Ssamstatic void 471138593Ssamset80211bssid(const char *val, int d, int s, const struct afswtch *rafp) 472138593Ssam{ 473138593Ssam 474138593Ssam if (!isanyarg(val)) { 475138593Ssam char *temp; 476138593Ssam struct sockaddr_dl sdl; 477138593Ssam 478138593Ssam temp = malloc(strlen(val) + 1); 479138593Ssam if (temp == NULL) 480138593Ssam errx(1, "malloc failed"); 481138593Ssam temp[0] = ':'; 482138593Ssam strcpy(temp + 1, val); 483138593Ssam sdl.sdl_len = sizeof(sdl); 484138593Ssam link_addr(temp, &sdl); 485138593Ssam free(temp); 486138593Ssam if (sdl.sdl_alen != IEEE80211_ADDR_LEN) 487138593Ssam errx(1, "malformed link-level address"); 488138593Ssam set80211(s, IEEE80211_IOC_BSSID, 0, 489138593Ssam IEEE80211_ADDR_LEN, LLADDR(&sdl)); 490138593Ssam } else { 491138593Ssam uint8_t zerobssid[IEEE80211_ADDR_LEN]; 492138593Ssam memset(zerobssid, 0, sizeof(zerobssid)); 493138593Ssam set80211(s, IEEE80211_IOC_BSSID, 0, 494138593Ssam IEEE80211_ADDR_LEN, zerobssid); 495138593Ssam } 496138593Ssam} 497138593Ssam 498138593Ssamstatic int 499138593Ssamgetac(const char *ac) 500138593Ssam{ 501138593Ssam if (strcasecmp(ac, "ac_be") == 0 || strcasecmp(ac, "be") == 0) 502138593Ssam return WME_AC_BE; 503138593Ssam if (strcasecmp(ac, "ac_bk") == 0 || strcasecmp(ac, "bk") == 0) 504138593Ssam return WME_AC_BK; 505138593Ssam if (strcasecmp(ac, "ac_vi") == 0 || strcasecmp(ac, "vi") == 0) 506138593Ssam return WME_AC_VI; 507138593Ssam if (strcasecmp(ac, "ac_vo") == 0 || strcasecmp(ac, "vo") == 0) 508138593Ssam return WME_AC_VO; 509138593Ssam errx(1, "unknown wme access class %s", ac); 510138593Ssam} 511138593Ssam 512138593Ssamstatic 513138593SsamDECL_CMD_FUNC2(set80211cwmin, ac, val) 514138593Ssam{ 515138593Ssam set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac), NULL); 516138593Ssam} 517138593Ssam 518138593Ssamstatic 519138593SsamDECL_CMD_FUNC2(set80211cwmax, ac, val) 520138593Ssam{ 521138593Ssam set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac), NULL); 522138593Ssam} 523138593Ssam 524138593Ssamstatic 525138593SsamDECL_CMD_FUNC2(set80211aifs, ac, val) 526138593Ssam{ 527138593Ssam set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac), NULL); 528138593Ssam} 529138593Ssam 530138593Ssamstatic 531138593SsamDECL_CMD_FUNC2(set80211txoplimit, ac, val) 532138593Ssam{ 533138593Ssam set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac), NULL); 534138593Ssam} 535138593Ssam 536138593Ssamstatic 537148621SsamDECL_CMD_FUNC(set80211acm, ac, d) 538138593Ssam{ 539148621Ssam set80211(s, IEEE80211_IOC_WME_ACM, 1, getac(ac), NULL); 540138593Ssam} 541148621Ssamstatic 542148621SsamDECL_CMD_FUNC(set80211noacm, ac, d) 543148621Ssam{ 544148621Ssam set80211(s, IEEE80211_IOC_WME_ACM, 0, getac(ac), NULL); 545148621Ssam} 546138593Ssam 547138593Ssamstatic 548148621SsamDECL_CMD_FUNC(set80211ackpolicy, ac, d) 549138593Ssam{ 550148621Ssam set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 1, getac(ac), NULL); 551138593Ssam} 552148621Ssamstatic 553148621SsamDECL_CMD_FUNC(set80211noackpolicy, ac, d) 554148621Ssam{ 555148621Ssam set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 0, getac(ac), NULL); 556148621Ssam} 557138593Ssam 558138593Ssamstatic 559138593SsamDECL_CMD_FUNC2(set80211bsscwmin, ac, val) 560138593Ssam{ 561138593Ssam set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), 562138593Ssam getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); 563138593Ssam} 564138593Ssam 565138593Ssamstatic 566138593SsamDECL_CMD_FUNC2(set80211bsscwmax, ac, val) 567138593Ssam{ 568138593Ssam set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), 569138593Ssam getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); 570138593Ssam} 571138593Ssam 572138593Ssamstatic 573138593SsamDECL_CMD_FUNC2(set80211bssaifs, ac, val) 574138593Ssam{ 575138593Ssam set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), 576138593Ssam getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); 577138593Ssam} 578138593Ssam 579138593Ssamstatic 580138593SsamDECL_CMD_FUNC2(set80211bsstxoplimit, ac, val) 581138593Ssam{ 582138593Ssam set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), 583138593Ssam getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); 584138593Ssam} 585138593Ssam 586138593Ssamstatic 587138593SsamDECL_CMD_FUNC(set80211dtimperiod, val, d) 588138593Ssam{ 589138593Ssam set80211(s, IEEE80211_IOC_DTIM_PERIOD, atoi(val), 0, NULL); 590138593Ssam} 591138593Ssam 592138593Ssamstatic 593138593SsamDECL_CMD_FUNC(set80211bintval, val, d) 594138593Ssam{ 595138593Ssam set80211(s, IEEE80211_IOC_BEACON_INTERVAL, atoi(val), 0, NULL); 596138593Ssam} 597138593Ssam 598138593Ssamstatic void 599138593Ssamset80211macmac(int s, int op, const char *val) 600138593Ssam{ 601138593Ssam char *temp; 602138593Ssam struct sockaddr_dl sdl; 603138593Ssam 604138593Ssam temp = malloc(strlen(val) + 1); 605138593Ssam if (temp == NULL) 606138593Ssam errx(1, "malloc failed"); 607138593Ssam temp[0] = ':'; 608138593Ssam strcpy(temp + 1, val); 609138593Ssam sdl.sdl_len = sizeof(sdl); 610138593Ssam link_addr(temp, &sdl); 611138593Ssam free(temp); 612138593Ssam if (sdl.sdl_alen != IEEE80211_ADDR_LEN) 613138593Ssam errx(1, "malformed link-level address"); 614138593Ssam set80211(s, op, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl)); 615138593Ssam} 616138593Ssam 617138593Ssamstatic 618138593SsamDECL_CMD_FUNC(set80211addmac, val, d) 619138593Ssam{ 620138593Ssam set80211macmac(s, IEEE80211_IOC_ADDMAC, val); 621138593Ssam} 622138593Ssam 623138593Ssamstatic 624138593SsamDECL_CMD_FUNC(set80211delmac, val, d) 625138593Ssam{ 626138593Ssam set80211macmac(s, IEEE80211_IOC_DELMAC, val); 627138593Ssam} 628138593Ssam 629138593Ssamstatic 630149029SsamDECL_CMD_FUNC(set80211kickmac, val, d) 631149029Ssam{ 632149029Ssam char *temp; 633149029Ssam struct sockaddr_dl sdl; 634149029Ssam struct ieee80211req_mlme mlme; 635149029Ssam 636149029Ssam temp = malloc(strlen(val) + 1); 637149029Ssam if (temp == NULL) 638149029Ssam errx(1, "malloc failed"); 639149029Ssam temp[0] = ':'; 640149029Ssam strcpy(temp + 1, val); 641149029Ssam sdl.sdl_len = sizeof(sdl); 642149029Ssam link_addr(temp, &sdl); 643149029Ssam free(temp); 644149029Ssam if (sdl.sdl_alen != IEEE80211_ADDR_LEN) 645149029Ssam errx(1, "malformed link-level address"); 646149029Ssam memset(&mlme, 0, sizeof(mlme)); 647149029Ssam mlme.im_op = IEEE80211_MLME_DEAUTH; 648149029Ssam mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE; 649149029Ssam memcpy(mlme.im_macaddr, LLADDR(&sdl), IEEE80211_ADDR_LEN); 650149029Ssam set80211(s, IEEE80211_IOC_MLME, 0, sizeof(mlme), (u_int8_t *) &mlme); 651149029Ssam} 652149029Ssam 653149029Ssamstatic 654138593SsamDECL_CMD_FUNC(set80211maccmd, val, d) 655138593Ssam{ 656138593Ssam set80211(s, IEEE80211_IOC_MACCMD, d, 0, NULL); 657138593Ssam} 658138593Ssam 659147795Ssamstatic void 660147795Ssamset80211pureg(const char *val, int d, int s, const struct afswtch *rafp) 661147795Ssam{ 662147795Ssam set80211(s, IEEE80211_IOC_PUREG, d, 0, NULL); 663147795Ssam} 664147795Ssam 665153422Ssamstatic void 666153422Ssamset80211burst(const char *val, int d, int s, const struct afswtch *rafp) 667153422Ssam{ 668153422Ssam set80211(s, IEEE80211_IOC_BURST, d, 0, NULL); 669153422Ssam} 670153422Ssam 671148416Ssamstatic 672153354SsamDECL_CMD_FUNC(set80211mcastrate, val, d) 673153354Ssam{ 674153354Ssam set80211(s, IEEE80211_IOC_MCAST_RATE, (int) 2*atof(val), 0, NULL); 675153354Ssam} 676153354Ssam 677153354Ssamstatic 678148416SsamDECL_CMD_FUNC(set80211fragthreshold, val, d) 679148416Ssam{ 680148416Ssam set80211(s, IEEE80211_IOC_FRAGTHRESHOLD, 681148416Ssam isundefarg(val) ? IEEE80211_FRAG_MAX : atoi(val), 0, NULL); 682148416Ssam} 683148416Ssam 684138593Ssamstatic int 685138593Ssamgetmaxrate(uint8_t rates[15], uint8_t nrates) 686138593Ssam{ 687138593Ssam int i, maxrate = -1; 688138593Ssam 689138593Ssam for (i = 0; i < nrates; i++) { 690138593Ssam int rate = rates[i] & IEEE80211_RATE_VAL; 691138593Ssam if (rate > maxrate) 692138593Ssam maxrate = rate; 693138593Ssam } 694138593Ssam return maxrate / 2; 695138593Ssam} 696138593Ssam 697138593Ssamstatic const char * 698138593Ssamgetcaps(int capinfo) 699138593Ssam{ 700138593Ssam static char capstring[32]; 701138593Ssam char *cp = capstring; 702138593Ssam 703138593Ssam if (capinfo & IEEE80211_CAPINFO_ESS) 704138593Ssam *cp++ = 'E'; 705138593Ssam if (capinfo & IEEE80211_CAPINFO_IBSS) 706138593Ssam *cp++ = 'I'; 707138593Ssam if (capinfo & IEEE80211_CAPINFO_CF_POLLABLE) 708138593Ssam *cp++ = 'c'; 709138593Ssam if (capinfo & IEEE80211_CAPINFO_CF_POLLREQ) 710138593Ssam *cp++ = 'C'; 711138593Ssam if (capinfo & IEEE80211_CAPINFO_PRIVACY) 712138593Ssam *cp++ = 'P'; 713138593Ssam if (capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) 714138593Ssam *cp++ = 'S'; 715138593Ssam if (capinfo & IEEE80211_CAPINFO_PBCC) 716138593Ssam *cp++ = 'B'; 717138593Ssam if (capinfo & IEEE80211_CAPINFO_CHNL_AGILITY) 718138593Ssam *cp++ = 'A'; 719138593Ssam if (capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) 720138593Ssam *cp++ = 's'; 721138593Ssam if (capinfo & IEEE80211_CAPINFO_RSN) 722138593Ssam *cp++ = 'R'; 723138593Ssam if (capinfo & IEEE80211_CAPINFO_DSSSOFDM) 724138593Ssam *cp++ = 'D'; 725138593Ssam *cp = '\0'; 726138593Ssam return capstring; 727138593Ssam} 728138593Ssam 729138593Ssamstatic void 730138593Ssamprintie(const char* tag, const uint8_t *ie, size_t ielen, int maxlen) 731138593Ssam{ 732138593Ssam printf("%s", tag); 733138593Ssam if (verbose) { 734138593Ssam maxlen -= strlen(tag)+2; 735138593Ssam if (2*ielen > maxlen) 736138593Ssam maxlen--; 737138593Ssam printf("<"); 738138593Ssam for (; ielen > 0; ie++, ielen--) { 739138593Ssam if (maxlen-- <= 0) 740138593Ssam break; 741138593Ssam printf("%02x", *ie); 742138593Ssam } 743138593Ssam if (ielen != 0) 744138593Ssam printf("-"); 745138593Ssam printf(">"); 746138593Ssam } 747138593Ssam} 748138593Ssam 749138593Ssam/* 750138593Ssam * Copy the ssid string contents into buf, truncating to fit. If the 751138593Ssam * ssid is entirely printable then just copy intact. Otherwise convert 752138593Ssam * to hexadecimal. If the result is truncated then replace the last 753138593Ssam * three characters with "...". 754138593Ssam */ 755146873Sjhbstatic int 756138593Ssamcopy_essid(char buf[], size_t bufsize, const u_int8_t *essid, size_t essid_len) 757138593Ssam{ 758138593Ssam const u_int8_t *p; 759138593Ssam size_t maxlen; 760138593Ssam int i; 761138593Ssam 762138593Ssam if (essid_len > bufsize) 763138593Ssam maxlen = bufsize; 764138593Ssam else 765138593Ssam maxlen = essid_len; 766138593Ssam /* determine printable or not */ 767138593Ssam for (i = 0, p = essid; i < maxlen; i++, p++) { 768138593Ssam if (*p < ' ' || *p > 0x7e) 769138593Ssam break; 770138593Ssam } 771138593Ssam if (i != maxlen) { /* not printable, print as hex */ 772138593Ssam if (bufsize < 3) 773138593Ssam return 0; 774138593Ssam strlcpy(buf, "0x", bufsize); 775138593Ssam bufsize -= 2; 776138593Ssam p = essid; 777138593Ssam for (i = 0; i < maxlen && bufsize >= 2; i++) { 778147489Savatar sprintf(&buf[2+2*i], "%02x", p[i]); 779138593Ssam bufsize -= 2; 780138593Ssam } 781147489Savatar if (i != essid_len) 782147489Savatar memcpy(&buf[2+2*i-3], "...", 3); 783138593Ssam } else { /* printable, truncate as needed */ 784138593Ssam memcpy(buf, essid, maxlen); 785147489Savatar if (maxlen != essid_len) 786147489Savatar memcpy(&buf[maxlen-3], "...", 3); 787138593Ssam } 788138593Ssam return maxlen; 789138593Ssam} 790138593Ssam 791148686Sstefanf/* unaligned little endian access */ 792138593Ssam#define LE_READ_4(p) \ 793138593Ssam ((u_int32_t) \ 794138593Ssam ((((const u_int8_t *)(p))[0] ) | \ 795138593Ssam (((const u_int8_t *)(p))[1] << 8) | \ 796138593Ssam (((const u_int8_t *)(p))[2] << 16) | \ 797138593Ssam (((const u_int8_t *)(p))[3] << 24))) 798138593Ssam 799138593Ssamstatic int __inline 800138593Ssamiswpaoui(const u_int8_t *frm) 801138593Ssam{ 802138593Ssam return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); 803138593Ssam} 804138593Ssam 805138593Ssamstatic int __inline 806138593Ssamiswmeoui(const u_int8_t *frm) 807138593Ssam{ 808138593Ssam return frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI); 809138593Ssam} 810138593Ssam 811138593Ssamstatic int __inline 812138593Ssamisatherosoui(const u_int8_t *frm) 813138593Ssam{ 814138593Ssam return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI); 815138593Ssam} 816138593Ssam 817138593Ssamstatic void 818138593Ssamprinties(const u_int8_t *vp, int ielen, int maxcols) 819138593Ssam{ 820138593Ssam while (ielen > 0) { 821138593Ssam switch (vp[0]) { 822138593Ssam case IEEE80211_ELEMID_VENDOR: 823138593Ssam if (iswpaoui(vp)) 824138593Ssam printie(" WPA", vp, 2+vp[1], maxcols); 825138593Ssam else if (iswmeoui(vp)) 826138593Ssam printie(" WME", vp, 2+vp[1], maxcols); 827139492Ssam else if (isatherosoui(vp)) 828139492Ssam printie(" ATH", vp, 2+vp[1], maxcols); 829138593Ssam else 830138593Ssam printie(" VEN", vp, 2+vp[1], maxcols); 831138593Ssam break; 832138593Ssam case IEEE80211_ELEMID_RSN: 833138593Ssam printie(" RSN", vp, 2+vp[1], maxcols); 834138593Ssam break; 835138593Ssam default: 836138593Ssam printie(" ???", vp, 2+vp[1], maxcols); 837138593Ssam break; 838138593Ssam } 839138593Ssam ielen -= 2+vp[1]; 840138593Ssam vp += 2+vp[1]; 841138593Ssam } 842138593Ssam} 843138593Ssam 844138593Ssamstatic void 845138593Ssamlist_scan(int s) 846138593Ssam{ 847138593Ssam uint8_t buf[24*1024]; 848138593Ssam struct ieee80211req ireq; 849138593Ssam char ssid[14]; 850138593Ssam uint8_t *cp; 851138593Ssam int len; 852138593Ssam 85377218Sphk (void) memset(&ireq, 0, sizeof(ireq)); 85477218Sphk (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 855138593Ssam ireq.i_type = IEEE80211_IOC_SCAN_RESULTS; 856138593Ssam ireq.i_data = buf; 857138593Ssam ireq.i_len = sizeof(buf); 858138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 859138593Ssam errx(1, "unable to get scan results"); 860138593Ssam len = ireq.i_len; 861138593Ssam if (len < sizeof(struct ieee80211req_scan_result)) 862138593Ssam return; 863138593Ssam 864138593Ssam printf("%-14.14s %-17.17s %4s %4s %-5s %3s %4s\n" 865138593Ssam , "SSID" 866138593Ssam , "BSSID" 867138593Ssam , "CHAN" 868138593Ssam , "RATE" 869138593Ssam , "S:N" 870138593Ssam , "INT" 871138593Ssam , "CAPS" 872138593Ssam ); 873138593Ssam cp = buf; 874138593Ssam do { 875138593Ssam struct ieee80211req_scan_result *sr; 876138593Ssam uint8_t *vp; 877138593Ssam 878138593Ssam sr = (struct ieee80211req_scan_result *) cp; 879138593Ssam vp = (u_int8_t *)(sr+1); 880138593Ssam printf("%-14.*s %s %3d %3dM %2d:%-2d %3d %-4.4s" 881138593Ssam , copy_essid(ssid, sizeof(ssid), vp, sr->isr_ssid_len) 882138593Ssam , ssid 883138593Ssam , ether_ntoa((const struct ether_addr *) sr->isr_bssid) 884138593Ssam , ieee80211_mhz2ieee(sr->isr_freq) 885138593Ssam , getmaxrate(sr->isr_rates, sr->isr_nrates) 886138593Ssam , sr->isr_rssi, sr->isr_noise 887138593Ssam , sr->isr_intval 888138593Ssam , getcaps(sr->isr_capinfo) 889138593Ssam ); 890138593Ssam printies(vp + sr->isr_ssid_len, sr->isr_ie_len, 24);; 891138593Ssam printf("\n"); 892138593Ssam cp += sr->isr_len, len -= sr->isr_len; 893138593Ssam } while (len >= sizeof(struct ieee80211req_scan_result)); 894138593Ssam} 895138593Ssam 896138593Ssam#include <net80211/ieee80211_freebsd.h> 897138593Ssam 898138593Ssamstatic void 899138593Ssamscan_and_wait(int s) 900138593Ssam{ 901138593Ssam struct ieee80211req ireq; 902138593Ssam int sroute; 903138593Ssam 904138593Ssam sroute = socket(PF_ROUTE, SOCK_RAW, 0); 905138593Ssam if (sroute < 0) { 906138593Ssam perror("socket(PF_ROUTE,SOCK_RAW)"); 907138593Ssam return; 908138593Ssam } 909138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 910138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 911138593Ssam ireq.i_type = IEEE80211_IOC_SCAN_REQ; 912138593Ssam /* NB: only root can trigger a scan so ignore errors */ 913138593Ssam if (ioctl(s, SIOCS80211, &ireq) >= 0) { 914138593Ssam char buf[2048]; 915138593Ssam struct if_announcemsghdr *ifan; 916138593Ssam struct rt_msghdr *rtm; 917138593Ssam 918138593Ssam do { 919138593Ssam if (read(sroute, buf, sizeof(buf)) < 0) { 920138593Ssam perror("read(PF_ROUTE)"); 921138593Ssam break; 922138593Ssam } 923138593Ssam rtm = (struct rt_msghdr *) buf; 924138593Ssam if (rtm->rtm_version != RTM_VERSION) 925138593Ssam break; 926138593Ssam ifan = (struct if_announcemsghdr *) rtm; 927138593Ssam } while (rtm->rtm_type != RTM_IEEE80211 || 928138593Ssam ifan->ifan_what != RTM_IEEE80211_SCAN); 929138593Ssam } 930138593Ssam close(sroute); 931138593Ssam} 932138593Ssam 933138593Ssamstatic 934138593SsamDECL_CMD_FUNC(set80211scan, val, d) 935138593Ssam{ 936138593Ssam scan_and_wait(s); 937138593Ssam list_scan(s); 938138593Ssam} 939138593Ssam 940138593Ssamstatic void 941138593Ssamlist_stations(int s) 942138593Ssam{ 943138593Ssam uint8_t buf[24*1024]; 944138593Ssam struct ieee80211req ireq; 945138593Ssam uint8_t *cp; 946138593Ssam int len; 947138593Ssam 948138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 949138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 950138593Ssam ireq.i_type = IEEE80211_IOC_STA_INFO; 951138593Ssam ireq.i_data = buf; 952138593Ssam ireq.i_len = sizeof(buf); 953138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 954138593Ssam errx(1, "unable to get station information"); 955138593Ssam len = ireq.i_len; 956138593Ssam if (len < sizeof(struct ieee80211req_sta_info)) 957138593Ssam return; 958138593Ssam 959138593Ssam printf("%-17.17s %4s %4s %4s %4s %4s %6s %6s %4s %3s\n" 960138593Ssam , "ADDR" 961138593Ssam , "AID" 962138593Ssam , "CHAN" 963138593Ssam , "RATE" 964138593Ssam , "RSSI" 965138593Ssam , "IDLE" 966138593Ssam , "TXSEQ" 967138593Ssam , "RXSEQ" 968138593Ssam , "CAPS" 969138593Ssam , "ERP" 970138593Ssam ); 971138593Ssam cp = buf; 972138593Ssam do { 973138593Ssam struct ieee80211req_sta_info *si; 974138593Ssam uint8_t *vp; 975138593Ssam 976138593Ssam si = (struct ieee80211req_sta_info *) cp; 977138593Ssam vp = (u_int8_t *)(si+1); 978138593Ssam printf("%s %4u %4d %3dM %4d %4d %6d %6d %-4.4s %3x" 979138593Ssam , ether_ntoa((const struct ether_addr*) si->isi_macaddr) 980138593Ssam , IEEE80211_AID(si->isi_associd) 981138593Ssam , ieee80211_mhz2ieee(si->isi_freq) 982138593Ssam , (si->isi_rates[si->isi_txrate] & IEEE80211_RATE_VAL)/2 983138593Ssam , si->isi_rssi 984138593Ssam , si->isi_inact 985138593Ssam , si->isi_txseqs[0] 986138593Ssam , si->isi_rxseqs[0] 987138593Ssam , getcaps(si->isi_capinfo) 988138593Ssam , si->isi_erp 989138593Ssam ); 990138593Ssam printies(vp, si->isi_ie_len, 24); 991138593Ssam printf("\n"); 992138593Ssam cp += si->isi_len, len -= si->isi_len; 993138593Ssam } while (len >= sizeof(struct ieee80211req_sta_info)); 994138593Ssam} 995138593Ssam 996138593Ssamstatic void 997138593Ssamprint_chaninfo(const struct ieee80211_channel *c) 998138593Ssam{ 999138593Ssam#define IEEE80211_IS_CHAN_PASSIVE(_c) \ 1000138593Ssam (((_c)->ic_flags & IEEE80211_CHAN_PASSIVE)) 1001138593Ssam char buf[14]; 1002138593Ssam 1003138593Ssam buf[0] = '\0'; 1004138593Ssam if (IEEE80211_IS_CHAN_FHSS(c)) 1005138593Ssam strlcat(buf, " FHSS", sizeof(buf)); 1006138593Ssam if (IEEE80211_IS_CHAN_A(c)) 1007138593Ssam strlcat(buf, " 11a", sizeof(buf)); 1008138593Ssam /* XXX 11g schizophrenia */ 1009138593Ssam if (IEEE80211_IS_CHAN_G(c) || 1010138593Ssam IEEE80211_IS_CHAN_PUREG(c)) 1011138593Ssam strlcat(buf, " 11g", sizeof(buf)); 1012138593Ssam else if (IEEE80211_IS_CHAN_B(c)) 1013138593Ssam strlcat(buf, " 11b", sizeof(buf)); 1014138593Ssam if (IEEE80211_IS_CHAN_T(c)) 1015138593Ssam strlcat(buf, " Turbo", sizeof(buf)); 1016138593Ssam printf("Channel %3u : %u%c Mhz%-14.14s", 1017138593Ssam ieee80211_mhz2ieee(c->ic_freq), c->ic_freq, 1018138593Ssam IEEE80211_IS_CHAN_PASSIVE(c) ? '*' : ' ', buf); 1019138593Ssam#undef IEEE80211_IS_CHAN_PASSIVE 1020138593Ssam} 1021138593Ssam 1022138593Ssamstatic void 1023138593Ssamlist_channels(int s, int allchans) 1024138593Ssam{ 1025138593Ssam struct ieee80211req ireq; 1026138593Ssam struct ieee80211req_chaninfo chans; 1027138593Ssam struct ieee80211req_chaninfo achans; 1028138593Ssam const struct ieee80211_channel *c; 1029138593Ssam int i, half; 1030138593Ssam 1031138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1032138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1033138593Ssam ireq.i_type = IEEE80211_IOC_CHANINFO; 1034138593Ssam ireq.i_data = &chans; 1035138593Ssam ireq.i_len = sizeof(chans); 1036138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1037138593Ssam errx(1, "unable to get channel information"); 1038138593Ssam if (!allchans) { 1039138593Ssam struct ieee80211req_chanlist active; 1040138593Ssam 1041138593Ssam ireq.i_type = IEEE80211_IOC_CHANLIST; 1042138593Ssam ireq.i_data = &active; 1043138593Ssam ireq.i_len = sizeof(active); 1044138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1045138593Ssam errx(1, "unable to get active channel list"); 1046138593Ssam memset(&achans, 0, sizeof(achans)); 1047138593Ssam for (i = 0; i < chans.ic_nchans; i++) { 1048138593Ssam c = &chans.ic_chans[i]; 1049138593Ssam if (isset(active.ic_channels, ieee80211_mhz2ieee(c->ic_freq)) || allchans) 1050138593Ssam achans.ic_chans[achans.ic_nchans++] = *c; 1051138593Ssam } 1052138593Ssam } else 1053138593Ssam achans = chans; 1054138593Ssam half = achans.ic_nchans / 2; 1055138593Ssam if (achans.ic_nchans % 2) 1056138593Ssam half++; 1057138593Ssam for (i = 0; i < achans.ic_nchans / 2; i++) { 1058138593Ssam print_chaninfo(&achans.ic_chans[i]); 1059138593Ssam print_chaninfo(&achans.ic_chans[half+i]); 1060138593Ssam printf("\n"); 1061138593Ssam } 1062138593Ssam if (achans.ic_nchans % 2) { 1063138593Ssam print_chaninfo(&achans.ic_chans[i]); 1064138593Ssam printf("\n"); 1065138593Ssam } 1066138593Ssam} 1067138593Ssam 1068138593Ssamstatic void 1069138593Ssamlist_keys(int s) 1070138593Ssam{ 1071138593Ssam} 1072138593Ssam 1073138593Ssam#define IEEE80211_C_BITS \ 1074138593Ssam"\020\1WEP\2TKIP\3AES\4AES_CCM\6CKIP\11IBSS\12PMGT\13HOSTAP\14AHDEMO" \ 1075138593Ssam"\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE\21MONITOR\22TKIPMIC\30WPA1" \ 1076138593Ssam"\31WPA2\32BURST\33WME" 1077138593Ssam 1078138593Ssamstatic void 1079138593Ssamlist_capabilities(int s) 1080138593Ssam{ 1081138593Ssam struct ieee80211req ireq; 1082138593Ssam u_int32_t caps; 1083138593Ssam 1084138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1085138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1086138593Ssam ireq.i_type = IEEE80211_IOC_DRIVER_CAPS; 1087138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1088138593Ssam errx(1, "unable to get driver capabilities"); 1089138593Ssam caps = (((u_int16_t) ireq.i_val) << 16) | ((u_int16_t) ireq.i_len); 1090138593Ssam printb(name, caps, IEEE80211_C_BITS); 1091138593Ssam putchar('\n'); 1092138593Ssam} 1093138593Ssam 1094138593Ssamstatic void 1095138593Ssamlist_wme(int s) 1096138593Ssam{ 1097138593Ssam static const char *acnames[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" }; 1098138593Ssam struct ieee80211req ireq; 1099138593Ssam int ac; 1100138593Ssam 1101138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1102138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1103138593Ssam ireq.i_len = 0; 1104138593Ssam for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++) { 1105138593Ssamagain: 1106138593Ssam if (ireq.i_len & IEEE80211_WMEPARAM_BSS) 1107138593Ssam printf("\t%s", " "); 1108138593Ssam else 1109138593Ssam printf("\t%s", acnames[ac]); 1110138593Ssam 1111138593Ssam ireq.i_len = (ireq.i_len & IEEE80211_WMEPARAM_BSS) | ac; 1112138593Ssam 1113138593Ssam /* show WME BSS parameters */ 1114138593Ssam ireq.i_type = IEEE80211_IOC_WME_CWMIN; 1115138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1116138593Ssam printf(" cwmin %2u", ireq.i_val); 1117138593Ssam ireq.i_type = IEEE80211_IOC_WME_CWMAX; 1118138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1119138593Ssam printf(" cwmax %2u", ireq.i_val); 1120138593Ssam ireq.i_type = IEEE80211_IOC_WME_AIFS; 1121138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1122138593Ssam printf(" aifs %2u", ireq.i_val); 1123138593Ssam ireq.i_type = IEEE80211_IOC_WME_TXOPLIMIT; 1124138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1125138593Ssam printf(" txopLimit %3u", ireq.i_val); 1126138593Ssam ireq.i_type = IEEE80211_IOC_WME_ACM; 1127138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1128138593Ssam if (ireq.i_val) 1129138593Ssam printf(" acm"); 1130138593Ssam else if (verbose) 1131138593Ssam printf(" -acm"); 1132138593Ssam } 1133138593Ssam /* !BSS only */ 1134138593Ssam if ((ireq.i_len & IEEE80211_WMEPARAM_BSS) == 0) { 1135138593Ssam ireq.i_type = IEEE80211_IOC_WME_ACKPOLICY; 1136138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1137138593Ssam if (!ireq.i_val) 1138138593Ssam printf(" -ack"); 1139138593Ssam else if (verbose) 1140138593Ssam printf(" ack"); 1141138593Ssam } 1142138593Ssam } 1143138593Ssam printf("\n"); 1144138593Ssam if ((ireq.i_len & IEEE80211_WMEPARAM_BSS) == 0) { 1145138593Ssam ireq.i_len |= IEEE80211_WMEPARAM_BSS; 1146138593Ssam goto again; 1147138593Ssam } else 1148138593Ssam ireq.i_len &= ~IEEE80211_WMEPARAM_BSS; 1149138593Ssam } 1150138593Ssam} 1151138593Ssam 1152149029Ssamstatic void 1153149029Ssamlist_mac(int s) 1154149029Ssam{ 1155149029Ssam struct ieee80211req ireq; 1156149029Ssam struct ieee80211req_maclist *acllist; 1157149029Ssam int i, nacls, policy; 1158149029Ssam char c; 1159149029Ssam 1160149029Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1161149029Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); /* XXX ?? */ 1162149029Ssam ireq.i_type = IEEE80211_IOC_MACCMD; 1163149029Ssam ireq.i_val = IEEE80211_MACCMD_POLICY; 1164149029Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) { 1165149029Ssam if (errno == EINVAL) { 1166149029Ssam printf("No acl policy loaded\n"); 1167149029Ssam return; 1168149029Ssam } 1169149029Ssam err(1, "unable to get mac policy"); 1170149029Ssam } 1171149029Ssam policy = ireq.i_val; 1172149029Ssam 1173149029Ssam ireq.i_val = IEEE80211_MACCMD_LIST; 1174149029Ssam ireq.i_len = 0; 1175149029Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1176149029Ssam err(1, "unable to get mac acl list size"); 1177149029Ssam if (ireq.i_len == 0) /* NB: no acls */ 1178149029Ssam return; 1179149029Ssam 1180149029Ssam ireq.i_data = malloc(ireq.i_len); 1181149029Ssam if (ireq.i_data == NULL) 1182149029Ssam err(1, "out of memory for acl list"); 1183149029Ssam 1184149029Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1185149029Ssam err(1, "unable to get mac acl list"); 1186149029Ssam if (policy == IEEE80211_MACCMD_POLICY_OPEN) { 1187149029Ssam if (verbose) 1188149029Ssam printf("policy: open\n"); 1189149029Ssam c = '*'; 1190149029Ssam } else if (policy == IEEE80211_MACCMD_POLICY_ALLOW) { 1191149029Ssam if (verbose) 1192149029Ssam printf("policy: allow\n"); 1193149029Ssam c = '+'; 1194149029Ssam } else if (policy == IEEE80211_MACCMD_POLICY_DENY) { 1195149029Ssam if (verbose) 1196149029Ssam printf("policy: deny\n"); 1197149029Ssam c = '-'; 1198149029Ssam } else { 1199149029Ssam printf("policy: unknown (%u)\n", policy); 1200149029Ssam c = '?'; 1201149029Ssam } 1202149029Ssam nacls = ireq.i_len / sizeof(*acllist); 1203149029Ssam acllist = (struct ieee80211req_maclist *) ireq.i_data; 1204149029Ssam for (i = 0; i < nacls; i++) 1205149029Ssam printf("%c%s\n", c, ether_ntoa( 1206149029Ssam (const struct ether_addr *) acllist[i].ml_macaddr)); 1207149029Ssam} 1208149029Ssam 1209138593Ssamstatic 1210138593SsamDECL_CMD_FUNC(set80211list, arg, d) 1211138593Ssam{ 1212138593Ssam#define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0) 1213138593Ssam 1214138593Ssam if (iseq(arg, "sta")) 1215138593Ssam list_stations(s); 1216138593Ssam else if (iseq(arg, "scan") || iseq(arg, "ap")) 1217138593Ssam list_scan(s); 1218138593Ssam else if (iseq(arg, "chan") || iseq(arg, "freq")) 1219138593Ssam list_channels(s, 1); 1220138593Ssam else if (iseq(arg, "active")) 1221138593Ssam list_channels(s, 0); 1222138593Ssam else if (iseq(arg, "keys")) 1223138593Ssam list_keys(s); 1224138593Ssam else if (iseq(arg, "caps")) 1225138593Ssam list_capabilities(s); 1226138593Ssam else if (iseq(arg, "wme")) 1227138593Ssam list_wme(s); 1228149029Ssam else if (iseq(arg, "mac")) 1229149029Ssam list_mac(s); 1230138593Ssam else 1231138593Ssam errx(1, "Don't know how to list %s for %s", arg, name); 1232138593Ssam#undef iseq 1233138593Ssam} 1234138593Ssam 1235138593Ssamstatic enum ieee80211_opmode 1236138593Ssamget80211opmode(int s) 1237138593Ssam{ 1238138593Ssam struct ifmediareq ifmr; 1239138593Ssam 1240138593Ssam (void) memset(&ifmr, 0, sizeof(ifmr)); 1241138593Ssam (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1242138593Ssam 1243138593Ssam if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { 1244138593Ssam if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) 1245138593Ssam return IEEE80211_M_IBSS; /* XXX ahdemo */ 1246138593Ssam if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) 1247138593Ssam return IEEE80211_M_HOSTAP; 1248138593Ssam if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) 1249138593Ssam return IEEE80211_M_MONITOR; 1250138593Ssam } 1251138593Ssam return IEEE80211_M_STA; 1252138593Ssam} 1253138593Ssam 1254138593Ssamstatic const struct ieee80211_channel * 1255138593Ssamgetchaninfo(int s, int chan) 1256138593Ssam{ 1257138593Ssam struct ieee80211req ireq; 1258138593Ssam static struct ieee80211req_chaninfo chans; 1259138593Ssam static struct ieee80211_channel undef; 1260138593Ssam const struct ieee80211_channel *c; 1261138593Ssam int i, freq; 1262138593Ssam 1263138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1264138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 1265138593Ssam ireq.i_type = IEEE80211_IOC_CHANINFO; 1266138593Ssam ireq.i_data = &chans; 1267138593Ssam ireq.i_len = sizeof(chans); 1268138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1269138593Ssam errx(1, "unable to get channel information"); 1270138593Ssam freq = ieee80211_ieee2mhz(chan); 1271138593Ssam for (i = 0; i < chans.ic_nchans; i++) { 1272138593Ssam c = &chans.ic_chans[i]; 1273138593Ssam if (c->ic_freq == freq) 1274138593Ssam return c; 1275138593Ssam } 1276138593Ssam return &undef; 1277138593Ssam} 1278138593Ssam 1279138593Ssam#if 0 1280138593Ssamstatic void 1281138593Ssamprintcipher(int s, struct ieee80211req *ireq, int keylenop) 1282138593Ssam{ 1283138593Ssam switch (ireq->i_val) { 1284138593Ssam case IEEE80211_CIPHER_WEP: 1285138593Ssam ireq->i_type = keylenop; 1286138593Ssam if (ioctl(s, SIOCG80211, ireq) != -1) 1287138593Ssam printf("WEP-%s", 1288138593Ssam ireq->i_len <= 5 ? "40" : 1289138593Ssam ireq->i_len <= 13 ? "104" : "128"); 1290138593Ssam else 1291138593Ssam printf("WEP"); 1292138593Ssam break; 1293138593Ssam case IEEE80211_CIPHER_TKIP: 1294138593Ssam printf("TKIP"); 1295138593Ssam break; 1296138593Ssam case IEEE80211_CIPHER_AES_OCB: 1297138593Ssam printf("AES-OCB"); 1298138593Ssam break; 1299138593Ssam case IEEE80211_CIPHER_AES_CCM: 1300138593Ssam printf("AES-CCM"); 1301138593Ssam break; 1302138593Ssam case IEEE80211_CIPHER_CKIP: 1303138593Ssam printf("CKIP"); 1304138593Ssam break; 1305138593Ssam case IEEE80211_CIPHER_NONE: 1306138593Ssam printf("NONE"); 1307138593Ssam break; 1308138593Ssam default: 1309138593Ssam printf("UNKNOWN (0x%x)", ireq->i_val); 1310138593Ssam break; 1311138593Ssam } 1312138593Ssam} 1313138593Ssam#endif 1314138593Ssam 1315138593Ssam#define MAXCOL 78 1316138593Ssamint col; 1317138593Ssamchar spacer; 1318138593Ssam 1319138593Ssam#define LINE_BREAK() do { \ 1320138593Ssam if (spacer != '\t') { \ 1321138593Ssam printf("\n"); \ 1322138593Ssam spacer = '\t'; \ 1323138593Ssam } \ 1324138593Ssam col = 8; /* 8-col tab */ \ 1325138593Ssam} while (0) 1326138593Ssam#define LINE_CHECK(fmt, ...) do { \ 1327138593Ssam col += sizeof(fmt)-2; \ 1328138593Ssam if (col > MAXCOL) { \ 1329138593Ssam LINE_BREAK(); \ 1330138593Ssam col += sizeof(fmt)-2; \ 1331138593Ssam } \ 1332138593Ssam printf(fmt, __VA_ARGS__); \ 1333138593Ssam spacer = ' '; \ 1334138593Ssam} while (0) 1335138593Ssam 1336138593Ssamstatic void 1337138593Ssamprintkey(const struct ieee80211req_key *ik) 1338138593Ssam{ 1339138593Ssam static const uint8_t zerodata[IEEE80211_KEYBUF_SIZE]; 1340138593Ssam int keylen = ik->ik_keylen; 1341138593Ssam int printcontents; 1342138593Ssam 1343148001Srwatson printcontents = printkeys && 1344138593Ssam (memcmp(ik->ik_keydata, zerodata, keylen) != 0 || verbose); 1345138593Ssam if (printcontents) 1346138593Ssam LINE_BREAK(); 1347138593Ssam switch (ik->ik_type) { 1348138593Ssam case IEEE80211_CIPHER_WEP: 1349138593Ssam /* compatibility */ 1350138593Ssam LINE_CHECK("%cwepkey %u:%s", spacer, ik->ik_keyix+1, 1351138593Ssam keylen <= 5 ? "40-bit" : 1352138593Ssam keylen <= 13 ? "104-bit" : "128-bit"); 1353138593Ssam break; 1354138593Ssam case IEEE80211_CIPHER_TKIP: 1355138593Ssam if (keylen > 128/8) 1356138593Ssam keylen -= 128/8; /* ignore MIC for now */ 1357138593Ssam LINE_CHECK("%cTKIP %u:%u-bit", 1358138593Ssam spacer, ik->ik_keyix+1, 8*keylen); 1359138593Ssam break; 1360138593Ssam case IEEE80211_CIPHER_AES_OCB: 1361138593Ssam LINE_CHECK("%cAES-OCB %u:%u-bit", 1362138593Ssam spacer, ik->ik_keyix+1, 8*keylen); 1363138593Ssam break; 1364138593Ssam case IEEE80211_CIPHER_AES_CCM: 1365138593Ssam LINE_CHECK("%cAES-CCM %u:%u-bit", 1366138593Ssam spacer, ik->ik_keyix+1, 8*keylen); 1367138593Ssam break; 1368138593Ssam case IEEE80211_CIPHER_CKIP: 1369138593Ssam LINE_CHECK("%cCKIP %u:%u-bit", 1370138593Ssam spacer, ik->ik_keyix+1, 8*keylen); 1371138593Ssam break; 1372138593Ssam case IEEE80211_CIPHER_NONE: 1373138593Ssam LINE_CHECK("%cNULL %u:%u-bit", 1374138593Ssam spacer, ik->ik_keyix+1, 8*keylen); 1375138593Ssam break; 1376138593Ssam default: 1377138593Ssam LINE_CHECK("%cUNKNOWN (0x%x) %u:%u-bit", spacer, 1378138593Ssam ik->ik_type, ik->ik_keyix+1, 8*keylen); 1379138593Ssam break; 1380138593Ssam } 1381138593Ssam if (printcontents) { 1382138593Ssam int i; 1383138593Ssam 1384138593Ssam printf(" <"); 1385138593Ssam for (i = 0; i < keylen; i++) 1386138593Ssam printf("%02x", ik->ik_keydata[i]); 1387138593Ssam printf(">"); 1388138593Ssam if (ik->ik_type != IEEE80211_CIPHER_WEP && 1389138593Ssam (ik->ik_keyrsc != 0 || verbose)) 1390146873Sjhb printf(" rsc %ju", (uintmax_t)ik->ik_keyrsc); 1391138593Ssam if (ik->ik_type != IEEE80211_CIPHER_WEP && 1392138593Ssam (ik->ik_keytsc != 0 || verbose)) 1393146873Sjhb printf(" tsc %ju", (uintmax_t)ik->ik_keytsc); 1394138593Ssam if (ik->ik_flags != 0 && verbose) { 1395138593Ssam const char *sep = " "; 1396138593Ssam 1397138593Ssam if (ik->ik_flags & IEEE80211_KEY_XMIT) 1398138593Ssam printf("%stx", sep), sep = "+"; 1399138593Ssam if (ik->ik_flags & IEEE80211_KEY_RECV) 1400138593Ssam printf("%srx", sep), sep = "+"; 1401138593Ssam if (ik->ik_flags & IEEE80211_KEY_DEFAULT) 1402138593Ssam printf("%sdef", sep), sep = "+"; 1403138593Ssam } 1404138593Ssam LINE_BREAK(); 1405138593Ssam } 1406138593Ssam} 1407138593Ssam 1408138593Ssamstatic void 1409139494Ssamieee80211_status(int s) 1410138593Ssam{ 1411138593Ssam static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; 1412138593Ssam enum ieee80211_opmode opmode = get80211opmode(s); 1413138593Ssam int i, num, wpa, wme; 1414138593Ssam struct ieee80211req ireq; 1415138593Ssam u_int8_t data[32]; 1416138593Ssam const struct ieee80211_channel *c; 1417138593Ssam 1418138593Ssam (void) memset(&ireq, 0, sizeof(ireq)); 1419138593Ssam (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 142077218Sphk ireq.i_data = &data; 142177218Sphk 1422138593Ssam wpa = 0; /* unknown/not set */ 1423138593Ssam 142477218Sphk ireq.i_type = IEEE80211_IOC_SSID; 142577218Sphk ireq.i_val = -1; 142677218Sphk if (ioctl(s, SIOCG80211, &ireq) < 0) { 1427148686Sstefanf /* If we can't get the SSID, this isn't an 802.11 device. */ 142877218Sphk return; 142977218Sphk } 143088748Sambrisko num = 0; 143188748Sambrisko ireq.i_type = IEEE80211_IOC_NUMSSIDS; 1432138593Ssam if (ioctl(s, SIOCG80211, &ireq) >= 0) 143388748Sambrisko num = ireq.i_val; 1434138593Ssam printf("\tssid "); 1435138593Ssam if (num > 1) { 1436138593Ssam ireq.i_type = IEEE80211_IOC_SSID; 1437138593Ssam for (ireq.i_val = 0; ireq.i_val < num; ireq.i_val++) { 1438138593Ssam if (ioctl(s, SIOCG80211, &ireq) >= 0 && ireq.i_len > 0) { 1439138593Ssam printf(" %d:", ireq.i_val + 1); 1440138593Ssam print_string(data, ireq.i_len); 1441138593Ssam } 144288748Sambrisko } 1443138593Ssam } else 1444138593Ssam print_string(data, ireq.i_len); 144577218Sphk 1446138593Ssam ireq.i_type = IEEE80211_IOC_CHANNEL; 1447138593Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 1448138593Ssam goto end; 1449138593Ssam c = getchaninfo(s, ireq.i_val); 1450138593Ssam if (ireq.i_val != -1) { 1451138593Ssam printf(" channel %d", ireq.i_val); 1452138593Ssam if (verbose) 1453138593Ssam printf(" (%u)", c->ic_freq); 1454138593Ssam } else if (verbose) 1455138593Ssam printf(" channel UNDEF"); 1456138593Ssam 1457138593Ssam ireq.i_type = IEEE80211_IOC_BSSID; 1458138593Ssam ireq.i_len = IEEE80211_ADDR_LEN; 1459138593Ssam if (ioctl(s, SIOCG80211, &ireq) >= 0 && 1460153405Ssam (memcmp(ireq.i_data, zerobssid, sizeof(zerobssid)) != 0 || verbose)) 1461138593Ssam printf(" bssid %s", ether_ntoa(ireq.i_data)); 1462138593Ssam 146377218Sphk ireq.i_type = IEEE80211_IOC_STATIONNAME; 146477218Sphk if (ioctl(s, SIOCG80211, &ireq) != -1) { 1465138593Ssam printf("\n\tstationname "); 146677218Sphk print_string(data, ireq.i_len); 146777218Sphk } 146877218Sphk 1469138593Ssam spacer = ' '; /* force first break */ 1470138593Ssam LINE_BREAK(); 147177218Sphk 147277218Sphk ireq.i_type = IEEE80211_IOC_AUTHMODE; 147377218Sphk if (ioctl(s, SIOCG80211, &ireq) != -1) { 147477218Sphk switch (ireq.i_val) { 147577218Sphk case IEEE80211_AUTH_NONE: 1476138593Ssam LINE_CHECK("%cauthmode NONE", spacer); 147777218Sphk break; 147877218Sphk case IEEE80211_AUTH_OPEN: 1479138593Ssam LINE_CHECK("%cauthmode OPEN", spacer); 148077218Sphk break; 148177218Sphk case IEEE80211_AUTH_SHARED: 1482138593Ssam LINE_CHECK("%cauthmode SHARED", spacer); 148377218Sphk break; 1484138593Ssam case IEEE80211_AUTH_8021X: 1485138593Ssam LINE_CHECK("%cauthmode 802.1x", spacer); 148677218Sphk break; 1487138593Ssam case IEEE80211_AUTH_WPA: 1488138593Ssam ireq.i_type = IEEE80211_IOC_WPA; 1489138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1490138593Ssam wpa = ireq.i_val; 1491138593Ssam if (!wpa) 1492138593Ssam wpa = 1; /* default to WPA1 */ 1493138593Ssam switch (wpa) { 1494138593Ssam case 2: 1495138593Ssam LINE_CHECK("%cauthmode WPA2/802.11i", 1496138593Ssam spacer); 1497138593Ssam break; 1498138593Ssam case 3: 1499138593Ssam LINE_CHECK("%cauthmode WPA1+WPA2/802.11i", 1500138593Ssam spacer); 1501138593Ssam break; 1502138593Ssam default: 1503138593Ssam LINE_CHECK("%cauthmode WPA", spacer); 1504138593Ssam break; 1505138593Ssam } 150677218Sphk break; 1507138593Ssam case IEEE80211_AUTH_AUTO: 1508138593Ssam LINE_CHECK("%cauthmode AUTO", spacer); 150977218Sphk break; 1510127649Ssam default: 1511138593Ssam LINE_CHECK("%cauthmode UNKNOWN (0x%x)", 1512138593Ssam spacer, ireq.i_val); 1513127649Ssam break; 1514127649Ssam } 1515127649Ssam } 1516127649Ssam 151777218Sphk ireq.i_type = IEEE80211_IOC_WEP; 151880315Sbrooks if (ioctl(s, SIOCG80211, &ireq) != -1 && 151980315Sbrooks ireq.i_val != IEEE80211_WEP_NOSUP) { 1520138718Ssam int firstkey, wepmode; 1521138593Ssam 1522138718Ssam wepmode = ireq.i_val; 1523138718Ssam switch (wepmode) { 152477218Sphk case IEEE80211_WEP_OFF: 1525138593Ssam LINE_CHECK("%cprivacy OFF", spacer); 152677218Sphk break; 152777218Sphk case IEEE80211_WEP_ON: 1528138593Ssam LINE_CHECK("%cprivacy ON", spacer); 152977218Sphk break; 153077218Sphk case IEEE80211_WEP_MIXED: 1531138593Ssam LINE_CHECK("%cprivacy MIXED", spacer); 153277218Sphk break; 153377218Sphk default: 1534138593Ssam LINE_CHECK("%cprivacy UNKNOWN (0x%x)", 1535138718Ssam spacer, wepmode); 153677218Sphk break; 153777218Sphk } 153877218Sphk 153977218Sphk /* 154077218Sphk * If we get here then we've got WEP support so we need 154177218Sphk * to print WEP status. 154291454Sbrooks */ 154377218Sphk 154477218Sphk ireq.i_type = IEEE80211_IOC_WEPTXKEY; 154577218Sphk if (ioctl(s, SIOCG80211, &ireq) < 0) { 154677218Sphk warn("WEP support, but no tx key!"); 154777218Sphk goto end; 154877218Sphk } 1549138593Ssam if (ireq.i_val != -1) 1550138593Ssam LINE_CHECK("%cdeftxkey %d", spacer, ireq.i_val+1); 1551138718Ssam else if (wepmode != IEEE80211_WEP_OFF || verbose) 1552138593Ssam LINE_CHECK("%cdeftxkey UNDEF", spacer); 155377218Sphk 155477218Sphk ireq.i_type = IEEE80211_IOC_NUMWEPKEYS; 155577218Sphk if (ioctl(s, SIOCG80211, &ireq) < 0) { 155677218Sphk warn("WEP support, but no NUMWEPKEYS support!"); 155777218Sphk goto end; 155877218Sphk } 155977218Sphk num = ireq.i_val; 156077218Sphk 1561138593Ssam firstkey = 1; 1562138593Ssam for (i = 0; i < num; i++) { 1563138593Ssam struct ieee80211req_key ik; 156477218Sphk 1565138593Ssam memset(&ik, 0, sizeof(ik)); 1566138593Ssam ik.ik_keyix = i; 1567138593Ssam ireq.i_type = IEEE80211_IOC_WPAKEY; 1568138593Ssam ireq.i_data = &ik; 1569138593Ssam ireq.i_len = sizeof(ik); 157077218Sphk if (ioctl(s, SIOCG80211, &ireq) < 0) { 157177218Sphk warn("WEP support, but can get keys!"); 157277218Sphk goto end; 157377218Sphk } 1574138593Ssam if (ik.ik_keylen != 0) { 1575138593Ssam if (verbose) 1576138593Ssam LINE_BREAK(); 1577138593Ssam printkey(&ik); 1578138593Ssam firstkey = 0; 1579138593Ssam } 1580138593Ssam } 1581138593Ssam } 1582138593Ssam 1583138593Ssam ireq.i_type = IEEE80211_IOC_POWERSAVE; 1584138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1 && 1585138593Ssam ireq.i_val != IEEE80211_POWERSAVE_NOSUP ) { 1586138593Ssam if (ireq.i_val != IEEE80211_POWERSAVE_OFF || verbose) { 1587138593Ssam switch (ireq.i_val) { 1588138593Ssam case IEEE80211_POWERSAVE_OFF: 1589138593Ssam LINE_CHECK("%cpowersavemode OFF", 1590138593Ssam spacer); 1591138593Ssam break; 1592138593Ssam case IEEE80211_POWERSAVE_CAM: 1593138593Ssam LINE_CHECK("%cpowersavemode CAM", 1594138593Ssam spacer); 1595138593Ssam break; 1596138593Ssam case IEEE80211_POWERSAVE_PSP: 1597138593Ssam LINE_CHECK("%cpowersavemode PSP", 1598138593Ssam spacer); 1599138593Ssam break; 1600138593Ssam case IEEE80211_POWERSAVE_PSP_CAM: 1601138593Ssam LINE_CHECK("%cpowersavemode PSP-CAM", 1602138593Ssam spacer); 1603138593Ssam break; 1604138593Ssam } 1605138593Ssam ireq.i_type = IEEE80211_IOC_POWERSAVESLEEP; 1606138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1607138593Ssam LINE_CHECK("%cpowersavesleep %d", 1608138593Ssam spacer, ireq.i_val); 1609138593Ssam } 1610138593Ssam } 1611138593Ssam 1612138593Ssam ireq.i_type = IEEE80211_IOC_TXPOWMAX; 1613138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1614138593Ssam LINE_CHECK("%ctxpowmax %d", spacer, ireq.i_val); 1615138593Ssam 1616138593Ssam if (verbose) { 1617138593Ssam ireq.i_type = IEEE80211_IOC_TXPOWER; 1618138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1619138593Ssam LINE_CHECK("%ctxpower %d", spacer, ireq.i_val); 1620138593Ssam } 1621138593Ssam 1622138593Ssam ireq.i_type = IEEE80211_IOC_RTSTHRESHOLD; 1623138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1624138593Ssam if (ireq.i_val != IEEE80211_RTS_MAX || verbose) 1625138593Ssam LINE_CHECK("%crtsthreshold %d", spacer, ireq.i_val); 1626138593Ssam } 1627138593Ssam 1628153354Ssam ireq.i_type = IEEE80211_IOC_MCAST_RATE; 1629153354Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1630153354Ssam if (ireq.i_val != 2*1 || verbose) { 1631153354Ssam if (ireq.i_val == 11) 1632153354Ssam LINE_CHECK("%cmcastrate 5.5", spacer); 1633153354Ssam else 1634153354Ssam LINE_CHECK("%cmcastrate %d", spacer, 1635153354Ssam ireq.i_val/2); 1636153354Ssam } 1637153354Ssam } 1638153354Ssam 1639148416Ssam ireq.i_type = IEEE80211_IOC_FRAGTHRESHOLD; 1640148416Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1641148416Ssam if (ireq.i_val != IEEE80211_FRAG_MAX || verbose) 1642148416Ssam LINE_CHECK("%cfragthreshold %d", spacer, ireq.i_val); 1643148416Ssam } 1644148416Ssam 1645138593Ssam if (IEEE80211_IS_CHAN_G(c) || IEEE80211_IS_CHAN_PUREG(c) || verbose) { 1646147795Ssam ireq.i_type = IEEE80211_IOC_PUREG; 1647147795Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1648147795Ssam if (ireq.i_val) 1649147795Ssam LINE_CHECK("%cpureg", spacer); 1650147795Ssam else if (verbose) 1651147795Ssam LINE_CHECK("%c-pureg", spacer); 1652147795Ssam } 1653138593Ssam ireq.i_type = IEEE80211_IOC_PROTMODE; 1654138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1655138593Ssam switch (ireq.i_val) { 1656138593Ssam case IEEE80211_PROTMODE_OFF: 1657138593Ssam LINE_CHECK("%cprotmode OFF", spacer); 1658138593Ssam break; 1659138593Ssam case IEEE80211_PROTMODE_CTS: 1660138593Ssam LINE_CHECK("%cprotmode CTS", spacer); 1661138593Ssam break; 1662138593Ssam case IEEE80211_PROTMODE_RTSCTS: 1663138593Ssam LINE_CHECK("%cprotmode RTSCTS", spacer); 1664138593Ssam break; 1665138593Ssam default: 1666138593Ssam LINE_CHECK("%cprotmode UNKNOWN (0x%x)", 1667138593Ssam spacer, ireq.i_val); 1668138593Ssam break; 1669138593Ssam } 1670138593Ssam } 1671138593Ssam } 1672138593Ssam 1673138593Ssam ireq.i_type = IEEE80211_IOC_WME; 1674138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1675138593Ssam wme = ireq.i_val; 1676138593Ssam if (wme) 1677138593Ssam LINE_CHECK("%cwme", spacer); 1678138593Ssam else if (verbose) 1679138593Ssam LINE_CHECK("%c-wme", spacer); 1680138593Ssam } else 1681138593Ssam wme = 0; 1682138593Ssam 1683153422Ssam ireq.i_type = IEEE80211_IOC_BURST; 1684153422Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1685153422Ssam if (ireq.i_val) 1686153422Ssam LINE_CHECK("%cburst", spacer); 1687153422Ssam else if (verbose) 1688153422Ssam LINE_CHECK("%c-burst", spacer); 1689153422Ssam } 1690153422Ssam 1691138593Ssam if (opmode == IEEE80211_M_HOSTAP) { 1692138593Ssam ireq.i_type = IEEE80211_IOC_HIDESSID; 1693138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1694138593Ssam if (ireq.i_val) 1695138593Ssam LINE_CHECK("%cssid HIDE", spacer); 1696138593Ssam else if (verbose) 1697138593Ssam LINE_CHECK("%cssid SHOW", spacer); 1698138593Ssam } 1699138593Ssam 1700138593Ssam ireq.i_type = IEEE80211_IOC_APBRIDGE; 1701138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1702138593Ssam if (!ireq.i_val) 1703138593Ssam LINE_CHECK("%c-apbridge", spacer); 1704138593Ssam else if (verbose) 1705138593Ssam LINE_CHECK("%capbridge", spacer); 1706138593Ssam } 1707138593Ssam 1708138593Ssam ireq.i_type = IEEE80211_IOC_DTIM_PERIOD; 1709138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) 1710138593Ssam LINE_CHECK("%cdtimperiod %u", spacer, ireq.i_val); 1711138593Ssam } else { 1712138593Ssam ireq.i_type = IEEE80211_IOC_ROAMING; 1713138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1714138593Ssam if (ireq.i_val != IEEE80211_ROAMING_AUTO || verbose) { 1715138593Ssam switch (ireq.i_val) { 1716138593Ssam case IEEE80211_ROAMING_DEVICE: 1717138593Ssam LINE_CHECK("%croaming DEVICE", spacer); 1718138593Ssam break; 1719138593Ssam case IEEE80211_ROAMING_AUTO: 1720138593Ssam LINE_CHECK("%croaming AUTO", spacer); 1721138593Ssam break; 1722138593Ssam case IEEE80211_ROAMING_MANUAL: 1723138593Ssam LINE_CHECK("%croaming MANUAL", spacer); 1724138593Ssam break; 1725138593Ssam default: 1726138593Ssam LINE_CHECK("%croaming UNKNOWN (0x%x)", 1727138593Ssam spacer, ireq.i_val); 1728138593Ssam break; 1729138593Ssam } 1730138593Ssam } 1731138593Ssam } 1732138593Ssam } 1733138593Ssam ireq.i_type = IEEE80211_IOC_BEACON_INTERVAL; 1734138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1735138593Ssam if (ireq.i_val) 1736138593Ssam LINE_CHECK("%cbintval %u", spacer, ireq.i_val); 1737138593Ssam else if (verbose) 1738138593Ssam LINE_CHECK("%cbintval %u", spacer, ireq.i_val); 1739138593Ssam } 1740138593Ssam 1741138593Ssam if (wme && verbose) { 1742138593Ssam LINE_BREAK(); 1743138593Ssam list_wme(s); 1744138593Ssam } 1745138593Ssam 1746138593Ssam if (wpa) { 1747138593Ssam ireq.i_type = IEEE80211_IOC_COUNTERMEASURES; 1748138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1749138593Ssam if (ireq.i_val) 1750138593Ssam LINE_CHECK("%ccountermeasures", spacer); 1751138593Ssam else if (verbose) 1752138593Ssam LINE_CHECK("%c-countermeasures", spacer); 1753138593Ssam } 1754138593Ssam#if 0 1755138593Ssam /* XXX not interesting with WPA done in user space */ 1756138593Ssam ireq.i_type = IEEE80211_IOC_KEYMGTALGS; 1757138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1758138593Ssam } 1759138593Ssam 1760138593Ssam ireq.i_type = IEEE80211_IOC_MCASTCIPHER; 1761138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1762138593Ssam printf("%cmcastcipher ", spacer); 1763138593Ssam printcipher(s, &ireq, IEEE80211_IOC_MCASTKEYLEN); 1764138593Ssam spacer = ' '; 1765138593Ssam } 1766138593Ssam 1767138593Ssam ireq.i_type = IEEE80211_IOC_UCASTCIPHER; 1768138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1769138593Ssam printf("%cucastcipher ", spacer); 1770138593Ssam printcipher(s, &ireq, IEEE80211_IOC_UCASTKEYLEN); 1771138593Ssam } 1772138593Ssam 1773138593Ssam if (wpa & 2) { 1774138593Ssam ireq.i_type = IEEE80211_IOC_RSNCAPS; 1775138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1776138593Ssam printf("%cRSN caps 0x%x", spacer, ireq.i_val); 177777218Sphk spacer = ' '; 1778138593Ssam } 177977218Sphk } 1780138593Ssam 1781138593Ssam ireq.i_type = IEEE80211_IOC_UCASTCIPHERS; 1782138593Ssam if (ioctl(s, SIOCG80211, &ireq) != -1) { 1783138593Ssam } 1784138593Ssam#endif 1785138593Ssam LINE_BREAK(); 178677218Sphk } 1787138593Ssam LINE_BREAK(); 178877218Sphk 178977218Sphkend: 179077218Sphk return; 179177218Sphk} 179277218Sphk 179377218Sphkstatic void 179477218Sphkset80211(int s, int type, int val, int len, u_int8_t *data) 179577218Sphk{ 179677218Sphk struct ieee80211req ireq; 179777218Sphk 179877218Sphk (void) memset(&ireq, 0, sizeof(ireq)); 179977218Sphk (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); 180077218Sphk ireq.i_type = type; 180177218Sphk ireq.i_val = val; 180277218Sphk ireq.i_len = len; 180377218Sphk ireq.i_data = data; 180491454Sbrooks if (ioctl(s, SIOCS80211, &ireq) < 0) 180577218Sphk err(1, "SIOCS80211"); 180677218Sphk} 180777218Sphk 180877218Sphkstatic const char * 180977218Sphkget_string(const char *val, const char *sep, u_int8_t *buf, int *lenp) 181077218Sphk{ 181177218Sphk int len; 181277218Sphk int hexstr; 181377218Sphk u_int8_t *p; 181477218Sphk 181577218Sphk len = *lenp; 181677218Sphk p = buf; 181777218Sphk hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); 181877218Sphk if (hexstr) 181977218Sphk val += 2; 182077218Sphk for (;;) { 182177218Sphk if (*val == '\0') 182277218Sphk break; 182377218Sphk if (sep != NULL && strchr(sep, *val) != NULL) { 182477218Sphk val++; 182577218Sphk break; 182677218Sphk } 182777218Sphk if (hexstr) { 1828127831Sphk if (!isxdigit((u_char)val[0])) { 182977218Sphk warnx("bad hexadecimal digits"); 183077218Sphk return NULL; 183177218Sphk } 1832127831Sphk if (!isxdigit((u_char)val[1])) { 1833127831Sphk warnx("odd count hexadecimal digits"); 1834127831Sphk return NULL; 1835127831Sphk } 183677218Sphk } 1837127831Sphk if (p >= buf + len) { 183877218Sphk if (hexstr) 183977218Sphk warnx("hexadecimal digits too long"); 184077218Sphk else 1841127831Sphk warnx("string too long"); 184277218Sphk return NULL; 184377218Sphk } 184477218Sphk if (hexstr) { 184577218Sphk#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) 184677218Sphk *p++ = (tohex((u_char)val[0]) << 4) | 184777218Sphk tohex((u_char)val[1]); 184877218Sphk#undef tohex 184977218Sphk val += 2; 185077218Sphk } else 185177218Sphk *p++ = *val++; 185277218Sphk } 185377218Sphk len = p - buf; 185477218Sphk /* The string "-" is treated as the empty string. */ 185577218Sphk if (!hexstr && len == 1 && buf[0] == '-') 185677218Sphk len = 0; 185777218Sphk if (len < *lenp) 185877218Sphk memset(p, 0, *lenp - len); 185977218Sphk *lenp = len; 186077218Sphk return val; 186177218Sphk} 186277218Sphk 186377218Sphkstatic void 186477218Sphkprint_string(const u_int8_t *buf, int len) 186577218Sphk{ 186677218Sphk int i; 186777218Sphk int hasspc; 186877218Sphk 186977218Sphk i = 0; 187077218Sphk hasspc = 0; 187191454Sbrooks for (; i < len; i++) { 187277218Sphk if (!isprint(buf[i]) && buf[i] != '\0') 187377218Sphk break; 187477218Sphk if (isspace(buf[i])) 187577218Sphk hasspc++; 187677218Sphk } 187777218Sphk if (i == len) { 187877218Sphk if (hasspc || len == 0 || buf[0] == '\0') 187977218Sphk printf("\"%.*s\"", len, buf); 188077218Sphk else 188177218Sphk printf("%.*s", len, buf); 188277218Sphk } else { 188377218Sphk printf("0x"); 188477218Sphk for (i = 0; i < len; i++) 188577218Sphk printf("%02x", buf[i]); 188677218Sphk } 188777218Sphk} 188877218Sphk 1889138593Ssamstatic struct cmd ieee80211_cmds[] = { 1890138593Ssam DEF_CMD_ARG("ssid", set80211ssid), 1891138593Ssam DEF_CMD_ARG("nwid", set80211ssid), 1892138593Ssam DEF_CMD_ARG("stationname", set80211stationname), 1893138593Ssam DEF_CMD_ARG("station", set80211stationname), /* BSD/OS */ 1894138593Ssam DEF_CMD_ARG("channel", set80211channel), 1895138593Ssam DEF_CMD_ARG("authmode", set80211authmode), 1896138593Ssam DEF_CMD_ARG("powersavemode", set80211powersavemode), 1897138593Ssam DEF_CMD("powersave", 1, set80211powersave), 1898138593Ssam DEF_CMD("-powersave", 0, set80211powersave), 1899138593Ssam DEF_CMD_ARG("powersavesleep", set80211powersavesleep), 1900138593Ssam DEF_CMD_ARG("wepmode", set80211wepmode), 1901138593Ssam DEF_CMD("wep", 1, set80211wep), 1902138593Ssam DEF_CMD("-wep", 0, set80211wep), 1903139493Ssam DEF_CMD_ARG("deftxkey", set80211weptxkey), 1904138593Ssam DEF_CMD_ARG("weptxkey", set80211weptxkey), 1905138593Ssam DEF_CMD_ARG("wepkey", set80211wepkey), 1906138593Ssam DEF_CMD_ARG("nwkey", set80211nwkey), /* NetBSD */ 1907138593Ssam DEF_CMD("-nwkey", 0, set80211wep), /* NetBSD */ 1908138593Ssam DEF_CMD_ARG("rtsthreshold", set80211rtsthreshold), 1909138593Ssam DEF_CMD_ARG("protmode", set80211protmode), 1910138593Ssam DEF_CMD_ARG("txpower", set80211txpower), 1911138593Ssam DEF_CMD_ARG("roaming", set80211roaming), 1912138593Ssam DEF_CMD("wme", 1, set80211wme), 1913138593Ssam DEF_CMD("-wme", 0, set80211wme), 1914138593Ssam DEF_CMD("hidessid", 1, set80211hidessid), 1915138593Ssam DEF_CMD("-hidessid", 0, set80211hidessid), 1916138593Ssam DEF_CMD("apbridge", 1, set80211apbridge), 1917138593Ssam DEF_CMD("-apbridge", 0, set80211apbridge), 1918138593Ssam DEF_CMD_ARG("chanlist", set80211chanlist), 1919138593Ssam DEF_CMD_ARG("bssid", set80211bssid), 1920138593Ssam DEF_CMD_ARG("ap", set80211bssid), 1921138593Ssam DEF_CMD("scan", 0, set80211scan), 1922138593Ssam DEF_CMD_ARG("list", set80211list), 1923138593Ssam DEF_CMD_ARG2("cwmin", set80211cwmin), 1924138593Ssam DEF_CMD_ARG2("cwmax", set80211cwmax), 1925138593Ssam DEF_CMD_ARG2("aifs", set80211aifs), 1926138593Ssam DEF_CMD_ARG2("txoplimit", set80211txoplimit), 1927148621Ssam DEF_CMD_ARG("acm", set80211acm), 1928148621Ssam DEF_CMD_ARG("-acm", set80211noacm), 1929148621Ssam DEF_CMD_ARG("ack", set80211ackpolicy), 1930148621Ssam DEF_CMD_ARG("-ack", set80211noackpolicy), 1931138593Ssam DEF_CMD_ARG2("bss:cwmin", set80211bsscwmin), 1932138593Ssam DEF_CMD_ARG2("bss:cwmax", set80211bsscwmax), 1933138593Ssam DEF_CMD_ARG2("bss:aifs", set80211bssaifs), 1934138593Ssam DEF_CMD_ARG2("bss:txoplimit", set80211bsstxoplimit), 1935138593Ssam DEF_CMD_ARG("dtimperiod", set80211dtimperiod), 1936138593Ssam DEF_CMD_ARG("bintval", set80211bintval), 1937138593Ssam DEF_CMD("mac:open", IEEE80211_MACCMD_POLICY_OPEN, set80211maccmd), 1938138593Ssam DEF_CMD("mac:allow", IEEE80211_MACCMD_POLICY_ALLOW, set80211maccmd), 1939138593Ssam DEF_CMD("mac:deny", IEEE80211_MACCMD_POLICY_DENY, set80211maccmd), 1940138593Ssam DEF_CMD("mac:flush", IEEE80211_MACCMD_FLUSH, set80211maccmd), 1941138593Ssam DEF_CMD("mac:detach", IEEE80211_MACCMD_DETACH, set80211maccmd), 1942138593Ssam DEF_CMD_ARG("mac:add", set80211addmac), 1943138593Ssam DEF_CMD_ARG("mac:del", set80211delmac), 1944138593Ssam DEF_CMD_ARG("mac:kick", set80211kickmac), 1945147795Ssam DEF_CMD("pureg", 1, set80211pureg), 1946147795Ssam DEF_CMD("-pureg", 0, set80211pureg), 1947153354Ssam DEF_CMD_ARG("mcastrate", set80211mcastrate), 1948148416Ssam DEF_CMD_ARG("fragthreshold", set80211fragthreshold), 1949153422Ssam DEF_CMD("burst", 1, set80211burst), 1950153422Ssam DEF_CMD("-burst", 0, set80211burst), 1951138593Ssam}; 1952138593Ssamstatic struct afswtch af_ieee80211 = { 1953138593Ssam .af_name = "af_ieee80211", 1954138593Ssam .af_af = AF_UNSPEC, 1955139494Ssam .af_other_status = ieee80211_status, 1956138593Ssam}; 1957138593Ssam 1958138593Ssamstatic __constructor void 1959138593Ssamieee80211_ctor(void) 1960138593Ssam{ 1961138593Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 1962138593Ssam int i; 1963138593Ssam 1964138593Ssam for (i = 0; i < N(ieee80211_cmds); i++) 1965138593Ssam cmd_register(&ieee80211_cmds[i]); 1966138593Ssam af_register(&af_ieee80211); 1967138593Ssam#undef N 1968138593Ssam} 1969