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