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 */
17 /*********************** FREQUENCIES/CHANNELS ***********************/
19 /*------------------------------------------------------------------*/
21 * Print the number of channels and available frequency for the device
24 print_freq_info(int skfd,
26 char * args[], /* Command line args */
27 int count) /* Args count */
30 struct iw_range range;
34 char buffer[128]; /* Temporary buffer */
36 /* Avoid "Unused parameter" warning */
37 args = args; count = count;
39 /* Get list of frequencies / channels */
40 if(iw_get_range_info(skfd, ifname, &range) < 0)
41 fprintf(stderr, "%-8.8s no frequency information.\n\n",
45 if(range.num_frequency > 0)
47 printf("%-8.8s %d channels in total; available frequencies :\n",
48 ifname, range.num_channels);
50 for(k = 0; k < range.num_frequency; k++)
52 printf(" Channel %.2d : ", range.freq[k].i);
53 freq = iw_freq2float(&(range.freq[k]));
55 printf("%g GHz\n", freq / GIGA);
58 printf("%g MHz\n", freq / MEGA);
60 printf("%g kHz\n", freq / KILO);
64 printf("%-8.8s %d channels\n",
65 ifname, range.num_channels);
67 /* Get current frequency / channel and display it */
68 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
70 freq = iw_freq2float(&(wrq.u.freq));
71 iw_print_freq(buffer, freq);
72 channel = iw_freq_to_channel(freq, &range);
74 printf(" Current %s (channel %.2d)\n\n", buffer, channel);
76 printf(" Current %s\n\n", buffer);
82 /************************ ACCESS POINT LIST ************************/
84 * Note : now that we have scanning support, this is depracted and
85 * won't survive long. Actually, next version it's out !
88 /*------------------------------------------------------------------*/
90 * Display the list of ap addresses and the associated stats
91 * Exacly the same as the spy list, only with different IOCTL and messages
94 print_ap_info(int skfd,
96 char * args[], /* Command line args */
97 int count) /* Args count */
100 char buffer[(sizeof(struct iw_quality) +
101 sizeof(struct sockaddr)) * IW_MAX_AP];
103 struct sockaddr * hwa;
104 struct iw_quality * qual;
111 /* Avoid "Unused parameter" warning */
112 args = args; count = count;
115 wrq.u.data.pointer = (caddr_t) buffer;
116 wrq.u.data.length = IW_MAX_AP;
117 wrq.u.data.flags = 0;
118 if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
120 fprintf(stderr, "%-8.8s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
124 /* Number of addresses */
125 n = wrq.u.data.length;
126 has_qual = wrq.u.data.flags;
129 hwa = (struct sockaddr *) buffer;
130 qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
132 /* Check if we have valid mac address type */
133 if(iw_check_mac_addr_type(skfd, ifname) < 0)
135 fprintf(stderr, "%-8.8s Interface doesn't support MAC addresses\n\n", ifname);
139 /* Get range info if we can */
140 if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
145 printf("%-8.8s No Peers/Access-Point in range\n", ifname);
147 printf("%-8.8s Peers/Access-Points in range:\n", ifname);
148 for(i = 0; i < n; i++)
152 /* Print stats for this address */
153 printf(" %s : ", iw_pr_ether(temp, hwa[i].sa_data));
154 iw_print_stats(temp, &qual[i], &range, has_range);
155 printf("%s\n", temp);
158 /* Only print the address */
159 printf(" %s\n", iw_pr_ether(temp, hwa[i].sa_data));
165 /***************************** BITRATES *****************************/
167 /*------------------------------------------------------------------*/
169 * Print the number of available bitrates for the device
172 print_bitrate_info(int skfd,
174 char * args[], /* Command line args */
175 int count) /* Args count */
178 struct iw_range range;
182 /* Avoid "Unused parameter" warning */
183 args = args; count = count;
185 /* Extract range info */
186 if(iw_get_range_info(skfd, ifname, &range) < 0)
187 fprintf(stderr, "%-8.8s no bit-rate information.\n\n",
191 if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
193 printf("%-8.8s %d available bit-rates :\n",
194 ifname, range.num_bitrates);
196 for(k = 0; k < range.num_bitrates; k++)
198 iw_print_bitrate(buffer, range.bitrate[k]);
199 /* Maybe this should be %10s */
200 printf("\t %s\n", buffer);
204 printf("%-8.8s No bit-rates ? Please update driver...\n", ifname);
206 /* Get current bit rate */
207 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
209 iw_print_bitrate(buffer, wrq.u.bitrate.value);
210 printf(" Current Bit Rate%c%s\n\n",
211 (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
217 /************************* ENCRYPTION KEYS *************************/
219 /*------------------------------------------------------------------*/
221 * Print the number of available encryption key for the device
224 print_keys_info(int skfd,
226 char * args[], /* Command line args */
227 int count) /* Args count */
230 struct iw_range range;
231 unsigned char key[IW_ENCODING_TOKEN_MAX];
235 /* Avoid "Unused parameter" warning */
236 args = args; count = count;
238 /* Extract range info */
239 if(iw_get_range_info(skfd, ifname, &range) < 0)
240 fprintf(stderr, "%-8.8s no encryption keys information.\n\n",
244 printf("%-8.8s ", ifname);
245 /* Print key sizes */
246 if((range.num_encoding_sizes > 0) &&
247 (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
249 printf("%d key sizes : %d", range.num_encoding_sizes,
250 range.encoding_size[0] * 8);
252 for(k = 1; k < range.num_encoding_sizes; k++)
253 printf(", %d", range.encoding_size[k] * 8);
256 /* Print the keys and associate mode */
257 printf("%d keys available :\n", range.max_encoding_tokens);
258 for(k = 1; k <= range.max_encoding_tokens; k++)
260 wrq.u.data.pointer = (caddr_t) key;
261 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
262 wrq.u.data.flags = k;
263 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
265 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
268 if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
269 (wrq.u.data.length == 0))
270 printf("\t\t[%d]: off\n", k);
273 /* Display the key */
274 iw_print_key(buffer, key, wrq.u.data.length, wrq.u.data.flags);
275 printf("\t\t[%d]: %s", k, buffer);
278 printf(" (%d bits)", wrq.u.data.length * 8);
282 /* Print current key and mode */
283 wrq.u.data.pointer = (caddr_t) key;
284 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
285 wrq.u.data.flags = 0; /* Set index to zero to get current */
286 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
288 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
291 printf(" Current Transmit Key: [%d]\n",
292 wrq.u.data.flags & IW_ENCODE_INDEX);
293 if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
294 printf(" Security mode:restricted\n");
295 if(wrq.u.data.flags & IW_ENCODE_OPEN)
296 printf(" Security mode:open\n");
303 /************************* POWER MANAGEMENT *************************/
305 /*------------------------------------------------------------------*/
307 * Print Power Management info for each device
310 get_pm_value(int skfd,
316 /* Get Another Power Management value */
317 pwrq->u.power.flags = flags;
318 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
320 /* Let's check the value and its type */
321 if(pwrq->u.power.flags & IW_POWER_TYPE)
323 iw_print_pm_value(buffer, pwrq->u.power.value, pwrq->u.power.flags);
324 printf("\n %s", buffer);
327 return(pwrq->u.power.flags);
330 /*------------------------------------------------------------------*/
332 * Print Power Management info for each device
335 print_pm_info(int skfd,
337 char * args[], /* Command line args */
338 int count) /* Args count */
341 struct iw_range range;
344 /* Avoid "Unused parameter" warning */
345 args = args; count = count;
347 /* Extract range info */
348 if(iw_get_range_info(skfd, ifname, &range) < 0)
349 fprintf(stderr, "%-8.8s no power management information.\n\n",
353 printf("%-8.8s ", ifname);
355 /* Display modes availables */
356 if(range.pm_capa & IW_POWER_MODE)
358 printf("Supported modes :\n ");
359 if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
360 printf("\t\to Receive all packets (unicast & multicast)\n ");
361 if(range.pm_capa & IW_POWER_UNICAST_R)
362 printf("\t\to Receive Unicast only (discard multicast)\n ");
363 if(range.pm_capa & IW_POWER_MULTICAST_R)
364 printf("\t\to Receive Multicast only (discard unicast)\n ");
365 if(range.pm_capa & IW_POWER_FORCE_S)
366 printf("\t\to Force sending using Power Management\n ");
367 if(range.pm_capa & IW_POWER_REPEATER)
368 printf("\t\to Repeat multicast\n ");
370 /* Display min/max period availables */
371 if(range.pmp_flags & IW_POWER_PERIOD)
373 int flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
374 /* Display if auto or fixed */
375 if(range.pmp_flags & IW_POWER_MIN)
376 printf("Auto period ; ");
378 printf("Fixed period ; ");
379 /* Print the range */
380 iw_print_pm_value(buffer, range.min_pmp, flags | IW_POWER_MIN);
381 printf("%s\n ", buffer);
382 iw_print_pm_value(buffer, range.max_pmp, flags | IW_POWER_MAX);
383 printf("%s\n ", buffer);
386 /* Display min/max timeout availables */
387 if(range.pmt_flags & IW_POWER_TIMEOUT)
389 int flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
390 /* Display if auto or fixed */
391 if(range.pmt_flags & IW_POWER_MIN)
392 printf("Auto timeout ; ");
394 printf("Fixed timeout ; ");
395 /* Print the range */
396 iw_print_pm_value(buffer, range.min_pmt, flags | IW_POWER_MIN);
397 printf("%s\n ", buffer);
398 iw_print_pm_value(buffer, range.max_pmt, flags | IW_POWER_MAX);
399 printf("%s\n ", buffer);
402 #endif /* WIRELESS_EXT > 9 */
404 /* Get current Power Management settings */
405 wrq.u.power.flags = 0;
406 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
408 int flags = wrq.u.power.flags;
410 /* Is it disabled ? */
411 if(wrq.u.power.disabled)
412 printf("Current mode:off\n ");
417 /* Let's check the mode */
418 iw_print_pm_mode(buffer, flags);
419 printf("Current %s", buffer);
421 /* Let's check if nothing (simply on) */
422 if((flags & IW_POWER_MODE) == IW_POWER_ON)
426 /* Let's check the value and its type */
427 if(wrq.u.power.flags & IW_POWER_TYPE)
429 iw_print_pm_value(buffer,
430 wrq.u.power.value, wrq.u.power.flags);
431 printf("%s", buffer);
434 /* If we have been returned a MIN value, ask for the MAX */
435 if(flags & IW_POWER_MIN)
436 pm_mask = IW_POWER_MAX;
437 /* If we have been returned a MAX value, ask for the MIN */
438 if(flags & IW_POWER_MAX)
439 pm_mask = IW_POWER_MIN;
440 /* If we have something to ask for... */
442 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
445 /* And if we have both a period and a timeout, ask the other */
446 pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
450 int base_mask = pm_mask;
451 flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
454 /* If we have been returned a MIN value, ask for the MAX */
455 if(flags & IW_POWER_MIN)
456 pm_mask = IW_POWER_MAX | base_mask;
457 /* If we have been returned a MAX value, ask for the MIN */
458 if(flags & IW_POWER_MAX)
459 pm_mask = IW_POWER_MIN | base_mask;
460 /* If we have something to ask for... */
462 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
464 #endif /* WIRELESS_EXT > 9 */
472 /************************** TRANSMIT POWER **************************/
474 /*------------------------------------------------------------------*/
476 * Print the number of available transmit powers for the device
479 print_txpower_info(int skfd,
481 char * args[], /* Command line args */
482 int count) /* Args count */
485 struct iw_range range;
490 /* Avoid "Unused parameter" warning */
491 args = args; count = count;
494 /* Extract range info */
495 if(iw_get_range_info(skfd, ifname, &range) < 0)
496 fprintf(stderr, "%-8.8s no transmit-power information.\n\n",
500 if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
501 printf("%-8.8s No transmit-powers ? Please update driver...\n\n", ifname);
504 printf("%-8.8s %d available transmit-powers :\n",
505 ifname, range.num_txpower);
507 for(k = 0; k < range.num_txpower; k++)
509 if(range.txpower_capa & IW_TXPOW_MWATT)
511 dbm = iw_mwatt2dbm(range.txpower[k]);
512 mwatt = range.txpower[k];
516 dbm = range.txpower[k];
517 mwatt = iw_dbm2mwatt(range.txpower[k]);
519 printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
522 /* Get current Transmit Power */
523 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
525 printf(" Current Tx-Power");
527 if(wrq.u.txpower.disabled)
532 if(wrq.u.txpower.fixed)
536 if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
538 dbm = iw_mwatt2dbm(wrq.u.txpower.value);
539 mwatt = wrq.u.txpower.value;
543 dbm = wrq.u.txpower.value;
544 mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
546 printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
551 #endif /* WIRELESS_EXT > 9 */
555 /*********************** RETRY LIMIT/LIFETIME ***********************/
557 #if WIRELESS_EXT > 10
558 /*------------------------------------------------------------------*/
560 * Print one retry value
563 get_retry_value(int skfd,
569 /* Get Another retry value */
570 pwrq->u.retry.flags = flags;
571 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
573 /* Let's check the value and its type */
574 if(pwrq->u.retry.flags & IW_RETRY_TYPE)
576 iw_print_retry_value(buffer,
577 pwrq->u.retry.value, pwrq->u.retry.flags);
578 printf("%s\n ", buffer);
581 return(pwrq->u.retry.flags);
584 /*------------------------------------------------------------------*/
586 * Print Retry info for each device
589 print_retry_info(int skfd,
591 char * args[], /* Command line args */
592 int count) /* Args count */
595 struct iw_range range;
598 /* Avoid "Unused parameter" warning */
599 args = args; count = count;
601 /* Extract range info */
602 if(iw_get_range_info(skfd, ifname, &range) < 0)
603 fprintf(stderr, "%-8.8s no retry limit/lifetime information.\n\n",
607 printf("%-8.8s ", ifname);
609 /* Display min/max limit availables */
610 if(range.retry_flags & IW_RETRY_LIMIT)
612 int flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
613 /* Display if auto or fixed */
614 if(range.retry_flags & IW_RETRY_MIN)
615 printf("Auto limit ; ");
617 printf("Fixed limit ; ");
618 /* Print the range */
619 iw_print_retry_value(buffer, range.min_retry, flags | IW_RETRY_MIN);
620 printf("%s\n ", buffer);
621 iw_print_retry_value(buffer, range.max_retry, flags | IW_RETRY_MAX);
622 printf("%s\n ", buffer);
625 /* Display min/max lifetime availables */
626 if(range.r_time_flags & IW_RETRY_LIFETIME)
628 int flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
629 /* Display if auto or fixed */
630 if(range.r_time_flags & IW_RETRY_MIN)
631 printf("Auto lifetime ; ");
633 printf("Fixed lifetime ; ");
634 /* Print the range */
635 iw_print_retry_value(buffer, range.min_r_time, flags | IW_RETRY_MIN);
636 printf("%s\n ", buffer);
637 iw_print_retry_value(buffer, range.max_r_time, flags | IW_RETRY_MAX);
638 printf("%s\n ", buffer);
642 /* Get current retry settings */
643 wrq.u.retry.flags = 0;
644 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
646 int flags = wrq.u.retry.flags;
648 /* Is it disabled ? */
649 if(wrq.u.retry.disabled)
650 printf("Current mode:off\n ");
655 /* Let's check the mode */
656 printf("Current mode:on\n ");
658 /* Let's check the value and its type */
659 if(wrq.u.retry.flags & IW_RETRY_TYPE)
661 iw_print_retry_value(buffer,
662 wrq.u.retry.value, wrq.u.retry.flags);
663 printf("%s", buffer);
666 /* If we have been returned a MIN value, ask for the MAX */
667 if(flags & IW_RETRY_MIN)
668 retry_mask = IW_RETRY_MAX;
669 /* If we have been returned a MAX value, ask for the MIN */
670 if(flags & IW_RETRY_MAX)
671 retry_mask = IW_RETRY_MIN;
672 /* If we have something to ask for... */
674 get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
676 /* And if we have both a period and a timeout, ask the other */
677 retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
681 int base_mask = retry_mask;
682 flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
686 /* If we have been returned a MIN value, ask for the MAX */
687 if(flags & IW_RETRY_MIN)
688 retry_mask = IW_RETRY_MAX | base_mask;
689 /* If we have been returned a MAX value, ask for the MIN */
690 if(flags & IW_RETRY_MAX)
691 retry_mask = IW_RETRY_MIN | base_mask;
692 /* If we have something to ask for... */
694 get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
703 #endif /* WIRELESS_EXT > 10 */
705 /***************************** SCANNING *****************************/
707 * This one behave quite differently from the others
709 #if WIRELESS_EXT > 13
710 /*------------------------------------------------------------------*/
712 * Print one element from the scanning results
715 print_scanning_token(struct iw_event * event, /* Extracted token */
716 int ap_num, /* AP number */
717 struct iw_range * iwrange, /* Range info */
720 char buffer[128]; /* Temporary buffer */
722 /* Now, let's decode the event */
726 printf(" Cell %02d - Address: %s\n", ap_num,
727 iw_pr_ether(buffer, event->u.ap_addr.sa_data));
731 if(event->u.nwid.disabled)
732 printf(" NWID:off/any\n");
734 printf(" NWID:%X\n", event->u.nwid.value);
738 double freq; /* Frequency/channel */
739 freq = iw_freq2float(&(event->u.freq));
740 iw_print_freq(buffer, freq);
741 printf(" %s\n", buffer);
746 iw_operation_mode[event->u.mode]);
749 printf(" Protocol:%-1.16s\n", event->u.name);
753 char essid[IW_ESSID_MAX_SIZE+1];
754 if((event->u.essid.pointer) && (event->u.essid.length))
755 memcpy(essid, event->u.essid.pointer, event->u.essid.length);
756 essid[event->u.essid.length] = '\0';
757 if(event->u.essid.flags)
759 /* Does it have an ESSID index ? */
760 if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)
761 printf(" ESSID:\"%s\" [%d]\n", essid,
762 (event->u.essid.flags & IW_ENCODE_INDEX));
764 printf(" ESSID:\"%s\"\n", essid);
767 printf(" ESSID:off/any\n");
772 unsigned char key[IW_ENCODING_TOKEN_MAX];
773 if(event->u.data.pointer)
774 memcpy(key, event->u.essid.pointer, event->u.data.length);
776 event->u.data.flags |= IW_ENCODE_NOKEY;
777 printf(" Encryption key:");
778 if(event->u.data.flags & IW_ENCODE_DISABLED)
782 /* Display the key */
783 iw_print_key(buffer, key, event->u.data.length,
784 event->u.data.flags);
785 printf("%s", buffer);
788 if((event->u.data.flags & IW_ENCODE_INDEX) > 1)
789 printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX);
790 if(event->u.data.flags & IW_ENCODE_RESTRICTED)
791 printf(" Security mode:restricted");
792 if(event->u.data.flags & IW_ENCODE_OPEN)
793 printf(" Security mode:open");
799 iw_print_bitrate(buffer, event->u.bitrate.value);
800 printf(" Bit Rate:%s\n", buffer);
804 event->u.qual.updated = 0x0; /* Not that reliable, disable */
805 iw_print_stats(buffer, &event->u.qual, iwrange, has_range);
806 printf(" %s\n", buffer);
809 #if WIRELESS_EXT > 14
812 char custom[IW_CUSTOM_MAX+1];
813 if((event->u.data.pointer) && (event->u.data.length))
814 memcpy(custom, event->u.data.pointer, event->u.data.length);
815 custom[event->u.data.length] = '\0';
816 printf(" Extra:%s\n", custom);
819 #endif /* WIRELESS_EXT > 14 */
821 printf(" (Unknown Wireless Token 0x%04X)\n",
823 } /* switch(event->cmd) */
825 /* May have changed */
829 /*------------------------------------------------------------------*/
831 * Perform a scanning on one device
834 print_scanning_info(int skfd,
836 char * args[], /* Command line args */
837 int count) /* Args count */
840 unsigned char buffer[IW_SCAN_MAX_DATA]; /* Results */
841 struct timeval tv; /* Select timeout */
842 int timeout = 5000000; /* 5s */
844 /* Avoid "Unused parameter" warning */
845 args = args; count = count;
847 /* Init timeout value -> 250ms*/
852 * Here we should look at the command line args and set the IW_SCAN_ flags
855 wrq.u.param.flags = IW_SCAN_DEFAULT;
856 wrq.u.param.value = 0; /* Later */
858 /* Initiate Scanning */
859 if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
863 fprintf(stderr, "%-8.8s Interface doesn't support scanning : %s\n\n",
864 ifname, strerror(errno));
867 /* If we don't have the permission to initiate the scan, we may
868 * still have permission to read left-over results.
869 * But, don't wait !!! */
871 /* Not cool, it display for non wireless interfaces... */
872 fprintf(stderr, "%-8.8s (Could not trigger scanning, just reading left-over results)\n", ifname);
876 timeout -= tv.tv_usec;
881 fd_set rfds; /* File descriptors for select */
882 int last_fd; /* Last fd */
885 /* Guess what ? We must re-generate rfds each time */
889 /* In here, add the rtnetlink fd in the list */
891 /* Wait until something happens */
892 ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
894 /* Check if there was an error */
897 if(errno == EAGAIN || errno == EINTR)
899 fprintf(stderr, "Unhandled signal - exiting...\n");
903 /* Check if there was a timeout */
906 /* Try to read the results */
907 wrq.u.data.pointer = buffer;
908 wrq.u.data.flags = 0;
909 wrq.u.data.length = sizeof(buffer);
910 if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
912 /* Check if results not available yet */
915 /* Restart timer for only 100ms*/
918 timeout -= tv.tv_usec;
920 continue; /* Try again later */
924 fprintf(stderr, "%-8.8s Failed to read scan data : %s\n\n",
925 ifname, strerror(errno));
929 /* We have the results, go to process them */
933 /* In here, check if event and event type
934 * if scan event, read results. All errors bad & no reset timeout */
937 if(wrq.u.data.length)
940 struct stream_descr stream;
943 struct iw_range range;
946 /* Debugging code. In theory useless, because it's debugged ;-) */
948 printf("Scan result [%02X", buffer[0]);
949 for(i = 1; i < wrq.u.data.length; i++)
950 printf(":%02X", buffer[i]);
953 has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
954 printf("%-8.8s Scan completed :\n", ifname);
955 iw_init_event_stream(&stream, buffer, wrq.u.data.length);
958 /* Extract an event and print it */
959 ret = iw_extract_event_stream(&stream, &iwe);
961 ap_num = print_scanning_token(&iwe, ap_num, &range, has_range);
967 printf("%-8.8s No scan results\n", ifname);
971 #endif /* WIRELESS_EXT > 13 */
973 /************************* COMMON UTILITIES *************************/
975 * This section was written by Michael Tokarev <mjt@tls.msk.ru>
976 * But modified by me ;-)
980 typedef struct iwlist_entry {
987 static const struct iwlist_entry iwlist_cmds[] = {
988 { "frequency", print_freq_info, 0, 0 },
989 { "channel", print_freq_info, 0, 0 },
990 { "ap", print_ap_info, 0, 0 },
991 { "accesspoints", print_ap_info, 0, 0 },
992 { "peers", print_ap_info, 0, 0 },
993 { "bitrate", print_bitrate_info, 0, 0 },
994 { "rate", print_bitrate_info, 0, 0 },
995 { "encryption", print_keys_info, 0, 0 },
996 { "key", print_keys_info, 0, 0 },
997 { "power", print_pm_info, 0, 0 },
998 { "txpower", print_txpower_info, 0, 0 },
999 #if WIRELESS_EXT > 10
1000 { "retry", print_retry_info, 0, 0 },
1002 #if WIRELESS_EXT > 13
1003 { "scanning", print_scanning_info, 0, 5 },
1005 { NULL, NULL, 0, 0 },
1008 /*------------------------------------------------------------------*/
1010 * Find the most appropriate command matching the command line
1012 static inline const iwlist_cmd *
1013 find_command(const char * cmd)
1015 const iwlist_cmd * found = NULL;
1017 unsigned int len = strlen(cmd);
1020 /* Go through all commands */
1021 for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
1023 /* No match -> next one */
1024 if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
1027 /* Exact match -> perfect */
1028 if(len == strlen(iwlist_cmds[i].cmd))
1029 return &iwlist_cmds[i];
1034 found = &iwlist_cmds[i];
1037 if (iwlist_cmds[i].fn != found->fn)
1043 fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
1049 fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
1056 /*------------------------------------------------------------------*/
1060 static void iw_usage(int status)
1062 FILE* f = status ? stderr : stdout;
1065 fprintf(f, "Usage: iwlist [interface] %s\n", iwlist_cmds[0].cmd);
1066 for(i = 1; iwlist_cmds[i].cmd != NULL; ++i)
1067 fprintf(f, " [interface] %s\n", iwlist_cmds[i].cmd);
1071 /******************************* MAIN ********************************/
1073 /*------------------------------------------------------------------*/
1081 int skfd; /* generic raw socket desc. */
1082 char *dev; /* device name */
1083 char *cmd; /* command */
1084 char **args; /* Command arguments */
1085 int count; /* Number of arguments */
1086 const iwlist_cmd *iwcmd;
1088 if(argc == 1 || argc > 3)
1091 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1094 /* This is also handled slightly differently */
1095 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
1096 return(iw_print_version_info("iwlist"));
1113 /* find a command */
1114 iwcmd = find_command(cmd);
1118 /* Check arg numbers */
1119 if(count < iwcmd->min_count)
1121 fprintf(stderr, "iwlist: command `%s' needs more arguments\n", cmd);
1124 if(count > iwcmd->max_count)
1126 fprintf(stderr, "iwlist: command `%s' needs fewer arguments\n", cmd);
1130 /* Create a channel to the NET kernel. */
1131 if((skfd = iw_sockets_open()) < 0)
1137 /* do the actual work */
1139 (*iwcmd->fn)(skfd, dev, args, count);
1141 iw_enum_devices(skfd, iwcmd->fn, args, count);
1143 /* Close the socket. */