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