X-Git-Url: http://git.osdn.net/view?p=android-x86%2Fexternal-wireless-tools.git;a=blobdiff_plain;f=wireless_tools%2Fiwlist.c;h=0703f3e81a7e3a03eff2a14dcc02a9248bef75c1;hp=b8284af25fb5d4ba0c81fb26e902867b40f1bcec;hb=92c266503ddec9d3bd219978c118a77a46dc12d4;hpb=37268af80055faf826140ff0c255f495df34b616 diff --git a/wireless_tools/iwlist.c b/wireless_tools/iwlist.c index b8284af..0703f3e 100644 --- a/wireless_tools/iwlist.c +++ b/wireless_tools/iwlist.c @@ -5,12 +5,14 @@ * * This tool can access various piece of information on the card * not part of iwconfig... - * You need to link this code against "iwcommon.c" and "-lm". + * You need to link this code against "iwlist.c" and "-lm". * * This file is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ -#include "iwcommon.h" /* Header */ +#include "iwlib.h" /* Header */ +#include /*********************** FREQUENCIES/CHANNELS ***********************/ @@ -18,15 +20,20 @@ /* * Print the number of channels and available frequency for the device */ -static void +static int print_freq_info(int skfd, - char * ifname) + char * ifname, + char * args[], /* Command line args */ + int count) /* Args count */ { float freq; struct iw_range range; int k; - if(get_range_info(skfd, ifname, &range) < 0) + /* Avoid "Unused parameter" warning */ + args = args; count = count; + + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no frequency information.\n\n", ifname); else @@ -39,7 +46,7 @@ print_freq_info(int skfd, for(k = 0; k < range.num_frequency; k++) { printf("\t Channel %.2d : ", range.freq[k].i); - freq = freq2float(&(range.freq[k])); + freq = iw_freq2float(&(range.freq[k])); if(freq >= GIGA) printf("%g GHz\n", freq / GIGA); else @@ -54,33 +61,7 @@ print_freq_info(int skfd, printf("%-8.8s %d channels\n\n", ifname, range.num_channels); } -} - -/*------------------------------------------------------------------*/ -/* - * Get frequency info on all devices and print it on the screen - */ -static void -print_freq_devices(int skfd) -{ - char buff[1024]; - struct ifconf ifc; - struct ifreq *ifr; - int i; - - /* Get list of active devices */ - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) - { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); - return; - } - ifr = ifc.ifc_req; - - /* Print them */ - for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) - print_freq_info(skfd, ifr->ifr_name); + return(0); } /************************ ACCESS POINT LIST ************************/ @@ -90,13 +71,16 @@ print_freq_devices(int skfd) * Display the list of ap addresses and the associated stats * Exacly the same as the spy list, only with different IOCTL and messages */ -static void +static int print_ap_info(int skfd, - char * ifname) + char * ifname, + char * args[], /* Command line args */ + int count) /* Args count */ { struct iwreq wrq; char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_AP]; + char temp[128]; struct sockaddr * hwa; struct iw_quality * qual; iwrange range; @@ -105,15 +89,17 @@ print_ap_info(int skfd, int n; int i; + /* Avoid "Unused parameter" warning */ + args = args; count = count; + /* Collect stats */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) buffer; - wrq.u.data.length = 0; + wrq.u.data.length = IW_MAX_AP; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWAPLIST, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0) { fprintf(stderr, "%-8.8s Interface doesn't have a list of Access Points\n\n", ifname); - return; + return(-1); } /* Number of addresses */ @@ -124,15 +110,15 @@ print_ap_info(int skfd, hwa = (struct sockaddr *) buffer; qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); - /* Check if we have valid address types */ - if(check_addr_type(skfd, ifname) < 0) + /* Check if we have valid mac address type */ + if(iw_check_mac_addr_type(skfd, ifname) < 0) { - fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname); - return; + fprintf(stderr, "%-8.8s Interface doesn't support MAC addresses\n\n", ifname); + return(-2); } /* Get range info if we can */ - if(get_range_info(skfd, ifname, &(range)) >= 0) + if(iw_get_range_info(skfd, ifname, &(range)) >= 0) has_range = 1; /* Display it */ @@ -145,41 +131,16 @@ print_ap_info(int skfd, if(has_qual) { /* Print stats for this address */ - printf(" %s : ", pr_ether(hwa[i].sa_data)); - print_stats(stdout, &qual[i], &range, has_range); + printf(" %s : ", iw_pr_ether(temp, hwa[i].sa_data)); + iw_print_stats(temp, &qual[i], &range, has_range); + printf("%s\n", temp); } else /* Only print the address */ - printf(" %s\n", pr_ether(hwa[i].sa_data)); + printf(" %s\n", iw_pr_ether(temp, hwa[i].sa_data)); } printf("\n"); -} - -/*------------------------------------------------------------------*/ -/* - * Get list of AP on all devices and print it on the screen - */ -static void -print_ap_devices(int skfd) -{ - char buff[1024]; - struct ifconf ifc; - struct ifreq *ifr; - int i; - - /* Get list of active devices */ - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) - { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); - return; - } - ifr = ifc.ifc_req; - - /* Print them */ - for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) - print_ap_info(skfd, ifr->ifr_name); + return(0); } /***************************** BITRATES *****************************/ @@ -188,16 +149,21 @@ print_ap_devices(int skfd) /* * Print the number of available bitrates for the device */ -static void +static int print_bitrate_info(int skfd, - char * ifname) + char * ifname, + char * args[], /* Command line args */ + int count) /* Args count */ { - float bitrate; struct iw_range range; int k; + char buffer[128]; + + /* Avoid "Unused parameter" warning */ + args = args; count = count; /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no bit-rate information.\n\n", ifname); else @@ -209,48 +175,16 @@ print_bitrate_info(int skfd, /* Print them all */ for(k = 0; k < range.num_bitrates; k++) { - printf("\t "); - bitrate = range.bitrate[k]; - if(bitrate >= GIGA) - printf("%g Gb/s\n", bitrate / GIGA); - else - if(bitrate >= MEGA) - printf("%g Mb/s\n", bitrate / MEGA); - else - printf("%g kb/s\n", bitrate / KILO); + iw_print_bitrate(buffer, range.bitrate[k]); + /* Maybe this should be %10s */ + printf("\t %s\n", buffer); } printf("\n\n"); } else printf("%-8.8s No bit-rates ? Please update driver...\n\n", ifname); } -} - -/*------------------------------------------------------------------*/ -/* - * Get bit-rate info on all devices and print it on the screen - */ -static void -print_bitrate_devices(int skfd) -{ - char buff[1024]; - struct ifconf ifc; - struct ifreq *ifr; - int i; - - /* Get list of active devices */ - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) - { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); - return; - } - ifr = ifc.ifc_req; - - /* Print them */ - for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) - print_bitrate_info(skfd, ifr->ifr_name); + return(0); } /************************* ENCRYPTION KEYS *************************/ @@ -259,17 +193,23 @@ print_bitrate_devices(int skfd) /* * Print the number of available encryption key for the device */ -static void +static int print_keys_info(int skfd, - char * ifname) + char * ifname, + char * args[], /* Command line args */ + int count) /* Args count */ { struct iwreq wrq; struct iw_range range; unsigned char key[IW_ENCODING_TOKEN_MAX]; int k; + char buffer[128]; + + /* Avoid "Unused parameter" warning */ + args = args; count = count; /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no encryption keys information.\n\n", ifname); else @@ -290,11 +230,10 @@ print_keys_info(int skfd, printf("%d keys available :\n", range.max_encoding_tokens); for(k = 1; k <= range.max_encoding_tokens; k++) { - strcpy(wrq.ifr_name, ifname); wrq.u.data.pointer = (caddr_t) key; - wrq.u.data.length = 0; + wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = k; - if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); break; @@ -305,8 +244,8 @@ print_keys_info(int skfd, else { /* Display the key */ - printf("\t\t[%d]: ", k); - print_key(stdout, key, wrq.u.data.length, wrq.u.data.flags); + iw_print_key(buffer, key, wrq.u.data.length, wrq.u.data.flags); + printf("\t\t[%d]: %s", k, buffer); /* Other info... */ printf(" (%d bits)", wrq.u.data.length * 8); @@ -314,14 +253,13 @@ print_keys_info(int skfd, } } /* Print current key and mode */ - strcpy(wrq.ifr_name, ifname); wrq.u.data.pointer = (caddr_t) key; - wrq.u.data.length = 0; + wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; /* Set index to zero to get current */ - if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); - return; + return(-1); } printf(" Current Transmit Key: [%d]\n", wrq.u.data.flags & IW_ENCODE_INDEX); @@ -332,33 +270,7 @@ print_keys_info(int skfd, printf("\n\n"); } -} - -/*------------------------------------------------------------------*/ -/* - * Get encryption info on all devices and print it on the screen - */ -static void -print_keys_devices(int skfd) -{ - char buff[1024]; - struct ifconf ifc; - struct ifreq *ifr; - int i; - - /* Get list of active devices */ - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) - { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); - return; - } - ifr = ifc.ifc_req; - - /* Print them */ - for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) - print_keys_info(skfd, ifr->ifr_name); + return(0); } /************************* POWER MANAGEMENT *************************/ @@ -371,18 +283,18 @@ static inline int get_pm_value(int skfd, char * ifname, struct iwreq * pwrq, - int flags) + int flags, + char * buffer) { /* Get Another Power Management value */ - strcpy(pwrq->ifr_name, ifname); pwrq->u.power.flags = flags; - if(ioctl(skfd, SIOCGIWPOWER, pwrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0) { /* Let's check the value and its type */ if(pwrq->u.power.flags & IW_POWER_TYPE) { - printf("\n "); - print_pm_value(stdout, pwrq->u.power.value, pwrq->u.power.flags); + iw_print_pm_value(buffer, pwrq->u.power.value, pwrq->u.power.flags); + printf("\n %s", buffer); } } return(pwrq->u.power.flags); @@ -392,15 +304,21 @@ get_pm_value(int skfd, /* * Print Power Management info for each device */ -static void +static int print_pm_info(int skfd, - char * ifname) + char * ifname, + char * args[], /* Command line args */ + int count) /* Args count */ { struct iwreq wrq; struct iw_range range; + char buffer[128]; + + /* Avoid "Unused parameter" warning */ + args = args; count = count; /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no power management information.\n\n", ifname); else @@ -432,10 +350,10 @@ print_pm_info(int skfd, else printf("Fixed period ; "); /* Print the range */ - print_pm_value(stdout, range.min_pmp, flags | IW_POWER_MIN); - printf("\n "); - print_pm_value(stdout, range.max_pmp, flags | IW_POWER_MAX); - printf("\n "); + iw_print_pm_value(buffer, range.min_pmp, flags | IW_POWER_MIN); + printf("%s\n ", buffer); + iw_print_pm_value(buffer, range.max_pmp, flags | IW_POWER_MAX); + printf("%s\n ", buffer); } /* Display min/max timeout availables */ @@ -448,18 +366,17 @@ print_pm_info(int skfd, else printf("Fixed timeout ; "); /* Print the range */ - print_pm_value(stdout, range.min_pmt, flags | IW_POWER_MIN); - printf("\n "); - print_pm_value(stdout, range.max_pmt, flags | IW_POWER_MAX); - printf("\n "); + iw_print_pm_value(buffer, range.min_pmt, flags | IW_POWER_MIN); + printf("%s\n ", buffer); + iw_print_pm_value(buffer, range.max_pmt, flags | IW_POWER_MAX); + printf("%s\n ", buffer); } #endif /* WIRELESS_EXT > 9 */ /* Get current Power Management settings */ - strcpy(wrq.ifr_name, ifname); wrq.u.power.flags = 0; - if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0) { int flags = wrq.u.power.flags; @@ -471,17 +388,21 @@ print_pm_info(int skfd, int pm_mask = 0; /* Let's check the mode */ - printf("Current"); - print_pm_mode(stdout, flags); + iw_print_pm_mode(buffer, flags); + printf("Current %s", buffer); /* Let's check if nothing (simply on) */ if((flags & IW_POWER_MODE) == IW_POWER_ON) - printf(" mode:on"); + printf("mode:on"); printf("\n "); /* Let's check the value and its type */ if(wrq.u.power.flags & IW_POWER_TYPE) - print_pm_value(stdout, wrq.u.power.value, wrq.u.power.flags); + { + iw_print_pm_value(buffer, + wrq.u.power.value, wrq.u.power.flags); + printf("%s", buffer); + } /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_POWER_MIN) @@ -491,7 +412,7 @@ print_pm_info(int skfd, pm_mask = IW_POWER_MIN; /* If we have something to ask for... */ if(pm_mask) - get_pm_value(skfd, ifname, &wrq, pm_mask); + get_pm_value(skfd, ifname, &wrq, pm_mask, buffer); #if WIRELESS_EXT > 9 /* And if we have both a period and a timeout, ask the other */ @@ -500,7 +421,7 @@ print_pm_info(int skfd, if(pm_mask) { int base_mask = pm_mask; - flags = get_pm_value(skfd, ifname, &wrq, pm_mask); + flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer); pm_mask = 0; /* If we have been returned a MIN value, ask for the MAX */ @@ -511,40 +432,14 @@ print_pm_info(int skfd, pm_mask = IW_POWER_MIN | base_mask; /* If we have something to ask for... */ if(pm_mask) - get_pm_value(skfd, ifname, &wrq, pm_mask); + get_pm_value(skfd, ifname, &wrq, pm_mask, buffer); } #endif /* WIRELESS_EXT > 9 */ } } printf("\n"); } -} - -/*------------------------------------------------------------------*/ -/* - * Get Power Management info on all devices and print it on the screen - */ -static void -print_pm_devices(int skfd) -{ - char buff[1024]; - struct ifconf ifc; - struct ifreq *ifr; - int i; - - /* Get list of active devices */ - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) - { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); - return; - } - ifr = ifc.ifc_req; - - /* Print them */ - for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) - print_pm_info(skfd, ifr->ifr_name); + return(0); } /************************** TRANSMIT POWER **************************/ @@ -553,18 +448,23 @@ print_pm_devices(int skfd) /* * Print the number of available transmit powers for the device */ -static void +static int print_txpower_info(int skfd, - char * ifname) + char * ifname, + char * args[], /* Command line args */ + int count) /* Args count */ { struct iw_range range; int dbm; int mwatt; int k; + /* Avoid "Unused parameter" warning */ + args = args; count = count; + #if WIRELESS_EXT > 9 /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no transmit-power information.\n\n", ifname); else @@ -578,13 +478,13 @@ print_txpower_info(int skfd, { if(range.txpower_capa & IW_TXPOW_MWATT) { - dbm = mwatt2dbm(range.txpower[k]); + dbm = iw_mwatt2dbm(range.txpower[k]); mwatt = range.txpower[k]; } else { dbm = range.txpower[k]; - mwatt = dbm2mwatt(range.txpower[k]); + mwatt = iw_dbm2mwatt(range.txpower[k]); } printf("\t %d dBm \t(%d mW)\n", dbm, mwatt); } @@ -594,33 +494,7 @@ print_txpower_info(int skfd, printf("%-8.8s No transmit-powers ? Please update driver...\n\n", ifname); } #endif /* WIRELESS_EXT > 9 */ -} - -/*------------------------------------------------------------------*/ -/* - * Get tx-power info on all devices and print it on the screen - */ -static void -print_txpower_devices(int skfd) -{ - char buff[1024]; - struct ifconf ifc; - struct ifreq *ifr; - int i; - - /* Get list of active devices */ - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) - { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); - return; - } - ifr = ifc.ifc_req; - - /* Print them */ - for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) - print_txpower_info(skfd, ifr->ifr_name); + return(0); } /*********************** RETRY LIMIT/LIFETIME ***********************/ @@ -634,18 +508,19 @@ static inline int get_retry_value(int skfd, char * ifname, struct iwreq * pwrq, - int flags) + int flags, + char * buffer) { /* Get Another retry value */ - strcpy(pwrq->ifr_name, ifname); pwrq->u.retry.flags = flags; - if(ioctl(skfd, SIOCGIWRETRY, pwrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0) { /* Let's check the value and its type */ if(pwrq->u.retry.flags & IW_RETRY_TYPE) { - printf("\n "); - print_retry_value(stdout, pwrq->u.retry.value, pwrq->u.retry.flags); + iw_print_retry_value(buffer, + pwrq->u.retry.value, pwrq->u.retry.flags); + printf("%s\n ", buffer); } } return(pwrq->u.retry.flags); @@ -655,15 +530,21 @@ get_retry_value(int skfd, /* * Print Retry info for each device */ -static void +static int print_retry_info(int skfd, - char * ifname) + char * ifname, + char * args[], /* Command line args */ + int count) /* Args count */ { struct iwreq wrq; struct iw_range range; + char buffer[128]; + + /* Avoid "Unused parameter" warning */ + args = args; count = count; /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no retry limit/lifetime information.\n\n", ifname); else @@ -680,10 +561,10 @@ print_retry_info(int skfd, else printf("Fixed limit ; "); /* Print the range */ - print_retry_value(stdout, range.min_retry, flags | IW_RETRY_MIN); - printf("\n "); - print_retry_value(stdout, range.max_retry, flags | IW_RETRY_MAX); - printf("\n "); + iw_print_retry_value(buffer, range.min_retry, flags | IW_RETRY_MIN); + printf("%s\n ", buffer); + iw_print_retry_value(buffer, range.max_retry, flags | IW_RETRY_MAX); + printf("%s\n ", buffer); } /* Display min/max lifetime availables */ @@ -696,17 +577,16 @@ print_retry_info(int skfd, else printf("Fixed lifetime ; "); /* Print the range */ - print_retry_value(stdout, range.min_r_time, flags | IW_RETRY_MIN); - printf("\n "); - print_retry_value(stdout, range.max_r_time, flags | IW_RETRY_MAX); - printf("\n "); + iw_print_retry_value(buffer, range.min_r_time, flags | IW_RETRY_MIN); + printf("%s\n ", buffer); + iw_print_retry_value(buffer, range.max_r_time, flags | IW_RETRY_MAX); + printf("%s\n ", buffer); } /* Get current retry settings */ - strcpy(wrq.ifr_name, ifname); wrq.u.retry.flags = 0; - if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0) { int flags = wrq.u.retry.flags; @@ -722,7 +602,11 @@ print_retry_info(int skfd, /* Let's check the value and its type */ if(wrq.u.retry.flags & IW_RETRY_TYPE) - print_retry_value(stdout, wrq.u.retry.value, wrq.u.retry.flags); + { + iw_print_retry_value(buffer, + wrq.u.retry.value, wrq.u.retry.flags); + printf("%s", buffer); + } /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_RETRY_MIN) @@ -732,7 +616,7 @@ print_retry_info(int skfd, retry_mask = IW_RETRY_MIN; /* If we have something to ask for... */ if(retry_mask) - get_retry_value(skfd, ifname, &wrq, retry_mask); + get_retry_value(skfd, ifname, &wrq, retry_mask, buffer); /* And if we have both a period and a timeout, ask the other */ retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) & @@ -740,7 +624,8 @@ print_retry_info(int skfd, if(retry_mask) { int base_mask = retry_mask; - flags = get_retry_value(skfd, ifname, &wrq, retry_mask); + flags = get_retry_value(skfd, ifname, &wrq, retry_mask, + buffer); retry_mask = 0; /* If we have been returned a MIN value, ask for the MAX */ @@ -751,201 +636,438 @@ print_retry_info(int skfd, retry_mask = IW_RETRY_MIN | base_mask; /* If we have something to ask for... */ if(retry_mask) - get_retry_value(skfd, ifname, &wrq, retry_mask); + get_retry_value(skfd, ifname, &wrq, retry_mask, buffer); } } } printf("\n"); } + return(0); } +#endif /* WIRELESS_EXT > 10 */ + +/***************************** SCANNING *****************************/ +/* + * This one behave quite differently from the others + */ +#if WIRELESS_EXT > 13 /*------------------------------------------------------------------*/ /* - * Get retry info on all devices and print it on the screen + * Print one element from the scanning results */ -static void -print_retry_devices(int skfd) +static inline int +print_scanning_token(struct iw_event * event, /* Extracted token */ + int ap_num, /* AP number */ + struct iw_range * iwrange, /* Range info */ + int has_range) { - char buff[1024]; - struct ifconf ifc; - struct ifreq *ifr; - int i; + char buffer[128]; /* Temporary buffer */ - /* Get list of active devices */ - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) + /* Now, let's decode the event */ + switch(event->cmd) { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); - return; - } - ifr = ifc.ifc_req; - - /* Print them */ - for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) - print_retry_info(skfd, ifr->ifr_name); + case SIOCGIWAP: + printf(" Cell %02d - Address: %s\n", ap_num, + iw_pr_ether(buffer, event->u.ap_addr.sa_data)); + ap_num++; + break; + case SIOCGIWNWID: + if(event->u.nwid.disabled) + printf(" NWID:off/any\n"); + else + printf(" NWID:%X\n", event->u.nwid.value); + break; + case SIOCGIWFREQ: + { + float freq; /* Frequency/channel */ + freq = iw_freq2float(&(event->u.freq)); + iw_print_freq(buffer, freq); + printf(" %s\n", buffer); + } + break; + case SIOCGIWMODE: + printf(" Mode:%s\n", + iw_operation_mode[event->u.mode]); + break; + case SIOCGIWESSID: + { + char essid[IW_ESSID_MAX_SIZE+1]; + if((event->u.essid.pointer) && (event->u.essid.length)) + memcpy(essid, event->u.essid.pointer, event->u.essid.length); + essid[event->u.essid.length] = '\0'; + if(event->u.essid.flags) + { + /* Does it have an ESSID index ? */ + if((event->u.essid.flags & IW_ENCODE_INDEX) > 1) + printf(" ESSID:\"%s\" [%d]\n", essid, + (event->u.essid.flags & IW_ENCODE_INDEX)); + else + printf(" ESSID:\"%s\"\n", essid); + } + else + printf(" ESSID:off/any\n"); + } + break; + case SIOCGIWENCODE: + { + unsigned char key[IW_ENCODING_TOKEN_MAX]; + if(event->u.data.pointer) + memcpy(key, event->u.essid.pointer, event->u.data.length); + else + event->u.data.flags |= IW_ENCODE_NOKEY; + printf(" Encryption key:"); + if(event->u.data.flags & IW_ENCODE_DISABLED) + printf("off\n"); + else + { + /* Display the key */ + iw_print_key(buffer, key, event->u.data.length, + event->u.data.flags); + printf("%s", buffer); + + /* Other info... */ + if((event->u.data.flags & IW_ENCODE_INDEX) > 1) + printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX); + if(event->u.data.flags & IW_ENCODE_RESTRICTED) + printf(" Encryption mode:restricted"); + if(event->u.data.flags & IW_ENCODE_OPEN) + printf(" Encryption mode:open"); + printf("\n"); + } + } + break; + case SIOCGIWRATE: + iw_print_bitrate(buffer, event->u.bitrate.value); + printf(" Bit Rate:%s\n", buffer); + break; + case IWEVQUAL: + { + event->u.qual.updated = 0x0; /* Not that reliable, disable */ + iw_print_stats(buffer, &event->u.qual, iwrange, has_range); + printf(" %s\n", buffer); + break; + } + default: + printf(" (Unknown Wireless Token 0x%04X)\n", + event->cmd); + } /* switch(event->cmd) */ + + /* May have changed */ + return(ap_num); } -#endif /* WIRELESS_EXT > 10 */ - -/******************************* MAIN ********************************/ /*------------------------------------------------------------------*/ /* - * The main ! + * Perform a scanning on one device */ -int -main(int argc, - char ** argv) +static int +print_scanning_info(int skfd, + char * ifname, + char * args[], /* Command line args */ + int count) /* Args count */ { - int skfd = -1; /* generic raw socket desc. */ - - /* Create a channel to the NET kernel. */ - if((skfd = sockets_open()) < 0) + struct iwreq wrq; + unsigned char buffer[IW_SCAN_MAX_DATA]; /* Results */ + struct timeval tv; /* Select timeout */ + int timeout = 5000000; /* 5s */ + + /* Avoid "Unused parameter" warning */ + args = args; count = count; + + /* Init timeout value -> 250ms*/ + tv.tv_sec = 0; + tv.tv_usec = 250000; + + /* + * Here we should look at the command line args and set the IW_SCAN_ flags + * properly + */ + wrq.u.param.flags = IW_SCAN_DEFAULT; + wrq.u.param.value = 0; /* Later */ + + /* Initiate Scanning */ + if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0) { - perror("socket"); - exit(-1); + if(errno != EPERM) + { + fprintf(stderr, "%-8.8s Interface doesn't support scanning : %s\n\n", + ifname, strerror(errno)); + return(-1); + } + /* If we don't have the permission to initiate the scan, we may + * still have permission to read left-over results. + * But, don't wait !!! */ +#if 0 + /* Not cool, it display for non wireless interfaces... */ + fprintf(stderr, "%-8.8s (Could not trigger scanning, just reading left-over results)\n", ifname); +#endif + tv.tv_usec = 0; } + timeout -= tv.tv_usec; - /* Help */ - if((argc == 1) || (argc > 3) || - (!strncmp(argv[1], "-h", 9)) || (!strcmp(argv[1], "--help"))) + /* Forever */ + while(1) { - fprintf(stderr, "Usage: iwlist [interface] freq\n"); - fprintf(stderr, " [interface] ap\n"); - fprintf(stderr, " [interface] bitrate\n"); - fprintf(stderr, " [interface] keys\n"); - fprintf(stderr, " [interface] power\n"); - fprintf(stderr, " [interface] txpower\n"); - fprintf(stderr, " [interface] retries\n"); - close(skfd); - exit(0); - } + fd_set rfds; /* File descriptors for select */ + int last_fd; /* Last fd */ + int ret; - /* Frequency list */ - if((!strncmp(argv[1], "freq", 4)) || - (!strncmp(argv[1], "channel", 7))) - { - print_freq_devices(skfd); - close(skfd); - exit(0); - } + /* Guess what ? We must re-generate rfds each time */ + FD_ZERO(&rfds); + last_fd = -1; - /* Access Point list */ - if(!strcasecmp(argv[1], "ap")) - { - print_ap_devices(skfd); - close(skfd); - exit(0); - } + /* In here, add the rtnetlink fd in the list */ - /* Bit-rate list */ - if((!strncmp(argv[1], "bit", 3)) || - (!strcmp(argv[1], "rate"))) - { - print_bitrate_devices(skfd); - close(skfd); - exit(0); - } + /* Wait until something happens */ + ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); - /* Encryption key list */ - if((!strncmp(argv[1], "enc", 3)) || - (!strncmp(argv[1], "key", 3))) - { - print_keys_devices(skfd); - close(skfd); - exit(0); - } + /* Check if there was an error */ + if(ret < 0) + { + if(errno == EAGAIN || errno == EINTR) + continue; + fprintf(stderr, "Unhandled signal - exiting...\n"); + return(-1); + } - /* Power Management list */ - if(!strncmp(argv[1], "power", 3)) - { - print_pm_devices(skfd); - close(skfd); - exit(0); + /* Check if there was a timeout */ + if(ret == 0) + { + /* Try to read the results */ + wrq.u.data.pointer = buffer; + wrq.u.data.flags = 0; + wrq.u.data.length = sizeof(buffer); + if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) + { + /* Check if results not available yet */ + if(errno == EAGAIN) + { + /* Restart timer for only 100ms*/ + tv.tv_sec = 0; + tv.tv_usec = 100000; + timeout -= tv.tv_usec; + if(timeout > 0) + continue; /* Try again later */ + } + + /* Bad error */ + fprintf(stderr, "%-8.8s Failed to read scan data : %s\n\n", + ifname, strerror(errno)); + return(-2); + } + else + /* We have the results, go to process them */ + break; + } + + /* In here, check if event and event type + * if scan event, read results. All errors bad & no reset timeout */ } - /* Transmit Power list */ - if(!strncmp(argv[1], "txpower", 3)) + if(wrq.u.data.length) { - print_txpower_devices(skfd); - close(skfd); - exit(0); + struct iw_event iwe; + struct stream_descr stream; + int ap_num = 1; + int ret; + struct iw_range range; + int has_range; +#if 0 + /* Debugging code. In theory useless, because it's debugged ;-) */ + int i; + printf("Scan result [%02X", buffer[0]); + for(i = 1; i < wrq.u.data.length; i++) + printf(":%02X", buffer[i]); + printf("]\n"); +#endif + has_range = (iw_get_range_info(skfd, ifname, &range) >= 0); + printf("%-8.8s Scan completed :\n", ifname); + iw_init_event_stream(&stream, buffer, wrq.u.data.length); + do + { + /* Extract an event and print it */ + ret = iw_extract_event_stream(&stream, &iwe); + if(ret > 0) + ap_num = print_scanning_token(&iwe, ap_num, &range, has_range); + } + while(ret > 0); + printf("\n"); } + else + printf("%-8.8s No scan results\n", ifname); + + return(0); +} +#endif /* WIRELESS_EXT > 13 */ +/************************* COMMON UTILITIES *************************/ +/* + * This section was written by Michael Tokarev + * But modified by me ;-) + */ + +/* command list */ +typedef struct iwlist_entry { + const char *cmd; + iw_enum_handler fn; + int min_count; + int max_count; +} iwlist_cmd; + +static const struct iwlist_entry iwlist_cmds[] = { + { "frequency", print_freq_info, 0, 0 }, + { "channel", print_freq_info, 0, 0 }, + { "ap", print_ap_info, 0, 0 }, + { "accesspoints", print_ap_info, 0, 0 }, + { "bitrate", print_bitrate_info, 0, 0 }, + { "rate", print_bitrate_info, 0, 0 }, + { "encryption", print_keys_info, 0, 0 }, + { "key", print_keys_info, 0, 0 }, + { "power", print_pm_info, 0, 0 }, + { "txpower", print_txpower_info, 0, 0 }, #if WIRELESS_EXT > 10 - /* Retry limit/lifetime */ - if(!strncmp(argv[1], "retry", 4)) - { - print_retry_devices(skfd); - close(skfd); - exit(0); - } + { "retry", print_retry_info, 0, 0 }, #endif +#if WIRELESS_EXT > 13 + { "scanning", print_scanning_info, 0, 5 }, +#endif + { NULL, NULL, 0, 0 }, +}; - /* Special cases take two... */ - /* Frequency list */ - if((!strncmp(argv[2], "freq", 4)) || - (!strncmp(argv[2], "channel", 7))) +/*------------------------------------------------------------------*/ +/* + * Find the most appropriate command matching the command line + */ +static inline const iwlist_cmd * +find_command(const char * cmd) +{ + const iwlist_cmd * found = NULL; + int ambig = 0; + unsigned int len = strlen(cmd); + int i; + + /* Go through all commands */ + for(i = 0; iwlist_cmds[i].cmd != NULL; ++i) { - print_freq_info(skfd, argv[1]); - close(skfd); - exit(0); + /* No match -> next one */ + if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0) + continue; + + /* Exact match -> perfect */ + if(len == strlen(iwlist_cmds[i].cmd)) + return &iwlist_cmds[i]; + + /* Partial match */ + if(found == NULL) + /* First time */ + found = &iwlist_cmds[i]; + else + /* Another time */ + if (iwlist_cmds[i].fn != found->fn) + ambig = 1; } - /* Access Point list */ - if(!strcasecmp(argv[2], "ap")) + if(found == NULL) { - print_ap_info(skfd, argv[1]); - close(skfd); - exit(0); + fprintf(stderr, "iwlist: unknown command `%s'\n", cmd); + return NULL; } - /* Bit-rate list */ - if((!strncmp(argv[2], "bit", 3)) || - (!strcmp(argv[2], "rate"))) + if(ambig) { - print_bitrate_info(skfd, argv[1]); - close(skfd); - exit(0); + fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd); + return NULL; } - /* Encryption key list */ - if((!strncmp(argv[2], "enc", 3)) || - (!strncmp(argv[2], "key", 3))) + return found; +} + +/*------------------------------------------------------------------*/ +/* + * Display help + */ +static void iw_usage(int status) +{ + FILE* f = status ? stderr : stdout; + int i; + + fprintf(f, "Usage: iwlist [interface] %s\n", iwlist_cmds[0].cmd); + for(i = 1; iwlist_cmds[i].cmd != NULL; ++i) + fprintf(f, " [interface] %s\n", iwlist_cmds[i].cmd); + exit(status); +} + +/******************************* MAIN ********************************/ + +/*------------------------------------------------------------------*/ +/* + * The main ! + */ +int +main(int argc, + char ** argv) +{ + int skfd; /* generic raw socket desc. */ + char *dev; /* device name */ + char *cmd; /* command */ + char **args; /* Command arguments */ + int count; /* Number of arguments */ + const iwlist_cmd *iwcmd; + + if(argc == 1 || argc > 3) + iw_usage(1); + + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) + iw_usage(0); + + if (argc == 2) { - print_keys_info(skfd, argv[1]); - close(skfd); - exit(0); + cmd = argv[1]; + dev = NULL; + args = NULL; + count = 0; } - - /* Power Management list */ - if(!strncmp(argv[2], "power", 3)) + else { - print_pm_info(skfd, argv[1]); - close(skfd); - exit(0); + cmd = argv[2]; + dev = argv[1]; + args = argv + 3; + count = argc - 3; } - /* Transmit Power list */ - if(!strncmp(argv[2], "txpower", 3)) + /* find a command */ + iwcmd = find_command(cmd); + if(iwcmd == NULL) + return 1; + + /* Check arg numbers */ + if(count < iwcmd->min_count) { - print_txpower_info(skfd, argv[1]); - close(skfd); - exit(0); + fprintf(stderr, "iwlist: command `%s' needs more arguments\n", cmd); + return 1; + } + if(count > iwcmd->max_count) + { + fprintf(stderr, "iwlist: command `%s' needs fewer arguments\n", cmd); + return 1; } -#if WIRELESS_EXT > 10 - /* Retry limit/lifetime */ - if(!strncmp(argv[2], "retry", 4)) + /* Create a channel to the NET kernel. */ + if((skfd = iw_sockets_open()) < 0) { - print_retry_info(skfd, argv[1]); - close(skfd); - exit(0); + perror("socket"); + return -1; } -#endif + + /* do the actual work */ + if (dev) + (*iwcmd->fn)(skfd, dev, args, count); + else + iw_enum_devices(skfd, iwcmd->fn, args, count); /* Close the socket. */ close(skfd); - return(1); + return 0; }