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