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-private.h" /* Private 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 + 2;
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[256]; /* 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 /* Escape the non-printable characters */
177 iw_essid_escape(buffer, info->b.essid, info->b.essid_len);
178 /* Does it have an ESSID index ? */
179 if((info->b.essid_on & IW_ENCODE_INDEX) > 1)
180 printf("ESSID:\"%s\" [%d] ", buffer,
181 (info->b.essid_on & IW_ENCODE_INDEX));
183 printf("ESSID:\"%s\" ", buffer);
186 printf("ESSID:off/any ");
190 /* Display NickName (station name), if any */
191 if(info->has_nickname)
192 printf("Nickname:\"%s\"", info->nickname);
193 #endif /* WE_ESSENTIAL */
196 if(info->b.has_essid || info->has_nickname)
203 /* Display Network ID */
206 /* Note : should display proper number of digits according to info
207 * in range structure */
208 if(info->b.nwid.disabled)
209 printf("NWID:off/any ");
211 printf("NWID:%X ", info->b.nwid.value);
214 #endif /* WE_ESSENTIAL */
216 /* Display the current mode of operation */
219 printf("Mode:%s ", iw_operation_mode[info->b.mode]);
223 /* Display frequency / channel */
226 double freq = info->b.freq; /* Frequency/channel */
227 int channel = -1; /* Converted to channel */
228 /* Some drivers insist of returning channel instead of frequency.
229 * This fixes them up. Note that, driver should still return
230 * frequency, because other tools depend on it. */
231 if(info->has_range && (freq < KILO))
232 channel = iw_channel_to_freq((int) freq, &freq, &info->range);
234 iw_print_freq(buffer, sizeof(buffer), freq, -1, info->b.freq_flags);
235 printf("%s ", buffer);
239 /* Display the address of the current Access Point */
240 if(info->has_ap_addr)
242 /* A bit of clever formatting */
250 /* Oups ! No Access Point in Ad-Hoc mode */
251 if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC))
254 printf("Access Point:");
255 printf(" %s ", iw_sawap_ntop(&info->ap_addr, buffer));
258 /* Display the currently used/set bit-rate */
259 if(info->has_bitrate)
261 /* A bit of clever formatting */
270 iw_print_bitrate(buffer, sizeof(buffer), info->bitrate.value);
271 printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
275 /* Display the Transmit Power */
276 if(info->has_txpower)
278 /* A bit of clever formatting */
287 iw_print_txpower(buffer, sizeof(buffer), &info->txpower);
288 printf("Tx-Power%c%s ", (info->txpower.fixed ? '=' : ':'), buffer);
291 /* Display sensitivity */
294 /* A bit of clever formatting */
303 printf("Sensitivity%c", info->sens.fixed ? '=' : ':');
306 /* Display in dBm ? */
307 if(info->sens.value < 0)
308 printf("%d dBm ", info->sens.value);
310 printf("%d/%d ", info->sens.value, info->range.sensitivity);
312 printf("%d ", info->sens.value);
314 #endif /* WE_ESSENTIAL */
320 /* Display retry limit/lifetime information */
325 if(info->retry.disabled)
329 /* Let's check the value and its type */
330 if(info->retry.flags & IW_RETRY_TYPE)
332 iw_print_retry_value(buffer, sizeof(buffer),
333 info->retry.value, info->retry.flags,
334 info->range.we_version_compiled);
335 printf("%s", buffer);
338 /* Let's check if nothing (simply on) */
339 if(info->retry.flags == IW_RETRY_ON)
343 tokens += 5; /* Between 3 and 5, depend on flags */
346 /* Display the RTS threshold */
350 if(info->rts.disabled)
351 printf("RTS thr:off ");
355 printf("RTS thr%c%d B ",
356 info->rts.fixed ? '=' : ':',
362 /* Display the fragmentation threshold */
365 /* A bit of clever formatting */
374 if(info->frag.disabled)
375 printf("Fragment thr:off");
379 printf("Fragment thr%c%d B ",
380 info->frag.fixed ? '=' : ':',
388 #endif /* WE_ESSENTIAL */
390 /* Display encryption information */
391 /* Note : we display only the "current" key, use iwlist to list all keys */
394 printf("Encryption key:");
395 if((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0))
399 /* Display the key */
400 iw_print_key(buffer, sizeof(buffer),
401 info->b.key, info->b.key_size, info->b.key_flags);
402 printf("%s", buffer);
405 if((info->b.key_flags & IW_ENCODE_INDEX) > 1)
406 printf(" [%d]", info->b.key_flags & IW_ENCODE_INDEX);
407 if(info->b.key_flags & IW_ENCODE_RESTRICTED)
408 printf(" Security mode:restricted");
409 if(info->b.key_flags & IW_ENCODE_OPEN)
410 printf(" Security mode:open");
415 /* Display Power Management information */
416 /* Note : we display only one parameter, period or timeout. If a device
417 * (such as HiperLan) has both, the user need to use iwlist... */
418 if(info->has_power) /* I hope the device has power ;-) */
420 printf("Power Management");
422 if(info->power.disabled)
426 /* Let's check the value and its type */
427 if(info->power.flags & IW_POWER_TYPE)
429 iw_print_pm_value(buffer, sizeof(buffer),
430 info->power.value, info->power.flags,
431 info->range.we_version_compiled);
432 printf("%s ", buffer);
435 /* Let's check the mode */
436 iw_print_pm_mode(buffer, sizeof(buffer), info->power.flags);
437 printf("%s", buffer);
439 /* Let's check if nothing (simply on) */
440 if(info->power.flags == IW_POWER_ON)
446 /* Display statistics */
449 iw_print_stats(buffer, sizeof(buffer),
450 &info->stats.qual, &info->range, info->has_range);
451 printf("Link %s\n", buffer);
453 if(info->range.we_version_compiled > 11)
454 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",
455 info->stats.discard.nwid,
456 info->stats.discard.code,
457 info->stats.discard.fragment,
458 info->stats.discard.retries,
459 info->stats.discard.misc,
460 info->stats.miss.beacon);
462 printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
463 info->stats.discard.nwid,
464 info->stats.discard.code,
465 info->stats.discard.misc);
471 /*------------------------------------------------------------------*/
473 * Print on the screen in a neat fashion all the info we have collected
482 struct wireless_info info;
485 /* Avoid "Unused parameter" warning */
486 args = args; count = count;
488 rc = get_info(skfd, ifname, &info);
491 case 0: /* Success */
493 display_info(&info, ifname);
497 fprintf(stderr, "%-8.16s no wireless extensions.\n\n",
502 fprintf(stderr, "%-8.16s %s\n\n", ifname, strerror(-rc));
507 /****************** COMMAND LINE MODIFIERS PARSING ******************/
509 * Factor out the parsing of command line modifiers.
512 /*------------------------------------------------------------------*/
514 * Map command line modifiers to the proper flags...
516 typedef struct iwconfig_modifier {
517 const char * cmd; /* Command line shorthand */
518 __u16 flag; /* Flags to add */
519 __u16 exclude; /* Modifiers to exclude */
522 /*------------------------------------------------------------------*/
524 * Modifiers for Power
526 static const struct iwconfig_modifier iwmod_power[] = {
527 { "min", IW_POWER_MIN, IW_POWER_MAX },
528 { "max", IW_POWER_MAX, IW_POWER_MIN },
529 { "period", IW_POWER_PERIOD, IW_POWER_TIMEOUT | IW_POWER_SAVING },
530 { "timeout", IW_POWER_TIMEOUT, IW_POWER_PERIOD | IW_POWER_SAVING },
531 { "saving", IW_POWER_SAVING, IW_POWER_TIMEOUT | IW_POWER_PERIOD },
533 #define IWMOD_POWER_NUM (sizeof(iwmod_power)/sizeof(iwmod_power[0]))
535 /*------------------------------------------------------------------*/
537 * Modifiers for Retry
540 static const struct iwconfig_modifier iwmod_retry[] = {
541 { "min", IW_RETRY_MIN, IW_RETRY_MAX },
542 { "max", IW_RETRY_MAX, IW_RETRY_MIN },
543 { "short", IW_RETRY_SHORT, IW_RETRY_LONG },
544 { "long", IW_RETRY_LONG, IW_RETRY_SHORT },
545 { "limit", IW_RETRY_LIMIT, IW_RETRY_LIFETIME },
546 { "lifetime", IW_RETRY_LIFETIME, IW_RETRY_LIMIT },
548 #define IWMOD_RETRY_NUM (sizeof(iwmod_retry)/sizeof(iwmod_retry[0]))
549 #endif /* WE_ESSENTIAL */
551 /*------------------------------------------------------------------*/
553 * Parse command line modifiers.
554 * Return error or number arg parsed.
555 * Modifiers must be at the beggining of command line.
558 parse_modifiers(char * args[], /* Command line args */
559 int count, /* Args count */
560 __u16 * pout, /* Flags to write */
561 const struct iwconfig_modifier modifier[],
566 __u16 result = 0; /* Default : no flag set */
568 /* Get all modifiers and value types on the command line */
571 for(k = 0; k < modnum; k++)
573 /* Check if matches */
574 if(!strcasecmp(args[i], modifier[k].cmd))
576 /* Check for conflicting flags */
577 if(result & modifier[k].exclude)
580 return(IWERR_ARG_CONFLICT);
583 result |= modifier[k].flag;
589 /* For as long as current arg matched and not out of args */
590 while((i < count) && (k < modnum));
592 /* Check there remains one arg for value */
594 return(IWERR_ARG_NUM);
602 /*********************** SETTING SUB-ROUTINES ***********************/
604 * The following functions are use to set some wireless parameters and
605 * are called by the set dispatcher set_info().
606 * They take as arguments the remaining of the command line, with
607 * arguments processed already removed.
608 * An error is indicated by a negative return value.
609 * 0 and positive return values indicate the number of args consumed.
612 /*------------------------------------------------------------------*/
617 set_essid_info(int skfd,
619 char * args[], /* Command line args */
620 int count) /* Args count */
624 char essid[4*IW_ESSID_MAX_SIZE + 1];
627 int we_kernel_version;
629 if((!strcasecmp(args[0], "off")) ||
630 (!strcasecmp(args[0], "any")))
632 wrq.u.essid.flags = 0;
637 if(!strcasecmp(args[0], "on"))
640 memset(essid, '\0', sizeof(essid));
641 wrq.u.essid.pointer = (caddr_t) essid;
642 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 2;
643 wrq.u.essid.flags = 0;
644 if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0)
645 return(IWERR_GET_EXT);
646 wrq.u.essid.flags = 1;
647 essid_len = wrq.u.essid.length;
653 /* '-' or '--' allow to escape the ESSID string, allowing
654 * to set it to the string "any" or "off".
655 * This is a big ugly, but it will do for now */
656 if((!strcmp(args[0], "-")) || (!strcmp(args[0], "--")))
659 return(IWERR_ARG_NUM);
660 essid_len = strlen(args[i]);
663 /* First size check : check if ot fits in our internal buffer.
664 * We do a two pass size check because of unescaping */
665 if(strlen(args[i]) > (4*IW_ESSID_MAX_SIZE))
667 errmax = IW_ESSID_MAX_SIZE;
668 return(IWERR_ARG_SIZE);
671 /* Unescape the ESSID to allow the user to enter weird chars */
672 essid_len = iw_essid_unescape(essid, args[i]);
674 /* Check the size to see if it fits the API. */
675 if(essid_len > IW_ESSID_MAX_SIZE)
677 errmax = IW_ESSID_MAX_SIZE;
678 return(IWERR_ARG_SIZE);
681 wrq.u.essid.flags = 1;
684 /* Check for ESSID index */
686 (sscanf(args[i], "[%i]", &essid_index) == 1) &&
687 (essid_index > 0) && (essid_index < IW_ENCODE_INDEX))
689 wrq.u.essid.flags = essid_index;
694 /* Get version from kernel, device may not have range... */
695 we_kernel_version = iw_get_kernel_we_version();
697 /* Finally set the ESSID value */
698 wrq.u.essid.pointer = (caddr_t) essid;
699 wrq.u.essid.length = essid_len;
700 if(we_kernel_version < 21)
701 wrq.u.essid.length++;
703 if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
704 return(IWERR_SET_EXT);
710 /*------------------------------------------------------------------*/
715 set_mode_info(int skfd,
717 char * args[], /* Command line args */
718 int count) /* Args count */
721 unsigned int k; /* Must be unsigned */
723 /* Avoid "Unused parameter" warning */
726 /* Check if it is a uint, otherwise get is as a string */
727 if(sscanf(args[0], "%i", &k) != 1)
730 while((k < IW_NUM_OPER_MODE) &&
731 strncasecmp(args[0], iw_operation_mode[k], 3))
734 if(k >= IW_NUM_OPER_MODE)
737 return(IWERR_ARG_TYPE);
741 if(iw_set_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
742 return(IWERR_SET_EXT);
748 /*------------------------------------------------------------------*/
750 * Set frequency/channel
753 set_freq_info(int skfd,
755 char * args[], /* Command line args */
756 int count) /* Args count */
761 if(!strcasecmp(args[0], "auto"))
765 wrq.u.freq.flags = 0;
769 if(!strcasecmp(args[0], "fixed"))
771 /* Get old frequency */
772 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
773 return(IWERR_GET_EXT);
774 wrq.u.freq.flags = IW_FREQ_FIXED;
776 else /* Should be a numeric value */
781 freq = strtod(args[0], &unit);
785 return(IWERR_ARG_TYPE);
789 if(unit[0] == 'G') freq *= GIGA;
790 if(unit[0] == 'M') freq *= MEGA;
791 if(unit[0] == 'k') freq *= KILO;
794 iw_float2freq(freq, &(wrq.u.freq));
796 wrq.u.freq.flags = IW_FREQ_FIXED;
798 /* Check for an additional argument */
799 if((i < count) && (!strcasecmp(args[i], "auto")))
801 wrq.u.freq.flags = 0;
804 if((i < count) && (!strcasecmp(args[i], "fixed")))
806 wrq.u.freq.flags = IW_FREQ_FIXED;
812 if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
813 return(IWERR_SET_EXT);
819 /*------------------------------------------------------------------*/
824 set_bitrate_info(int skfd,
826 char * args[], /* Command line args */
827 int count) /* Args count */
832 wrq.u.bitrate.flags = 0;
833 if(!strcasecmp(args[0], "auto"))
835 wrq.u.bitrate.value = -1;
836 wrq.u.bitrate.fixed = 0;
840 if(!strcasecmp(args[0], "fixed"))
842 /* Get old bitrate */
843 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) < 0)
844 return(IWERR_GET_EXT);
845 wrq.u.bitrate.fixed = 1;
847 else /* Should be a numeric value */
852 brate = strtod(args[0], &unit);
856 return(IWERR_ARG_TYPE);
860 if(unit[0] == 'G') brate *= GIGA;
861 if(unit[0] == 'M') brate *= MEGA;
862 if(unit[0] == 'k') brate *= KILO;
864 wrq.u.bitrate.value = (long) brate;
865 wrq.u.bitrate.fixed = 1;
867 /* Check for an additional argument */
868 if((i < count) && (!strcasecmp(args[i], "auto")))
870 wrq.u.bitrate.fixed = 0;
873 if((i < count) && (!strcasecmp(args[i], "fixed")))
875 wrq.u.bitrate.fixed = 1;
878 if((i < count) && (!strcasecmp(args[i], "unicast")))
880 wrq.u.bitrate.flags |= IW_BITRATE_UNICAST;
883 if((i < count) && (!strcasecmp(args[i], "broadcast")))
885 wrq.u.bitrate.flags |= IW_BITRATE_BROADCAST;
891 if(iw_set_ext(skfd, ifname, SIOCSIWRATE, &wrq) < 0)
892 return(IWERR_SET_EXT);
898 /*------------------------------------------------------------------*/
903 set_enc_info(int skfd,
905 char * args[], /* Command line args */
906 int count) /* Args count */
910 unsigned char key[IW_ENCODING_TOKEN_MAX];
912 if(!strcasecmp(args[0], "on"))
914 /* Get old encryption information */
915 wrq.u.data.pointer = (caddr_t) key;
916 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
917 wrq.u.data.flags = 0;
918 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
919 return(IWERR_GET_EXT);
920 wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
929 wrq.u.data.pointer = (caddr_t) NULL;
930 wrq.u.data.flags = 0;
931 wrq.u.data.length = 0;
934 /* Allow arguments in any order (it's safe) */
939 /* -- Check for the key -- */
942 keylen = iw_in_key_full(skfd, ifname,
943 args[i], key, &wrq.u.data.flags);
946 wrq.u.data.length = keylen;
947 wrq.u.data.pointer = (caddr_t) key;
953 /* -- Check for token index -- */
955 (sscanf(args[i], "[%i]", &temp) == 1) &&
956 (temp > 0) && (temp < IW_ENCODE_INDEX))
958 wrq.u.encoding.flags |= temp;
963 /* -- Check the various flags -- */
964 if((i < count) && (!strcasecmp(args[i], "off")))
966 wrq.u.data.flags |= IW_ENCODE_DISABLED;
970 if((i < count) && (!strcasecmp(args[i], "open")))
972 wrq.u.data.flags |= IW_ENCODE_OPEN;
976 if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
978 wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
982 if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
984 wrq.u.data.flags |= IW_ENCODE_TEMP;
989 while(gotone != oldone);
991 /* Pointer is absent in new API */
992 if(wrq.u.data.pointer == NULL)
993 wrq.u.data.flags |= IW_ENCODE_NOKEY;
995 /* Check if we have any invalid argument */
999 return(IWERR_ARG_TYPE);
1003 if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
1004 return(IWERR_SET_EXT);
1010 /*------------------------------------------------------------------*/
1012 * Set Power Management
1015 set_power_info(int skfd,
1017 char * args[], /* Command line args */
1018 int count) /* Args count */
1023 if(!strcasecmp(args[0], "off"))
1024 wrq.u.power.disabled = 1; /* i.e. max size */
1026 if(!strcasecmp(args[0], "on"))
1028 /* Get old Power info */
1029 wrq.u.power.flags = 0;
1030 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) < 0)
1031 return(IWERR_GET_EXT);
1032 wrq.u.power.disabled = 0;
1040 /* Parse modifiers */
1041 i = parse_modifiers(args, count, &wrq.u.power.flags,
1042 iwmod_power, IWMOD_POWER_NUM);
1046 wrq.u.power.disabled = 0;
1048 /* Is there any value to grab ? */
1049 value = strtod(args[i], &unit);
1052 struct iw_range range;
1054 /* Extract range info to handle properly 'relative' */
1055 if(iw_get_range_info(skfd, ifname, &range) < 0)
1056 memset(&range, 0, sizeof(range));
1058 /* Get the flags to be able to do the proper conversion */
1059 switch(wrq.u.power.flags & IW_POWER_TYPE)
1061 case IW_POWER_SAVING:
1062 flags = range.pms_flags;
1064 case IW_POWER_TIMEOUT:
1065 flags = range.pmt_flags;
1068 flags = range.pmp_flags;
1071 /* Check if time or relative */
1072 if(flags & IW_POWER_RELATIVE)
1074 if(range.we_version_compiled < 21)
1077 wrq.u.power.flags |= IW_POWER_RELATIVE;
1081 value *= MEGA; /* default = s */
1082 if(unit[0] == 'u') value /= MEGA;
1083 if(unit[0] == 'm') value /= KILO;
1085 wrq.u.power.value = (long) value;
1086 /* Set some default type if none */
1087 if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
1088 wrq.u.power.flags |= IW_POWER_PERIOD;
1093 /* Now, check the mode */
1096 if(!strcasecmp(args[i], "all"))
1097 wrq.u.power.flags |= IW_POWER_ALL_R;
1098 if(!strncasecmp(args[i], "unicast", 4))
1099 wrq.u.power.flags |= IW_POWER_UNICAST_R;
1100 if(!strncasecmp(args[i], "multicast", 5))
1101 wrq.u.power.flags |= IW_POWER_MULTICAST_R;
1102 if(!strncasecmp(args[i], "force", 5))
1103 wrq.u.power.flags |= IW_POWER_FORCE_S;
1104 if(!strcasecmp(args[i], "repeat"))
1105 wrq.u.power.flags |= IW_POWER_REPEATER;
1106 if(wrq.u.power.flags & IW_POWER_MODE)
1115 return(IWERR_ARG_TYPE);
1119 if(iw_set_ext(skfd, ifname, SIOCSIWPOWER, &wrq) < 0)
1120 return(IWERR_SET_EXT);
1126 #ifndef WE_ESSENTIAL
1127 /*------------------------------------------------------------------*/
1132 set_nick_info(int skfd,
1134 char * args[], /* Command line args */
1135 int count) /* Args count */
1138 int we_kernel_version;
1140 /* Avoid "Unused parameter" warning */
1143 if(strlen(args[0]) > IW_ESSID_MAX_SIZE)
1145 errmax = IW_ESSID_MAX_SIZE;
1146 return(IWERR_ARG_SIZE);
1149 we_kernel_version = iw_get_kernel_we_version();
1151 wrq.u.essid.pointer = (caddr_t) args[0];
1152 wrq.u.essid.length = strlen(args[0]);
1153 if(we_kernel_version < 21)
1154 wrq.u.essid.length++;
1156 if(iw_set_ext(skfd, ifname, SIOCSIWNICKN, &wrq) < 0)
1157 return(IWERR_SET_EXT);
1163 /*------------------------------------------------------------------*/
1168 set_nwid_info(int skfd,
1170 char * args[], /* Command line args */
1171 int count) /* Args count */
1176 /* Avoid "Unused parameter" warning */
1179 if((!strcasecmp(args[0], "off")) ||
1180 (!strcasecmp(args[0], "any")))
1181 wrq.u.nwid.disabled = 1;
1183 if(!strcasecmp(args[0], "on"))
1186 if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0)
1187 return(IWERR_GET_EXT);
1188 wrq.u.nwid.disabled = 0;
1191 if(sscanf(args[0], "%lX", &(temp)) != 1)
1194 return(IWERR_ARG_TYPE);
1198 wrq.u.nwid.value = temp;
1199 wrq.u.nwid.disabled = 0;
1202 wrq.u.nwid.fixed = 1;
1205 if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
1206 return(IWERR_SET_EXT);
1212 /*------------------------------------------------------------------*/
1217 set_apaddr_info(int skfd,
1219 char * args[], /* Command line args */
1220 int count) /* Args count */
1224 /* Avoid "Unused parameter" warning */
1227 if((!strcasecmp(args[0], "auto")) ||
1228 (!strcasecmp(args[0], "any")))
1230 /* Send a broadcast address */
1231 iw_broad_ether(&(wrq.u.ap_addr));
1235 if(!strcasecmp(args[0], "off"))
1237 /* Send a NULL address */
1238 iw_null_ether(&(wrq.u.ap_addr));
1242 /* Get the address and check if the interface supports it */
1243 if(iw_in_addr(skfd, ifname, args[0], &(wrq.u.ap_addr)) < 0)
1246 return(IWERR_ARG_TYPE);
1251 if(iw_set_ext(skfd, ifname, SIOCSIWAP, &wrq) < 0)
1252 return(IWERR_SET_EXT);
1258 /*------------------------------------------------------------------*/
1263 set_txpower_info(int skfd,
1265 char * args[], /* Command line args */
1266 int count) /* Args count */
1271 /* Avoid "Unused parameter" warning */
1272 args = args; count = count;
1274 /* Prepare the request */
1275 wrq.u.txpower.value = -1;
1276 wrq.u.txpower.fixed = 1;
1277 wrq.u.txpower.disabled = 0;
1278 wrq.u.txpower.flags = IW_TXPOW_DBM;
1280 if(!strcasecmp(args[0], "off"))
1281 wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
1283 if(!strcasecmp(args[0], "auto"))
1284 wrq.u.txpower.fixed = 0; /* i.e. use power control */
1287 if(!strcasecmp(args[0], "on"))
1289 /* Get old tx-power */
1290 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
1291 return(IWERR_GET_EXT);
1292 wrq.u.txpower.disabled = 0;
1296 if(!strcasecmp(args[0], "fixed"))
1298 /* Get old tx-power */
1299 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
1300 return(IWERR_GET_EXT);
1301 wrq.u.txpower.fixed = 1;
1302 wrq.u.txpower.disabled = 0;
1304 else /* Should be a numeric value */
1308 struct iw_range range;
1310 /* Extract range info to do proper conversion */
1311 if(iw_get_range_info(skfd, ifname, &range) < 0)
1312 memset(&range, 0, sizeof(range));
1315 if(sscanf(args[0], "%i", &(power)) != 1)
1318 return(IWERR_ARG_TYPE);
1321 /* Check if milliWatt
1322 * We authorise a single 'm' as a shorthand for 'mW',
1323 * on the other hand a 'd' probably means 'dBm'... */
1324 ismwatt = ((strchr(args[0], 'm') != NULL)
1325 && (strchr(args[0], 'd') == NULL));
1327 /* We could check 'W' alone... Another time... */
1330 if(range.txpower_capa & IW_TXPOW_RELATIVE)
1336 return(IWERR_ARG_TYPE);
1338 wrq.u.txpower.flags = IW_TXPOW_RELATIVE;
1341 if(range.txpower_capa & IW_TXPOW_MWATT)
1344 power = iw_dbm2mwatt(power);
1345 wrq.u.txpower.flags = IW_TXPOW_MWATT;
1350 power = iw_mwatt2dbm(power);
1351 wrq.u.txpower.flags = IW_TXPOW_DBM;
1353 wrq.u.txpower.value = power;
1355 /* Check for an additional argument */
1356 if((i < count) && (!strcasecmp(args[i], "auto")))
1358 wrq.u.txpower.fixed = 0;
1361 if((i < count) && (!strcasecmp(args[i], "fixed")))
1363 wrq.u.txpower.fixed = 1;
1370 if(iw_set_ext(skfd, ifname, SIOCSIWTXPOW, &wrq) < 0)
1371 return(IWERR_SET_EXT);
1377 /*------------------------------------------------------------------*/
1382 set_sens_info(int skfd,
1384 char * args[], /* Command line args */
1385 int count) /* Args count */
1390 /* Avoid "Unused parameter" warning */
1393 if(sscanf(args[0], "%i", &(temp)) != 1)
1396 return(IWERR_ARG_TYPE);
1398 wrq.u.sens.value = temp;
1400 if(iw_set_ext(skfd, ifname, SIOCSIWSENS, &wrq) < 0)
1401 return(IWERR_SET_EXT);
1407 /*------------------------------------------------------------------*/
1412 set_retry_info(int skfd,
1414 char * args[], /* Command line args */
1415 int count) /* Args count */
1422 /* Parse modifiers */
1423 i = parse_modifiers(args, count, &wrq.u.retry.flags,
1424 iwmod_retry, IWMOD_RETRY_NUM);
1428 /* Add default type if none */
1429 if((wrq.u.retry.flags & IW_RETRY_TYPE) == 0)
1430 wrq.u.retry.flags |= IW_RETRY_LIMIT;
1432 wrq.u.retry.disabled = 0;
1434 /* Is there any value to grab ? */
1435 value = strtod(args[i], &unit);
1439 return(IWERR_ARG_TYPE);
1442 /* Limit is absolute, on the other hand lifetime is seconds */
1443 if(wrq.u.retry.flags & IW_RETRY_LIFETIME)
1445 struct iw_range range;
1446 /* Extract range info to handle properly 'relative' */
1447 if(iw_get_range_info(skfd, ifname, &range) < 0)
1448 memset(&range, 0, sizeof(range));
1450 if(range.r_time_flags & IW_RETRY_RELATIVE)
1452 if(range.we_version_compiled < 21)
1455 wrq.u.retry.flags |= IW_RETRY_RELATIVE;
1459 /* Normalise lifetime */
1460 value *= MEGA; /* default = s */
1461 if(unit[0] == 'u') value /= MEGA;
1462 if(unit[0] == 'm') value /= KILO;
1465 wrq.u.retry.value = (long) value;
1468 if(iw_set_ext(skfd, ifname, SIOCSIWRETRY, &wrq) < 0)
1469 return(IWERR_SET_EXT);
1475 /*------------------------------------------------------------------*/
1480 set_rts_info(int skfd,
1482 char * args[], /* Command line args */
1483 int count) /* Args count */
1487 /* Avoid "Unused parameter" warning */
1490 wrq.u.rts.value = -1;
1491 wrq.u.rts.fixed = 1;
1492 wrq.u.rts.disabled = 0;
1494 if(!strcasecmp(args[0], "off"))
1495 wrq.u.rts.disabled = 1; /* i.e. max size */
1497 if(!strcasecmp(args[0], "auto"))
1498 wrq.u.rts.fixed = 0;
1501 if(!strcasecmp(args[0], "fixed"))
1503 /* Get old RTS threshold */
1504 if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) < 0)
1505 return(IWERR_GET_EXT);
1506 wrq.u.rts.fixed = 1;
1509 { /* Should be a numeric value */
1511 if(sscanf(args[0], "%li", (unsigned long *) &(temp)) != 1)
1514 return(IWERR_ARG_TYPE);
1516 wrq.u.rts.value = temp;
1520 if(iw_set_ext(skfd, ifname, SIOCSIWRTS, &wrq) < 0)
1521 return(IWERR_SET_EXT);
1527 /*------------------------------------------------------------------*/
1529 * Set Fragmentation Threshold
1532 set_frag_info(int skfd,
1534 char * args[], /* Command line args */
1535 int count) /* Args count */
1539 /* Avoid "Unused parameter" warning */
1542 wrq.u.frag.value = -1;
1543 wrq.u.frag.fixed = 1;
1544 wrq.u.frag.disabled = 0;
1546 if(!strcasecmp(args[0], "off"))
1547 wrq.u.frag.disabled = 1; /* i.e. max size */
1549 if(!strcasecmp(args[0], "auto"))
1550 wrq.u.frag.fixed = 0;
1553 if(!strcasecmp(args[0], "fixed"))
1555 /* Get old fragmentation threshold */
1556 if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) < 0)
1557 return(IWERR_GET_EXT);
1558 wrq.u.frag.fixed = 1;
1561 { /* Should be a numeric value */
1563 if(sscanf(args[0], "%li", &(temp))
1567 return(IWERR_ARG_TYPE);
1569 wrq.u.frag.value = temp;
1573 if(iw_set_ext(skfd, ifname, SIOCSIWFRAG, &wrq) < 0)
1574 return(IWERR_SET_EXT);
1580 /*------------------------------------------------------------------*/
1585 set_modulation_info(int skfd,
1587 char * args[], /* Command line args */
1588 int count) /* Args count */
1593 /* Avoid "Unused parameter" warning */
1594 args = args; count = count;
1596 if(!strcasecmp(args[0], "auto"))
1597 wrq.u.param.fixed = 0; /* i.e. use any modulation */
1600 if(!strcasecmp(args[0], "fixed"))
1602 /* Get old modulation */
1603 if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) < 0)
1604 return(IWERR_GET_EXT);
1605 wrq.u.param.fixed = 1;
1611 /* Allow multiple modulations, combine them together */
1612 wrq.u.param.value = 0x0;
1616 for(k = 0; k < IW_SIZE_MODUL_LIST; k++)
1618 if(!strcasecmp(args[i], iw_modul_list[k].cmd))
1620 wrq.u.param.value |= iw_modul_list[k].mask;
1626 /* For as long as current arg matched and not out of args */
1627 while((i < count) && (k < IW_SIZE_MODUL_LIST));
1629 /* Check we got something */
1633 return(IWERR_ARG_TYPE);
1636 /* Check for an additional argument */
1637 if((i < count) && (!strcasecmp(args[i], "auto")))
1639 wrq.u.param.fixed = 0;
1642 if((i < count) && (!strcasecmp(args[i], "fixed")))
1644 wrq.u.param.fixed = 1;
1650 if(iw_set_ext(skfd, ifname, SIOCSIWMODUL, &wrq) < 0)
1651 return(IWERR_SET_EXT);
1656 #endif /* WE_ESSENTIAL */
1658 /*------------------------------------------------------------------*/
1663 set_commit_info(int skfd,
1665 char * args[], /* Command line args */
1666 int count) /* Args count */
1670 /* Avoid "Unused parameter" warning */
1671 args = args; count = count;
1673 if(iw_set_ext(skfd, ifname, SIOCSIWCOMMIT, &wrq) < 0)
1674 return(IWERR_SET_EXT);
1680 /************************** SET DISPATCHER **************************/
1682 * This is a modified version of the dispatcher in iwlist.
1683 * The main difference is that here we may have multiple commands per
1684 * line. Also, most commands here do take arguments, and most often
1685 * a variable number of them.
1686 * Therefore, the handler *must* return how many args were consumed...
1688 * Note that the use of multiple commands per line is not advised
1689 * in scripts, as it makes error management hard. All commands before
1690 * the error are executed, but commands after the error are not
1692 * We also try to give as much clue as possible via stderr to the caller
1693 * on which command did fail, but if there are two time the same command,
1694 * you don't know which one failed...
1697 /*------------------------------------------------------------------*/
1699 * Map command line arguments to the proper procedure...
1701 typedef struct iwconfig_entry {
1702 const char * cmd; /* Command line shorthand */
1703 iw_enum_handler fn; /* Subroutine */
1705 int request; /* WE numerical ID */
1706 const char * name; /* Human readable string */
1707 const char * argsname; /* Args as human readable string */
1710 static const struct iwconfig_entry iwconfig_cmds[] = {
1711 { "essid", set_essid_info, 1, SIOCSIWESSID,
1712 "Set ESSID", "{NNN|any|on|off}" },
1713 { "mode", set_mode_info, 1, SIOCSIWMODE,
1714 "Set Mode", "{managed|ad-hoc|master|...}" },
1715 { "freq", set_freq_info, 1, SIOCSIWFREQ,
1716 "Set Frequency", "N.NNN[k|M|G]" },
1717 { "channel", set_freq_info, 1, SIOCSIWFREQ,
1718 "Set Frequency", "N" },
1719 { "bit", set_bitrate_info, 1, SIOCSIWRATE,
1720 "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
1721 { "rate", set_bitrate_info, 1, SIOCSIWRATE,
1722 "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
1723 { "enc", set_enc_info, 1, SIOCSIWENCODE,
1724 "Set Encode", "{NNNN-NNNN|off}" },
1725 { "key", set_enc_info, 1, SIOCSIWENCODE,
1726 "Set Encode", "{NNNN-NNNN|off}" },
1727 { "power", set_power_info, 1, SIOCSIWPOWER,
1728 "Set Power Management", "{period N|timeout N|saving N|off}" },
1729 #ifndef WE_ESSENTIAL
1730 { "nickname", set_nick_info, 1, SIOCSIWNICKN,
1731 "Set Nickname", "NNN" },
1732 { "nwid", set_nwid_info, 1, SIOCSIWNWID,
1733 "Set NWID", "{NN|on|off}" },
1734 { "ap", set_apaddr_info, 1, SIOCSIWAP,
1735 "Set AP Address", "{N|off|auto}" },
1736 { "txpower", set_txpower_info, 1, SIOCSIWTXPOW,
1737 "Set Tx Power", "{NmW|NdBm|off|auto}" },
1738 { "sens", set_sens_info, 1, SIOCSIWSENS,
1739 "Set Sensitivity", "N" },
1740 { "retry", set_retry_info, 1, SIOCSIWRETRY,
1741 "Set Retry Limit", "{limit N|lifetime N}" },
1742 { "rts", set_rts_info, 1, SIOCSIWRTS,
1743 "Set RTS Threshold", "{N|auto|fixed|off}" },
1744 { "frag", set_frag_info, 1, SIOCSIWFRAG,
1745 "Set Fragmentation Threshold", "{N|auto|fixed|off}" },
1746 { "modulation", set_modulation_info, 1, SIOCGIWMODUL,
1747 "Set Modulation", "{11g|11a|CCK|OFDMg|...}" },
1748 #endif /* WE_ESSENTIAL */
1749 { "commit", set_commit_info, 0, SIOCSIWCOMMIT,
1750 "Commit changes", "" },
1751 { NULL, NULL, 0, 0, NULL, NULL },
1754 /*------------------------------------------------------------------*/
1756 * Find the most appropriate command matching the command line
1758 static inline const iwconfig_cmd *
1759 find_command(const char * cmd)
1761 const iwconfig_cmd * found = NULL;
1763 unsigned int len = strlen(cmd);
1766 /* Go through all commands */
1767 for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
1769 /* No match -> next one */
1770 if(strncasecmp(iwconfig_cmds[i].cmd, cmd, len) != 0)
1773 /* Exact match -> perfect */
1774 if(len == strlen(iwconfig_cmds[i].cmd))
1775 return &iwconfig_cmds[i];
1780 found = &iwconfig_cmds[i];
1783 if (iwconfig_cmds[i].fn != found->fn)
1789 fprintf(stderr, "iwconfig: unknown command \"%s\"\n", cmd);
1795 fprintf(stderr, "iwconfig: command \"%s\" is ambiguous\n", cmd);
1802 /*------------------------------------------------------------------*/
1804 * Set the wireless options requested on command line
1805 * Find the individual commands and call the appropriate subroutine
1808 set_info(int skfd, /* The socket */
1809 char * args[], /* Command line args */
1810 int count, /* Args count */
1811 char * ifname) /* Dev name */
1813 const iwconfig_cmd * iwcmd;
1816 /* Loop until we run out of args... */
1819 /* find the command matching the keyword */
1820 iwcmd = find_command(args[0]);
1823 /* Here we have an unrecognised arg... Error already printed out. */
1827 /* One arg is consumed (the command name) */
1831 /* Check arg numbers */
1832 if(count < iwcmd->min_count)
1833 ret = IWERR_ARG_NUM;
1837 /* Call the command */
1839 ret = (*iwcmd->fn)(skfd, ifname, args, count);
1841 /* Deal with various errors */
1844 int request = iwcmd->request;
1845 if(ret == IWERR_GET_EXT)
1846 request++; /* Transform the SET into GET */
1848 fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n",
1849 iwcmd->name, request);
1853 fprintf(stderr, " too few arguments.\n");
1855 case IWERR_ARG_TYPE:
1860 fprintf(stderr, " invalid argument \"%s\".\n", args[errarg]);
1862 case IWERR_ARG_SIZE:
1863 fprintf(stderr, " argument too big (max %d)\n", errmax);
1865 case IWERR_ARG_CONFLICT:
1870 fprintf(stderr, " conflicting argument \"%s\".\n", args[errarg]);
1873 fprintf(stderr, " SET failed on device %-1.16s ; %s.\n",
1874 ifname, strerror(errno));
1877 fprintf(stderr, " GET failed on device %-1.16s ; %s.\n",
1878 ifname, strerror(errno));
1881 /* Stop processing, we don't know if we are in a consistent state
1882 * in reading the command line */
1886 /* Substract consumed args from command line */
1893 /* Done, all done */
1897 /*------------------------------------------------------------------*/
1906 fprintf(stderr, "Usage: iwconfig [interface]\n");
1907 for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
1908 fprintf(stderr, " interface %s %s\n",
1909 iwconfig_cmds[i].cmd, iwconfig_cmds[i].argsname);
1910 fprintf(stderr, " Check man pages for more details.\n");
1914 /******************************* MAIN ********************************/
1916 /*------------------------------------------------------------------*/
1924 int skfd; /* generic raw socket desc. */
1927 /* Create a channel to the NET kernel. */
1928 if((skfd = iw_sockets_open()) < 0)
1934 /* No argument : show the list of all device + info */
1936 iw_enum_devices(skfd, &print_info, NULL, 0);
1938 /* Special case for help... */
1939 if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
1942 /* Special case for version... */
1943 if(!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
1944 goterr = iw_print_version_info("iwconfig");
1947 /* '--' escape device name */
1948 if((argc > 2) && !strcmp(argv[1], "--"))
1954 /* The device name must be the first argument */
1956 goterr = print_info(skfd, argv[1], NULL, 0);
1958 /* The other args on the line specify options to be set... */
1959 goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
1962 /* Close the socket. */
1963 iw_sockets_close(skfd);