OSDN Git Service

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