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++)
153 printf("\t Channel %.2d : ", range.freq[k].i);
154 freq = freq2float(&(range.freq[k]));
156 printf("%g GHz\n", freq / GIGA);
159 printf("%g MHz\n", freq / MEGA);
161 printf("%g kHz\n", freq / KILO);
166 printf("%-8.8s %d channels\n\n",
167 ifname, range.num_channels);
171 /*------------------------------------------------------------------*/
173 * Get frequency info on all devices and print it on the screen
176 print_freq_devices(int skfd)
183 /* Get list of active devices */
184 ifc.ifc_len = sizeof(buff);
186 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
188 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
194 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
195 print_freq_info(skfd, ifr->ifr_name);
198 /*------------------------------------------------------------------*/
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
204 print_ap_info(int skfd,
208 char buffer[(sizeof(struct iw_quality) +
209 sizeof(struct sockaddr)) * IW_MAX_AP];
210 struct sockaddr * hwa;
211 struct iw_quality * qual;
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)
225 fprintf(stderr, "%-8.8s Interface doesn't have a list of Access Points\n\n", ifname);
229 /* Number of addresses */
230 n = wrq.u.data.length;
231 has_qual = wrq.u.data.flags;
234 hwa = (struct sockaddr *) buffer;
235 qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
237 /* Check if we have valid address types */
238 if(check_addr_type(skfd, ifname) < 0)
240 fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname);
244 /* Get range info if we can */
245 if(get_range_info(skfd, ifname, &(range)) >= 0)
250 printf("%-8.8s No Access Point in range\n", ifname);
252 printf("%-8.8s Access Points in range:\n", ifname);
253 for(i = 0; i < n; i++)
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)" : "");
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)" : "");
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)" : "");
277 printf(" %s\n", pr_ether(hwa[i].sa_data));
282 /*------------------------------------------------------------------*/
284 * Get list of AP on all devices and print it on the screen
287 print_ap_devices(int skfd)
294 /* Get list of active devices */
295 ifc.ifc_len = sizeof(buff);
297 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
299 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
305 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
306 print_ap_info(skfd, ifr->ifr_name);
309 /*------------------------------------------------------------------*/
311 * Print the number of available bitrates for the device
314 print_bitrate_info(int skfd,
319 struct iw_range range;
322 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
323 wrq.u.data.pointer = (caddr_t) ⦥
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",
331 if((range.num_bitrates > 0) && (range.num_bitrates < IW_MAX_BITRATES))
333 printf("%-8.8s %d available bit-rates :\n",
334 ifname, range.num_bitrates);
336 for(k = 0; k < range.num_bitrates; k++)
339 bitrate = range.bitrate[k];
341 printf("%g Gb/s\n", bitrate / GIGA);
344 printf("%g Mb/s\n", bitrate / MEGA);
346 printf("%g kb/s\n", bitrate / KILO);
351 printf("%-8.8s No bit-rates ? Please update driver...\n\n", ifname);
355 /*------------------------------------------------------------------*/
357 * Get bit-rate info on all devices and print it on the screen
360 print_bitrate_devices(int skfd)
367 /* Get list of active devices */
368 ifc.ifc_len = sizeof(buff);
370 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
372 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
378 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
379 print_bitrate_info(skfd, ifr->ifr_name);
382 /*------------------------------------------------------------------*/
384 * Print the number of available bitrates for the device
387 print_keys_info(int skfd,
391 struct iw_range range;
392 unsigned char key[IW_ENCODING_TOKEN_MAX];
395 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
396 wrq.u.data.pointer = (caddr_t) ⦥
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",
404 printf("%-8.8s ", ifname);
405 if((range.num_encoding_sizes > 0) &&
406 (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
408 printf("%d key sizes : %d", range.num_encoding_sizes,
409 range.encoding_size[0] * 8);
411 for(k = 1; k < range.num_encoding_sizes; k++)
412 printf(", %d", range.encoding_size[k] * 8);
415 printf("%d keys available :\n", range.max_encoding_tokens);
416 for(k = 1; k <= range.max_encoding_tokens; k++)
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)
424 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
427 if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
428 (wrq.u.data.length == 0))
429 printf("\t\t[%d]: off\n", k);
434 printf("\t\t[%d]: %.2X", k, key[0]);
435 for(i = 1; i < wrq.u.data.length; i++)
439 printf("%.2X", key[i]);
443 printf(" (%d bits)", wrq.u.data.length * 8);
452 /*------------------------------------------------------------------*/
454 * Get bit-rate info on all devices and print it on the screen
457 print_keys_devices(int skfd)
464 /* Get list of active devices */
465 ifc.ifc_len = sizeof(buff);
467 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
469 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
475 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
476 print_keys_info(skfd, ifr->ifr_name);
479 /************************* SETTING ROUTINES **************************/
481 /*------------------------------------------------------------------*/
483 * Set list of addresses specified on command line in the driver.
486 set_spy_info(int skfd, /* The socket */
487 char * args[], /* Command line args */
488 int count, /* Args count */
489 char * ifname) /* Dev name */
493 int nbr; /* Number of valid addresses */
494 struct sockaddr hw_address[IW_MAX_SPY];
496 /* Read command line */
497 i = 0; /* first arg to read */
498 nbr = 0; /* Number of args readen so far */
500 /* Check if we have valid address types */
501 if(check_addr_type(skfd, ifname) < 0)
503 fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname);
507 /* "off" : disable functionality (set 0 addresses) */
508 if(!strcmp(args[0], "off"))
509 i = count; /* hack */
511 /* "+" : add all addresses already in the driver */
512 if(!strcmp(args[0], "+"))
514 char buffer[(sizeof(struct iw_quality) +
515 sizeof(struct sockaddr)) * IW_MAX_SPY];
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)
523 fprintf(stderr, "Interface doesn't accept reading addresses...\n");
524 fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
528 /* Copy old addresses */
529 nbr = wrq.u.data.length;
530 memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
532 i = 1; /* skip the "+" */
535 /* Read other args on command line */
536 while((i < count) && (nbr < IW_MAX_SPY))
538 if(in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
543 /* Check the number of addresses */
544 if((nbr == 0) && strcmp(args[0], "off"))
546 fprintf(stderr, "No valid addresses found : exiting...\n");
550 /* Check if there is some remaining arguments */
553 fprintf(stderr, "Got only the first %d addresses, remaining discarded\n", IW_MAX_SPY);
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)
563 fprintf(stderr, "Interface doesn't accept addresses...\n");
564 fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno));
571 /******************************* MAIN ********************************/
573 /*------------------------------------------------------------------*/
581 int skfd = -1; /* generic raw socket desc. */
584 /* Create a channel to the NET kernel. */
585 if((skfd = sockets_open()) < 0)
591 /* No argument : show the list of all device + info */
594 print_spy_devices(skfd);
599 /* Special cases take one... */
601 if((!strncmp(argv[1], "-h", 9)) ||
602 (!strcmp(argv[1], "--help")))
604 fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n");
605 fprintf(stderr, " interface [freq]\n");
606 fprintf(stderr, " interface [ap]\n");
612 if((!strncmp(argv[1], "freq", 4)) ||
613 (!strncmp(argv[1], "channel", 7)))
615 print_freq_devices(skfd);
620 /* Access Point list */
621 if(!strcasecmp(argv[1], "ap"))
623 print_ap_devices(skfd);
629 if((!strncmp(argv[1], "bit", 3)) ||
630 (!strcmp(argv[1], "rate")))
632 print_bitrate_devices(skfd);
637 /* Encryption key list */
638 if((!strncmp(argv[1], "enc", 3)) ||
639 (!strncmp(argv[1], "key", 3)))
641 print_keys_devices(skfd);
646 /* The device name must be the first argument */
647 /* Name only : show spy list for that device only */
650 print_spy_info(skfd, argv[1]);
655 /* Special cases take two... */
657 if((!strncmp(argv[2], "freq", 4)) ||
658 (!strncmp(argv[2], "channel", 7)))
660 print_freq_info(skfd, argv[1]);
665 /* Access Point list */
666 if(!strcasecmp(argv[2], "ap"))
668 print_ap_info(skfd, argv[1]);
673 /* Access Point list */
674 if((!strncmp(argv[2], "bit", 3)) ||
675 (!strcmp(argv[2], "rate")))
677 print_bitrate_info(skfd, argv[1]);
682 /* Access Point list */
683 if((!strncmp(argv[2], "enc", 3)) ||
684 (!strncmp(argv[2], "key", 3)))
686 print_keys_info(skfd, argv[1]);
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]);
694 /* Close the socket. */