4 * Jean II - HPLB '99 - HPL 99->04
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-2004 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.16s no frequency information.\n\n",
45 if(range.num_frequency > 0)
47 printf("%-8.16s %d channels in total; available frequencies :\n",
48 ifname, range.num_channels);
50 for(k = 0; k < range.num_frequency; k++)
52 freq = iw_freq2float(&(range.freq[k]));
53 iw_print_freq_value(buffer, sizeof(buffer), freq);
54 printf(" Channel %.2d : %s\n",
55 range.freq[k].i, buffer);
59 printf("%-8.16s %d channels\n",
60 ifname, range.num_channels);
62 /* Get current frequency / channel and display it */
63 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
65 freq = iw_freq2float(&(wrq.u.freq));
66 channel = iw_freq_to_channel(freq, &range);
67 iw_print_freq(buffer, sizeof(buffer),
68 freq, channel, wrq.u.freq.flags);
69 printf(" Current %s\n\n", buffer);
75 /************************ ACCESS POINT LIST ************************/
77 * Note : now that we have scanning support, this is depracted and
78 * won't survive long. Actually, next version it's out !
81 /*------------------------------------------------------------------*/
83 * Display the list of ap addresses and the associated stats
84 * Exacly the same as the spy list, only with different IOCTL and messages
87 print_ap_info(int skfd,
89 char * args[], /* Command line args */
90 int count) /* Args count */
93 char buffer[(sizeof(struct iw_quality) +
94 sizeof(struct sockaddr)) * IW_MAX_AP];
96 struct sockaddr * hwa;
97 struct iw_quality * qual;
104 /* Avoid "Unused parameter" warning */
105 args = args; count = count;
108 wrq.u.data.pointer = (caddr_t) buffer;
109 wrq.u.data.length = IW_MAX_AP;
110 wrq.u.data.flags = 0;
111 if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
113 fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
117 /* Number of addresses */
118 n = wrq.u.data.length;
119 has_qual = wrq.u.data.flags;
122 hwa = (struct sockaddr *) buffer;
123 qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
125 /* Check if we have valid mac address type */
126 if(iw_check_mac_addr_type(skfd, ifname) < 0)
128 fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
132 /* Get range info if we can */
133 if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
138 printf("%-8.16s No Peers/Access-Point in range\n", ifname);
140 printf("%-8.16s Peers/Access-Points in range:\n", ifname);
141 for(i = 0; i < n; i++)
145 /* Print stats for this address */
146 printf(" %s : ", iw_pr_ether(temp, hwa[i].sa_data));
147 iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
148 printf("%s\n", temp);
151 /* Only print the address */
152 printf(" %s\n", iw_pr_ether(temp, hwa[i].sa_data));
158 /***************************** BITRATES *****************************/
160 /*------------------------------------------------------------------*/
162 * Print the number of available bitrates for the device
165 print_bitrate_info(int skfd,
167 char * args[], /* Command line args */
168 int count) /* Args count */
171 struct iw_range range;
175 /* Avoid "Unused parameter" warning */
176 args = args; count = count;
178 /* Extract range info */
179 if(iw_get_range_info(skfd, ifname, &range) < 0)
180 fprintf(stderr, "%-8.16s no bit-rate information.\n\n",
184 if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
186 printf("%-8.16s %d available bit-rates :\n",
187 ifname, range.num_bitrates);
189 for(k = 0; k < range.num_bitrates; k++)
191 iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
192 /* Maybe this should be %10s */
193 printf("\t %s\n", buffer);
197 printf("%-8.16s unknown bit-rate information.\n", ifname);
199 /* Get current bit rate */
200 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
202 iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
203 printf(" Current Bit Rate%c%s\n\n",
204 (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
210 /************************* ENCRYPTION KEYS *************************/
212 /*------------------------------------------------------------------*/
214 * Print the number of available encryption key for the device
217 print_keys_info(int skfd,
219 char * args[], /* Command line args */
220 int count) /* Args count */
223 struct iw_range range;
224 unsigned char key[IW_ENCODING_TOKEN_MAX];
228 /* Avoid "Unused parameter" warning */
229 args = args; count = count;
231 /* Extract range info */
232 if(iw_get_range_info(skfd, ifname, &range) < 0)
233 fprintf(stderr, "%-8.16s no encryption keys information.\n\n",
237 printf("%-8.16s ", ifname);
238 /* Print key sizes */
239 if((range.num_encoding_sizes > 0) &&
240 (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
242 printf("%d key sizes : %d", range.num_encoding_sizes,
243 range.encoding_size[0] * 8);
245 for(k = 1; k < range.num_encoding_sizes; k++)
246 printf(", %d", range.encoding_size[k] * 8);
249 /* Print the keys and associate mode */
250 printf("%d keys available :\n", range.max_encoding_tokens);
251 for(k = 1; k <= range.max_encoding_tokens; k++)
253 wrq.u.data.pointer = (caddr_t) key;
254 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
255 wrq.u.data.flags = k;
256 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
258 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
261 if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
262 (wrq.u.data.length == 0))
263 printf("\t\t[%d]: off\n", k);
266 /* Display the key */
267 iw_print_key(buffer, sizeof(buffer),
268 key, wrq.u.data.length, wrq.u.data.flags);
269 printf("\t\t[%d]: %s", k, buffer);
272 printf(" (%d bits)", wrq.u.data.length * 8);
276 /* Print current key and mode */
277 wrq.u.data.pointer = (caddr_t) key;
278 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
279 wrq.u.data.flags = 0; /* Set index to zero to get current */
280 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
282 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
285 printf(" Current Transmit Key: [%d]\n",
286 wrq.u.data.flags & IW_ENCODE_INDEX);
287 if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
288 printf(" Security mode:restricted\n");
289 if(wrq.u.data.flags & IW_ENCODE_OPEN)
290 printf(" Security mode:open\n");
297 /************************* POWER MANAGEMENT *************************/
299 /*------------------------------------------------------------------*/
301 * Print Power Management info for each device
304 get_pm_value(int skfd,
310 /* Get Another Power Management value */
311 pwrq->u.power.flags = flags;
312 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
314 /* Let's check the value and its type */
315 if(pwrq->u.power.flags & IW_POWER_TYPE)
317 iw_print_pm_value(buffer, sizeof(buffer),
318 pwrq->u.power.value, pwrq->u.power.flags);
319 printf("\n %s", buffer);
322 return(pwrq->u.power.flags);
325 /*------------------------------------------------------------------*/
327 * Print Power Management info for each device
330 print_pm_info(int skfd,
332 char * args[], /* Command line args */
333 int count) /* Args count */
336 struct iw_range range;
339 /* Avoid "Unused parameter" warning */
340 args = args; count = count;
342 /* Extract range info */
343 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
344 (range.we_version_compiled < 10))
345 fprintf(stderr, "%-8.16s no power management information.\n\n",
349 printf("%-8.16s ", ifname);
351 /* Display modes availables */
352 if(range.pm_capa & IW_POWER_MODE)
354 printf("Supported modes :\n ");
355 if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
356 printf("\t\to Receive all packets (unicast & multicast)\n ");
357 if(range.pm_capa & IW_POWER_UNICAST_R)
358 printf("\t\to Receive Unicast only (discard multicast)\n ");
359 if(range.pm_capa & IW_POWER_MULTICAST_R)
360 printf("\t\to Receive Multicast only (discard unicast)\n ");
361 if(range.pm_capa & IW_POWER_FORCE_S)
362 printf("\t\to Force sending using Power Management\n ");
363 if(range.pm_capa & IW_POWER_REPEATER)
364 printf("\t\to Repeat multicast\n ");
366 /* Display min/max period availables */
367 if(range.pmp_flags & IW_POWER_PERIOD)
369 int flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
370 /* Display if auto or fixed */
371 if(range.pmp_flags & IW_POWER_MIN)
372 printf("Auto period ; ");
374 printf("Fixed period ; ");
375 /* Print the range */
376 iw_print_pm_value(buffer, sizeof(buffer),
377 range.min_pmp, flags | IW_POWER_MIN);
378 printf("%s\n ", buffer);
379 iw_print_pm_value(buffer, sizeof(buffer),
380 range.max_pmp, flags | IW_POWER_MAX);
381 printf("%s\n ", buffer);
383 /* Display min/max timeout availables */
384 if(range.pmt_flags & IW_POWER_TIMEOUT)
386 int flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
387 /* Display if auto or fixed */
388 if(range.pmt_flags & IW_POWER_MIN)
389 printf("Auto timeout ; ");
391 printf("Fixed timeout ; ");
392 /* Print the range */
393 iw_print_pm_value(buffer, sizeof(buffer),
394 range.min_pmt, flags | IW_POWER_MIN);
395 printf("%s\n ", buffer);
396 iw_print_pm_value(buffer, sizeof(buffer),
397 range.max_pmt, flags | IW_POWER_MAX);
398 printf("%s\n ", buffer);
401 /* Get current Power Management settings */
402 wrq.u.power.flags = 0;
403 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
405 int flags = wrq.u.power.flags;
407 /* Is it disabled ? */
408 if(wrq.u.power.disabled)
409 printf("Current mode:off\n ");
414 /* Let's check the mode */
415 iw_print_pm_mode(buffer, sizeof(buffer), flags);
416 printf("Current %s", buffer);
418 /* Let's check if nothing (simply on) */
419 if((flags & IW_POWER_MODE) == IW_POWER_ON)
423 /* Let's check the value and its type */
424 if(wrq.u.power.flags & IW_POWER_TYPE)
426 iw_print_pm_value(buffer, sizeof(buffer),
427 wrq.u.power.value, wrq.u.power.flags);
428 printf("%s", buffer);
431 /* If we have been returned a MIN value, ask for the MAX */
432 if(flags & IW_POWER_MIN)
433 pm_mask = IW_POWER_MAX;
434 /* If we have been returned a MAX value, ask for the MIN */
435 if(flags & IW_POWER_MAX)
436 pm_mask = IW_POWER_MIN;
437 /* If we have something to ask for... */
439 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
441 /* And if we have both a period and a timeout, ask the other */
442 pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
446 int base_mask = pm_mask;
447 flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
450 /* If we have been returned a MIN value, ask for the MAX */
451 if(flags & IW_POWER_MIN)
452 pm_mask = IW_POWER_MAX | base_mask;
453 /* If we have been returned a MAX value, ask for the MIN */
454 if(flags & IW_POWER_MAX)
455 pm_mask = IW_POWER_MIN | base_mask;
456 /* If we have something to ask for... */
458 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
467 /************************** TRANSMIT POWER **************************/
469 /*------------------------------------------------------------------*/
471 * Print the number of available transmit powers for the device
474 print_txpower_info(int skfd,
476 char * args[], /* Command line args */
477 int count) /* Args count */
480 struct iw_range range;
485 /* Avoid "Unused parameter" warning */
486 args = args; count = count;
488 /* Extract range info */
489 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
490 (range.we_version_compiled < 10))
491 fprintf(stderr, "%-8.16s no transmit-power information.\n\n",
495 if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
496 printf("%-8.16s unknown transmit-power information.\n\n", ifname);
499 printf("%-8.16s %d available transmit-powers :\n",
500 ifname, range.num_txpower);
502 for(k = 0; k < range.num_txpower; k++)
504 /* Check for relative values */
505 if(range.txpower_capa & IW_TXPOW_RELATIVE)
507 printf("\t %d (no units)\n", range.txpower[k]);
511 if(range.txpower_capa & IW_TXPOW_MWATT)
513 dbm = iw_mwatt2dbm(range.txpower[k]);
514 mwatt = range.txpower[k];
518 dbm = range.txpower[k];
519 mwatt = iw_dbm2mwatt(range.txpower[k]);
521 printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
526 /* Get current Transmit Power */
527 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
529 printf(" Current Tx-Power");
531 if(wrq.u.txpower.disabled)
536 if(wrq.u.txpower.fixed)
540 /* Check for relative values */
541 if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
543 /* I just hate relative value, because they are
544 * driver specific, so not very meaningfull to apps.
545 * But, we have to support that, because
546 * this is the way hardware is... */
547 printf("\t %d (no units)\n", wrq.u.txpower.value);
551 if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
553 dbm = iw_mwatt2dbm(wrq.u.txpower.value);
554 mwatt = wrq.u.txpower.value;
558 dbm = wrq.u.txpower.value;
559 mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
561 printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
569 /*********************** RETRY LIMIT/LIFETIME ***********************/
571 /*------------------------------------------------------------------*/
573 * Print one retry value
576 get_retry_value(int skfd,
583 /* Get Another retry value */
584 pwrq->u.retry.flags = flags;
585 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
587 /* Let's check the value and its type */
588 if(pwrq->u.retry.flags & IW_RETRY_TYPE)
590 iw_print_retry_value(buffer, buflen,
591 pwrq->u.retry.value, pwrq->u.retry.flags);
592 printf("%s\n ", buffer);
595 return(pwrq->u.retry.flags);
598 /*------------------------------------------------------------------*/
600 * Print Retry info for each device
603 print_retry_info(int skfd,
605 char * args[], /* Command line args */
606 int count) /* Args count */
609 struct iw_range range;
612 /* Avoid "Unused parameter" warning */
613 args = args; count = count;
615 /* Extract range info */
616 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
617 (range.we_version_compiled < 11))
618 fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n",
622 printf("%-8.16s ", ifname);
624 /* Display min/max limit availables */
625 if(range.retry_flags & IW_RETRY_LIMIT)
627 int flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
628 /* Display if auto or fixed */
629 if(range.retry_flags & IW_RETRY_MIN)
630 printf("Auto limit ; ");
632 printf("Fixed limit ; ");
633 /* Print the range */
634 iw_print_retry_value(buffer, sizeof(buffer),
635 range.min_retry, flags | IW_RETRY_MIN);
636 printf("%s\n ", buffer);
637 iw_print_retry_value(buffer, sizeof(buffer),
638 range.max_retry, flags | IW_RETRY_MAX);
639 printf("%s\n ", buffer);
642 /* Display min/max lifetime availables */
643 if(range.r_time_flags & IW_RETRY_LIFETIME)
645 int flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
646 /* Display if auto or fixed */
647 if(range.r_time_flags & IW_RETRY_MIN)
648 printf("Auto lifetime ; ");
650 printf("Fixed lifetime ; ");
651 /* Print the range */
652 iw_print_retry_value(buffer, sizeof(buffer),
653 range.min_r_time, flags | IW_RETRY_MIN);
654 printf("%s\n ", buffer);
655 iw_print_retry_value(buffer, sizeof(buffer),
656 range.max_r_time, flags | IW_RETRY_MAX);
657 printf("%s\n ", buffer);
661 /* Get current retry settings */
662 wrq.u.retry.flags = 0;
663 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
665 int flags = wrq.u.retry.flags;
667 /* Is it disabled ? */
668 if(wrq.u.retry.disabled)
669 printf("Current mode:off\n ");
674 /* Let's check the mode */
675 printf("Current mode:on\n ");
677 /* Let's check the value and its type */
678 if(wrq.u.retry.flags & IW_RETRY_TYPE)
680 iw_print_retry_value(buffer, sizeof(buffer),
681 wrq.u.retry.value, wrq.u.retry.flags);
682 printf("%s\n ", buffer);
685 /* If we have been returned a MIN value, ask for the MAX */
686 if(flags & IW_RETRY_MIN)
687 retry_mask = IW_RETRY_MAX;
688 /* If we have been returned a MAX value, ask for the MIN */
689 if(flags & IW_RETRY_MAX)
690 retry_mask = IW_RETRY_MIN;
691 /* If we have something to ask for... */
693 get_retry_value(skfd, ifname, &wrq, retry_mask,
694 buffer, sizeof(buffer));
696 /* And if we have both a period and a timeout, ask the other */
697 retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
701 int base_mask = retry_mask;
702 flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
703 buffer, sizeof(buffer));
706 /* If we have been returned a MIN value, ask for the MAX */
707 if(flags & IW_RETRY_MIN)
708 retry_mask = IW_RETRY_MAX | base_mask;
709 /* If we have been returned a MAX value, ask for the MIN */
710 if(flags & IW_RETRY_MAX)
711 retry_mask = IW_RETRY_MIN | base_mask;
712 /* If we have something to ask for... */
714 get_retry_value(skfd, ifname, &wrq, retry_mask,
715 buffer, sizeof(buffer));
724 /***************************** SCANNING *****************************/
726 * This one behave quite differently from the others
728 * Note that we don't use the scanning capability of iwlib (functions
729 * iw_process_scan() and iw_scan()). The main reason is that
730 * iw_process_scan() return only a subset of the scan data to the caller,
731 * for example custom elements and bitrates are ommited. Here, we
732 * do the complete job...
735 /*------------------------------------------------------------------*/
737 * Print one element from the scanning results
740 print_scanning_token(struct iw_event * event, /* Extracted token */
741 int ap_num, /* AP number */
742 struct iw_range * iw_range, /* Range info */
745 char buffer[128]; /* Temporary buffer */
747 /* Now, let's decode the event */
751 printf(" Cell %02d - Address: %s\n", ap_num,
752 iw_pr_ether(buffer, event->u.ap_addr.sa_data));
756 if(event->u.nwid.disabled)
757 printf(" NWID:off/any\n");
759 printf(" NWID:%X\n", event->u.nwid.value);
763 double freq; /* Frequency/channel */
764 int channel = -1; /* Converted to channel */
765 freq = iw_freq2float(&(event->u.freq));
766 /* Convert to channel if possible */
768 channel = iw_freq_to_channel(freq, iw_range);
769 iw_print_freq(buffer, sizeof(buffer),
770 freq, channel, event->u.freq.flags);
771 printf(" %s\n", buffer);
776 iw_operation_mode[event->u.mode]);
779 printf(" Protocol:%-1.16s\n", event->u.name);
783 char essid[IW_ESSID_MAX_SIZE+1];
784 if((event->u.essid.pointer) && (event->u.essid.length))
785 memcpy(essid, event->u.essid.pointer, event->u.essid.length);
786 essid[event->u.essid.length] = '\0';
787 if(event->u.essid.flags)
789 /* Does it have an ESSID index ? */
790 if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)
791 printf(" ESSID:\"%s\" [%d]\n", essid,
792 (event->u.essid.flags & IW_ENCODE_INDEX));
794 printf(" ESSID:\"%s\"\n", essid);
797 printf(" ESSID:off/any\n");
802 unsigned char key[IW_ENCODING_TOKEN_MAX];
803 if(event->u.data.pointer)
804 memcpy(key, event->u.essid.pointer, event->u.data.length);
806 event->u.data.flags |= IW_ENCODE_NOKEY;
807 printf(" Encryption key:");
808 if(event->u.data.flags & IW_ENCODE_DISABLED)
812 /* Display the key */
813 iw_print_key(buffer, sizeof(buffer), key, event->u.data.length,
814 event->u.data.flags);
815 printf("%s", buffer);
818 if((event->u.data.flags & IW_ENCODE_INDEX) > 1)
819 printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX);
820 if(event->u.data.flags & IW_ENCODE_RESTRICTED)
821 printf(" Security mode:restricted");
822 if(event->u.data.flags & IW_ENCODE_OPEN)
823 printf(" Security mode:open");
829 iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);
830 printf(" Bit Rate:%s\n", buffer);
834 iw_print_stats(buffer, sizeof(buffer),
835 &event->u.qual, iw_range, has_range);
836 printf(" %s\n", buffer);
841 char custom[IW_CUSTOM_MAX+1];
842 if((event->u.data.pointer) && (event->u.data.length))
843 memcpy(custom, event->u.data.pointer, event->u.data.length);
844 custom[event->u.data.length] = '\0';
845 printf(" Extra:%s\n", custom);
849 printf(" (Unknown Wireless Token 0x%04X)\n",
851 } /* switch(event->cmd) */
853 /* May have changed */
857 /*------------------------------------------------------------------*/
859 * Perform a scanning on one device
862 print_scanning_info(int skfd,
864 char * args[], /* Command line args */
865 int count) /* Args count */
868 unsigned char * buffer = NULL; /* Results */
869 int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
870 struct iw_range range;
872 struct timeval tv; /* Select timeout */
873 int timeout = 5000000; /* 5s */
875 /* Avoid "Unused parameter" warning */
876 args = args; count = count;
878 /* Get range stuff */
879 has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
881 /* Check if the interface could support scanning. */
882 if((!has_range) || (range.we_version_compiled < 14))
884 fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n",
889 /* Init timeout value -> 250ms*/
894 * Here we should look at the command line args and set the IW_SCAN_ flags
897 wrq.u.data.pointer = NULL; /* Later */
898 wrq.u.data.flags = 0;
899 wrq.u.data.length = 0;
901 /* Initiate Scanning */
902 if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
906 fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
907 ifname, strerror(errno));
910 /* If we don't have the permission to initiate the scan, we may
911 * still have permission to read left-over results.
912 * But, don't wait !!! */
914 /* Not cool, it display for non wireless interfaces... */
915 fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
919 timeout -= tv.tv_usec;
924 fd_set rfds; /* File descriptors for select */
925 int last_fd; /* Last fd */
928 /* Guess what ? We must re-generate rfds each time */
932 /* In here, add the rtnetlink fd in the list */
934 /* Wait until something happens */
935 ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
937 /* Check if there was an error */
940 if(errno == EAGAIN || errno == EINTR)
942 fprintf(stderr, "Unhandled signal - exiting...\n");
946 /* Check if there was a timeout */
949 unsigned char * newbuf;
952 /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
953 newbuf = realloc(buffer, buflen);
958 fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
963 /* Try to read the results */
964 wrq.u.data.pointer = buffer;
965 wrq.u.data.flags = 0;
966 wrq.u.data.length = buflen;
967 if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
969 /* Check if buffer was too small (WE-17 only) */
970 if((errno == E2BIG) && (range.we_version_compiled > 16))
972 /* Some driver may return very large scan results, either
973 * because there are many cells, or because they have many
974 * large elements in cells (like IWEVCUSTOM). Most will
975 * only need the regular sized buffer. We now use a dynamic
976 * allocation of the buffer to satisfy everybody. Of course,
977 * as we don't know in advance the size of the array, we try
978 * various increasing sizes. Jean II */
980 /* Check if the driver gave us any hints. */
981 if(wrq.u.data.length > buflen)
982 buflen = wrq.u.data.length;
990 /* Check if results not available yet */
993 /* Restart timer for only 100ms*/
996 timeout -= tv.tv_usec;
998 continue; /* Try again later */
1003 fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
1004 ifname, strerror(errno));
1008 /* We have the results, go to process them */
1012 /* In here, check if event and event type
1013 * if scan event, read results. All errors bad & no reset timeout */
1016 if(wrq.u.data.length)
1018 struct iw_event iwe;
1019 struct stream_descr stream;
1023 /* Debugging code. In theory useless, because it's debugged ;-) */
1025 printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
1026 for(i = 1; i < wrq.u.data.length; i++)
1027 printf(":%02X", buffer[i]);
1030 printf("%-8.16s Scan completed :\n", ifname);
1031 iw_init_event_stream(&stream, buffer, wrq.u.data.length);
1034 /* Extract an event and print it */
1035 ret = iw_extract_event_stream(&stream, &iwe,
1036 range.we_version_compiled);
1038 ap_num = print_scanning_token(&iwe, ap_num, &range, has_range);
1044 printf("%-8.16s No scan results\n", ifname);
1050 /******************** WIRELESS EVENT CAPABILITY ********************/
1052 static const char * event_capa_req[] =
1054 [SIOCSIWNWID - SIOCIWFIRST] = "Set NWID (kernel generated)",
1055 [SIOCSIWFREQ - SIOCIWFIRST] = "Set Frequency/Channel (kernel generated)",
1056 [SIOCGIWFREQ - SIOCIWFIRST] = "New Frequency/Channel",
1057 [SIOCSIWMODE - SIOCIWFIRST] = "Set Mode (kernel generated)",
1058 [SIOCGIWTHRSPY - SIOCIWFIRST] = "Spy threshold crossed",
1059 [SIOCGIWAP - SIOCIWFIRST] = "New Access Point/Cell address - roaming",
1060 [SIOCGIWSCAN - SIOCIWFIRST] = "Scan request completed",
1061 [SIOCSIWESSID - SIOCIWFIRST] = "Set ESSID (kernel generated)",
1062 [SIOCGIWESSID - SIOCIWFIRST] = "New ESSID",
1063 [SIOCGIWRATE - SIOCIWFIRST] = "New bit-rate",
1064 [SIOCSIWENCODE - SIOCIWFIRST] = "Set Encoding (kernel generated)",
1065 [SIOCGIWPOWER - SIOCIWFIRST] = NULL,
1068 static const char * event_capa_evt[] =
1070 [IWEVTXDROP - IWEVFIRST] = "Tx packet dropped - retry exceeded",
1071 [IWEVCUSTOM - IWEVFIRST] = "Custom driver event",
1072 [IWEVREGISTERED - IWEVFIRST] = "Registered node",
1073 [IWEVEXPIRED - IWEVFIRST] = "Expired node",
1076 /*------------------------------------------------------------------*/
1078 * Print the number of available transmit powers for the device
1081 print_event_capa_info(int skfd,
1083 char * args[], /* Command line args */
1084 int count) /* Args count */
1086 struct iw_range range;
1089 /* Avoid "Unused parameter" warning */
1090 args = args; count = count;
1092 /* Extract range info */
1093 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1094 (range.we_version_compiled < 10))
1095 fprintf(stderr, "%-8.16s no wireless event capability information.\n\n",
1101 for(cmd = 0x8B00; cmd < 0x8C0F; cmd++)
1103 int idx = IW_EVENT_CAPA_INDEX(cmd);
1104 int mask = IW_EVENT_CAPA_MASK(cmd);
1105 printf("0x%X - %d - %X\n", cmd, idx, mask);
1109 printf("%-8.16s Wireless Events supported :\n", ifname);
1111 for(cmd = SIOCIWFIRST; cmd <= SIOCGIWPOWER; cmd++)
1113 int idx = IW_EVENT_CAPA_INDEX(cmd);
1114 int mask = IW_EVENT_CAPA_MASK(cmd);
1115 if(range.event_capa[idx] & mask)
1116 printf(" 0x%04X : %s\n",
1117 cmd, event_capa_req[cmd - SIOCIWFIRST]);
1119 for(cmd = IWEVFIRST; cmd <= IWEVEXPIRED; cmd++)
1121 int idx = IW_EVENT_CAPA_INDEX(cmd);
1122 int mask = IW_EVENT_CAPA_MASK(cmd);
1123 if(range.event_capa[idx] & mask)
1124 printf(" 0x%04X : %s\n",
1125 cmd, event_capa_evt[cmd - IWEVFIRST]);
1132 /************************* COMMON UTILITIES *************************/
1134 * This section was written by Michael Tokarev <mjt@tls.msk.ru>
1135 * But modified by me ;-)
1139 typedef struct iwlist_entry {
1146 static const struct iwlist_entry iwlist_cmds[] = {
1147 { "scanning", print_scanning_info, 0, 5 },
1148 { "frequency", print_freq_info, 0, 0 },
1149 { "channel", print_freq_info, 0, 0 },
1150 { "bitrate", print_bitrate_info, 0, 0 },
1151 { "rate", print_bitrate_info, 0, 0 },
1152 { "encryption", print_keys_info, 0, 0 },
1153 { "key", print_keys_info, 0, 0 },
1154 { "power", print_pm_info, 0, 0 },
1155 { "txpower", print_txpower_info, 0, 0 },
1156 { "retry", print_retry_info, 0, 0 },
1157 { "ap", print_ap_info, 0, 0 },
1158 { "accesspoints", print_ap_info, 0, 0 },
1159 { "peers", print_ap_info, 0, 0 },
1160 { "event", print_event_capa_info, 0, 0 },
1161 { NULL, NULL, 0, 0 },
1164 /*------------------------------------------------------------------*/
1166 * Find the most appropriate command matching the command line
1168 static inline const iwlist_cmd *
1169 find_command(const char * cmd)
1171 const iwlist_cmd * found = NULL;
1173 unsigned int len = strlen(cmd);
1176 /* Go through all commands */
1177 for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
1179 /* No match -> next one */
1180 if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
1183 /* Exact match -> perfect */
1184 if(len == strlen(iwlist_cmds[i].cmd))
1185 return &iwlist_cmds[i];
1190 found = &iwlist_cmds[i];
1193 if (iwlist_cmds[i].fn != found->fn)
1199 fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
1205 fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
1212 /*------------------------------------------------------------------*/
1216 static void iw_usage(int status)
1218 FILE* f = status ? stderr : stdout;
1221 fprintf(f, "Usage: iwlist [interface] %s\n", iwlist_cmds[0].cmd);
1222 for(i = 1; iwlist_cmds[i].cmd != NULL; ++i)
1223 fprintf(f, " [interface] %s\n", iwlist_cmds[i].cmd);
1227 /******************************* MAIN ********************************/
1229 /*------------------------------------------------------------------*/
1237 int skfd; /* generic raw socket desc. */
1238 char *dev; /* device name */
1239 char *cmd; /* command */
1240 char **args; /* Command arguments */
1241 int count; /* Number of arguments */
1242 const iwlist_cmd *iwcmd;
1244 if(argc == 1 || argc > 3)
1247 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1250 /* This is also handled slightly differently */
1251 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
1252 return(iw_print_version_info("iwlist"));
1269 /* find a command */
1270 iwcmd = find_command(cmd);
1274 /* Check arg numbers */
1275 if(count < iwcmd->min_count)
1277 fprintf(stderr, "iwlist: command `%s' needs more arguments\n", cmd);
1280 if(count > iwcmd->max_count)
1282 fprintf(stderr, "iwlist: command `%s' needs fewer arguments\n", cmd);
1286 /* Create a channel to the NET kernel. */
1287 if((skfd = iw_sockets_open()) < 0)
1293 /* do the actual work */
1295 (*iwcmd->fn)(skfd, dev, args, count);
1297 iw_enum_devices(skfd, iwcmd->fn, args, count);
1299 /* Close the socket. */
1300 iw_sockets_close(skfd);