4 * Jean II - HPLB 97->99 - HPL 99->04
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-2004 Jean Tourrilhes <jt@hpl.hp.com>
14 #include "iwlib.h" /* Header */
16 /************************* MISC SUBROUTINES **************************/
18 /*------------------------------------------------------------------*/
26 "Usage: iwconfig interface [essid {NN|on|off}]\n"
27 " [nwid {NN|on|off}]\n"
28 " [mode {managed|ad-hoc|...}\n"
29 " [freq N.NNNN[k|M|G]]\n"
31 " [ap {N|off|auto}]\n"
34 " [rate {N|auto|fixed}]\n"
35 " [rts {N|auto|fixed|off}]\n"
36 " [frag {N|auto|fixed|off}]\n"
37 " [enc {NNNN-NNNN|off}]\n"
38 " [power {period N|timeout N}]\n"
39 " [retry {limit N|lifetime N}]\n"
40 " [txpower N {mW|dBm}]\n"
42 " Check man pages for more details.\n\n"
47 /************************* DISPLAY ROUTINES **************************/
49 /*------------------------------------------------------------------*/
51 * Get wireless informations & config from the device driver
52 * We will call all the classical wireless ioctl on the driver through
53 * the socket to know what is supported and to get the settings...
58 struct wireless_info * info)
62 memset((char *) info, 0, sizeof(struct wireless_info));
64 /* Get basic information */
65 if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0)
67 /* If no wireless name : no wireless extensions */
68 /* But let's check if the interface exists at all */
71 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
72 if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
79 if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
83 if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
86 memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
90 if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
92 info->has_ap_addr = 1;
93 memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
97 wrq.u.essid.pointer = (caddr_t) info->nickname;
98 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
99 wrq.u.essid.flags = 0;
100 if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
101 if(wrq.u.data.length > 1)
102 info->has_nickname = 1;
105 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
107 info->has_bitrate = 1;
108 memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
111 /* Get RTS threshold */
112 if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
115 memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
118 /* Get fragmentation threshold */
119 if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
122 memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
125 /* Get Power Management settings */
126 wrq.u.power.flags = 0;
127 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
130 memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
133 if((info->has_range) && (info->range.we_version_compiled > 9))
135 /* Get Transmit Power */
136 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
138 info->has_txpower = 1;
139 memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
143 if((info->has_range) && (info->range.we_version_compiled > 10))
145 /* Get retry limit/lifetime */
146 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
149 memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
154 if(iw_get_stats(skfd, ifname, &(info->stats),
155 &info->range, info->has_range) >= 0)
161 /* Note : currently disabled to not bloat iwconfig output. Also,
162 * if does not make total sense to display parameters that we
163 * don't allow (yet) to configure.
164 * For now, use iwlist instead... Jean II */
166 /* Get WPA/802.1x/802.11i security parameters */
167 if((info->has_range) && (info->range.we_version_compiled > 17))
169 wrq.u.param.flags = IW_AUTH_KEY_MGMT;
170 if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
172 info->has_auth_key_mgmt = 1;
173 info->auth_key_mgmt = wrq.u.param.value;
176 wrq.u.param.flags = IW_AUTH_CIPHER_PAIRWISE;
177 if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
179 info->has_auth_cipher_pairwise = 1;
180 info->auth_cipher_pairwise = wrq.u.param.value;
183 wrq.u.param.flags = IW_AUTH_CIPHER_GROUP;
184 if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
186 info->has_auth_cipher_group = 1;
187 info->auth_cipher_group = wrq.u.param.value;
195 /*------------------------------------------------------------------*/
197 * Print on the screen in a neat fashion all the info we have collected
201 display_info(struct wireless_info * info,
204 char buffer[128]; /* Temporary buffer */
206 /* One token is more of less 5 characters, 14 tokens per line */
207 int tokens = 3; /* For name */
209 /* Display device name and wireless name (name of the protocol used) */
210 printf("%-8.16s %s ", ifname, info->b.name);
212 /* Display ESSID (extended network), if any */
213 if(info->b.has_essid)
217 /* Does it have an ESSID index ? */
218 if((info->b.essid_on & IW_ENCODE_INDEX) > 1)
219 printf("ESSID:\"%s\" [%d] ", info->b.essid,
220 (info->b.essid_on & IW_ENCODE_INDEX));
222 printf("ESSID:\"%s\" ", info->b.essid);
225 printf("ESSID:off/any ");
228 /* Display NickName (station name), if any */
229 if(info->has_nickname)
230 printf("Nickname:\"%s\"", info->nickname);
233 if(info->b.has_essid || info->has_nickname)
239 /* Display Network ID */
242 /* Note : should display proper number of digits according to info
243 * in range structure */
244 if(info->b.nwid.disabled)
245 printf("NWID:off/any ");
247 printf("NWID:%X ", info->b.nwid.value);
251 /* Display the current mode of operation */
254 printf("Mode:%s ", iw_operation_mode[info->b.mode]);
258 /* Display frequency / channel */
261 double freq = info->b.freq; /* Frequency/channel */
262 int channel = -1; /* Converted to channel */
263 /* Some drivers insist of returning channel instead of frequency.
264 * This fixes them up. Note that, driver should still return
265 * frequency, because other tools depend on it. */
266 if(info->has_range && (freq < KILO))
267 channel = iw_channel_to_freq((int) freq, &freq, &info->range);
269 iw_print_freq(buffer, sizeof(buffer), freq, -1, info->b.freq_flags);
270 printf("%s ", buffer);
274 /* Display the address of the current Access Point */
275 if(info->has_ap_addr)
277 /* A bit of clever formatting */
285 /* Oups ! No Access Point in Ad-Hoc mode */
286 if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC))
289 printf("Access Point:");
290 printf(" %s ", iw_sawap_ntop(&info->ap_addr, buffer));
293 /* Display the currently used/set bit-rate */
294 if(info->has_bitrate)
296 /* A bit of clever formatting */
305 iw_print_bitrate(buffer, sizeof(buffer), info->bitrate.value);
306 printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
309 /* Display the Transmit Power */
310 if(info->has_txpower)
312 /* A bit of clever formatting */
321 iw_print_txpower(buffer, sizeof(buffer), &info->txpower);
322 printf("Tx-Power%c%s ", (info->txpower.fixed ? '=' : ':'), buffer);
325 /* Display sensitivity */
328 /* A bit of clever formatting */
338 printf("Sensitivity=");
340 printf("Sensitivity:");
343 /* Display in dBm ? */
344 if(info->sens.value < 0)
345 printf("%d dBm ", info->sens.value);
347 printf("%d/%d ", info->sens.value, info->range.sensitivity);
349 printf("%d ", info->sens.value);
355 /* Display retry limit/lifetime information */
360 if(info->retry.disabled)
364 /* Let's check the value and its type */
365 if(info->retry.flags & IW_RETRY_TYPE)
367 iw_print_retry_value(buffer, sizeof(buffer),
368 info->retry.value, info->retry.flags);
369 printf("%s", buffer);
372 /* Let's check if nothing (simply on) */
373 if(info->retry.flags == IW_RETRY_ON)
377 tokens += 5; /* Between 3 and 5, depend on flags */
380 /* Display the RTS threshold */
384 if(info->rts.disabled)
385 printf("RTS thr:off ");
394 printf("%d B ", info->rts.value);
399 /* Display the fragmentation threshold */
402 /* A bit of clever formatting */
411 if(info->frag.disabled)
412 printf("Fragment thr:off");
417 printf("Fragment thr=");
419 printf("Fragment thr:");
421 printf("%d B ", info->frag.value);
429 /* Display encryption information */
430 /* Note : we display only the "current" key, use iwlist to list all keys */
433 printf("Encryption key:");
434 if((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0))
438 /* Display the key */
439 iw_print_key(buffer, sizeof(buffer),
440 info->b.key, info->b.key_size, info->b.key_flags);
441 printf("%s", buffer);
444 if((info->b.key_flags & IW_ENCODE_INDEX) > 1)
445 printf(" [%d]", info->b.key_flags & IW_ENCODE_INDEX);
446 if(info->b.key_flags & IW_ENCODE_RESTRICTED)
447 printf(" Security mode:restricted");
448 if(info->b.key_flags & IW_ENCODE_OPEN)
449 printf(" Security mode:open");
455 /* Display WPA/802.1x/802.11i security parameters */
456 if(info->has_auth_key_mgmt || info->has_auth_cipher_pairwise ||
457 info->has_auth_cipher_group)
459 printf("Auth params:");
460 if(info->has_auth_key_mgmt)
461 printf(" key_mgmt:0x%X ", info->auth_key_mgmt);
462 if(info->has_auth_cipher_pairwise)
463 printf(" cipher_pairwise:0x%X ", info->auth_cipher_pairwise);
464 if(info->has_auth_cipher_group)
465 printf(" cipher_group:0x%X ", info->auth_cipher_group);
470 /* Display Power Management information */
471 /* Note : we display only one parameter, period or timeout. If a device
472 * (such as HiperLan) has both, the user need to use iwlist... */
473 if(info->has_power) /* I hope the device has power ;-) */
475 printf("Power Management");
477 if(info->power.disabled)
481 /* Let's check the value and its type */
482 if(info->power.flags & IW_POWER_TYPE)
484 iw_print_pm_value(buffer, sizeof(buffer),
485 info->power.value, info->power.flags);
486 printf("%s ", buffer);
489 /* Let's check the mode */
490 iw_print_pm_mode(buffer, sizeof(buffer), info->power.flags);
491 printf("%s", buffer);
493 /* Let's check if nothing (simply on) */
494 if(info->power.flags == IW_POWER_ON)
500 /* Display statistics */
503 iw_print_stats(buffer, sizeof(buffer),
504 &info->stats.qual, &info->range, info->has_range);
505 printf("Link %s\n", buffer);
507 if(info->range.we_version_compiled > 11)
508 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",
509 info->stats.discard.nwid,
510 info->stats.discard.code,
511 info->stats.discard.fragment,
512 info->stats.discard.retries,
513 info->stats.discard.misc,
514 info->stats.miss.beacon);
516 printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
517 info->stats.discard.nwid,
518 info->stats.discard.code,
519 info->stats.discard.misc);
525 /*------------------------------------------------------------------*/
527 * Print on the screen in a neat fashion all the info we have collected
536 struct wireless_info info;
539 /* Avoid "Unused parameter" warning */
540 args = args; count = count;
542 rc = get_info(skfd, ifname, &info);
545 case 0: /* Success */
547 display_info(&info, ifname);
551 fprintf(stderr, "%-8.16s no wireless extensions.\n\n",
556 fprintf(stderr, "%-8.16s %s\n\n", ifname, strerror(-rc));
561 /************************* SETTING ROUTINES **************************/
563 /*------------------------------------------------------------------*/
565 * Macro to handle errors when setting WE
566 * Print a nice error message and exit...
567 * We define them as macro so that "return" do the right thing.
568 * The "do {...} while(0)" is a standard trick
570 #define ERR_SET_EXT(rname, request) \
571 fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \
574 #define ABORT_ARG_NUM(rname, request) \
576 ERR_SET_EXT(rname, request); \
577 fprintf(stderr, " too few arguments.\n"); \
581 #define ABORT_ARG_TYPE(rname, request, arg) \
583 ERR_SET_EXT(rname, request); \
584 fprintf(stderr, " invalid argument \"%s\".\n", arg); \
588 #define ABORT_ARG_SIZE(rname, request, max) \
590 ERR_SET_EXT(rname, request); \
591 fprintf(stderr, " argument too big (max %d)\n", max); \
595 /*------------------------------------------------------------------*/
597 * Wrapper to push some Wireless Parameter in the driver
598 * Use standard wrapper and add pretty error message if fail...
600 #define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \
602 if(iw_set_ext(skfd, ifname, request, wrq) < 0) { \
603 ERR_SET_EXT(rname, request); \
604 fprintf(stderr, " SET failed on device %-1.16s ; %s.\n", \
605 ifname, strerror(errno)); \
609 /*------------------------------------------------------------------*/
611 * Wrapper to extract some Wireless Parameter out of the driver
612 * Use standard wrapper and add pretty error message if fail...
614 #define IW_GET_EXT_ERR(skfd, ifname, request, wrq, rname) \
616 if(iw_get_ext(skfd, ifname, request, wrq) < 0) { \
617 ERR_SET_EXT(rname, request); \
618 fprintf(stderr, " GET failed on device %-1.16s ; %s.\n", \
619 ifname, strerror(errno)); \
623 /*------------------------------------------------------------------*/
625 * Set the wireless options requested on command line
626 * This function is too long and probably should be split,
627 * because it look like the perfect definition of spaghetti code,
628 * but I'm way to lazy
631 set_info(int skfd, /* The socket */
632 char * args[], /* Command line args */
633 int count, /* Args count */
634 char * ifname) /* Dev name */
639 /* if nothing after the device name - will never happen */
642 fprintf(stderr, "Error : too few arguments.\n");
646 /* The other args on the line specify options to be set... */
647 for(i = 0; i < count; i++)
649 /* ---------- Commit changes to driver ---------- */
650 if(!strncmp(args[i], "commit", 6))
653 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq,
658 /* ---------- Set network ID ---------- */
659 if((!strcasecmp(args[i], "nwid")) ||
660 (!strcasecmp(args[i], "domain")))
664 ABORT_ARG_NUM("Set NWID", SIOCSIWNWID);
665 if((!strcasecmp(args[i], "off")) ||
666 (!strcasecmp(args[i], "any")))
667 wrq.u.nwid.disabled = 1;
669 if(!strcasecmp(args[i], "on"))
672 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq,
674 wrq.u.nwid.disabled = 0;
677 if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
679 ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]);
681 wrq.u.nwid.disabled = 0;
682 wrq.u.nwid.fixed = 1;
685 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq,
690 /* ---------- Set frequency / channel ---------- */
691 if((!strncmp(args[i], "freq", 4)) ||
692 (!strcmp(args[i], "channel")))
697 ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
698 if(!strcasecmp(args[i], "auto"))
702 wrq.u.freq.flags = 0;
706 if(!strcasecmp(args[i], "fixed"))
708 /* Get old bitrate */
709 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFREQ, &wrq,
711 wrq.u.freq.flags = IW_FREQ_FIXED;
713 else /* Should be a numeric value */
715 if(sscanf(args[i], "%lg", &(freq)) != 1)
716 ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]);
717 if(index(args[i], 'G')) freq *= GIGA;
718 if(index(args[i], 'M')) freq *= MEGA;
719 if(index(args[i], 'k')) freq *= KILO;
721 iw_float2freq(freq, &(wrq.u.freq));
723 wrq.u.freq.flags = IW_FREQ_FIXED;
725 /* Check for an additional argument */
726 if(((i+1) < count) &&
727 (!strcasecmp(args[i+1], "auto")))
729 wrq.u.freq.flags = 0;
732 if(((i+1) < count) &&
733 (!strcasecmp(args[i+1], "fixed")))
735 wrq.u.freq.flags = IW_FREQ_FIXED;
741 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
746 /* ---------- Set sensitivity ---------- */
747 if(!strncmp(args[i], "sens", 4))
750 ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS);
751 if(sscanf(args[i], "%i", &(wrq.u.sens.value)) != 1)
752 ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]);
754 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq,
759 /* ---------- Set encryption stuff ---------- */
760 if((!strncmp(args[i], "enc", 3)) ||
761 (!strcmp(args[i], "key")))
763 unsigned char key[IW_ENCODING_TOKEN_MAX];
766 ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE);
768 if(!strcasecmp(args[i], "on"))
770 /* Get old encryption information */
771 wrq.u.data.pointer = (caddr_t) key;
772 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
773 wrq.u.data.flags = 0;
774 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq,
776 wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
785 wrq.u.data.pointer = (caddr_t) NULL;
786 wrq.u.data.flags = 0;
787 wrq.u.data.length = 0;
789 /* Allow arguments in any order (it's safe) */
794 /* -- Check for the key -- */
797 keylen = iw_in_key_full(skfd, ifname,
798 args[i], key, &wrq.u.data.flags);
801 wrq.u.data.length = keylen;
802 wrq.u.data.pointer = (caddr_t) key;
808 /* -- Check for token index -- */
810 (sscanf(args[i], "[%i]", &temp) == 1) &&
811 (temp > 0) && (temp < IW_ENCODE_INDEX))
813 wrq.u.encoding.flags |= temp;
818 /* -- Check the various flags -- */
819 if((i < count) && (!strcasecmp(args[i], "off")))
821 wrq.u.data.flags |= IW_ENCODE_DISABLED;
825 if((i < count) && (!strcasecmp(args[i], "open")))
827 wrq.u.data.flags |= IW_ENCODE_OPEN;
831 if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
833 wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
837 if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
839 wrq.u.data.flags |= IW_ENCODE_TEMP;
844 while(gotone != oldone);
846 /* Pointer is absent in new API */
847 if(wrq.u.data.pointer == NULL)
848 wrq.u.data.flags |= IW_ENCODE_NOKEY;
850 /* Check if we have any invalid argument */
852 ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]);
853 /* Get back to last processed argument */
857 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq,
862 /* ---------- Set ESSID ---------- */
863 if(!strcasecmp(args[i], "essid"))
865 char essid[IW_ESSID_MAX_SIZE + 1];
866 int we_kernel_version;
870 ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
871 if((!strcasecmp(args[i], "off")) ||
872 (!strcasecmp(args[i], "any")))
874 wrq.u.essid.flags = 0;
878 if(!strcasecmp(args[i], "on"))
881 memset(essid, '\0', sizeof(essid));
882 wrq.u.essid.pointer = (caddr_t) essid;
883 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
884 wrq.u.essid.flags = 0;
885 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq,
887 wrq.u.essid.flags = 1;
891 /* '-' or '--' allow to escape the ESSID string, allowing
892 * to set it to the string "any" or "off".
893 * This is a big ugly, but it will do for now */
894 if((!strcmp(args[i], "-")) || (!strcmp(args[i], "--")))
898 ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
901 /* Check the size of what the user passed us to avoid
902 * buffer overflows */
903 if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
904 ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE);
909 wrq.u.essid.flags = 1;
910 strcpy(essid, args[i]); /* Size checked, all clear */
912 /* Check for ESSID index */
913 if(((i+1) < count) &&
914 (sscanf(args[i+1], "[%i]", &temp) == 1) &&
915 (temp > 0) && (temp < IW_ENCODE_INDEX))
917 wrq.u.essid.flags = temp;
923 /* Get version from kernel, device may not have range... */
924 we_kernel_version = iw_get_kernel_we_version();
926 /* Finally set the ESSID value */
927 wrq.u.essid.pointer = (caddr_t) essid;
928 wrq.u.essid.length = strlen(essid) + 1;
929 if(we_kernel_version > 20)
930 wrq.u.essid.length--;
931 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq,
936 /* ---------- Set AP address ---------- */
937 if(!strcasecmp(args[i], "ap"))
940 ABORT_ARG_NUM("Set AP Address", SIOCSIWAP);
942 if((!strcasecmp(args[i], "auto")) ||
943 (!strcasecmp(args[i], "any")))
945 /* Send a broadcast address */
946 iw_broad_ether(&(wrq.u.ap_addr));
950 if(!strcasecmp(args[i], "off"))
952 /* Send a NULL address */
953 iw_null_ether(&(wrq.u.ap_addr));
957 /* Get the address and check if the interface supports it */
958 if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
959 ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]);
963 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq,
968 /* ---------- Set NickName ---------- */
969 if(!strncmp(args[i], "nick", 4))
971 int we_kernel_version;
975 ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN);
976 if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
977 ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE);
979 we_kernel_version = iw_get_kernel_we_version();
981 wrq.u.essid.pointer = (caddr_t) args[i];
982 wrq.u.essid.length = strlen(args[i]) + 1;
983 if(we_kernel_version > 20)
984 wrq.u.essid.length--;
985 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq,
990 /* ---------- Set Bit-Rate ---------- */
991 if((!strncmp(args[i], "bit", 3)) ||
992 (!strcmp(args[i], "rate")))
995 ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE);
996 if(!strcasecmp(args[i], "auto"))
998 wrq.u.bitrate.value = -1;
999 wrq.u.bitrate.fixed = 0;
1003 if(!strcasecmp(args[i], "fixed"))
1005 /* Get old bitrate */
1006 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq,
1008 wrq.u.bitrate.fixed = 1;
1010 else /* Should be a numeric value */
1014 if(sscanf(args[i], "%lg", &(brate)) != 1)
1015 ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]);
1016 if(index(args[i], 'G')) brate *= GIGA;
1017 if(index(args[i], 'M')) brate *= MEGA;
1018 if(index(args[i], 'k')) brate *= KILO;
1019 wrq.u.bitrate.value = (long) brate;
1020 wrq.u.bitrate.fixed = 1;
1022 /* Check for an additional argument */
1023 if(((i+1) < count) &&
1024 (!strcasecmp(args[i+1], "auto")))
1026 wrq.u.bitrate.fixed = 0;
1029 if(((i+1) < count) &&
1030 (!strcasecmp(args[i+1], "fixed")))
1032 wrq.u.bitrate.fixed = 1;
1038 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq,
1043 /* ---------- Set RTS threshold ---------- */
1044 if(!strncasecmp(args[i], "rts", 3))
1048 ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS);
1049 wrq.u.rts.value = -1;
1050 wrq.u.rts.fixed = 1;
1051 wrq.u.rts.disabled = 0;
1052 if(!strcasecmp(args[i], "off"))
1053 wrq.u.rts.disabled = 1; /* i.e. max size */
1055 if(!strcasecmp(args[i], "auto"))
1056 wrq.u.rts.fixed = 0;
1059 if(!strcasecmp(args[i], "fixed"))
1061 /* Get old RTS threshold */
1062 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq,
1063 "Set RTS Threshold");
1064 wrq.u.rts.fixed = 1;
1066 else /* Should be a numeric value */
1067 if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.rts.value))
1069 ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]);
1072 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq,
1073 "Set RTS Threshold");
1077 /* ---------- Set fragmentation threshold ---------- */
1078 if(!strncmp(args[i], "frag", 4))
1082 ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG);
1083 wrq.u.frag.value = -1;
1084 wrq.u.frag.fixed = 1;
1085 wrq.u.frag.disabled = 0;
1086 if(!strcasecmp(args[i], "off"))
1087 wrq.u.frag.disabled = 1; /* i.e. max size */
1089 if(!strcasecmp(args[i], "auto"))
1090 wrq.u.frag.fixed = 0;
1093 if(!strcasecmp(args[i], "fixed"))
1095 /* Get old fragmentation threshold */
1096 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq,
1097 "Set Fragmentation Threshold");
1098 wrq.u.frag.fixed = 1;
1100 else /* Should be a numeric value */
1101 if(sscanf(args[i], "%li",
1102 (unsigned long *) &(wrq.u.frag.value))
1104 ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG,
1108 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq,
1109 "Set Fragmentation Threshold");
1113 /* ---------- Set operation mode ---------- */
1114 if(!strcmp(args[i], "mode"))
1120 ABORT_ARG_NUM("Set Mode", SIOCSIWMODE);
1122 if(sscanf(args[i], "%i", &k) != 1)
1125 while((k < IW_NUM_OPER_MODE) &&
1126 strncasecmp(args[i], iw_operation_mode[k], 3))
1129 if((k >= IW_NUM_OPER_MODE) || (k < 0))
1130 ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]);
1133 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq,
1138 /* ---------- Set Power Management ---------- */
1139 if(!strncmp(args[i], "power", 3))
1142 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1144 if(!strcasecmp(args[i], "off"))
1145 wrq.u.power.disabled = 1; /* i.e. max size */
1147 if(!strcasecmp(args[i], "on"))
1149 /* Get old Power info */
1150 wrq.u.power.flags = 0;
1151 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq,
1152 "Set Power Management");
1153 wrq.u.power.disabled = 0;
1159 /* Default - nope */
1160 wrq.u.power.flags = IW_POWER_ON;
1161 wrq.u.power.disabled = 0;
1163 /* Check value modifier */
1164 if(!strcasecmp(args[i], "min"))
1166 wrq.u.power.flags |= IW_POWER_MIN;
1168 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1171 if(!strcasecmp(args[i], "max"))
1173 wrq.u.power.flags |= IW_POWER_MAX;
1175 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1178 /* Check value type */
1179 if(!strcasecmp(args[i], "period"))
1181 wrq.u.power.flags |= IW_POWER_PERIOD;
1183 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1186 if(!strcasecmp(args[i], "timeout"))
1188 wrq.u.power.flags |= IW_POWER_TIMEOUT;
1190 ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1193 /* Is there any value to grab ? */
1194 if(sscanf(args[i], "%lg", &(temp)) == 1)
1196 temp *= MEGA; /* default = s */
1197 if(index(args[i], 'u')) temp /= MEGA;
1198 if(index(args[i], 'm')) temp /= KILO;
1199 wrq.u.power.value = (long) temp;
1200 if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
1201 wrq.u.power.flags |= IW_POWER_PERIOD;
1206 /* Now, check the mode */
1209 if(!strcasecmp(args[i], "all"))
1210 wrq.u.power.flags |= IW_POWER_ALL_R;
1211 if(!strncasecmp(args[i], "unicast", 4))
1212 wrq.u.power.flags |= IW_POWER_UNICAST_R;
1213 if(!strncasecmp(args[i], "multicast", 5))
1214 wrq.u.power.flags |= IW_POWER_MULTICAST_R;
1215 if(!strncasecmp(args[i], "force", 5))
1216 wrq.u.power.flags |= IW_POWER_FORCE_S;
1217 if(!strcasecmp(args[i], "repeat"))
1218 wrq.u.power.flags |= IW_POWER_REPEATER;
1219 if(wrq.u.power.flags & IW_POWER_MODE)
1226 ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER,
1231 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq,
1232 "Set Power Management");
1236 /* ---------- Set Transmit-Power ---------- */
1237 if(!strncmp(args[i], "txpower", 3))
1239 struct iw_range range;
1242 ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW);
1244 /* Extract range info */
1245 if(iw_get_range_info(skfd, ifname, &range) < 0)
1246 memset(&range, 0, sizeof(range));
1248 /* Prepare the request */
1249 wrq.u.txpower.value = -1;
1250 wrq.u.txpower.fixed = 1;
1251 wrq.u.txpower.disabled = 0;
1252 wrq.u.txpower.flags = IW_TXPOW_DBM;
1253 if(!strcasecmp(args[i], "off"))
1254 wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
1256 if(!strcasecmp(args[i], "auto"))
1257 wrq.u.txpower.fixed = 0; /* i.e. use power control */
1260 if(!strcasecmp(args[i], "on"))
1262 /* Get old tx-power */
1263 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1265 wrq.u.txpower.disabled = 0;
1269 if(!strcasecmp(args[i], "fixed"))
1271 /* Get old tx-power */
1272 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1274 wrq.u.txpower.fixed = 1;
1275 wrq.u.txpower.disabled = 0;
1277 else /* Should be a numeric value */
1283 if(sscanf(args[i], "%i", &(power)) != 1)
1284 ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW,
1287 /* Check if milliWatt
1288 * We authorise a single 'm' as a shorthand for 'mW',
1289 * on the other hand a 'd' probably means 'dBm'... */
1290 ismwatt = ((index(args[i], 'm') != NULL)
1291 && (index(args[i], 'd') == NULL));
1293 /* We could check 'W' alone... Another time... */
1296 if(range.txpower_capa & IW_TXPOW_RELATIVE)
1300 ABORT_ARG_TYPE("Set Tx Power",
1305 if(range.txpower_capa & IW_TXPOW_MWATT)
1308 power = iw_dbm2mwatt(power);
1309 wrq.u.txpower.flags = IW_TXPOW_MWATT;
1314 power = iw_mwatt2dbm(power);
1315 wrq.u.txpower.flags = IW_TXPOW_DBM;
1317 wrq.u.txpower.value = power;
1319 /* Check for an additional argument */
1320 if(((i+1) < count) &&
1321 (!strcasecmp(args[i+1], "auto")))
1323 wrq.u.txpower.fixed = 0;
1326 if(((i+1) < count) &&
1327 (!strcasecmp(args[i+1], "fixed")))
1329 wrq.u.txpower.fixed = 1;
1336 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq,
1341 /* ---------- Set Retry limit ---------- */
1342 if(!strncmp(args[i], "retry", 3))
1348 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1350 /* Default - nope */
1351 wrq.u.retry.flags = IW_RETRY_LIMIT;
1352 wrq.u.retry.disabled = 0;
1354 /* Check value modifier */
1355 if(!strcasecmp(args[i], "min"))
1357 wrq.u.retry.flags |= IW_RETRY_MIN;
1359 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1362 if(!strcasecmp(args[i], "max"))
1364 wrq.u.retry.flags |= IW_RETRY_MAX;
1366 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1369 /* Check value type */
1370 if(!strcasecmp(args[i], "limit"))
1372 wrq.u.retry.flags |= IW_RETRY_LIMIT;
1374 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1377 if(!strncasecmp(args[i], "lifetime", 4))
1379 wrq.u.retry.flags &= ~IW_RETRY_LIMIT;
1380 wrq.u.retry.flags |= IW_RETRY_LIFETIME;
1382 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1385 /* Is there any value to grab ? */
1386 if(sscanf(args[i], "%lg", &(temp)) == 1)
1388 /* Limit is absolute, on the other hand lifetime is seconds */
1389 if(!(wrq.u.retry.flags & IW_RETRY_LIMIT))
1391 /* Normalise lifetime */
1392 temp *= MEGA; /* default = s */
1393 if(index(args[i], 'u')) temp /= MEGA;
1394 if(index(args[i], 'm')) temp /= KILO;
1396 wrq.u.retry.value = (long) temp;
1402 ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]);
1405 IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq,
1410 /* ---------- Other ---------- */
1411 /* Here we have an unrecognised arg... */
1412 fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
1415 } /* for(index ... */
1419 /******************************* MAIN ********************************/
1421 /*------------------------------------------------------------------*/
1429 int skfd; /* generic raw socket desc. */
1432 /* Create a channel to the NET kernel. */
1433 if((skfd = iw_sockets_open()) < 0)
1439 /* No argument : show the list of all device + info */
1441 iw_enum_devices(skfd, &print_info, NULL, 0);
1443 /* Special case for help... */
1444 if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
1447 /* Special case for version... */
1448 if(!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
1449 goterr = iw_print_version_info("iwconfig");
1452 /* '--' escape device name */
1453 if((argc > 2) && !strcmp(argv[1], "--"))
1459 /* The device name must be the first argument */
1461 print_info(skfd, argv[1], NULL, 0);
1463 /* The other args on the line specify options to be set... */
1464 goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
1467 /* Close the socket. */
1468 iw_sockets_close(skfd);