161822Sgreen/* 255992Swpaul * Copyright 1997, 1998, 1999 355992Swpaul * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. 455992Swpaul * 555992Swpaul * Redistribution and use in source and binary forms, with or without 655992Swpaul * modification, are permitted provided that the following conditions 755992Swpaul * are met: 855992Swpaul * 1. Redistributions of source code must retain the above copyright 955992Swpaul * notice, this list of conditions and the following disclaimer. 1055992Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1155992Swpaul * notice, this list of conditions and the following disclaimer in the 1255992Swpaul * documentation and/or other materials provided with the distribution. 1355992Swpaul * 3. All advertising materials mentioning features or use of this software 1455992Swpaul * must display the following acknowledgement: 1555992Swpaul * This product includes software developed by Bill Paul. 1655992Swpaul * 4. Neither the name of the author nor the names of any co-contributors 1755992Swpaul * may be used to endorse or promote products derived from this software 1855992Swpaul * without specific prior written permission. 1955992Swpaul * 2055992Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2155992Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2255992Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2355992Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 2455992Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2555992Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2655992Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2755992Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2855992Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2955992Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3055992Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 3155992Swpaul */ 3255992Swpaul 33114601Sobrien#if 0 3481586Sru#ifndef lint 3581586Srustatic const char copyright[] = "@(#) Copyright (c) 1997, 1998, 1999\ 3681586Sru Bill Paul. All rights reserved."; 3781586Sru#endif 38114601Sobrien#endif 39114601Sobrien#include <sys/cdefs.h> 40114601Sobrien__FBSDID("$FreeBSD$"); 4181586Sru 4255992Swpaul#include <sys/types.h> 4355992Swpaul#include <sys/socket.h> 4455992Swpaul#include <sys/ioctl.h> 4555992Swpaul 4690868Smike#include <arpa/inet.h> 4790868Smike 4855992Swpaul#include <net/if.h> 4955992Swpaul#include <net/if_var.h> 5055992Swpaul#include <net/ethernet.h> 5155992Swpaul 5255992Swpaul#include <dev/an/if_aironet_ieee.h> 5355992Swpaul 5455992Swpaul#include <stdio.h> 5555992Swpaul#include <string.h> 5655992Swpaul#include <stdlib.h> 5755992Swpaul#include <unistd.h> 5855992Swpaul#include <errno.h> 5955992Swpaul#include <err.h> 6088748Sambrisko#include <md4.h> 61108401Sambrisko#include <ctype.h> 6255992Swpaul 63108401Sambriskostatic int an_getval(const char *, struct an_req *); 6499800Salfredstatic void an_setval(const char *, struct an_req *); 65132860Snjlstatic void an_printwords(const u_int16_t *, int); 66132860Snjlstatic void an_printspeeds(const u_int8_t *, int); 6799800Salfredstatic void an_printbool(int); 68132860Snjlstatic void an_printhex(const char *, int); 6999800Salfredstatic void an_printstr(char *, int); 7099800Salfredstatic void an_dumpstatus(const char *); 7199800Salfredstatic void an_dumpstats(const char *); 7299800Salfredstatic void an_dumpconfig(const char *); 7399800Salfredstatic void an_dumpcaps(const char *); 7499800Salfredstatic void an_dumpssid(const char *); 7599800Salfredstatic void an_dumpap(const char *); 7699800Salfredstatic void an_setconfig(const char *, int, void *); 7799800Salfredstatic void an_setssid(const char *, int, void *); 7899800Salfredstatic void an_setap(const char *, int, void *); 7999800Salfredstatic void an_setspeed(const char *, int, void *); 8099800Salfredstatic void an_readkeyinfo(const char *); 8155992Swpaul#ifdef ANCACHE 8299800Salfredstatic void an_zerocache(const char *); 8399800Salfredstatic void an_readcache(const char *); 8455992Swpaul#endif 8599800Salfredstatic int an_hex2int(char); 86132860Snjlstatic void an_str2key(const char *, struct an_ltv_key *); 87132860Snjlstatic void an_setkeys(const char *, const char *, int); 88132860Snjlstatic void an_enable_tx_key(const char *, const char *); 89132860Snjlstatic void an_enable_leap_mode(const char *, const char *); 90108401Sambriskostatic void an_dumprssimap(const char *); 91132860Snjlstatic void usage(const char *); 9255992Swpaul 9355992Swpaul#define ACT_DUMPSTATS 1 9455992Swpaul#define ACT_DUMPCONFIG 2 9555992Swpaul#define ACT_DUMPSTATUS 3 9655992Swpaul#define ACT_DUMPCAPS 4 9755992Swpaul#define ACT_DUMPSSID 5 9855992Swpaul#define ACT_DUMPAP 6 9955992Swpaul 10055992Swpaul#define ACT_SET_OPMODE 7 101119156Sambrisko#define ACT_SET_SSID 8 10255992Swpaul#define ACT_SET_FREQ 11 10355992Swpaul#define ACT_SET_AP1 12 10455992Swpaul#define ACT_SET_AP2 13 10555992Swpaul#define ACT_SET_AP3 14 10655992Swpaul#define ACT_SET_AP4 15 10755992Swpaul#define ACT_SET_DRIVERNAME 16 10855992Swpaul#define ACT_SET_SCANMODE 17 10955992Swpaul#define ACT_SET_TXRATE 18 11055992Swpaul#define ACT_SET_RTS_THRESH 19 11155992Swpaul#define ACT_SET_PWRSAVE 20 11255992Swpaul#define ACT_SET_DIVERSITY_RX 21 11355992Swpaul#define ACT_SET_DIVERSITY_TX 22 11455992Swpaul#define ACT_SET_RTS_RETRYLIM 23 11555992Swpaul#define ACT_SET_WAKE_DURATION 24 11655992Swpaul#define ACT_SET_BEACON_PERIOD 25 11755992Swpaul#define ACT_SET_TXPWR 26 11855992Swpaul#define ACT_SET_FRAG_THRESH 27 11955992Swpaul#define ACT_SET_NETJOIN 28 12055992Swpaul#define ACT_SET_MYNAME 29 12155992Swpaul#define ACT_SET_MAC 30 12255992Swpaul 12355992Swpaul#define ACT_DUMPCACHE 31 12455992Swpaul#define ACT_ZEROCACHE 32 12555992Swpaul 12668692Swpaul#define ACT_ENABLE_WEP 33 12768692Swpaul#define ACT_SET_KEY_TYPE 34 12868692Swpaul#define ACT_SET_KEYS 35 12969772Sarchie#define ACT_ENABLE_TX_KEY 36 13083269Sbrooks#define ACT_SET_MONITOR_MODE 37 13188748Sambrisko#define ACT_SET_LEAP_MODE 38 13268692Swpaul 133108401Sambrisko#define ACT_DUMPRSSIMAP 39 134108401Sambrisko 135132860Snjlstatic int 136132860Snjlan_getval(const char *iface, struct an_req *areq) 13755992Swpaul{ 13855992Swpaul struct ifreq ifr; 139108401Sambrisko int s, okay = 1; 14055992Swpaul 141132900Snjl bzero(&ifr, sizeof(ifr)); 14255992Swpaul 14361815Sroberto strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); 14455992Swpaul ifr.ifr_data = (caddr_t)areq; 14555992Swpaul 14655992Swpaul s = socket(AF_INET, SOCK_DGRAM, 0); 14755992Swpaul 14855992Swpaul if (s == -1) 14955992Swpaul err(1, "socket"); 15055992Swpaul 151108401Sambrisko if (ioctl(s, SIOCGAIRONET, &ifr) == -1) { 152108401Sambrisko okay = 0; 15355992Swpaul err(1, "SIOCGAIRONET"); 154108401Sambrisko } 15555992Swpaul 15655992Swpaul close(s); 15755992Swpaul 158132860Snjl return (okay); 15955992Swpaul} 16055992Swpaul 161132860Snjlstatic void 162132860Snjlan_setval(const char *iface, struct an_req *areq) 16355992Swpaul{ 16455992Swpaul struct ifreq ifr; 16555992Swpaul int s; 16655992Swpaul 167132900Snjl bzero(&ifr, sizeof(ifr)); 16855992Swpaul 16961815Sroberto strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); 17055992Swpaul ifr.ifr_data = (caddr_t)areq; 17155992Swpaul 17255992Swpaul s = socket(AF_INET, SOCK_DGRAM, 0); 17355992Swpaul 17455992Swpaul if (s == -1) 17555992Swpaul err(1, "socket"); 17655992Swpaul 17755992Swpaul if (ioctl(s, SIOCSAIRONET, &ifr) == -1) 17855992Swpaul err(1, "SIOCSAIRONET"); 17955992Swpaul 18055992Swpaul close(s); 18155992Swpaul 18255992Swpaul return; 18355992Swpaul} 18455992Swpaul 185132860Snjlstatic void 186132860Snjlan_printstr(char *str, int len) 18755992Swpaul{ 18855992Swpaul int i; 18955992Swpaul 19055992Swpaul for (i = 0; i < len - 1; i++) { 19155992Swpaul if (str[i] == '\0') 19255992Swpaul str[i] = ' '; 19355992Swpaul } 19455992Swpaul 19555992Swpaul printf("[ %.*s ]", len, str); 19655992Swpaul} 19755992Swpaul 198132860Snjlstatic void 199132860Snjlan_printwords(const u_int16_t *w, int len) 20055992Swpaul{ 20155992Swpaul int i; 20255992Swpaul 20355992Swpaul printf("[ "); 20455992Swpaul for (i = 0; i < len; i++) 205132860Snjl printf("%u ", w[i]); 20655992Swpaul printf("]"); 20755992Swpaul} 20855992Swpaul 209132860Snjlstatic void 210132860Snjlan_printspeeds(const u_int8_t *w, int len) 21155992Swpaul{ 21255992Swpaul int i; 21355992Swpaul 21455992Swpaul printf("[ "); 21555992Swpaul for (i = 0; i < len && w[i]; i++) 21655992Swpaul printf("%2.1fMbps ", w[i] * 0.500); 21755992Swpaul printf("]"); 21855992Swpaul} 21955992Swpaul 220132860Snjlstatic void 221132860Snjlan_printbool(int val) 22255992Swpaul{ 22355992Swpaul if (val) 22455992Swpaul printf("[ On ]"); 22555992Swpaul else 22655992Swpaul printf("[ Off ]"); 22755992Swpaul} 22855992Swpaul 229132860Snjlstatic void 230132860Snjlan_printhex(const char *ptr, int len) 23155992Swpaul{ 23255992Swpaul int i; 23355992Swpaul 23455992Swpaul printf("[ "); 23555992Swpaul for (i = 0; i < len; i++) { 23655992Swpaul printf("%02x", ptr[i] & 0xFF); 23755992Swpaul if (i < (len - 1)) 23855992Swpaul printf(":"); 23955992Swpaul } 24055992Swpaul 24155992Swpaul printf(" ]"); 24255992Swpaul} 24355992Swpaul 24468692Swpaul 24568692Swpaul 246132860Snjlstatic void 247132860Snjlan_dumpstatus(const char *iface) 24855992Swpaul{ 24955992Swpaul struct an_ltv_status *sts; 25055992Swpaul struct an_req areq; 251108401Sambrisko struct an_ltv_rssi_map an_rssimap; 252108401Sambrisko int rssimap_valid = 0; 25355992Swpaul 254108401Sambrisko /* 255108401Sambrisko * Try to get RSSI to percent and dBM table 256108401Sambrisko */ 257108401Sambrisko 258108401Sambrisko an_rssimap.an_len = sizeof(an_rssimap); 259108401Sambrisko an_rssimap.an_type = AN_RID_RSSI_MAP; 260108401Sambrisko rssimap_valid = an_getval(iface, (struct an_req*)&an_rssimap); 261108401Sambrisko 262108401Sambrisko if (rssimap_valid) 263108401Sambrisko printf("RSSI table:\t\t[ present ]\n"); 264108401Sambrisko else 265108401Sambrisko printf("RSSI table:\t\t[ not available ]\n"); 266108401Sambrisko 26755992Swpaul areq.an_len = sizeof(areq); 26855992Swpaul areq.an_type = AN_RID_STATUS; 26955992Swpaul 27055992Swpaul an_getval(iface, &areq); 27155992Swpaul 27255992Swpaul sts = (struct an_ltv_status *)&areq; 27355992Swpaul 27455992Swpaul printf("MAC address:\t\t"); 27555992Swpaul an_printhex((char *)&sts->an_macaddr, ETHER_ADDR_LEN); 27655992Swpaul printf("\nOperating mode:\t\t[ "); 27755992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_CONFIGURED) 27855992Swpaul printf("configured "); 27955992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_MAC_ENABLED) 28055992Swpaul printf("MAC ON "); 28155992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_RX_ENABLED) 28255992Swpaul printf("RX ON "); 28355992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_IN_SYNC) 28455992Swpaul printf("synced "); 28555992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_ASSOCIATED) 28655992Swpaul printf("associated "); 28788748Sambrisko if (sts->an_opmode & AN_STATUS_OPMODE_LEAP) 28888748Sambrisko printf("LEAP "); 28955992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_ERROR) 29055992Swpaul printf("error "); 29155992Swpaul printf("]\n"); 29255992Swpaul printf("Error code:\t\t"); 29355992Swpaul an_printhex((char *)&sts->an_errcode, 1); 294108401Sambrisko if (rssimap_valid) 295132860Snjl printf("\nSignal strength:\t[ %u%% ]", 296108401Sambrisko an_rssimap.an_entries[ 297108401Sambrisko sts->an_normalized_strength].an_rss_pct); 298108401Sambrisko else 299132860Snjl printf("\nSignal strength:\t[ %u%% ]", 300108401Sambrisko sts->an_normalized_strength); 301132860Snjl printf("\nAverage Noise:\t\t[ %u%% ]", sts->an_avg_noise_prev_min_pc); 302108401Sambrisko if (rssimap_valid) 303132860Snjl printf("\nSignal quality:\t\t[ %u%% ]", 304108401Sambrisko an_rssimap.an_entries[ 305108401Sambrisko sts->an_cur_signal_quality].an_rss_pct); 306108401Sambrisko else 307132860Snjl printf("\nSignal quality:\t\t[ %u ]", 308108401Sambrisko sts->an_cur_signal_quality); 309132860Snjl printf("\nMax Noise:\t\t[ %u%% ]", sts->an_max_noise_prev_min_pc); 31078788Sbrooks /* 31178788Sbrooks * XXX: This uses the old definition of the rate field (units of 31278788Sbrooks * 500kbps). Technically the new definition is that this field 31378788Sbrooks * contains arbitrary values, but no devices which need this 31478788Sbrooks * support exist and the IEEE seems to intend to use the old 31578788Sbrooks * definition until they get something big so we'll keep using 31678788Sbrooks * it as well because this will work with new cards with 31778788Sbrooks * rate <= 63.5Mbps. 31878788Sbrooks */ 319132860Snjl printf("\nCurrent TX rate:\t[ %u%s ]", sts->an_current_tx_rate / 2, 32078788Sbrooks (sts->an_current_tx_rate % 2) ? ".5" : ""); 32155992Swpaul printf("\nCurrent SSID:\t\t"); 32255992Swpaul an_printstr((char *)&sts->an_ssid, sts->an_ssidlen); 32355992Swpaul printf("\nCurrent AP name:\t"); 32455992Swpaul an_printstr((char *)&sts->an_ap_name, 16); 32555992Swpaul printf("\nCurrent BSSID:\t\t"); 32655992Swpaul an_printhex((char *)&sts->an_cur_bssid, ETHER_ADDR_LEN); 32755992Swpaul printf("\nBeacon period:\t\t"); 32855992Swpaul an_printwords(&sts->an_beacon_period, 1); 32955992Swpaul printf("\nDTIM period:\t\t"); 33055992Swpaul an_printwords(&sts->an_dtim_period, 1); 33155992Swpaul printf("\nATIM duration:\t\t"); 33255992Swpaul an_printwords(&sts->an_atim_duration, 1); 33355992Swpaul printf("\nHOP period:\t\t"); 33455992Swpaul an_printwords(&sts->an_hop_period, 1); 33555992Swpaul printf("\nChannel set:\t\t"); 33655992Swpaul an_printwords(&sts->an_channel_set, 1); 33755992Swpaul printf("\nCurrent channel:\t"); 33855992Swpaul an_printwords(&sts->an_cur_channel, 1); 33955992Swpaul printf("\nHops to backbone:\t"); 34055992Swpaul an_printwords(&sts->an_hops_to_backbone, 1); 34155992Swpaul printf("\nTotal AP load:\t\t"); 34255992Swpaul an_printwords(&sts->an_ap_total_load, 1); 34355992Swpaul printf("\nOur generated load:\t"); 34455992Swpaul an_printwords(&sts->an_our_generated_load, 1); 34555992Swpaul printf("\nAccumulated ARL:\t"); 34655992Swpaul an_printwords(&sts->an_accumulated_arl, 1); 34755992Swpaul printf("\n"); 34855992Swpaul return; 34955992Swpaul} 35055992Swpaul 351132860Snjlstatic void 352132860Snjlan_dumpcaps(const char *iface) 35355992Swpaul{ 35455992Swpaul struct an_ltv_caps *caps; 35555992Swpaul struct an_req areq; 35655992Swpaul u_int16_t tmp; 35755992Swpaul 35855992Swpaul areq.an_len = sizeof(areq); 35955992Swpaul areq.an_type = AN_RID_CAPABILITIES; 36055992Swpaul 36155992Swpaul an_getval(iface, &areq); 36255992Swpaul 36355992Swpaul caps = (struct an_ltv_caps *)&areq; 36455992Swpaul 36555992Swpaul printf("OUI:\t\t\t"); 36655992Swpaul an_printhex((char *)&caps->an_oui, 3); 36755992Swpaul printf("\nProduct number:\t\t"); 36855992Swpaul an_printwords(&caps->an_prodnum, 1); 36955992Swpaul printf("\nManufacturer name:\t"); 37055992Swpaul an_printstr((char *)&caps->an_manufname, 32); 37155992Swpaul printf("\nProduce name:\t\t"); 37255992Swpaul an_printstr((char *)&caps->an_prodname, 16); 37355992Swpaul printf("\nFirmware version:\t"); 37455992Swpaul an_printstr((char *)&caps->an_prodvers, 1); 37555992Swpaul printf("\nOEM MAC address:\t"); 37655992Swpaul an_printhex((char *)&caps->an_oemaddr, ETHER_ADDR_LEN); 37755992Swpaul printf("\nAironet MAC address:\t"); 37855992Swpaul an_printhex((char *)&caps->an_aironetaddr, ETHER_ADDR_LEN); 37955992Swpaul printf("\nRadio type:\t\t[ "); 38055992Swpaul if (caps->an_radiotype & AN_RADIOTYPE_80211_FH) 38155992Swpaul printf("802.11 FH"); 38255992Swpaul else if (caps->an_radiotype & AN_RADIOTYPE_80211_DS) 38355992Swpaul printf("802.11 DS"); 38455992Swpaul else if (caps->an_radiotype & AN_RADIOTYPE_LM2000_DS) 38555992Swpaul printf("LM2000 DS"); 38655992Swpaul else 38755992Swpaul printf("unknown (%x)", caps->an_radiotype); 38855992Swpaul printf(" ]"); 38955992Swpaul printf("\nRegulatory domain:\t"); 39055992Swpaul an_printwords(&caps->an_regdomain, 1); 39155992Swpaul printf("\nAssigned CallID:\t"); 39255992Swpaul an_printhex((char *)&caps->an_callid, 6); 39355992Swpaul printf("\nSupported speeds:\t"); 39455992Swpaul an_printspeeds(caps->an_rates, 8); 39555992Swpaul printf("\nRX Diversity:\t\t[ "); 396108401Sambrisko if (caps->an_rx_diversity == AN_DIVERSITY_FACTORY_DEFAULT) 397108401Sambrisko printf("factory default"); 398108401Sambrisko else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY) 39955992Swpaul printf("antenna 1 only"); 40055992Swpaul else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY) 40155992Swpaul printf("antenna 2 only"); 40255992Swpaul else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2) 40355992Swpaul printf("antenna 1 and 2"); 40455992Swpaul printf(" ]"); 40555992Swpaul printf("\nTX Diversity:\t\t[ "); 406108401Sambrisko if (caps->an_tx_diversity == AN_DIVERSITY_FACTORY_DEFAULT) 407108401Sambrisko printf("factory default"); 408108401Sambrisko else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY) 40955992Swpaul printf("antenna 1 only"); 410108401Sambrisko else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY) 41155992Swpaul printf("antenna 2 only"); 412108401Sambrisko else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2) 41355992Swpaul printf("antenna 1 and 2"); 41455992Swpaul printf(" ]"); 41555992Swpaul printf("\nSupported power levels:\t"); 41655992Swpaul an_printwords(caps->an_tx_powerlevels, 8); 41755992Swpaul printf("\nHardware revision:\t"); 41855992Swpaul tmp = ntohs(caps->an_hwrev); 41955992Swpaul an_printhex((char *)&tmp, 2); 42055992Swpaul printf("\nSoftware revision:\t"); 42155992Swpaul tmp = ntohs(caps->an_fwrev); 42255992Swpaul an_printhex((char *)&tmp, 2); 42355992Swpaul printf("\nSoftware subrevision:\t"); 42455992Swpaul tmp = ntohs(caps->an_fwsubrev); 42555992Swpaul an_printhex((char *)&tmp, 2); 42655992Swpaul printf("\nInterface revision:\t"); 42755992Swpaul tmp = ntohs(caps->an_ifacerev); 42855992Swpaul an_printhex((char *)&tmp, 2); 42955992Swpaul printf("\nBootblock revision:\t"); 43055992Swpaul tmp = ntohs(caps->an_bootblockrev); 43155992Swpaul an_printhex((char *)&tmp, 2); 43255992Swpaul printf("\n"); 43355992Swpaul return; 43455992Swpaul} 43555992Swpaul 436132860Snjlstatic void 437132860Snjlan_dumpstats(const char *iface) 43855992Swpaul{ 43955992Swpaul struct an_ltv_stats *stats; 44055992Swpaul struct an_req areq; 44155992Swpaul 44255992Swpaul areq.an_len = sizeof(areq); 44355992Swpaul areq.an_type = AN_RID_32BITS_CUM; 44455992Swpaul 44555992Swpaul an_getval(iface, &areq); 44655992Swpaul 447132900Snjl stats = (struct an_ltv_stats *)((uint16_t *)&areq - 1); 44855992Swpaul 449132860Snjl printf("RX overruns:\t\t\t\t\t[ %u ]\n", stats->an_rx_overruns); 450132860Snjl printf("RX PLCP CSUM errors:\t\t\t\t[ %u ]\n", 45155992Swpaul stats->an_rx_plcp_csum_errs); 452132860Snjl printf("RX PLCP format errors:\t\t\t\t[ %u ]\n", 45355992Swpaul stats->an_rx_plcp_format_errs); 454132860Snjl printf("RX PLCP length errors:\t\t\t\t[ %u ]\n", 45555992Swpaul stats->an_rx_plcp_len_errs); 456132860Snjl printf("RX MAC CRC errors:\t\t\t\t[ %u ]\n", 45755992Swpaul stats->an_rx_mac_crc_errs); 458132860Snjl printf("RX MAC CRC OK:\t\t\t\t\t[ %u ]\n", 45955992Swpaul stats->an_rx_mac_crc_ok); 460132860Snjl printf("RX WEP errors:\t\t\t\t\t[ %u ]\n", 46155992Swpaul stats->an_rx_wep_errs); 462132860Snjl printf("RX WEP OK:\t\t\t\t\t[ %u ]\n", 46355992Swpaul stats->an_rx_wep_ok); 464132860Snjl printf("Long retries:\t\t\t\t\t[ %u ]\n", 46555992Swpaul stats->an_retry_long); 466132860Snjl printf("Short retries:\t\t\t\t\t[ %u ]\n", 46755992Swpaul stats->an_retry_short); 468132860Snjl printf("Retries exhausted:\t\t\t\t[ %u ]\n", 46955992Swpaul stats->an_retry_max); 470132860Snjl printf("Bad ACK:\t\t\t\t\t[ %u ]\n", 47155992Swpaul stats->an_no_ack); 472132860Snjl printf("Bad CTS:\t\t\t\t\t[ %u ]\n", 47355992Swpaul stats->an_no_cts); 474132860Snjl printf("RX good ACKs:\t\t\t\t\t[ %u ]\n", 47555992Swpaul stats->an_rx_ack_ok); 476132860Snjl printf("RX good CTSs:\t\t\t\t\t[ %u ]\n", 47755992Swpaul stats->an_rx_cts_ok); 478132860Snjl printf("TX good ACKs:\t\t\t\t\t[ %u ]\n", 47955992Swpaul stats->an_tx_ack_ok); 480132860Snjl printf("TX good RTSs:\t\t\t\t\t[ %u ]\n", 48155992Swpaul stats->an_tx_rts_ok); 482132860Snjl printf("TX good CTSs:\t\t\t\t\t[ %u ]\n", 48355992Swpaul stats->an_tx_cts_ok); 484132860Snjl printf("LMAC multicasts transmitted:\t\t\t[ %u ]\n", 48555992Swpaul stats->an_tx_lmac_mcasts); 486132860Snjl printf("LMAC broadcasts transmitted:\t\t\t[ %u ]\n", 48755992Swpaul stats->an_tx_lmac_bcasts); 488132860Snjl printf("LMAC unicast frags transmitted:\t\t\t[ %u ]\n", 48955992Swpaul stats->an_tx_lmac_ucast_frags); 490132860Snjl printf("LMAC unicasts transmitted:\t\t\t[ %u ]\n", 49155992Swpaul stats->an_tx_lmac_ucasts); 492132860Snjl printf("Beacons transmitted:\t\t\t\t[ %u ]\n", 49355992Swpaul stats->an_tx_beacons); 494132860Snjl printf("Beacons received:\t\t\t\t[ %u ]\n", 49555992Swpaul stats->an_rx_beacons); 496132860Snjl printf("Single transmit collisions:\t\t\t[ %u ]\n", 49755992Swpaul stats->an_tx_single_cols); 498132860Snjl printf("Multiple transmit collisions:\t\t\t[ %u ]\n", 49955992Swpaul stats->an_tx_multi_cols); 500132860Snjl printf("Transmits without deferrals:\t\t\t[ %u ]\n", 50155992Swpaul stats->an_tx_defers_no); 502132860Snjl printf("Transmits deferred due to protocol:\t\t[ %u ]\n", 50355992Swpaul stats->an_tx_defers_prot); 504132860Snjl printf("Transmits deferred due to energy detect:\t\t[ %u ]\n", 50555992Swpaul stats->an_tx_defers_energy); 506132860Snjl printf("RX duplicate frames/frags:\t\t\t[ %u ]\n", 50755992Swpaul stats->an_rx_dups); 508132860Snjl printf("RX partial frames:\t\t\t\t[ %u ]\n", 50955992Swpaul stats->an_rx_partial); 510132860Snjl printf("TX max lifetime exceeded:\t\t\t[ %u ]\n", 51155992Swpaul stats->an_tx_too_old); 512132860Snjl printf("RX max lifetime exceeded:\t\t\t[ %u ]\n", 51355992Swpaul stats->an_tx_too_old); 514132860Snjl printf("Sync lost due to too many missed beacons:\t[ %u ]\n", 51555992Swpaul stats->an_lostsync_missed_beacons); 516132860Snjl printf("Sync lost due to ARL exceeded:\t\t\t[ %u ]\n", 51755992Swpaul stats->an_lostsync_arl_exceeded); 518132860Snjl printf("Sync lost due to deauthentication:\t\t[ %u ]\n", 51955992Swpaul stats->an_lostsync_deauthed); 520132860Snjl printf("Sync lost due to disassociation:\t\t[ %u ]\n", 52155992Swpaul stats->an_lostsync_disassociated); 522132860Snjl printf("Sync lost due to excess change in TSF timing:\t[ %u ]\n", 52355992Swpaul stats->an_lostsync_tsf_timing); 524132860Snjl printf("Host transmitted multicasts:\t\t\t[ %u ]\n", 52555992Swpaul stats->an_tx_host_mcasts); 526132860Snjl printf("Host transmitted broadcasts:\t\t\t[ %u ]\n", 52755992Swpaul stats->an_tx_host_bcasts); 528132860Snjl printf("Host transmitted unicasts:\t\t\t[ %u ]\n", 52955992Swpaul stats->an_tx_host_ucasts); 530132860Snjl printf("Host transmission failures:\t\t\t[ %u ]\n", 53155992Swpaul stats->an_tx_host_failed); 532132860Snjl printf("Host received multicasts:\t\t\t[ %u ]\n", 53355992Swpaul stats->an_rx_host_mcasts); 534132860Snjl printf("Host received broadcasts:\t\t\t[ %u ]\n", 53555992Swpaul stats->an_rx_host_bcasts); 536132860Snjl printf("Host received unicasts:\t\t\t\t[ %u ]\n", 53755992Swpaul stats->an_rx_host_ucasts); 538132860Snjl printf("Host receive discards:\t\t\t\t[ %u ]\n", 53955992Swpaul stats->an_rx_host_discarded); 540132860Snjl printf("HMAC transmitted multicasts:\t\t\t[ %u ]\n", 54155992Swpaul stats->an_tx_hmac_mcasts); 542132860Snjl printf("HMAC transmitted broadcasts:\t\t\t[ %u ]\n", 54355992Swpaul stats->an_tx_hmac_bcasts); 544132860Snjl printf("HMAC transmitted unicasts:\t\t\t[ %u ]\n", 54555992Swpaul stats->an_tx_hmac_ucasts); 546132860Snjl printf("HMAC transmissions failed:\t\t\t[ %u ]\n", 54755992Swpaul stats->an_tx_hmac_failed); 548132860Snjl printf("HMAC received multicasts:\t\t\t[ %u ]\n", 54955992Swpaul stats->an_rx_hmac_mcasts); 550132860Snjl printf("HMAC received broadcasts:\t\t\t[ %u ]\n", 55155992Swpaul stats->an_rx_hmac_bcasts); 552132860Snjl printf("HMAC received unicasts:\t\t\t\t[ %u ]\n", 55355992Swpaul stats->an_rx_hmac_ucasts); 554132860Snjl printf("HMAC receive discards:\t\t\t\t[ %u ]\n", 55555992Swpaul stats->an_rx_hmac_discarded); 556132860Snjl printf("HMAC transmits accepted:\t\t\t[ %u ]\n", 55755992Swpaul stats->an_tx_hmac_accepted); 558132860Snjl printf("SSID mismatches:\t\t\t\t[ %u ]\n", 55955992Swpaul stats->an_ssid_mismatches); 560132860Snjl printf("Access point mismatches:\t\t\t[ %u ]\n", 56155992Swpaul stats->an_ap_mismatches); 562132860Snjl printf("Speed mismatches:\t\t\t\t[ %u ]\n", 56355992Swpaul stats->an_rates_mismatches); 564132860Snjl printf("Authentication rejects:\t\t\t\t[ %u ]\n", 56555992Swpaul stats->an_auth_rejects); 566132860Snjl printf("Authentication timeouts:\t\t\t[ %u ]\n", 56755992Swpaul stats->an_auth_timeouts); 568132860Snjl printf("Association rejects:\t\t\t\t[ %u ]\n", 56955992Swpaul stats->an_assoc_rejects); 570132860Snjl printf("Association timeouts:\t\t\t\t[ %u ]\n", 57155992Swpaul stats->an_assoc_timeouts); 572132860Snjl printf("Management frames received:\t\t\t[ %u ]\n", 57355992Swpaul stats->an_rx_mgmt_pkts); 574132860Snjl printf("Management frames transmitted:\t\t\t[ %u ]\n", 57555992Swpaul stats->an_tx_mgmt_pkts); 576132860Snjl printf("Refresh frames received:\t\t\t[ %u ]\n", 57755992Swpaul stats->an_rx_refresh_pkts), 578132860Snjl printf("Refresh frames transmitted:\t\t\t[ %u ]\n", 57955992Swpaul stats->an_tx_refresh_pkts), 580132860Snjl printf("Poll frames received:\t\t\t\t[ %u ]\n", 58155992Swpaul stats->an_rx_poll_pkts); 582132860Snjl printf("Poll frames transmitted:\t\t\t[ %u ]\n", 58355992Swpaul stats->an_tx_poll_pkts); 584132860Snjl printf("Host requested sync losses:\t\t\t[ %u ]\n", 58555992Swpaul stats->an_lostsync_hostreq); 586132860Snjl printf("Host transmitted bytes:\t\t\t\t[ %u ]\n", 58755992Swpaul stats->an_host_tx_bytes); 588132860Snjl printf("Host received bytes:\t\t\t\t[ %u ]\n", 58955992Swpaul stats->an_host_rx_bytes); 590132860Snjl printf("Uptime in microseconds:\t\t\t\t[ %u ]\n", 59155992Swpaul stats->an_uptime_usecs); 592132860Snjl printf("Uptime in seconds:\t\t\t\t[ %u ]\n", 59355992Swpaul stats->an_uptime_secs); 594132860Snjl printf("Sync lost due to better AP:\t\t\t[ %u ]\n", 59555992Swpaul stats->an_lostsync_better_ap); 59655992Swpaul} 59755992Swpaul 598132860Snjlstatic void 599132860Snjlan_dumpap(const char *iface) 60055992Swpaul{ 60155992Swpaul struct an_ltv_aplist *ap; 60255992Swpaul struct an_req areq; 60355992Swpaul 60455992Swpaul areq.an_len = sizeof(areq); 60555992Swpaul areq.an_type = AN_RID_APLIST; 60655992Swpaul 60755992Swpaul an_getval(iface, &areq); 60855992Swpaul 60955992Swpaul ap = (struct an_ltv_aplist *)&areq; 61055992Swpaul printf("Access point 1:\t\t\t"); 61155992Swpaul an_printhex((char *)&ap->an_ap1, ETHER_ADDR_LEN); 61255992Swpaul printf("\nAccess point 2:\t\t\t"); 61355992Swpaul an_printhex((char *)&ap->an_ap2, ETHER_ADDR_LEN); 61455992Swpaul printf("\nAccess point 3:\t\t\t"); 61555992Swpaul an_printhex((char *)&ap->an_ap3, ETHER_ADDR_LEN); 61655992Swpaul printf("\nAccess point 4:\t\t\t"); 61755992Swpaul an_printhex((char *)&ap->an_ap4, ETHER_ADDR_LEN); 61855992Swpaul printf("\n"); 61955992Swpaul 62055992Swpaul return; 62155992Swpaul} 62255992Swpaul 623132860Snjlstatic void 624132860Snjlan_dumpssid(const char *iface) 62555992Swpaul{ 626119156Sambrisko struct an_ltv_ssidlist_new *ssid; 62755992Swpaul struct an_req areq; 628119156Sambrisko int i, max; 62955992Swpaul 63055992Swpaul areq.an_len = sizeof(areq); 63155992Swpaul areq.an_type = AN_RID_SSIDLIST; 63255992Swpaul 63355992Swpaul an_getval(iface, &areq); 63455992Swpaul 635119156Sambrisko max = (areq.an_len - 4) / sizeof(struct an_ltv_ssid_entry); 636119156Sambrisko if ( max > MAX_SSIDS ) { 637132860Snjl printf("Too many SSIDs only printing %d of %d\n", 638119156Sambrisko MAX_SSIDS, max); 639119156Sambrisko max = MAX_SSIDS; 640119156Sambrisko } 641119156Sambrisko ssid = (struct an_ltv_ssidlist_new *)&areq; 642119156Sambrisko for (i = 0; i < max; i++) 643119156Sambrisko printf("SSID %2d:\t\t\t[ %.*s ]\n", i + 1, 644119156Sambrisko ssid->an_entry[i].an_len, 645119156Sambrisko ssid->an_entry[i].an_ssid); 64655992Swpaul 64755992Swpaul return; 64855992Swpaul} 64955992Swpaul 650132860Snjlstatic void 651132860Snjlan_dumpconfig(const char *iface) 65255992Swpaul{ 65355992Swpaul struct an_ltv_genconfig *cfg; 65455992Swpaul struct an_req areq; 65580454Sbrooks unsigned char diversity; 65655992Swpaul 65755992Swpaul areq.an_len = sizeof(areq); 65855992Swpaul areq.an_type = AN_RID_ACTUALCFG; 65955992Swpaul 66055992Swpaul an_getval(iface, &areq); 66155992Swpaul 66255992Swpaul cfg = (struct an_ltv_genconfig *)&areq; 66355992Swpaul 66455992Swpaul printf("Operating mode:\t\t\t\t[ "); 66555992Swpaul if ((cfg->an_opmode & 0x7) == AN_OPMODE_IBSS_ADHOC) 66655992Swpaul printf("ad-hoc"); 66755992Swpaul if ((cfg->an_opmode & 0x7) == AN_OPMODE_INFRASTRUCTURE_STATION) 66855992Swpaul printf("infrastructure"); 66955992Swpaul if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP) 67055992Swpaul printf("access point"); 67155992Swpaul if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP_REPEATER) 67255992Swpaul printf("access point repeater"); 67355992Swpaul printf(" ]"); 67455992Swpaul printf("\nReceive mode:\t\t\t\t[ "); 67555992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_MC_ADDR) 67655992Swpaul printf("broadcast/multicast/unicast"); 67755992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_ADDR) 67855992Swpaul printf("broadcast/unicast"); 67955992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_ADDR) 68055992Swpaul printf("unicast"); 68155992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_CURBSS) 68255992Swpaul printf("802.11 monitor, current BSSID"); 68355992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_ANYBSS) 68455992Swpaul printf("802.11 monitor, any BSSID"); 68555992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_LAN_MONITOR_CURBSS) 68655992Swpaul printf("LAN monitor, current BSSID"); 68755992Swpaul printf(" ]"); 68855992Swpaul printf("\nFragment threshold:\t\t\t"); 68955992Swpaul an_printwords(&cfg->an_fragthresh, 1); 69055992Swpaul printf("\nRTS threshold:\t\t\t\t"); 69155992Swpaul an_printwords(&cfg->an_rtsthresh, 1); 69255992Swpaul printf("\nMAC address:\t\t\t\t"); 69355992Swpaul an_printhex((char *)&cfg->an_macaddr, ETHER_ADDR_LEN); 69455992Swpaul printf("\nSupported rates:\t\t\t"); 69555992Swpaul an_printspeeds(cfg->an_rates, 8); 69655992Swpaul printf("\nShort retry limit:\t\t\t"); 69755992Swpaul an_printwords(&cfg->an_shortretry_limit, 1); 69855992Swpaul printf("\nLong retry limit:\t\t\t"); 69955992Swpaul an_printwords(&cfg->an_longretry_limit, 1); 70055992Swpaul printf("\nTX MSDU lifetime:\t\t\t"); 70155992Swpaul an_printwords(&cfg->an_tx_msdu_lifetime, 1); 70255992Swpaul printf("\nRX MSDU lifetime:\t\t\t"); 70355992Swpaul an_printwords(&cfg->an_rx_msdu_lifetime, 1); 70455992Swpaul printf("\nStationary:\t\t\t\t"); 70555992Swpaul an_printbool(cfg->an_stationary); 70655992Swpaul printf("\nOrdering:\t\t\t\t"); 70755992Swpaul an_printbool(cfg->an_ordering); 70855992Swpaul printf("\nDevice type:\t\t\t\t[ "); 70955992Swpaul if (cfg->an_devtype == AN_DEVTYPE_PC4500) 71055992Swpaul printf("PC4500"); 71155992Swpaul else if (cfg->an_devtype == AN_DEVTYPE_PC4800) 71255992Swpaul printf("PC4800"); 71355992Swpaul else 71455992Swpaul printf("unknown (%x)", cfg->an_devtype); 71555992Swpaul printf(" ]"); 71655992Swpaul printf("\nScanning mode:\t\t\t\t[ "); 71755992Swpaul if (cfg->an_scanmode == AN_SCANMODE_ACTIVE) 71855992Swpaul printf("active"); 71955992Swpaul if (cfg->an_scanmode == AN_SCANMODE_PASSIVE) 72055992Swpaul printf("passive"); 72155992Swpaul if (cfg->an_scanmode == AN_SCANMODE_AIRONET_ACTIVE) 72255992Swpaul printf("Aironet active"); 72355992Swpaul printf(" ]"); 72455992Swpaul printf("\nProbe delay:\t\t\t\t"); 72555992Swpaul an_printwords(&cfg->an_probedelay, 1); 72655992Swpaul printf("\nProbe energy timeout:\t\t\t"); 72755992Swpaul an_printwords(&cfg->an_probe_energy_timeout, 1); 72855992Swpaul printf("\nProbe response timeout:\t\t\t"); 72955992Swpaul an_printwords(&cfg->an_probe_response_timeout, 1); 73055992Swpaul printf("\nBeacon listen timeout:\t\t\t"); 73155992Swpaul an_printwords(&cfg->an_beacon_listen_timeout, 1); 73255992Swpaul printf("\nIBSS join network timeout:\t\t"); 73355992Swpaul an_printwords(&cfg->an_ibss_join_net_timeout, 1); 73455992Swpaul printf("\nAuthentication timeout:\t\t\t"); 73555992Swpaul an_printwords(&cfg->an_auth_timeout, 1); 73668692Swpaul printf("\nWEP enabled:\t\t\t\t[ "); 73769772Sarchie if (cfg->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) 73869772Sarchie { 73988748Sambrisko if (cfg->an_authtype & AN_AUTHTYPE_LEAP) 74088748Sambrisko printf("LEAP"); 74188748Sambrisko else if (cfg->an_authtype & AN_AUTHTYPE_ALLOW_UNENCRYPTED) 74269772Sarchie printf("mixed cell"); 74369772Sarchie else 74469772Sarchie printf("full"); 74569772Sarchie } 74668692Swpaul else 74768692Swpaul printf("no"); 74868692Swpaul printf(" ]"); 74955992Swpaul printf("\nAuthentication type:\t\t\t[ "); 75068692Swpaul if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_NONE) 75168692Swpaul printf("none"); 75268692Swpaul if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_OPEN) 75355992Swpaul printf("open"); 75468692Swpaul if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_SHAREDKEY) 75555992Swpaul printf("shared key"); 75655992Swpaul printf(" ]"); 75755992Swpaul printf("\nAssociation timeout:\t\t\t"); 75855992Swpaul an_printwords(&cfg->an_assoc_timeout, 1); 75955992Swpaul printf("\nSpecified AP association timeout:\t"); 76055992Swpaul an_printwords(&cfg->an_specified_ap_timeout, 1); 76155992Swpaul printf("\nOffline scan interval:\t\t\t"); 76255992Swpaul an_printwords(&cfg->an_offline_scan_interval, 1); 76355992Swpaul printf("\nOffline scan duration:\t\t\t"); 76455992Swpaul an_printwords(&cfg->an_offline_scan_duration, 1); 76555992Swpaul printf("\nLink loss delay:\t\t\t"); 76655992Swpaul an_printwords(&cfg->an_link_loss_delay, 1); 76755992Swpaul printf("\nMax beacon loss time:\t\t\t"); 76855992Swpaul an_printwords(&cfg->an_max_beacon_lost_time, 1); 76955992Swpaul printf("\nRefresh interval:\t\t\t"); 77055992Swpaul an_printwords(&cfg->an_refresh_interval, 1); 77155992Swpaul printf("\nPower save mode:\t\t\t[ "); 77255992Swpaul if (cfg->an_psave_mode == AN_PSAVE_NONE) 77355992Swpaul printf("none"); 77455992Swpaul if (cfg->an_psave_mode == AN_PSAVE_CAM) 77555992Swpaul printf("constantly awake mode"); 77655992Swpaul if (cfg->an_psave_mode == AN_PSAVE_PSP) 77755992Swpaul printf("PSP"); 77855992Swpaul if (cfg->an_psave_mode == AN_PSAVE_PSP_CAM) 77955992Swpaul printf("PSP-CAM (fast PSP)"); 78055992Swpaul printf(" ]"); 78155992Swpaul printf("\nSleep through DTIMs:\t\t\t"); 78255992Swpaul an_printbool(cfg->an_sleep_for_dtims); 78355992Swpaul printf("\nPower save listen interval:\t\t"); 78455992Swpaul an_printwords(&cfg->an_listen_interval, 1); 78555992Swpaul printf("\nPower save fast listen interval:\t"); 78655992Swpaul an_printwords(&cfg->an_fast_listen_interval, 1); 78755992Swpaul printf("\nPower save listen decay:\t\t"); 78855992Swpaul an_printwords(&cfg->an_listen_decay, 1); 78955992Swpaul printf("\nPower save fast listen decay:\t\t"); 79055992Swpaul an_printwords(&cfg->an_fast_listen_decay, 1); 79155992Swpaul printf("\nAP/ad-hoc Beacon period:\t\t"); 79255992Swpaul an_printwords(&cfg->an_beacon_period, 1); 79355992Swpaul printf("\nAP/ad-hoc ATIM duration:\t\t"); 79455992Swpaul an_printwords(&cfg->an_atim_duration, 1); 79555992Swpaul printf("\nAP/ad-hoc current channel:\t\t"); 79655992Swpaul an_printwords(&cfg->an_ds_channel, 1); 79755992Swpaul printf("\nAP/ad-hoc DTIM period:\t\t\t"); 79855992Swpaul an_printwords(&cfg->an_dtim_period, 1); 79955992Swpaul printf("\nRadio type:\t\t\t\t[ "); 80055992Swpaul if (cfg->an_radiotype & AN_RADIOTYPE_80211_FH) 80155992Swpaul printf("802.11 FH"); 80255992Swpaul else if (cfg->an_radiotype & AN_RADIOTYPE_80211_DS) 80355992Swpaul printf("802.11 DS"); 80455992Swpaul else if (cfg->an_radiotype & AN_RADIOTYPE_LM2000_DS) 80555992Swpaul printf("LM2000 DS"); 80655992Swpaul else 80755992Swpaul printf("unknown (%x)", cfg->an_radiotype); 80855992Swpaul printf(" ]"); 80955992Swpaul printf("\nRX Diversity:\t\t\t\t[ "); 81080454Sbrooks diversity = cfg->an_diversity & 0xFF; 811108401Sambrisko if (diversity == AN_DIVERSITY_FACTORY_DEFAULT) 812108401Sambrisko printf("factory default"); 813108401Sambrisko else if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY) 81455992Swpaul printf("antenna 1 only"); 81580454Sbrooks else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY) 81655992Swpaul printf("antenna 2 only"); 81780454Sbrooks else if (diversity == AN_DIVERSITY_ANTENNA_1_AND_2) 81855992Swpaul printf("antenna 1 and 2"); 81955992Swpaul printf(" ]"); 82055992Swpaul printf("\nTX Diversity:\t\t\t\t[ "); 82180454Sbrooks diversity = (cfg->an_diversity >> 8) & 0xFF; 822108401Sambrisko if (diversity == AN_DIVERSITY_FACTORY_DEFAULT) 823108401Sambrisko printf("factory default"); 824108401Sambrisko else if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY) 82555992Swpaul printf("antenna 1 only"); 82680454Sbrooks else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY) 82755992Swpaul printf("antenna 2 only"); 82880454Sbrooks else if (diversity == AN_DIVERSITY_ANTENNA_1_AND_2) 82955992Swpaul printf("antenna 1 and 2"); 83055992Swpaul printf(" ]"); 83155992Swpaul printf("\nTransmit power level:\t\t\t"); 83255992Swpaul an_printwords(&cfg->an_tx_power, 1); 83355992Swpaul printf("\nRSS threshold:\t\t\t\t"); 83455992Swpaul an_printwords(&cfg->an_rss_thresh, 1); 83555992Swpaul printf("\nNode name:\t\t\t\t"); 83655992Swpaul an_printstr((char *)&cfg->an_nodename, 16); 83755992Swpaul printf("\nARL threshold:\t\t\t\t"); 83855992Swpaul an_printwords(&cfg->an_arl_thresh, 1); 83955992Swpaul printf("\nARL decay:\t\t\t\t"); 84055992Swpaul an_printwords(&cfg->an_arl_decay, 1); 84155992Swpaul printf("\nARL delay:\t\t\t\t"); 84255992Swpaul an_printwords(&cfg->an_arl_delay, 1); 84388748Sambrisko printf("\nConfiguration:\t\t\t\t[ "); 84488748Sambrisko if (cfg->an_home_product & AN_HOME_NETWORK) 84588748Sambrisko printf("Home Configuration"); 84688748Sambrisko else 84788748Sambrisko printf("Enterprise Configuration"); 84888748Sambrisko printf(" ]"); 84955992Swpaul 85055992Swpaul printf("\n"); 85169772Sarchie printf("\n"); 85269772Sarchie an_readkeyinfo(iface); 85355992Swpaul} 85455992Swpaul 855132860Snjlstatic void 856132860Snjlan_dumprssimap(const char *iface) 857108401Sambrisko{ 858108401Sambrisko struct an_ltv_rssi_map *rssi; 859108401Sambrisko struct an_req areq; 860108401Sambrisko int i; 86155992Swpaul 862108401Sambrisko areq.an_len = sizeof(areq); 863108401Sambrisko areq.an_type = AN_RID_RSSI_MAP; 864108401Sambrisko 865108401Sambrisko an_getval(iface, &areq); 866108401Sambrisko 867108401Sambrisko rssi = (struct an_ltv_rssi_map *)&areq; 868108401Sambrisko 869108401Sambrisko printf("idx\tpct\t dBm\n"); 870108401Sambrisko 871108401Sambrisko for (i = 0; i < 0xFF; i++) { 872108401Sambrisko /* 873108401Sambrisko * negate the dBm value: it's the only way the power 874108401Sambrisko * level makes sense 875108401Sambrisko */ 876108401Sambrisko printf("%3d\t%3d\t%4d\n", i, 877108401Sambrisko rssi->an_entries[i].an_rss_pct, 878108401Sambrisko - rssi->an_entries[i].an_rss_dbm); 879108401Sambrisko } 880108401Sambrisko} 881108401Sambrisko 882132860Snjlstatic void 883132860Snjlusage(const char *p) 88455992Swpaul{ 88555992Swpaul fprintf(stderr, "usage: %s -i iface -A (show specified APs)\n", p); 88655992Swpaul fprintf(stderr, "\t%s -i iface -N (show specified SSIDss)\n", p); 88755992Swpaul fprintf(stderr, "\t%s -i iface -S (show NIC status)\n", p); 88855992Swpaul fprintf(stderr, "\t%s -i iface -I (show NIC capabilities)\n", p); 88955992Swpaul fprintf(stderr, "\t%s -i iface -T (show stats counters)\n", p); 89055992Swpaul fprintf(stderr, "\t%s -i iface -C (show current config)\n", p); 891108401Sambrisko fprintf(stderr, "\t%s -i iface -R (show RSSI map)\n", p); 89289380Sambrisko fprintf(stderr, "\t%s -i iface -t 0-4 (set TX speed)\n", p); 89389380Sambrisko fprintf(stderr, "\t%s -i iface -s 0-3 (set power save mode)\n", p); 89489380Sambrisko fprintf(stderr, "\t%s -i iface [-v 1-4] -a AP (specify AP)\n", p); 89555992Swpaul fprintf(stderr, "\t%s -i iface -b val (set beacon period)\n", p); 89655992Swpaul fprintf(stderr, "\t%s -i iface [-v 0|1] -d val (set diversity)\n", p); 89755992Swpaul fprintf(stderr, "\t%s -i iface -j val (set netjoin timeout)\n", p); 89889380Sambrisko fprintf(stderr, "\t%s -i iface -e 0-4 (enable transmit key)\n", p); 89989380Sambrisko fprintf(stderr, "\t%s -i iface [-v 0-8] -k key (set key)\n", p); 90089380Sambrisko fprintf(stderr, "\t%s -i iface -K 0-2 (no auth/open/shared secret)\n", p); 90189380Sambrisko fprintf(stderr, "\t%s -i iface -W 0-2 (no WEP/full WEP/mixed cell)\n", p); 90255992Swpaul fprintf(stderr, "\t%s -i iface -l val (set station name)\n", p); 90355992Swpaul fprintf(stderr, "\t%s -i iface -m val (set MAC address)\n", p); 90489380Sambrisko fprintf(stderr, "\t%s -i iface [-v 1-3] -n SSID " 90555992Swpaul "(specify SSID)\n", p); 90655992Swpaul fprintf(stderr, "\t%s -i iface -o 0|1 (set operating mode)\n", p); 90755992Swpaul fprintf(stderr, "\t%s -i iface -c val (set ad-hoc channel)\n", p); 90855992Swpaul fprintf(stderr, "\t%s -i iface -f val (set frag threshold)\n", p); 90955992Swpaul fprintf(stderr, "\t%s -i iface -r val (set RTS threshold)\n", p); 91083269Sbrooks fprintf(stderr, "\t%s -i iface -M 0-15 (set monitor mode)\n", p); 91188748Sambrisko fprintf(stderr, "\t%s -i iface -L user (enter LEAP authentication mode)\n", p); 91255992Swpaul#ifdef ANCACHE 91355992Swpaul fprintf(stderr, "\t%s -i iface -Q print signal quality cache\n", p); 91455992Swpaul fprintf(stderr, "\t%s -i iface -Z zero out signal cache\n", p); 91555992Swpaul#endif 91655992Swpaul 91755992Swpaul fprintf(stderr, "\t%s -h (display this message)\n", p); 91855992Swpaul 91955992Swpaul exit(1); 92055992Swpaul} 92155992Swpaul 922132860Snjlstatic void 923132860Snjlan_setconfig(const char *iface, int act, void *arg) 92455992Swpaul{ 92555992Swpaul struct an_ltv_genconfig *cfg; 92655992Swpaul struct an_ltv_caps *caps; 92755992Swpaul struct an_req areq; 92855992Swpaul struct an_req areq_caps; 92955992Swpaul u_int16_t diversity = 0; 93055992Swpaul struct ether_addr *addr; 93155992Swpaul int i; 93255992Swpaul 93355992Swpaul areq.an_len = sizeof(areq); 93455992Swpaul areq.an_type = AN_RID_GENCONFIG; 93555992Swpaul an_getval(iface, &areq); 93655992Swpaul cfg = (struct an_ltv_genconfig *)&areq; 93755992Swpaul 93855992Swpaul areq_caps.an_len = sizeof(areq); 93955992Swpaul areq_caps.an_type = AN_RID_CAPABILITIES; 94055992Swpaul an_getval(iface, &areq_caps); 94155992Swpaul caps = (struct an_ltv_caps *)&areq_caps; 94255992Swpaul 94355992Swpaul switch(act) { 94455992Swpaul case ACT_SET_OPMODE: 94555992Swpaul cfg->an_opmode = atoi(arg); 94655992Swpaul break; 94755992Swpaul case ACT_SET_FREQ: 94855992Swpaul cfg->an_ds_channel = atoi(arg); 94955992Swpaul break; 95055992Swpaul case ACT_SET_PWRSAVE: 95155992Swpaul cfg->an_psave_mode = atoi(arg); 95255992Swpaul break; 95355992Swpaul case ACT_SET_SCANMODE: 95455992Swpaul cfg->an_scanmode = atoi(arg); 95555992Swpaul break; 95655992Swpaul case ACT_SET_DIVERSITY_RX: 95755992Swpaul case ACT_SET_DIVERSITY_TX: 95855992Swpaul switch(atoi(arg)) { 95955992Swpaul case 0: 96055992Swpaul diversity = AN_DIVERSITY_FACTORY_DEFAULT; 96155992Swpaul break; 96255992Swpaul case 1: 96355992Swpaul diversity = AN_DIVERSITY_ANTENNA_1_ONLY; 96455992Swpaul break; 96555992Swpaul case 2: 96655992Swpaul diversity = AN_DIVERSITY_ANTENNA_2_ONLY; 96755992Swpaul break; 96855992Swpaul case 3: 96955992Swpaul diversity = AN_DIVERSITY_ANTENNA_1_AND_2; 97055992Swpaul break; 97155992Swpaul default: 972132860Snjl errx(1, "bad diversity setting: %u", diversity); 97355992Swpaul break; 97455992Swpaul } 975108401Sambrisko if (act == ACT_SET_DIVERSITY_RX) { 976108401Sambrisko cfg->an_diversity &= 0xFF00; 977108401Sambrisko cfg->an_diversity |= diversity; 978108401Sambrisko } else { 97955992Swpaul cfg->an_diversity &= 0x00FF; 98055992Swpaul cfg->an_diversity |= (diversity << 8); 98155992Swpaul } 98255992Swpaul break; 98355992Swpaul case ACT_SET_TXPWR: 98455992Swpaul for (i = 0; i < 8; i++) { 98555992Swpaul if (caps->an_tx_powerlevels[i] == atoi(arg)) 98655992Swpaul break; 98755992Swpaul } 98855992Swpaul if (i == 8) 98955992Swpaul errx(1, "unsupported power level: %dmW", atoi(arg)); 99055992Swpaul 99155992Swpaul cfg->an_tx_power = atoi(arg); 99255992Swpaul break; 99355992Swpaul case ACT_SET_RTS_THRESH: 99455992Swpaul cfg->an_rtsthresh = atoi(arg); 99555992Swpaul break; 99655992Swpaul case ACT_SET_RTS_RETRYLIM: 99755992Swpaul cfg->an_shortretry_limit = 99855992Swpaul cfg->an_longretry_limit = atoi(arg); 99955992Swpaul break; 100055992Swpaul case ACT_SET_BEACON_PERIOD: 100155992Swpaul cfg->an_beacon_period = atoi(arg); 100255992Swpaul break; 100355992Swpaul case ACT_SET_WAKE_DURATION: 100455992Swpaul cfg->an_atim_duration = atoi(arg); 100555992Swpaul break; 100655992Swpaul case ACT_SET_FRAG_THRESH: 100755992Swpaul cfg->an_fragthresh = atoi(arg); 100855992Swpaul break; 100955992Swpaul case ACT_SET_NETJOIN: 101055992Swpaul cfg->an_ibss_join_net_timeout = atoi(arg); 101155992Swpaul break; 101255992Swpaul case ACT_SET_MYNAME: 101355992Swpaul bzero(cfg->an_nodename, 16); 101455992Swpaul strncpy((char *)&cfg->an_nodename, optarg, 16); 101555992Swpaul break; 101655992Swpaul case ACT_SET_MAC: 101755992Swpaul addr = ether_aton((char *)arg); 101855992Swpaul 101955992Swpaul if (addr == NULL) 102055992Swpaul errx(1, "badly formatted address"); 102155992Swpaul bzero(cfg->an_macaddr, ETHER_ADDR_LEN); 1022132900Snjl bcopy(addr, &cfg->an_macaddr, ETHER_ADDR_LEN); 102355992Swpaul break; 102468692Swpaul case ACT_ENABLE_WEP: 102569772Sarchie switch (atoi (arg)) { 102669772Sarchie case 0: 102769772Sarchie /* no WEP */ 102869772Sarchie cfg->an_authtype &= ~(AN_AUTHTYPE_PRIVACY_IN_USE 102988748Sambrisko | AN_AUTHTYPE_ALLOW_UNENCRYPTED 103088748Sambrisko | AN_AUTHTYPE_LEAP); 103169772Sarchie break; 103269772Sarchie case 1: 103369772Sarchie /* full WEP */ 103469772Sarchie cfg->an_authtype |= AN_AUTHTYPE_PRIVACY_IN_USE; 103569772Sarchie cfg->an_authtype &= ~AN_AUTHTYPE_ALLOW_UNENCRYPTED; 103688748Sambrisko cfg->an_authtype &= ~AN_AUTHTYPE_LEAP; 103769772Sarchie break; 103869772Sarchie case 2: 103969772Sarchie /* mixed cell */ 104069772Sarchie cfg->an_authtype = AN_AUTHTYPE_PRIVACY_IN_USE 104169772Sarchie | AN_AUTHTYPE_ALLOW_UNENCRYPTED; 104269772Sarchie break; 104369772Sarchie } 104468692Swpaul break; 104568692Swpaul case ACT_SET_KEY_TYPE: 104668692Swpaul cfg->an_authtype = (cfg->an_authtype & ~AN_AUTHTYPE_MASK) 104768692Swpaul | atoi(arg); 104868692Swpaul break; 104983269Sbrooks case ACT_SET_MONITOR_MODE: 105083269Sbrooks areq.an_type = AN_RID_MONITOR_MODE; 105183269Sbrooks cfg->an_len = atoi(arg); /* mode is put in length */ 105283269Sbrooks break; 105355992Swpaul default: 105455992Swpaul errx(1, "unknown action"); 105555992Swpaul break; 105655992Swpaul } 105755992Swpaul 105855992Swpaul an_setval(iface, &areq); 105955992Swpaul exit(0); 106055992Swpaul} 106155992Swpaul 1062132860Snjlstatic void 1063132860Snjlan_setspeed(const char *iface, int act __unused, void *arg) 106455992Swpaul{ 106555992Swpaul struct an_req areq; 106655992Swpaul struct an_ltv_caps *caps; 106755992Swpaul u_int16_t speed; 106855992Swpaul 106955992Swpaul areq.an_len = sizeof(areq); 107055992Swpaul areq.an_type = AN_RID_CAPABILITIES; 107155992Swpaul 107255992Swpaul an_getval(iface, &areq); 107355992Swpaul caps = (struct an_ltv_caps *)&areq; 107455992Swpaul 107555992Swpaul switch(atoi(arg)) { 107655992Swpaul case 0: 107755992Swpaul speed = 0; 107855992Swpaul break; 107955992Swpaul case 1: 108055992Swpaul speed = AN_RATE_1MBPS; 108155992Swpaul break; 108255992Swpaul case 2: 108355992Swpaul speed = AN_RATE_2MBPS; 108455992Swpaul break; 108555992Swpaul case 3: 108655992Swpaul if (caps->an_rates[2] != AN_RATE_5_5MBPS) 108755992Swpaul errx(1, "5.5Mbps not supported on this card"); 108855992Swpaul speed = AN_RATE_5_5MBPS; 108955992Swpaul break; 109055992Swpaul case 4: 109155992Swpaul if (caps->an_rates[3] != AN_RATE_11MBPS) 109255992Swpaul errx(1, "11Mbps not supported on this card"); 109355992Swpaul speed = AN_RATE_11MBPS; 109455992Swpaul break; 109555992Swpaul default: 109655992Swpaul errx(1, "unsupported speed"); 109755992Swpaul break; 109855992Swpaul } 109955992Swpaul 110055992Swpaul areq.an_len = 6; 110155992Swpaul areq.an_type = AN_RID_TX_SPEED; 110255992Swpaul areq.an_val[0] = speed; 110355992Swpaul 110455992Swpaul an_setval(iface, &areq); 110555992Swpaul exit(0); 110655992Swpaul} 110755992Swpaul 1108132860Snjlstatic void 1109132860Snjlan_setap(const char *iface, int act, void *arg) 111055992Swpaul{ 111155992Swpaul struct an_ltv_aplist *ap; 111255992Swpaul struct an_req areq; 111355992Swpaul struct ether_addr *addr; 111455992Swpaul 111555992Swpaul areq.an_len = sizeof(areq); 111655992Swpaul areq.an_type = AN_RID_APLIST; 111755992Swpaul 111855992Swpaul an_getval(iface, &areq); 111955992Swpaul ap = (struct an_ltv_aplist *)&areq; 112055992Swpaul 112155992Swpaul addr = ether_aton((char *)arg); 112255992Swpaul 112355992Swpaul if (addr == NULL) 112455992Swpaul errx(1, "badly formatted address"); 112555992Swpaul 112655992Swpaul switch(act) { 112755992Swpaul case ACT_SET_AP1: 112855992Swpaul bzero(ap->an_ap1, ETHER_ADDR_LEN); 1129132900Snjl bcopy(addr, &ap->an_ap1, ETHER_ADDR_LEN); 113055992Swpaul break; 113155992Swpaul case ACT_SET_AP2: 113255992Swpaul bzero(ap->an_ap2, ETHER_ADDR_LEN); 1133132900Snjl bcopy(addr, &ap->an_ap2, ETHER_ADDR_LEN); 113455992Swpaul break; 113555992Swpaul case ACT_SET_AP3: 113655992Swpaul bzero(ap->an_ap3, ETHER_ADDR_LEN); 1137132900Snjl bcopy(addr, &ap->an_ap3, ETHER_ADDR_LEN); 113855992Swpaul break; 113955992Swpaul case ACT_SET_AP4: 114055992Swpaul bzero(ap->an_ap4, ETHER_ADDR_LEN); 1141132900Snjl bcopy(addr, &ap->an_ap4, ETHER_ADDR_LEN); 114255992Swpaul break; 114355992Swpaul default: 114455992Swpaul errx(1, "unknown action"); 114555992Swpaul break; 114655992Swpaul } 114755992Swpaul 114855992Swpaul an_setval(iface, &areq); 114955992Swpaul exit(0); 115055992Swpaul} 115155992Swpaul 1152132860Snjlstatic void 1153132860Snjlan_setssid(const char *iface, int act, void *arg) 115455992Swpaul{ 1155119156Sambrisko struct an_ltv_ssidlist_new *ssid; 115655992Swpaul struct an_req areq; 1157119156Sambrisko int max; 115855992Swpaul 115955992Swpaul areq.an_len = sizeof(areq); 116055992Swpaul areq.an_type = AN_RID_SSIDLIST; 116155992Swpaul 116255992Swpaul an_getval(iface, &areq); 1163119156Sambrisko ssid = (struct an_ltv_ssidlist_new *)&areq; 116455992Swpaul 1165119156Sambrisko max = (areq.an_len - 4) / sizeof(struct an_ltv_ssid_entry); 1166119156Sambrisko if ( max > MAX_SSIDS ) { 1167132860Snjl printf("Too many SSIDs only printing %d of %d\n", 1168119156Sambrisko MAX_SSIDS, max); 1169119156Sambrisko max = MAX_SSIDS; 117055992Swpaul } 117155992Swpaul 1172119156Sambrisko if ( act > max ) { 1173119156Sambrisko errx(1, "bad modifier %d: there " 1174119156Sambrisko "are only %d SSID settings", act, max); 1175119156Sambrisko exit(1); 1176119156Sambrisko } 1177119156Sambrisko 1178119156Sambrisko bzero(ssid->an_entry[act-1].an_ssid, 1179119156Sambrisko sizeof(ssid->an_entry[act-1].an_ssid)); 1180119156Sambrisko strlcpy(ssid->an_entry[act-1].an_ssid, (char *)arg, 1181119156Sambrisko sizeof(ssid->an_entry[act-1].an_ssid)); 1182119156Sambrisko ssid->an_entry[act-1].an_len 1183119156Sambrisko = strlen(ssid->an_entry[act-1].an_ssid); 1184119156Sambrisko 118555992Swpaul an_setval(iface, &areq); 1186119156Sambrisko 118755992Swpaul exit(0); 118855992Swpaul} 118955992Swpaul 119055992Swpaul#ifdef ANCACHE 1191132860Snjlstatic void 1192132860Snjlan_zerocache(const char *iface) 119355992Swpaul{ 119455992Swpaul struct an_req areq; 119555992Swpaul 1196132900Snjl bzero(&areq, sizeof(areq)); 119755992Swpaul areq.an_len = 0; 119855992Swpaul areq.an_type = AN_RID_ZERO_CACHE; 119955992Swpaul 120055992Swpaul an_getval(iface, &areq); 120155992Swpaul} 120255992Swpaul 1203132860Snjlstatic void 1204132860Snjlan_readcache(const char *iface) 120555992Swpaul{ 120655992Swpaul struct an_req areq; 1207132900Snjl uint16_t *an_sigitems; 120855992Swpaul struct an_sigcache *sc; 120955992Swpaul int i; 121055992Swpaul 121155992Swpaul if (iface == NULL) 121255992Swpaul errx(1, "must specify interface name"); 121355992Swpaul 1214132900Snjl bzero(&areq, sizeof(areq)); 121555992Swpaul areq.an_len = AN_MAX_DATALEN; 121655992Swpaul areq.an_type = AN_RID_READ_CACHE; 121755992Swpaul 121855992Swpaul an_getval(iface, &areq); 121955992Swpaul 1220132900Snjl an_sigitems = areq.an_val; 1221132900Snjl sc = (struct an_sigcache *)((int32_t *)areq.an_val + 1); 122255992Swpaul 122355992Swpaul for (i = 0; i < *an_sigitems; i++) { 122455992Swpaul printf("[%d/%d]:", i+1, *an_sigitems); 122555992Swpaul printf(" %02x:%02x:%02x:%02x:%02x:%02x,", 122655992Swpaul sc->macsrc[0]&0xff, 122755992Swpaul sc->macsrc[1]&0xff, 122855992Swpaul sc->macsrc[2]&0xff, 122955992Swpaul sc->macsrc[3]&0xff, 123055992Swpaul sc->macsrc[4]&0xff, 123155992Swpaul sc->macsrc[5]&0xff); 123255992Swpaul printf(" %d.%d.%d.%d,",((sc->ipsrc >> 0) & 0xff), 123355992Swpaul ((sc->ipsrc >> 8) & 0xff), 123455992Swpaul ((sc->ipsrc >> 16) & 0xff), 123555992Swpaul ((sc->ipsrc >> 24) & 0xff)); 123655992Swpaul printf(" sig: %d, noise: %d, qual: %d\n", 123755992Swpaul sc->signal, 123855992Swpaul sc->noise, 123955992Swpaul sc->quality); 124055992Swpaul sc++; 124155992Swpaul } 124255992Swpaul} 124355992Swpaul#endif 124455992Swpaul 1245132860Snjlstatic int 1246132860Snjlan_hex2int(char c) 124768692Swpaul{ 124868692Swpaul if (c >= '0' && c <= '9') 124968692Swpaul return (c - '0'); 125068692Swpaul if (c >= 'A' && c <= 'F') 125168692Swpaul return (c - 'A' + 10); 125268692Swpaul if (c >= 'a' && c <= 'f') 125368692Swpaul return (c - 'a' + 10); 125455992Swpaul 125568692Swpaul return (0); 125668692Swpaul} 125768692Swpaul 1258132860Snjlstatic void 1259132860Snjlan_str2key(const char *s, struct an_ltv_key *k) 126068692Swpaul{ 126168692Swpaul int n, i; 126268692Swpaul char *p; 126368692Swpaul 126468692Swpaul /* Is this a hex string? */ 126568692Swpaul if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { 126668692Swpaul /* Yes, convert to int. */ 126768692Swpaul n = 0; 126868692Swpaul p = (char *)&k->key[0]; 126980454Sbrooks for (i = 2; s[i] != '\0' && s[i + 1] != '\0'; i+= 2) { 127068692Swpaul *p++ = (an_hex2int(s[i]) << 4) + an_hex2int(s[i + 1]); 127168692Swpaul n++; 127268692Swpaul } 127380454Sbrooks if (s[i] != '\0') 127480454Sbrooks errx(1, "hex strings must be of even length"); 127568692Swpaul k->klen = n; 127668692Swpaul } else { 127768692Swpaul /* No, just copy it in. */ 127868692Swpaul bcopy(s, k->key, strlen(s)); 127968692Swpaul k->klen = strlen(s); 128068692Swpaul } 128168692Swpaul 128268692Swpaul return; 128368692Swpaul} 128468692Swpaul 1285132860Snjlstatic void 1286132860Snjlan_setkeys(const char *iface, const char *key, int keytype) 128768692Swpaul{ 128868692Swpaul struct an_req areq; 128968692Swpaul struct an_ltv_key *k; 129068692Swpaul 1291132900Snjl bzero(&areq, sizeof(areq)); 129268692Swpaul k = (struct an_ltv_key *)&areq; 129368692Swpaul 129468692Swpaul if (strlen(key) > 28) { 129568692Swpaul err(1, "encryption key must be no " 129668692Swpaul "more than 18 characters long"); 129768692Swpaul } 129868692Swpaul 129968692Swpaul an_str2key(key, k); 130068692Swpaul 130168692Swpaul k->kindex=keytype/2; 130268692Swpaul 130368692Swpaul if (!(k->klen==0 || k->klen==5 || k->klen==13)) { 130468692Swpaul err(1, "encryption key must be 0, 5 or 13 bytes long"); 130568692Swpaul } 130668692Swpaul 130768692Swpaul /* default mac and only valid one (from manual) 1.0.0.0.0.0 */ 130868692Swpaul k->mac[0]=1; 130968692Swpaul k->mac[1]=0; 131068692Swpaul k->mac[2]=0; 131168692Swpaul k->mac[3]=0; 131268692Swpaul k->mac[4]=0; 131368692Swpaul k->mac[5]=0; 131468692Swpaul 131588748Sambrisko switch(keytype & 1) { 131668692Swpaul case 0: 131768692Swpaul areq.an_len = sizeof(struct an_ltv_key); 131868692Swpaul areq.an_type = AN_RID_WEP_PERM; 131968692Swpaul an_setval(iface, &areq); 132068692Swpaul break; 132168692Swpaul case 1: 132268692Swpaul areq.an_len = sizeof(struct an_ltv_key); 132368692Swpaul areq.an_type = AN_RID_WEP_TEMP; 132468692Swpaul an_setval(iface, &areq); 132568692Swpaul break; 132668692Swpaul } 132768692Swpaul} 132868692Swpaul 1329201387Sedstatic void 1330201387Sedan_readkeyinfo(const char *iface) 133169772Sarchie{ 133269772Sarchie struct an_req areq; 133389380Sambrisko struct an_ltv_genconfig *cfg; 133469772Sarchie struct an_ltv_key *k; 133569772Sarchie int i; 133689380Sambrisko int home; 133769772Sarchie 133889380Sambrisko areq.an_len = sizeof(areq); 133989380Sambrisko areq.an_type = AN_RID_ACTUALCFG; 134089380Sambrisko an_getval(iface, &areq); 134189380Sambrisko cfg = (struct an_ltv_genconfig *)&areq; 134289380Sambrisko if (cfg->an_home_product & AN_HOME_NETWORK) 134389380Sambrisko home = 1; 134489380Sambrisko else 134589380Sambrisko home = 0; 134689380Sambrisko 1347132900Snjl bzero(&areq, sizeof(areq)); 134869772Sarchie k = (struct an_ltv_key *)&areq; 134969772Sarchie 135069772Sarchie printf("WEP Key status:\n"); 135169772Sarchie areq.an_type = AN_RID_WEP_TEMP; /* read first key */ 135288748Sambrisko for(i=0; i<5; i++) { 135369772Sarchie areq.an_len = sizeof(struct an_ltv_key); 135469772Sarchie an_getval(iface, &areq); 135588748Sambrisko if (k->kindex == 0xffff) 135683269Sbrooks break; 135788748Sambrisko switch (k->klen) { 135869772Sarchie case 0: 1359132860Snjl printf("\tKey %u is unset\n", k->kindex); 136069772Sarchie break; 136169772Sarchie case 5: 1362132860Snjl printf("\tKey %u is set 40 bits\n", k->kindex); 136369772Sarchie break; 136469772Sarchie case 13: 1365132860Snjl printf("\tKey %u is set 128 bits\n", k->kindex); 136669772Sarchie break; 136769772Sarchie default: 1368132860Snjl printf("\tWEP Key %d has an unknown size %u\n", 136969772Sarchie i, k->klen); 137069772Sarchie } 137169772Sarchie 137269772Sarchie areq.an_type = AN_RID_WEP_PERM; /* read next key */ 137369772Sarchie } 137469772Sarchie k->kindex = 0xffff; 137569772Sarchie areq.an_len = sizeof(struct an_ltv_key); 137669772Sarchie an_getval(iface, &areq); 137789380Sambrisko printf("\tThe active transmit key is %d\n", 4 * home + k->mac[0]); 137869772Sarchie 137969772Sarchie return; 138069772Sarchie} 138169772Sarchie 1382132860Snjlstatic void 1383132860Snjlan_enable_tx_key(const char *iface, const char *arg) 138469772Sarchie{ 138569772Sarchie struct an_req areq; 138669772Sarchie struct an_ltv_key *k; 138788748Sambrisko struct an_ltv_genconfig *config; 138869772Sarchie 1389132900Snjl bzero(&areq, sizeof(areq)); 139088748Sambrisko 139188748Sambrisko /* set home or not home mode */ 139288748Sambrisko areq.an_len = sizeof(struct an_ltv_genconfig); 139388748Sambrisko areq.an_type = AN_RID_GENCONFIG; 139488748Sambrisko an_getval(iface, &areq); 139588748Sambrisko config = (struct an_ltv_genconfig *)&areq; 139688748Sambrisko if (atoi(arg) == 4) { 139788748Sambrisko config->an_home_product |= AN_HOME_NETWORK; 139888748Sambrisko }else{ 139988748Sambrisko config->an_home_product &= ~AN_HOME_NETWORK; 140088748Sambrisko } 140188748Sambrisko an_setval(iface, &areq); 140288748Sambrisko 1403132900Snjl bzero(&areq, sizeof(areq)); 140488748Sambrisko 140569772Sarchie k = (struct an_ltv_key *)&areq; 140669772Sarchie 140769772Sarchie /* From a Cisco engineer write the transmit key to use in the 140869772Sarchie first MAC, index is FFFF*/ 140969772Sarchie k->kindex=0xffff; 141069772Sarchie k->klen=0; 141169772Sarchie 141269772Sarchie k->mac[0]=atoi(arg); 141369772Sarchie k->mac[1]=0; 141469772Sarchie k->mac[2]=0; 141569772Sarchie k->mac[3]=0; 141669772Sarchie k->mac[4]=0; 141769772Sarchie k->mac[5]=0; 141869772Sarchie 141969772Sarchie areq.an_len = sizeof(struct an_ltv_key); 142069772Sarchie areq.an_type = AN_RID_WEP_PERM; 142169772Sarchie an_setval(iface, &areq); 142269772Sarchie} 142369772Sarchie 1424132860Snjlstatic void 1425132860Snjlan_enable_leap_mode(const char *iface, const char *username) 142688748Sambrisko{ 142788748Sambrisko struct an_req areq; 142888748Sambrisko struct an_ltv_status *sts; 142988748Sambrisko struct an_ltv_genconfig *cfg; 143088748Sambrisko struct an_ltv_caps *caps; 143188748Sambrisko struct an_ltv_leap_username an_username; 143288748Sambrisko struct an_ltv_leap_password an_password; 143388748Sambrisko char *password; 143488748Sambrisko MD4_CTX context; 143588748Sambrisko int len; 143688748Sambrisko int i; 143788748Sambrisko char unicode_password[LEAP_PASSWORD_MAX * 2]; 143888748Sambrisko 143988748Sambrisko areq.an_len = sizeof(areq); 144088748Sambrisko areq.an_type = AN_RID_CAPABILITIES; 144188748Sambrisko 144288748Sambrisko an_getval(iface, &areq); 144388748Sambrisko 144488748Sambrisko caps = (struct an_ltv_caps *)&areq; 144588748Sambrisko 1446238221Seadler if (!(caps->an_softcaps & AN_AUTHTYPE_LEAP)) { 144788748Sambrisko fprintf(stderr, "Firmware does not support LEAP\n"); 144888748Sambrisko exit(1); 144988748Sambrisko } 145088748Sambrisko 145188748Sambrisko bzero(&an_username, sizeof(an_username)); 145288748Sambrisko bzero(&an_password, sizeof(an_password)); 145388748Sambrisko 145488748Sambrisko len = strlen(username); 145588748Sambrisko if (len > LEAP_USERNAME_MAX) { 145688748Sambrisko printf("Username too long (max %d)\n", LEAP_USERNAME_MAX); 145788748Sambrisko exit(1); 145888748Sambrisko } 145988748Sambrisko strncpy(an_username.an_username, username, len); 146088748Sambrisko an_username.an_username_len = len; 146188748Sambrisko an_username.an_len = sizeof(an_username); 146288748Sambrisko an_username.an_type = AN_RID_LEAPUSERNAME; 146388748Sambrisko 146488748Sambrisko password = getpass("Enter LEAP password:"); 146588748Sambrisko 146688748Sambrisko len = strlen(password); 146788748Sambrisko if (len > LEAP_PASSWORD_MAX) { 146888748Sambrisko printf("Password too long (max %d)\n", LEAP_PASSWORD_MAX); 146988748Sambrisko exit(1); 147088748Sambrisko } 147188748Sambrisko 147288748Sambrisko bzero(&unicode_password, sizeof(unicode_password)); 147388748Sambrisko for(i = 0; i < len; i++) { 147488748Sambrisko unicode_password[i * 2] = *password++; 147588748Sambrisko } 147688748Sambrisko 147788748Sambrisko /* First half */ 147888748Sambrisko MD4Init(&context); 147988748Sambrisko MD4Update(&context, unicode_password, len * 2); 148088748Sambrisko MD4Final(&an_password.an_password[0], &context); 148188748Sambrisko 148288748Sambrisko /* Second half */ 148388748Sambrisko MD4Init (&context); 148488748Sambrisko MD4Update (&context, &an_password.an_password[0], 16); 148588748Sambrisko MD4Final (&an_password.an_password[16], &context); 148688748Sambrisko 148788748Sambrisko an_password.an_password_len = 32; 148888748Sambrisko an_password.an_len = sizeof(an_password); 148988748Sambrisko an_password.an_type = AN_RID_LEAPPASSWORD; 149088748Sambrisko 149188748Sambrisko an_setval(iface, (struct an_req *)&an_username); 149288748Sambrisko an_setval(iface, (struct an_req *)&an_password); 149388748Sambrisko 149488748Sambrisko areq.an_len = sizeof(areq); 149588748Sambrisko areq.an_type = AN_RID_GENCONFIG; 149688748Sambrisko an_getval(iface, &areq); 149788748Sambrisko cfg = (struct an_ltv_genconfig *)&areq; 149888748Sambrisko cfg->an_authtype = (AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP); 149988748Sambrisko an_setval(iface, &areq); 150088748Sambrisko 150188748Sambrisko sts = (struct an_ltv_status *)&areq; 150288748Sambrisko areq.an_type = AN_RID_STATUS; 150388748Sambrisko 150488748Sambrisko for (i = 60; i > 0; i--) { 150588748Sambrisko an_getval(iface, &areq); 150688748Sambrisko if (sts->an_opmode & AN_STATUS_OPMODE_LEAP) { 150788748Sambrisko printf("Authenticated\n"); 150888748Sambrisko break; 150988748Sambrisko } 151088748Sambrisko sleep(1); 151188748Sambrisko } 151288748Sambrisko 151388748Sambrisko if (i == 0) { 151488748Sambrisko fprintf(stderr, "Failed LEAP authentication\n"); 151588748Sambrisko exit(1); 151688748Sambrisko } 151788748Sambrisko} 151888748Sambrisko 1519132860Snjlint 1520132860Snjlmain(int argc, char *argv[]) 152155992Swpaul{ 152255992Swpaul int ch; 152355992Swpaul int act = 0; 152480454Sbrooks const char *iface = NULL; 152555992Swpaul int modifier = 0; 152668692Swpaul char *key = NULL; 152755992Swpaul void *arg = NULL; 152855992Swpaul char *p = argv[0]; 152955992Swpaul 153067823Sjoe /* Get the interface name */ 153167823Sjoe opterr = 0; 153267823Sjoe ch = getopt(argc, argv, "i:"); 153367823Sjoe if (ch == 'i') { 153467823Sjoe iface = optarg; 153567823Sjoe } else { 153670532Simp if (argc > 1 && *argv[1] != '-') { 153770532Simp iface = argv[1]; 153870532Simp optind = 2; 153970532Simp } else { 154070532Simp iface = "an0"; 154170532Simp optind = 1; 154270532Simp } 154367823Sjoe optreset = 1; 154467823Sjoe } 154567823Sjoe opterr = 1; 154667823Sjoe 154755992Swpaul while ((ch = getopt(argc, argv, 1548137169Sceri "ANISCTRht:a:e:o:s:n:v:d:j:b:c:f:r:p:w:m:l:k:K:W:QZM:L:")) != -1) { 154955992Swpaul switch(ch) { 155055992Swpaul case 'Z': 155155992Swpaul#ifdef ANCACHE 155255992Swpaul act = ACT_ZEROCACHE; 155355992Swpaul#else 155455992Swpaul errx(1, "ANCACHE not available"); 155555992Swpaul#endif 155655992Swpaul break; 155755992Swpaul case 'Q': 155855992Swpaul#ifdef ANCACHE 155955992Swpaul act = ACT_DUMPCACHE; 156055992Swpaul#else 156155992Swpaul errx(1, "ANCACHE not available"); 156255992Swpaul#endif 156355992Swpaul break; 156455992Swpaul case 'A': 156555992Swpaul act = ACT_DUMPAP; 156655992Swpaul break; 156755992Swpaul case 'N': 156855992Swpaul act = ACT_DUMPSSID; 156955992Swpaul break; 157055992Swpaul case 'S': 157155992Swpaul act = ACT_DUMPSTATUS; 157255992Swpaul break; 157355992Swpaul case 'I': 157455992Swpaul act = ACT_DUMPCAPS; 157555992Swpaul break; 157655992Swpaul case 'T': 157755992Swpaul act = ACT_DUMPSTATS; 157855992Swpaul break; 157955992Swpaul case 'C': 158055992Swpaul act = ACT_DUMPCONFIG; 158155992Swpaul break; 1582108401Sambrisko case 'R': 1583108401Sambrisko act = ACT_DUMPRSSIMAP; 1584108401Sambrisko break; 158555992Swpaul case 't': 158655992Swpaul act = ACT_SET_TXRATE; 158755992Swpaul arg = optarg; 158855992Swpaul break; 158955992Swpaul case 's': 159055992Swpaul act = ACT_SET_PWRSAVE; 159155992Swpaul arg = optarg; 159255992Swpaul break; 159355992Swpaul case 'p': 159455992Swpaul act = ACT_SET_TXPWR; 159555992Swpaul arg = optarg; 159655992Swpaul break; 159755992Swpaul case 'v': 159855992Swpaul modifier = atoi(optarg); 159955992Swpaul break; 160055992Swpaul case 'a': 160155992Swpaul switch(modifier) { 160255992Swpaul case 0: 160355992Swpaul case 1: 160455992Swpaul act = ACT_SET_AP1; 160555992Swpaul break; 160655992Swpaul case 2: 160755992Swpaul act = ACT_SET_AP2; 160855992Swpaul break; 160955992Swpaul case 3: 161055992Swpaul act = ACT_SET_AP3; 161155992Swpaul break; 161255992Swpaul case 4: 161355992Swpaul act = ACT_SET_AP4; 161455992Swpaul break; 161555992Swpaul default: 161655992Swpaul errx(1, "bad modifier %d: there " 161755992Swpaul "are only 4 access point settings", 161855992Swpaul modifier); 161955992Swpaul usage(p); 162055992Swpaul break; 162155992Swpaul } 162255992Swpaul arg = optarg; 162355992Swpaul break; 162455992Swpaul case 'b': 162555992Swpaul act = ACT_SET_BEACON_PERIOD; 162655992Swpaul arg = optarg; 162755992Swpaul break; 162855992Swpaul case 'd': 162955992Swpaul switch(modifier) { 163055992Swpaul case 0: 163155992Swpaul act = ACT_SET_DIVERSITY_RX; 163255992Swpaul break; 163355992Swpaul case 1: 163455992Swpaul act = ACT_SET_DIVERSITY_TX; 163555992Swpaul break; 163655992Swpaul default: 1637108401Sambrisko errx(1, "must specify RX or TX diversity"); 163855992Swpaul break; 163955992Swpaul } 1640108401Sambrisko if (!isdigit(*optarg)) { 1641108401Sambrisko errx(1, "%s is not numeric", optarg); 1642108401Sambrisko exit(1); 1643108401Sambrisko } 164455992Swpaul arg = optarg; 164555992Swpaul break; 164655992Swpaul case 'j': 164755992Swpaul act = ACT_SET_NETJOIN; 164855992Swpaul arg = optarg; 164955992Swpaul break; 165055992Swpaul case 'l': 165155992Swpaul act = ACT_SET_MYNAME; 165255992Swpaul arg = optarg; 165355992Swpaul break; 165455992Swpaul case 'm': 165555992Swpaul act = ACT_SET_MAC; 165655992Swpaul arg = optarg; 165755992Swpaul break; 165855992Swpaul case 'n': 1659119156Sambrisko if (modifier == 0) 1660119156Sambrisko modifier = 1; 1661119156Sambrisko act = ACT_SET_SSID; 166255992Swpaul arg = optarg; 166355992Swpaul break; 166455992Swpaul case 'o': 166555992Swpaul act = ACT_SET_OPMODE; 166655992Swpaul arg = optarg; 166755992Swpaul break; 166855992Swpaul case 'c': 166955992Swpaul act = ACT_SET_FREQ; 167055992Swpaul arg = optarg; 167155992Swpaul break; 167255992Swpaul case 'f': 167355992Swpaul act = ACT_SET_FRAG_THRESH; 167455992Swpaul arg = optarg; 167555992Swpaul break; 167668692Swpaul case 'W': 167768692Swpaul act = ACT_ENABLE_WEP; 167868692Swpaul arg = optarg; 167968692Swpaul break; 168068692Swpaul case 'K': 168168692Swpaul act = ACT_SET_KEY_TYPE; 168268692Swpaul arg = optarg; 168368692Swpaul break; 168468692Swpaul case 'k': 168568692Swpaul act = ACT_SET_KEYS; 168668692Swpaul key = optarg; 168768692Swpaul break; 168869772Sarchie case 'e': 168969772Sarchie act = ACT_ENABLE_TX_KEY; 169069772Sarchie arg = optarg; 169169772Sarchie break; 169255992Swpaul case 'q': 169355992Swpaul act = ACT_SET_RTS_RETRYLIM; 169455992Swpaul arg = optarg; 169555992Swpaul break; 169655992Swpaul case 'r': 169755992Swpaul act = ACT_SET_RTS_THRESH; 169855992Swpaul arg = optarg; 169955992Swpaul break; 170055992Swpaul case 'w': 170155992Swpaul act = ACT_SET_WAKE_DURATION; 170255992Swpaul arg = optarg; 170355992Swpaul break; 170483269Sbrooks case 'M': 170583269Sbrooks act = ACT_SET_MONITOR_MODE; 170683269Sbrooks arg = optarg; 170783269Sbrooks break; 170888748Sambrisko case 'L': 170988748Sambrisko act = ACT_SET_LEAP_MODE; 171088748Sambrisko arg = optarg; 171188748Sambrisko break; 171255992Swpaul case 'h': 171355992Swpaul default: 171455992Swpaul usage(p); 171555992Swpaul } 171655992Swpaul } 171755992Swpaul 171868692Swpaul if (iface == NULL || (!act && !key)) 171955992Swpaul usage(p); 172055992Swpaul 172155992Swpaul switch(act) { 172255992Swpaul case ACT_DUMPSTATUS: 172355992Swpaul an_dumpstatus(iface); 172455992Swpaul break; 172555992Swpaul case ACT_DUMPCAPS: 172655992Swpaul an_dumpcaps(iface); 172755992Swpaul break; 172855992Swpaul case ACT_DUMPSTATS: 172955992Swpaul an_dumpstats(iface); 173055992Swpaul break; 173155992Swpaul case ACT_DUMPCONFIG: 173255992Swpaul an_dumpconfig(iface); 173355992Swpaul break; 173455992Swpaul case ACT_DUMPSSID: 173555992Swpaul an_dumpssid(iface); 173655992Swpaul break; 173755992Swpaul case ACT_DUMPAP: 173855992Swpaul an_dumpap(iface); 173955992Swpaul break; 1740108401Sambrisko case ACT_DUMPRSSIMAP: 1741108401Sambrisko an_dumprssimap(iface); 1742108401Sambrisko break; 1743119156Sambrisko case ACT_SET_SSID: 1744119156Sambrisko an_setssid(iface, modifier, arg); 174555992Swpaul break; 174655992Swpaul case ACT_SET_AP1: 174755992Swpaul case ACT_SET_AP2: 174855992Swpaul case ACT_SET_AP3: 174955992Swpaul case ACT_SET_AP4: 175055992Swpaul an_setap(iface, act, arg); 175155992Swpaul break; 175255992Swpaul case ACT_SET_TXRATE: 175355992Swpaul an_setspeed(iface, act, arg); 175455992Swpaul break; 175555992Swpaul#ifdef ANCACHE 175655992Swpaul case ACT_ZEROCACHE: 175755992Swpaul an_zerocache(iface); 175855992Swpaul break; 175955992Swpaul case ACT_DUMPCACHE: 176055992Swpaul an_readcache(iface); 176155992Swpaul break; 176268692Swpaul 176355992Swpaul#endif 176468692Swpaul case ACT_SET_KEYS: 176568692Swpaul an_setkeys(iface, key, modifier); 176668692Swpaul break; 176769772Sarchie case ACT_ENABLE_TX_KEY: 176869772Sarchie an_enable_tx_key(iface, arg); 176969772Sarchie break; 177088748Sambrisko case ACT_SET_LEAP_MODE: 177188748Sambrisko an_enable_leap_mode(iface, arg); 177288748Sambrisko break; 177355992Swpaul default: 177455992Swpaul an_setconfig(iface, act, arg); 177555992Swpaul break; 177655992Swpaul } 177755992Swpaul 177855992Swpaul exit(0); 177955992Swpaul} 178055992Swpaul 1781