OSDN Git Service

v24
authorchris-kirby <chris.kirby@hpe.com>
Tue, 11 Oct 2016 21:03:11 +0000 (15:03 -0600)
committerchris-kirby <chris.kirby@hpe.com>
Tue, 11 Oct 2016 21:03:11 +0000 (15:03 -0600)
20 files changed:
wireless_tools/CHANGELOG.h
wireless_tools/INSTALL
wireless_tools/Makefile
wireless_tools/README
wireless_tools/iwconfig.8
wireless_tools/iwconfig.c
wireless_tools/iwevent.8 [new file with mode: 0644]
wireless_tools/iwevent.c [new file with mode: 0644]
wireless_tools/iwgetid.8 [new file with mode: 0644]
wireless_tools/iwgetid.c
wireless_tools/iwlib.c
wireless_tools/iwlib.h
wireless_tools/iwlist.8
wireless_tools/iwlist.c
wireless_tools/iwpriv.c
wireless_tools/iwspy.c
wireless_tools/macaddr.c
wireless_tools/wireless.13.h [new file with mode: 0644]
wireless_tools/wireless.14.h [new file with mode: 0644]
wireless_tools/wireless.h

index 67093d6..cffb6b2 100644 (file)
  *     o Add "commit" to force parameters on the card [iwconfig]
  *     o Wrap ioctl() in iw_set/get_ext() wrappers [all]
  *     o Beautify set request error messages [iwconfig]
+ *
+ * wireless 24 :
+ * -----------
+ *     o Added common function to display frequency [iwlib]
+ *     o Added handler to parse Wireless Events [iwlib]
+ *     o Added tool to display Wireless Events [iwevent]
+ *     o Pass command line to subroutines [iwlist]
+ *     o Scanning support through SIOCSIWSCAN [iwlist]
+ *     ---
+ *     o Added common function to display bitrate [iwlib]
+ *     o Add bitrate/encoding scanning support [iwlist]
+ *     o Allow to read scan results for non-root users [iwlist]
+ *     o Set 5s timeout on waiting for scan results [iwlist]
+ *     o Cleanup iwgetid & support ap+scheme display [iwgetid]
+ *     o iwevent man page [iwevent]
+ *             (From Guus Sliepen <guus@warande3094.warande.uu.nl>)
+ *     o iwgetid man page [iwgetid]
+ *     ---
+ *     o Add "#define WIRELESS_EXT > 13" around event code [iwlib]
+ *     o Move iw_enum_devices() from iwlist.c to iwlib.c [iwlib]
+ *     o Use iw_enum_devices() everywhere [iwconfig/iwspy/iwpriv]
+ *             (From Pavel Roskin <proski@gnu.org>, rewrite by me)
+ *     o Return proper error message on non existent interfaces [iwconfig]
+ *     o Read interface list in /proc/net/wireless and not SIOCGIFCONF [iwlib]
+ *     ---
+ *             (From Pavel Roskin <proski@gnu.org> - again !!!)
+ *     o Don't loose flags when setting encryption key [iwconfig]
+ *     o Add <time.h> [iwevent]
+ *     ---
+ *             (From Casey Carter <Casey@Carter.net>)
+ *     o Improved compilations directives, stricter warnings [Makefile]
+ *     o Fix strict warnings (static func, unused args...) [various]
+ *     o New routines to display/input Ethernet MAC addresses [iwlib]
+ *     o Correct my english & spelling [various]
+ *     o Get macaddr to compile [macaddr]
+ *     o Fix range checking in max number of args [iwlist]
+ *     ---
+ *     o Display time when we receive event [iwevent]
+ *     ---
+ *     o Display time before event, easier to read [iwevent]
+ *             (From "Dr. Michael Rietz" <rietz@mail.amps.de>)
+ *     o Use a generic set of header, may end header mess [iwlib]
+ *             (From Casey Carter <Casey@Carter.net>)
+ *     o Zillions cleanups, small fixes and code reorg [all over]
+ *     o Proper usage/help printout [iwevent, iwgetid, ...]
+ *     ---
+ *     o Send broadcast address for iwconfig ethX ap auto/any [iwconfig]
+ *     ---
+ *     o Send NULL address for iwconfig ethX ap off [iwconfig]
+ *     o Add iw_in_key() helper (and use it) [iwlib]
+ *     o Create symbolink link libiw.so to libiw.so.XX [Makefile]
+ *             (From Javier Achirica <achirica@ttd.net>)
+ *     o Always send TxPower flags to the driver [iwconfig]
+ *             (From John M. Choi <johnchoi@its.caltech.edu>)
+ *     o Header definition for Slackware (kernel 2.2/glibc 2.2) [iwlib]
  */
 
 /* ----------------------------- TODO ----------------------------- */
  *
  * iwspy :
  * -----
- *     -
+ *     Add an "auto" flag to have the driver cache the last n results
+ *
+ * iwlist :
+ * ------
+ *     Add scanning command line modifiers
+ *     More scan types support
+ *
+ * iwevent :
+ * -------
+ *     Make it non root-only
  *
  * Doc & man pages :
  * ---------------
index efa4eca..cf2b323 100644 (file)
@@ -73,6 +73,7 @@ the tools from compiling.
        The trick is to copy the file .../include/linux/wireless.h
 from the kernel to the /usr/include headers.
        A similar procedure may be used to update Wireless Extensions
-in an older kernel...
+in an older kernel, but you may want to be careful because from time
+to time changes are required in the kernel as well...
 
        Jean <jt@hpl.hp.com>
index f4e0fcf..5de0c9a 100644 (file)
@@ -4,19 +4,25 @@
 
 # Targets to build
 STATIC=libiw.a
-DYNAMIC=libiw.so.23
-PROGS= iwconfig iwlist iwpriv iwspy iwgetid
-MANPAGES=iwconfig.8 iwlist.8 iwpriv.8 iwspy.8
+DYNAMIC=libiw.so.24
+PROGS= iwconfig iwlist iwpriv iwspy iwgetid iwevent
+MANPAGES=iwconfig.8 iwlist.8 iwpriv.8 iwspy.8 iwgetid.8 iwevent.8
 
 # Composition of the library :
 OBJS = iwlib.o
 
 # Define if tools should be built using static or dynamic version of the lib
-IWLIBS=$(OBJS)
-#IWLIBS=-liw
+IWLIB=$(STATIC)
+#IWLIB=$(DYNAMIC)
+
+# Standard name for dynamic library so that the dynamic linker can pick it.
+# We will just create a symbolic link to the real thing.
+DYNAMIC_LINK= libiw.so
 
 # Installation directory. By default, go in local.
 # Distributions should probably use /usr/sbin, but they probably know better...
+# Don't forget trailing slash to avoid issues
+
 INSTALL_DIR= /usr/local/sbin/
 INSTALL_LIB= /usr/local/lib/
 INSTALL_INC= /usr/local/include/
@@ -36,35 +42,41 @@ WE_HEADER=
 CC = gcc
 RM = rm -f
 
-RM_CMD = $(RM) *.BAK *.bak *.o ,* *~ *.a
+RM_CMD = $(RM) *.BAK *.bak *.o *.so ,* *~ *.a *.orig *.rej
 
-CFLAGS=-O2 -Wall $(HEADERS) $(WE_HEADER)
+#CFLAGS=-O2 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror
+CFLAGS=-O2 -W -Wall -Wstrict-prototypes
+XCFLAGS=$(CFLAGS) $(WARN) $(HEADERS) $(WE_HEADER)
+PICFLAG=-fPIC
 
-LIBS=$(IWLIBS) -lm
+LIBS= -lm
 
 all:: $(STATIC) $(DYNAMIC) $(PROGS)
 
-.c.o:
-       $(CC) $(CFLAGS) -c $<
+%: %.o
+       $(CC) $(XCFLAGS) -o $@ $^ $(LIBS)
+%.o: %.c
+       $(CC) $(XCFLAGS) -c $<
+%.so: %.c
+       $(CC) $(XCFLAGS) $(PICFLAG) -c -o $@ $<
 
-iwconfig: iwconfig.o $(OBJS)
-       $(CC) $(CFLAGS) -o $@ $< $(LIBS)
+iwconfig: iwconfig.o $(IWLIB)
 
-iwlist: iwlist.o $(OBJS)
-       $(CC) $(CFLAGS) -o $@ $< $(LIBS)
+iwlist: iwlist.o $(IWLIB)
 
-iwpriv: iwpriv.o $(OBJS)
-       $(CC) $(CFLAGS) -o $@ $< $(LIBS)
+iwpriv: iwpriv.o $(IWLIB)
 
-iwspy: iwspy.o $(OBJS)
-       $(CC) $(CFLAGS) -o $@ $< $(LIBS)
+iwspy: iwspy.o $(IWLIB)
 
 iwgetid: iwgetid.o
-       $(CC) $(CFLAGS) -o $@ $^
+
+iwevent: iwevent.o $(IWLIB)
+
+macaddr: macaddr.o $(IWLIB)
 
 # Compilation of the dynamic library
-$(DYNAMIC): $(OBJS)
-       $(CC) -O2 -shared -o $@ -Wl,-soname,$@ -lm -lc $^
+$(DYNAMIC): $(OBJS:.o=.so)
+       $(CC) -shared -o $@ -Wl,-soname,$@ -lm -lc $^
 
 # Compilation of the static library
 $(STATIC): $(OBJS)
@@ -78,7 +90,8 @@ install::
        install -m 755 $(PROGS) $(INSTALL_DIR)
        install -m 644 $(STATIC) $(INSTALL_LIB)
        install -m 755 $(DYNAMIC) $(INSTALL_LIB)
-       echo "Don't forget to fix your /etc/ld.so.conf and run ldconfig."
+       ln -s $(INSTALL_LIB)/$(DYNAMIC) $(INSTALL_LIB)/$(DYNAMIC_LINK)
+       echo "Don't forget to add $(INSTALL_LIB) to /etc/ld.so.conf, and run ldconfig."
        install -m 644 iwlib.h $(INSTALL_INC)
        install -m 644 $(MANPAGES) $(INSTALL_MAN)/man8/
 
@@ -87,7 +100,7 @@ clean::
 
 realclean::
        $(RM_CMD) 
-       $(RM) $(STATIC) $(DYNAMIC) $(PROGS)
+       $(RM) $(STATIC) $(DYNAMIC) $(PROGS) macaddr
 
 depend::
        makedepend -s "# DO NOT DELETE" -- $(INCLUDES) -- $(SRCS)
index 7ac44ab..9391e28 100644 (file)
@@ -15,6 +15,7 @@ web page
 INSTALL
 -------
        This file contains installation instruction and requirements.
+       A *must* read.
 
 PCMCIA.txt
 ----------
@@ -26,7 +27,7 @@ man pages (iwconfig.8, iwlist.8, iwpriv.8, iwspy.8)
        VERY IMPORTANT : I try to keep the man page up to date, so
 you'd better read them before asking questions.
        ALSO IMPORTANT : Those man pages describe the capacity of the
-tools, no device implement the full range (and driver usually
+tools, no device implement the full range (and drivers usually
 implement even less).
 
        As far as I know, the man pages are the most complete, up to
@@ -64,23 +65,33 @@ iwgetid.c
        Output the ESSID or NWID of the specified device.
        Can also output it in a form that can be used as a Pcmcia Scheme.
 
+iwevent.c
+---------
+       Display Wireless Events. This is new, so there is not much support
+in drivers for it yet...
+
 Changelog, contributions
 ------------------------
-       See iwcommon.h
+       See CHANGELOG.h
 
 wireless.h
 ----------
        Definition of the Wireless Extensions. You may drop this file
 in your kernel headers to update the Wireless Extensions.
+       Just for your enjoyement, there is various release of it. If
+your kernel/drivers are old, you may want to try the older releases...
 
 Other tools :
 -----------
-       My web page above list many other tools using Wireless
+       My web page list many other tools using Wireless
 Extensions that you may find useful...
+       http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html#links
 
+Other questions :
+---------------
+       You have the source, and it is documented. In 99% of the case,
+you will find your answer there.
 
-       The list of changes, credits and errata notes are in
-iwcommon.h. Compilation might be tricky, see iwcommon.h for header
-problems...
+       Good luck...
 
        Jean <jt@hpl.hp.com>
index 814861f..1e8f323 100644 (file)
@@ -135,13 +135,27 @@ topology. The mode can be
 .I "   iwconfig eth0 mode Managed"
 .TP
 .B ap
-Register to the Access Point given by the address, if it is
-possible. When the quality of the connection goes too low, the driver
-may revert back to automatic mode.
+Force the card to register to the Access Point given by the address,
+if it is possible. When the quality of the connection goes too low,
+the driver may revert back to automatic mode (the card finds the best
+Access Point in range).
+.br
+You may also use
+.I off
+to re-enable automatic mode without changing the current Access Point,
+or you may use
+.I any
+or
+.I auto
+to force the card to reassociate with the current best Access Point.
 .br
 .B Example :
 .br
 .I "   iwconfig eth0 ap 00:60:1D:01:23:45"
+.br
+.I "   iwconfig eth0 ap any"
+.br
+.I "   iwconfig eth0 ap off"
 .TP
 .BR nick [name]
 Set the nickname, or the station name. Most 802.11 products do define
@@ -175,6 +189,8 @@ the driver will use all bit lower and equal than this value.
 .I "   iwconfig eth0 rate 11M"
 .br
 .I "   iwconfig eth0 rate auto"
+.br
+.I "   iwconfig eth0 rate 5.5M auto"
 .TP
 .BR rts [_threshold]
 RTS/CTS adds a handshake before each packet transmission to make sure
@@ -330,8 +346,8 @@ is the short retry limit (non RTS/CTS packets).
 .BR commit
 Some cards may not apply changes done through Wireless Extensions
 immediately (they may wait to agregate the changes or apply it only
-when the card is brought up). This command (when available) force
-the card to apply all pending changes.
+when the card is brought up via ifconfig). This command (when
+available) force the card to apply all pending changes.
 .br
 This is normally not needed, because the card will eventually apply
 the changes, but can be usefull for debugging.
index 5b38484..73e7ec1 100644 (file)
@@ -57,8 +57,17 @@ get_info(int                 skfd,
 
   /* Get wireless name */
   if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
-    /* If no wireless name : no wireless extensions */
-    return(-1);
+    {
+      /* If no wireless name : no wireless extensions */
+      /* But let's check if the interface exists at all */
+      struct ifreq ifr;
+
+      strcpy(ifr.ifr_name, ifname);
+      if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
+       return(-ENODEV);
+      else
+       return(-ENOTSUP);
+    }
   else
     strcpy(info->name, wrq.u.name);
 
@@ -147,9 +156,9 @@ get_info(int                        skfd,
   /* Get operation mode */
   if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
     {
-      if((wrq.u.mode < IW_NUM_OPER_MODE) && (wrq.u.mode >= 0))
-       info->has_mode = 1;
       info->mode = wrq.u.mode;
+      if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
+       info->has_mode = 1;
     }
 
   /* Get Power Management settings */
@@ -198,7 +207,7 @@ display_info(struct wireless_info * info,
 {
   char         buffer[128];    /* Temporary buffer */
 
-  /* One token is more of less 5 character, 14 tokens per line */
+  /* One token is more of less 5 characters, 14 tokens per line */
   int  tokens = 3;     /* For name */
 
   /* Display device name and wireless name (name of the protocol used) */
@@ -253,20 +262,8 @@ display_info(struct wireless_info *        info,
   /* Display frequency / channel */
   if(info->has_freq)
     {
-      if(info->freq < KILO)
-       printf("Channel:%g  ", info->freq);
-      else
-       {
-         if(info->freq >= GIGA)
-           printf("Frequency:%gGHz  ", info->freq / GIGA);
-         else
-           {
-             if(info->freq >= MEGA)
-               printf("Frequency:%gMHz  ", info->freq / MEGA);
-             else
-               printf("Frequency:%gkHz  ", info->freq / KILO);
-           }
-       }
+      iw_print_freq(buffer, info->freq);
+      printf("%s  ", buffer);
       tokens +=4;
     }
 
@@ -300,20 +297,9 @@ display_info(struct wireless_info *        info,
        }
       tokens +=3;
 
-      /* Fixed ? */
-      if(info->bitrate.fixed)
-       printf("Bit Rate=");
-      else
-       printf("Bit Rate:");
-
-      if(info->bitrate.value >= GIGA)
-       printf("%gGb/s", info->bitrate.value / GIGA);
-      else
-       if(info->bitrate.value >= MEGA)
-         printf("%gMb/s", info->bitrate.value / MEGA);
-       else
-         printf("%gkb/s", info->bitrate.value / KILO);
-      printf("   ");
+      /* Display it */
+      iw_print_bitrate(buffer, info->bitrate.value);
+      printf("Bit Rate%c%s   ", (info->bitrate.fixed ? '=' : ':'), buffer);
     }
 
 #if WIRELESS_EXT > 9
@@ -498,7 +484,7 @@ display_info(struct wireless_info * info,
          if(info->power.flags & IW_POWER_TYPE)
            {
              iw_print_pm_value(buffer, info->power.value, info->power.flags);
-             printf("%s", buffer);
+             printf("%s  ", buffer);
            }
 
          /* Let's check the mode */
@@ -543,48 +529,35 @@ display_info(struct wireless_info *       info,
  * Print on the screen in a neat fashion all the info we have collected
  * on a device.
  */
-static void
+static int
 print_info(int         skfd,
-          char *       ifname)
+          char *       ifname,
+          char *       args[],
+          int          count)
 {
   struct wireless_info info;
+  int                  rc;
+
+  /* Avoid "Unused parameter" warning */
+  args = args; count = count;
 
-  if(get_info(skfd, ifname, &info) < 0)
+  rc = get_info(skfd, ifname, &info);
+  switch(rc)
     {
+    case 0:    /* Success */
+      /* Display it ! */
+      display_info(&info, ifname);
+      break;
+
+    case -ENOTSUP:
       fprintf(stderr, "%-8.8s  no wireless extensions.\n\n",
              ifname);
-      return;
-    }
-
-  /* Display it ! */
-  display_info(&info, ifname);
-}
+      break;
 
-/*------------------------------------------------------------------*/
-/*
- * Get info on all devices and print it on the screen
- */
-static void
-print_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;
+    default:
+      fprintf(stderr, "%-8.8s  %s\n\n", ifname, strerror(-rc));
     }
-  ifr = ifc.ifc_req;
-
-  /* Print them */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    print_info(skfd, ifr->ifr_name);
+  return(rc);
 }
 
 /************************* SETTING ROUTINES **************************/
@@ -771,62 +744,23 @@ set_info(int              skfd,           /* The socket */
            }
          else
            {
-             char *    buff;
-             char *    p;
-             int               temp;
-             int               k = 0;
-             int               gotone = 1;
+             int       gotone = 1;
+             int       keylen;
+             int       temp;
 
              wrq.u.data.pointer = (caddr_t) NULL;
              wrq.u.data.flags = 0;
              wrq.u.data.length = 0;
 
              /* -- Check for the key -- */
-             if(!strncmp(args[i], "s:", 2))
+             keylen = iw_in_key(args[i], key);
+             if(keylen > 0)
                {
-                 /* First case : as an ASCII string */
-                 wrq.u.data.length = strlen(args[i] + 2);
-                 if(wrq.u.data.length > IW_ENCODING_TOKEN_MAX)
-                   wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
-                 strncpy(key, args[i] + 2, wrq.u.data.length);
+                 wrq.u.data.length = keylen;
                  wrq.u.data.pointer = (caddr_t) key;
                  ++i;
                  gotone = 1;
                }
-             else
-               {
-                 /* Second case : as hexadecimal digits */
-                 buff = malloc(strlen(args[i]) + 1);
-                 if(buff == NULL)
-                   {
-                     fprintf(stderr, "Set Encode : Malloc failed (string too long ?)\n");
-                     return(-10);
-                   }
-                 strcpy(buff, args[i]);
-
-                 p = strtok(buff, "-:;.,");
-                 while((p != (char *) NULL) && (k < IW_ENCODING_TOKEN_MAX))
-                   {
-                     if(sscanf(p, "%2X", &temp) != 1)
-                       {
-                         gotone = 0;
-                         break;
-                       }
-                     key[k++] = (unsigned char) (temp & 0xFF);
-                     if(strlen(p) > 2) /* Token not finished yet */
-                       p += 2;
-                     else
-                       p = strtok((char *) NULL, "-:;.,");
-                   }
-                 free(buff);
-
-                 if(gotone)
-                   {
-                     ++i;
-                     wrq.u.data.length = k;
-                     wrq.u.data.pointer = (caddr_t) key;
-                   }
-               }
 
              /* -- Check for token index -- */
              if((i < count) &&
@@ -855,7 +789,7 @@ set_info(int                skfd,           /* The socket */
                }
              /* Pointer is absent in new API */
              if(wrq.u.data.pointer == NULL)
-               wrq.u.data.flags = IW_ENCODE_NOKEY;
+               wrq.u.data.flags |= IW_ENCODE_NOKEY;
 
              if(!gotone)
                ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]);
@@ -927,9 +861,26 @@ set_info(int               skfd,           /* The socket */
          if(++i >= count)
            ABORT_ARG_NUM("Set AP Address", SIOCSIWAP);
 
-         /* Get the address and check if the interface supports it */
-         if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
-           ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]);
+         if((!strcasecmp(args[i], "auto")) ||
+            (!strcasecmp(args[i], "any")))
+           {
+             /* Send a broadcast address */
+             iw_broad_ether(&(wrq.u.ap_addr));
+           }
+         else
+           {
+             if(!strcasecmp(args[i], "off"))
+               {
+                 /* Send a NULL address */
+                 iw_null_ether(&(wrq.u.ap_addr));
+               }
+             else
+               {
+                 /* Get the address and check if the interface supports it */
+                 if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
+                   ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]);
+               }
+           }
 
          IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq,
                         "Set AP Address");
@@ -1243,13 +1194,18 @@ set_info(int            skfd,           /* The socket */
                    ismwatt = (index(args[i], 'm') != NULL);
 
                    /* Convert */
-                   if(!ismwatt && (range.txpower_capa & IW_TXPOW_MWATT))
+                   if(range.txpower_capa & IW_TXPOW_MWATT)
                      {
-                       power = iw_dbm2mwatt(power);
+                       if(!ismwatt)
+                         power = iw_dbm2mwatt(power);
                        wrq.u.data.flags = IW_TXPOW_MWATT;
                      }
-                   if(ismwatt && !(range.txpower_capa & IW_TXPOW_MWATT))
-                     power = iw_mwatt2dbm(power);
+                   else
+                     {
+                       if(ismwatt)
+                         power = iw_mwatt2dbm(power);
+                       wrq.u.data.flags = IW_TXPOW_DBM;
+                     }
                    wrq.u.bitrate.value = power;
 
                    /* Check for an additional argument */
@@ -1364,7 +1320,7 @@ int
 main(int       argc,
      char **   argv)
 {
-  int skfd = -1;               /* generic raw socket desc.     */
+  int skfd;            /* generic raw socket desc.     */
   int goterr = 0;
 
   /* Create a channel to the NET kernel. */
@@ -1376,31 +1332,19 @@ main(int        argc,
 
   /* No argument : show the list of all device + info */
   if(argc == 1)
-    {
-      print_devices(skfd);
-      close(skfd);
-      exit(0);
-    }
-
-  /* Special case for help... */
-  if((!strncmp(argv[1], "-h", 9)) ||
-     (!strcmp(argv[1], "--help")))
-    {
+    iw_enum_devices(skfd, &print_info, NULL, 0);
+  else
+    /* Special case for help... */
+    if((!strncmp(argv[1], "-h", 9)) ||
+       (!strcmp(argv[1], "--help")))
       iw_usage();
-      close(skfd);
-      exit(0);
-    }
-
-  /* The device name must be the first argument */
-  if(argc == 2)
-    {
-      print_info(skfd, argv[1]);
-      close(skfd);
-      exit(0);
-    }
-
-  /* The other args on the line specify options to be set... */
-  goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
+    else
+      /* The device name must be the first argument */
+      if(argc == 2)
+       print_info(skfd, argv[1], NULL, 0);
+      else
+       /* The other args on the line specify options to be set... */
+       goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
 
   /* Close the socket. */
   close(skfd);
diff --git a/wireless_tools/iwevent.8 b/wireless_tools/iwevent.8
new file mode 100644 (file)
index 0000000..2a73d6d
--- /dev/null
@@ -0,0 +1,89 @@
+.\" Jean Tourrilhes - HPL - 2002
+.\" iwevent.8
+.\"
+.TH IWEVENT 8 "25 January 2002" "net-tools" "Linux Programmer's Manual"
+.\"
+.\" NAME part
+.\"
+.SH NAME
+iwevent \- Display Wireless Events generated by drivers and setting changes
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.BI "iwevent "
+.br
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B iwevent
+display Wireless Events received through the RTNetlink socket. Each
+line display the specific Wireless Event which describe what has
+happened on the specified wireless interface.
+.br
+This command doesn't take any arguments.
+.\"
+.\" DISPLAY part
+.\"
+.SH DISPLAY
+There is two classes of Wireless Events.
+.PP
+The first class is events related to a change of wireless settings on
+the interface (typically done through
+.B iwconfig
+or a script calling
+.BR iwconfig ).
+Only settings that could result in a disruption of connectivity are
+reported. The events currently reported are changing one of the
+following setting :
+.br
+.I "   Network ID"
+.br
+.I "   ESSID"
+.br
+.I "   Frequency"
+.br
+.I "   Mode"
+.br
+.I "   Encryption"
+.br
+All those events will be generated on all wireless interfaces by the
+kernel wireless subsystem (but only if the driver has been converted
+to the new driver API).
+.PP
+The second class of events are events generated by the hardware, when
+something happens or a task has been finished. Those events include :
+.TP
+.B New Access Point/Cell address
+The interface has joined a new Access Point or Ad-Hoc Cell, or lost
+its association with it. This is the same MAC address that is reported
+by
+.BR iwconfig .
+.TP
+.B Scan request completed
+A scanning request has been completed, results of the scan are
+available (see
+.BR iwlist ).
+.TP
+.B Tx packet dropped
+A packet directed at this address has been dropped because the card
+believes this node doesn't answer anymore. An early indication that
+the node may have left the cell or gone out of range.
+.PP
+Only some of those events will be generated on some wireless
+interfaces by the wireless driver, and their support depend on the
+specific hardware/driver combination.
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTHOR
+Jean Tourrilhes \- jt@hpl.hp.com
+.\"
+.\" SEE ALSO part
+.\"
+.SH SEE ALSO
+.BR iwconfig (8),
+.BR ifconfig (8),
+.BR iwspy (8),
+.BR iwpriv (8).
diff --git a/wireless_tools/iwevent.c b/wireless_tools/iwevent.c
new file mode 100644 (file)
index 0000000..6a1de90
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+ *     Wireless Tools
+ *
+ *             Jean II - HPL 99->01
+ *
+ * Main code for "iwevent". This listent for wireless events on rtnetlink.
+ * You need to link this code against "iwcommon.c" and "-lm".
+ *
+ * Part of this code is from Alexey Kuznetsov, part is from Casey Carter,
+ * I've just put the pieces together...
+ * By the way, if you know a way to remove the root restrictions, tell me
+ * about it...
+ *
+ * This file is released under the GPL license.
+ *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ */
+
+/***************************** INCLUDES *****************************/
+
+#include "iwlib.h"             /* Header */
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <getopt.h>
+#include <time.h>
+#include <sys/time.h>
+
+/************************ RTNETLINK HELPERS ************************/
+/*
+ * The following code is extracted from :
+ * ----------------------------------------------
+ * libnetlink.c        RTnetlink service routines.
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ * -----------------------------------------------
+ */
+
+struct rtnl_handle
+{
+       int                     fd;
+       struct sockaddr_nl      local;
+       struct sockaddr_nl      peer;
+       __u32                   seq;
+       __u32                   dump;
+};
+
+static inline void rtnl_close(struct rtnl_handle *rth)
+{
+       close(rth->fd);
+}
+
+static inline int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
+{
+       int addr_len;
+
+       memset(rth, 0, sizeof(rth));
+
+       rth->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+       if (rth->fd < 0) {
+               perror("Cannot open netlink socket");
+               return -1;
+       }
+
+       memset(&rth->local, 0, sizeof(rth->local));
+       rth->local.nl_family = AF_NETLINK;
+       rth->local.nl_groups = subscriptions;
+
+       if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
+               perror("Cannot bind netlink socket");
+               return -1;
+       }
+       addr_len = sizeof(rth->local);
+       if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
+               perror("Cannot getsockname");
+               return -1;
+       }
+       if (addr_len != sizeof(rth->local)) {
+               fprintf(stderr, "Wrong address length %d\n", addr_len);
+               return -1;
+       }
+       if (rth->local.nl_family != AF_NETLINK) {
+               fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
+               return -1;
+       }
+       rth->seq = time(NULL);
+       return 0;
+}
+
+/********************* WIRELESS EVENT DECODING *********************/
+/*
+ * This is the bit I wrote...
+ */
+
+#if WIRELESS_EXT > 13
+/*------------------------------------------------------------------*/
+/*
+ * Print one element from the scanning results
+ */
+static inline int
+print_event_token(struct iw_event *    event,  /* Extracted token */
+                 struct iw_range *     iwrange,        /* Range info */
+                 int                   has_range)
+{
+  char         buffer[128];    /* Temporary buffer */
+
+  /* Now, let's decode the event */
+  switch(event->cmd)
+    {
+      /* ----- set events ----- */
+      /* Events that result from a "SET XXX" operation by the user */
+    case SIOCSIWNWID:
+      if(event->u.nwid.disabled)
+       printf("NWID:off/any\n");
+      else
+       printf("NWID:%X\n", event->u.nwid.value);
+      break;
+    case SIOCSIWFREQ:
+      {
+       float           freq;                   /* Frequency/channel */
+       freq = iw_freq2float(&(event->u.freq));
+       iw_print_freq(buffer, freq);
+       printf("%s\n", buffer);
+      }
+      break;
+    case SIOCSIWMODE:
+      printf("Mode:%s\n",
+            iw_operation_mode[event->u.mode]);
+      break;
+    case SIOCSIWESSID:
+      {
+       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 SIOCSIWENCODE:
+      {
+       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;
+      /* ----- driver events ----- */
+      /* Events generated by the driver when something important happens */
+    case SIOCGIWAP:
+      printf("New Access Point/Cell address:%s\n",
+            iw_pr_ether(buffer, event->u.ap_addr.sa_data));
+      break;
+    case SIOCGIWSCAN:
+      printf("Scan request completed\n");
+      break;
+    case IWEVTXDROP:
+      printf("Tx packet dropped:%s\n",
+            iw_pr_ether(buffer, event->u.ap_addr.sa_data));
+      break;
+      /* ----- junk ----- */
+      /* other junk not currently in use */
+    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("Link %s\n", buffer);
+       break;
+      }
+    default:
+      printf("(Unknown Wireless event 0x%04X)\n", event->cmd);
+    }  /* switch(event->cmd) */
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print out all Wireless Events part of the RTNetlink message
+ * Most often, there will be only one event per message, but
+ * just make sure we read everything...
+ */
+static inline int
+print_event_stream(char *      ifname,
+                  char *       data,
+                  int          len)
+{
+  struct iw_event      iwe;
+  struct stream_descr  stream;
+  int                  i = 0;
+  int                  ret;
+  char                 buffer[64];
+  struct timeval       recv_time;
+#if 0
+  struct iw_range      range;
+  int                  has_range;
+#endif
+
+#if 0
+  has_range = (iw_get_range_info(skfd, ifname, &range) < 0);
+#endif
+
+  /* In readable form */
+  gettimeofday(&recv_time, NULL);
+  iw_print_timeval(buffer, &recv_time);
+
+  iw_init_event_stream(&stream, data, len);
+  do
+    {
+      /* Extract an event and print it */
+      ret = iw_extract_event_stream(&stream, &iwe);
+      if(ret != 0)
+       {
+         if(i++ == 0)
+           printf("%s   %-8.8s ", buffer, ifname);
+         else
+           printf("                           ");
+         if(ret > 0)
+           print_event_token(&iwe, NULL, 0);
+         else
+           printf("(Invalid event)\n");
+       }
+    }
+  while(ret > 0);
+
+  return(0);
+}
+#endif /* WIRELESS_EXT > 13 */
+
+/*********************** RTNETLINK EVENT DUMP***********************/
+/*
+ * Dump the events we receive from rtnetlink
+ * This code is mostly from Casey
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Respond to a single RTM_NEWLINK event from the rtnetlink socket.
+ */
+static inline int
+index2name(int index, char *name)
+{
+  int          skfd = -1;      /* generic raw socket desc.     */
+  struct ifreq irq;
+  int          ret = 0;
+
+  memset(name, 0, IFNAMSIZ + 1);
+
+  /* Create a channel to the NET kernel. */
+  if((skfd = iw_sockets_open()) < 0)
+    {
+      perror("socket");
+      exit(-1);
+    }
+
+  /* Get interface name */
+  irq.ifr_ifindex = index;
+  if(ioctl(skfd, SIOCGIFNAME, &irq) < 0)
+    ret = -1;
+  else
+    strncpy(name, irq.ifr_name, IFNAMSIZ);
+
+  close(skfd);
+  return(ret);
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Respond to a single RTM_NEWLINK event from the rtnetlink socket.
+ */
+static int
+LinkCatcher(struct nlmsghdr *nlh)
+{
+  struct ifinfomsg* ifi;
+  char ifname[IFNAMSIZ + 1];
+
+#if 0
+  fprintf(stderr, "nlmsg_type = %d.\n", nlh->nlmsg_type);
+#endif
+
+  if(nlh->nlmsg_type != RTM_NEWLINK)
+    return 0;
+
+  ifi = NLMSG_DATA(nlh);
+
+  /* Get a name... */
+  index2name(ifi->ifi_index, ifname);
+
+#if WIRELESS_EXT > 13
+  /* Code is ugly, but sort of works - Jean II */
+
+  /* Check for attributes */
+  if (nlh->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) {
+      int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg));
+      struct rtattr *attr = (void*)ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg));
+
+      while (RTA_OK(attr, attrlen)) {
+       /* Check if the Wireless kind */
+       if(attr->rta_type == IFLA_WIRELESS) {
+         /* Go to display it */
+         print_event_stream(ifname,
+                            (void *)attr + RTA_ALIGN(sizeof(struct rtattr)),
+                            attr->rta_len - RTA_ALIGN(sizeof(struct rtattr)));
+       }
+       attr = RTA_NEXT(attr, attrlen);
+      }
+  }
+#endif /* WIRELESS_EXT > 13 */
+
+  return 0;
+}
+
+/* ---------------------------------------------------------------- */
+/*
+ * We must watch the rtnelink socket for events.
+ * This routine handles those events (i.e., call this when rth.fd
+ * is ready to read).
+ */
+static inline void
+handle_netlink_events(struct rtnl_handle *     rth)
+{
+  while(1)
+    {
+      struct sockaddr_nl sanl;
+      socklen_t sanllen;
+
+      struct nlmsghdr *h;
+      int amt;
+      char buf[8192];
+
+      amt = recvfrom(rth->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sanl, &sanllen);
+      if(amt < 0)
+       {
+         if(errno != EINTR && errno != EAGAIN)
+           {
+             fprintf(stderr, "%s: error reading netlink: %s.\n",
+                     __PRETTY_FUNCTION__, strerror(errno));
+           }
+         return;
+       }
+
+      if(amt == 0)
+       {
+         fprintf(stderr, "%s: EOF on netlink??\n", __PRETTY_FUNCTION__);
+         return;
+       }
+
+      h = (struct nlmsghdr*)buf;
+      while(amt >= (int)sizeof(*h))
+       {
+         int len = h->nlmsg_len;
+         int l = len - sizeof(*h);
+
+         if(l < 0 || len > amt)
+           {
+             fprintf(stderr, "%s: malformed netlink message: len=%d\n", __PRETTY_FUNCTION__, len);
+             break;
+           }
+
+         switch(h->nlmsg_type)
+           {
+           case RTM_NEWLINK:
+             LinkCatcher(h);
+             break;
+           default:
+#if 0
+             fprintf(stderr, "%s: got nlmsg of type %#x.\n", __PRETTY_FUNCTION__, h->nlmsg_type);
+#endif
+             break;
+           }
+
+         len = NLMSG_ALIGN(len);
+         amt -= len;
+         h = (struct nlmsghdr*)((char*)h + len);
+       }
+
+      if(amt > 0)
+       fprintf(stderr, "%s: remnant of size %d on netlink\n", __PRETTY_FUNCTION__, amt);
+    }
+}
+
+/**************************** MAIN LOOP ****************************/
+
+/* ---------------------------------------------------------------- */
+/*
+ * Wait until we get an event
+ */
+static inline int
+wait_for_event(struct rtnl_handle *    rth)
+{
+#if 0
+  struct timeval       tv;     /* Select timeout */
+#endif
+
+  /* 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);
+      FD_SET(rth->fd, &rfds);
+      last_fd = rth->fd;
+
+      /* Wait until something happens */
+      ret = select(last_fd + 1, &rfds, NULL, NULL, NULL);
+
+      /* Check if there was an error */
+      if(ret < 0)
+       {
+         if(errno == EAGAIN || errno == EINTR)
+           continue;
+         fprintf(stderr, "Unhandled signal - exiting...\n");
+         break;
+       }
+
+      /* Check if there was a timeout */
+      if(ret == 0)
+       {
+         continue;
+       }
+
+      /* Check for interface discovery events. */
+      if(FD_ISSET(rth->fd, &rfds))
+       handle_netlink_events(rth);
+    }
+
+  return(0);
+}
+
+/******************************* MAIN *******************************/
+
+/* ---------------------------------------------------------------- */
+/*
+ * helper ;-)
+ */
+static void
+iw_usage(int status)
+{
+  fputs("Usage: iwevent [OPTIONS]\n"
+       "   Monitors and displays Wireless Events.\n"
+       "   Options are:\n"
+       "     -h,--help  Print this message.\n",
+       status ? stderr : stdout);
+  exit(status);
+}
+/* Command line options */
+static const struct option long_opts[] = {
+  { "help", no_argument, NULL, 'h' },
+  { NULL, 0, NULL, 0 }
+};
+
+/* ---------------------------------------------------------------- */
+/*
+ * main body of the program
+ */
+int
+main(int       argc,
+     char *    argv[])
+{
+  struct rtnl_handle   rth;
+  int opt;
+
+  /* Check command line options */
+  while((opt = getopt_long(argc, argv, "h", long_opts, NULL)) > 0)
+    {
+      switch(opt)
+       {
+       case 'h':
+         iw_usage(0);
+         break;
+
+       default:
+         iw_usage(1);
+         break;
+       }
+    }
+  if(optind < argc)
+    {
+      fputs("Too many arguments.\n", stderr);
+      iw_usage(1);
+    }
+
+  /* Open netlink channel */
+  if(rtnl_open(&rth, RTMGRP_LINK) < 0)
+    {
+      perror("Can't initialize rtnetlink socket");
+      return(1);
+    }
+
+  /* Do what we have to do */
+  wait_for_event(&rth);
+
+  /* Cleanup - only if you are pedantic */
+  rtnl_close(&rth);
+
+  return(0);
+}
diff --git a/wireless_tools/iwgetid.8 b/wireless_tools/iwgetid.8
new file mode 100644 (file)
index 0000000..323ce8c
--- /dev/null
@@ -0,0 +1,67 @@
+.\" Guus Sliepen - 2001
+.\" Completed and fixed up by Jean Tourrilhes - 2002
+.\" iwgetid.8
+.\"
+.TH IWGETID 8 "7 August 2001" "net-tools" "Linux Programmer's Manual"
+.\"
+.\" NAME part
+.\"
+.SH NAME
+iwgetid \- Report ESSID, NWID or AP/Cell Address of wireless network
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.BI "iwgetid " [interface] " [--scheme] [--ap]"
+.br
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B iwgetid
+is used to find out the NWID, ESSID or AP/Cell Address of the wireless
+network that is currently used. The information reported is the same
+as the one shown by
+.BR iwconfig ", but " iwgetid
+is easier to integrate in various scripts.
+.br
+By default,
+.B iwgetid
+will print the
+.I ESSID
+of the device, and if the device doesn't have any ESSID it will print
+its
+.IR NWID .
+.\"
+.\" OPTIONS part
+.\"
+.SH OPTIONS
+.TP
+.B --scheme
+This option disables pretty-printing of the information, only the raw
+ESSID (or NWID, or AP Address) is printed. Also, characters that are
+not alphanumerics (like space, punctuation and control characters) are
+skipped.
+.br
+The resulting output is a valid Pcmcia scheme identifier (that may be used as an argument of the command
+.BR "cardctl scheme" ).
+This format is also ideal when using the result of iwgetid as a
+variable in
+.I Shell
+or
+.I Perl
+scripts.
+.TP
+.B --ap
+Display the MAC address of the Wireless
+.I Access Point
+or the
+.IR Cell .
+.\"
+.\" SEE ALSO part
+.\"
+.SH SEE ALSO
+.BR iwconfig (8),
+.BR ifconfig (8),
+.BR iwspy (8),
+.BR iwpriv (8).
index c550431..f573209 100644 (file)
 
 #include "iwlib.h"             /* Header */
 
+#include <getopt.h>
+
 #define FORMAT_DEFAULT 0       /* Nice looking display for the user */
 #define FORMAT_SCHEME  1       /* To be used as a Pcmcia Scheme */
+#define WTYPE_ESSID    0       /* Display ESSID or NWID */
+#define WTYPE_AP       1       /* Display AP/Cell Address */
 
 /*
  * Note on Pcmcia Schemes :
  * Jean II - 29/3/01
  */
 
+/*************************** SUBROUTINES ***************************/
+/*
+ * Just for the heck of it, let's try to not link with iwlib.
+ * This will keep the binary small and tiny...
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Open a socket.
+ * Depending on the protocol present, open the right socket. The socket
+ * will allow us to talk to the driver.
+ */
+int
+iw_sockets_open(void)
+{
+        int ipx_sock = -1;              /* IPX socket                   */
+        int ax25_sock = -1;             /* AX.25 socket                 */
+        int inet_sock = -1;             /* INET socket                  */
+        int ddp_sock = -1;              /* Appletalk DDP socket         */
+
+        /*
+         * Now pick any (exisiting) useful socket family for generic queries
+        * Note : don't open all the socket, only returns when one matches,
+        * all protocols might not be valid.
+        * Workaround by Jim Kaba <jkaba@sarnoff.com>
+        * Note : in 99% of the case, we will just open the inet_sock.
+        * The remaining 1% case are not fully correct...
+         */
+        inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
+        if(inet_sock!=-1)
+                return inet_sock;
+        ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
+        if(ipx_sock!=-1)
+                return ipx_sock;
+        ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
+        if(ax25_sock!=-1)
+                return ax25_sock;
+        ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
+        /*
+         * If this is -1 we have no known network layers and its time to jump.
+         */
+        return ddp_sock;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Display an Ethernet address in readable format.
+ */
+void
+iw_ether_ntop(const struct ether_addr* eth, char* buf)
+{
+  sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+         eth->ether_addr_octet[0], eth->ether_addr_octet[1],
+         eth->ether_addr_octet[2], eth->ether_addr_octet[3],
+         eth->ether_addr_octet[4], eth->ether_addr_octet[5]);
+}
+
 /************************ DISPLAY ESSID/NWID ************************/
 
 /*------------------------------------------------------------------*/
  * Display the ESSID if possible
  */
 static int
-print_essid(int                skfd,
-           char *      ifname,
-           int         format)
+print_essid(int                        skfd,
+           const char *        ifname,
+           int                 format)
 {
   struct iwreq         wrq;
   char                 essid[IW_ESSID_MAX_SIZE + 1];   /* ESSID */
   char                 pessid[IW_ESSID_MAX_SIZE + 1];  /* Pcmcia format */
-  int          i;
-  int          j;
+  unsigned int         i;
+  unsigned int         j;
 
   /* Get ESSID */
   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
@@ -89,7 +150,7 @@ print_essid(int              skfd,
   switch(format)
     {
     case FORMAT_SCHEME:
-      /* Stip all white space and stuff */
+      /* Strip all white space and stuff */
       j = 0;
       for(i = 0; i < strlen(essid); i++)
        if(isalnum(essid[i]))
@@ -98,7 +159,6 @@ print_essid(int              skfd,
       if((j == 0) || (j > 32))
        return(-2);
       printf("%s\n", pessid);
-      fflush(stdout);
       break;
     default:
       printf("%-8.8s  ESSID:\"%s\"\n", ifname, essid);
@@ -114,7 +174,7 @@ print_essid(int             skfd,
  */
 static int
 print_nwid(int         skfd,
-          char *       ifname,
+          const char * ifname,
           int          format)
 {
   struct iwreq         wrq;
@@ -129,7 +189,6 @@ print_nwid(int              skfd,
     case FORMAT_SCHEME:
       /* Prefix with nwid to avoid name space collisions */
       printf("nwid%X\n", wrq.u.nwid.value);
-      fflush(stdout);
       break;
     default:
       printf("%-8.8s  NWID:%X\n", ifname, wrq.u.nwid.value);
@@ -139,143 +198,96 @@ print_nwid(int           skfd,
   return(0);
 }
 
+/**************************** AP ADDRESS ****************************/
+
 /*------------------------------------------------------------------*/
 /*
- * Try the various devices until one return something we can use
+ * Display the AP Address if possible
  */
 static int
-scan_devices(int               skfd,
-            int                format)
+print_ap(int           skfd,
+        const char *   ifname,
+        int            format)
 {
-  char         buff[1024];
-  struct ifconf ifc;
-  struct ifreq *ifr;
-  int          i;
-  int          ret;
+  struct iwreq         wrq;
+  char                 buffer[64];
 
-  /* 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(-1);
-    }
-  ifr = ifc.ifc_req;
+  /* Get AP Address */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  if(ioctl(skfd, SIOCGIWAP, &wrq) < 0)
+    return(-1);
 
-  /* Print the first match */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
+  /* Print */
+  iw_ether_ntop((const struct ether_addr *) wrq.u.ap_addr.sa_data, buffer);
+  switch(format)
     {
-      /* Try to print an ESSID */
-      ret = print_essid(skfd, ifr->ifr_name, format);
-      if(ret == 0)
-       return(0);      /* Success */
-
-      /* Try to print a nwid */
-      ret = print_nwid(skfd, ifr->ifr_name, format);
-      if(ret == 0)
-       return(0);      /* Success */
+    case FORMAT_SCHEME:
+      /* I think ':' are not problematic, because Pcmcia scripts
+       * seem to handle them properly... */
+      printf("%s\n", buffer);
+      break;
+    default:
+      printf("%-8.8s  Access Point: %s\n", ifname, buffer);
+      break;
     }
-  return(-1);
-}
-
-/*************************** SUBROUTINES ***************************/
-
-/*------------------------------------------------------------------*/
-/*
- * Display an Ethernet address in readable format.
- */
-char *
-pr_ether(char *                buffer,
-        unsigned char *ptr)
-{
-  sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X",
-         (ptr[0] & 0xFF), (ptr[1] & 0xFF), (ptr[2] & 0xFF),
-         (ptr[3] & 0xFF), (ptr[4] & 0xFF), (ptr[5] & 0xFF)
-  );
-  return(buffer);
-}
 
-/*------------------------------------------------------------------*/
-/*
- * Open a socket.
- * Depending on the protocol present, open the right socket. The socket
- * will allow us to talk to the driver.
- */
-int
-sockets_open(void)
-{
-       int ipx_sock = -1;              /* IPX socket                   */
-       int ax25_sock = -1;             /* AX.25 socket                 */
-       int inet_sock = -1;             /* INET socket                  */
-       int ddp_sock = -1;              /* Appletalk DDP socket         */
-
-       inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
-       ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
-       ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
-       ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
-       /*
-        * Now pick any (exisiting) useful socket family for generic queries
-        */
-       if(inet_sock!=-1)
-               return inet_sock;
-       if(ipx_sock!=-1)
-               return ipx_sock;
-       if(ax25_sock!=-1)
-               return ax25_sock;
-       /*
-        * If this is -1 we have no known network layers and its time to jump.
-        */
-        
-       return ddp_sock;
+  return(0);
 }
 
-/**************************** AP ADDRESS ****************************/
+/******************************* MAIN ********************************/
 
 /*------------------------------------------------------------------*/
 /*
- * Display the NWID if possible
+ * Check options and call the proper handler
  */
 static int
-print_ap(int           skfd,
-        char *         ifname,
-        int            format)
+print_one_device(int           skfd,
+                int            format,
+                int            wtype,
+                const char*    ifname)
 {
-  struct iwreq         wrq;
-  char                 buffer[64];
+  int ret;
 
-  /* Get network ID */
-  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
-  if(ioctl(skfd, SIOCGIWAP, &wrq) < 0)
-    return(-1);
+  /* Check wtype */
+  if(wtype == WTYPE_AP)
+    {
+      /* Try to print an AP */
+      ret = print_ap(skfd, ifname, format);
+      return(ret);
+    }
 
-  /* Print */
-  printf("%-8.8s  Access Point: %s\n", ifname,
-        pr_ether(buffer, wrq.u.ap_addr.sa_data));
+  /* Try to print an ESSID */
+  ret = print_essid(skfd, ifname, format);
 
-  return(0);
+  if(ret < 0)
+    {
+      /* Try to print a nwid */
+      ret = print_nwid(skfd, ifname, format);
+    }
+
+  return(ret);
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Try the various devices until one return something we can use
  */
-static inline int
-scan_ap(int            skfd,
-       int             format)
+static int
+scan_devices(int               skfd,
+            int                format,
+            int                wtype)
 {
   char         buff[1024];
   struct ifconf ifc;
   struct ifreq *ifr;
   int          i;
-  int          ret;
 
   /* 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));
+      perror("SIOCGIFCONF");
       return(-1);
     }
   ifr = ifc.ifc_req;
@@ -283,15 +295,34 @@ scan_ap(int               skfd,
   /* Print the first match */
   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
     {
-      /* Try to print an ESSID */
-      ret = print_ap(skfd, ifr->ifr_name, format);
-      if(ret == 0)
-       return(0);      /* Success */
+      if(print_one_device(skfd, format, wtype, ifr->ifr_name) >= 0)
+       return 0;
     }
   return(-1);
 }
 
-/******************************* MAIN ********************************/
+/*------------------------------------------------------------------*/
+/*
+ * helper
+ */
+static void
+iw_usage(int status)
+{
+  fputs("Usage iwgetid [OPTIONS] [ifname]\n"
+       "  Options are:\n"
+       "    -a,--ap      Print the access point address\n"
+       "    -h,--help    Print this message\n"
+       "    -s,--scheme  Format the output as a PCMCIA scheme identifier\n",
+       status ? stderr : stdout);
+  exit(status);
+}
+
+static const struct option long_opts[] = {
+  { "ap", no_argument, NULL, 'a' },
+  { "help", no_argument, NULL, 'h' },
+  { "scheme", no_argument, NULL, 's' },
+  { NULL, 0, NULL, 0 }
+};
 
 /*------------------------------------------------------------------*/
 /*
@@ -301,85 +332,61 @@ int
 main(int       argc,
      char **   argv)
 {
-  int  skfd = -1;              /* generic raw socket desc.     */
+  int  skfd;                   /* generic raw socket desc.     */
   int  format = FORMAT_DEFAULT;
+  int  wtype = WTYPE_ESSID;
+  int  opt;
   int  ret = -1;
 
-  /* Create a channel to the NET kernel. */
-  if((skfd = sockets_open()) < 0)
-    {
-      perror("socket");
-      return(-1);
-    }
-
-  /* No argument */
-  if(argc == 1)
-    {
-      /* Look on all devices */
-      ret = scan_devices(skfd, format);
-      close(skfd);
-      return(ret);
-    }
-
-  /* Only ask for first AP address */
-  if((!strcmp(argv[1], "--ap")) || (!strcmp(argv[1], "-a")))
+  /* Check command line arguments */
+  while((opt = getopt_long(argc, argv, "ahs", long_opts, NULL)) > 0)
     {
-      /* Look on all devices */
-      ret = scan_ap(skfd, format);
-      close(skfd);
-      return(ret);
+      switch(opt)
+       {
+       case 'a':
+         /* User wants AP/Cell Address */
+         wtype = WTYPE_AP;
+         break;
+
+       case 'h':
+         iw_usage(0);
+         break;
+
+       case 's':
+         /* User wants a Scheme format */
+         format = FORMAT_SCHEME;
+         break;
+
+       default:
+         iw_usage(1);
+         break;
+       }
     }
+  if(optind + 1 < argc) {
+    fputs("Too many arguments.\n", stderr);
+    iw_usage(1);
+  }
 
-  /* Only the format, no interface name */
-  if((!strncmp(argv[1], "--scheme", 4)) || (!strcmp(argv[1], "-s")))
+  /* Create a channel to the NET kernel. */
+  if((skfd = iw_sockets_open()) < 0)
     {
-      /* Look on all devices */
-      format = FORMAT_SCHEME;
-      ret = scan_devices(skfd, format);
-      close(skfd);
-      return(ret);
+      perror("socket");
+      return(-1);
     }
 
-  /* Help */
-  if((argc > 3) ||
-     (!strncmp(argv[1], "-h", 9)) || (!strcmp(argv[1], "--help")))
+  /* Check if first argument is a device name */
+  if(optind < argc)
     {
-      fprintf(stderr, "Usage: iwgetid [interface]\n");
-      fprintf(stderr, "               [interface] --scheme\n");
-      return(-1);
+      /* Yes : query only this device */
+      ret = print_one_device(skfd, format, wtype, argv[optind]);
     }
-
-  /* If at least a device name */
-  if(argc > 1)
+  else
     {
-      /* Check extra format argument */
-      if(argc > 2)
-       {
-         /* Only ask for first AP address */
-         if((!strcmp(argv[2], "--ap")) || (!strcmp(argv[2], "-a")))
-           {
-             ret = print_ap(skfd, argv[1], format);
-             close(skfd);
-             return(ret);
-           }
-
-         /* Want scheme format */
-         if((!strncmp(argv[2], "--scheme", 4)) || (!strcmp(argv[2], "-s")))
-           format = FORMAT_SCHEME;
-       }
-
-      /* Try to print an ESSID */
-      ret = print_essid(skfd, argv[1], format);
-
-      if(ret == -1)
-       {
-         /* Try to print a nwid */
-         ret = print_nwid(skfd, argv[1], format);
-       }
+      /* No : query all devices and print first found */
+      ret = scan_devices(skfd, format, wtype);
     }
 
-  /* Close the socket. */
+  fflush(stdout);
   close(skfd);
-
   return(ret);
 }
index 421f4e1..9d0f575 100644 (file)
@@ -13,7 +13,7 @@
 
 /**************************** VARIABLES ****************************/
 
-const char *   iw_operation_mode[] = { "Auto",
+const char * const iw_operation_mode[] = { "Auto",
                                        "Ad-Hoc",
                                        "Managed",
                                        "Master",
@@ -31,33 +31,132 @@ const char *       iw_operation_mode[] = { "Auto",
 int
 iw_sockets_open(void)
 {
-        int ipx_sock = -1;              /* IPX socket                   */
-        int ax25_sock = -1;             /* AX.25 socket                 */
-        int inet_sock = -1;             /* INET socket                  */
-        int ddp_sock = -1;              /* Appletalk DDP socket         */
-
-        /*
-         * Now pick any (exisiting) useful socket family for generic queries
-        * Note : don't open all the socket, only returns when one matches,
-        * all protocols might not be valid.
-        * Workaround by Jim Kaba <jkaba@sarnoff.com>
-        * Note : in 99% of the case, we will just open the inet_sock.
-        * The remaining 1% case are not fully correct...
-         */
-        inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
-        if(inet_sock!=-1)
-                return inet_sock;
-        ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
-        if(ipx_sock!=-1)
-                return ipx_sock;
-        ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
-        if(ax25_sock!=-1)
-                return ax25_sock;
-        ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
-        /*
-         * If this is -1 we have no known network layers and its time to jump.
-         */
-        return ddp_sock;
+  static const int families[] = {
+    AF_INET, AF_IPX, AF_AX25, AF_APPLETALK
+  };
+  unsigned int i;
+  int          sock;
+
+  /*
+   * Now pick any (exisiting) useful socket family for generic queries
+   * Note : don't open all the socket, only returns when one matches,
+   * all protocols might not be valid.
+   * Workaround by Jim Kaba <jkaba@sarnoff.com>
+   * Note : in 99% of the case, we will just open the inet_sock.
+   * The remaining 1% case are not fully correct...
+   */
+
+  /* Try all families we support */
+  for(i = 0; i < sizeof(families)/sizeof(int); ++i)
+    {
+      /* Try to open the socket, if success returns it */
+      sock = socket(families[i], SOCK_DGRAM, 0);
+      if(sock >= 0)
+       return sock;
+  }
+
+  return -1;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the interface name out of /proc/net/wireless
+ * Important note : this procedure will work only with /proc/net/wireless
+ * and not /proc/net/dev, because it doesn't guarantee a ' ' after the ':'.
+ */
+static inline char *
+iw_get_ifname(char *   name,   /* Where to store the name */
+             int       nsize,  /* Size of name buffer */
+             char *    buf)    /* Current position in buffer */
+{
+  char *       end;
+
+  /* Skip leading spaces */
+  while(isspace(*buf))
+    buf++;
+
+  /* Get name up to ": "
+   * Note : we compare to ": " to make sure to process aliased interfaces
+   * properly. */
+  end = strstr(buf, ": ");
+
+  /* Not found ??? To big ??? */
+  if((end == NULL) || (((end - buf) + 1) > nsize))
+    return(NULL);
+
+  /* Copy */
+  memcpy(name, buf, (end - buf));
+  name[end - buf] = '\0';
+
+  return(end + 2);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Enumerate devices and call specified routine
+ * The new way just use /proc/net/wireless, so get all wireless interfaces,
+ * whether configured or not. This is the default if available.
+ * The old way use SIOCGIFCONF, so get only configured interfaces (wireless
+ * or not).
+ */
+void
+iw_enum_devices(int            skfd,
+               iw_enum_handler fn,
+               char *          args[],
+               int             count)
+{
+  char         buff[1024];
+  FILE *       fh;
+  struct ifconf ifc;
+  struct ifreq *ifr;
+  int          i;
+
+  /* Check if /proc/net/wireless is available */
+  fh = fopen(PROC_NET_WIRELESS, "r");
+
+  if(fh != NULL)
+    {
+      /* Success : use data from /proc/net/wireless */
+
+      /* Eat 2 lines of header */
+      fgets(buff, sizeof(buff), fh);
+      fgets(buff, sizeof(buff), fh);
+
+      /* Read each device line */
+      while(fgets(buff, sizeof(buff), fh))
+       {
+         char  name[IFNAMSIZ + 1];
+         char *s;
+
+         /* Extract interface name */
+         s = iw_get_ifname(name, sizeof(name), buff);
+
+         if(!s)
+           /* Failed to parse, complain and continue */
+           fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
+         else
+           /* Got it, print info about this interface */
+           (*fn)(skfd, name, args, count);
+       }
+
+      fclose(fh);
+    }
+  else
+    {
+      /* Get list of configured devices using "traditional" way */
+      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++)
+       (*fn)(skfd, ifr->ifr_name, args, count);
+    }
 }
 
 /*********************** WIRELESS SUBROUTINES ************************/
@@ -75,10 +174,10 @@ iw_get_range_info(int              skfd,
   char                 buffer[sizeof(iwrange) * 2];    /* Large enough */
 
   /* Cleanup */
-  memset(buffer, 0, sizeof(iwrange) * 2);
+  memset(buffer, 0, sizeof(buffer));
 
   wrq.u.data.pointer = (caddr_t) buffer;
-  wrq.u.data.length = sizeof(iwrange) * 2;
+  wrq.u.data.length = sizeof(buffer);
   wrq.u.data.flags = 0;
   if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
     return(-1);
@@ -86,7 +185,7 @@ iw_get_range_info(int                skfd,
   /* Copy stuff at the right place, ignore extra */
   memcpy((char *) range, buffer, sizeof(iwrange));
 
-  /* Lot's of people have driver and tools out of sync as far as Wireless
+  /* Lots of people have driver and tools out of sync as far as Wireless
    * Extensions are concerned. It's because /usr/include/linux/wireless.h
    * and /usr/src/linux/include/linux/wireless.h are different.
    * We try to catch this stuff here... */
@@ -207,9 +306,9 @@ iw_get_basic_config(int                     skfd,
   /* Get operation mode */
   if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
     {
-      if((wrq.u.mode < 6) && (wrq.u.mode >= 0))
-       info->has_mode = 1;
       info->mode = wrq.u.mode;
+      if((info->mode < 6) && (info->mode >= 0))
+       info->has_mode = 1;
     }
 
   return(0);
@@ -363,6 +462,51 @@ iw_freq2float(iwfreq *     in)
   return ((double) in->m) * pow(10,in->e);
 }
 
+/*------------------------------------------------------------------*/
+/*
+ * Output a frequency with proper scaling
+ */
+void
+iw_print_freq(char *   buffer,
+             float     freq)
+{
+  if(freq < KILO)
+    sprintf(buffer, "Channel:%g", freq);
+  else
+    {
+      if(freq >= GIGA)
+       sprintf(buffer, "Frequency:%gGHz", freq / GIGA);
+      else
+       {
+         if(freq >= MEGA)
+           sprintf(buffer, "Frequency:%gMHz", freq / MEGA);
+         else
+           sprintf(buffer, "Frequency:%gkHz", freq / KILO);
+       }
+    }
+}
+
+/*********************** BITRATE SUBROUTINES ***********************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Output a bitrate with proper scaling
+ */
+void
+iw_print_bitrate(char *        buffer,
+                int    bitrate)
+{
+  double       rate = bitrate;
+
+  if(rate >= GIGA)
+    sprintf(buffer, "%gGb/s", rate / GIGA);
+  else
+    if(rate >= MEGA)
+      sprintf(buffer, "%gMb/s", rate / MEGA);
+    else
+      sprintf(buffer, "%gkb/s", rate / KILO);
+}
+
 /************************ POWER SUBROUTINES *************************/
 
 /*------------------------------------------------------------------*/
@@ -407,7 +551,7 @@ iw_get_stats(int    skfd,
 
   return(0);
 #else /* WIRELESS_EXT > 11 */
-  FILE *       f=fopen("/proc/net/wireless","r");
+  FILE *       f = fopen(PROC_NET_WIRELESS, "r");
   char         buf[256];
   char *       bp;
   int          t;
@@ -523,15 +667,20 @@ iw_print_key(char *               buffer,
   /* Is the key present ??? */
   if(key_flags & IW_ENCODE_NOKEY)
     {
-      /* Nope : print dummy */
-      strcpy(buffer, "**");
-      buffer +=2;
-      for(i = 1; i < key_size; i++)
+      /* Nope : print on or dummy */
+      if(key_size <= 0)
+       strcpy(buffer, "on");
+      else
        {
-         if((i & 0x1) == 0)
-           strcpy(buffer++, "-");
          strcpy(buffer, "**");
          buffer +=2;
+         for(i = 1; i < key_size; i++)
+           {
+             if((i & 0x1) == 0)
+               strcpy(buffer++, "-");
+             strcpy(buffer, "**");
+             buffer +=2;
+           }
        }
     }
   else
@@ -549,6 +698,58 @@ iw_print_key(char *                buffer,
     }
 }
 
+/*------------------------------------------------------------------*/
+/*
+ * Parse a key from the command line.
+ * Return size of the key, or 0 (no key) or -1 (error)
+ */
+int
+iw_in_key(char *               input,
+         unsigned char *       key)
+{
+  int          keylen = 0;
+  char *       buff;
+  char *       p;
+  int          temp;
+
+  /* Check the type of key */
+  if(!strncmp(input, "s:", 2))
+    {
+      /* First case : as an ASCII string */
+      keylen = strlen(input + 2);              /* skip "s:" */
+      if(keylen > IW_ENCODING_TOKEN_MAX)
+       keylen = IW_ENCODING_TOKEN_MAX;
+      strncpy(key, input + 2, keylen);
+    }
+  else
+    {
+      /* Second case : as hexadecimal digits */
+      buff = malloc(strlen(input) + 1);
+      if(buff == NULL)
+       {
+         fprintf(stderr, "Malloc failed (string too long ?)\n");
+         return(-1);
+       }
+      /* Preserve original buffer */
+      strcpy(buff, input);
+
+      /* Parse */
+      p = strtok(buff, "-:;.,");
+      while((p != (char *) NULL) && (keylen < IW_ENCODING_TOKEN_MAX))
+       {
+         if(sscanf(p, "%2X", &temp) != 1)
+           return(-1);         /* Error */
+         key[keylen++] = (unsigned char) (temp & 0xFF);
+         if(strlen(p) > 2)     /* Token not finished yet */
+           p += 2;
+         else
+           p = strtok((char *) NULL, "-:;.,");
+       }
+      free(buff);
+    }
+
+  return(keylen);
+}
 
 /******************* POWER MANAGEMENT SUBROUTINES *******************/
 
@@ -587,17 +788,17 @@ iw_print_pm_value(char *  buffer,
 
   /* Display value without units */
   if(flags & IW_POWER_RELATIVE)
-    sprintf(buffer, "%g  ", ((double) value) / MEGA);
+    sprintf(buffer, "%g", ((double) value) / MEGA);
   else
     {
       /* Display value with units */
       if(value >= (int) MEGA)
-       sprintf(buffer, "%gs  ", ((double) value) / MEGA);
+       sprintf(buffer, "%gs", ((double) value) / MEGA);
       else
        if(value >= (int) KILO)
-         sprintf(buffer, "%gms  ", ((double) value) / KILO);
+         sprintf(buffer, "%gms", ((double) value) / KILO);
        else
-         sprintf(buffer, "%dus  ", value);
+         sprintf(buffer, "%dus", value);
     }
 }
 
@@ -613,19 +814,19 @@ iw_print_pm_mode(char *   buffer,
   switch(flags & IW_POWER_MODE)
     {
     case IW_POWER_UNICAST_R:
-      strcpy(buffer, " mode:Unicast only received");
+      strcpy(buffer, "mode:Unicast only received");
       break;
     case IW_POWER_MULTICAST_R:
-      strcpy(buffer, " mode:Multicast only received");
+      strcpy(buffer, "mode:Multicast only received");
       break;
     case IW_POWER_ALL_R:
-      strcpy(buffer, " mode:All packets received");
+      strcpy(buffer, "mode:All packets received");
       break;
     case IW_POWER_FORCE_S:
-      strcpy(buffer, " mode:Force sending");
+      strcpy(buffer, "mode:Force sending");
       break;
     case IW_POWER_REPEATER:
-      strcpy(buffer, " mode:Repeat multicasts");
+      strcpy(buffer, "mode:Repeat multicasts");
       break;
     default:
     }
@@ -681,6 +882,25 @@ iw_print_retry_value(char *        buffer,
 }
 #endif /* WIRELESS_EXT > 10 */
 
+/************************* TIME SUBROUTINES *************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print timestamps
+ * Inspired from irdadump...
+ */
+void
+iw_print_timeval(char *                        buffer,
+                const struct timeval * time)
+{
+        int s;
+
+       s = (time->tv_sec) % 86400;
+       sprintf(buffer, "%02d:%02d:%02d.%06u ", 
+               s / 3600, (s % 3600) / 60, 
+               s % 60, (u_int32_t) time->tv_usec);
+}
+
 /*********************** ADDRESS SUBROUTINES ************************/
 /*
  * This section is mostly a cut & past from net-tools-1.2.0
@@ -710,7 +930,7 @@ iw_check_mac_addr_type(int          skfd,
 
 #ifdef DEBUG
   printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family,
-        pr_ether(ifr.ifr_hwaddr.sa_data));
+        iw_ether_ntoa((struct ether_addr *) ifr.ifr_hwaddr.sa_data));
 #endif
 
   return(0);
@@ -770,15 +990,26 @@ iw_check_addr_type(int            skfd,
 /*
  * Display an Ethernet address in readable format.
  */
+void
+iw_ether_ntop(const struct ether_addr* eth, char* buf)
+{
+  sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+         eth->ether_addr_octet[0], eth->ether_addr_octet[1],
+         eth->ether_addr_octet[2], eth->ether_addr_octet[3],
+         eth->ether_addr_octet[4], eth->ether_addr_octet[5]);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Display an Ethernet address in readable format.
+ * Same with a static buffer
+ */
 char *
-iw_pr_ether(char *             buffer,
-           unsigned char *     ptr)
+iw_ether_ntoa(const struct ether_addr* eth)
 {
-  sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X",
-         (ptr[0] & 0xFF), (ptr[1] & 0xFF), (ptr[2] & 0xFF),
-         (ptr[3] & 0xFF), (ptr[4] & 0xFF), (ptr[5] & 0xFF)
-  );
-  return(buffer);
+  static char buf[20];
+  iw_ether_ntop(eth, buf);
+  return buf;
 }
 
 /*------------------------------------------------------------------*/
@@ -786,84 +1017,64 @@ iw_pr_ether(char *               buffer,
  * Input an Ethernet address and convert to binary.
  */
 int
-iw_in_ether(char *bufp, struct sockaddr *sap)
+iw_ether_aton(const char *orig, struct ether_addr *eth)
 {
-  unsigned char *ptr;
-  char c, *orig;
-  int i, val;
-
-  sap->sa_family = ARPHRD_ETHER;
-  ptr = sap->sa_data;
+  const char *bufp;
+  int i;
 
   i = 0;
-  orig = bufp;
-  while((*bufp != '\0') && (i < ETH_ALEN)) {
-       val = 0;
-       c = *bufp++;
+  for(bufp = orig; *bufp != '\0'; ++bufp) {
+       unsigned int val;
+       unsigned char c = *bufp++;
        if (isdigit(c)) val = c - '0';
-         else if (c >= 'a' && c <= 'f') val = c - 'a' + 10;
-         else if (c >= 'A' && c <= 'F') val = c - 'A' + 10;
-         else {
-#ifdef DEBUG
-               fprintf(stderr, "in_ether(%s): invalid ether address!\n", orig);
-#endif
-               errno = EINVAL;
-               return(-1);
-       }
+       else if (c >= 'a' && c <= 'f') val = c - 'a' + 10;
+       else if (c >= 'A' && c <= 'F') val = c - 'A' + 10;
+       else break;
+
        val <<= 4;
        c = *bufp++;
        if (isdigit(c)) val |= c - '0';
-         else if (c >= 'a' && c <= 'f') val |= c - 'a' + 10;
-         else if (c >= 'A' && c <= 'F') val |= c - 'A' + 10;
-         else {
-#ifdef DEBUG
-               fprintf(stderr, "in_ether(%s): invalid ether address!\n", orig);
-#endif
-               errno = EINVAL;
-               return(-1);
-       }
-       *ptr++ = (unsigned char) (val & 0377);
-       i++;
-
-       /* We might get a semicolon here - not required. */
-       if (*bufp == ':') {
-               if (i == ETH_ALEN) {
+       else if (c >= 'a' && c <= 'f') val |= c - 'a' + 10;
+       else if (c >= 'A' && c <= 'F') val |= c - 'A' + 10;
+       else break;
+
+       eth->ether_addr_octet[i] = (unsigned char) (val & 0377);
+       if(++i == ETH_ALEN) {
+               /* That's it.  Any trailing junk? */
+               if (*bufp != '\0') {
 #ifdef DEBUG
-                       fprintf(stderr, "in_ether(%s): trailing : ignored!\n",
-                               orig)
+                       fprintf(stderr, "iw_ether_aton(%s): trailing junk!\n", orig);
+                       errno = EINVAL;
+                       return(0);
 #endif
-                                               ; /* nothing */
                }
-               bufp++;
-       }
-  }
-
-  /* That's it.  Any trailing junk? */
-  if ((i == ETH_ALEN) && (*bufp != '\0')) {
 #ifdef DEBUG
-       fprintf(stderr, "in_ether(%s): trailing junk!\n", orig);
-       errno = EINVAL;
-       return(-1);
+               fprintf(stderr, "iw_ether_aton(%s): %s\n",
+                       orig, ether_ntoa(eth));
 #endif
+               return(1);
+       }
+       if (*bufp != ':')
+               break;
   }
 
 #ifdef DEBUG
-  fprintf(stderr, "in_ether(%s): %s\n", orig, pr_ether(sap->sa_data));
+  fprintf(stderr, "iw_ether_aton(%s): invalid ether address!\n", orig);
 #endif
-
+  errno = EINVAL;
   return(0);
 }
 
+
 /*------------------------------------------------------------------*/
 /*
  * Input an Internet address and convert to binary.
  */
 int
-iw_in_inet(char *bufp, struct sockaddr *sap)
+iw_in_inet(char *name, struct sockaddr *sap)
 {
   struct hostent *hp;
   struct netent *np;
-  char *name = bufp;
   struct sockaddr_in *sin = (struct sockaddr_in *) sap;
 
   /* Grmpf. -FvK */
@@ -946,7 +1157,7 @@ iw_in_addr(int             skfd,
 
 #ifdef DEBUG
       printf("IP Address %s => Hw Address = %s\n",
-            bufp, pr_ether(sap->sa_data));
+            bufp, iw_ether_ntoa((struct ether_addr *) sap->sa_data));
 #endif
     }
   else /* If it's an hardware address */
@@ -967,7 +1178,7 @@ iw_in_addr(int             skfd,
     }
 
 #ifdef DEBUG
-  printf("Hw Address = %s\n", pr_ether(sap->sa_data));
+  printf("Hw Address = %s\n", iw_ether_ntoa((struct ether_addr *) sap->sa_data));
 #endif
 
   return(0);
@@ -977,6 +1188,7 @@ iw_in_addr(int             skfd,
 
 /*------------------------------------------------------------------*/
 /*
+ * Max size in bytes of an private argument.
  */
 int
 iw_byte_size(int       args)
@@ -993,3 +1205,217 @@ iw_byte_size(int args)
   return ret;
 }
 
+/************************ EVENT SUBROUTINES ************************/
+/*
+ * The Wireless Extension API 14 and greater define Wireless Events,
+ * that are used for various events and scanning.
+ * Those functions help the decoding of events, so are needed only in
+ * this case.
+ */
+#if WIRELESS_EXT > 13
+
+/* Type of headers we know about (basically union iwreq_data) */
+#define IW_HEADER_TYPE_NULL    0       /* Not available */
+#define IW_HEADER_TYPE_CHAR    2       /* char [IFNAMSIZ] */
+#define IW_HEADER_TYPE_UINT    4       /* __u32 */
+#define IW_HEADER_TYPE_FREQ    5       /* struct iw_freq */
+#define IW_HEADER_TYPE_POINT   6       /* struct iw_point */
+#define IW_HEADER_TYPE_PARAM   7       /* struct iw_param */
+#define IW_HEADER_TYPE_ADDR    8       /* struct sockaddr */
+#define IW_HEADER_TYPE_QUAL    9       /* struct iw_quality */
+
+/* Headers for the various requests */
+static const char standard_ioctl_hdr[] = {
+       IW_HEADER_TYPE_NULL,    /* SIOCSIWCOMMIT */
+       IW_HEADER_TYPE_CHAR,    /* SIOCGIWNAME */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWNWID */
+       IW_HEADER_TYPE_PARAM,   /* SIOCGIWNWID */
+       IW_HEADER_TYPE_FREQ,    /* SIOCSIWFREQ */
+       IW_HEADER_TYPE_FREQ,    /* SIOCGIWFREQ */
+       IW_HEADER_TYPE_UINT,    /* SIOCSIWMODE */
+       IW_HEADER_TYPE_UINT,    /* SIOCGIWMODE */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWSENS */
+       IW_HEADER_TYPE_PARAM,   /* SIOCGIWSENS */
+       IW_HEADER_TYPE_NULL,    /* SIOCSIWRANGE */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWRANGE */
+       IW_HEADER_TYPE_NULL,    /* SIOCSIWPRIV */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWPRIV */
+       IW_HEADER_TYPE_NULL,    /* SIOCSIWSTATS */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWSTATS */
+       IW_HEADER_TYPE_POINT,   /* SIOCSIWSPY */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWSPY */
+       IW_HEADER_TYPE_NULL,    /* -- hole -- */
+       IW_HEADER_TYPE_NULL,    /* -- hole -- */
+       IW_HEADER_TYPE_ADDR,    /* SIOCSIWAP */
+       IW_HEADER_TYPE_ADDR,    /* SIOCGIWAP */
+       IW_HEADER_TYPE_NULL,    /* -- hole -- */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWAPLIST */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWSCAN */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWSCAN */
+       IW_HEADER_TYPE_POINT,   /* SIOCSIWESSID */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWESSID */
+       IW_HEADER_TYPE_POINT,   /* SIOCSIWNICKN */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWNICKN */
+       IW_HEADER_TYPE_NULL,    /* -- hole -- */
+       IW_HEADER_TYPE_NULL,    /* -- hole -- */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWRATE */
+       IW_HEADER_TYPE_PARAM,   /* SIOCGIWRATE */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWRTS */
+       IW_HEADER_TYPE_PARAM,   /* SIOCGIWRTS */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWFRAG */
+       IW_HEADER_TYPE_PARAM,   /* SIOCGIWFRAG */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWTXPOW */
+       IW_HEADER_TYPE_PARAM,   /* SIOCGIWTXPOW */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWRETRY */
+       IW_HEADER_TYPE_PARAM,   /* SIOCGIWRETRY */
+       IW_HEADER_TYPE_POINT,   /* SIOCSIWENCODE */
+       IW_HEADER_TYPE_POINT,   /* SIOCGIWENCODE */
+       IW_HEADER_TYPE_PARAM,   /* SIOCSIWPOWER */
+       IW_HEADER_TYPE_PARAM,   /* SIOCGIWPOWER */
+};
+static const unsigned int standard_ioctl_num = sizeof(standard_ioctl_hdr);
+
+/*
+ * Meta-data about all the additional standard Wireless Extension events
+ * we know about.
+ */
+static const char      standard_event_hdr[] = {
+       IW_HEADER_TYPE_ADDR,    /* IWEVTXDROP */
+       IW_HEADER_TYPE_QUAL,    /* IWEVQUAL */
+};
+static const unsigned int standard_event_num = sizeof(standard_event_hdr);
+
+/* Size (in bytes) of various events */
+static const int event_type_size[] = {
+       IW_EV_LCP_LEN,
+       0,
+       IW_EV_CHAR_LEN,
+       0,
+       IW_EV_UINT_LEN,
+       IW_EV_FREQ_LEN,
+       IW_EV_POINT_LEN,                /* Without variable payload */
+       IW_EV_PARAM_LEN,
+       IW_EV_ADDR_LEN,
+       IW_EV_QUAL_LEN,
+};
+
+/*------------------------------------------------------------------*/
+/*
+ * Initialise the struct stream_descr so that we can extract
+ * individual events from the event stream.
+ */
+void
+iw_init_event_stream(struct stream_descr *     stream, /* Stream of events */
+                    char *                     data,
+                    int                        len)
+{
+  /* Cleanup */
+  memset((char *) stream, '\0', sizeof(struct stream_descr));
+
+  /* Set things up */
+  stream->current = data;
+  stream->end = data + len;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the next event from the event stream.
+ */
+int
+iw_extract_event_stream(struct stream_descr *  stream, /* Stream of events */
+                       struct iw_event *       iwe)    /* Extracted event */
+{
+  int          event_type = 0;
+  int          event_len = 1;          /* Invalid */
+  char *       pointer;
+  /* Don't "optimise" the following variable, it will crash */
+  unsigned     cmd_index;              /* *MUST* be unsigned */
+
+  /* Check for end of stream */
+  if((stream->current + IW_EV_LCP_LEN) > stream->end)
+    return(0);
+
+#if 0
+  printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n",
+        stream->current, stream->value, stream->end);
+#endif
+
+  /* Extract the event header (to get the event id).
+   * Note : the event may be unaligned, therefore copy... */
+  memcpy((char *) iwe, stream->current, IW_EV_LCP_LEN);
+
+#if 0
+  printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n",
+        iwe->cmd, iwe->len);
+#endif
+
+   /* Get the type and length of that event */
+  if(iwe->cmd <= SIOCIWLAST)
+    {
+      cmd_index = iwe->cmd - SIOCIWFIRST;
+      if(cmd_index < standard_ioctl_num)
+       event_type = standard_ioctl_hdr[cmd_index];
+    }
+  else
+    {
+      cmd_index = iwe->cmd - IWEVFIRST;
+      if(cmd_index < standard_event_num)
+       event_type = standard_event_hdr[cmd_index];
+    }
+  event_len = event_type_size[event_type];
+
+  /* Check if we know about this event */
+  if((event_len == 0) || (iwe->len == 0))
+    return(-1);
+  event_len -= IW_EV_LCP_LEN;
+
+  /* Set pointer on data */
+  if(stream->value != NULL)
+    pointer = stream->value;                   /* Next value in event */
+  else
+    pointer = stream->current + IW_EV_LCP_LEN; /* First value in event */
+
+#if 0
+  printf("DBG - event_type = %d, event_len = %d, pointer = %p\n",
+        event_type, event_len, pointer);
+#endif
+
+  /* Copy the rest of the event (at least, fixed part) */
+  if((pointer + event_len) > stream->end)
+    return(-2);
+  memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
+
+  /* Skip event in the stream */
+  pointer += event_len;
+
+  /* Special processing for iw_point events */
+  if(event_type == IW_HEADER_TYPE_POINT)
+    {
+      /* Check the length of the payload */
+      if((iwe->len - (event_len + IW_EV_LCP_LEN)) > 0)
+       /* Set pointer on variable part (warning : non aligned) */
+       iwe->u.data.pointer = pointer;
+      else
+       /* No data */
+       iwe->u.data.pointer = NULL;
+
+       /* Go to next event */
+      stream->current += iwe->len;
+    }
+  else
+    {
+      /* Is there more value in the event ? */
+      if((pointer + event_len) <= (stream->current + iwe->len))
+       /* Go to next value */
+       stream->value = pointer;
+      else
+       {
+         /* Go to next event */
+         stream->value = NULL;
+         stream->current += iwe->len;
+       }
+    }
+  return(1);
+}
+
+#endif /* WIRELESS_EXT > 13 */
index b195b82..475e67e 100644 (file)
@@ -28,6 +28,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <netdb.h>             /* gethostbyname, getnetbyname */
+#include <net/ethernet.h>      /* struct ether_addr */
+#include <sys/time.h>          /* struct timeval */
+#include <unistd.h>
 
 /* This is our header selection. Try to hide the mess and the misery :-(
  * Don't look, you would go blind ;-) */
 #include <linux/version.h>
 #endif
 
-/* Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1 */
+/* Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1
+ * Kernel headers 2.2.X + Glibc 2.2 - Slackware 8.0 */
 #if defined(__GLIBC__) \
     && __GLIBC__ == 2 \
     && __GLIBC_MINOR__ >= 2 \
-    && LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#define GLIBC22_HEADERS
+    && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+//#define GLIBC22_HEADERS
+#define GENERIC_HEADERS
 
 /* Kernel headers 2.4.X + Glibc 2.1 - Debian 2.2 upgraded, RH 7.0
  * Kernel headers 2.2.X + Glibc 2.1 - Debian 2.2, RH 6.1 */
@@ -49,7 +54,8 @@
       && __GLIBC__ == 2 \
       && __GLIBC_MINOR__ == 1 \
       && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-#define GLIBC_HEADERS
+//#define GLIBC_HEADERS
+#define GENERIC_HEADERS
 
 /* Kernel headers 2.2.X + Glibc 2.0 - Debian 2.1 */
 #elif defined(__GLIBC__) \
 #error "Your kernel/libc combination is not supported"
 #endif
 
+#ifdef GENERIC_HEADERS 
+/* Proposed by Dr. Michael Rietz <rietz@mail.amps.de>, 27.3.2 */
+/* If this works for all, it might be more stable on the long term - Jean II */
+#include <net/if_arp.h>                /* For ARPHRD_ETHER */
+#include <sys/socket.h>                /* For AF_INET & struct sockaddr */
+#include <netinet/in.h>         /* For struct sockaddr_in */
+#include <netinet/if_ether.h>
+#endif /* GENERIC_HEADERS */    
+
 #ifdef GLIBC22_HEADERS 
 /* Added by Ross G. Miller <Ross_Miller@baylor.edu>, 3/28/01 */
 #include <linux/if_arp.h>      /* For ARPHRD_ETHER */
 #endif /* PRIVATE_WE_HEADER */
 
 #if WIRELESS_EXT < 9
-#error "Wireless Extension v9 or newer required :-(\
+#error "Wireless Extension v9 or newer required :-( - \
 Use Wireless Tools v19 or update your kernel headers"
 #endif
-#if WIRELESS_EXT < 12
-#warning "Wireless Extension v12 recommended...\
-You may update your kernel and/or system headers to get the new features..."
+#if WIRELESS_EXT < 14
+#warning "Wireless Extension v14 recommended (but not mandatory)... - \
+You may update your kernel and/or system headers to get the new features, \
+or you may just ignore this message"
 #endif
 
 /****************************** DEBUG ******************************/
@@ -129,6 +145,9 @@ You may update your kernel and/or system headers to get the new features..."
 
 /************************ CONSTANTS & MACROS ************************/
 
+/* Paths */
+#define PROC_NET_WIRELESS      "/proc/net/wireless"
+
 /* Some usefull constants */
 #define KILO   1e3
 #define MEGA   1e6
@@ -229,6 +248,20 @@ typedef struct wireless_config
   int          mode;                   /* Operation mode */
 } wireless_config;
 
+typedef struct stream_descr
+{
+  char *       end;            /* End of the stream */
+  char *       current;        /* Current event in stream of events */
+  char *       value;          /* Current value in event */
+} stream_descr;
+
+/* Prototype for handling display of each single interface on the
+ * system - see iw_enum_devices() */
+typedef int (*iw_enum_handler)(int     skfd,
+                              char *   ifname,
+                              char *   args[],
+                              int      count);
+
 /**************************** PROTOTYPES ****************************/
 /*
  * All the functions in iwcommon.c
@@ -236,6 +269,11 @@ typedef struct wireless_config
 /* ---------------------- SOCKET SUBROUTINES -----------------------*/
 int
        iw_sockets_open(void);
+void
+       iw_enum_devices(int             skfd,
+                       iw_enum_handler fn,
+                       char *          args[],
+                       int             count);
 /* --------------------- WIRELESS SUBROUTINES ----------------------*/
 int
        iw_get_range_info(int           skfd,
@@ -259,6 +297,12 @@ void
                   iwfreq *     out);
 double
        iw_freq2float(iwfreq *  in);
+void
+       iw_print_freq(char *    buffer,
+                     float     freq);
+void
+       iw_print_bitrate(char * buffer,
+                        int    bitrate);
 /* ---------------------- POWER SUBROUTINES ----------------------- */
 int
        iw_dbm2mwatt(int        in);
@@ -280,6 +324,9 @@ void
                     unsigned char *    key,
                     int                key_size,
                     int                key_flags);
+int
+       iw_in_key(char *                input,
+                 unsigned char *       key);
 /* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */
 void
        iw_print_pm_value(char *        buffer,
@@ -295,6 +342,10 @@ void
                             int        value,
                             int        flags);
 #endif
+/* ----------------------- TIME SUBROUTINES ----------------------- */
+void
+       iw_print_timeval(char *                 buffer,
+                        const struct timeval * time);
 /* --------------------- ADDRESS SUBROUTINES ---------------------- */
 int
        iw_check_mac_addr_type(int      skfd,
@@ -304,13 +355,15 @@ int
                              char *    ifname);
 #if 0
 int
-       iw_check_addr_type(int  skfd,
-                       char *  ifname);
+       iw_check_addr_type(int          skfd,
+                          char *       ifname);
 #endif
-char *
-       iw_pr_ether(char *buffer, unsigned char *ptr);
+void
+       iw_ether_ntop(const struct ether_addr* eth, char* buf);
+char*
+       iw_ether_ntoa(const struct ether_addr* eth);
 int
-       iw_in_ether(char *bufp, struct sockaddr *sap);
+       iw_ether_aton(const char* bufp, struct ether_addr* eth);
 int
        iw_in_inet(char *bufp, struct sockaddr *sap);
 int
@@ -322,14 +375,25 @@ int
 int
        iw_byte_size(int                args);
 
+#if WIRELESS_EXT > 13
+/* ---------------------- EVENT SUBROUTINES ---------------------- */
+void
+       iw_init_event_stream(struct stream_descr *      stream,
+                            char *                     data,
+                            int                        len);
+int
+       iw_extract_event_stream(struct stream_descr *   stream,
+                               struct iw_event *       iwe);
+#endif /* WIRELESS_EXT > 13 */
+
 /**************************** VARIABLES ****************************/
 
-extern const char *    iw_operation_mode[];
+extern const char * const      iw_operation_mode[];
 #define IW_NUM_OPER_MODE       6
 
 /************************* INLINE FUNTIONS *************************/
 /*
- * Function that are so simple that it's more efficient inlining them
+ * Functions that are so simple that it's more efficient inlining them
  */
 
 /*
@@ -369,4 +433,44 @@ iw_get_ext(int                     skfd,           /* Socket to the kernel */
   return(ioctl(skfd, request, pwrq));
 }
 
+/*------------------------------------------------------------------*/
+/* Backwards compatability
+ * Actually, those form are much easier to use when dealing with
+ * struct sockaddr... */
+static inline char*
+iw_pr_ether(char* bufp, const unsigned char* addr)
+{
+  iw_ether_ntop((const struct ether_addr *) addr, bufp);
+  return bufp;
+}
+/* Backwards compatability */
+static inline int
+iw_in_ether(const char *bufp, struct sockaddr *sap)
+{
+  sap->sa_family = ARPHRD_ETHER;
+  return iw_ether_aton(bufp, (struct ether_addr *) sap->sa_data) ? 0 : -1;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Create an Ethernet broadcast address
+ */
+static inline void
+iw_broad_ether(struct sockaddr *sap)
+{
+  sap->sa_family = ARPHRD_ETHER;
+  memset((char *) sap->sa_data, 0xFF, ETH_ALEN);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Create an Ethernet NULL address
+ */
+static inline void
+iw_null_ether(struct sockaddr *sap)
+{
+  sap->sa_family = ARPHRD_ETHER;
+  memset((char *) sap->sa_data, 0x00, ETH_ALEN);
+}
+
 #endif /* IWLIB_H */
index 3c86fef..09a4981 100644 (file)
@@ -15,6 +15,8 @@ iwlist \- Get wireless statistics from specific nodes
 .br
 .BI "iwlist " interface " ap"
 .br
+.BI "iwlist " interface " scan"
+.br
 .BI "iwlist " interface " rate"
 .br
 .BI "iwlist " interface " key"
@@ -46,7 +48,22 @@ displayed and channel numbers.
 .TP
 .BR ap / accesspoint
 Give the list of Access Points in range, and optionally the quality of
-link to them.
+link to them. This feature is obsolte and now deprecated in favor of
+scanning support (below), and it will disappear in the future.
+.TP
+.BR scan [ning]
+Give the list of Access Points and Ad-Hoc cells in range, and
+optionally a whole bunch of information about them (ESSID, Quality,
+Frequency, Mode...). The type of information returned depend on what
+the card support.
+.br
+Triggering scanning is a priviledged operation
+.RI ( root
+only) and normal users can only read letf-over scan results. By
+default, the way scanning is done (the scope of the scan) will be
+impacted by the current setting of the driver. Also, this command is
+supposed to take extra arguments to control the scanning behaviour,
+but this is currently not implemented.
 .TP
 .BR rate / bit [rate]
 List the bit-rates supported by the device.
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);
index 2db4afd..333f98f 100644 (file)
 
 #include "iwlib.h"             /* Header */
 
+/**************************** CONSTANTS ****************************/
+
+static const char *    argtype[] = {
+  "    ", "byte", "char", "", "int ", "float" };
+
 /************************* MISC SUBROUTINES **************************/
 
 /*------------------------------------------------------------------*/
@@ -34,14 +39,18 @@ iw_usage(void)
  * Print on the screen in a neat fashion all the info we have collected
  * on a device.
  */
-static void
+static int
 print_priv_info(int            skfd,
-               char *          ifname)
+               char *          ifname,
+               char *          args[],
+               int             count)
 {
   int          k;
   iwprivargs   priv[32];
   int          n;
-  char *       argtype[] = { "    ", "byte", "char", "", "int ", "float" };
+
+  /* Avoid "Unused parameter" warning */
+  args = args; count = count;
 
   /* Read the private ioctls */
   n = iw_get_priv_info(skfd, ifname, priv);
@@ -56,7 +65,7 @@ print_priv_info(int           skfd,
   else
     {
       printf("%-8.8s  Available private ioctl :\n", ifname);
-      /* Print the all */
+      /* Print them all */
       for(k = 0; k < n; k++)
        printf("          %s (%X) : set %3d %s & get %3d %s\n",
               priv[k].name, priv[k].cmd,
@@ -66,33 +75,7 @@ print_priv_info(int          skfd,
               argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]);
       printf("\n");
     }
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Get info on all devices and print it on the screen
- */
-static void
-print_priv_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_priv_info(skfd, ifr->ifr_name);
+  return(0);
 }
 
 /************************* SETTING ROUTINES **************************/
@@ -487,7 +470,7 @@ int
 main(int       argc,
      char **   argv)
 {
-  int skfd = -1;               /* generic raw socket desc.     */
+  int skfd;            /* generic raw socket desc.     */
   int goterr = 0;
 
   /* Create a channel to the NET kernel. */
@@ -499,50 +482,30 @@ main(int  argc,
 
   /* No argument : show the list of all device + info */
   if(argc == 1)
-    {
-      print_priv_devices(skfd);
-      close(skfd);
-      return(0);
-    }
-
-  /* Special cases take one... */
-  /* Help */
-  if((!strncmp(argv[1], "-h", 9)) ||
-     (!strcmp(argv[1], "--help")))
-    {
+    iw_enum_devices(skfd, &print_priv_info, NULL, 0);
+  else
+    /* Special cases take one... */
+    /* Help */
+    if((!strncmp(argv[1], "-h", 9)) ||
+       (!strcmp(argv[1], "--help")))
       iw_usage();
-      close(skfd);
-      return(0);
-    }
-
-  /* The device name must be the first argument */
-  /* Name only : show for that device only */
-  if(argc == 2)
-    {
-      print_priv_info(skfd, argv[1]);
-      close(skfd);
-      return(0);
-    }
-
-  /* Special cases take two... */
-  /* Roaming */
-  if(!strncmp(argv[2], "roam", 4))
-    {
-      goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]);
-      close(skfd);
-      return(goterr);
-    }
-
-  /* Port type */
-  if(!strncmp(argv[2], "port", 4))
-    {
-      goterr = port_type(skfd, argv + 3, argc - 3, argv[1]);
-      close(skfd);
-      return(goterr);
-    }
-
-  /* Otherwise, it's a private ioctl */
-  goterr = set_private(skfd, argv + 2, argc - 2, argv[1]);
+    else
+      /* The device name must be the first argument */
+      /* Name only : show for that device only */
+      if(argc == 2)
+       print_priv_info(skfd, argv[1], NULL, 0);
+      else
+       /* Special cases take two... */
+       /* Roaming */
+       if(!strncmp(argv[2], "roam", 4))
+         goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]);
+       else
+         /* Port type */
+         if(!strncmp(argv[2], "port", 4))
+           goterr = port_type(skfd, argv + 3, argc - 3, argv[1]);
+         else
+           /* Otherwise, it's a private ioctl */
+           goterr = set_private(skfd, argv + 2, argc - 2, argv[1]);
 
   /* Close the socket. */
   close(skfd);
index 57d9b25..6b02c1b 100644 (file)
 /*
  * Display the spy list of addresses and the associated stats
  */
-static void
+static int
 print_spy_info(int     skfd,
-              char *   ifname)
+              char *   ifname,
+              char *   args[],
+              int      count)
 {
   struct iwreq         wrq;
   char         buffer[(sizeof(struct iw_quality) +
@@ -33,6 +35,9 @@ print_spy_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_SPY;
@@ -40,7 +45,7 @@ print_spy_info(int    skfd,
   if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
     {
       fprintf(stderr, "%-8.8s  Interface doesn't support wireless statistic collection\n\n", ifname);
-      return;
+      return(-1);
     }
 
   /* Number of addresses */
@@ -50,7 +55,7 @@ print_spy_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 */
@@ -84,33 +89,7 @@ print_spy_info(int   skfd,
 #endif /* WIRELESS_EXT > 11 */
 
   printf("\n");
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Get info on all devices and print it on the screen
- */
-static void
-print_spy_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_spy_info(skfd, ifr->ifr_name);
+  return(0);
 }
 
 /************************* SETTING ROUTINES **************************/
@@ -132,62 +111,64 @@ set_spy_info(int          skfd,           /* The socket */
 
   /* Read command line */
   i = 0;       /* first arg to read */
-  nbr = 0;     /* Number of args readen so far */
+  nbr = 0;     /* Number of args read so far */
 
   /* "off" : disable functionality (set 0 addresses) */
   if(!strcmp(args[0], "off"))
-    i = count; /* hack */
-
-  /* "+" : add all addresses already in the driver */
-  if(!strcmp(args[0], "+"))
+    i = 1;     /* skip the "off" */
+  else
     {
-      char     buffer[(sizeof(struct iw_quality) +
+      /* "+" : add all addresses already in the driver */
+      if(!strcmp(args[0], "+"))
+       {
+         char  buffer[(sizeof(struct iw_quality) +
                        sizeof(struct sockaddr)) * IW_MAX_SPY];
 
-      /* Check if we have valid mac address type */
-      if(iw_check_mac_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 addresses\n", ifname);
+             return(-1);
+           }
+
+         wrq.u.data.pointer = (caddr_t) buffer;
+         wrq.u.data.length = 0;
+         wrq.u.data.flags = 0;
+         if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
+           {
+             fprintf(stderr, "Interface doesn't accept reading addresses...\n");
+             fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
+             return(-1);
+           }
+
+         /* Copy old addresses */
+         nbr = wrq.u.data.length;
+         memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
+
+         i = 1;        /* skip the "+" */
+       }
+
+      /* Read other args on command line */
+      while((i < count) && (nbr < IW_MAX_SPY))
        {
-         fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n", ifname);
-         return(-1);
+         /* Get the address and check if the interface supports it */
+         if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
+           continue;
+         nbr++;
        }
 
-      wrq.u.data.pointer = (caddr_t) buffer;
-      wrq.u.data.length = 0;
-      wrq.u.data.flags = 0;
-      if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
+      /* Check the number of addresses */
+      if(nbr == 0)
        {
-         fprintf(stderr, "Interface doesn't accept reading addresses...\n");
-         fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
+         fprintf(stderr, "No valid addresses found : exiting...\n");
          return(-1);
        }
-
-      /* Copy old addresses */
-      nbr = wrq.u.data.length;
-      memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
-
-      i = 1;   /* skip the "+" */
-    }
-
-  /* Read other args on command line */
-  while((i < count) && (nbr < IW_MAX_SPY))
-    {
-      /* Get the address and check if the interface supports it */
-      if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
-       continue;
-      nbr++;
-    }
-
-  /* Check the number of addresses */
-  if((nbr == 0) && strcmp(args[0], "off"))
-    {
-      fprintf(stderr, "No valid addresses found : exiting...\n");
-      return(-1);
     }
 
   /* Check if there is some remaining arguments */
   if(i < count)
     {
-      fprintf(stderr, "Got only the first %d addresses, remaining discarded\n", IW_MAX_SPY);
+      fprintf(stderr, "Got only the first %d arguments, remaining discarded\n", i);
     }
 
   /* Time to do send addresses to the driver */
@@ -214,7 +195,7 @@ int
 main(int       argc,
      char **   argv)
 {
-  int skfd = -1;               /* generic raw socket desc.     */
+  int skfd;                    /* generic raw socket desc.     */
   int goterr = 0;
 
   /* Create a channel to the NET kernel. */
@@ -226,33 +207,21 @@ main(int  argc,
 
   /* No argument : show the list of all device + info */
   if(argc == 1)
-    {
-      print_spy_devices(skfd);
-      close(skfd);
-      return(0);
-    }
-
-  /* Special cases take one... */
-  /* Help */
-  if((!strncmp(argv[1], "-h", 9)) ||
-     (!strcmp(argv[1], "--help")))
-    {
+    iw_enum_devices(skfd, &print_spy_info, NULL, 0);
+  else
+    /* Special cases take one... */
+    /* Help */
+    if((!strncmp(argv[1], "-h", 9)) ||
+       (!strcmp(argv[1], "--help")))
       fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n");
-      close(skfd);
-      return(0);
-    }
-
-  /* The device name must be the first argument */
-  /* Name only : show spy list for that device only */
-  if(argc == 2)
-    {
-      print_spy_info(skfd, argv[1]);
-      close(skfd);
-      return(0);
-    }
-
-  /* Otherwise, it's a list of address to set in the spy list */
-  goterr = set_spy_info(skfd, argv + 2, argc - 2, argv[1]);
+    else
+      /* The device name must be the first argument */
+      /* Name only : show spy list for that device only */
+      if(argc == 2)
+       print_spy_info(skfd, argv[1], NULL, 0);
+      else
+       /* Otherwise, it's a list of address to set in the spy list */
+       goterr = set_spy_info(skfd, argv + 2, argc - 2, argv[1]);
 
   /* Close the socket. */
   close(skfd);
index 8c5a93a..5950fd9 100644 (file)
  *     This is released unther the GPL license.
  */
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <linux/in.h>
-#include <linux/socket.h>
-#include <linux/if.h>
 
-int main(int argc, char** argv) {
+#include "iwlib.h"
+
+int main(int argc, char** argv)
+{
 
        int devsock;
        struct ifreq ifbuffer;
-       int i;
 
-       if (argc != 2) {
+       if ((argc != 2) || (argv[1][0] == '-')) {
                printf("Usage: macaddr interface\n");
                exit(1);
        }
 
-       devsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       devsock = socket(AF_INET, SOCK_STREAM, 0);
 
        if (devsock == -1) {
-               printf("Failed opening socket\n");
+               perror("Failed opening socket");
                exit (1);
        }
 
        memset(&ifbuffer, 0, sizeof(ifbuffer));
-       strcpy(ifbuffer.ifr_name, argv[1]);
+       strncpy(ifbuffer.ifr_name, argv[1], sizeof(ifbuffer.ifr_name));
        if (ioctl(devsock, SIOCGIFHWADDR, &ifbuffer) == -1) {
-               printf("There is no MACADDR for %s\n", argv[1]);
+               fprintf(stderr, "There is no MACADDR for %s\n", argv[1]);
                exit(1);
        }
-       close (devsock);
+       close(devsock);
 
-       for (i = 0; i < IFHWADDRLEN; i++)
-               printf("%02X", (unsigned char) ifbuffer.ifr_ifru.ifru_hwaddr.sa_data[i]);
-       printf("\n");
+       puts(iw_ether_ntoa((struct ether_addr *) ifbuffer.ifr_ifru.ifru_hwaddr.sa_data));
 
        exit(0);
-
 }
diff --git a/wireless_tools/wireless.13.h b/wireless_tools/wireless.13.h
new file mode 100644 (file)
index 0000000..fa3c64f
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version :   13      6.12.01
+ *
+ * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands.  This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ *     # net/core/dev.c (two place + add include)
+ *     # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ *     # net/core/dev.c (two other places)
+ *     # include/linux/netdevice.h (one place)
+ *     # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2001 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ *     # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ *     # include/linux/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+#include <linux/types.h>               /* for "caddr_t" et al          */
+#include <linux/socket.h>              /* for "struct sockaddr" et al  */
+#include <linux/if.h>                  /* for IFNAMSIZ and co... */
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT   13
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ *     Alan Cox start some incompatibles changes. I've integrated a bit more.
+ *     - Encryption renamed to Encode to avoid US regulation problems
+ *     - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ *     - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ *     - Missing encoding definitions in range
+ *     - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ *     - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ *     - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ *     - Changed my e-mail address
+ *     - More 802.11 support (nickname, rate, rts, frag)
+ *     - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ *     - Support for 'mode of operation' (ad-hoc, managed...)
+ *     - Support for unicast and multicast power saving
+ *     - Change encoding to support larger tokens (>64 bits)
+ *     - Updated iw_params (disable, flags) and use it for NWID
+ *     - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ *     - Add PM capability to range structure
+ *     - Add PM modifier : MAX/MIN/RELATIVE
+ *     - Add encoding option : IW_ENCODE_NOKEY
+ *     - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ *     - Add WE version in range (help backward/forward compatibility)
+ *     - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ *     - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ *     - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ *     - Add new statistics (frag, retry, beacon)
+ *     - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ *     - Document creation of new driver API.
+ *     - Extract union iwreq_data from struct iwreq (for new driver API).
+ *     - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Basic operations */
+#define SIOCSIWCOMMIT  0x8B00          /* Commit pending changes to driver */
+#define SIOCGIWNAME    0x8B01          /* get name == wireless protocol */
+#define SIOCSIWNWID    0x8B02          /* set network id (the cell) */
+#define SIOCGIWNWID    0x8B03          /* get network id */
+#define SIOCSIWFREQ    0x8B04          /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ    0x8B05          /* get channel/frequency (Hz) */
+#define SIOCSIWMODE    0x8B06          /* set operation mode */
+#define SIOCGIWMODE    0x8B07          /* get operation mode */
+#define SIOCSIWSENS    0x8B08          /* set sensitivity (dBm) */
+#define SIOCGIWSENS    0x8B09          /* get sensitivity (dBm) */
+
+/* Informative stuff */
+#define SIOCSIWRANGE   0x8B0A          /* Unused */
+#define SIOCGIWRANGE   0x8B0B          /* Get range of parameters */
+#define SIOCSIWPRIV    0x8B0C          /* Unused */
+#define SIOCGIWPRIV    0x8B0D          /* get private ioctl interface info */
+#define SIOCSIWSTATS   0x8B0E          /* Unused */
+#define SIOCGIWSTATS   0x8B0F          /* Get /proc/net/wireless stats */
+
+/* Mobile IP support */
+#define SIOCSIWSPY     0x8B10          /* set spy addresses */
+#define SIOCGIWSPY     0x8B11          /* get spy info (quality of link) */
+
+/* Access Point manipulation */
+#define SIOCSIWAP      0x8B14          /* set access point MAC addresses */
+#define SIOCGIWAP      0x8B15          /* get access point MAC addresses */
+#define SIOCGIWAPLIST  0x8B17          /* get list of access point in range */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID   0x8B1A          /* set ESSID (network name) */
+#define SIOCGIWESSID   0x8B1B          /* get ESSID */
+#define SIOCSIWNICKN   0x8B1C          /* set node name/nickname */
+#define SIOCGIWNICKN   0x8B1D          /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE...
+ * The "flags" member indicate if the ESSID is active or not (promiscuous).
+ */
+
+/* Other parameters useful in 802.11 and some other devices */
+#define SIOCSIWRATE    0x8B20          /* set default bit rate (bps) */
+#define SIOCGIWRATE    0x8B21          /* get default bit rate (bps) */
+#define SIOCSIWRTS     0x8B22          /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS     0x8B23          /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG    0x8B24          /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG    0x8B25          /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW   0x8B26          /* set transmit power (dBm) */
+#define SIOCGIWTXPOW   0x8B27          /* get transmit power (dBm) */
+#define SIOCSIWRETRY   0x8B28          /* set retry limits and lifetime */
+#define SIOCGIWRETRY   0x8B29          /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+#define SIOCSIWENCODE  0x8B2A          /* set encoding token & mode */
+#define SIOCGIWENCODE  0x8B2B          /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+#define SIOCSIWPOWER   0x8B2C          /* set Power Management settings */
+#define SIOCGIWPOWER   0x8B2D          /* get Power Management settings */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 16 ioctl are wireless device private.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+#define SIOCIWFIRSTPRIV        0x8BE0
+#define SIOCIWLASTPRIV 0x8BFF
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'odd' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command).
+ * And I repeat : you are not obliged to use them with iwspy, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST    0x8B00
+#define SIOCIWLAST     SIOCIWLASTPRIV          /* 0x8BFF */
+
+/* Even : get (world access), odd : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+#define IW_PRIV_TYPE_MASK      0x7000  /* Type of arguments */
+#define IW_PRIV_TYPE_NONE      0x0000
+#define IW_PRIV_TYPE_BYTE      0x1000  /* Char as number */
+#define IW_PRIV_TYPE_CHAR      0x2000  /* Char as character */
+#define IW_PRIV_TYPE_INT       0x4000  /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT     0x5000
+
+#define IW_PRIV_SIZE_FIXED     0x0800  /* Variable or fixed nuber of args */
+
+#define IW_PRIV_SIZE_MASK      0x07FF  /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+#define IW_MAX_FREQUENCIES     16
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+#define IW_MAX_BITRATES                8
+
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER         8
+
+/* Maximum of address that you may set with SPY */
+#define IW_MAX_SPY             8
+
+/* Maximum of address that you may get in the
+   list of access points in range */
+#define IW_MAX_AP              8
+
+/* Maximum size of the ESSID and NICKN strings */
+#define IW_ESSID_MAX_SIZE      32
+
+/* Modes of operation */
+#define IW_MODE_AUTO   0       /* Let the driver decides */
+#define IW_MODE_ADHOC  1       /* Single cell network */
+#define IW_MODE_INFRA  2       /* Multi cell network, roaming, ... */
+#define IW_MODE_MASTER 3       /* Synchronisation master or Access Point */
+#define IW_MODE_REPEAT 4       /* Wireless Repeater (forwarder) */
+#define IW_MODE_SECOND 5       /* Secondary master/repeater (backup) */
+
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+#define IW_MAX_ENCODING_SIZES  8
+
+/* Maximum size of the encoding token in bytes */
+#define IW_ENCODING_TOKEN_MAX  32      /* 256 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+#define IW_ENCODE_INDEX                0x00FF  /* Token index (if needed) */
+#define IW_ENCODE_FLAGS                0xFF00  /* Flags defined below */
+#define IW_ENCODE_MODE         0xF000  /* Modes defined below */
+#define IW_ENCODE_DISABLED     0x8000  /* Encoding disabled */
+#define IW_ENCODE_ENABLED      0x0000  /* Encoding enabled */
+#define IW_ENCODE_RESTRICTED   0x4000  /* Refuse non-encoded packets */
+#define IW_ENCODE_OPEN         0x2000  /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
+
+/* Power management flags available (along with the value, if any) */
+#define IW_POWER_ON            0x0000  /* No details... */
+#define IW_POWER_TYPE          0xF000  /* Type of parameter */
+#define IW_POWER_PERIOD                0x1000  /* Value is a period/duration of  */
+#define IW_POWER_TIMEOUT       0x2000  /* Value is a timeout (to go asleep) */
+#define IW_POWER_MODE          0x0F00  /* Power Management mode */
+#define IW_POWER_UNICAST_R     0x0100  /* Receive only unicast messages */
+#define IW_POWER_MULTICAST_R   0x0200  /* Receive only multicast messages */
+#define IW_POWER_ALL_R         0x0300  /* Receive all messages though PM */
+#define IW_POWER_FORCE_S       0x0400  /* Force PM procedure for sending unicast */
+#define IW_POWER_REPEATER      0x0800  /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER      0x000F  /* Modify a parameter */
+#define IW_POWER_MIN           0x0001  /* Value is a minimum  */
+#define IW_POWER_MAX           0x0002  /* Value is a maximum */
+#define IW_POWER_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_DBM           0x0000  /* Value is in dBm */
+#define IW_TXPOW_MWATT         0x0001  /* Value is in mW */
+
+/* Retry limits and lifetime flags available */
+#define IW_RETRY_ON            0x0000  /* No details... */
+#define IW_RETRY_TYPE          0xF000  /* Type of parameter */
+#define IW_RETRY_LIMIT         0x1000  /* Maximum number of retries*/
+#define IW_RETRY_LIFETIME      0x2000  /* Maximum duration of retries in us */
+#define IW_RETRY_MODIFIER      0x000F  /* Modify a parameter */
+#define IW_RETRY_MIN           0x0001  /* Value is a minimum  */
+#define IW_RETRY_MAX           0x0002  /* Value is a maximum */
+#define IW_RETRY_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ *     Generic format for most parameters that fit in an int
+ */
+struct iw_param
+{
+  __s32                value;          /* The value of the parameter itself */
+  __u8         fixed;          /* Hardware should not use auto select */
+  __u8         disabled;       /* Disable the feature */
+  __u16                flags;          /* Various specifc flags (if any) */
+};
+
+/*
+ *     For all data larger than 16 octets, we need to use a
+ *     pointer to memory allocated in user space.
+ */
+struct iw_point
+{
+  caddr_t      pointer;        /* Pointer to the data  (in user space) */
+  __u16                length;         /* number of fields or size in bytes */
+  __u16                flags;          /* Optional params */
+};
+
+/*
+ *     A frequency
+ *     For numbers lower than 10^9, we encode the number in 'm' and
+ *     set 'e' to 0
+ *     For number greater than 10^9, we divide it by the lowest power
+ *     of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ *     The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq
+{
+       __u32           m;              /* Mantissa */
+       __u16           e;              /* Exponent */
+       __u8            i;              /* List index (when in range struct) */
+};
+
+/*
+ *     Quality of the link
+ */
+struct iw_quality
+{
+       __u8            qual;           /* link quality (%retries, SNR,
+                                          %missed beacons or better...) */
+       __u8            level;          /* signal level (dBm) */
+       __u8            noise;          /* noise level (dBm) */
+       __u8            updated;        /* Flags to know if updated */
+};
+
+/*
+ *     Packet discarded in the wireless adapter due to
+ *     "wireless" specific problems...
+ *     Note : the list of counter and statistics in net_device_stats
+ *     is already pretty exhaustive, and you should use that first.
+ *     This is only additional stats...
+ */
+struct iw_discarded
+{
+       __u32           nwid;           /* Rx : Wrong nwid/essid */
+       __u32           code;           /* Rx : Unable to code/decode (WEP) */
+       __u32           fragment;       /* Rx : Can't perform MAC reassembly */
+       __u32           retries;        /* Tx : Max MAC retries num reached */
+       __u32           misc;           /* Others cases */
+};
+
+/*
+ *     Packet/Time period missed in the wireless adapter due to
+ *     "wireless" specific problems...
+ */
+struct iw_missed
+{
+       __u32           beacon;         /* Missed beacons/superframe */
+};
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics
+{
+       __u16           status;         /* Status
+                                        * - device dependent for now */
+
+       struct iw_quality       qual;           /* Quality of the link
+                                                * (instant/mean/max) */
+       struct iw_discarded     discard;        /* Packet discarded counts */
+       struct iw_missed        miss;           /* Packet missed counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used 
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ */
+union  iwreq_data
+{
+       /* Config - generic */
+       char            name[IFNAMSIZ];
+       /* Name : used to verify the presence of  wireless extensions.
+        * Name of the protocol/provider... */
+
+       struct iw_point essid;          /* Extended network name */
+       struct iw_param nwid;           /* network id (or domain - the cell) */
+       struct iw_freq  freq;           /* frequency or channel :
+                                        * 0-1000 = channel
+                                        * > 1000 = frequency in Hz */
+
+       struct iw_param sens;           /* signal level threshold */
+       struct iw_param bitrate;        /* default bit rate */
+       struct iw_param txpower;        /* default transmit power */
+       struct iw_param rts;            /* RTS threshold threshold */
+       struct iw_param frag;           /* Fragmentation threshold */
+       __u32           mode;           /* Operation mode */
+       struct iw_param retry;          /* Retry limits & lifetime */
+
+       struct iw_point encoding;       /* Encoding stuff : tokens */
+       struct iw_param power;          /* PM duration/timeout */
+
+       struct sockaddr ap_addr;        /* Access point address */
+
+       struct iw_point data;           /* Other large parameters */
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+ */
+struct iwreq 
+{
+       union
+       {
+               char    ifrn_name[IFNAMSIZ];    /* if name, e.g. "eth0" */
+       } ifr_ifrn;
+
+       /* Data part (defined just above) */
+       union   iwreq_data      u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ *     For those ioctl which want to exchange mode data that what could
+ *     fit in the above structure...
+ */
+
+/*
+ *     Range of parameters
+ */
+
+struct iw_range
+{
+       /* Informative stuff (to choose between different interface) */
+       __u32           throughput;     /* To give an idea... */
+       /* In theory this value should be the maximum benchmarked
+        * TCP/IP throughput, because with most of these devices the
+        * bit rate is meaningless (overhead an co) to estimate how
+        * fast the connection will go and pick the fastest one.
+        * I suggest people to play with Netperf or any benchmark...
+        */
+
+       /* NWID (or domain id) */
+       __u32           min_nwid;       /* Minimal NWID we are able to set */
+       __u32           max_nwid;       /* Maximal NWID we are able to set */
+
+       /* Frequency */
+       __u16           num_channels;   /* Number of channels [0; num - 1] */
+       __u8            num_frequency;  /* Number of entry in the list */
+       struct iw_freq  freq[IW_MAX_FREQUENCIES];       /* list */
+       /* Note : this frequency list doesn't need to fit channel numbers */
+
+       /* signal level threshold range */
+       __s32   sensitivity;
+
+       /* Quality of link & SNR stuff */
+       struct iw_quality       max_qual;       /* Quality of the link */
+
+       /* Rates */
+       __u8            num_bitrates;   /* Number of entries in the list */
+       __s32           bitrate[IW_MAX_BITRATES];       /* list, in bps */
+
+       /* RTS threshold */
+       __s32           min_rts;        /* Minimal RTS threshold */
+       __s32           max_rts;        /* Maximal RTS threshold */
+
+       /* Frag threshold */
+       __s32           min_frag;       /* Minimal frag threshold */
+       __s32           max_frag;       /* Maximal frag threshold */
+
+       /* Power Management duration & timeout */
+       __s32           min_pmp;        /* Minimal PM period */
+       __s32           max_pmp;        /* Maximal PM period */
+       __s32           min_pmt;        /* Minimal PM timeout */
+       __s32           max_pmt;        /* Maximal PM timeout */
+       __u16           pmp_flags;      /* How to decode max/min PM period */
+       __u16           pmt_flags;      /* How to decode max/min PM timeout */
+       __u16           pm_capa;        /* What PM options are supported */
+
+       /* Encoder stuff */
+       __u16   encoding_size[IW_MAX_ENCODING_SIZES];   /* Different token sizes */
+       __u8    num_encoding_sizes;     /* Number of entry in the list */
+       __u8    max_encoding_tokens;    /* Max number of tokens */
+
+       /* Transmit power */
+       __u16           txpower_capa;   /* What options are supported */
+       __u8            num_txpower;    /* Number of entries in the list */
+       __s32           txpower[IW_MAX_TXPOWER];        /* list, in bps */
+
+       /* Wireless Extension version info */
+       __u8            we_version_compiled;    /* Must be WIRELESS_EXT */
+       __u8            we_version_source;      /* Last update of source */
+
+       /* Retry limits and lifetime */
+       __u16           retry_capa;     /* What retry options are supported */
+       __u16           retry_flags;    /* How to decode max/min retry limit */
+       __u16           r_time_flags;   /* How to decode max/min retry life */
+       __s32           min_retry;      /* Minimal number of retries */
+       __s32           max_retry;      /* Maximal number of retries */
+       __s32           min_r_time;     /* Minimal retry lifetime */
+       __s32           max_r_time;     /* Maximal retry lifetime */
+
+       /* Average quality of link & SNR */
+       struct iw_quality       avg_qual;       /* Quality of the link */
+       /* This should contain the average/typical values of the quality
+        * indicator. This should be the threshold between a "good" and
+        * a "bad" link (example : monitor going from green to orange).
+        * Currently, user space apps like quality monitors don't have any
+        * way to calibrate the measurement. With this, they can split
+        * the range between 0 and max_qual in different quality level
+        * (using a geometric subdivision centered on the average).
+        * I expect that people doing the user space apps will feedback
+        * us on which value we need to put in each driver...
+        */
+};
+
+/*
+ * Private ioctl interface information
+ */
+struct iw_priv_args
+{
+       __u32           cmd;            /* Number of the ioctl to issue */
+       __u16           set_args;       /* Type and number of args */
+       __u16           get_args;       /* Type and number of args */
+       char            name[IFNAMSIZ]; /* Name of the extension */
+};
+
+#endif /* _LINUX_WIRELESS_H */
diff --git a/wireless_tools/wireless.14.h b/wireless_tools/wireless.14.h
new file mode 100644 (file)
index 0000000..226f540
--- /dev/null
@@ -0,0 +1,669 @@
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version :   14      25.1.02
+ *
+ * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands.  This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ *     # net/core/dev.c (two place + add include)
+ *     # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ *     # net/core/dev.c (two other places)
+ *     # include/linux/netdevice.h (one place)
+ *     # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ *     # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ *     # include/linux/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+ *     # include/linux/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+#include <linux/types.h>               /* for "caddr_t" et al          */
+#include <linux/socket.h>              /* for "struct sockaddr" et al  */
+#include <linux/if.h>                  /* for IFNAMSIZ and co... */
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT   14
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ *     Alan Cox start some incompatibles changes. I've integrated a bit more.
+ *     - Encryption renamed to Encode to avoid US regulation problems
+ *     - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ *     - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ *     - Missing encoding definitions in range
+ *     - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ *     - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ *     - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ *     - Changed my e-mail address
+ *     - More 802.11 support (nickname, rate, rts, frag)
+ *     - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ *     - Support for 'mode of operation' (ad-hoc, managed...)
+ *     - Support for unicast and multicast power saving
+ *     - Change encoding to support larger tokens (>64 bits)
+ *     - Updated iw_params (disable, flags) and use it for NWID
+ *     - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ *     - Add PM capability to range structure
+ *     - Add PM modifier : MAX/MIN/RELATIVE
+ *     - Add encoding option : IW_ENCODE_NOKEY
+ *     - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ *     - Add WE version in range (help backward/forward compatibility)
+ *     - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ *     - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ *     - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ *     - Add new statistics (frag, retry, beacon)
+ *     - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ *     - Document creation of new driver API.
+ *     - Extract union iwreq_data from struct iwreq (for new driver API).
+ *     - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ *
+ * V13 to V14
+ * ----------
+ *     - Wireless Events support : define struct iw_event
+ *     - Define additional specific event numbers
+ *     - Add "addr" and "param" fields in union iwreq_data
+ *     - AP scanning stuff (SIOCSIWSCAN and friends)
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Basic operations */
+#define SIOCSIWCOMMIT  0x8B00          /* Commit pending changes to driver */
+#define SIOCGIWNAME    0x8B01          /* get name == wireless protocol */
+#define SIOCSIWNWID    0x8B02          /* set network id (the cell) */
+#define SIOCGIWNWID    0x8B03          /* get network id */
+#define SIOCSIWFREQ    0x8B04          /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ    0x8B05          /* get channel/frequency (Hz) */
+#define SIOCSIWMODE    0x8B06          /* set operation mode */
+#define SIOCGIWMODE    0x8B07          /* get operation mode */
+#define SIOCSIWSENS    0x8B08          /* set sensitivity (dBm) */
+#define SIOCGIWSENS    0x8B09          /* get sensitivity (dBm) */
+
+/* Informative stuff */
+#define SIOCSIWRANGE   0x8B0A          /* Unused */
+#define SIOCGIWRANGE   0x8B0B          /* Get range of parameters */
+#define SIOCSIWPRIV    0x8B0C          /* Unused */
+#define SIOCGIWPRIV    0x8B0D          /* get private ioctl interface info */
+#define SIOCSIWSTATS   0x8B0E          /* Unused */
+#define SIOCGIWSTATS   0x8B0F          /* Get /proc/net/wireless stats */
+
+/* Mobile IP support */
+#define SIOCSIWSPY     0x8B10          /* set spy addresses */
+#define SIOCGIWSPY     0x8B11          /* get spy info (quality of link) */
+
+/* Access Point manipulation */
+#define SIOCSIWAP      0x8B14          /* set access point MAC addresses */
+#define SIOCGIWAP      0x8B15          /* get access point MAC addresses */
+#define SIOCGIWAPLIST  0x8B17          /* get list of access point in range */
+#define SIOCSIWSCAN    0x8B18          /* trigger scanning */
+#define SIOCGIWSCAN    0x8B19          /* get scanning results */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID   0x8B1A          /* set ESSID (network name) */
+#define SIOCGIWESSID   0x8B1B          /* get ESSID */
+#define SIOCSIWNICKN   0x8B1C          /* set node name/nickname */
+#define SIOCGIWNICKN   0x8B1D          /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE...
+ * The "flags" member indicate if the ESSID is active or not (promiscuous).
+ */
+
+/* Other parameters useful in 802.11 and some other devices */
+#define SIOCSIWRATE    0x8B20          /* set default bit rate (bps) */
+#define SIOCGIWRATE    0x8B21          /* get default bit rate (bps) */
+#define SIOCSIWRTS     0x8B22          /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS     0x8B23          /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG    0x8B24          /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG    0x8B25          /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW   0x8B26          /* set transmit power (dBm) */
+#define SIOCGIWTXPOW   0x8B27          /* get transmit power (dBm) */
+#define SIOCSIWRETRY   0x8B28          /* set retry limits and lifetime */
+#define SIOCGIWRETRY   0x8B29          /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+#define SIOCSIWENCODE  0x8B2A          /* set encoding token & mode */
+#define SIOCGIWENCODE  0x8B2B          /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+#define SIOCSIWPOWER   0x8B2C          /* set Power Management settings */
+#define SIOCGIWPOWER   0x8B2D          /* get Power Management settings */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 16 ioctl are wireless device private.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+#define SIOCIWFIRSTPRIV        0x8BE0
+#define SIOCIWLASTPRIV 0x8BFF
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'odd' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command).
+ * And I repeat : you are not obliged to use them with iwspy, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST    0x8B00
+#define SIOCIWLAST     SIOCIWLASTPRIV          /* 0x8BFF */
+
+/* Even : get (world access), odd : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/* Those are *NOT* ioctls, do not issue request on them !!! */
+/* Most events use the same identifier as ioctl requests */
+
+#define IWEVTXDROP     0x8C00          /* Packet dropped to excessive retry */
+#define IWEVQUAL       0x8C01          /* Quality part of statistics */
+
+#define IWEVFIRST      0x8C00
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+#define IW_PRIV_TYPE_MASK      0x7000  /* Type of arguments */
+#define IW_PRIV_TYPE_NONE      0x0000
+#define IW_PRIV_TYPE_BYTE      0x1000  /* Char as number */
+#define IW_PRIV_TYPE_CHAR      0x2000  /* Char as character */
+#define IW_PRIV_TYPE_INT       0x4000  /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT     0x5000
+
+#define IW_PRIV_SIZE_FIXED     0x0800  /* Variable or fixed nuber of args */
+
+#define IW_PRIV_SIZE_MASK      0x07FF  /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+#define IW_MAX_FREQUENCIES     16
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+#define IW_MAX_BITRATES                8
+
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER         8
+
+/* Maximum of address that you may set with SPY */
+#define IW_MAX_SPY             8
+
+/* Maximum of address that you may get in the
+   list of access points in range */
+#define IW_MAX_AP              8
+
+/* Maximum size of the ESSID and NICKN strings */
+#define IW_ESSID_MAX_SIZE      32
+
+/* Modes of operation */
+#define IW_MODE_AUTO   0       /* Let the driver decides */
+#define IW_MODE_ADHOC  1       /* Single cell network */
+#define IW_MODE_INFRA  2       /* Multi cell network, roaming, ... */
+#define IW_MODE_MASTER 3       /* Synchronisation master or Access Point */
+#define IW_MODE_REPEAT 4       /* Wireless Repeater (forwarder) */
+#define IW_MODE_SECOND 5       /* Secondary master/repeater (backup) */
+
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+#define IW_MAX_ENCODING_SIZES  8
+
+/* Maximum size of the encoding token in bytes */
+#define IW_ENCODING_TOKEN_MAX  32      /* 256 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+#define IW_ENCODE_INDEX                0x00FF  /* Token index (if needed) */
+#define IW_ENCODE_FLAGS                0xFF00  /* Flags defined below */
+#define IW_ENCODE_MODE         0xF000  /* Modes defined below */
+#define IW_ENCODE_DISABLED     0x8000  /* Encoding disabled */
+#define IW_ENCODE_ENABLED      0x0000  /* Encoding enabled */
+#define IW_ENCODE_RESTRICTED   0x4000  /* Refuse non-encoded packets */
+#define IW_ENCODE_OPEN         0x2000  /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
+
+/* Power management flags available (along with the value, if any) */
+#define IW_POWER_ON            0x0000  /* No details... */
+#define IW_POWER_TYPE          0xF000  /* Type of parameter */
+#define IW_POWER_PERIOD                0x1000  /* Value is a period/duration of  */
+#define IW_POWER_TIMEOUT       0x2000  /* Value is a timeout (to go asleep) */
+#define IW_POWER_MODE          0x0F00  /* Power Management mode */
+#define IW_POWER_UNICAST_R     0x0100  /* Receive only unicast messages */
+#define IW_POWER_MULTICAST_R   0x0200  /* Receive only multicast messages */
+#define IW_POWER_ALL_R         0x0300  /* Receive all messages though PM */
+#define IW_POWER_FORCE_S       0x0400  /* Force PM procedure for sending unicast */
+#define IW_POWER_REPEATER      0x0800  /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER      0x000F  /* Modify a parameter */
+#define IW_POWER_MIN           0x0001  /* Value is a minimum  */
+#define IW_POWER_MAX           0x0002  /* Value is a maximum */
+#define IW_POWER_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_DBM           0x0000  /* Value is in dBm */
+#define IW_TXPOW_MWATT         0x0001  /* Value is in mW */
+
+/* Retry limits and lifetime flags available */
+#define IW_RETRY_ON            0x0000  /* No details... */
+#define IW_RETRY_TYPE          0xF000  /* Type of parameter */
+#define IW_RETRY_LIMIT         0x1000  /* Maximum number of retries*/
+#define IW_RETRY_LIFETIME      0x2000  /* Maximum duration of retries in us */
+#define IW_RETRY_MODIFIER      0x000F  /* Modify a parameter */
+#define IW_RETRY_MIN           0x0001  /* Value is a minimum  */
+#define IW_RETRY_MAX           0x0002  /* Value is a maximum */
+#define IW_RETRY_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
+
+/* Scanning request flags */
+#define IW_SCAN_DEFAULT                0x0000  /* Default scan of the driver */
+#define IW_SCAN_ALL_ESSID      0x0001  /* Scan all ESSIDs */
+#define IW_SCAN_THIS_ESSID     0x0002  /* Scan only this ESSID */
+#define IW_SCAN_ALL_FREQ       0x0004  /* Scan all Frequencies */
+#define IW_SCAN_THIS_FREQ      0x0008  /* Scan only this Frequency */
+#define IW_SCAN_ALL_MODE       0x0010  /* Scan all Modes */
+#define IW_SCAN_THIS_MODE      0x0020  /* Scan only this Mode */
+#define IW_SCAN_ALL_RATE       0x0040  /* Scan all Bit-Rates */
+#define IW_SCAN_THIS_RATE      0x0080  /* Scan only this Bit-Rate */
+/* Maximum size of returned data */
+#define IW_SCAN_MAX_DATA       4096    /* In bytes */
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ *     Generic format for most parameters that fit in an int
+ */
+struct iw_param
+{
+  __s32                value;          /* The value of the parameter itself */
+  __u8         fixed;          /* Hardware should not use auto select */
+  __u8         disabled;       /* Disable the feature */
+  __u16                flags;          /* Various specifc flags (if any) */
+};
+
+/*
+ *     For all data larger than 16 octets, we need to use a
+ *     pointer to memory allocated in user space.
+ */
+struct iw_point
+{
+  caddr_t      pointer;        /* Pointer to the data  (in user space) */
+  __u16                length;         /* number of fields or size in bytes */
+  __u16                flags;          /* Optional params */
+};
+
+/*
+ *     A frequency
+ *     For numbers lower than 10^9, we encode the number in 'm' and
+ *     set 'e' to 0
+ *     For number greater than 10^9, we divide it by the lowest power
+ *     of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ *     The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq
+{
+       __u32           m;              /* Mantissa */
+       __u16           e;              /* Exponent */
+       __u8            i;              /* List index (when in range struct) */
+};
+
+/*
+ *     Quality of the link
+ */
+struct iw_quality
+{
+       __u8            qual;           /* link quality (%retries, SNR,
+                                          %missed beacons or better...) */
+       __u8            level;          /* signal level (dBm) */
+       __u8            noise;          /* noise level (dBm) */
+       __u8            updated;        /* Flags to know if updated */
+};
+
+/*
+ *     Packet discarded in the wireless adapter due to
+ *     "wireless" specific problems...
+ *     Note : the list of counter and statistics in net_device_stats
+ *     is already pretty exhaustive, and you should use that first.
+ *     This is only additional stats...
+ */
+struct iw_discarded
+{
+       __u32           nwid;           /* Rx : Wrong nwid/essid */
+       __u32           code;           /* Rx : Unable to code/decode (WEP) */
+       __u32           fragment;       /* Rx : Can't perform MAC reassembly */
+       __u32           retries;        /* Tx : Max MAC retries num reached */
+       __u32           misc;           /* Others cases */
+};
+
+/*
+ *     Packet/Time period missed in the wireless adapter due to
+ *     "wireless" specific problems...
+ */
+struct iw_missed
+{
+       __u32           beacon;         /* Missed beacons/superframe */
+};
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics
+{
+       __u16           status;         /* Status
+                                        * - device dependent for now */
+
+       struct iw_quality       qual;           /* Quality of the link
+                                                * (instant/mean/max) */
+       struct iw_discarded     discard;        /* Packet discarded counts */
+       struct iw_missed        miss;           /* Packet missed counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used 
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ */
+union  iwreq_data
+{
+       /* Config - generic */
+       char            name[IFNAMSIZ];
+       /* Name : used to verify the presence of  wireless extensions.
+        * Name of the protocol/provider... */
+
+       struct iw_point essid;          /* Extended network name */
+       struct iw_param nwid;           /* network id (or domain - the cell) */
+       struct iw_freq  freq;           /* frequency or channel :
+                                        * 0-1000 = channel
+                                        * > 1000 = frequency in Hz */
+
+       struct iw_param sens;           /* signal level threshold */
+       struct iw_param bitrate;        /* default bit rate */
+       struct iw_param txpower;        /* default transmit power */
+       struct iw_param rts;            /* RTS threshold threshold */
+       struct iw_param frag;           /* Fragmentation threshold */
+       __u32           mode;           /* Operation mode */
+       struct iw_param retry;          /* Retry limits & lifetime */
+
+       struct iw_point encoding;       /* Encoding stuff : tokens */
+       struct iw_param power;          /* PM duration/timeout */
+       struct iw_quality qual;         /* Quality part of statistics */
+
+       struct sockaddr ap_addr;        /* Access point address */
+       struct sockaddr addr;           /* Destination address (hw) */
+
+       struct iw_param param;          /* Other small parameters */
+       struct iw_point data;           /* Other large parameters */
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+ */
+struct iwreq 
+{
+       union
+       {
+               char    ifrn_name[IFNAMSIZ];    /* if name, e.g. "eth0" */
+       } ifr_ifrn;
+
+       /* Data part (defined just above) */
+       union   iwreq_data      u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ *     For those ioctl which want to exchange mode data that what could
+ *     fit in the above structure...
+ */
+
+/*
+ *     Range of parameters
+ */
+
+struct iw_range
+{
+       /* Informative stuff (to choose between different interface) */
+       __u32           throughput;     /* To give an idea... */
+       /* In theory this value should be the maximum benchmarked
+        * TCP/IP throughput, because with most of these devices the
+        * bit rate is meaningless (overhead an co) to estimate how
+        * fast the connection will go and pick the fastest one.
+        * I suggest people to play with Netperf or any benchmark...
+        */
+
+       /* NWID (or domain id) */
+       __u32           min_nwid;       /* Minimal NWID we are able to set */
+       __u32           max_nwid;       /* Maximal NWID we are able to set */
+
+       /* Frequency */
+       __u16           num_channels;   /* Number of channels [0; num - 1] */
+       __u8            num_frequency;  /* Number of entry in the list */
+       struct iw_freq  freq[IW_MAX_FREQUENCIES];       /* list */
+       /* Note : this frequency list doesn't need to fit channel numbers */
+
+       /* signal level threshold range */
+       __s32   sensitivity;
+
+       /* Quality of link & SNR stuff */
+       struct iw_quality       max_qual;       /* Quality of the link */
+
+       /* Rates */
+       __u8            num_bitrates;   /* Number of entries in the list */
+       __s32           bitrate[IW_MAX_BITRATES];       /* list, in bps */
+
+       /* RTS threshold */
+       __s32           min_rts;        /* Minimal RTS threshold */
+       __s32           max_rts;        /* Maximal RTS threshold */
+
+       /* Frag threshold */
+       __s32           min_frag;       /* Minimal frag threshold */
+       __s32           max_frag;       /* Maximal frag threshold */
+
+       /* Power Management duration & timeout */
+       __s32           min_pmp;        /* Minimal PM period */
+       __s32           max_pmp;        /* Maximal PM period */
+       __s32           min_pmt;        /* Minimal PM timeout */
+       __s32           max_pmt;        /* Maximal PM timeout */
+       __u16           pmp_flags;      /* How to decode max/min PM period */
+       __u16           pmt_flags;      /* How to decode max/min PM timeout */
+       __u16           pm_capa;        /* What PM options are supported */
+
+       /* Encoder stuff */
+       __u16   encoding_size[IW_MAX_ENCODING_SIZES];   /* Different token sizes */
+       __u8    num_encoding_sizes;     /* Number of entry in the list */
+       __u8    max_encoding_tokens;    /* Max number of tokens */
+
+       /* Transmit power */
+       __u16           txpower_capa;   /* What options are supported */
+       __u8            num_txpower;    /* Number of entries in the list */
+       __s32           txpower[IW_MAX_TXPOWER];        /* list, in bps */
+
+       /* Wireless Extension version info */
+       __u8            we_version_compiled;    /* Must be WIRELESS_EXT */
+       __u8            we_version_source;      /* Last update of source */
+
+       /* Retry limits and lifetime */
+       __u16           retry_capa;     /* What retry options are supported */
+       __u16           retry_flags;    /* How to decode max/min retry limit */
+       __u16           r_time_flags;   /* How to decode max/min retry life */
+       __s32           min_retry;      /* Minimal number of retries */
+       __s32           max_retry;      /* Maximal number of retries */
+       __s32           min_r_time;     /* Minimal retry lifetime */
+       __s32           max_r_time;     /* Maximal retry lifetime */
+
+       /* Average quality of link & SNR */
+       struct iw_quality       avg_qual;       /* Quality of the link */
+       /* This should contain the average/typical values of the quality
+        * indicator. This should be the threshold between a "good" and
+        * a "bad" link (example : monitor going from green to orange).
+        * Currently, user space apps like quality monitors don't have any
+        * way to calibrate the measurement. With this, they can split
+        * the range between 0 and max_qual in different quality level
+        * (using a geometric subdivision centered on the average).
+        * I expect that people doing the user space apps will feedback
+        * us on which value we need to put in each driver...
+        */
+};
+
+/*
+ * Private ioctl interface information
+ */
+struct iw_priv_args
+{
+       __u32           cmd;            /* Number of the ioctl to issue */
+       __u16           set_args;       /* Type and number of args */
+       __u16           get_args;       /* Type and number of args */
+       char            name[IFNAMSIZ]; /* Name of the extension */
+};
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/*
+ * Wireless events are carried through the rtnetlink socket to user
+ * space. They are encapsulated in the IFLA_WIRELESS field of
+ * a RTM_NEWLINK message.
+ */
+
+/*
+ * A Wireless Event. Contains basically the same data as the ioctl...
+ */
+struct iw_event
+{
+       __u16           len;                    /* Real lenght of this stuff */
+       __u16           cmd;                    /* Wireless IOCTL */
+       union iwreq_data        u;              /* IOCTL fixed payload */
+};
+
+/* Size of the Event prefix (including padding and alignement junk) */
+#define IW_EV_LCP_LEN  (sizeof(struct iw_event) - sizeof(union iwreq_data))
+/* Size of the various events */
+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
+#define IW_EV_POINT_LEN        (IW_EV_LCP_LEN + sizeof(struct iw_point))
+#define IW_EV_PARAM_LEN        (IW_EV_LCP_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
+
+/* Note : in the case of iw_point, the extra data will come at the
+ * end of the event */
+
+#endif /* _LINUX_WIRELESS_H */
index fa3c64f..e69de29 100644 (file)
@@ -1,599 +0,0 @@
-/*
- * This file define a set of standard wireless extensions
- *
- * Version :   13      6.12.01
- *
- * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
- */
-
-#ifndef _LINUX_WIRELESS_H
-#define _LINUX_WIRELESS_H
-
-/************************** DOCUMENTATION **************************/
-/*
- * Initial APIs (1996 -> onward) :
- * -----------------------------
- * Basically, the wireless extensions are for now a set of standard ioctl
- * call + /proc/net/wireless
- *
- * The entry /proc/net/wireless give statistics and information on the
- * driver.
- * This is better than having each driver having its entry because
- * its centralised and we may remove the driver module safely.
- *
- * Ioctl are used to configure the driver and issue commands.  This is
- * better than command line options of insmod because we may want to
- * change dynamically (while the driver is running) some parameters.
- *
- * The ioctl mechanimsm are copied from standard devices ioctl.
- * We have the list of command plus a structure descibing the
- * data exchanged...
- * Note that to add these ioctl, I was obliged to modify :
- *     # net/core/dev.c (two place + add include)
- *     # net/ipv4/af_inet.c (one place + add include)
- *
- * /proc/net/wireless is a copy of /proc/net/dev.
- * We have a structure for data passed from the driver to /proc/net/wireless
- * Too add this, I've modified :
- *     # net/core/dev.c (two other places)
- *     # include/linux/netdevice.h (one place)
- *     # include/linux/proc_fs.h (one place)
- *
- * New driver API (2001 -> onward) :
- * -------------------------------
- * This file is only concerned with the user space API and common definitions.
- * The new driver API is defined and documented in :
- *     # include/net/iw_handler.h
- *
- * Note as well that /proc/net/wireless implementation has now moved in :
- *     # include/linux/wireless.c
- *
- * Other comments :
- * --------------
- * Do not add here things that are redundant with other mechanisms
- * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
- * wireless specific.
- *
- * These wireless extensions are not magic : each driver has to provide
- * support for them...
- *
- * IMPORTANT NOTE : As everything in the kernel, this is very much a
- * work in progress. Contact me if you have ideas of improvements...
- */
-
-/***************************** INCLUDES *****************************/
-
-#include <linux/types.h>               /* for "caddr_t" et al          */
-#include <linux/socket.h>              /* for "struct sockaddr" et al  */
-#include <linux/if.h>                  /* for IFNAMSIZ and co... */
-
-/***************************** VERSION *****************************/
-/*
- * This constant is used to know the availability of the wireless
- * extensions and to know which version of wireless extensions it is
- * (there is some stuff that will be added in the future...)
- * I just plan to increment with each new version.
- */
-#define WIRELESS_EXT   13
-
-/*
- * Changes :
- *
- * V2 to V3
- * --------
- *     Alan Cox start some incompatibles changes. I've integrated a bit more.
- *     - Encryption renamed to Encode to avoid US regulation problems
- *     - Frequency changed from float to struct to avoid problems on old 386
- *
- * V3 to V4
- * --------
- *     - Add sensitivity
- *
- * V4 to V5
- * --------
- *     - Missing encoding definitions in range
- *     - Access points stuff
- *
- * V5 to V6
- * --------
- *     - 802.11 support (ESSID ioctls)
- *
- * V6 to V7
- * --------
- *     - define IW_ESSID_MAX_SIZE and IW_MAX_AP
- *
- * V7 to V8
- * --------
- *     - Changed my e-mail address
- *     - More 802.11 support (nickname, rate, rts, frag)
- *     - List index in frequencies
- *
- * V8 to V9
- * --------
- *     - Support for 'mode of operation' (ad-hoc, managed...)
- *     - Support for unicast and multicast power saving
- *     - Change encoding to support larger tokens (>64 bits)
- *     - Updated iw_params (disable, flags) and use it for NWID
- *     - Extracted iw_point from iwreq for clarity
- *
- * V9 to V10
- * ---------
- *     - Add PM capability to range structure
- *     - Add PM modifier : MAX/MIN/RELATIVE
- *     - Add encoding option : IW_ENCODE_NOKEY
- *     - Add TxPower ioctls (work like TxRate)
- *
- * V10 to V11
- * ----------
- *     - Add WE version in range (help backward/forward compatibility)
- *     - Add retry ioctls (work like PM)
- *
- * V11 to V12
- * ----------
- *     - Add SIOCSIWSTATS to get /proc/net/wireless programatically
- *     - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
- *     - Add new statistics (frag, retry, beacon)
- *     - Add average quality (for user space calibration)
- *
- * V12 to V13
- * ----------
- *     - Document creation of new driver API.
- *     - Extract union iwreq_data from struct iwreq (for new driver API).
- *     - Rename SIOCSIWNAME as SIOCSIWCOMMIT
- */
-
-/**************************** CONSTANTS ****************************/
-
-/* -------------------------- IOCTL LIST -------------------------- */
-
-/* Basic operations */
-#define SIOCSIWCOMMIT  0x8B00          /* Commit pending changes to driver */
-#define SIOCGIWNAME    0x8B01          /* get name == wireless protocol */
-#define SIOCSIWNWID    0x8B02          /* set network id (the cell) */
-#define SIOCGIWNWID    0x8B03          /* get network id */
-#define SIOCSIWFREQ    0x8B04          /* set channel/frequency (Hz) */
-#define SIOCGIWFREQ    0x8B05          /* get channel/frequency (Hz) */
-#define SIOCSIWMODE    0x8B06          /* set operation mode */
-#define SIOCGIWMODE    0x8B07          /* get operation mode */
-#define SIOCSIWSENS    0x8B08          /* set sensitivity (dBm) */
-#define SIOCGIWSENS    0x8B09          /* get sensitivity (dBm) */
-
-/* Informative stuff */
-#define SIOCSIWRANGE   0x8B0A          /* Unused */
-#define SIOCGIWRANGE   0x8B0B          /* Get range of parameters */
-#define SIOCSIWPRIV    0x8B0C          /* Unused */
-#define SIOCGIWPRIV    0x8B0D          /* get private ioctl interface info */
-#define SIOCSIWSTATS   0x8B0E          /* Unused */
-#define SIOCGIWSTATS   0x8B0F          /* Get /proc/net/wireless stats */
-
-/* Mobile IP support */
-#define SIOCSIWSPY     0x8B10          /* set spy addresses */
-#define SIOCGIWSPY     0x8B11          /* get spy info (quality of link) */
-
-/* Access Point manipulation */
-#define SIOCSIWAP      0x8B14          /* set access point MAC addresses */
-#define SIOCGIWAP      0x8B15          /* get access point MAC addresses */
-#define SIOCGIWAPLIST  0x8B17          /* get list of access point in range */
-
-/* 802.11 specific support */
-#define SIOCSIWESSID   0x8B1A          /* set ESSID (network name) */
-#define SIOCGIWESSID   0x8B1B          /* get ESSID */
-#define SIOCSIWNICKN   0x8B1C          /* set node name/nickname */
-#define SIOCGIWNICKN   0x8B1D          /* get node name/nickname */
-/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
- * within the 'iwreq' structure, so we need to use the 'data' member to
- * point to a string in user space, like it is done for RANGE...
- * The "flags" member indicate if the ESSID is active or not (promiscuous).
- */
-
-/* Other parameters useful in 802.11 and some other devices */
-#define SIOCSIWRATE    0x8B20          /* set default bit rate (bps) */
-#define SIOCGIWRATE    0x8B21          /* get default bit rate (bps) */
-#define SIOCSIWRTS     0x8B22          /* set RTS/CTS threshold (bytes) */
-#define SIOCGIWRTS     0x8B23          /* get RTS/CTS threshold (bytes) */
-#define SIOCSIWFRAG    0x8B24          /* set fragmentation thr (bytes) */
-#define SIOCGIWFRAG    0x8B25          /* get fragmentation thr (bytes) */
-#define SIOCSIWTXPOW   0x8B26          /* set transmit power (dBm) */
-#define SIOCGIWTXPOW   0x8B27          /* get transmit power (dBm) */
-#define SIOCSIWRETRY   0x8B28          /* set retry limits and lifetime */
-#define SIOCGIWRETRY   0x8B29          /* get retry limits and lifetime */
-
-/* Encoding stuff (scrambling, hardware security, WEP...) */
-#define SIOCSIWENCODE  0x8B2A          /* set encoding token & mode */
-#define SIOCGIWENCODE  0x8B2B          /* get encoding token & mode */
-/* Power saving stuff (power management, unicast and multicast) */
-#define SIOCSIWPOWER   0x8B2C          /* set Power Management settings */
-#define SIOCGIWPOWER   0x8B2D          /* get Power Management settings */
-
-/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
-
-/* These 16 ioctl are wireless device private.
- * Each driver is free to use them for whatever purpose it chooses,
- * however the driver *must* export the description of those ioctls
- * with SIOCGIWPRIV and *must* use arguments as defined below.
- * If you don't follow those rules, DaveM is going to hate you (reason :
- * it make mixed 32/64bit operation impossible).
- */
-#define SIOCIWFIRSTPRIV        0x8BE0
-#define SIOCIWLASTPRIV 0x8BFF
-/* Previously, we were using SIOCDEVPRIVATE, but we now have our
- * separate range because of collisions with other tools such as
- * 'mii-tool'.
- * We now have 32 commands, so a bit more space ;-).
- * Also, all 'odd' commands are only usable by root and don't return the
- * content of ifr/iwr to user (but you are not obliged to use the set/get
- * convention, just use every other two command).
- * And I repeat : you are not obliged to use them with iwspy, but you
- * must be compliant with it.
- */
-
-/* ------------------------- IOCTL STUFF ------------------------- */
-
-/* The first and the last (range) */
-#define SIOCIWFIRST    0x8B00
-#define SIOCIWLAST     SIOCIWLASTPRIV          /* 0x8BFF */
-
-/* Even : get (world access), odd : set (root access) */
-#define IW_IS_SET(cmd) (!((cmd) & 0x1))
-#define IW_IS_GET(cmd) ((cmd) & 0x1)
-
-/* ------------------------- PRIVATE INFO ------------------------- */
-/*
- * The following is used with SIOCGIWPRIV. It allow a driver to define
- * the interface (name, type of data) for its private ioctl.
- * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
- */
-
-#define IW_PRIV_TYPE_MASK      0x7000  /* Type of arguments */
-#define IW_PRIV_TYPE_NONE      0x0000
-#define IW_PRIV_TYPE_BYTE      0x1000  /* Char as number */
-#define IW_PRIV_TYPE_CHAR      0x2000  /* Char as character */
-#define IW_PRIV_TYPE_INT       0x4000  /* 32 bits int */
-#define IW_PRIV_TYPE_FLOAT     0x5000
-
-#define IW_PRIV_SIZE_FIXED     0x0800  /* Variable or fixed nuber of args */
-
-#define IW_PRIV_SIZE_MASK      0x07FF  /* Max number of those args */
-
-/*
- * Note : if the number of args is fixed and the size < 16 octets,
- * instead of passing a pointer we will put args in the iwreq struct...
- */
-
-/* ----------------------- OTHER CONSTANTS ----------------------- */
-
-/* Maximum frequencies in the range struct */
-#define IW_MAX_FREQUENCIES     16
-/* Note : if you have something like 80 frequencies,
- * don't increase this constant and don't fill the frequency list.
- * The user will be able to set by channel anyway... */
-
-/* Maximum bit rates in the range struct */
-#define IW_MAX_BITRATES                8
-
-/* Maximum tx powers in the range struct */
-#define IW_MAX_TXPOWER         8
-
-/* Maximum of address that you may set with SPY */
-#define IW_MAX_SPY             8
-
-/* Maximum of address that you may get in the
-   list of access points in range */
-#define IW_MAX_AP              8
-
-/* Maximum size of the ESSID and NICKN strings */
-#define IW_ESSID_MAX_SIZE      32
-
-/* Modes of operation */
-#define IW_MODE_AUTO   0       /* Let the driver decides */
-#define IW_MODE_ADHOC  1       /* Single cell network */
-#define IW_MODE_INFRA  2       /* Multi cell network, roaming, ... */
-#define IW_MODE_MASTER 3       /* Synchronisation master or Access Point */
-#define IW_MODE_REPEAT 4       /* Wireless Repeater (forwarder) */
-#define IW_MODE_SECOND 5       /* Secondary master/repeater (backup) */
-
-/* Maximum number of size of encoding token available
- * they are listed in the range structure */
-#define IW_MAX_ENCODING_SIZES  8
-
-/* Maximum size of the encoding token in bytes */
-#define IW_ENCODING_TOKEN_MAX  32      /* 256 bits (for now) */
-
-/* Flags for encoding (along with the token) */
-#define IW_ENCODE_INDEX                0x00FF  /* Token index (if needed) */
-#define IW_ENCODE_FLAGS                0xFF00  /* Flags defined below */
-#define IW_ENCODE_MODE         0xF000  /* Modes defined below */
-#define IW_ENCODE_DISABLED     0x8000  /* Encoding disabled */
-#define IW_ENCODE_ENABLED      0x0000  /* Encoding enabled */
-#define IW_ENCODE_RESTRICTED   0x4000  /* Refuse non-encoded packets */
-#define IW_ENCODE_OPEN         0x2000  /* Accept non-encoded packets */
-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
-
-/* Power management flags available (along with the value, if any) */
-#define IW_POWER_ON            0x0000  /* No details... */
-#define IW_POWER_TYPE          0xF000  /* Type of parameter */
-#define IW_POWER_PERIOD                0x1000  /* Value is a period/duration of  */
-#define IW_POWER_TIMEOUT       0x2000  /* Value is a timeout (to go asleep) */
-#define IW_POWER_MODE          0x0F00  /* Power Management mode */
-#define IW_POWER_UNICAST_R     0x0100  /* Receive only unicast messages */
-#define IW_POWER_MULTICAST_R   0x0200  /* Receive only multicast messages */
-#define IW_POWER_ALL_R         0x0300  /* Receive all messages though PM */
-#define IW_POWER_FORCE_S       0x0400  /* Force PM procedure for sending unicast */
-#define IW_POWER_REPEATER      0x0800  /* Repeat broadcast messages in PM period */
-#define IW_POWER_MODIFIER      0x000F  /* Modify a parameter */
-#define IW_POWER_MIN           0x0001  /* Value is a minimum  */
-#define IW_POWER_MAX           0x0002  /* Value is a maximum */
-#define IW_POWER_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
-
-/* Transmit Power flags available */
-#define IW_TXPOW_DBM           0x0000  /* Value is in dBm */
-#define IW_TXPOW_MWATT         0x0001  /* Value is in mW */
-
-/* Retry limits and lifetime flags available */
-#define IW_RETRY_ON            0x0000  /* No details... */
-#define IW_RETRY_TYPE          0xF000  /* Type of parameter */
-#define IW_RETRY_LIMIT         0x1000  /* Maximum number of retries*/
-#define IW_RETRY_LIFETIME      0x2000  /* Maximum duration of retries in us */
-#define IW_RETRY_MODIFIER      0x000F  /* Modify a parameter */
-#define IW_RETRY_MIN           0x0001  /* Value is a minimum  */
-#define IW_RETRY_MAX           0x0002  /* Value is a maximum */
-#define IW_RETRY_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
-
-/****************************** TYPES ******************************/
-
-/* --------------------------- SUBTYPES --------------------------- */
-/*
- *     Generic format for most parameters that fit in an int
- */
-struct iw_param
-{
-  __s32                value;          /* The value of the parameter itself */
-  __u8         fixed;          /* Hardware should not use auto select */
-  __u8         disabled;       /* Disable the feature */
-  __u16                flags;          /* Various specifc flags (if any) */
-};
-
-/*
- *     For all data larger than 16 octets, we need to use a
- *     pointer to memory allocated in user space.
- */
-struct iw_point
-{
-  caddr_t      pointer;        /* Pointer to the data  (in user space) */
-  __u16                length;         /* number of fields or size in bytes */
-  __u16                flags;          /* Optional params */
-};
-
-/*
- *     A frequency
- *     For numbers lower than 10^9, we encode the number in 'm' and
- *     set 'e' to 0
- *     For number greater than 10^9, we divide it by the lowest power
- *     of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
- *     The power of 10 is in 'e', the result of the division is in 'm'.
- */
-struct iw_freq
-{
-       __u32           m;              /* Mantissa */
-       __u16           e;              /* Exponent */
-       __u8            i;              /* List index (when in range struct) */
-};
-
-/*
- *     Quality of the link
- */
-struct iw_quality
-{
-       __u8            qual;           /* link quality (%retries, SNR,
-                                          %missed beacons or better...) */
-       __u8            level;          /* signal level (dBm) */
-       __u8            noise;          /* noise level (dBm) */
-       __u8            updated;        /* Flags to know if updated */
-};
-
-/*
- *     Packet discarded in the wireless adapter due to
- *     "wireless" specific problems...
- *     Note : the list of counter and statistics in net_device_stats
- *     is already pretty exhaustive, and you should use that first.
- *     This is only additional stats...
- */
-struct iw_discarded
-{
-       __u32           nwid;           /* Rx : Wrong nwid/essid */
-       __u32           code;           /* Rx : Unable to code/decode (WEP) */
-       __u32           fragment;       /* Rx : Can't perform MAC reassembly */
-       __u32           retries;        /* Tx : Max MAC retries num reached */
-       __u32           misc;           /* Others cases */
-};
-
-/*
- *     Packet/Time period missed in the wireless adapter due to
- *     "wireless" specific problems...
- */
-struct iw_missed
-{
-       __u32           beacon;         /* Missed beacons/superframe */
-};
-
-/* ------------------------ WIRELESS STATS ------------------------ */
-/*
- * Wireless statistics (used for /proc/net/wireless)
- */
-struct iw_statistics
-{
-       __u16           status;         /* Status
-                                        * - device dependent for now */
-
-       struct iw_quality       qual;           /* Quality of the link
-                                                * (instant/mean/max) */
-       struct iw_discarded     discard;        /* Packet discarded counts */
-       struct iw_missed        miss;           /* Packet missed counts */
-};
-
-/* ------------------------ IOCTL REQUEST ------------------------ */
-/*
- * This structure defines the payload of an ioctl, and is used 
- * below.
- *
- * Note that this structure should fit on the memory footprint
- * of iwreq (which is the same as ifreq), which mean a max size of
- * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
- * You should check this when increasing the structures defined
- * above in this file...
- */
-union  iwreq_data
-{
-       /* Config - generic */
-       char            name[IFNAMSIZ];
-       /* Name : used to verify the presence of  wireless extensions.
-        * Name of the protocol/provider... */
-
-       struct iw_point essid;          /* Extended network name */
-       struct iw_param nwid;           /* network id (or domain - the cell) */
-       struct iw_freq  freq;           /* frequency or channel :
-                                        * 0-1000 = channel
-                                        * > 1000 = frequency in Hz */
-
-       struct iw_param sens;           /* signal level threshold */
-       struct iw_param bitrate;        /* default bit rate */
-       struct iw_param txpower;        /* default transmit power */
-       struct iw_param rts;            /* RTS threshold threshold */
-       struct iw_param frag;           /* Fragmentation threshold */
-       __u32           mode;           /* Operation mode */
-       struct iw_param retry;          /* Retry limits & lifetime */
-
-       struct iw_point encoding;       /* Encoding stuff : tokens */
-       struct iw_param power;          /* PM duration/timeout */
-
-       struct sockaddr ap_addr;        /* Access point address */
-
-       struct iw_point data;           /* Other large parameters */
-};
-
-/*
- * The structure to exchange data for ioctl.
- * This structure is the same as 'struct ifreq', but (re)defined for
- * convenience...
- * Do I need to remind you about structure size (32 octets) ?
- */
-struct iwreq 
-{
-       union
-       {
-               char    ifrn_name[IFNAMSIZ];    /* if name, e.g. "eth0" */
-       } ifr_ifrn;
-
-       /* Data part (defined just above) */
-       union   iwreq_data      u;
-};
-
-/* -------------------------- IOCTL DATA -------------------------- */
-/*
- *     For those ioctl which want to exchange mode data that what could
- *     fit in the above structure...
- */
-
-/*
- *     Range of parameters
- */
-
-struct iw_range
-{
-       /* Informative stuff (to choose between different interface) */
-       __u32           throughput;     /* To give an idea... */
-       /* In theory this value should be the maximum benchmarked
-        * TCP/IP throughput, because with most of these devices the
-        * bit rate is meaningless (overhead an co) to estimate how
-        * fast the connection will go and pick the fastest one.
-        * I suggest people to play with Netperf or any benchmark...
-        */
-
-       /* NWID (or domain id) */
-       __u32           min_nwid;       /* Minimal NWID we are able to set */
-       __u32           max_nwid;       /* Maximal NWID we are able to set */
-
-       /* Frequency */
-       __u16           num_channels;   /* Number of channels [0; num - 1] */
-       __u8            num_frequency;  /* Number of entry in the list */
-       struct iw_freq  freq[IW_MAX_FREQUENCIES];       /* list */
-       /* Note : this frequency list doesn't need to fit channel numbers */
-
-       /* signal level threshold range */
-       __s32   sensitivity;
-
-       /* Quality of link & SNR stuff */
-       struct iw_quality       max_qual;       /* Quality of the link */
-
-       /* Rates */
-       __u8            num_bitrates;   /* Number of entries in the list */
-       __s32           bitrate[IW_MAX_BITRATES];       /* list, in bps */
-
-       /* RTS threshold */
-       __s32           min_rts;        /* Minimal RTS threshold */
-       __s32           max_rts;        /* Maximal RTS threshold */
-
-       /* Frag threshold */
-       __s32           min_frag;       /* Minimal frag threshold */
-       __s32           max_frag;       /* Maximal frag threshold */
-
-       /* Power Management duration & timeout */
-       __s32           min_pmp;        /* Minimal PM period */
-       __s32           max_pmp;        /* Maximal PM period */
-       __s32           min_pmt;        /* Minimal PM timeout */
-       __s32           max_pmt;        /* Maximal PM timeout */
-       __u16           pmp_flags;      /* How to decode max/min PM period */
-       __u16           pmt_flags;      /* How to decode max/min PM timeout */
-       __u16           pm_capa;        /* What PM options are supported */
-
-       /* Encoder stuff */
-       __u16   encoding_size[IW_MAX_ENCODING_SIZES];   /* Different token sizes */
-       __u8    num_encoding_sizes;     /* Number of entry in the list */
-       __u8    max_encoding_tokens;    /* Max number of tokens */
-
-       /* Transmit power */
-       __u16           txpower_capa;   /* What options are supported */
-       __u8            num_txpower;    /* Number of entries in the list */
-       __s32           txpower[IW_MAX_TXPOWER];        /* list, in bps */
-
-       /* Wireless Extension version info */
-       __u8            we_version_compiled;    /* Must be WIRELESS_EXT */
-       __u8            we_version_source;      /* Last update of source */
-
-       /* Retry limits and lifetime */
-       __u16           retry_capa;     /* What retry options are supported */
-       __u16           retry_flags;    /* How to decode max/min retry limit */
-       __u16           r_time_flags;   /* How to decode max/min retry life */
-       __s32           min_retry;      /* Minimal number of retries */
-       __s32           max_retry;      /* Maximal number of retries */
-       __s32           min_r_time;     /* Minimal retry lifetime */
-       __s32           max_r_time;     /* Maximal retry lifetime */
-
-       /* Average quality of link & SNR */
-       struct iw_quality       avg_qual;       /* Quality of the link */
-       /* This should contain the average/typical values of the quality
-        * indicator. This should be the threshold between a "good" and
-        * a "bad" link (example : monitor going from green to orange).
-        * Currently, user space apps like quality monitors don't have any
-        * way to calibrate the measurement. With this, they can split
-        * the range between 0 and max_qual in different quality level
-        * (using a geometric subdivision centered on the average).
-        * I expect that people doing the user space apps will feedback
-        * us on which value we need to put in each driver...
-        */
-};
-
-/*
- * Private ioctl interface information
- */
-struct iw_priv_args
-{
-       __u32           cmd;            /* Number of the ioctl to issue */
-       __u16           set_args;       /* Type and number of args */
-       __u16           get_args;       /* Type and number of args */
-       char            name[IFNAMSIZ]; /* Name of the extension */
-};
-
-#endif /* _LINUX_WIRELESS_H */