OSDN Git Service

v24
[android-x86/external-wireless-tools.git] / wireless_tools / iwlist.c
index 30640e6..0703f3e 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #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;
 
+  /* 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);
@@ -55,6 +61,7 @@ print_freq_info(int           skfd,
        printf("%-8.8s  %d channels\n\n",
               ifname, range.num_channels);
     }
+  return(0);
 }
 
 /************************ ACCESS POINT LIST ************************/
@@ -64,9 +71,11 @@ print_freq_info(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) +
@@ -80,6 +89,9 @@ print_ap_info(int     skfd,
   int          n;
   int          i;
 
+  /* Avoid "Unused parameter" warning */
+  args = args; count = count;
+
   /* Collect stats */
   wrq.u.data.pointer = (caddr_t) buffer;
   wrq.u.data.length = IW_MAX_AP;
@@ -87,7 +99,7 @@ print_ap_info(int     skfd,
   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 */
@@ -102,7 +114,7 @@ print_ap_info(int   skfd,
   if(iw_check_mac_addr_type(skfd, ifname) < 0)
     {
       fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n\n", ifname);
-      return;
+      return(-2);
     }
 
   /* Get range info if we can */
@@ -128,6 +140,7 @@ print_ap_info(int   skfd,
        printf("    %s\n", iw_pr_ether(temp, hwa[i].sa_data));
     }
   printf("\n");
+  return(0);
 }
 
 /***************************** BITRATES *****************************/
@@ -136,13 +149,18 @@ print_ap_info(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(iw_get_range_info(skfd, ifname, &range) < 0)
@@ -157,21 +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);
     }
+  return(0);
 }
 
 /************************* ENCRYPTION KEYS *************************/
@@ -180,9 +193,11 @@ print_bitrate_info(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;
@@ -190,6 +205,9 @@ print_keys_info(int         skfd,
   int                  k;
   char                 buffer[128];
 
+  /* Avoid "Unused parameter" warning */
+  args = args; count = count;
+
   /* Extract range info */
   if(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no encryption keys information.\n\n",
@@ -241,7 +259,7 @@ print_keys_info(int         skfd,
       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);
@@ -252,6 +270,7 @@ print_keys_info(int         skfd,
 
       printf("\n\n");
     }
+  return(0);
 }
 
 /************************* POWER MANAGEMENT *************************/
@@ -285,14 +304,19 @@ 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(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no power management information.\n\n",
@@ -365,11 +389,11 @@ print_pm_info(int         skfd,
 
              /* Let's check the mode */
              iw_print_pm_mode(buffer, flags);
-             printf("Current%s", buffer);
+             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 */
@@ -415,6 +439,7 @@ print_pm_info(int           skfd,
        }
       printf("\n");
     }
+  return(0);
 }
 
 /************************** TRANSMIT POWER **************************/
@@ -423,15 +448,20 @@ print_pm_info(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(iw_get_range_info(skfd, ifname, &range) < 0)
@@ -464,6 +494,7 @@ print_txpower_info(int              skfd,
        printf("%-8.8s  No transmit-powers ? Please update driver...\n\n", ifname);
     }
 #endif /* WIRELESS_EXT > 9 */
+  return(0);
 }
 
 /*********************** RETRY LIMIT/LIFETIME ***********************/
@@ -499,14 +530,19 @@ 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(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no retry limit/lifetime information.\n\n",
@@ -606,74 +642,360 @@ print_retry_info(int             skfd,
        }
       printf("\n");
     }
+  return(0);
 }
 
 #endif /* WIRELESS_EXT > 10 */
 
-/************************* COMMON UTILITIES *************************/
+/***************************** SCANNING *****************************/
 /*
- * This section was written by Michael Tokarev <mjt@tls.msk.ru>
+ * This one behave quite differently from the others
+ */
+#if WIRELESS_EXT > 13
+/*------------------------------------------------------------------*/
+/*
+ * Print one element from the scanning results
  */
+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         buffer[128];    /* Temporary buffer */
+
+  /* Now, let's decode the event */
+  switch(event->cmd)
+    {
+    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);
+}
 
 /*------------------------------------------------------------------*/
 /*
- * Enumerate devices and call specified routine
+ * Perform a scanning on one device
  */
-static void
-enum_devices(int skfd, void (*fn)(int skfd, char *ifname))
+static int
+print_scanning_info(int                skfd,
+                   char *      ifname,
+                   char *      args[],         /* Command line args */
+                   int         count)          /* Args count */
 {
-  char         buff[1024];
-  struct ifconf ifc;
-  struct ifreq *ifr;
-  int i;
+  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)
+    {
+      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;
+
+  /* Forever */
+  while(1)
+    {
+      fd_set           rfds;           /* File descriptors for select */
+      int              last_fd;        /* Last fd */
+      int              ret;
+
+      /* Guess what ? We must re-generate rfds each time */
+      FD_ZERO(&rfds);
+      last_fd = -1;
+
+      /* In here, add the rtnetlink fd in the list */
+
+      /* Wait until something happens */
+      ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
+
+      /* Check if there was an error */
+      if(ret < 0)
+       {
+         if(errno == EAGAIN || errno == EINTR)
+           continue;
+         fprintf(stderr, "Unhandled signal - exiting...\n");
+         return(-1);
+       }
+
+      /* 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 */
+    }
 
-  /* Get list of active devices */
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
+  if(wrq.u.data.length)
     {
-      fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
-      return;
+      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");
     }
-  ifr = ifc.ifc_req;
+  else
+    printf("%-8.8s  No scan results\n", ifname);
 
-  /* Print them */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    (*fn)(skfd, ifr->ifr_name);
+  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;
-  void (*fn)(int skfd, char *ifname);
+  iw_enum_handler fn;
+  int min_count;
+  int max_count;
 } iwlist_cmd;
 
 static const struct iwlist_entry iwlist_cmds[] = {
-  { "frequency",    print_freq_info },
-  { "channel",      print_freq_info },
-  { "ap",           print_ap_info },
-  { "accesspoints", print_ap_info },
-  { "bitrate",      print_bitrate_info },
-  { "rate",         print_bitrate_info },
-  { "encryption",   print_keys_info },
-  { "key",          print_keys_info },
-  { "power",        print_pm_info },
-  { "txpower",      print_txpower_info },
+  { "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",        print_retry_info },
+  { "retry",           print_retry_info,       0, 0 },
 #endif
-  { NULL, 0 },
+#if WIRELESS_EXT > 13
+  { "scanning",                print_scanning_info,    0, 5 },
+#endif
+  { NULL, NULL, 0, 0 },
 };
 
-/* Display help */
-static void usage(FILE *f)
+/*------------------------------------------------------------------*/
+/*
+ * Find the most appropriate command matching the command line
+ */
+static inline const iwlist_cmd *
+find_command(const char *      cmd)
 {
-  int i;
+  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)
-    fprintf(f, "%s [interface] %s\n",
-            i ? "             " :
-                "Usage: iwlist",
-            iwlist_cmds[i].cmd);
+    {
+      /* 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;
+    }
+
+  if(found == NULL)
+    {
+      fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
+      return NULL;
+    }
+
+  if(ambig)
+    {
+      fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
+      return NULL;
+    }
+
+  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 ********************************/
@@ -686,63 +1008,50 @@ int
 main(int       argc,
      char **   argv)
 {
-  int skfd = -1;               /* generic raw socket desc.     */
+  int skfd;                    /* generic raw socket desc.     */
   char *dev;                   /* device name                  */
   char *cmd;                   /* command                      */
-  int i;
+  char **args;                 /* Command arguments */
+  int count;                   /* Number of arguments */
+  const iwlist_cmd *iwcmd;
 
   if(argc == 1 || argc > 3)
-    {
-      usage(stderr);
-      return 1;
-    }
+    iw_usage(1);
+
   if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
-    {
-      usage(stdout);
-      return 0;
-    }
+    iw_usage(0);
+
   if (argc == 2)
     {
       cmd = argv[1];
       dev = NULL;
+      args = NULL;
+      count = 0;
     }
   else
     {
       cmd = argv[2];
       dev = argv[1];
+      args = argv + 3;
+      count = argc - 3;
     }
 
   /* find a command */
-  {
-    int found = -1, ambig = 0;
-    int len = strlen(cmd);
-    for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
-      {
-       if (strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
-         continue;
-       if (len == strlen(iwlist_cmds[i].cmd))  /* exact match */
-         {
-           found = i;
-           ambig = 0;
-           break;
-         }
-       if (found < 0)
-         found = i;
-       else if (iwlist_cmds[i].fn != iwlist_cmds[found].fn)
-         ambig = 1;
-      }
-    if (found < 0)
-      {
-       fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
-       return 1;
-      }
-    if (ambig)
-      {
-       fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
-       return 1;
-      }
-    i = found;
-  }
+  iwcmd = find_command(cmd);
+  if(iwcmd == NULL)
+    return 1;
+
+  /* Check arg numbers */
+  if(count < iwcmd->min_count)
+    {
+      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;
+    }
 
   /* Create a channel to the NET kernel. */
   if((skfd = iw_sockets_open()) < 0)
@@ -753,9 +1062,9 @@ main(int   argc,
 
   /* do the actual work */
   if (dev)
-    (*iwlist_cmds[i].fn)(skfd, dev);
+    (*iwcmd->fn)(skfd, dev, args, count);
   else
-    enum_devices(skfd, iwlist_cmds[i].fn);
+    iw_enum_devices(skfd, iwcmd->fn, args, count);
 
   /* Close the socket. */
   close(skfd);