OSDN Git Service

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