OSDN Git Service

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