ancontrol.c revision 69772
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 * $FreeBSD: head/usr.sbin/ancontrol/ancontrol.c 69772 2000-12-08 19:02:35Z archie $
3355992Swpaul */
3455992Swpaul
3555992Swpaul#include <sys/types.h>
3655992Swpaul#include <sys/cdefs.h>
3755992Swpaul#include <sys/param.h>
3855992Swpaul#include <sys/socket.h>
3955992Swpaul#include <sys/ioctl.h>
4055992Swpaul#include <sys/socket.h>
4155992Swpaul
4255992Swpaul#include <net/if.h>
4355992Swpaul#include <net/if_var.h>
4455992Swpaul#include <net/ethernet.h>
4555992Swpaul
4655992Swpaul#include <dev/an/if_aironet_ieee.h>
4755992Swpaul
4855992Swpaul#include <stdio.h>
4955992Swpaul#include <string.h>
5055992Swpaul#include <stdlib.h>
5155992Swpaul#include <unistd.h>
5255992Swpaul#include <errno.h>
5355992Swpaul#include <err.h>
5455992Swpaul
5555992Swpaul#if !defined(lint)
5655992Swpaulstatic const char copyright[] = "@(#) Copyright (c) 1997, 1998, 1999\
5755992Swpaul	Bill Paul. All rights reserved.";
5855992Swpaulstatic const char rcsid[] =
5955992Swpaul  "@(#) $FreeBSD: head/usr.sbin/ancontrol/ancontrol.c 69772 2000-12-08 19:02:35Z archie $";
6055992Swpaul#endif
6155992Swpaul
6255992Swpaulstatic void an_getval		__P((char *, struct an_req *));
6355992Swpaulstatic void an_setval		__P((char *, struct an_req *));
6455992Swpaulstatic void an_printwords	__P((u_int16_t *, int));
6555992Swpaulstatic void an_printspeeds	__P((u_int8_t*, int));
6655992Swpaulstatic void an_printbool	__P((int));
6755992Swpaulstatic void an_printhex		__P((char *, int));
6855992Swpaulstatic void an_printstr		__P((char *, int));
6955992Swpaulstatic void an_dumpstatus	__P((char *));
7055992Swpaulstatic void an_dumpstats	__P((char *));
7155992Swpaulstatic void an_dumpconfig	__P((char *));
7255992Swpaulstatic void an_dumpcaps		__P((char *));
7355992Swpaulstatic void an_dumpssid		__P((char *));
7455992Swpaulstatic void an_dumpap		__P((char *));
7555992Swpaulstatic void an_setconfig	__P((char *, int, void *));
7655992Swpaulstatic void an_setssid		__P((char *, int, void *));
7755992Swpaulstatic void an_setap		__P((char *, int, void *));
7855992Swpaulstatic void an_setspeed		__P((char *, int, void *));
7969772Sarchiestatic void an_readkeyinfo	__P((char *));
8055992Swpaul#ifdef ANCACHE
8155992Swpaulstatic void an_zerocache	__P((char *));
8255992Swpaulstatic void an_readcache	__P((char *));
8355992Swpaul#endif
8455992Swpaulstatic void usage		__P((char *));
8555992Swpaulint main			__P((int, char **));
8655992Swpaul
8755992Swpaul#define ACT_DUMPSTATS 1
8855992Swpaul#define ACT_DUMPCONFIG 2
8955992Swpaul#define ACT_DUMPSTATUS 3
9055992Swpaul#define ACT_DUMPCAPS 4
9155992Swpaul#define ACT_DUMPSSID 5
9255992Swpaul#define ACT_DUMPAP 6
9355992Swpaul
9455992Swpaul#define ACT_SET_OPMODE 7
9555992Swpaul#define ACT_SET_SSID1 8
9655992Swpaul#define ACT_SET_SSID2 9
9755992Swpaul#define ACT_SET_SSID3 10
9855992Swpaul#define ACT_SET_FREQ 11
9955992Swpaul#define ACT_SET_AP1 12
10055992Swpaul#define ACT_SET_AP2 13
10155992Swpaul#define ACT_SET_AP3 14
10255992Swpaul#define ACT_SET_AP4 15
10355992Swpaul#define ACT_SET_DRIVERNAME 16
10455992Swpaul#define ACT_SET_SCANMODE 17
10555992Swpaul#define ACT_SET_TXRATE 18
10655992Swpaul#define ACT_SET_RTS_THRESH 19
10755992Swpaul#define ACT_SET_PWRSAVE 20
10855992Swpaul#define ACT_SET_DIVERSITY_RX 21
10955992Swpaul#define ACT_SET_DIVERSITY_TX 22
11055992Swpaul#define ACT_SET_RTS_RETRYLIM 23
11155992Swpaul#define ACT_SET_WAKE_DURATION 24
11255992Swpaul#define ACT_SET_BEACON_PERIOD 25
11355992Swpaul#define ACT_SET_TXPWR 26
11455992Swpaul#define ACT_SET_FRAG_THRESH 27
11555992Swpaul#define ACT_SET_NETJOIN 28
11655992Swpaul#define ACT_SET_MYNAME 29
11755992Swpaul#define ACT_SET_MAC 30
11855992Swpaul
11955992Swpaul#define ACT_DUMPCACHE 31
12055992Swpaul#define ACT_ZEROCACHE 32
12155992Swpaul
12268692Swpaul#define ACT_ENABLE_WEP 33
12368692Swpaul#define ACT_SET_KEY_TYPE 34
12468692Swpaul#define ACT_SET_KEYS 35
12569772Sarchie#define ACT_ENABLE_TX_KEY 36
12668692Swpaul
12755992Swpaulstatic void an_getval(iface, areq)
12855992Swpaul	char			*iface;
12955992Swpaul	struct an_req		*areq;
13055992Swpaul{
13155992Swpaul	struct ifreq		ifr;
13255992Swpaul	int			s;
13355992Swpaul
13455992Swpaul	bzero((char *)&ifr, sizeof(ifr));
13555992Swpaul
13661815Sroberto	strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
13755992Swpaul	ifr.ifr_data = (caddr_t)areq;
13855992Swpaul
13955992Swpaul	s = socket(AF_INET, SOCK_DGRAM, 0);
14055992Swpaul
14155992Swpaul	if (s == -1)
14255992Swpaul		err(1, "socket");
14355992Swpaul
14455992Swpaul	if (ioctl(s, SIOCGAIRONET, &ifr) == -1)
14555992Swpaul		err(1, "SIOCGAIRONET");
14655992Swpaul
14755992Swpaul	close(s);
14855992Swpaul
14955992Swpaul	return;
15055992Swpaul}
15155992Swpaul
15255992Swpaulstatic void an_setval(iface, areq)
15355992Swpaul	char			*iface;
15455992Swpaul	struct an_req		*areq;
15555992Swpaul{
15655992Swpaul	struct ifreq		ifr;
15755992Swpaul	int			s;
15855992Swpaul
15955992Swpaul	bzero((char *)&ifr, sizeof(ifr));
16055992Swpaul
16161815Sroberto	strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
16255992Swpaul	ifr.ifr_data = (caddr_t)areq;
16355992Swpaul
16455992Swpaul	s = socket(AF_INET, SOCK_DGRAM, 0);
16555992Swpaul
16655992Swpaul	if (s == -1)
16755992Swpaul		err(1, "socket");
16855992Swpaul
16955992Swpaul	if (ioctl(s, SIOCSAIRONET, &ifr) == -1)
17055992Swpaul		err(1, "SIOCSAIRONET");
17155992Swpaul
17255992Swpaul	close(s);
17355992Swpaul
17455992Swpaul	return;
17555992Swpaul}
17655992Swpaul
17755992Swpaulstatic void an_printstr(str, len)
17855992Swpaul	char			*str;
17955992Swpaul	int			len;
18055992Swpaul{
18155992Swpaul	int			i;
18255992Swpaul
18355992Swpaul	for (i = 0; i < len - 1; i++) {
18455992Swpaul		if (str[i] == '\0')
18555992Swpaul			str[i] = ' ';
18655992Swpaul	}
18755992Swpaul
18855992Swpaul	printf("[ %.*s ]", len, str);
18955992Swpaul
19055992Swpaul	return;
19155992Swpaul}
19255992Swpaul
19355992Swpaulstatic void an_printwords(w, len)
19455992Swpaul	u_int16_t		*w;
19555992Swpaul	int			len;
19655992Swpaul{
19755992Swpaul	int			i;
19855992Swpaul
19955992Swpaul	printf("[ ");
20055992Swpaul	for (i = 0; i < len; i++)
20155992Swpaul		printf("%d ", w[i]);
20255992Swpaul	printf("]");
20355992Swpaul
20455992Swpaul	return;
20555992Swpaul}
20655992Swpaul
20755992Swpaulstatic void an_printspeeds(w, len)
20855992Swpaul	u_int8_t		*w;
20955992Swpaul	int			len;
21055992Swpaul{
21155992Swpaul	int			i;
21255992Swpaul
21355992Swpaul	printf("[ ");
21455992Swpaul	for (i = 0; i < len && w[i]; i++)
21555992Swpaul		printf("%2.1fMbps ", w[i] * 0.500);
21655992Swpaul	printf("]");
21755992Swpaul
21855992Swpaul	return;
21955992Swpaul}
22055992Swpaul
22155992Swpaulstatic void an_printbool(val)
22255992Swpaul	int			val;
22355992Swpaul{
22455992Swpaul	if (val)
22555992Swpaul		printf("[ On ]");
22655992Swpaul	else
22755992Swpaul		printf("[ Off ]");
22855992Swpaul
22955992Swpaul	return;
23055992Swpaul}
23155992Swpaul
23255992Swpaulstatic void an_printhex(ptr, len)
23355992Swpaul	char			*ptr;
23455992Swpaul	int			len;
23555992Swpaul{
23655992Swpaul	int			i;
23755992Swpaul
23855992Swpaul	printf("[ ");
23955992Swpaul	for (i = 0; i < len; i++) {
24055992Swpaul		printf("%02x", ptr[i] & 0xFF);
24155992Swpaul		if (i < (len - 1))
24255992Swpaul			printf(":");
24355992Swpaul	}
24455992Swpaul
24555992Swpaul	printf(" ]");
24655992Swpaul	return;
24755992Swpaul}
24855992Swpaul
24968692Swpaul
25068692Swpaul
25155992Swpaulstatic void an_dumpstatus(iface)
25255992Swpaul	char			*iface;
25355992Swpaul{
25455992Swpaul	struct an_ltv_status	*sts;
25555992Swpaul	struct an_req		areq;
25655992Swpaul
25755992Swpaul	areq.an_len = sizeof(areq);
25855992Swpaul	areq.an_type = AN_RID_STATUS;
25955992Swpaul
26055992Swpaul	an_getval(iface, &areq);
26155992Swpaul
26255992Swpaul	sts = (struct an_ltv_status *)&areq;
26355992Swpaul
26455992Swpaul	printf("MAC address:\t\t");
26555992Swpaul	an_printhex((char *)&sts->an_macaddr, ETHER_ADDR_LEN);
26655992Swpaul	printf("\nOperating mode:\t\t[ ");
26755992Swpaul	if (sts->an_opmode & AN_STATUS_OPMODE_CONFIGURED)
26855992Swpaul		printf("configured ");
26955992Swpaul	if (sts->an_opmode & AN_STATUS_OPMODE_MAC_ENABLED)
27055992Swpaul		printf("MAC ON ");
27155992Swpaul	if (sts->an_opmode & AN_STATUS_OPMODE_RX_ENABLED)
27255992Swpaul		printf("RX ON ");
27355992Swpaul	if (sts->an_opmode & AN_STATUS_OPMODE_IN_SYNC)
27455992Swpaul		printf("synced ");
27555992Swpaul	if (sts->an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
27655992Swpaul		printf("associated ");
27755992Swpaul	if (sts->an_opmode & AN_STATUS_OPMODE_ERROR)
27855992Swpaul		printf("error ");
27955992Swpaul	printf("]\n");
28055992Swpaul	printf("Error code:\t\t");
28155992Swpaul	an_printhex((char *)&sts->an_errcode, 1);
28255992Swpaul	printf("\nSignal quality:\t\t");
28355992Swpaul	an_printhex((char *)&sts->an_cur_signal_quality, 1);
28455992Swpaul	printf("\nCurrent SSID:\t\t");
28555992Swpaul	an_printstr((char *)&sts->an_ssid, sts->an_ssidlen);
28655992Swpaul	printf("\nCurrent AP name:\t");
28755992Swpaul	an_printstr((char *)&sts->an_ap_name, 16);
28855992Swpaul	printf("\nCurrent BSSID:\t\t");
28955992Swpaul	an_printhex((char *)&sts->an_cur_bssid, ETHER_ADDR_LEN);
29055992Swpaul	printf("\nBeacon period:\t\t");
29155992Swpaul	an_printwords(&sts->an_beacon_period, 1);
29255992Swpaul	printf("\nDTIM period:\t\t");
29355992Swpaul	an_printwords(&sts->an_dtim_period, 1);
29455992Swpaul	printf("\nATIM duration:\t\t");
29555992Swpaul	an_printwords(&sts->an_atim_duration, 1);
29655992Swpaul	printf("\nHOP period:\t\t");
29755992Swpaul	an_printwords(&sts->an_hop_period, 1);
29855992Swpaul	printf("\nChannel set:\t\t");
29955992Swpaul	an_printwords(&sts->an_channel_set, 1);
30055992Swpaul	printf("\nCurrent channel:\t");
30155992Swpaul	an_printwords(&sts->an_cur_channel, 1);
30255992Swpaul	printf("\nHops to backbone:\t");
30355992Swpaul	an_printwords(&sts->an_hops_to_backbone, 1);
30455992Swpaul	printf("\nTotal AP load:\t\t");
30555992Swpaul	an_printwords(&sts->an_ap_total_load, 1);
30655992Swpaul	printf("\nOur generated load:\t");
30755992Swpaul	an_printwords(&sts->an_our_generated_load, 1);
30855992Swpaul	printf("\nAccumulated ARL:\t");
30955992Swpaul	an_printwords(&sts->an_accumulated_arl, 1);
31055992Swpaul	printf("\n");
31155992Swpaul	return;
31255992Swpaul}
31355992Swpaul
31455992Swpaulstatic void an_dumpcaps(iface)
31555992Swpaul	char			*iface;
31655992Swpaul{
31755992Swpaul	struct an_ltv_caps	*caps;
31855992Swpaul	struct an_req		areq;
31955992Swpaul	u_int16_t		tmp;
32055992Swpaul
32155992Swpaul	areq.an_len = sizeof(areq);
32255992Swpaul	areq.an_type = AN_RID_CAPABILITIES;
32355992Swpaul
32455992Swpaul	an_getval(iface, &areq);
32555992Swpaul
32655992Swpaul	caps = (struct an_ltv_caps *)&areq;
32755992Swpaul
32855992Swpaul	printf("OUI:\t\t\t");
32955992Swpaul	an_printhex((char *)&caps->an_oui, 3);
33055992Swpaul	printf("\nProduct number:\t\t");
33155992Swpaul	an_printwords(&caps->an_prodnum, 1);
33255992Swpaul	printf("\nManufacturer name:\t");
33355992Swpaul	an_printstr((char *)&caps->an_manufname, 32);
33455992Swpaul	printf("\nProduce name:\t\t");
33555992Swpaul	an_printstr((char *)&caps->an_prodname, 16);
33655992Swpaul	printf("\nFirmware version:\t");
33755992Swpaul	an_printstr((char *)&caps->an_prodvers, 1);
33855992Swpaul	printf("\nOEM MAC address:\t");
33955992Swpaul	an_printhex((char *)&caps->an_oemaddr, ETHER_ADDR_LEN);
34055992Swpaul	printf("\nAironet MAC address:\t");
34155992Swpaul	an_printhex((char *)&caps->an_aironetaddr, ETHER_ADDR_LEN);
34255992Swpaul	printf("\nRadio type:\t\t[ ");
34355992Swpaul	if (caps->an_radiotype & AN_RADIOTYPE_80211_FH)
34455992Swpaul		printf("802.11 FH");
34555992Swpaul	else if (caps->an_radiotype & AN_RADIOTYPE_80211_DS)
34655992Swpaul		printf("802.11 DS");
34755992Swpaul	else if (caps->an_radiotype & AN_RADIOTYPE_LM2000_DS)
34855992Swpaul		printf("LM2000 DS");
34955992Swpaul	else
35055992Swpaul		printf("unknown (%x)", caps->an_radiotype);
35155992Swpaul	printf(" ]");
35255992Swpaul	printf("\nRegulatory domain:\t");
35355992Swpaul	an_printwords(&caps->an_regdomain, 1);
35455992Swpaul	printf("\nAssigned CallID:\t");
35555992Swpaul	an_printhex((char *)&caps->an_callid, 6);
35655992Swpaul	printf("\nSupported speeds:\t");
35755992Swpaul	an_printspeeds(caps->an_rates, 8);
35855992Swpaul	printf("\nRX Diversity:\t\t[ ");
35955992Swpaul	if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
36055992Swpaul		printf("antenna 1 only");
36155992Swpaul	else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
36255992Swpaul		printf("antenna 2 only");
36355992Swpaul	else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
36455992Swpaul		printf("antenna 1 and 2");
36555992Swpaul	printf(" ]");
36655992Swpaul	printf("\nTX Diversity:\t\t[ ");
36755992Swpaul	if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
36855992Swpaul		printf("antenna 1 only");
36955992Swpaul	else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
37055992Swpaul		printf("antenna 2 only");
37155992Swpaul	else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
37255992Swpaul		printf("antenna 1 and 2");
37355992Swpaul	printf(" ]");
37455992Swpaul	printf("\nSupported power levels:\t");
37555992Swpaul	an_printwords(caps->an_tx_powerlevels, 8);
37655992Swpaul	printf("\nHardware revision:\t");
37755992Swpaul	tmp = ntohs(caps->an_hwrev);
37855992Swpaul	an_printhex((char *)&tmp, 2);
37955992Swpaul	printf("\nSoftware revision:\t");
38055992Swpaul	tmp = ntohs(caps->an_fwrev);
38155992Swpaul	an_printhex((char *)&tmp, 2);
38255992Swpaul	printf("\nSoftware subrevision:\t");
38355992Swpaul	tmp = ntohs(caps->an_fwsubrev);
38455992Swpaul	an_printhex((char *)&tmp, 2);
38555992Swpaul	printf("\nInterface revision:\t");
38655992Swpaul	tmp = ntohs(caps->an_ifacerev);
38755992Swpaul	an_printhex((char *)&tmp, 2);
38855992Swpaul	printf("\nBootblock revision:\t");
38955992Swpaul	tmp = ntohs(caps->an_bootblockrev);
39055992Swpaul	an_printhex((char *)&tmp, 2);
39155992Swpaul	printf("\n");
39255992Swpaul	return;
39355992Swpaul}
39455992Swpaul
39555992Swpaulstatic void an_dumpstats(iface)
39655992Swpaul	char			*iface;
39755992Swpaul{
39855992Swpaul	struct an_ltv_stats	*stats;
39955992Swpaul	struct an_req		areq;
40055992Swpaul	caddr_t			ptr;
40155992Swpaul
40255992Swpaul	areq.an_len = sizeof(areq);
40355992Swpaul	areq.an_type = AN_RID_32BITS_CUM;
40455992Swpaul
40555992Swpaul	an_getval(iface, &areq);
40655992Swpaul
40755992Swpaul	ptr = (caddr_t)&areq;
40855992Swpaul	ptr -= 2;
40955992Swpaul	stats = (struct an_ltv_stats *)ptr;
41055992Swpaul
41155992Swpaul	printf("RX overruns:\t\t\t\t\t[ %d ]\n", stats->an_rx_overruns);
41255992Swpaul	printf("RX PLCP CSUM errors:\t\t\t\t[ %d ]\n",
41355992Swpaul	    stats->an_rx_plcp_csum_errs);
41455992Swpaul	printf("RX PLCP format errors:\t\t\t\t[ %d ]\n",
41555992Swpaul	    stats->an_rx_plcp_format_errs);
41655992Swpaul	printf("RX PLCP length errors:\t\t\t\t[ %d ]\n",
41755992Swpaul	    stats->an_rx_plcp_len_errs);
41855992Swpaul	printf("RX MAC CRC errors:\t\t\t\t[ %d ]\n",
41955992Swpaul	    stats->an_rx_mac_crc_errs);
42055992Swpaul	printf("RX MAC CRC OK:\t\t\t\t\t[ %d ]\n",
42155992Swpaul	    stats->an_rx_mac_crc_ok);
42255992Swpaul	printf("RX WEP errors:\t\t\t\t\t[ %d ]\n",
42355992Swpaul	    stats->an_rx_wep_errs);
42455992Swpaul	printf("RX WEP OK:\t\t\t\t\t[ %d ]\n",
42555992Swpaul	    stats->an_rx_wep_ok);
42655992Swpaul	printf("Long retries:\t\t\t\t\t[ %d ]\n",
42755992Swpaul	    stats->an_retry_long);
42855992Swpaul	printf("Short retries:\t\t\t\t\t[ %d ]\n",
42955992Swpaul	    stats->an_retry_short);
43055992Swpaul	printf("Retries exchausted:\t\t\t\t[ %d ]\n",
43155992Swpaul	    stats->an_retry_max);
43255992Swpaul	printf("Bad ACK:\t\t\t\t\t[ %d ]\n",
43355992Swpaul	    stats->an_no_ack);
43455992Swpaul	printf("Bad CTS:\t\t\t\t\t[ %d ]\n",
43555992Swpaul	    stats->an_no_cts);
43655992Swpaul	printf("RX good ACKs:\t\t\t\t\t[ %d ]\n",
43755992Swpaul	    stats->an_rx_ack_ok);
43855992Swpaul	printf("RX good CTSs:\t\t\t\t\t[ %d ]\n",
43955992Swpaul	    stats->an_rx_cts_ok);
44055992Swpaul	printf("TX good ACKs:\t\t\t\t\t[ %d ]\n",
44155992Swpaul	    stats->an_tx_ack_ok);
44255992Swpaul	printf("TX good RTSs:\t\t\t\t\t[ %d ]\n",
44355992Swpaul	    stats->an_tx_rts_ok);
44455992Swpaul	printf("TX good CTSs:\t\t\t\t\t[ %d ]\n",
44555992Swpaul	    stats->an_tx_cts_ok);
44655992Swpaul	printf("LMAC multicasts transmitted:\t\t\t[ %d ]\n",
44755992Swpaul	    stats->an_tx_lmac_mcasts);
44855992Swpaul	printf("LMAC broadcasts transmitted:\t\t\t[ %d ]\n",
44955992Swpaul	    stats->an_tx_lmac_bcasts);
45055992Swpaul	printf("LMAC unicast frags transmitted:\t\t\t[ %d ]\n",
45155992Swpaul	    stats->an_tx_lmac_ucast_frags);
45255992Swpaul	printf("LMAC unicasts transmitted:\t\t\t[ %d ]\n",
45355992Swpaul	    stats->an_tx_lmac_ucasts);
45455992Swpaul	printf("Beacons transmitted:\t\t\t\t[ %d ]\n",
45555992Swpaul	    stats->an_tx_beacons);
45655992Swpaul	printf("Beacons received:\t\t\t\t[ %d ]\n",
45755992Swpaul	    stats->an_rx_beacons);
45855992Swpaul	printf("Single transmit collisions:\t\t\t[ %d ]\n",
45955992Swpaul	    stats->an_tx_single_cols);
46055992Swpaul	printf("Multiple transmit collisions:\t\t\t[ %d ]\n",
46155992Swpaul	    stats->an_tx_multi_cols);
46255992Swpaul	printf("Transmits without deferrals:\t\t\t[ %d ]\n",
46355992Swpaul	    stats->an_tx_defers_no);
46455992Swpaul	printf("Transmits defered due to protocol:\t\t[ %d ]\n",
46555992Swpaul	    stats->an_tx_defers_prot);
46655992Swpaul	printf("Transmits defered due to energy detect:\t\t[ %d ]\n",
46755992Swpaul	    stats->an_tx_defers_energy);
46855992Swpaul	printf("RX duplicate frames/frags:\t\t\t[ %d ]\n",
46955992Swpaul	    stats->an_rx_dups);
47055992Swpaul	printf("RX partial frames:\t\t\t\t[ %d ]\n",
47155992Swpaul	    stats->an_rx_partial);
47255992Swpaul	printf("TX max lifetime exceeded:\t\t\t[ %d ]\n",
47355992Swpaul	    stats->an_tx_too_old);
47455992Swpaul	printf("RX max lifetime exceeded:\t\t\t[ %d ]\n",
47555992Swpaul	    stats->an_tx_too_old);
47655992Swpaul	printf("Sync lost due to too many missed beacons:\t[ %d ]\n",
47755992Swpaul	    stats->an_lostsync_missed_beacons);
47855992Swpaul	printf("Sync lost due to ARL exceeded:\t\t\t[ %d ]\n",
47955992Swpaul	    stats->an_lostsync_arl_exceeded);
48055992Swpaul	printf("Sync lost due to deauthentication:\t\t[ %d ]\n",
48155992Swpaul	    stats->an_lostsync_deauthed);
48255992Swpaul	printf("Sync lost due to disassociation:\t\t[ %d ]\n",
48355992Swpaul	    stats->an_lostsync_disassociated);
48455992Swpaul	printf("Sync lost due to excess change in TSF timing:\t[ %d ]\n",
48555992Swpaul	    stats->an_lostsync_tsf_timing);
48655992Swpaul	printf("Host transmitted multicasts:\t\t\t[ %d ]\n",
48755992Swpaul	    stats->an_tx_host_mcasts);
48855992Swpaul	printf("Host transmitted broadcasts:\t\t\t[ %d ]\n",
48955992Swpaul	    stats->an_tx_host_bcasts);
49055992Swpaul	printf("Host transmitted unicasts:\t\t\t[ %d ]\n",
49155992Swpaul	    stats->an_tx_host_ucasts);
49255992Swpaul	printf("Host transmission failures:\t\t\t[ %d ]\n",
49355992Swpaul	    stats->an_tx_host_failed);
49455992Swpaul	printf("Host received multicasts:\t\t\t[ %d ]\n",
49555992Swpaul	    stats->an_rx_host_mcasts);
49655992Swpaul	printf("Host received broadcasts:\t\t\t[ %d ]\n",
49755992Swpaul	    stats->an_rx_host_bcasts);
49855992Swpaul	printf("Host received unicasts:\t\t\t\t[ %d ]\n",
49955992Swpaul	    stats->an_rx_host_ucasts);
50055992Swpaul	printf("Host receive discards:\t\t\t\t[ %d ]\n",
50155992Swpaul	    stats->an_rx_host_discarded);
50255992Swpaul	printf("HMAC transmitted multicasts:\t\t\t[ %d ]\n",
50355992Swpaul	    stats->an_tx_hmac_mcasts);
50455992Swpaul	printf("HMAC transmitted broadcasts:\t\t\t[ %d ]\n",
50555992Swpaul	    stats->an_tx_hmac_bcasts);
50655992Swpaul	printf("HMAC transmitted unicasts:\t\t\t[ %d ]\n",
50755992Swpaul	    stats->an_tx_hmac_ucasts);
50855992Swpaul	printf("HMAC transmissions failed:\t\t\t[ %d ]\n",
50955992Swpaul	    stats->an_tx_hmac_failed);
51055992Swpaul	printf("HMAC received multicasts:\t\t\t[ %d ]\n",
51155992Swpaul	    stats->an_rx_hmac_mcasts);
51255992Swpaul	printf("HMAC received broadcasts:\t\t\t[ %d ]\n",
51355992Swpaul	    stats->an_rx_hmac_bcasts);
51455992Swpaul	printf("HMAC received unicasts:\t\t\t\t[ %d ]\n",
51555992Swpaul	    stats->an_rx_hmac_ucasts);
51655992Swpaul	printf("HMAC receive discards:\t\t\t\t[ %d ]\n",
51755992Swpaul	    stats->an_rx_hmac_discarded);
51855992Swpaul	printf("HMAC transmits accepted:\t\t\t[ %d ]\n",
51955992Swpaul	    stats->an_tx_hmac_accepted);
52055992Swpaul	printf("SSID mismatches:\t\t\t\t[ %d ]\n",
52155992Swpaul	    stats->an_ssid_mismatches);
52255992Swpaul	printf("Access point mismatches:\t\t\t[ %d ]\n",
52355992Swpaul	    stats->an_ap_mismatches);
52455992Swpaul	printf("Speed mismatches:\t\t\t\t[ %d ]\n",
52555992Swpaul	    stats->an_rates_mismatches);
52655992Swpaul	printf("Authentication rejects:\t\t\t\t[ %d ]\n",
52755992Swpaul	    stats->an_auth_rejects);
52855992Swpaul	printf("Authentication timeouts:\t\t\t[ %d ]\n",
52955992Swpaul	    stats->an_auth_timeouts);
53055992Swpaul	printf("Association rejects:\t\t\t\t[ %d ]\n",
53155992Swpaul	    stats->an_assoc_rejects);
53255992Swpaul	printf("Association timeouts:\t\t\t\t[ %d ]\n",
53355992Swpaul	    stats->an_assoc_timeouts);
53455992Swpaul	printf("Management frames received:\t\t\t[ %d ]\n",
53555992Swpaul	    stats->an_rx_mgmt_pkts);
53655992Swpaul	printf("Management frames transmitted:\t\t\t[ %d ]\n",
53755992Swpaul	    stats->an_tx_mgmt_pkts);
53855992Swpaul	printf("Refresh frames received:\t\t\t[ %d ]\n",
53955992Swpaul	    stats->an_rx_refresh_pkts),
54055992Swpaul	printf("Refresh frames transmitted:\t\t\t[ %d ]\n",
54155992Swpaul	    stats->an_tx_refresh_pkts),
54255992Swpaul	printf("Poll frames received:\t\t\t\t[ %d ]\n",
54355992Swpaul	    stats->an_rx_poll_pkts);
54455992Swpaul	printf("Poll frames transmitted:\t\t\t[ %d ]\n",
54555992Swpaul	    stats->an_tx_poll_pkts);
54655992Swpaul	printf("Host requested sync losses:\t\t\t[ %d ]\n",
54755992Swpaul	    stats->an_lostsync_hostreq);
54855992Swpaul	printf("Host transmitted bytes:\t\t\t\t[ %d ]\n",
54955992Swpaul	    stats->an_host_tx_bytes);
55055992Swpaul	printf("Host received bytes:\t\t\t\t[ %d ]\n",
55155992Swpaul	    stats->an_host_rx_bytes);
55255992Swpaul	printf("Uptime in microseconds:\t\t\t\t[ %d ]\n",
55355992Swpaul	    stats->an_uptime_usecs);
55455992Swpaul	printf("Uptime in seconds:\t\t\t\t[ %d ]\n",
55555992Swpaul	    stats->an_uptime_secs);
55655992Swpaul	printf("Sync lost due to better AP:\t\t\t[ %d ]\n",
55755992Swpaul	    stats->an_lostsync_better_ap);
55855992Swpaul
55955992Swpaul	return;
56055992Swpaul}
56155992Swpaul
56255992Swpaulstatic void an_dumpap(iface)
56355992Swpaul	char			*iface;
56455992Swpaul{
56555992Swpaul	struct an_ltv_aplist	*ap;
56655992Swpaul	struct an_req		areq;
56755992Swpaul
56855992Swpaul	areq.an_len = sizeof(areq);
56955992Swpaul	areq.an_type = AN_RID_APLIST;
57055992Swpaul
57155992Swpaul	an_getval(iface, &areq);
57255992Swpaul
57355992Swpaul	ap = (struct an_ltv_aplist *)&areq;
57455992Swpaul	printf("Access point 1:\t\t\t");
57555992Swpaul	an_printhex((char *)&ap->an_ap1, ETHER_ADDR_LEN);
57655992Swpaul	printf("\nAccess point 2:\t\t\t");
57755992Swpaul	an_printhex((char *)&ap->an_ap2, ETHER_ADDR_LEN);
57855992Swpaul	printf("\nAccess point 3:\t\t\t");
57955992Swpaul	an_printhex((char *)&ap->an_ap3, ETHER_ADDR_LEN);
58055992Swpaul	printf("\nAccess point 4:\t\t\t");
58155992Swpaul	an_printhex((char *)&ap->an_ap4, ETHER_ADDR_LEN);
58255992Swpaul	printf("\n");
58355992Swpaul
58455992Swpaul	return;
58555992Swpaul}
58655992Swpaul
58755992Swpaulstatic void an_dumpssid(iface)
58855992Swpaul	char			*iface;
58955992Swpaul{
59055992Swpaul	struct an_ltv_ssidlist	*ssid;
59155992Swpaul	struct an_req		areq;
59255992Swpaul
59355992Swpaul	areq.an_len = sizeof(areq);
59455992Swpaul	areq.an_type = AN_RID_SSIDLIST;
59555992Swpaul
59655992Swpaul	an_getval(iface, &areq);
59755992Swpaul
59855992Swpaul	ssid = (struct an_ltv_ssidlist *)&areq;
59955992Swpaul	printf("SSID 1:\t\t\t[ %.*s ]\n", ssid->an_ssid1_len, ssid->an_ssid1);
60055992Swpaul	printf("SSID 2:\t\t\t[ %.*s ]\n", ssid->an_ssid2_len, ssid->an_ssid2);
60155992Swpaul	printf("SSID 3:\t\t\t[ %.*s ]\n", ssid->an_ssid3_len, ssid->an_ssid3);
60255992Swpaul
60355992Swpaul	return;
60455992Swpaul}
60555992Swpaul
60655992Swpaulstatic void an_dumpconfig(iface)
60755992Swpaul	char			*iface;
60855992Swpaul{
60955992Swpaul	struct an_ltv_genconfig	*cfg;
61055992Swpaul	struct an_req		areq;
61155992Swpaul	unsigned char		div;
61255992Swpaul
61355992Swpaul	areq.an_len = sizeof(areq);
61455992Swpaul	areq.an_type = AN_RID_ACTUALCFG;
61555992Swpaul
61655992Swpaul	an_getval(iface, &areq);
61755992Swpaul
61855992Swpaul	cfg = (struct an_ltv_genconfig *)&areq;
61955992Swpaul
62055992Swpaul	printf("Operating mode:\t\t\t\t[ ");
62155992Swpaul	if ((cfg->an_opmode & 0x7) == AN_OPMODE_IBSS_ADHOC)
62255992Swpaul		printf("ad-hoc");
62355992Swpaul	if ((cfg->an_opmode & 0x7) == AN_OPMODE_INFRASTRUCTURE_STATION)
62455992Swpaul		printf("infrastructure");
62555992Swpaul	if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP)
62655992Swpaul		printf("access point");
62755992Swpaul	if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP_REPEATER)
62855992Swpaul		printf("access point repeater");
62955992Swpaul	printf(" ]");
63055992Swpaul	printf("\nReceive mode:\t\t\t\t[ ");
63155992Swpaul	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_MC_ADDR)
63255992Swpaul		printf("broadcast/multicast/unicast");
63355992Swpaul	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_ADDR)
63455992Swpaul		printf("broadcast/unicast");
63555992Swpaul	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_ADDR)
63655992Swpaul		printf("unicast");
63755992Swpaul	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_CURBSS)
63855992Swpaul		printf("802.11 monitor, current BSSID");
63955992Swpaul	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_ANYBSS)
64055992Swpaul		printf("802.11 monitor, any BSSID");
64155992Swpaul	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_LAN_MONITOR_CURBSS)
64255992Swpaul		printf("LAN monitor, current BSSID");
64355992Swpaul	printf(" ]");
64455992Swpaul	printf("\nFragment threshold:\t\t\t");
64555992Swpaul	an_printwords(&cfg->an_fragthresh, 1);
64655992Swpaul	printf("\nRTS threshold:\t\t\t\t");
64755992Swpaul	an_printwords(&cfg->an_rtsthresh, 1);
64855992Swpaul	printf("\nMAC address:\t\t\t\t");
64955992Swpaul	an_printhex((char *)&cfg->an_macaddr, ETHER_ADDR_LEN);
65055992Swpaul	printf("\nSupported rates:\t\t\t");
65155992Swpaul	an_printspeeds(cfg->an_rates, 8);
65255992Swpaul	printf("\nShort retry limit:\t\t\t");
65355992Swpaul	an_printwords(&cfg->an_shortretry_limit, 1);
65455992Swpaul	printf("\nLong retry limit:\t\t\t");
65555992Swpaul	an_printwords(&cfg->an_longretry_limit, 1);
65655992Swpaul	printf("\nTX MSDU lifetime:\t\t\t");
65755992Swpaul	an_printwords(&cfg->an_tx_msdu_lifetime, 1);
65855992Swpaul	printf("\nRX MSDU lifetime:\t\t\t");
65955992Swpaul	an_printwords(&cfg->an_rx_msdu_lifetime, 1);
66055992Swpaul	printf("\nStationary:\t\t\t\t");
66155992Swpaul	an_printbool(cfg->an_stationary);
66255992Swpaul	printf("\nOrdering:\t\t\t\t");
66355992Swpaul	an_printbool(cfg->an_ordering);
66455992Swpaul	printf("\nDevice type:\t\t\t\t[ ");
66555992Swpaul	if (cfg->an_devtype == AN_DEVTYPE_PC4500)
66655992Swpaul		printf("PC4500");
66755992Swpaul	else if (cfg->an_devtype == AN_DEVTYPE_PC4800)
66855992Swpaul		printf("PC4800");
66955992Swpaul	else
67055992Swpaul		printf("unknown (%x)", cfg->an_devtype);
67155992Swpaul	printf(" ]");
67255992Swpaul	printf("\nScanning mode:\t\t\t\t[ ");
67355992Swpaul	if (cfg->an_scanmode == AN_SCANMODE_ACTIVE)
67455992Swpaul		printf("active");
67555992Swpaul	if (cfg->an_scanmode == AN_SCANMODE_PASSIVE)
67655992Swpaul		printf("passive");
67755992Swpaul	if (cfg->an_scanmode == AN_SCANMODE_AIRONET_ACTIVE)
67855992Swpaul		printf("Aironet active");
67955992Swpaul	printf(" ]");
68055992Swpaul	printf("\nProbe delay:\t\t\t\t");
68155992Swpaul	an_printwords(&cfg->an_probedelay, 1);
68255992Swpaul	printf("\nProbe energy timeout:\t\t\t");
68355992Swpaul	an_printwords(&cfg->an_probe_energy_timeout, 1);
68455992Swpaul	printf("\nProbe response timeout:\t\t\t");
68555992Swpaul	an_printwords(&cfg->an_probe_response_timeout, 1);
68655992Swpaul	printf("\nBeacon listen timeout:\t\t\t");
68755992Swpaul	an_printwords(&cfg->an_beacon_listen_timeout, 1);
68855992Swpaul	printf("\nIBSS join network timeout:\t\t");
68955992Swpaul	an_printwords(&cfg->an_ibss_join_net_timeout, 1);
69055992Swpaul	printf("\nAuthentication timeout:\t\t\t");
69155992Swpaul	an_printwords(&cfg->an_auth_timeout, 1);
69268692Swpaul	printf("\nWEP enabled:\t\t\t\t[ ");
69369772Sarchie	if (cfg->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE)
69469772Sarchie	{
69569772Sarchie		if (cfg->an_authtype & AN_AUTHTYPE_ALLOW_UNENCRYPTED)
69669772Sarchie			 printf("mixed cell");
69769772Sarchie		else
69869772Sarchie			 printf("full");
69969772Sarchie	}
70068692Swpaul	else
70168692Swpaul		printf("no");
70268692Swpaul	printf(" ]");
70355992Swpaul	printf("\nAuthentication type:\t\t\t[ ");
70468692Swpaul	if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_NONE)
70568692Swpaul		printf("none");
70668692Swpaul	if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_OPEN)
70755992Swpaul		printf("open");
70868692Swpaul	if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_SHAREDKEY)
70955992Swpaul		printf("shared key");
71055992Swpaul	printf(" ]");
71155992Swpaul	printf("\nAssociation timeout:\t\t\t");
71255992Swpaul	an_printwords(&cfg->an_assoc_timeout, 1);
71355992Swpaul	printf("\nSpecified AP association timeout:\t");
71455992Swpaul	an_printwords(&cfg->an_specified_ap_timeout, 1);
71555992Swpaul	printf("\nOffline scan interval:\t\t\t");
71655992Swpaul	an_printwords(&cfg->an_offline_scan_interval, 1);
71755992Swpaul	printf("\nOffline scan duration:\t\t\t");
71855992Swpaul	an_printwords(&cfg->an_offline_scan_duration, 1);
71955992Swpaul	printf("\nLink loss delay:\t\t\t");
72055992Swpaul	an_printwords(&cfg->an_link_loss_delay, 1);
72155992Swpaul	printf("\nMax beacon loss time:\t\t\t");
72255992Swpaul	an_printwords(&cfg->an_max_beacon_lost_time, 1);
72355992Swpaul	printf("\nRefresh interval:\t\t\t");
72455992Swpaul	an_printwords(&cfg->an_refresh_interval, 1);
72555992Swpaul	printf("\nPower save mode:\t\t\t[ ");
72655992Swpaul	if (cfg->an_psave_mode == AN_PSAVE_NONE)
72755992Swpaul		printf("none");
72855992Swpaul	if (cfg->an_psave_mode == AN_PSAVE_CAM)
72955992Swpaul		printf("constantly awake mode");
73055992Swpaul	if (cfg->an_psave_mode == AN_PSAVE_PSP)
73155992Swpaul		printf("PSP");
73255992Swpaul	if (cfg->an_psave_mode == AN_PSAVE_PSP_CAM)
73355992Swpaul		printf("PSP-CAM (fast PSP)");
73455992Swpaul	printf(" ]");
73555992Swpaul	printf("\nSleep through DTIMs:\t\t\t");
73655992Swpaul	an_printbool(cfg->an_sleep_for_dtims);
73755992Swpaul	printf("\nPower save listen interval:\t\t");
73855992Swpaul	an_printwords(&cfg->an_listen_interval, 1);
73955992Swpaul	printf("\nPower save fast listen interval:\t");
74055992Swpaul	an_printwords(&cfg->an_fast_listen_interval, 1);
74155992Swpaul	printf("\nPower save listen decay:\t\t");
74255992Swpaul	an_printwords(&cfg->an_listen_decay, 1);
74355992Swpaul	printf("\nPower save fast listen decay:\t\t");
74455992Swpaul	an_printwords(&cfg->an_fast_listen_decay, 1);
74555992Swpaul	printf("\nAP/ad-hoc Beacon period:\t\t");
74655992Swpaul	an_printwords(&cfg->an_beacon_period, 1);
74755992Swpaul	printf("\nAP/ad-hoc ATIM duration:\t\t");
74855992Swpaul	an_printwords(&cfg->an_atim_duration, 1);
74955992Swpaul	printf("\nAP/ad-hoc current channel:\t\t");
75055992Swpaul	an_printwords(&cfg->an_ds_channel, 1);
75155992Swpaul	printf("\nAP/ad-hoc DTIM period:\t\t\t");
75255992Swpaul	an_printwords(&cfg->an_dtim_period, 1);
75355992Swpaul	printf("\nRadio type:\t\t\t\t[ ");
75455992Swpaul	if (cfg->an_radiotype & AN_RADIOTYPE_80211_FH)
75555992Swpaul		printf("802.11 FH");
75655992Swpaul	else if (cfg->an_radiotype & AN_RADIOTYPE_80211_DS)
75755992Swpaul		printf("802.11 DS");
75855992Swpaul	else if (cfg->an_radiotype & AN_RADIOTYPE_LM2000_DS)
75955992Swpaul		printf("LM2000 DS");
76055992Swpaul	else
76155992Swpaul		printf("unknown (%x)", cfg->an_radiotype);
76255992Swpaul	printf(" ]");
76355992Swpaul	printf("\nRX Diversity:\t\t\t\t[ ");
76455992Swpaul	div = cfg->an_diversity & 0xFF;
76555992Swpaul	if (div == AN_DIVERSITY_ANTENNA_1_ONLY)
76655992Swpaul		printf("antenna 1 only");
76755992Swpaul	else if (div == AN_DIVERSITY_ANTENNA_2_ONLY)
76855992Swpaul		printf("antenna 2 only");
76955992Swpaul	else if (div == AN_DIVERSITY_ANTENNA_1_AND_2)
77055992Swpaul		printf("antenna 1 and 2");
77155992Swpaul	printf(" ]");
77255992Swpaul	printf("\nTX Diversity:\t\t\t\t[ ");
77355992Swpaul	div = (cfg->an_diversity >> 8) & 0xFF;
77455992Swpaul	if (div == AN_DIVERSITY_ANTENNA_1_ONLY)
77555992Swpaul		printf("antenna 1 only");
77655992Swpaul	else if (div == AN_DIVERSITY_ANTENNA_2_ONLY)
77755992Swpaul		printf("antenna 2 only");
77855992Swpaul	else if (div == AN_DIVERSITY_ANTENNA_1_AND_2)
77955992Swpaul		printf("antenna 1 and 2");
78055992Swpaul	printf(" ]");
78155992Swpaul	printf("\nTransmit power level:\t\t\t");
78255992Swpaul	an_printwords(&cfg->an_tx_power, 1);
78355992Swpaul	printf("\nRSS threshold:\t\t\t\t");
78455992Swpaul	an_printwords(&cfg->an_rss_thresh, 1);
78555992Swpaul	printf("\nNode name:\t\t\t\t");
78655992Swpaul	an_printstr((char *)&cfg->an_nodename, 16);
78755992Swpaul	printf("\nARL threshold:\t\t\t\t");
78855992Swpaul	an_printwords(&cfg->an_arl_thresh, 1);
78955992Swpaul	printf("\nARL decay:\t\t\t\t");
79055992Swpaul	an_printwords(&cfg->an_arl_decay, 1);
79155992Swpaul	printf("\nARL delay:\t\t\t\t");
79255992Swpaul	an_printwords(&cfg->an_arl_delay, 1);
79355992Swpaul
79455992Swpaul	printf("\n");
79569772Sarchie	printf("\n");
79669772Sarchie	an_readkeyinfo(iface);
79755992Swpaul
79855992Swpaul	return;
79955992Swpaul}
80055992Swpaul
80155992Swpaul
80255992Swpaulstatic void usage(p)
80355992Swpaul	char			*p;
80455992Swpaul{
80555992Swpaul	fprintf(stderr, "usage:  %s -i iface -A (show specified APs)\n", p);
80655992Swpaul	fprintf(stderr, "\t%s -i iface -N (show specified SSIDss)\n", p);
80755992Swpaul	fprintf(stderr, "\t%s -i iface -S (show NIC status)\n", p);
80855992Swpaul	fprintf(stderr, "\t%s -i iface -I (show NIC capabilities)\n", p);
80955992Swpaul	fprintf(stderr, "\t%s -i iface -T (show stats counters)\n", p);
81055992Swpaul	fprintf(stderr, "\t%s -i iface -C (show current config)\n", p);
81155992Swpaul	fprintf(stderr, "\t%s -i iface -t 0|1|2|3|4 (set TX speed)\n", p);
81255992Swpaul	fprintf(stderr, "\t%s -i iface -s 0|1|2|3 (set power same mode)\n", p);
81355992Swpaul	fprintf(stderr, "\t%s -i iface [-v 1|2|3|4] -a AP (specify AP)\n", p);
81455992Swpaul	fprintf(stderr, "\t%s -i iface -b val (set beacon period)\n", p);
81555992Swpaul	fprintf(stderr, "\t%s -i iface [-v 0|1] -d val (set diversity)\n", p);
81655992Swpaul	fprintf(stderr, "\t%s -i iface -j val (set netjoin timeout)\n", p);
81769772Sarchie	fprintf(stderr, "\t%s -i iface -e 0|1|2|3 (enable transmit key)\n", p);
81868692Swpaul	fprintf(stderr, "\t%s -i iface [-v 0|1|2|3|4|5|6|7] -k key (set key)\n", p);
81969772Sarchie	fprintf(stderr, "\t%s -i iface -K 0|1|2 (no auth/open/shared secret)\n", p);
82069772Sarchie	fprintf(stderr, "\t%s -i iface -W 0|1|2 (no WEP/full WEP/mixed cell)\n", p);
82155992Swpaul	fprintf(stderr, "\t%s -i iface -l val (set station name)\n", p);
82255992Swpaul	fprintf(stderr, "\t%s -i iface -m val (set MAC address)\n", p);
82355992Swpaul	fprintf(stderr, "\t%s -i iface [-v 1|2|3] -n SSID "
82455992Swpaul	    "(specify SSID)\n", p);
82555992Swpaul	fprintf(stderr, "\t%s -i iface -o 0|1 (set operating mode)\n", p);
82655992Swpaul	fprintf(stderr, "\t%s -i iface -c val (set ad-hoc channel)\n", p);
82755992Swpaul	fprintf(stderr, "\t%s -i iface -f val (set frag threshold)\n", p);
82855992Swpaul	fprintf(stderr, "\t%s -i iface -r val (set RTS threshold)\n", p);
82955992Swpaul#ifdef ANCACHE
83055992Swpaul	fprintf(stderr, "\t%s -i iface -Q print signal quality cache\n", p);
83155992Swpaul	fprintf(stderr, "\t%s -i iface -Z zero out signal cache\n", p);
83255992Swpaul#endif
83355992Swpaul
83455992Swpaul	fprintf(stderr, "\t%s -h (display this message)\n", p);
83555992Swpaul
83655992Swpaul
83755992Swpaul	exit(1);
83855992Swpaul}
83955992Swpaul
84055992Swpaulstatic void an_setconfig(iface, act, arg)
84155992Swpaul	char			*iface;
84255992Swpaul	int			act;
84355992Swpaul	void			*arg;
84455992Swpaul{
84555992Swpaul	struct an_ltv_genconfig	*cfg;
84655992Swpaul	struct an_ltv_caps	*caps;
84755992Swpaul	struct an_req		areq;
84855992Swpaul	struct an_req		areq_caps;
84955992Swpaul	u_int16_t		diversity = 0;
85055992Swpaul	struct ether_addr	*addr;
85155992Swpaul	int			i;
85255992Swpaul
85355992Swpaul	areq.an_len = sizeof(areq);
85455992Swpaul	areq.an_type = AN_RID_GENCONFIG;
85555992Swpaul	an_getval(iface, &areq);
85655992Swpaul	cfg = (struct an_ltv_genconfig *)&areq;
85755992Swpaul
85855992Swpaul	areq_caps.an_len = sizeof(areq);
85955992Swpaul	areq_caps.an_type = AN_RID_CAPABILITIES;
86055992Swpaul	an_getval(iface, &areq_caps);
86155992Swpaul	caps = (struct an_ltv_caps *)&areq_caps;
86255992Swpaul
86355992Swpaul	switch(act) {
86455992Swpaul	case ACT_SET_OPMODE:
86555992Swpaul		cfg->an_opmode = atoi(arg);
86655992Swpaul		break;
86755992Swpaul	case ACT_SET_FREQ:
86855992Swpaul		cfg->an_ds_channel = atoi(arg);
86955992Swpaul		break;
87055992Swpaul	case ACT_SET_PWRSAVE:
87155992Swpaul		cfg->an_psave_mode = atoi(arg);
87255992Swpaul		break;
87355992Swpaul	case ACT_SET_SCANMODE:
87455992Swpaul		cfg->an_scanmode = atoi(arg);
87555992Swpaul		break;
87655992Swpaul	case ACT_SET_DIVERSITY_RX:
87755992Swpaul	case ACT_SET_DIVERSITY_TX:
87855992Swpaul		switch(atoi(arg)) {
87955992Swpaul		case 0:
88055992Swpaul			diversity = AN_DIVERSITY_FACTORY_DEFAULT;
88155992Swpaul			break;
88255992Swpaul		case 1:
88355992Swpaul			diversity = AN_DIVERSITY_ANTENNA_1_ONLY;
88455992Swpaul			break;
88555992Swpaul		case 2:
88655992Swpaul			diversity = AN_DIVERSITY_ANTENNA_2_ONLY;
88755992Swpaul			break;
88855992Swpaul		case 3:
88955992Swpaul			diversity = AN_DIVERSITY_ANTENNA_1_AND_2;
89055992Swpaul			break;
89155992Swpaul		default:
89255992Swpaul			errx(1, "bad diversity setting: %d", diversity);
89355992Swpaul			break;
89455992Swpaul		}
89555992Swpaul		if (atoi(arg) == ACT_SET_DIVERSITY_RX) {
89655992Swpaul			cfg->an_diversity &= 0x00FF;
89755992Swpaul			cfg->an_diversity |= (diversity << 8);
89855992Swpaul		} else {
89955992Swpaul			cfg->an_diversity &= 0xFF00;
90055992Swpaul			cfg->an_diversity |= diversity;
90155992Swpaul		}
90255992Swpaul		break;
90355992Swpaul	case ACT_SET_TXPWR:
90455992Swpaul		for (i = 0; i < 8; i++) {
90555992Swpaul			if (caps->an_tx_powerlevels[i] == atoi(arg))
90655992Swpaul				break;
90755992Swpaul		}
90855992Swpaul		if (i == 8)
90955992Swpaul			errx(1, "unsupported power level: %dmW", atoi(arg));
91055992Swpaul
91155992Swpaul		cfg->an_tx_power = atoi(arg);
91255992Swpaul		break;
91355992Swpaul	case ACT_SET_RTS_THRESH:
91455992Swpaul		cfg->an_rtsthresh = atoi(arg);
91555992Swpaul		break;
91655992Swpaul	case ACT_SET_RTS_RETRYLIM:
91755992Swpaul		cfg->an_shortretry_limit =
91855992Swpaul		   cfg->an_longretry_limit = atoi(arg);
91955992Swpaul		break;
92055992Swpaul	case ACT_SET_BEACON_PERIOD:
92155992Swpaul		cfg->an_beacon_period = atoi(arg);
92255992Swpaul		break;
92355992Swpaul	case ACT_SET_WAKE_DURATION:
92455992Swpaul		cfg->an_atim_duration = atoi(arg);
92555992Swpaul		break;
92655992Swpaul	case ACT_SET_FRAG_THRESH:
92755992Swpaul		cfg->an_fragthresh = atoi(arg);
92855992Swpaul		break;
92955992Swpaul	case ACT_SET_NETJOIN:
93055992Swpaul		cfg->an_ibss_join_net_timeout = atoi(arg);
93155992Swpaul		break;
93255992Swpaul	case ACT_SET_MYNAME:
93355992Swpaul		bzero(cfg->an_nodename, 16);
93455992Swpaul		strncpy((char *)&cfg->an_nodename, optarg, 16);
93555992Swpaul		break;
93655992Swpaul	case ACT_SET_MAC:
93755992Swpaul		addr = ether_aton((char *)arg);
93855992Swpaul
93955992Swpaul		if (addr == NULL)
94055992Swpaul			errx(1, "badly formatted address");
94155992Swpaul		bzero(cfg->an_macaddr, ETHER_ADDR_LEN);
94255992Swpaul		bcopy((char *)addr, (char *)&cfg->an_macaddr, ETHER_ADDR_LEN);
94355992Swpaul		break;
94468692Swpaul	case ACT_ENABLE_WEP:
94569772Sarchie		switch (atoi (arg)) {
94669772Sarchie		case 0:
94769772Sarchie			/* no WEP */
94869772Sarchie			cfg->an_authtype &= ~(AN_AUTHTYPE_PRIVACY_IN_USE
94969772Sarchie					| AN_AUTHTYPE_ALLOW_UNENCRYPTED);
95069772Sarchie			break;
95169772Sarchie		case 1:
95269772Sarchie			/* full WEP */
95369772Sarchie			cfg->an_authtype |= AN_AUTHTYPE_PRIVACY_IN_USE;
95469772Sarchie			cfg->an_authtype &= ~AN_AUTHTYPE_ALLOW_UNENCRYPTED;
95569772Sarchie			break;
95669772Sarchie		case 2:
95769772Sarchie			/* mixed cell */
95869772Sarchie			cfg->an_authtype = AN_AUTHTYPE_PRIVACY_IN_USE
95969772Sarchie					| AN_AUTHTYPE_ALLOW_UNENCRYPTED;
96069772Sarchie			break;
96169772Sarchie		}
96268692Swpaul		break;
96368692Swpaul	case ACT_SET_KEY_TYPE:
96468692Swpaul		cfg->an_authtype = (cfg->an_authtype & ~AN_AUTHTYPE_MASK)
96568692Swpaul		        | atoi(arg);
96668692Swpaul		break;
96755992Swpaul	default:
96855992Swpaul		errx(1, "unknown action");
96955992Swpaul		break;
97055992Swpaul	}
97155992Swpaul
97255992Swpaul	an_setval(iface, &areq);
97355992Swpaul	exit(0);
97455992Swpaul}
97555992Swpaul
97655992Swpaulstatic void an_setspeed(iface, act, arg)
97755992Swpaul	char			*iface;
97855992Swpaul	int			act;
97955992Swpaul	void			*arg;
98055992Swpaul{
98155992Swpaul	struct an_req		areq;
98255992Swpaul	struct an_ltv_caps	*caps;
98355992Swpaul	u_int16_t		speed;
98455992Swpaul
98555992Swpaul	areq.an_len = sizeof(areq);
98655992Swpaul	areq.an_type = AN_RID_CAPABILITIES;
98755992Swpaul
98855992Swpaul	an_getval(iface, &areq);
98955992Swpaul	caps = (struct an_ltv_caps *)&areq;
99055992Swpaul
99155992Swpaul	switch(atoi(arg)) {
99255992Swpaul	case 0:
99355992Swpaul		speed = 0;
99455992Swpaul		break;
99555992Swpaul	case 1:
99655992Swpaul		speed = AN_RATE_1MBPS;
99755992Swpaul		break;
99855992Swpaul	case 2:
99955992Swpaul		speed = AN_RATE_2MBPS;
100055992Swpaul		break;
100155992Swpaul	case 3:
100255992Swpaul		if (caps->an_rates[2] != AN_RATE_5_5MBPS)
100355992Swpaul			errx(1, "5.5Mbps not supported on this card");
100455992Swpaul		speed = AN_RATE_5_5MBPS;
100555992Swpaul		break;
100655992Swpaul	case 4:
100755992Swpaul		if (caps->an_rates[3] != AN_RATE_11MBPS)
100855992Swpaul			errx(1, "11Mbps not supported on this card");
100955992Swpaul		speed = AN_RATE_11MBPS;
101055992Swpaul		break;
101155992Swpaul	default:
101255992Swpaul		errx(1, "unsupported speed");
101355992Swpaul		break;
101455992Swpaul	}
101555992Swpaul
101655992Swpaul	areq.an_len = 6;
101755992Swpaul	areq.an_type = AN_RID_TX_SPEED;
101855992Swpaul	areq.an_val[0] = speed;
101955992Swpaul
102055992Swpaul	an_setval(iface, &areq);
102155992Swpaul	exit(0);
102255992Swpaul}
102355992Swpaul
102455992Swpaulstatic void an_setap(iface, act, arg)
102555992Swpaul	char			*iface;
102655992Swpaul	int			act;
102755992Swpaul	void			*arg;
102855992Swpaul{
102955992Swpaul	struct an_ltv_aplist	*ap;
103055992Swpaul	struct an_req		areq;
103155992Swpaul	struct ether_addr	*addr;
103255992Swpaul
103355992Swpaul	areq.an_len = sizeof(areq);
103455992Swpaul	areq.an_type = AN_RID_APLIST;
103555992Swpaul
103655992Swpaul	an_getval(iface, &areq);
103755992Swpaul	ap = (struct an_ltv_aplist *)&areq;
103855992Swpaul
103955992Swpaul	addr = ether_aton((char *)arg);
104055992Swpaul
104155992Swpaul	if (addr == NULL)
104255992Swpaul		errx(1, "badly formatted address");
104355992Swpaul
104455992Swpaul	switch(act) {
104555992Swpaul	case ACT_SET_AP1:
104655992Swpaul		bzero(ap->an_ap1, ETHER_ADDR_LEN);
104755992Swpaul		bcopy((char *)addr, (char *)&ap->an_ap1, ETHER_ADDR_LEN);
104855992Swpaul		break;
104955992Swpaul	case ACT_SET_AP2:
105055992Swpaul		bzero(ap->an_ap2, ETHER_ADDR_LEN);
105155992Swpaul		bcopy((char *)addr, (char *)&ap->an_ap2, ETHER_ADDR_LEN);
105255992Swpaul		break;
105355992Swpaul	case ACT_SET_AP3:
105455992Swpaul		bzero(ap->an_ap3, ETHER_ADDR_LEN);
105555992Swpaul		bcopy((char *)addr, (char *)&ap->an_ap3, ETHER_ADDR_LEN);
105655992Swpaul		break;
105755992Swpaul	case ACT_SET_AP4:
105855992Swpaul		bzero(ap->an_ap4, ETHER_ADDR_LEN);
105955992Swpaul		bcopy((char *)addr, (char *)&ap->an_ap4, ETHER_ADDR_LEN);
106055992Swpaul		break;
106155992Swpaul	default:
106255992Swpaul		errx(1, "unknown action");
106355992Swpaul		break;
106455992Swpaul	}
106555992Swpaul
106655992Swpaul	an_setval(iface, &areq);
106755992Swpaul	exit(0);
106855992Swpaul}
106955992Swpaul
107055992Swpaulstatic void an_setssid(iface, act, arg)
107155992Swpaul	char			*iface;
107255992Swpaul	int			act;
107355992Swpaul	void			*arg;
107455992Swpaul{
107555992Swpaul	struct an_ltv_ssidlist	*ssid;
107655992Swpaul	struct an_req		areq;
107755992Swpaul
107855992Swpaul	areq.an_len = sizeof(areq);
107955992Swpaul	areq.an_type = AN_RID_SSIDLIST;
108055992Swpaul
108155992Swpaul	an_getval(iface, &areq);
108255992Swpaul	ssid = (struct an_ltv_ssidlist *)&areq;
108355992Swpaul
108461815Sroberto	switch (act) {
108555992Swpaul	case ACT_SET_SSID1:
108655992Swpaul		bzero(ssid->an_ssid1, sizeof(ssid->an_ssid1));
108761815Sroberto		strlcpy(ssid->an_ssid1, (char *)arg, sizeof(ssid->an_ssid1));
108861815Sroberto		ssid->an_ssid1_len = strlen(ssid->an_ssid1);
108955992Swpaul		break;
109055992Swpaul	case ACT_SET_SSID2:
109155992Swpaul		bzero(ssid->an_ssid2, sizeof(ssid->an_ssid2));
109261815Sroberto		strlcpy(ssid->an_ssid2, (char *)arg, sizeof(ssid->an_ssid2));
109361815Sroberto		ssid->an_ssid2_len = strlen(ssid->an_ssid2);
109455992Swpaul		break;
109555992Swpaul	case ACT_SET_SSID3:
109655992Swpaul		bzero(ssid->an_ssid3, sizeof(ssid->an_ssid3));
109761815Sroberto		strlcpy(ssid->an_ssid3, (char *)arg, sizeof(ssid->an_ssid3));
109861815Sroberto		ssid->an_ssid3_len = strlen(ssid->an_ssid3);
109955992Swpaul		break;
110055992Swpaul	default:
110155992Swpaul		errx(1, "unknown action");
110255992Swpaul		break;
110355992Swpaul	}
110455992Swpaul
110555992Swpaul	an_setval(iface, &areq);
110655992Swpaul	exit(0);
110755992Swpaul}
110855992Swpaul
110955992Swpaul#ifdef ANCACHE
111055992Swpaulstatic void an_zerocache(iface)
111155992Swpaul	char			*iface;
111255992Swpaul{
111355992Swpaul	struct an_req		areq;
111455992Swpaul
111555992Swpaul	bzero((char *)&areq, sizeof(areq));
111655992Swpaul	areq.an_len = 0;
111755992Swpaul	areq.an_type = AN_RID_ZERO_CACHE;
111855992Swpaul
111955992Swpaul	an_getval(iface, &areq);
112055992Swpaul
112155992Swpaul	return;
112255992Swpaul}
112355992Swpaul
112455992Swpaulstatic void an_readcache(iface)
112555992Swpaul	char			*iface;
112655992Swpaul{
112755992Swpaul	struct an_req		areq;
112855992Swpaul	int 			*an_sigitems;
112955992Swpaul	struct an_sigcache 	*sc;
113055992Swpaul	char *			pt;
113155992Swpaul	int 			i;
113255992Swpaul
113355992Swpaul	if (iface == NULL)
113455992Swpaul		errx(1, "must specify interface name");
113555992Swpaul
113655992Swpaul	bzero((char *)&areq, sizeof(areq));
113755992Swpaul	areq.an_len = AN_MAX_DATALEN;
113855992Swpaul	areq.an_type = AN_RID_READ_CACHE;
113955992Swpaul
114055992Swpaul	an_getval(iface, &areq);
114155992Swpaul
114255992Swpaul	an_sigitems = (int *) &areq.an_val;
114355992Swpaul	pt = ((char *) &areq.an_val);
114455992Swpaul	pt += sizeof(int);
114555992Swpaul	sc = (struct an_sigcache *) pt;
114655992Swpaul
114755992Swpaul	for (i = 0; i < *an_sigitems; i++) {
114855992Swpaul		printf("[%d/%d]:", i+1, *an_sigitems);
114955992Swpaul		printf(" %02x:%02x:%02x:%02x:%02x:%02x,",
115055992Swpaul		  		    	sc->macsrc[0]&0xff,
115155992Swpaul		  		    	sc->macsrc[1]&0xff,
115255992Swpaul		   		    	sc->macsrc[2]&0xff,
115355992Swpaul		   			sc->macsrc[3]&0xff,
115455992Swpaul		   			sc->macsrc[4]&0xff,
115555992Swpaul		   			sc->macsrc[5]&0xff);
115655992Swpaul        	printf(" %d.%d.%d.%d,",((sc->ipsrc >> 0) & 0xff),
115755992Swpaul				        ((sc->ipsrc >> 8) & 0xff),
115855992Swpaul				        ((sc->ipsrc >> 16) & 0xff),
115955992Swpaul				        ((sc->ipsrc >> 24) & 0xff));
116055992Swpaul		printf(" sig: %d, noise: %d, qual: %d\n",
116155992Swpaul		   			sc->signal,
116255992Swpaul		   			sc->noise,
116355992Swpaul		   			sc->quality);
116455992Swpaul		sc++;
116555992Swpaul	}
116655992Swpaul
116755992Swpaul	return;
116855992Swpaul}
116955992Swpaul#endif
117055992Swpaul
117168692Swpaulstatic int an_hex2int(c)
117268692Swpaul	char			c;
117368692Swpaul{
117468692Swpaul	if (c >= '0' && c <= '9')
117568692Swpaul		return (c - '0');
117668692Swpaul	if (c >= 'A' && c <= 'F')
117768692Swpaul		return (c - 'A' + 10);
117868692Swpaul	if (c >= 'a' && c <= 'f')
117968692Swpaul		return (c - 'a' + 10);
118055992Swpaul
118168692Swpaul	return (0);
118268692Swpaul}
118368692Swpaul
118468692Swpaulstatic void an_str2key(s, k)
118568692Swpaul	char			*s;
118668692Swpaul	struct an_ltv_key	*k;
118768692Swpaul{
118868692Swpaul	int			n, i;
118968692Swpaul	char			*p;
119068692Swpaul
119168692Swpaul	/* Is this a hex string? */
119268692Swpaul	if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
119368692Swpaul		/* Yes, convert to int. */
119468692Swpaul		n = 0;
119568692Swpaul		p = (char *)&k->key[0];
119668692Swpaul		for (i = 2; i < strlen(s); i+= 2) {
119768692Swpaul			*p++ = (an_hex2int(s[i]) << 4) + an_hex2int(s[i + 1]);
119868692Swpaul			n++;
119968692Swpaul		}
120068692Swpaul		k->klen = n;
120168692Swpaul	} else {
120268692Swpaul		/* No, just copy it in. */
120368692Swpaul		bcopy(s, k->key, strlen(s));
120468692Swpaul		k->klen = strlen(s);
120568692Swpaul	}
120668692Swpaul
120768692Swpaul	return;
120868692Swpaul}
120968692Swpaul
121068692Swpaulstatic void an_setkeys(iface, key, keytype)
121168692Swpaul	char			*iface;
121268692Swpaul	char			*key;
121368692Swpaul	int			keytype;
121468692Swpaul{
121568692Swpaul	struct an_req		areq;
121668692Swpaul	struct an_ltv_key	*k;
121768692Swpaul
121868692Swpaul	bzero((char *)&areq, sizeof(areq));
121968692Swpaul	k = (struct an_ltv_key *)&areq;
122068692Swpaul
122168692Swpaul	if (strlen(key) > 28) {
122268692Swpaul		err(1, "encryption key must be no "
122368692Swpaul		    "more than 18 characters long");
122468692Swpaul	}
122568692Swpaul
122668692Swpaul	an_str2key(key, k);
122768692Swpaul
122868692Swpaul	k->kindex=keytype/2;
122968692Swpaul
123068692Swpaul	if (!(k->klen==0 || k->klen==5 || k->klen==13)) {
123168692Swpaul		err(1, "encryption key must be 0, 5 or 13 bytes long");
123268692Swpaul	}
123368692Swpaul
123468692Swpaul	/* default mac and only valid one (from manual) 1.0.0.0.0.0 */
123568692Swpaul	k->mac[0]=1;
123668692Swpaul	k->mac[1]=0;
123768692Swpaul	k->mac[2]=0;
123868692Swpaul	k->mac[3]=0;
123968692Swpaul	k->mac[4]=0;
124068692Swpaul	k->mac[5]=0;
124168692Swpaul
124268692Swpaul	switch(keytype & 1){
124368692Swpaul	case 0:
124468692Swpaul	  areq.an_len = sizeof(struct an_ltv_key);
124568692Swpaul	  areq.an_type = AN_RID_WEP_PERM;
124668692Swpaul	  an_setval(iface, &areq);
124768692Swpaul	  break;
124868692Swpaul	case 1:
124968692Swpaul	  areq.an_len = sizeof(struct an_ltv_key);
125068692Swpaul	  areq.an_type = AN_RID_WEP_TEMP;
125168692Swpaul	  an_setval(iface, &areq);
125268692Swpaul	  break;
125368692Swpaul	}
125468692Swpaul
125568692Swpaul	return;
125668692Swpaul}
125768692Swpaul
125869772Sarchiestatic void an_readkeyinfo(iface)
125969772Sarchie	char			*iface;
126069772Sarchie{
126169772Sarchie	struct an_req		areq;
126269772Sarchie	struct an_ltv_key	*k;
126369772Sarchie	int i;
126469772Sarchie
126569772Sarchie	bzero((char *)&areq, sizeof(areq));
126669772Sarchie	k = (struct an_ltv_key *)&areq;
126769772Sarchie
126869772Sarchie	printf("WEP Key status:\n");
126969772Sarchie	areq.an_type = AN_RID_WEP_TEMP;  	/* read first key */
127069772Sarchie	for(i=0; i<4; i++){
127169772Sarchie		areq.an_len = sizeof(struct an_ltv_key);
127269772Sarchie		an_getval(iface, &areq);
127369772Sarchie		switch (k->klen){
127469772Sarchie		case 0:
127569772Sarchie			printf("\tKey %d is unset\n",i);
127669772Sarchie			break;
127769772Sarchie		case 5:
127869772Sarchie			printf("\tKey %d is set  40 bits\n",i);
127969772Sarchie			break;
128069772Sarchie		case 13:
128169772Sarchie			printf("\tKey %d is set 128 bits\n",i);
128269772Sarchie			break;
128369772Sarchie		default:
128469772Sarchie			printf("\tWEP Key %d has an unknown size %d\n",
128569772Sarchie			    i, k->klen);
128669772Sarchie		}
128769772Sarchie
128869772Sarchie		areq.an_type = AN_RID_WEP_PERM;	/* read next key */
128969772Sarchie	}
129069772Sarchie	k->kindex = 0xffff;
129169772Sarchie	areq.an_len = sizeof(struct an_ltv_key);
129269772Sarchie      	an_getval(iface, &areq);
129369772Sarchie	printf("\tThe active transmit key is %d\n", k->mac[0]);
129469772Sarchie
129569772Sarchie	return;
129669772Sarchie}
129769772Sarchie
129869772Sarchiestatic void an_enable_tx_key(iface, arg)
129969772Sarchie	char			*iface;
130069772Sarchie	char			*arg;
130169772Sarchie{
130269772Sarchie	struct an_req		areq;
130369772Sarchie	struct an_ltv_key	*k;
130469772Sarchie
130569772Sarchie	bzero((char *)&areq, sizeof(areq));
130669772Sarchie	k = (struct an_ltv_key *)&areq;
130769772Sarchie
130869772Sarchie	/* From a Cisco engineer write the transmit key to use in the
130969772Sarchie	   first MAC, index is FFFF*/
131069772Sarchie	k->kindex=0xffff;
131169772Sarchie	k->klen=0;
131269772Sarchie
131369772Sarchie	k->mac[0]=atoi(arg);
131469772Sarchie	k->mac[1]=0;
131569772Sarchie	k->mac[2]=0;
131669772Sarchie	k->mac[3]=0;
131769772Sarchie	k->mac[4]=0;
131869772Sarchie	k->mac[5]=0;
131969772Sarchie
132069772Sarchie	areq.an_len = sizeof(struct an_ltv_key);
132169772Sarchie	areq.an_type = AN_RID_WEP_PERM;
132269772Sarchie	an_setval(iface, &areq);
132369772Sarchie
132469772Sarchie	return;
132569772Sarchie}
132669772Sarchie
132755992Swpaulint main(argc, argv)
132855992Swpaul	int			argc;
132955992Swpaul	char			*argv[];
133055992Swpaul{
133155992Swpaul	int			ch;
133255992Swpaul	int			act = 0;
133355992Swpaul	char			*iface = NULL;
133455992Swpaul	int			modifier = 0;
133568692Swpaul	char			*key = NULL;
133655992Swpaul	void			*arg = NULL;
133755992Swpaul	char			*p = argv[0];
133855992Swpaul
133967823Sjoe	/* Get the interface name */
134067823Sjoe	opterr = 0;
134167823Sjoe	ch = getopt(argc, argv, "i:");
134267823Sjoe	if (ch == 'i') {
134367823Sjoe		iface = optarg;
134467823Sjoe	} else {
134567823Sjoe		iface = "an0";
134667823Sjoe		optreset = 1;
134767823Sjoe		optind = 1;
134867823Sjoe	}
134967823Sjoe	opterr = 1;
135067823Sjoe
135155992Swpaul	while ((ch = getopt(argc, argv,
135269772Sarchie	    "ANISCTht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZ")) != -1) {
135355992Swpaul		switch(ch) {
135455992Swpaul		case 'Z':
135555992Swpaul#ifdef ANCACHE
135655992Swpaul			act = ACT_ZEROCACHE;
135755992Swpaul#else
135855992Swpaul			errx(1, "ANCACHE not available");
135955992Swpaul#endif
136055992Swpaul			break;
136155992Swpaul		case 'Q':
136255992Swpaul#ifdef ANCACHE
136355992Swpaul			act = ACT_DUMPCACHE;
136455992Swpaul#else
136555992Swpaul			errx(1, "ANCACHE not available");
136655992Swpaul#endif
136755992Swpaul			break;
136855992Swpaul		case 'A':
136955992Swpaul			act = ACT_DUMPAP;
137055992Swpaul			break;
137155992Swpaul		case 'N':
137255992Swpaul			act = ACT_DUMPSSID;
137355992Swpaul			break;
137455992Swpaul		case 'S':
137555992Swpaul			act = ACT_DUMPSTATUS;
137655992Swpaul			break;
137755992Swpaul		case 'I':
137855992Swpaul			act = ACT_DUMPCAPS;
137955992Swpaul			break;
138055992Swpaul		case 'T':
138155992Swpaul			act = ACT_DUMPSTATS;
138255992Swpaul			break;
138355992Swpaul		case 'C':
138455992Swpaul			act = ACT_DUMPCONFIG;
138555992Swpaul			break;
138655992Swpaul		case 't':
138755992Swpaul			act = ACT_SET_TXRATE;
138855992Swpaul			arg = optarg;
138955992Swpaul			break;
139055992Swpaul		case 's':
139155992Swpaul			act = ACT_SET_PWRSAVE;
139255992Swpaul			arg = optarg;
139355992Swpaul			break;
139455992Swpaul		case 'p':
139555992Swpaul			act = ACT_SET_TXPWR;
139655992Swpaul			arg = optarg;
139755992Swpaul			break;
139855992Swpaul		case 'v':
139955992Swpaul			modifier = atoi(optarg);
140055992Swpaul			break;
140155992Swpaul		case 'a':
140255992Swpaul			switch(modifier) {
140355992Swpaul			case 0:
140455992Swpaul			case 1:
140555992Swpaul				act = ACT_SET_AP1;
140655992Swpaul				break;
140755992Swpaul			case 2:
140855992Swpaul				act = ACT_SET_AP2;
140955992Swpaul				break;
141055992Swpaul			case 3:
141155992Swpaul				act = ACT_SET_AP3;
141255992Swpaul				break;
141355992Swpaul			case 4:
141455992Swpaul				act = ACT_SET_AP4;
141555992Swpaul				break;
141655992Swpaul			default:
141755992Swpaul				errx(1, "bad modifier %d: there "
141855992Swpaul				    "are only 4 access point settings",
141955992Swpaul				    modifier);
142055992Swpaul				usage(p);
142155992Swpaul				break;
142255992Swpaul			}
142355992Swpaul			arg = optarg;
142455992Swpaul			break;
142555992Swpaul		case 'b':
142655992Swpaul			act = ACT_SET_BEACON_PERIOD;
142755992Swpaul			arg = optarg;
142855992Swpaul			break;
142955992Swpaul		case 'd':
143055992Swpaul			switch(modifier) {
143155992Swpaul			case 0:
143255992Swpaul				act = ACT_SET_DIVERSITY_RX;
143355992Swpaul				break;
143455992Swpaul			case 1:
143555992Swpaul				act = ACT_SET_DIVERSITY_TX;
143655992Swpaul				break;
143755992Swpaul			default:
143855992Swpaul				errx(1, "must specift RX or TX diversity");
143955992Swpaul				break;
144055992Swpaul			}
144155992Swpaul			arg = optarg;
144255992Swpaul			break;
144355992Swpaul		case 'j':
144455992Swpaul			act = ACT_SET_NETJOIN;
144555992Swpaul			arg = optarg;
144655992Swpaul			break;
144755992Swpaul		case 'l':
144855992Swpaul			act = ACT_SET_MYNAME;
144955992Swpaul			arg = optarg;
145055992Swpaul			break;
145155992Swpaul		case 'm':
145255992Swpaul			act = ACT_SET_MAC;
145355992Swpaul			arg = optarg;
145455992Swpaul			break;
145555992Swpaul		case 'n':
145655992Swpaul			switch(modifier) {
145755992Swpaul			case 0:
145855992Swpaul			case 1:
145955992Swpaul				act = ACT_SET_SSID1;
146055992Swpaul				break;
146155992Swpaul			case 2:
146255992Swpaul				act = ACT_SET_SSID2;
146355992Swpaul				break;
146455992Swpaul			case 3:
146555992Swpaul				act = ACT_SET_SSID3;
146655992Swpaul				break;
146755992Swpaul			default:
146855992Swpaul				errx(1, "bad modifier %d: there"
146955992Swpaul				    "are only 3 SSID settings", modifier);
147055992Swpaul				usage(p);
147155992Swpaul				break;
147255992Swpaul			}
147355992Swpaul			arg = optarg;
147455992Swpaul			break;
147555992Swpaul		case 'o':
147655992Swpaul			act = ACT_SET_OPMODE;
147755992Swpaul			arg = optarg;
147855992Swpaul			break;
147955992Swpaul		case 'c':
148055992Swpaul			act = ACT_SET_FREQ;
148155992Swpaul			arg = optarg;
148255992Swpaul			break;
148355992Swpaul		case 'f':
148455992Swpaul			act = ACT_SET_FRAG_THRESH;
148555992Swpaul			arg = optarg;
148655992Swpaul			break;
148768692Swpaul		case 'W':
148868692Swpaul			act = ACT_ENABLE_WEP;
148968692Swpaul			arg = optarg;
149068692Swpaul			break;
149168692Swpaul		case 'K':
149268692Swpaul			act = ACT_SET_KEY_TYPE;
149368692Swpaul			arg = optarg;
149468692Swpaul			break;
149568692Swpaul		case 'k':
149668692Swpaul			act = ACT_SET_KEYS;
149768692Swpaul			key = optarg;
149868692Swpaul			break;
149969772Sarchie		case 'e':
150069772Sarchie			act = ACT_ENABLE_TX_KEY;
150169772Sarchie			arg = optarg;
150269772Sarchie			break;
150355992Swpaul		case 'q':
150455992Swpaul			act = ACT_SET_RTS_RETRYLIM;
150555992Swpaul			arg = optarg;
150655992Swpaul			break;
150755992Swpaul		case 'r':
150855992Swpaul			act = ACT_SET_RTS_THRESH;
150955992Swpaul			arg = optarg;
151055992Swpaul			break;
151155992Swpaul		case 'w':
151255992Swpaul			act = ACT_SET_WAKE_DURATION;
151355992Swpaul			arg = optarg;
151455992Swpaul			break;
151555992Swpaul		case 'h':
151655992Swpaul		default:
151755992Swpaul			usage(p);
151855992Swpaul		}
151955992Swpaul	}
152055992Swpaul
152168692Swpaul	if (iface == NULL || (!act && !key))
152255992Swpaul		usage(p);
152355992Swpaul
152455992Swpaul	switch(act) {
152555992Swpaul	case ACT_DUMPSTATUS:
152655992Swpaul		an_dumpstatus(iface);
152755992Swpaul		break;
152855992Swpaul	case ACT_DUMPCAPS:
152955992Swpaul		an_dumpcaps(iface);
153055992Swpaul		break;
153155992Swpaul	case ACT_DUMPSTATS:
153255992Swpaul		an_dumpstats(iface);
153355992Swpaul		break;
153455992Swpaul	case ACT_DUMPCONFIG:
153555992Swpaul		an_dumpconfig(iface);
153655992Swpaul		break;
153755992Swpaul	case ACT_DUMPSSID:
153855992Swpaul		an_dumpssid(iface);
153955992Swpaul		break;
154055992Swpaul	case ACT_DUMPAP:
154155992Swpaul		an_dumpap(iface);
154255992Swpaul		break;
154355992Swpaul	case ACT_SET_SSID1:
154455992Swpaul	case ACT_SET_SSID2:
154555992Swpaul	case ACT_SET_SSID3:
154655992Swpaul		an_setssid(iface, act, arg);
154755992Swpaul		break;
154855992Swpaul	case ACT_SET_AP1:
154955992Swpaul	case ACT_SET_AP2:
155055992Swpaul	case ACT_SET_AP3:
155155992Swpaul	case ACT_SET_AP4:
155255992Swpaul		an_setap(iface, act, arg);
155355992Swpaul		break;
155455992Swpaul	case ACT_SET_TXRATE:
155555992Swpaul		an_setspeed(iface, act, arg);
155655992Swpaul		break;
155755992Swpaul#ifdef ANCACHE
155855992Swpaul	case ACT_ZEROCACHE:
155955992Swpaul		an_zerocache(iface);
156055992Swpaul		break;
156155992Swpaul	case ACT_DUMPCACHE:
156255992Swpaul		an_readcache(iface);
156355992Swpaul		break;
156468692Swpaul
156555992Swpaul#endif
156668692Swpaul	case ACT_SET_KEYS:
156768692Swpaul		an_setkeys(iface, key, modifier);
156868692Swpaul		break;
156969772Sarchie	case ACT_ENABLE_TX_KEY:
157069772Sarchie		an_enable_tx_key(iface, arg);
157169772Sarchie		break;
157255992Swpaul	default:
157355992Swpaul		an_setconfig(iface, act, arg);
157455992Swpaul		break;
157555992Swpaul	}
157655992Swpaul
157755992Swpaul	exit(0);
157855992Swpaul}
157955992Swpaul
1580