OSDN Git Service

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