6 * Main code for "iwconfig". This is the generic tool for most
8 * You need to link this code against "iwcommon.c" and "-lm".
11 #include "iwcommon.h" /* Header */
13 /************************* DISPLAY ROUTINES **************************/
15 /*------------------------------------------------------------------*/
17 * Display the spy list of addresses and the associated stats
20 print_spy_info(int skfd,
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];
34 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
35 wrq.u.data.pointer = (caddr_t) buffer;
36 wrq.u.data.length = 0;
38 if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0)
40 fprintf(stderr, "%-8.8s Interface doesn't support wireless statistic collection\n\n", ifname);
44 /* Number of addresses */
45 n = wrq.u.data.length;
49 /* Check if we have valid address types */
50 if(check_addr_type(skfd, ifname) < 0)
52 fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname);
56 /* Get range info if we can */
57 if(get_range_info(skfd, ifname, &(range)) >= 0)
62 printf("%-8.8s No statistics to collect\n", ifname);
64 printf("%-8.8s Statistics collected:\n", ifname);
68 memcpy(hwa, buffer, n * sizeof(struct sockaddr));
69 memcpy(qual, buffer + n*sizeof(struct sockaddr), n*sizeof(struct iw_quality));
71 for(i = 0; i < n; i++)
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)" : "");
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)" : "");
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)" : "");
97 /*------------------------------------------------------------------*/
99 * Get info on all devices and print it on the screen
102 print_spy_devices(int skfd)
109 /* Get list of active devices */
110 ifc.ifc_len = sizeof(buff);
112 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
114 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
120 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
121 print_spy_info(skfd, ifr->ifr_name);
124 /*------------------------------------------------------------------*/
126 * Print the number of channels and available frequency for the device
129 print_freq_info(int skfd,
134 struct iw_range range;
137 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
138 wrq.u.data.pointer = (caddr_t) ⦥
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",
146 if(range.num_frequency > 0)
148 printf("%-8.8s %d channels in total; available frequencies :\n",
149 ifname, range.num_channels);
151 for(k = 0; k < range.num_frequency; k++)
154 printf("\t Channel %.2d : ", range.freq[k].i);
158 freq = freq2float(&(range.freq[k]));
160 printf("%g GHz\n", freq / GIGA);
163 printf("%g MHz\n", freq / MEGA);
165 printf("%g kHz\n", freq / KILO);
170 printf("%-8.8s %d channels\n\n",
171 ifname, range.num_channels);
175 /*------------------------------------------------------------------*/
177 * Get frequency info on all devices and print it on the screen
180 print_freq_devices(int skfd)
187 /* Get list of active devices */
188 ifc.ifc_len = sizeof(buff);
190 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
192 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
198 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
199 print_freq_info(skfd, ifr->ifr_name);
203 /*------------------------------------------------------------------*/
205 * Display the list of ap addresses and the associated stats
206 * Exacly the same as the spy list, only with different IOCTL and messages
209 print_ap_info(int skfd,
213 char buffer[(sizeof(struct iw_quality) +
214 sizeof(struct sockaddr)) * IW_MAX_AP];
215 struct sockaddr * hwa;
216 struct iw_quality * qual;
224 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
225 wrq.u.data.pointer = (caddr_t) buffer;
226 wrq.u.data.length = 0;
227 wrq.u.data.flags = 0;
228 if(ioctl(skfd, SIOCGIWAPLIST, &wrq) < 0)
230 fprintf(stderr, "%-8.8s Interface doesn't have a list of Access Points\n\n", ifname);
234 /* Number of addresses */
235 n = wrq.u.data.length;
236 has_qual = wrq.u.data.flags;
239 hwa = (struct sockaddr *) buffer;
240 qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
242 /* Check if we have valid address types */
243 if(check_addr_type(skfd, ifname) < 0)
245 fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname);
249 /* Get range info if we can */
250 if(get_range_info(skfd, ifname, &(range)) >= 0)
255 printf("%-8.8s No Access Point in range\n", ifname);
257 printf("%-8.8s Access Points in range:\n", ifname);
258 for(i = 0; i < n; i++)
262 /* If the statistics are in dBm */
263 if(qual[i].level > range.max_qual.level)
264 printf(" %s : Quality %d/%d ; Signal %d dBm ; Noise %d dBm %s\n",
265 pr_ether(hwa[i].sa_data),
266 qual[i].qual, range.max_qual.qual,
267 qual[i].level - 0x100, qual[i].noise - 0x100,
268 qual[i].updated & 0x7 ? "(updated)" : "");
270 printf(" %s : Quality %d/%d ; Signal %d/%d ; Noise %d/%d %s\n",
271 pr_ether(hwa[i].sa_data),
272 qual[i].qual, range.max_qual.qual,
273 qual[i].level, range.max_qual.level,
274 qual[i].noise, range.max_qual.noise,
275 qual[i].updated & 0x7 ? "(updated)" : "");
277 printf(" %s : Quality %d ; Signal %d ; Noise %d %s\n",
278 pr_ether(hwa[i].sa_data),
279 qual[i].qual, qual[i].level, qual[i].noise,
280 qual[i].updated & 0x7 ? "(updated)" : "");
282 printf(" %s\n", pr_ether(hwa[i].sa_data));
287 /*------------------------------------------------------------------*/
289 * Get list of AP on all devices and print it on the screen
292 print_ap_devices(int skfd)
299 /* Get list of active devices */
300 ifc.ifc_len = sizeof(buff);
302 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
304 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
310 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
311 print_ap_info(skfd, ifr->ifr_name);
313 #endif /* WIRELESS_EXT > 5 */
316 /*------------------------------------------------------------------*/
318 * Print the number of available bitrates for the device
321 print_bitrate_info(int skfd,
326 struct iw_range range;
329 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
330 wrq.u.data.pointer = (caddr_t) ⦥
331 wrq.u.data.length = 0;
332 wrq.u.data.flags = 0;
333 if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0)
334 fprintf(stderr, "%-8.8s no bit-rate information.\n\n",
338 if((range.num_bitrates > 0) && (range.num_bitrates < IW_MAX_BITRATES))
340 printf("%-8.8s %d available bit-rates :\n",
341 ifname, range.num_bitrates);
343 for(k = 0; k < range.num_bitrates; k++)
346 bitrate = range.bitrate[k];
348 printf("%g Gb/s\n", bitrate / GIGA);
351 printf("%g Mb/s\n", bitrate / MEGA);
353 printf("%g kb/s\n", bitrate / KILO);
358 printf("%-8.8s No bit-rates ? Please update driver...\n\n", ifname);
362 /*------------------------------------------------------------------*/
364 * Get bit-rate info on all devices and print it on the screen
367 print_bitrate_devices(int skfd)
374 /* Get list of active devices */
375 ifc.ifc_len = sizeof(buff);
377 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
379 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
385 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
386 print_bitrate_info(skfd, ifr->ifr_name);
388 #endif /* WIRELESS_EXT > 7 */
390 /************************* SETTING ROUTINES **************************/
392 /*------------------------------------------------------------------*/
394 * Set list of addresses specified on command line in the driver.
397 set_spy_info(int skfd, /* The socket */
398 char * args[], /* Command line args */
399 int count, /* Args count */
400 char * ifname) /* Dev name */
404 int nbr; /* Number of valid addresses */
405 struct sockaddr hw_address[IW_MAX_SPY];
407 /* Read command line */
408 i = 0; /* first arg to read */
409 nbr = 0; /* Number of args readen so far */
411 /* Check if we have valid address types */
412 if(check_addr_type(skfd, ifname) < 0)
414 fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname);
418 /* "off" : disable functionality (set 0 addresses) */
419 if(!strcmp(args[0], "off"))
420 i = count; /* hack */
422 /* "+" : add all addresses already in the driver */
423 if(!strcmp(args[0], "+"))
425 char buffer[(sizeof(struct iw_quality) +
426 sizeof(struct sockaddr)) * IW_MAX_SPY];
428 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
429 wrq.u.data.pointer = (caddr_t) buffer;
430 wrq.u.data.length = 0;
431 wrq.u.data.flags = 0;
432 if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0)
434 fprintf(stderr, "Interface doesn't accept reading addresses...\n");
435 fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
439 /* Copy old addresses */
440 nbr = wrq.u.data.length;
441 memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
443 i = 1; /* skip the "+" */
446 /* Read other args on command line */
447 while((i < count) && (nbr < IW_MAX_SPY))
449 if(in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
454 /* Check the number of addresses */
455 if((nbr == 0) && strcmp(args[0], "off"))
457 fprintf(stderr, "No valid addresses found : exiting...\n");
461 /* Check if there is some remaining arguments */
464 fprintf(stderr, "Got only the first %d addresses, remaining discarded\n", IW_MAX_SPY);
467 /* Time to do send addresses to the driver */
468 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
469 wrq.u.data.pointer = (caddr_t) hw_address;
470 wrq.u.data.length = nbr;
471 wrq.u.data.flags = 0;
472 if(ioctl(skfd, SIOCSIWSPY, &wrq) < 0)
474 fprintf(stderr, "Interface doesn't accept addresses...\n");
475 fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno));
482 /******************************* MAIN ********************************/
484 /*------------------------------------------------------------------*/
492 int skfd = -1; /* generic raw socket desc. */
495 /* Create a channel to the NET kernel. */
496 if((skfd = sockets_open()) < 0)
502 /* No argument : show the list of all device + info */
505 print_spy_devices(skfd);
510 /* Special cases take one... */
512 if((!strncmp(argv[1], "-h", 9)) ||
513 (!strcmp(argv[1], "--help")))
515 fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n");
516 fprintf(stderr, " interface [freq]\n");
517 fprintf(stderr, " interface [ap]\n");
523 if((!strncmp(argv[1], "freq", 4)) ||
524 (!strncmp(argv[1], "channel", 7)))
526 print_freq_devices(skfd);
532 /* Access Point list */
533 if(!strcasecmp(argv[1], "ap"))
535 print_ap_devices(skfd);
539 #endif /* WIRELESS_EXT > 5 */
543 if((!strncmp(argv[1], "bit", 3)) ||
544 (!strcmp(argv[1], "rate")))
546 print_bitrate_devices(skfd);
550 #endif /* WIRELESS_EXT > 7 */
552 /* The device name must be the first argument */
553 /* Name only : show spy list for that device only */
556 print_spy_info(skfd, argv[1]);
561 /* Special cases take two... */
563 if((!strncmp(argv[2], "freq", 4)) ||
564 (!strncmp(argv[2], "channel", 7)))
566 print_freq_info(skfd, argv[1]);
572 /* Access Point list */
573 if(!strcasecmp(argv[2], "ap"))
575 print_ap_info(skfd, argv[1]);
579 #endif /* WIRELESS_EXT > 5 */
582 /* Access Point list */
583 if((!strncmp(argv[2], "bit", 3)) ||
584 (!strcmp(argv[2], "rate")))
586 print_bitrate_info(skfd, argv[1]);
590 #endif /* WIRELESS_EXT > 7 */
592 /* Otherwise, it's a list of address to set in the spy list */
593 goterr = set_spy_info(skfd, argv + 2, argc - 2, argv[1]);
595 /* Close the socket. */