OSDN Git Service

v26
[android-x86/external-wireless-tools.git] / wireless_tools / iwspy.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPLB '99
5  *
6  * This tool can manipulate the spy list : add addresses and display stat
7  * You need to link this code against "iwlib.c" and "-lm".
8  *
9  * This file is released under the GPL license.
10  *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
11  */
12
13 #include "iwlib.h"              /* Header */
14
15 /************************* DISPLAY ROUTINES **************************/
16
17 /*------------------------------------------------------------------*/
18 /*
19  * Display the spy list of addresses and the associated stats
20  */
21 static int
22 print_spy_info(int      skfd,
23                char *   ifname,
24                char *   args[],
25                int      count)
26 {
27   struct iwreq          wrq;
28   char          buffer[(sizeof(struct iw_quality) +
29                         sizeof(struct sockaddr)) * IW_MAX_SPY];
30   char          temp[128];
31   struct sockaddr *     hwa;
32   struct iw_quality *   qual;
33   iwrange       range;
34   int           has_range = 0;
35   int           n;
36   int           i;
37
38   /* Avoid "Unused parameter" warning */
39   args = args; count = count;
40
41   /* Collect stats */
42   wrq.u.data.pointer = (caddr_t) buffer;
43   wrq.u.data.length = IW_MAX_SPY;
44   wrq.u.data.flags = 0;
45   if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
46     {
47       fprintf(stderr, "%-8.8s  Interface doesn't support wireless statistic collection\n\n", ifname);
48       return(-1);
49     }
50
51   /* Number of addresses */
52   n = wrq.u.data.length;
53
54   /* Check if we have valid mac address type */
55   if(iw_check_mac_addr_type(skfd, ifname) < 0)
56     {
57       fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n\n", ifname);
58       return(-2);
59     }
60
61   /* Get range info if we can */
62   if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
63     has_range = 1;
64
65   /* Display it */
66   if(n == 0)
67     printf("%-8.8s  No statistics to collect\n", ifname);
68   else
69     printf("%-8.8s  Statistics collected:\n", ifname);
70  
71   /* The two lists */
72   hwa = (struct sockaddr *) buffer;
73   qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
74
75   for(i = 0; i < n; i++)
76     {
77       /* Print stats for each address */
78       printf("    %s : ", iw_pr_ether(temp, hwa[i].sa_data));
79       iw_print_stats(temp, &qual[i], &range, has_range);
80       printf("%s\n", temp);
81     }
82 #if WIRELESS_EXT > 11
83   if((n > 0) && (has_range))
84     {
85       iwstats   stats;
86
87       /* Get /proc/net/wireless */
88       if(iw_get_stats(skfd, ifname, &stats) >= 0)
89         {
90           iw_print_stats(buffer, &stats.qual, &range, has_range);
91           printf("    Link/Cell/AP      : %s\n", buffer);
92           /* Display the static data */
93           iw_print_stats(temp, &range.avg_qual, &range, has_range);
94           printf("    Typical/Reference : %s\n", temp);
95         }
96     }
97 #endif /* WIRELESS_EXT > 11 */
98
99   printf("\n");
100   return(0);
101 }
102
103 /*------------------------------------------------------------------*/
104 /*
105  * Get spy thresholds from the driver and display
106  */
107 static int
108 get_spy_threshold(int           skfd,           /* The socket */
109                   char *        ifname,         /* Dev name */
110                   char *        args[],         /* Command line args */
111                   int           count)          /* Args count */
112 {
113 #if WIRELESS_EXT > 15
114   struct iwreq          wrq;
115   struct iw_thrspy      threshold;
116   iwrange       range;
117   int                   has_range = 0;
118
119   /* Avoid "Unused parameter" warning */
120   args = args; count = count;
121
122   /* Time to send thresholds to the driver */
123   wrq.u.data.pointer = (caddr_t) &threshold;
124   wrq.u.data.length = 1;
125   wrq.u.data.flags = 0;
126   if(iw_set_ext(skfd, ifname, SIOCGIWTHRSPY, &wrq) < 0)
127     {
128       fprintf(stderr, "Interface doesn't support thresholds...\n");
129       fprintf(stderr, "SIOCGIWTHRSPY: %s\n", strerror(errno));
130       return(-1);
131     }
132
133   /* Get range info if we can */
134   if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
135     has_range = 1;
136
137   /* Display thresholds */
138   if((has_range) && (threshold.low.level))
139     {
140       /* If the statistics are in dBm */
141       if(threshold.low.level > range.max_qual.level)
142         {
143           /* Statistics are in dBm (absolute power measurement) */
144           printf("%-8.8s  Low threshold:%d dBm  High threshold:%d dBm\n\n",
145                  ifname,
146                  threshold.low.level - 0x100, threshold.high.level - 0x100);
147         }
148       else
149         {
150           /* Statistics are relative values (0 -> max) */
151           printf("%-8.8s  Low threshold:%d/%d  High threshold:%d/%d\n\n",
152                  ifname,
153                  threshold.low.level, range.max_qual.level,
154                  threshold.high.level, range.max_qual.level);
155         }
156     }
157   else
158     {
159       /* We can't read the range, so we don't know... */
160       printf("%-8.8s  Low threshold:%d  High threshold:%d\n\n",
161              ifname,
162              threshold.low.level, threshold.high.level);
163     }
164
165   return(0);
166 #else /* WIRELESS_EXT > 15 */
167   /* Avoid "Unused parameter" warning */
168   skfd = skfd; ifname = ifname; args = args; count = count;
169
170   fprintf(stderr, "Feature not available...\n");
171   return(-1);
172 #endif /* WIRELESS_EXT > 15 */
173 }
174
175 /************************* SETTING ROUTINES **************************/
176
177 /*------------------------------------------------------------------*/
178 /*
179  * Set list of addresses specified on command line in the driver.
180  */
181 static int
182 set_spy_info(int                skfd,           /* The socket */
183              char *             ifname,         /* Dev name */
184              char *             args[],         /* Command line args */
185              int                count)          /* Args count */
186 {
187   struct iwreq          wrq;
188   int                   i;
189   int                   nbr;            /* Number of valid addresses */
190   struct sockaddr       hw_address[IW_MAX_SPY];
191
192   /* Read command line */
193   i = 0;        /* first arg to read */
194   nbr = 0;      /* Number of args read so far */
195
196   /* "off" : disable functionality (set 0 addresses) */
197   if(!strcmp(args[0], "off"))
198     i = 1;      /* skip the "off" */
199   else
200     {
201       /* "+" : add all addresses already in the driver */
202       if(!strcmp(args[0], "+"))
203         {
204           char  buffer[(sizeof(struct iw_quality) +
205                         sizeof(struct sockaddr)) * IW_MAX_SPY];
206
207           /* Check if we have valid mac address type */
208           if(iw_check_mac_addr_type(skfd, ifname) < 0)
209             {
210               fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n", ifname);
211               return(-1);
212             }
213
214           wrq.u.data.pointer = (caddr_t) buffer;
215           wrq.u.data.length = 0;
216           wrq.u.data.flags = 0;
217           if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
218             {
219               fprintf(stderr, "Interface doesn't accept reading addresses...\n");
220               fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
221               return(-1);
222             }
223
224           /* Copy old addresses */
225           nbr = wrq.u.data.length;
226           memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
227
228           i = 1;        /* skip the "+" */
229         }
230
231       /* Read other args on command line */
232       while((i < count) && (nbr < IW_MAX_SPY))
233         {
234           /* Get the address and check if the interface supports it */
235           if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
236             continue;
237           nbr++;
238         }
239
240       /* Check the number of addresses */
241       if(nbr == 0)
242         {
243           fprintf(stderr, "No valid addresses found : exiting...\n");
244           return(-1);
245         }
246     }
247
248   /* Check if there is some remaining arguments */
249   if(i < count)
250     {
251       fprintf(stderr, "Got only the first %d arguments, remaining discarded\n", i);
252     }
253
254   /* Time to do send addresses to the driver */
255   wrq.u.data.pointer = (caddr_t) hw_address;
256   wrq.u.data.length = nbr;
257   wrq.u.data.flags = 0;
258   if(iw_set_ext(skfd, ifname, SIOCSIWSPY, &wrq) < 0)
259     {
260       fprintf(stderr, "Interface doesn't accept addresses...\n");
261       fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno));
262       return(-1);
263     }
264
265   return(0);
266 }
267
268 /*------------------------------------------------------------------*/
269 /*
270  * Set spy thresholds in the driver from command line
271  */
272 static int
273 set_spy_threshold(int           skfd,           /* The socket */
274                   char *        ifname,         /* Dev name */
275                   char *        args[],         /* Command line args */
276                   int           count)          /* Args count */
277 {
278 #if WIRELESS_EXT > 15
279   struct iwreq          wrq;
280   struct iw_thrspy      threshold;
281   int                   low_thr;
282   int                   high_thr;
283
284   /* Init */
285   memset(&threshold, '\0', sizeof(threshold));
286
287   /* "off" : disable functionality (set 0 addresses) */
288   if(!strcmp(args[0], "off"))
289     {
290       /* Just send null threshold, will disable it */
291     }
292   else
293     {
294       /* Try to get our threshold */
295       if(count < 2)
296         {
297           fprintf(stderr, "%-8.8s  Need two threshold values\n", ifname);
298           return(-1);
299         }
300       if((sscanf(args[0], "%i", &low_thr) != 1) ||
301          (sscanf(args[1], "%i", &high_thr) != 1))
302         {
303           fprintf(stderr, "%-8.8s  Invalid threshold values\n", ifname);
304           return(-1);
305         }
306       /* Basic sanity check */
307       if(high_thr < low_thr)
308         {
309           fprintf(stderr, "%-8.8s  Inverted threshold range\n", ifname);
310           return(-1);
311         }
312       /* Copy thresholds */
313       threshold.low.level = low_thr;
314       threshold.low.updated = 0x2;
315       threshold.high.level = high_thr;
316       threshold.high.updated = 0x2;
317     }
318
319   /* Time to send thresholds to the driver */
320   wrq.u.data.pointer = (caddr_t) &threshold;
321   wrq.u.data.length = 1;
322   wrq.u.data.flags = 0;
323   if(iw_set_ext(skfd, ifname, SIOCSIWTHRSPY, &wrq) < 0)
324     {
325       fprintf(stderr, "Interface doesn't accept thresholds...\n");
326       fprintf(stderr, "SIOCSIWTHRSPY: %s\n", strerror(errno));
327       return(-1);
328     }
329
330   return(0);
331 #else /* WIRELESS_EXT > 15 */
332   /* Avoid "Unused parameter" warning */
333   skfd = skfd; ifname = ifname; args = args; count = count;
334
335   fprintf(stderr, "Feature not available...\n");
336   return(-1);
337 #endif /* WIRELESS_EXT > 15 */
338 }
339
340 /******************************* MAIN ********************************/
341
342 /*------------------------------------------------------------------*/
343 /*
344  * The main !
345  */
346 int
347 main(int        argc,
348      char **    argv)
349 {
350   int skfd;                     /* generic raw socket desc.     */
351   int goterr = 0;
352
353   /* Create a channel to the NET kernel. */
354   if((skfd = iw_sockets_open()) < 0)
355     {
356       perror("socket");
357       return(-1);
358     }
359
360   /* No argument : show the list of all device + info */
361   if(argc == 1)
362     iw_enum_devices(skfd, &print_spy_info, NULL, 0);
363   else
364     /* Special cases take one... */
365     /* Help */
366     if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
367       fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n");
368     else
369       /* Version */
370       if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
371         goterr = iw_print_version_info("iwspy");
372       else
373         /* The device name must be the first argument */
374         /* Name only : show spy list for that device only */
375         if(argc == 2)
376           print_spy_info(skfd, argv[1], NULL, 0);
377         else
378           /* Special commands */
379           if(!strcmp(argv[2], "setthr"))
380             goterr = set_spy_threshold(skfd, argv[1], argv + 3, argc - 3);
381           else
382             if(!strcmp(argv[2], "getthr"))
383               goterr = get_spy_threshold(skfd, argv[1], argv + 3, argc - 3);
384             else
385               /* Otherwise, it's a list of address to set in the spy list */
386               goterr = set_spy_info(skfd, argv[1], argv + 2, argc - 2);
387
388   /* Close the socket. */
389   close(skfd);
390
391   return(goterr);
392 }