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 "iwlist.c" and "-lm".
10 * This file is released under the GPL license.
11 * Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
14 #include "iwlib.h" /* Header */
16 /*********************** FREQUENCIES/CHANNELS ***********************/
18 /*------------------------------------------------------------------*/
20 * Print the number of channels and available frequency for the device
23 print_freq_info(int skfd,
27 struct iw_range range;
30 if(iw_get_range_info(skfd, ifname, &range) < 0)
31 fprintf(stderr, "%-8.8s no frequency information.\n\n",
35 if(range.num_frequency > 0)
37 printf("%-8.8s %d channels in total; available frequencies :\n",
38 ifname, range.num_channels);
40 for(k = 0; k < range.num_frequency; k++)
42 printf("\t Channel %.2d : ", range.freq[k].i);
43 freq = iw_freq2float(&(range.freq[k]));
45 printf("%g GHz\n", freq / GIGA);
48 printf("%g MHz\n", freq / MEGA);
50 printf("%g kHz\n", freq / KILO);
55 printf("%-8.8s %d channels\n\n",
56 ifname, range.num_channels);
60 /************************ ACCESS POINT LIST ************************/
62 /*------------------------------------------------------------------*/
64 * Display the list of ap addresses and the associated stats
65 * Exacly the same as the spy list, only with different IOCTL and messages
68 print_ap_info(int skfd,
72 char buffer[(sizeof(struct iw_quality) +
73 sizeof(struct sockaddr)) * IW_MAX_AP];
75 struct sockaddr * hwa;
76 struct iw_quality * qual;
84 wrq.u.data.pointer = (caddr_t) buffer;
85 wrq.u.data.length = IW_MAX_AP;
87 if(iw_get_ext(skfd, ifname, 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 mac address type */
102 if(iw_check_mac_addr_type(skfd, ifname) < 0)
104 fprintf(stderr, "%-8.8s Interface doesn't support MAC 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 wrq.u.data.pointer = (caddr_t) key;
216 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
217 wrq.u.data.flags = k;
218 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
220 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
223 if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
224 (wrq.u.data.length == 0))
225 printf("\t\t[%d]: off\n", k);
228 /* Display the key */
229 iw_print_key(buffer, key, wrq.u.data.length, wrq.u.data.flags);
230 printf("\t\t[%d]: %s", k, buffer);
233 printf(" (%d bits)", wrq.u.data.length * 8);
237 /* Print current key and mode */
238 wrq.u.data.pointer = (caddr_t) key;
239 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
240 wrq.u.data.flags = 0; /* Set index to zero to get current */
241 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
243 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
246 printf(" Current Transmit Key: [%d]\n",
247 wrq.u.data.flags & IW_ENCODE_INDEX);
248 if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
249 printf(" Encryption mode:restricted\n");
250 if(wrq.u.data.flags & IW_ENCODE_OPEN)
251 printf(" Encryption mode:open\n");
257 /************************* POWER MANAGEMENT *************************/
259 /*------------------------------------------------------------------*/
261 * Print Power Management info for each device
264 get_pm_value(int skfd,
270 /* Get Another Power Management value */
271 pwrq->u.power.flags = flags;
272 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
274 /* Let's check the value and its type */
275 if(pwrq->u.power.flags & IW_POWER_TYPE)
277 iw_print_pm_value(buffer, pwrq->u.power.value, pwrq->u.power.flags);
278 printf("\n %s", buffer);
281 return(pwrq->u.power.flags);
284 /*------------------------------------------------------------------*/
286 * Print Power Management info for each device
289 print_pm_info(int skfd,
293 struct iw_range range;
296 /* Extract range info */
297 if(iw_get_range_info(skfd, ifname, &range) < 0)
298 fprintf(stderr, "%-8.8s no power management information.\n\n",
302 printf("%-8.8s ", ifname);
304 /* Display modes availables */
305 if(range.pm_capa & IW_POWER_MODE)
307 printf("Supported modes :\n ");
308 if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
309 printf("\t\to Receive all packets (unicast & multicast)\n ");
310 if(range.pm_capa & IW_POWER_UNICAST_R)
311 printf("\t\to Receive Unicast only (discard multicast)\n ");
312 if(range.pm_capa & IW_POWER_MULTICAST_R)
313 printf("\t\to Receive Multicast only (discard unicast)\n ");
314 if(range.pm_capa & IW_POWER_FORCE_S)
315 printf("\t\to Force sending using Power Management\n ");
316 if(range.pm_capa & IW_POWER_REPEATER)
317 printf("\t\to Repeat multicast\n ");
319 /* Display min/max period availables */
320 if(range.pmp_flags & IW_POWER_PERIOD)
322 int flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
323 /* Display if auto or fixed */
324 if(range.pmp_flags & IW_POWER_MIN)
325 printf("Auto period ; ");
327 printf("Fixed period ; ");
328 /* Print the range */
329 iw_print_pm_value(buffer, range.min_pmp, flags | IW_POWER_MIN);
330 printf("%s\n ", buffer);
331 iw_print_pm_value(buffer, range.max_pmp, flags | IW_POWER_MAX);
332 printf("%s\n ", buffer);
335 /* Display min/max timeout availables */
336 if(range.pmt_flags & IW_POWER_TIMEOUT)
338 int flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
339 /* Display if auto or fixed */
340 if(range.pmt_flags & IW_POWER_MIN)
341 printf("Auto timeout ; ");
343 printf("Fixed timeout ; ");
344 /* Print the range */
345 iw_print_pm_value(buffer, range.min_pmt, flags | IW_POWER_MIN);
346 printf("%s\n ", buffer);
347 iw_print_pm_value(buffer, range.max_pmt, flags | IW_POWER_MAX);
348 printf("%s\n ", buffer);
351 #endif /* WIRELESS_EXT > 9 */
353 /* Get current Power Management settings */
354 wrq.u.power.flags = 0;
355 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
357 int flags = wrq.u.power.flags;
359 /* Is it disabled ? */
360 if(wrq.u.power.disabled)
361 printf("Current mode:off\n ");
366 /* Let's check the mode */
367 iw_print_pm_mode(buffer, flags);
368 printf("Current%s", buffer);
370 /* Let's check if nothing (simply on) */
371 if((flags & IW_POWER_MODE) == IW_POWER_ON)
375 /* Let's check the value and its type */
376 if(wrq.u.power.flags & IW_POWER_TYPE)
378 iw_print_pm_value(buffer,
379 wrq.u.power.value, wrq.u.power.flags);
380 printf("%s", buffer);
383 /* If we have been returned a MIN value, ask for the MAX */
384 if(flags & IW_POWER_MIN)
385 pm_mask = IW_POWER_MAX;
386 /* If we have been returned a MAX value, ask for the MIN */
387 if(flags & IW_POWER_MAX)
388 pm_mask = IW_POWER_MIN;
389 /* If we have something to ask for... */
391 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
394 /* And if we have both a period and a timeout, ask the other */
395 pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
399 int base_mask = pm_mask;
400 flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
403 /* If we have been returned a MIN value, ask for the MAX */
404 if(flags & IW_POWER_MIN)
405 pm_mask = IW_POWER_MAX | base_mask;
406 /* If we have been returned a MAX value, ask for the MIN */
407 if(flags & IW_POWER_MAX)
408 pm_mask = IW_POWER_MIN | base_mask;
409 /* If we have something to ask for... */
411 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
413 #endif /* WIRELESS_EXT > 9 */
420 /************************** TRANSMIT POWER **************************/
422 /*------------------------------------------------------------------*/
424 * Print the number of available transmit powers for the device
427 print_txpower_info(int skfd,
430 struct iw_range range;
436 /* Extract range info */
437 if(iw_get_range_info(skfd, ifname, &range) < 0)
438 fprintf(stderr, "%-8.8s no transmit-power information.\n\n",
442 if((range.num_txpower > 0) && (range.num_txpower < IW_MAX_TXPOWER))
444 printf("%-8.8s %d available transmit-powers :\n",
445 ifname, range.num_txpower);
447 for(k = 0; k < range.num_txpower; k++)
449 if(range.txpower_capa & IW_TXPOW_MWATT)
451 dbm = iw_mwatt2dbm(range.txpower[k]);
452 mwatt = range.txpower[k];
456 dbm = range.txpower[k];
457 mwatt = iw_dbm2mwatt(range.txpower[k]);
459 printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
464 printf("%-8.8s No transmit-powers ? Please update driver...\n\n", ifname);
466 #endif /* WIRELESS_EXT > 9 */
469 /*********************** RETRY LIMIT/LIFETIME ***********************/
471 #if WIRELESS_EXT > 10
472 /*------------------------------------------------------------------*/
474 * Print one retry value
477 get_retry_value(int skfd,
483 /* Get Another retry value */
484 pwrq->u.retry.flags = flags;
485 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
487 /* Let's check the value and its type */
488 if(pwrq->u.retry.flags & IW_RETRY_TYPE)
490 iw_print_retry_value(buffer,
491 pwrq->u.retry.value, pwrq->u.retry.flags);
492 printf("%s\n ", buffer);
495 return(pwrq->u.retry.flags);
498 /*------------------------------------------------------------------*/
500 * Print Retry info for each device
503 print_retry_info(int skfd,
507 struct iw_range range;
510 /* Extract range info */
511 if(iw_get_range_info(skfd, ifname, &range) < 0)
512 fprintf(stderr, "%-8.8s no retry limit/lifetime information.\n\n",
516 printf("%-8.8s ", ifname);
518 /* Display min/max limit availables */
519 if(range.retry_flags & IW_RETRY_LIMIT)
521 int flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
522 /* Display if auto or fixed */
523 if(range.retry_flags & IW_RETRY_MIN)
524 printf("Auto limit ; ");
526 printf("Fixed limit ; ");
527 /* Print the range */
528 iw_print_retry_value(buffer, range.min_retry, flags | IW_RETRY_MIN);
529 printf("%s\n ", buffer);
530 iw_print_retry_value(buffer, range.max_retry, flags | IW_RETRY_MAX);
531 printf("%s\n ", buffer);
534 /* Display min/max lifetime availables */
535 if(range.r_time_flags & IW_RETRY_LIFETIME)
537 int flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
538 /* Display if auto or fixed */
539 if(range.r_time_flags & IW_RETRY_MIN)
540 printf("Auto lifetime ; ");
542 printf("Fixed lifetime ; ");
543 /* Print the range */
544 iw_print_retry_value(buffer, range.min_r_time, flags | IW_RETRY_MIN);
545 printf("%s\n ", buffer);
546 iw_print_retry_value(buffer, range.max_r_time, flags | IW_RETRY_MAX);
547 printf("%s\n ", buffer);
551 /* Get current retry settings */
552 wrq.u.retry.flags = 0;
553 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
555 int flags = wrq.u.retry.flags;
557 /* Is it disabled ? */
558 if(wrq.u.retry.disabled)
559 printf("Current mode:off\n ");
564 /* Let's check the mode */
565 printf("Current mode:on\n ");
567 /* Let's check the value and its type */
568 if(wrq.u.retry.flags & IW_RETRY_TYPE)
570 iw_print_retry_value(buffer,
571 wrq.u.retry.value, wrq.u.retry.flags);
572 printf("%s", buffer);
575 /* If we have been returned a MIN value, ask for the MAX */
576 if(flags & IW_RETRY_MIN)
577 retry_mask = IW_RETRY_MAX;
578 /* If we have been returned a MAX value, ask for the MIN */
579 if(flags & IW_RETRY_MAX)
580 retry_mask = IW_RETRY_MIN;
581 /* If we have something to ask for... */
583 get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
585 /* And if we have both a period and a timeout, ask the other */
586 retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
590 int base_mask = retry_mask;
591 flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
595 /* If we have been returned a MIN value, ask for the MAX */
596 if(flags & IW_RETRY_MIN)
597 retry_mask = IW_RETRY_MAX | base_mask;
598 /* If we have been returned a MAX value, ask for the MIN */
599 if(flags & IW_RETRY_MAX)
600 retry_mask = IW_RETRY_MIN | base_mask;
601 /* If we have something to ask for... */
603 get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
611 #endif /* WIRELESS_EXT > 10 */
613 /************************* COMMON UTILITIES *************************/
615 * This section was written by Michael Tokarev <mjt@tls.msk.ru>
618 /*------------------------------------------------------------------*/
620 * Enumerate devices and call specified routine
623 enum_devices(int skfd, void (*fn)(int skfd, char *ifname))
630 /* Get list of active devices */
631 ifc.ifc_len = sizeof(buff);
633 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
635 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
641 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
642 (*fn)(skfd, ifr->ifr_name);
646 typedef struct iwlist_entry {
648 void (*fn)(int skfd, char *ifname);
651 static const struct iwlist_entry iwlist_cmds[] = {
652 { "frequency", print_freq_info },
653 { "channel", print_freq_info },
654 { "ap", print_ap_info },
655 { "accesspoints", print_ap_info },
656 { "bitrate", print_bitrate_info },
657 { "rate", print_bitrate_info },
658 { "encryption", print_keys_info },
659 { "key", print_keys_info },
660 { "power", print_pm_info },
661 { "txpower", print_txpower_info },
662 #if WIRELESS_EXT > 10
663 { "retry", print_retry_info },
669 static void usage(FILE *f)
672 for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
673 fprintf(f, "%s [interface] %s\n",
679 /******************************* MAIN ********************************/
681 /*------------------------------------------------------------------*/
689 int skfd = -1; /* generic raw socket desc. */
690 char *dev; /* device name */
691 char *cmd; /* command */
694 if(argc == 1 || argc > 3)
699 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
717 int found = -1, ambig = 0;
718 int len = strlen(cmd);
719 for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
721 if (strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
723 if (len == strlen(iwlist_cmds[i].cmd)) /* exact match */
731 else if (iwlist_cmds[i].fn != iwlist_cmds[found].fn)
736 fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
741 fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
747 /* Create a channel to the NET kernel. */
748 if((skfd = iw_sockets_open()) < 0)
754 /* do the actual work */
756 (*iwlist_cmds[i].fn)(skfd, dev);
758 enum_devices(skfd, iwlist_cmds[i].fn);
760 /* Close the socket. */