OSDN Git Service

2db4afd2106cd8ca849ec1cb34934562d9fcd498
[android-x86/external-wireless-tools.git] / wireless_tools / iwpriv.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPLB 97->99 - HPL 99->00
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: iwpriv interface [private-command [private-arguments]]\n");
26   fprintf(stderr, "              interface [roam {on|off}]\n");
27   fprintf(stderr, "              interface [port {ad-hoc|managed|N}]\n");
28 }
29
30 /************************ GENERIC FUNCTIONS *************************/
31
32 /*------------------------------------------------------------------*/
33 /*
34  * Print on the screen in a neat fashion all the info we have collected
35  * on a device.
36  */
37 static void
38 print_priv_info(int             skfd,
39                 char *          ifname)
40 {
41   int           k;
42   iwprivargs    priv[32];
43   int           n;
44   char *        argtype[] = { "    ", "byte", "char", "", "int ", "float" };
45
46   /* Read the private ioctls */
47   n = iw_get_priv_info(skfd, ifname, priv);
48
49   /* Is there any ? */
50   if(n <= 0)
51     {
52       /* Could skip this message ? */
53       fprintf(stderr, "%-8.8s  no private ioctls.\n\n",
54               ifname);
55     }
56   else
57     {
58       printf("%-8.8s  Available private ioctl :\n", ifname);
59       /* Print the all */
60       for(k = 0; k < n; k++)
61         printf("          %s (%X) : set %3d %s & get %3d %s\n",
62                priv[k].name, priv[k].cmd,
63                priv[k].set_args & IW_PRIV_SIZE_MASK,
64                argtype[(priv[k].set_args & IW_PRIV_TYPE_MASK) >> 12],
65                priv[k].get_args & IW_PRIV_SIZE_MASK,
66                argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]);
67       printf("\n");
68     }
69 }
70
71 /*------------------------------------------------------------------*/
72 /*
73  * Get info on all devices and print it on the screen
74  */
75 static void
76 print_priv_devices(int          skfd)
77 {
78   char          buff[1024];
79   struct ifconf ifc;
80   struct ifreq *ifr;
81   int i;
82
83   /* Get list of active devices */
84   ifc.ifc_len = sizeof(buff);
85   ifc.ifc_buf = buff;
86   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
87     {
88       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
89       return;
90     }
91   ifr = ifc.ifc_req;
92
93   /* Print them */
94   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
95     print_priv_info(skfd, ifr->ifr_name);
96 }
97
98 /************************* SETTING ROUTINES **************************/
99
100 /*------------------------------------------------------------------*/
101 /*
102  * Execute a private command on the interface
103  */
104 static int
105 set_private(int         skfd,           /* Socket */
106             char *      args[],         /* Command line args */
107             int         count,          /* Args count */
108             char *      ifname)         /* Dev name */
109 {
110   u_char        buffer[1024];
111   struct iwreq          wrq;
112   int           i = 0;          /* Start with first arg */
113   int           k;
114   iwprivargs    priv[16];
115   int           number;
116   int           temp;
117
118   /* Read the private ioctls */
119   number = iw_get_priv_info(skfd, ifname, priv);
120
121   /* Is there any ? */
122   if(number <= 0)
123     {
124       /* Could skip this message ? */
125       fprintf(stderr, "%-8.8s  no private ioctls.\n\n",
126               ifname);
127       return(-1);
128     }
129
130   /* Search the correct ioctl */
131   k = -1;
132   while((++k < number) && strcmp(priv[k].name, args[i]));
133
134   /* If not found... */
135   if(k == number)
136     {
137       fprintf(stderr, "Invalid command : %s\n", args[i]);
138       return(-1);
139     }
140           
141   /* Next arg */
142   i++;
143
144   /* If we have to set some data */
145   if((priv[k].set_args & IW_PRIV_TYPE_MASK) &&
146      (priv[k].set_args & IW_PRIV_SIZE_MASK))
147     {
148       switch(priv[k].set_args & IW_PRIV_TYPE_MASK)
149         {
150         case IW_PRIV_TYPE_BYTE:
151           /* Number of args to fetch */
152           wrq.u.data.length = count - 1;
153           if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK))
154             wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK;
155
156           /* Fetch args */
157           for(; i < wrq.u.data.length + 1; i++) {
158             sscanf(args[i], "%d", &temp);
159             buffer[i - 1] = (char) temp;
160           }
161           break;
162
163         case IW_PRIV_TYPE_INT:
164           /* Number of args to fetch */
165           wrq.u.data.length = count - 1;
166           if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK))
167             wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK;
168
169           /* Fetch args */
170           for(; i < wrq.u.data.length + 1; i++)
171             sscanf(args[i], "%d", ((u_int *) buffer) + i - 1);
172           break;
173
174         case IW_PRIV_TYPE_CHAR:
175           if(i < count)
176             {
177               /* Size of the string to fetch */
178               wrq.u.data.length = strlen(args[i]) + 1;
179               if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK))
180                 wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK;
181
182               /* Fetch string */
183               memcpy(buffer, args[i], wrq.u.data.length);
184               buffer[sizeof(buffer) - 1] = '\0';
185               i++;
186             }
187           else
188             {
189               wrq.u.data.length = 1;
190               buffer[0] = '\0';
191             }
192           break;
193
194         default:
195           fprintf(stderr, "Not yet implemented...\n");
196           return(-1);
197         }
198           
199       if((priv[k].set_args & IW_PRIV_SIZE_FIXED) &&
200          (wrq.u.data.length != (priv[k].set_args & IW_PRIV_SIZE_MASK)))
201         {
202           printf("The command %s need exactly %d argument...\n",
203                  priv[k].name, priv[k].set_args & IW_PRIV_SIZE_MASK);
204           return(-1);
205         }
206     }   /* if args to set */
207   else
208     {
209       wrq.u.data.length = 0L;
210     }
211
212   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
213
214   if((priv[k].set_args & IW_PRIV_SIZE_FIXED) &&
215      (iw_byte_size(priv[k].set_args) < IFNAMSIZ))
216     memcpy(wrq.u.name, buffer, IFNAMSIZ);
217   else
218     {
219       wrq.u.data.pointer = (caddr_t) buffer;
220       wrq.u.data.flags = 0;
221     }
222
223   /* Perform the private ioctl */
224   if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
225     {
226       fprintf(stderr, "Interface doesn't accept private ioctl...\n");
227       fprintf(stderr, "%X: %s\n", priv[k].cmd, strerror(errno));
228       return(-1);
229     }
230
231   /* If we have to get some data */
232   if((priv[k].get_args & IW_PRIV_TYPE_MASK) &&
233      (priv[k].get_args & IW_PRIV_SIZE_MASK))
234     {
235       int       j;
236       int       n = 0;          /* number of args */
237
238       printf("%-8.8s  %s:", ifname, priv[k].name);
239
240       if((priv[k].get_args & IW_PRIV_SIZE_FIXED) &&
241          (iw_byte_size(priv[k].get_args) < IFNAMSIZ))
242         {
243           memcpy(buffer, wrq.u.name, IFNAMSIZ);
244           n = priv[k].get_args & IW_PRIV_SIZE_MASK;
245         }
246       else
247         n = wrq.u.data.length;
248
249       switch(priv[k].get_args & IW_PRIV_TYPE_MASK)
250         {
251         case IW_PRIV_TYPE_BYTE:
252           /* Display args */
253           for(j = 0; j < n; j++)
254             printf("%d  ", buffer[j]);
255           printf("\n");
256           break;
257
258         case IW_PRIV_TYPE_INT:
259           /* Display args */
260           for(j = 0; j < n; j++)
261             printf("%d  ", ((u_int *) buffer)[j]);
262           printf("\n");
263           break;
264
265         case IW_PRIV_TYPE_CHAR:
266           /* Display args */
267           buffer[wrq.u.data.length - 1] = '\0';
268           printf("%s\n", buffer);
269           break;
270
271         default:
272           fprintf(stderr, "Not yet implemented...\n");
273           return(-1);
274         }
275     }   /* if args to set */
276
277   return(0);
278 }
279
280 /********************** PRIVATE IOCTLS MANIPS ***********************/
281 /*
282  * Convenient access to some private ioctls of some devices
283  */
284
285 /*------------------------------------------------------------------*/
286 /*
287  * Set roaming mode on and off
288  * Found in wavelan_cs driver
289  */
290 static int
291 set_roaming(int         skfd,           /* Socket */
292             char *      args[],         /* Command line args */
293             int         count,          /* Args count */
294             char *      ifname)         /* Dev name */
295 {
296   u_char        buffer[1024];
297   struct iwreq          wrq;
298   int           i = 0;          /* Start with first arg */
299   int           k;
300   iwprivargs    priv[16];
301   int           number;
302   char          RoamState;              /* buffer to hold new roam state */
303   char          ChangeRoamState=0;      /* whether or not we are going to
304                                            change roam states */
305
306   /* Read the private ioctls */
307   number = iw_get_priv_info(skfd, ifname, priv);
308
309   /* Is there any ? */
310   if(number <= 0)
311     {
312       /* Could skip this message ? */
313       fprintf(stderr, "%-8.8s  no private ioctls.\n\n",
314               ifname);
315       return(-1);
316     }
317
318   if(count != 1)
319     {
320       iw_usage();
321       return(-1);
322     }
323
324   if(!strcasecmp(args[i], "on"))
325     {
326       printf("%-8.8s  enable roaming\n", ifname);
327       if(!number)
328         {
329           fprintf(stderr, "This device doesn't support roaming\n");
330           return(-1);
331         }
332       ChangeRoamState=1;
333       RoamState=1;
334     }
335   else
336     if(!strcasecmp(args[i], "off"))
337       {
338         i++;
339         printf("%-8.8s  disable roaming\n",  ifname);
340         if(!number)
341           {
342             fprintf(stderr, "This device doesn't support roaming\n");
343             return(-1);
344           }
345         ChangeRoamState=1;
346         RoamState=0;
347       }
348     else
349       {
350         iw_usage();
351         return(-1);
352       }
353
354   if(ChangeRoamState)
355     {
356       k = -1;
357       while((++k < number) && strcmp(priv[k].name, "setroam"));
358       if(k == number)
359         {
360           fprintf(stderr, "This device doesn't support roaming\n");
361           return(-1);
362         }
363       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
364
365       buffer[0]=RoamState;
366
367       memcpy(wrq.u.name, &buffer, IFNAMSIZ);
368
369       if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
370         {
371           fprintf(stderr, "Roaming support is broken.\n");
372           return(-1);
373         }
374     }
375
376   return(0);
377 }
378
379 /*------------------------------------------------------------------*/
380 /*
381  * Get and set the port type
382  * Found in wavelan2_cs and wvlan_cs drivers
383  */
384 static int
385 port_type(int           skfd,           /* Socket */
386           char *        args[],         /* Command line args */
387           int           count,          /* Args count */
388           char *        ifname)         /* Dev name */
389 {
390   struct iwreq  wrq;
391   int           i = 0;          /* Start with first arg */
392   int           k;
393   iwprivargs    priv[16];
394   int           number;
395   char          ptype = 0;
396   char *        modes[] = { "invalid", "managed (BSS)", "reserved", "ad-hoc" };
397
398   /* Read the private ioctls */
399   number = iw_get_priv_info(skfd, ifname, priv);
400
401   /* Is there any ? */
402   if(number <= 0)
403     {
404       /* Could skip this message ? */
405       fprintf(stderr, "%-8.8s  no private ioctls.\n\n", ifname);
406       return(-1);
407     }
408
409   /* Arguments ? */
410   if(count == 0)
411     {
412       /* So, we just want to see the current value... */
413       k = -1;
414       while((++k < number) && strcmp(priv[k].name, "gport_type") &&
415              strcmp(priv[k].name, "get_port"));
416       if(k == number)
417         {
418           fprintf(stderr, "This device doesn't support getting port type\n");
419           return(-1);
420         }
421       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
422
423       /* Get it */
424       if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
425         {
426           fprintf(stderr, "Port type support is broken.\n");
427           exit(0);
428         }
429       ptype = *wrq.u.name;
430
431       /* Display it */
432       printf("%-8.8s  Current port mode is %s <port type is %d>.\n\n",
433              ifname, modes[(int) ptype], ptype);
434
435       return(0);
436     }
437
438   if(count != 1)
439     {
440       iw_usage();
441       return(-1);
442     }
443
444   /* Read it */
445   /* As a string... */
446   k = 0;
447   while((k < 4) && strncasecmp(args[i], modes[k], 2))
448     k++;
449   if(k < 4)
450     ptype = k;
451   else
452     /* ...or as an integer */
453     if(sscanf(args[i], "%d", (int *) &ptype) != 1)
454       {
455         iw_usage();
456         return(-1);
457       }
458   
459   k = -1;
460   while((++k < number) && strcmp(priv[k].name, "sport_type") &&
461         strcmp(priv[k].name, "set_port"));
462   if(k == number)
463     {
464       fprintf(stderr, "This device doesn't support setting port type\n");
465       return(-1);
466     }
467   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
468
469   *(wrq.u.name) = ptype;
470
471   if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
472     {
473       fprintf(stderr, "Invalid port type (or setting not allowed)\n");
474       return(-1);
475     }
476
477   return(0);
478 }
479
480 /******************************* MAIN ********************************/
481
482 /*------------------------------------------------------------------*/
483 /*
484  * The main !
485  */
486 int
487 main(int        argc,
488      char **    argv)
489 {
490   int skfd = -1;                /* generic raw socket desc.     */
491   int goterr = 0;
492
493   /* Create a channel to the NET kernel. */
494   if((skfd = iw_sockets_open()) < 0)
495     {
496       perror("socket");
497       return(-1);
498     }
499
500   /* No argument : show the list of all device + info */
501   if(argc == 1)
502     {
503       print_priv_devices(skfd);
504       close(skfd);
505       return(0);
506     }
507
508   /* Special cases take one... */
509   /* Help */
510   if((!strncmp(argv[1], "-h", 9)) ||
511      (!strcmp(argv[1], "--help")))
512     {
513       iw_usage();
514       close(skfd);
515       return(0);
516     }
517
518   /* The device name must be the first argument */
519   /* Name only : show for that device only */
520   if(argc == 2)
521     {
522       print_priv_info(skfd, argv[1]);
523       close(skfd);
524       return(0);
525     }
526
527   /* Special cases take two... */
528   /* Roaming */
529   if(!strncmp(argv[2], "roam", 4))
530     {
531       goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]);
532       close(skfd);
533       return(goterr);
534     }
535
536   /* Port type */
537   if(!strncmp(argv[2], "port", 4))
538     {
539       goterr = port_type(skfd, argv + 3, argc - 3, argv[1]);
540       close(skfd);
541       return(goterr);
542     }
543
544   /* Otherwise, it's a private ioctl */
545   goterr = set_private(skfd, argv + 2, argc - 2, argv[1]);
546
547   /* Close the socket. */
548   close(skfd);
549
550   return(goterr);
551 }