*
* 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 <jt@hpl.hp.com>
*/
-#include "iwcommon.h" /* Header */
+#include "iwlib.h" /* Header */
+#include <sys/time.h>
/*********************** FREQUENCIES/CHANNELS ***********************/
/*
* 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
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
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 ************************/
* 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;
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 */
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 */
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 *****************************/
/*
* 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
/* 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 *************************/
/*
* 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
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;
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);
}
}
/* 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);
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 *************************/
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);
/*
* 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
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 */
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;
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)
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 */
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 */
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 **************************/
/*
* 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
{
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);
}
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 ***********************/
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);
/*
* 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
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 */
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;
/* 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)
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) &
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 */
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 <mjt@tls.msk.ru>
+ * 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;
}