OSDN Git Service

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