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