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