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