blob: a81ee9f25e88cfe2ccf7d93c7857f0257631f23b [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * Wireless Tools
3 *
4 * Jean II - HPLB 97->99 - HPL 99->01
5 *
6 * Main code for "iwconfig". This is the generic tool for most
7 * manipulations...
8 * You need to link this code against "iwlib.c" and "-lm".
9 *
10 * This file is released under the GPL license.
11 * Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
12 */
13
14#include "iwlib.h" /* Header */
15
16/************************* MISC SUBROUTINES **************************/
17
18/*------------------------------------------------------------------*/
19/*
20 * Print usage string
21 */
22static void
23iw_usage(void)
24{
25 fprintf(stderr, "Usage: iwconfig interface [essid {NN|on|off}]\n");
26 fprintf(stderr, " [nwid {NN|on|off}]\n");
27 fprintf(stderr, " [mode {managed|ad-hoc|...}\n");
28 fprintf(stderr, " [freq N.NNNN[k|M|G]]\n");
29 fprintf(stderr, " [channel N]\n");
30 fprintf(stderr, " [sens N]\n");
31 fprintf(stderr, " [nick N]\n");
32 fprintf(stderr, " [rate {N|auto|fixed}]\n");
33 fprintf(stderr, " [rts {N|auto|fixed|off}]\n");
34 fprintf(stderr, " [frag {N|auto|fixed|off}]\n");
35 fprintf(stderr, " [enc {NNNN-NNNN|off}]\n");
36 fprintf(stderr, " [power {period N|timeout N}]\n");
37 fprintf(stderr, " [txpower N {mW|dBm}]\n");
38 fprintf(stderr, " [commit]\n");
39 fprintf(stderr, " Check man pages for more details.\n\n");
40}
41
42
43/************************* DISPLAY ROUTINES **************************/
44
45/*------------------------------------------------------------------*/
46/*
47 * Get wireless informations & config from the device driver
48 * We will call all the classical wireless ioctl on the driver through
49 * the socket to know what is supported and to get the settings...
50 */
51static int
52get_info(int skfd,
53 char * ifname,
54 struct wireless_info * info)
55{
56 struct iwreq wrq;
57
58 memset((char *) info, 0, sizeof(struct wireless_info));
59
60 /* Get wireless name */
61 if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
62 {
63 /* If no wireless name : no wireless extensions */
64 /* But let's check if the interface exists at all */
65 struct ifreq ifr;
66
67 strcpy(ifr.ifr_name, ifname);
68 if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
69 return(-ENODEV);
70 else
71 return(-ENOTSUP);
72 }
73 else
74 {
75 strncpy(info->name, wrq.u.name, IFNAMSIZ);
76 info->name[IFNAMSIZ] = '\0';
77 }
78
79 /* Get ranges */
80 if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
81 info->has_range = 1;
82
83 /* Get network ID */
84 if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0)
85 {
86 info->has_nwid = 1;
87 memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
88 }
89
90 /* Get frequency / channel */
91 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
92 {
93 info->has_freq = 1;
94 info->freq = iw_freq2float(&(wrq.u.freq));
95 }
96
97 /* Get sensitivity */
98 if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
99 {
100 info->has_sens = 1;
101 memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
102 }
103
104 /* Get encryption information */
105 wrq.u.data.pointer = (caddr_t) info->key;
106 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
107 wrq.u.data.flags = 0;
108 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
109 {
110 info->has_key = 1;
111 info->key_size = wrq.u.data.length;
112 info->key_flags = wrq.u.data.flags;
113 }
114
115 /* Get ESSID */
116 wrq.u.essid.pointer = (caddr_t) info->essid;
117 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
118 wrq.u.essid.flags = 0;
119 if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0)
120 {
121 info->has_essid = 1;
122 info->essid_on = wrq.u.data.flags;
123 }
124
125 /* Get AP address */
126 if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
127 {
128 info->has_ap_addr = 1;
129 memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
130 }
131
132 /* Get NickName */
133 wrq.u.essid.pointer = (caddr_t) info->nickname;
134 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
135 wrq.u.essid.flags = 0;
136 if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
137 if(wrq.u.data.length > 1)
138 info->has_nickname = 1;
139
140 /* Get bit rate */
141 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
142 {
143 info->has_bitrate = 1;
144 memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
145 }
146
147 /* Get RTS threshold */
148 if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
149 {
150 info->has_rts = 1;
151 memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
152 }
153
154 /* Get fragmentation threshold */
155 if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
156 {
157 info->has_frag = 1;
158 memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
159 }
160
161 /* Get operation mode */
162 if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
163 {
164 info->mode = wrq.u.mode;
165 if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
166 info->has_mode = 1;
167 }
168
169 /* Get Power Management settings */
170 wrq.u.power.flags = 0;
171 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
172 {
173 info->has_power = 1;
174 memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
175 }
176
177#if WIRELESS_EXT > 9
178 /* Get Transmit Power */
179 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
180 {
181 info->has_txpower = 1;
182 memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
183 }
184#endif
185
186#if WIRELESS_EXT > 10
187 /* Get retry limit/lifetime */
188 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
189 {
190 info->has_retry = 1;
191 memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
192 }
193#endif /* WIRELESS_EXT > 10 */
194
195 /* Get stats */
196 if(iw_get_stats(skfd, ifname, &(info->stats)) >= 0)
197 {
198 info->has_stats = 1;
199 }
200
201 return(0);
202}
203
204/*------------------------------------------------------------------*/
205/*
206 * Print on the screen in a neat fashion all the info we have collected
207 * on a device.
208 */
209static void
210display_info(struct wireless_info * info,
211 char * ifname)
212{
213 char buffer[128]; /* Temporary buffer */
214
215 /* One token is more of less 5 characters, 14 tokens per line */
216 int tokens = 3; /* For name */
217
218 /* Display device name and wireless name (name of the protocol used) */
219 printf("%-8.8s %s ", ifname, info->name);
220
221 /* Display ESSID (extended network), if any */
222 if(info->has_essid)
223 {
224 if(info->essid_on)
225 {
226 /* Does it have an ESSID index ? */
227 if((info->essid_on & IW_ENCODE_INDEX) > 1)
228 printf("ESSID:\"%s\" [%d] ", info->essid,
229 (info->essid_on & IW_ENCODE_INDEX));
230 else
231 printf("ESSID:\"%s\" ", info->essid);
232 }
233 else
234 printf("ESSID:off/any ");
235 }
236
237 /* Display NickName (station name), if any */
238 if(info->has_nickname)
239 printf("Nickname:\"%s\"", info->nickname);
240
241 /* Formatting */
242 if(info->has_essid || info->has_nickname)
243 {
244 printf("\n ");
245 tokens = 0;
246 }
247
248 /* Display Network ID */
249 if(info->has_nwid)
250 {
251 /* Note : should display proper number of digit according to info
252 * in range structure */
253 if(info->nwid.disabled)
254 printf("NWID:off/any ");
255 else
256 printf("NWID:%X ", info->nwid.value);
257 tokens +=2;
258 }
259
260 /* Display the current mode of operation */
261 if(info->has_mode)
262 {
263 printf("Mode:%s ", iw_operation_mode[info->mode]);
264 tokens +=3;
265 }
266
267 /* Display frequency / channel */
268 if(info->has_freq)
269 {
270 iw_print_freq(buffer, info->freq);
271 printf("%s ", buffer);
272 tokens +=4;
273 }
274
275 /* Display the address of the current Access Point */
276 if(info->has_ap_addr)
277 {
278 /* A bit of clever formatting */
279 if(tokens > 8)
280 {
281 printf("\n ");
282 tokens = 0;
283 }
284 tokens +=6;
285
286 /* Oups ! No Access Point in Ad-Hoc mode */
287 if((info->has_mode) && (info->mode == IW_MODE_ADHOC))
288 printf("Cell:");
289 else
290 printf("Access Point:");
291 printf(" %s ", iw_pr_ether(buffer, (unsigned char *)info->ap_addr.sa_data));
292 }
293
294 /* Display the currently used/set bit-rate */
295 if(info->has_bitrate)
296 {
297 /* A bit of clever formatting */
298 if(tokens > 11)
299 {
300 printf("\n ");
301 tokens = 0;
302 }
303 tokens +=3;
304
305 /* Display it */
306 iw_print_bitrate(buffer, info->bitrate.value);
307 printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
308 }
309
310#if WIRELESS_EXT > 9
311 /* Display the Transmit Power */
312 if(info->has_txpower)
313 {
314 /* A bit of clever formatting */
315 if(tokens > 11)
316 {
317 printf("\n ");
318 tokens = 0;
319 }
320 tokens +=3;
321
322 /* Disabled ? */
323 if(info->txpower.disabled)
324 printf("Tx-Power:off ");
325 else
326 {
327 int dbm;
328
329 /* Fixed ? */
330 if(info->txpower.fixed)
331 printf("Tx-Power=");
332 else
333 printf("Tx-Power:");
334
335 /* Convert everything to dBm */
336 if(info->txpower.flags & IW_TXPOW_MWATT)
337 dbm = iw_mwatt2dbm(info->txpower.value);
338 else
339 dbm = info->txpower.value;
340
341 /* Display */
342 printf("%d dBm ", dbm);
343 }
344 }
345#endif
346
347 /* Display sensitivity */
348 if(info->has_sens)
349 {
350 /* A bit of clever formatting */
351 if(tokens > 10)
352 {
353 printf("\n ");
354 tokens = 0;
355 }
356 tokens +=4;
357
358 /* Fixed ? */
359 if(info->sens.fixed)
360 printf("Sensitivity=");
361 else
362 printf("Sensitivity:");
363
364 if(info->has_range)
365 /* Display in dBm ? */
366 if(info->sens.value < 0)
367 printf("%d dBm ", info->sens.value);
368 else
369 printf("%d/%d ", info->sens.value, info->range.sensitivity);
370 else
371 printf("%d ", info->sens.value);
372 }
373
374 printf("\n ");
375 tokens = 0;
376
377#if WIRELESS_EXT > 10
378 /* Display retry limit/lifetime information */
379 if(info->has_retry)
380 {
381 printf("Retry");
382 /* Disabled ? */
383 if(info->retry.disabled)
384 printf(":off");
385 else
386 {
387 /* Let's check the value and its type */
388 if(info->retry.flags & IW_RETRY_TYPE)
389 {
390 iw_print_retry_value(buffer,
391 info->retry.value, info->retry.flags);
392 printf("%s", buffer);
393 }
394
395 /* Let's check if nothing (simply on) */
396 if(info->retry.flags == IW_RETRY_ON)
397 printf(":on");
398 }
399 printf(" ");
400 tokens += 5; /* Between 3 and 5, depend on flags */
401 }
402#endif /* WIRELESS_EXT > 10 */
403
404 /* Display the RTS threshold */
405 if(info->has_rts)
406 {
407 /* Disabled ? */
408 if(info->rts.disabled)
409 printf("RTS thr:off ");
410 else
411 {
412 /* Fixed ? */
413 if(info->rts.fixed)
414 printf("RTS thr=");
415 else
416 printf("RTS thr:");
417
418 printf("%d B ", info->rts.value);
419 }
420 tokens += 3;
421 }
422
423 /* Display the fragmentation threshold */
424 if(info->has_frag)
425 {
426 /* A bit of clever formatting */
427 if(tokens > 10)
428 {
429 printf("\n ");
430 tokens = 0;
431 }
432 tokens +=4;
433
434 /* Disabled ? */
435 if(info->frag.disabled)
436 printf("Fragment thr:off");
437 else
438 {
439 /* Fixed ? */
440 if(info->frag.fixed)
441 printf("Fragment thr=");
442 else
443 printf("Fragment thr:");
444
445 printf("%d B ", info->frag.value);
446 }
447 }
448
449 /* Formating */
450 if(tokens > 0)
451 printf("\n ");
452
453 /* Display encryption information */
454 /* Note : we display only the "current" key, use iwlist to list all keys */
455 if(info->has_key)
456 {
457 printf("Encryption key:");
458 if((info->key_flags & IW_ENCODE_DISABLED) || (info->key_size == 0))
459 printf("off\n ");
460 else
461 {
462 /* Display the key */
463 iw_print_key(buffer, info->key, info->key_size, info->key_flags);
464 printf("%s", buffer);
465
466 /* Other info... */
467 if((info->key_flags & IW_ENCODE_INDEX) > 1)
468 printf(" [%d]", info->key_flags & IW_ENCODE_INDEX);
469 if(info->key_flags & IW_ENCODE_RESTRICTED)
470 printf(" Encryption mode:restricted");
471 if(info->key_flags & IW_ENCODE_OPEN)
472 printf(" Encryption mode:open");
473 printf("\n ");
474 }
475 }
476
477 /* Display Power Management information */
478 /* Note : we display only one parameter, period or timeout. If a device
479 * (such as HiperLan) has both, the user need to use iwlist... */
480 if(info->has_power) /* I hope the device has power ;-) */
481 {
482 printf("Power Management");
483 /* Disabled ? */
484 if(info->power.disabled)
485 printf(":off\n ");
486 else
487 {
488 /* Let's check the value and its type */
489 if(info->power.flags & IW_POWER_TYPE)
490 {
491 iw_print_pm_value(buffer, info->power.value, info->power.flags);
492 printf("%s ", buffer);
493 }
494
495 /* Let's check the mode */
496 iw_print_pm_mode(buffer, info->power.flags);
497 printf("%s", buffer);
498
499 /* Let's check if nothing (simply on) */
500 if(info->power.flags == IW_POWER_ON)
501 printf(":on");
502 printf("\n ");
503 }
504 }
505
506 /* Display statistics */
507 if(info->has_stats)
508 {
509 info->stats.qual.updated = 0x0; /* Not that reliable, disable */
510 iw_print_stats(buffer, &info->stats.qual, &info->range, info->has_range);
511 printf("Link %s\n", buffer);
512
513#if WIRELESS_EXT > 11
514 printf(" Rx invalid nwid:%d Rx invalid crypt:%d Rx invalid frag:%d\n Tx excessive retries:%d Invalid misc:%d Missed beacon:%d\n",
515 info->stats.discard.nwid,
516 info->stats.discard.code,
517 info->stats.discard.fragment,
518 info->stats.discard.retries,
519 info->stats.discard.misc,
520 info->stats.miss.beacon);
521#else /* WIRELESS_EXT > 11 */
522 printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
523 info->stats.discard.nwid,
524 info->stats.discard.code,
525 info->stats.discard.misc);
526#endif /* WIRELESS_EXT > 11 */
527 }
528
529 printf("\n");
530}
531
532/*------------------------------------------------------------------*/
533/*
534 * Print on the screen in a neat fashion all the info we have collected
535 * on a device.
536 */
537static int
538print_info(int skfd,
539 char * ifname,
540 char * args[],
541 int count)
542{
543 struct wireless_info info;
544 int rc;
545
546 /* Avoid "Unused parameter" warning */
547 args = args; count = count;
548
549 rc = get_info(skfd, ifname, &info);
550 switch(rc)
551 {
552 case 0: /* Success */
553 /* Display it ! */
554 display_info(&info, ifname);
555 break;
556
557 case -ENOTSUP:
558 fprintf(stderr, "%-8.8s no wireless extensions.\n\n",
559 ifname);
560 break;
561
562 default:
563 fprintf(stderr, "%-8.8s %s\n\n", ifname, strerror(-rc));
564 }
565 return(rc);
566}
567
568/************************* SETTING ROUTINES **************************/
569
570/*------------------------------------------------------------------*/
571/*
572 * Macro to handle errors when setting WE
573 * Print a nice error message and exit...
574 * We define them as macro so that "return" do the right thing.
575 * The "do {...} while(0)" is a standard trick
576 */
577#define ERR_SET_EXT(rname, request) \
578 fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \
579 rname, request)
580
581#define ABORT_ARG_NUM(rname, request) \
582 do { \
583 ERR_SET_EXT(rname, request); \
584 fprintf(stderr, " too few arguments.\n"); \
585 return(-1); \
586 } while(0)
587
588#define ABORT_ARG_TYPE(rname, request, arg) \
589 do { \
590 ERR_SET_EXT(rname, request); \
591 fprintf(stderr, " invalid argument \"%s\".\n", arg); \
592 return(-2); \
593 } while(0)
594
595#define ABORT_ARG_SIZE(rname, request, max) \
596 do { \
597 ERR_SET_EXT(rname, request); \
598 fprintf(stderr, " argument too big (max %d)\n", max); \
599 return(-3); \
600 } while(0)
601
602/*------------------------------------------------------------------*/
603/*
604 * Wrapper to push some Wireless Parameter in the driver
605 * Use standard wrapper and add pretty error message if fail...
606 */
607#define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \
608 do { \
609 if(iw_set_ext(skfd, ifname, request, wrq) < 0) { \
610 ERR_SET_EXT(rname, request); \
611 fprintf(stderr, " SET failed on device %-1.8s ; %s.\n", \
612 ifname, strerror(errno)); \
613 return(-5); \
614 } } while(0)
615
616/*------------------------------------------------------------------*/
617/*
618 * Wrapper to extract some Wireless Parameter out of the driver
619 * Use standard wrapper and add pretty error message if fail...
620 */
621#define IW_GET_EXT_ERR(skfd, ifname, request, wrq, rname) \
622 do { \
623 if(iw_get_ext(skfd, ifname, request, wrq) < 0) { \
624 ERR_SET_EXT(rname, request); \
625 fprintf(stderr, " GET failed on device %-1.8s ; %s.\n", \
626 ifname, strerror(errno)); \
627 return(-6); \
628 } } while(0)
629
630/*------------------------------------------------------------------*/
631/*
632 * Set the wireless options requested on command line
633 * This function is too long and probably should be split,
634 * because it look like the perfect definition of spaghetti code,
635 * but I'm way to lazy
636 */
637static int
638set_info(int skfd, /* The socket */
639 char * args[], /* Command line args */
640 int count, /* Args count */
641 char * ifname) /* Dev name */
642{
643 struct iwreq wrq;
644 int i;
645
646 /* if nothing after the device name - will never happen */
647 if(count < 1)
648 {
649 fprintf(stderr, "Error : too few arguments.\n");
650 return(-1);
651 }
652
653 /* The other args on the line specify options to be set... */
654 for(i = 0; i < count; i++)
655 {
656 /* ---------- Commit changes to driver ---------- */
657 if(!strncmp(args[i], "commit", 6))
658 {
659 /* No args */
660 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq,
661 "Commit changes");
662 continue;
663 }
664
665 /* ---------- Set network ID ---------- */
666 if((!strcasecmp(args[i], "nwid")) ||
667 (!strcasecmp(args[i], "domain")))
668 {
669 i++;
670 if(i >= count)
671 ABORT_ARG_NUM("Set NWID", SIOCSIWNWID);
672 if((!strcasecmp(args[i], "off")) ||
673 (!strcasecmp(args[i], "any")))
674 wrq.u.nwid.disabled = 1;
675 else
676 if(!strcasecmp(args[i], "on"))
677 {
678 /* Get old nwid */
679 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq,
680 "Set NWID");
681 wrq.u.nwid.disabled = 0;
682 }
683 else
684 if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
685 != 1)
686 ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]);
687 else
688 wrq.u.nwid.disabled = 0;
689 wrq.u.nwid.fixed = 1;
690
691 /* Set new nwid */
692 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq,
693 "Set NWID");
694 continue;
695 }
696
697 /* ---------- Set frequency / channel ---------- */
698 if((!strncmp(args[i], "freq", 4)) ||
699 (!strcmp(args[i], "channel")))
700 {
701 double freq;
702
703 if(++i >= count)
704 ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
705 if(sscanf(args[i], "%lg", &(freq)) != 1)
706 ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]);
707 if(index(args[i], 'G')) freq *= GIGA;
708 if(index(args[i], 'M')) freq *= MEGA;
709 if(index(args[i], 'k')) freq *= KILO;
710
711 iw_float2freq(freq, &(wrq.u.freq));
712
713 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
714 "Set Frequency");
715 continue;
716 }
717
718 /* ---------- Set sensitivity ---------- */
719 if(!strncmp(args[i], "sens", 4))
720 {
721 if(++i >= count)
722 ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS);
723 if(sscanf(args[i], "%d", &(wrq.u.sens.value)) != 1)
724 ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]);
725
726 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq,
727 "Set Sensitivity");
728 continue;
729 }
730
731 /* ---------- Set encryption stuff ---------- */
732 if((!strncmp(args[i], "enc", 3)) ||
733 (!strcmp(args[i], "key")))
734 {
735 unsigned char key[IW_ENCODING_TOKEN_MAX];
736
737 if(++i >= count)
738 ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE);
739
740 if(!strcasecmp(args[i], "on"))
741 {
742 /* Get old encryption information */
743 wrq.u.data.pointer = (caddr_t) key;
744 wrq.u.data.length = 0;
745 wrq.u.data.flags = 0;
746 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq,
747 "Set Encode");
748 wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
749 }
750 else
751 {
752 int gotone = 0;
753 int oldone;
754 int keylen;
755 int temp;
756
757 wrq.u.data.pointer = (caddr_t) NULL;
758 wrq.u.data.flags = 0;
759 wrq.u.data.length = 0;
760
761 /* Allow arguments in any order (it's safe) */
762 do
763 {
764 oldone = gotone;
765
766 /* -- Check for the key -- */
767 if(i < count)
768 {
769 keylen = iw_in_key(args[i], key);
770 if(keylen > 0)
771 {
772 wrq.u.data.length = keylen;
773 wrq.u.data.pointer = (caddr_t) key;
774 ++i;
775 gotone++;
776 }
777 }
778
779 /* -- Check for token index -- */
780 if((i < count) &&
781 (sscanf(args[i], "[%d]", &temp) == 1) &&
782 (temp > 0) && (temp < IW_ENCODE_INDEX))
783 {
784 wrq.u.encoding.flags |= temp;
785 ++i;
786 gotone++;
787 }
788
789 /* -- Check the various flags -- */
790 if((i < count) && (!strcasecmp(args[i], "off")))
791 {
792 wrq.u.data.flags |= IW_ENCODE_DISABLED;
793 ++i;
794 gotone++;
795 }
796 if((i < count) && (!strcasecmp(args[i], "open")))
797 {
798 wrq.u.data.flags |= IW_ENCODE_OPEN;
799 ++i;
800 gotone++;
801 }
802 if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
803 {
804 wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
805 ++i;
806 gotone++;
807 }
808 }
809 while(gotone != oldone);
810
811 /* Pointer is absent in new API */
812 if(wrq.u.data.pointer == NULL)
813 wrq.u.data.flags |= IW_ENCODE_NOKEY;
814
815 /* Check if we have any invalid argument */
816 if(!gotone)
817 ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]);
818 /* Get back to last processed argument */
819 --i;
820 }
821
822 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq,
823 "Set Encode");
824 continue;
825 }
826
827 /* ---------- Set ESSID ---------- */
828 if(!strcasecmp(args[i], "essid"))
829 {
830 char essid[IW_ESSID_MAX_SIZE + 1];
831
832 i++;
833 if(i >= count)
834 ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
835 if((!strcasecmp(args[i], "off")) ||
836 (!strcasecmp(args[i], "any")))
837 {
838 wrq.u.essid.flags = 0;
839 essid[0] = '\0';
840 }
841 else
842 if(!strcasecmp(args[i], "on"))
843 {
844 /* Get old essid */
845 wrq.u.essid.pointer = (caddr_t) essid;
846 wrq.u.essid.length = 0;
847 wrq.u.essid.flags = 0;
848 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq,
849 "Set ESSID");
850 wrq.u.essid.flags = 1;
851 }
852 else
853 /* Check the size of what the user passed us to avoid
854 * buffer overflows */
855 if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
856 ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE);
857 else
858 {
859 int temp;
860
861 wrq.u.essid.flags = 1;
862 strcpy(essid, args[i]); /* Size checked, all clear */
863
864 /* Check for ESSID index */
865 if(((i+1) < count) &&
866 (sscanf(args[i+1], "[%d]", &temp) == 1) &&
867 (temp > 0) && (temp < IW_ENCODE_INDEX))
868 {
869 wrq.u.essid.flags = temp;
870 ++i;
871 }
872 }
873
874 wrq.u.essid.pointer = (caddr_t) essid;
875 wrq.u.essid.length = strlen(essid) + 1;
876 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq,
877 "Set ESSID");
878 continue;
879 }
880
881 /* ---------- Set AP address ---------- */
882 if(!strcasecmp(args[i], "ap"))
883 {
884 if(++i >= count)
885 ABORT_ARG_NUM("Set AP Address", SIOCSIWAP);
886
887 if((!strcasecmp(args[i], "auto")) ||
888 (!strcasecmp(args[i], "any")))
889 {
890 /* Send a broadcast address */
891 iw_broad_ether(&(wrq.u.ap_addr));
892 }
893 else
894 {
895 if(!strcasecmp(args[i], "off"))
896 {
897 /* Send a NULL address */
898 iw_null_ether(&(wrq.u.ap_addr));
899 }
900 else
901 {
902 /* Get the address and check if the interface supports it */
903 if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
904 ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]);
905 }
906 }
907
908 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq,
909 "Set AP Address");
910 continue;
911 }
912
913 /* ---------- Set NickName ---------- */
914 if(!strncmp(args[i], "nick", 4))
915 {
916 i++;
917 if(i >= count)
918 ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN);
919 if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
920 ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE);
921
922 wrq.u.essid.pointer = (caddr_t) args[i];
923 wrq.u.essid.length = strlen(args[i]) + 1;
924 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq,
925 "Set Nickname");
926 continue;
927 }
928
929 /* ---------- Set Bit-Rate ---------- */
930 if((!strncmp(args[i], "bit", 3)) ||
931 (!strcmp(args[i], "rate")))
932 {
933 if(++i >= count)
934 ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE);
935 if(!strcasecmp(args[i], "auto"))
936 {
937 wrq.u.bitrate.value = -1;
938 wrq.u.bitrate.fixed = 0;
939 }
940 else
941 {
942 if(!strcasecmp(args[i], "fixed"))
943 {
944 /* Get old bitrate */
945 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq,
946 "Set Bit Rate");
947 wrq.u.bitrate.fixed = 1;
948 }
949 else /* Should be a numeric value */
950 {
951 double brate;
952
953 if(sscanf(args[i], "%lg", &(brate)) != 1)
954 ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]);
955 if(index(args[i], 'G')) brate *= GIGA;
956 if(index(args[i], 'M')) brate *= MEGA;
957 if(index(args[i], 'k')) brate *= KILO;
958 wrq.u.bitrate.value = (long) brate;
959 wrq.u.bitrate.fixed = 1;
960
961 /* Check for an additional argument */
962 if(((i+1) < count) &&
963 (!strcasecmp(args[i+1], "auto")))
964 {
965 wrq.u.bitrate.fixed = 0;
966 ++i;
967 }
968 if(((i+1) < count) &&
969 (!strcasecmp(args[i+1], "fixed")))
970 {
971 wrq.u.bitrate.fixed = 1;
972 ++i;
973 }
974 }
975 }
976
977 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq,
978 "Set Bit Rate");
979 continue;
980 }
981
982 /* ---------- Set RTS threshold ---------- */
983 if(!strncasecmp(args[i], "rts", 3))
984 {
985 i++;
986 if(i >= count)
987 ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS);
988 wrq.u.rts.value = -1;
989 wrq.u.rts.fixed = 1;
990 wrq.u.rts.disabled = 0;
991 if(!strcasecmp(args[i], "off"))
992 wrq.u.rts.disabled = 1; /* i.e. max size */
993 else
994 if(!strcasecmp(args[i], "auto"))
995 wrq.u.rts.fixed = 0;
996 else
997 {
998 if(!strcasecmp(args[i], "fixed"))
999 {
1000 /* Get old RTS threshold */
1001 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq,
1002 "Set RTS Threshold");
1003 wrq.u.rts.fixed = 1;
1004 }
1005 else /* Should be a numeric value */
1006 if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value))
1007 != 1)
1008 ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]);
1009 }
1010
1011 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq,
1012 "Set RTS Threshold");
1013 continue;
1014 }
1015
1016 /* ---------- Set fragmentation threshold ---------- */
1017 if(!strncmp(args[i], "frag", 4))
1018 {
1019 i++;
1020 if(i >= count)
1021 ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG);
1022 wrq.u.frag.value = -1;
1023 wrq.u.frag.fixed = 1;
1024 wrq.u.frag.disabled = 0;
1025 if(!strcasecmp(args[i], "off"))
1026 wrq.u.frag.disabled = 1; /* i.e. max size */
1027 else
1028 if(!strcasecmp(args[i], "auto"))
1029 wrq.u.frag.fixed = 0;
1030 else
1031 {
1032 if(!strcasecmp(args[i], "fixed"))
1033 {
1034 /* Get old fragmentation threshold */
1035 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq,
1036 "Set Fragmentation Threshold");
1037 wrq.u.frag.fixed = 1;
1038 }
1039 else /* Should be a numeric value */
1040 if(sscanf(args[i], "%ld",
1041 (unsigned long *) &(wrq.u.frag.value))
1042 != 1)
1043 ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG,
1044 args[i]);
1045 }
1046
1047 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq,
1048 "Set Fragmentation Threshold");
1049 continue;
1050 }
1051
1052 /* ---------- Set operation mode ---------- */
1053 if(!strcmp(args[i], "mode"))
1054 {
1055 int k;
1056
1057 i++;
1058 if(i >= count)
1059 ABORT_ARG_NUM("Set Mode", SIOCSIWMODE);
1060
1061 if(sscanf(args[i], "%d", &k) != 1)
1062 {
1063 k = 0;
1064 while((k < IW_NUM_OPER_MODE) &&
1065 strncasecmp(args[i], iw_operation_mode[k], 3))
1066 k++;
1067 }
1068 if((k >= IW_NUM_OPER_MODE) || (k < 0))
1069 ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]);
1070
1071 wrq.u.mode = k;
1072 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq,
1073 "Set Mode");
1074 continue;
1075 }
1076
1077 /* ---------- Set Power Management ---------- */
1078 if(!strncmp(args[i], "power", 3))
1079 {
1080 if(++i >= count)
1081 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1082
1083 if(!strcasecmp(args[i], "off"))
1084 wrq.u.power.disabled = 1; /* i.e. max size */
1085 else
1086 if(!strcasecmp(args[i], "on"))
1087 {
1088 /* Get old Power info */
1089 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq,
1090 "Set Power Management");
1091 wrq.u.power.disabled = 0;
1092 }
1093 else
1094 {
1095 double temp;
1096 int gotone = 0;
1097 /* Default - nope */
1098 wrq.u.power.flags = IW_POWER_ON;
1099 wrq.u.power.disabled = 0;
1100
1101 /* Check value modifier */
1102 if(!strcasecmp(args[i], "min"))
1103 {
1104 wrq.u.power.flags |= IW_POWER_MIN;
1105 if(++i >= count)
1106 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1107 }
1108 else
1109 if(!strcasecmp(args[i], "max"))
1110 {
1111 wrq.u.power.flags |= IW_POWER_MAX;
1112 if(++i >= count)
1113 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1114 }
1115
1116 /* Check value type */
1117 if(!strcasecmp(args[i], "period"))
1118 {
1119 wrq.u.power.flags |= IW_POWER_PERIOD;
1120 if(++i >= count)
1121 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1122 }
1123 else
1124 if(!strcasecmp(args[i], "timeout"))
1125 {
1126 wrq.u.power.flags |= IW_POWER_TIMEOUT;
1127 if(++i >= count)
1128 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1129 }
1130
1131 /* Is there any value to grab ? */
1132 if(sscanf(args[i], "%lg", &(temp)) == 1)
1133 {
1134 temp *= MEGA; /* default = s */
1135 if(index(args[i], 'u')) temp /= MEGA;
1136 if(index(args[i], 'm')) temp /= KILO;
1137 wrq.u.power.value = (long) temp;
1138 if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
1139 wrq.u.power.flags |= IW_POWER_PERIOD;
1140 ++i;
1141 gotone = 1;
1142 }
1143
1144 /* Now, check the mode */
1145 if(i < count)
1146 {
1147 if(!strcasecmp(args[i], "all"))
1148 wrq.u.power.flags |= IW_POWER_ALL_R;
1149 if(!strncasecmp(args[i], "unicast", 4))
1150 wrq.u.power.flags |= IW_POWER_UNICAST_R;
1151 if(!strncasecmp(args[i], "multicast", 5))
1152 wrq.u.power.flags |= IW_POWER_MULTICAST_R;
1153 if(!strncasecmp(args[i], "force", 5))
1154 wrq.u.power.flags |= IW_POWER_FORCE_S;
1155 if(!strcasecmp(args[i], "repeat"))
1156 wrq.u.power.flags |= IW_POWER_REPEATER;
1157 if(wrq.u.power.flags & IW_POWER_MODE)
1158 {
1159 ++i;
1160 gotone = 1;
1161 }
1162 }
1163 if(!gotone)
1164 ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER,
1165 args[i]);
1166 --i;
1167 }
1168
1169 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq,
1170 "Set Power Management");
1171 continue;
1172 }
1173
1174#if WIRELESS_EXT > 9
1175 /* ---------- Set Transmit-Power ---------- */
1176 if(!strncmp(args[i], "txpower", 3))
1177 {
1178 struct iw_range range;
1179
1180 if(++i >= count)
1181 ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW);
1182
1183 /* Extract range info */
1184 if(iw_get_range_info(skfd, ifname, &range) < 0)
1185 memset(&range, 0, sizeof(range));
1186
1187 /* Prepare the request */
1188 wrq.u.txpower.value = -1;
1189 wrq.u.txpower.fixed = 1;
1190 wrq.u.txpower.disabled = 0;
1191 wrq.u.data.flags = IW_TXPOW_DBM;
1192 if(!strcasecmp(args[i], "off"))
1193 wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
1194 else
1195 if(!strcasecmp(args[i], "auto"))
1196 wrq.u.txpower.fixed = 0; /* i.e. use power control */
1197 else
1198 {
1199 if(!strcasecmp(args[i], "fixed"))
1200 {
1201 /* Get old tx-power */
1202 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1203 "Set Tx Power");
1204 wrq.u.txpower.fixed = 1;
1205 }
1206 else /* Should be a numeric value */
1207 {
1208 int power;
1209 int ismwatt = 0;
1210
1211 /* Get the value */
1212 if(sscanf(args[i], "%ld",
1213 (unsigned long *) &(power)) != 1)
1214 ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW, args[i]);
1215
1216 /* Check if milliwatt */
1217 ismwatt = (index(args[i], 'm') != NULL);
1218
1219 /* Convert */
1220 if(range.txpower_capa & IW_TXPOW_MWATT)
1221 {
1222 if(!ismwatt)
1223 power = iw_dbm2mwatt(power);
1224 wrq.u.data.flags = IW_TXPOW_MWATT;
1225 }
1226 else
1227 {
1228 if(ismwatt)
1229 power = iw_mwatt2dbm(power);
1230 wrq.u.data.flags = IW_TXPOW_DBM;
1231 }
1232 wrq.u.bitrate.value = power;
1233
1234 /* Check for an additional argument */
1235 if(((i+1) < count) &&
1236 (!strcasecmp(args[i+1], "auto")))
1237 {
1238 wrq.u.txpower.fixed = 0;
1239 ++i;
1240 }
1241 if(((i+1) < count) &&
1242 (!strcasecmp(args[i+1], "fixed")))
1243 {
1244 wrq.u.txpower.fixed = 1;
1245 ++i;
1246 }
1247 }
1248 }
1249
1250 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq,
1251 "Set Tx Power");
1252 continue;
1253 }
1254#endif
1255
1256#if WIRELESS_EXT > 10
1257 /* ---------- Set Retry limit ---------- */
1258 if(!strncmp(args[i], "retry", 3))
1259 {
1260 double temp;
1261 int gotone = 0;
1262
1263 if(++i >= count)
1264 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1265
1266 /* Default - nope */
1267 wrq.u.retry.flags = IW_RETRY_LIMIT;
1268 wrq.u.retry.disabled = 0;
1269
1270 /* Check value modifier */
1271 if(!strcasecmp(args[i], "min"))
1272 {
1273 wrq.u.retry.flags |= IW_RETRY_MIN;
1274 if(++i >= count)
1275 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1276 }
1277 else
1278 if(!strcasecmp(args[i], "max"))
1279 {
1280 wrq.u.retry.flags |= IW_RETRY_MAX;
1281 if(++i >= count)
1282 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1283 }
1284
1285 /* Check value type */
1286 if(!strcasecmp(args[i], "limit"))
1287 {
1288 wrq.u.retry.flags |= IW_RETRY_LIMIT;
1289 if(++i >= count)
1290 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1291 }
1292 else
1293 if(!strncasecmp(args[i], "lifetime", 4))
1294 {
1295 wrq.u.retry.flags |= IW_RETRY_LIFETIME;
1296 if(++i >= count)
1297 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1298 }
1299
1300 /* Is there any value to grab ? */
1301 if(sscanf(args[i], "%lg", &(temp)) == 1)
1302 {
1303 /* Limit is absolute, on the other hand lifetime is seconds */
1304 if(!(wrq.u.retry.flags & IW_RETRY_LIMIT))
1305 {
1306 /* Normalise lifetime */
1307 temp *= MEGA; /* default = s */
1308 if(index(args[i], 'u')) temp /= MEGA;
1309 if(index(args[i], 'm')) temp /= KILO;
1310 }
1311 wrq.u.retry.value = (long) temp;
1312 ++i;
1313 gotone = 1;
1314 }
1315
1316 if(!gotone)
1317 ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]);
1318 --i;
1319
1320 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq,
1321 "Set Retry Limit");
1322 continue;
1323 }
1324
1325#endif /* WIRELESS_EXT > 10 */
1326
1327 /* ---------- Other ---------- */
1328 /* Here we have an unrecognised arg... */
1329 fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
1330 args[i]);
1331 return(-1);
1332 } /* for(index ... */
1333 return(0);
1334}
1335
1336/******************************* MAIN ********************************/
1337
1338/*------------------------------------------------------------------*/
1339/*
1340 * The main !
1341 */
1342int
1343main(int argc,
1344 char ** argv)
1345{
1346 int skfd; /* generic raw socket desc. */
1347 int goterr = 0;
1348
1349 /* Create a channel to the NET kernel. */
1350 if((skfd = iw_sockets_open()) < 0)
1351 {
1352 perror("socket");
1353 exit(-1);
1354 }
1355
1356 /* No argument : show the list of all device + info */
1357 if(argc == 1)
1358 iw_enum_devices(skfd, &print_info, NULL, 0);
1359 else
1360 /* Special case for help... */
1361 if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
1362 iw_usage();
1363 else
1364 /* Special case for version... */
1365 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
1366 goterr = iw_print_version_info("iwconfig");
1367 else
1368 /* The device name must be the first argument */
1369 if(argc == 2)
1370 print_info(skfd, argv[1], NULL, 0);
1371 else
1372 /* The other args on the line specify options to be set... */
1373 goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
1374
1375 /* Close the socket. */
1376 close(skfd);
1377
1378 return(goterr);
1379}