OSDN Git Service

c65f92e3c48e0edfb58b8ea19726ad077112c950
[android-x86/external-wireless-tools.git] / wireless_tools / iwconfig.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPLB '99
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
11 #include "iwcommon.h"           /* Header */
12
13 /**************************** VARIABLES ****************************/
14 char *  operation_mode[] = { "Auto",
15                              "Ad-Hoc",
16                              "Managed",
17                              "Master",
18                              "Repeater",
19                              "Secondary" };
20
21 /************************* MISC SUBROUTINES **************************/
22
23 /*------------------------------------------------------------------*/
24 /*
25  * Print usage string
26  */
27 static void
28 iw_usage(void)
29 {
30   fprintf(stderr, "Usage: iwconfig interface [essid {NN|on|off}]\n");
31   fprintf(stderr, "                          [nwid {NN|on|off}]\n");
32   fprintf(stderr, "                          [freq N.NNNN[k|M|G]]\n");
33   fprintf(stderr, "                          [channel N]\n");
34   fprintf(stderr, "                          [sens N]\n");
35   fprintf(stderr, "                          [nick N]\n");
36   fprintf(stderr, "                          [rate {N|auto|fixed}]\n");
37   fprintf(stderr, "                          [rts {N|auto|fixed|off}]\n");
38   fprintf(stderr, "                          [frag {N|auto|fixed|off}]\n");
39   fprintf(stderr, "                          [enc NNNN-NNNN]\n");
40   exit(1);
41 }
42
43
44 /************************* DISPLAY ROUTINES **************************/
45
46 /*------------------------------------------------------------------*/
47 /*
48  * Read /proc/net/wireless to get the latest statistics
49  */
50 static int
51 iw_getstats(char *      ifname,
52             iwstats *   stats)
53 {
54   FILE *        f=fopen("/proc/net/wireless","r");
55   char          buf[256];
56   char *        bp;
57   int           t;
58   if(f==NULL)
59     return -1;
60   /* Loop on all devices */
61   while(fgets(buf,255,f))
62     {
63       bp=buf;
64       while(*bp&&isspace(*bp))
65         bp++;
66       /* Is it the good device ? */
67       if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
68         {
69           /* Skip ethX: */
70           bp=strchr(bp,':');
71           bp++;
72           /* -- status -- */
73           bp = strtok(bp, " ");
74           sscanf(bp, "%X", &t);
75           stats->status = (unsigned short) t;
76           /* -- link quality -- */
77           bp = strtok(NULL, " ");
78           if(strchr(bp,'.') != NULL)
79             stats->qual.updated |= 1;
80           sscanf(bp, "%d", &t);
81           stats->qual.qual = (unsigned char) t;
82           /* -- signal level -- */
83           bp = strtok(NULL, " ");
84           if(strchr(bp,'.') != NULL)
85             stats->qual.updated |= 2;
86           sscanf(bp, "%d", &t);
87           stats->qual.level = (unsigned char) t;
88           /* -- noise level -- */
89           bp = strtok(NULL, " ");
90           if(strchr(bp,'.') != NULL)
91             stats->qual.updated += 4;
92           sscanf(bp, "%d", &t);
93           stats->qual.noise = (unsigned char) t;
94           /* -- discarded packets -- */
95           bp = strtok(NULL, " ");
96           sscanf(bp, "%d", &stats->discard.nwid);
97           bp = strtok(NULL, " ");
98           sscanf(bp, "%d", &stats->discard.code);
99           bp = strtok(NULL, " ");
100           sscanf(bp, "%d", &stats->discard.misc);
101           fclose(f);
102           return 0;
103         }
104     }
105   fclose(f);
106   return -1;
107 }
108
109 /*------------------------------------------------------------------*/
110 /*
111  * Get wireless informations & config from the device driver
112  * We will call all the classical wireless ioctl on the driver through
113  * the socket to know what is supported and to get the settings...
114  */
115 static int
116 get_info(int                    skfd,
117          char *                 ifname,
118          struct wireless_info * info)
119 {
120   struct iwreq          wrq;
121
122   memset((char *) info, 0, sizeof(struct wireless_info));
123
124   /* Get wireless name */
125   strcpy(wrq.ifr_name, ifname);
126   if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
127     /* If no wireless name : no wireless extensions */
128     return(-1);
129   else
130     strcpy(info->name, wrq.u.name);
131
132   /* Get network ID */
133   strcpy(wrq.ifr_name, ifname);
134   if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0)
135     {
136       info->has_nwid = 1;
137       memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
138     }
139
140   /* Get frequency / channel */
141   strcpy(wrq.ifr_name, ifname);
142   if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0)
143     {
144       info->has_freq = 1;
145       info->freq = freq2float(&(wrq.u.freq));
146     }
147
148   /* Get sensitivity */
149   strcpy(wrq.ifr_name, ifname);
150   if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0)
151     {
152       info->has_sens = 1;
153       memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
154     }
155
156   /* Get encryption information */
157   strcpy(wrq.ifr_name, ifname);
158   wrq.u.data.pointer = (caddr_t) info->key;
159   wrq.u.data.length = 0;
160   wrq.u.data.flags = 0;
161   if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0)
162     {
163       info->has_key = 1;
164       info->key_size = wrq.u.data.length;
165       info->key_flags = wrq.u.data.flags;
166     }
167
168   /* Get ESSID */
169   strcpy(wrq.ifr_name, ifname);
170   wrq.u.essid.pointer = (caddr_t) info->essid;
171   wrq.u.essid.length = 0;
172   wrq.u.essid.flags = 0;
173   if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0)
174     {
175       info->has_essid = 1;
176       info->essid_on = wrq.u.data.flags;
177     }
178
179   /* Get AP address */
180   strcpy(wrq.ifr_name, ifname);
181   if(ioctl(skfd, SIOCGIWAP, &wrq) >= 0)
182     {
183       info->has_ap_addr = 1;
184       memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
185     }
186
187   /* Get NickName */
188   strcpy(wrq.ifr_name, ifname);
189   wrq.u.essid.pointer = (caddr_t) info->nickname;
190   wrq.u.essid.length = 0;
191   wrq.u.essid.flags = 0;
192   if(ioctl(skfd, SIOCGIWNICKN, &wrq) >= 0)
193     if(wrq.u.data.length > 1)
194       info->has_nickname = 1;
195
196   /* Get bit rate */
197   strcpy(wrq.ifr_name, ifname);
198   if(ioctl(skfd, SIOCGIWRATE, &wrq) >= 0)
199     {
200       info->has_bitrate = 1;
201       memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
202     }
203
204   /* Get RTS threshold */
205   strcpy(wrq.ifr_name, ifname);
206   if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0)
207     {
208       info->has_rts = 1;
209       memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
210     }
211
212   /* Get fragmentation threshold */
213   strcpy(wrq.ifr_name, ifname);
214   if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0)
215     {
216       info->has_frag = 1;
217       memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
218     }
219
220   /* Get operation mode */
221   strcpy(wrq.ifr_name, ifname);
222   if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0)
223     {
224       if((wrq.u.mode < 6) && (wrq.u.mode >= 0))
225         info->has_mode = 1;
226       info->mode = wrq.u.mode;
227     }
228
229   /* Get Power Management settings */
230   strcpy(wrq.ifr_name, ifname);
231   if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0)
232     {
233       info->has_power = 1;
234       memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
235     }
236
237   /* Get stats */
238   if(iw_getstats(ifname, &(info->stats)) >= 0)
239     {
240       info->has_stats = 1;
241     }
242
243   /* Get ranges */
244   if(get_range_info(skfd, ifname, &(info->range)) >= 0)
245     info->has_range = 1;
246
247   return(0);
248 }
249
250 /*------------------------------------------------------------------*/
251 /*
252  * Print on the screen in a neat fashion all the info we have collected
253  * on a device.
254  */
255 static void
256 display_info(struct wireless_info *     info,
257              char *                     ifname)
258 {
259   /* Display device name and wireless name (name of the protocol used) */
260   printf("%-8.8s  %s  ", ifname, info->name);
261
262   /* Display ESSID (extended network), if any */
263   if(info->has_essid)
264     {
265       if(info->essid_on)
266         printf("ESSID:\"%s\"  ", info->essid);
267       else
268         printf("ESSID:off  ");
269     }
270
271   /* Display NickName (station name), if any */
272   if(info->has_nickname)
273     printf("Nickname:\"%s\"", info->nickname);
274
275   /* Formatting */
276   if(info->has_essid || info->has_nickname)
277     printf("\n          ");
278
279   /* Display Network ID */
280   if(info->has_nwid)
281     {
282       /* Note : should display right number of digit according to info
283        * in range structure */
284       if(info->nwid.disabled)
285         printf("NWID:off/any  ");
286       else
287         printf("NWID:%X  ", info->nwid.value);
288     }
289
290   /* Display frequency / channel */
291   if(info->has_freq)
292     {
293       if(info->freq < KILO)
294         printf("Channel:%g  ", info->freq);
295       else
296         {
297           if(info->freq >= GIGA)
298             printf("Frequency:%gGHz  ", info->freq / GIGA);
299           else
300             {
301               if(info->freq >= MEGA)
302                 printf("Frequency:%gMHz  ", info->freq / MEGA);
303               else
304                 printf("Frequency:%gkHz  ", info->freq / KILO);
305             }
306         }
307     }
308
309   /* Display sensitivity */
310   if(info->has_sens)
311     {
312       /* Fixed ? */
313       if(info->sens.fixed)
314         printf("Sensitivity=");
315       else
316         printf("Sensitivity:");
317
318       if(info->has_range)
319         /* Display in dBm ? */
320         if(info->sens.value < 0)
321           printf("%d dBm  ", info->sens.value);
322         else
323           printf("%d/%d  ", info->sens.value, info->range.sensitivity);
324       else
325         printf("%d  ", info->sens.value);
326     }
327
328   /* Display the current mode of operation */
329   if(info->has_mode)
330     {
331       /* A bit of clever formatting */
332       if((info->has_nwid + 2*info->has_freq + 2*info->has_sens
333           + !info->has_essid) > 4)
334         printf("\n          ");
335
336       printf("Mode:%s  ", operation_mode[info->mode]);
337     }
338
339   /* Display the address of the current Access Point */
340   if(info->has_ap_addr)
341     {
342       /* A bit of clever formatting */
343       if((info->has_nwid + 2*info->has_freq + 2*info->has_sens
344           + info->has_mode + !info->has_essid) > 3)
345         printf("\n          ");
346
347       printf("Access Point: %s", pr_ether(info->ap_addr.sa_data));
348     }
349
350   printf("\n          ");
351
352   /* Display the currently used/set bit-rate */
353   if(info->has_bitrate)
354     {
355       /* Fixed ? */
356       if(info->bitrate.fixed)
357         printf("Bit Rate=");
358       else
359         printf("Bit Rate:");
360
361       if(info->bitrate.value >= GIGA)
362         printf("%gGb/s", info->bitrate.value / GIGA);
363       else
364         if(info->bitrate.value >= MEGA)
365           printf("%gMb/s", info->bitrate.value / MEGA);
366         else
367           printf("%gkb/s", info->bitrate.value / KILO);
368       printf("   ");
369     }
370
371   /* Display the RTS threshold */
372   if(info->has_rts)
373     {
374       /* Disabled ? */
375       if(info->rts.disabled)
376         printf("RTS thr:off   ");
377       else
378         {
379           /* Fixed ? */
380           if(info->rts.fixed)
381             printf("RTS thr=");
382           else
383             printf("RTS thr:");
384
385           printf("%d B   ", info->rts.value);
386         }
387     }
388
389   /* Display the fragmentation threshold */
390   if(info->has_frag)
391     {
392       /* Disabled ? */
393       if(info->frag.disabled)
394         printf("Fragment thr:off   ");
395       else
396         {
397           /* Fixed ? */
398           if(info->frag.fixed)
399             printf("Fragment thr=");
400           else
401             printf("Fragment thr:");
402
403           printf("%d B   ", info->frag.value);
404         }
405     }
406
407   /* Formating */
408   if((info->has_bitrate) || (info->has_rts) || (info->has_bitrate))
409     printf("\n          ");
410
411   /* Display encryption information */
412   /* Note : we display only the "current" key, use iwspy to list all keys */
413   if(info->has_key)
414     {
415       printf("Encryption key:");
416       if((info->key_flags & IW_ENCODE_DISABLED) || (info->key_size == 0))
417         printf("off\n          ");
418       else
419         {
420           int   i;
421
422           printf("%.2X", info->key[0]);
423           for(i = 1; i < info->key_size; i++)
424             {
425               if((i & 0x1) == 0)
426                 printf("-");
427               printf("%.2X", info->key[i]);
428             }
429
430           /* Other info... */
431           if((info->key_flags & IW_ENCODE_INDEX) > 1)
432             printf(" [%d]", info->key_flags & IW_ENCODE_INDEX);
433           if(info->key_flags & IW_ENCODE_RESTRICTED)
434             printf("   Encryption mode:restricted");
435           if(info->key_flags & IW_ENCODE_OPEN)
436             printf("   Encryption mode:open");
437           printf("\n          ");
438         }
439     }
440
441   /* Display Power Management information */
442   /* Note : we display only one parameter, period or timeout. If a device
443    * (such as HiperLan) has both, we would need to be a bit more clever... */
444   if(info->has_power)   /* I hope the device has power ;-) */
445     { 
446       printf("Power Management");
447       /* Disabled ? */
448       if(info->power.disabled)
449         printf(":off\n          ");
450       else
451         {
452           /* Let's check the value and its type */
453           if(info->power.flags & IW_POWER_TYPE)
454             {
455               /* Type */
456               if(info->power.flags & IW_POWER_TIMEOUT)
457                 printf(" timeout:");
458               else
459                 printf(" period:");
460
461               /* Display value with units */
462               if(info->power.value >= (int) MEGA)
463                 printf("%gs  ", ((double) info->power.value) / MEGA);
464               else
465                 if(info->power.value  >= (int) KILO)
466                   printf("%gms  ", ((double) info->power.value) / KILO);
467                 else
468                   printf("%dus  ", info->power.value);
469             }
470
471           /* Let's check the mode */
472           switch(info->power.flags & IW_POWER_MODE)
473             {
474             case IW_POWER_UNICAST_R:
475               printf(" mode:Unicast received");
476               break;
477             case IW_POWER_MULTICAST_R:
478               printf(" mode:Multicast received");
479               break;
480             case IW_POWER_ALL_R:
481               printf(" mode:All packets received");
482               break;
483             case IW_POWER_FORCE_S:
484               printf(" mode:Force sending");
485               break;
486             case IW_POWER_REPEATER:
487               printf(" mode:Repeat multicasts");
488               break;
489             default:
490             }
491
492           /* Let's check if nothing (simply on) */
493           if(info->power.flags == IW_POWER_ON)
494             printf(":on");
495           printf("\n          ");
496         }
497     }
498
499   if(info->has_stats)
500     {
501       if(info->has_range && (info->stats.qual.level != 0))
502         /* If the statistics are in dBm */
503         if(info->stats.qual.level > info->range.max_qual.level)
504           printf("Link quality:%d/%d  Signal level:%d dBm  Noise level:%d dBm\n",
505                  info->stats.qual.qual, info->range.max_qual.qual,
506                  info->stats.qual.level - 0x100,
507                  info->stats.qual.noise - 0x100);
508         else
509           /* Statistics are relative values (0 -> max) */
510           printf("Link quality:%d/%d  Signal level:%d/%d  Noise level:%d/%d\n",
511                  info->stats.qual.qual, info->range.max_qual.qual,
512                  info->stats.qual.level, info->range.max_qual.level,
513                  info->stats.qual.noise, info->range.max_qual.noise);
514       else
515         /* We can't read the range, so we don't know... */
516         printf("Link quality:%d  Signal level:%d  Noise level:%d\n",
517                info->stats.qual.qual,
518                info->stats.qual.level,
519                info->stats.qual.noise);
520
521       printf("          Rx invalid nwid:%d  invalid crypt:%d  invalid misc:%d\n",
522              info->stats.discard.nwid,
523              info->stats.discard.code,
524              info->stats.discard.misc);
525     }
526
527   printf("\n");
528 }
529
530 /*------------------------------------------------------------------*/
531 /*
532  * Print on the screen in a neat fashion all the info we have collected
533  * on a device.
534  */
535 static void
536 print_info(int          skfd,
537            char *       ifname)
538 {
539   struct wireless_info  info;
540
541   if(get_info(skfd, ifname, &info) < 0)
542     {
543       fprintf(stderr, "%-8.8s  no wireless extensions.\n\n",
544               ifname);
545       return;
546     }
547
548   /* Display it ! */
549   display_info(&info, ifname);
550 }
551
552 /*------------------------------------------------------------------*/
553 /*
554  * Get info on all devices and print it on the screen
555  */
556 static void
557 print_devices(int       skfd)
558 {
559   char buff[1024];
560   struct ifconf ifc;
561   struct ifreq *ifr;
562   int i;
563
564   /* Get list of active devices */
565   ifc.ifc_len = sizeof(buff);
566   ifc.ifc_buf = buff;
567   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
568     {
569       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
570       return;
571     }
572   ifr = ifc.ifc_req;
573
574   /* Print them */
575   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
576     print_info(skfd, ifr->ifr_name);
577 }
578
579 /************************* SETTING ROUTINES **************************/
580
581 /*------------------------------------------------------------------*/
582 /*
583  * Set the wireless options requested on command line
584  * This function is too long and probably should be split,
585  * because it look like the perfect definition of spaghetti code,
586  * but I'm way to lazy
587  */
588 static int
589 set_info(int            skfd,           /* The socket */
590          char *         args[],         /* Command line args */
591          int            count,          /* Args count */
592          char *         ifname)         /* Dev name */
593 {
594   struct iwreq          wrq;
595   int                   i;
596
597   /* Set dev name */
598   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
599
600   /* if nothing after the device name */
601   if(count<1)
602     iw_usage();
603
604   /* The other args on the line specify options to be set... */
605   for(i = 0; i < count; i++)
606     {
607       /* ---------- Set network ID ---------- */
608       if((!strcasecmp(args[i], "nwid")) ||
609          (!strcasecmp(args[i], "domain")))
610         {
611           i++;
612           if(i >= count)
613             iw_usage();
614           if((!strcasecmp(args[i], "off")) ||
615              (!strcasecmp(args[i], "any")))
616             wrq.u.nwid.disabled = 1;
617           else
618             if(!strcasecmp(args[i], "on"))
619               {
620                 /* Get old nwid */
621                 if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0)
622                   {
623                     fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno));
624                     return(-1);
625                   }
626                 strcpy(wrq.ifr_name, ifname);
627                 wrq.u.nwid.disabled = 0;
628               }
629             else
630               if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
631                  != 1)
632                 iw_usage();
633               else
634                 wrq.u.nwid.disabled = 0;
635           wrq.u.nwid.fixed = 1;
636
637           if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0)
638             {
639               fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
640               return(-1);
641             }
642           continue;
643         }
644
645       /* ---------- Set frequency / channel ---------- */
646       if((!strncmp(args[i], "freq", 4)) ||
647          (!strcmp(args[i], "channel")))
648         {
649           double                freq;
650
651           if(++i >= count)
652             iw_usage();
653           if(sscanf(args[i], "%lg", &(freq)) != 1)
654             iw_usage();
655           if(index(args[i], 'G')) freq *= GIGA;
656           if(index(args[i], 'M')) freq *= MEGA;
657           if(index(args[i], 'k')) freq *= KILO;
658
659           float2freq(freq, &(wrq.u.freq));
660
661           if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
662             {
663               fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
664               return(-1);
665             }
666           continue;
667         }
668
669       /* ---------- Set sensitivity ---------- */
670       if(!strncmp(args[i], "sens", 4))
671         {
672           if(++i >= count)
673             iw_usage();
674           if(sscanf(args[i], "%d", &(wrq.u.sens.value)) != 1)
675             iw_usage();
676
677           if(ioctl(skfd, SIOCSIWSENS, &wrq) < 0)
678             {
679               fprintf(stderr, "SIOCSIWSENS: %s\n", strerror(errno));
680               return(-1);
681             }
682           continue;
683         }
684
685       /* ---------- Set encryption stuff ---------- */
686       if((!strncmp(args[i], "enc", 3)) ||
687          (!strcmp(args[i], "key")))
688         {
689           unsigned char key[IW_ENCODING_TOKEN_MAX];
690
691           if(++i >= count)
692             iw_usage();
693
694           if(!strcasecmp(args[i], "on"))
695             {
696               /* Get old encryption information */
697               wrq.u.data.pointer = (caddr_t) key;
698               wrq.u.data.length = 0;
699               wrq.u.data.flags = 0;
700               if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
701                 {
702                   fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
703                   return(-1);
704                 }
705               strcpy(wrq.ifr_name, ifname);
706               wrq.u.data.flags &= ~IW_ENCODE_DISABLED;  /* Enable */
707             }
708           else
709             {
710               char *    buff;
711               char *    p;
712               int               temp;
713               int               k = 0;
714               int               gotone = 1;
715
716               wrq.u.data.pointer = (caddr_t) NULL;
717               wrq.u.data.flags = 0;
718               wrq.u.data.length = 0;
719
720               /* -- Check for the key -- */
721               if(!strncmp(args[i], "s:", 2))
722                 {
723                   /* First case : as an ASCII string */
724                   wrq.u.data.length = strlen(args[i] + 2);
725                   if(wrq.u.data.length > IW_ENCODING_TOKEN_MAX)
726                     wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
727                   strncpy(key, args[i] + 2, wrq.u.data.length);
728                   wrq.u.data.pointer = (caddr_t) key;
729                   ++i;
730                   gotone = 1;
731                 }
732               else
733                 {
734                   /* Second case : has hexadecimal digits */
735                   p = buff = malloc(strlen(args[i]) + 1);
736                   strcpy(buff, args[i]);
737
738                   p = strtok(buff, "-:;.,");
739                   while(p != (char *) NULL)
740                     {
741                       if(sscanf(p, "%2X", &temp) != 1)
742                         {
743                           gotone = 0;
744                           break;
745                         }
746                       key[k++] = (unsigned char) (temp & 0xFF);
747                       if(strlen(p) > 2) /* Token not finished yet */
748                         p += 2;
749                       else
750                         p = strtok((char *) NULL, "-:;.,");
751                     }
752                   free(buff);
753
754                   if(gotone)
755                     {
756                       ++i;
757                       wrq.u.data.length = k;
758                       wrq.u.data.pointer = (caddr_t) key;
759                     }
760                 }
761
762               /* -- Check for token index -- */
763               if((i < count) &&
764                  (sscanf(args[i], "[%d]", &temp) == 1) &&
765                  (temp > 0) && (temp < IW_ENCODE_INDEX))
766                 {
767                   wrq.u.encoding.flags |= temp;
768                   ++i;
769                   gotone = 1;
770                 }
771
772               /* -- Check the various flags -- */
773               if(i < count)
774                 {
775                   if(!strcasecmp(args[i], "off"))
776                     wrq.u.data.flags |= IW_ENCODE_DISABLED;
777                   if(!strcasecmp(args[i], "open"))
778                     wrq.u.data.flags |= IW_ENCODE_OPEN;
779                   if(!strncasecmp(args[i], "restricted", 5))
780                     wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
781                   if(wrq.u.data.flags & IW_ENCODE_FLAGS)
782                     {
783                       ++i;
784                       gotone = 1;
785                     }
786                 }
787
788               if(!gotone)
789                 iw_usage();
790               --i;
791             }
792
793           if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0)
794             {
795               fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
796                       errno, strerror(errno));
797               return(-1);
798             }
799           continue;
800         }
801
802       /* ---------- Set ESSID ---------- */
803       if(!strcasecmp(args[i], "essid"))
804         {
805           char          essid[IW_ESSID_MAX_SIZE + 1];
806
807           i++;
808           if(i >= count)
809             iw_usage();
810           if((!strcasecmp(args[i], "off")) ||
811              (!strcasecmp(args[i], "any")))
812             {
813               wrq.u.essid.flags = 0;
814               essid[0] = '\0';
815             }
816           else
817             if(!strcasecmp(args[i], "on"))
818               {
819                 /* Get old essid */
820                 wrq.u.essid.pointer = (caddr_t) essid;
821                 wrq.u.essid.length = 0;
822                 wrq.u.essid.flags = 0;
823                 if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0)
824                   {
825                     fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno));
826                     return(-1);
827                   }
828                 strcpy(wrq.ifr_name, ifname);
829                 wrq.u.essid.flags = 1;
830               }
831             else
832               if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
833                 {
834                   fprintf(stderr, "ESSID too long (max %d): ``%s''\n",
835                           IW_ESSID_MAX_SIZE, args[i]);
836                   iw_usage();
837                 }
838               else
839                 {
840                   wrq.u.essid.flags = 1;
841                   strcpy(essid, args[i]);
842                 }
843
844           wrq.u.essid.pointer = (caddr_t) essid;
845           wrq.u.essid.length = strlen(essid) + 1;
846           if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0)
847             {
848               fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
849               return(-1);
850             }
851           continue;
852         }
853
854       /* ---------- Set AP address ---------- */
855       if(!strcasecmp(args[i], "ap"))
856         {
857           if(++i >= count)
858             iw_usage();
859
860           /* Check if we have valid address types */
861           if(check_addr_type(skfd, ifname) < 0)
862             {
863               fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n", ifname);
864               return(-1);
865             }
866
867           /* Get the address */
868           if(in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
869             iw_usage();
870
871           if(ioctl(skfd, SIOCSIWAP, &wrq) < 0)
872             {
873               fprintf(stderr, "SIOCSIWAP: %s\n", strerror(errno));
874               return(-1);
875             }
876           continue;
877         }
878
879       /* ---------- Set NickName ---------- */
880       if(!strncmp(args[i], "nick", 4))
881         {
882           i++;
883           if(i >= count)
884             iw_usage();
885           if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
886             {
887               fprintf(stderr, "Name too long (max %d) : ``%s''\n",
888                       IW_ESSID_MAX_SIZE, args[i]);
889               iw_usage();
890             }
891
892           wrq.u.essid.pointer = (caddr_t) args[i];
893           wrq.u.essid.length = strlen(args[i]) + 1;
894           if(ioctl(skfd, SIOCSIWNICKN, &wrq) < 0)
895             {
896               fprintf(stderr, "SIOCSIWNICKN: %s\n", strerror(errno));
897               return(-1);
898             }
899           continue;
900         }
901
902       /* ---------- Set Bit-Rate ---------- */
903       if((!strncmp(args[i], "bit", 3)) ||
904          (!strcmp(args[i], "rate")))
905         {
906           if(++i >= count)
907             iw_usage();
908           if(!strcasecmp(args[i], "auto"))
909             {
910               wrq.u.bitrate.value = -1;
911               wrq.u.bitrate.fixed = 0;
912             }
913           else
914             {
915               if(!strcasecmp(args[i], "fixed"))
916                 {
917                   /* Get old bitrate */
918                   if(ioctl(skfd, SIOCGIWRATE, &wrq) < 0)
919                     {
920                       fprintf(stderr, "SIOCGIWRATE: %s\n", strerror(errno));
921                       return(-1);
922                     }
923                   strcpy(wrq.ifr_name, ifname);
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                     iw_usage();
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                 }
946             }
947
948           if(ioctl(skfd, SIOCSIWRATE, &wrq) < 0)
949             {
950               fprintf(stderr, "SIOCSIWRATE: %s\n", strerror(errno));
951               return(-1);
952             }
953           continue;
954         }
955
956       /* ---------- Set RTS threshold ---------- */
957       if(!strncasecmp(args[i], "rts", 3))
958         {
959           i++;
960           if(i >= count)
961             iw_usage();
962           wrq.u.rts.value = -1;
963           wrq.u.rts.fixed = 1;
964           wrq.u.rts.disabled = 0;
965           if(!strcasecmp(args[i], "off"))
966             wrq.u.rts.disabled = 1;     /* i.e. max size */
967           else
968             if(!strcasecmp(args[i], "auto"))
969               wrq.u.rts.fixed = 0;
970             else
971               {
972                 if(!strcasecmp(args[i], "fixed"))
973                   {
974                     /* Get old RTS threshold */
975                     if(ioctl(skfd, SIOCGIWRTS, &wrq) < 0)
976                       {
977                         fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno));
978                         return(-1);
979                       }
980                     strcpy(wrq.ifr_name, ifname);
981                     wrq.u.rts.fixed = 1;
982                   }
983                 else                    /* Should be a numeric value */
984                   if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value))
985                      != 1)
986                     iw_usage();
987             }
988
989           if(ioctl(skfd, SIOCSIWRTS, &wrq) < 0)
990             {
991               fprintf(stderr, "SIOCSIWRTS: %s\n", strerror(errno));
992               return(-1);
993             }
994           continue;
995         }
996
997       /* ---------- Set fragmentation threshold ---------- */
998       if(!strncmp(args[i], "frag", 4))
999         {
1000           i++;
1001           if(i >= count)
1002             iw_usage();
1003           wrq.u.frag.value = -1;
1004           wrq.u.frag.fixed = 1;
1005           wrq.u.frag.disabled = 0;
1006           if(!strcasecmp(args[i], "off"))
1007             wrq.u.frag.disabled = 1;    /* i.e. max size */
1008           else
1009             if(!strcasecmp(args[i], "auto"))
1010               wrq.u.frag.fixed = 0;
1011             else
1012               {
1013                 if(!strcasecmp(args[i], "fixed"))
1014                   {
1015                     /* Get old fragmentation threshold */
1016                     if(ioctl(skfd, SIOCGIWFRAG, &wrq) < 0)
1017                       {
1018                         fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno));
1019                         return(-1);
1020                       }
1021                     strcpy(wrq.ifr_name, ifname);
1022                     wrq.u.frag.fixed = 1;
1023                   }
1024                 else                    /* Should be a numeric value */
1025                   if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.frag.value))
1026                      != 1)
1027                     iw_usage();
1028             }
1029
1030           if(ioctl(skfd, SIOCSIWFRAG, &wrq) < 0)
1031             {
1032               fprintf(stderr, "SIOCSIWFRAG: %s\n", strerror(errno));
1033               return(-1);
1034             }
1035           continue;
1036         }
1037
1038       /* ---------- Set operation mode ---------- */
1039       if(!strcmp(args[i], "mode"))
1040         {
1041           int   k;
1042
1043           i++;
1044           if(i >= count)
1045             iw_usage();
1046
1047           if(sscanf(args[i], "%d", &k) != 1)
1048             {
1049               k = 0;
1050               while(k < 6 && strncasecmp(args[i], operation_mode[k], 3))
1051                 k++;
1052             }
1053           if((k > 5) || (k < 0))
1054             iw_usage();
1055
1056           wrq.u.mode = k;
1057           if(ioctl(skfd, SIOCSIWMODE, &wrq) < 0)
1058             {
1059               fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
1060               return(-1);
1061             }
1062           continue;
1063         }
1064
1065       /* ---------- Set Power Management ---------- */
1066       if(!strncmp(args[i], "power", 3))
1067         {
1068           if(++i >= count)
1069             iw_usage();
1070
1071           if(!strcasecmp(args[i], "off"))
1072             wrq.u.power.disabled = 1;   /* i.e. max size */
1073           else
1074             if(!strcasecmp(args[i], "on"))
1075               {
1076                 /* Get old Power info */
1077                 if(ioctl(skfd, SIOCGIWPOWER, &wrq) < 0)
1078                   {
1079                     fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno));
1080                     return(-1);
1081                   }
1082                 strcpy(wrq.ifr_name, ifname);
1083                 wrq.u.power.disabled = 0;
1084               }
1085             else
1086               {
1087                 double          temp;
1088                 int             gotone = 0;
1089                 /* Default - nope */
1090                 wrq.u.power.flags = IW_POWER_ON;
1091                 wrq.u.power.disabled = 0;
1092
1093                 /* Check value modifier */
1094                 if(!strcasecmp(args[i], "period"))
1095                   {
1096                     wrq.u.power.flags = IW_POWER_PERIOD;
1097                     if(++i >= count)
1098                       iw_usage();
1099                   }
1100                 else
1101                   if(!strcasecmp(args[i], "timeout"))
1102                     {
1103                       wrq.u.power.flags = IW_POWER_TIMEOUT;
1104                       if(++i >= count)
1105                         iw_usage();
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_ON)
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                   iw_usage();
1142                 --i;
1143               }
1144
1145           if(ioctl(skfd, SIOCSIWPOWER, &wrq) < 0)
1146             {
1147               fprintf(stderr, "SIOCSIWPOWER(%d): %s\n",
1148                       errno, strerror(errno));
1149               return(-1);
1150             }
1151           continue;
1152         }
1153
1154       /* ---------- Other ---------- */
1155       /* Here we have an unrecognised arg... */
1156       fprintf(stderr, "Invalid argument : %s\n", args[i]);
1157       iw_usage();
1158       return(-1);
1159     }           /* for(index ... */
1160   return(0);
1161 }
1162
1163 /******************************* MAIN ********************************/
1164
1165 /*------------------------------------------------------------------*/
1166 /*
1167  * The main !
1168  */
1169 int
1170 main(int        argc,
1171      char **    argv)
1172 {
1173   int skfd = -1;                /* generic raw socket desc.     */
1174   int goterr = 0;
1175
1176   /* Create a channel to the NET kernel. */
1177   if((skfd = sockets_open()) < 0)
1178     {
1179       perror("socket");
1180       exit(-1);
1181     }
1182
1183   /* No argument : show the list of all device + info */
1184   if(argc == 1)
1185     {
1186       print_devices(skfd);
1187       close(skfd);
1188       exit(0);
1189     }
1190
1191   /* Special case for help... */
1192   if((!strncmp(argv[1], "-h", 9)) ||
1193      (!strcmp(argv[1], "--help")))
1194     {
1195       iw_usage();
1196       close(skfd);
1197       exit(0);
1198     }
1199
1200   /* The device name must be the first argument */
1201   if(argc == 2)
1202     {
1203       print_info(skfd, argv[1]);
1204       close(skfd);
1205       exit(0);
1206     }
1207
1208   /* The other args on the line specify options to be set... */
1209   goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
1210
1211   /* Close the socket. */
1212   close(skfd);
1213
1214   return(goterr);
1215 }
1216
1217