1 /* $NetBSD: wiconfig.c,v 1.10 2000/11/24 09:53:36 jdolecek Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 1998, 1999 5 * Bill Paul <wpaul@ctr.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 * From: Id: wicontrol.c,v 1.6 1999/05/22 16:12:49 wpaul Exp $ 35 */ 36 37 #include <sys/types.h> 38 #include <sys/cdefs.h> 39 #include <sys/param.h> 40 #include <sys/socket.h> 41 #include <sys/ioctl.h> 42 #include <sys/socket.h> 43 44 #include <net/if.h> 45 #ifdef __FreeBSD__ 46 #include <net/if_var.h> 47 #include <net/ethernet.h> 48 49 #include <machine/if_wavelan_ieee.h> 50 #else 51 #include <netinet/in.h> 52 #include <netinet/if_ether.h> 53 #ifdef __NetBSD__ 54 #include <dev/pcmcia/if_wi_ieee.h> 55 #else 56 #include <dev/pcmcia/if_wavelan_ieee.h> 57 #endif 58 #endif 59 60 #include <stdio.h> 61 #include <string.h> 62 #include <ctype.h> 63 #include <stdlib.h> 64 #include <unistd.h> 65 #include <errno.h> 66 #include <err.h> 67 68 #if !defined(lint) 69 static const char copyright[] = "@(#) Copyright (c) 1997, 1998, 1999\ 70 Bill Paul. All rights reserved."; 71 static const char rcsid[] = 72 "@(#) $Id: wiconfig.c,v 1.10 2000/11/24 09:53:36 jdolecek Exp $"; 73 #endif 74 75 struct wi_table { 76 int wi_type; 77 int wi_code; 78 #define WI_NONE 0x00 79 #define WI_STRING 0x01 80 #define WI_BOOL 0x02 81 #define WI_WORDS 0x03 82 #define WI_HEXBYTES 0x04 83 #define WI_KEYSTRUCT 0x05 84 char *wi_label; /* label used to print info */ 85 int wi_opt; /* option character to set this */ 86 char *wi_desc; 87 char *wi_optval; 88 }; 89 90 static void wi_getval __P((char *, struct wi_req *)); 91 static void wi_setval __P((char *, struct wi_req *)); 92 static void wi_printstr __P((struct wi_req *)); 93 static void wi_setstr __P((char *, int, char *)); 94 static void wi_setbytes __P((char *, int, char *, int)); 95 static void wi_setword __P((char *, int, int)); 96 static void wi_sethex __P((char *, int, char *)); 97 static void wi_printwords __P((struct wi_req *)); 98 static void wi_printbool __P((struct wi_req *)); 99 static void wi_printhex __P((struct wi_req *)); 100 static void wi_dumpinfo __P((char *)); 101 static void wi_setkeys __P((char *, char *, int)); 102 static void wi_printkeys __P((struct wi_req *)); 103 static void wi_dumpstats __P((char *)); 104 static void usage __P((void)); 105 static struct wi_table * 106 wi_optlookup __P((struct wi_table *, int)); 107 static int wi_hex2int(char c); 108 static void wi_str2key __P((char *, struct wi_key *)); 109 int main __P((int argc, char **argv)); 110 111 static void wi_getval(iface, wreq) 112 char *iface; 113 struct wi_req *wreq; 114 { 115 struct ifreq ifr; 116 int s; 117 118 bzero((char *)&ifr, sizeof(ifr)); 119 120 strcpy(ifr.ifr_name, iface); 121 ifr.ifr_data = (caddr_t)wreq; 122 123 s = socket(AF_INET, SOCK_DGRAM, 0); 124 125 if (s == -1) 126 err(1, "socket"); 127 128 if (ioctl(s, SIOCGWAVELAN, &ifr) == -1) 129 err(1, "SIOCGWAVELAN"); 130 131 close(s); 132 133 return; 134 } 135 136 static void wi_setval(iface, wreq) 137 char *iface; 138 struct wi_req *wreq; 139 { 140 struct ifreq ifr; 141 int s; 142 143 bzero((char *)&ifr, sizeof(ifr)); 144 145 strcpy(ifr.ifr_name, iface); 146 ifr.ifr_data = (caddr_t)wreq; 147 148 s = socket(AF_INET, SOCK_DGRAM, 0); 149 150 if (s == -1) 151 err(1, "socket"); 152 153 if (ioctl(s, SIOCSWAVELAN, &ifr) == -1) 154 err(1, "SIOCSWAVELAN"); 155 156 close(s); 157 158 return; 159 } 160 161 void wi_printstr(wreq) 162 struct wi_req *wreq; 163 { 164 char *ptr; 165 int i; 166 167 if (wreq->wi_type == WI_RID_SERIALNO) { 168 ptr = (char *)&wreq->wi_val; 169 for (i = 0; i < (wreq->wi_len - 1) * 2; i++) { 170 if (ptr[i] == '\0') 171 ptr[i] = ' '; 172 } 173 } else { 174 ptr = (char *)&wreq->wi_val[1]; 175 for (i = 0; i < wreq->wi_val[0]; i++) { 176 if (ptr[i] == '\0') 177 ptr[i] = ' '; 178 } 179 } 180 181 ptr[i] = '\0'; 182 printf("[ %s ]", ptr); 183 184 return; 185 } 186 187 void wi_setstr(iface, code, str) 188 char *iface; 189 int code; 190 char *str; 191 { 192 struct wi_req wreq; 193 194 bzero((char *)&wreq, sizeof(wreq)); 195 196 if (strlen(str) > 30) 197 errx(1, "string too long"); 198 199 wreq.wi_type = code; 200 wreq.wi_len = 18; 201 wreq.wi_val[0] = strlen(str); 202 bcopy(str, (char *)&wreq.wi_val[1], strlen(str)); 203 204 wi_setval(iface, &wreq); 205 206 return; 207 } 208 209 void wi_setbytes(iface, code, bytes, len) 210 char *iface; 211 int code; 212 char *bytes; 213 int len; 214 { 215 struct wi_req wreq; 216 217 bzero((char *)&wreq, sizeof(wreq)); 218 219 wreq.wi_type = code; 220 wreq.wi_len = (len / 2) + 1; 221 bcopy(bytes, (char *)&wreq.wi_val[0], len); 222 223 wi_setval(iface, &wreq); 224 225 return; 226 } 227 228 void wi_setword(iface, code, word) 229 char *iface; 230 int code; 231 int word; 232 { 233 struct wi_req wreq; 234 235 bzero((char *)&wreq, sizeof(wreq)); 236 237 wreq.wi_type = code; 238 wreq.wi_len = 2; 239 wreq.wi_val[0] = word; 240 241 wi_setval(iface, &wreq); 242 243 return; 244 } 245 246 void wi_sethex(iface, code, str) 247 char *iface; 248 int code; 249 char *str; 250 { 251 struct ether_addr *addr; 252 253 addr = ether_aton(str); 254 if (addr == NULL) 255 errx(1, "badly formatted address"); 256 257 wi_setbytes(iface, code, (char *)addr, ETHER_ADDR_LEN); 258 259 return; 260 } 261 262 static int 263 wi_hex2int(char c) 264 { 265 if (c >= '0' && c <= '9') 266 return (c - '0'); 267 if (c >= 'A' && c <= 'F') 268 return (c - 'A' + 10); 269 if (c >= 'a' && c <= 'f') 270 return (c - 'a' + 10); 271 272 return (0); 273 } 274 275 static void wi_str2key(s, k) 276 char *s; 277 struct wi_key *k; 278 { 279 int n, i; 280 char *p; 281 282 /* Is this a hex string? */ 283 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { 284 /* Yes, convert to int. */ 285 n = 0; 286 p = (char *)&k->wi_keydat[0]; 287 for (i = 2; i < strlen(s); i+= 2) { 288 *p++ = (wi_hex2int(s[i]) << 4) + wi_hex2int(s[i + 1]); 289 n++; 290 } 291 k->wi_keylen = n; 292 } else { 293 /* No, just copy it in. */ 294 bcopy(s, k->wi_keydat, strlen(s)); 295 k->wi_keylen = strlen(s); 296 } 297 298 return; 299 } 300 301 static void wi_setkeys(iface, key, idx) 302 char *iface; 303 char *key; 304 int idx; 305 { 306 struct wi_req wreq; 307 struct wi_ltv_keys *keys; 308 struct wi_key *k; 309 310 bzero((char *)&wreq, sizeof(wreq)); 311 wreq.wi_len = WI_MAX_DATALEN; 312 wreq.wi_type = WI_RID_WEP_AVAIL; 313 314 wi_getval(iface, &wreq); 315 if (wreq.wi_val[0] == 0) 316 err(1, "no WEP option available on this card"); 317 318 bzero((char *)&wreq, sizeof(wreq)); 319 wreq.wi_len = WI_MAX_DATALEN; 320 wreq.wi_type = WI_RID_DEFLT_CRYPT_KEYS; 321 322 wi_getval(iface, &wreq); 323 keys = (struct wi_ltv_keys *)&wreq; 324 325 if (key[0] == '0' && (key[1] == 'x' || key[1] == 'X')) { 326 if (strlen(key) > 30) 327 err(1, "encryption key must be no " 328 "more than 28 hex digits long"); 329 } else { 330 if (strlen(key) > 14) 331 err(1, "encryption key must be no " 332 "more than 14 characters long"); 333 } 334 335 if (idx > 3) 336 err(1, "only 4 encryption keys available"); 337 338 k = &keys->wi_keys[idx]; 339 wi_str2key(key, k); 340 341 wreq.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1; 342 wreq.wi_type = WI_RID_DEFLT_CRYPT_KEYS; 343 wi_setval(iface, &wreq); 344 345 return; 346 } 347 348 static void wi_printkeys(wreq) 349 struct wi_req *wreq; 350 { 351 int i, j, bn; 352 struct wi_key *k; 353 struct wi_ltv_keys *keys; 354 char *ptr; 355 356 keys = (struct wi_ltv_keys *)wreq; 357 358 for (i = 0, bn = 0; i < 4; i++, bn = 0) { 359 k = &keys->wi_keys[i]; 360 ptr = (char *)k->wi_keydat; 361 for (j = 0; j < k->wi_keylen; j++) { 362 if (!isprint((unsigned char) ptr[j])) { 363 bn = 1; 364 break; 365 } 366 } 367 368 if (bn) { 369 printf("[ 0x"); 370 for (j = 0; j < k->wi_keylen; j++) 371 printf("%02x", ((unsigned char *) ptr)[j]); 372 printf(" ]"); 373 } else { 374 ptr[j] = '\0'; 375 printf("[ %s ]", ptr); 376 } 377 } 378 379 return; 380 }; 381 382 void wi_printwords(wreq) 383 struct wi_req *wreq; 384 { 385 int i; 386 387 printf("[ "); 388 for (i = 0; i < wreq->wi_len - 1; i++) 389 printf("%d ", wreq->wi_val[i]); 390 printf("]"); 391 392 return; 393 } 394 395 void wi_printbool(wreq) 396 struct wi_req *wreq; 397 { 398 if (wreq->wi_val[0]) 399 printf("[ On ]"); 400 else 401 printf("[ Off ]"); 402 403 return; 404 } 405 406 void wi_printhex(wreq) 407 struct wi_req *wreq; 408 { 409 int i; 410 unsigned char *c; 411 412 c = (unsigned char *)&wreq->wi_val; 413 414 printf("[ "); 415 for (i = 0; i < (wreq->wi_len - 1) * 2; i++) { 416 printf("%02x", c[i]); 417 if (i < ((wreq->wi_len - 1) * 2) - 1) 418 printf(":"); 419 } 420 421 printf(" ]"); 422 return; 423 } 424 425 static struct wi_table wi_table[] = { 426 { WI_RID_SERIALNO, WI_STRING, "NIC serial number:\t\t\t" }, 427 { WI_RID_NODENAME, WI_STRING, "Station name:\t\t\t\t", 428 's', "station name" }, 429 { WI_RID_OWN_SSID, WI_STRING, "SSID for IBSS creation:\t\t\t", 430 'q', "own SSID" }, 431 { WI_RID_CURRENT_SSID, WI_STRING, "Current netname (SSID):\t\t\t" }, 432 { WI_RID_DESIRED_SSID, WI_STRING, "Desired netname (SSID):\t\t\t", 433 'n', "network name" }, 434 { WI_RID_CURRENT_BSSID, WI_HEXBYTES, "Current BSSID:\t\t\t\t" }, 435 { WI_RID_CHANNEL_LIST, WI_WORDS, "Channel list:\t\t\t\t" }, 436 { WI_RID_OWN_CHNL, WI_WORDS, "IBSS channel:\t\t\t\t", 437 'f', "frequency" }, 438 { WI_RID_CURRENT_CHAN, WI_WORDS, "Current channel:\t\t\t" }, 439 { WI_RID_COMMS_QUALITY, WI_WORDS, "Comms quality/signal/noise:\t\t" }, 440 { WI_RID_PROMISC, WI_BOOL, "Promiscuous mode:\t\t\t" }, 441 { WI_RID_PORTTYPE, WI_WORDS, "Port type (1=BSS, 3=ad-hoc):\t\t", 442 'p', "port type" }, 443 { WI_RID_MAC_NODE, WI_HEXBYTES, "MAC address:\t\t\t\t", 444 'm', "MAC address" }, 445 { WI_RID_TX_RATE, WI_WORDS, "TX rate (selection):\t\t\t", 446 't', "TX rate" }, 447 { WI_RID_CUR_TX_RATE, WI_WORDS, "TX rate (actual speed):\t\t\t"}, 448 { WI_RID_MAX_DATALEN, WI_WORDS, "Maximum data length:\t\t\t", 449 'd', "maximum data length" }, 450 { WI_RID_RTS_THRESH, WI_WORDS, "RTS/CTS handshake threshold:\t\t", 451 'r', "RTS threshold" }, 452 { WI_RID_CREATE_IBSS, WI_BOOL, "Create IBSS:\t\t\t\t", 453 'c', "create ibss" }, 454 { WI_RID_SYSTEM_SCALE, WI_WORDS, "Access point density:\t\t\t", 455 'a', "system scale" }, 456 { WI_RID_PM_ENABLED, WI_WORDS, "Power Mgmt (1=on, 0=off):\t\t", 457 'P', "power management enabled" }, 458 { WI_RID_MAX_SLEEP, WI_WORDS, "Max sleep time:\t\t\t\t", 459 'S', "max sleep duration" }, 460 { WI_RID_MICROWAVE_OVEN, WI_WORDS, "Microwave oven robustness:\t\t", 461 'M', "microwave oven robustness enabled" }, 462 { 0, WI_NONE } 463 }; 464 465 static struct wi_table wi_crypt_table[] = { 466 { WI_RID_ENCRYPTION, WI_BOOL, "WEP encryption:\t\t\t\t", 467 'e', "encryption" }, 468 { WI_RID_TX_CRYPT_KEY, WI_WORDS, "TX encryption key:\t\t\t" }, 469 { WI_RID_DEFLT_CRYPT_KEYS, WI_KEYSTRUCT, "Encryption keys:\t\t\t" }, 470 { 0, WI_NONE } 471 }; 472 473 static struct wi_table *wi_tables[] = { 474 wi_table, 475 wi_crypt_table, 476 NULL 477 }; 478 479 static struct wi_table * 480 wi_optlookup(table, opt) 481 struct wi_table *table; 482 int opt; 483 { 484 struct wi_table *wt; 485 486 for (wt = table; wt->wi_type != 0; wt++) 487 if (wt->wi_opt == opt) 488 return (wt); 489 return (NULL); 490 } 491 492 static void wi_dumpinfo(iface) 493 char *iface; 494 { 495 struct wi_req wreq; 496 int i, has_wep; 497 struct wi_table *w; 498 499 bzero((char *)&wreq, sizeof(wreq)); 500 501 wreq.wi_len = WI_MAX_DATALEN; 502 wreq.wi_type = WI_RID_WEP_AVAIL; 503 504 wi_getval(iface, &wreq); 505 has_wep = wreq.wi_val[0]; 506 507 w = wi_table; 508 509 for (i = 0; w[i].wi_code != WI_NONE; i++) { 510 bzero((char *)&wreq, sizeof(wreq)); 511 512 wreq.wi_len = WI_MAX_DATALEN; 513 wreq.wi_type = w[i].wi_type; 514 515 wi_getval(iface, &wreq); 516 printf("%s", w[i].wi_label); 517 switch (w[i].wi_code) { 518 case WI_STRING: 519 wi_printstr(&wreq); 520 break; 521 case WI_WORDS: 522 wi_printwords(&wreq); 523 break; 524 case WI_BOOL: 525 wi_printbool(&wreq); 526 break; 527 case WI_HEXBYTES: 528 wi_printhex(&wreq); 529 break; 530 default: 531 break; 532 } 533 printf("\n"); 534 } 535 536 if (has_wep) { 537 w = wi_crypt_table; 538 for (i = 0; w[i].wi_code != WI_NONE; i++) { 539 bzero((char *)&wreq, sizeof(wreq)); 540 541 wreq.wi_len = WI_MAX_DATALEN; 542 wreq.wi_type = w[i].wi_type; 543 544 wi_getval(iface, &wreq); 545 printf("%s", w[i].wi_label); 546 switch (w[i].wi_code) { 547 case WI_STRING: 548 wi_printstr(&wreq); 549 break; 550 case WI_WORDS: 551 if (wreq.wi_type == WI_RID_TX_CRYPT_KEY) 552 wreq.wi_val[0]++; 553 wi_printwords(&wreq); 554 break; 555 case WI_BOOL: 556 wi_printbool(&wreq); 557 break; 558 case WI_HEXBYTES: 559 wi_printhex(&wreq); 560 break; 561 case WI_KEYSTRUCT: 562 wi_printkeys(&wreq); 563 break; 564 default: 565 break; 566 } 567 printf("\n"); 568 } 569 } 570 571 return; 572 } 573 574 static void wi_dumpstats(iface) 575 char *iface; 576 { 577 struct wi_req wreq; 578 struct wi_counters *c; 579 580 bzero((char *)&wreq, sizeof(wreq)); 581 wreq.wi_len = WI_MAX_DATALEN; 582 wreq.wi_type = WI_RID_IFACE_STATS; 583 584 wi_getval(iface, &wreq); 585 586 c = (struct wi_counters *)&wreq.wi_val; 587 588 printf("Transmitted unicast frames:\t\t%d\n", 589 c->wi_tx_unicast_frames); 590 printf("Transmitted multicast frames:\t\t%d\n", 591 c->wi_tx_multicast_frames); 592 printf("Transmitted fragments:\t\t\t%d\n", 593 c->wi_tx_fragments); 594 printf("Transmitted unicast octets:\t\t%d\n", 595 c->wi_tx_unicast_octets); 596 printf("Transmitted multicast octets:\t\t%d\n", 597 c->wi_tx_multicast_octets); 598 printf("Single transmit retries:\t\t%d\n", 599 c->wi_tx_single_retries); 600 printf("Multiple transmit retries:\t\t%d\n", 601 c->wi_tx_multi_retries); 602 printf("Transmit retry limit exceeded:\t\t%d\n", 603 c->wi_tx_retry_limit); 604 printf("Transmit discards:\t\t\t%d\n", 605 c->wi_tx_discards); 606 printf("Transmit discards due to wrong SA:\t%d\n", 607 c->wi_tx_discards_wrong_sa); 608 printf("Received unicast frames:\t\t%d\n", 609 c->wi_rx_unicast_frames); 610 printf("Received multicast frames:\t\t%d\n", 611 c->wi_rx_multicast_frames); 612 printf("Received fragments:\t\t\t%d\n", 613 c->wi_rx_fragments); 614 printf("Received unicast octets:\t\t%d\n", 615 c->wi_rx_unicast_octets); 616 printf("Received multicast octets:\t\t%d\n", 617 c->wi_rx_multicast_octets); 618 printf("Receive FCS errors:\t\t\t%d\n", 619 c->wi_rx_fcs_errors); 620 printf("Receive discards due to no buffer:\t%d\n", 621 c->wi_rx_discards_nobuf); 622 printf("Can't decrypt WEP frame:\t\t%d\n", 623 c->wi_rx_WEP_cant_decrypt); 624 printf("Received message fragments:\t\t%d\n", 625 c->wi_rx_msg_in_msg_frags); 626 printf("Received message bad fragments:\t\t%d\n", 627 c->wi_rx_msg_in_bad_msg_frags); 628 629 return; 630 } 631 632 static void 633 usage() 634 { 635 extern char *__progname; 636 637 fprintf(stderr, 638 "usage: %s interface " 639 "[-o] [-t tx rate] [-n network name] [-s station name]\n" 640 " [-e 0|1] [-k key [-v 1|2|3|4]] [-T 1|2|3|4]\n" 641 " [-c 0|1] [-q SSID] [-p port type] [-a access point density]\n" 642 " [-m MAC address] [-d max data length] [-r RTS threshold]\n" 643 " [-f frequency] [-M 0|1] [-P 0|1] [-S max sleep duration]\n" 644 , 645 __progname); 646 exit(1); 647 } 648 649 int main(argc, argv) 650 int argc; 651 char *argv[]; 652 { 653 struct wi_table *wt, **table; 654 char *iface, *key, *keyv[4], *tx_crypt_key; 655 int ch, dumpinfo, dumpstats, modifier, oldind; 656 657 #define SET_OPERAND(opr, desc) do { \ 658 if ((opr) == NULL) \ 659 (opr) = optarg; \ 660 else \ 661 warnx("%s is already specified to %s", \ 662 desc, (opr)); \ 663 } while (0) 664 665 dumpinfo = 1; 666 dumpstats = 0; 667 iface = key = keyv[0] = keyv[1] = keyv[2] = keyv[3] = 668 tx_crypt_key = NULL; 669 670 if (argc > 1 && argv[1][0] != '-') { 671 iface = argv[1]; 672 optind++; 673 } 674 675 while ((ch = getopt(argc, argv, 676 "a:c:d:e:f:hi:k:m:n:op:q:r:s:t:M:S:P:T:")) != -1) { 677 if (ch != 'i') 678 dumpinfo = 0; 679 /* 680 * Lookup generic options and remeber operand if found. 681 */ 682 for (table = wi_tables; *table != NULL; table++) 683 if ((wt = wi_optlookup(*table, ch)) != NULL) { 684 SET_OPERAND(wt->wi_optval, wt->wi_desc); 685 break; 686 } 687 if (wt == NULL) 688 /* 689 * Handle special options. 690 */ 691 switch (ch) { 692 case 'o': 693 dumpstats = 1; 694 break; 695 case 'i': 696 SET_OPERAND(iface, "interface"); 697 break; 698 case 'k': 699 key = optarg; 700 oldind = optind; 701 opterr = 0; 702 ch = getopt(argc, argv, "v:"); 703 opterr = 1; 704 switch (ch) { 705 case 'v': 706 modifier = atoi(optarg) - 1; 707 break; 708 default: 709 modifier = 0; 710 optind = oldind; 711 break; 712 } 713 keyv[modifier] = key; 714 break; 715 case 'T': 716 SET_OPERAND(tx_crypt_key, "TX encryption key"); 717 break; 718 case 'h': 719 default: 720 usage(); 721 break; 722 } 723 } 724 725 if (iface == NULL) 726 usage(); 727 728 for (table = wi_tables; *table != NULL; table++) 729 for (wt = *table; wt->wi_code != WI_NONE; wt++) 730 if (wt->wi_optval != NULL) { 731 switch (wt->wi_code) { 732 case WI_BOOL: 733 case WI_WORDS: 734 wi_setword(iface, wt->wi_type, 735 atoi(wt->wi_optval)); 736 break; 737 case WI_STRING: 738 wi_setstr(iface, wt->wi_type, 739 wt->wi_optval); 740 break; 741 case WI_HEXBYTES: 742 wi_sethex(iface, wt->wi_type, 743 wt->wi_optval); 744 break; 745 } 746 } 747 748 if (tx_crypt_key != NULL) 749 wi_setword(iface, WI_RID_TX_CRYPT_KEY, atoi(tx_crypt_key) - 1); 750 751 for (modifier = 0; modifier < sizeof(keyv) / sizeof(keyv[0]); 752 modifier++) 753 if (keyv[modifier] != NULL) 754 wi_setkeys(iface, keyv[modifier], modifier); 755 756 if (dumpstats) 757 wi_dumpstats(iface); 758 if (dumpinfo) 759 wi_dumpinfo(iface); 760 761 exit(0); 762 } 763