wiconfig.c revision 1.1 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.1 1999/07/14 22:33:34 sommerfeld 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 #include <net/if_ether.h>
44
45 #include <dev/pcmcia/if_wi_ieee.h>
46
47 #include <stdio.h>
48 #include <string.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #include <err.h>
53
54 #if !defined(lint)
55 static const char copyright[] = "@(#) Copyright (c) 1997, 1998, 1999\
56 Bill Paul. All rights reserved.";
57 static const char rcsid[] =
58 "@(#) $Id: wiconfig.c,v 1.1 1999/07/14 22:33:34 sommerfeld Exp $";
59 #endif
60
61 static void wi_getval __P((char *, struct wi_req *));
62 static void wi_setval __P((char *, struct wi_req *));
63 static void wi_printstr __P((struct wi_req *));
64 static void wi_setstr __P((char *, int, char *));
65 static void wi_setbytes __P((char *, int, char *, int));
66 static void wi_setword __P((char *, int, int));
67 static void wi_sethex __P((char *, int, char *));
68 static void wi_printwords __P((struct wi_req *));
69 static void wi_printbool __P((struct wi_req *));
70 static void wi_printhex __P((struct wi_req *));
71 static void wi_dumpinfo __P((char *));
72 static void wi_dumpstats __P((char *));
73 static void usage __P((char *));
74 int main __P((int argc, char **argv));
75
76 static void wi_getval(iface, wreq)
77 char *iface;
78 struct wi_req *wreq;
79 {
80 struct ifreq ifr;
81 int s;
82
83 bzero((char *)&ifr, sizeof(ifr));
84
85 strcpy(ifr.ifr_name, iface);
86 ifr.ifr_data = (caddr_t)wreq;
87
88 s = socket(AF_INET, SOCK_DGRAM, 0);
89
90 if (s == -1)
91 err(1, "socket");
92
93 if (ioctl(s, SIOCGWAVELAN, &ifr) == -1)
94 err(1, "SIOCGWAVELAN");
95
96 close(s);
97
98 return;
99 }
100
101 static void wi_setval(iface, wreq)
102 char *iface;
103 struct wi_req *wreq;
104 {
105 struct ifreq ifr;
106 int s;
107
108 bzero((char *)&ifr, sizeof(ifr));
109
110 strcpy(ifr.ifr_name, iface);
111 ifr.ifr_data = (caddr_t)wreq;
112
113 s = socket(AF_INET, SOCK_DGRAM, 0);
114
115 if (s == -1)
116 err(1, "socket");
117
118 if (ioctl(s, SIOCSWAVELAN, &ifr) == -1)
119 err(1, "SIOCSWAVELAN");
120
121 close(s);
122
123 return;
124 }
125
126 void wi_printstr(wreq)
127 struct wi_req *wreq;
128 {
129 char *ptr;
130 int i;
131
132 if (wreq->wi_type == WI_RID_SERIALNO) {
133 ptr = (char *)&wreq->wi_val;
134 for (i = 0; i < (wreq->wi_len - 1) * 2; i++) {
135 if (ptr[i] == '\0')
136 ptr[i] = ' ';
137 }
138 } else {
139 ptr = (char *)&wreq->wi_val[1];
140 for (i = 0; i < wreq->wi_val[0]; i++) {
141 if (ptr[i] == '\0')
142 ptr[i] = ' ';
143 }
144 }
145
146 ptr[i] = '\0';
147 printf("[ %s ]", ptr);
148
149 return;
150 }
151
152 void wi_setstr(iface, code, str)
153 char *iface;
154 int code;
155 char *str;
156 {
157 struct wi_req wreq;
158
159 if (iface == NULL)
160 errx(1, "must specify interface name");
161
162 if (str == NULL)
163 errx(1, "must specify string");
164
165 bzero((char *)&wreq, sizeof(wreq));
166
167 if (strlen(str) > 30)
168 errx(1, "string too long");
169
170 wreq.wi_type = code;
171 wreq.wi_len = 18;
172 wreq.wi_val[0] = strlen(str);
173 bcopy(str, (char *)&wreq.wi_val[1], strlen(str));
174
175 wi_setval(iface, &wreq);
176
177 return;
178 }
179
180 void wi_setbytes(iface, code, bytes, len)
181 char *iface;
182 int code;
183 char *bytes;
184 int len;
185 {
186 struct wi_req wreq;
187
188 if (iface == NULL)
189 errx(1, "must specify interface name");
190
191 bzero((char *)&wreq, sizeof(wreq));
192
193 wreq.wi_type = code;
194 wreq.wi_len = (len / 2) + 1;
195 bcopy(bytes, (char *)&wreq.wi_val[0], len);
196
197 wi_setval(iface, &wreq);
198
199 return;
200 }
201
202 void wi_setword(iface, code, word)
203 char *iface;
204 int code;
205 int word;
206 {
207 struct wi_req wreq;
208
209 bzero((char *)&wreq, sizeof(wreq));
210
211 wreq.wi_type = code;
212 wreq.wi_len = 2;
213 wreq.wi_val[0] = word;
214
215 wi_setval(iface, &wreq);
216
217 return;
218 }
219
220 void wi_sethex(iface, code, str)
221 char *iface;
222 int code;
223 char *str;
224 {
225 struct ether_addr *addr;
226
227 if (str == NULL)
228 errx(1, "must specify address");
229
230 addr = ether_aton(str);
231
232 if (addr == NULL)
233 errx(1, "badly formatted address");
234
235 wi_setbytes(iface, code, (char *)addr, ETHER_ADDR_LEN);
236
237 return;
238 }
239
240 void wi_printwords(wreq)
241 struct wi_req *wreq;
242 {
243 int i;
244
245 printf("[ ");
246 for (i = 0; i < wreq->wi_len - 1; i++)
247 printf("%d ", wreq->wi_val[i]);
248 printf("]");
249
250 return;
251 }
252
253 void wi_printbool(wreq)
254 struct wi_req *wreq;
255 {
256 if (wreq->wi_val[0])
257 printf("[ On ]");
258 else
259 printf("[ Off ]");
260
261 return;
262 }
263
264 void wi_printhex(wreq)
265 struct wi_req *wreq;
266 {
267 int i;
268 unsigned char *c;
269
270 c = (unsigned char *)&wreq->wi_val;
271
272 printf("[ ");
273 for (i = 0; i < (wreq->wi_len - 1) * 2; i++) {
274 printf("%02x", c[i]);
275 if (i < ((wreq->wi_len - 1) * 2) - 1)
276 printf(":");
277 }
278
279 printf(" ]");
280 return;
281 }
282
283 #define WI_STRING 0x01
284 #define WI_BOOL 0x02
285 #define WI_WORDS 0x03
286 #define WI_HEXBYTES 0x04
287
288 struct wi_table {
289 int wi_code;
290 int wi_type;
291 char *wi_str;
292 };
293
294 static struct wi_table wi_table[] = {
295 { WI_RID_SERIALNO, WI_STRING, "NIC serial number:\t\t\t" },
296 { WI_RID_NODENAME, WI_STRING, "Station name:\t\t\t\t" },
297 { WI_RID_OWN_SSID, WI_STRING, "SSID for IBSS creation:\t\t\t" },
298 { WI_RID_CURRENT_SSID, WI_STRING, "Current netname (SSID):\t\t\t" },
299 { WI_RID_DESIRED_SSID, WI_STRING, "Desired netname (SSID):\t\t\t" },
300 { WI_RID_CURRENT_BSSID, WI_HEXBYTES, "Current BSSID:\t\t\t\t" },
301 { WI_RID_CHANNEL_LIST, WI_WORDS, "Channel list:\t\t\t\t" },
302 { WI_RID_OWN_CHNL, WI_WORDS, "IBSS channel:\t\t\t\t" },
303 { WI_RID_CURRENT_CHAN, WI_WORDS, "Current channel:\t\t\t" },
304 { WI_RID_COMMS_QUALITY, WI_WORDS, "Comms quality/signal/noise:\t\t" },
305 { WI_RID_PROMISC, WI_BOOL, "Promiscuous mode:\t\t\t" },
306 { WI_RID_PORTTYPE, WI_WORDS, "Port type (1=BSS, 3=ad-hoc):\t\t"},
307 { WI_RID_MAC_NODE, WI_HEXBYTES, "MAC address:\t\t\t\t"},
308 { WI_RID_TX_RATE, WI_WORDS, "TX rate:\t\t\t\t"},
309 { WI_RID_RTS_THRESH, WI_WORDS, "RTS/CTS handshake threshold:\t\t"},
310 { WI_RID_CREATE_IBSS, WI_BOOL, "Create IBSS:\t\t\t\t" },
311 { WI_RID_SYSTEM_SCALE, WI_WORDS, "Access point density:\t\t\t" },
312 { WI_RID_PM_ENABLED, WI_WORDS, "Power Mgmt (1=on, 0=off):\t\t" },
313 { WI_RID_MAX_SLEEP, WI_WORDS, "Max sleep time:\t\t\t\t" },
314 { 0, NULL }
315 };
316
317 static void wi_dumpinfo(iface)
318 char *iface;
319 {
320 struct wi_req wreq;
321 int i;
322 struct wi_table *w;
323
324 w = wi_table;
325
326 for (i = 0; w[i].wi_type; i++) {
327 bzero((char *)&wreq, sizeof(wreq));
328
329 wreq.wi_len = WI_MAX_DATALEN;
330 wreq.wi_type = w[i].wi_code;
331
332 wi_getval(iface, &wreq);
333 printf("%s", w[i].wi_str);
334 switch(w[i].wi_type) {
335 case WI_STRING:
336 wi_printstr(&wreq);
337 break;
338 case WI_WORDS:
339 wi_printwords(&wreq);
340 break;
341 case WI_BOOL:
342 wi_printbool(&wreq);
343 break;
344 case WI_HEXBYTES:
345 wi_printhex(&wreq);
346 break;
347 default:
348 break;
349 }
350 printf("\n");
351 }
352
353 return;
354 }
355
356 static void wi_dumpstats(iface)
357 char *iface;
358 {
359 struct wi_req wreq;
360 struct wi_counters *c;
361
362 if (iface == NULL)
363 errx(1, "must specify interface name");
364
365 bzero((char *)&wreq, sizeof(wreq));
366 wreq.wi_len = WI_MAX_DATALEN;
367 wreq.wi_type = WI_RID_IFACE_STATS;
368
369 wi_getval(iface, &wreq);
370
371 c = (struct wi_counters *)&wreq.wi_val;
372
373 printf("Transmitted unicast frames:\t\t%d\n",
374 c->wi_tx_unicast_frames);
375 printf("Transmitted multicast frames:\t\t%d\n",
376 c->wi_tx_multicast_frames);
377 printf("Transmitted fragments:\t\t\t%d\n",
378 c->wi_tx_fragments);
379 printf("Transmitted unicast octets:\t\t%d\n",
380 c->wi_tx_unicast_octets);
381 printf("Transmitted multicast octets:\t\t%d\n",
382 c->wi_tx_multicast_octets);
383 printf("Single transmit retries:\t\t%d\n",
384 c->wi_tx_single_retries);
385 printf("Multiple transmit retries:\t\t%d\n",
386 c->wi_tx_multi_retries);
387 printf("Transmit retry limit exceeded:\t\t%d\n",
388 c->wi_tx_retry_limit);
389 printf("Transmit discards:\t\t\t%d\n",
390 c->wi_tx_discards);
391 printf("Transmit discards due to wrong SA:\t%d\n",
392 c->wi_tx_discards_wrong_sa);
393 printf("Received unicast frames:\t\t%d\n",
394 c->wi_rx_unicast_frames);
395 printf("Received multicast frames:\t\t%d\n",
396 c->wi_rx_multicast_frames);
397 printf("Received fragments:\t\t\t%d\n",
398 c->wi_rx_fragments);
399 printf("Received unicast octets:\t\t%d\n",
400 c->wi_rx_unicast_octets);
401 printf("Received multicast octets:\t\t%d\n",
402 c->wi_rx_multicast_octets);
403 printf("Receive FCS errors:\t\t\t%d\n",
404 c->wi_rx_fcs_errors);
405 printf("Receive discards due to no buffer:\t%d\n",
406 c->wi_rx_discards_nobuf);
407 printf("Can't decrypt WEP frame:\t\t%d\n",
408 c->wi_rx_WEP_cant_decrypt);
409 printf("Received message fragments:\t\t%d\n",
410 c->wi_rx_msg_in_msg_frags);
411 printf("Received message bad fragments:\t\t%d\n",
412 c->wi_rx_msg_in_bad_msg_frags);
413
414 return;
415 }
416
417 static void usage(p)
418 char *p;
419 {
420 fprintf(stderr, "usage: %s -i iface\n", p);
421 fprintf(stderr, "\t%s -i iface -o\n", p);
422 fprintf(stderr, "\t%s -i iface -t tx rate\n", p);
423 fprintf(stderr, "\t%s -i iface -n network name\n", p);
424 fprintf(stderr, "\t%s -i iface -s station name\n", p);
425 fprintf(stderr, "\t%s -i iface -c 0|1\n", p);
426 fprintf(stderr, "\t%s -i iface -q SSID\n", p);
427 fprintf(stderr, "\t%s -i iface -p port type\n", p);
428 fprintf(stderr, "\t%s -i iface -a access point density\n", p);
429 fprintf(stderr, "\t%s -i iface -m mac address\n", p);
430 fprintf(stderr, "\t%s -i iface -d max data length\n", p);
431 fprintf(stderr, "\t%s -i iface -r RTS threshold\n", p);
432 fprintf(stderr, "\t%s -i iface -f frequency\n", p);
433 fprintf(stderr, "\t%s -i iface -P 0|1t\n", p);
434 fprintf(stderr, "\t%s -i iface -S max sleep duration\n", p);
435
436 exit(1);
437 }
438
439 int main(argc, argv)
440 int argc;
441 char *argv[];
442 {
443 int ch;
444 char *iface = NULL;
445 char *p = argv[0];
446
447 while((ch = getopt(argc, argv,
448 "hoc:d:f:i:p:r:q:t:n:s:m:P:S:")) != -1) {
449 switch(ch) {
450 case 'o':
451 wi_dumpstats(iface);
452 exit(0);
453 break;
454 case 'i':
455 iface = optarg;
456 break;
457 case 'c':
458 wi_setword(iface, WI_RID_CREATE_IBSS, atoi(optarg));
459 exit(0);
460 break;
461 case 'd':
462 wi_setword(iface, WI_RID_MAX_DATALEN, atoi(optarg));
463 exit(0);
464 break;
465 case 'f':
466 wi_setword(iface, WI_RID_OWN_CHNL, atoi(optarg));
467 exit(0);
468 break;
469 case 'p':
470 wi_setword(iface, WI_RID_PORTTYPE, atoi(optarg));
471 exit(0);
472 break;
473 case 'r':
474 wi_setword(iface, WI_RID_RTS_THRESH, atoi(optarg));
475 exit(0);
476 break;
477 case 't':
478 wi_setword(iface, WI_RID_TX_RATE, atoi(optarg));
479 exit(0);
480 break;
481 case 'n':
482 wi_setstr(iface, WI_RID_DESIRED_SSID, optarg);
483 exit(0);
484 break;
485 case 's':
486 wi_setstr(iface, WI_RID_NODENAME, optarg);
487 exit(0);
488 break;
489 case 'm':
490 wi_sethex(iface, WI_RID_MAC_NODE, optarg);
491 exit(0);
492 break;
493 case 'q':
494 wi_setstr(iface, WI_RID_OWN_SSID, optarg);
495 exit(0);
496 break;
497 case 'S':
498 wi_setword(iface, WI_RID_MAX_SLEEP, atoi(optarg));
499 exit(0);
500 break;
501 case 'P':
502 wi_setword(iface, WI_RID_PM_ENABLED, atoi(optarg));
503 exit(0);
504 break;
505 case 'h':
506 default:
507 usage(p);
508 break;
509 }
510 }
511
512 if (iface == NULL)
513 usage(p);
514
515 wi_dumpinfo(iface);
516
517 exit(0);
518 }
519