OSDN Git Service

03093e64d8dbe3b60bef16c87894c710115c6996
[android-x86/external-wireless-tools.git] / wireless_tools / iwconfig.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPLB 97->99 - HPL 99->04
5  *
6  * Main code for "iwconfig". This is the generic tool for most
7  * manipulations...
8  * You need to link this code against "iwlib.c" and "-lm".
9  *
10  * This file is released under the GPL license.
11  *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
12  */
13
14 #include "iwlib.h"              /* Header */
15
16 /************************* MISC SUBROUTINES **************************/
17
18 /*------------------------------------------------------------------*/
19 /*
20  * Print usage string
21  */
22 static void
23 iw_usage(void)
24 {
25   fprintf(stderr,
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"
30         "                          [channel N]\n"
31         "                          [ap {N|off|auto}]\n"
32         "                          [sens N]\n"
33         "                          [nick N]\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"
41         "                          [commit]\n"
42         "       Check man pages for more details.\n\n"
43   );
44 }
45
46
47 /************************* DISPLAY ROUTINES **************************/
48
49 /*------------------------------------------------------------------*/
50 /*
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...
54  */
55 static int
56 get_info(int                    skfd,
57          char *                 ifname,
58          struct wireless_info * info)
59 {
60   struct iwreq          wrq;
61
62   memset((char *) info, 0, sizeof(struct wireless_info));
63
64   /* Get basic information */
65   if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0)
66     {
67       /* If no wireless name : no wireless extensions */
68       /* But let's check if the interface exists at all */
69       struct ifreq ifr;
70
71       strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
72       if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
73         return(-ENODEV);
74       else
75         return(-ENOTSUP);
76     }
77
78   /* Get ranges */
79   if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
80     info->has_range = 1;
81
82   /* Get sensitivity */
83   if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
84     {
85       info->has_sens = 1;
86       memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
87     }
88
89   /* Get AP address */
90   if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
91     {
92       info->has_ap_addr = 1;
93       memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
94     }
95
96   /* Get NickName */
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;
103
104   /* Get bit rate */
105   if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
106     {
107       info->has_bitrate = 1;
108       memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
109     }
110
111   /* Get RTS threshold */
112   if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
113     {
114       info->has_rts = 1;
115       memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
116     }
117
118   /* Get fragmentation threshold */
119   if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
120     {
121       info->has_frag = 1;
122       memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
123     }
124
125   /* Get Power Management settings */
126   wrq.u.power.flags = 0;
127   if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
128     {
129       info->has_power = 1;
130       memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
131     }
132
133   if((info->has_range) && (info->range.we_version_compiled > 9))
134     {
135       /* Get Transmit Power */
136       if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
137         {
138           info->has_txpower = 1;
139           memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
140         }
141     }
142
143   if((info->has_range) && (info->range.we_version_compiled > 10))
144     {
145       /* Get retry limit/lifetime */
146       if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
147         {
148           info->has_retry = 1;
149           memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
150         }
151     }
152
153   /* Get stats */
154   if(iw_get_stats(skfd, ifname, &(info->stats),
155                   &info->range, info->has_range) >= 0)
156     {
157       info->has_stats = 1;
158     }
159
160 #ifdef DISPLAY_WPA
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 */
165
166   /* Get WPA/802.1x/802.11i security parameters */
167   if((info->has_range) && (info->range.we_version_compiled > 17))
168     {
169       wrq.u.param.flags = IW_AUTH_KEY_MGMT;
170       if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
171         {
172           info->has_auth_key_mgmt = 1;
173           info->auth_key_mgmt = wrq.u.param.value;
174         }
175
176       wrq.u.param.flags = IW_AUTH_CIPHER_PAIRWISE;
177       if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
178         {
179           info->has_auth_cipher_pairwise = 1;
180           info->auth_cipher_pairwise = wrq.u.param.value;
181         }
182
183       wrq.u.param.flags = IW_AUTH_CIPHER_GROUP;
184       if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
185         {
186           info->has_auth_cipher_group = 1;
187           info->auth_cipher_group = wrq.u.param.value;
188         }
189     }
190 #endif
191
192   return(0);
193 }
194
195 /*------------------------------------------------------------------*/
196 /*
197  * Print on the screen in a neat fashion all the info we have collected
198  * on a device.
199  */
200 static void
201 display_info(struct wireless_info *     info,
202              char *                     ifname)
203 {
204   char          buffer[128];    /* Temporary buffer */
205
206   /* One token is more of less 5 characters, 14 tokens per line */
207   int   tokens = 3;     /* For name */
208
209   /* Display device name and wireless name (name of the protocol used) */
210   printf("%-8.16s  %s  ", ifname, info->b.name);
211
212   /* Display ESSID (extended network), if any */
213   if(info->b.has_essid)
214     {
215       if(info->b.essid_on)
216         {
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));
221           else
222             printf("ESSID:\"%s\"  ", info->b.essid);
223         }
224       else
225         printf("ESSID:off/any  ");
226     }
227
228   /* Display NickName (station name), if any */
229   if(info->has_nickname)
230     printf("Nickname:\"%s\"", info->nickname);
231
232   /* Formatting */
233   if(info->b.has_essid || info->has_nickname)
234     {
235       printf("\n          ");
236       tokens = 0;
237     }
238
239   /* Display Network ID */
240   if(info->b.has_nwid)
241     {
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  ");
246       else
247         printf("NWID:%X  ", info->b.nwid.value);
248       tokens +=2;
249     }
250
251   /* Display the current mode of operation */
252   if(info->b.has_mode)
253     {
254       printf("Mode:%s  ", iw_operation_mode[info->b.mode]);
255       tokens +=3;
256     }
257
258   /* Display frequency / channel */
259   if(info->b.has_freq)
260     {
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);
268       /* Display */
269       iw_print_freq(buffer, sizeof(buffer), freq, -1, info->b.freq_flags);
270       printf("%s  ", buffer);
271       tokens +=4;
272     }
273
274   /* Display the address of the current Access Point */
275   if(info->has_ap_addr)
276     {
277       /* A bit of clever formatting */
278       if(tokens > 8)
279         {
280           printf("\n          ");
281           tokens = 0;
282         }
283       tokens +=6;
284
285       /* Oups ! No Access Point in Ad-Hoc mode */
286       if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC))
287         printf("Cell:");
288       else
289         printf("Access Point:");
290       printf(" %s   ", iw_sawap_ntop(&info->ap_addr, buffer));
291     }
292
293   /* Display the currently used/set bit-rate */
294   if(info->has_bitrate)
295     {
296       /* A bit of clever formatting */
297       if(tokens > 11)
298         {
299           printf("\n          ");
300           tokens = 0;
301         }
302       tokens +=3;
303
304       /* Display it */
305       iw_print_bitrate(buffer, sizeof(buffer), info->bitrate.value);
306       printf("Bit Rate%c%s   ", (info->bitrate.fixed ? '=' : ':'), buffer);
307     }
308
309   /* Display the Transmit Power */
310   if(info->has_txpower)
311     {
312       /* A bit of clever formatting */
313       if(tokens > 11)
314         {
315           printf("\n          ");
316           tokens = 0;
317         }
318       tokens +=3;
319
320       /* Display it */
321       iw_print_txpower(buffer, sizeof(buffer), &info->txpower);
322       printf("Tx-Power%c%s   ", (info->txpower.fixed ? '=' : ':'), buffer);
323     }
324
325   /* Display sensitivity */
326   if(info->has_sens)
327     {
328       /* A bit of clever formatting */
329       if(tokens > 10)
330         {
331           printf("\n          ");
332           tokens = 0;
333         }
334       tokens +=4;
335
336       /* Fixed ? */
337       if(info->sens.fixed)
338         printf("Sensitivity=");
339       else
340         printf("Sensitivity:");
341
342       if(info->has_range)
343         /* Display in dBm ? */
344         if(info->sens.value < 0)
345           printf("%d dBm  ", info->sens.value);
346         else
347           printf("%d/%d  ", info->sens.value, info->range.sensitivity);
348       else
349         printf("%d  ", info->sens.value);
350     }
351
352   printf("\n          ");
353   tokens = 0;
354
355   /* Display retry limit/lifetime information */
356   if(info->has_retry)
357     { 
358       printf("Retry");
359       /* Disabled ? */
360       if(info->retry.disabled)
361         printf(":off");
362       else
363         {
364           /* Let's check the value and its type */
365           if(info->retry.flags & IW_RETRY_TYPE)
366             {
367               iw_print_retry_value(buffer, sizeof(buffer),
368                                    info->retry.value, info->retry.flags);
369               printf("%s", buffer);
370             }
371
372           /* Let's check if nothing (simply on) */
373           if(info->retry.flags == IW_RETRY_ON)
374             printf(":on");
375         }
376       printf("   ");
377       tokens += 5;      /* Between 3 and 5, depend on flags */
378     }
379
380   /* Display the RTS threshold */
381   if(info->has_rts)
382     {
383       /* Disabled ? */
384       if(info->rts.disabled)
385         printf("RTS thr:off   ");
386       else
387         {
388           /* Fixed ? */
389           if(info->rts.fixed)
390             printf("RTS thr=");
391           else
392             printf("RTS thr:");
393
394           printf("%d B   ", info->rts.value);
395         }
396       tokens += 3;
397     }
398
399   /* Display the fragmentation threshold */
400   if(info->has_frag)
401     {
402       /* A bit of clever formatting */
403       if(tokens > 10)
404         {
405           printf("\n          ");
406           tokens = 0;
407         }
408       tokens +=4;
409
410       /* Disabled ? */
411       if(info->frag.disabled)
412         printf("Fragment thr:off");
413       else
414         {
415           /* Fixed ? */
416           if(info->frag.fixed)
417             printf("Fragment thr=");
418           else
419             printf("Fragment thr:");
420
421           printf("%d B   ", info->frag.value);
422         }
423     }
424
425   /* Formating */
426   if(tokens > 0)
427     printf("\n          ");
428
429   /* Display encryption information */
430   /* Note : we display only the "current" key, use iwlist to list all keys */
431   if(info->b.has_key)
432     {
433       printf("Encryption key:");
434       if((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0))
435         printf("off");
436       else
437         {
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);
442
443           /* Other info... */
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");
450         }
451       printf("\n          ");
452     }
453
454 #ifdef DISPLAY_WPA
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)
458     {
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);
466       printf("\n          ");
467     }
468 #endif
469
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 ;-) */
474     { 
475       printf("Power Management");
476       /* Disabled ? */
477       if(info->power.disabled)
478         printf(":off");
479       else
480         {
481           /* Let's check the value and its type */
482           if(info->power.flags & IW_POWER_TYPE)
483             {
484               iw_print_pm_value(buffer, sizeof(buffer),
485                                 info->power.value, info->power.flags);
486               printf("%s  ", buffer);
487             }
488
489           /* Let's check the mode */
490           iw_print_pm_mode(buffer, sizeof(buffer), info->power.flags);
491           printf("%s", buffer);
492
493           /* Let's check if nothing (simply on) */
494           if(info->power.flags == IW_POWER_ON)
495             printf(":on");
496         }
497       printf("\n          ");
498     }
499
500   /* Display statistics */
501   if(info->has_stats)
502     {
503       iw_print_stats(buffer, sizeof(buffer),
504                      &info->stats.qual, &info->range, info->has_range);
505       printf("Link %s\n", buffer);
506
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);
515       else
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);
520     }
521
522   printf("\n");
523 }
524
525 /*------------------------------------------------------------------*/
526 /*
527  * Print on the screen in a neat fashion all the info we have collected
528  * on a device.
529  */
530 static int
531 print_info(int          skfd,
532            char *       ifname,
533            char *       args[],
534            int          count)
535 {
536   struct wireless_info  info;
537   int                   rc;
538
539   /* Avoid "Unused parameter" warning */
540   args = args; count = count;
541
542   rc = get_info(skfd, ifname, &info);
543   switch(rc)
544     {
545     case 0:     /* Success */
546       /* Display it ! */
547       display_info(&info, ifname);
548       break;
549
550     case -ENOTSUP:
551       fprintf(stderr, "%-8.16s  no wireless extensions.\n\n",
552               ifname);
553       break;
554
555     default:
556       fprintf(stderr, "%-8.16s  %s\n\n", ifname, strerror(-rc));
557     }
558   return(rc);
559 }
560
561 /************************* SETTING ROUTINES **************************/
562
563 /*------------------------------------------------------------------*/
564 /*
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
569  */
570 #define ERR_SET_EXT(rname, request) \
571         fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \
572                 rname, request)
573
574 #define ABORT_ARG_NUM(rname, request) \
575         do { \
576                 ERR_SET_EXT(rname, request); \
577                 fprintf(stderr, "    too few arguments.\n"); \
578                 return(-1); \
579         } while(0)
580
581 #define ABORT_ARG_TYPE(rname, request, arg) \
582         do { \
583                 ERR_SET_EXT(rname, request); \
584                 fprintf(stderr, "    invalid argument \"%s\".\n", arg); \
585                 return(-2); \
586         } while(0)
587
588 #define ABORT_ARG_SIZE(rname, request, max) \
589         do { \
590                 ERR_SET_EXT(rname, request); \
591                 fprintf(stderr, "    argument too big (max %d)\n", max); \
592                 return(-3); \
593         } while(0)
594
595 /*------------------------------------------------------------------*/
596 /*
597  * Wrapper to push some Wireless Parameter in the driver
598  * Use standard wrapper and add pretty error message if fail...
599  */
600 #define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \
601         do { \
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)); \
606                 return(-5); \
607         } } while(0)
608
609 /*------------------------------------------------------------------*/
610 /*
611  * Wrapper to extract some Wireless Parameter out of the driver
612  * Use standard wrapper and add pretty error message if fail...
613  */
614 #define IW_GET_EXT_ERR(skfd, ifname, request, wrq, rname) \
615         do { \
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)); \
620                 return(-6); \
621         } } while(0)
622
623 /*------------------------------------------------------------------*/
624 /*
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
629  */
630 static int
631 set_info(int            skfd,           /* The socket */
632          char *         args[],         /* Command line args */
633          int            count,          /* Args count */
634          char *         ifname)         /* Dev name */
635 {
636   struct iwreq          wrq;
637   int                   i;
638
639   /* if nothing after the device name - will never happen */
640   if(count < 1)
641     {
642       fprintf(stderr, "Error : too few arguments.\n");
643       return(-1);
644     }
645
646   /* The other args on the line specify options to be set... */
647   for(i = 0; i < count; i++)
648     {
649       /* ---------- Commit changes to driver ---------- */
650       if(!strncmp(args[i], "commit", 6))
651         {
652           /* No args */
653           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq,
654                          "Commit changes");
655           continue;
656         }
657
658       /* ---------- Set network ID ---------- */
659       if((!strcasecmp(args[i], "nwid")) ||
660          (!strcasecmp(args[i], "domain")))
661         {
662           i++;
663           if(i >= count)
664             ABORT_ARG_NUM("Set NWID", SIOCSIWNWID);
665           if((!strcasecmp(args[i], "off")) ||
666              (!strcasecmp(args[i], "any")))
667             wrq.u.nwid.disabled = 1;
668           else
669             if(!strcasecmp(args[i], "on"))
670               {
671                 /* Get old nwid */
672                 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq,
673                                "Set NWID");
674                 wrq.u.nwid.disabled = 0;
675               }
676             else
677               if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
678                  != 1)
679                 ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]);
680               else
681                 wrq.u.nwid.disabled = 0;
682           wrq.u.nwid.fixed = 1;
683
684           /* Set new nwid */
685           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq,
686                          "Set NWID");
687           continue;
688         }
689
690       /* ---------- Set frequency / channel ---------- */
691       if((!strncmp(args[i], "freq", 4)) ||
692          (!strcmp(args[i], "channel")))
693         {
694           double                freq;
695
696           if(++i >= count)
697             ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
698           if(!strcasecmp(args[i], "auto"))
699             {
700               wrq.u.freq.m = -1;
701               wrq.u.freq.e = 0;
702               wrq.u.freq.flags = 0;
703             }
704           else
705             {
706               if(!strcasecmp(args[i], "fixed"))
707                 {
708                   /* Get old bitrate */
709                   IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFREQ, &wrq,
710                                  "Set Bit Rate");
711                   wrq.u.freq.flags = IW_FREQ_FIXED;
712                 }
713               else                      /* Should be a numeric value */
714                 {
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;
720
721                   iw_float2freq(freq, &(wrq.u.freq));
722
723                   wrq.u.freq.flags = IW_FREQ_FIXED;
724
725                   /* Check for an additional argument */
726                   if(((i+1) < count) &&
727                      (!strcasecmp(args[i+1], "auto")))
728                     {
729                       wrq.u.freq.flags = 0;
730                       ++i;
731                     }
732                   if(((i+1) < count) &&
733                      (!strcasecmp(args[i+1], "fixed")))
734                     {
735                       wrq.u.freq.flags = IW_FREQ_FIXED;
736                       ++i;
737                     }
738                 }
739             }
740
741           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
742                          "Set Frequency");
743           continue;
744         }
745
746       /* ---------- Set sensitivity ---------- */
747       if(!strncmp(args[i], "sens", 4))
748         {
749           if(++i >= count)
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]);
753
754           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq,
755                          "Set Sensitivity");
756           continue;
757         }
758
759       /* ---------- Set encryption stuff ---------- */
760       if((!strncmp(args[i], "enc", 3)) ||
761          (!strcmp(args[i], "key")))
762         {
763           unsigned char key[IW_ENCODING_TOKEN_MAX];
764
765           if(++i >= count)
766             ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE);
767
768           if(!strcasecmp(args[i], "on"))
769             {
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,
775                              "Set Encode");
776               wrq.u.data.flags &= ~IW_ENCODE_DISABLED;  /* Enable */
777             }
778           else
779             {
780               int       gotone = 0;
781               int       oldone;
782               int       keylen;
783               int       temp;
784
785               wrq.u.data.pointer = (caddr_t) NULL;
786               wrq.u.data.flags = 0;
787               wrq.u.data.length = 0;
788
789               /* Allow arguments in any order (it's safe) */
790               do
791                 {
792                   oldone = gotone;
793
794                   /* -- Check for the key -- */
795                   if(i < count)
796                     {
797                       keylen = iw_in_key_full(skfd, ifname,
798                                               args[i], key, &wrq.u.data.flags);
799                       if(keylen > 0)
800                         {
801                           wrq.u.data.length = keylen;
802                           wrq.u.data.pointer = (caddr_t) key;
803                           ++i;
804                           gotone++;
805                         }
806                     }
807
808                   /* -- Check for token index -- */
809                   if((i < count) &&
810                      (sscanf(args[i], "[%i]", &temp) == 1) &&
811                      (temp > 0) && (temp < IW_ENCODE_INDEX))
812                     {
813                       wrq.u.encoding.flags |= temp;
814                       ++i;
815                       gotone++;
816                     }
817
818                   /* -- Check the various flags -- */
819                   if((i < count) && (!strcasecmp(args[i], "off")))
820                     {
821                       wrq.u.data.flags |= IW_ENCODE_DISABLED;
822                       ++i;
823                       gotone++;
824                     }
825                   if((i < count) && (!strcasecmp(args[i], "open")))
826                     {
827                       wrq.u.data.flags |= IW_ENCODE_OPEN;
828                       ++i;
829                       gotone++;
830                     }
831                   if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
832                     {
833                       wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
834                       ++i;
835                       gotone++;
836                     }
837                   if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
838                     {
839                       wrq.u.data.flags |= IW_ENCODE_TEMP;
840                       ++i;
841                       gotone++;
842                     }
843                 }
844               while(gotone != oldone);
845
846               /* Pointer is absent in new API */
847               if(wrq.u.data.pointer == NULL)
848                 wrq.u.data.flags |= IW_ENCODE_NOKEY;
849
850               /* Check if we have any invalid argument */
851               if(!gotone)
852                 ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]);
853               /* Get back to last processed argument */
854               --i;
855             }
856
857           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq,
858                          "Set Encode");
859           continue;
860         }
861
862       /* ---------- Set ESSID ---------- */
863       if(!strcasecmp(args[i], "essid"))
864         {
865           char          essid[IW_ESSID_MAX_SIZE + 1];
866           int           we_kernel_version;
867
868           i++;
869           if(i >= count)
870             ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
871           if((!strcasecmp(args[i], "off")) ||
872              (!strcasecmp(args[i], "any")))
873             {
874               wrq.u.essid.flags = 0;
875               essid[0] = '\0';
876             }
877           else
878             if(!strcasecmp(args[i], "on"))
879               {
880                 /* Get old essid */
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,
886                                "Set ESSID");
887                 wrq.u.essid.flags = 1;
888               }
889             else
890               {
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], "--")))
895                   {
896                     i++;
897                     if(i >= count)
898                       ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
899                   }
900
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);
905                 else
906                   {
907                     int         temp;
908
909                     wrq.u.essid.flags = 1;
910                     strcpy(essid, args[i]);     /* Size checked, all clear */
911
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))
916                       {
917                         wrq.u.essid.flags = temp;
918                         ++i;
919                       }
920                   }
921               }
922
923           /* Get version from kernel, device may not have range... */
924           we_kernel_version = iw_get_kernel_we_version();
925
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,
932                          "Set ESSID");
933           continue;
934         }
935
936       /* ---------- Set AP address ---------- */
937       if(!strcasecmp(args[i], "ap"))
938         {
939           if(++i >= count)
940             ABORT_ARG_NUM("Set AP Address", SIOCSIWAP);
941
942           if((!strcasecmp(args[i], "auto")) ||
943              (!strcasecmp(args[i], "any")))
944             {
945               /* Send a broadcast address */
946               iw_broad_ether(&(wrq.u.ap_addr));
947             }
948           else
949             {
950               if(!strcasecmp(args[i], "off"))
951                 {
952                   /* Send a NULL address */
953                   iw_null_ether(&(wrq.u.ap_addr));
954                 }
955               else
956                 {
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]);
960                 }
961             }
962
963           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq,
964                          "Set AP Address");
965           continue;
966         }
967
968       /* ---------- Set NickName ---------- */
969       if(!strncmp(args[i], "nick", 4))
970         {
971           int           we_kernel_version;
972
973           i++;
974           if(i >= count)
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);
978
979           we_kernel_version = iw_get_kernel_we_version();
980
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,
986                          "Set Nickname");
987           continue;
988         }
989
990       /* ---------- Set Bit-Rate ---------- */
991       if((!strncmp(args[i], "bit", 3)) ||
992          (!strcmp(args[i], "rate")))
993         {
994           if(++i >= count)
995             ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE);
996           if(!strcasecmp(args[i], "auto"))
997             {
998               wrq.u.bitrate.value = -1;
999               wrq.u.bitrate.fixed = 0;
1000             }
1001           else
1002             {
1003               if(!strcasecmp(args[i], "fixed"))
1004                 {
1005                   /* Get old bitrate */
1006                   IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq,
1007                                  "Set Bit Rate");
1008                   wrq.u.bitrate.fixed = 1;
1009                 }
1010               else                      /* Should be a numeric value */
1011                 {
1012                   double                brate;
1013
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;
1021
1022                   /* Check for an additional argument */
1023                   if(((i+1) < count) &&
1024                      (!strcasecmp(args[i+1], "auto")))
1025                     {
1026                       wrq.u.bitrate.fixed = 0;
1027                       ++i;
1028                     }
1029                   if(((i+1) < count) &&
1030                      (!strcasecmp(args[i+1], "fixed")))
1031                     {
1032                       wrq.u.bitrate.fixed = 1;
1033                       ++i;
1034                     }
1035                 }
1036             }
1037
1038           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq,
1039                          "Set Bit Rate");
1040           continue;
1041         }
1042
1043       /* ---------- Set RTS threshold ---------- */
1044       if(!strncasecmp(args[i], "rts", 3))
1045         {
1046           i++;
1047           if(i >= count)
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 */
1054           else
1055             if(!strcasecmp(args[i], "auto"))
1056               wrq.u.rts.fixed = 0;
1057             else
1058               {
1059                 if(!strcasecmp(args[i], "fixed"))
1060                   {
1061                     /* Get old RTS threshold */
1062                     IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq,
1063                                    "Set RTS Threshold");
1064                     wrq.u.rts.fixed = 1;
1065                   }
1066                 else                    /* Should be a numeric value */
1067                   if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.rts.value))
1068                      != 1)
1069                     ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]);
1070             }
1071
1072           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq,
1073                          "Set RTS Threshold");
1074           continue;
1075         }
1076
1077       /* ---------- Set fragmentation threshold ---------- */
1078       if(!strncmp(args[i], "frag", 4))
1079         {
1080           i++;
1081           if(i >= count)
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 */
1088           else
1089             if(!strcasecmp(args[i], "auto"))
1090               wrq.u.frag.fixed = 0;
1091             else
1092               {
1093                 if(!strcasecmp(args[i], "fixed"))
1094                   {
1095                     /* Get old fragmentation threshold */
1096                     IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq,
1097                                    "Set Fragmentation Threshold");
1098                     wrq.u.frag.fixed = 1;
1099                   }
1100                 else                    /* Should be a numeric value */
1101                   if(sscanf(args[i], "%li",
1102                             (unsigned long *) &(wrq.u.frag.value))
1103                      != 1)
1104                     ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG,
1105                                    args[i]);
1106             }
1107
1108           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq,
1109                          "Set Fragmentation Threshold");
1110           continue;
1111         }
1112
1113       /* ---------- Set operation mode ---------- */
1114       if(!strcmp(args[i], "mode"))
1115         {
1116           int   k;
1117
1118           i++;
1119           if(i >= count)
1120             ABORT_ARG_NUM("Set Mode", SIOCSIWMODE);
1121
1122           if(sscanf(args[i], "%i", &k) != 1)
1123             {
1124               k = 0;
1125               while((k < IW_NUM_OPER_MODE) &&
1126                     strncasecmp(args[i], iw_operation_mode[k], 3))
1127                 k++;
1128             }
1129           if((k >= IW_NUM_OPER_MODE) || (k < 0))
1130             ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]);
1131
1132           wrq.u.mode = k;
1133           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq,
1134                          "Set Mode");
1135           continue;
1136         }
1137
1138       /* ---------- Set Power Management ---------- */
1139       if(!strncmp(args[i], "power", 3))
1140         {
1141           if(++i >= count)
1142             ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1143
1144           if(!strcasecmp(args[i], "off"))
1145             wrq.u.power.disabled = 1;   /* i.e. max size */
1146           else
1147             if(!strcasecmp(args[i], "on"))
1148               {
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;
1154               }
1155             else
1156               {
1157                 double          temp;
1158                 int             gotone = 0;
1159                 /* Default - nope */
1160                 wrq.u.power.flags = IW_POWER_ON;
1161                 wrq.u.power.disabled = 0;
1162
1163                 /* Check value modifier */
1164                 if(!strcasecmp(args[i], "min"))
1165                   {
1166                     wrq.u.power.flags |= IW_POWER_MIN;
1167                     if(++i >= count)
1168                       ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1169                   }
1170                 else
1171                   if(!strcasecmp(args[i], "max"))
1172                     {
1173                       wrq.u.power.flags |= IW_POWER_MAX;
1174                       if(++i >= count)
1175                         ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1176                     }
1177
1178                 /* Check value type */
1179                 if(!strcasecmp(args[i], "period"))
1180                   {
1181                     wrq.u.power.flags |= IW_POWER_PERIOD;
1182                     if(++i >= count)
1183                       ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1184                   }
1185                 else
1186                   if(!strcasecmp(args[i], "timeout"))
1187                     {
1188                       wrq.u.power.flags |= IW_POWER_TIMEOUT;
1189                       if(++i >= count)
1190                         ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1191                     }
1192
1193                 /* Is there any value to grab ? */
1194                 if(sscanf(args[i], "%lg", &(temp)) == 1)
1195                   {
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;
1202                     ++i;
1203                     gotone = 1;
1204                   }
1205
1206                 /* Now, check the mode */
1207                 if(i < count)
1208                   {
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)
1220                       {
1221                         ++i;
1222                         gotone = 1;
1223                       }
1224                   }
1225                 if(!gotone)
1226                   ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER,
1227                                  args[i]);
1228                 --i;
1229               }
1230
1231           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq,
1232                        "Set Power Management");
1233           continue;
1234         }
1235
1236       /* ---------- Set Transmit-Power ---------- */
1237       if(!strncmp(args[i], "txpower", 3))
1238         {
1239           struct iw_range       range;
1240
1241           if(++i >= count)
1242             ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW);
1243
1244           /* Extract range info */
1245           if(iw_get_range_info(skfd, ifname, &range) < 0)
1246             memset(&range, 0, sizeof(range));
1247
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 */
1255           else
1256             if(!strcasecmp(args[i], "auto"))
1257               wrq.u.txpower.fixed = 0;  /* i.e. use power control */
1258             else
1259               {
1260                 if(!strcasecmp(args[i], "on"))
1261                   {
1262                     /* Get old tx-power */
1263                     IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1264                                    "Set Tx Power");
1265                     wrq.u.txpower.disabled = 0;
1266                   }
1267                 else
1268                   {
1269                     if(!strcasecmp(args[i], "fixed"))
1270                       {
1271                         /* Get old tx-power */
1272                         IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1273                                        "Set Tx Power");
1274                         wrq.u.txpower.fixed = 1;
1275                         wrq.u.txpower.disabled = 0;
1276                       }
1277                     else                        /* Should be a numeric value */
1278                       {
1279                         int             power;
1280                         int             ismwatt = 0;
1281
1282                         /* Get the value */
1283                         if(sscanf(args[i], "%i", &(power)) != 1)
1284                           ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW,
1285                                          args[i]);
1286
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));
1292
1293                         /* We could check 'W' alone... Another time... */
1294
1295                         /* Convert */
1296                         if(range.txpower_capa & IW_TXPOW_RELATIVE)
1297                           {
1298                             /* Can't convert */
1299                             if(ismwatt)
1300                               ABORT_ARG_TYPE("Set Tx Power",
1301                                              SIOCSIWTXPOW,
1302                                              args[i]);
1303                           }
1304                         else
1305                           if(range.txpower_capa & IW_TXPOW_MWATT)
1306                             {
1307                               if(!ismwatt)
1308                                 power = iw_dbm2mwatt(power);
1309                               wrq.u.txpower.flags = IW_TXPOW_MWATT;
1310                             }
1311                           else
1312                             {
1313                               if(ismwatt)
1314                                 power = iw_mwatt2dbm(power);
1315                               wrq.u.txpower.flags = IW_TXPOW_DBM;
1316                             }
1317                         wrq.u.txpower.value = power;
1318
1319                         /* Check for an additional argument */
1320                         if(((i+1) < count) &&
1321                            (!strcasecmp(args[i+1], "auto")))
1322                           {
1323                             wrq.u.txpower.fixed = 0;
1324                             ++i;
1325                           }
1326                         if(((i+1) < count) &&
1327                            (!strcasecmp(args[i+1], "fixed")))
1328                           {
1329                             wrq.u.txpower.fixed = 1;
1330                             ++i;
1331                           }
1332                       }
1333                   }
1334               }
1335
1336           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq,
1337                          "Set Tx Power");
1338           continue;
1339         }
1340
1341       /* ---------- Set Retry limit ---------- */
1342       if(!strncmp(args[i], "retry", 3))
1343         {
1344           double                temp;
1345           int           gotone = 0;
1346
1347           if(++i >= count)
1348             ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1349
1350           /* Default - nope */
1351           wrq.u.retry.flags = IW_RETRY_LIMIT;
1352           wrq.u.retry.disabled = 0;
1353
1354           /* Check value modifier */
1355           if(!strcasecmp(args[i], "min"))
1356             {
1357               wrq.u.retry.flags |= IW_RETRY_MIN;
1358               if(++i >= count)
1359                 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1360             }
1361           else
1362             if(!strcasecmp(args[i], "max"))
1363               {
1364                 wrq.u.retry.flags |= IW_RETRY_MAX;
1365                 if(++i >= count)
1366                   ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1367               }
1368
1369           /* Check value type */
1370           if(!strcasecmp(args[i], "limit"))
1371             {
1372               wrq.u.retry.flags |= IW_RETRY_LIMIT;
1373               if(++i >= count)
1374                 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1375             }
1376           else
1377             if(!strncasecmp(args[i], "lifetime", 4))
1378               {
1379                 wrq.u.retry.flags &= ~IW_RETRY_LIMIT;
1380                 wrq.u.retry.flags |= IW_RETRY_LIFETIME;
1381                 if(++i >= count)
1382                   ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1383               }
1384
1385           /* Is there any value to grab ? */
1386           if(sscanf(args[i], "%lg", &(temp)) == 1)
1387             {
1388               /* Limit is absolute, on the other hand lifetime is seconds */
1389               if(!(wrq.u.retry.flags & IW_RETRY_LIMIT))
1390                 {
1391                   /* Normalise lifetime */
1392                   temp *= MEGA; /* default = s */
1393                   if(index(args[i], 'u')) temp /= MEGA;
1394                   if(index(args[i], 'm')) temp /= KILO;
1395                 }
1396               wrq.u.retry.value = (long) temp;
1397               ++i;
1398               gotone = 1;
1399             }
1400
1401           if(!gotone)
1402             ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]);
1403           --i;
1404
1405           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq,
1406                          "Set Retry Limit");
1407           continue;
1408         }
1409
1410       /* ---------- Other ---------- */
1411       /* Here we have an unrecognised arg... */
1412       fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
1413               args[i]);
1414       return(-1);
1415     }           /* for(index ... */
1416   return(0);
1417 }
1418
1419 /******************************* MAIN ********************************/
1420
1421 /*------------------------------------------------------------------*/
1422 /*
1423  * The main !
1424  */
1425 int
1426 main(int        argc,
1427      char **    argv)
1428 {
1429   int skfd;             /* generic raw socket desc.     */
1430   int goterr = 0;
1431
1432   /* Create a channel to the NET kernel. */
1433   if((skfd = iw_sockets_open()) < 0)
1434     {
1435       perror("socket");
1436       exit(-1);
1437     }
1438
1439   /* No argument : show the list of all device + info */
1440   if(argc == 1)
1441     iw_enum_devices(skfd, &print_info, NULL, 0);
1442   else
1443     /* Special case for help... */
1444     if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
1445       iw_usage();
1446     else
1447       /* Special case for version... */
1448       if(!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
1449         goterr = iw_print_version_info("iwconfig");
1450       else
1451         {
1452           /* '--' escape device name */
1453           if((argc > 2) && !strcmp(argv[1], "--"))
1454             {
1455               argv++;
1456               argc--;
1457             }
1458
1459           /* The device name must be the first argument */
1460           if(argc == 2)
1461             print_info(skfd, argv[1], NULL, 0);
1462           else
1463             /* The other args on the line specify options to be set... */
1464             goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
1465         }
1466
1467   /* Close the socket. */
1468   iw_sockets_close(skfd);
1469
1470   return(goterr);
1471 }