OSDN Git Service

v22
authorchris-kirby <chris.kirby@hpe.com>
Tue, 11 Oct 2016 20:57:54 +0000 (14:57 -0600)
committerchris-kirby <chris.kirby@hpe.com>
Tue, 11 Oct 2016 20:57:54 +0000 (14:57 -0600)
13 files changed:
wireless_tools/CHANGELOG.h [new file with mode: 0644]
wireless_tools/Makefile
wireless_tools/iwcommon.h [deleted file]
wireless_tools/iwconfig.c
wireless_tools/iwgetid.c
wireless_tools/iwlib.c [moved from wireless_tools/iwcommon.c with 52% similarity]
wireless_tools/iwlib.h [new file with mode: 0644]
wireless_tools/iwlist.c
wireless_tools/iwpriv.c
wireless_tools/iwspy.c
wireless_tools/macaddr.c [new file with mode: 0644]
wireless_tools/wireless.11.h [new file with mode: 0644]
wireless_tools/wireless.h

diff --git a/wireless_tools/CHANGELOG.h b/wireless_tools/CHANGELOG.h
new file mode 100644 (file)
index 0000000..e3d5308
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *     Wireless Tools
+ *
+ *             Jean II - HPLB 97->99 - HPL 99->01
+ *
+ * The changelog...
+ *
+ * This file is released under the GPL license.
+ */
+
+/* --------------------------- HISTORY --------------------------- */
+/*
+ * wireless 16 :               (Jean Tourrilhes)
+ * -----------
+ *     o iwconfig, iwpriv & iwspy
+ *
+ * wireless 17 :               (Justin Seger)
+ * -----------
+ *     o Compile under glibc fix
+ *     o merge iwpriv in iwconfig
+ *     o Add Wavelan roaming support
+ *     o Update man page of iwconfig
+ *
+ * wireless 18 :
+ * -----------
+ *             (From Andreas Neuhaus <andy@fasta.fh-dortmund.de>)
+ *     o Many fix to remove "core dumps" in iwconfig
+ *     o Remove useless headers in iwconfig
+ *     o CHAR wide private ioctl
+ *             (From Jean Tourrilhes)
+ *     o Create iwcommon.h and iwcommon.c
+ *     o Separate iwpriv again for user interface issues
+ *       The folllowing didn't make sense and crashed :
+ *             iwconfig eth0 priv sethisto 12 15 nwid 100
+ *     o iwspy no longer depend on net-tools-1.2.0
+ *     o Reorganisation of the code, cleanup
+ *     o Add ESSID stuff in iwconfig
+ *     o Add display of level & noise in dBm (stats in iwconfig)
+ *     o Update man page of iwconfig and iwpriv
+ *     o Add xwireless (didn't check if it compiles)
+ *             (From Dean W. Gehnert <deang@tpi.com>)
+ *     o Minor fixes
+ *             (Jan Rafaj <rafaj@cedric.vabo.cz>)
+ *     o Cosmetic changes (sensitivity relative, freq list)
+ *     o Frequency computation on double
+ *     o Compile clean on libc5
+ *             (From Jean Tourrilhes)
+ *     o Move listing of frequencies to iwspy
+ *     o Add AP address stuff in iwconfig
+ *     o Add AP list stuff in iwspy
+ *
+ * wireless 19 :
+ * -----------
+ *             (From Jean Tourrilhes)
+ *     o Allow for sensitivity in dBm (if < 0) [iwconfig]
+ *     o Formatting changes in displaying ap address in [iwconfig]
+ *     o Slightly improved man pages and usage display
+ *     o Add channel number for each frequency in list [iwspy]
+ *     o Add nickname... [iwconfig]
+ *     o Add "port" private ioctl shortcut [iwpriv]
+ *     o If signal level = 0, no range or dBms [iwconfig]
+ *     o I think I now got set/get char strings right in [iwpriv]
+ *             (From Thomas Ekstrom <tomeck@thelogic.com>)
+ *     o Fix a very obscure bug in [iwspy]
+ *
+ * wireless 20 :
+ * -----------
+ *             (From Jean Tourrilhes)
+ *     o Remove all #ifdef WIRELESS ugliness, but add a #error :
+ *             we require Wireless Extensions 9 or nothing !  [all]
+ *     o Switch to new 'nwid' definition (specific -> iw_param) [iwconfig]
+ *     o Rewriten totally the encryption support [iwconfig]
+ *             - Multiple keys, through key index
+ *             - Flexible/multiple key size, and remove 64bits upper limit
+ *             - Open/Restricted modes
+ *             - Enter keys as ASCII strings
+ *     o List key sizes supported and all keys in [iwspy]
+ *     o Mode of operation support (ad-hoc, managed...) [iwconfig]
+ *     o Use '=' to indicate fixed instead of ugly '(f)' [iwconfig]
+ *     o Ability to disable RTS & frag (off), now the right way [iwconfig]
+ *     o Auto as an input modifier for bitrate [iwconfig]
+ *     o Power Management support [iwconfig]
+ *             - set timeout or period and its value
+ *             - Reception mode (unicast/multicast/all)
+ *     o Updated man pages with all that ;-)
+ *
+ * wireless 21 :
+ * -----------
+ *             (from Alan McReynolds <alan_mcreynolds@hpl.hp.com>)
+ *     o Use proper macros for compilation directives [Makefile]
+ *             (From Jean Tourrilhes)
+ *     o Put licensing info everywhere (almost). Yes, it's GPL !
+ *     o Document the use of /etc/pcmcia/wireless.opts
+ *     o Add min/max modifiers to power management parameters [iwconfig]
+ *             -> requested by Lee Keyser-Allen for the Spectrum24 driver
+ *     o Optionally output a second power management parameter [iwconfig]
+ *     ---
+ *     o Common subroutines to display stats & power saving info [iwcommon]
+ *     o Display all power management info, capability and values [iwspy]
+ *     ---
+ *     o Optional index for ESSID (for Aironet driver) [iwcommon]
+ *     o IW_ENCODE_NOKEY for write only keys [iwconfig/iwspy]
+ *     o Common subrouting to print encoding keys [iwspy]
+ *     ---
+ *     o Transmit Power stuff (dBm + mW) [iwconfig/iwspy]
+ *     o Cleaner formatting algorithm when displaying params [iwconfig]
+ *     ---
+ *     o Fix get_range_info() and use it everywhere - Should fix core dumps.
+ *     o Catch WE version differences between tools and driver and
+ *       warn user. Thanks to Tobias Ringstrom for the tip... [iwcommon]
+ *     o Add Retry limit and lifetime support. [iwconfig/iwlist]
+ *     o Display "Cell:" instead of "Access Point:" in ad-hoc mode [iwconfig]
+ *     o Header fix for glibc2.2 by Ross G. Miller <Ross_Miller@baylor.edu>
+ *     o Move header selection flags in Makefile [iwcommon/Makefile]
+ *     o Spin-off iwlist.c from iwspy.c. iwspy is now much smaller
+ *       After moving this bit of code all over the place, from iwpriv
+ *       to iwconfig to iwspy, it now has a home of its own... [iwspy/iwlist]
+ *     o Wrote quick'n'dirty iwgetid.
+ *     o Remove output of second power management parameter [iwconfig]
+ *       Please use iwlist, I don't want to bloat iwconfig
+ *     ---
+ *     o Fix bug in display ints - "Allen Miu" <aklmiu@mit.edu> [iwpriv]
+ *
+ * wireless 22 :
+ * -----------
+ *             (From Jim Kaba <jkaba@sarnoff.com>)
+ *     o Fix socket_open to not open all types of sockets [iwcommon]
+ *             (From Michael Tokarev <mjt@tls.msk.ru>)
+ *     o Rewrite main (top level) + command line parsing of [iwlist]
+ *             (From Jean Tourrilhes)
+ *     o Set commands should return proper success flag [iwspy/iwpriv]
+ *       requested by Michael Tokarev
+ *     ---
+ *             (From Torgeir Hansen <torgeir@trenger.ro>)
+ *     o Replace "strcpy(wrq.ifr_name," with strncpy to avoid buffer
+ *       overflows. This is OK because the kernel use strncmp...
+ *     ---
+ *     o Move operation_mode in iwcommon and add NUM_OPER_MODE [iwconfig]
+ *     o print_stats, print_key, ... use char * instead if FILE * [iwcommon]
+ *     o Add `iw_' prefix to avoid namespace pollution [iwcommon]
+ *     o Add iw_get_basic_config() and iw_set_basic_config() [iwcommon]
+ *     o Move iw_getstats from iwconfig to iwcommon [iwcommon]
+ *     o Move changelog to CHANGELOG.h [iwcommon]
+ *     o Rename iwcommon.* into iwlib.* [iwcommon->iwlib]
+ *     o Compile iwlib. as a dynamic or static library [Makefile]
+ *     o Allow the tools to be compiled with the dynamic library [Makefile]
+ *     --- Update to Wireless Extension 12 ---
+ *     o Show typical/average quality in iwspy [iwspy]
+ *     o Get Wireless Stats through ioctl instead of /proc [iwlib]
+ *
+ */
+
+/* ----------------------------- TODO ----------------------------- */
+/*
+ * One day, maybe...
+ *
+ * iwconfig :
+ * --------
+ *     Make disable a per encryption key modifier if some hardware
+ *     requires it.
+ *
+ * iwpriv :
+ * ------
+ *     Remove 'port' and 'roam' cruft now that we have mode in iwconfig
+ *
+ * iwspy :
+ * -----
+ *     -
+ *
+ * Doc & man pages :
+ * ---------------
+ *     Update main doc.
+ *
+ * Other :
+ * -----
+ *     What about some graphical tools ?
+ */
index b7f7550..236acbb 100644 (file)
@@ -3,16 +3,27 @@
 #
 
 # Targets to build
+STATIC=libiw.a
+DYNAMIC=libiw.so.22
 PROGS= iwconfig iwlist iwpriv iwspy iwgetid
 
+# 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
+
 # Installation directory. By default, go in local.
 # Distributions should probably use /usr/sbin, but they probably know better...
 INSTALL_DIR= /usr/local/sbin
+INSTALL_LIB= /usr/local/lib
+INSTALL_INC= /usr/local/include
 
 # This is our header selection. Try to hide the mess and the misery :-(
 # Please choose *only one* of the define...
 
-# Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0 */
+# Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1
 #HEADERS= -DGLIBC22_HEADERS
 
 # Kernel headers 2.0.X + Glibc 2.0 - Debian 2.0, RH 5
@@ -42,38 +53,51 @@ RM_CMD = $(RM) *.BAK *.bak *.o ,* *~ *.a
 
 CFLAGS=-O2 -Wall $(HEADERS) $(WE_HEADER)
 
-LIBS=-lm
+LIBS=$(IWLIBS) -lm
 
-all:: $(PROGS)
+all:: $(STATIC) $(DYNAMIC) $(PROGS)
 
 .c.o:
        $(CC) $(CFLAGS) -c $<
 
-iwconfig: iwconfig.o iwcommon.o
-       $(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+iwconfig: iwconfig.o $(OBJS)
+       $(CC) $(CFLAGS) -o $@ $< $(LIBS)
 
-iwlist: iwlist.o iwcommon.o
-       $(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+iwlist: iwlist.o $(OBJS)
+       $(CC) $(CFLAGS) -o $@ $< $(LIBS)
 
-iwpriv: iwpriv.o iwcommon.o
-       $(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+iwpriv: iwpriv.o $(OBJS)
+       $(CC) $(CFLAGS) -o $@ $< $(LIBS)
 
-iwspy: iwspy.o iwcommon.o
-       $(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+iwspy: iwspy.o $(OBJS)
+       $(CC) $(CFLAGS) -o $@ $< $(LIBS)
 
 iwgetid: iwgetid.o
        $(CC) $(CFLAGS) -o $@ $^
 
+# Compilation of the dynamic library
+libiw.so.22: $(OBJS)
+       $(CC) -O2 -shared -o $@ -Wl,-soname,$@ -lm -lc $^
+
+# Compilation of the static library
+libiw.a: $(OBJS)
+       $(RM) $@
+       ar cru $@ $^
+       ranlib $@
+
 # So crude but so effective ;-)
 install::
        cp $(PROGS) $(INSTALL_DIR)
+       cp $(STATIC) $(DYNAMIC) $(INSTALL_LIB)
+       echo "Don't forget to fix you /etc/ld.so.conf and run ldconfig."
+       cp iwlib.h $(INSTALL_INC)
 
 clean::
        $(RM_CMD) 
 
 realclean::
        $(RM_CMD) 
-       $(RM) $(PROGS)
+       $(RM) $(STATIC) $(DYNAMIC) $(PROGS)
 
 depend::
        makedepend -s "# DO NOT DELETE" -- $(INCLUDES) -- $(SRCS)
diff --git a/wireless_tools/iwcommon.h b/wireless_tools/iwcommon.h
deleted file mode 100644 (file)
index 1c23c41..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- *     Wireless Tools
- *
- *             Jean II - HPLB 97->99 - HPL 99->00
- *
- * Common header for the wireless tools...
- *
- * This file is released under the GPL license.
- */
-
-#ifndef IWCOMMON_H
-#define IWCOMMON_H
-
-/************************** DOCUMENTATION **************************/
-/*
- * None ? Todo...
- */
-
-/* --------------------------- HISTORY --------------------------- */
-/*
- * wireless 16 :               (Jean Tourrilhes)
- * -----------
- *     o iwconfig, iwpriv & iwspy
- *
- * wireless 17 :               (Justin Seger)
- * -----------
- *     o Compile under glibc fix
- *     o merge iwpriv in iwconfig
- *     o Add Wavelan roaming support
- *     o Update man page of iwconfig
- *
- * wireless 18 :
- * -----------
- *             (From Andreas Neuhaus <andy@fasta.fh-dortmund.de>)
- *     o Many fix to remove "core dumps" in iwconfig
- *     o Remove useless headers in iwconfig
- *     o CHAR wide private ioctl
- *             (From Jean Tourrilhes)
- *     o Create iwcommon.h and iwcommon.c
- *     o Separate iwpriv again for user interface issues
- *       The folllowing didn't make sense and crashed :
- *             iwconfig eth0 priv sethisto 12 15 nwid 100
- *     o iwspy no longer depend on net-tools-1.2.0
- *     o Reorganisation of the code, cleanup
- *     o Add ESSID stuff in iwconfig
- *     o Add display of level & noise in dBm (stats in iwconfig)
- *     o Update man page of iwconfig and iwpriv
- *     o Add xwireless (didn't check if it compiles)
- *             (From Dean W. Gehnert <deang@tpi.com>)
- *     o Minor fixes
- *             (Jan Rafaj <rafaj@cedric.vabo.cz>)
- *     o Cosmetic changes (sensitivity relative, freq list)
- *     o Frequency computation on double
- *     o Compile clean on libc5
- *             (From Jean Tourrilhes)
- *     o Move listing of frequencies to iwspy
- *     o Add AP address stuff in iwconfig
- *     o Add AP list stuff in iwspy
- *
- * wireless 19 :
- * -----------
- *             (From Jean Tourrilhes)
- *     o Allow for sensitivity in dBm (if < 0) [iwconfig]
- *     o Formatting changes in displaying ap address in [iwconfig]
- *     o Slightly improved man pages and usage display
- *     o Add channel number for each frequency in list [iwspy]
- *     o Add nickname... [iwconfig]
- *     o Add "port" private ioctl shortcut [iwpriv]
- *     o If signal level = 0, no range or dBms [iwconfig]
- *     o I think I now got set/get char strings right in [iwpriv]
- *             (From Thomas Ekstrom <tomeck@thelogic.com>)
- *     o Fix a very obscure bug in [iwspy]
- *
- * wireless 20 :
- * -----------
- *             (From Jean Tourrilhes)
- *     o Remove all #ifdef WIRELESS ugliness, but add a #error :
- *             we require Wireless Extensions 9 or nothing !  [all]
- *     o Switch to new 'nwid' definition (specific -> iw_param) [iwconfig]
- *     o Rewriten totally the encryption support [iwconfig]
- *             - Multiple keys, through key index
- *             - Flexible/multiple key size, and remove 64bits upper limit
- *             - Open/Restricted modes
- *             - Enter keys as ASCII strings
- *     o List key sizes supported and all keys in [iwspy]
- *     o Mode of operation support (ad-hoc, managed...) [iwconfig]
- *     o Use '=' to indicate fixed instead of ugly '(f)' [iwconfig]
- *     o Ability to disable RTS & frag (off), now the right way [iwconfig]
- *     o Auto as an input modifier for bitrate [iwconfig]
- *     o Power Management support [iwconfig]
- *             - set timeout or period and its value
- *             - Reception mode (unicast/multicast/all)
- *     o Updated man pages with all that ;-)
- *
- * wireless 21 :
- * -----------
- *             (from Alan McReynolds <alan_mcreynolds@hpl.hp.com>)
- *     o Use proper macros for compilation directives [Makefile]
- *             (From Jean Tourrilhes)
- *     o Put licensing info everywhere (almost). Yes, it's GPL !
- *     o Document the use of /etc/pcmcia/wireless.opts
- *     o Add min/max modifiers to power management parameters [iwconfig]
- *             -> requested by Lee Keyser-Allen for the Spectrum24 driver
- *     o Optionally output a second power management parameter [iwconfig]
- *     ---
- *     o Common subroutines to display stats & power saving info [iwcommon]
- *     o Display all power management info, capability and values [iwspy]
- *     ---
- *     o Optional index for ESSID (for Aironet driver) [iwcommon]
- *     o IW_ENCODE_NOKEY for write only keys [iwconfig/iwspy]
- *     o Common subrouting to print encoding keys [iwspy]
- *     ---
- *     o Transmit Power stuff (dBm + mW) [iwconfig/iwspy]
- *     o Cleaner formatting algorithm when displaying params [iwconfig]
- *     ---
- *     o Fix get_range_info() and use it everywhere - Should fix core dumps.
- *     o Catch WE version differences between tools and driver and
- *       warn user. Thanks to Tobias Ringstrom for the tip... [iwcommon]
- *     o Add Retry limit and lifetime support. [iwconfig/iwlist]
- *     o Display "Cell:" instead of "Access Point:" in ad-hoc mode [iwconfig]
- *     o Header fix for glibc2.2 by Ross G. Miller <Ross_Miller@baylor.edu>
- *     o Move header selection flags in Makefile [iwcommon/Makefile]
- *     o Spin-off iwlist.c from iwspy.c. iwspy is now much smaller
- *       After moving this bit of code all over the place, from iwpriv
- *       to iwconfig to iwspy, it now has a home of its own... [iwspy/iwlist]
- *     o Wrote quick'n'dirty iwgetid.
- *     o Remove output of second power management parameter [iwconfig]
- *       Please use iwlist, I don't want to bloat iwconfig
- *     ---
- *     o Fix bug in display ints - "Allen Miu" <aklmiu@mit.edu> [iwpriv]
- */
-
-/* ----------------------------- TODO ----------------------------- */
-/*
- * One day, maybe...
- *
- * iwconfig :
- * --------
- *     Make disable a per encryption key modifier if some hardware
- *     requires it.
- *
- * iwpriv :
- * ------
- *     Remove 'port' and 'roam' cruft now that we have mode in iwconfig
- *
- * iwspy :
- * -----
- *     -
- *
- * Doc & man pages :
- * ---------------
- *     Update main doc.
- *
- * Other :
- * -----
- *     What about some graphical tools ?
- */
-
-/***************************** INCLUDES *****************************/
-
-/* Standard headers */
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <stdio.h>
-#include <math.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>             /* gethostbyname, getnetbyname */
-
-/* This is our header selection. Try to hide the mess and the misery :-(
- * The selection has been moved in the Makefile, here we have only
- * the ugly part. Don't look, you would go blind ;-) */
-
-#ifdef KLUDGE_HEADERS
-#include <socketbits.h>
-#endif /* KLUDGE_HEADERS */
-
-#if defined(KLUDGE_HEADERS) || defined(GLIBC_HEADERS)
-#include <linux/if_arp.h>      /* For ARPHRD_ETHER */
-#include <linux/socket.h>      /* For AF_INET & struct sockaddr */
-#include <linux/in.h>          /* For struct sockaddr_in */
-#endif /* KLUDGE_HEADERS || GLIBC_HEADERS */
-
-#ifdef GLIBC22_HEADERS 
-/* Added by Ross G. Miller <Ross_Miller@baylor.edu>, 3/28/01 */
-#include <linux/if_arp.h>      /* For ARPHRD_ETHER */
-#include <linux/socket.h>      /* For AF_INET & struct sockaddr */
-#include <sys/socket.h>
-#endif /* GLIBC22_HEADERS */    
-
-#ifdef LIBC5_HEADERS
-#include <sys/socket.h>                /* For AF_INET & struct sockaddr & socket() */
-#include <linux/if_arp.h>      /* For ARPHRD_ETHER */
-#include <linux/in.h>          /* For struct sockaddr_in */
-#endif /* LIBC5_HEADERS */
-
-#ifdef PRIVATE_WE_HEADER
-/* Private copy of Wireless extensions */
-#include "wireless.h"
-#else  /* PRIVATE_WE_HEADER */
-/* System wide Wireless extensions */
-#include <linux/wireless.h>
-#endif /* PRIVATE_WE_HEADER */
-
-#if WIRELESS_EXT < 9
-#error "Wireless Extension v9 or newer required :-(\
-Use Wireless Tools v19 or update your kernel headers"
-#endif
-#if WIRELESS_EXT < 11
-#warning "Wireless Extension v11 recommended...\
-You may update your kernel and/or system headers to get the new features..."
-#endif
-
-/****************************** DEBUG ******************************/
-
-
-/************************ CONSTANTS & MACROS ************************/
-
-/* Some usefull constants */
-#define KILO   1e3
-#define MEGA   1e6
-#define GIGA   1e9
-
-/* Backward compatibility for Wireless Extension 9 */
-#ifndef IW_POWER_MODIFIER
-#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 */
-#endif IW_POWER_MODIFIER
-
-#ifndef IW_ENCODE_NOKEY
-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not here */
-#define IW_ENCODE_MODE         0xF000  /* Modes defined below */
-#endif IW_ENCODE_NOKEY
-
-/****************************** TYPES ******************************/
-
-/* Shortcuts */
-typedef struct iw_statistics   iwstats;
-typedef struct iw_range                iwrange;
-typedef struct iw_param                iwparam;
-typedef struct iw_freq         iwfreq;
-typedef struct iw_quality      iwqual;
-typedef struct iw_priv_args    iwprivargs;
-typedef struct sockaddr                sockaddr;
-
-/* Structure for storing all wireless information for each device */
-typedef struct wireless_info
-{
-  char         name[IFNAMSIZ];         /* Wireless/protocol name */
-  int          has_nwid;
-  iwparam      nwid;                   /* Network ID */
-  int          has_freq;
-  float                freq;                   /* Frequency/channel */
-  int          has_sens;
-  iwparam      sens;                   /* sensitivity */
-  int          has_key;
-  unsigned char        key[IW_ENCODING_TOKEN_MAX];     /* Encoding key used */
-  int          key_size;               /* Number of bytes */
-  int          key_flags;              /* Various flags */
-  int          has_essid;
-  int          essid_on;
-  char         essid[IW_ESSID_MAX_SIZE + 1];   /* ESSID (extended network) */
-  int          has_nickname;
-  char         nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */
-  int          has_ap_addr;
-  sockaddr     ap_addr;                /* Access point address */
-  int          has_bitrate;
-  iwparam      bitrate;                /* Bit rate in bps */
-  int          has_rts;
-  iwparam      rts;                    /* RTS threshold in bytes */
-  int          has_frag;
-  iwparam      frag;                   /* Fragmentation threshold in bytes */
-  int          has_mode;
-  int          mode;                   /* Operation mode */
-  int          has_power;
-  iwparam      power;                  /* Power management parameters */
-  int          has_txpower;
-  iwparam      txpower;                /* Transmit Power in dBm */
-  int          has_retry;
-  iwparam      retry;                  /* Retry limit or lifetime */
-
-  /* Stats */
-  iwstats      stats;
-  int          has_stats;
-  iwrange      range;
-  int          has_range;
-} wireless_info;
-
-/**************************** PROTOTYPES ****************************/
-/*
- * All the functions in iwcommon.c
- */
-/* ---------------------- SOCKET SUBROUTINES -----------------------*/
-int
-       sockets_open(void);
-/* --------------------- WIRELESS SUBROUTINES ----------------------*/
-int
-       get_range_info(int              skfd,
-                      char *           ifname,
-                      iwrange *        range);
-int
-       get_priv_info(int               skfd,
-                     char *            ifname,
-                     iwprivargs *      priv);
-/* -------------------- FREQUENCY SUBROUTINES --------------------- */
-void
-       float2freq(double       in,
-                  iwfreq *     out);
-double
-       freq2float(iwfreq *     in);
-/* ---------------------- POWER SUBROUTINES ----------------------- */
-int
-       dbm2mwatt(int   in);
-int
-       mwatt2dbm(int   in);
-/* -------------------- STATISTICS SUBROUTINES -------------------- */
-void
-       print_stats(FILE *      stream,
-                   iwqual *    qual,
-                   iwrange *   range,
-                   int         has_range);
-/* --------------------- ENCODING SUBROUTINES --------------------- */
-void
-       print_key(FILE *                stream,
-                 unsigned char *       key,
-                 int                   key_size,
-                 int                   key_flags);
-/* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */
-void
-       print_pm_value(FILE *   stream,
-                      int      value,
-                      int      flags);
-void
-       print_pm_mode(FILE *    stream,
-                     int       flags);
-/* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */
-#if WIRELESS_EXT > 10
-void
-       print_retry_value(FILE *        stream,
-                         int           value,
-                         int           flags);
-#endif
-/* --------------------- ADDRESS SUBROUTINES ---------------------- */
-int
-       check_addr_type(int     skfd,
-                       char *  ifname);
-char *
-       pr_ether(unsigned char *ptr);
-int
-       in_ether(char *bufp, struct sockaddr *sap);
-int
-       in_inet(char *bufp, struct sockaddr *sap);
-int
-       in_addr(int             skfd,
-               char *          ifname,
-               char *          bufp,
-               struct sockaddr *sap);
-/* ----------------------- MISC SUBROUTINES ------------------------ */
-int
-       byte_size(int           args);
-
-/**************************** VARIABLES ****************************/
-
-#endif /* IWCOMMON_H */
index b70c049..efc0a43 100644 (file)
  * This file is released under the GPL license.
  */
 
-#include "iwcommon.h"          /* Header */
-
-/**************************** VARIABLES ****************************/
-char * operation_mode[] = { "Auto",
-                            "Ad-Hoc",
-                            "Managed",
-                            "Master",
-                            "Repeater",
-                            "Secondary" };
+#include "iwlib.h"             /* Header */
 
 /************************* MISC SUBROUTINES **************************/
 
@@ -49,69 +41,6 @@ iw_usage(void)
 
 /*------------------------------------------------------------------*/
 /*
- * Read /proc/net/wireless to get the latest statistics
- */
-static int
-iw_getstats(char *     ifname,
-           iwstats *   stats)
-{
-  FILE *       f=fopen("/proc/net/wireless","r");
-  char         buf[256];
-  char *       bp;
-  int          t;
-  if(f==NULL)
-    return -1;
-  /* Loop on all devices */
-  while(fgets(buf,255,f))
-    {
-      bp=buf;
-      while(*bp&&isspace(*bp))
-       bp++;
-      /* Is it the good device ? */
-      if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
-       {
-         /* Skip ethX: */
-         bp=strchr(bp,':');
-         bp++;
-         /* -- status -- */
-         bp = strtok(bp, " ");
-         sscanf(bp, "%X", &t);
-         stats->status = (unsigned short) t;
-         /* -- link quality -- */
-         bp = strtok(NULL, " ");
-         if(strchr(bp,'.') != NULL)
-           stats->qual.updated |= 1;
-         sscanf(bp, "%d", &t);
-         stats->qual.qual = (unsigned char) t;
-         /* -- signal level -- */
-         bp = strtok(NULL, " ");
-         if(strchr(bp,'.') != NULL)
-           stats->qual.updated |= 2;
-         sscanf(bp, "%d", &t);
-         stats->qual.level = (unsigned char) t;
-         /* -- noise level -- */
-         bp = strtok(NULL, " ");
-         if(strchr(bp,'.') != NULL)
-           stats->qual.updated += 4;
-         sscanf(bp, "%d", &t);
-         stats->qual.noise = (unsigned char) t;
-         /* -- discarded packets -- */
-         bp = strtok(NULL, " ");
-         sscanf(bp, "%d", &stats->discard.nwid);
-         bp = strtok(NULL, " ");
-         sscanf(bp, "%d", &stats->discard.code);
-         bp = strtok(NULL, " ");
-         sscanf(bp, "%d", &stats->discard.misc);
-         fclose(f);
-         return 0;
-       }
-    }
-  fclose(f);
-  return -1;
-}
-
-/*------------------------------------------------------------------*/
-/*
  * Get wireless informations & config from the device driver
  * We will call all the classical wireless ioctl on the driver through
  * the socket to know what is supported and to get the settings...
@@ -126,7 +55,7 @@ get_info(int                 skfd,
   memset((char *) info, 0, sizeof(struct wireless_info));
 
   /* Get wireless name */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
     /* If no wireless name : no wireless extensions */
     return(-1);
@@ -134,11 +63,11 @@ get_info(int                       skfd,
     strcpy(info->name, wrq.u.name);
 
   /* Get ranges */
-  if(get_range_info(skfd, ifname, &(info->range)) >= 0)
+  if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
     info->has_range = 1;
 
   /* Get network ID */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0)
     {
       info->has_nwid = 1;
@@ -146,15 +75,15 @@ get_info(int                       skfd,
     }
 
   /* Get frequency / channel */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0)
     {
       info->has_freq = 1;
-      info->freq = freq2float(&(wrq.u.freq));
+      info->freq = iw_freq2float(&(wrq.u.freq));
     }
 
   /* Get sensitivity */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0)
     {
       info->has_sens = 1;
@@ -162,7 +91,7 @@ get_info(int                 skfd,
     }
 
   /* Get encryption information */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   wrq.u.data.pointer = (caddr_t) info->key;
   wrq.u.data.length = 0;
   wrq.u.data.flags = 0;
@@ -174,7 +103,7 @@ get_info(int                        skfd,
     }
 
   /* Get ESSID */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   wrq.u.essid.pointer = (caddr_t) info->essid;
   wrq.u.essid.length = 0;
   wrq.u.essid.flags = 0;
@@ -185,7 +114,7 @@ get_info(int                        skfd,
     }
 
   /* Get AP address */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWAP, &wrq) >= 0)
     {
       info->has_ap_addr = 1;
@@ -193,7 +122,7 @@ get_info(int                        skfd,
     }
 
   /* Get NickName */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   wrq.u.essid.pointer = (caddr_t) info->nickname;
   wrq.u.essid.length = 0;
   wrq.u.essid.flags = 0;
@@ -202,7 +131,7 @@ get_info(int                        skfd,
       info->has_nickname = 1;
 
   /* Get bit rate */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWRATE, &wrq) >= 0)
     {
       info->has_bitrate = 1;
@@ -210,7 +139,7 @@ get_info(int                        skfd,
     }
 
   /* Get RTS threshold */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0)
     {
       info->has_rts = 1;
@@ -218,7 +147,7 @@ get_info(int                        skfd,
     }
 
   /* Get fragmentation threshold */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0)
     {
       info->has_frag = 1;
@@ -226,16 +155,16 @@ get_info(int                      skfd,
     }
 
   /* Get operation mode */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0)
     {
-      if((wrq.u.mode < 6) && (wrq.u.mode >= 0))
+      if((wrq.u.mode < IW_NUM_OPER_MODE) && (wrq.u.mode >= 0))
        info->has_mode = 1;
       info->mode = wrq.u.mode;
     }
 
   /* Get Power Management settings */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   wrq.u.power.flags = 0;
   if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0)
     {
@@ -245,7 +174,7 @@ get_info(int                        skfd,
 
 #if WIRELESS_EXT > 9
   /* Get Transmit Power */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWTXPOW, &wrq) >= 0)
     {
       info->has_txpower = 1;
@@ -255,7 +184,7 @@ get_info(int                        skfd,
 
 #if WIRELESS_EXT > 10
   /* Get retry limit/lifetime */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0)
     {
       info->has_retry = 1;
@@ -264,7 +193,7 @@ get_info(int                        skfd,
 #endif /* WIRELESS_EXT > 10 */
 
   /* Get stats */
-  if(iw_getstats(ifname, &(info->stats)) >= 0)
+  if(iw_get_stats(skfd, ifname, &(info->stats)) >= 0)
     {
       info->has_stats = 1;
     }
@@ -281,6 +210,8 @@ static void
 display_info(struct wireless_info *    info,
             char *                     ifname)
 {
+  char         buffer[128];    /* Temporary buffer */
+
   /* One token is more of less 5 character, 14 tokens per line */
   int  tokens = 3;     /* For name */
 
@@ -300,7 +231,7 @@ display_info(struct wireless_info * info,
            printf("ESSID:\"%s\"  ", info->essid);
        }
       else
-       printf("ESSID:off  ");
+       printf("ESSID:off/any  ");
     }
 
   /* Display NickName (station name), if any */
@@ -317,7 +248,7 @@ display_info(struct wireless_info * info,
   /* Display Network ID */
   if(info->has_nwid)
     {
-      /* Note : should display right number of digit according to info
+      /* Note : should display proper number of digit according to info
        * in range structure */
       if(info->nwid.disabled)
        printf("NWID:off/any  ");
@@ -329,7 +260,7 @@ display_info(struct wireless_info * info,
   /* Display the current mode of operation */
   if(info->has_mode)
     {
-      printf("Mode:%s  ", operation_mode[info->mode]);
+      printf("Mode:%s  ", iw_operation_mode[info->mode]);
       tokens +=3;
     }
 
@@ -369,7 +300,7 @@ display_info(struct wireless_info * info,
        printf("Cell:");
       else
        printf("Access Point:");
-      printf(" %s", pr_ether(info->ap_addr.sa_data));
+      printf(" %s", iw_pr_ether(buffer, info->ap_addr.sa_data));
     }
 
   /* Display the currently used/set bit-rate */
@@ -426,7 +357,7 @@ display_info(struct wireless_info * info,
 
          /* Convert everything to dBm */
          if(info->txpower.flags & IW_TXPOW_MWATT)
-           dbm = mwatt2dbm(info->txpower.value);
+           dbm = iw_mwatt2dbm(info->txpower.value);
          else
            dbm = info->txpower.value;
 
@@ -478,7 +409,11 @@ display_info(struct wireless_info *        info,
        {
          /* Let's check the value and its type */
          if(info->retry.flags & IW_RETRY_TYPE)
-           print_retry_value(stdout, info->retry.value, info->retry.flags);
+           {
+             iw_print_retry_value(buffer,
+                                  info->retry.value, info->retry.flags);
+             printf("%s", buffer);
+           }
 
          /* Let's check if nothing (simply on) */
          if(info->retry.flags == IW_RETRY_ON)
@@ -548,7 +483,8 @@ display_info(struct wireless_info * info,
       else
        {
          /* Display the key */
-         print_key(stdout, info->key, info->key_size, info->key_flags);
+         iw_print_key(buffer, info->key, info->key_size, info->key_flags);
+         printf("%s", buffer);
 
          /* Other info... */
          if((info->key_flags & IW_ENCODE_INDEX) > 1)
@@ -574,10 +510,14 @@ display_info(struct wireless_info *       info,
        {
          /* Let's check the value and its type */
          if(info->power.flags & IW_POWER_TYPE)
-           print_pm_value(stdout, info->power.value, info->power.flags);
+           {
+             iw_print_pm_value(buffer, info->power.value, info->power.flags);
+             printf("%s", buffer);
+           }
 
          /* Let's check the mode */
-         print_pm_mode(stdout, info->power.flags);
+         iw_print_pm_mode(buffer, info->power.flags);
+         printf("%s", buffer);
 
          /* Let's check if nothing (simply on) */
          if(info->power.flags == IW_POWER_ON)
@@ -590,13 +530,23 @@ display_info(struct wireless_info *       info,
   if(info->has_stats)
     {
       info->stats.qual.updated = 0x0;  /* Not that reliable, disable */
-      printf("Link ");
-      print_stats(stdout, &info->stats.qual, &info->range, info->has_range);
+      iw_print_stats(buffer, &info->stats.qual, &info->range, info->has_range);
+      printf("Link %s\n", buffer);
 
+#if WIRELESS_EXT > 11
+      printf("          Rx invalid nwid:%d  Rx invalid crypt:%d  Rx invalid frag:%d\n          Tx excessive retries:%d  Invalid misc:%d   Missed beacon:%d\n",
+            info->stats.discard.nwid,
+            info->stats.discard.code,
+            info->stats.discard.fragment,
+            info->stats.discard.retries,
+            info->stats.discard.misc,
+            info->stats.miss.beacon);
+#else /* WIRELESS_EXT > 11 */
       printf("          Rx invalid nwid:%d  invalid crypt:%d  invalid misc:%d\n",
             info->stats.discard.nwid,
             info->stats.discard.code,
             info->stats.discard.misc);
+#endif /* WIRELESS_EXT > 11 */
     }
 
   printf("\n");
@@ -698,7 +648,7 @@ set_info(int                skfd,           /* The socket */
                    fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno));
                    return(-1);
                  }
-               strcpy(wrq.ifr_name, ifname);
+               strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
                wrq.u.nwid.disabled = 0;
              }
            else
@@ -731,7 +681,7 @@ set_info(int                skfd,           /* The socket */
          if(index(args[i], 'M')) freq *= MEGA;
          if(index(args[i], 'k')) freq *= KILO;
 
-         float2freq(freq, &(wrq.u.freq));
+         iw_float2freq(freq, &(wrq.u.freq));
 
          if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
            {
@@ -777,7 +727,7 @@ set_info(int                skfd,           /* The socket */
                  fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
                  return(-1);
                }
-             strcpy(wrq.ifr_name, ifname);
+             strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
              wrq.u.data.flags &= ~IW_ENCODE_DISABLED;  /* Enable */
            }
          else
@@ -806,12 +756,17 @@ set_info(int              skfd,           /* The socket */
                }
              else
                {
-                 /* Second case : has hexadecimal digits */
-                 p = buff = malloc(strlen(args[i]) + 1);
+                 /* Second case : as hexadecimal digits */
+                 buff = malloc(strlen(args[i]) + 1);
+                 if(buff == NULL)
+                   {
+                     fprintf(stderr, "Setting key : Malloc failed (string too long ?)\n");
+                     return(-1);
+                   }
                  strcpy(buff, args[i]);
 
                  p = strtok(buff, "-:;.,");
-                 while(p != (char *) NULL)
+                 while((p != (char *) NULL) && (k < IW_ENCODING_TOKEN_MAX))
                    {
                      if(sscanf(p, "%2X", &temp) != 1)
                        {
@@ -900,10 +855,12 @@ set_info(int              skfd,           /* The socket */
                    fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno));
                    return(-1);
                  }
-               strcpy(wrq.ifr_name, ifname);
+               strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
                wrq.u.essid.flags = 1;
              }
            else
+             /* Check the size of what the user passed us to avoid
+              * buffer overflows */
              if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
                {
                  fprintf(stderr, "ESSID too long (max %d): ``%s''\n",
@@ -915,7 +872,7 @@ set_info(int                skfd,           /* The socket */
                  int           temp;
 
                  wrq.u.essid.flags = 1;
-                 strcpy(essid, args[i]);
+                 strcpy(essid, args[i]);       /* Size checked, all clear */
 
                  /* Check for ESSID index */
                  if(((i+1) < count) &&
@@ -944,14 +901,14 @@ set_info(int              skfd,           /* The socket */
            iw_usage();
 
          /* Check if we have valid address types */
-         if(check_addr_type(skfd, ifname) < 0)
+         if(iw_check_addr_type(skfd, ifname) < 0)
            {
              fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n", ifname);
              return(-1);
            }
 
          /* Get the address */
-         if(in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
+         if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
            iw_usage();
 
          if(ioctl(skfd, SIOCSIWAP, &wrq) < 0)
@@ -1006,7 +963,7 @@ set_info(int               skfd,           /* The socket */
                      fprintf(stderr, "SIOCGIWRATE: %s\n", strerror(errno));
                      return(-1);
                    }
-                 strcpy(wrq.ifr_name, ifname);
+                 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
                  wrq.u.bitrate.fixed = 1;
                }
              else                      /* Should be a numeric value */
@@ -1069,7 +1026,7 @@ set_info(int              skfd,           /* The socket */
                        fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno));
                        return(-1);
                      }
-                   strcpy(wrq.ifr_name, ifname);
+                   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
                    wrq.u.rts.fixed = 1;
                  }
                else                    /* Should be a numeric value */
@@ -1110,7 +1067,7 @@ set_info(int              skfd,           /* The socket */
                        fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno));
                        return(-1);
                      }
-                   strcpy(wrq.ifr_name, ifname);
+                   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
                    wrq.u.frag.fixed = 1;
                  }
                else                    /* Should be a numeric value */
@@ -1139,10 +1096,11 @@ set_info(int            skfd,           /* The socket */
          if(sscanf(args[i], "%d", &k) != 1)
            {
              k = 0;
-             while(k < 6 && strncasecmp(args[i], operation_mode[k], 3))
+             while((k < IW_NUM_OPER_MODE) &&
+                   strncasecmp(args[i], iw_operation_mode[k], 3))
                k++;
            }
-         if((k > 5) || (k < 0))
+         if((k >= IW_NUM_OPER_MODE) || (k < 0))
            iw_usage();
 
          wrq.u.mode = k;
@@ -1171,7 +1129,7 @@ set_info(int              skfd,           /* The socket */
                    fprintf(stderr, "SIOCGIWPOWER: %s\n", strerror(errno));
                    return(-1);
                  }
-               strcpy(wrq.ifr_name, ifname);
+               strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
                wrq.u.power.disabled = 0;
              }
            else
@@ -1268,7 +1226,7 @@ set_info(int              skfd,           /* The socket */
            iw_usage();
 
          /* Extract range info */
-         if(get_range_info(skfd, ifname, &range) < 0)
+         if(iw_get_range_info(skfd, ifname, &range) < 0)
            memset(&range, 0, sizeof(range));
 
          /* Prepare the request */
@@ -1292,7 +1250,7 @@ set_info(int              skfd,           /* The socket */
                        fprintf(stderr, "SIOCGIWTXPOW: %s\n", strerror(errno));
                        return(-1);
                      }
-                   strcpy(wrq.ifr_name, ifname);
+                   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
                    wrq.u.txpower.fixed = 1;
                  }
                else                    /* Should be a numeric value */
@@ -1311,11 +1269,11 @@ set_info(int            skfd,           /* The socket */
                    /* Convert */
                    if(!ismwatt && (range.txpower_capa & IW_TXPOW_MWATT))
                      {
-                       power = dbm2mwatt(power);
+                       power = iw_dbm2mwatt(power);
                        wrq.u.data.flags = IW_TXPOW_MWATT;
                      }
                    if(ismwatt && !(range.txpower_capa & IW_TXPOW_MWATT))
-                     power = mwatt2dbm(power);
+                     power = iw_mwatt2dbm(power);
                    wrq.u.bitrate.value = power;
 
                    /* Check for an additional argument */
@@ -1441,7 +1399,7 @@ main(int  argc,
   int goterr = 0;
 
   /* Create a channel to the NET kernel. */
-  if((skfd = sockets_open()) < 0)
+  if((skfd = iw_sockets_open()) < 0)
     {
       perror("socket");
       exit(-1);
index ef3ea8d..226c8c5 100644 (file)
@@ -8,7 +8,7 @@
  * This file is released under the GPL license.
  */
 
-#include "iwcommon.h"          /* Header */
+#include "iwlib.h"             /* Header */
 
 #define FORMAT_DEFAULT 0       /* Nice looking display for the user */
 #define FORMAT_SCHEME  1       /* To be used as a Pcmcia Scheme */
@@ -78,7 +78,7 @@ print_essid(int               skfd,
   int          j;
 
   /* Get ESSID */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   wrq.u.essid.pointer = (caddr_t) essid;
   wrq.u.essid.length = 0;
   wrq.u.essid.flags = 0;
@@ -119,7 +119,7 @@ print_nwid(int              skfd,
   struct iwreq         wrq;
 
   /* Get network ID */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0)
     return(-1);
 
@@ -185,15 +185,14 @@ scan_devices(int          skfd,
  * Display an Ethernet address in readable format.
  */
 char *
-pr_ether(unsigned char *ptr)
+pr_ether(char *                buffer,
+        unsigned char *ptr)
 {
-  static char buff[64];
-
-  sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
-       (ptr[0] & 0xFF), (ptr[1] & 0xFF), (ptr[2] & 0xFF),
-       (ptr[3] & 0xFF), (ptr[4] & 0xFF), (ptr[5] & 0xFF)
+  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(buff);
+  return(buffer);
 }
 
 /*------------------------------------------------------------------*/
@@ -242,15 +241,16 @@ print_ap(int              skfd,
         int            format)
 {
   struct iwreq         wrq;
+  char                 buffer[64];
 
   /* Get network ID */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   if(ioctl(skfd, SIOCGIWAP, &wrq) < 0)
     return(-1);
 
   /* Print */
   printf("%-8.8s  Access Point: %s\n", ifname,
-        pr_ether(wrq.u.ap_addr.sa_data));
+        pr_ether(buffer, wrq.u.ap_addr.sa_data));
 
   return(0);
 }
similarity index 52%
rename from wireless_tools/iwcommon.c
rename to wireless_tools/iwlib.c
index 0b2be07..ed3e357 100644 (file)
@@ -1,14 +1,23 @@
 /*
  *     Wireless Tools
  *
- *             Jean II - HPLB 97->99 - HPL 99->00
+ *             Jean II - HPLB 97->99 - HPL 99->01
  *
  * Common subroutines to all the wireless tools...
  *
  * This file is released under the GPL license.
  */
 
-#include "iwcommon.h"          /* Header */
+#include "iwlib.h"             /* Header */
+
+/**************************** VARIABLES ****************************/
+
+const char *   iw_operation_mode[] = { "Auto",
+                                       "Ad-Hoc",
+                                       "Managed",
+                                       "Master",
+                                       "Repeater",
+                                       "Secondary" };
 
 /************************ SOCKET SUBROUTINES *************************/
 
  * will allow us to talk to the driver.
  */
 int
-sockets_open(void)
+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         */
-
-       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;
+        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;
 }
 
 /*********************** WIRELESS SUBROUTINES ************************/
@@ -53,9 +66,9 @@ sockets_open(void)
  * Get the range information out of the driver
  */
 int
-get_range_info(int             skfd,
-              char *           ifname,
-              iwrange *        range)
+iw_get_range_info(int          skfd,
+                 char *        ifname,
+                 iwrange *     range)
 {
   struct iwreq         wrq;
   char                 buffer[sizeof(iwrange) * 2];    /* Large enough */
@@ -63,7 +76,7 @@ get_range_info(int            skfd,
   /* Cleanup */
   memset(buffer, 0, sizeof(range));
 
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   wrq.u.data.pointer = (caddr_t) buffer;
   wrq.u.data.length = 0;
   wrq.u.data.flags = 0;
@@ -115,14 +128,14 @@ get_range_info(int                skfd,
  * Get information about what private ioctls are supported by the driver
  */
 int
-get_priv_info(int              skfd,
-             char *            ifname,
-             iwprivargs *      priv)
+iw_get_priv_info(int           skfd,
+                char *         ifname,
+                iwprivargs *   priv)
 {
   struct iwreq         wrq;
 
   /* Ask the driver */
-  strcpy(wrq.ifr_name, ifname);
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   wrq.u.data.pointer = (caddr_t) priv;
   wrq.u.data.length = 0;
   wrq.u.data.flags = 0;
@@ -133,6 +146,200 @@ get_priv_info(int         skfd,
   return(wrq.u.data.length);
 }
 
+/*------------------------------------------------------------------*/
+/*
+ * Get essential wireless config from the device driver
+ * We will call all the classical wireless ioctl on the driver through
+ * the socket to know what is supported and to get the settings...
+ * Note : compare to the version in iwconfig, we extract only
+ * what's *really* needed to configure a device...
+ */
+int
+iw_get_basic_config(int                        skfd,
+                   char *              ifname,
+                   wireless_config *   info)
+{
+  struct iwreq         wrq;
+
+  memset((char *) info, 0, sizeof(struct wireless_config));
+
+  /* Get wireless name */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
+    /* If no wireless name : no wireless extensions */
+    return(-1);
+  else
+    strcpy(info->name, wrq.u.name);
+
+  /* Get network ID */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0)
+    {
+      info->has_nwid = 1;
+      memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
+    }
+
+  /* Get frequency / channel */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0)
+    {
+      info->has_freq = 1;
+      info->freq = iw_freq2float(&(wrq.u.freq));
+    }
+
+  /* Get encryption information */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  wrq.u.data.pointer = (caddr_t) info->key;
+  wrq.u.data.length = 0;
+  wrq.u.data.flags = 0;
+  if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0)
+    {
+      info->has_key = 1;
+      info->key_size = wrq.u.data.length;
+      info->key_flags = wrq.u.data.flags;
+    }
+
+  /* Get ESSID */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  wrq.u.essid.pointer = (caddr_t) info->essid;
+  wrq.u.essid.length = 0;
+  wrq.u.essid.flags = 0;
+  if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0)
+    {
+      info->has_essid = 1;
+      info->essid_on = wrq.u.data.flags;
+    }
+
+  /* Get operation mode */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0)
+    {
+      if((wrq.u.mode < 6) && (wrq.u.mode >= 0))
+       info->has_mode = 1;
+      info->mode = wrq.u.mode;
+    }
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set essential wireless config in the device driver
+ * We will call all the classical wireless ioctl on the driver through
+ * the socket to know what is supported and to set the settings...
+ * We support only the restricted set as above...
+ */
+int
+iw_set_basic_config(int                        skfd,
+                   char *              ifname,
+                   wireless_config *   info)
+{
+  struct iwreq         wrq;
+  int                  ret = 0;
+
+  /* Get wireless name (check if interface is valid) */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
+    /* If no wireless name : no wireless extensions */
+    return(-2);
+
+  /* Set Network ID, if available (this is for non-802.11 cards) */
+  if(info->has_nwid)
+    {
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+      memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam));
+      wrq.u.nwid.fixed = 1;    /* Hum... When in Rome... */
+
+      if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0)
+       {
+         fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
+         ret = -1;
+       }
+    }
+
+  /* Set frequency / channel */
+  if(info->has_freq)
+    {
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+      iw_float2freq(info->freq, &(wrq.u.freq));
+
+      if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
+       {
+         fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
+         ret = -1;
+       }
+    }
+
+  /* Set encryption information */
+  if(info->has_key)
+    {
+      int              flags = info->key_flags;
+
+      /* Check if there is a key index */
+      if((flags & IW_ENCODE_INDEX) > 0)
+       {
+         /* Set the index */
+         strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+         wrq.u.data.pointer = (caddr_t) NULL;
+         wrq.u.data.flags = flags & (IW_ENCODE_INDEX);
+         wrq.u.data.length = 0;
+
+         if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0)
+           {
+             fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
+                     errno, strerror(errno));
+             ret = -1;
+           }
+       }
+
+      /* Mask out index to minimise probability of reject when setting key */
+      flags = flags & (~IW_ENCODE_INDEX);
+
+      /* Set the key itself (set current key in this case) */
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+      wrq.u.data.pointer = (caddr_t) info->key;
+      wrq.u.data.length = info->key_size;
+      wrq.u.data.flags = flags;
+
+      if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0)
+       {
+         fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
+                 errno, strerror(errno));
+         ret = -1;
+       }
+    }
+
+  /* Set ESSID (extended network), if available */
+  if(info->has_essid)
+    {
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+      wrq.u.essid.pointer = (caddr_t) info->essid;
+      wrq.u.essid.length = strlen(info->essid) + 1;
+      wrq.u.data.flags = info->essid_on;
+
+      if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0)
+       {
+         fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
+         ret = -1;
+       }
+    }
+
+  /* Set the current mode of operation */
+  if(info->has_mode)
+    {
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+      wrq.u.mode = info->mode;
+
+      if(ioctl(skfd, SIOCSIWMODE, &wrq) < 0)
+       {
+         fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
+         ret = -1;
+       }
+    }
+
+  return(ret);
+}
+
 /********************** FREQUENCY SUBROUTINES ***********************/
 
 /*------------------------------------------------------------------*/
@@ -143,8 +350,8 @@ get_priv_info(int           skfd,
  * this custom format instead.
  */
 void
-float2freq(double      in,
-          iwfreq *     out)
+iw_float2freq(double   in,
+             iwfreq *  out)
 {
   out->e = (short) (floor(log10(in)));
   if(out->e > 8)
@@ -164,7 +371,7 @@ float2freq(double   in,
  * Convert our internal representation of frequencies to a floating point.
  */
 double
-freq2float(iwfreq *    in)
+iw_freq2float(iwfreq * in)
 {
   return ((double) in->m) * pow(10,in->e);
 }
@@ -176,7 +383,7 @@ freq2float(iwfreq * in)
  * Convert a value in dBm to a value in milliWatt.
  */
 int
-dbm2mwatt(int  in)
+iw_dbm2mwatt(int       in)
 {
   return((int) (floor(pow(10.0, (((double) in) / 10.0)))));
 }
@@ -186,7 +393,7 @@ dbm2mwatt(int       in)
  * Convert a value in milliWatt to a value in dBm.
  */
 int
-mwatt2dbm(int  in)
+iw_mwatt2dbm(int       in)
 {
   return((int) (ceil(10.0 * log10((double) in))));
 }
@@ -195,13 +402,89 @@ mwatt2dbm(int     in)
 
 /*------------------------------------------------------------------*/
 /*
+ * Read /proc/net/wireless to get the latest statistics
+ */
+int
+iw_get_stats(int       skfd,
+            char *     ifname,
+            iwstats *  stats)
+{
+#if WIRELESS_EXT > 11
+  struct iwreq         wrq;
+  wrq.u.data.pointer = (caddr_t) stats;
+  wrq.u.data.length = 0;
+  wrq.u.data.flags = 1;                /* Clear updated flag */
+  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+  if(ioctl(skfd, SIOCGIWSTATS, &wrq) < 0)
+    return(-1);
+
+  return(0);
+#else /* WIRELESS_EXT > 11 */
+  FILE *       f=fopen("/proc/net/wireless","r");
+  char         buf[256];
+  char *       bp;
+  int          t;
+  if(f==NULL)
+    return -1;
+  /* Loop on all devices */
+  while(fgets(buf,255,f))
+    {
+      bp=buf;
+      while(*bp&&isspace(*bp))
+       bp++;
+      /* Is it the good device ? */
+      if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
+       {
+         /* Skip ethX: */
+         bp=strchr(bp,':');
+         bp++;
+         /* -- status -- */
+         bp = strtok(bp, " ");
+         sscanf(bp, "%X", &t);
+         stats->status = (unsigned short) t;
+         /* -- link quality -- */
+         bp = strtok(NULL, " ");
+         if(strchr(bp,'.') != NULL)
+           stats->qual.updated |= 1;
+         sscanf(bp, "%d", &t);
+         stats->qual.qual = (unsigned char) t;
+         /* -- signal level -- */
+         bp = strtok(NULL, " ");
+         if(strchr(bp,'.') != NULL)
+           stats->qual.updated |= 2;
+         sscanf(bp, "%d", &t);
+         stats->qual.level = (unsigned char) t;
+         /* -- noise level -- */
+         bp = strtok(NULL, " ");
+         if(strchr(bp,'.') != NULL)
+           stats->qual.updated += 4;
+         sscanf(bp, "%d", &t);
+         stats->qual.noise = (unsigned char) t;
+         /* -- discarded packets -- */
+         bp = strtok(NULL, " ");
+         sscanf(bp, "%d", &stats->discard.nwid);
+         bp = strtok(NULL, " ");
+         sscanf(bp, "%d", &stats->discard.code);
+         bp = strtok(NULL, " ");
+         sscanf(bp, "%d", &stats->discard.misc);
+         fclose(f);
+         return 0;
+       }
+    }
+  fclose(f);
+  return -1;
+#endif /* WIRELESS_EXT > 11 */
+}
+
+/*------------------------------------------------------------------*/
+/*
  * Output the link statistics, taking care of formating
  */
 void
-print_stats(FILE *     stream,
-           iwqual *    qual,
-           iwrange *   range,
-           int         has_range)
+iw_print_stats(char *          buffer,
+              iwqual *         qual,
+              iwrange *        range,
+              int              has_range)
 {
   /* Just do it */
   if(has_range && (qual->level != 0))
@@ -210,8 +493,8 @@ print_stats(FILE *  stream,
       if(qual->level > range->max_qual.level)
        {
          /* Statistics are in dBm (absolute power measurement) */
-         fprintf(stream,
-                 "Quality:%d/%d  Signal level:%d dBm  Noise level:%d dBm%s\n",
+         sprintf(buffer,
+                 "Quality:%d/%d  Signal level:%d dBm  Noise level:%d dBm%s",
                  qual->qual, range->max_qual.qual,
                  qual->level - 0x100, qual->noise - 0x100,
                  (qual->updated & 0x7) ? " (updated)" : "");
@@ -219,8 +502,8 @@ print_stats(FILE *  stream,
       else
        {
          /* Statistics are relative values (0 -> max) */
-         fprintf(stream,
-                 "Quality:%d/%d  Signal level:%d/%d  Noise level:%d/%d%s\n",
+         sprintf(buffer,
+                 "Quality:%d/%d  Signal level:%d/%d  Noise level:%d/%d%s",
                  qual->qual, range->max_qual.qual,
                  qual->level, range->max_qual.level,
                  qual->noise, range->max_qual.noise,
@@ -230,7 +513,7 @@ print_stats(FILE *  stream,
   else
     {
       /* We can't read the range, so we don't know... */
-      fprintf(stream, "Quality:%d  Signal level:%d  Noise level:%d%s\n",
+      sprintf(buffer, "Quality:%d  Signal level:%d  Noise level:%d%s",
              qual->qual, qual->level, qual->noise,
              (qual->updated & 0x7) ? " (updated)" : "");
     }
@@ -243,10 +526,10 @@ print_stats(FILE *        stream,
  * Output the encoding key, with a nice formating
  */
 void
-print_key(FILE *               stream,
-         unsigned char *       key,
-         int                   key_size,
-         int                   key_flags)
+iw_print_key(char *            buffer,
+            unsigned char *    key,
+            int                key_size,
+            int                key_flags)
 {
   int  i;
 
@@ -254,23 +537,27 @@ print_key(FILE *          stream,
   if(key_flags & IW_ENCODE_NOKEY)
     {
       /* Nope : print dummy */
-      printf("**");
+      strcpy(buffer, "**");
+      buffer +=2;
       for(i = 1; i < key_size; i++)
        {
          if((i & 0x1) == 0)
-           printf("-");
-         printf("**");
+           strcpy(buffer++, "-");
+         strcpy(buffer, "**");
+         buffer +=2;
        }
     }
   else
     {
       /* Yes : print the key */
-      printf("%.2X", key[0]);
+      sprintf(buffer, "%.2X", key[0]);
+      buffer +=2;
       for(i = 1; i < key_size; i++)
        {
          if((i & 0x1) == 0)
-           printf("-");
-         printf("%.2X", key[i]);
+           strcpy(buffer++, "-");
+         sprintf(buffer, "%.2X", key[i]);
+         buffer +=2;
        }
     }
 }
@@ -283,35 +570,47 @@ print_key(FILE *          stream,
  * Output a power management value with all attributes...
  */
 void
-print_pm_value(FILE *  stream,
-              int      value,
-              int      flags)
+iw_print_pm_value(char *       buffer,
+                 int           value,
+                 int           flags)
 {
   /* Modifiers */
   if(flags & IW_POWER_MIN)
-    fprintf(stream, " min");
+    {
+      strcpy(buffer, " min");
+      buffer += 4;
+    }
   if(flags & IW_POWER_MAX)
-    fprintf(stream, " max");
+    {
+      strcpy(buffer, " max");
+      buffer += 4;
+    }
 
   /* Type */
   if(flags & IW_POWER_TIMEOUT)
-    fprintf(stream, " timeout:");
+    {
+      strcpy(buffer, " timeout:");
+      buffer += 9;
+    }
   else
-    fprintf(stream, " period:");
+    {
+      strcpy(buffer, " period:");
+      buffer += 8;
+    }
 
   /* Display value without units */
   if(flags & IW_POWER_RELATIVE)
-    fprintf(stream, "%g  ", ((double) value) / MEGA);
+    sprintf(buffer, "%g  ", ((double) value) / MEGA);
   else
     {
       /* Display value with units */
       if(value >= (int) MEGA)
-       fprintf(stream, "%gs  ", ((double) value) / MEGA);
+       sprintf(buffer, "%gs  ", ((double) value) / MEGA);
       else
        if(value >= (int) KILO)
-         fprintf(stream, "%gms  ", ((double) value) / KILO);
+         sprintf(buffer, "%gms  ", ((double) value) / KILO);
        else
-         fprintf(stream, "%dus  ", value);
+         sprintf(buffer, "%dus  ", value);
     }
 }
 
@@ -320,26 +619,26 @@ print_pm_value(FILE *     stream,
  * Output a power management mode
  */
 void
-print_pm_mode(FILE *   stream,
-             int       flags)
+iw_print_pm_mode(char *        buffer,
+                int    flags)
 {
   /* Print the proper mode... */
   switch(flags & IW_POWER_MODE)
     {
     case IW_POWER_UNICAST_R:
-      fprintf(stream, " mode:Unicast only received");
+      strcpy(buffer, " mode:Unicast only received");
       break;
     case IW_POWER_MULTICAST_R:
-      fprintf(stream, " mode:Multicast only received");
+      strcpy(buffer, " mode:Multicast only received");
       break;
     case IW_POWER_ALL_R:
-      fprintf(stream, " mode:All packets received");
+      strcpy(buffer, " mode:All packets received");
       break;
     case IW_POWER_FORCE_S:
-      fprintf(stream, " mode:Force sending");
+      strcpy(buffer, " mode:Force sending");
       break;
     case IW_POWER_REPEATER:
-      fprintf(stream, " mode:Repeat multicasts");
+      strcpy(buffer, " mode:Repeat multicasts");
       break;
     default:
     }
@@ -353,38 +652,45 @@ print_pm_mode(FILE *      stream,
  * Output a retry value with all attributes...
  */
 void
-print_retry_value(FILE *       stream,
-                 int           value,
-                 int           flags)
+iw_print_retry_value(char *    buffer,
+                    int        value,
+                    int        flags)
 {
   /* Modifiers */
   if(flags & IW_RETRY_MIN)
-    fprintf(stream, " min");
+    {
+      strcpy(buffer, " min");
+      buffer += 4;
+    }
   if(flags & IW_RETRY_MAX)
-    fprintf(stream, " max");
+    {
+      strcpy(buffer, " max");
+      buffer += 4;
+    }
 
   /* Type lifetime of limit */
   if(flags & IW_RETRY_LIFETIME)
     {
-      fprintf(stream, " lifetime:");
+      strcpy(buffer, " lifetime:");
+      buffer += 10;
 
       /* Display value without units */
       if(flags & IW_POWER_RELATIVE)
-       fprintf(stream, "%g", ((double) value) / MEGA);
+       sprintf(buffer, "%g", ((double) value) / MEGA);
       else
        {
          /* Display value with units */
          if(value >= (int) MEGA)
-           fprintf(stream, "%gs", ((double) value) / MEGA);
+           sprintf(buffer, "%gs", ((double) value) / MEGA);
          else
            if(value >= (int) KILO)
-             fprintf(stream, "%gms", ((double) value) / KILO);
+             sprintf(buffer, "%gms", ((double) value) / KILO);
            else
-             fprintf(stream, "%dus", value);
+             sprintf(buffer, "%dus", value);
        }
     }
   else
-    fprintf(stream, " limit:%d", value);
+    sprintf(buffer, " limit:%d", value);
 }
 #endif /* WIRELESS_EXT > 10 */
 
@@ -399,13 +705,13 @@ print_retry_value(FILE *  stream,
  * Check if interface support the right address types...
  */
 int
-check_addr_type(int    skfd,
-               char *  ifname)
+iw_check_addr_type(int         skfd,
+                  char *       ifname)
 {
   struct ifreq         ifr;
 
   /* Get the type of interface address */
-  strcpy(ifr.ifr_name, ifname);
+  strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
   if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) ||
      (ifr.ifr_addr.sa_family !=  AF_INET))
     {
@@ -420,7 +726,7 @@ check_addr_type(int skfd,
 #endif
 
   /* Get the type of hardware address */
-  strcpy(ifr.ifr_name, ifname);
+  strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
   if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) ||
      (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER))
     {
@@ -444,15 +750,14 @@ check_addr_type(int       skfd,
  * Display an Ethernet address in readable format.
  */
 char *
-pr_ether(unsigned char *ptr)
+iw_pr_ether(char *             buffer,
+           unsigned char *     ptr)
 {
-  static char buff[64];
-
-  sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
-       (ptr[0] & 0xFF), (ptr[1] & 0xFF), (ptr[2] & 0xFF),
-       (ptr[3] & 0xFF), (ptr[4] & 0xFF), (ptr[5] & 0xFF)
+  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(buff);
+  return(buffer);
 }
 
 /*------------------------------------------------------------------*/
@@ -460,7 +765,7 @@ pr_ether(unsigned char *ptr)
  * Input an Ethernet address and convert to binary.
  */
 int
-in_ether(char *bufp, struct sockaddr *sap)
+iw_in_ether(char *bufp, struct sockaddr *sap)
 {
   unsigned char *ptr;
   char c, *orig;
@@ -533,7 +838,7 @@ in_ether(char *bufp, struct sockaddr *sap)
  * Input an Internet address and convert to binary.
  */
 int
-in_inet(char *bufp, struct sockaddr *sap)
+iw_in_inet(char *bufp, struct sockaddr *sap)
 {
   struct hostent *hp;
   struct netent *np;
@@ -571,10 +876,10 @@ in_inet(char *bufp, struct sockaddr *sap)
  * Input an address and convert to binary.
  */
 int
-in_addr(int            skfd,
-       char *          ifname,
-       char *          bufp,
-       struct sockaddr *sap)
+iw_in_addr(int         skfd,
+          char *       ifname,
+          char *       bufp,
+          struct sockaddr *sap)
 {
   /* Check if it is a hardware or IP address */
   if(index(bufp, ':') == NULL)
@@ -583,7 +888,7 @@ in_addr(int         skfd,
       struct arpreq    arp_query;
 
       /* Read interface address */
-      if(in_inet(bufp, &if_address) < 0)
+      if(iw_in_inet(bufp, &if_address) < 0)
        {
          fprintf(stderr, "Invalid interface address %s\n", bufp);
          return(-1);
@@ -597,7 +902,7 @@ in_addr(int         skfd,
       arp_query.arp_flags = 0;
       /* The following restrict the search to the interface only */
       /* For old kernels which complain, just comment it... */
-      strcpy(arp_query.arp_dev, ifname);
+      strncpy(arp_query.arp_dev, ifname, IFNAMSIZ);
       if((ioctl(skfd, SIOCGARP, &arp_query) < 0) ||
         !(arp_query.arp_flags & ATF_COM))
        {
@@ -618,7 +923,7 @@ in_addr(int         skfd,
     }
   else /* If it's an hardware address */
     /* Get the hardware address */
-    if(in_ether(bufp, sap) < 0)
+    if(iw_in_ether(bufp, sap) < 0)
       {
        fprintf(stderr, "Invalid hardware address %s\n", bufp);
        return(-1);
@@ -637,7 +942,7 @@ in_addr(int         skfd,
 /*
  */
 int
-byte_size(int  args)
+iw_byte_size(int       args)
 {
   int  ret = args & IW_PRIV_SIZE_MASK;
 
diff --git a/wireless_tools/iwlib.h b/wireless_tools/iwlib.h
new file mode 100644 (file)
index 0000000..723475b
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ *     Wireless Tools
+ *
+ *             Jean II - HPLB 97->99 - HPL 99->01
+ *
+ * Common header for the Wireless Extension library...
+ *
+ * This file is released under the GPL license.
+ */
+
+#ifndef IWLIB_H
+#define IWLIB_H
+
+/*#include "CHANGELOG.h"*/
+
+/***************************** INCLUDES *****************************/
+
+/* Standard headers */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <math.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>             /* gethostbyname, getnetbyname */
+
+/* This is our header selection. Try to hide the mess and the misery :-(
+ * The selection has been moved in the Makefile, here we have only
+ * the ugly part. Don't look, you would go blind ;-) */
+
+#ifdef KLUDGE_HEADERS
+#include <socketbits.h>
+#endif /* KLUDGE_HEADERS */
+
+#if defined(KLUDGE_HEADERS) || defined(GLIBC_HEADERS)
+#include <linux/if_arp.h>      /* For ARPHRD_ETHER */
+#include <linux/socket.h>      /* For AF_INET & struct sockaddr */
+#include <linux/in.h>          /* For struct sockaddr_in */
+#endif /* KLUDGE_HEADERS || GLIBC_HEADERS */
+
+#ifdef GLIBC22_HEADERS 
+/* Added by Ross G. Miller <Ross_Miller@baylor.edu>, 3/28/01 */
+#include <linux/if_arp.h>      /* For ARPHRD_ETHER */
+#include <linux/socket.h>      /* For AF_INET & struct sockaddr */
+#include <sys/socket.h>
+#endif /* GLIBC22_HEADERS */    
+
+#ifdef LIBC5_HEADERS
+#include <sys/socket.h>                /* For AF_INET & struct sockaddr & socket() */
+#include <linux/if_arp.h>      /* For ARPHRD_ETHER */
+#include <linux/in.h>          /* For struct sockaddr_in */
+#endif /* LIBC5_HEADERS */
+
+#ifdef PRIVATE_WE_HEADER
+/* Private copy of Wireless extensions */
+#include "wireless.h"
+#else  /* PRIVATE_WE_HEADER */
+/* System wide Wireless extensions */
+#include <linux/wireless.h>
+#endif /* PRIVATE_WE_HEADER */
+
+#if WIRELESS_EXT < 9
+#error "Wireless Extension v9 or newer required :-(\
+Use Wireless Tools v19 or update your kernel headers"
+#endif
+#if WIRELESS_EXT < 11
+#warning "Wireless Extension v11 recommended...\
+You may update your kernel and/or system headers to get the new features..."
+#endif
+
+/****************************** DEBUG ******************************/
+
+
+/************************ CONSTANTS & MACROS ************************/
+
+/* Some usefull constants */
+#define KILO   1e3
+#define MEGA   1e6
+#define GIGA   1e9
+
+/* Backward compatibility for Wireless Extension 9 */
+#ifndef IW_POWER_MODIFIER
+#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 */
+#endif IW_POWER_MODIFIER
+
+#ifndef IW_ENCODE_NOKEY
+#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not here */
+#define IW_ENCODE_MODE         0xF000  /* Modes defined below */
+#endif IW_ENCODE_NOKEY
+
+/****************************** TYPES ******************************/
+
+/* Shortcuts */
+typedef struct iw_statistics   iwstats;
+typedef struct iw_range                iwrange;
+typedef struct iw_param                iwparam;
+typedef struct iw_freq         iwfreq;
+typedef struct iw_quality      iwqual;
+typedef struct iw_priv_args    iwprivargs;
+typedef struct sockaddr                sockaddr;
+
+/* Structure for storing all wireless information for each device
+ * This is pretty exhaustive... */
+typedef struct wireless_info
+{
+  char         name[IFNAMSIZ];         /* Wireless/protocol name */
+  int          has_nwid;
+  iwparam      nwid;                   /* Network ID */
+  int          has_freq;
+  float                freq;                   /* Frequency/channel */
+  int          has_sens;
+  iwparam      sens;                   /* sensitivity */
+  int          has_key;
+  unsigned char        key[IW_ENCODING_TOKEN_MAX];     /* Encoding key used */
+  int          key_size;               /* Number of bytes */
+  int          key_flags;              /* Various flags */
+  int          has_essid;
+  int          essid_on;
+  char         essid[IW_ESSID_MAX_SIZE + 1];   /* ESSID (extended network) */
+  int          has_nickname;
+  char         nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */
+  int          has_ap_addr;
+  sockaddr     ap_addr;                /* Access point address */
+  int          has_bitrate;
+  iwparam      bitrate;                /* Bit rate in bps */
+  int          has_rts;
+  iwparam      rts;                    /* RTS threshold in bytes */
+  int          has_frag;
+  iwparam      frag;                   /* Fragmentation threshold in bytes */
+  int          has_mode;
+  int          mode;                   /* Operation mode */
+  int          has_power;
+  iwparam      power;                  /* Power management parameters */
+  int          has_txpower;
+  iwparam      txpower;                /* Transmit Power in dBm */
+  int          has_retry;
+  iwparam      retry;                  /* Retry limit or lifetime */
+
+  /* Stats */
+  iwstats      stats;
+  int          has_stats;
+  iwrange      range;
+  int          has_range;
+} wireless_info;
+
+/* Structure for storing all wireless information for each device
+ * This is a cut down version of the one above, containing only
+ * the things *truly* needed to configure a card.
+ * Don't add other junk, I'll remove it... */
+typedef struct wireless_config
+{
+  char         name[IFNAMSIZ];         /* Wireless/protocol name */
+  int          has_nwid;
+  iwparam      nwid;                   /* Network ID */
+  int          has_freq;
+  float                freq;                   /* Frequency/channel */
+  int          has_key;
+  unsigned char        key[IW_ENCODING_TOKEN_MAX];     /* Encoding key used */
+  int          key_size;               /* Number of bytes */
+  int          key_flags;              /* Various flags */
+  int          has_essid;
+  int          essid_on;
+  char         essid[IW_ESSID_MAX_SIZE + 1];   /* ESSID (extended network) */
+  int          has_mode;
+  int          mode;                   /* Operation mode */
+} wireless_config;
+
+/**************************** PROTOTYPES ****************************/
+/*
+ * All the functions in iwcommon.c
+ */
+/* ---------------------- SOCKET SUBROUTINES -----------------------*/
+int
+       iw_sockets_open(void);
+/* --------------------- WIRELESS SUBROUTINES ----------------------*/
+int
+       iw_get_range_info(int           skfd,
+                         char *        ifname,
+                         iwrange *     range);
+int
+       iw_get_priv_info(int            skfd,
+                        char *         ifname,
+                        iwprivargs *   priv);
+int
+       iw_get_basic_config(int                 skfd,
+                           char *              ifname,
+                           wireless_config *   info);
+int
+       iw_set_basic_config(int                 skfd,
+                           char *              ifname,
+                           wireless_config *   info);
+/* -------------------- FREQUENCY SUBROUTINES --------------------- */
+void
+       iw_float2freq(double    in,
+                  iwfreq *     out);
+double
+       iw_freq2float(iwfreq *  in);
+/* ---------------------- POWER SUBROUTINES ----------------------- */
+int
+       iw_dbm2mwatt(int        in);
+int
+       iw_mwatt2dbm(int        in);
+/* -------------------- STATISTICS SUBROUTINES -------------------- */
+int
+       iw_get_stats(int        skfd,
+                    char *     ifname,
+                    iwstats *  stats);
+void
+       iw_print_stats(char *           buffer,
+                      iwqual *         qual,
+                      iwrange *        range,
+                      int              has_range);
+/* --------------------- ENCODING SUBROUTINES --------------------- */
+void
+       iw_print_key(char *             buffer,
+                    unsigned char *    key,
+                    int                key_size,
+                    int                key_flags);
+/* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */
+void
+       iw_print_pm_value(char *        buffer,
+                         int           value,
+                         int           flags);
+void
+       iw_print_pm_mode(char *         buffer,
+                        int            flags);
+/* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */
+#if WIRELESS_EXT > 10
+void
+       iw_print_retry_value(char *     buffer,
+                            int        value,
+                            int        flags);
+#endif
+/* --------------------- ADDRESS SUBROUTINES ---------------------- */
+int
+       iw_check_addr_type(int  skfd,
+                       char *  ifname);
+char *
+       iw_pr_ether(char *buffer, unsigned char *ptr);
+int
+       iw_in_ether(char *bufp, struct sockaddr *sap);
+int
+       iw_in_inet(char *bufp, struct sockaddr *sap);
+int
+       iw_in_addr(int                  skfd,
+                  char *               ifname,
+                  char *               bufp,
+                  struct sockaddr *    sap);
+/* ----------------------- MISC SUBROUTINES ------------------------ */
+int
+       iw_byte_size(int                args);
+
+/**************************** VARIABLES ****************************/
+
+extern const char *    iw_operation_mode[];
+#define IW_NUM_OPER_MODE       6
+
+#endif /* IWLIB_H */
index b8284af..50db6c9 100644 (file)
@@ -10,7 +10,7 @@
  * This file is released under the GPL license.
  */
 
-#include "iwcommon.h"          /* Header */
+#include "iwlib.h"             /* Header */
 
 /*********************** FREQUENCIES/CHANNELS ***********************/
 
@@ -26,7 +26,7 @@ print_freq_info(int           skfd,
   struct iw_range      range;
   int                  k;
 
-  if(get_range_info(skfd, ifname, &range) < 0)
+  if(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no frequency information.\n\n",
                      ifname);
   else
@@ -39,7 +39,7 @@ print_freq_info(int           skfd,
          for(k = 0; k < range.num_frequency; k++)
            {
              printf("\t  Channel %.2d : ", range.freq[k].i);
-             freq = freq2float(&(range.freq[k]));
+             freq = iw_freq2float(&(range.freq[k]));
              if(freq >= GIGA)
                printf("%g GHz\n", freq / GIGA);
              else
@@ -56,33 +56,6 @@ print_freq_info(int          skfd,
     }
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Get frequency info on all devices and print it on the screen
- */
-static void
-print_freq_devices(int         skfd)
-{
-  char         buff[1024];
-  struct ifconf ifc;
-  struct ifreq *ifr;
-  int i;
-
-  /* Get list of active devices */
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
-    {
-      fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
-      return;
-    }
-  ifr = ifc.ifc_req;
-
-  /* Print them */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    print_freq_info(skfd, ifr->ifr_name);
-}
-
 /************************ ACCESS POINT LIST ************************/
 
 /*------------------------------------------------------------------*/
@@ -92,11 +65,12 @@ print_freq_devices(int              skfd)
  */
 static void
 print_ap_info(int      skfd,
-              char *   ifname)
+             char *    ifname)
 {
   struct iwreq         wrq;
   char         buffer[(sizeof(struct iw_quality) +
                        sizeof(struct sockaddr)) * IW_MAX_AP];
+  char         temp[128];
   struct sockaddr *    hwa;
   struct iw_quality *  qual;
   iwrange      range;
@@ -125,14 +99,14 @@ print_ap_info(int  skfd,
   qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
 
   /* Check if we have valid address types */
-  if(check_addr_type(skfd, ifname) < 0)
+  if(iw_check_addr_type(skfd, ifname) < 0)
     {
       fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n\n", ifname);
       return;
     }
 
   /* Get range info if we can */
-  if(get_range_info(skfd, ifname, &(range)) >= 0)
+  if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
     has_range = 1;
 
   /* Display it */
@@ -145,43 +119,17 @@ print_ap_info(int skfd,
       if(has_qual)
        {
          /* Print stats for this address */
-         printf("    %s : ", pr_ether(hwa[i].sa_data));
-         print_stats(stdout, &qual[i], &range, has_range);
+         printf("    %s : ", iw_pr_ether(temp, hwa[i].sa_data));
+         iw_print_stats(temp, &qual[i], &range, has_range);
+         printf("%s\n", temp);
        }
       else
        /* Only print the address */
-       printf("    %s\n", pr_ether(hwa[i].sa_data));
+       printf("    %s\n", iw_pr_ether(temp, hwa[i].sa_data));
     }
   printf("\n");
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Get list of AP on all devices and print it on the screen
- */
-static void
-print_ap_devices(int           skfd)
-{
-  char         buff[1024];
-  struct ifconf ifc;
-  struct ifreq *ifr;
-  int i;
-
-  /* Get list of active devices */
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
-    {
-      fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
-      return;
-    }
-  ifr = ifc.ifc_req;
-
-  /* Print them */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    print_ap_info(skfd, ifr->ifr_name);
-}
-
 /***************************** BITRATES *****************************/
 
 /*------------------------------------------------------------------*/
@@ -197,7 +145,7 @@ print_bitrate_info(int              skfd,
   int                  k;
 
   /* Extract range info */
-  if(get_range_info(skfd, ifname, &range) < 0)
+  if(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no bit-rate information.\n\n",
                      ifname);
   else
@@ -226,33 +174,6 @@ print_bitrate_info(int             skfd,
     }
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Get bit-rate info on all devices and print it on the screen
- */
-static void
-print_bitrate_devices(int              skfd)
-{
-  char         buff[1024];
-  struct ifconf ifc;
-  struct ifreq *ifr;
-  int i;
-
-  /* Get list of active devices */
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
-    {
-      fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
-      return;
-    }
-  ifr = ifc.ifc_req;
-
-  /* Print them */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    print_bitrate_info(skfd, ifr->ifr_name);
-}
-
 /************************* ENCRYPTION KEYS *************************/
 
 /*------------------------------------------------------------------*/
@@ -267,9 +188,10 @@ print_keys_info(int                skfd,
   struct iw_range      range;
   unsigned char                key[IW_ENCODING_TOKEN_MAX];
   int                  k;
+  char                 buffer[128];
 
   /* Extract range info */
-  if(get_range_info(skfd, ifname, &range) < 0)
+  if(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no encryption keys information.\n\n",
                      ifname);
   else
@@ -290,7 +212,7 @@ print_keys_info(int         skfd,
       printf("%d keys available :\n", range.max_encoding_tokens);
       for(k = 1; k <= range.max_encoding_tokens; k++)
        {
-         strcpy(wrq.ifr_name, ifname);
+         strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
          wrq.u.data.pointer = (caddr_t) key;
          wrq.u.data.length = 0;
          wrq.u.data.flags = k;
@@ -305,8 +227,8 @@ print_keys_info(int         skfd,
          else
            {
              /* Display the key */
-             printf("\t\t[%d]: ", k);
-             print_key(stdout, key, wrq.u.data.length, wrq.u.data.flags);
+             iw_print_key(buffer, key, wrq.u.data.length, wrq.u.data.flags);
+             printf("\t\t[%d]: %s", k, buffer);
 
              /* Other info... */
              printf(" (%d bits)", wrq.u.data.length * 8);
@@ -314,7 +236,7 @@ print_keys_info(int         skfd,
            }
        }
       /* Print current key and mode */
-      strcpy(wrq.ifr_name, ifname);
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
       wrq.u.data.pointer = (caddr_t) key;
       wrq.u.data.length = 0;
       wrq.u.data.flags = 0;    /* Set index to zero to get current */
@@ -334,33 +256,6 @@ print_keys_info(int                skfd,
     }
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Get encryption info on all devices and print it on the screen
- */
-static void
-print_keys_devices(int         skfd)
-{
-  char         buff[1024];
-  struct ifconf ifc;
-  struct ifreq *ifr;
-  int i;
-
-  /* Get list of active devices */
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
-    {
-      fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
-      return;
-    }
-  ifr = ifc.ifc_req;
-
-  /* Print them */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    print_keys_info(skfd, ifr->ifr_name);
-}
-
 /************************* POWER MANAGEMENT *************************/
 
 /*------------------------------------------------------------------*/
@@ -371,18 +266,19 @@ static inline int
 get_pm_value(int               skfd,
             char *             ifname,
             struct iwreq *     pwrq,
-            int                flags)
+            int                flags,
+            char *             buffer)
 {
   /* Get Another Power Management value */
-  strcpy(pwrq->ifr_name, ifname);
+  strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
   pwrq->u.power.flags = flags;
   if(ioctl(skfd, SIOCGIWPOWER, pwrq) >= 0)
     {
       /* Let's check the value and its type */
       if(pwrq->u.power.flags & IW_POWER_TYPE)
        {
-         printf("\n                 ");
-         print_pm_value(stdout, pwrq->u.power.value, pwrq->u.power.flags);
+         iw_print_pm_value(buffer, pwrq->u.power.value, pwrq->u.power.flags);
+         printf("\n                 %s", buffer);
        }
     }
   return(pwrq->u.power.flags);
@@ -398,9 +294,10 @@ print_pm_info(int          skfd,
 {
   struct iwreq         wrq;
   struct iw_range      range;
+  char                 buffer[128];
 
   /* Extract range info */
-  if(get_range_info(skfd, ifname, &range) < 0)
+  if(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no power management information.\n\n",
                      ifname);
   else
@@ -432,10 +329,10 @@ print_pm_info(int         skfd,
          else
            printf("Fixed period  ; ");
          /* Print the range */
-         print_pm_value(stdout, range.min_pmp, flags | IW_POWER_MIN);
-         printf("\n                          ");
-         print_pm_value(stdout, range.max_pmp, flags | IW_POWER_MAX);
-         printf("\n          ");
+         iw_print_pm_value(buffer, range.min_pmp, flags | IW_POWER_MIN);
+         printf("%s\n                          ", buffer);
+         iw_print_pm_value(buffer, range.max_pmp, flags | IW_POWER_MAX);
+         printf("%s\n          ", buffer);
          
        }
       /* Display min/max timeout availables */
@@ -448,16 +345,16 @@ print_pm_info(int         skfd,
          else
            printf("Fixed timeout ; ");
          /* Print the range */
-         print_pm_value(stdout, range.min_pmt, flags | IW_POWER_MIN);
-         printf("\n                          ");
-         print_pm_value(stdout, range.max_pmt, flags | IW_POWER_MAX);
-         printf("\n          ");
+         iw_print_pm_value(buffer, range.min_pmt, flags | IW_POWER_MIN);
+         printf("%s\n                          ", buffer);
+         iw_print_pm_value(buffer, range.max_pmt, flags | IW_POWER_MAX);
+         printf("%s\n          ", buffer);
          
        }
 #endif /* WIRELESS_EXT > 9 */
 
       /* Get current Power Management settings */
-      strcpy(wrq.ifr_name, ifname);
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
       wrq.u.power.flags = 0;
       if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0)
        {
@@ -471,8 +368,8 @@ print_pm_info(int           skfd,
              int       pm_mask = 0;
 
              /* Let's check the mode */
-             printf("Current");
-             print_pm_mode(stdout, flags);
+             iw_print_pm_mode(buffer, flags);
+             printf("Current%s", buffer);
 
              /* Let's check if nothing (simply on) */
              if((flags & IW_POWER_MODE) == IW_POWER_ON)
@@ -481,7 +378,11 @@ print_pm_info(int          skfd,
 
              /* Let's check the value and its type */
              if(wrq.u.power.flags & IW_POWER_TYPE)
-               print_pm_value(stdout, wrq.u.power.value, wrq.u.power.flags);
+               {
+                 iw_print_pm_value(buffer,
+                                   wrq.u.power.value, wrq.u.power.flags);
+                 printf("%s", buffer);
+               }
 
              /* If we have been returned a MIN value, ask for the MAX */
              if(flags & IW_POWER_MIN)
@@ -491,7 +392,7 @@ print_pm_info(int           skfd,
                pm_mask = IW_POWER_MIN;
              /* If we have something to ask for... */
              if(pm_mask)
-               get_pm_value(skfd, ifname, &wrq, pm_mask);
+               get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
 
 #if WIRELESS_EXT > 9
              /* And if we have both a period and a timeout, ask the other */
@@ -500,7 +401,7 @@ print_pm_info(int           skfd,
              if(pm_mask)
                {
                  int   base_mask = pm_mask;
-                 flags = get_pm_value(skfd, ifname, &wrq, pm_mask);
+                 flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
                  pm_mask = 0;
 
                  /* If we have been returned a MIN value, ask for the MAX */
@@ -511,7 +412,7 @@ print_pm_info(int           skfd,
                    pm_mask = IW_POWER_MIN | base_mask;
                  /* If we have something to ask for... */
                  if(pm_mask)
-                   get_pm_value(skfd, ifname, &wrq, pm_mask);
+                   get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
                }
 #endif /* WIRELESS_EXT > 9 */
            }
@@ -520,33 +421,6 @@ print_pm_info(int          skfd,
     }
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Get Power Management info on all devices and print it on the screen
- */
-static void
-print_pm_devices(int           skfd)
-{
-  char         buff[1024];
-  struct ifconf ifc;
-  struct ifreq *ifr;
-  int i;
-
-  /* Get list of active devices */
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
-    {
-      fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
-      return;
-    }
-  ifr = ifc.ifc_req;
-
-  /* Print them */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    print_pm_info(skfd, ifr->ifr_name);
-}
-
 /************************** TRANSMIT POWER **************************/
 
 /*------------------------------------------------------------------*/
@@ -564,7 +438,7 @@ print_txpower_info(int              skfd,
 
 #if WIRELESS_EXT > 9
   /* Extract range info */
-  if(get_range_info(skfd, ifname, &range) < 0)
+  if(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no transmit-power information.\n\n",
                      ifname);
   else
@@ -578,13 +452,13 @@ print_txpower_info(int            skfd,
            {
              if(range.txpower_capa & IW_TXPOW_MWATT)
                {
-                 dbm = mwatt2dbm(range.txpower[k]);
+                 dbm = iw_mwatt2dbm(range.txpower[k]);
                  mwatt = range.txpower[k];
                }
              else
                {
                  dbm = range.txpower[k];
-                 mwatt = dbm2mwatt(range.txpower[k]);
+                 mwatt = iw_dbm2mwatt(range.txpower[k]);
                }
              printf("\t  %d dBm  \t(%d mW)\n", dbm, mwatt);
            }
@@ -596,33 +470,6 @@ print_txpower_info(int             skfd,
 #endif /* WIRELESS_EXT > 9 */
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Get tx-power info on all devices and print it on the screen
- */
-static void
-print_txpower_devices(int              skfd)
-{
-  char         buff[1024];
-  struct ifconf ifc;
-  struct ifreq *ifr;
-  int i;
-
-  /* Get list of active devices */
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
-    {
-      fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
-      return;
-    }
-  ifr = ifc.ifc_req;
-
-  /* Print them */
-  for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    print_txpower_info(skfd, ifr->ifr_name);
-}
-
 /*********************** RETRY LIMIT/LIFETIME ***********************/
 
 #if WIRELESS_EXT > 10
@@ -634,18 +481,20 @@ static inline int
 get_retry_value(int            skfd,
                char *          ifname,
                struct iwreq *  pwrq,
-               int             flags)
+               int             flags,
+               char *          buffer)
 {
   /* Get Another retry value */
-  strcpy(pwrq->ifr_name, ifname);
+  strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
   pwrq->u.retry.flags = flags;
   if(ioctl(skfd, SIOCGIWRETRY, pwrq) >= 0)
     {
       /* Let's check the value and its type */
       if(pwrq->u.retry.flags & IW_RETRY_TYPE)
        {
-         printf("\n                 ");
-         print_retry_value(stdout, pwrq->u.retry.value, pwrq->u.retry.flags);
+         iw_print_retry_value(buffer,
+                              pwrq->u.retry.value, pwrq->u.retry.flags);
+         printf("%s\n                 ", buffer);
        }
     }
   return(pwrq->u.retry.flags);
@@ -657,13 +506,14 @@ get_retry_value(int               skfd,
  */
 static void
 print_retry_info(int           skfd,
-             char *            ifname)
+                char *         ifname)
 {
   struct iwreq         wrq;
   struct iw_range      range;
+  char                 buffer[128];
 
   /* Extract range info */
-  if(get_range_info(skfd, ifname, &range) < 0)
+  if(iw_get_range_info(skfd, ifname, &range) < 0)
       fprintf(stderr, "%-8.8s  no retry limit/lifetime information.\n\n",
              ifname);
   else
@@ -680,10 +530,10 @@ print_retry_info(int              skfd,
          else
            printf("Fixed limit    ; ");
          /* Print the range */
-         print_retry_value(stdout, range.min_retry, flags | IW_RETRY_MIN);
-         printf("\n                           ");
-         print_retry_value(stdout, range.max_retry, flags | IW_RETRY_MAX);
-         printf("\n          ");
+         iw_print_retry_value(buffer, range.min_retry, flags | IW_RETRY_MIN);
+         printf("%s\n                           ", buffer);
+         iw_print_retry_value(buffer, range.max_retry, flags | IW_RETRY_MAX);
+         printf("%s\n          ", buffer);
          
        }
       /* Display min/max lifetime availables */
@@ -696,15 +546,15 @@ print_retry_info(int              skfd,
          else
            printf("Fixed lifetime ; ");
          /* Print the range */
-         print_retry_value(stdout, range.min_r_time, flags | IW_RETRY_MIN);
-         printf("\n                           ");
-         print_retry_value(stdout, range.max_r_time, flags | IW_RETRY_MAX);
-         printf("\n          ");
+         iw_print_retry_value(buffer, range.min_r_time, flags | IW_RETRY_MIN);
+         printf("%s\n                           ", buffer);
+         iw_print_retry_value(buffer, range.max_r_time, flags | IW_RETRY_MAX);
+         printf("%s\n          ", buffer);
          
        }
 
       /* Get current retry settings */
-      strcpy(wrq.ifr_name, ifname);
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
       wrq.u.retry.flags = 0;
       if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0)
        {
@@ -722,7 +572,11 @@ print_retry_info(int               skfd,
 
              /* Let's check the value and its type */
              if(wrq.u.retry.flags & IW_RETRY_TYPE)
-               print_retry_value(stdout, wrq.u.retry.value, wrq.u.retry.flags);
+               {
+                 iw_print_retry_value(buffer,
+                                      wrq.u.retry.value, wrq.u.retry.flags);
+                 printf("%s", buffer);
+               }
 
              /* If we have been returned a MIN value, ask for the MAX */
              if(flags & IW_RETRY_MIN)
@@ -732,7 +586,7 @@ print_retry_info(int                skfd,
                retry_mask = IW_RETRY_MIN;
              /* If we have something to ask for... */
              if(retry_mask)
-               get_retry_value(skfd, ifname, &wrq, retry_mask);
+               get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
 
              /* And if we have both a period and a timeout, ask the other */
              retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
@@ -740,7 +594,8 @@ print_retry_info(int                skfd,
              if(retry_mask)
                {
                  int   base_mask = retry_mask;
-                 flags = get_retry_value(skfd, ifname, &wrq, retry_mask);
+                 flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
+                                         buffer);
                  retry_mask = 0;
 
                  /* If we have been returned a MIN value, ask for the MAX */
@@ -751,7 +606,7 @@ print_retry_info(int                skfd,
                    retry_mask = IW_RETRY_MIN | base_mask;
                  /* If we have something to ask for... */
                  if(retry_mask)
-                   get_retry_value(skfd, ifname, &wrq, retry_mask);
+                   get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
                }
            }
        }
@@ -759,12 +614,19 @@ print_retry_info(int              skfd,
     }
 }
 
+#endif /* WIRELESS_EXT > 10 */
+
+/************************* COMMON UTILITIES *************************/
+/*
+ * This section was written by Michael Tokarev <mjt@tls.msk.ru>
+ */
+
 /*------------------------------------------------------------------*/
 /*
- * Get retry info on all devices and print it on the screen
+ * Enumerate devices and call specified routine
  */
 static void
-print_retry_devices(int                skfd)
+enum_devices(int skfd, void (*fn)(int skfd, char *ifname))
 {
   char         buff[1024];
   struct ifconf ifc;
@@ -783,9 +645,42 @@ print_retry_devices(int            skfd)
 
   /* Print them */
   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
-    print_retry_info(skfd, ifr->ifr_name);
+    (*fn)(skfd, ifr->ifr_name);
+}
+
+/* command list */
+typedef struct iwlist_entry {
+  const char *cmd;
+  void (*fn)(int skfd, char *ifname);
+} 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 },
+  { "encription",   print_keys_info },
+  { "key",          print_keys_info },
+  { "power",        print_pm_info },
+  { "txpower",      print_txpower_info },
+#if WIRELESS_EXT > 10
+  { "retry",        print_retry_info },
+#endif
+  { NULL, 0 },
+};
+
+/* Display help */
+static void usage(FILE *f)
+{
+  int i;
+  for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
+    fprintf(f, "%s [interface] %s\n",
+            i ? "             " :
+                "Usage: iwlist",
+            iwlist_cmds[i].cmd);
 }
-#endif /* WIRELESS_EXT > 10 */
 
 /******************************* MAIN ********************************/
 
@@ -798,154 +693,78 @@ main(int argc,
      char **   argv)
 {
   int skfd = -1;               /* generic raw socket desc.     */
+  char *dev;                   /* device name                  */
+  char *cmd;                   /* command                      */
+  int i;
 
-  /* Create a channel to the NET kernel. */
-  if((skfd = sockets_open()) < 0)
-    {
-      perror("socket");
-      exit(-1);
-    }
-
-  /* Help */
-  if((argc == 1) || (argc > 3) ||
-     (!strncmp(argv[1], "-h", 9)) || (!strcmp(argv[1], "--help")))
-    {
-      fprintf(stderr, "Usage: iwlist [interface] freq\n");
-      fprintf(stderr, "              [interface] ap\n");
-      fprintf(stderr, "              [interface] bitrate\n");
-      fprintf(stderr, "              [interface] keys\n");
-      fprintf(stderr, "              [interface] power\n");
-      fprintf(stderr, "              [interface] txpower\n");
-      fprintf(stderr, "              [interface] retries\n");
-      close(skfd);
-      exit(0);
-    }
-
-  /* Frequency list */
-  if((!strncmp(argv[1], "freq", 4)) ||
-     (!strncmp(argv[1], "channel", 7)))
-    {
-      print_freq_devices(skfd);
-      close(skfd);
-      exit(0);
-    }
-
-  /* Access Point list */
-  if(!strcasecmp(argv[1], "ap"))
-    {
-      print_ap_devices(skfd);
-      close(skfd);
-      exit(0);
-    }
-
-  /* Bit-rate list */
-  if((!strncmp(argv[1], "bit", 3)) ||
-     (!strcmp(argv[1], "rate")))
-    {
-      print_bitrate_devices(skfd);
-      close(skfd);
-      exit(0);
-    }
-
-  /* Encryption key list */
-  if((!strncmp(argv[1], "enc", 3)) ||
-     (!strncmp(argv[1], "key", 3)))
-    {
-      print_keys_devices(skfd);
-      close(skfd);
-      exit(0);
-    }
-
-  /* Power Management list */
-  if(!strncmp(argv[1], "power", 3))
-    {
-      print_pm_devices(skfd);
-      close(skfd);
-      exit(0);
-    }
-
-  /* Transmit Power list */
-  if(!strncmp(argv[1], "txpower", 3))
-    {
-      print_txpower_devices(skfd);
-      close(skfd);
-      exit(0);
-    }
-
-#if WIRELESS_EXT > 10
-  /* Retry limit/lifetime */
-  if(!strncmp(argv[1], "retry", 4))
-    {
-      print_retry_devices(skfd);
-      close(skfd);
-      exit(0);
-    }
-#endif
-
-  /* Special cases take two... */
-  /* Frequency list */
-  if((!strncmp(argv[2], "freq", 4)) ||
-     (!strncmp(argv[2], "channel", 7)))
-    {
-      print_freq_info(skfd, argv[1]);
-      close(skfd);
-      exit(0);
-    }
-
-  /* Access Point  list */
-  if(!strcasecmp(argv[2], "ap"))
+  if(argc == 1 || argc > 3)
     {
-      print_ap_info(skfd, argv[1]);
-      close(skfd);
-      exit(0);
+      usage(stderr);
+      return 1;
     }
-
-  /* Bit-rate list */
-  if((!strncmp(argv[2], "bit", 3)) ||
-     (!strcmp(argv[2], "rate")))
+  if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
     {
-      print_bitrate_info(skfd, argv[1]);
-      close(skfd);
-      exit(0);
+      usage(stdout);
+      return 0;
     }
-
-  /* Encryption key list */
-  if((!strncmp(argv[2], "enc", 3)) ||
-     (!strncmp(argv[2], "key", 3)))
+  if (argc == 2)
     {
-      print_keys_info(skfd, argv[1]);
-      close(skfd);
-      exit(0);
+      cmd = argv[1];
+      dev = NULL;
     }
-
-  /* Power Management list */
-  if(!strncmp(argv[2], "power", 3))
+  else
     {
-      print_pm_info(skfd, argv[1]);
-      close(skfd);
-      exit(0);
-    }
+      cmd = argv[2];
+      dev = argv[1];
+    }
+
+  /* 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;
+  }
 
-  /* Transmit Power list */
-  if(!strncmp(argv[2], "txpower", 3))
+  /* Create a channel to the NET kernel. */
+  if((skfd = iw_sockets_open()) < 0)
     {
-      print_txpower_info(skfd, argv[1]);
-      close(skfd);
-      exit(0);
+      perror("socket");
+      return -1;
     }
 
-#if WIRELESS_EXT > 10
-  /* Retry limit/lifetime */
-  if(!strncmp(argv[2], "retry", 4))
-    {
-      print_retry_info(skfd, argv[1]);
-      close(skfd);
-      exit(0);
-    }
-#endif
+  /* do the actual work */
+  if (dev)
+    (*iwlist_cmds[i].fn)(skfd, dev);
+  else
+    enum_devices(skfd, iwlist_cmds[i].fn);
 
   /* Close the socket. */
   close(skfd);
 
-  return(1);
+  return 0;
 }
index de98613..65a0aee 100644 (file)
@@ -10,7 +10,7 @@
  * This file is released under the GPL license.
  */
 
-#include "iwcommon.h"          /* Header */
+#include "iwlib.h"             /* Header */
 
 /************************* MISC SUBROUTINES **************************/
 
@@ -24,7 +24,6 @@ iw_usage(void)
   fprintf(stderr, "Usage: iwpriv interface [private-command [private-arguments]]\n");
   fprintf(stderr, "              interface [roam {on|off}]\n");
   fprintf(stderr, "              interface [port {ad-hoc|managed|N}]\n");
-  exit(1);
 }
 
 /************************ GENERIC FUNCTIONS *************************/
@@ -41,10 +40,10 @@ print_priv_info(int         skfd,
   int          k;
   iwprivargs   priv[16];
   int          n;
-  char *       argtype[] = { "    ", "byte", "char", "", "int", "float" };
+  char *       argtype[] = { "    ", "byte", "char", "", "int ", "float" };
 
   /* Read the private ioctls */
-  n = get_priv_info(skfd, ifname, priv);
+  n = iw_get_priv_info(skfd, ifname, priv);
 
   /* Is there any ? */
   if(n <= 0)
@@ -115,7 +114,7 @@ set_private(int             skfd,           /* Socket */
   int          number;
 
   /* Read the private ioctls */
-  number = get_priv_info(skfd, ifname, priv);
+  number = iw_get_priv_info(skfd, ifname, priv);
 
   /* Is there any ? */
   if(number <= 0)
@@ -209,7 +208,7 @@ set_private(int             skfd,           /* Socket */
   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
 
   if((priv[k].set_args & IW_PRIV_SIZE_FIXED) &&
-     (byte_size(priv[k].set_args) < IFNAMSIZ))
+     (iw_byte_size(priv[k].set_args) < IFNAMSIZ))
     memcpy(wrq.u.name, buffer, IFNAMSIZ);
   else
     {
@@ -235,7 +234,7 @@ set_private(int             skfd,           /* Socket */
       printf("%-8.8s  %s:", ifname, priv[k].name);
 
       if((priv[k].get_args & IW_PRIV_SIZE_FIXED) &&
-        (byte_size(priv[k].get_args) < IFNAMSIZ))
+        (iw_byte_size(priv[k].get_args) < IFNAMSIZ))
        {
          memcpy(buffer, wrq.u.name, IFNAMSIZ);
          n = priv[k].get_args & IW_PRIV_SIZE_MASK;
@@ -301,7 +300,7 @@ set_roaming(int             skfd,           /* Socket */
                                           change roam states */
 
   /* Read the private ioctls */
-  number = get_priv_info(skfd, ifname, priv);
+  number = iw_get_priv_info(skfd, ifname, priv);
 
   /* Is there any ? */
   if(number <= 0)
@@ -313,7 +312,10 @@ set_roaming(int            skfd,           /* Socket */
     }
 
   if(count != 1)
-    iw_usage();
+    {
+      iw_usage();
+      return(-1);
+    }
 
   if(!strcasecmp(args[i], "on"))
     {
@@ -363,12 +365,11 @@ set_roaming(int           skfd,           /* Socket */
       if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
        {
          fprintf(stderr, "Roaming support is broken.\n");
-         exit(0);
+         return(-1);
        }
     }
-  i++;
 
-  return(i);
+  return(0);
 }
 
 /*------------------------------------------------------------------*/
@@ -391,7 +392,7 @@ port_type(int               skfd,           /* Socket */
   char *       modes[] = { "invalid", "managed (BSS)", "reserved", "ad-hoc" };
 
   /* Read the private ioctls */
-  number = get_priv_info(skfd, ifname, priv);
+  number = iw_get_priv_info(skfd, ifname, priv);
 
   /* Is there any ? */
   if(number <= 0)
@@ -431,7 +432,10 @@ port_type(int              skfd,           /* Socket */
     }
 
   if(count != 1)
-    iw_usage();
+    {
+      iw_usage();
+      return(-1);
+    }
 
   /* Read it */
   /* As a string... */
@@ -443,7 +447,10 @@ port_type(int              skfd,           /* Socket */
   else
     /* ...or as an integer */
     if(sscanf(args[i], "%d", (int *) &ptype) != 1)
-      iw_usage();
+      {
+       iw_usage();
+       return(-1);
+      }
   
   k = -1;
   while((++k < number) && strcmp(priv[k].name, "sport_type") &&
@@ -460,11 +467,10 @@ port_type(int             skfd,           /* Socket */
   if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
     {
       fprintf(stderr, "Invalid port type (or setting not allowed)\n");
-      exit(0);
+      return(-1);
     }
 
-  i++;
-  return(i);
+  return(0);
 }
 
 /******************************* MAIN ********************************/
@@ -481,10 +487,10 @@ main(int  argc,
   int goterr = 0;
 
   /* Create a channel to the NET kernel. */
-  if((skfd = sockets_open()) < 0)
+  if((skfd = iw_sockets_open()) < 0)
     {
       perror("socket");
-      exit(-1);
+      return(-1);
     }
 
   /* No argument : show the list of all device + info */
@@ -492,7 +498,7 @@ main(int    argc,
     {
       print_priv_devices(skfd);
       close(skfd);
-      exit(0);
+      return(0);
     }
 
   /* Special cases take one... */
@@ -502,7 +508,7 @@ main(int    argc,
     {
       iw_usage();
       close(skfd);
-      exit(0);
+      return(0);
     }
 
   /* The device name must be the first argument */
@@ -511,7 +517,7 @@ main(int    argc,
     {
       print_priv_info(skfd, argv[1]);
       close(skfd);
-      exit(0);
+      return(0);
     }
 
   /* Special cases take two... */
@@ -520,7 +526,7 @@ main(int    argc,
     {
       goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]);
       close(skfd);
-      exit(0);
+      return(goterr);
     }
 
   /* Port type */
@@ -528,7 +534,7 @@ main(int    argc,
     {
       goterr = port_type(skfd, argv + 3, argc - 3, argv[1]);
       close(skfd);
-      exit(0);
+      return(goterr);
     }
 
   /* Otherwise, it's a private ioctl */
@@ -537,5 +543,5 @@ main(int    argc,
   /* Close the socket. */
   close(skfd);
 
-  return(1);
+  return(goterr);
 }
index ead9a62..cd41ccd 100644 (file)
@@ -9,7 +9,7 @@
  * This file is released under the GPL license.
  */
 
-#include "iwcommon.h"          /* Header */
+#include "iwlib.h"             /* Header */
 
 /************************* DISPLAY ROUTINES **************************/
 
@@ -24,6 +24,7 @@ print_spy_info(int    skfd,
   struct iwreq         wrq;
   char         buffer[(sizeof(struct iw_quality) +
                        sizeof(struct sockaddr)) * IW_MAX_SPY];
+  char         temp[128];
   struct sockaddr      hwa[IW_MAX_SPY];
   struct iw_quality    qual[IW_MAX_SPY];
   iwrange      range;
@@ -48,14 +49,14 @@ print_spy_info(int  skfd,
 
 
   /* Check if we have valid address types */
-  if(check_addr_type(skfd, ifname) < 0)
+  if(iw_check_addr_type(skfd, ifname) < 0)
     {
       fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n\n", ifname);
       return;
     }
 
   /* Get range info if we can */
-  if(get_range_info(skfd, ifname, &(range)) >= 0)
+  if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
     has_range = 1;
 
   /* Display it */
@@ -72,9 +73,18 @@ print_spy_info(int   skfd,
   for(i = 0; i < n; i++)
     {
       /* Print stats for each address */
-      printf("    %s : ", pr_ether(hwa[i].sa_data));
-      print_stats(stdout, &qual[i], &range, has_range);
+      printf("    %s : ", iw_pr_ether(temp, hwa[i].sa_data));
+      iw_print_stats(temp, &qual[i], &range, has_range);
+      printf("%s\n", temp);
     }
+#if WIRELESS_EXT > 11
+  if((n > 0) && (has_range))
+    {
+      iw_print_stats(temp, &range.avg_qual, &range, has_range);
+      printf("    typical/average   : %s\n", temp);
+    }
+#endif /* WIRELESS_EXT > 11 */
+
   printf("\n");
 }
 
@@ -127,7 +137,7 @@ set_spy_info(int            skfd,           /* The socket */
   nbr = 0;     /* Number of args readen so far */
 
   /* Check if we have valid address types */
-  if(check_addr_type(skfd, ifname) < 0)
+  if(iw_check_addr_type(skfd, ifname) < 0)
     {
       fprintf(stderr, "%-8.8s  Interface doesn't support MAC & IP addresses\n", ifname);
       return(-1);
@@ -164,7 +174,7 @@ set_spy_info(int            skfd,           /* The socket */
   /* Read other args on command line */
   while((i < count) && (nbr < IW_MAX_SPY))
     {
-      if(in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
+      if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
        continue;
       nbr++;
     }
@@ -173,7 +183,7 @@ set_spy_info(int            skfd,           /* The socket */
   if((nbr == 0) && strcmp(args[0], "off"))
     {
       fprintf(stderr, "No valid addresses found : exiting...\n");
-      exit(0);
+      return(-1);
     }
 
   /* Check if there is some remaining arguments */
@@ -211,10 +221,10 @@ main(int  argc,
   int goterr = 0;
 
   /* Create a channel to the NET kernel. */
-  if((skfd = sockets_open()) < 0)
+  if((skfd = iw_sockets_open()) < 0)
     {
       perror("socket");
-      exit(-1);
+      return(-1);
     }
 
   /* No argument : show the list of all device + info */
@@ -222,7 +232,7 @@ main(int    argc,
     {
       print_spy_devices(skfd);
       close(skfd);
-      exit(0);
+      return(0);
     }
 
   /* Special cases take one... */
@@ -231,10 +241,8 @@ main(int   argc,
      (!strcmp(argv[1], "--help")))
     {
       fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n");
-      fprintf(stderr, "             interface [freq]\n");
-      fprintf(stderr, "             interface [ap]\n");
       close(skfd);
-      exit(0);
+      return(0);
     }
 
   /* The device name must be the first argument */
@@ -243,7 +251,7 @@ main(int    argc,
     {
       print_spy_info(skfd, argv[1]);
       close(skfd);
-      exit(0);
+      return(0);
     }
 
   /* Otherwise, it's a list of address to set in the spy list */
@@ -252,5 +260,5 @@ main(int    argc,
   /* Close the socket. */
   close(skfd);
 
-  return(1);
+  return(goterr);
 }
diff --git a/wireless_tools/macaddr.c b/wireless_tools/macaddr.c
new file mode 100644 (file)
index 0000000..8c5a93a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *     macaddr
+ *
+ *     Program to return the MAC address of an Ethernet
+ *     adapter.  This was written to help configure the
+ *     adapter based on the MAC address rather than the
+ *     name.
+ *
+ *     Version 1.0     Eric Dittman    2001-10-19
+ *
+ *     This is released unther the GPL license.
+ */
+
+#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) {
+
+       int devsock;
+       struct ifreq ifbuffer;
+       int i;
+
+       if (argc != 2) {
+               printf("Usage: macaddr interface\n");
+               exit(1);
+       }
+
+       devsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+       if (devsock == -1) {
+               printf("Failed opening socket\n");
+               exit (1);
+       }
+
+       memset(&ifbuffer, 0, sizeof(ifbuffer));
+       strcpy(ifbuffer.ifr_name, argv[1]);
+       if (ioctl(devsock, SIOCGIFHWADDR, &ifbuffer) == -1) {
+               printf("There is no MACADDR for %s\n", argv[1]);
+               exit(1);
+       }
+       close (devsock);
+
+       for (i = 0; i < IFHWADDRLEN; i++)
+               printf("%02X", (unsigned char) ifbuffer.ifr_ifru.ifru_hwaddr.sa_data[i]);
+       printf("\n");
+
+       exit(0);
+
+}
diff --git a/wireless_tools/wireless.11.h b/wireless_tools/wireless.11.h
new file mode 100644 (file)
index 0000000..fe42409
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version :   11      28.3.01
+ *
+ * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * 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)
+ *
+ * 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... */
+
+/**************************** CONSTANTS ****************************/
+
+/* --------------------------- 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   11
+
+/*
+ * 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)
+ */
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Basic operations */
+#define SIOCSIWNAME    0x8B00          /* Unused */
+#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 */
+
+/* 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 usefull 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 */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST    0x8B00
+#define SIOCIWLAST     0x8B30
+
+/* 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 SIOCDEVPRIVATE -> SIOCDEVPRIVATE + 0xF
+ */
+
+#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 alocated 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 or better...) */
+       __u8            level;          /* signal level */
+       __u8            noise;          /* noise level */
+       __u8            updated;        /* Flags to know if updated */
+};
+
+/*
+ *     Packet discarded in the wireless adapter due to
+ *     "wireless" specific problems...
+ */
+struct iw_discarded
+{
+       __u32           nwid;           /* Wrong nwid */
+       __u32           code;           /* Unable to code/decode */
+       __u32           misc;           /* Others cases */
+};
+
+/* ------------------------ 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 */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ *
+ * Note that it should fit on the same memory footprint !
+ * You should check this when increasing the above structures (16 octets)
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ */
+struct iwreq 
+{
+       union
+       {
+               char    ifrn_name[IFNAMSIZ];    /* if name, e.g. "eth0" */
+       } ifr_ifrn;
+
+       /* Data part */
+       union
+       {
+               /* 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 */
+       }       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 */
+};
+
+/*
+ * 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 */
index fe42409..4183d4a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :   11      28.3.01
+ * Version :   12      5.10.01
  *
  * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  */
@@ -63,7 +63,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT   11
+#define WIRELESS_EXT   12
 
 /*
  * Changes :
  * ----------
  *     - 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)
  */
 
 /* -------------------------- IOCTL LIST -------------------------- */
 #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 */
  * The "flags" member indicate if the ESSID is active or not (promiscuous).
  */
 
-/* Other parameters usefull in 802.11 and some other devices */
+/* 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 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 know 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     0x8B30
+#define SIOCIWLAST     SIOCIWLASTPRIV          /* 0x8BFF */
 
 /* Even : get (world access), odd : set (root access) */
 #define IW_IS_SET(cmd) (!((cmd) & 0x1))
 /*
  * 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 SIOCDEVPRIVATE -> SIOCDEVPRIVATE + 0xF
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
  */
 
 #define IW_PRIV_TYPE_MASK      0x7000  /* Type of arguments */
@@ -305,7 +336,7 @@ struct      iw_param
 
 /*
  *     For all data larger than 16 octets, we need to use a
- *     pointer to memory alocated in user space.
+ *     pointer to memory allocated in user space.
  */
 struct iw_point
 {
@@ -334,23 +365,38 @@ struct    iw_freq
  */
 struct iw_quality
 {
-       __u8            qual;           /* link quality (%retries, SNR or better...) */
-       __u8            level;          /* signal level */
-       __u8            noise;          /* noise level */
+       __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;           /* Wrong nwid */
-       __u32           code;           /* Unable to code/decode */
+       __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)
@@ -363,6 +409,7 @@ struct      iw_statistics
        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 ------------------------ */
@@ -493,6 +540,19 @@ struct     iw_range
        __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...
+        */
 };
 
 /*