Merge branch 'vendor/OPENSSH'
[dragonfly.git] / usr.sbin / ancontrol / ancontrol.c
1 /*
2  * Copyright 1997, 1998, 1999
3  *      Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * @(#) Copyright (c) 1997, 1998, 1999 Bill Paul. All rights reserved.
33  * $FreeBSD: src/usr.sbin/ancontrol/ancontrol.c,v 1.1.2.9 2003/02/01 03:25:13 ambrisko Exp $
34  */
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/ioctl.h>
40
41 #include <net/if.h>
42 #include <net/if_var.h>
43 #include <net/ethernet.h>
44
45 #include <dev/netif/an/if_aironet_ieee.h>
46
47 #include <stdio.h>
48 #include <string.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #include <err.h>
53 #include <md4.h>
54 #include <ctype.h>
55
56 static int an_getval    (const char *, struct an_req *);
57 static void an_setval   (const char *, struct an_req *);
58 static void an_printwords(u_int16_t *, int);
59 static void an_printspeeds(u_int8_t*, int);
60 static void an_printbool(int);
61 static void an_printhex (char *, int);
62 static void an_printstr (char *, int);
63 static void an_dumpstatus(const char *);
64 static void an_dumpstats(const char *);
65 static void an_dumpconfig(const char *);
66 static void an_dumpcaps (const char *);
67 static void an_dumpssid (const char *);
68 static void an_dumpap   (const char *);
69 static void an_setconfig(const char *, int, void *);
70 static void an_setssid  (const char *, int, void *);
71 static void an_setap    (const char *, int, void *);
72 static void an_setspeed (const char *, int, void *);
73 static void an_readkeyinfo(const char *);
74 #ifdef ANCACHE
75 static void an_zerocache(const char *);
76 static void an_readcache(const char *);
77 #endif
78 static int an_hex2int   (char);
79 static void an_str2key  (char *, struct an_ltv_key *);
80 static void an_setkeys  (const char *, char *, int);
81 static void an_enable_tx_key(const char *, char *);
82 static void an_enable_leap_mode(const char *, char *);
83 static void usage       (char *);
84 static void             an_dumprssimap(const char *);
85
86 #define ACT_DUMPSTATS 1
87 #define ACT_DUMPCONFIG 2
88 #define ACT_DUMPSTATUS 3
89 #define ACT_DUMPCAPS 4
90 #define ACT_DUMPSSID 5
91 #define ACT_DUMPAP 6
92
93 #define ACT_SET_OPMODE 7
94 #define ACT_SET_SSID1 8
95 #define ACT_SET_SSID2 9
96 #define ACT_SET_SSID3 10
97 #define ACT_SET_FREQ 11
98 #define ACT_SET_AP1 12
99 #define ACT_SET_AP2 13
100 #define ACT_SET_AP3 14
101 #define ACT_SET_AP4 15
102 #define ACT_SET_DRIVERNAME 16
103 #define ACT_SET_SCANMODE 17
104 #define ACT_SET_TXRATE 18
105 #define ACT_SET_RTS_THRESH 19
106 #define ACT_SET_PWRSAVE 20
107 #define ACT_SET_DIVERSITY_RX 21
108 #define ACT_SET_DIVERSITY_TX 22
109 #define ACT_SET_RTS_RETRYLIM 23
110 #define ACT_SET_WAKE_DURATION 24
111 #define ACT_SET_BEACON_PERIOD 25
112 #define ACT_SET_TXPWR 26
113 #define ACT_SET_FRAG_THRESH 27
114 #define ACT_SET_NETJOIN 28
115 #define ACT_SET_MYNAME 29
116 #define ACT_SET_MAC 30
117
118 #define ACT_DUMPCACHE 31
119 #define ACT_ZEROCACHE 32
120
121 #define ACT_ENABLE_WEP 33
122 #define ACT_SET_KEY_TYPE 34
123 #define ACT_SET_KEYS 35
124 #define ACT_ENABLE_TX_KEY 36
125 #define ACT_SET_MONITOR_MODE 37
126 #define ACT_SET_LEAP_MODE 38
127
128 #define ACT_DUMPRSSIMAP 39
129
130 static int
131 an_getval(const char *iface, struct an_req *areq)
132 {
133         struct ifreq            ifr;
134         int                     s, okay = 1;
135
136         bzero((char *)&ifr, sizeof(ifr));
137
138         strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
139         ifr.ifr_data = (caddr_t)areq;
140
141         s = socket(AF_INET, SOCK_DGRAM, 0);
142
143         if (s == -1)
144                 err(1, "socket");
145
146         if (ioctl(s, SIOCGAIRONET, &ifr) == -1) {
147                 okay = 0;
148                 err(1, "SIOCGAIRONET");
149         }
150
151         close(s);
152
153         return okay;
154 }
155
156 static void
157 an_setval(const char *iface, struct an_req *areq)
158 {
159         struct ifreq            ifr;
160         int                     s;
161
162         bzero((char *)&ifr, sizeof(ifr));
163
164         strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
165         ifr.ifr_data = (caddr_t)areq;
166
167         s = socket(AF_INET, SOCK_DGRAM, 0);
168
169         if (s == -1)
170                 err(1, "socket");
171
172         if (ioctl(s, SIOCSAIRONET, &ifr) == -1)
173                 err(1, "SIOCSAIRONET");
174
175         close(s);
176
177         return;
178 }
179
180 static void
181 an_printstr(char *str, int len)
182 {
183         int                     i;
184
185         for (i = 0; i < len - 1; i++) {
186                 if (str[i] == '\0')
187                         str[i] = ' ';
188         }
189
190         printf("[ %.*s ]", len, str);
191
192         return;
193 }
194
195 static void
196 an_printwords(u_int16_t *w, int len)
197 {
198         int                     i;
199
200         printf("[ ");
201         for (i = 0; i < len; i++)
202                 printf("%d ", w[i]);
203         printf("]");
204
205         return;
206 }
207
208 static void
209 an_printspeeds(u_int8_t *w, int len)
210 {
211         int                     i;
212
213         printf("[ ");
214         for (i = 0; i < len && w[i]; i++)
215                 printf("%2.1fMbps ", w[i] * 0.500);
216         printf("]");
217
218         return;
219 }
220
221 static void
222 an_printbool(int val)
223 {
224         if (val)
225                 printf("[ On ]");
226         else
227                 printf("[ Off ]");
228
229         return;
230 }
231
232 static void
233 an_printhex(char *ptr, int len)
234 {
235         int                     i;
236
237         printf("[ ");
238         for (i = 0; i < len; i++) {
239                 printf("%02x", ptr[i] & 0xFF);
240                 if (i < (len - 1))
241                         printf(":");
242         }
243
244         printf(" ]");
245         return;
246 }
247
248 static void
249 an_dumpstatus(const char *iface)
250 {
251         struct an_ltv_status    *sts;
252         struct an_req           areq;
253         struct an_ltv_rssi_map  an_rssimap;
254         int rssimap_valid = 0;
255
256         /*
257          * Try to get RSSI to percent and dBM table
258          */
259
260         an_rssimap.an_len = sizeof(an_rssimap);
261         an_rssimap.an_type = AN_RID_RSSI_MAP;
262         rssimap_valid = an_getval(iface, (struct an_req*)&an_rssimap);  
263
264         if (rssimap_valid)
265                 printf("RSSI table:\t\t[ present ]\n");
266         else
267                 printf("RSSI table:\t\t[ not available ]\n");
268
269         areq.an_len = sizeof(areq);
270         areq.an_type = AN_RID_STATUS;
271
272         an_getval(iface, &areq);
273
274         sts = (struct an_ltv_status *)&areq;
275
276         printf("MAC address:\t\t");
277         an_printhex((char *)&sts->an_macaddr, ETHER_ADDR_LEN);
278         printf("\nOperating mode:\t\t[ ");
279         if (sts->an_opmode & AN_STATUS_OPMODE_CONFIGURED)
280                 printf("configured ");
281         if (sts->an_opmode & AN_STATUS_OPMODE_MAC_ENABLED)
282                 printf("MAC ON ");
283         if (sts->an_opmode & AN_STATUS_OPMODE_RX_ENABLED)
284                 printf("RX ON ");
285         if (sts->an_opmode & AN_STATUS_OPMODE_IN_SYNC)
286                 printf("synced ");
287         if (sts->an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
288                 printf("associated ");
289         if (sts->an_opmode & AN_STATUS_OPMODE_LEAP)
290                 printf("LEAP ");
291         if (sts->an_opmode & AN_STATUS_OPMODE_ERROR)
292                 printf("error ");
293         printf("]\n");
294         printf("Error code:\t\t");
295         an_printhex((char *)&sts->an_errcode, 1);
296         if (rssimap_valid)
297                 printf("\nSignal strength:\t[ %d%% ]",
298                     an_rssimap.an_entries[
299                         sts->an_normalized_strength].an_rss_pct);
300         else 
301                 printf("\nSignal strength:\t[ %d%% ]",
302                     sts->an_normalized_strength);
303         printf("\nAverage Noise:\t\t[ %d%% ]",sts->an_avg_noise_prev_min_pc);
304         if (rssimap_valid)
305                 printf("\nSignal quality:\t\t[ %d%% ]", 
306                     an_rssimap.an_entries[
307                         sts->an_cur_signal_quality].an_rss_pct);
308         else 
309                 printf("\nSignal quality:\t\t[ %d ]", 
310                     sts->an_cur_signal_quality);
311         printf("\nMax Noise:\t\t[ %d%% ]",sts->an_max_noise_prev_min_pc);
312         /*
313          * XXX: This uses the old definition of the rate field (units of
314          * 500kbps).  Technically the new definition is that this field
315          * contains arbitrary values, but no devices which need this
316          * support exist and the IEEE seems to intend to use the old
317          * definition until they get something big so we'll keep using
318          * it as well because this will work with new cards with
319          * rate <= 63.5Mbps.
320          */
321         printf("\nCurrent TX rate:\t[ %d%s ]", sts->an_current_tx_rate / 2,
322             (sts->an_current_tx_rate % 2) ? ".5" : "");
323         printf("\nCurrent SSID:\t\t");
324         an_printstr((char *)&sts->an_ssid, sts->an_ssidlen);
325         printf("\nCurrent AP name:\t");
326         an_printstr((char *)&sts->an_ap_name, 16);
327         printf("\nCurrent BSSID:\t\t");
328         an_printhex((char *)&sts->an_cur_bssid, ETHER_ADDR_LEN);
329         printf("\nBeacon period:\t\t");
330         an_printwords(&sts->an_beacon_period, 1);
331         printf("\nDTIM period:\t\t");
332         an_printwords(&sts->an_dtim_period, 1);
333         printf("\nATIM duration:\t\t");
334         an_printwords(&sts->an_atim_duration, 1);
335         printf("\nHOP period:\t\t");
336         an_printwords(&sts->an_hop_period, 1);
337         printf("\nChannel set:\t\t");
338         an_printwords(&sts->an_channel_set, 1);
339         printf("\nCurrent channel:\t");
340         an_printwords(&sts->an_cur_channel, 1);
341         printf("\nHops to backbone:\t");
342         an_printwords(&sts->an_hops_to_backbone, 1);
343         printf("\nTotal AP load:\t\t");
344         an_printwords(&sts->an_ap_total_load, 1);
345         printf("\nOur generated load:\t");
346         an_printwords(&sts->an_our_generated_load, 1);
347         printf("\nAccumulated ARL:\t");
348         an_printwords(&sts->an_accumulated_arl, 1);
349         printf("\n");
350         return;
351 }
352
353 static void
354 an_dumpcaps(const char *iface)
355 {
356         struct an_ltv_caps      *caps;
357         struct an_req           areq;
358         u_int16_t               tmp;
359
360         areq.an_len = sizeof(areq);
361         areq.an_type = AN_RID_CAPABILITIES;
362
363         an_getval(iface, &areq);
364
365         caps = (struct an_ltv_caps *)&areq;
366
367         printf("OUI:\t\t\t");
368         an_printhex((char *)&caps->an_oui, 3);
369         printf("\nProduct number:\t\t");
370         an_printwords(&caps->an_prodnum, 1);
371         printf("\nManufacturer name:\t");
372         an_printstr((char *)&caps->an_manufname, 32);
373         printf("\nProduce name:\t\t");
374         an_printstr((char *)&caps->an_prodname, 16);
375         printf("\nFirmware version:\t");
376         an_printstr((char *)&caps->an_prodvers, 1);
377         printf("\nOEM MAC address:\t");
378         an_printhex((char *)&caps->an_oemaddr, ETHER_ADDR_LEN);
379         printf("\nAironet MAC address:\t");
380         an_printhex((char *)&caps->an_aironetaddr, ETHER_ADDR_LEN);
381         printf("\nRadio type:\t\t[ ");
382         if (caps->an_radiotype & AN_RADIOTYPE_80211_FH)
383                 printf("802.11 FH");
384         else if (caps->an_radiotype & AN_RADIOTYPE_80211_DS)
385                 printf("802.11 DS");
386         else if (caps->an_radiotype & AN_RADIOTYPE_LM2000_DS)
387                 printf("LM2000 DS");
388         else
389                 printf("unknown (%x)", caps->an_radiotype);
390         printf(" ]");
391         printf("\nRegulatory domain:\t");
392         an_printwords(&caps->an_regdomain, 1);
393         printf("\nAssigned CallID:\t");
394         an_printhex((char *)&caps->an_callid, 6);
395         printf("\nSupported speeds:\t");
396         an_printspeeds(caps->an_rates, 8);
397         printf("\nRX Diversity:\t\t[ ");
398         if (caps->an_rx_diversity == AN_DIVERSITY_FACTORY_DEFAULT)
399                 printf("factory default");
400         else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
401                 printf("antenna 1 only");
402         else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
403                 printf("antenna 2 only");
404         else if (caps->an_rx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
405                 printf("antenna 1 and 2");
406         printf(" ]");
407         printf("\nTX Diversity:\t\t[ ");
408         if (caps->an_tx_diversity == AN_DIVERSITY_FACTORY_DEFAULT)
409                 printf("factory default");
410         else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
411                 printf("antenna 1 only");
412         else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
413                 printf("antenna 2 only");
414         else if (caps->an_tx_diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
415                 printf("antenna 1 and 2");
416         printf(" ]");
417         printf("\nSupported power levels:\t");
418         an_printwords(caps->an_tx_powerlevels, 8);
419         printf("\nHardware revision:\t");
420         tmp = ntohs(caps->an_hwrev);
421         an_printhex((char *)&tmp, 2);
422         printf("\nSoftware revision:\t");
423         tmp = ntohs(caps->an_fwrev);
424         an_printhex((char *)&tmp, 2);
425         printf("\nSoftware subrevision:\t");
426         tmp = ntohs(caps->an_fwsubrev);
427         an_printhex((char *)&tmp, 2);
428         printf("\nInterface revision:\t");
429         tmp = ntohs(caps->an_ifacerev);
430         an_printhex((char *)&tmp, 2);
431         printf("\nBootblock revision:\t");
432         tmp = ntohs(caps->an_bootblockrev);
433         an_printhex((char *)&tmp, 2);
434         printf("\n");
435         return;
436 }
437
438 static void
439 an_dumpstats(const char *iface)
440 {
441         struct an_ltv_stats     *stats;
442         struct an_req           areq;
443         caddr_t                 ptr;
444
445         areq.an_len = sizeof(areq);
446         areq.an_type = AN_RID_32BITS_CUM;
447
448         an_getval(iface, &areq);
449
450         ptr = (caddr_t)&areq;
451         ptr -= 2;
452         stats = (struct an_ltv_stats *)ptr;
453
454         printf("RX overruns:\t\t\t\t\t[ %d ]\n", stats->an_rx_overruns);
455         printf("RX PLCP CSUM errors:\t\t\t\t[ %d ]\n",
456             stats->an_rx_plcp_csum_errs);
457         printf("RX PLCP format errors:\t\t\t\t[ %d ]\n",
458             stats->an_rx_plcp_format_errs);
459         printf("RX PLCP length errors:\t\t\t\t[ %d ]\n",
460             stats->an_rx_plcp_len_errs);
461         printf("RX MAC CRC errors:\t\t\t\t[ %d ]\n",
462             stats->an_rx_mac_crc_errs);
463         printf("RX MAC CRC OK:\t\t\t\t\t[ %d ]\n",
464             stats->an_rx_mac_crc_ok);
465         printf("RX WEP errors:\t\t\t\t\t[ %d ]\n",
466             stats->an_rx_wep_errs);
467         printf("RX WEP OK:\t\t\t\t\t[ %d ]\n",
468             stats->an_rx_wep_ok);
469         printf("Long retries:\t\t\t\t\t[ %d ]\n",
470             stats->an_retry_long);
471         printf("Short retries:\t\t\t\t\t[ %d ]\n",
472             stats->an_retry_short);
473         printf("Retries exhausted:\t\t\t\t[ %d ]\n",
474             stats->an_retry_max);
475         printf("Bad ACK:\t\t\t\t\t[ %d ]\n",
476             stats->an_no_ack);
477         printf("Bad CTS:\t\t\t\t\t[ %d ]\n",
478             stats->an_no_cts);
479         printf("RX good ACKs:\t\t\t\t\t[ %d ]\n",
480             stats->an_rx_ack_ok);
481         printf("RX good CTSs:\t\t\t\t\t[ %d ]\n",
482             stats->an_rx_cts_ok);
483         printf("TX good ACKs:\t\t\t\t\t[ %d ]\n",
484             stats->an_tx_ack_ok);
485         printf("TX good RTSs:\t\t\t\t\t[ %d ]\n",
486             stats->an_tx_rts_ok);
487         printf("TX good CTSs:\t\t\t\t\t[ %d ]\n",
488             stats->an_tx_cts_ok);
489         printf("LMAC multicasts transmitted:\t\t\t[ %d ]\n",
490             stats->an_tx_lmac_mcasts);
491         printf("LMAC broadcasts transmitted:\t\t\t[ %d ]\n",
492             stats->an_tx_lmac_bcasts);
493         printf("LMAC unicast frags transmitted:\t\t\t[ %d ]\n",
494             stats->an_tx_lmac_ucast_frags);
495         printf("LMAC unicasts transmitted:\t\t\t[ %d ]\n",
496             stats->an_tx_lmac_ucasts);
497         printf("Beacons transmitted:\t\t\t\t[ %d ]\n",
498             stats->an_tx_beacons);
499         printf("Beacons received:\t\t\t\t[ %d ]\n",
500             stats->an_rx_beacons);
501         printf("Single transmit collisions:\t\t\t[ %d ]\n",
502             stats->an_tx_single_cols);
503         printf("Multiple transmit collisions:\t\t\t[ %d ]\n",
504             stats->an_tx_multi_cols);
505         printf("Transmits without deferrals:\t\t\t[ %d ]\n",
506             stats->an_tx_defers_no);
507         printf("Transmits deferred due to protocol:\t\t[ %d ]\n",
508             stats->an_tx_defers_prot);
509         printf("Transmits deferred due to energy detect:\t\t[ %d ]\n",
510             stats->an_tx_defers_energy);
511         printf("RX duplicate frames/frags:\t\t\t[ %d ]\n",
512             stats->an_rx_dups);
513         printf("RX partial frames:\t\t\t\t[ %d ]\n",
514             stats->an_rx_partial);
515         printf("TX max lifetime exceeded:\t\t\t[ %d ]\n",
516             stats->an_tx_too_old);
517         printf("RX max lifetime exceeded:\t\t\t[ %d ]\n",
518             stats->an_tx_too_old);
519         printf("Sync lost due to too many missed beacons:\t[ %d ]\n",
520             stats->an_lostsync_missed_beacons);
521         printf("Sync lost due to ARL exceeded:\t\t\t[ %d ]\n",
522             stats->an_lostsync_arl_exceeded);
523         printf("Sync lost due to deauthentication:\t\t[ %d ]\n",
524             stats->an_lostsync_deauthed);
525         printf("Sync lost due to disassociation:\t\t[ %d ]\n",
526             stats->an_lostsync_disassociated);
527         printf("Sync lost due to excess change in TSF timing:\t[ %d ]\n",
528             stats->an_lostsync_tsf_timing);
529         printf("Host transmitted multicasts:\t\t\t[ %d ]\n",
530             stats->an_tx_host_mcasts);
531         printf("Host transmitted broadcasts:\t\t\t[ %d ]\n",
532             stats->an_tx_host_bcasts);
533         printf("Host transmitted unicasts:\t\t\t[ %d ]\n",
534             stats->an_tx_host_ucasts);
535         printf("Host transmission failures:\t\t\t[ %d ]\n",
536             stats->an_tx_host_failed);
537         printf("Host received multicasts:\t\t\t[ %d ]\n",
538             stats->an_rx_host_mcasts);
539         printf("Host received broadcasts:\t\t\t[ %d ]\n",
540             stats->an_rx_host_bcasts);
541         printf("Host received unicasts:\t\t\t\t[ %d ]\n",
542             stats->an_rx_host_ucasts);
543         printf("Host receive discards:\t\t\t\t[ %d ]\n",
544             stats->an_rx_host_discarded);
545         printf("HMAC transmitted multicasts:\t\t\t[ %d ]\n",
546             stats->an_tx_hmac_mcasts);
547         printf("HMAC transmitted broadcasts:\t\t\t[ %d ]\n",
548             stats->an_tx_hmac_bcasts);
549         printf("HMAC transmitted unicasts:\t\t\t[ %d ]\n",
550             stats->an_tx_hmac_ucasts);
551         printf("HMAC transmissions failed:\t\t\t[ %d ]\n",
552             stats->an_tx_hmac_failed);
553         printf("HMAC received multicasts:\t\t\t[ %d ]\n",
554             stats->an_rx_hmac_mcasts);
555         printf("HMAC received broadcasts:\t\t\t[ %d ]\n",
556             stats->an_rx_hmac_bcasts);
557         printf("HMAC received unicasts:\t\t\t\t[ %d ]\n",
558             stats->an_rx_hmac_ucasts);
559         printf("HMAC receive discards:\t\t\t\t[ %d ]\n",
560             stats->an_rx_hmac_discarded);
561         printf("HMAC transmits accepted:\t\t\t[ %d ]\n",
562             stats->an_tx_hmac_accepted);
563         printf("SSID mismatches:\t\t\t\t[ %d ]\n",
564             stats->an_ssid_mismatches);
565         printf("Access point mismatches:\t\t\t[ %d ]\n",
566             stats->an_ap_mismatches);
567         printf("Speed mismatches:\t\t\t\t[ %d ]\n",
568             stats->an_rates_mismatches);
569         printf("Authentication rejects:\t\t\t\t[ %d ]\n",
570             stats->an_auth_rejects);
571         printf("Authentication timeouts:\t\t\t[ %d ]\n",
572             stats->an_auth_timeouts);
573         printf("Association rejects:\t\t\t\t[ %d ]\n",
574             stats->an_assoc_rejects);
575         printf("Association timeouts:\t\t\t\t[ %d ]\n",
576             stats->an_assoc_timeouts);
577         printf("Management frames received:\t\t\t[ %d ]\n",
578             stats->an_rx_mgmt_pkts);
579         printf("Management frames transmitted:\t\t\t[ %d ]\n",
580             stats->an_tx_mgmt_pkts);
581         printf("Refresh frames received:\t\t\t[ %d ]\n",
582             stats->an_rx_refresh_pkts),
583         printf("Refresh frames transmitted:\t\t\t[ %d ]\n",
584             stats->an_tx_refresh_pkts),
585         printf("Poll frames received:\t\t\t\t[ %d ]\n",
586             stats->an_rx_poll_pkts);
587         printf("Poll frames transmitted:\t\t\t[ %d ]\n",
588             stats->an_tx_poll_pkts);
589         printf("Host requested sync losses:\t\t\t[ %d ]\n",
590             stats->an_lostsync_hostreq);
591         printf("Host transmitted bytes:\t\t\t\t[ %d ]\n",
592             stats->an_host_tx_bytes);
593         printf("Host received bytes:\t\t\t\t[ %d ]\n",
594             stats->an_host_rx_bytes);
595         printf("Uptime in microseconds:\t\t\t\t[ %d ]\n",
596             stats->an_uptime_usecs);
597         printf("Uptime in seconds:\t\t\t\t[ %d ]\n",
598             stats->an_uptime_secs);
599         printf("Sync lost due to better AP:\t\t\t[ %d ]\n",
600             stats->an_lostsync_better_ap);
601
602         return;
603 }
604
605 static void
606 an_dumpap(const char *iface)
607 {
608         struct an_ltv_aplist    *ap;
609         struct an_req           areq;
610
611         areq.an_len = sizeof(areq);
612         areq.an_type = AN_RID_APLIST;
613
614         an_getval(iface, &areq);
615
616         ap = (struct an_ltv_aplist *)&areq;
617         printf("Access point 1:\t\t\t");
618         an_printhex((char *)&ap->an_ap1, ETHER_ADDR_LEN);
619         printf("\nAccess point 2:\t\t\t");
620         an_printhex((char *)&ap->an_ap2, ETHER_ADDR_LEN);
621         printf("\nAccess point 3:\t\t\t");
622         an_printhex((char *)&ap->an_ap3, ETHER_ADDR_LEN);
623         printf("\nAccess point 4:\t\t\t");
624         an_printhex((char *)&ap->an_ap4, ETHER_ADDR_LEN);
625         printf("\n");
626
627         return;
628 }
629
630 static void
631 an_dumpssid(const char *iface)
632 {
633         struct an_ltv_ssidlist  *ssid;
634         struct an_req           areq;
635
636         areq.an_len = sizeof(areq);
637         areq.an_type = AN_RID_SSIDLIST;
638
639         an_getval(iface, &areq);
640
641         ssid = (struct an_ltv_ssidlist *)&areq;
642         printf("SSID 1:\t\t\t[ %.*s ]\n", ssid->an_ssid1_len, ssid->an_ssid1);
643         printf("SSID 2:\t\t\t[ %.*s ]\n", ssid->an_ssid2_len, ssid->an_ssid2);
644         printf("SSID 3:\t\t\t[ %.*s ]\n", ssid->an_ssid3_len, ssid->an_ssid3);
645
646         return;
647 }
648
649 static void
650 an_dumpconfig(const char *iface)
651 {
652         struct an_ltv_genconfig *cfg;
653         struct an_req           areq;
654         unsigned char           diversity;
655
656         areq.an_len = sizeof(areq);
657         areq.an_type = AN_RID_ACTUALCFG;
658
659         an_getval(iface, &areq);
660
661         cfg = (struct an_ltv_genconfig *)&areq;
662
663         printf("Operating mode:\t\t\t\t[ ");
664         if ((cfg->an_opmode & 0x7) == AN_OPMODE_IBSS_ADHOC)
665                 printf("ad-hoc");
666         if ((cfg->an_opmode & 0x7) == AN_OPMODE_INFRASTRUCTURE_STATION)
667                 printf("infrastructure");
668         if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP)
669                 printf("access point");
670         if ((cfg->an_opmode & 0x7) == AN_OPMODE_AP_REPEATER)
671                 printf("access point repeater");
672         printf(" ]");
673         printf("\nReceive mode:\t\t\t\t[ ");
674         if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_MC_ADDR)
675                 printf("broadcast/multicast/unicast");
676         if ((cfg->an_rxmode & 0x7) == AN_RXMODE_BC_ADDR)
677                 printf("broadcast/unicast");
678         if ((cfg->an_rxmode & 0x7) == AN_RXMODE_ADDR)
679                 printf("unicast");
680         if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_CURBSS)
681                 printf("802.11 monitor, current BSSID");
682         if ((cfg->an_rxmode & 0x7) == AN_RXMODE_80211_MONITOR_ANYBSS)
683                 printf("802.11 monitor, any BSSID");
684         if ((cfg->an_rxmode & 0x7) == AN_RXMODE_LAN_MONITOR_CURBSS)
685                 printf("LAN monitor, current BSSID");
686         printf(" ]");
687         printf("\nFragment threshold:\t\t\t");
688         an_printwords(&cfg->an_fragthresh, 1);
689         printf("\nRTS threshold:\t\t\t\t");
690         an_printwords(&cfg->an_rtsthresh, 1);
691         printf("\nMAC address:\t\t\t\t");
692         an_printhex((char *)&cfg->an_macaddr, ETHER_ADDR_LEN);
693         printf("\nSupported rates:\t\t\t");
694         an_printspeeds(cfg->an_rates, 8);
695         printf("\nShort retry limit:\t\t\t");
696         an_printwords(&cfg->an_shortretry_limit, 1);
697         printf("\nLong retry limit:\t\t\t");
698         an_printwords(&cfg->an_longretry_limit, 1);
699         printf("\nTX MSDU lifetime:\t\t\t");
700         an_printwords(&cfg->an_tx_msdu_lifetime, 1);
701         printf("\nRX MSDU lifetime:\t\t\t");
702         an_printwords(&cfg->an_rx_msdu_lifetime, 1);
703         printf("\nStationary:\t\t\t\t");
704         an_printbool(cfg->an_stationary);
705         printf("\nOrdering:\t\t\t\t");
706         an_printbool(cfg->an_ordering);
707         printf("\nDevice type:\t\t\t\t[ ");
708         if (cfg->an_devtype == AN_DEVTYPE_PC4500)
709                 printf("PC4500");
710         else if (cfg->an_devtype == AN_DEVTYPE_PC4800)
711                 printf("PC4800");
712         else
713                 printf("unknown (%x)", cfg->an_devtype);
714         printf(" ]");
715         printf("\nScanning mode:\t\t\t\t[ ");
716         if (cfg->an_scanmode == AN_SCANMODE_ACTIVE)
717                 printf("active");
718         if (cfg->an_scanmode == AN_SCANMODE_PASSIVE)
719                 printf("passive");
720         if (cfg->an_scanmode == AN_SCANMODE_AIRONET_ACTIVE)
721                 printf("Aironet active");
722         printf(" ]");
723         printf("\nProbe delay:\t\t\t\t");
724         an_printwords(&cfg->an_probedelay, 1);
725         printf("\nProbe energy timeout:\t\t\t");
726         an_printwords(&cfg->an_probe_energy_timeout, 1);
727         printf("\nProbe response timeout:\t\t\t");
728         an_printwords(&cfg->an_probe_response_timeout, 1);
729         printf("\nBeacon listen timeout:\t\t\t");
730         an_printwords(&cfg->an_beacon_listen_timeout, 1);
731         printf("\nIBSS join network timeout:\t\t");
732         an_printwords(&cfg->an_ibss_join_net_timeout, 1);
733         printf("\nAuthentication timeout:\t\t\t");
734         an_printwords(&cfg->an_auth_timeout, 1);
735         printf("\nWEP enabled:\t\t\t\t[ ");
736         if (cfg->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE)
737         {
738                 if (cfg->an_authtype & AN_AUTHTYPE_LEAP)
739                          printf("LEAP");
740                 else if (cfg->an_authtype & AN_AUTHTYPE_ALLOW_UNENCRYPTED)
741                          printf("mixed cell");
742                 else
743                          printf("full");
744         }
745         else
746                 printf("no");
747         printf(" ]");
748         printf("\nAuthentication type:\t\t\t[ ");
749         if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_NONE)
750                 printf("none");
751         if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_OPEN)
752                 printf("open");
753         if ((cfg->an_authtype & AN_AUTHTYPE_MASK) == AN_AUTHTYPE_SHAREDKEY)
754                 printf("shared key");
755         printf(" ]");
756         printf("\nAssociation timeout:\t\t\t");
757         an_printwords(&cfg->an_assoc_timeout, 1);
758         printf("\nSpecified AP association timeout:\t");
759         an_printwords(&cfg->an_specified_ap_timeout, 1);
760         printf("\nOffline scan interval:\t\t\t");
761         an_printwords(&cfg->an_offline_scan_interval, 1);
762         printf("\nOffline scan duration:\t\t\t");
763         an_printwords(&cfg->an_offline_scan_duration, 1);
764         printf("\nLink loss delay:\t\t\t");
765         an_printwords(&cfg->an_link_loss_delay, 1);
766         printf("\nMax beacon loss time:\t\t\t");
767         an_printwords(&cfg->an_max_beacon_lost_time, 1);
768         printf("\nRefresh interval:\t\t\t");
769         an_printwords(&cfg->an_refresh_interval, 1);
770         printf("\nPower save mode:\t\t\t[ ");
771         if (cfg->an_psave_mode == AN_PSAVE_NONE)
772                 printf("none");
773         if (cfg->an_psave_mode == AN_PSAVE_CAM)
774                 printf("constantly awake mode");
775         if (cfg->an_psave_mode == AN_PSAVE_PSP)
776                 printf("PSP");
777         if (cfg->an_psave_mode == AN_PSAVE_PSP_CAM)
778                 printf("PSP-CAM (fast PSP)");
779         printf(" ]");
780         printf("\nSleep through DTIMs:\t\t\t");
781         an_printbool(cfg->an_sleep_for_dtims);
782         printf("\nPower save listen interval:\t\t");
783         an_printwords(&cfg->an_listen_interval, 1);
784         printf("\nPower save fast listen interval:\t");
785         an_printwords(&cfg->an_fast_listen_interval, 1);
786         printf("\nPower save listen decay:\t\t");
787         an_printwords(&cfg->an_listen_decay, 1);
788         printf("\nPower save fast listen decay:\t\t");
789         an_printwords(&cfg->an_fast_listen_decay, 1);
790         printf("\nAP/ad-hoc Beacon period:\t\t");
791         an_printwords(&cfg->an_beacon_period, 1);
792         printf("\nAP/ad-hoc ATIM duration:\t\t");
793         an_printwords(&cfg->an_atim_duration, 1);
794         printf("\nAP/ad-hoc current channel:\t\t");
795         an_printwords(&cfg->an_ds_channel, 1);
796         printf("\nAP/ad-hoc DTIM period:\t\t\t");
797         an_printwords(&cfg->an_dtim_period, 1);
798         printf("\nRadio type:\t\t\t\t[ ");
799         if (cfg->an_radiotype & AN_RADIOTYPE_80211_FH)
800                 printf("802.11 FH");
801         else if (cfg->an_radiotype & AN_RADIOTYPE_80211_DS)
802                 printf("802.11 DS");
803         else if (cfg->an_radiotype & AN_RADIOTYPE_LM2000_DS)
804                 printf("LM2000 DS");
805         else
806                 printf("unknown (%x)", cfg->an_radiotype);
807         printf(" ]");
808         printf("\nRX Diversity:\t\t\t\t[ ");
809         diversity = cfg->an_diversity & 0xFF;
810         if (diversity == AN_DIVERSITY_FACTORY_DEFAULT)
811                 printf("factory default");
812         else if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
813                 printf("antenna 1 only");
814         else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
815                 printf("antenna 2 only");
816         else if (diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
817                 printf("antenna 1 and 2");
818         printf(" ]");
819         printf("\nTX Diversity:\t\t\t\t[ ");
820         diversity = (cfg->an_diversity >> 8) & 0xFF;
821         if (diversity == AN_DIVERSITY_FACTORY_DEFAULT)
822                 printf("factory default");
823         else if (diversity == AN_DIVERSITY_ANTENNA_1_ONLY)
824                 printf("antenna 1 only");
825         else if (diversity == AN_DIVERSITY_ANTENNA_2_ONLY)
826                 printf("antenna 2 only");
827         else if (diversity == AN_DIVERSITY_ANTENNA_1_AND_2)
828                 printf("antenna 1 and 2");
829         printf(" ]");
830         printf("\nTransmit power level:\t\t\t");
831         an_printwords(&cfg->an_tx_power, 1);
832         printf("\nRSS threshold:\t\t\t\t");
833         an_printwords(&cfg->an_rss_thresh, 1);
834         printf("\nNode name:\t\t\t\t");
835         an_printstr((char *)&cfg->an_nodename, 16);
836         printf("\nARL threshold:\t\t\t\t");
837         an_printwords(&cfg->an_arl_thresh, 1);
838         printf("\nARL decay:\t\t\t\t");
839         an_printwords(&cfg->an_arl_decay, 1);
840         printf("\nARL delay:\t\t\t\t");
841         an_printwords(&cfg->an_arl_delay, 1);
842         printf("\nConfiguration:\t\t\t\t[ ");
843         if (cfg->an_home_product & AN_HOME_NETWORK)
844                 printf("Home Configuration");
845         else
846                 printf("Enterprise Configuration");
847         printf(" ]");
848
849         printf("\n");
850         printf("\n");
851         an_readkeyinfo(iface);
852
853         return;
854 }
855
856 static void
857 an_dumprssimap(const char *iface)
858 {
859         struct an_ltv_rssi_map  *rssi;
860         struct an_req           areq;
861         int                     i;
862
863         areq.an_len = sizeof(areq);
864         areq.an_type = AN_RID_RSSI_MAP;
865
866         an_getval(iface, &areq);
867
868         rssi = (struct an_ltv_rssi_map *)&areq;
869
870         printf("idx\tpct\t dBm\n");
871
872         for (i = 0; i < 0xFF; i++) {
873                 /* 
874                  * negate the dBm value: it's the only way the power 
875                  * level makes sense 
876                  */
877                 printf("%3d\t%3d\t%4d\n", i, 
878                         rssi->an_entries[i].an_rss_pct,
879                         - rssi->an_entries[i].an_rss_dbm);
880         }
881
882         return;
883 }
884
885 static void
886 usage(char *p)
887 {
888         fprintf(stderr, "usage:  %s -i iface -A (show specified APs)\n", p);
889         fprintf(stderr, "\t%s -i iface -N (show specified SSIDss)\n", p);
890         fprintf(stderr, "\t%s -i iface -S (show NIC status)\n", p);
891         fprintf(stderr, "\t%s -i iface -I (show NIC capabilities)\n", p);
892         fprintf(stderr, "\t%s -i iface -T (show stats counters)\n", p);
893         fprintf(stderr, "\t%s -i iface -C (show current config)\n", p);
894         fprintf(stderr, "\t%s -i iface -R (show RSSI map)\n", p);
895         fprintf(stderr, "\t%s -i iface -t 0-4 (set TX speed)\n", p);
896         fprintf(stderr, "\t%s -i iface -s 0-3 (set power save mode)\n", p);
897         fprintf(stderr, "\t%s -i iface [-v 1-4] -a AP (specify AP)\n", p);
898         fprintf(stderr, "\t%s -i iface -b val (set beacon period)\n", p);
899         fprintf(stderr, "\t%s -i iface [-v 0|1] -d val (set diversity)\n", p);
900         fprintf(stderr, "\t%s -i iface -j val (set netjoin timeout)\n", p);
901         fprintf(stderr, "\t%s -i iface -e 0-4 (enable transmit key)\n", p);
902         fprintf(stderr, "\t%s -i iface [-v 0-8] -k key (set key)\n", p);
903         fprintf(stderr, "\t%s -i iface -K 0-2 (no auth/open/shared secret)\n", p);
904         fprintf(stderr, "\t%s -i iface -W 0-2 (no WEP/full WEP/mixed cell)\n", p);
905         fprintf(stderr, "\t%s -i iface -l val (set station name)\n", p);
906         fprintf(stderr, "\t%s -i iface -m val (set MAC address)\n", p);
907         fprintf(stderr, "\t%s -i iface [-v 1-3] -n SSID "
908             "(specify SSID)\n", p);
909         fprintf(stderr, "\t%s -i iface -o 0|1 (set operating mode)\n", p);
910         fprintf(stderr, "\t%s -i iface -c val (set ad-hoc channel)\n", p);
911         fprintf(stderr, "\t%s -i iface -f val (set frag threshold)\n", p);
912         fprintf(stderr, "\t%s -i iface -r val (set RTS threshold)\n", p);
913         fprintf(stderr, "\t%s -i iface -M 0-15 (set monitor mode)\n", p);
914         fprintf(stderr, "\t%s -i iface -L user (enter LEAP authentication mode)\n", p);
915 #ifdef ANCACHE
916         fprintf(stderr, "\t%s -i iface -Q print signal quality cache\n", p);
917         fprintf(stderr, "\t%s -i iface -Z zero out signal cache\n", p);
918 #endif
919
920         fprintf(stderr, "\t%s -h (display this message)\n", p);
921
922
923         exit(1);
924 }
925
926 static void
927 an_setconfig(const char *iface, int act, void *arg)
928 {
929         struct an_ltv_genconfig *cfg;
930         struct an_ltv_caps      *caps;
931         struct an_req           areq;
932         struct an_req           areq_caps;
933         u_int16_t               diversity = 0;
934         struct ether_addr       *addr;
935         int                     i;
936
937         areq.an_len = sizeof(areq);
938         areq.an_type = AN_RID_GENCONFIG;
939         an_getval(iface, &areq);
940         cfg = (struct an_ltv_genconfig *)&areq;
941
942         areq_caps.an_len = sizeof(areq);
943         areq_caps.an_type = AN_RID_CAPABILITIES;
944         an_getval(iface, &areq_caps);
945         caps = (struct an_ltv_caps *)&areq_caps;
946
947         switch(act) {
948         case ACT_SET_OPMODE:
949                 cfg->an_opmode = atoi(arg);
950                 break;
951         case ACT_SET_FREQ:
952                 cfg->an_ds_channel = atoi(arg);
953                 break;
954         case ACT_SET_PWRSAVE:
955                 cfg->an_psave_mode = atoi(arg);
956                 break;
957         case ACT_SET_SCANMODE:
958                 cfg->an_scanmode = atoi(arg);
959                 break;
960         case ACT_SET_DIVERSITY_RX:
961         case ACT_SET_DIVERSITY_TX:
962                 switch(atoi(arg)) {
963                 case 0:
964                         diversity = AN_DIVERSITY_FACTORY_DEFAULT;
965                         break;
966                 case 1:
967                         diversity = AN_DIVERSITY_ANTENNA_1_ONLY;
968                         break;
969                 case 2:
970                         diversity = AN_DIVERSITY_ANTENNA_2_ONLY;
971                         break;
972                 case 3:
973                         diversity = AN_DIVERSITY_ANTENNA_1_AND_2;
974                         break;
975                 default:
976                         errx(1, "bad diversity setting: %d", diversity);
977                         break;
978                 }
979                 if (act == ACT_SET_DIVERSITY_RX) {
980                         cfg->an_diversity &= 0xFF00;
981                         cfg->an_diversity |= diversity;
982                 } else {
983                         cfg->an_diversity &= 0x00FF;
984                         cfg->an_diversity |= (diversity << 8);
985                 }
986                 break;
987         case ACT_SET_TXPWR:
988                 for (i = 0; i < 8; i++) {
989                         if (caps->an_tx_powerlevels[i] == atoi(arg))
990                                 break;
991                 }
992                 if (i == 8)
993                         errx(1, "unsupported power level: %dmW", atoi(arg));
994
995                 cfg->an_tx_power = atoi(arg);
996                 break;
997         case ACT_SET_RTS_THRESH:
998                 cfg->an_rtsthresh = atoi(arg);
999                 break;
1000         case ACT_SET_RTS_RETRYLIM:
1001                 cfg->an_shortretry_limit =
1002                    cfg->an_longretry_limit = atoi(arg);
1003                 break;
1004         case ACT_SET_BEACON_PERIOD:
1005                 cfg->an_beacon_period = atoi(arg);
1006                 break;
1007         case ACT_SET_WAKE_DURATION:
1008                 cfg->an_atim_duration = atoi(arg);
1009                 break;
1010         case ACT_SET_FRAG_THRESH:
1011                 cfg->an_fragthresh = atoi(arg);
1012                 break;
1013         case ACT_SET_NETJOIN:
1014                 cfg->an_ibss_join_net_timeout = atoi(arg);
1015                 break;
1016         case ACT_SET_MYNAME:
1017                 bzero(cfg->an_nodename, 16);
1018                 strncpy((char *)&cfg->an_nodename, optarg, 16);
1019                 break;
1020         case ACT_SET_MAC:
1021                 addr = ether_aton((char *)arg);
1022
1023                 if (addr == NULL)
1024                         errx(1, "badly formatted address");
1025                 bzero(cfg->an_macaddr, ETHER_ADDR_LEN);
1026                 bcopy((char *)addr, (char *)&cfg->an_macaddr, ETHER_ADDR_LEN);
1027                 break;
1028         case ACT_ENABLE_WEP:
1029                 switch (atoi (arg)) {
1030                 case 0:
1031                         /* no WEP */
1032                         cfg->an_authtype &= ~(AN_AUTHTYPE_PRIVACY_IN_USE 
1033                                         | AN_AUTHTYPE_ALLOW_UNENCRYPTED
1034                                         | AN_AUTHTYPE_LEAP);
1035                         break;
1036                 case 1:
1037                         /* full WEP */
1038                         cfg->an_authtype |= AN_AUTHTYPE_PRIVACY_IN_USE;
1039                         cfg->an_authtype &= ~AN_AUTHTYPE_ALLOW_UNENCRYPTED;
1040                         cfg->an_authtype &= ~AN_AUTHTYPE_LEAP;
1041                         break;
1042                 case 2:
1043                         /* mixed cell */
1044                         cfg->an_authtype = AN_AUTHTYPE_PRIVACY_IN_USE 
1045                                         | AN_AUTHTYPE_ALLOW_UNENCRYPTED;
1046                         break;
1047                 }
1048                 break;
1049         case ACT_SET_KEY_TYPE:
1050                 cfg->an_authtype = (cfg->an_authtype & ~AN_AUTHTYPE_MASK) 
1051                         | atoi(arg);
1052                 break;
1053         case ACT_SET_MONITOR_MODE:
1054                 areq.an_type = AN_RID_MONITOR_MODE;
1055                 cfg->an_len = atoi(arg);      /* mode is put in length */
1056                 break;
1057         default:
1058                 errx(1, "unknown action");
1059                 break;
1060         }
1061
1062         an_setval(iface, &areq);
1063         exit(0);
1064 }
1065
1066 static void
1067 an_setspeed(const char *iface, int act __unused, void *arg)
1068 {
1069         struct an_req           areq;
1070         struct an_ltv_caps      *caps;
1071         u_int16_t               speed;
1072
1073         areq.an_len = sizeof(areq);
1074         areq.an_type = AN_RID_CAPABILITIES;
1075
1076         an_getval(iface, &areq);
1077         caps = (struct an_ltv_caps *)&areq;
1078
1079         switch(atoi(arg)) {
1080         case 0:
1081                 speed = 0;
1082                 break;
1083         case 1:
1084                 speed = AN_RATE_1MBPS;
1085                 break;
1086         case 2:
1087                 speed = AN_RATE_2MBPS;
1088                 break;
1089         case 3:
1090                 if (caps->an_rates[2] != AN_RATE_5_5MBPS)
1091                         errx(1, "5.5Mbps not supported on this card");
1092                 speed = AN_RATE_5_5MBPS;
1093                 break;
1094         case 4:
1095                 if (caps->an_rates[3] != AN_RATE_11MBPS)
1096                         errx(1, "11Mbps not supported on this card");
1097                 speed = AN_RATE_11MBPS;
1098                 break;
1099         default:
1100                 errx(1, "unsupported speed");
1101                 break;
1102         }
1103
1104         areq.an_len = 6;
1105         areq.an_type = AN_RID_TX_SPEED;
1106         areq.an_val[0] = speed;
1107
1108         an_setval(iface, &areq);
1109         exit(0);
1110 }
1111
1112 static void
1113 an_setap(const char *iface, int act, void *arg)
1114 {
1115         struct an_ltv_aplist    *ap;
1116         struct an_req           areq;
1117         struct ether_addr       *addr;
1118
1119         areq.an_len = sizeof(areq);
1120         areq.an_type = AN_RID_APLIST;
1121
1122         an_getval(iface, &areq);
1123         ap = (struct an_ltv_aplist *)&areq;
1124
1125         addr = ether_aton((char *)arg);
1126
1127         if (addr == NULL)
1128                 errx(1, "badly formatted address");
1129
1130         switch(act) {
1131         case ACT_SET_AP1:
1132                 bzero(ap->an_ap1, ETHER_ADDR_LEN);
1133                 bcopy((char *)addr, (char *)&ap->an_ap1, ETHER_ADDR_LEN);
1134                 break;
1135         case ACT_SET_AP2:
1136                 bzero(ap->an_ap2, ETHER_ADDR_LEN);
1137                 bcopy((char *)addr, (char *)&ap->an_ap2, ETHER_ADDR_LEN);
1138                 break;
1139         case ACT_SET_AP3:
1140                 bzero(ap->an_ap3, ETHER_ADDR_LEN);
1141                 bcopy((char *)addr, (char *)&ap->an_ap3, ETHER_ADDR_LEN);
1142                 break;
1143         case ACT_SET_AP4:
1144                 bzero(ap->an_ap4, ETHER_ADDR_LEN);
1145                 bcopy((char *)addr, (char *)&ap->an_ap4, ETHER_ADDR_LEN);
1146                 break;
1147         default:
1148                 errx(1, "unknown action");
1149                 break;
1150         }
1151
1152         an_setval(iface, &areq);
1153         exit(0);
1154 }
1155
1156 static void
1157 an_setssid(const char *iface, int act, void *arg)
1158 {
1159         struct an_ltv_ssidlist  *ssid;
1160         struct an_req           areq;
1161
1162         areq.an_len = sizeof(areq);
1163         areq.an_type = AN_RID_SSIDLIST;
1164
1165         an_getval(iface, &areq);
1166         ssid = (struct an_ltv_ssidlist *)&areq;
1167
1168         switch (act) {
1169         case ACT_SET_SSID1:
1170                 bzero(ssid->an_ssid1, sizeof(ssid->an_ssid1));
1171                 strlcpy(ssid->an_ssid1, (char *)arg, sizeof(ssid->an_ssid1));
1172                 ssid->an_ssid1_len = strlen(ssid->an_ssid1);
1173                 break;
1174         case ACT_SET_SSID2:
1175                 bzero(ssid->an_ssid2, sizeof(ssid->an_ssid2));
1176                 strlcpy(ssid->an_ssid2, (char *)arg, sizeof(ssid->an_ssid2));
1177                 ssid->an_ssid2_len = strlen(ssid->an_ssid2);
1178                 break;
1179         case ACT_SET_SSID3:
1180                 bzero(ssid->an_ssid3, sizeof(ssid->an_ssid3));
1181                 strlcpy(ssid->an_ssid3, (char *)arg, sizeof(ssid->an_ssid3));
1182                 ssid->an_ssid3_len = strlen(ssid->an_ssid3);
1183                 break;
1184         default:
1185                 errx(1, "unknown action");
1186                 break;
1187         }
1188
1189         an_setval(iface, &areq);
1190         exit(0);
1191 }
1192
1193 #ifdef ANCACHE
1194 static void
1195 an_zerocache(const char *iface)
1196 {
1197         struct an_req           areq;
1198
1199         bzero((char *)&areq, sizeof(areq));
1200         areq.an_len = 0;
1201         areq.an_type = AN_RID_ZERO_CACHE;
1202
1203         an_getval(iface, &areq);
1204
1205         return;
1206 }
1207
1208 static void
1209 an_readcache(const char *iface)
1210 {
1211         struct an_req           areq;
1212         int                     *an_sigitems;
1213         struct an_sigcache      *sc;
1214         char *                  pt;
1215         int                     i;
1216
1217         if (iface == NULL)
1218                 errx(1, "must specify interface name");
1219
1220         bzero((char *)&areq, sizeof(areq));
1221         areq.an_len = AN_MAX_DATALEN;
1222         areq.an_type = AN_RID_READ_CACHE;
1223
1224         an_getval(iface, &areq);
1225
1226         an_sigitems = (int *) &areq.an_val; 
1227         pt = ((char *) &areq.an_val);
1228         pt += sizeof(int);
1229         sc = (struct an_sigcache *) pt;
1230
1231         for (i = 0; i < *an_sigitems; i++) {
1232                 printf("[%d/%d]:", i+1, *an_sigitems);
1233                 printf(" %02x:%02x:%02x:%02x:%02x:%02x,",
1234                                         sc->macsrc[0]&0xff,
1235                                         sc->macsrc[1]&0xff,
1236                                         sc->macsrc[2]&0xff,
1237                                         sc->macsrc[3]&0xff,
1238                                         sc->macsrc[4]&0xff,
1239                                         sc->macsrc[5]&0xff);
1240                 printf(" %d.%d.%d.%d,",((sc->ipsrc >> 0) & 0xff),
1241                                         ((sc->ipsrc >> 8) & 0xff),
1242                                         ((sc->ipsrc >> 16) & 0xff),
1243                                         ((sc->ipsrc >> 24) & 0xff));
1244                 printf(" sig: %d, noise: %d, qual: %d\n",
1245                                         sc->signal,
1246                                         sc->noise,
1247                                         sc->quality);
1248                 sc++;
1249         }
1250
1251         return;
1252 }
1253 #endif
1254
1255 static int
1256 an_hex2int(char c)
1257 {
1258         if (c >= '0' && c <= '9')
1259                 return (c - '0');
1260         if (c >= 'A' && c <= 'F')
1261                 return (c - 'A' + 10);
1262         if (c >= 'a' && c <= 'f')
1263                 return (c - 'a' + 10);
1264
1265         return (0); 
1266 }
1267
1268 static void
1269 an_str2key(char *s, struct an_ltv_key *k)
1270 {
1271         int                     n, i;
1272         char                    *p;
1273
1274         /* Is this a hex string? */
1275         if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
1276                 /* Yes, convert to int. */
1277                 n = 0;
1278                 p = (char *)&k->key[0];
1279                 for (i = 2; s[i] != '\0' && s[i + 1] != '\0'; i+= 2) {
1280                         *p++ = (an_hex2int(s[i]) << 4) + an_hex2int(s[i + 1]);
1281                         n++;
1282                 }
1283                 if (s[i] != '\0')
1284                         errx(1, "hex strings must be of even length");
1285                 k->klen = n;
1286         } else {
1287                 /* No, just copy it in. */
1288                 bcopy(s, k->key, strlen(s));
1289                 k->klen = strlen(s);
1290         }
1291
1292         return;
1293 }
1294
1295 static void
1296 an_setkeys(const char *iface, char *key, int keytype)
1297 {
1298         struct an_req           areq;
1299         struct an_ltv_key       *k;
1300
1301         bzero((char *)&areq, sizeof(areq));
1302         k = (struct an_ltv_key *)&areq;
1303
1304         if (strlen(key) > 28) {
1305                 err(1, "encryption key must be no "
1306                     "more than 18 characters long");
1307         }
1308
1309         an_str2key(key, k);
1310         
1311         k->kindex=keytype/2;
1312
1313         if (!(k->klen==0 || k->klen==5 || k->klen==13)) {
1314                 err(1, "encryption key must be 0, 5 or 13 bytes long");
1315         }
1316
1317         /* default mac and only valid one (from manual) 1.0.0.0.0.0 */
1318         k->mac[0]=1;
1319         k->mac[1]=0;
1320         k->mac[2]=0;
1321         k->mac[3]=0;
1322         k->mac[4]=0;
1323         k->mac[5]=0;
1324
1325         switch(keytype & 1) {
1326         case 0:
1327           areq.an_len = sizeof(struct an_ltv_key);
1328           areq.an_type = AN_RID_WEP_PERM;
1329           an_setval(iface, &areq);
1330           break;
1331         case 1:
1332           areq.an_len = sizeof(struct an_ltv_key);
1333           areq.an_type = AN_RID_WEP_TEMP;
1334           an_setval(iface, &areq);
1335           break;
1336         }
1337           
1338         return;
1339 }
1340
1341 static void
1342 an_readkeyinfo(const char *iface)
1343 {
1344         struct an_req           areq;
1345         struct an_ltv_genconfig *cfg;
1346         struct an_ltv_key       *k;
1347         int i;
1348         int home;
1349
1350         areq.an_len = sizeof(areq);
1351         areq.an_type = AN_RID_ACTUALCFG;
1352         an_getval(iface, &areq);
1353         cfg = (struct an_ltv_genconfig *)&areq;
1354         if (cfg->an_home_product & AN_HOME_NETWORK)
1355                 home = 1;
1356         else
1357                 home = 0;
1358
1359         bzero((char *)&areq, sizeof(areq));
1360         k = (struct an_ltv_key *)&areq;
1361
1362         printf("WEP Key status:\n");
1363         areq.an_type = AN_RID_WEP_TEMP;         /* read first key */
1364         for(i=0; i<5; i++) {
1365                 areq.an_len = sizeof(struct an_ltv_key);
1366                 an_getval(iface, &areq);
1367                 if (k->kindex == 0xffff)
1368                         break;
1369                 switch (k->klen) {
1370                 case 0:
1371                         printf("\tKey %d is unset\n",k->kindex);
1372                         break;
1373                 case 5:
1374                         printf("\tKey %d is set  40 bits\n",k->kindex);
1375                         break;
1376                 case 13:
1377                         printf("\tKey %d is set 128 bits\n",k->kindex);
1378                         break;
1379                 default:
1380                         printf("\tWEP Key %d has an unknown size %d\n",
1381                             i, k->klen);
1382                 }
1383
1384                 areq.an_type = AN_RID_WEP_PERM; /* read next key */
1385         }
1386         k->kindex = 0xffff;
1387         areq.an_len = sizeof(struct an_ltv_key);
1388         an_getval(iface, &areq);
1389         printf("\tThe active transmit key is %d\n", 4 * home + k->mac[0]);
1390
1391         return;
1392 }
1393
1394 static void
1395 an_enable_tx_key(const char *iface, char *arg)
1396 {
1397         struct an_req           areq;
1398         struct an_ltv_key       *k;
1399         struct an_ltv_genconfig *config;
1400
1401         bzero((char *)&areq, sizeof(areq));
1402
1403         /* set home or not home mode */
1404         areq.an_len  = sizeof(struct an_ltv_genconfig);
1405         areq.an_type = AN_RID_GENCONFIG;
1406         an_getval(iface, &areq);
1407         config = (struct an_ltv_genconfig *)&areq;
1408         if (atoi(arg) == 4) {
1409                 config->an_home_product |= AN_HOME_NETWORK;
1410         }else{
1411                 config->an_home_product &= ~AN_HOME_NETWORK;
1412         }
1413         an_setval(iface, &areq);
1414
1415         bzero((char *)&areq, sizeof(areq));
1416
1417         k = (struct an_ltv_key *)&areq;
1418
1419         /* From a Cisco engineer write the transmit key to use in the
1420            first MAC, index is FFFF*/
1421         k->kindex=0xffff;
1422         k->klen=0;
1423
1424         k->mac[0]=atoi(arg);
1425         k->mac[1]=0;
1426         k->mac[2]=0;
1427         k->mac[3]=0;
1428         k->mac[4]=0;
1429         k->mac[5]=0;
1430
1431         areq.an_len = sizeof(struct an_ltv_key);
1432         areq.an_type = AN_RID_WEP_PERM;
1433         an_setval(iface, &areq);
1434           
1435         return;
1436 }
1437
1438 static void
1439 an_enable_leap_mode(const char *iface, char *username)
1440 {
1441         struct an_req           areq;
1442         struct an_ltv_status    *sts;
1443         struct an_ltv_genconfig *cfg;
1444         struct an_ltv_caps      *caps;
1445         struct an_ltv_leap_username an_username;
1446         struct an_ltv_leap_password an_password;
1447         char *password;
1448         MD4_CTX context;
1449         int len;
1450         int i;
1451         char unicode_password[LEAP_PASSWORD_MAX * 2];
1452
1453         areq.an_len = sizeof(areq);
1454         areq.an_type = AN_RID_CAPABILITIES;
1455
1456         an_getval(iface, &areq);
1457
1458         caps = (struct an_ltv_caps *)&areq;
1459
1460         if (!(caps->an_softcaps & AN_AUTHTYPE_LEAP)) {
1461                 fprintf(stderr, "Firmware does not support LEAP\n");
1462                 exit(1);
1463         }
1464
1465         bzero(&an_username, sizeof(an_username));
1466         bzero(&an_password, sizeof(an_password));
1467
1468         len = strlen(username);
1469         if (len > LEAP_USERNAME_MAX) {
1470                 printf("Username too long (max %d)\n", LEAP_USERNAME_MAX);
1471                 exit(1);
1472         }
1473         strncpy(an_username.an_username, username, len);
1474         an_username.an_username_len = len;
1475         an_username.an_len  = sizeof(an_username);      
1476         an_username.an_type = AN_RID_LEAPUSERNAME;
1477
1478         password = getpass("Enter LEAP password:");
1479
1480         len = strlen(password);
1481         if (len > LEAP_PASSWORD_MAX) {
1482                 printf("Password too long (max %d)\n", LEAP_PASSWORD_MAX);
1483                 exit(1);
1484         }
1485         
1486         bzero(&unicode_password, sizeof(unicode_password));
1487         for(i = 0; i < len; i++) {
1488                 unicode_password[i * 2] = *password++;
1489         }
1490         
1491         /* First half */
1492         MD4Init(&context);
1493         MD4Update(&context, unicode_password, len * 2);
1494         MD4Final(&an_password.an_password[0], &context);
1495         
1496         /* Second half */
1497         MD4Init (&context);
1498         MD4Update (&context, &an_password.an_password[0], 16);
1499         MD4Final (&an_password.an_password[16], &context);
1500
1501         an_password.an_password_len = 32;
1502         an_password.an_len  = sizeof(an_password);      
1503         an_password.an_type = AN_RID_LEAPPASSWORD;      
1504
1505         an_setval(iface, (struct an_req *)&an_username);
1506         an_setval(iface, (struct an_req *)&an_password);
1507         
1508         areq.an_len = sizeof(areq);
1509         areq.an_type = AN_RID_GENCONFIG;
1510         an_getval(iface, &areq);
1511         cfg = (struct an_ltv_genconfig *)&areq;
1512         cfg->an_authtype = (AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP);
1513         an_setval(iface, &areq);
1514
1515         sts = (struct an_ltv_status *)&areq;
1516         areq.an_type = AN_RID_STATUS;
1517         
1518         for (i = 60; i > 0; i--) {
1519                 an_getval(iface, &areq);
1520                 if (sts->an_opmode & AN_STATUS_OPMODE_LEAP) {
1521                         printf("Authenticated\n");
1522                         break;
1523                 }
1524                 sleep(1);
1525         }
1526
1527         if (i == 0) {
1528                 fprintf(stderr, "Failed LEAP authentication\n");
1529                 exit(1);
1530         }
1531 }
1532
1533 int
1534 main(int argc, char **argv)
1535 {
1536         int                     ch;
1537         int                     act = 0;
1538         const char              *iface = NULL;
1539         int                     modifier = 0;
1540         char                    *key = NULL;
1541         void                    *arg = NULL;
1542         char                    *p = argv[0];
1543
1544         /* Get the interface name */
1545         opterr = 0;
1546         ch = getopt(argc, argv, "i:");
1547         if (ch == 'i') {
1548                 iface = optarg;
1549         } else {
1550                 if (argc > 1 && *argv[1] != '-') {
1551                         iface = argv[1];
1552                         optind = 2; 
1553                 } else {
1554                         iface = "an0";
1555                         optind = 1;
1556                 }
1557                 optreset = 1;
1558         }
1559         opterr = 1;
1560
1561         while ((ch = getopt(argc, argv,
1562             "ANISCTRht:a:e:o:s:n:v:d:j:b:c:r:p:w:m:l:k:K:W:QZM:L:")) != -1) {
1563                 switch(ch) {
1564                 case 'Z':
1565 #ifdef ANCACHE
1566                         act = ACT_ZEROCACHE;
1567 #else
1568                         errx(1, "ANCACHE not available");
1569 #endif
1570                         break;
1571                 case 'Q':
1572 #ifdef ANCACHE
1573                         act = ACT_DUMPCACHE;
1574 #else
1575                         errx(1, "ANCACHE not available");
1576 #endif
1577                         break;
1578                 case 'A':
1579                         act = ACT_DUMPAP;
1580                         break;
1581                 case 'N':
1582                         act = ACT_DUMPSSID;
1583                         break;
1584                 case 'S':
1585                         act = ACT_DUMPSTATUS;
1586                         break;
1587                 case 'I':
1588                         act = ACT_DUMPCAPS;
1589                         break;
1590                 case 'T':
1591                         act = ACT_DUMPSTATS;
1592                         break;
1593                 case 'C':
1594                         act = ACT_DUMPCONFIG;
1595                         break;
1596                 case 'R':
1597                         act = ACT_DUMPRSSIMAP;
1598                         break;
1599                 case 't':
1600                         act = ACT_SET_TXRATE;
1601                         arg = optarg;
1602                         break;
1603                 case 's':
1604                         act = ACT_SET_PWRSAVE;
1605                         arg = optarg;
1606                         break;
1607                 case 'p':
1608                         act = ACT_SET_TXPWR;
1609                         arg = optarg;
1610                         break;
1611                 case 'v':
1612                         modifier = atoi(optarg);
1613                         break;
1614                 case 'a':
1615                         switch(modifier) {
1616                         case 0:
1617                         case 1:
1618                                 act = ACT_SET_AP1;
1619                                 break;
1620                         case 2:
1621                                 act = ACT_SET_AP2;
1622                                 break;
1623                         case 3:
1624                                 act = ACT_SET_AP3;
1625                                 break;
1626                         case 4:
1627                                 act = ACT_SET_AP4;
1628                                 break;
1629                         default:
1630                                 errx(1, "bad modifier %d: there "
1631                                     "are only 4 access point settings",
1632                                     modifier);
1633                                 usage(p);
1634                                 break;
1635                         }
1636                         arg = optarg;
1637                         break;
1638                 case 'b':
1639                         act = ACT_SET_BEACON_PERIOD;
1640                         arg = optarg;
1641                         break;
1642                 case 'd':
1643                         switch(modifier) {
1644                         case 0:
1645                                 act = ACT_SET_DIVERSITY_RX;
1646                                 break;
1647                         case 1:
1648                                 act = ACT_SET_DIVERSITY_TX;
1649                                 break;
1650                         default:
1651                                 errx(1, "must specify RX or TX diversity");
1652                                 break;
1653                         }
1654                         if (!isdigit(*optarg)) {
1655                                 errx(1, "%s is not numeric", optarg);
1656                                 exit(1);
1657                         }
1658                         arg = optarg;
1659                         break;
1660                 case 'j':
1661                         act = ACT_SET_NETJOIN;
1662                         arg = optarg;
1663                         break;
1664                 case 'l':
1665                         act = ACT_SET_MYNAME;
1666                         arg = optarg;
1667                         break;
1668                 case 'm':
1669                         act = ACT_SET_MAC;
1670                         arg = optarg;
1671                         break;
1672                 case 'n':
1673                         switch(modifier) {
1674                         case 0:
1675                         case 1:
1676                                 act = ACT_SET_SSID1;
1677                                 break;
1678                         case 2:
1679                                 act = ACT_SET_SSID2;
1680                                 break;
1681                         case 3:
1682                                 act = ACT_SET_SSID3;
1683                                 break;
1684                         default:
1685                                 errx(1, "bad modifier %d: there"
1686                                     "are only 3 SSID settings", modifier);
1687                                 usage(p);
1688                                 break;
1689                         }
1690                         arg = optarg;
1691                         break;
1692                 case 'o':
1693                         act = ACT_SET_OPMODE;
1694                         arg = optarg;
1695                         break;
1696                 case 'c':
1697                         act = ACT_SET_FREQ;
1698                         arg = optarg;
1699                         break;
1700                 case 'f':
1701                         act = ACT_SET_FRAG_THRESH;
1702                         arg = optarg;
1703                         break;
1704                 case 'W':
1705                         act = ACT_ENABLE_WEP;
1706                         arg = optarg;
1707                         break;
1708                 case 'K':
1709                         act = ACT_SET_KEY_TYPE;
1710                         arg = optarg;
1711                         break;
1712                 case 'k':
1713                         act = ACT_SET_KEYS;
1714                         key = optarg;
1715                         break;
1716                 case 'e':
1717                         act = ACT_ENABLE_TX_KEY;
1718                         arg = optarg;
1719                         break;
1720                 case 'q':
1721                         act = ACT_SET_RTS_RETRYLIM;
1722                         arg = optarg;
1723                         break;
1724                 case 'r':
1725                         act = ACT_SET_RTS_THRESH;
1726                         arg = optarg;
1727                         break;
1728                 case 'w':
1729                         act = ACT_SET_WAKE_DURATION;
1730                         arg = optarg;
1731                         break;
1732                 case 'M':
1733                         act = ACT_SET_MONITOR_MODE;
1734                         arg = optarg;
1735                         break;
1736                 case 'L':
1737                         act = ACT_SET_LEAP_MODE;
1738                         arg = optarg;
1739                         break;
1740                 case 'h':
1741                 default:
1742                         usage(p);
1743                 }
1744         }
1745
1746         if (iface == NULL || (!act && !key))
1747                 usage(p);
1748
1749         switch(act) {
1750         case ACT_DUMPSTATUS:
1751                 an_dumpstatus(iface);
1752                 break;
1753         case ACT_DUMPCAPS:
1754                 an_dumpcaps(iface);
1755                 break;
1756         case ACT_DUMPSTATS:
1757                 an_dumpstats(iface);
1758                 break;
1759         case ACT_DUMPCONFIG:
1760                 an_dumpconfig(iface);
1761                 break;
1762         case ACT_DUMPSSID:
1763                 an_dumpssid(iface);
1764                 break;
1765         case ACT_DUMPAP:
1766                 an_dumpap(iface);
1767                 break;
1768         case ACT_DUMPRSSIMAP:
1769                 an_dumprssimap(iface);
1770                 break;
1771         case ACT_SET_SSID1:
1772         case ACT_SET_SSID2:
1773         case ACT_SET_SSID3:
1774                 an_setssid(iface, act, arg);
1775                 break;
1776         case ACT_SET_AP1:
1777         case ACT_SET_AP2:
1778         case ACT_SET_AP3:
1779         case ACT_SET_AP4:
1780                 an_setap(iface, act, arg);
1781                 break;
1782         case ACT_SET_TXRATE:
1783                 an_setspeed(iface, act, arg);
1784                 break;
1785 #ifdef ANCACHE
1786         case ACT_ZEROCACHE:
1787                 an_zerocache(iface);
1788                 break;
1789         case ACT_DUMPCACHE:
1790                 an_readcache(iface);
1791                 break;
1792
1793 #endif
1794         case ACT_SET_KEYS:
1795                 an_setkeys(iface, key, modifier);
1796                 break;
1797         case ACT_ENABLE_TX_KEY:
1798                 an_enable_tx_key(iface, arg);
1799                 break;
1800         case ACT_SET_LEAP_MODE:
1801                 an_enable_leap_mode(iface, arg);
1802                 break;
1803         default:
1804                 an_setconfig(iface, act, arg);
1805                 break;
1806         }
1807
1808         exit(0);
1809 }
1810