OSDN Git Service

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