ancontrol.c revision 201387
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: head/usr.sbin/ancontrol/ancontrol.c 201387 2010-01-02 11:05:34Z ed $"); 4181586Sru 4255992Swpaul#include <sys/types.h> 4355992Swpaul#include <sys/cdefs.h> 4455992Swpaul#include <sys/socket.h> 4555992Swpaul#include <sys/ioctl.h> 4655992Swpaul 4790868Smike#include <arpa/inet.h> 4890868Smike 4955992Swpaul#include <net/if.h> 5055992Swpaul#include <net/if_var.h> 5155992Swpaul#include <net/ethernet.h> 5255992Swpaul 5355992Swpaul#include <dev/an/if_aironet_ieee.h> 5455992Swpaul 5555992Swpaul#include <stdio.h> 5655992Swpaul#include <string.h> 5755992Swpaul#include <stdlib.h> 5855992Swpaul#include <unistd.h> 5955992Swpaul#include <errno.h> 6055992Swpaul#include <err.h> 6188748Sambrisko#include <md4.h> 62108401Sambrisko#include <ctype.h> 6355992Swpaul 64108401Sambriskostatic int an_getval(const char *, struct an_req *); 6599800Salfredstatic void an_setval(const char *, struct an_req *); 66132860Snjlstatic void an_printwords(const u_int16_t *, int); 67132860Snjlstatic void an_printspeeds(const u_int8_t *, int); 6899800Salfredstatic void an_printbool(int); 69132860Snjlstatic void an_printhex(const char *, int); 7099800Salfredstatic void an_printstr(char *, int); 7199800Salfredstatic void an_dumpstatus(const char *); 7299800Salfredstatic void an_dumpstats(const char *); 7399800Salfredstatic void an_dumpconfig(const char *); 7499800Salfredstatic void an_dumpcaps(const char *); 7599800Salfredstatic void an_dumpssid(const char *); 7699800Salfredstatic void an_dumpap(const char *); 7799800Salfredstatic void an_setconfig(const char *, int, void *); 7899800Salfredstatic void an_setssid(const char *, int, void *); 7999800Salfredstatic void an_setap(const char *, int, void *); 8099800Salfredstatic void an_setspeed(const char *, int, void *); 8199800Salfredstatic void an_readkeyinfo(const char *); 8255992Swpaul#ifdef ANCACHE 8399800Salfredstatic void an_zerocache(const char *); 8499800Salfredstatic void an_readcache(const char *); 8555992Swpaul#endif 8699800Salfredstatic int an_hex2int(char); 87132860Snjlstatic void an_str2key(const char *, struct an_ltv_key *); 88132860Snjlstatic void an_setkeys(const char *, const char *, int); 89132860Snjlstatic void an_enable_tx_key(const char *, const char *); 90132860Snjlstatic void an_enable_leap_mode(const char *, const char *); 91108401Sambriskostatic void an_dumprssimap(const char *); 92132860Snjlstatic void usage(const char *); 9355992Swpaul 9455992Swpaul#define ACT_DUMPSTATS 1 9555992Swpaul#define ACT_DUMPCONFIG 2 9655992Swpaul#define ACT_DUMPSTATUS 3 9755992Swpaul#define ACT_DUMPCAPS 4 9855992Swpaul#define ACT_DUMPSSID 5 9955992Swpaul#define ACT_DUMPAP 6 10055992Swpaul 10155992Swpaul#define ACT_SET_OPMODE 7 102119156Sambrisko#define ACT_SET_SSID 8 10355992Swpaul#define ACT_SET_FREQ 11 10455992Swpaul#define ACT_SET_AP1 12 10555992Swpaul#define ACT_SET_AP2 13 10655992Swpaul#define ACT_SET_AP3 14 10755992Swpaul#define ACT_SET_AP4 15 10855992Swpaul#define ACT_SET_DRIVERNAME 16 10955992Swpaul#define ACT_SET_SCANMODE 17 11055992Swpaul#define ACT_SET_TXRATE 18 11155992Swpaul#define ACT_SET_RTS_THRESH 19 11255992Swpaul#define ACT_SET_PWRSAVE 20 11355992Swpaul#define ACT_SET_DIVERSITY_RX 21 11455992Swpaul#define ACT_SET_DIVERSITY_TX 22 11555992Swpaul#define ACT_SET_RTS_RETRYLIM 23 11655992Swpaul#define ACT_SET_WAKE_DURATION 24 11755992Swpaul#define ACT_SET_BEACON_PERIOD 25 11855992Swpaul#define ACT_SET_TXPWR 26 11955992Swpaul#define ACT_SET_FRAG_THRESH 27 12055992Swpaul#define ACT_SET_NETJOIN 28 12155992Swpaul#define ACT_SET_MYNAME 29 12255992Swpaul#define ACT_SET_MAC 30 12355992Swpaul 12455992Swpaul#define ACT_DUMPCACHE 31 12555992Swpaul#define ACT_ZEROCACHE 32 12655992Swpaul 12768692Swpaul#define ACT_ENABLE_WEP 33 12868692Swpaul#define ACT_SET_KEY_TYPE 34 12968692Swpaul#define ACT_SET_KEYS 35 13069772Sarchie#define ACT_ENABLE_TX_KEY 36 13183269Sbrooks#define ACT_SET_MONITOR_MODE 37 13288748Sambrisko#define ACT_SET_LEAP_MODE 38 13368692Swpaul 134108401Sambrisko#define ACT_DUMPRSSIMAP 39 135108401Sambrisko 136132860Snjlstatic int 137132860Snjlan_getval(const char *iface, struct an_req *areq) 13855992Swpaul{ 13955992Swpaul struct ifreq ifr; 140108401Sambrisko int s, okay = 1; 14155992Swpaul 142132900Snjl bzero(&ifr, sizeof(ifr)); 14355992Swpaul 14461815Sroberto strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); 14555992Swpaul ifr.ifr_data = (caddr_t)areq; 14655992Swpaul 14755992Swpaul s = socket(AF_INET, SOCK_DGRAM, 0); 14855992Swpaul 14955992Swpaul if (s == -1) 15055992Swpaul err(1, "socket"); 15155992Swpaul 152108401Sambrisko if (ioctl(s, SIOCGAIRONET, &ifr) == -1) { 153108401Sambrisko okay = 0; 15455992Swpaul err(1, "SIOCGAIRONET"); 155108401Sambrisko } 15655992Swpaul 15755992Swpaul close(s); 15855992Swpaul 159132860Snjl return (okay); 16055992Swpaul} 16155992Swpaul 162132860Snjlstatic void 163132860Snjlan_setval(const char *iface, struct an_req *areq) 16455992Swpaul{ 16555992Swpaul struct ifreq ifr; 16655992Swpaul int s; 16755992Swpaul 168132900Snjl bzero(&ifr, sizeof(ifr)); 16955992Swpaul 17061815Sroberto strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); 17155992Swpaul ifr.ifr_data = (caddr_t)areq; 17255992Swpaul 17355992Swpaul s = socket(AF_INET, SOCK_DGRAM, 0); 17455992Swpaul 17555992Swpaul if (s == -1) 17655992Swpaul err(1, "socket"); 17755992Swpaul 17855992Swpaul if (ioctl(s, SIOCSAIRONET, &ifr) == -1) 17955992Swpaul err(1, "SIOCSAIRONET"); 18055992Swpaul 18155992Swpaul close(s); 18255992Swpaul 18355992Swpaul return; 18455992Swpaul} 18555992Swpaul 186132860Snjlstatic void 187132860Snjlan_printstr(char *str, int len) 18855992Swpaul{ 18955992Swpaul int i; 19055992Swpaul 19155992Swpaul for (i = 0; i < len - 1; i++) { 19255992Swpaul if (str[i] == '\0') 19355992Swpaul str[i] = ' '; 19455992Swpaul } 19555992Swpaul 19655992Swpaul printf("[ %.*s ]", len, str); 19755992Swpaul} 19855992Swpaul 199132860Snjlstatic void 200132860Snjlan_printwords(const u_int16_t *w, int len) 20155992Swpaul{ 20255992Swpaul int i; 20355992Swpaul 20455992Swpaul printf("[ "); 20555992Swpaul for (i = 0; i < len; i++) 206132860Snjl printf("%u ", w[i]); 20755992Swpaul printf("]"); 20855992Swpaul} 20955992Swpaul 210132860Snjlstatic void 211132860Snjlan_printspeeds(const u_int8_t *w, int len) 21255992Swpaul{ 21355992Swpaul int i; 21455992Swpaul 21555992Swpaul printf("[ "); 21655992Swpaul for (i = 0; i < len && w[i]; i++) 21755992Swpaul printf("%2.1fMbps ", w[i] * 0.500); 21855992Swpaul printf("]"); 21955992Swpaul} 22055992Swpaul 221132860Snjlstatic void 222132860Snjlan_printbool(int val) 22355992Swpaul{ 22455992Swpaul if (val) 22555992Swpaul printf("[ On ]"); 22655992Swpaul else 22755992Swpaul printf("[ Off ]"); 22855992Swpaul} 22955992Swpaul 230132860Snjlstatic void 231132860Snjlan_printhex(const char *ptr, int len) 23255992Swpaul{ 23355992Swpaul int i; 23455992Swpaul 23555992Swpaul printf("[ "); 23655992Swpaul for (i = 0; i < len; i++) { 23755992Swpaul printf("%02x", ptr[i] & 0xFF); 23855992Swpaul if (i < (len - 1)) 23955992Swpaul printf(":"); 24055992Swpaul } 24155992Swpaul 24255992Swpaul printf(" ]"); 24355992Swpaul} 24455992Swpaul 24568692Swpaul 24668692Swpaul 247132860Snjlstatic void 248132860Snjlan_dumpstatus(const char *iface) 24955992Swpaul{ 25055992Swpaul struct an_ltv_status *sts; 25155992Swpaul struct an_req areq; 252108401Sambrisko struct an_ltv_rssi_map an_rssimap; 253108401Sambrisko int rssimap_valid = 0; 25455992Swpaul 255108401Sambrisko /* 256108401Sambrisko * Try to get RSSI to percent and dBM table 257108401Sambrisko */ 258108401Sambrisko 259108401Sambrisko an_rssimap.an_len = sizeof(an_rssimap); 260108401Sambrisko an_rssimap.an_type = AN_RID_RSSI_MAP; 261108401Sambrisko rssimap_valid = an_getval(iface, (struct an_req*)&an_rssimap); 262108401Sambrisko 263108401Sambrisko if (rssimap_valid) 264108401Sambrisko printf("RSSI table:\t\t[ present ]\n"); 265108401Sambrisko else 266108401Sambrisko printf("RSSI table:\t\t[ not available ]\n"); 267108401Sambrisko 26855992Swpaul areq.an_len = sizeof(areq); 26955992Swpaul areq.an_type = AN_RID_STATUS; 27055992Swpaul 27155992Swpaul an_getval(iface, &areq); 27255992Swpaul 27355992Swpaul sts = (struct an_ltv_status *)&areq; 27455992Swpaul 27555992Swpaul printf("MAC address:\t\t"); 27655992Swpaul an_printhex((char *)&sts->an_macaddr, ETHER_ADDR_LEN); 27755992Swpaul printf("\nOperating mode:\t\t[ "); 27855992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_CONFIGURED) 27955992Swpaul printf("configured "); 28055992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_MAC_ENABLED) 28155992Swpaul printf("MAC ON "); 28255992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_RX_ENABLED) 28355992Swpaul printf("RX ON "); 28455992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_IN_SYNC) 28555992Swpaul printf("synced "); 28655992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_ASSOCIATED) 28755992Swpaul printf("associated "); 28888748Sambrisko if (sts->an_opmode & AN_STATUS_OPMODE_LEAP) 28988748Sambrisko printf("LEAP "); 29055992Swpaul if (sts->an_opmode & AN_STATUS_OPMODE_ERROR) 29155992Swpaul printf("error "); 29255992Swpaul printf("]\n"); 29355992Swpaul printf("Error code:\t\t"); 29455992Swpaul an_printhex((char *)&sts->an_errcode, 1); 295108401Sambrisko if (rssimap_valid) 296132860Snjl printf("\nSignal strength:\t[ %u%% ]", 297108401Sambrisko an_rssimap.an_entries[ 298108401Sambrisko sts->an_normalized_strength].an_rss_pct); 299108401Sambrisko else 300132860Snjl printf("\nSignal strength:\t[ %u%% ]", 301108401Sambrisko sts->an_normalized_strength); 302132860Snjl printf("\nAverage Noise:\t\t[ %u%% ]", sts->an_avg_noise_prev_min_pc); 303108401Sambrisko if (rssimap_valid) 304132860Snjl printf("\nSignal quality:\t\t[ %u%% ]", 305108401Sambrisko an_rssimap.an_entries[ 306108401Sambrisko sts->an_cur_signal_quality].an_rss_pct); 307108401Sambrisko else 308132860Snjl printf("\nSignal quality:\t\t[ %u ]", 309108401Sambrisko sts->an_cur_signal_quality); 310132860Snjl printf("\nMax Noise:\t\t[ %u%% ]", sts->an_max_noise_prev_min_pc); 31178788Sbrooks /* 31278788Sbrooks * XXX: This uses the old definition of the rate field (units of 31378788Sbrooks * 500kbps). Technically the new definition is that this field 31478788Sbrooks * contains arbitrary values, but no devices which need this 31578788Sbrooks * support exist and the IEEE seems to intend to use the old 31678788Sbrooks * definition until they get something big so we'll keep using 31778788Sbrooks * it as well because this will work with new cards with 31878788Sbrooks * rate <= 63.5Mbps. 31978788Sbrooks */ 320132860Snjl printf("\nCurrent TX rate:\t[ %u%s ]", sts->an_current_tx_rate / 2, 32178788Sbrooks (sts->an_current_tx_rate % 2) ? ".5" : ""); 32255992Swpaul printf("\nCurrent SSID:\t\t"); 32355992Swpaul an_printstr((char *)&sts->an_ssid, sts->an_ssidlen); 32455992Swpaul printf("\nCurrent AP name:\t"); 32555992Swpaul an_printstr((char *)&sts->an_ap_name, 16); 32655992Swpaul printf("\nCurrent BSSID:\t\t"); 32755992Swpaul an_printhex((char *)&sts->an_cur_bssid, ETHER_ADDR_LEN); 32855992Swpaul printf("\nBeacon period:\t\t"); 32955992Swpaul an_printwords(&sts->an_beacon_period, 1); 33055992Swpaul printf("\nDTIM period:\t\t"); 33155992Swpaul an_printwords(&sts->an_dtim_period, 1); 33255992Swpaul printf("\nATIM duration:\t\t"); 33355992Swpaul an_printwords(&sts->an_atim_duration, 1); 33455992Swpaul printf("\nHOP period:\t\t"); 33555992Swpaul an_printwords(&sts->an_hop_period, 1); 33655992Swpaul printf("\nChannel set:\t\t"); 33755992Swpaul an_printwords(&sts->an_channel_set, 1); 33855992Swpaul printf("\nCurrent channel:\t"); 33955992Swpaul an_printwords(&sts->an_cur_channel, 1); 34055992Swpaul printf("\nHops to backbone:\t"); 34155992Swpaul an_printwords(&sts->an_hops_to_backbone, 1); 34255992Swpaul printf("\nTotal AP load:\t\t"); 34355992Swpaul an_printwords(&sts->an_ap_total_load, 1); 34455992Swpaul printf("\nOur generated load:\t"); 34555992Swpaul an_printwords(&sts->an_our_generated_load, 1); 34655992Swpaul printf("\nAccumulated ARL:\t"); 34755992Swpaul an_printwords(&sts->an_accumulated_arl, 1); 34855992Swpaul printf("\n"); 34955992Swpaul return; 35055992Swpaul} 35155992Swpaul 352132860Snjlstatic void 353132860Snjlan_dumpcaps(const char *iface) 35455992Swpaul{ 35555992Swpaul struct an_ltv_caps *caps; 35655992Swpaul struct an_req areq; 35755992Swpaul u_int16_t tmp; 35855992Swpaul 35955992Swpaul areq.an_len = sizeof(areq); 36055992Swpaul areq.an_type = AN_RID_CAPABILITIES; 36155992Swpaul 36255992Swpaul an_getval(iface, &areq); 36355992Swpaul 36455992Swpaul caps = (struct an_ltv_caps *)&areq; 36555992Swpaul 36655992Swpaul printf("OUI:\t\t\t"); 36755992Swpaul an_printhex((char *)&caps->an_oui, 3); 36855992Swpaul printf("\nProduct number:\t\t"); 36955992Swpaul an_printwords(&caps->an_prodnum, 1); 37055992Swpaul printf("\nManufacturer name:\t"); 37155992Swpaul an_printstr((char *)&caps->an_manufname, 32); 37255992Swpaul printf("\nProduce name:\t\t"); 37355992Swpaul an_printstr((char *)&caps->an_prodname, 16); 37455992Swpaul printf("\nFirmware version:\t"); 37555992Swpaul an_printstr((char *)&caps->an_prodvers, 1); 37655992Swpaul printf("\nOEM MAC address:\t"); 37755992Swpaul an_printhex((char *)&caps->an_oemaddr, ETHER_ADDR_LEN); 37855992Swpaul printf("\nAironet MAC address:\t"); 37955992Swpaul an_printhex((char *)&caps->an_aironetaddr, ETHER_ADDR_LEN); 38055992Swpaul printf("\nRadio type:\t\t[ "); 38155992Swpaul if (caps->an_radiotype & AN_RADIOTYPE_80211_FH) 38255992Swpaul printf("802.11 FH"); 38355992Swpaul else if (caps->an_radiotype & AN_RADIOTYPE_80211_DS) 38455992Swpaul printf("802.11 DS"); 38555992Swpaul else if (caps->an_radiotype & AN_RADIOTYPE_LM2000_DS) 38655992Swpaul printf("LM2000 DS"); 38755992Swpaul else 38855992Swpaul printf("unknown (%x)", caps->an_radiotype); 38955992Swpaul printf(" ]"); 39055992Swpaul printf("\nRegulatory domain:\t"); 39155992Swpaul an_printwords(&caps->an_regdomain, 1); 39255992Swpaul printf("\nAssigned CallID:\t"); 39355992Swpaul an_printhex((char *)&caps->an_callid, 6); 39455992Swpaul printf("\nSupported speeds:\t"); 39555992Swpaul an_printspeeds(caps->an_rates, 8); 39655992Swpaul printf("\nRX Diversity:\t\t[ "); 397108401Sambrisko if (caps->an_rx_diversity == AN_DIVERSITY_FACTORY_DEFAULT) 398108401Sambrisko printf("factory default"); 399108401Sambrisko else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY) 40055992Swpaul printf("antenna 1 only"); 40155992Swpaul else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY) 40255992Swpaul printf("antenna 2 only"); 40355992Swpaul else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2) 40455992Swpaul printf("antenna 1 and 2"); 40555992Swpaul printf(" ]"); 40655992Swpaul printf("\nTX Diversity:\t\t[ "); 407108401Sambrisko if (caps->an_tx_diversity == AN_DIVERSITY_FACTORY_DEFAULT) 408108401Sambrisko printf("factory default"); 409108401Sambrisko else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY) 41055992Swpaul printf("antenna 1 only"); 411108401Sambrisko else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY) 41255992Swpaul printf("antenna 2 only"); 413108401Sambrisko else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2) 41455992Swpaul printf("antenna 1 and 2"); 41555992Swpaul printf(" ]"); 41655992Swpaul printf("\nSupported power levels:\t"); 41755992Swpaul an_printwords(caps->an_tx_powerlevels, 8); 41855992Swpaul printf("\nHardware revision:\t"); 41955992Swpaul tmp = ntohs(caps->an_hwrev); 42055992Swpaul an_printhex((char *)&tmp, 2); 42155992Swpaul printf("\nSoftware revision:\t"); 42255992Swpaul tmp = ntohs(caps->an_fwrev); 42355992Swpaul an_printhex((char *)&tmp, 2); 42455992Swpaul printf("\nSoftware subrevision:\t"); 42555992Swpaul tmp = ntohs(caps->an_fwsubrev); 42655992Swpaul an_printhex((char *)&tmp, 2); 42755992Swpaul printf("\nInterface revision:\t"); 42855992Swpaul tmp = ntohs(caps->an_ifacerev); 42955992Swpaul an_printhex((char *)&tmp, 2); 43055992Swpaul printf("\nBootblock revision:\t"); 43155992Swpaul tmp = ntohs(caps->an_bootblockrev); 43255992Swpaul an_printhex((char *)&tmp, 2); 43355992Swpaul printf("\n"); 43455992Swpaul return; 43555992Swpaul} 43655992Swpaul 437132860Snjlstatic void 438132860Snjlan_dumpstats(const char *iface) 43955992Swpaul{ 44055992Swpaul struct an_ltv_stats *stats; 44155992Swpaul struct an_req areq; 44255992Swpaul 44355992Swpaul areq.an_len = sizeof(areq); 44455992Swpaul areq.an_type = AN_RID_32BITS_CUM; 44555992Swpaul 44655992Swpaul an_getval(iface, &areq); 44755992Swpaul 448132900Snjl stats = (struct an_ltv_stats *)((uint16_t *)&areq - 1); 44955992Swpaul 450132860Snjl printf("RX overruns:\t\t\t\t\t[ %u ]\n", stats->an_rx_overruns); 451132860Snjl printf("RX PLCP CSUM errors:\t\t\t\t[ %u ]\n", 45255992Swpaul stats->an_rx_plcp_csum_errs); 453132860Snjl printf("RX PLCP format errors:\t\t\t\t[ %u ]\n", 45455992Swpaul stats->an_rx_plcp_format_errs); 455132860Snjl printf("RX PLCP length errors:\t\t\t\t[ %u ]\n", 45655992Swpaul stats->an_rx_plcp_len_errs); 457132860Snjl printf("RX MAC CRC errors:\t\t\t\t[ %u ]\n", 45855992Swpaul stats->an_rx_mac_crc_errs); 459132860Snjl printf("RX MAC CRC OK:\t\t\t\t\t[ %u ]\n", 46055992Swpaul stats->an_rx_mac_crc_ok); 461132860Snjl printf("RX WEP errors:\t\t\t\t\t[ %u ]\n", 46255992Swpaul stats->an_rx_wep_errs); 463132860Snjl printf("RX WEP OK:\t\t\t\t\t[ %u ]\n", 46455992Swpaul stats->an_rx_wep_ok); 465132860Snjl printf("Long retries:\t\t\t\t\t[ %u ]\n", 46655992Swpaul stats->an_retry_long); 467132860Snjl printf("Short retries:\t\t\t\t\t[ %u ]\n", 46855992Swpaul stats->an_retry_short); 469132860Snjl printf("Retries exhausted:\t\t\t\t[ %u ]\n", 47055992Swpaul stats->an_retry_max); 471132860Snjl printf("Bad ACK:\t\t\t\t\t[ %u ]\n", 47255992Swpaul stats->an_no_ack); 473132860Snjl printf("Bad CTS:\t\t\t\t\t[ %u ]\n", 47455992Swpaul stats->an_no_cts); 475132860Snjl printf("RX good ACKs:\t\t\t\t\t[ %u ]\n", 47655992Swpaul stats->an_rx_ack_ok); 477132860Snjl printf("RX good CTSs:\t\t\t\t\t[ %u ]\n", 47855992Swpaul stats->an_rx_cts_ok); 479132860Snjl printf("TX good ACKs:\t\t\t\t\t[ %u ]\n", 48055992Swpaul stats->an_tx_ack_ok); 481132860Snjl printf("TX good RTSs:\t\t\t\t\t[ %u ]\n", 48255992Swpaul stats->an_tx_rts_ok); 483132860Snjl printf("TX good CTSs:\t\t\t\t\t[ %u ]\n", 48455992Swpaul stats->an_tx_cts_ok); 485132860Snjl printf("LMAC multicasts transmitted:\t\t\t[ %u ]\n", 48655992Swpaul stats->an_tx_lmac_mcasts); 487132860Snjl printf("LMAC broadcasts transmitted:\t\t\t[ %u ]\n", 48855992Swpaul stats->an_tx_lmac_bcasts); 489132860Snjl printf("LMAC unicast frags transmitted:\t\t\t[ %u ]\n", 49055992Swpaul stats->an_tx_lmac_ucast_frags); 491132860Snjl printf("LMAC unicasts transmitted:\t\t\t[ %u ]\n", 49255992Swpaul stats->an_tx_lmac_ucasts); 493132860Snjl printf("Beacons transmitted:\t\t\t\t[ %u ]\n", 49455992Swpaul stats->an_tx_beacons); 495132860Snjl printf("Beacons received:\t\t\t\t[ %u ]\n", 49655992Swpaul stats->an_rx_beacons); 497132860Snjl printf("Single transmit collisions:\t\t\t[ %u ]\n", 49855992Swpaul stats->an_tx_single_cols); 499132860Snjl printf("Multiple transmit collisions:\t\t\t[ %u ]\n", 50055992Swpaul stats->an_tx_multi_cols); 501132860Snjl printf("Transmits without deferrals:\t\t\t[ %u ]\n", 50255992Swpaul stats->an_tx_defers_no); 503132860Snjl printf("Transmits deferred due to protocol:\t\t[ %u ]\n", 50455992Swpaul stats->an_tx_defers_prot); 505132860Snjl printf("Transmits deferred due to energy detect:\t\t[ %u ]\n", 50655992Swpaul stats->an_tx_defers_energy); 507132860Snjl printf("RX duplicate frames/frags:\t\t\t[ %u ]\n", 50855992Swpaul stats->an_rx_dups); 509132860Snjl printf("RX partial frames:\t\t\t\t[ %u ]\n", 51055992Swpaul stats->an_rx_partial); 511132860Snjl printf("TX max lifetime exceeded:\t\t\t[ %u ]\n", 51255992Swpaul stats->an_tx_too_old); 513132860Snjl printf("RX max lifetime exceeded:\t\t\t[ %u ]\n", 51455992Swpaul stats->an_tx_too_old); 515132860Snjl printf("Sync lost due to too many missed beacons:\t[ %u ]\n", 51655992Swpaul stats->an_lostsync_missed_beacons); 517132860Snjl printf("Sync lost due to ARL exceeded:\t\t\t[ %u ]\n", 51855992Swpaul stats->an_lostsync_arl_exceeded); 519132860Snjl printf("Sync lost due to deauthentication:\t\t[ %u ]\n", 52055992Swpaul stats->an_lostsync_deauthed); 521132860Snjl printf("Sync lost due to disassociation:\t\t[ %u ]\n", 52255992Swpaul stats->an_lostsync_disassociated); 523132860Snjl printf("Sync lost due to excess change in TSF timing:\t[ %u ]\n", 52455992Swpaul stats->an_lostsync_tsf_timing); 525132860Snjl printf("Host transmitted multicasts:\t\t\t[ %u ]\n", 52655992Swpaul stats->an_tx_host_mcasts); 527132860Snjl printf("Host transmitted broadcasts:\t\t\t[ %u ]\n", 52855992Swpaul stats->an_tx_host_bcasts); 529132860Snjl printf("Host transmitted unicasts:\t\t\t[ %u ]\n", 53055992Swpaul stats->an_tx_host_ucasts); 531132860Snjl printf("Host transmission failures:\t\t\t[ %u ]\n", 53255992Swpaul stats->an_tx_host_failed); 533132860Snjl printf("Host received multicasts:\t\t\t[ %u ]\n", 53455992Swpaul stats->an_rx_host_mcasts); 535132860Snjl printf("Host received broadcasts:\t\t\t[ %u ]\n", 53655992Swpaul stats->an_rx_host_bcasts); 537132860Snjl printf("Host received unicasts:\t\t\t\t[ %u ]\n", 53855992Swpaul stats->an_rx_host_ucasts); 539132860Snjl printf("Host receive discards:\t\t\t\t[ %u ]\n", 54055992Swpaul stats->an_rx_host_discarded); 541132860Snjl printf("HMAC transmitted multicasts:\t\t\t[ %u ]\n", 54255992Swpaul stats->an_tx_hmac_mcasts); 543132860Snjl printf("HMAC transmitted broadcasts:\t\t\t[ %u ]\n", 54455992Swpaul stats->an_tx_hmac_bcasts); 545132860Snjl printf("HMAC transmitted unicasts:\t\t\t[ %u ]\n", 54655992Swpaul stats->an_tx_hmac_ucasts); 547132860Snjl printf("HMAC transmissions failed:\t\t\t[ %u ]\n", 54855992Swpaul stats->an_tx_hmac_failed); 549132860Snjl printf("HMAC received multicasts:\t\t\t[ %u ]\n", 55055992Swpaul stats->an_rx_hmac_mcasts); 551132860Snjl printf("HMAC received broadcasts:\t\t\t[ %u ]\n", 55255992Swpaul stats->an_rx_hmac_bcasts); 553132860Snjl printf("HMAC received unicasts:\t\t\t\t[ %u ]\n", 55455992Swpaul stats->an_rx_hmac_ucasts); 555132860Snjl printf("HMAC receive discards:\t\t\t\t[ %u ]\n", 55655992Swpaul stats->an_rx_hmac_discarded); 557132860Snjl printf("HMAC transmits accepted:\t\t\t[ %u ]\n", 55855992Swpaul stats->an_tx_hmac_accepted); 559132860Snjl printf("SSID mismatches:\t\t\t\t[ %u ]\n", 56055992Swpaul stats->an_ssid_mismatches); 561132860Snjl printf("Access point mismatches:\t\t\t[ %u ]\n", 56255992Swpaul stats->an_ap_mismatches); 563132860Snjl printf("Speed mismatches:\t\t\t\t[ %u ]\n", 56455992Swpaul stats->an_rates_mismatches); 565132860Snjl printf("Authentication rejects:\t\t\t\t[ %u ]\n", 56655992Swpaul stats->an_auth_rejects); 567132860Snjl printf("Authentication timeouts:\t\t\t[ %u ]\n", 56855992Swpaul stats->an_auth_timeouts); 569132860Snjl printf("Association rejects:\t\t\t\t[ %u ]\n", 57055992Swpaul stats->an_assoc_rejects); 571132860Snjl printf("Association timeouts:\t\t\t\t[ %u ]\n", 57255992Swpaul stats->an_assoc_timeouts); 573132860Snjl printf("Management frames received:\t\t\t[ %u ]\n", 57455992Swpaul stats->an_rx_mgmt_pkts); 575132860Snjl printf("Management frames transmitted:\t\t\t[ %u ]\n", 57655992Swpaul stats->an_tx_mgmt_pkts); 577132860Snjl printf("Refresh frames received:\t\t\t[ %u ]\n", 57855992Swpaul stats->an_rx_refresh_pkts), 579132860Snjl printf("Refresh frames transmitted:\t\t\t[ %u ]\n", 58055992Swpaul stats->an_tx_refresh_pkts), 581132860Snjl printf("Poll frames received:\t\t\t\t[ %u ]\n", 58255992Swpaul stats->an_rx_poll_pkts); 583132860Snjl printf("Poll frames transmitted:\t\t\t[ %u ]\n", 58455992Swpaul stats->an_tx_poll_pkts); 585132860Snjl printf("Host requested sync losses:\t\t\t[ %u ]\n", 58655992Swpaul stats->an_lostsync_hostreq); 587132860Snjl printf("Host transmitted bytes:\t\t\t\t[ %u ]\n", 58855992Swpaul stats->an_host_tx_bytes); 589132860Snjl printf("Host received bytes:\t\t\t\t[ %u ]\n", 59055992Swpaul stats->an_host_rx_bytes); 591132860Snjl printf("Uptime in microseconds:\t\t\t\t[ %u ]\n", 59255992Swpaul stats->an_uptime_usecs); 593132860Snjl printf("Uptime in seconds:\t\t\t\t[ %u ]\n", 59455992Swpaul stats->an_uptime_secs); 595132860Snjl printf("Sync lost due to better AP:\t\t\t[ %u ]\n", 59655992Swpaul stats->an_lostsync_better_ap); 59755992Swpaul} 59855992Swpaul 599132860Snjlstatic void 600132860Snjlan_dumpap(const char *iface) 60155992Swpaul{ 60255992Swpaul struct an_ltv_aplist *ap; 60355992Swpaul struct an_req areq; 60455992Swpaul 60555992Swpaul areq.an_len = sizeof(areq); 60655992Swpaul areq.an_type = AN_RID_APLIST; 60755992Swpaul 60855992Swpaul an_getval(iface, &areq); 60955992Swpaul 61055992Swpaul ap = (struct an_ltv_aplist *)&areq; 61155992Swpaul printf("Access point 1:\t\t\t"); 61255992Swpaul an_printhex((char *)&ap->an_ap1, ETHER_ADDR_LEN); 61355992Swpaul printf("\nAccess point 2:\t\t\t"); 61455992Swpaul an_printhex((char *)&ap->an_ap2, ETHER_ADDR_LEN); 61555992Swpaul printf("\nAccess point 3:\t\t\t"); 61655992Swpaul an_printhex((char *)&ap->an_ap3, ETHER_ADDR_LEN); 61755992Swpaul printf("\nAccess point 4:\t\t\t"); 61855992Swpaul an_printhex((char *)&ap->an_ap4, ETHER_ADDR_LEN); 61955992Swpaul printf("\n"); 62055992Swpaul 62155992Swpaul return; 62255992Swpaul} 62355992Swpaul 624132860Snjlstatic void 625132860Snjlan_dumpssid(const char *iface) 62655992Swpaul{ 627119156Sambrisko struct an_ltv_ssidlist_new *ssid; 62855992Swpaul struct an_req areq; 629119156Sambrisko int i, max; 63055992Swpaul 63155992Swpaul areq.an_len = sizeof(areq); 63255992Swpaul areq.an_type = AN_RID_SSIDLIST; 63355992Swpaul 63455992Swpaul an_getval(iface, &areq); 63555992Swpaul 636119156Sambrisko max = (areq.an_len - 4) / sizeof(struct an_ltv_ssid_entry); 637119156Sambrisko if ( max > MAX_SSIDS ) { 638132860Snjl printf("Too many SSIDs only printing %d of %d\n", 639119156Sambrisko MAX_SSIDS, max); 640119156Sambrisko max = MAX_SSIDS; 641119156Sambrisko } 642119156Sambrisko ssid = (struct an_ltv_ssidlist_new *)&areq; 643119156Sambrisko for (i = 0; i < max; i++) 644119156Sambrisko printf("SSID %2d:\t\t\t[ %.*s ]\n", i + 1, 645119156Sambrisko ssid->an_entry[i].an_len, 646119156Sambrisko ssid->an_entry[i].an_ssid); 64755992Swpaul 64855992Swpaul return; 64955992Swpaul} 65055992Swpaul 651132860Snjlstatic void 652132860Snjlan_dumpconfig(const char *iface) 65355992Swpaul{ 65455992Swpaul struct an_ltv_genconfig *cfg; 65555992Swpaul struct an_req areq; 65680454Sbrooks unsigned char diversity; 65755992Swpaul 65855992Swpaul areq.an_len = sizeof(areq); 65955992Swpaul areq.an_type = AN_RID_ACTUALCFG; 66055992Swpaul 66155992Swpaul an_getval(iface, &areq); 66255992Swpaul 66355992Swpaul cfg = (struct an_ltv_genconfig *)&areq; 66455992Swpaul 66555992Swpaul printf("Operating mode:\t\t\t\t[ "); 66655992Swpaul if ((cfg->an_opmode & 0x7) == AN_OPMODE_IBSS_ADHOC) 66755992Swpaul printf("ad-hoc"); 66855992Swpaul if ((cfg->an_opmode & 0x7) == AN_OPMODE_INFRASTRUCTURE_STATION) 66955992Swpaul printf("infrastructure"); 67055992Swpaul if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP) 67155992Swpaul printf("access point"); 67255992Swpaul if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP_REPEATER) 67355992Swpaul printf("access point repeater"); 67455992Swpaul printf(" ]"); 67555992Swpaul printf("\nReceive mode:\t\t\t\t[ "); 67655992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_MC_ADDR) 67755992Swpaul printf("broadcast/multicast/unicast"); 67855992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_ADDR) 67955992Swpaul printf("broadcast/unicast"); 68055992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_ADDR) 68155992Swpaul printf("unicast"); 68255992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_CURBSS) 68355992Swpaul printf("802.11 monitor, current BSSID"); 68455992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_ANYBSS) 68555992Swpaul printf("802.11 monitor, any BSSID"); 68655992Swpaul if ((cfg->an_rxmode & 0x7) == AN_RXMODE_LAN_MONITOR_CURBSS) 68755992Swpaul printf("LAN monitor, current BSSID"); 68855992Swpaul printf(" ]"); 68955992Swpaul printf("\nFragment threshold:\t\t\t"); 69055992Swpaul an_printwords(&cfg->an_fragthresh, 1); 69155992Swpaul printf("\nRTS threshold:\t\t\t\t"); 69255992Swpaul an_printwords(&cfg->an_rtsthresh, 1); 69355992Swpaul printf("\nMAC address:\t\t\t\t"); 69455992Swpaul an_printhex((char *)&cfg->an_macaddr, ETHER_ADDR_LEN); 69555992Swpaul printf("\nSupported rates:\t\t\t"); 69655992Swpaul an_printspeeds(cfg->an_rates, 8); 69755992Swpaul printf("\nShort retry limit:\t\t\t"); 69855992Swpaul an_printwords(&cfg->an_shortretry_limit, 1); 69955992Swpaul printf("\nLong retry limit:\t\t\t"); 70055992Swpaul an_printwords(&cfg->an_longretry_limit, 1); 70155992Swpaul printf("\nTX MSDU lifetime:\t\t\t"); 70255992Swpaul an_printwords(&cfg->an_tx_msdu_lifetime, 1); 70355992Swpaul printf("\nRX MSDU lifetime:\t\t\t"); 70455992Swpaul an_printwords(&cfg->an_rx_msdu_lifetime, 1); 70555992Swpaul printf("\nStationary:\t\t\t\t"); 70655992Swpaul an_printbool(cfg->an_stationary); 70755992Swpaul printf("\nOrdering:\t\t\t\t"); 70855992Swpaul an_printbool(cfg->an_ordering); 70955992Swpaul printf("\nDevice type:\t\t\t\t[ "); 71055992Swpaul if (cfg->an_devtype == AN_DEVTYPE_PC4500) 71155992Swpaul printf("PC4500"); 71255992Swpaul else if (cfg->an_devtype == AN_DEVTYPE_PC4800) 71355992Swpaul printf("PC4800"); 71455992Swpaul else 71555992Swpaul printf("unknown (%x)", cfg->an_devtype); 71655992Swpaul printf(" ]"); 71755992Swpaul printf("\nScanning mode:\t\t\t\t[ "); 71855992Swpaul if (cfg->an_scanmode == AN_SCANMODE_ACTIVE) 71955992Swpaul printf("active"); 72055992Swpaul if (cfg->an_scanmode == AN_SCANMODE_PASSIVE) 72155992Swpaul printf("passive"); 72255992Swpaul if (cfg->an_scanmode == AN_SCANMODE_AIRONET_ACTIVE) 72355992Swpaul printf("Aironet active"); 72455992Swpaul printf(" ]"); 72555992Swpaul printf("\nProbe delay:\t\t\t\t"); 72655992Swpaul an_printwords(&cfg->an_probedelay, 1); 72755992Swpaul printf("\nProbe energy timeout:\t\t\t"); 72855992Swpaul an_printwords(&cfg->an_probe_energy_timeout, 1); 72955992Swpaul printf("\nProbe response timeout:\t\t\t"); 73055992Swpaul an_printwords(&cfg->an_probe_response_timeout, 1); 73155992Swpaul printf("\nBeacon listen timeout:\t\t\t"); 73255992Swpaul an_printwords(&cfg->an_beacon_listen_timeout, 1); 73355992Swpaul printf("\nIBSS join network timeout:\t\t"); 73455992Swpaul an_printwords(&cfg->an_ibss_join_net_timeout, 1); 73555992Swpaul printf("\nAuthentication timeout:\t\t\t"); 73655992Swpaul an_printwords(&cfg->an_auth_timeout, 1); 73768692Swpaul printf("\nWEP enabled:\t\t\t\t[ "); 73869772Sarchie if (cfg->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) 73969772Sarchie { 74088748Sambrisko if (cfg->an_authtype & AN_AUTHTYPE_LEAP) 74188748Sambrisko printf("LEAP"); 74288748Sambrisko else if (cfg->an_authtype & AN_AUTHTYPE_ALLOW_UNENCRYPTED) 74369772Sarchie printf("mixed cell"); 74469772Sarchie else 74569772Sarchie printf("full"); 74669772Sarchie } 74768692Swpaul else 74868692Swpaul printf("no"); 74968692Swpaul printf(" ]"); 75055992Swpaul printf("\nAuthentication type:\t\t\t[ "); 75168692Swpaul if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_NONE) 75268692Swpaul printf("none"); 75368692Swpaul if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_OPEN) 75455992Swpaul printf("open"); 75568692Swpaul if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_SHAREDKEY) 75655992Swpaul printf("shared key"); 75755992Swpaul printf(" ]"); 75855992Swpaul printf("\nAssociation timeout:\t\t\t"); 75955992Swpaul an_printwords(&cfg->an_assoc_timeout, 1); 76055992Swpaul printf("\nSpecified AP association timeout:\t"); 76155992Swpaul an_printwords(&cfg->an_specified_ap_timeout, 1); 76255992Swpaul printf("\nOffline scan interval:\t\t\t"); 76355992Swpaul an_printwords(&cfg->an_offline_scan_interval, 1); 76455992Swpaul printf("\nOffline scan duration:\t\t\t"); 76555992Swpaul an_printwords(&cfg->an_offline_scan_duration, 1); 76655992Swpaul printf("\nLink loss delay:\t\t\t"); 76755992Swpaul an_printwords(&cfg->an_link_loss_delay, 1); 76855992Swpaul printf("\nMax beacon loss time:\t\t\t"); 76955992Swpaul an_printwords(&cfg->an_max_beacon_lost_time, 1); 77055992Swpaul printf("\nRefresh interval:\t\t\t"); 77155992Swpaul an_printwords(&cfg->an_refresh_interval, 1); 77255992Swpaul printf("\nPower save mode:\t\t\t[ "); 77355992Swpaul if (cfg->an_psave_mode == AN_PSAVE_NONE) 77455992Swpaul printf("none"); 77555992Swpaul if (cfg->an_psave_mode == AN_PSAVE_CAM) 77655992Swpaul printf("constantly awake mode"); 77755992Swpaul if (cfg->an_psave_mode == AN_PSAVE_PSP) 77855992Swpaul printf("PSP"); 77955992Swpaul if (cfg->an_psave_mode == AN_PSAVE_PSP_CAM) 78055992Swpaul printf("PSP-CAM (fast PSP)"); 78155992Swpaul printf(" ]"); 78255992Swpaul printf("\nSleep through DTIMs:\t\t\t"); 78355992Swpaul an_printbool(cfg->an_sleep_for_dtims); 78455992Swpaul printf("\nPower save listen interval:\t\t"); 78555992Swpaul an_printwords(&cfg->an_listen_interval, 1); 78655992Swpaul printf("\nPower save fast listen interval:\t"); 78755992Swpaul an_printwords(&cfg->an_fast_listen_interval, 1); 78855992Swpaul printf("\nPower save listen decay:\t\t"); 78955992Swpaul an_printwords(&cfg->an_listen_decay, 1); 79055992Swpaul printf("\nPower save fast listen decay:\t\t"); 79155992Swpaul an_printwords(&cfg->an_fast_listen_decay, 1); 79255992Swpaul printf("\nAP/ad-hoc Beacon period:\t\t"); 79355992Swpaul an_printwords(&cfg->an_beacon_period, 1); 79455992Swpaul printf("\nAP/ad-hoc ATIM duration:\t\t"); 79555992Swpaul an_printwords(&cfg->an_atim_duration, 1); 79655992Swpaul printf("\nAP/ad-hoc current channel:\t\t"); 79755992Swpaul an_printwords(&cfg->an_ds_channel, 1); 79855992Swpaul printf("\nAP/ad-hoc DTIM period:\t\t\t"); 79955992Swpaul an_printwords(&cfg->an_dtim_period, 1); 80055992Swpaul printf("\nRadio type:\t\t\t\t[ "); 80155992Swpaul if (cfg->an_radiotype & AN_RADIOTYPE_80211_FH) 80255992Swpaul printf("802.11 FH"); 80355992Swpaul else if (cfg->an_radiotype & AN_RADIOTYPE_80211_DS) 80455992Swpaul printf("802.11 DS"); 80555992Swpaul else if (cfg->an_radiotype & AN_RADIOTYPE_LM2000_DS) 80655992Swpaul printf("LM2000 DS"); 80755992Swpaul else 80855992Swpaul printf("unknown (%x)", cfg->an_radiotype); 80955992Swpaul printf(" ]"); 81055992Swpaul printf("\nRX Diversity:\t\t\t\t[ "); 81180454Sbrooks diversity = cfg->an_diversity & 0xFF; 812108401Sambrisko if (diversity == AN_DIVERSITY_FACTORY_DEFAULT) 813108401Sambrisko printf("factory default"); 814108401Sambrisko else if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY) 81555992Swpaul printf("antenna 1 only"); 81680454Sbrooks else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY) 81755992Swpaul printf("antenna 2 only"); 81880454Sbrooks else if (diversity == AN_DIVERSITY_ANTENNA_1_AND_2) 81955992Swpaul printf("antenna 1 and 2"); 82055992Swpaul printf(" ]"); 82155992Swpaul printf("\nTX Diversity:\t\t\t\t[ "); 82280454Sbrooks diversity = (cfg->an_diversity >> 8) & 0xFF; 823108401Sambrisko if (diversity == AN_DIVERSITY_FACTORY_DEFAULT) 824108401Sambrisko printf("factory default"); 825108401Sambrisko else if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY) 82655992Swpaul printf("antenna 1 only"); 82780454Sbrooks else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY) 82855992Swpaul printf("antenna 2 only"); 82980454Sbrooks else if (diversity == AN_DIVERSITY_ANTENNA_1_AND_2) 83055992Swpaul printf("antenna 1 and 2"); 83155992Swpaul printf(" ]"); 83255992Swpaul printf("\nTransmit power level:\t\t\t"); 83355992Swpaul an_printwords(&cfg->an_tx_power, 1); 83455992Swpaul printf("\nRSS threshold:\t\t\t\t"); 83555992Swpaul an_printwords(&cfg->an_rss_thresh, 1); 83655992Swpaul printf("\nNode name:\t\t\t\t"); 83755992Swpaul an_printstr((char *)&cfg->an_nodename, 16); 83855992Swpaul printf("\nARL threshold:\t\t\t\t"); 83955992Swpaul an_printwords(&cfg->an_arl_thresh, 1); 84055992Swpaul printf("\nARL decay:\t\t\t\t"); 84155992Swpaul an_printwords(&cfg->an_arl_decay, 1); 84255992Swpaul printf("\nARL delay:\t\t\t\t"); 84355992Swpaul an_printwords(&cfg->an_arl_delay, 1); 84488748Sambrisko printf("\nConfiguration:\t\t\t\t[ "); 84588748Sambrisko if (cfg->an_home_product & AN_HOME_NETWORK) 84688748Sambrisko printf("Home Configuration"); 84788748Sambrisko else 84888748Sambrisko printf("Enterprise Configuration"); 84988748Sambrisko printf(" ]"); 85055992Swpaul 85155992Swpaul printf("\n"); 85269772Sarchie printf("\n"); 85369772Sarchie an_readkeyinfo(iface); 85455992Swpaul} 85555992Swpaul 856132860Snjlstatic void 857132860Snjlan_dumprssimap(const char *iface) 858108401Sambrisko{ 859108401Sambrisko struct an_ltv_rssi_map *rssi; 860108401Sambrisko struct an_req areq; 861108401Sambrisko int i; 86255992Swpaul 863108401Sambrisko areq.an_len = sizeof(areq); 864108401Sambrisko areq.an_type = AN_RID_RSSI_MAP; 865108401Sambrisko 866108401Sambrisko an_getval(iface, &areq); 867108401Sambrisko 868108401Sambrisko rssi = (struct an_ltv_rssi_map *)&areq; 869108401Sambrisko 870108401Sambrisko printf("idx\tpct\t dBm\n"); 871108401Sambrisko 872108401Sambrisko for (i = 0; i < 0xFF; i++) { 873108401Sambrisko /* 874108401Sambrisko * negate the dBm value: it's the only way the power 875108401Sambrisko * level makes sense 876108401Sambrisko */ 877108401Sambrisko printf("%3d\t%3d\t%4d\n", i, 878108401Sambrisko rssi->an_entries[i].an_rss_pct, 879108401Sambrisko - rssi->an_entries[i].an_rss_dbm); 880108401Sambrisko } 881108401Sambrisko} 882108401Sambrisko 883132860Snjlstatic void 884132860Snjlusage(const char *p) 88555992Swpaul{ 88655992Swpaul fprintf(stderr, "usage: %s -i iface -A (show specified APs)\n", p); 88755992Swpaul fprintf(stderr, "\t%s -i iface -N (show specified SSIDss)\n", p); 88855992Swpaul fprintf(stderr, "\t%s -i iface -S (show NIC status)\n", p); 88955992Swpaul fprintf(stderr, "\t%s -i iface -I (show NIC capabilities)\n", p); 89055992Swpaul fprintf(stderr, "\t%s -i iface -T (show stats counters)\n", p); 89155992Swpaul fprintf(stderr, "\t%s -i iface -C (show current config)\n", p); 892108401Sambrisko fprintf(stderr, "\t%s -i iface -R (show RSSI map)\n", p); 89389380Sambrisko fprintf(stderr, "\t%s -i iface -t 0-4 (set TX speed)\n", p); 89489380Sambrisko fprintf(stderr, "\t%s -i iface -s 0-3 (set power save mode)\n", p); 89589380Sambrisko fprintf(stderr, "\t%s -i iface [-v 1-4] -a AP (specify AP)\n", p); 89655992Swpaul fprintf(stderr, "\t%s -i iface -b val (set beacon period)\n", p); 89755992Swpaul fprintf(stderr, "\t%s -i iface [-v 0|1] -d val (set diversity)\n", p); 89855992Swpaul fprintf(stderr, "\t%s -i iface -j val (set netjoin timeout)\n", p); 89989380Sambrisko fprintf(stderr, "\t%s -i iface -e 0-4 (enable transmit key)\n", p); 90089380Sambrisko fprintf(stderr, "\t%s -i iface [-v 0-8] -k key (set key)\n", p); 90189380Sambrisko fprintf(stderr, "\t%s -i iface -K 0-2 (no auth/open/shared secret)\n", p); 90289380Sambrisko fprintf(stderr, "\t%s -i iface -W 0-2 (no WEP/full WEP/mixed cell)\n", p); 90355992Swpaul fprintf(stderr, "\t%s -i iface -l val (set station name)\n", p); 90455992Swpaul fprintf(stderr, "\t%s -i iface -m val (set MAC address)\n", p); 90589380Sambrisko fprintf(stderr, "\t%s -i iface [-v 1-3] -n SSID " 90655992Swpaul "(specify SSID)\n", p); 90755992Swpaul fprintf(stderr, "\t%s -i iface -o 0|1 (set operating mode)\n", p); 90855992Swpaul fprintf(stderr, "\t%s -i iface -c val (set ad-hoc channel)\n", p); 90955992Swpaul fprintf(stderr, "\t%s -i iface -f val (set frag threshold)\n", p); 91055992Swpaul fprintf(stderr, "\t%s -i iface -r val (set RTS threshold)\n", p); 91183269Sbrooks fprintf(stderr, "\t%s -i iface -M 0-15 (set monitor mode)\n", p); 91288748Sambrisko fprintf(stderr, "\t%s -i iface -L user (enter LEAP authentication mode)\n", p); 91355992Swpaul#ifdef ANCACHE 91455992Swpaul fprintf(stderr, "\t%s -i iface -Q print signal quality cache\n", p); 91555992Swpaul fprintf(stderr, "\t%s -i iface -Z zero out signal cache\n", p); 91655992Swpaul#endif 91755992Swpaul 91855992Swpaul fprintf(stderr, "\t%s -h (display this message)\n", p); 91955992Swpaul 92055992Swpaul exit(1); 92155992Swpaul} 92255992Swpaul 923132860Snjlstatic void 924132860Snjlan_setconfig(const char *iface, int act, void *arg) 92555992Swpaul{ 92655992Swpaul struct an_ltv_genconfig *cfg; 92755992Swpaul struct an_ltv_caps *caps; 92855992Swpaul struct an_req areq; 92955992Swpaul struct an_req areq_caps; 93055992Swpaul u_int16_t diversity = 0; 93155992Swpaul struct ether_addr *addr; 93255992Swpaul int i; 93355992Swpaul 93455992Swpaul areq.an_len = sizeof(areq); 93555992Swpaul areq.an_type = AN_RID_GENCONFIG; 93655992Swpaul an_getval(iface, &areq); 93755992Swpaul cfg = (struct an_ltv_genconfig *)&areq; 93855992Swpaul 93955992Swpaul areq_caps.an_len = sizeof(areq); 94055992Swpaul areq_caps.an_type = AN_RID_CAPABILITIES; 94155992Swpaul an_getval(iface, &areq_caps); 94255992Swpaul caps = (struct an_ltv_caps *)&areq_caps; 94355992Swpaul 94455992Swpaul switch(act) { 94555992Swpaul case ACT_SET_OPMODE: 94655992Swpaul cfg->an_opmode = atoi(arg); 94755992Swpaul break; 94855992Swpaul case ACT_SET_FREQ: 94955992Swpaul cfg->an_ds_channel = atoi(arg); 95055992Swpaul break; 95155992Swpaul case ACT_SET_PWRSAVE: 95255992Swpaul cfg->an_psave_mode = atoi(arg); 95355992Swpaul break; 95455992Swpaul case ACT_SET_SCANMODE: 95555992Swpaul cfg->an_scanmode = atoi(arg); 95655992Swpaul break; 95755992Swpaul case ACT_SET_DIVERSITY_RX: 95855992Swpaul case ACT_SET_DIVERSITY_TX: 95955992Swpaul switch(atoi(arg)) { 96055992Swpaul case 0: 96155992Swpaul diversity = AN_DIVERSITY_FACTORY_DEFAULT; 96255992Swpaul break; 96355992Swpaul case 1: 96455992Swpaul diversity = AN_DIVERSITY_ANTENNA_1_ONLY; 96555992Swpaul break; 96655992Swpaul case 2: 96755992Swpaul diversity = AN_DIVERSITY_ANTENNA_2_ONLY; 96855992Swpaul break; 96955992Swpaul case 3: 97055992Swpaul diversity = AN_DIVERSITY_ANTENNA_1_AND_2; 97155992Swpaul break; 97255992Swpaul default: 973132860Snjl errx(1, "bad diversity setting: %u", diversity); 97455992Swpaul break; 97555992Swpaul } 976108401Sambrisko if (act == ACT_SET_DIVERSITY_RX) { 977108401Sambrisko cfg->an_diversity &= 0xFF00; 978108401Sambrisko cfg->an_diversity |= diversity; 979108401Sambrisko } else { 98055992Swpaul cfg->an_diversity &= 0x00FF; 98155992Swpaul cfg->an_diversity |= (diversity << 8); 98255992Swpaul } 98355992Swpaul break; 98455992Swpaul case ACT_SET_TXPWR: 98555992Swpaul for (i = 0; i < 8; i++) { 98655992Swpaul if (caps->an_tx_powerlevels[i] == atoi(arg)) 98755992Swpaul break; 98855992Swpaul } 98955992Swpaul if (i == 8) 99055992Swpaul errx(1, "unsupported power level: %dmW", atoi(arg)); 99155992Swpaul 99255992Swpaul cfg->an_tx_power = atoi(arg); 99355992Swpaul break; 99455992Swpaul case ACT_SET_RTS_THRESH: 99555992Swpaul cfg->an_rtsthresh = atoi(arg); 99655992Swpaul break; 99755992Swpaul case ACT_SET_RTS_RETRYLIM: 99855992Swpaul cfg->an_shortretry_limit = 99955992Swpaul cfg->an_longretry_limit = atoi(arg); 100055992Swpaul break; 100155992Swpaul case ACT_SET_BEACON_PERIOD: 100255992Swpaul cfg->an_beacon_period = atoi(arg); 100355992Swpaul break; 100455992Swpaul case ACT_SET_WAKE_DURATION: 100555992Swpaul cfg->an_atim_duration = atoi(arg); 100655992Swpaul break; 100755992Swpaul case ACT_SET_FRAG_THRESH: 100855992Swpaul cfg->an_fragthresh = atoi(arg); 100955992Swpaul break; 101055992Swpaul case ACT_SET_NETJOIN: 101155992Swpaul cfg->an_ibss_join_net_timeout = atoi(arg); 101255992Swpaul break; 101355992Swpaul case ACT_SET_MYNAME: 101455992Swpaul bzero(cfg->an_nodename, 16); 101555992Swpaul strncpy((char *)&cfg->an_nodename, optarg, 16); 101655992Swpaul break; 101755992Swpaul case ACT_SET_MAC: 101855992Swpaul addr = ether_aton((char *)arg); 101955992Swpaul 102055992Swpaul if (addr == NULL) 102155992Swpaul errx(1, "badly formatted address"); 102255992Swpaul bzero(cfg->an_macaddr, ETHER_ADDR_LEN); 1023132900Snjl bcopy(addr, &cfg->an_macaddr, ETHER_ADDR_LEN); 102455992Swpaul break; 102568692Swpaul case ACT_ENABLE_WEP: 102669772Sarchie switch (atoi (arg)) { 102769772Sarchie case 0: 102869772Sarchie /* no WEP */ 102969772Sarchie cfg->an_authtype &= ~(AN_AUTHTYPE_PRIVACY_IN_USE 103088748Sambrisko | AN_AUTHTYPE_ALLOW_UNENCRYPTED 103188748Sambrisko | AN_AUTHTYPE_LEAP); 103269772Sarchie break; 103369772Sarchie case 1: 103469772Sarchie /* full WEP */ 103569772Sarchie cfg->an_authtype |= AN_AUTHTYPE_PRIVACY_IN_USE; 103669772Sarchie cfg->an_authtype &= ~AN_AUTHTYPE_ALLOW_UNENCRYPTED; 103788748Sambrisko cfg->an_authtype &= ~AN_AUTHTYPE_LEAP; 103869772Sarchie break; 103969772Sarchie case 2: 104069772Sarchie /* mixed cell */ 104169772Sarchie cfg->an_authtype = AN_AUTHTYPE_PRIVACY_IN_USE 104269772Sarchie | AN_AUTHTYPE_ALLOW_UNENCRYPTED; 104369772Sarchie break; 104469772Sarchie } 104568692Swpaul break; 104668692Swpaul case ACT_SET_KEY_TYPE: 104768692Swpaul cfg->an_authtype = (cfg->an_authtype & ~AN_AUTHTYPE_MASK) 104868692Swpaul | atoi(arg); 104968692Swpaul break; 105083269Sbrooks case ACT_SET_MONITOR_MODE: 105183269Sbrooks areq.an_type = AN_RID_MONITOR_MODE; 105283269Sbrooks cfg->an_len = atoi(arg); /* mode is put in length */ 105383269Sbrooks break; 105455992Swpaul default: 105555992Swpaul errx(1, "unknown action"); 105655992Swpaul break; 105755992Swpaul } 105855992Swpaul 105955992Swpaul an_setval(iface, &areq); 106055992Swpaul exit(0); 106155992Swpaul} 106255992Swpaul 1063132860Snjlstatic void 1064132860Snjlan_setspeed(const char *iface, int act __unused, void *arg) 106555992Swpaul{ 106655992Swpaul struct an_req areq; 106755992Swpaul struct an_ltv_caps *caps; 106855992Swpaul u_int16_t speed; 106955992Swpaul 107055992Swpaul areq.an_len = sizeof(areq); 107155992Swpaul areq.an_type = AN_RID_CAPABILITIES; 107255992Swpaul 107355992Swpaul an_getval(iface, &areq); 107455992Swpaul caps = (struct an_ltv_caps *)&areq; 107555992Swpaul 107655992Swpaul switch(atoi(arg)) { 107755992Swpaul case 0: 107855992Swpaul speed = 0; 107955992Swpaul break; 108055992Swpaul case 1: 108155992Swpaul speed = AN_RATE_1MBPS; 108255992Swpaul break; 108355992Swpaul case 2: 108455992Swpaul speed = AN_RATE_2MBPS; 108555992Swpaul break; 108655992Swpaul case 3: 108755992Swpaul if (caps->an_rates[2] != AN_RATE_5_5MBPS) 108855992Swpaul errx(1, "5.5Mbps not supported on this card"); 108955992Swpaul speed = AN_RATE_5_5MBPS; 109055992Swpaul break; 109155992Swpaul case 4: 109255992Swpaul if (caps->an_rates[3] != AN_RATE_11MBPS) 109355992Swpaul errx(1, "11Mbps not supported on this card"); 109455992Swpaul speed = AN_RATE_11MBPS; 109555992Swpaul break; 109655992Swpaul default: 109755992Swpaul errx(1, "unsupported speed"); 109855992Swpaul break; 109955992Swpaul } 110055992Swpaul 110155992Swpaul areq.an_len = 6; 110255992Swpaul areq.an_type = AN_RID_TX_SPEED; 110355992Swpaul areq.an_val[0] = speed; 110455992Swpaul 110555992Swpaul an_setval(iface, &areq); 110655992Swpaul exit(0); 110755992Swpaul} 110855992Swpaul 1109132860Snjlstatic void 1110132860Snjlan_setap(const char *iface, int act, void *arg) 111155992Swpaul{ 111255992Swpaul struct an_ltv_aplist *ap; 111355992Swpaul struct an_req areq; 111455992Swpaul struct ether_addr *addr; 111555992Swpaul 111655992Swpaul areq.an_len = sizeof(areq); 111755992Swpaul areq.an_type = AN_RID_APLIST; 111855992Swpaul 111955992Swpaul an_getval(iface, &areq); 112055992Swpaul ap = (struct an_ltv_aplist *)&areq; 112155992Swpaul 112255992Swpaul addr = ether_aton((char *)arg); 112355992Swpaul 112455992Swpaul if (addr == NULL) 112555992Swpaul errx(1, "badly formatted address"); 112655992Swpaul 112755992Swpaul switch(act) { 112855992Swpaul case ACT_SET_AP1: 112955992Swpaul bzero(ap->an_ap1, ETHER_ADDR_LEN); 1130132900Snjl bcopy(addr, &ap->an_ap1, ETHER_ADDR_LEN); 113155992Swpaul break; 113255992Swpaul case ACT_SET_AP2: 113355992Swpaul bzero(ap->an_ap2, ETHER_ADDR_LEN); 1134132900Snjl bcopy(addr, &ap->an_ap2, ETHER_ADDR_LEN); 113555992Swpaul break; 113655992Swpaul case ACT_SET_AP3: 113755992Swpaul bzero(ap->an_ap3, ETHER_ADDR_LEN); 1138132900Snjl bcopy(addr, &ap->an_ap3, ETHER_ADDR_LEN); 113955992Swpaul break; 114055992Swpaul case ACT_SET_AP4: 114155992Swpaul bzero(ap->an_ap4, ETHER_ADDR_LEN); 1142132900Snjl bcopy(addr, &ap->an_ap4, ETHER_ADDR_LEN); 114355992Swpaul break; 114455992Swpaul default: 114555992Swpaul errx(1, "unknown action"); 114655992Swpaul break; 114755992Swpaul } 114855992Swpaul 114955992Swpaul an_setval(iface, &areq); 115055992Swpaul exit(0); 115155992Swpaul} 115255992Swpaul 1153132860Snjlstatic void 1154132860Snjlan_setssid(const char *iface, int act, void *arg) 115555992Swpaul{ 1156119156Sambrisko struct an_ltv_ssidlist_new *ssid; 115755992Swpaul struct an_req areq; 1158119156Sambrisko int max; 115955992Swpaul 116055992Swpaul areq.an_len = sizeof(areq); 116155992Swpaul areq.an_type = AN_RID_SSIDLIST; 116255992Swpaul 116355992Swpaul an_getval(iface, &areq); 1164119156Sambrisko ssid = (struct an_ltv_ssidlist_new *)&areq; 116555992Swpaul 1166119156Sambrisko max = (areq.an_len - 4) / sizeof(struct an_ltv_ssid_entry); 1167119156Sambrisko if ( max > MAX_SSIDS ) { 1168132860Snjl printf("Too many SSIDs only printing %d of %d\n", 1169119156Sambrisko MAX_SSIDS, max); 1170119156Sambrisko max = MAX_SSIDS; 117155992Swpaul } 117255992Swpaul 1173119156Sambrisko if ( act > max ) { 1174119156Sambrisko errx(1, "bad modifier %d: there " 1175119156Sambrisko "are only %d SSID settings", act, max); 1176119156Sambrisko exit(1); 1177119156Sambrisko } 1178119156Sambrisko 1179119156Sambrisko bzero(ssid->an_entry[act-1].an_ssid, 1180119156Sambrisko sizeof(ssid->an_entry[act-1].an_ssid)); 1181119156Sambrisko strlcpy(ssid->an_entry[act-1].an_ssid, (char *)arg, 1182119156Sambrisko sizeof(ssid->an_entry[act-1].an_ssid)); 1183119156Sambrisko ssid->an_entry[act-1].an_len 1184119156Sambrisko = strlen(ssid->an_entry[act-1].an_ssid); 1185119156Sambrisko 118655992Swpaul an_setval(iface, &areq); 1187119156Sambrisko 118855992Swpaul exit(0); 118955992Swpaul} 119055992Swpaul 119155992Swpaul#ifdef ANCACHE 1192132860Snjlstatic void 1193132860Snjlan_zerocache(const char *iface) 119455992Swpaul{ 119555992Swpaul struct an_req areq; 119655992Swpaul 1197132900Snjl bzero(&areq, sizeof(areq)); 119855992Swpaul areq.an_len = 0; 119955992Swpaul areq.an_type = AN_RID_ZERO_CACHE; 120055992Swpaul 120155992Swpaul an_getval(iface, &areq); 120255992Swpaul} 120355992Swpaul 1204132860Snjlstatic void 1205132860Snjlan_readcache(const char *iface) 120655992Swpaul{ 120755992Swpaul struct an_req areq; 1208132900Snjl uint16_t *an_sigitems; 120955992Swpaul struct an_sigcache *sc; 121055992Swpaul int i; 121155992Swpaul 121255992Swpaul if (iface == NULL) 121355992Swpaul errx(1, "must specify interface name"); 121455992Swpaul 1215132900Snjl bzero(&areq, sizeof(areq)); 121655992Swpaul areq.an_len = AN_MAX_DATALEN; 121755992Swpaul areq.an_type = AN_RID_READ_CACHE; 121855992Swpaul 121955992Swpaul an_getval(iface, &areq); 122055992Swpaul 1221132900Snjl an_sigitems = areq.an_val; 1222132900Snjl sc = (struct an_sigcache *)((int32_t *)areq.an_val + 1); 122355992Swpaul 122455992Swpaul for (i = 0; i < *an_sigitems; i++) { 122555992Swpaul printf("[%d/%d]:", i+1, *an_sigitems); 122655992Swpaul printf(" %02x:%02x:%02x:%02x:%02x:%02x,", 122755992Swpaul sc->macsrc[0]&0xff, 122855992Swpaul sc->macsrc[1]&0xff, 122955992Swpaul sc->macsrc[2]&0xff, 123055992Swpaul sc->macsrc[3]&0xff, 123155992Swpaul sc->macsrc[4]&0xff, 123255992Swpaul sc->macsrc[5]&0xff); 123355992Swpaul printf(" %d.%d.%d.%d,",((sc->ipsrc >> 0) & 0xff), 123455992Swpaul ((sc->ipsrc >> 8) & 0xff), 123555992Swpaul ((sc->ipsrc >> 16) & 0xff), 123655992Swpaul ((sc->ipsrc >> 24) & 0xff)); 123755992Swpaul printf(" sig: %d, noise: %d, qual: %d\n", 123855992Swpaul sc->signal, 123955992Swpaul sc->noise, 124055992Swpaul sc->quality); 124155992Swpaul sc++; 124255992Swpaul } 124355992Swpaul} 124455992Swpaul#endif 124555992Swpaul 1246132860Snjlstatic int 1247132860Snjlan_hex2int(char c) 124868692Swpaul{ 124968692Swpaul if (c >= '0' && c <= '9') 125068692Swpaul return (c - '0'); 125168692Swpaul if (c >= 'A' && c <= 'F') 125268692Swpaul return (c - 'A' + 10); 125368692Swpaul if (c >= 'a' && c <= 'f') 125468692Swpaul return (c - 'a' + 10); 125555992Swpaul 125668692Swpaul return (0); 125768692Swpaul} 125868692Swpaul 1259132860Snjlstatic void 1260132860Snjlan_str2key(const char *s, struct an_ltv_key *k) 126168692Swpaul{ 126268692Swpaul int n, i; 126368692Swpaul char *p; 126468692Swpaul 126568692Swpaul /* Is this a hex string? */ 126668692Swpaul if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { 126768692Swpaul /* Yes, convert to int. */ 126868692Swpaul n = 0; 126968692Swpaul p = (char *)&k->key[0]; 127080454Sbrooks for (i = 2; s[i] != '\0' && s[i + 1] != '\0'; i+= 2) { 127168692Swpaul *p++ = (an_hex2int(s[i]) << 4) + an_hex2int(s[i + 1]); 127268692Swpaul n++; 127368692Swpaul } 127480454Sbrooks if (s[i] != '\0') 127580454Sbrooks errx(1, "hex strings must be of even length"); 127668692Swpaul k->klen = n; 127768692Swpaul } else { 127868692Swpaul /* No, just copy it in. */ 127968692Swpaul bcopy(s, k->key, strlen(s)); 128068692Swpaul k->klen = strlen(s); 128168692Swpaul } 128268692Swpaul 128368692Swpaul return; 128468692Swpaul} 128568692Swpaul 1286132860Snjlstatic void 1287132860Snjlan_setkeys(const char *iface, const char *key, int keytype) 128868692Swpaul{ 128968692Swpaul struct an_req areq; 129068692Swpaul struct an_ltv_key *k; 129168692Swpaul 1292132900Snjl bzero(&areq, sizeof(areq)); 129368692Swpaul k = (struct an_ltv_key *)&areq; 129468692Swpaul 129568692Swpaul if (strlen(key) > 28) { 129668692Swpaul err(1, "encryption key must be no " 129768692Swpaul "more than 18 characters long"); 129868692Swpaul } 129968692Swpaul 130068692Swpaul an_str2key(key, k); 130168692Swpaul 130268692Swpaul k->kindex=keytype/2; 130368692Swpaul 130468692Swpaul if (!(k->klen==0 || k->klen==5 || k->klen==13)) { 130568692Swpaul err(1, "encryption key must be 0, 5 or 13 bytes long"); 130668692Swpaul } 130768692Swpaul 130868692Swpaul /* default mac and only valid one (from manual) 1.0.0.0.0.0 */ 130968692Swpaul k->mac[0]=1; 131068692Swpaul k->mac[1]=0; 131168692Swpaul k->mac[2]=0; 131268692Swpaul k->mac[3]=0; 131368692Swpaul k->mac[4]=0; 131468692Swpaul k->mac[5]=0; 131568692Swpaul 131688748Sambrisko switch(keytype & 1) { 131768692Swpaul case 0: 131868692Swpaul areq.an_len = sizeof(struct an_ltv_key); 131968692Swpaul areq.an_type = AN_RID_WEP_PERM; 132068692Swpaul an_setval(iface, &areq); 132168692Swpaul break; 132268692Swpaul case 1: 132368692Swpaul areq.an_len = sizeof(struct an_ltv_key); 132468692Swpaul areq.an_type = AN_RID_WEP_TEMP; 132568692Swpaul an_setval(iface, &areq); 132668692Swpaul break; 132768692Swpaul } 132868692Swpaul} 132968692Swpaul 1330201387Sedstatic void 1331201387Sedan_readkeyinfo(const char *iface) 133269772Sarchie{ 133369772Sarchie struct an_req areq; 133489380Sambrisko struct an_ltv_genconfig *cfg; 133569772Sarchie struct an_ltv_key *k; 133669772Sarchie int i; 133789380Sambrisko int home; 133869772Sarchie 133989380Sambrisko areq.an_len = sizeof(areq); 134089380Sambrisko areq.an_type = AN_RID_ACTUALCFG; 134189380Sambrisko an_getval(iface, &areq); 134289380Sambrisko cfg = (struct an_ltv_genconfig *)&areq; 134389380Sambrisko if (cfg->an_home_product & AN_HOME_NETWORK) 134489380Sambrisko home = 1; 134589380Sambrisko else 134689380Sambrisko home = 0; 134789380Sambrisko 1348132900Snjl bzero(&areq, sizeof(areq)); 134969772Sarchie k = (struct an_ltv_key *)&areq; 135069772Sarchie 135169772Sarchie printf("WEP Key status:\n"); 135269772Sarchie areq.an_type = AN_RID_WEP_TEMP; /* read first key */ 135388748Sambrisko for(i=0; i<5; i++) { 135469772Sarchie areq.an_len = sizeof(struct an_ltv_key); 135569772Sarchie an_getval(iface, &areq); 135688748Sambrisko if (k->kindex == 0xffff) 135783269Sbrooks break; 135888748Sambrisko switch (k->klen) { 135969772Sarchie case 0: 1360132860Snjl printf("\tKey %u is unset\n", k->kindex); 136169772Sarchie break; 136269772Sarchie case 5: 1363132860Snjl printf("\tKey %u is set 40 bits\n", k->kindex); 136469772Sarchie break; 136569772Sarchie case 13: 1366132860Snjl printf("\tKey %u is set 128 bits\n", k->kindex); 136769772Sarchie break; 136869772Sarchie default: 1369132860Snjl printf("\tWEP Key %d has an unknown size %u\n", 137069772Sarchie i, k->klen); 137169772Sarchie } 137269772Sarchie 137369772Sarchie areq.an_type = AN_RID_WEP_PERM; /* read next key */ 137469772Sarchie } 137569772Sarchie k->kindex = 0xffff; 137669772Sarchie areq.an_len = sizeof(struct an_ltv_key); 137769772Sarchie an_getval(iface, &areq); 137889380Sambrisko printf("\tThe active transmit key is %d\n", 4 * home + k->mac[0]); 137969772Sarchie 138069772Sarchie return; 138169772Sarchie} 138269772Sarchie 1383132860Snjlstatic void 1384132860Snjlan_enable_tx_key(const char *iface, const char *arg) 138569772Sarchie{ 138669772Sarchie struct an_req areq; 138769772Sarchie struct an_ltv_key *k; 138888748Sambrisko struct an_ltv_genconfig *config; 138969772Sarchie 1390132900Snjl bzero(&areq, sizeof(areq)); 139188748Sambrisko 139288748Sambrisko /* set home or not home mode */ 139388748Sambrisko areq.an_len = sizeof(struct an_ltv_genconfig); 139488748Sambrisko areq.an_type = AN_RID_GENCONFIG; 139588748Sambrisko an_getval(iface, &areq); 139688748Sambrisko config = (struct an_ltv_genconfig *)&areq; 139788748Sambrisko if (atoi(arg) == 4) { 139888748Sambrisko config->an_home_product |= AN_HOME_NETWORK; 139988748Sambrisko }else{ 140088748Sambrisko config->an_home_product &= ~AN_HOME_NETWORK; 140188748Sambrisko } 140288748Sambrisko an_setval(iface, &areq); 140388748Sambrisko 1404132900Snjl bzero(&areq, sizeof(areq)); 140588748Sambrisko 140669772Sarchie k = (struct an_ltv_key *)&areq; 140769772Sarchie 140869772Sarchie /* From a Cisco engineer write the transmit key to use in the 140969772Sarchie first MAC, index is FFFF*/ 141069772Sarchie k->kindex=0xffff; 141169772Sarchie k->klen=0; 141269772Sarchie 141369772Sarchie k->mac[0]=atoi(arg); 141469772Sarchie k->mac[1]=0; 141569772Sarchie k->mac[2]=0; 141669772Sarchie k->mac[3]=0; 141769772Sarchie k->mac[4]=0; 141869772Sarchie k->mac[5]=0; 141969772Sarchie 142069772Sarchie areq.an_len = sizeof(struct an_ltv_key); 142169772Sarchie areq.an_type = AN_RID_WEP_PERM; 142269772Sarchie an_setval(iface, &areq); 142369772Sarchie} 142469772Sarchie 1425132860Snjlstatic void 1426132860Snjlan_enable_leap_mode(const char *iface, const char *username) 142788748Sambrisko{ 142888748Sambrisko struct an_req areq; 142988748Sambrisko struct an_ltv_status *sts; 143088748Sambrisko struct an_ltv_genconfig *cfg; 143188748Sambrisko struct an_ltv_caps *caps; 143288748Sambrisko struct an_ltv_leap_username an_username; 143388748Sambrisko struct an_ltv_leap_password an_password; 143488748Sambrisko char *password; 143588748Sambrisko MD4_CTX context; 143688748Sambrisko int len; 143788748Sambrisko int i; 143888748Sambrisko char unicode_password[LEAP_PASSWORD_MAX * 2]; 143988748Sambrisko 144088748Sambrisko areq.an_len = sizeof(areq); 144188748Sambrisko areq.an_type = AN_RID_CAPABILITIES; 144288748Sambrisko 144388748Sambrisko an_getval(iface, &areq); 144488748Sambrisko 144588748Sambrisko caps = (struct an_ltv_caps *)&areq; 144688748Sambrisko 144788748Sambrisko if (!caps->an_softcaps & AN_AUTHTYPE_LEAP) { 144888748Sambrisko fprintf(stderr, "Firmware does not support LEAP\n"); 144988748Sambrisko exit(1); 145088748Sambrisko } 145188748Sambrisko 145288748Sambrisko bzero(&an_username, sizeof(an_username)); 145388748Sambrisko bzero(&an_password, sizeof(an_password)); 145488748Sambrisko 145588748Sambrisko len = strlen(username); 145688748Sambrisko if (len > LEAP_USERNAME_MAX) { 145788748Sambrisko printf("Username too long (max %d)\n", LEAP_USERNAME_MAX); 145888748Sambrisko exit(1); 145988748Sambrisko } 146088748Sambrisko strncpy(an_username.an_username, username, len); 146188748Sambrisko an_username.an_username_len = len; 146288748Sambrisko an_username.an_len = sizeof(an_username); 146388748Sambrisko an_username.an_type = AN_RID_LEAPUSERNAME; 146488748Sambrisko 146588748Sambrisko password = getpass("Enter LEAP password:"); 146688748Sambrisko 146788748Sambrisko len = strlen(password); 146888748Sambrisko if (len > LEAP_PASSWORD_MAX) { 146988748Sambrisko printf("Password too long (max %d)\n", LEAP_PASSWORD_MAX); 147088748Sambrisko exit(1); 147188748Sambrisko } 147288748Sambrisko 147388748Sambrisko bzero(&unicode_password, sizeof(unicode_password)); 147488748Sambrisko for(i = 0; i < len; i++) { 147588748Sambrisko unicode_password[i * 2] = *password++; 147688748Sambrisko } 147788748Sambrisko 147888748Sambrisko /* First half */ 147988748Sambrisko MD4Init(&context); 148088748Sambrisko MD4Update(&context, unicode_password, len * 2); 148188748Sambrisko MD4Final(&an_password.an_password[0], &context); 148288748Sambrisko 148388748Sambrisko /* Second half */ 148488748Sambrisko MD4Init (&context); 148588748Sambrisko MD4Update (&context, &an_password.an_password[0], 16); 148688748Sambrisko MD4Final (&an_password.an_password[16], &context); 148788748Sambrisko 148888748Sambrisko an_password.an_password_len = 32; 148988748Sambrisko an_password.an_len = sizeof(an_password); 149088748Sambrisko an_password.an_type = AN_RID_LEAPPASSWORD; 149188748Sambrisko 149288748Sambrisko an_setval(iface, (struct an_req *)&an_username); 149388748Sambrisko an_setval(iface, (struct an_req *)&an_password); 149488748Sambrisko 149588748Sambrisko areq.an_len = sizeof(areq); 149688748Sambrisko areq.an_type = AN_RID_GENCONFIG; 149788748Sambrisko an_getval(iface, &areq); 149888748Sambrisko cfg = (struct an_ltv_genconfig *)&areq; 149988748Sambrisko cfg->an_authtype = (AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP); 150088748Sambrisko an_setval(iface, &areq); 150188748Sambrisko 150288748Sambrisko sts = (struct an_ltv_status *)&areq; 150388748Sambrisko areq.an_type = AN_RID_STATUS; 150488748Sambrisko 150588748Sambrisko for (i = 60; i > 0; i--) { 150688748Sambrisko an_getval(iface, &areq); 150788748Sambrisko if (sts->an_opmode & AN_STATUS_OPMODE_LEAP) { 150888748Sambrisko printf("Authenticated\n"); 150988748Sambrisko break; 151088748Sambrisko } 151188748Sambrisko sleep(1); 151288748Sambrisko } 151388748Sambrisko 151488748Sambrisko if (i == 0) { 151588748Sambrisko fprintf(stderr, "Failed LEAP authentication\n"); 151688748Sambrisko exit(1); 151788748Sambrisko } 151888748Sambrisko} 151988748Sambrisko 1520132860Snjlint 1521132860Snjlmain(int argc, char *argv[]) 152255992Swpaul{ 152355992Swpaul int ch; 152455992Swpaul int act = 0; 152580454Sbrooks const char *iface = NULL; 152655992Swpaul int modifier = 0; 152768692Swpaul char *key = NULL; 152855992Swpaul void *arg = NULL; 152955992Swpaul char *p = argv[0]; 153055992Swpaul 153167823Sjoe /* Get the interface name */ 153267823Sjoe opterr = 0; 153367823Sjoe ch = getopt(argc, argv, "i:"); 153467823Sjoe if (ch == 'i') { 153567823Sjoe iface = optarg; 153667823Sjoe } else { 153770532Simp if (argc > 1 && *argv[1] != '-') { 153870532Simp iface = argv[1]; 153970532Simp optind = 2; 154070532Simp } else { 154170532Simp iface = "an0"; 154270532Simp optind = 1; 154370532Simp } 154467823Sjoe optreset = 1; 154567823Sjoe } 154667823Sjoe opterr = 1; 154767823Sjoe 154855992Swpaul while ((ch = getopt(argc, argv, 1549137169Sceri "ANISCTRht:a:e:o:s:n:v:d:j:b:c:f:r:p:w:m:l:k:K:W:QZM:L:")) != -1) { 155055992Swpaul switch(ch) { 155155992Swpaul case 'Z': 155255992Swpaul#ifdef ANCACHE 155355992Swpaul act = ACT_ZEROCACHE; 155455992Swpaul#else 155555992Swpaul errx(1, "ANCACHE not available"); 155655992Swpaul#endif 155755992Swpaul break; 155855992Swpaul case 'Q': 155955992Swpaul#ifdef ANCACHE 156055992Swpaul act = ACT_DUMPCACHE; 156155992Swpaul#else 156255992Swpaul errx(1, "ANCACHE not available"); 156355992Swpaul#endif 156455992Swpaul break; 156555992Swpaul case 'A': 156655992Swpaul act = ACT_DUMPAP; 156755992Swpaul break; 156855992Swpaul case 'N': 156955992Swpaul act = ACT_DUMPSSID; 157055992Swpaul break; 157155992Swpaul case 'S': 157255992Swpaul act = ACT_DUMPSTATUS; 157355992Swpaul break; 157455992Swpaul case 'I': 157555992Swpaul act = ACT_DUMPCAPS; 157655992Swpaul break; 157755992Swpaul case 'T': 157855992Swpaul act = ACT_DUMPSTATS; 157955992Swpaul break; 158055992Swpaul case 'C': 158155992Swpaul act = ACT_DUMPCONFIG; 158255992Swpaul break; 1583108401Sambrisko case 'R': 1584108401Sambrisko act = ACT_DUMPRSSIMAP; 1585108401Sambrisko break; 158655992Swpaul case 't': 158755992Swpaul act = ACT_SET_TXRATE; 158855992Swpaul arg = optarg; 158955992Swpaul break; 159055992Swpaul case 's': 159155992Swpaul act = ACT_SET_PWRSAVE; 159255992Swpaul arg = optarg; 159355992Swpaul break; 159455992Swpaul case 'p': 159555992Swpaul act = ACT_SET_TXPWR; 159655992Swpaul arg = optarg; 159755992Swpaul break; 159855992Swpaul case 'v': 159955992Swpaul modifier = atoi(optarg); 160055992Swpaul break; 160155992Swpaul case 'a': 160255992Swpaul switch(modifier) { 160355992Swpaul case 0: 160455992Swpaul case 1: 160555992Swpaul act = ACT_SET_AP1; 160655992Swpaul break; 160755992Swpaul case 2: 160855992Swpaul act = ACT_SET_AP2; 160955992Swpaul break; 161055992Swpaul case 3: 161155992Swpaul act = ACT_SET_AP3; 161255992Swpaul break; 161355992Swpaul case 4: 161455992Swpaul act = ACT_SET_AP4; 161555992Swpaul break; 161655992Swpaul default: 161755992Swpaul errx(1, "bad modifier %d: there " 161855992Swpaul "are only 4 access point settings", 161955992Swpaul modifier); 162055992Swpaul usage(p); 162155992Swpaul break; 162255992Swpaul } 162355992Swpaul arg = optarg; 162455992Swpaul break; 162555992Swpaul case 'b': 162655992Swpaul act = ACT_SET_BEACON_PERIOD; 162755992Swpaul arg = optarg; 162855992Swpaul break; 162955992Swpaul case 'd': 163055992Swpaul switch(modifier) { 163155992Swpaul case 0: 163255992Swpaul act = ACT_SET_DIVERSITY_RX; 163355992Swpaul break; 163455992Swpaul case 1: 163555992Swpaul act = ACT_SET_DIVERSITY_TX; 163655992Swpaul break; 163755992Swpaul default: 1638108401Sambrisko errx(1, "must specify RX or TX diversity"); 163955992Swpaul break; 164055992Swpaul } 1641108401Sambrisko if (!isdigit(*optarg)) { 1642108401Sambrisko errx(1, "%s is not numeric", optarg); 1643108401Sambrisko exit(1); 1644108401Sambrisko } 164555992Swpaul arg = optarg; 164655992Swpaul break; 164755992Swpaul case 'j': 164855992Swpaul act = ACT_SET_NETJOIN; 164955992Swpaul arg = optarg; 165055992Swpaul break; 165155992Swpaul case 'l': 165255992Swpaul act = ACT_SET_MYNAME; 165355992Swpaul arg = optarg; 165455992Swpaul break; 165555992Swpaul case 'm': 165655992Swpaul act = ACT_SET_MAC; 165755992Swpaul arg = optarg; 165855992Swpaul break; 165955992Swpaul case 'n': 1660119156Sambrisko if (modifier == 0) 1661119156Sambrisko modifier = 1; 1662119156Sambrisko act = ACT_SET_SSID; 166355992Swpaul arg = optarg; 166455992Swpaul break; 166555992Swpaul case 'o': 166655992Swpaul act = ACT_SET_OPMODE; 166755992Swpaul arg = optarg; 166855992Swpaul break; 166955992Swpaul case 'c': 167055992Swpaul act = ACT_SET_FREQ; 167155992Swpaul arg = optarg; 167255992Swpaul break; 167355992Swpaul case 'f': 167455992Swpaul act = ACT_SET_FRAG_THRESH; 167555992Swpaul arg = optarg; 167655992Swpaul break; 167768692Swpaul case 'W': 167868692Swpaul act = ACT_ENABLE_WEP; 167968692Swpaul arg = optarg; 168068692Swpaul break; 168168692Swpaul case 'K': 168268692Swpaul act = ACT_SET_KEY_TYPE; 168368692Swpaul arg = optarg; 168468692Swpaul break; 168568692Swpaul case 'k': 168668692Swpaul act = ACT_SET_KEYS; 168768692Swpaul key = optarg; 168868692Swpaul break; 168969772Sarchie case 'e': 169069772Sarchie act = ACT_ENABLE_TX_KEY; 169169772Sarchie arg = optarg; 169269772Sarchie break; 169355992Swpaul case 'q': 169455992Swpaul act = ACT_SET_RTS_RETRYLIM; 169555992Swpaul arg = optarg; 169655992Swpaul break; 169755992Swpaul case 'r': 169855992Swpaul act = ACT_SET_RTS_THRESH; 169955992Swpaul arg = optarg; 170055992Swpaul break; 170155992Swpaul case 'w': 170255992Swpaul act = ACT_SET_WAKE_DURATION; 170355992Swpaul arg = optarg; 170455992Swpaul break; 170583269Sbrooks case 'M': 170683269Sbrooks act = ACT_SET_MONITOR_MODE; 170783269Sbrooks arg = optarg; 170883269Sbrooks break; 170988748Sambrisko case 'L': 171088748Sambrisko act = ACT_SET_LEAP_MODE; 171188748Sambrisko arg = optarg; 171288748Sambrisko break; 171355992Swpaul case 'h': 171455992Swpaul default: 171555992Swpaul usage(p); 171655992Swpaul } 171755992Swpaul } 171855992Swpaul 171968692Swpaul if (iface == NULL || (!act && !key)) 172055992Swpaul usage(p); 172155992Swpaul 172255992Swpaul switch(act) { 172355992Swpaul case ACT_DUMPSTATUS: 172455992Swpaul an_dumpstatus(iface); 172555992Swpaul break; 172655992Swpaul case ACT_DUMPCAPS: 172755992Swpaul an_dumpcaps(iface); 172855992Swpaul break; 172955992Swpaul case ACT_DUMPSTATS: 173055992Swpaul an_dumpstats(iface); 173155992Swpaul break; 173255992Swpaul case ACT_DUMPCONFIG: 173355992Swpaul an_dumpconfig(iface); 173455992Swpaul break; 173555992Swpaul case ACT_DUMPSSID: 173655992Swpaul an_dumpssid(iface); 173755992Swpaul break; 173855992Swpaul case ACT_DUMPAP: 173955992Swpaul an_dumpap(iface); 174055992Swpaul break; 1741108401Sambrisko case ACT_DUMPRSSIMAP: 1742108401Sambrisko an_dumprssimap(iface); 1743108401Sambrisko break; 1744119156Sambrisko case ACT_SET_SSID: 1745119156Sambrisko an_setssid(iface, modifier, arg); 174655992Swpaul break; 174755992Swpaul case ACT_SET_AP1: 174855992Swpaul case ACT_SET_AP2: 174955992Swpaul case ACT_SET_AP3: 175055992Swpaul case ACT_SET_AP4: 175155992Swpaul an_setap(iface, act, arg); 175255992Swpaul break; 175355992Swpaul case ACT_SET_TXRATE: 175455992Swpaul an_setspeed(iface, act, arg); 175555992Swpaul break; 175655992Swpaul#ifdef ANCACHE 175755992Swpaul case ACT_ZEROCACHE: 175855992Swpaul an_zerocache(iface); 175955992Swpaul break; 176055992Swpaul case ACT_DUMPCACHE: 176155992Swpaul an_readcache(iface); 176255992Swpaul break; 176368692Swpaul 176455992Swpaul#endif 176568692Swpaul case ACT_SET_KEYS: 176668692Swpaul an_setkeys(iface, key, modifier); 176768692Swpaul break; 176869772Sarchie case ACT_ENABLE_TX_KEY: 176969772Sarchie an_enable_tx_key(iface, arg); 177069772Sarchie break; 177188748Sambrisko case ACT_SET_LEAP_MODE: 177288748Sambrisko an_enable_leap_mode(iface, arg); 177388748Sambrisko break; 177455992Swpaul default: 177555992Swpaul an_setconfig(iface, act, arg); 177655992Swpaul break; 177755992Swpaul } 177855992Swpaul 177955992Swpaul exit(0); 178055992Swpaul} 178155992Swpaul 1782