OSDN Git Service

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