ancontrol.c revision 89380
1174982Salc/*
2174982Salc * Copyright 1997, 1998, 1999
3177956Salc *	Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
4174982Salc *
5174982Salc * Redistribution and use in source and binary forms, with or without
6174982Salc * modification, are permitted provided that the following conditions
7174982Salc * are met:
8174982Salc * 1. Redistributions of source code must retain the above copyright
9174982Salc *    notice, this list of conditions and the following disclaimer.
10174982Salc * 2. Redistributions in binary form must reproduce the above copyright
11174982Salc *    notice, this list of conditions and the following disclaimer in the
12174982Salc *    documentation and/or other materials provided with the distribution.
13174982Salc * 3. All advertising materials mentioning features or use of this software
14174982Salc *    must display the following acknowledgement:
15174982Salc *	This product includes software developed by Bill Paul.
16174982Salc * 4. Neither the name of the author nor the names of any co-contributors
17174982Salc *    may be used to endorse or promote products derived from this software
18174982Salc *    without specific prior written permission.
19174982Salc *
20174982Salc * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21174982Salc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22174982Salc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23174982Salc * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24174982Salc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25174982Salc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26174982Salc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27174982Salc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28174982Salc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29174982Salc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30174982Salc * THE POSSIBILITY OF SUCH DAMAGE.
31174982Salc */
32174982Salc
33174982Salc#ifndef lint
34174982Salcstatic const char copyright[] = "@(#) Copyright (c) 1997, 1998, 1999\
35174982Salc	Bill Paul. All rights reserved.";
36174982Salcstatic const char rcsid[] =
37174982Salc  "$FreeBSD: head/usr.sbin/ancontrol/ancontrol.c 89380 2002-01-15 04:31:08Z ambrisko $";
38174982Salc#endif
39174982Salc
40174982Salc#include <sys/types.h>
41174982Salc#include <sys/cdefs.h>
42174982Salc#include <sys/param.h>
43174982Salc#include <sys/socket.h>
44174982Salc#include <sys/ioctl.h>
45174982Salc#include <sys/socket.h>
46174982Salc
47174982Salc#include <net/if.h>
48174982Salc#include <net/if_var.h>
49174982Salc#include <net/ethernet.h>
50174982Salc
51174982Salc#include <dev/an/if_aironet_ieee.h>
52174982Salc
53174982Salc#include <stdio.h>
54174982Salc#include <string.h>
55174982Salc#include <stdlib.h>
56174982Salc#include <unistd.h>
57174982Salc#include <errno.h>
58174982Salc#include <err.h>
59174982Salc#include <md4.h>
60174982Salc
61174982Salcstatic void an_getval		__P((const char *, struct an_req *));
62174982Salcstatic void an_setval		__P((const char *, struct an_req *));
63174982Salcstatic void an_printwords	__P((u_int16_t *, int));
64174982Salcstatic void an_printspeeds	__P((u_int8_t*, int));
65174982Salcstatic void an_printbool	__P((int));
66174982Salcstatic void an_printhex		__P((char *, int));
67174982Salcstatic void an_printstr		__P((char *, int));
68174982Salcstatic void an_dumpstatus	__P((const char *));
69174982Salcstatic void an_dumpstats	__P((const char *));
70174982Salcstatic void an_dumpconfig	__P((const char *));
71174982Salcstatic void an_dumpcaps		__P((const char *));
72174982Salcstatic void an_dumpssid		__P((const char *));
73174982Salcstatic void an_dumpap		__P((const char *));
74174982Salcstatic void an_setconfig	__P((const char *, int, void *));
75174982Salcstatic void an_setssid		__P((const char *, int, void *));
76174982Salcstatic void an_setap		__P((const char *, int, void *));
77174982Salcstatic void an_setspeed		__P((const char *, int, void *));
78174982Salcstatic void an_readkeyinfo	__P((const char *));
79174982Salc#ifdef ANCACHE
80174982Salcstatic void an_zerocache	__P((const char *));
81174982Salcstatic void an_readcache	__P((const char *));
82174982Salc#endif
83174982Salcstatic int an_hex2int		__P((char));
84174982Salcstatic void an_str2key		__P((char *, struct an_ltv_key *));
85174982Salcstatic void an_setkeys		__P((const char *, char *, int));
86174982Salcstatic void an_enable_tx_key	__P((const char *, char *));
87174982Salcstatic void an_enable_leap_mode __P((const char *, char *));
88174982Salcstatic void usage		__P((char *));
89174982Salcint main			__P((int, char **));
90174982Salc
91174982Salc#define ACT_DUMPSTATS 1
92174982Salc#define ACT_DUMPCONFIG 2
93174982Salc#define ACT_DUMPSTATUS 3
94174982Salc#define ACT_DUMPCAPS 4
95174982Salc#define ACT_DUMPSSID 5
96174982Salc#define ACT_DUMPAP 6
97174982Salc
98174982Salc#define ACT_SET_OPMODE 7
99174982Salc#define ACT_SET_SSID1 8
100174982Salc#define ACT_SET_SSID2 9
101174982Salc#define ACT_SET_SSID3 10
102174982Salc#define ACT_SET_FREQ 11
103174982Salc#define ACT_SET_AP1 12
104174982Salc#define ACT_SET_AP2 13
105174982Salc#define ACT_SET_AP3 14
106174982Salc#define ACT_SET_AP4 15
107174982Salc#define ACT_SET_DRIVERNAME 16
108174982Salc#define ACT_SET_SCANMODE 17
109174982Salc#define ACT_SET_TXRATE 18
110174982Salc#define ACT_SET_RTS_THRESH 19
111174982Salc#define ACT_SET_PWRSAVE 20
112174982Salc#define ACT_SET_DIVERSITY_RX 21
113174982Salc#define ACT_SET_DIVERSITY_TX 22
114174982Salc#define ACT_SET_RTS_RETRYLIM 23
115174982Salc#define ACT_SET_WAKE_DURATION 24
116174982Salc#define ACT_SET_BEACON_PERIOD 25
117174982Salc#define ACT_SET_TXPWR 26
118174982Salc#define ACT_SET_FRAG_THRESH 27
119174982Salc#define ACT_SET_NETJOIN 28
120174982Salc#define ACT_SET_MYNAME 29
121174982Salc#define ACT_SET_MAC 30
122174982Salc
123174982Salc#define ACT_DUMPCACHE 31
124174982Salc#define ACT_ZEROCACHE 32
125174982Salc
126174982Salc#define ACT_ENABLE_WEP 33
127174982Salc#define ACT_SET_KEY_TYPE 34
128174982Salc#define ACT_SET_KEYS 35
129174982Salc#define ACT_ENABLE_TX_KEY 36
130174982Salc#define ACT_SET_MONITOR_MODE 37
131174982Salc#define ACT_SET_LEAP_MODE 38
132174982Salc
133174982Salcstatic void an_getval(iface, areq)
134174982Salc	const char		*iface;
135174982Salc	struct an_req		*areq;
136174982Salc{
137174982Salc	struct ifreq		ifr;
138174982Salc	int			s;
139174982Salc
140174982Salc	bzero((char *)&ifr, sizeof(ifr));
141190912Salc
142190912Salc	strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
143174982Salc	ifr.ifr_data = (caddr_t)areq;
144174982Salc
145174982Salc	s = socket(AF_INET, SOCK_DGRAM, 0);
146174982Salc
147174982Salc	if (s == -1)
148174982Salc		err(1, "socket");
149174982Salc
150174982Salc	if (ioctl(s, SIOCGAIRONET, &ifr) == -1)
151174982Salc		err(1, "SIOCGAIRONET");
152174982Salc
153174982Salc	close(s);
154174982Salc
155174982Salc	return;
156174982Salc}
157174982Salc
158174982Salcstatic void an_setval(iface, areq)
159174982Salc	const char		*iface;
160174982Salc	struct an_req		*areq;
161174982Salc{
162174982Salc	struct ifreq		ifr;
163174982Salc	int			s;
164174982Salc
165174982Salc	bzero((char *)&ifr, sizeof(ifr));
166174982Salc
167174982Salc	strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
168174982Salc	ifr.ifr_data = (caddr_t)areq;
169174982Salc
170174982Salc	s = socket(AF_INET, SOCK_DGRAM, 0);
171174982Salc
172174982Salc	if (s == -1)
173177956Salc		err(1, "socket");
174174982Salc
175174982Salc	if (ioctl(s, SIOCSAIRONET, &ifr) == -1)
176174982Salc		err(1, "SIOCSAIRONET");
177174982Salc
178174982Salc	close(s);
179174982Salc
180174982Salc	return;
181174982Salc}
182174982Salc
183174982Salcstatic void an_printstr(str, len)
184174982Salc	char			*str;
185217916Smdf	int			len;
186217916Smdf{
187217916Smdf	int			i;
188212750Smdf
189174982Salc	for (i = 0; i < len - 1; i++) {
190174982Salc		if (str[i] == '\0')
191174982Salc			str[i] = ' ';
192174982Salc	}
193174982Salc
194174982Salc	printf("[ %.*s ]", len, str);
195174982Salc
196174982Salc	return;
197174982Salc}
198174982Salc
199214564Salcstatic void an_printwords(w, len)
200215093Salc	u_int16_t		*w;
201174982Salc	int			len;
202212750Smdf{
203174982Salc	int			i;
204174982Salc
205174982Salc	printf("[ ");
206174982Salc	for (i = 0; i < len; i++)
207174982Salc		printf("%d ", w[i]);
208174982Salc	printf("]");
209174982Salc
210190912Salc	return;
211174982Salc}
212174982Salc
213174982Salcstatic void an_printspeeds(w, len)
214174982Salc	u_int8_t		*w;
215174982Salc	int			len;
216174982Salc{
217174982Salc	int			i;
218174982Salc
219174982Salc	printf("[ ");
220174982Salc	for (i = 0; i < len && w[i]; i++)
221174982Salc		printf("%2.1fMbps ", w[i] * 0.500);
222174982Salc	printf("]");
223174982Salc
224174982Salc	return;
225174982Salc}
226174982Salc
227174982Salcstatic void an_printbool(val)
228174982Salc	int			val;
229174982Salc{
230174982Salc	if (val)
231174982Salc		printf("[ On ]");
232174982Salc	else
233174982Salc		printf("[ Off ]");
234174982Salc
235174982Salc	return;
236190912Salc}
237174982Salc
238174982Salcstatic void an_printhex(ptr, len)
239174982Salc	char			*ptr;
240174982Salc	int			len;
241174982Salc{
242174982Salc	int			i;
243174982Salc
244174982Salc	printf("[ ");
245174982Salc	for (i = 0; i < len; i++) {
246174982Salc		printf("%02x", ptr[i] & 0xFF);
247174982Salc		if (i < (len - 1))
248174982Salc			printf(":");
249174982Salc	}
250174982Salc
251174982Salc	printf(" ]");
252174982Salc	return;
253174982Salc}
254174982Salc
255174982Salc
256174982Salc
257174982Salcstatic void an_dumpstatus(iface)
258174982Salc	const char		*iface;
259174982Salc{
260174982Salc	struct an_ltv_status	*sts;
261174982Salc	struct an_req		areq;
262174982Salc
263174982Salc	areq.an_len = sizeof(areq);
264174982Salc	areq.an_type = AN_RID_STATUS;
265174982Salc
266174982Salc	an_getval(iface, &areq);
267174982Salc
268174982Salc	sts = (struct an_ltv_status *)&areq;
269174982Salc
270174982Salc	printf("MAC address:\t\t");
271174982Salc	an_printhex((char *)&sts->an_macaddr, ETHER_ADDR_LEN);
272174982Salc	printf("\nOperating mode:\t\t[ ");
273174982Salc	if (sts->an_opmode & AN_STATUS_OPMODE_CONFIGURED)
274174982Salc		printf("configured ");
275174982Salc	if (sts->an_opmode & AN_STATUS_OPMODE_MAC_ENABLED)
276174982Salc		printf("MAC ON ");
277174982Salc	if (sts->an_opmode & AN_STATUS_OPMODE_RX_ENABLED)
278174982Salc		printf("RX ON ");
279174982Salc	if (sts->an_opmode & AN_STATUS_OPMODE_IN_SYNC)
280174982Salc		printf("synced ");
281174982Salc	if (sts->an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
282174982Salc		printf("associated ");
283174982Salc	if (sts->an_opmode & AN_STATUS_OPMODE_LEAP)
284174982Salc		printf("LEAP ");
285174982Salc	if (sts->an_opmode & AN_STATUS_OPMODE_ERROR)
286174982Salc		printf("error ");
287174982Salc	printf("]\n");
288174982Salc	printf("Error code:\t\t");
289174982Salc	an_printhex((char *)&sts->an_errcode, 1);
290174982Salc	printf("\nSignal quality:\t\t");
291174982Salc	an_printhex((char *)&sts->an_cur_signal_quality, 1);
292174982Salc	printf("\nSignal strength:\t[ %d%% ]",sts->an_normalized_rssi);
293174982Salc	printf("\nMax Noise:\t\t[ %d%% ]",sts->an_avg_noise_prev_min);
294174982Salc	/*
295174982Salc	 * XXX: This uses the old definition of the rate field (units of
296174982Salc	 * 500kbps).  Technically the new definition is that this field
297174982Salc	 * contains arbitrary values, but no devices which need this
298174982Salc	 * support exist and the IEEE seems to intend to use the old
299174982Salc	 * definition until they get something big so we'll keep using
300174982Salc	 * it as well because this will work with new cards with
301174982Salc	 * rate <= 63.5Mbps.
302174982Salc	 */
303174982Salc	printf("\nCurrent TX rate:\t[ %d%s ]", sts->an_current_tx_rate / 2,
304174982Salc	    (sts->an_current_tx_rate % 2) ? ".5" : "");
305174982Salc	printf("\nCurrent SSID:\t\t");
306174982Salc	an_printstr((char *)&sts->an_ssid, sts->an_ssidlen);
307174982Salc	printf("\nCurrent AP name:\t");
308174982Salc	an_printstr((char *)&sts->an_ap_name, 16);
309174982Salc	printf("\nCurrent BSSID:\t\t");
310174982Salc	an_printhex((char *)&sts->an_cur_bssid, ETHER_ADDR_LEN);
311174982Salc	printf("\nBeacon period:\t\t");
312174982Salc	an_printwords(&sts->an_beacon_period, 1);
313174982Salc	printf("\nDTIM period:\t\t");
314174982Salc	an_printwords(&sts->an_dtim_period, 1);
315174982Salc	printf("\nATIM duration:\t\t");
316174982Salc	an_printwords(&sts->an_atim_duration, 1);
317174982Salc	printf("\nHOP period:\t\t");
318174982Salc	an_printwords(&sts->an_hop_period, 1);
319174982Salc	printf("\nChannel set:\t\t");
320174982Salc	an_printwords(&sts->an_channel_set, 1);
321174982Salc	printf("\nCurrent channel:\t");
322174982Salc	an_printwords(&sts->an_cur_channel, 1);
323174982Salc	printf("\nHops to backbone:\t");
324174982Salc	an_printwords(&sts->an_hops_to_backbone, 1);
325174982Salc	printf("\nTotal AP load:\t\t");
326174982Salc	an_printwords(&sts->an_ap_total_load, 1);
327174982Salc	printf("\nOur generated load:\t");
328174982Salc	an_printwords(&sts->an_our_generated_load, 1);
329174982Salc	printf("\nAccumulated ARL:\t");
330174982Salc	an_printwords(&sts->an_accumulated_arl, 1);
331174982Salc	printf("\n");
332174982Salc	return;
333174982Salc}
334174982Salc
335174982Salcstatic void an_dumpcaps(iface)
336174982Salc	const char		*iface;
337174982Salc{
338174982Salc	struct an_ltv_caps	*caps;
339174982Salc	struct an_req		areq;
340174982Salc	u_int16_t		tmp;
341174982Salc
342174982Salc	areq.an_len = sizeof(areq);
343174982Salc	areq.an_type = AN_RID_CAPABILITIES;
344174982Salc
345174982Salc	an_getval(iface, &areq);
346174982Salc
347174982Salc	caps = (struct an_ltv_caps *)&areq;
348174982Salc
349174982Salc	printf("OUI:\t\t\t");
350174982Salc	an_printhex((char *)&caps->an_oui, 3);
351174982Salc	printf("\nProduct number:\t\t");
352174982Salc	an_printwords(&caps->an_prodnum, 1);
353174982Salc	printf("\nManufacturer name:\t");
354174982Salc	an_printstr((char *)&caps->an_manufname, 32);
355174982Salc	printf("\nProduce name:\t\t");
356174982Salc	an_printstr((char *)&caps->an_prodname, 16);
357174982Salc	printf("\nFirmware version:\t");
358174982Salc	an_printstr((char *)&caps->an_prodvers, 1);
359174982Salc	printf("\nOEM MAC address:\t");
360174982Salc	an_printhex((char *)&caps->an_oemaddr, ETHER_ADDR_LEN);
361174982Salc	printf("\nAironet MAC address:\t");
362174982Salc	an_printhex((char *)&caps->an_aironetaddr, ETHER_ADDR_LEN);
363174982Salc	printf("\nRadio type:\t\t[ ");
364174982Salc	if (caps->an_radiotype & AN_RADIOTYPE_80211_FH)
365174982Salc		printf("802.11 FH");
366174982Salc	else if (caps->an_radiotype & AN_RADIOTYPE_80211_DS)
367174982Salc		printf("802.11 DS");
368174982Salc	else if (caps->an_radiotype & AN_RADIOTYPE_LM2000_DS)
369174982Salc		printf("LM2000 DS");
370174982Salc	else
371174982Salc		printf("unknown (%x)", caps->an_radiotype);
372174982Salc	printf(" ]");
373174982Salc	printf("\nRegulatory domain:\t");
374174982Salc	an_printwords(&caps->an_regdomain, 1);
375174982Salc	printf("\nAssigned CallID:\t");
376174982Salc	an_printhex((char *)&caps->an_callid, 6);
377174982Salc	printf("\nSupported speeds:\t");
378174982Salc	an_printspeeds(caps->an_rates, 8);
379174982Salc	printf("\nRX Diversity:\t\t[ ");
380174982Salc	if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
381174982Salc		printf("antenna 1 only");
382174982Salc	else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
383174982Salc		printf("antenna 2 only");
384174982Salc	else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
385174982Salc		printf("antenna 1 and 2");
386174982Salc	printf(" ]");
387174982Salc	printf("\nTX Diversity:\t\t[ ");
388174982Salc	if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
389174982Salc		printf("antenna 1 only");
390174982Salc	else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
391174982Salc		printf("antenna 2 only");
392174982Salc	else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
393174982Salc		printf("antenna 1 and 2");
394174982Salc	printf(" ]");
395174982Salc	printf("\nSupported power levels:\t");
396174982Salc	an_printwords(caps->an_tx_powerlevels, 8);
397174982Salc	printf("\nHardware revision:\t");
398174982Salc	tmp = ntohs(caps->an_hwrev);
399174982Salc	an_printhex((char *)&tmp, 2);
400174982Salc	printf("\nSoftware revision:\t");
401174982Salc	tmp = ntohs(caps->an_fwrev);
402174982Salc	an_printhex((char *)&tmp, 2);
403174982Salc	printf("\nSoftware subrevision:\t");
404174982Salc	tmp = ntohs(caps->an_fwsubrev);
405174982Salc	an_printhex((char *)&tmp, 2);
406174982Salc	printf("\nInterface revision:\t");
407174982Salc	tmp = ntohs(caps->an_ifacerev);
408174982Salc	an_printhex((char *)&tmp, 2);
409174982Salc	printf("\nBootblock revision:\t");
410174982Salc	tmp = ntohs(caps->an_bootblockrev);
411174982Salc	an_printhex((char *)&tmp, 2);
412174982Salc	printf("\n");
413174982Salc	return;
414174982Salc}
415174982Salc
416174982Salcstatic void an_dumpstats(iface)
417174982Salc	const char		*iface;
418174982Salc{
419174982Salc	struct an_ltv_stats	*stats;
420174982Salc	struct an_req		areq;
421174982Salc	caddr_t			ptr;
422174982Salc
423174982Salc	areq.an_len = sizeof(areq);
424174982Salc	areq.an_type = AN_RID_32BITS_CUM;
425174982Salc
426174982Salc	an_getval(iface, &areq);
427174982Salc
428174982Salc	ptr = (caddr_t)&areq;
429174982Salc	ptr -= 2;
430174982Salc	stats = (struct an_ltv_stats *)ptr;
431174982Salc
432174982Salc	printf("RX overruns:\t\t\t\t\t[ %d ]\n", stats->an_rx_overruns);
433174982Salc	printf("RX PLCP CSUM errors:\t\t\t\t[ %d ]\n",
434174982Salc	    stats->an_rx_plcp_csum_errs);
435174982Salc	printf("RX PLCP format errors:\t\t\t\t[ %d ]\n",
436174982Salc	    stats->an_rx_plcp_format_errs);
437174982Salc	printf("RX PLCP length errors:\t\t\t\t[ %d ]\n",
438174982Salc	    stats->an_rx_plcp_len_errs);
439174982Salc	printf("RX MAC CRC errors:\t\t\t\t[ %d ]\n",
440174982Salc	    stats->an_rx_mac_crc_errs);
441174982Salc	printf("RX MAC CRC OK:\t\t\t\t\t[ %d ]\n",
442174982Salc	    stats->an_rx_mac_crc_ok);
443174982Salc	printf("RX WEP errors:\t\t\t\t\t[ %d ]\n",
444174982Salc	    stats->an_rx_wep_errs);
445174982Salc	printf("RX WEP OK:\t\t\t\t\t[ %d ]\n",
446174982Salc	    stats->an_rx_wep_ok);
447174982Salc	printf("Long retries:\t\t\t\t\t[ %d ]\n",
448174982Salc	    stats->an_retry_long);
449174982Salc	printf("Short retries:\t\t\t\t\t[ %d ]\n",
450174982Salc	    stats->an_retry_short);
451174982Salc	printf("Retries exhausted:\t\t\t\t[ %d ]\n",
452174982Salc	    stats->an_retry_max);
453174982Salc	printf("Bad ACK:\t\t\t\t\t[ %d ]\n",
454174982Salc	    stats->an_no_ack);
455174982Salc	printf("Bad CTS:\t\t\t\t\t[ %d ]\n",
456174982Salc	    stats->an_no_cts);
457174982Salc	printf("RX good ACKs:\t\t\t\t\t[ %d ]\n",
458174982Salc	    stats->an_rx_ack_ok);
459174982Salc	printf("RX good CTSs:\t\t\t\t\t[ %d ]\n",
460174982Salc	    stats->an_rx_cts_ok);
461174982Salc	printf("TX good ACKs:\t\t\t\t\t[ %d ]\n",
462174982Salc	    stats->an_tx_ack_ok);
463174982Salc	printf("TX good RTSs:\t\t\t\t\t[ %d ]\n",
464174982Salc	    stats->an_tx_rts_ok);
465174982Salc	printf("TX good CTSs:\t\t\t\t\t[ %d ]\n",
466174982Salc	    stats->an_tx_cts_ok);
467234771Salc	printf("LMAC multicasts transmitted:\t\t\t[ %d ]\n",
468234771Salc	    stats->an_tx_lmac_mcasts);
469234771Salc	printf("LMAC broadcasts transmitted:\t\t\t[ %d ]\n",
470234771Salc	    stats->an_tx_lmac_bcasts);
471234771Salc	printf("LMAC unicast frags transmitted:\t\t\t[ %d ]\n",
472234771Salc	    stats->an_tx_lmac_ucast_frags);
473234771Salc	printf("LMAC unicasts transmitted:\t\t\t[ %d ]\n",
474174982Salc	    stats->an_tx_lmac_ucasts);
475174982Salc	printf("Beacons transmitted:\t\t\t\t[ %d ]\n",
476174982Salc	    stats->an_tx_beacons);
477174982Salc	printf("Beacons received:\t\t\t\t[ %d ]\n",
478174982Salc	    stats->an_rx_beacons);
479174982Salc	printf("Single transmit collisions:\t\t\t[ %d ]\n",
480174982Salc	    stats->an_tx_single_cols);
481174982Salc	printf("Multiple transmit collisions:\t\t\t[ %d ]\n",
482174982Salc	    stats->an_tx_multi_cols);
483174982Salc	printf("Transmits without deferrals:\t\t\t[ %d ]\n",
484174982Salc	    stats->an_tx_defers_no);
485174982Salc	printf("Transmits deferred due to protocol:\t\t[ %d ]\n",
486174982Salc	    stats->an_tx_defers_prot);
487174982Salc	printf("Transmits deferred due to energy detect:\t\t[ %d ]\n",
488174982Salc	    stats->an_tx_defers_energy);
489174982Salc	printf("RX duplicate frames/frags:\t\t\t[ %d ]\n",
490174982Salc	    stats->an_rx_dups);
491174982Salc	printf("RX partial frames:\t\t\t\t[ %d ]\n",
492174982Salc	    stats->an_rx_partial);
493174982Salc	printf("TX max lifetime exceeded:\t\t\t[ %d ]\n",
494174982Salc	    stats->an_tx_too_old);
495174982Salc	printf("RX max lifetime exceeded:\t\t\t[ %d ]\n",
496174982Salc	    stats->an_tx_too_old);
497174982Salc	printf("Sync lost due to too many missed beacons:\t[ %d ]\n",
498174982Salc	    stats->an_lostsync_missed_beacons);
499174982Salc	printf("Sync lost due to ARL exceeded:\t\t\t[ %d ]\n",
500174982Salc	    stats->an_lostsync_arl_exceeded);
501174982Salc	printf("Sync lost due to deauthentication:\t\t[ %d ]\n",
502174982Salc	    stats->an_lostsync_deauthed);
503174982Salc	printf("Sync lost due to disassociation:\t\t[ %d ]\n",
504174982Salc	    stats->an_lostsync_disassociated);
505174982Salc	printf("Sync lost due to excess change in TSF timing:\t[ %d ]\n",
506174982Salc	    stats->an_lostsync_tsf_timing);
507174982Salc	printf("Host transmitted multicasts:\t\t\t[ %d ]\n",
508174982Salc	    stats->an_tx_host_mcasts);
509174982Salc	printf("Host transmitted broadcasts:\t\t\t[ %d ]\n",
510174982Salc	    stats->an_tx_host_bcasts);
511174982Salc	printf("Host transmitted unicasts:\t\t\t[ %d ]\n",
512174982Salc	    stats->an_tx_host_ucasts);
513174982Salc	printf("Host transmission failures:\t\t\t[ %d ]\n",
514174982Salc	    stats->an_tx_host_failed);
515174982Salc	printf("Host received multicasts:\t\t\t[ %d ]\n",
516174982Salc	    stats->an_rx_host_mcasts);
517174982Salc	printf("Host received broadcasts:\t\t\t[ %d ]\n",
518174982Salc	    stats->an_rx_host_bcasts);
519174982Salc	printf("Host received unicasts:\t\t\t\t[ %d ]\n",
520174982Salc	    stats->an_rx_host_ucasts);
521174982Salc	printf("Host receive discards:\t\t\t\t[ %d ]\n",
522174982Salc	    stats->an_rx_host_discarded);
523174982Salc	printf("HMAC transmitted multicasts:\t\t\t[ %d ]\n",
524174982Salc	    stats->an_tx_hmac_mcasts);
525174982Salc	printf("HMAC transmitted broadcasts:\t\t\t[ %d ]\n",
526174982Salc	    stats->an_tx_hmac_bcasts);
527174982Salc	printf("HMAC transmitted unicasts:\t\t\t[ %d ]\n",
528174982Salc	    stats->an_tx_hmac_ucasts);
529174982Salc	printf("HMAC transmissions failed:\t\t\t[ %d ]\n",
530174982Salc	    stats->an_tx_hmac_failed);
531174982Salc	printf("HMAC received multicasts:\t\t\t[ %d ]\n",
532174982Salc	    stats->an_rx_hmac_mcasts);
533174982Salc	printf("HMAC received broadcasts:\t\t\t[ %d ]\n",
534174982Salc	    stats->an_rx_hmac_bcasts);
535174982Salc	printf("HMAC received unicasts:\t\t\t\t[ %d ]\n",
536174982Salc	    stats->an_rx_hmac_ucasts);
537174982Salc	printf("HMAC receive discards:\t\t\t\t[ %d ]\n",
538174982Salc	    stats->an_rx_hmac_discarded);
539174982Salc	printf("HMAC transmits accepted:\t\t\t[ %d ]\n",
540174982Salc	    stats->an_tx_hmac_accepted);
541174982Salc	printf("SSID mismatches:\t\t\t\t[ %d ]\n",
542174982Salc	    stats->an_ssid_mismatches);
543174982Salc	printf("Access point mismatches:\t\t\t[ %d ]\n",
544174982Salc	    stats->an_ap_mismatches);
545174982Salc	printf("Speed mismatches:\t\t\t\t[ %d ]\n",
546174982Salc	    stats->an_rates_mismatches);
547174982Salc	printf("Authentication rejects:\t\t\t\t[ %d ]\n",
548174982Salc	    stats->an_auth_rejects);
549174982Salc	printf("Authentication timeouts:\t\t\t[ %d ]\n",
550174982Salc	    stats->an_auth_timeouts);
551174982Salc	printf("Association rejects:\t\t\t\t[ %d ]\n",
552174982Salc	    stats->an_assoc_rejects);
553174982Salc	printf("Association timeouts:\t\t\t\t[ %d ]\n",
554174982Salc	    stats->an_assoc_timeouts);
555174982Salc	printf("Management frames received:\t\t\t[ %d ]\n",
556174982Salc	    stats->an_rx_mgmt_pkts);
557174982Salc	printf("Management frames transmitted:\t\t\t[ %d ]\n",
558174982Salc	    stats->an_tx_mgmt_pkts);
559174982Salc	printf("Refresh frames received:\t\t\t[ %d ]\n",
560174982Salc	    stats->an_rx_refresh_pkts),
561174982Salc	printf("Refresh frames transmitted:\t\t\t[ %d ]\n",
562174982Salc	    stats->an_tx_refresh_pkts),
563174982Salc	printf("Poll frames received:\t\t\t\t[ %d ]\n",
564174982Salc	    stats->an_rx_poll_pkts);
565174982Salc	printf("Poll frames transmitted:\t\t\t[ %d ]\n",
566174982Salc	    stats->an_tx_poll_pkts);
567174982Salc	printf("Host requested sync losses:\t\t\t[ %d ]\n",
568174982Salc	    stats->an_lostsync_hostreq);
569174982Salc	printf("Host transmitted bytes:\t\t\t\t[ %d ]\n",
570174982Salc	    stats->an_host_tx_bytes);
571174982Salc	printf("Host received bytes:\t\t\t\t[ %d ]\n",
572177956Salc	    stats->an_host_rx_bytes);
573177956Salc	printf("Uptime in microseconds:\t\t\t\t[ %d ]\n",
574177956Salc	    stats->an_uptime_usecs);
575177956Salc	printf("Uptime in seconds:\t\t\t\t[ %d ]\n",
576177956Salc	    stats->an_uptime_secs);
577177956Salc	printf("Sync lost due to better AP:\t\t\t[ %d ]\n",
578177956Salc	    stats->an_lostsync_better_ap);
579177956Salc
580177956Salc	return;
581177956Salc}
582177956Salc
583177956Salcstatic void an_dumpap(iface)
584177956Salc	const char		*iface;
585177956Salc{
586177956Salc	struct an_ltv_aplist	*ap;
587177956Salc	struct an_req		areq;
588177956Salc
589177956Salc	areq.an_len = sizeof(areq);
590177956Salc	areq.an_type = AN_RID_APLIST;
591177956Salc
592177956Salc	an_getval(iface, &areq);
593177956Salc
594177956Salc	ap = (struct an_ltv_aplist *)&areq;
595177956Salc	printf("Access point 1:\t\t\t");
596177956Salc	an_printhex((char *)&ap->an_ap1, ETHER_ADDR_LEN);
597177956Salc	printf("\nAccess point 2:\t\t\t");
598177956Salc	an_printhex((char *)&ap->an_ap2, ETHER_ADDR_LEN);
599177956Salc	printf("\nAccess point 3:\t\t\t");
600177956Salc	an_printhex((char *)&ap->an_ap3, ETHER_ADDR_LEN);
601177956Salc	printf("\nAccess point 4:\t\t\t");
602177956Salc	an_printhex((char *)&ap->an_ap4, ETHER_ADDR_LEN);
603174982Salc	printf("\n");
604174982Salc
605174982Salc	return;
606174982Salc}
607174982Salc
608174982Salcstatic void an_dumpssid(iface)
609174982Salc	const char		*iface;
610177956Salc{
611174982Salc	struct an_ltv_ssidlist	*ssid;
612174982Salc	struct an_req		areq;
613174982Salc
614174982Salc	areq.an_len = sizeof(areq);
615174982Salc	areq.an_type = AN_RID_SSIDLIST;
616177956Salc
617174982Salc	an_getval(iface, &areq);
618174982Salc
619174982Salc	ssid = (struct an_ltv_ssidlist *)&areq;
620174982Salc	printf("SSID 1:\t\t\t[ %.*s ]\n", ssid->an_ssid1_len, ssid->an_ssid1);
621174982Salc	printf("SSID 2:\t\t\t[ %.*s ]\n", ssid->an_ssid2_len, ssid->an_ssid2);
622174982Salc	printf("SSID 3:\t\t\t[ %.*s ]\n", ssid->an_ssid3_len, ssid->an_ssid3);
623177956Salc
624177956Salc	return;
625177956Salc}
626177956Salc
627177956Salcstatic void an_dumpconfig(iface)
628177956Salc	const char		*iface;
629177956Salc{
630177956Salc	struct an_ltv_genconfig	*cfg;
631177956Salc	struct an_req		areq;
632177956Salc	unsigned char		diversity;
633262933Sdumbbell
634177956Salc	areq.an_len = sizeof(areq);
635177956Salc	areq.an_type = AN_RID_ACTUALCFG;
636177956Salc
637177956Salc	an_getval(iface, &areq);
638177956Salc
639177956Salc	cfg = (struct an_ltv_genconfig *)&areq;
640177956Salc
641177956Salc	printf("Operating mode:\t\t\t\t[ ");
642177956Salc	if ((cfg->an_opmode & 0x7) == AN_OPMODE_IBSS_ADHOC)
643177956Salc		printf("ad-hoc");
644177956Salc	if ((cfg->an_opmode & 0x7) == AN_OPMODE_INFRASTRUCTURE_STATION)
645177956Salc		printf("infrastructure");
646177956Salc	if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP)
647177956Salc		printf("access point");
648177956Salc	if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP_REPEATER)
649177956Salc		printf("access point repeater");
650177956Salc	printf(" ]");
651177956Salc	printf("\nReceive mode:\t\t\t\t[ ");
652177956Salc	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_MC_ADDR)
653177956Salc		printf("broadcast/multicast/unicast");
654177956Salc	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_ADDR)
655177956Salc		printf("broadcast/unicast");
656177956Salc	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_ADDR)
657177956Salc		printf("unicast");
658177956Salc	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_CURBSS)
659177956Salc		printf("802.11 monitor, current BSSID");
660177956Salc	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_ANYBSS)
661177956Salc		printf("802.11 monitor, any BSSID");
662215508Smlaier	if ((cfg->an_rxmode & 0x7) == AN_RXMODE_LAN_MONITOR_CURBSS)
663215508Smlaier		printf("LAN monitor, current BSSID");
664177956Salc	printf(" ]");
665177956Salc	printf("\nFragment threshold:\t\t\t");
666177956Salc	an_printwords(&cfg->an_fragthresh, 1);
667177956Salc	printf("\nRTS threshold:\t\t\t\t");
668177956Salc	an_printwords(&cfg->an_rtsthresh, 1);
669177956Salc	printf("\nMAC address:\t\t\t\t");
670177956Salc	an_printhex((char *)&cfg->an_macaddr, ETHER_ADDR_LEN);
671177956Salc	printf("\nSupported rates:\t\t\t");
672177956Salc	an_printspeeds(cfg->an_rates, 8);
673177956Salc	printf("\nShort retry limit:\t\t\t");
674174982Salc	an_printwords(&cfg->an_shortretry_limit, 1);
675174982Salc	printf("\nLong retry limit:\t\t\t");
676174982Salc	an_printwords(&cfg->an_longretry_limit, 1);
677174982Salc	printf("\nTX MSDU lifetime:\t\t\t");
678174982Salc	an_printwords(&cfg->an_tx_msdu_lifetime, 1);
679174982Salc	printf("\nRX MSDU lifetime:\t\t\t");
680174982Salc	an_printwords(&cfg->an_rx_msdu_lifetime, 1);
681174982Salc	printf("\nStationary:\t\t\t\t");
682174982Salc	an_printbool(cfg->an_stationary);
683174982Salc	printf("\nOrdering:\t\t\t\t");
684174982Salc	an_printbool(cfg->an_ordering);
685174982Salc	printf("\nDevice type:\t\t\t\t[ ");
686174982Salc	if (cfg->an_devtype == AN_DEVTYPE_PC4500)
687174982Salc		printf("PC4500");
688174982Salc	else if (cfg->an_devtype == AN_DEVTYPE_PC4800)
689174982Salc		printf("PC4800");
690174982Salc	else
691174982Salc		printf("unknown (%x)", cfg->an_devtype);
692174982Salc	printf(" ]");
693174982Salc	printf("\nScanning mode:\t\t\t\t[ ");
694174982Salc	if (cfg->an_scanmode == AN_SCANMODE_ACTIVE)
695174982Salc		printf("active");
696174982Salc	if (cfg->an_scanmode == AN_SCANMODE_PASSIVE)
697174982Salc		printf("passive");
698174982Salc	if (cfg->an_scanmode == AN_SCANMODE_AIRONET_ACTIVE)
699174982Salc		printf("Aironet active");
700174982Salc	printf(" ]");
701174982Salc	printf("\nProbe delay:\t\t\t\t");
702174982Salc	an_printwords(&cfg->an_probedelay, 1);
703174982Salc	printf("\nProbe energy timeout:\t\t\t");
704174982Salc	an_printwords(&cfg->an_probe_energy_timeout, 1);
705174982Salc	printf("\nProbe response timeout:\t\t\t");
706174982Salc	an_printwords(&cfg->an_probe_response_timeout, 1);
707174982Salc	printf("\nBeacon listen timeout:\t\t\t");
708174982Salc	an_printwords(&cfg->an_beacon_listen_timeout, 1);
709174982Salc	printf("\nIBSS join network timeout:\t\t");
710174982Salc	an_printwords(&cfg->an_ibss_join_net_timeout, 1);
711174982Salc	printf("\nAuthentication timeout:\t\t\t");
712174982Salc	an_printwords(&cfg->an_auth_timeout, 1);
713174982Salc	printf("\nWEP enabled:\t\t\t\t[ ");
714174982Salc	if (cfg->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE)
715174982Salc	{
716174982Salc		if (cfg->an_authtype & AN_AUTHTYPE_LEAP)
717174982Salc			 printf("LEAP");
718174982Salc		else if (cfg->an_authtype & AN_AUTHTYPE_ALLOW_UNENCRYPTED)
719174982Salc			 printf("mixed cell");
720174982Salc		else
721174982Salc			 printf("full");
722174982Salc	}
723174982Salc	else
724174982Salc		printf("no");
725174982Salc	printf(" ]");
726174982Salc	printf("\nAuthentication type:\t\t\t[ ");
727174982Salc	if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_NONE)
728174982Salc		printf("none");
729174982Salc	if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_OPEN)
730174982Salc		printf("open");
731174982Salc	if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_SHAREDKEY)
732174982Salc		printf("shared key");
733	printf(" ]");
734	printf("\nAssociation timeout:\t\t\t");
735	an_printwords(&cfg->an_assoc_timeout, 1);
736	printf("\nSpecified AP association timeout:\t");
737	an_printwords(&cfg->an_specified_ap_timeout, 1);
738	printf("\nOffline scan interval:\t\t\t");
739	an_printwords(&cfg->an_offline_scan_interval, 1);
740	printf("\nOffline scan duration:\t\t\t");
741	an_printwords(&cfg->an_offline_scan_duration, 1);
742	printf("\nLink loss delay:\t\t\t");
743	an_printwords(&cfg->an_link_loss_delay, 1);
744	printf("\nMax beacon loss time:\t\t\t");
745	an_printwords(&cfg->an_max_beacon_lost_time, 1);
746	printf("\nRefresh interval:\t\t\t");
747	an_printwords(&cfg->an_refresh_interval, 1);
748	printf("\nPower save mode:\t\t\t[ ");
749	if (cfg->an_psave_mode == AN_PSAVE_NONE)
750		printf("none");
751	if (cfg->an_psave_mode == AN_PSAVE_CAM)
752		printf("constantly awake mode");
753	if (cfg->an_psave_mode == AN_PSAVE_PSP)
754		printf("PSP");
755	if (cfg->an_psave_mode == AN_PSAVE_PSP_CAM)
756		printf("PSP-CAM (fast PSP)");
757	printf(" ]");
758	printf("\nSleep through DTIMs:\t\t\t");
759	an_printbool(cfg->an_sleep_for_dtims);
760	printf("\nPower save listen interval:\t\t");
761	an_printwords(&cfg->an_listen_interval, 1);
762	printf("\nPower save fast listen interval:\t");
763	an_printwords(&cfg->an_fast_listen_interval, 1);
764	printf("\nPower save listen decay:\t\t");
765	an_printwords(&cfg->an_listen_decay, 1);
766	printf("\nPower save fast listen decay:\t\t");
767	an_printwords(&cfg->an_fast_listen_decay, 1);
768	printf("\nAP/ad-hoc Beacon period:\t\t");
769	an_printwords(&cfg->an_beacon_period, 1);
770	printf("\nAP/ad-hoc ATIM duration:\t\t");
771	an_printwords(&cfg->an_atim_duration, 1);
772	printf("\nAP/ad-hoc current channel:\t\t");
773	an_printwords(&cfg->an_ds_channel, 1);
774	printf("\nAP/ad-hoc DTIM period:\t\t\t");
775	an_printwords(&cfg->an_dtim_period, 1);
776	printf("\nRadio type:\t\t\t\t[ ");
777	if (cfg->an_radiotype & AN_RADIOTYPE_80211_FH)
778		printf("802.11 FH");
779	else if (cfg->an_radiotype & AN_RADIOTYPE_80211_DS)
780		printf("802.11 DS");
781	else if (cfg->an_radiotype & AN_RADIOTYPE_LM2000_DS)
782		printf("LM2000 DS");
783	else
784		printf("unknown (%x)", cfg->an_radiotype);
785	printf(" ]");
786	printf("\nRX Diversity:\t\t\t\t[ ");
787	diversity = cfg->an_diversity & 0xFF;
788	if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
789		printf("antenna 1 only");
790	else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
791		printf("antenna 2 only");
792	else if (diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
793		printf("antenna 1 and 2");
794	printf(" ]");
795	printf("\nTX Diversity:\t\t\t\t[ ");
796	diversity = (cfg->an_diversity >> 8) & 0xFF;
797	if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
798		printf("antenna 1 only");
799	else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
800		printf("antenna 2 only");
801	else if (diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
802		printf("antenna 1 and 2");
803	printf(" ]");
804	printf("\nTransmit power level:\t\t\t");
805	an_printwords(&cfg->an_tx_power, 1);
806	printf("\nRSS threshold:\t\t\t\t");
807	an_printwords(&cfg->an_rss_thresh, 1);
808	printf("\nNode name:\t\t\t\t");
809	an_printstr((char *)&cfg->an_nodename, 16);
810	printf("\nARL threshold:\t\t\t\t");
811	an_printwords(&cfg->an_arl_thresh, 1);
812	printf("\nARL decay:\t\t\t\t");
813	an_printwords(&cfg->an_arl_decay, 1);
814	printf("\nARL delay:\t\t\t\t");
815	an_printwords(&cfg->an_arl_delay, 1);
816	printf("\nConfiguration:\t\t\t\t[ ");
817	if (cfg->an_home_product & AN_HOME_NETWORK)
818		printf("Home Configuration");
819	else
820		printf("Enterprise Configuration");
821	printf(" ]");
822
823	printf("\n");
824	printf("\n");
825	an_readkeyinfo(iface);
826
827	return;
828}
829
830
831static void usage(p)
832	char			*p;
833{
834	fprintf(stderr, "usage:  %s -i iface -A (show specified APs)\n", p);
835	fprintf(stderr, "\t%s -i iface -N (show specified SSIDss)\n", p);
836	fprintf(stderr, "\t%s -i iface -S (show NIC status)\n", p);
837	fprintf(stderr, "\t%s -i iface -I (show NIC capabilities)\n", p);
838	fprintf(stderr, "\t%s -i iface -T (show stats counters)\n", p);
839	fprintf(stderr, "\t%s -i iface -C (show current config)\n", p);
840	fprintf(stderr, "\t%s -i iface -t 0-4 (set TX speed)\n", p);
841	fprintf(stderr, "\t%s -i iface -s 0-3 (set power save mode)\n", p);
842	fprintf(stderr, "\t%s -i iface [-v 1-4] -a AP (specify AP)\n", p);
843	fprintf(stderr, "\t%s -i iface -b val (set beacon period)\n", p);
844	fprintf(stderr, "\t%s -i iface [-v 0|1] -d val (set diversity)\n", p);
845	fprintf(stderr, "\t%s -i iface -j val (set netjoin timeout)\n", p);
846	fprintf(stderr, "\t%s -i iface -e 0-4 (enable transmit key)\n", p);
847	fprintf(stderr, "\t%s -i iface [-v 0-8] -k key (set key)\n", p);
848	fprintf(stderr, "\t%s -i iface -K 0-2 (no auth/open/shared secret)\n", p);
849	fprintf(stderr, "\t%s -i iface -W 0-2 (no WEP/full WEP/mixed cell)\n", p);
850	fprintf(stderr, "\t%s -i iface -l val (set station name)\n", p);
851	fprintf(stderr, "\t%s -i iface -m val (set MAC address)\n", p);
852	fprintf(stderr, "\t%s -i iface [-v 1-3] -n SSID "
853	    "(specify SSID)\n", p);
854	fprintf(stderr, "\t%s -i iface -o 0|1 (set operating mode)\n", p);
855	fprintf(stderr, "\t%s -i iface -c val (set ad-hoc channel)\n", p);
856	fprintf(stderr, "\t%s -i iface -f val (set frag threshold)\n", p);
857	fprintf(stderr, "\t%s -i iface -r val (set RTS threshold)\n", p);
858	fprintf(stderr, "\t%s -i iface -M 0-15 (set monitor mode)\n", p);
859	fprintf(stderr, "\t%s -i iface -L user (enter LEAP authentication mode)\n", p);
860#ifdef ANCACHE
861	fprintf(stderr, "\t%s -i iface -Q print signal quality cache\n", p);
862	fprintf(stderr, "\t%s -i iface -Z zero out signal cache\n", p);
863#endif
864
865	fprintf(stderr, "\t%s -h (display this message)\n", p);
866
867
868	exit(1);
869}
870
871static void an_setconfig(iface, act, arg)
872	const char		*iface;
873	int			act;
874	void			*arg;
875{
876	struct an_ltv_genconfig	*cfg;
877	struct an_ltv_caps	*caps;
878	struct an_req		areq;
879	struct an_req		areq_caps;
880	u_int16_t		diversity = 0;
881	struct ether_addr	*addr;
882	int			i;
883
884	areq.an_len = sizeof(areq);
885	areq.an_type = AN_RID_GENCONFIG;
886	an_getval(iface, &areq);
887	cfg = (struct an_ltv_genconfig *)&areq;
888
889	areq_caps.an_len = sizeof(areq);
890	areq_caps.an_type = AN_RID_CAPABILITIES;
891	an_getval(iface, &areq_caps);
892	caps = (struct an_ltv_caps *)&areq_caps;
893
894	switch(act) {
895	case ACT_SET_OPMODE:
896		cfg->an_opmode = atoi(arg);
897		break;
898	case ACT_SET_FREQ:
899		cfg->an_ds_channel = atoi(arg);
900		break;
901	case ACT_SET_PWRSAVE:
902		cfg->an_psave_mode = atoi(arg);
903		break;
904	case ACT_SET_SCANMODE:
905		cfg->an_scanmode = atoi(arg);
906		break;
907	case ACT_SET_DIVERSITY_RX:
908	case ACT_SET_DIVERSITY_TX:
909		switch(atoi(arg)) {
910		case 0:
911			diversity = AN_DIVERSITY_FACTORY_DEFAULT;
912			break;
913		case 1:
914			diversity = AN_DIVERSITY_ANTENNA_1_ONLY;
915			break;
916		case 2:
917			diversity = AN_DIVERSITY_ANTENNA_2_ONLY;
918			break;
919		case 3:
920			diversity = AN_DIVERSITY_ANTENNA_1_AND_2;
921			break;
922		default:
923			errx(1, "bad diversity setting: %d", diversity);
924			break;
925		}
926		if (atoi(arg) == ACT_SET_DIVERSITY_RX) {
927			cfg->an_diversity &= 0x00FF;
928			cfg->an_diversity |= (diversity << 8);
929		} else {
930			cfg->an_diversity &= 0xFF00;
931			cfg->an_diversity |= diversity;
932		}
933		break;
934	case ACT_SET_TXPWR:
935		for (i = 0; i < 8; i++) {
936			if (caps->an_tx_powerlevels[i] == atoi(arg))
937				break;
938		}
939		if (i == 8)
940			errx(1, "unsupported power level: %dmW", atoi(arg));
941
942		cfg->an_tx_power = atoi(arg);
943		break;
944	case ACT_SET_RTS_THRESH:
945		cfg->an_rtsthresh = atoi(arg);
946		break;
947	case ACT_SET_RTS_RETRYLIM:
948		cfg->an_shortretry_limit =
949		   cfg->an_longretry_limit = atoi(arg);
950		break;
951	case ACT_SET_BEACON_PERIOD:
952		cfg->an_beacon_period = atoi(arg);
953		break;
954	case ACT_SET_WAKE_DURATION:
955		cfg->an_atim_duration = atoi(arg);
956		break;
957	case ACT_SET_FRAG_THRESH:
958		cfg->an_fragthresh = atoi(arg);
959		break;
960	case ACT_SET_NETJOIN:
961		cfg->an_ibss_join_net_timeout = atoi(arg);
962		break;
963	case ACT_SET_MYNAME:
964		bzero(cfg->an_nodename, 16);
965		strncpy((char *)&cfg->an_nodename, optarg, 16);
966		break;
967	case ACT_SET_MAC:
968		addr = ether_aton((char *)arg);
969
970		if (addr == NULL)
971			errx(1, "badly formatted address");
972		bzero(cfg->an_macaddr, ETHER_ADDR_LEN);
973		bcopy((char *)addr, (char *)&cfg->an_macaddr, ETHER_ADDR_LEN);
974		break;
975	case ACT_ENABLE_WEP:
976		switch (atoi (arg)) {
977		case 0:
978			/* no WEP */
979			cfg->an_authtype &= ~(AN_AUTHTYPE_PRIVACY_IN_USE
980					| AN_AUTHTYPE_ALLOW_UNENCRYPTED
981					| AN_AUTHTYPE_LEAP);
982			break;
983		case 1:
984			/* full WEP */
985			cfg->an_authtype |= AN_AUTHTYPE_PRIVACY_IN_USE;
986			cfg->an_authtype &= ~AN_AUTHTYPE_ALLOW_UNENCRYPTED;
987			cfg->an_authtype &= ~AN_AUTHTYPE_LEAP;
988			break;
989		case 2:
990			/* mixed cell */
991			cfg->an_authtype = AN_AUTHTYPE_PRIVACY_IN_USE
992					| AN_AUTHTYPE_ALLOW_UNENCRYPTED;
993			break;
994		}
995		break;
996	case ACT_SET_KEY_TYPE:
997		cfg->an_authtype = (cfg->an_authtype & ~AN_AUTHTYPE_MASK)
998		        | atoi(arg);
999		break;
1000	case ACT_SET_MONITOR_MODE:
1001		areq.an_type = AN_RID_MONITOR_MODE;
1002		cfg->an_len = atoi(arg);      /* mode is put in length */
1003		break;
1004	default:
1005		errx(1, "unknown action");
1006		break;
1007	}
1008
1009	an_setval(iface, &areq);
1010	exit(0);
1011}
1012
1013static void an_setspeed(iface, act, arg)
1014	const char		*iface;
1015	int			act __unused;
1016	void			*arg;
1017{
1018	struct an_req		areq;
1019	struct an_ltv_caps	*caps;
1020	u_int16_t		speed;
1021
1022	areq.an_len = sizeof(areq);
1023	areq.an_type = AN_RID_CAPABILITIES;
1024
1025	an_getval(iface, &areq);
1026	caps = (struct an_ltv_caps *)&areq;
1027
1028	switch(atoi(arg)) {
1029	case 0:
1030		speed = 0;
1031		break;
1032	case 1:
1033		speed = AN_RATE_1MBPS;
1034		break;
1035	case 2:
1036		speed = AN_RATE_2MBPS;
1037		break;
1038	case 3:
1039		if (caps->an_rates[2] != AN_RATE_5_5MBPS)
1040			errx(1, "5.5Mbps not supported on this card");
1041		speed = AN_RATE_5_5MBPS;
1042		break;
1043	case 4:
1044		if (caps->an_rates[3] != AN_RATE_11MBPS)
1045			errx(1, "11Mbps not supported on this card");
1046		speed = AN_RATE_11MBPS;
1047		break;
1048	default:
1049		errx(1, "unsupported speed");
1050		break;
1051	}
1052
1053	areq.an_len = 6;
1054	areq.an_type = AN_RID_TX_SPEED;
1055	areq.an_val[0] = speed;
1056
1057	an_setval(iface, &areq);
1058	exit(0);
1059}
1060
1061static void an_setap(iface, act, arg)
1062	const char		*iface;
1063	int			act;
1064	void			*arg;
1065{
1066	struct an_ltv_aplist	*ap;
1067	struct an_req		areq;
1068	struct ether_addr	*addr;
1069
1070	areq.an_len = sizeof(areq);
1071	areq.an_type = AN_RID_APLIST;
1072
1073	an_getval(iface, &areq);
1074	ap = (struct an_ltv_aplist *)&areq;
1075
1076	addr = ether_aton((char *)arg);
1077
1078	if (addr == NULL)
1079		errx(1, "badly formatted address");
1080
1081	switch(act) {
1082	case ACT_SET_AP1:
1083		bzero(ap->an_ap1, ETHER_ADDR_LEN);
1084		bcopy((char *)addr, (char *)&ap->an_ap1, ETHER_ADDR_LEN);
1085		break;
1086	case ACT_SET_AP2:
1087		bzero(ap->an_ap2, ETHER_ADDR_LEN);
1088		bcopy((char *)addr, (char *)&ap->an_ap2, ETHER_ADDR_LEN);
1089		break;
1090	case ACT_SET_AP3:
1091		bzero(ap->an_ap3, ETHER_ADDR_LEN);
1092		bcopy((char *)addr, (char *)&ap->an_ap3, ETHER_ADDR_LEN);
1093		break;
1094	case ACT_SET_AP4:
1095		bzero(ap->an_ap4, ETHER_ADDR_LEN);
1096		bcopy((char *)addr, (char *)&ap->an_ap4, ETHER_ADDR_LEN);
1097		break;
1098	default:
1099		errx(1, "unknown action");
1100		break;
1101	}
1102
1103	an_setval(iface, &areq);
1104	exit(0);
1105}
1106
1107static void an_setssid(iface, act, arg)
1108	const char		*iface;
1109	int			act;
1110	void			*arg;
1111{
1112	struct an_ltv_ssidlist	*ssid;
1113	struct an_req		areq;
1114
1115	areq.an_len = sizeof(areq);
1116	areq.an_type = AN_RID_SSIDLIST;
1117
1118	an_getval(iface, &areq);
1119	ssid = (struct an_ltv_ssidlist *)&areq;
1120
1121	switch (act) {
1122	case ACT_SET_SSID1:
1123		bzero(ssid->an_ssid1, sizeof(ssid->an_ssid1));
1124		strlcpy(ssid->an_ssid1, (char *)arg, sizeof(ssid->an_ssid1));
1125		ssid->an_ssid1_len = strlen(ssid->an_ssid1);
1126		break;
1127	case ACT_SET_SSID2:
1128		bzero(ssid->an_ssid2, sizeof(ssid->an_ssid2));
1129		strlcpy(ssid->an_ssid2, (char *)arg, sizeof(ssid->an_ssid2));
1130		ssid->an_ssid2_len = strlen(ssid->an_ssid2);
1131		break;
1132	case ACT_SET_SSID3:
1133		bzero(ssid->an_ssid3, sizeof(ssid->an_ssid3));
1134		strlcpy(ssid->an_ssid3, (char *)arg, sizeof(ssid->an_ssid3));
1135		ssid->an_ssid3_len = strlen(ssid->an_ssid3);
1136		break;
1137	default:
1138		errx(1, "unknown action");
1139		break;
1140	}
1141
1142	an_setval(iface, &areq);
1143	exit(0);
1144}
1145
1146#ifdef ANCACHE
1147static void an_zerocache(iface)
1148	const char		*iface;
1149{
1150	struct an_req		areq;
1151
1152	bzero((char *)&areq, sizeof(areq));
1153	areq.an_len = 0;
1154	areq.an_type = AN_RID_ZERO_CACHE;
1155
1156	an_getval(iface, &areq);
1157
1158	return;
1159}
1160
1161static void an_readcache(iface)
1162	const char		*iface;
1163{
1164	struct an_req		areq;
1165	int 			*an_sigitems;
1166	struct an_sigcache 	*sc;
1167	char *			pt;
1168	int 			i;
1169
1170	if (iface == NULL)
1171		errx(1, "must specify interface name");
1172
1173	bzero((char *)&areq, sizeof(areq));
1174	areq.an_len = AN_MAX_DATALEN;
1175	areq.an_type = AN_RID_READ_CACHE;
1176
1177	an_getval(iface, &areq);
1178
1179	an_sigitems = (int *) &areq.an_val;
1180	pt = ((char *) &areq.an_val);
1181	pt += sizeof(int);
1182	sc = (struct an_sigcache *) pt;
1183
1184	for (i = 0; i < *an_sigitems; i++) {
1185		printf("[%d/%d]:", i+1, *an_sigitems);
1186		printf(" %02x:%02x:%02x:%02x:%02x:%02x,",
1187		  		    	sc->macsrc[0]&0xff,
1188		  		    	sc->macsrc[1]&0xff,
1189		   		    	sc->macsrc[2]&0xff,
1190		   			sc->macsrc[3]&0xff,
1191		   			sc->macsrc[4]&0xff,
1192		   			sc->macsrc[5]&0xff);
1193        	printf(" %d.%d.%d.%d,",((sc->ipsrc >> 0) & 0xff),
1194				        ((sc->ipsrc >> 8) & 0xff),
1195				        ((sc->ipsrc >> 16) & 0xff),
1196				        ((sc->ipsrc >> 24) & 0xff));
1197		printf(" sig: %d, noise: %d, qual: %d\n",
1198		   			sc->signal,
1199		   			sc->noise,
1200		   			sc->quality);
1201		sc++;
1202	}
1203
1204	return;
1205}
1206#endif
1207
1208static int an_hex2int(c)
1209	char			c;
1210{
1211	if (c >= '0' && c <= '9')
1212		return (c - '0');
1213	if (c >= 'A' && c <= 'F')
1214		return (c - 'A' + 10);
1215	if (c >= 'a' && c <= 'f')
1216		return (c - 'a' + 10);
1217
1218	return (0);
1219}
1220
1221static void an_str2key(s, k)
1222	char			*s;
1223	struct an_ltv_key	*k;
1224{
1225	int			n, i;
1226	char			*p;
1227
1228	/* Is this a hex string? */
1229	if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
1230		/* Yes, convert to int. */
1231		n = 0;
1232		p = (char *)&k->key[0];
1233		for (i = 2; s[i] != '\0' && s[i + 1] != '\0'; i+= 2) {
1234			*p++ = (an_hex2int(s[i]) << 4) + an_hex2int(s[i + 1]);
1235			n++;
1236		}
1237		if (s[i] != '\0')
1238			errx(1, "hex strings must be of even length");
1239		k->klen = n;
1240	} else {
1241		/* No, just copy it in. */
1242		bcopy(s, k->key, strlen(s));
1243		k->klen = strlen(s);
1244	}
1245
1246	return;
1247}
1248
1249static void an_setkeys(iface, key, keytype)
1250	const char		*iface;
1251	char			*key;
1252	int			keytype;
1253{
1254	struct an_req		areq;
1255	struct an_ltv_key	*k;
1256
1257	bzero((char *)&areq, sizeof(areq));
1258	k = (struct an_ltv_key *)&areq;
1259
1260	if (strlen(key) > 28) {
1261		err(1, "encryption key must be no "
1262		    "more than 18 characters long");
1263	}
1264
1265	an_str2key(key, k);
1266
1267	k->kindex=keytype/2;
1268
1269	if (!(k->klen==0 || k->klen==5 || k->klen==13)) {
1270		err(1, "encryption key must be 0, 5 or 13 bytes long");
1271	}
1272
1273	/* default mac and only valid one (from manual) 1.0.0.0.0.0 */
1274	k->mac[0]=1;
1275	k->mac[1]=0;
1276	k->mac[2]=0;
1277	k->mac[3]=0;
1278	k->mac[4]=0;
1279	k->mac[5]=0;
1280
1281	switch(keytype & 1) {
1282	case 0:
1283	  areq.an_len = sizeof(struct an_ltv_key);
1284	  areq.an_type = AN_RID_WEP_PERM;
1285	  an_setval(iface, &areq);
1286	  break;
1287	case 1:
1288	  areq.an_len = sizeof(struct an_ltv_key);
1289	  areq.an_type = AN_RID_WEP_TEMP;
1290	  an_setval(iface, &areq);
1291	  break;
1292	}
1293
1294	return;
1295}
1296
1297static void an_readkeyinfo(iface)
1298	const char		*iface;
1299{
1300	struct an_req		areq;
1301	struct an_ltv_genconfig	*cfg;
1302	struct an_ltv_key	*k;
1303	int i;
1304	int home;
1305
1306	areq.an_len = sizeof(areq);
1307	areq.an_type = AN_RID_ACTUALCFG;
1308	an_getval(iface, &areq);
1309	cfg = (struct an_ltv_genconfig *)&areq;
1310	if (cfg->an_home_product & AN_HOME_NETWORK)
1311		home = 1;
1312	else
1313		home = 0;
1314
1315	bzero((char *)&areq, sizeof(areq));
1316	k = (struct an_ltv_key *)&areq;
1317
1318	printf("WEP Key status:\n");
1319	areq.an_type = AN_RID_WEP_TEMP;  	/* read first key */
1320	for(i=0; i<5; i++) {
1321		areq.an_len = sizeof(struct an_ltv_key);
1322		an_getval(iface, &areq);
1323       		if (k->kindex == 0xffff)
1324			break;
1325		switch (k->klen) {
1326		case 0:
1327			printf("\tKey %d is unset\n",k->kindex);
1328			break;
1329		case 5:
1330			printf("\tKey %d is set  40 bits\n",k->kindex);
1331			break;
1332		case 13:
1333			printf("\tKey %d is set 128 bits\n",k->kindex);
1334			break;
1335		default:
1336			printf("\tWEP Key %d has an unknown size %d\n",
1337			    i, k->klen);
1338		}
1339
1340		areq.an_type = AN_RID_WEP_PERM;	/* read next key */
1341	}
1342	k->kindex = 0xffff;
1343	areq.an_len = sizeof(struct an_ltv_key);
1344      	an_getval(iface, &areq);
1345	printf("\tThe active transmit key is %d\n", 4 * home + k->mac[0]);
1346
1347	return;
1348}
1349
1350static void an_enable_tx_key(iface, arg)
1351	const char		*iface;
1352	char			*arg;
1353{
1354	struct an_req		areq;
1355	struct an_ltv_key	*k;
1356	struct an_ltv_genconfig *config;
1357
1358	bzero((char *)&areq, sizeof(areq));
1359
1360	/* set home or not home mode */
1361	areq.an_len  = sizeof(struct an_ltv_genconfig);
1362	areq.an_type = AN_RID_GENCONFIG;
1363	an_getval(iface, &areq);
1364	config = (struct an_ltv_genconfig *)&areq;
1365	if (atoi(arg) == 4) {
1366		config->an_home_product |= AN_HOME_NETWORK;
1367	}else{
1368		config->an_home_product &= ~AN_HOME_NETWORK;
1369	}
1370	an_setval(iface, &areq);
1371
1372	bzero((char *)&areq, sizeof(areq));
1373
1374	k = (struct an_ltv_key *)&areq;
1375
1376	/* From a Cisco engineer write the transmit key to use in the
1377	   first MAC, index is FFFF*/
1378	k->kindex=0xffff;
1379	k->klen=0;
1380
1381	k->mac[0]=atoi(arg);
1382	k->mac[1]=0;
1383	k->mac[2]=0;
1384	k->mac[3]=0;
1385	k->mac[4]=0;
1386	k->mac[5]=0;
1387
1388	areq.an_len = sizeof(struct an_ltv_key);
1389	areq.an_type = AN_RID_WEP_PERM;
1390	an_setval(iface, &areq);
1391
1392	return;
1393}
1394
1395static void an_enable_leap_mode(iface, username)
1396	const char		*iface;
1397	char			*username;
1398{
1399	struct an_req		areq;
1400	struct an_ltv_status	*sts;
1401	struct an_ltv_genconfig	*cfg;
1402	struct an_ltv_caps	*caps;
1403	struct an_ltv_leap_username an_username;
1404	struct an_ltv_leap_password an_password;
1405	char *password;
1406	MD4_CTX context;
1407	int len;
1408	int i;
1409	char unicode_password[LEAP_PASSWORD_MAX * 2];
1410
1411	areq.an_len = sizeof(areq);
1412	areq.an_type = AN_RID_CAPABILITIES;
1413
1414	an_getval(iface, &areq);
1415
1416	caps = (struct an_ltv_caps *)&areq;
1417
1418	if (!caps->an_softcaps & AN_AUTHTYPE_LEAP) {
1419		fprintf(stderr, "Firmware does not support LEAP\n");
1420		exit(1);
1421	}
1422
1423	bzero(&an_username, sizeof(an_username));
1424	bzero(&an_password, sizeof(an_password));
1425
1426	len = strlen(username);
1427	if (len > LEAP_USERNAME_MAX) {
1428		printf("Username too long (max %d)\n", LEAP_USERNAME_MAX);
1429		exit(1);
1430	}
1431	strncpy(an_username.an_username, username, len);
1432	an_username.an_username_len = len;
1433	an_username.an_len  = sizeof(an_username);
1434	an_username.an_type = AN_RID_LEAPUSERNAME;
1435
1436	password = getpass("Enter LEAP password:");
1437
1438	len = strlen(password);
1439	if (len > LEAP_PASSWORD_MAX) {
1440		printf("Password too long (max %d)\n", LEAP_PASSWORD_MAX);
1441		exit(1);
1442	}
1443
1444	bzero(&unicode_password, sizeof(unicode_password));
1445	for(i = 0; i < len; i++) {
1446		unicode_password[i * 2] = *password++;
1447	}
1448
1449	/* First half */
1450	MD4Init(&context);
1451	MD4Update(&context, unicode_password, len * 2);
1452	MD4Final(&an_password.an_password[0], &context);
1453
1454	/* Second half */
1455	MD4Init (&context);
1456	MD4Update (&context, &an_password.an_password[0], 16);
1457	MD4Final (&an_password.an_password[16], &context);
1458
1459	an_password.an_password_len = 32;
1460	an_password.an_len  = sizeof(an_password);
1461	an_password.an_type = AN_RID_LEAPPASSWORD;
1462
1463	an_setval(iface, (struct an_req *)&an_username);
1464	an_setval(iface, (struct an_req *)&an_password);
1465
1466	areq.an_len = sizeof(areq);
1467	areq.an_type = AN_RID_GENCONFIG;
1468	an_getval(iface, &areq);
1469	cfg = (struct an_ltv_genconfig *)&areq;
1470	cfg->an_authtype = (AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP);
1471	an_setval(iface, &areq);
1472
1473	sts = (struct an_ltv_status *)&areq;
1474	areq.an_type = AN_RID_STATUS;
1475
1476	for (i = 60; i > 0; i--) {
1477		an_getval(iface, &areq);
1478		if (sts->an_opmode & AN_STATUS_OPMODE_LEAP) {
1479			printf("Authenticated\n");
1480			break;
1481		}
1482		sleep(1);
1483	}
1484
1485	if (i == 0) {
1486		fprintf(stderr, "Failed LEAP authentication\n");
1487		exit(1);
1488	}
1489}
1490
1491int main(argc, argv)
1492	int			argc;
1493	char			*argv[];
1494{
1495	int			ch;
1496	int			act = 0;
1497	const char		*iface = NULL;
1498	int			modifier = 0;
1499	char			*key = NULL;
1500	void			*arg = NULL;
1501	char			*p = argv[0];
1502
1503	/* Get the interface name */
1504	opterr = 0;
1505	ch = getopt(argc, argv, "i:");
1506	if (ch == 'i') {
1507		iface = optarg;
1508	} else {
1509		if (argc > 1 && *argv[1] != '-') {
1510			iface = argv[1];
1511			optind = 2;
1512		} else {
1513			iface = "an0";
1514			optind = 1;
1515		}
1516		optreset = 1;
1517	}
1518	opterr = 1;
1519
1520	while ((ch = getopt(argc, argv,
1521	    "ANISCTht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZM:L:")) != -1) {
1522		switch(ch) {
1523		case 'Z':
1524#ifdef ANCACHE
1525			act = ACT_ZEROCACHE;
1526#else
1527			errx(1, "ANCACHE not available");
1528#endif
1529			break;
1530		case 'Q':
1531#ifdef ANCACHE
1532			act = ACT_DUMPCACHE;
1533#else
1534			errx(1, "ANCACHE not available");
1535#endif
1536			break;
1537		case 'A':
1538			act = ACT_DUMPAP;
1539			break;
1540		case 'N':
1541			act = ACT_DUMPSSID;
1542			break;
1543		case 'S':
1544			act = ACT_DUMPSTATUS;
1545			break;
1546		case 'I':
1547			act = ACT_DUMPCAPS;
1548			break;
1549		case 'T':
1550			act = ACT_DUMPSTATS;
1551			break;
1552		case 'C':
1553			act = ACT_DUMPCONFIG;
1554			break;
1555		case 't':
1556			act = ACT_SET_TXRATE;
1557			arg = optarg;
1558			break;
1559		case 's':
1560			act = ACT_SET_PWRSAVE;
1561			arg = optarg;
1562			break;
1563		case 'p':
1564			act = ACT_SET_TXPWR;
1565			arg = optarg;
1566			break;
1567		case 'v':
1568			modifier = atoi(optarg);
1569			break;
1570		case 'a':
1571			switch(modifier) {
1572			case 0:
1573			case 1:
1574				act = ACT_SET_AP1;
1575				break;
1576			case 2:
1577				act = ACT_SET_AP2;
1578				break;
1579			case 3:
1580				act = ACT_SET_AP3;
1581				break;
1582			case 4:
1583				act = ACT_SET_AP4;
1584				break;
1585			default:
1586				errx(1, "bad modifier %d: there "
1587				    "are only 4 access point settings",
1588				    modifier);
1589				usage(p);
1590				break;
1591			}
1592			arg = optarg;
1593			break;
1594		case 'b':
1595			act = ACT_SET_BEACON_PERIOD;
1596			arg = optarg;
1597			break;
1598		case 'd':
1599			switch(modifier) {
1600			case 0:
1601				act = ACT_SET_DIVERSITY_RX;
1602				break;
1603			case 1:
1604				act = ACT_SET_DIVERSITY_TX;
1605				break;
1606			default:
1607				errx(1, "must specift RX or TX diversity");
1608				break;
1609			}
1610			arg = optarg;
1611			break;
1612		case 'j':
1613			act = ACT_SET_NETJOIN;
1614			arg = optarg;
1615			break;
1616		case 'l':
1617			act = ACT_SET_MYNAME;
1618			arg = optarg;
1619			break;
1620		case 'm':
1621			act = ACT_SET_MAC;
1622			arg = optarg;
1623			break;
1624		case 'n':
1625			switch(modifier) {
1626			case 0:
1627			case 1:
1628				act = ACT_SET_SSID1;
1629				break;
1630			case 2:
1631				act = ACT_SET_SSID2;
1632				break;
1633			case 3:
1634				act = ACT_SET_SSID3;
1635				break;
1636			default:
1637				errx(1, "bad modifier %d: there"
1638				    "are only 3 SSID settings", modifier);
1639				usage(p);
1640				break;
1641			}
1642			arg = optarg;
1643			break;
1644		case 'o':
1645			act = ACT_SET_OPMODE;
1646			arg = optarg;
1647			break;
1648		case 'c':
1649			act = ACT_SET_FREQ;
1650			arg = optarg;
1651			break;
1652		case 'f':
1653			act = ACT_SET_FRAG_THRESH;
1654			arg = optarg;
1655			break;
1656		case 'W':
1657			act = ACT_ENABLE_WEP;
1658			arg = optarg;
1659			break;
1660		case 'K':
1661			act = ACT_SET_KEY_TYPE;
1662			arg = optarg;
1663			break;
1664		case 'k':
1665			act = ACT_SET_KEYS;
1666			key = optarg;
1667			break;
1668		case 'e':
1669			act = ACT_ENABLE_TX_KEY;
1670			arg = optarg;
1671			break;
1672		case 'q':
1673			act = ACT_SET_RTS_RETRYLIM;
1674			arg = optarg;
1675			break;
1676		case 'r':
1677			act = ACT_SET_RTS_THRESH;
1678			arg = optarg;
1679			break;
1680		case 'w':
1681			act = ACT_SET_WAKE_DURATION;
1682			arg = optarg;
1683			break;
1684		case 'M':
1685			act = ACT_SET_MONITOR_MODE;
1686			arg = optarg;
1687			break;
1688		case 'L':
1689			act = ACT_SET_LEAP_MODE;
1690			arg = optarg;
1691			break;
1692		case 'h':
1693		default:
1694			usage(p);
1695		}
1696	}
1697
1698	if (iface == NULL || (!act && !key))
1699		usage(p);
1700
1701	switch(act) {
1702	case ACT_DUMPSTATUS:
1703		an_dumpstatus(iface);
1704		break;
1705	case ACT_DUMPCAPS:
1706		an_dumpcaps(iface);
1707		break;
1708	case ACT_DUMPSTATS:
1709		an_dumpstats(iface);
1710		break;
1711	case ACT_DUMPCONFIG:
1712		an_dumpconfig(iface);
1713		break;
1714	case ACT_DUMPSSID:
1715		an_dumpssid(iface);
1716		break;
1717	case ACT_DUMPAP:
1718		an_dumpap(iface);
1719		break;
1720	case ACT_SET_SSID1:
1721	case ACT_SET_SSID2:
1722	case ACT_SET_SSID3:
1723		an_setssid(iface, act, arg);
1724		break;
1725	case ACT_SET_AP1:
1726	case ACT_SET_AP2:
1727	case ACT_SET_AP3:
1728	case ACT_SET_AP4:
1729		an_setap(iface, act, arg);
1730		break;
1731	case ACT_SET_TXRATE:
1732		an_setspeed(iface, act, arg);
1733		break;
1734#ifdef ANCACHE
1735	case ACT_ZEROCACHE:
1736		an_zerocache(iface);
1737		break;
1738	case ACT_DUMPCACHE:
1739		an_readcache(iface);
1740		break;
1741
1742#endif
1743	case ACT_SET_KEYS:
1744		an_setkeys(iface, key, modifier);
1745		break;
1746	case ACT_ENABLE_TX_KEY:
1747		an_enable_tx_key(iface, arg);
1748		break;
1749	case ACT_SET_LEAP_MODE:
1750		an_enable_leap_mode(iface, arg);
1751		break;
1752	default:
1753		an_setconfig(iface, act, arg);
1754		break;
1755	}
1756
1757	exit(0);
1758}
1759
1760