OSDN Git Service

1fa39d34e39462ed742987fa96530519cf1fef83
[android-x86/external-wireless-tools.git] / wireless_tools / iwspy.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 /************************* DISPLAY ROUTINES **************************/
14
15 /*------------------------------------------------------------------*/
16 /*
17  * Display the spy list of addresses and the associated stats
18  */
19 static void
20 print_spy_info(int      skfd,
21                char *   ifname)
22 {
23   struct iwreq          wrq;
24   char          buffer[(sizeof(struct iw_quality) +
25                         sizeof(struct sockaddr)) * IW_MAX_SPY];
26   struct sockaddr       hwa[IW_MAX_SPY];
27   struct iw_quality     qual[IW_MAX_SPY];
28   iwrange       range;
29   int           has_range = 0;
30   int           n;
31   int           i;
32
33   /* Collect stats */
34   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
35   wrq.u.data.pointer = (caddr_t) buffer;
36   wrq.u.data.length = 0;
37   wrq.u.data.flags = 0;
38   if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0)
39     {
40       fprintf(stderr, "%-8.8s  Interface doesn't support wireless statistic collection\n\n", ifname);
41       return;
42     }
43
44   /* Number of addresses */
45   n = wrq.u.data.length;
46
47
48
49   /* Check if we have valid address types */
50   if(check_addr_type(skfd, ifname) < 0)
51     {
52       fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n\n", ifname);
53       return;
54     }
55
56   /* Get range info if we can */
57   if(get_range_info(skfd, ifname, &(range)) >= 0)
58     has_range = 1;
59
60   /* Display it */
61   if(n == 0)
62     printf("%-8.8s  No statistics to collect\n", ifname);
63   else
64     printf("%-8.8s  Statistics collected:\n", ifname);
65  
66   /* The two lists */
67
68   memcpy(hwa, buffer, n * sizeof(struct sockaddr));
69   memcpy(qual, buffer + n*sizeof(struct sockaddr), n*sizeof(struct iw_quality));
70
71   for(i = 0; i < n; i++)
72     {
73       if(has_range && (qual[i].level != 0))
74         /* If the statistics are in dBm */
75         if(qual[i].level > range.max_qual.level)
76           printf("    %s : Quality %d/%d ; Signal %d dBm ; Noise %d dBm %s\n",
77                  pr_ether(hwa[i].sa_data),
78                  qual[i].qual, range.max_qual.qual,
79                  qual[i].level - 0x100, qual[i].noise - 0x100,
80                  qual[i].updated & 0x7 ? "(updated)" : "");
81         else
82           printf("    %s : Quality %d/%d ; Signal %d/%d ; Noise %d/%d %s\n",
83                  pr_ether(hwa[i].sa_data),
84                  qual[i].qual, range.max_qual.qual,
85                  qual[i].level, range.max_qual.level,
86                  qual[i].noise, range.max_qual.noise,
87                  qual[i].updated & 0x7 ? "(updated)" : "");
88       else
89         printf("    %s : Quality %d ; Signal %d ; Noise %d %s\n",
90                pr_ether(hwa[i].sa_data),
91                qual[i].qual, qual[i].level, qual[i].noise,
92                qual[i].updated & 0x7 ? "(updated)" : "");
93     }
94   printf("\n");
95 }
96
97 /*------------------------------------------------------------------*/
98 /*
99  * Get info on all devices and print it on the screen
100  */
101 static void
102 print_spy_devices(int           skfd)
103 {
104   char          buff[1024];
105   struct ifconf ifc;
106   struct ifreq *ifr;
107   int i;
108
109   /* Get list of active devices */
110   ifc.ifc_len = sizeof(buff);
111   ifc.ifc_buf = buff;
112   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
113     {
114       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
115       return;
116     }
117   ifr = ifc.ifc_req;
118
119   /* Print them */
120   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
121     print_spy_info(skfd, ifr->ifr_name);
122 }
123
124 /*------------------------------------------------------------------*/
125 /*
126  * Print the number of channels and available frequency for the device
127  */
128 static void
129 print_freq_info(int             skfd,
130                 char *          ifname)
131 {
132   struct iwreq          wrq;
133   float                 freq;
134   struct iw_range       range;
135   int                   k;
136
137   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
138   wrq.u.data.pointer = (caddr_t) &range;
139   wrq.u.data.length = 0;
140   wrq.u.data.flags = 0;
141   if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0)
142       fprintf(stderr, "%-8.8s  no frequency information.\n\n",
143                       ifname);
144   else
145     {
146       if(range.num_frequency > 0)
147         {
148           printf("%-8.8s  %d channels in total; available frequencies :\n",
149                  ifname, range.num_channels);
150           /* Print them all */
151           for(k = 0; k < range.num_frequency; k++)
152             {
153               printf("\t  Channel %.2d : ", range.freq[k].i);
154               freq = freq2float(&(range.freq[k]));
155               if(freq >= GIGA)
156                 printf("%g GHz\n", freq / GIGA);
157               else
158                 if(freq >= MEGA)
159                   printf("%g MHz\n", freq / MEGA);
160                 else
161                   printf("%g kHz\n", freq / KILO);
162             }
163           printf("\n\n");
164         }
165       else
166         printf("%-8.8s  %d channels\n\n",
167                ifname, range.num_channels);
168     }
169 }
170
171 /*------------------------------------------------------------------*/
172 /*
173  * Get frequency info on all devices and print it on the screen
174  */
175 static void
176 print_freq_devices(int          skfd)
177 {
178   char          buff[1024];
179   struct ifconf ifc;
180   struct ifreq *ifr;
181   int i;
182
183   /* Get list of active devices */
184   ifc.ifc_len = sizeof(buff);
185   ifc.ifc_buf = buff;
186   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
187     {
188       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
189       return;
190     }
191   ifr = ifc.ifc_req;
192
193   /* Print them */
194   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
195     print_freq_info(skfd, ifr->ifr_name);
196 }
197
198 /*------------------------------------------------------------------*/
199 /*
200  * Display the list of ap addresses and the associated stats
201  * Exacly the same as the spy list, only with different IOCTL and messages
202  */
203 static void
204 print_ap_info(int       skfd,
205                char *   ifname)
206 {
207   struct iwreq          wrq;
208   char          buffer[(sizeof(struct iw_quality) +
209                         sizeof(struct sockaddr)) * IW_MAX_AP];
210   struct sockaddr *     hwa;
211   struct iw_quality *   qual;
212   iwrange       range;
213   int           has_range = 0;
214   int           has_qual = 0;
215   int           n;
216   int           i;
217
218   /* Collect stats */
219   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
220   wrq.u.data.pointer = (caddr_t) buffer;
221   wrq.u.data.length = 0;
222   wrq.u.data.flags = 0;
223   if(ioctl(skfd, SIOCGIWAPLIST, &wrq) < 0)
224     {
225       fprintf(stderr, "%-8.8s  Interface doesn't have a list of Access Points\n\n", ifname);
226       return;
227     }
228
229   /* Number of addresses */
230   n = wrq.u.data.length;
231   has_qual = wrq.u.data.flags;
232
233   /* The two lists */
234   hwa = (struct sockaddr *) buffer;
235   qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
236
237   /* Check if we have valid address types */
238   if(check_addr_type(skfd, ifname) < 0)
239     {
240       fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n\n", ifname);
241       return;
242     }
243
244   /* Get range info if we can */
245   if(get_range_info(skfd, ifname, &(range)) >= 0)
246     has_range = 1;
247
248   /* Display it */
249   if(n == 0)
250     printf("%-8.8s  No Access Point in range\n", ifname);
251   else
252     printf("%-8.8s  Access Points in range:\n", ifname);
253   for(i = 0; i < n; i++)
254     {
255       if(has_qual)
256         if(has_range)
257           /* If the statistics are in dBm */
258           if(qual[i].level > range.max_qual.level)
259             printf("    %s : Quality %d/%d ; Signal %d dBm ; Noise %d dBm %s\n",
260                    pr_ether(hwa[i].sa_data),
261                    qual[i].qual, range.max_qual.qual,
262                    qual[i].level - 0x100, qual[i].noise - 0x100,
263                    qual[i].updated & 0x7 ? "(updated)" : "");
264           else
265             printf("    %s : Quality %d/%d ; Signal %d/%d ; Noise %d/%d %s\n",
266                    pr_ether(hwa[i].sa_data),
267                    qual[i].qual, range.max_qual.qual,
268                    qual[i].level, range.max_qual.level,
269                    qual[i].noise, range.max_qual.noise,
270                    qual[i].updated & 0x7 ? "(updated)" : "");
271         else
272           printf("    %s : Quality %d ; Signal %d ; Noise %d %s\n",
273                  pr_ether(hwa[i].sa_data),
274                  qual[i].qual, qual[i].level, qual[i].noise,
275                  qual[i].updated & 0x7 ? "(updated)" : "");
276       else
277         printf("    %s\n", pr_ether(hwa[i].sa_data));
278     }
279   printf("\n");
280 }
281
282 /*------------------------------------------------------------------*/
283 /*
284  * Get list of AP on all devices and print it on the screen
285  */
286 static void
287 print_ap_devices(int            skfd)
288 {
289   char          buff[1024];
290   struct ifconf ifc;
291   struct ifreq *ifr;
292   int i;
293
294   /* Get list of active devices */
295   ifc.ifc_len = sizeof(buff);
296   ifc.ifc_buf = buff;
297   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
298     {
299       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
300       return;
301     }
302   ifr = ifc.ifc_req;
303
304   /* Print them */
305   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
306     print_ap_info(skfd, ifr->ifr_name);
307 }
308
309 /*------------------------------------------------------------------*/
310 /*
311  * Print the number of available bitrates for the device
312  */
313 static void
314 print_bitrate_info(int          skfd,
315                    char *       ifname)
316 {
317   struct iwreq          wrq;
318   float                 bitrate;
319   struct iw_range       range;
320   int                   k;
321
322   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
323   wrq.u.data.pointer = (caddr_t) &range;
324   wrq.u.data.length = 0;
325   wrq.u.data.flags = 0;
326   if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0)
327       fprintf(stderr, "%-8.8s  no bit-rate information.\n\n",
328                       ifname);
329   else
330     {
331       if((range.num_bitrates > 0) && (range.num_bitrates < IW_MAX_BITRATES))
332         {
333           printf("%-8.8s  %d available bit-rates :\n",
334                  ifname, range.num_bitrates);
335           /* Print them all */
336           for(k = 0; k < range.num_bitrates; k++)
337             {
338               printf("\t  ");
339               bitrate = range.bitrate[k];
340               if(bitrate >= GIGA)
341                 printf("%g Gb/s\n", bitrate / GIGA);
342               else
343                 if(bitrate >= MEGA)
344                   printf("%g Mb/s\n", bitrate / MEGA);
345                 else
346                   printf("%g kb/s\n", bitrate / KILO);
347             }
348           printf("\n\n");
349         }
350       else
351         printf("%-8.8s  No bit-rates ? Please update driver...\n\n", ifname);
352     }
353 }
354
355 /*------------------------------------------------------------------*/
356 /*
357  * Get bit-rate info on all devices and print it on the screen
358  */
359 static void
360 print_bitrate_devices(int               skfd)
361 {
362   char          buff[1024];
363   struct ifconf ifc;
364   struct ifreq *ifr;
365   int i;
366
367   /* Get list of active devices */
368   ifc.ifc_len = sizeof(buff);
369   ifc.ifc_buf = buff;
370   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
371     {
372       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
373       return;
374     }
375   ifr = ifc.ifc_req;
376
377   /* Print them */
378   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
379     print_bitrate_info(skfd, ifr->ifr_name);
380 }
381
382 /*------------------------------------------------------------------*/
383 /*
384  * Print the number of available bitrates for the device
385  */
386 static void
387 print_keys_info(int             skfd,
388                 char *          ifname)
389 {
390   struct iwreq          wrq;
391   struct iw_range       range;
392   unsigned char         key[IW_ENCODING_TOKEN_MAX];
393   int                   k;
394
395   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
396   wrq.u.data.pointer = (caddr_t) &range;
397   wrq.u.data.length = 0;
398   wrq.u.data.flags = 0;
399   if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0)
400       fprintf(stderr, "%-8.8s  no encryption keys information.\n\n",
401                       ifname);
402   else
403     {
404       printf("%-8.8s  ", ifname);
405       if((range.num_encoding_sizes > 0) &&
406          (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
407         {
408           printf("%d key sizes : %d", range.num_encoding_sizes,
409                  range.encoding_size[0] * 8);
410           /* Print them all */
411           for(k = 1; k < range.num_encoding_sizes; k++)
412             printf(", %d", range.encoding_size[k] * 8);
413           printf("bits\n          ");
414         }
415       printf("%d keys available :\n", range.max_encoding_tokens);
416       for(k = 1; k <= range.max_encoding_tokens; k++)
417         {
418           strcpy(wrq.ifr_name, ifname);
419           wrq.u.data.pointer = (caddr_t) key;
420           wrq.u.data.length = 0;
421           wrq.u.data.flags = k;
422           if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
423             {
424               fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
425               break;
426             }
427           if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
428              (wrq.u.data.length == 0))
429             printf("\t\t[%d]: off\n", k);
430           else
431             {
432               int       i;
433
434               printf("\t\t[%d]: %.2X", k, key[0]);
435               for(i = 1; i < wrq.u.data.length; i++)
436                 {
437                   if((i & 0x1) == 0)
438                     printf("-");
439                   printf("%.2X", key[i]);
440                 }
441
442               /* Other info... */
443               printf(" (%d bits)", wrq.u.data.length * 8);
444               printf("\n");
445             }
446         }
447
448       printf("\n\n");
449     }
450 }
451
452 /*------------------------------------------------------------------*/
453 /*
454  * Get bit-rate info on all devices and print it on the screen
455  */
456 static void
457 print_keys_devices(int          skfd)
458 {
459   char          buff[1024];
460   struct ifconf ifc;
461   struct ifreq *ifr;
462   int i;
463
464   /* Get list of active devices */
465   ifc.ifc_len = sizeof(buff);
466   ifc.ifc_buf = buff;
467   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
468     {
469       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
470       return;
471     }
472   ifr = ifc.ifc_req;
473
474   /* Print them */
475   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
476     print_keys_info(skfd, ifr->ifr_name);
477 }
478
479 /************************* SETTING ROUTINES **************************/
480
481 /*------------------------------------------------------------------*/
482 /*
483  * Set list of addresses specified on command line in the driver.
484  */
485 static int
486 set_spy_info(int                skfd,           /* The socket */
487              char *             args[],         /* Command line args */
488              int                count,          /* Args count */
489              char *             ifname)         /* Dev name */
490 {
491   struct iwreq          wrq;
492   int                   i;
493   int                   nbr;            /* Number of valid addresses */
494   struct sockaddr       hw_address[IW_MAX_SPY];
495
496   /* Read command line */
497   i = 0;        /* first arg to read */
498   nbr = 0;      /* Number of args readen so far */
499
500   /* Check if we have valid address types */
501   if(check_addr_type(skfd, ifname) < 0)
502     {
503       fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n", ifname);
504       return(-1);
505     }
506
507   /* "off" : disable functionality (set 0 addresses) */
508   if(!strcmp(args[0], "off"))
509     i = count;  /* hack */
510
511   /* "+" : add all addresses already in the driver */
512   if(!strcmp(args[0], "+"))
513     {
514       char      buffer[(sizeof(struct iw_quality) +
515                         sizeof(struct sockaddr)) * IW_MAX_SPY];
516
517       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
518       wrq.u.data.pointer = (caddr_t) buffer;
519       wrq.u.data.length = 0;
520       wrq.u.data.flags = 0;
521       if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0)
522         {
523           fprintf(stderr, "Interface doesn't accept reading addresses...\n");
524           fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
525           return(-1);
526         }
527
528       /* Copy old addresses */
529       nbr = wrq.u.data.length;
530       memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
531
532       i = 1;    /* skip the "+" */
533     }
534
535   /* Read other args on command line */
536   while((i < count) && (nbr < IW_MAX_SPY))
537     {
538       if(in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
539         continue;
540       nbr++;
541     }
542
543   /* Check the number of addresses */
544   if((nbr == 0) && strcmp(args[0], "off"))
545     {
546       fprintf(stderr, "No valid addresses found : exiting...\n");
547       exit(0);
548     }
549
550   /* Check if there is some remaining arguments */
551   if(i < count)
552     {
553       fprintf(stderr, "Got only the first %d addresses, remaining discarded\n", IW_MAX_SPY);
554     }
555
556   /* Time to do send addresses to the driver */
557   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
558   wrq.u.data.pointer = (caddr_t) hw_address;
559   wrq.u.data.length = nbr;
560   wrq.u.data.flags = 0;
561   if(ioctl(skfd, SIOCSIWSPY, &wrq) < 0)
562     {
563       fprintf(stderr, "Interface doesn't accept addresses...\n");
564       fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno));
565       return(-1);
566     }
567
568   return(0);
569 }
570
571 /******************************* MAIN ********************************/
572
573 /*------------------------------------------------------------------*/
574 /*
575  * The main !
576  */
577 int
578 main(int        argc,
579      char **    argv)
580 {
581   int skfd = -1;                /* generic raw socket desc.     */
582   int goterr = 0;
583
584   /* Create a channel to the NET kernel. */
585   if((skfd = sockets_open()) < 0)
586     {
587       perror("socket");
588       exit(-1);
589     }
590
591   /* No argument : show the list of all device + info */
592   if(argc == 1)
593     {
594       print_spy_devices(skfd);
595       close(skfd);
596       exit(0);
597     }
598
599   /* Special cases take one... */
600   /* Help */
601   if((!strncmp(argv[1], "-h", 9)) ||
602      (!strcmp(argv[1], "--help")))
603     {
604       fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n");
605       fprintf(stderr, "             interface [freq]\n");
606       fprintf(stderr, "             interface [ap]\n");
607       close(skfd);
608       exit(0);
609     }
610
611   /* Frequency list */
612   if((!strncmp(argv[1], "freq", 4)) ||
613      (!strncmp(argv[1], "channel", 7)))
614     {
615       print_freq_devices(skfd);
616       close(skfd);
617       exit(0);
618     }
619
620   /* Access Point list */
621   if(!strcasecmp(argv[1], "ap"))
622     {
623       print_ap_devices(skfd);
624       close(skfd);
625       exit(0);
626     }
627
628   /* Bit-rate list */
629   if((!strncmp(argv[1], "bit", 3)) ||
630      (!strcmp(argv[1], "rate")))
631     {
632       print_bitrate_devices(skfd);
633       close(skfd);
634       exit(0);
635     }
636
637   /* Encryption key list */
638   if((!strncmp(argv[1], "enc", 3)) ||
639      (!strncmp(argv[1], "key", 3)))
640     {
641       print_keys_devices(skfd);
642       close(skfd);
643       exit(0);
644     }
645
646   /* The device name must be the first argument */
647   /* Name only : show spy list for that device only */
648   if(argc == 2)
649     {
650       print_spy_info(skfd, argv[1]);
651       close(skfd);
652       exit(0);
653     }
654
655   /* Special cases take two... */
656   /* Frequency list */
657   if((!strncmp(argv[2], "freq", 4)) ||
658      (!strncmp(argv[2], "channel", 7)))
659     {
660       print_freq_info(skfd, argv[1]);
661       close(skfd);
662       exit(0);
663     }
664
665   /* Access Point  list */
666   if(!strcasecmp(argv[2], "ap"))
667     {
668       print_ap_info(skfd, argv[1]);
669       close(skfd);
670       exit(0);
671     }
672
673   /* Access Point  list */
674   if((!strncmp(argv[2], "bit", 3)) ||
675      (!strcmp(argv[2], "rate")))
676     {
677       print_bitrate_info(skfd, argv[1]);
678       close(skfd);
679       exit(0);
680     }
681
682   /* Access Point  list */
683   if((!strncmp(argv[2], "enc", 3)) ||
684      (!strncmp(argv[2], "key", 3)))
685     {
686       print_keys_info(skfd, argv[1]);
687       close(skfd);
688       exit(0);
689     }
690
691   /* Otherwise, it's a list of address to set in the spy list */
692   goterr = set_spy_info(skfd, argv + 2, argc - 2, argv[1]);
693
694   /* Close the socket. */
695   close(skfd);
696
697   return(1);
698 }