OSDN Git Service

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