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