OSDN Git Service

v21
[android-x86/external-wireless-tools.git] / wireless_tools / iwlist.c
diff --git a/wireless_tools/iwlist.c b/wireless_tools/iwlist.c
new file mode 100644 (file)
index 0000000..b8284af
--- /dev/null
@@ -0,0 +1,951 @@
+/*
+ *     Wireless Tools
+ *
+ *             Jean II - HPLB '99 - HPL 99->01
+ *
+ * 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".
+ *
+ * This file is released under the GPL license.
+ */
+
+#include "iwcommon.h"          /* Header */
+
+/*********************** FREQUENCIES/CHANNELS ***********************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the number of channels and available frequency for the device
+ */
+static void
+print_freq_info(int            skfd,
+               char *          ifname)
+{
+  float                        freq;
+  struct iw_range      range;
+  int                  k;
+
+  if(get_range_info(skfd, ifname, &range) < 0)
+      fprintf(stderr, "%-8.8s  no frequency information.\n\n",
+                     ifname);
+  else
+    {
+      if(range.num_frequency > 0)
+       {
+         printf("%-8.8s  %d channels in total; available frequencies :\n",
+                ifname, range.num_channels);
+         /* Print them all */
+         for(k = 0; k < range.num_frequency; k++)
+           {
+             printf("\t  Channel %.2d : ", range.freq[k].i);
+             freq = freq2float(&(range.freq[k]));
+             if(freq >= GIGA)
+               printf("%g GHz\n", freq / GIGA);
+             else
+               if(freq >= MEGA)
+                 printf("%g MHz\n", freq / MEGA);
+               else
+                 printf("%g kHz\n", freq / KILO);
+           }
+         printf("\n\n");
+       }
+      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);
+}
+
+/************************ 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
+print_ap_info(int      skfd,
+              char *   ifname)
+{
+  struct iwreq         wrq;
+  char         buffer[(sizeof(struct iw_quality) +
+                       sizeof(struct sockaddr)) * IW_MAX_AP];
+  struct sockaddr *    hwa;
+  struct iw_quality *  qual;
+  iwrange      range;
+  int          has_range = 0;
+  int          has_qual = 0;
+  int          n;
+  int          i;
+
+  /* Collect stats */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  wrq.u.data.pointer = (caddr_t) buffer;
+  wrq.u.data.length = 0;
+  wrq.u.data.flags = 0;
+  if(ioctl(skfd, SIOCGIWAPLIST, &wrq) < 0)
+    {
+      fprintf(stderr, "%-8.8s  Interface doesn't have a list of Access Points\n\n", ifname);
+      return;
+    }
+
+  /* Number of addresses */
+  n = wrq.u.data.length;
+  has_qual = wrq.u.data.flags;
+
+  /* The two lists */
+  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)
+    {
+      fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n\n", ifname);
+      return;
+    }
+
+  /* Get range info if we can */
+  if(get_range_info(skfd, ifname, &(range)) >= 0)
+    has_range = 1;
+
+  /* Display it */
+  if(n == 0)
+    printf("%-8.8s  No Access Point in range\n", ifname);
+  else
+    printf("%-8.8s  Access Points in range:\n", ifname);
+  for(i = 0; i < n; i++)
+    {
+      if(has_qual)
+       {
+         /* Print stats for this address */
+         printf("    %s : ", pr_ether(hwa[i].sa_data));
+         print_stats(stdout, &qual[i], &range, has_range);
+       }
+      else
+       /* Only print the address */
+       printf("    %s\n", pr_ether(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);
+}
+
+/***************************** BITRATES *****************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the number of available bitrates for the device
+ */
+static void
+print_bitrate_info(int         skfd,
+                  char *       ifname)
+{
+  float                        bitrate;
+  struct iw_range      range;
+  int                  k;
+
+  /* Extract range info */
+  if(get_range_info(skfd, ifname, &range) < 0)
+      fprintf(stderr, "%-8.8s  no bit-rate information.\n\n",
+                     ifname);
+  else
+    {
+      if((range.num_bitrates > 0) && (range.num_bitrates < IW_MAX_BITRATES))
+       {
+         printf("%-8.8s  %d available bit-rates :\n",
+                ifname, range.num_bitrates);
+         /* 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);
+           }
+         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);
+}
+
+/************************* ENCRYPTION KEYS *************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the number of available encryption key for the device
+ */
+static void
+print_keys_info(int            skfd,
+               char *          ifname)
+{
+  struct iwreq         wrq;
+  struct iw_range      range;
+  unsigned char                key[IW_ENCODING_TOKEN_MAX];
+  int                  k;
+
+  /* Extract range info */
+  if(get_range_info(skfd, ifname, &range) < 0)
+      fprintf(stderr, "%-8.8s  no encryption keys information.\n\n",
+                     ifname);
+  else
+    {
+      printf("%-8.8s  ", ifname);
+      /* Print key sizes */
+      if((range.num_encoding_sizes > 0) &&
+        (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
+       {
+         printf("%d key sizes : %d", range.num_encoding_sizes,
+                range.encoding_size[0] * 8);
+         /* Print them all */
+         for(k = 1; k < range.num_encoding_sizes; k++)
+           printf(", %d", range.encoding_size[k] * 8);
+         printf("bits\n          ");
+       }
+      /* Print the keys and associate mode */
+      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.flags = k;
+         if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
+           {
+             fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
+             break;
+           }
+         if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
+            (wrq.u.data.length == 0))
+           printf("\t\t[%d]: off\n", k);
+         else
+           {
+             /* Display the key */
+             printf("\t\t[%d]: ", k);
+             print_key(stdout, key, wrq.u.data.length, wrq.u.data.flags);
+
+             /* Other info... */
+             printf(" (%d bits)", wrq.u.data.length * 8);
+             printf("\n");
+           }
+       }
+      /* 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.flags = 0;    /* Set index to zero to get current */
+      if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
+       {
+         fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
+         return;
+       }
+      printf("          Current Transmit Key: [%d]\n",
+            wrq.u.data.flags & IW_ENCODE_INDEX);
+      if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
+       printf("          Encryption mode:restricted\n");
+      if(wrq.u.data.flags & IW_ENCODE_OPEN)
+       printf("          Encryption mode:open\n");
+
+      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);
+}
+
+/************************* POWER MANAGEMENT *************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print Power Management info for each device
+ */
+static inline int
+get_pm_value(int               skfd,
+            char *             ifname,
+            struct iwreq *     pwrq,
+            int                flags)
+{
+  /* Get Another Power Management value */
+  strcpy(pwrq->ifr_name, ifname);
+  pwrq->u.power.flags = flags;
+  if(ioctl(skfd, 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);
+       }
+    }
+  return(pwrq->u.power.flags);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print Power Management info for each device
+ */
+static void
+print_pm_info(int              skfd,
+             char *            ifname)
+{
+  struct iwreq         wrq;
+  struct iw_range      range;
+
+  /* Extract range info */
+  if(get_range_info(skfd, ifname, &range) < 0)
+      fprintf(stderr, "%-8.8s  no power management information.\n\n",
+                     ifname);
+  else
+    {
+      printf("%-8.8s  ", ifname);
+#if WIRELESS_EXT > 9
+      /* Display modes availables */
+      if(range.pm_capa & IW_POWER_MODE)
+       {
+         printf("Supported modes :\n          ");
+         if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
+           printf("\t\to Receive all packets (unicast & multicast)\n          ");
+         if(range.pm_capa & IW_POWER_UNICAST_R)
+           printf("\t\to Receive Unicast only (discard multicast)\n          ");
+         if(range.pm_capa & IW_POWER_MULTICAST_R)
+           printf("\t\to Receive Multicast only (discard unicast)\n          ");
+         if(range.pm_capa & IW_POWER_FORCE_S)
+           printf("\t\to Force sending using Power Management\n          ");
+         if(range.pm_capa & IW_POWER_REPEATER)
+           printf("\t\to Repeat multicast\n          ");
+       }
+      /* Display min/max period availables */
+      if(range.pmp_flags & IW_POWER_PERIOD)
+       {
+         int   flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
+         /* Display if auto or fixed */
+         if(range.pmp_flags & IW_POWER_MIN)
+           printf("Auto  period  ; ");
+         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          ");
+         
+       }
+      /* Display min/max timeout availables */
+      if(range.pmt_flags & IW_POWER_TIMEOUT)
+       {
+         int   flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
+         /* Display if auto or fixed */
+         if(range.pmt_flags & IW_POWER_MIN)
+           printf("Auto  timeout ; ");
+         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          ");
+         
+       }
+#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)
+       {
+         int   flags = wrq.u.power.flags;
+
+         /* Is it disabled ? */
+         if(wrq.u.power.disabled)
+           printf("Current mode:off\n          ");
+         else
+           {
+             int       pm_mask = 0;
+
+             /* Let's check the mode */
+             printf("Current");
+             print_pm_mode(stdout, flags);
+
+             /* Let's check if nothing (simply on) */
+             if((flags & IW_POWER_MODE) == IW_POWER_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);
+
+             /* If we have been returned a MIN value, ask for the MAX */
+             if(flags & IW_POWER_MIN)
+               pm_mask = IW_POWER_MAX;
+             /* If we have been returned a MAX value, ask for the MIN */
+             if(flags & IW_POWER_MAX)
+               pm_mask = IW_POWER_MIN;
+             /* If we have something to ask for... */
+             if(pm_mask)
+               get_pm_value(skfd, ifname, &wrq, pm_mask);
+
+#if WIRELESS_EXT > 9
+             /* And if we have both a period and a timeout, ask the other */
+             pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
+                                         IW_POWER_TYPE));
+             if(pm_mask)
+               {
+                 int   base_mask = pm_mask;
+                 flags = get_pm_value(skfd, ifname, &wrq, pm_mask);
+                 pm_mask = 0;
+
+                 /* If we have been returned a MIN value, ask for the MAX */
+                 if(flags & IW_POWER_MIN)
+                   pm_mask = IW_POWER_MAX | base_mask;
+                 /* If we have been returned a MAX value, ask for the MIN */
+                 if(flags & IW_POWER_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);
+               }
+#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);
+}
+
+/************************** TRANSMIT POWER **************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the number of available transmit powers for the device
+ */
+static void
+print_txpower_info(int         skfd,
+                  char *       ifname)
+{
+  struct iw_range      range;
+  int                  dbm;
+  int                  mwatt;
+  int                  k;
+
+#if WIRELESS_EXT > 9
+  /* Extract range info */
+  if(get_range_info(skfd, ifname, &range) < 0)
+      fprintf(stderr, "%-8.8s  no transmit-power information.\n\n",
+                     ifname);
+  else
+    {
+      if((range.num_txpower > 0) && (range.num_txpower < IW_MAX_TXPOWER))
+       {
+         printf("%-8.8s  %d available transmit-powers :\n",
+                ifname, range.num_txpower);
+         /* Print them all */
+         for(k = 0; k < range.num_txpower; k++)
+           {
+             if(range.txpower_capa & IW_TXPOW_MWATT)
+               {
+                 dbm = mwatt2dbm(range.txpower[k]);
+                 mwatt = range.txpower[k];
+               }
+             else
+               {
+                 dbm = range.txpower[k];
+                 mwatt = dbm2mwatt(range.txpower[k]);
+               }
+             printf("\t  %d dBm  \t(%d mW)\n", dbm, mwatt);
+           }
+         printf("\n\n");
+       }
+      else
+       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);
+}
+
+/*********************** RETRY LIMIT/LIFETIME ***********************/
+
+#if WIRELESS_EXT > 10
+/*------------------------------------------------------------------*/
+/*
+ * Print one retry value
+ */
+static inline int
+get_retry_value(int            skfd,
+               char *          ifname,
+               struct iwreq *  pwrq,
+               int             flags)
+{
+  /* Get Another retry value */
+  strcpy(pwrq->ifr_name, ifname);
+  pwrq->u.retry.flags = flags;
+  if(ioctl(skfd, 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);
+       }
+    }
+  return(pwrq->u.retry.flags);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print Retry info for each device
+ */
+static void
+print_retry_info(int           skfd,
+             char *            ifname)
+{
+  struct iwreq         wrq;
+  struct iw_range      range;
+
+  /* Extract range info */
+  if(get_range_info(skfd, ifname, &range) < 0)
+      fprintf(stderr, "%-8.8s  no retry limit/lifetime information.\n\n",
+             ifname);
+  else
+    {
+      printf("%-8.8s  ", ifname);
+
+      /* Display min/max limit availables */
+      if(range.retry_flags & IW_RETRY_LIMIT)
+       {
+         int   flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
+         /* Display if auto or fixed */
+         if(range.retry_flags & IW_RETRY_MIN)
+           printf("Auto  limit    ; ");
+         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          ");
+         
+       }
+      /* Display min/max lifetime availables */
+      if(range.r_time_flags & IW_RETRY_LIFETIME)
+       {
+         int   flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
+         /* Display if auto or fixed */
+         if(range.r_time_flags & IW_RETRY_MIN)
+           printf("Auto  lifetime ; ");
+         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          ");
+         
+       }
+
+      /* Get current retry settings */
+      strcpy(wrq.ifr_name, ifname);
+      wrq.u.retry.flags = 0;
+      if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0)
+       {
+         int   flags = wrq.u.retry.flags;
+
+         /* Is it disabled ? */
+         if(wrq.u.retry.disabled)
+           printf("Current mode:off\n          ");
+         else
+           {
+             int       retry_mask = 0;
+
+             /* Let's check the mode */
+             printf("Current mode:on\n                 ");
+
+             /* 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);
+
+             /* If we have been returned a MIN value, ask for the MAX */
+             if(flags & IW_RETRY_MIN)
+               retry_mask = IW_RETRY_MAX;
+             /* If we have been returned a MAX value, ask for the MIN */
+             if(flags & IW_RETRY_MAX)
+               retry_mask = IW_RETRY_MIN;
+             /* If we have something to ask for... */
+             if(retry_mask)
+               get_retry_value(skfd, ifname, &wrq, retry_mask);
+
+             /* And if we have both a period and a timeout, ask the other */
+             retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
+                                         IW_RETRY_TYPE));
+             if(retry_mask)
+               {
+                 int   base_mask = retry_mask;
+                 flags = get_retry_value(skfd, ifname, &wrq, retry_mask);
+                 retry_mask = 0;
+
+                 /* If we have been returned a MIN value, ask for the MAX */
+                 if(flags & IW_RETRY_MIN)
+                   retry_mask = IW_RETRY_MAX | base_mask;
+                 /* If we have been returned a MAX value, ask for the MIN */
+                 if(flags & IW_RETRY_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);
+               }
+           }
+       }
+      printf("\n");
+    }
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Get retry info on all devices and print it on the screen
+ */
+static void
+print_retry_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_retry_info(skfd, ifr->ifr_name);
+}
+#endif /* WIRELESS_EXT > 10 */
+
+/******************************* MAIN ********************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * The main !
+ */
+int
+main(int       argc,
+     char **   argv)
+{
+  int skfd = -1;               /* generic raw socket desc.     */
+
+  /* Create a channel to the NET kernel. */
+  if((skfd = sockets_open()) < 0)
+    {
+      perror("socket");
+      exit(-1);
+    }
+
+  /* Help */
+  if((argc == 1) || (argc > 3) ||
+     (!strncmp(argv[1], "-h", 9)) || (!strcmp(argv[1], "--help")))
+    {
+      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);
+    }
+
+  /* Frequency list */
+  if((!strncmp(argv[1], "freq", 4)) ||
+     (!strncmp(argv[1], "channel", 7)))
+    {
+      print_freq_devices(skfd);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Access Point list */
+  if(!strcasecmp(argv[1], "ap"))
+    {
+      print_ap_devices(skfd);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Bit-rate list */
+  if((!strncmp(argv[1], "bit", 3)) ||
+     (!strcmp(argv[1], "rate")))
+    {
+      print_bitrate_devices(skfd);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Encryption key list */
+  if((!strncmp(argv[1], "enc", 3)) ||
+     (!strncmp(argv[1], "key", 3)))
+    {
+      print_keys_devices(skfd);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Power Management list */
+  if(!strncmp(argv[1], "power", 3))
+    {
+      print_pm_devices(skfd);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Transmit Power list */
+  if(!strncmp(argv[1], "txpower", 3))
+    {
+      print_txpower_devices(skfd);
+      close(skfd);
+      exit(0);
+    }
+
+#if WIRELESS_EXT > 10
+  /* Retry limit/lifetime */
+  if(!strncmp(argv[1], "retry", 4))
+    {
+      print_retry_devices(skfd);
+      close(skfd);
+      exit(0);
+    }
+#endif
+
+  /* Special cases take two... */
+  /* Frequency list */
+  if((!strncmp(argv[2], "freq", 4)) ||
+     (!strncmp(argv[2], "channel", 7)))
+    {
+      print_freq_info(skfd, argv[1]);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Access Point  list */
+  if(!strcasecmp(argv[2], "ap"))
+    {
+      print_ap_info(skfd, argv[1]);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Bit-rate list */
+  if((!strncmp(argv[2], "bit", 3)) ||
+     (!strcmp(argv[2], "rate")))
+    {
+      print_bitrate_info(skfd, argv[1]);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Encryption key list */
+  if((!strncmp(argv[2], "enc", 3)) ||
+     (!strncmp(argv[2], "key", 3)))
+    {
+      print_keys_info(skfd, argv[1]);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Power Management list */
+  if(!strncmp(argv[2], "power", 3))
+    {
+      print_pm_info(skfd, argv[1]);
+      close(skfd);
+      exit(0);
+    }
+
+  /* Transmit Power list */
+  if(!strncmp(argv[2], "txpower", 3))
+    {
+      print_txpower_info(skfd, argv[1]);
+      close(skfd);
+      exit(0);
+    }
+
+#if WIRELESS_EXT > 10
+  /* Retry limit/lifetime */
+  if(!strncmp(argv[2], "retry", 4))
+    {
+      print_retry_info(skfd, argv[1]);
+      close(skfd);
+      exit(0);
+    }
+#endif
+
+  /* Close the socket. */
+  close(skfd);
+
+  return(1);
+}