4 * Jean II - HPLB 97->99 - HPL 99->07
6 * Main code for "iwconfig". This is the generic tool for most
8 * You need to link this code against "iwlib.c" and "-lm".
10 * This file is released under the GPL license.
11 * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
14 #include "iwlib.h" /* Header */
16 /**************************** CONSTANTS ****************************/
19 * Error codes defined for setting args
21 #define IWERR_ARG_NUM -2
22 #define IWERR_ARG_TYPE -3
23 #define IWERR_ARG_SIZE -4
24 #define IWERR_ARG_CONFLICT -5
25 #define IWERR_SET_EXT -6
26 #define IWERR_GET_EXT -7
28 /**************************** VARIABLES ****************************/
31 * Ugly, but deal with errors in set_info() efficiently...
36 /************************* DISPLAY ROUTINES **************************/
38 /*------------------------------------------------------------------*/
40 * Get wireless informations & config from the device driver
41 * We will call all the classical wireless ioctl on the driver through
42 * the socket to know what is supported and to get the settings...
47 struct wireless_info * info)
51 memset((char *) info, 0, sizeof(struct wireless_info));
53 /* Get basic information */
54 if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0)
56 /* If no wireless name : no wireless extensions */
57 /* But let's check if the interface exists at all */
60 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
61 if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
68 if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
72 if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
74 info->has_ap_addr = 1;
75 memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
79 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
81 info->has_bitrate = 1;
82 memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
85 /* Get Power Management settings */
86 wrq.u.power.flags = 0;
87 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
90 memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
94 if(iw_get_stats(skfd, ifname, &(info->stats),
95 &info->range, info->has_range) >= 0)
102 wrq.u.essid.pointer = (caddr_t) info->nickname;
103 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
104 wrq.u.essid.flags = 0;
105 if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
106 if(wrq.u.data.length > 1)
107 info->has_nickname = 1;
109 if((info->has_range) && (info->range.we_version_compiled > 9))
111 /* Get Transmit Power */
112 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
114 info->has_txpower = 1;
115 memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
119 /* Get sensitivity */
120 if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
123 memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
126 if((info->has_range) && (info->range.we_version_compiled > 10))
128 /* Get retry limit/lifetime */
129 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
132 memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
136 /* Get RTS threshold */
137 if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
140 memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
143 /* Get fragmentation threshold */
144 if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
147 memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
149 #endif /* WE_ESSENTIAL */
154 /*------------------------------------------------------------------*/
156 * Print on the screen in a neat fashion all the info we have collected
160 display_info(struct wireless_info * info,
163 char buffer[128]; /* Temporary buffer */
165 /* One token is more of less 5 characters, 14 tokens per line */
166 int tokens = 3; /* For name */
168 /* Display device name and wireless name (name of the protocol used) */
169 printf("%-8.16s %s ", ifname, info->b.name);
171 /* Display ESSID (extended network), if any */
172 if(info->b.has_essid)
176 /* Does it have an ESSID index ? */
177 if((info->b.essid_on & IW_ENCODE_INDEX) > 1)
178 printf("ESSID:\"%s\" [%d] ", info->b.essid,
179 (info->b.essid_on & IW_ENCODE_INDEX));
181 printf("ESSID:\"%s\" ", info->b.essid);
184 printf("ESSID:off/any ");
188 /* Display NickName (station name), if any */
189 if(info->has_nickname)
190 printf("Nickname:\"%s\"", info->nickname);
191 #endif /* WE_ESSENTIAL */
194 if(info->b.has_essid || info->has_nickname)
201 /* Display Network ID */
204 /* Note : should display proper number of digits according to info
205 * in range structure */
206 if(info->b.nwid.disabled)
207 printf("NWID:off/any ");
209 printf("NWID:%X ", info->b.nwid.value);
212 #endif /* WE_ESSENTIAL */
214 /* Display the current mode of operation */
217 printf("Mode:%s ", iw_operation_mode[info->b.mode]);
221 /* Display frequency / channel */
224 double freq = info->b.freq; /* Frequency/channel */
225 int channel = -1; /* Converted to channel */
226 /* Some drivers insist of returning channel instead of frequency.
227 * This fixes them up. Note that, driver should still return
228 * frequency, because other tools depend on it. */
229 if(info->has_range && (freq < KILO))
230 channel = iw_channel_to_freq((int) freq, &freq, &info->range);
232 iw_print_freq(buffer, sizeof(buffer), freq, -1, info->b.freq_flags);
233 printf("%s ", buffer);
237 /* Display the address of the current Access Point */
238 if(info->has_ap_addr)
240 /* A bit of clever formatting */
248 /* Oups ! No Access Point in Ad-Hoc mode */
249 if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC))
252 printf("Access Point:");
253 printf(" %s ", iw_sawap_ntop(&info->ap_addr, buffer));
256 /* Display the currently used/set bit-rate */
257 if(info->has_bitrate)
259 /* A bit of clever formatting */
268 iw_print_bitrate(buffer, sizeof(buffer), info->bitrate.value);
269 printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
273 /* Display the Transmit Power */
274 if(info->has_txpower)
276 /* A bit of clever formatting */
285 iw_print_txpower(buffer, sizeof(buffer), &info->txpower);
286 printf("Tx-Power%c%s ", (info->txpower.fixed ? '=' : ':'), buffer);
289 /* Display sensitivity */
292 /* A bit of clever formatting */
301 printf("Sensitivity%c", info->sens.fixed ? '=' : ':');
304 /* Display in dBm ? */
305 if(info->sens.value < 0)
306 printf("%d dBm ", info->sens.value);
308 printf("%d/%d ", info->sens.value, info->range.sensitivity);
310 printf("%d ", info->sens.value);
312 #endif /* WE_ESSENTIAL */
318 /* Display retry limit/lifetime information */
323 if(info->retry.disabled)
327 /* Let's check the value and its type */
328 if(info->retry.flags & IW_RETRY_TYPE)
330 iw_print_retry_value(buffer, sizeof(buffer),
331 info->retry.value, info->retry.flags,
332 info->range.we_version_compiled);
333 printf("%s", buffer);
336 /* Let's check if nothing (simply on) */
337 if(info->retry.flags == IW_RETRY_ON)
341 tokens += 5; /* Between 3 and 5, depend on flags */
344 /* Display the RTS threshold */
348 if(info->rts.disabled)
349 printf("RTS thr:off ");
353 printf("RTS thr%c%d B ",
354 info->rts.fixed ? '=' : ':',
360 /* Display the fragmentation threshold */
363 /* A bit of clever formatting */
372 if(info->frag.disabled)
373 printf("Fragment thr:off");
377 printf("Fragment thr%c%d B ",
378 info->frag.fixed ? '=' : ':',
386 #endif /* WE_ESSENTIAL */
388 /* Display encryption information */
389 /* Note : we display only the "current" key, use iwlist to list all keys */
392 printf("Encryption key:");
393 if((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0))
397 /* Display the key */
398 iw_print_key(buffer, sizeof(buffer),
399 info->b.key, info->b.key_size, info->b.key_flags);
400 printf("%s", buffer);
403 if((info->b.key_flags & IW_ENCODE_INDEX) > 1)
404 printf(" [%d]", info->b.key_flags & IW_ENCODE_INDEX);
405 if(info->b.key_flags & IW_ENCODE_RESTRICTED)
406 printf(" Security mode:restricted");
407 if(info->b.key_flags & IW_ENCODE_OPEN)
408 printf(" Security mode:open");
413 /* Display Power Management information */
414 /* Note : we display only one parameter, period or timeout. If a device
415 * (such as HiperLan) has both, the user need to use iwlist... */
416 if(info->has_power) /* I hope the device has power ;-) */
418 printf("Power Management");
420 if(info->power.disabled)
424 /* Let's check the value and its type */
425 if(info->power.flags & IW_POWER_TYPE)
427 iw_print_pm_value(buffer, sizeof(buffer),
428 info->power.value, info->power.flags,
429 info->range.we_version_compiled);
430 printf("%s ", buffer);
433 /* Let's check the mode */
434 iw_print_pm_mode(buffer, sizeof(buffer), info->power.flags);
435 printf("%s", buffer);
437 /* Let's check if nothing (simply on) */
438 if(info->power.flags == IW_POWER_ON)
444 /* Display statistics */
447 iw_print_stats(buffer, sizeof(buffer),
448 &info->stats.qual, &info->range, info->has_range);
449 printf("Link %s\n", buffer);
451 if(info->range.we_version_compiled > 11)
452 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",
453 info->stats.discard.nwid,
454 info->stats.discard.code,
455 info->stats.discard.fragment,
456 info->stats.discard.retries,
457 info->stats.discard.misc,
458 info->stats.miss.beacon);
460 printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
461 info->stats.discard.nwid,
462 info->stats.discard.code,
463 info->stats.discard.misc);
469 /*------------------------------------------------------------------*/
471 * Print on the screen in a neat fashion all the info we have collected
480 struct wireless_info info;
483 /* Avoid "Unused parameter" warning */
484 args = args; count = count;
486 rc = get_info(skfd, ifname, &info);
489 case 0: /* Success */
491 display_info(&info, ifname);
495 fprintf(stderr, "%-8.16s no wireless extensions.\n\n",
500 fprintf(stderr, "%-8.16s %s\n\n", ifname, strerror(-rc));
505 /****************** COMMAND LINE MODIFIERS PARSING ******************/
507 * Factor out the parsing of command line modifiers.
510 /*------------------------------------------------------------------*/
512 * Map command line modifiers to the proper flags...
514 typedef struct iwconfig_modifier {
515 const char * cmd; /* Command line shorthand */
516 __u16 flag; /* Flags to add */
517 __u16 exclude; /* Modifiers to exclude */
520 /*------------------------------------------------------------------*/
522 * Modifiers for Power
524 static const struct iwconfig_modifier iwmod_power[] = {
525 { "min", IW_POWER_MIN, IW_POWER_MAX },
526 { "max", IW_POWER_MAX, IW_POWER_MIN },
527 { "period", IW_POWER_PERIOD, IW_POWER_TIMEOUT | IW_POWER_SAVING },
528 { "timeout", IW_POWER_TIMEOUT, IW_POWER_PERIOD | IW_POWER_SAVING },
529 { "saving", IW_POWER_SAVING, IW_POWER_TIMEOUT | IW_POWER_PERIOD },
531 #define IWMOD_POWER_NUM (sizeof(iwmod_power)/sizeof(iwmod_power[0]))
533 /*------------------------------------------------------------------*/
535 * Modifiers for Retry
538 static const struct iwconfig_modifier iwmod_retry[] = {
539 { "min", IW_RETRY_MIN, IW_RETRY_MAX },
540 { "max", IW_RETRY_MAX, IW_RETRY_MIN },
541 { "short", IW_RETRY_SHORT, IW_RETRY_LONG },
542 { "long", IW_RETRY_LONG, IW_RETRY_SHORT },
543 { "limit", IW_RETRY_LIMIT, IW_RETRY_LIFETIME },
544 { "lifetime", IW_RETRY_LIFETIME, IW_RETRY_LIMIT },
546 #define IWMOD_RETRY_NUM (sizeof(iwmod_retry)/sizeof(iwmod_retry[0]))
547 #endif /* WE_ESSENTIAL */
549 /*------------------------------------------------------------------*/
551 * Parse command line modifiers.
552 * Return error or number arg parsed.
553 * Modifiers must be at the beggining of command line.
556 parse_modifiers(char * args[], /* Command line args */
557 int count, /* Args count */
558 __u16 * pout, /* Flags to write */
559 const struct iwconfig_modifier modifier[],
564 __u16 result = 0; /* Default : no flag set */
566 /* Get all modifiers and value types on the command line */
569 for(k = 0; k < modnum; k++)
571 /* Check if matches */
572 if(!strcasecmp(args[i], modifier[k].cmd))
574 /* Check for conflicting flags */
575 if(result & modifier[k].exclude)
578 return(IWERR_ARG_CONFLICT);
581 result |= modifier[k].flag;
587 /* For as long as current arg matched and not out of args */
588 while((i < count) && (k < modnum));
590 /* Check there remains one arg for value */
592 return(IWERR_ARG_NUM);
600 /*********************** SETTING SUB-ROUTINES ***********************/
602 * The following functions are use to set some wireless parameters and
603 * are called by the set dispatcher set_info().
604 * They take as arguments the remaining of the command line, with
605 * arguments processed already removed.
606 * An error is indicated by a negative return value.
607 * 0 and positive return values indicate the number of args consumed.
610 /*------------------------------------------------------------------*/
615 set_essid_info(int skfd,
617 char * args[], /* Command line args */
618 int count) /* Args count */
622 char essid[IW_ESSID_MAX_SIZE + 1];
623 int we_kernel_version;
625 if((!strcasecmp(args[0], "off")) ||
626 (!strcasecmp(args[0], "any")))
628 wrq.u.essid.flags = 0;
632 if(!strcasecmp(args[0], "on"))
635 memset(essid, '\0', sizeof(essid));
636 wrq.u.essid.pointer = (caddr_t) essid;
637 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
638 wrq.u.essid.flags = 0;
639 if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0)
640 return(IWERR_GET_EXT);
641 wrq.u.essid.flags = 1;
647 /* '-' or '--' allow to escape the ESSID string, allowing
648 * to set it to the string "any" or "off".
649 * This is a big ugly, but it will do for now */
650 if((!strcmp(args[0], "-")) || (!strcmp(args[0], "--")))
653 return(IWERR_ARG_NUM);
656 /* Check the size of what the user passed us to avoid
657 * buffer overflows */
658 if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
660 errmax = IW_ESSID_MAX_SIZE;
661 return(IWERR_ARG_SIZE);
667 wrq.u.essid.flags = 1;
668 strcpy(essid, args[i]); /* Size checked, all clear */
671 /* Check for ESSID index */
673 (sscanf(args[i], "[%i]", &temp) == 1) &&
674 (temp > 0) && (temp < IW_ENCODE_INDEX))
676 wrq.u.essid.flags = temp;
682 /* Get version from kernel, device may not have range... */
683 we_kernel_version = iw_get_kernel_we_version();
685 /* Finally set the ESSID value */
686 wrq.u.essid.pointer = (caddr_t) essid;
687 wrq.u.essid.length = strlen(essid);
688 if(we_kernel_version < 21)
689 wrq.u.essid.length++;
691 if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
692 return(IWERR_SET_EXT);
698 /*------------------------------------------------------------------*/
703 set_mode_info(int skfd,
705 char * args[], /* Command line args */
706 int count) /* Args count */
709 unsigned int k; /* Must be unsigned */
711 /* Avoid "Unused parameter" warning */
714 /* Check if it is a uint, otherwise get is as a string */
715 if(sscanf(args[0], "%i", &k) != 1)
718 while((k < IW_NUM_OPER_MODE) &&
719 strncasecmp(args[0], iw_operation_mode[k], 3))
722 if(k >= IW_NUM_OPER_MODE)
725 return(IWERR_ARG_TYPE);
729 if(iw_set_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
730 return(IWERR_SET_EXT);
736 /*------------------------------------------------------------------*/
738 * Set frequency/channel
741 set_freq_info(int skfd,
743 char * args[], /* Command line args */
744 int count) /* Args count */
749 if(!strcasecmp(args[0], "auto"))
753 wrq.u.freq.flags = 0;
757 if(!strcasecmp(args[0], "fixed"))
759 /* Get old frequency */
760 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
761 return(IWERR_GET_EXT);
762 wrq.u.freq.flags = IW_FREQ_FIXED;
764 else /* Should be a numeric value */
769 freq = strtod(args[0], &unit);
773 return(IWERR_ARG_TYPE);
777 if(unit[0] == 'G') freq *= GIGA;
778 if(unit[0] == 'M') freq *= MEGA;
779 if(unit[0] == 'k') freq *= KILO;
782 iw_float2freq(freq, &(wrq.u.freq));
784 wrq.u.freq.flags = IW_FREQ_FIXED;
786 /* Check for an additional argument */
787 if((i < count) && (!strcasecmp(args[i], "auto")))
789 wrq.u.freq.flags = 0;
792 if((i < count) && (!strcasecmp(args[i], "fixed")))
794 wrq.u.freq.flags = IW_FREQ_FIXED;
800 if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
801 return(IWERR_SET_EXT);
807 /*------------------------------------------------------------------*/
812 set_bitrate_info(int skfd,
814 char * args[], /* Command line args */
815 int count) /* Args count */
820 wrq.u.bitrate.flags = 0;
821 if(!strcasecmp(args[0], "auto"))
823 wrq.u.bitrate.value = -1;
824 wrq.u.bitrate.fixed = 0;
828 if(!strcasecmp(args[0], "fixed"))
830 /* Get old bitrate */
831 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) < 0)
832 return(IWERR_GET_EXT);
833 wrq.u.bitrate.fixed = 1;
835 else /* Should be a numeric value */
840 brate = strtod(args[0], &unit);
844 return(IWERR_ARG_TYPE);
848 if(unit[0] == 'G') brate *= GIGA;
849 if(unit[0] == 'M') brate *= MEGA;
850 if(unit[0] == 'k') brate *= KILO;
852 wrq.u.bitrate.value = (long) brate;
853 wrq.u.bitrate.fixed = 1;
855 /* Check for an additional argument */
856 if((i < count) && (!strcasecmp(args[i], "auto")))
858 wrq.u.bitrate.fixed = 0;
861 if((i < count) && (!strcasecmp(args[i], "fixed")))
863 wrq.u.bitrate.fixed = 1;
866 if((i < count) && (!strcasecmp(args[i], "unicast")))
868 wrq.u.bitrate.flags |= IW_BITRATE_UNICAST;
871 if((i < count) && (!strcasecmp(args[i], "broadcast")))
873 wrq.u.bitrate.flags |= IW_BITRATE_BROADCAST;
879 if(iw_set_ext(skfd, ifname, SIOCSIWRATE, &wrq) < 0)
880 return(IWERR_SET_EXT);
886 /*------------------------------------------------------------------*/
891 set_enc_info(int skfd,
893 char * args[], /* Command line args */
894 int count) /* Args count */
898 unsigned char key[IW_ENCODING_TOKEN_MAX];
900 if(!strcasecmp(args[0], "on"))
902 /* Get old encryption information */
903 wrq.u.data.pointer = (caddr_t) key;
904 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
905 wrq.u.data.flags = 0;
906 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
907 return(IWERR_GET_EXT);
908 wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
917 wrq.u.data.pointer = (caddr_t) NULL;
918 wrq.u.data.flags = 0;
919 wrq.u.data.length = 0;
922 /* Allow arguments in any order (it's safe) */
927 /* -- Check for the key -- */
930 keylen = iw_in_key_full(skfd, ifname,
931 args[i], key, &wrq.u.data.flags);
934 wrq.u.data.length = keylen;
935 wrq.u.data.pointer = (caddr_t) key;
941 /* -- Check for token index -- */
943 (sscanf(args[i], "[%i]", &temp) == 1) &&
944 (temp > 0) && (temp < IW_ENCODE_INDEX))
946 wrq.u.encoding.flags |= temp;
951 /* -- Check the various flags -- */
952 if((i < count) && (!strcasecmp(args[i], "off")))
954 wrq.u.data.flags |= IW_ENCODE_DISABLED;
958 if((i < count) && (!strcasecmp(args[i], "open")))
960 wrq.u.data.flags |= IW_ENCODE_OPEN;
964 if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
966 wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
970 if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
972 wrq.u.data.flags |= IW_ENCODE_TEMP;
977 while(gotone != oldone);
979 /* Pointer is absent in new API */
980 if(wrq.u.data.pointer == NULL)
981 wrq.u.data.flags |= IW_ENCODE_NOKEY;
983 /* Check if we have any invalid argument */
987 return(IWERR_ARG_TYPE);
991 if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
992 return(IWERR_SET_EXT);
998 /*------------------------------------------------------------------*/
1000 * Set Power Management
1003 set_power_info(int skfd,
1005 char * args[], /* Command line args */
1006 int count) /* Args count */
1011 if(!strcasecmp(args[0], "off"))
1012 wrq.u.power.disabled = 1; /* i.e. max size */
1014 if(!strcasecmp(args[0], "on"))
1016 /* Get old Power info */
1017 wrq.u.power.flags = 0;
1018 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) < 0)
1019 return(IWERR_GET_EXT);
1020 wrq.u.power.disabled = 0;
1028 /* Parse modifiers */
1029 i = parse_modifiers(args, count, &wrq.u.power.flags,
1030 iwmod_power, IWMOD_POWER_NUM);
1034 wrq.u.power.disabled = 0;
1036 /* Is there any value to grab ? */
1037 value = strtod(args[0], &unit);
1040 struct iw_range range;
1042 /* Extract range info to handle properly 'relative' */
1043 if(iw_get_range_info(skfd, ifname, &range) < 0)
1044 memset(&range, 0, sizeof(range));
1046 /* Get the flags to be able to do the proper conversion */
1047 switch(wrq.u.power.flags & IW_POWER_TYPE)
1049 case IW_POWER_SAVING:
1050 flags = range.pms_flags;
1052 case IW_POWER_TIMEOUT:
1053 flags = range.pmt_flags;
1056 flags = range.pmp_flags;
1059 /* Check if time or relative */
1060 if(flags & IW_POWER_RELATIVE)
1062 if(range.we_version_compiled < 21)
1065 wrq.u.power.flags |= IW_POWER_RELATIVE;
1069 value *= MEGA; /* default = s */
1070 if(unit[0] == 'u') value /= MEGA;
1071 if(unit[0] == 'm') value /= KILO;
1073 wrq.u.power.value = (long) value;
1074 /* Set some default type if none */
1075 if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
1076 wrq.u.power.flags |= IW_POWER_PERIOD;
1081 /* Now, check the mode */
1084 if(!strcasecmp(args[i], "all"))
1085 wrq.u.power.flags |= IW_POWER_ALL_R;
1086 if(!strncasecmp(args[i], "unicast", 4))
1087 wrq.u.power.flags |= IW_POWER_UNICAST_R;
1088 if(!strncasecmp(args[i], "multicast", 5))
1089 wrq.u.power.flags |= IW_POWER_MULTICAST_R;
1090 if(!strncasecmp(args[i], "force", 5))
1091 wrq.u.power.flags |= IW_POWER_FORCE_S;
1092 if(!strcasecmp(args[i], "repeat"))
1093 wrq.u.power.flags |= IW_POWER_REPEATER;
1094 if(wrq.u.power.flags & IW_POWER_MODE)
1103 return(IWERR_ARG_TYPE);
1107 if(iw_set_ext(skfd, ifname, SIOCSIWPOWER, &wrq) < 0)
1108 return(IWERR_SET_EXT);
1114 #ifndef WE_ESSENTIAL
1115 /*------------------------------------------------------------------*/
1120 set_nick_info(int skfd,
1122 char * args[], /* Command line args */
1123 int count) /* Args count */
1126 int we_kernel_version;
1128 /* Avoid "Unused parameter" warning */
1131 if(strlen(args[0]) > IW_ESSID_MAX_SIZE)
1133 errmax = IW_ESSID_MAX_SIZE;
1134 return(IWERR_ARG_SIZE);
1137 we_kernel_version = iw_get_kernel_we_version();
1139 wrq.u.essid.pointer = (caddr_t) args[0];
1140 wrq.u.essid.length = strlen(args[0]);
1141 if(we_kernel_version < 21)
1142 wrq.u.essid.length++;
1144 if(iw_set_ext(skfd, ifname, SIOCSIWNICKN, &wrq) < 0)
1145 return(IWERR_SET_EXT);
1151 /*------------------------------------------------------------------*/
1156 set_nwid_info(int skfd,
1158 char * args[], /* Command line args */
1159 int count) /* Args count */
1164 /* Avoid "Unused parameter" warning */
1167 if((!strcasecmp(args[0], "off")) ||
1168 (!strcasecmp(args[0], "any")))
1169 wrq.u.nwid.disabled = 1;
1171 if(!strcasecmp(args[0], "on"))
1174 if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0)
1175 return(IWERR_GET_EXT);
1176 wrq.u.nwid.disabled = 0;
1179 if(sscanf(args[0], "%lX", &(temp)) != 1)
1182 return(IWERR_ARG_TYPE);
1186 wrq.u.nwid.value = temp;
1187 wrq.u.nwid.disabled = 0;
1190 wrq.u.nwid.fixed = 1;
1193 if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
1194 return(IWERR_SET_EXT);
1200 /*------------------------------------------------------------------*/
1205 set_apaddr_info(int skfd,
1207 char * args[], /* Command line args */
1208 int count) /* Args count */
1212 /* Avoid "Unused parameter" warning */
1215 if((!strcasecmp(args[0], "auto")) ||
1216 (!strcasecmp(args[0], "any")))
1218 /* Send a broadcast address */
1219 iw_broad_ether(&(wrq.u.ap_addr));
1223 if(!strcasecmp(args[0], "off"))
1225 /* Send a NULL address */
1226 iw_null_ether(&(wrq.u.ap_addr));
1230 /* Get the address and check if the interface supports it */
1231 if(iw_in_addr(skfd, ifname, args[0], &(wrq.u.ap_addr)) < 0)
1234 return(IWERR_ARG_TYPE);
1239 if(iw_set_ext(skfd, ifname, SIOCSIWAP, &wrq) < 0)
1240 return(IWERR_SET_EXT);
1246 /*------------------------------------------------------------------*/
1251 set_txpower_info(int skfd,
1253 char * args[], /* Command line args */
1254 int count) /* Args count */
1259 /* Avoid "Unused parameter" warning */
1260 args = args; count = count;
1262 /* Prepare the request */
1263 wrq.u.txpower.value = -1;
1264 wrq.u.txpower.fixed = 1;
1265 wrq.u.txpower.disabled = 0;
1266 wrq.u.txpower.flags = IW_TXPOW_DBM;
1268 if(!strcasecmp(args[0], "off"))
1269 wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
1271 if(!strcasecmp(args[0], "auto"))
1272 wrq.u.txpower.fixed = 0; /* i.e. use power control */
1275 if(!strcasecmp(args[0], "on"))
1277 /* Get old tx-power */
1278 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
1279 return(IWERR_GET_EXT);
1280 wrq.u.txpower.disabled = 0;
1284 if(!strcasecmp(args[0], "fixed"))
1286 /* Get old tx-power */
1287 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
1288 return(IWERR_GET_EXT);
1289 wrq.u.txpower.fixed = 1;
1290 wrq.u.txpower.disabled = 0;
1292 else /* Should be a numeric value */
1296 struct iw_range range;
1298 /* Extract range info to do proper conversion */
1299 if(iw_get_range_info(skfd, ifname, &range) < 0)
1300 memset(&range, 0, sizeof(range));
1303 if(sscanf(args[0], "%i", &(power)) != 1)
1306 return(IWERR_ARG_TYPE);
1309 /* Check if milliWatt
1310 * We authorise a single 'm' as a shorthand for 'mW',
1311 * on the other hand a 'd' probably means 'dBm'... */
1312 ismwatt = ((strchr(args[0], 'm') != NULL)
1313 && (strchr(args[0], 'd') == NULL));
1315 /* We could check 'W' alone... Another time... */
1318 if(range.txpower_capa & IW_TXPOW_RELATIVE)
1324 return(IWERR_ARG_TYPE);
1326 wrq.u.txpower.flags = IW_TXPOW_RELATIVE;
1329 if(range.txpower_capa & IW_TXPOW_MWATT)
1332 power = iw_dbm2mwatt(power);
1333 wrq.u.txpower.flags = IW_TXPOW_MWATT;
1338 power = iw_mwatt2dbm(power);
1339 wrq.u.txpower.flags = IW_TXPOW_DBM;
1341 wrq.u.txpower.value = power;
1343 /* Check for an additional argument */
1344 if((i < count) && (!strcasecmp(args[i], "auto")))
1346 wrq.u.txpower.fixed = 0;
1349 if((i < count) && (!strcasecmp(args[i], "fixed")))
1351 wrq.u.txpower.fixed = 1;
1358 if(iw_set_ext(skfd, ifname, SIOCSIWTXPOW, &wrq) < 0)
1359 return(IWERR_SET_EXT);
1365 /*------------------------------------------------------------------*/
1370 set_sens_info(int skfd,
1372 char * args[], /* Command line args */
1373 int count) /* Args count */
1378 /* Avoid "Unused parameter" warning */
1381 if(sscanf(args[0], "%i", &(temp)) != 1)
1384 return(IWERR_ARG_TYPE);
1386 wrq.u.sens.value = temp;
1388 if(iw_set_ext(skfd, ifname, SIOCSIWSENS, &wrq) < 0)
1389 return(IWERR_SET_EXT);
1395 /*------------------------------------------------------------------*/
1400 set_retry_info(int skfd,
1402 char * args[], /* Command line args */
1403 int count) /* Args count */
1410 /* Parse modifiers */
1411 i = parse_modifiers(args, count, &wrq.u.retry.flags,
1412 iwmod_retry, IWMOD_RETRY_NUM);
1416 /* Add default type if none */
1417 if((wrq.u.retry.flags & IW_RETRY_TYPE) == 0)
1418 wrq.u.retry.flags |= IW_RETRY_LIMIT;
1420 wrq.u.retry.disabled = 0;
1422 /* Is there any value to grab ? */
1423 value = strtod(args[0], &unit);
1427 return(IWERR_ARG_TYPE);
1430 /* Limit is absolute, on the other hand lifetime is seconds */
1431 if(wrq.u.retry.flags & IW_RETRY_LIFETIME)
1433 struct iw_range range;
1434 /* Extract range info to handle properly 'relative' */
1435 if(iw_get_range_info(skfd, ifname, &range) < 0)
1436 memset(&range, 0, sizeof(range));
1438 if(range.r_time_flags & IW_RETRY_RELATIVE)
1440 if(range.we_version_compiled < 21)
1443 wrq.u.retry.flags |= IW_RETRY_RELATIVE;
1447 /* Normalise lifetime */
1448 value *= MEGA; /* default = s */
1449 if(unit[0] == 'u') value /= MEGA;
1450 if(unit[0] == 'm') value /= KILO;
1453 wrq.u.retry.value = (long) value;
1456 if(iw_set_ext(skfd, ifname, SIOCSIWRETRY, &wrq) < 0)
1457 return(IWERR_SET_EXT);
1463 /*------------------------------------------------------------------*/
1468 set_rts_info(int skfd,
1470 char * args[], /* Command line args */
1471 int count) /* Args count */
1475 /* Avoid "Unused parameter" warning */
1478 wrq.u.rts.value = -1;
1479 wrq.u.rts.fixed = 1;
1480 wrq.u.rts.disabled = 0;
1482 if(!strcasecmp(args[0], "off"))
1483 wrq.u.rts.disabled = 1; /* i.e. max size */
1485 if(!strcasecmp(args[0], "auto"))
1486 wrq.u.rts.fixed = 0;
1489 if(!strcasecmp(args[0], "fixed"))
1491 /* Get old RTS threshold */
1492 if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) < 0)
1493 return(IWERR_GET_EXT);
1494 wrq.u.rts.fixed = 1;
1497 { /* Should be a numeric value */
1499 if(sscanf(args[0], "%li", (unsigned long *) &(temp)) != 1)
1502 return(IWERR_ARG_TYPE);
1504 wrq.u.rts.value = temp;
1508 if(iw_set_ext(skfd, ifname, SIOCSIWRTS, &wrq) < 0)
1509 return(IWERR_SET_EXT);
1515 /*------------------------------------------------------------------*/
1517 * Set Fragmentation Threshold
1520 set_frag_info(int skfd,
1522 char * args[], /* Command line args */
1523 int count) /* Args count */
1527 /* Avoid "Unused parameter" warning */
1530 wrq.u.frag.value = -1;
1531 wrq.u.frag.fixed = 1;
1532 wrq.u.frag.disabled = 0;
1534 if(!strcasecmp(args[0], "off"))
1535 wrq.u.frag.disabled = 1; /* i.e. max size */
1537 if(!strcasecmp(args[0], "auto"))
1538 wrq.u.frag.fixed = 0;
1541 if(!strcasecmp(args[0], "fixed"))
1543 /* Get old fragmentation threshold */
1544 if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) < 0)
1545 return(IWERR_GET_EXT);
1546 wrq.u.frag.fixed = 1;
1549 { /* Should be a numeric value */
1551 if(sscanf(args[0], "%li", &(temp))
1555 return(IWERR_ARG_TYPE);
1557 wrq.u.frag.value = temp;
1561 if(iw_set_ext(skfd, ifname, SIOCSIWFRAG, &wrq) < 0)
1562 return(IWERR_SET_EXT);
1568 /*------------------------------------------------------------------*/
1573 set_modulation_info(int skfd,
1575 char * args[], /* Command line args */
1576 int count) /* Args count */
1581 /* Avoid "Unused parameter" warning */
1582 args = args; count = count;
1584 if(!strcasecmp(args[0], "auto"))
1585 wrq.u.param.fixed = 0; /* i.e. use any modulation */
1588 if(!strcasecmp(args[0], "fixed"))
1590 /* Get old modulation */
1591 if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) < 0)
1592 return(IWERR_GET_EXT);
1593 wrq.u.param.fixed = 1;
1599 /* Allow multiple modulations, combine them together */
1600 wrq.u.param.value = 0x0;
1604 for(k = 0; k < IW_SIZE_MODUL_LIST; k++)
1606 if(!strcasecmp(args[i], iw_modul_list[k].cmd))
1608 wrq.u.param.value |= iw_modul_list[k].mask;
1614 /* For as long as current arg matched and not out of args */
1615 while((i < count) && (k < IW_SIZE_MODUL_LIST));
1617 /* Check we got something */
1621 return(IWERR_ARG_TYPE);
1624 /* Check for an additional argument */
1625 if((i < count) && (!strcasecmp(args[i], "auto")))
1627 wrq.u.param.fixed = 0;
1630 if((i < count) && (!strcasecmp(args[i], "fixed")))
1632 wrq.u.param.fixed = 1;
1638 if(iw_set_ext(skfd, ifname, SIOCSIWMODUL, &wrq) < 0)
1639 return(IWERR_SET_EXT);
1644 #endif /* WE_ESSENTIAL */
1646 /*------------------------------------------------------------------*/
1651 set_commit_info(int skfd,
1653 char * args[], /* Command line args */
1654 int count) /* Args count */
1658 /* Avoid "Unused parameter" warning */
1659 args = args; count = count;
1661 if(iw_set_ext(skfd, ifname, SIOCSIWCOMMIT, &wrq) < 0)
1662 return(IWERR_SET_EXT);
1668 /************************** SET DISPATCHER **************************/
1670 * This is a modified version of the dispatcher in iwlist.
1671 * The main difference is that here we may have multiple commands per
1672 * line. Also, most commands here do take arguments, and most often
1673 * a variable number of them.
1674 * Therefore, the handler *must* return how many args were consumed...
1676 * Note that the use of multiple commands per line is not advised
1677 * in scripts, as it makes error management hard. All commands before
1678 * the error are executed, but commands after the error are not
1680 * We also try to give as much clue as possible via stderr to the caller
1681 * on which command did fail, but if there are two time the same command,
1682 * you don't know which one failed...
1685 /*------------------------------------------------------------------*/
1687 * Map command line arguments to the proper procedure...
1689 typedef struct iwconfig_entry {
1690 const char * cmd; /* Command line shorthand */
1691 iw_enum_handler fn; /* Subroutine */
1693 int request; /* WE numerical ID */
1694 const char * name; /* Human readable string */
1695 const char * argsname; /* Args as human readable string */
1698 static const struct iwconfig_entry iwconfig_cmds[] = {
1699 { "essid", set_essid_info, 1, SIOCSIWESSID,
1700 "Set ESSID", "{NNN|any|on|off}" },
1701 { "mode", set_mode_info, 1, SIOCSIWMODE,
1702 "Set Mode", "{managed|ad-hoc|master|...}" },
1703 { "freq", set_freq_info, 1, SIOCSIWFREQ,
1704 "Set Frequency", "N.NNN[k|M|G]" },
1705 { "channel", set_freq_info, 1, SIOCSIWFREQ,
1706 "Set Frequency", "N" },
1707 { "bit", set_bitrate_info, 1, SIOCSIWRATE,
1708 "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
1709 { "rate", set_bitrate_info, 1, SIOCSIWRATE,
1710 "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
1711 { "enc", set_enc_info, 1, SIOCSIWENCODE,
1712 "Set Encode", "{NNNN-NNNN|off}" },
1713 { "key", set_enc_info, 1, SIOCSIWENCODE,
1714 "Set Encode", "{NNNN-NNNN|off}" },
1715 { "power", set_power_info, 1, SIOCSIWPOWER,
1716 "Set Power Management", "{period N|timeout N|saving N|off}" },
1717 #ifndef WE_ESSENTIAL
1718 { "nickname", set_nick_info, 1, SIOCSIWNICKN,
1719 "Set Nickname", "NNN" },
1720 { "nwid", set_nwid_info, 1, SIOCSIWNWID,
1721 "Set NWID", "{NN|on|off}" },
1722 { "ap", set_apaddr_info, 1, SIOCSIWAP,
1723 "Set AP Address", "{N|off|auto}" },
1724 { "txpower", set_txpower_info, 1, SIOCSIWTXPOW,
1725 "Set Tx Power", "{NmW|NdBm|off|auto}" },
1726 { "sens", set_sens_info, 1, SIOCSIWSENS,
1727 "Set Sensitivity", "N" },
1728 { "retry", set_retry_info, 1, SIOCSIWRETRY,
1729 "Set Retry Limit", "{limit N|lifetime N}" },
1730 { "rts", set_rts_info, 1, SIOCSIWRTS,
1731 "Set RTS Threshold", "{N|auto|fixed|off}" },
1732 { "frag", set_frag_info, 1, SIOCSIWFRAG,
1733 "Set Fragmentation Threshold", "{N|auto|fixed|off}" },
1734 { "modulation", set_modulation_info, 1, SIOCGIWMODUL,
1735 "Set Modulation", "{11g|11a|CCK|OFDMg|...}" },
1736 #endif /* WE_ESSENTIAL */
1737 { "commit", set_commit_info, 0, SIOCSIWCOMMIT,
1738 "Commit changes", "" },
1739 { NULL, NULL, 0, 0, NULL, NULL },
1742 /*------------------------------------------------------------------*/
1744 * Find the most appropriate command matching the command line
1746 static inline const iwconfig_cmd *
1747 find_command(const char * cmd)
1749 const iwconfig_cmd * found = NULL;
1751 unsigned int len = strlen(cmd);
1754 /* Go through all commands */
1755 for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
1757 /* No match -> next one */
1758 if(strncasecmp(iwconfig_cmds[i].cmd, cmd, len) != 0)
1761 /* Exact match -> perfect */
1762 if(len == strlen(iwconfig_cmds[i].cmd))
1763 return &iwconfig_cmds[i];
1768 found = &iwconfig_cmds[i];
1771 if (iwconfig_cmds[i].fn != found->fn)
1777 fprintf(stderr, "iwconfig: unknown command \"%s\"\n", cmd);
1783 fprintf(stderr, "iwconfig: command \"%s\" is ambiguous\n", cmd);
1790 /*------------------------------------------------------------------*/
1792 * Set the wireless options requested on command line
1793 * Find the individual commands and call the appropriate subroutine
1796 set_info(int skfd, /* The socket */
1797 char * args[], /* Command line args */
1798 int count, /* Args count */
1799 char * ifname) /* Dev name */
1801 const iwconfig_cmd * iwcmd;
1804 /* Loop until we run out of args... */
1807 /* find the command matching the keyword */
1808 iwcmd = find_command(args[0]);
1811 /* Here we have an unrecognised arg... Error already printed out. */
1815 /* One arg is consumed (the command name) */
1819 /* Check arg numbers */
1820 if(count < iwcmd->min_count)
1821 ret = IWERR_ARG_NUM;
1825 /* Call the command */
1827 ret = (*iwcmd->fn)(skfd, ifname, args, count);
1829 /* Deal with various errors */
1832 int request = iwcmd->request;
1833 if(ret == IWERR_GET_EXT)
1834 request++; /* Transform the SET into GET */
1836 fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n",
1837 iwcmd->name, request);
1841 fprintf(stderr, " too few arguments.\n");
1843 case IWERR_ARG_TYPE:
1848 fprintf(stderr, " invalid argument \"%s\".\n", args[errarg]);
1850 case IWERR_ARG_SIZE:
1851 fprintf(stderr, " argument too big (max %d)\n", errmax);
1853 case IWERR_ARG_CONFLICT:
1858 fprintf(stderr, " conflicting argument \"%s\".\n", args[errarg]);
1861 fprintf(stderr, " SET failed on device %-1.16s ; %s.\n",
1862 ifname, strerror(errno));
1865 fprintf(stderr, " GET failed on device %-1.16s ; %s.\n",
1866 ifname, strerror(errno));
1869 /* Stop processing, we don't know if we are in a consistent state
1870 * in reading the command line */
1874 /* Substract consumed args from command line */
1881 /* Done, all done */
1885 /*------------------------------------------------------------------*/
1894 fprintf(stderr, "Usage: iwconfig [interface]\n");
1895 for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
1896 fprintf(stderr, " interface %s %s\n",
1897 iwconfig_cmds[i].cmd, iwconfig_cmds[i].argsname);
1898 fprintf(stderr, " Check man pages for more details.\n");
1902 /******************************* MAIN ********************************/
1904 /*------------------------------------------------------------------*/
1912 int skfd; /* generic raw socket desc. */
1915 /* Create a channel to the NET kernel. */
1916 if((skfd = iw_sockets_open()) < 0)
1922 /* No argument : show the list of all device + info */
1924 iw_enum_devices(skfd, &print_info, NULL, 0);
1926 /* Special case for help... */
1927 if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
1930 /* Special case for version... */
1931 if(!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
1932 goterr = iw_print_version_info("iwconfig");
1935 /* '--' escape device name */
1936 if((argc > 2) && !strcmp(argv[1], "--"))
1942 /* The device name must be the first argument */
1944 print_info(skfd, argv[1], NULL, 0);
1946 /* The other args on the line specify options to be set... */
1947 goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
1950 /* Close the socket. */
1951 iw_sockets_close(skfd);