4 * Jean II - HPLB '99 - HPL 99->01
6 * This tool can access various piece of information on the card
7 * not part of iwconfig...
8 * You need to link this code against "iwcommon.c" and "-lm".
10 * This file is released under the GPL license.
13 #include "iwlib.h" /* Header */
15 /*********************** FREQUENCIES/CHANNELS ***********************/
17 /*------------------------------------------------------------------*/
19 * Print the number of channels and available frequency for the device
22 print_freq_info(int skfd,
26 struct iw_range range;
29 if(iw_get_range_info(skfd, ifname, &range) < 0)
30 fprintf(stderr, "%-8.8s no frequency information.\n\n",
34 if(range.num_frequency > 0)
36 printf("%-8.8s %d channels in total; available frequencies :\n",
37 ifname, range.num_channels);
39 for(k = 0; k < range.num_frequency; k++)
41 printf("\t Channel %.2d : ", range.freq[k].i);
42 freq = iw_freq2float(&(range.freq[k]));
44 printf("%g GHz\n", freq / GIGA);
47 printf("%g MHz\n", freq / MEGA);
49 printf("%g kHz\n", freq / KILO);
54 printf("%-8.8s %d channels\n\n",
55 ifname, range.num_channels);
59 /************************ ACCESS POINT LIST ************************/
61 /*------------------------------------------------------------------*/
63 * Display the list of ap addresses and the associated stats
64 * Exacly the same as the spy list, only with different IOCTL and messages
67 print_ap_info(int skfd,
71 char buffer[(sizeof(struct iw_quality) +
72 sizeof(struct sockaddr)) * IW_MAX_AP];
74 struct sockaddr * hwa;
75 struct iw_quality * qual;
83 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
84 wrq.u.data.pointer = (caddr_t) buffer;
85 wrq.u.data.length = 0;
87 if(ioctl(skfd, SIOCGIWAPLIST, &wrq) < 0)
89 fprintf(stderr, "%-8.8s Interface doesn't have a list of Access Points\n\n", ifname);
93 /* Number of addresses */
94 n = wrq.u.data.length;
95 has_qual = wrq.u.data.flags;
98 hwa = (struct sockaddr *) buffer;
99 qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
101 /* Check if we have valid address types */
102 if(iw_check_addr_type(skfd, ifname) < 0)
104 fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname);
108 /* Get range info if we can */
109 if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
114 printf("%-8.8s No Access Point in range\n", ifname);
116 printf("%-8.8s Access Points in range:\n", ifname);
117 for(i = 0; i < n; i++)
121 /* Print stats for this address */
122 printf(" %s : ", iw_pr_ether(temp, hwa[i].sa_data));
123 iw_print_stats(temp, &qual[i], &range, has_range);
124 printf("%s\n", temp);
127 /* Only print the address */
128 printf(" %s\n", iw_pr_ether(temp, hwa[i].sa_data));
133 /***************************** BITRATES *****************************/
135 /*------------------------------------------------------------------*/
137 * Print the number of available bitrates for the device
140 print_bitrate_info(int skfd,
144 struct iw_range range;
147 /* Extract range info */
148 if(iw_get_range_info(skfd, ifname, &range) < 0)
149 fprintf(stderr, "%-8.8s no bit-rate information.\n\n",
153 if((range.num_bitrates > 0) && (range.num_bitrates < IW_MAX_BITRATES))
155 printf("%-8.8s %d available bit-rates :\n",
156 ifname, range.num_bitrates);
158 for(k = 0; k < range.num_bitrates; k++)
161 bitrate = range.bitrate[k];
163 printf("%g Gb/s\n", bitrate / GIGA);
166 printf("%g Mb/s\n", bitrate / MEGA);
168 printf("%g kb/s\n", bitrate / KILO);
173 printf("%-8.8s No bit-rates ? Please update driver...\n\n", ifname);
177 /************************* ENCRYPTION KEYS *************************/
179 /*------------------------------------------------------------------*/
181 * Print the number of available encryption key for the device
184 print_keys_info(int skfd,
188 struct iw_range range;
189 unsigned char key[IW_ENCODING_TOKEN_MAX];
193 /* Extract range info */
194 if(iw_get_range_info(skfd, ifname, &range) < 0)
195 fprintf(stderr, "%-8.8s no encryption keys information.\n\n",
199 printf("%-8.8s ", ifname);
200 /* Print key sizes */
201 if((range.num_encoding_sizes > 0) &&
202 (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
204 printf("%d key sizes : %d", range.num_encoding_sizes,
205 range.encoding_size[0] * 8);
207 for(k = 1; k < range.num_encoding_sizes; k++)
208 printf(", %d", range.encoding_size[k] * 8);
211 /* Print the keys and associate mode */
212 printf("%d keys available :\n", range.max_encoding_tokens);
213 for(k = 1; k <= range.max_encoding_tokens; k++)
215 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
216 wrq.u.data.pointer = (caddr_t) key;
217 wrq.u.data.length = 0;
218 wrq.u.data.flags = k;
219 if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
221 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
224 if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
225 (wrq.u.data.length == 0))
226 printf("\t\t[%d]: off\n", k);
229 /* Display the key */
230 iw_print_key(buffer, key, wrq.u.data.length, wrq.u.data.flags);
231 printf("\t\t[%d]: %s", k, buffer);
234 printf(" (%d bits)", wrq.u.data.length * 8);
238 /* Print current key and mode */
239 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
240 wrq.u.data.pointer = (caddr_t) key;
241 wrq.u.data.length = 0;
242 wrq.u.data.flags = 0; /* Set index to zero to get current */
243 if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
245 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
248 printf(" Current Transmit Key: [%d]\n",
249 wrq.u.data.flags & IW_ENCODE_INDEX);
250 if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
251 printf(" Encryption mode:restricted\n");
252 if(wrq.u.data.flags & IW_ENCODE_OPEN)
253 printf(" Encryption mode:open\n");
259 /************************* POWER MANAGEMENT *************************/
261 /*------------------------------------------------------------------*/
263 * Print Power Management info for each device
266 get_pm_value(int skfd,
272 /* Get Another Power Management value */
273 strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
274 pwrq->u.power.flags = flags;
275 if(ioctl(skfd, SIOCGIWPOWER, pwrq) >= 0)
277 /* Let's check the value and its type */
278 if(pwrq->u.power.flags & IW_POWER_TYPE)
280 iw_print_pm_value(buffer, pwrq->u.power.value, pwrq->u.power.flags);
281 printf("\n %s", buffer);
284 return(pwrq->u.power.flags);
287 /*------------------------------------------------------------------*/
289 * Print Power Management info for each device
292 print_pm_info(int skfd,
296 struct iw_range range;
299 /* Extract range info */
300 if(iw_get_range_info(skfd, ifname, &range) < 0)
301 fprintf(stderr, "%-8.8s no power management information.\n\n",
305 printf("%-8.8s ", ifname);
307 /* Display modes availables */
308 if(range.pm_capa & IW_POWER_MODE)
310 printf("Supported modes :\n ");
311 if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
312 printf("\t\to Receive all packets (unicast & multicast)\n ");
313 if(range.pm_capa & IW_POWER_UNICAST_R)
314 printf("\t\to Receive Unicast only (discard multicast)\n ");
315 if(range.pm_capa & IW_POWER_MULTICAST_R)
316 printf("\t\to Receive Multicast only (discard unicast)\n ");
317 if(range.pm_capa & IW_POWER_FORCE_S)
318 printf("\t\to Force sending using Power Management\n ");
319 if(range.pm_capa & IW_POWER_REPEATER)
320 printf("\t\to Repeat multicast\n ");
322 /* Display min/max period availables */
323 if(range.pmp_flags & IW_POWER_PERIOD)
325 int flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
326 /* Display if auto or fixed */
327 if(range.pmp_flags & IW_POWER_MIN)
328 printf("Auto period ; ");
330 printf("Fixed period ; ");
331 /* Print the range */
332 iw_print_pm_value(buffer, range.min_pmp, flags | IW_POWER_MIN);
333 printf("%s\n ", buffer);
334 iw_print_pm_value(buffer, range.max_pmp, flags | IW_POWER_MAX);
335 printf("%s\n ", buffer);
338 /* Display min/max timeout availables */
339 if(range.pmt_flags & IW_POWER_TIMEOUT)
341 int flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
342 /* Display if auto or fixed */
343 if(range.pmt_flags & IW_POWER_MIN)
344 printf("Auto timeout ; ");
346 printf("Fixed timeout ; ");
347 /* Print the range */
348 iw_print_pm_value(buffer, range.min_pmt, flags | IW_POWER_MIN);
349 printf("%s\n ", buffer);
350 iw_print_pm_value(buffer, range.max_pmt, flags | IW_POWER_MAX);
351 printf("%s\n ", buffer);
354 #endif /* WIRELESS_EXT > 9 */
356 /* Get current Power Management settings */
357 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
358 wrq.u.power.flags = 0;
359 if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0)
361 int flags = wrq.u.power.flags;
363 /* Is it disabled ? */
364 if(wrq.u.power.disabled)
365 printf("Current mode:off\n ");
370 /* Let's check the mode */
371 iw_print_pm_mode(buffer, flags);
372 printf("Current%s", buffer);
374 /* Let's check if nothing (simply on) */
375 if((flags & IW_POWER_MODE) == IW_POWER_ON)
379 /* Let's check the value and its type */
380 if(wrq.u.power.flags & IW_POWER_TYPE)
382 iw_print_pm_value(buffer,
383 wrq.u.power.value, wrq.u.power.flags);
384 printf("%s", buffer);
387 /* If we have been returned a MIN value, ask for the MAX */
388 if(flags & IW_POWER_MIN)
389 pm_mask = IW_POWER_MAX;
390 /* If we have been returned a MAX value, ask for the MIN */
391 if(flags & IW_POWER_MAX)
392 pm_mask = IW_POWER_MIN;
393 /* If we have something to ask for... */
395 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
398 /* And if we have both a period and a timeout, ask the other */
399 pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
403 int base_mask = pm_mask;
404 flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
407 /* If we have been returned a MIN value, ask for the MAX */
408 if(flags & IW_POWER_MIN)
409 pm_mask = IW_POWER_MAX | base_mask;
410 /* If we have been returned a MAX value, ask for the MIN */
411 if(flags & IW_POWER_MAX)
412 pm_mask = IW_POWER_MIN | base_mask;
413 /* If we have something to ask for... */
415 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
417 #endif /* WIRELESS_EXT > 9 */
424 /************************** TRANSMIT POWER **************************/
426 /*------------------------------------------------------------------*/
428 * Print the number of available transmit powers for the device
431 print_txpower_info(int skfd,
434 struct iw_range range;
440 /* Extract range info */
441 if(iw_get_range_info(skfd, ifname, &range) < 0)
442 fprintf(stderr, "%-8.8s no transmit-power information.\n\n",
446 if((range.num_txpower > 0) && (range.num_txpower < IW_MAX_TXPOWER))
448 printf("%-8.8s %d available transmit-powers :\n",
449 ifname, range.num_txpower);
451 for(k = 0; k < range.num_txpower; k++)
453 if(range.txpower_capa & IW_TXPOW_MWATT)
455 dbm = iw_mwatt2dbm(range.txpower[k]);
456 mwatt = range.txpower[k];
460 dbm = range.txpower[k];
461 mwatt = iw_dbm2mwatt(range.txpower[k]);
463 printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
468 printf("%-8.8s No transmit-powers ? Please update driver...\n\n", ifname);
470 #endif /* WIRELESS_EXT > 9 */
473 /*********************** RETRY LIMIT/LIFETIME ***********************/
475 #if WIRELESS_EXT > 10
476 /*------------------------------------------------------------------*/
478 * Print one retry value
481 get_retry_value(int skfd,
487 /* Get Another retry value */
488 strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
489 pwrq->u.retry.flags = flags;
490 if(ioctl(skfd, SIOCGIWRETRY, pwrq) >= 0)
492 /* Let's check the value and its type */
493 if(pwrq->u.retry.flags & IW_RETRY_TYPE)
495 iw_print_retry_value(buffer,
496 pwrq->u.retry.value, pwrq->u.retry.flags);
497 printf("%s\n ", buffer);
500 return(pwrq->u.retry.flags);
503 /*------------------------------------------------------------------*/
505 * Print Retry info for each device
508 print_retry_info(int skfd,
512 struct iw_range range;
515 /* Extract range info */
516 if(iw_get_range_info(skfd, ifname, &range) < 0)
517 fprintf(stderr, "%-8.8s no retry limit/lifetime information.\n\n",
521 printf("%-8.8s ", ifname);
523 /* Display min/max limit availables */
524 if(range.retry_flags & IW_RETRY_LIMIT)
526 int flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
527 /* Display if auto or fixed */
528 if(range.retry_flags & IW_RETRY_MIN)
529 printf("Auto limit ; ");
531 printf("Fixed limit ; ");
532 /* Print the range */
533 iw_print_retry_value(buffer, range.min_retry, flags | IW_RETRY_MIN);
534 printf("%s\n ", buffer);
535 iw_print_retry_value(buffer, range.max_retry, flags | IW_RETRY_MAX);
536 printf("%s\n ", buffer);
539 /* Display min/max lifetime availables */
540 if(range.r_time_flags & IW_RETRY_LIFETIME)
542 int flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
543 /* Display if auto or fixed */
544 if(range.r_time_flags & IW_RETRY_MIN)
545 printf("Auto lifetime ; ");
547 printf("Fixed lifetime ; ");
548 /* Print the range */
549 iw_print_retry_value(buffer, range.min_r_time, flags | IW_RETRY_MIN);
550 printf("%s\n ", buffer);
551 iw_print_retry_value(buffer, range.max_r_time, flags | IW_RETRY_MAX);
552 printf("%s\n ", buffer);
556 /* Get current retry settings */
557 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
558 wrq.u.retry.flags = 0;
559 if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0)
561 int flags = wrq.u.retry.flags;
563 /* Is it disabled ? */
564 if(wrq.u.retry.disabled)
565 printf("Current mode:off\n ");
570 /* Let's check the mode */
571 printf("Current mode:on\n ");
573 /* Let's check the value and its type */
574 if(wrq.u.retry.flags & IW_RETRY_TYPE)
576 iw_print_retry_value(buffer,
577 wrq.u.retry.value, wrq.u.retry.flags);
578 printf("%s", buffer);
581 /* If we have been returned a MIN value, ask for the MAX */
582 if(flags & IW_RETRY_MIN)
583 retry_mask = IW_RETRY_MAX;
584 /* If we have been returned a MAX value, ask for the MIN */
585 if(flags & IW_RETRY_MAX)
586 retry_mask = IW_RETRY_MIN;
587 /* If we have something to ask for... */
589 get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
591 /* And if we have both a period and a timeout, ask the other */
592 retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
596 int base_mask = retry_mask;
597 flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
601 /* If we have been returned a MIN value, ask for the MAX */
602 if(flags & IW_RETRY_MIN)
603 retry_mask = IW_RETRY_MAX | base_mask;
604 /* If we have been returned a MAX value, ask for the MIN */
605 if(flags & IW_RETRY_MAX)
606 retry_mask = IW_RETRY_MIN | base_mask;
607 /* If we have something to ask for... */
609 get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
617 #endif /* WIRELESS_EXT > 10 */
619 /************************* COMMON UTILITIES *************************/
621 * This section was written by Michael Tokarev <mjt@tls.msk.ru>
624 /*------------------------------------------------------------------*/
626 * Enumerate devices and call specified routine
629 enum_devices(int skfd, void (*fn)(int skfd, char *ifname))
636 /* Get list of active devices */
637 ifc.ifc_len = sizeof(buff);
639 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
641 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
647 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
648 (*fn)(skfd, ifr->ifr_name);
652 typedef struct iwlist_entry {
654 void (*fn)(int skfd, char *ifname);
657 static const struct iwlist_entry iwlist_cmds[] = {
658 { "frequency", print_freq_info },
659 { "channel", print_freq_info },
660 { "ap", print_ap_info },
661 { "accesspoints", print_ap_info },
662 { "bitrate", print_bitrate_info },
663 { "rate", print_bitrate_info },
664 { "encription", print_keys_info },
665 { "key", print_keys_info },
666 { "power", print_pm_info },
667 { "txpower", print_txpower_info },
668 #if WIRELESS_EXT > 10
669 { "retry", print_retry_info },
675 static void usage(FILE *f)
678 for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
679 fprintf(f, "%s [interface] %s\n",
685 /******************************* MAIN ********************************/
687 /*------------------------------------------------------------------*/
695 int skfd = -1; /* generic raw socket desc. */
696 char *dev; /* device name */
697 char *cmd; /* command */
700 if(argc == 1 || argc > 3)
705 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
723 int found = -1, ambig = 0;
724 int len = strlen(cmd);
725 for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
727 if (strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
729 if (len == strlen(iwlist_cmds[i].cmd)) /* exact match */
737 else if (iwlist_cmds[i].fn != iwlist_cmds[found].fn)
742 fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
747 fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
753 /* Create a channel to the NET kernel. */
754 if((skfd = iw_sockets_open()) < 0)
760 /* do the actual work */
762 (*iwlist_cmds[i].fn)(skfd, dev);
764 enum_devices(skfd, iwlist_cmds[i].fn);
766 /* Close the socket. */