nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Wireless Tools |
||
3 | * |
||
4 | * Jean II - HPLB '99 - HPL 99->04 |
||
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-2004 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.16s 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.16s 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.16s No statistics to collect\n", ifname); |
||
68 | else |
||
69 | printf("%-8.16s 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_saether_ntop(&hwa[i], temp)); |
||
79 | iw_print_stats(temp, sizeof(temp), &qual[i], &range, has_range); |
||
80 | printf("%s\n", temp); |
||
81 | } |
||
82 | |||
83 | if((n > 0) && (has_range) && (range.we_version_compiled > 11)) |
||
84 | { |
||
85 | iwstats stats; |
||
86 | |||
87 | /* Get /proc/net/wireless */ |
||
88 | if(iw_get_stats(skfd, ifname, &stats, &range, has_range) >= 0) |
||
89 | { |
||
90 | iw_print_stats(temp, sizeof(temp), &stats.qual, &range, has_range); |
||
91 | printf(" Link/Cell/AP : %s\n", temp); |
||
92 | /* Display the static data */ |
||
93 | iw_print_stats(temp, sizeof(temp), |
||
94 | &range.avg_qual, &range, has_range); |
||
95 | printf(" Typical/Reference : %s\n", temp); |
||
96 | } |
||
97 | } |
||
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 | struct iwreq wrq; |
||
114 | struct iw_thrspy threshold; |
||
115 | iwrange range; |
||
116 | int has_range = 0; |
||
117 | |||
118 | /* Avoid "Unused parameter" warning */ |
||
119 | args = args; count = count; |
||
120 | |||
121 | /* Time to send thresholds to the driver */ |
||
122 | wrq.u.data.pointer = (caddr_t) &threshold; |
||
123 | wrq.u.data.length = 1; |
||
124 | wrq.u.data.flags = 0; |
||
125 | if(iw_set_ext(skfd, ifname, SIOCGIWTHRSPY, &wrq) < 0) |
||
126 | { |
||
127 | fprintf(stderr, "Interface doesn't support thresholds...\n"); |
||
128 | fprintf(stderr, "SIOCGIWTHRSPY: %s\n", strerror(errno)); |
||
129 | return(-1); |
||
130 | } |
||
131 | |||
132 | /* Get range info if we can */ |
||
133 | if(iw_get_range_info(skfd, ifname, &(range)) >= 0) |
||
134 | has_range = 1; |
||
135 | |||
136 | /* Display thresholds */ |
||
137 | if((has_range) && (threshold.low.level)) |
||
138 | { |
||
139 | /* If the statistics are in dBm */ |
||
140 | if(threshold.low.level > range.max_qual.level) |
||
141 | { |
||
142 | /* Statistics are in dBm (absolute power measurement) */ |
||
143 | printf("%-8.16s Low threshold:%d dBm High threshold:%d dBm\n\n", |
||
144 | ifname, |
||
145 | threshold.low.level - 0x100, threshold.high.level - 0x100); |
||
146 | } |
||
147 | else |
||
148 | { |
||
149 | /* Statistics are relative values (0 -> max) */ |
||
150 | printf("%-8.16s Low threshold:%d/%d High threshold:%d/%d\n\n", |
||
151 | ifname, |
||
152 | threshold.low.level, range.max_qual.level, |
||
153 | threshold.high.level, range.max_qual.level); |
||
154 | } |
||
155 | } |
||
156 | else |
||
157 | { |
||
158 | /* We can't read the range, so we don't know... */ |
||
159 | printf("%-8.16s Low threshold:%d High threshold:%d\n\n", |
||
160 | ifname, |
||
161 | threshold.low.level, threshold.high.level); |
||
162 | } |
||
163 | |||
164 | return(0); |
||
165 | } |
||
166 | |||
167 | /************************* SETTING ROUTINES **************************/ |
||
168 | |||
169 | /*------------------------------------------------------------------*/ |
||
170 | /* |
||
171 | * Set list of addresses specified on command line in the driver. |
||
172 | */ |
||
173 | static int |
||
174 | set_spy_info(int skfd, /* The socket */ |
||
175 | char * ifname, /* Dev name */ |
||
176 | char * args[], /* Command line args */ |
||
177 | int count) /* Args count */ |
||
178 | { |
||
179 | struct iwreq wrq; |
||
180 | int i; |
||
181 | int nbr; /* Number of valid addresses */ |
||
182 | struct sockaddr hw_address[IW_MAX_SPY]; |
||
183 | |||
184 | /* Read command line */ |
||
185 | i = 0; /* first arg to read */ |
||
186 | nbr = 0; /* Number of args read so far */ |
||
187 | |||
188 | /* "off" : disable functionality (set 0 addresses) */ |
||
189 | if(!strcmp(args[0], "off")) |
||
190 | i = 1; /* skip the "off" */ |
||
191 | else |
||
192 | { |
||
193 | /* "+" : add all addresses already in the driver */ |
||
194 | if(!strcmp(args[0], "+")) |
||
195 | { |
||
196 | char buffer[(sizeof(struct iw_quality) + |
||
197 | sizeof(struct sockaddr)) * IW_MAX_SPY]; |
||
198 | |||
199 | /* Check if we have valid mac address type */ |
||
200 | if(iw_check_mac_addr_type(skfd, ifname) < 0) |
||
201 | { |
||
202 | fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname); |
||
203 | return(-1); |
||
204 | } |
||
205 | |||
206 | wrq.u.data.pointer = (caddr_t) buffer; |
||
207 | wrq.u.data.length = IW_MAX_SPY; |
||
208 | wrq.u.data.flags = 0; |
||
209 | if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) |
||
210 | { |
||
211 | fprintf(stderr, "Interface doesn't accept reading addresses...\n"); |
||
212 | fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno)); |
||
213 | return(-1); |
||
214 | } |
||
215 | |||
216 | /* Copy old addresses */ |
||
217 | nbr = wrq.u.data.length; |
||
218 | memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr)); |
||
219 | |||
220 | i = 1; /* skip the "+" */ |
||
221 | } |
||
222 | |||
223 | /* Read other args on command line */ |
||
224 | while((i < count) && (nbr < IW_MAX_SPY)) |
||
225 | { |
||
226 | /* Get the address and check if the interface supports it */ |
||
227 | if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0) |
||
228 | continue; |
||
229 | nbr++; |
||
230 | } |
||
231 | |||
232 | /* Check the number of addresses */ |
||
233 | if(nbr == 0) |
||
234 | { |
||
235 | fprintf(stderr, "No valid addresses found : exiting...\n"); |
||
236 | return(-1); |
||
237 | } |
||
238 | } |
||
239 | |||
240 | /* Check if there is some remaining arguments */ |
||
241 | if(i < count) |
||
242 | { |
||
243 | fprintf(stderr, "Got only the first %d arguments, remaining discarded\n", i); |
||
244 | } |
||
245 | |||
246 | /* Time to do send addresses to the driver */ |
||
247 | wrq.u.data.pointer = (caddr_t) hw_address; |
||
248 | wrq.u.data.length = nbr; |
||
249 | wrq.u.data.flags = 0; |
||
250 | if(iw_set_ext(skfd, ifname, SIOCSIWSPY, &wrq) < 0) |
||
251 | { |
||
252 | fprintf(stderr, "Interface doesn't accept addresses...\n"); |
||
253 | fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno)); |
||
254 | return(-1); |
||
255 | } |
||
256 | |||
257 | return(0); |
||
258 | } |
||
259 | |||
260 | /*------------------------------------------------------------------*/ |
||
261 | /* |
||
262 | * Set spy thresholds in the driver from command line |
||
263 | */ |
||
264 | static int |
||
265 | set_spy_threshold(int skfd, /* The socket */ |
||
266 | char * ifname, /* Dev name */ |
||
267 | char * args[], /* Command line args */ |
||
268 | int count) /* Args count */ |
||
269 | { |
||
270 | struct iwreq wrq; |
||
271 | struct iw_thrspy threshold; |
||
272 | int low_thr; |
||
273 | int high_thr; |
||
274 | |||
275 | /* Init */ |
||
276 | memset(&threshold, '\0', sizeof(threshold)); |
||
277 | |||
278 | /* "off" : disable functionality (set 0 addresses) */ |
||
279 | if(!strcmp(args[0], "off")) |
||
280 | { |
||
281 | /* Just send null threshold, will disable it */ |
||
282 | } |
||
283 | else |
||
284 | { |
||
285 | /* Try to get our threshold */ |
||
286 | if(count < 2) |
||
287 | { |
||
288 | fprintf(stderr, "%-8.16s Need two threshold values\n", ifname); |
||
289 | return(-1); |
||
290 | } |
||
291 | if((sscanf(args[0], "%i", &low_thr) != 1) || |
||
292 | (sscanf(args[1], "%i", &high_thr) != 1)) |
||
293 | { |
||
294 | fprintf(stderr, "%-8.16s Invalid threshold values\n", ifname); |
||
295 | return(-1); |
||
296 | } |
||
297 | /* Basic sanity check */ |
||
298 | if(high_thr < low_thr) |
||
299 | { |
||
300 | fprintf(stderr, "%-8.16s Inverted threshold range\n", ifname); |
||
301 | return(-1); |
||
302 | } |
||
303 | /* Copy thresholds */ |
||
304 | threshold.low.level = low_thr; |
||
305 | threshold.low.updated = 0x2; |
||
306 | threshold.high.level = high_thr; |
||
307 | threshold.high.updated = 0x2; |
||
308 | } |
||
309 | |||
310 | /* Time to send thresholds to the driver */ |
||
311 | wrq.u.data.pointer = (caddr_t) &threshold; |
||
312 | wrq.u.data.length = 1; |
||
313 | wrq.u.data.flags = 0; |
||
314 | if(iw_set_ext(skfd, ifname, SIOCSIWTHRSPY, &wrq) < 0) |
||
315 | { |
||
316 | fprintf(stderr, "Interface doesn't accept thresholds...\n"); |
||
317 | fprintf(stderr, "SIOCSIWTHRSPY: %s\n", strerror(errno)); |
||
318 | return(-1); |
||
319 | } |
||
320 | |||
321 | return(0); |
||
322 | } |
||
323 | |||
324 | /******************************* MAIN ********************************/ |
||
325 | |||
326 | /*------------------------------------------------------------------*/ |
||
327 | /* |
||
328 | * The main ! |
||
329 | */ |
||
330 | int |
||
331 | main(int argc, |
||
332 | char ** argv) |
||
333 | { |
||
334 | int skfd; /* generic raw socket desc. */ |
||
335 | int goterr = 0; |
||
336 | |||
337 | /* Create a channel to the NET kernel. */ |
||
338 | if((skfd = iw_sockets_open()) < 0) |
||
339 | { |
||
340 | perror("socket"); |
||
341 | return(-1); |
||
342 | } |
||
343 | |||
344 | /* No argument : show the list of all device + info */ |
||
345 | if(argc == 1) |
||
346 | iw_enum_devices(skfd, &print_spy_info, NULL, 0); |
||
347 | else |
||
348 | /* Special cases take one... */ |
||
349 | /* Help */ |
||
350 | if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) |
||
351 | fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n"); |
||
352 | else |
||
353 | /* Version */ |
||
354 | if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) |
||
355 | goterr = iw_print_version_info("iwspy"); |
||
356 | else |
||
357 | /* The device name must be the first argument */ |
||
358 | /* Name only : show spy list for that device only */ |
||
359 | if(argc == 2) |
||
360 | print_spy_info(skfd, argv[1], NULL, 0); |
||
361 | else |
||
362 | /* Special commands */ |
||
363 | if(!strcmp(argv[2], "setthr")) |
||
364 | goterr = set_spy_threshold(skfd, argv[1], argv + 3, argc - 3); |
||
365 | else |
||
366 | if(!strcmp(argv[2], "getthr")) |
||
367 | goterr = get_spy_threshold(skfd, argv[1], argv + 3, argc - 3); |
||
368 | else |
||
369 | /* Otherwise, it's a list of address to set in the spy list */ |
||
370 | goterr = set_spy_info(skfd, argv[1], argv + 2, argc - 2); |
||
371 | |||
372 | /* Close the socket. */ |
||
373 | iw_sockets_close(skfd); |
||
374 | |||
375 | return(goterr); |
||
376 | } |