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$"); 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 63static int an_getval(const char *, struct an_req *); 64static void an_setval(const char *, struct an_req *); 65static void an_printwords(const u_int16_t *, int); 66static void an_printspeeds(const u_int8_t *, int); 67static void an_printbool(int); 68static void an_printhex(const char *, int); 69static void an_printstr(char *, int); 70static void an_dumpstatus(const char *); 71static void an_dumpstats(const char *); 72static void an_dumpconfig(const char *); 73static void an_dumpcaps(const char *); 74static void an_dumpssid(const char *); 75static void an_dumpap(const char *); 76static void an_setconfig(const char *, int, void *); 77static void an_setssid(const char *, int, void *); 78static void an_setap(const char *, int, void *); 79static void an_setspeed(const char *, int, void *); 80static void an_readkeyinfo(const char *); 81#ifdef ANCACHE 82static void an_zerocache(const char *); 83static void an_readcache(const char *); 84#endif 85static int an_hex2int(char); 86static void an_str2key(const char *, struct an_ltv_key *); 87static void an_setkeys(const char *, const char *, int); 88static void an_enable_tx_key(const char *, const char *); 89static void an_enable_leap_mode(const char *, const char *); 90static void an_dumprssimap(const char *); 91static 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 135static int 136an_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 161static void 162an_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 185static void 186an_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 198static void 199an_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 209static void 210an_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 220static void 221an_printbool(int val) 222{ 223 if (val) 224 printf("[ On ]"); 225 else 226 printf("[ Off ]"); 227} 228 229static void 230an_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 246static void 247an_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 351static void 352an_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 436static void 437an_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 598static void 599an_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 623static void 624an_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 650static void 651an_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 855static void 856an_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 882static void 883usage(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 922static void 923an_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 1062static void 1063an_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 1108static void 1109an_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 1152static void 1153an_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 1191static void 1192an_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 1203static void 1204an_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 1245static int 1246an_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 1258static void 1259an_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 1285static void 1286an_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 1329static void 1330an_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 1382static void 1383an_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 1424static void 1425an_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 1519int 1520main(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 1781