OSDN Git Service

d1da985489456ec24e6b8178886b6dad35c9fcab
[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 {ad-hoc|managed|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   char *        modes[] = { "invalid", "managed (BSS)", "reserved", "ad-hoc" };
390
391   /* Read the private ioctls */
392   number = get_priv_info(skfd, ifname, priv);
393
394   /* Is there any ? */
395   if(number <= 0)
396     {
397       /* Could skip this message ? */
398       fprintf(stderr, "%-8.8s  no private ioctls.\n\n", ifname);
399       return(-1);
400     }
401
402   /* Arguments ? */
403   if(count == 0)
404     {
405       /* So, we just want to see the current value... */
406       k = -1;
407       while((++k < number) && strcmp(priv[k].name, "gport_type") &&
408              strcmp(priv[k].name, "get_port"));
409       if(k == number)
410         {
411           fprintf(stderr, "This device doesn't support getting port type\n");
412           return(-1);
413         }
414       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
415
416       /* Get it */
417       if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
418         {
419           fprintf(stderr, "Port type support is broken.\n");
420           exit(0);
421         }
422       ptype = *wrq.u.name;
423
424       /* Display it */
425       printf("%-8.8s  Current port mode is %s <port type is %d>.\n\n",
426              ifname, modes[(int) ptype], ptype);
427
428       return(0);
429     }
430
431   if(count != 1)
432     iw_usage();
433
434   /* Read it */
435   /* As a string... */
436   k = 0;
437   while((k < 4) && strncasecmp(args[i], modes[k], 2))
438     k++;
439   if(k < 4)
440     ptype = k;
441   else
442     /* ...or as an integer */
443     if(sscanf(args[i], "%d", (int *) &ptype) != 1)
444       iw_usage();
445   
446   k = -1;
447   while((++k < number) && strcmp(priv[k].name, "sport_type") &&
448         strcmp(priv[k].name, "set_port"));
449   if(k == number)
450     {
451       fprintf(stderr, "This device doesn't support setting port type\n");
452       return(-1);
453     }
454   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
455
456   *(wrq.u.name) = ptype;
457
458   if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
459     {
460       fprintf(stderr, "Invalid port type (or setting not allowed)\n");
461       exit(0);
462     }
463
464   i++;
465   return(i);
466 }
467
468 /******************************* MAIN ********************************/
469
470 /*------------------------------------------------------------------*/
471 /*
472  * The main !
473  */
474 int
475 main(int        argc,
476      char **    argv)
477 {
478   int skfd = -1;                /* generic raw socket desc.     */
479   int goterr = 0;
480
481   /* Create a channel to the NET kernel. */
482   if((skfd = sockets_open()) < 0)
483     {
484       perror("socket");
485       exit(-1);
486     }
487
488   /* No argument : show the list of all device + info */
489   if(argc == 1)
490     {
491       print_priv_devices(skfd);
492       close(skfd);
493       exit(0);
494     }
495
496   /* Special cases take one... */
497   /* Help */
498   if((!strncmp(argv[1], "-h", 9)) ||
499      (!strcmp(argv[1], "--help")))
500     {
501       iw_usage();
502       close(skfd);
503       exit(0);
504     }
505
506   /* The device name must be the first argument */
507   /* Name only : show for that device only */
508   if(argc == 2)
509     {
510       print_priv_info(skfd, argv[1]);
511       close(skfd);
512       exit(0);
513     }
514
515   /* Special cases take two... */
516   /* Roaming */
517   if(!strncmp(argv[2], "roam", 4))
518     {
519       goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]);
520       close(skfd);
521       exit(0);
522     }
523
524   /* Port type */
525   if(!strncmp(argv[2], "port", 4))
526     {
527       goterr = port_type(skfd, argv + 3, argc - 3, argv[1]);
528       close(skfd);
529       exit(0);
530     }
531
532   /* Otherwise, it's a private ioctl */
533   goterr = set_private(skfd, argv + 2, argc - 2, argv[1]);
534
535   /* Close the socket. */
536   close(skfd);
537
538   return(1);
539 }