OSDN Git Service

v27
authorchris-kirby <chris.kirby@hpe.com>
Tue, 11 Oct 2016 21:10:33 +0000 (15:10 -0600)
committerchris-kirby <chris.kirby@hpe.com>
Tue, 11 Oct 2016 21:10:33 +0000 (15:10 -0600)
36 files changed:
wireless_tools/CHANGELOG.h
wireless_tools/DISTRIBUTIONS.txt
wireless_tools/HOTPLUG.txt [new file with mode: 0644]
wireless_tools/INSTALL
wireless_tools/Makefile
wireless_tools/README
wireless_tools/README.fr [new file with mode: 0644]
wireless_tools/fr/ifrename.8 [new file with mode: 0644]
wireless_tools/fr/iftab.5 [new file with mode: 0644]
wireless_tools/fr/iwconfig.8 [new file with mode: 0644]
wireless_tools/fr/iwevent.8 [new file with mode: 0644]
wireless_tools/fr/iwgetid.8 [new file with mode: 0644]
wireless_tools/fr/iwlist.8 [new file with mode: 0644]
wireless_tools/fr/iwpriv.8 [new file with mode: 0644]
wireless_tools/fr/iwspy.8 [new file with mode: 0644]
wireless_tools/fr/wireless.7 [new file with mode: 0644]
wireless_tools/ifrename.8 [new file with mode: 0644]
wireless_tools/ifrename.c [new file with mode: 0644]
wireless_tools/iftab.5 [new file with mode: 0644]
wireless_tools/iwconfig.8
wireless_tools/iwconfig.c
wireless_tools/iwevent.8
wireless_tools/iwevent.c
wireless_tools/iwgetid.8
wireless_tools/iwgetid.c
wireless_tools/iwlib.c
wireless_tools/iwlib.h
wireless_tools/iwlist.8
wireless_tools/iwlist.c
wireless_tools/iwpriv.c
wireless_tools/iwredir.8 [deleted file]
wireless_tools/iwredir.c [deleted file]
wireless_tools/iwspy.c
wireless_tools/wireless.17.h [new file with mode: 0644]
wireless_tools/wireless.7
wireless_tools/wireless.h [deleted file]

index 92d9cd9..9fbbd36 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Wireless Tools
  *
 /*
  *     Wireless Tools
  *
- *             Jean II - HPLB 97->99 - HPL 99->02
+ *             Jean II - HPLB 97->99 - HPL 99->04
  *
  * The changelog...
  *
  *
  * The changelog...
  *
  *     o Don't cast "int power" to unsigned long in sscanf [iwconfig]
  *             (From Pavel Roskin <proski@gnu.org>)
  *     o Add $(LDFLAGS) for final linking [Makefile]
  *     o Don't cast "int power" to unsigned long in sscanf [iwconfig]
  *             (From Pavel Roskin <proski@gnu.org>)
  *     o Add $(LDFLAGS) for final linking [Makefile]
+ *
+ * wireless 27 :
+ * -----------
+ *     o Add 'sed' magic to automatically get WT/WE versions [Makefile]
+ *     o Change soname of iwlib to libiwWE.so.WT [Makefile]
+ *             Now dynamicaly linked versioned install can work
+ *     o Default to dynamic build, don't build static lib [Makefile]
+ *     o Update installation instructions [INSTALL]
+ *     o fflush(stdout), so that redirect to file/pipe works [iwevent]
+ *             (From Pavel Roskin <proski@gnu.org>)
+ *     o Display properly interface name larger than 8 char [all]
+ *     ---
+ *     o Implement auto/fixed frequencies [iwconfig]
+ *             (From Pavel Roskin <proski@gnu.org>)
+ *     o Don't fail is ldconfig fails [Makefile]
+ *     ---
+ *     o Fix one forgotten strcpy(ifname) -> strncpy change [iwconfig]
+ *     o Fix all dangerous sprintf, replace with snprintf [iwlib]
+ *     o Change iw_print_xxx() API to take buffer length [iwlib]
+ *     ---
+ *     o "iwspy ethX +" did not work, fix wrq.u.data.length [iwspy]
+ *     o Fix stupid bug in displaying link/ap/cell stats [iwspy]
+ *     o Fix display of fixed length char private args [iwpriv]
+ *     o Add raw output for shell scripts, options -r [iwgetid]
+ *     o Tweak scheme output for freq and mode [iwgetid]
+ *             (From Andreas Mohr)
+ *     o Spelling fixes in README and man page
+ *     ---
+ *     o Add definitions for older version of W-Ext [iwlib]
+ *     o Always force compile with latest local version of wext [Makefile]
+ *     o Change soname of iwlib back to libiw.so.WT [Makefile]
+ *     o Get rid of redirector and "make vinstall" [Makefile/iwredir]
+ *     o Convert any struct iw_range to latest version [iwlib]
+ *     o Change run-time version warning to reflect new reality [iwlib]
+ *     o Remove compile-time version warning [iwlib]
+ *     o Add iw_get_kernel_we_version() to guess kernel WE version [iwlib]
+ *     o Remove all #ifdef WIRELESS_EXT, use dynamic iwrange version [all]
+ *     o Get/display wireless stats based on iwrange version [iwlib]
+ *     o Get power and retry settings based on iwrange version [iwconfig]
+ *     o Display power and retry settings based on iwrange version [iwlist]
+ *     o Optimise use of iwrange : read on demand [iwevent]
+ *     ---
+ *     o #include <wireless.h>, instead of using a #define [iwlib.h]
+ *     o Copy latest wireless.XX.h as wireless.h and install it [Makefile]
+ *     ---
+ *     o Fix various iwlist retry display bugs [iwlist]
+ *     o Fix dynamic link to libiw back to be libiw.so (doh !) [Makefile]
+ *     ---
+ *     o Trivial cleanups and docs updates
+ *     ---
+ *     o Implement "iwconfig XXX txpower on" and fix "fixed" [iwconfig]
+ *     o Always properly initialise sanlen before recvfrom() [iwevent]
+ *     o Zero buffer so we don't print garbage after essid [iwgetid]
+ *     o Document that 00:00:00:00:00:00 == no association [iwconfig.8]
+ *             (From Guus Sliepen <guus@sliepen.eu.org>)
+ *     o Fix doc typo : ad_hoc => ad-hoc [wireless.7/DISTRIBUTIONS.txt]
+ *     ---
+ *             (From vda <vda@port.imtp.ilyichevsk.odessa.ua>)
+ *     o Accept arbitrary number of private definitions [iwlib/iwpriv]
+ *     ---
+ *     o Added Hotplug documentation [HOTPLUG.txt]
+ *     o Add dependancies (gcc way), remove makedepend [Makefile]
+ *             (From Maxime Charpenne <maxime.charpenne@free.fr>)
+ *     o Traduction en francais des pages manuel [fr/*]
+ *     o Fix some incorrect/ambiguous sentences [iwconfig.8/iwevent.8]
+ *             (From Joshua Kwan <joshk@triplehelix.org>)
+ *     o Add 'const' qualifier to iwlib API [iwlib.c/iwlib.h]
+ *             (From Joey Hess <joey@dragon.kitenet.net>)
+ *     o Add Debian schemes scripts [debian/ifscheme*]
+ *     ---
+ *     o Add 'ifrename', complete rewrite of nameif [ifrename]
+ *     o Update documentation about ifrename [HOTPLUG.txt]
+ *             (From Joshua Kwan <joshk@triplehelix.org>)
+ *     o Fix disabling of key/enc with iw_set_basic_config() & WE<13 [iwlib.c]
+ *     ---
+ *     o Various bug fixes and improvements [ifrename]
+ *     ---
+ *     o Man pages for ifrename [ifrename.8/iftab.5]
+ *     o Update hotplug/ifrename documentation [HOTPLUG.txt]
+ *     ---
+ *     o Read configuration from stdin [ifrename]
+ *             (From Thomas Hood <jdthood@yahoo.co.uk>)
+ *     o Spell check and updated man page [wireless.7]
+ *             (From Pavel Roskin <proski@gnu.org>)
+ *     o Update and spellcheck documentation [HOTPLUG.txt]
+ *     ---
+ *     o Spin-off 'ifscheme' in a separate package to please Guus Sliepen
+ *     o Update documentation on 'ifscheme' [DISTRIBUTIONS.txt/README]
+ *             (From dann frazier <dannf@debian.org>)
+ *     o Spell check and updated man page [iwlist.8]
+ *     ---
+ *     o Cache interface static data (ifname/iwrange) [iwevent.c]
+ *     ---
+ *     o Change the policy to delete entry from cache [iwevent.c]
+ *     o If no TxPower in iwrange, still print current TxPower [iwlist.c]
+ *     o Use iw_get_basic_config() in iwconfig, bloat-- [iwconfig.c/iwlib.h]
+ *     ---
+ *             (From Pavel Roskin <proski@gnu.org>)
+ *     o Fix mode boundary checking in iw_get_basic_config() [iwlib.c]
+ *     ---
+ *     o Improved priv documentation [iwpriv.c]
+ *             (From Pavel Roskin <proski@gnu.org>)
+ *     o Fix token index bug : allow zero args [iwpriv.c]
+ *     o Grammar fixes in priv documentation [iwpriv.c]
+ *     ---
+ *     o Make iw_protocol_compare() smarter [iwlib.c]
+ *     o Display freq->channel conversion in scan results [iwlist]
+ *     o Display freq->channel conversion in events [iwevent]
+ *     o Interface name takeover support [ifrename]
+ *     o Update docu for Debian Sarge, various improvements [HOTPLUG.txt]
+ *     o Set wireless parameters in the proper order [iwlib]
+ *     ---
+ *             (Suggested by Pavel Roskin <proski@gnu.org>)
+ *     o Be less dramatic is driver doesn't export txpower info [iwlist]
+ *     o Be less dramatic is driver doesn't export bitrate info [iwlist]
+ *     o Use 'updated' bits to disable printing some qual [iwlib]
+ *     o Change the way we show 'updated' bits -> '=' vs. ':' [iwlib]
+ *     o Cosmetic update to channel display [iwlist/iwevent]
+ *     ---
+ *     o Easy scanning API (blocking & non-blocking) [iwlib]
+ *     o Add channel only support to iwgetid [iwgetid]
+ *     o Compile iwgetid with iwlib for above [Makefile/iwgetid]
+ *             (From Loic Minier <lool@dooz.org> via Guus Sliepen)
+ *     o Fix french man pages to not use special 'oe' char [fr/*.8]
+ *             (From Thomas Hood <jdthood@yahoo.co.uk>)
+ *     o Use hyphens instead of underscores in Debian docs [*.txt/*.7]
+ *     ---
+ *     o Update for WE-17 (wrq.u.freq.flags, IW_QUAL_*) [all]
+ *     o Use iw_get_ext() instead of ioctl() [iwgetid]
+ *     o Retry getting scan results with larger buffer [iwlist/iwlib]
+ *     o Display wireless event capabilities [iwlist]
+ *     o Add support for relative TxPower (yick !) [iwconfig/iwlist]
+ *     o Create iw_print_txpower() [iwlib]
+ *     o Add "Set" prefix for all SET wireless events [iwevent]
+ *             (Suggested by Pavel Roskin <proski@gnu.org>)
+ *     o Add support for get_freq and get_essid events [iwevent]
+ *     ---
+ *     o Reorganise iw_print_freq() => create iw_print_freq_value() [iwlib]
+ *     o Create iw_channel_to_freq() and use it [iwlib/iwconfig/iwevent]
+ *     o Fixup for WE-18 : Set scan takes an iw_point [iwlist/iwlib]
+ *     o Fixup for WE-19 : Take care of IW_EV_POINT_OFF [iwlib]
+ *     ---
+ *     o Introduces iw_sockets_close() [all]
+ *     o Set proper size on SIOCGIWSTATS requests [iwlib]
+ *     o Use iw_print_freq_value() in iwlist [iwlist]
+ *     o Optimise iw_print_bitrate() [iwlib]
+ *     o Fix wrq.u.data.flags => wrq.u.txpower.flags [iwconfig]
+ *             (From Denis Ovsienko <pilot@altlinux.ru>)
+ *     o Add dry-run support (only print name changes) [ifrename]
+ *     ---
+ *     o Move WE_VERSION/WT_VERSION to iwlib.h [iwlib/Makefile]
+ *     o Add support for new selector pcmciaslot [ifrename]
+ *     o Improve/cleanup DEBUG/verbose output [ifrename]
+ *     o Minor documentation updates [HOTPLUG.txt/DISTRIBUTIONS.txt]
+ *             (From Francesco Potorti` <pot@potorti.it>)
+ *     o Allow iwgetid to accept '-c' options [iwgetid]
+ *             (From Ian Gulliver <ian@penguinhosting.net>)
+ *     o Transform #define DEBUG into verbose command line switch [ifrename]
+ *     ---
+ *             (From Dan Williams <dcbw@redhat.com>)
+ *     o Fix buffer memory leak in scanning [iwlib/iwlist]
+ *     ---
+ *     o Make sure gcc inline stuff properly [iwlib.h]
+ *     o Update Hotplug documentation [HOTPLUG.txt]
+ *     o Add support for new selector firmware [ifrename]
  */
 
 /* ----------------------------- TODO ----------------------------- */
  */
 
 /* ----------------------------- TODO ----------------------------- */
  *     Add scanning command line modifiers
  *     More scan types support
  *
  *     Add scanning command line modifiers
  *     More scan types support
  *
- * iwevent :
- * -------
- *     Make it non root-only
+ * ifrename :
+ * --------
+ *     Link Type should use readable form instead of numeric value
+ *     Support non MAC/Eth addresses ?
  *
  * Doc & man pages :
  * ---------------
  *
  * Doc & man pages :
  * ---------------
index a9b77c2..7ff2e66 100644 (file)
@@ -103,7 +103,7 @@ You can now add extra statements to the iface sections of the files in
 /etc/network/interfaces that are specific for wireless interfaces. They
 are of the form:
 
 /etc/network/interfaces that are specific for wireless interfaces. They
 are of the form:
 
-    wireless_<function> <value>
+    wireless-<function> <value>
 
 Before the interface is brought up, such a statement will result in the
 execution of the following command:
 
 Before the interface is brought up, such a statement will result in the
 execution of the following command:
@@ -117,8 +117,8 @@ iface eth0 inet static
     network 192.168.1.0
     netmask 255.255.255.0
     broadcast 192.168.1.255
     network 192.168.1.0
     netmask 255.255.255.0
     broadcast 192.168.1.255
-    wireless_essid Home
-    wireless_mode ad_hoc
+    wireless-essid Home
+    wireless-mode ad-hoc
 
        The current Debian script support all arguments present in
 wireless.opts apart from Nickname. You can check this in the script
 
        The current Debian script support all arguments present in
 wireless.opts apart from Nickname. You can check this in the script
@@ -135,19 +135,19 @@ do everything pcmcia schemes can do, and more. Here is part of mine:
 
 auto wlan0
 mapping wlan0
 
 auto wlan0
 mapping wlan0
-        script /usr/local/bin/ifscheme
+        script /usr/local/bin/ifscheme-mapping
 
 iface wlan0-home inet static
         address 192.168.1.5
         gateway 192.168.1.1
         netmask 255.255.255.0
 
 iface wlan0-home inet static
         address 192.168.1.5
         gateway 192.168.1.1
         netmask 255.255.255.0
-        wireless_mode ad_hoc
-        wireless_essid wortroot
-        wireless_nick dragon
-        wireless_channel 1
+        wireless-mode ad-hoc
+        wireless-essid wortroot
+        wireless-nick dragon
+        wireless-channel 1
 
 iface wlan0-away inet dhcp
 
 iface wlan0-away inet dhcp
-        wireless_mode managed
+        wireless-mode managed
 
 Now I can type 'ifscheme -s away' when I leave home, rather like
 cardctl scheme.
 
 Now I can type 'ifscheme -s away' when I leave home, rather like
 cardctl scheme.
@@ -171,8 +171,23 @@ ifupdown.
 
                                -----
 
 
                                -----
 
-       You may also want to check ifupdown-roaming :
+               (Contributed by Jean Tourrilhes <jt@hpl.hp.com>)
+       The 'ifscheme' scripts mentionned above are now available in
+Debian Sarge, in the 'ifscheme' package.
+       The MAC address based mapping mentioned above is deprecated,
+you should use 'ifrename' to assign a consistent interface name to
+each of your network interface. This is documented in
+HOTPLUG.txt. This enable the combination of MAC address identification
+of interfaces with scheme multi-configuration.
+
+                               -----
+
+       If you need automatic wireless configuration, you can look at
+the following packages :
+       o ifupdown-roaming :
                http://panopticon.csustan.edu/thood/ifupdown-roaming.html
                http://panopticon.csustan.edu/thood/ifupdown-roaming.html
+       o waproamd
+               http://0pointer.de/lennart/projects/waproamd/
 
 ---------------------------------------------------------------------
 
 
 ---------------------------------------------------------------------
 
@@ -339,13 +354,21 @@ eth0, eth1, ...).
 all of them. The script doing the configuration and where you can
 check the details is :
                /etc/network/network-scripts/ifup-wireless
 all of them. The script doing the configuration and where you can
 check the details is :
                /etc/network/network-scripts/ifup-wireless
-       You will of course need the Wireless Extension package :
+       You will of course need the Wireless Tools package :
                rpm -Uvh wireless-tools-XX-Xmdk.XXX.rpm
 
        Mandrake can also have wireless setting added to its
 Auto-Install procedure :
        http://members.shaw.ca/mandrake/drakx/8.2/HTML/section4-13.html
 
                rpm -Uvh wireless-tools-XX-Xmdk.XXX.rpm
 
        Mandrake can also have wireless setting added to its
 Auto-Install procedure :
        http://members.shaw.ca/mandrake/drakx/8.2/HTML/section4-13.html
 
+                               -----
+
+               (in e-mail from Thierry Vignaud <tvignaud@mandrakesoft.com>)
+       You may use the following tool :
+               o drakconnect
+       You may read the following documentation :
+               o ifcfg
+
 ---------------------------------------------------------------------
 
 
 ---------------------------------------------------------------------
 
 
diff --git a/wireless_tools/HOTPLUG.txt b/wireless_tools/HOTPLUG.txt
new file mode 100644 (file)
index 0000000..12a3d7a
--- /dev/null
@@ -0,0 +1,990 @@
+               Sane Hotplug network interface management
+               -----------------------------------------
+
+INTRODUCTION
+------------
+       In the old day, all Wireless cards were managed by the
+excellent Pcmcia subsystem and its rich configuration scripts, and
+life was happy. Then came the wireless PCI cards, then the wireless
+USB dongles. Some unification was needed, and rather than adapt the
+Pcmcia subsystem for PCI and USB, it was decided to create the much
+simpler Hotplug systems.
+       The USB subsystem already use Hotplug, and the Pcmcia
+subsystem is migrating to it, CardBus cards (32 bits) already use
+Hotplug, whereas Pcmcia cards (16 bits) still use the old Pcmcia
+scripts.
+       The Hotplug system is still in its infancy, but already show
+some good promises. Most users are disapointed at first by its
+apparent lack of features compared to the Pcmcia scripts. In this
+document, we will show how to fully exploit the Hotplug system and try
+to implement the equivalent of all the functionality of the Pcmcia
+scripts.
+
+ASSUMPTIONS
+-----------
+       The target audience of this document is mostly power users and
+distribution maintainers, but it should give enough clues to help
+newbies. You should have read and understood DISTRIBUTIONS.txt. The
+procedures described here are more advanced than the simple
+configuration described in DISTRIBUTIONS.txt.
+       The main focus is of course removable wireless interfaces, but
+we will try to keep things generic and talk of the whole network
+interface management, so this should apply also to built-in Ethernet
+cards.
+
+PROBLEM STATEMENT
+-----------------
+       Let assume a Linux system and two or more network devices,
+Device A and Device B. Those devices may be built-in or removable,
+they may be present or absent from the system at any time, and
+activated in any particular order.
+       The user wants to assign Configuration A to Device A and
+Configuration B to Device B, without the possibility that Device A get
+assigned Configuration B.
+       Different users may have different definition of what is
+Device A. For some, it's a specific instance of a specific hardware,
+for others any hardware that meet some criteria (a wireless card, an
+Ethernet card).
+       The user may also want to have multiple configurations
+depending on various factors (like the old Pcmcia schemes). Device A
+may get Configuration A1 or Configuration A2 depending on those
+factors.
+       By default, all network interfaces are created using a default
+interface name (starting at "eth0" and going up). I call that problem
+"all my cards are eth0". And by default, "eth0" point to a single
+fixed configuration in the configuration database. Clearly, this won't
+satisfy our requirements.
+
+EXAMPLE SYSTEM
+--------------
+       The distribution I use is Debian 3.0, and some parts will be
+specific to it. However, it should be easy to translate to other
+distributions and I welcome additions to this document.
+
+       The example system is as follows :
+               o Linux 2.6.X SMP kernel with hotplug support
+               o Fully modular system (all network drivers as modules)
+               o PCI Ethernet card : AMD PCnet LANCE (pcnet32 - eth4)
+               o PCI Ethernet card : HP 100VG J2585B (hp100 - eth2)
+               o ISA Wireless card : Old AT&T Wavelan (wavelan - eth3)
+               o ISA-Pcmcia bridge : VADEM VG-469 (i82365 - slot 0)
+               o PCI-CardBus bridge : Ricoh RL5c475 (yenta_socket - slot 2)
+               o Pcmcia 802.11 card : Aironet 350 (airo_cs - eth0)
+               o Pcmcia 802.11 card : Lucent Orinoco (orinoco_cs - eth0)
+               o CardBus 802.11 card : SMC 2835W (prism54 - prism0)
+
+       This system just happen to be my Linux development box, and
+has enough interfaces to make it interesting. All the example I quote
+in this document are extracted from this fully working system.
+
+BASIC CONCEPTS
+--------------
+       Most of the concept and tricks presented here are not really
+new, the main contribution is to integrate them together and make them
+work.
+
+       1) Removable network interfaces are managed by Hotplug
+(Pcmcia, CardBus, USB...). We can't assume that those interfaces are
+always present in this system and available at boot time (Pcmcia cards
+are not made to be soldered in the Pcmcia slot), therefore Hotplug is
+the only way to go.
+       2) Built-in PCI and ISA cards are managed by the init scripts,
+like they have always been. The ISA subsystem will never have Hotplug
+support, and hotplug is not necessary for PCI cards.
+       3) Built-in devices that are disable most of the time should
+be enabled manually.
+       4) (1), (2) and (3) must be compatible on the same system and
+play nice with each other.
+
+       5) A well defined and consistent network interface name is
+assigned to each network hardware interface using 'ifrename'. Device A
+is always named 'ethA' (or whatever name you like such as
+'mynetworkcard').
+       6) No interface is called 'eth0' (or 'wlan0'). Any unknown
+device would be 'eth0', thefore known device should avoid using it
+because it might be already taken.
+       7) Multiple configurations for a single interface (schemes)
+are managed by the ifup/ifdown subsystem.
+
+CONFIGURATION FROM INIT SCRIPTS
+-------------------------------
+       It may seems paradoxal, but before setting up Hotplug, we need
+to make sure that the initialisation of network cards via init
+scripts is done properly and doesn't get in our way.
+       The configuration of network cards via init scripts is the
+traditional way network is initialised in Linux. The advantage of this
+method is that it's very well documented and understood, and has not
+changed much over the years. Unfortunately, it doesn't support
+properly removable cards.
+       The init scripts perform the following 3 functions in that
+order :
+               1) load necessary driver modules
+               2) rename interface to name chosen by the user
+               3) configure those interfaces
+
+       1) Applicability
+       ----------------
+       Configuration from init scripts is applicable to any built-in
+network interface (ISA, PCI...), i.e. interfaces availalble at boot
+time and that will never be removed from the system.
+       The Hotplug subsystem has also the ability to configure some
+of the built-in network interfaces, such as PCI cards. However, there
+is a class of devices that will never have Hotplug support, such as
+ISA and EISA cards, and for those Hotplug won't work.
+       The advantage of using the init script method is that you are
+probably already familiar with it and you have the ability to select
+which interfaces should be configured at boot and which interface
+should only be enabled manually (whereas Hotplug just configures
+everything).
+
+       2) Loading driver modules (if/as needed)
+       ----------------------------------------
+       Most distributions build the kernel drivers as modules. This
+modular setup allow to minimise the amount of memory used by the
+system and the flexible loading/unloading of drivers.
+       You can also compile your kernel with static drivers
+(non-modular). In that case, the driver will always be available in
+your kernel, you don't need to configure the module subsystem, so you
+can skip directly to the next section.
+
+       There are 3 alternatives to manage device drivers as
+modules. Some distribution have explicit list of modules that are
+loaded at boot time, if you want to use that feature you need to check
+your distribution. Some system, such as hotplug or kudzu, can scan the
+various buses of the PC and load the appropriate drivers, and this is
+mostly configuration-free, but may not support all devices. The module
+subsystem also allow to load modules 'on-demand'.
+
+       I personally prefer to use the 'on-demand' feature of the
+module subsystem has, as it allows you to not have to specify the list
+of modules that need to be loaded, and only modules really necessary
+are loaded which save kernel memory. You can also choose which module
+to load when there are multiple altenate modules valid for your
+hardware (which happens quite often).
+
+       With kernel 2.6.X, the module subsystem is configured in
+/etc/modprobe.conf. To configure 'on-demand' module loading, I need to
+add to this file the following lines :
+
+--------- /etc/modprobe.conf ----------------
+# HP 100VG J2585B PCI card
+alias eth2 hp100
+
+# AMD AMD PCnet LANCE PCI card
+alias eth4 pcnet32
+
+# Old AT&T Wavelan ISA card
+alias eth3 wavelan
+options wavelan io=0x390 irq=15
+---------------------------------------------
+
+       Your distribution may already have lines for your interfaces,
+either replace them or make sure they are correct (some distro are
+notorious for picking the wrong driver name). This file also contains
+configuration for lot of other subsystems, obviously you don't want to
+touch that.
+       In this file, you put the name you would like the interface to
+have (we'll fix that in a minute). You note that for modern PCI cards,
+this is much more straightforward than for old ISA cards.
+
+       3) Installing 'ifrename'
+       ------------------------
+       You will need to install ifrename on your system. 'ifrename'
+is part of the Wireless Tools package (version 27 and later) and is a
+complete rewrite of the now obsolete 'nameif'.
+       Some distributions, such as Debian Sarge, offer a specific
+package for 'ifrename', and in this case you should just install this
+package. Other distributions may include ifrename as part of their
+'wireless tools' package (this should be the case for Geentoo and
+Mandrake). Other distributions, such as Debian 3.0, don't include
+ifrename at all, and you should compile yourself a recent version of
+Wireless Tools (v27 or later) and install it.
+
+       In any case, you should verify if 'ifrename' is properly
+installed, and what is the path to call it.
+--------------------------
+> which ifrename
+/sbin/ifrename
+--------------------------
+       Most distributions will install 'ifrename' in '/sbin', while if
+you compile your own wireless tools, it will be in '/usr/local/sbin'.
+
+       4) Making the boot scripts call 'ifrename'
+       ------------------------------------------
+       You need to make sure 'ifrename' is run at boot time. Most
+distributions don't do that yet by default.
+       This is a part that is distribution specific, so you will need
+to look into your init files. It will need to run just before the call
+to 'ifup' or 'ifconfig' command.
+
+       In Debian 3.0, it needs to be run from /etc/init.d/networking,
+which is not the default. The necessary patch is below :
+
+----------------------------------------------------------------
+--- networking-orig     Wed Feb 18 13:56:23 2004
++++ networking  Fri Feb 20 14:51:06 2004
+@@ -120,6 +120,15 @@ case "$1" in
+         doopt syncookies no
+         doopt ip_forward no
++       # Optionally remap interface names based on MAC address.
++       # '/sbin/ifrename' is part of wireless-tools package.
++       # /etc/iftab is currently not created by default. Jean II
++       if [ -x /sbin/ifrename ] && [ -r /etc/iftab ]; then
++           echo -n "Remapping network interfaces name: "
++           ifrename -p
++           echo "done."
++       fi
++
+         echo -n "Configuring network interfaces: "
+         ifup -a
+        echo "done."
+----------------------------------------------------------------
+       Don't forget to set the appropriate path to call ifrename (see
+step (3) above).
+
+       You may want to also set the proper options for ifrename
+(check the man page).
+       The option '-p' enable module autoloading compatibility.
+       The default version of 'ifrename' also includes some specific
+Debian support : using "ifrename -p -d", only the proper modules are
+loaded. If you are using Debian, you should use this option.
+
+       5) Renaming interfaces
+       ----------------------
+       As stated above, we use 'ifrename' to assign names to
+interfaces.
+
+       First, you need to get the MAC address of each of you
+interface. You can read it on the label on the card or display it
+using the 'ifconfig' command. Remember that the interface won't load
+yet with the proper name, so you may need to do a bit looking around :
+
+-----------------------------
+> modprobe pcnet32
+> ifconfig eth0
+eth0      Link encap:Ethernet  HWaddr 00:10:83:34:BA:E5  
+[...]
+-----------------------------
+
+       The configuration of 'ifrename' is simple, you just specify
+which name should be used for each MAC address in the file
+/etc/iftab :
+
+--------- /etc/iftab ------------------------
+# HP 100VG J2585B PCI card
+eth2           mac 08:00:09:*
+
+# Old AT&T Wavelan ISA card
+eth3           mac 08:00:0E:*
+
+# AMD AMD PCnet LANCE PCI card
+eth4           mac 00:10:83:*
+---------------------------------------------
+
+       The '*' in the MAC address is a wildcard and allow me to
+replicate my configuration between multiple identical computers. If
+you have to manage large number of computers (like a rack of server or
+clusters), you may want to look at other selectors offered by
+'ifrename', such as the ability to base interface name on Bus
+Information.
+
+       To test that ifrename works, do the following :
+               o load all your drivers, see section (2)
+               o check /proc/net/dev to see which interface exist
+               o bring all interfaces down : ifconfig ethX down
+               o run ifrename
+               o check each interface with ifconfig
+
+       6) Configuring interfaces
+       -------------------------
+       Most likely, your distribution is already doing this part
+properly. Just assign the proper IP and wireless configuration to each
+of the interface name you have chosen.
+       This part is distribution specific, and I already document it
+in the file DISTRIBUTIONS.txt.
+
+       In Debian, you would need to modify the file
+/etc/network/interfaces like this :
+
+--------- /etc/network/interfaces -----------
+# AMD AMD PCnet LANCE PCI card
+auto eth4
+iface eth4 inet dhcp
+
+# HP 100VG J2585B PCI card
+auto eth2
+iface eth2 inet static
+    address 10.0.0.2
+    network 10.0.0.0
+    netmask 255.255.255.0
+    broadcast 10.0.0.255
+    gateway 10.0.0.1
+---------------------------------------------
+
+       This was the last part. Now, at your next boot, all your
+interfaces should be assigned the proper name and proper
+configuration.
+
+CONFIGURATION VIA HOTPLUG
+-------------------------
+       Dealing with removable interfaces is similar to built-in
+interfaces, the only difference is that we will use the Hotplug
+scripts instead of the init scripts. Another difference is that it
+will require more work on your part because most distributions are not
+fully ready for it.
+
+       1) Applicability
+       ----------------
+       The Hotplug configuration method is the best choice for any
+removable network interface, such as :
+               o Pcmcia (16 bits) network cards
+               o CardBus (32 bits) network cards
+               o USB network dongles
+               o Hot-PCI network cards
+       It may also be used to manage other types of network
+interfaces, although it may not be the best choice for them.
+
+       2) How Hotplug works
+       --------------------
+       Conceptually, Hotplug is very simple. When something
+interesting happens, the Linux kernel generates an Hotplug event. This
+run the proper script from the /etc/hotplug directory.
+       There is 3 types of Hotplug events we care about :
+               o PCI event : a CardBus device is added or removed
+from the system. The script /etc/hotplug/pci.agent is run.
+               o USB event : a USB device is added or removed
+from the system. The script /etc/hotplug/usb.agent is run.
+               o Network event : a network interface is added or
+removed from the system. The script /etc/hotplug/net.agent is run.
+
+       If we insert a CardBus network card in the system, the
+following happens :
+               1) Kernel detects new CardBus device
+               2) Kernel generates PCI Hotplug event
+               3) /etc/hotplug/pci.agent runs, find proper driver module
+               4) /etc/hotplug/pci.agent loads driver module
+               5) Driver module initialises, creates new network device
+               6) Kernel detects new network device
+               7) Kernel generates Network Hotplug event
+               8) /etc/hotplug/net.agent runs, configure network device
+       The sequence of events is similar for removals and USB devices.
+
+       3) Make ifup reentrant
+       ----------------------
+       <Most people should ignore this part>
+       The first problem is that we need to make sure the command
+'ifup' is fully reentrant. If the system has built-in interfaces, the
+'ifup' may reenter itself at boot time :
+               1) Init scripts start running
+               2) Init script calls 'ifup -a' to initialise built-in network
+                       interfaces
+               3) 'ifup' auto-loads driver module for built-in network
+                       interface 'eth4'
+               4) Driver module initialises, creates new network device
+               5) Kernel generates Network hotplug event
+               6) /etc/hotplug/net.agent runs, call 'ifup eth4'
+       You can produce the same reentrancy if want to manually load
+module with the ifup command.
+
+       The default version of 'ifup' for Debian 3.0 is not reentrant and
+may deadlock during boot or if you use it manually. The patch to make
+'ifup' properly reentrant is available here :
+               http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=231197
+       Later version of Debian (Sarge and later) have some workaround
+that prevent deadlock in most case (but not fully eliminate them), so
+for normal use the default 'ifup' should work fine.
+
+       Other distributions have very different version of ifup, and I
+have not tried those (tell me about it).
+
+       4) Installing Hotplug for Debian Sarge (testing/unstable)
+       ---------------------------------------------------------
+       Thanks to the great work of many people, Debian Sarge has all
+the necessary packages and hotplug support, and will work mostly 'out
+of the box'.
+       You will need to install the following packages :
+               o hotplug
+               o ifrename
+
+       While the installation of Hotplug is simple, its configuration
+may seem complex. The current network Hotplug script has 3 modes,
+'all', 'auto' and 'hotplug', however for our purpose they all produce
+the same results when configured. This is controlled by the variable
+NET_AGENT_POLICY in /etc/default/hotplug.
+
+       In the mode "all", all interfaces are processed by
+'ifup'. This will work without further configuration.
+
+       In the mode "auto", only interfaces listed in a auto statement
+in /etc/network/interfaces will be processed by 'ifup'. If you choose
+this mode, you need to put in /etc/network/interfaces a statement auto
+with the complete list of all interfaces.
+--------- /etc/network/interfaces -----------
+# Enable Hotplug support for "auto" mode (Sarge and later)
+auto eth0 eth1 eth2 eth3 eth4 wlan0 wlan1 prism0 prism1 airo0 airo1
+---------------------------------------------
+       Unfortunately, this will make 'ifup' complain at boot time
+that it can't find those interfaces. This is why I don't recommend
+this mode.
+
+       In the mode "hotplug", hotplug network events are ignored by
+ifup by default. To enable them, therefore making this mode equal to
+"all", you will need to add the following lines to
+/etc/network/interfaces :
+--------- /etc/network/interfaces -----------
+# Enable Hotplug support for "hotplug" mode (Sarge and later)
+mapping hotplug
+    script echo
+---------------------------------------------
+
+       5) Installing Hotplug for Debian 3.0
+       ------------------------------------
+       Debian 3.0 doesn't come by default with hotplug, but the
+hotplug package is available as regular Debian package (on the CD or
+downloadable via apt-get), so you can just install that.
+
+       Unfortunately, this version of hotplug is not fully compatible
+with kernel 2.6.X. You will need to do the following modifications to
+the file /etc/hotplug/net.agent.
+
+------- /etc/hotplug/net.agent ------------------
+--- net.agent-d1        Fri Feb 20 18:18:05 2004
++++ net.agent   Fri Feb 20 18:22:50 2004
+@@ -26,7 +26,7 @@ if [ "$INTERFACE" = "" ]; then
+ fi
+ case $ACTION in
+-register)
++add|register)
+     case $INTERFACE in
+        # interfaces that are registered after being "up" (?)
+@@ -52,7 +52,7 @@ register)
+     mesg $1 $ACTION event not handled
+     ;;
+-unregister)
++remove|unregister)
+     # Assume that we want to run ifdown no matter what,  
+     # because it is not going to remove the data from the 
+     # ifstate database otherwise.
+-------------------------------------------------
+
+       Compared to the version in Sarge, this older version of
+hotplug is much more basic, and doesn't have any scanning at boot time
+and doesn't need to be enabled in /etc/network/interfaces.
+
+       6) Installing hotplug, other cases
+       ----------------------------------
+       The canonical version of hotplug is available at :
+               http://linux-hotplug.sourceforge.net/
+
+       Most distributions have various version of hotplug with
+various modifications on top of the canonical version, and chances are
+that the canonical version won't completely work on your system.
+       All these various changing versions make it difficult for me
+to tell what exactly need to be changed in the hotplug scripts to make
+them work.
+
+       Some version of hotplug will do scan at boot time, see section
+(4) for my comments on this.
+
+       My guess is that in a few release, all these problems will
+sort themselves out. Just be patient.
+
+       7) Dealing with 'init' hotplug
+       ------------------------------
+       In addition to the standard kernel Hotplug events, modern
+versions of the Hotplug scripts add init scripts that scan the system
+buses and generate pseudo Hotplug events. For the PCI buses, the
+script /etc/hotplug/pci.rc is run after the boot, for the USB bus,
+/etc/hotplug/usb.rc is run.
+       The end result is that the Hotplug subsystem will also attempt
+to configure built-in devices :
+               1) Kernel boots
+               2) Init runs, start to initialise the OS
+               3) /etc/hotplug/pci.rc runs, generate pseudo Hotplug event
+               4) /etc/hotplug/pci.agent loads driver module
+               5) Driver module initialises, creates new network device
+               6) Kernel generates Network Hotplug event
+               7) /etc/hotplug/net.agent runs, configure network device
+
+       At this point, you realise that at initialisation, both
+Hotplug and the regular init scripts (see "CONFIGURATION FROM INIT
+SCRIPTS") are trying to configure the same devices in parallel. This
+may create problem, and it is totally redundant.
+       Another reason I don't like this mechanism is that it blindly
+attempt to load drivers for all hardware present on the system, and
+don't use the configuration in /etc/modules.conf to select the proper
+driver. It's fairly common to have multiple driver for some hardware,
+and because of Murphy's law, Hotplug will usually load the wrong
+one. It's also fairly common to have hardware on the system that
+doesn't need enabling (for example, the IDE controller on my SCSI
+machine), not loading the driver makes your kernel smaller and boot
+faster.
+       Unfortunately, Hotplug did not provide a simple way to disable
+such a feature. More importantly, there is no way to selectively
+disable it (let say, disabled for network, enabled for sound).
+
+       One way to disable this functionality is to delete or rename
+the files /etc/hotplug/pci.rc and /etc/hotplug/usb.rc.
+
+       8) Making hotplug scripts call ifrename
+       ---------------------------------------
+       The last hotplug step is to make sure that 'ifrename' is run
+by the hotplug subsystem at the right time. As before, we want to run
+it just before calling 'ifup'.
+       The latest version of the hotplug scripts have this
+integrated. However, you need to check that the path they use for
+calling 'ifrename' is the proper one on your system. And, for older
+versions of hotplug scripts, you will need to add this support
+yourself.
+
+       Check the path for ifrename :
+--------------------------
+> which ifrename
+/sbin/ifrename
+--------------------------
+
+       The patch to add 'ifrename' to hotplug looks like :
+
+------- /etc/hotplug/net.agent ------------------
+--- net.agent-s2        Fri Feb 20 17:18:46 2004
++++ net.agent   Fri Feb 20 17:32:43 2004
+@@ -40,6 +40,21 @@ add|register)
+            # we can't do much here without distro-specific knowledge
+            # such as whether/how to invoke DHCP, set up bridging, etc.
++           # Run ifrename as needed - Jean II
++           # Remap interface names based on MAC address. This workaround
++           # the dreaded configuration problem "all my cards are 'eth0'"...
++           # This needs to be done before ifup otherwise ifup will get
++           # confused by the name changed and because iface need to be
++           # down to change its name.
++           if [ -x /sbin/ifrename ] && [ -r /etc/iftab ]; then
++               debug_mesg invoke ifrename for $INTERFACE
++               NEWNAME=`/sbin/ifrename -i $INTERFACE`
++               if [ -n "$NEWNAME" ]; then
++                   debug_mesg iface $INTERFACE is remapped to $NEWNAME
++                   INTERFACE=$NEWNAME
++               fi;
++           fi
++
+            # RedHat and similar
+            export IN_HOTPLUG=1
+            if [ -x /sbin/ifup ]; then
+-------------------------------------------------
+
+       If your hotplug scrips already include ifrename support, you
+should find a section in /etc/hotplug/net.agent looking like the patch
+above. Otherwise, just cut'n'paste the patch above in the right place.
+       The path for 'ifrename' is used twice above, so don't forget
+to modify both occurences...
+
+
+       9) Loading driver modules
+       -------------------------
+       Wow ! The most difficult part is done.
+       In theory, you don't need to do any specific configuration for
+the driver modules to be loaded. The 'pci.agent' and 'usb.agent'
+should load the right driver module for you.
+       Also, you don't need to define aliases in /etc/modprobe.conf,
+it's useless (and may be counter productive).
+
+       If you use driver compiled statically in the kernel, you also
+have nothing to do.
+
+       10) Renaming interfaces
+       -----------------------
+       We still use ifrename to assign names to interfaces. The
+configuration of 'ifrename' is the same. To keep the possibility of
+having multiple wireless cards (one in each CardBus slot), we use
+wildcards in both the MAC address and the name :
+
+--------- /etc/iftab -----------------------
+# SMC 2835W wireless CardBus card
+prism*         mac 00:30:B4:*
+---------------------------------------------
+
+       If you insert two cards, they would be named prism0 and
+prism1. Note that 'name wildcarding' is a feature only available in
+2.6.X, so if you use 2.4.X you will need to be explicit and list each
+card separatly :
+
+--------- /etc/iftab -----------------------
+# SMC 2835W wireless CardBus card
+prism0         mac 00:30:B4:64:27:8B
+prism1         mac 00:30:B4:64:27:8D
+---------------------------------------------
+
+       11) Configuring interfaces
+       -------------------------
+       At this point, configuration of Hotplug interfaces is done
+just like their built-in counterparts. This part is still distribution
+specific, and still already document in the file DISTRIBUTIONS.txt..
+
+       In Debian, you would need to modify the file
+/etc/network/interfaces like this :
+
+--------- /etc/network/interfaces -----------
+# Enable Hotplug support (Sarge and later)
+mapping hotplug
+    script echo
+
+# SMC 2835W wireless CardBus card
+iface prism0 inet static
+    address 10.0.1.2
+    network 10.0.1.0
+    netmask 255.255.255.0
+    broadcast 10.0.1.255
+    wireless-essid THE_ESSID
+    wireless-mode ad-hoc
+    wireless-channel 5
+---------------------------------------------
+
+       Now, just cross your finger and plug the card in the slot...
+
+PCMCIA INTERFACES (16 bits)
+---------------------------
+       The Pcmcia subsystem has quite some legacy, and can use
+various configuration procedure. The Pcmcia subsystem fully use
+hotplug for 32 bits card (if you are using the kernel Pcmcia modules,
+which is the only option for 2.6.X). For 16 bits cards, we can't make
+them fully hotplug yet and need the cardmgr and /etc/pcmcia directory,
+however we can make their network configuration use hotplug.
+
+       To use Hotplug network configuration with 16 bits Pcmcia
+cards, first make sure the Pcmcia subsystem is properly configured and
+that cardmgr load the right module (in most case, it should). Then,
+make sure that you don't have any configuration entries in
+/etc/pcmcia/network.opts and /etc/pcmcia/wireless.opts. Make sure that
+none of entries in your system network configuration use 'eth0' or
+'wlan0' (in /etc/network/interfaces for Debian users).
+       Then, just follow the procedure described above for
+"Configuration Using Hotplug" to configure your network cards.
+
+       You might want a little bit of explanation on why this magic
+will work (which would help in case it doesn't work).
+       There is two types of Pcmcia network configuration scripts,
+available as /etc/pcmcia/network. The original Pcmcia script configure
+network cards using options found in /etc/pcmcia/network.opts and
+/etc/pcmcia/wireless.opts. Most distributions replace it with a script
+calling 'ifup'. By making sure that network.opts and wireless.opts are
+"empty", we neutralise the first set of scripts. By making sure no
+system configuration uses 'eth0' or 'wlan0', we neutralise the second
+set of scripts, the script would call 'ifup' with the default
+interface name, which is usually 'eth0', ifup would not find a
+configuration for it and would just ignores it.
+       The card would still be configured because hotplug network
+events are generated for every interfaces, not only for devices
+managed by hotplug. So, net.agent would receive an event and perform
+the necessary steps to configure it.
+
+       Personally, I'm still using the original Pcmcia scripts for my
+Pcmcia cards as described in the file PCMCIA.txt, because I will
+migrate my complex configurations over time.
+       You can also decide to not use Hotplug for Pcmcia cards and
+modify the distribution Pcmcia scripts in /etc/pcmcia/* to handle
+Pcmcia cards properly. You would need to modify /etc/pcmcia/network to
+add 'ifrename' before 'ifup' the same way it was done for
+/etc/hotplug/net.agent. But, as in the long term Pcmcia will migrate
+to Hotplug, I would not bother...
+
+MANUAL LOADING, DOCKING STATIONS
+--------------------------------
+       Manual loading is used for built-in network interfaces that
+are only use at specific time, and that you want disabled the rest of
+the time. We assume that you still use modules so that when the
+interface is not used you can remove the driver from the kernel.
+
+       First, you need to set the configuration for those interfaces,
+the same way it's done for other network interfaces. The main
+difference is that you need to specify that those interfaces should
+not be enabled at boot time. It's also a good idea to disable Hotplug
+init scripts.
+       With Debian, you just need to make sure that the 'auto"
+keyword doesn't apply to this interface.
+--------- /etc/network/interfaces -----------
+# AMD AMD PCnet LANCE PCI card
+iface eth4 inet dhcp
+---------------------------------------------
+
+       If you use driver statically built in the kernel, you can just
+enable and disable those interfaces with 'ifup ethX' and 'ifdown ethX'.
+
+       If you use both a modular system and 'ifrename', you will need
+to change your habits when enabling those devices. The classical 'ifup
+ethX' won't work.
+       If you don't use Hotplug, you need to do :
+-----------------------------------
+modprobe eth4
+ifrename
+ifup eth4
+-----------------------------------
+       If you use hotplug, you only need to do :
+-----------------------------------
+modprobe eth4
+-----------------------------------
+
+       On the other hand, disabling the interface has not changed :
+-----------------------------------
+ifdown eth4
+modprobe -r eth4
+-----------------------------------
+       Using "modprobe -r" make sure that if the driver is composed
+of multiple module all the modules are unloaded.
+
+       Docking stations for laptops may contain built-in
+interfaces. My previous laptop had one, and Linux had no support for
+it. To be able to simply manage my docking station, I had created two
+little scripts to enable and disable my network interface.
+       After docking, you would run :
+-------- /sbin/dock ----------------------------
+#!/bin/sh
+modprobe eth4
+ifrename
+ifup eth4
+------------------------------------------------
+       And prior to undocking, you would run :
+-------- /sbin/undock ----------------------------
+#!/bin/sh
+ifdown eth4
+modprobe -r eth4
+------------------------------------------------
+       Thanks to 'ifrename', the network interface in your dock will
+always be properly configured regardless of if you have a Pcmcia
+network card in the Pcmcia slot or not.
+
+SCHEMES (MULTI-CONFIG)
+----------------------
+       Most Ethernet cards will only connect to a single network, or
+can use DHCP to be auto-configured. With Wireless Cards, it's much
+more likely that you will need multiple configurations, for example at
+work, at home and on-the-go.
+
+       Most distributions have various level of support for such
+schemes. Some distributions offer simple network schemes, while other
+offer "overall" schemes changing the whole configuration. I document
+the support for schemes in various distributions in the file
+DISTRIBUTIONS.txt.
+
+       You can also use tools such as IfPlugd, WapRoamd or
+Wlandetect. Those tools are a kind of "wireless-DHCP", they attempt to
+automatically detect the proper wireless configuration and apply
+it. Most will also attempt to detect network changes.
+       The main limitation of those tools is that they offer very
+little manual control. If two valid alternatives are possible, you
+can't switch between them. If a configuration can't be detected, they
+usually fail.
+       That's the same concept as using DHCP versus Static IP
+addresses. Some people are very happy with DHCP, my style is Static IP
+addresses.
+
+       If you use Debian and want to use simple manual schemes, these
+are the things you need to do.
+       1) Make sure that 'ifscheme' and 'ifscheme-mapping' are
+installed on the system. You may find them in a separate tar file on
+my web site.
+       2) Check the path for 'ifscheme-mapping' (using whereis).
+       3) Modify you /etc/network/interface to add proper mapping and
+configuration.
+
+------- /etc/network/interfaces ----------------------
+# Enable Hotplug support (Sarge and later)
+mapping hotplug
+    script echo
+
+# SMC 2835W wireless CardBus card
+mapping prism0
+    script /sbin/ifscheme-mapping
+
+iface prism0-any inet dhcp
+    wireless-essid any
+    wireless-mode managed
+
+iface prism0-adhoc inet static
+    address 10.0.1.2
+    network 10.0.1.0
+    netmask 255.255.255.0
+    broadcast 10.0.1.255
+    wireless-essid THE_ESSID
+    wireless-mode ad-hoc
+    wireless-channel 5
+
+iface prism0-other inet static
+    address 10.10.10.2
+    network 10.10.10.0
+    netmask 255.255.255.0
+    broadcast 10.10.10.255
+    wireless-essid ANOTHER_ESSID
+    wireless-mode ad-hoc
+    wireless-key "s:secure"
+------------------------------------------------------
+
+FIRMWARE LOADING
+----------------
+       A lot of modern wireless card don't have built in firmware and
+need firmware loading. Recent kernel (2.6.X) have a firmware
+loader. These are a few notes on how to use it.
+
+       First, read the documentation coming with your driver, because
+each driver has specificities (like the name of the firmware file it
+requires).
+
+       You need to compile your kernel with firmware loading
+(CONFIG_FW_LOADER in "Generic Driver Options"). If your driver was
+built from the kernel, chances are that it enabled this feature
+already. Make sure you boot from this new kernel.
+
+       The 'sysfs' file system must be mounted. The easiest is to
+mount it at boot time, add a line for it in /etc/fstab :
+
+-------- /etc/fstab ------------------------------
+sysfs          /sys          sysfs  defaults                   0      0
+--------------------------------------------------
+
+       Then, you add the firmware file in the directory where it's
+expected, which is /usr/lib/hotplug/firmware/ in most cases.
+
+       Most distributions nowadays have a version of the Hotplug
+scripts that knows how to deal with firmware. If it is not the case,
+just grab the 'firmware.agent' file from an alternate source and copy
+it into your /etc/hotplug directory (make sure it's executable).
+       You can try the canonical version :
+               http://linux-hotplug.sourceforge.net/
+       Or Debian's version :
+               http://packages.debian.org/unstable/admin/hotplug
+
+       Note that firmware loading will usually only work with
+interfaces that are fully managed by Hotplug. This is the only way to
+ensure the that proper sequence of action is happening in the right
+order every time. Firmware loading will usually not work properly for
+interfaces configured in the init scripts.
+       This means that if you have a built-in interface that require
+firmware loading, you should just use manage those interfaces like
+removable interfaces (see section above). However, interface
+configuration need to be explicitely triggered at boot time.
+
+       One possibility is to set-up Hotplug to be run from the init
+script at boot time. This is usually an option for recent
+distributions (it's not the case for Hotplug in Debian 3.0). But, we
+have seen that this has some issues.
+       The other possibility is to use an hybrid between the init
+script method and the hotplug method. First, you need to add an alias
+for the driver in /etc/modprobe.conf. Then, you need to specify a
+mapping for this interface in /etc/iftab, and specify a configuration
+for this interface and that that it is enabled at boot time. Lastly,
+you make sure that the network init scripts run 'ifrename
+-p'. 'Ifrename' will trigger the module to load, and all the Hotplug
+events will be generated properly to configure the interface.
+
+DEVICES WITH MULTIPLE NAMES
+---------------------------
+       Some wireless drivers offer multiple network interfaces for
+the same device. A classical example is the Aironet driver that
+creates a 'ethX' and 'wifiY' for each card.
+
+       'ifrename' allow you a finer selection of interfaces than
+'nameif'. For example, to only rename the pseudo-Ethernet network
+interface name of the Aironet driver, you would do :
+
+--------- /etc/iftab -----------------------
+# Cisco Aironet 350 wireless Pcmcia card
+airo*          mac 00:07:0E:* arp 1
+---------------------------------------------
+
+       After that, your device would be available through 'eth0' and
+'wifi0'.
+
+       You can rename both interfaces. You just need to remember that
+'ifrename' start matching from the last line of the file, so you would
+do :
+--------- /etc/iftab -----------------------
+# Cisco Aironet 350 wireless Pcmcia card
+wifi*          mac 00:07:0E:*
+airo*          mac 00:07:0E:* arp 1
+---------------------------------------------
+
+       The current version of 'ifrename' support only the most useful
+selectors, and is architectured such as adding selectors is relatively
+trivial. If you find a case that 'ifrename' can't handle, you should
+just extend it.
+
+DEVICES WITHOUT MAC ADDRESSES
+-----------------------------
+       Most Ethernet and Wireless devices have a fixed and unique MAC
+address, and it is therefore advised to name them based on this
+criteria. However, there is also network interfaces that don't have a
+fixed and unique MAC address, for example Ethernet over USB, IP over
+FireWire, PPP and tunnel interfaces.
+       The driver for those devices create the interface with a name
+specific to the driver, such as ppp* for PPP interfaces and usb* for
+Ethernet over USB, and therefore they are easy to identify and
+configure, and few users feel the need to rename them. Moreover, some
+of them, such as PPP, have their own configuration scripts and
+methodology addressing their unique needs.
+
+       There is a few cases where you might want to rename interfaces
+withour MAC addresses. One example is two Ethernet over USB
+dongles. The way to do this is to use alternate ifrename
+selectors. Choosing the right selector depend on what you want to
+achieve.
+       A quick theoretical example to illustrate :
+--------- /etc/iftab -----------------------
+# All other usbnet devices
+usb*           driver usbnet
+# Specific usbnet devices
+usb-p          firmware "Prolific PL-2301/PL-2302"
+usb-4          bus-info usb-00:02.0-1.4
+---------------------------------------------
+
+TROUBLESHOOTING
+---------------
+       If your interface doesn't show up as expected with ifconfig,
+you will need to find out why. First, you need to be familiar with the
+sequence of actions in the system and find which one did not happen.
+
+       You need to check if the driver module(s) was loaded using
+'lsmod'.
+
+       You need to check if the interface was properly renamed with
+'ifrename'. You can use 'ifrename -D -V' to debug your /etc/iftab.
+       Get the the list of interfaces on your system with 'cat
+/proc/net/dev', and check if an interface is using the name you
+assigned or 'eth0'. Check any suspicious interfaces with 'ifconfig
+eth0', and check its MAC address. Note that some rare drivers don't
+have a proper MAC address before brought up, which fools ifrename.
+       Verify that no line in /etc/iftab matches the all-zero MAC
+address. The all-zero MAC address matches the loopback interface 'lo'
+and various pseudo network devices, renaming the loopback interface is
+highly discouraged.
+
+       You need to check which configuration was given to the
+interface using 'ifconfig' and 'iwconfig'.
+
+       The Hotplug subsystem has also good debugging facilities.
+       To enable Hotplug debugging, just make sure the variable DEBUG
+is defined in /sbin/hotplug :
+--------- /sbin/hotplug ------------------------------
+--- /sbin/hotplug-old      Tue Mar 26 09:00:20 2002
++++ /sbin/hotplug       Fri Feb 20 18:40:38 2004
+@@ -22,7 +22,7 @@
+ cd /etc/hotplug
+ . hotplug.functions
+-# DEBUG=yes export DEBUG
++DEBUG=yes export DEBUG
+ if [ "$DEBUG" != "" ]; then
+     mesg "arguments ($*) env (`env`)"
+------------------------------------------------------
+       Then, you can check your message logs for Hotplug events with
+'tail -f /var/log/messages'. Verify that the various Hotplug events
+happen as expected (pci, firmware, net...), and verify the log
+messages from 'net.agent'.
+
+
+       Have fun...
+
+       Jean
index 37bf8d4..b938fa6 100644 (file)
@@ -1,96 +1,89 @@
 Very important note :
 -------------------
 Very important note :
 -------------------
-       This release of the Wireless Tools is not compatible with Wireless
-       Extensions earlier than 9.
-       Kernels that support this version of the Wireless Tools are listed
-       below. For all kernels before that, please use the version v19 of
-       the Wireless Tools.
-       You might have headers troubles and it doesn't compile, see below...
+       This release of the Wireless Tools is not compatible with
+Wireless Extensions earlier than 9. Version 9 and 10 should work fine
+but are not recommended. Version 8 and earlier will not work.
+       Kernels that support this version of the Wireless Tools are
+listed below. For all kernels before that, see at the end.
 
 You need :
 --------
        o Compiler and development environment
 
 You need :
 --------
        o Compiler and development environment
-       o A kernel supporting wireless extensions version 9 or higher
-               -> from 2.2.14 onward
-               -> from 2.3.24 onward
+       o A kernel supporting wireless extensions version 11 or higher
+               -> from 2.4.4 onward (including 2.6.X)
                Note : CONFIG_NET_RADIO must be enabled
        o (Optional) A Pcmcia package supporting Wireless Extension
        o A driver supporting wireless extensions
                Note : CONFIG_NET_RADIO must be enabled
        o (Optional) A Pcmcia package supporting Wireless Extension
        o A driver supporting wireless extensions
-               -> Check my web pages for latest list of drivers,
-                       otherwise patch your favourite driver...
+               -> Check my web pages for status of various drivers.
        Note : more recent kernels and drivers are likely to support
                more wireless extension features...
 
 Compile wireless tools :
 ----------------------
        In theory, a "make" should suffice to create the tools.
        Note : more recent kernels and drivers are likely to support
                more wireless extension features...
 
 Compile wireless tools :
 ----------------------
        In theory, a "make" should suffice to create the tools.
-       In practice, there is big troubles with the kernel
-headers. See below for how to fix that.
-       Note : as some internal data structures change from kernel to
-kernel, you are advised to not use the precompiled version of the
-tools but to recompile your own.
 
 Installation :
 ------------
 
 Installation :
 ------------
-       If I were you, I would not trust a "make install". If you feel
-courageous, just do "make install". It may even do the right
-thing. Actually, with the various bugfixes that happened over the
-time, it nowadays tend to do the right thing.
-       I advise to copy the executable (iwconfig, iwspy and iwpriv)
-in /usr/local/sbin or /usr/sbin. The man pages (iwconfig.8, iwspy.8
-and iwpriv.8) should be copied in /usr/local/man/man8 or
-/usr/man/man8.
-       In fact, if you want to use Pcmcia wireless.opts, this step is
-mandatory...
+       "make install" should do the right thing for you, and install
+the tools, their library and the man pages. You can also uninstall the
+tools via "make uninstall".
+       Note that the default installation is in the directory
+'/usr/local/sbin'. This may not be in your path. Also, other version
+of the tools may exist on the system, so double check which version is
+the default and adjust your path as necessary.
 
 
-Kernel headers (why it doesn't compile) :
----------------------------------------
-       Some changes in the kernel headers and glibc headers are
-making my life difficult. We now have a mechanism to automatically
-select the proper header based on various bits of information (libc
-version & kernel version), but it may fail to do the right thing.
-       You may also see the message :
-               "Your kernel/libc combination is not supported"
-       If this happens to you, you will need to hack the rules at the
-top of iwlib.h and send me the patch.
-
-       The second issue is that some distributions install some
-independant kernel headers in /usr/include. If you upgrade your
-kernel, those headers become out of sync and you don't benefit from
-the latest Wireless Extensions. Even worse, it can sometimes prevent
-the tools from compiling.
-       The trick is to copy the file .../include/linux/wireless.h
-from the kernel to the /usr/include headers.
-
-Multi-kernel installation (expert only) :
----------------------------------------
-       People who run different kernel on the same system may have
-problems due to the fact that those kernel have different version of
-Wireless Extensions and the Wireless Tools need to match the version
-of Wireless Extension used.
+Create a local copy of the tools :
+--------------------------------
+       By default, the package is built with iwlib as a dynamic
+library, and the tool will expect to use the default version of libiw
+on the system.
+       If you just want to experiment with a "local" version of the
+tools, you may want to pass the BUILD_STATIC flag to Makefile. It will
+create a self contained version of the tools.
+-------------
+make clean
+make BUILD_STATIC='y'
+-------------
+       The resulting binary can be used in the compilation directory
+or installed in any place you like.
 
 
-       It is now possible to install multiple versions of the
-Wireless Tools on a system and get the proper version used based on
-the kernel running, using a redirector. However, this support is still
-experimental and for expert users only.
-       The redirector will work properly only with kernel using
-Wireless Extensions version 16 and higher. Earlier version of Wireless
-Extensions will be detected as either v15 (v12, v13, v14 and v15) or
-as v11 (v11 and earlier).
+Wireless headers (past history) :
+-------------------------------
+       Previous version of the Wireless Tools had to be compiled with
+the same version of Wireless Extension that the kernel was using, and
+that was a major source of troubles.
+       Starting with version 27, Wireless Tools include all the ugly
+code to deal with any version of Wireless Extensions, so now you can
+compile a single "generic" version of the tools for any kernel.
+       Well, there are some limits, Wireless Extensions earlier than
+v11 are not supported (v9 and v10 should work fine), and versions
+later than the latest definition in the package are not
+supported. Once compile, the command "iwconfig --version" should tell
+you that.
+       Note that the previous option to make versioned installed of
+the tools no longer make sense and therefore is gone.
 
 
-       The installation looks typically like :
-------------------------------------
-make clean
-make FORCE_WEXT_VERSION=11
-make vinstall FORCE_WEXT_VERSION=11
-make clean
-make FORCE_WEXT_VERSION=15
-make vinstall FORCE_WEXT_VERSION=15
-make clean
-make FORCE_WEXT_VERSION=16
-make vinstall FORCE_WEXT_VERSION=16
-[...]
-------------------------------------
+Other useful Makefile options :
+-----------------------------
+       PREFIX : where the tools will be installed (default : /usr/local)
+       BUILD_STATIC : build tools with a static version of the wireless lib
+       BUILD_NOLIBM : build tools without mathematical lib (slower)
+       Note that you should pass the same command line options for
+all invocations of make ("make" and "make install").
 
 
+Old kernel with older Wireless Extensions :
+-----------------------------------------
+       Kernel prior to 2.2.14 : Those kernels include Wireless
+Extensions v8 or earlier. Those versions don't have proper support for
+802.11b, so are not very useful. You may want to consider upgrading.
+       Kernel 2.2.19 to 2.2.25 : Those kernels include Wireless
+Extensions v10. The tools should mostly work with it, but many drivers
+won't. You can upgrade those kernel to WE v15 with a patch on my web
+page.
+       Kernel 2.2.14 to 2.2.18 : Those kernels include Wireless
+Extensions v9. Same as above, you may want to upgrade to a later 2.2.X
+kernel and then apply the patch.
+       Kernel 2.0.X : Those kernels include very old version of
+Wireless Extensions. Same deal as old 2.2.X kernels.
 
        Jean <jt@hpl.hp.com>
 
        Jean <jt@hpl.hp.com>
index 15c8cb5..a34aa31 100644 (file)
@@ -3,51 +3,58 @@
 ##
 
 ## Installation directory. By default, go in /usr/local
 ##
 
 ## Installation directory. By default, go in /usr/local
-## Distributions should probably use /usr, but they probably know better...
+## Distributions should probably use /, but they probably know better...
 ifndef PREFIX
   PREFIX = /usr/local
 endif
 
 ifndef PREFIX
   PREFIX = /usr/local
 endif
 
-## Compiler to use
+## Compiler to use (modify this for cross compile)
 CC = gcc
 CC = gcc
+## Other tools you need to modify for cross compile (static lib only)
+AR = ar
+RANLIB = ranlib
 
 
-## Uncomment this to build against this kernel
-# KERNEL_SRC = /usr/src/linux
-
-## Uncomment this to force a particular version of wireless extensions.
-## This would use private copy of Wireless Extension definition instead
-## of the system wide one in /usr/include/linux. Use with care.
-## Can be used to create multiple versions of the tools on the same system
-## for multiple kernels or get around broken distributions.
-# FORCE_WEXT_VERSION = 16
-
-## Uncomment this to build tools using dynamic version of the library
-# BUILD_SHARED = y
+## Uncomment this to build tools using static version of the library
+## Mostly useful for embedded platforms without ldd, or to create
+## a local version (non-root).
+# BUILD_STATIC = y
 
 ## Uncomment this to build without using libm (less efficient)
 
 ## Uncomment this to build without using libm (less efficient)
-## This is mostly useful for embedded platforms
+## This is mostly useful for embedded platforms without maths.
 # BUILD_NOLIBM = y
 
 # ***************************************************************************
 # ***** Most users should not need to change anything beyond this point *****
 # ***************************************************************************
 
 # BUILD_NOLIBM = y
 
 # ***************************************************************************
 # ***** Most users should not need to change anything beyond this point *****
 # ***************************************************************************
 
+# Version of the Wireless Tools
+WT_VERSION := $(shell sed -ne "/WT_VERSION/{s:\([^0-9]*\)::;p;q;}" < iwlib.h )
+
+# Version of Wireless Extensions.
+WE_VERSION := $(shell sed -ne "/WE_VERSION/{s:\([^0-9]*\)::;p;q;}" < iwlib.h )
+
+# Always use local header for wireless extensions
+WEXT_HEADER = wireless.$(WE_VERSION).h
+
 # Targets to build
 STATIC=libiw.a
 # Targets to build
 STATIC=libiw.a
-DYNAMIC=libiw.so.26
-PROGS= iwconfig iwlist iwpriv iwspy iwgetid iwevent
-MANPAGES8=iwconfig.8 iwlist.8 iwpriv.8 iwspy.8 iwgetid.8 iwevent.8
+DYNAMIC=libiw.so.$(WT_VERSION)
+PROGS= iwconfig iwlist iwpriv iwspy iwgetid iwevent ifrename
+MANPAGES8=iwconfig.8 iwlist.8 iwpriv.8 iwspy.8 iwgetid.8 iwevent.8 ifrename.8
 MANPAGES7=wireless.7
 MANPAGES7=wireless.7
-EXTRAPROGS= macaddr iwredir
+MANPAGES5=iftab.5
+EXTRAPROGS= macaddr
 
 # Composition of the library :
 OBJS = iwlib.o
 
 
 # Composition of the library :
 OBJS = iwlib.o
 
-# Select library to link tool with
-ifdef BUILD_SHARED
-  IWLIB=$(DYNAMIC)
-else
+# Select which library to build and to link tool with
+ifdef BUILD_STATIC
   IWLIB=$(STATIC)
   IWLIB=$(STATIC)
+  IWLIB_INSTALL=install-static
+else
+  IWLIB=$(DYNAMIC)
+  IWLIB_INSTALL=install-dynamic
 endif
 
 # Standard name for dynamic library so that the dynamic linker can pick it.
 endif
 
 # Standard name for dynamic library so that the dynamic linker can pick it.
@@ -60,21 +67,10 @@ INSTALL_LIB= $(PREFIX)/lib/
 INSTALL_INC= $(PREFIX)/include/
 INSTALL_MAN= $(PREFIX)/man/
 
 INSTALL_INC= $(PREFIX)/include/
 INSTALL_MAN= $(PREFIX)/man/
 
-# Use local header if the version of wireless extensions is specified
-ifdef FORCE_WEXT_VERSION
-  WEXT_FLAG = -DWEXT_HEADER=\"wireless.$(FORCE_WEXT_VERSION).h\"
-endif
-
+# Various commands
 RM = rm -f
 RM = rm -f
-
-RM_CMD = $(RM) *.BAK *.bak *.o *.so ,* *~ *.a *.orig *.rej
-
-ifdef KERNEL_SRC
-  ifeq ($(wildcard $(KERNEL_SRC)/include/linux/wireless.h),)
-    $(error Kernel source is missing or incomplete)
-  endif
-  KERNEL_INCLUDES = -I $(KERNEL_SRC)/include
-endif
+RM_CMD = $(RM) *.BAK *.bak *.d *.o *.so ,* *~ *.a *.orig *.rej *.out
+LDCONFIG = ldconfig
 
 # Do we want to build with or without libm ?
 ifdef BUILD_NOLIBM
 
 # Do we want to build with or without libm ?
 ifdef BUILD_NOLIBM
@@ -84,18 +80,22 @@ else
   LIBS= -lm
 endif
 
   LIBS= -lm
 endif
 
-#CFLAGS=-O2 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror
-CFLAGS=-O2 -W -Wall -Wstrict-prototypes
-XCFLAGS=$(CFLAGS) $(WARN) $(HEADERS) $(WEXT_FLAG) $(WELIB_FLAG) $(KERNEL_INCLUDES)
+# Other flags
+CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \
+       -Wpointer-arith -Wcast-qual -Winline -I.
+#CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I.
+DEPFLAGS=-MMD
+XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG)
 PICFLAG=-fPIC
 
 PICFLAG=-fPIC
 
-all:: $(STATIC) $(DYNAMIC) $(PROGS)
+# Standard compilation targets
+all:: $(IWLIB) $(PROGS)
 
 %: %.o
        $(CC) $(LDFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS)
 
 %: %.o
        $(CC) $(LDFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS)
-%.o: %.c
+%.o: %.c wireless.h
        $(CC) $(XCFLAGS) -c $<
        $(CC) $(XCFLAGS) -c $<
-%.so: %.c
+%.so: %.c wireless.h
        $(CC) $(XCFLAGS) $(PICFLAG) -c -o $@ $<
 
 iwconfig: iwconfig.o $(IWLIB)
        $(CC) $(XCFLAGS) $(PICFLAG) -c -o $@ $<
 
 iwconfig: iwconfig.o $(IWLIB)
@@ -106,14 +106,18 @@ iwpriv: iwpriv.o $(IWLIB)
 
 iwspy: iwspy.o $(IWLIB)
 
 
 iwspy: iwspy.o $(IWLIB)
 
-iwgetid: iwgetid.o
+iwgetid: iwgetid.o $(IWLIB)
 
 iwevent: iwevent.o $(IWLIB)
 
 
 iwevent: iwevent.o $(IWLIB)
 
-iwredir: iwredir.o
+ifrename: ifrename.o $(IWLIB)
 
 macaddr: macaddr.o $(IWLIB)
 
 
 macaddr: macaddr.o $(IWLIB)
 
+# It's a kind of magic...
+wireless.h:
+       cp $(WEXT_HEADER) wireless.h
+
 # Compilation of the dynamic library
 $(DYNAMIC): $(OBJS:.o=.so)
        $(CC) -shared -o $@ -Wl,-soname,$@ $(LIBS) -lc $^
 # Compilation of the dynamic library
 $(DYNAMIC): $(OBJS:.o=.so)
        $(CC) -shared -o $@ -Wl,-soname,$@ $(LIBS) -lc $^
@@ -121,32 +125,43 @@ $(DYNAMIC): $(OBJS:.o=.so)
 # Compilation of the static library
 $(STATIC): $(OBJS)
        $(RM) $@
 # Compilation of the static library
 $(STATIC): $(OBJS)
        $(RM) $@
-       ar cru $@ $^
-       ranlib $@
+       $(AR) cru $@ $^
+       $(RANLIB) $@
 
 # So crude but so effective ;-)
 # Less crude thanks to many contributions ;-)
 
 # So crude but so effective ;-)
 # Less crude thanks to many contributions ;-)
-install:: all
+install:: all $(IWLIB_INSTALL)
        install -m 755 -d $(INSTALL_DIR)
        install -m 755 $(PROGS) $(INSTALL_DIR)
        install -m 755 -d $(INSTALL_DIR)
        install -m 755 $(PROGS) $(INSTALL_DIR)
-       install -m 755 -d $(INSTALL_LIB)
-       install -m 644 $(STATIC) $(INSTALL_LIB)
-       install -m 755 $(DYNAMIC) $(INSTALL_LIB)
-       ln -sfn $(DYNAMIC) $(INSTALL_LIB)/$(DYNAMIC_LINK)
-       echo "Don't forget to add $(INSTALL_LIB) to /etc/ld.so.conf, and run ldconfig."
        install -m 755 -d $(INSTALL_INC)
        install -m 644 iwlib.h $(INSTALL_INC)
        install -m 755 -d $(INSTALL_INC)
        install -m 644 iwlib.h $(INSTALL_INC)
+       install -m 644 wireless.h $(INSTALL_INC)
        install -m 755 -d $(INSTALL_MAN)/man8/
        install -m 644 $(MANPAGES8) $(INSTALL_MAN)/man8/
        install -m 755 -d $(INSTALL_MAN)/man7/
        install -m 644 $(MANPAGES7) $(INSTALL_MAN)/man7/
        install -m 755 -d $(INSTALL_MAN)/man8/
        install -m 644 $(MANPAGES8) $(INSTALL_MAN)/man8/
        install -m 755 -d $(INSTALL_MAN)/man7/
        install -m 644 $(MANPAGES7) $(INSTALL_MAN)/man7/
+       install -m 755 -d $(INSTALL_MAN)/man5/
+       install -m 644 $(MANPAGES5) $(INSTALL_MAN)/man5/
+
+# Install the dynamic library
+install-dynamic:: $(DYNAMIC)
+       install -m 755 -d $(INSTALL_LIB)
+       install -m 755 $(DYNAMIC) $(INSTALL_LIB)
+       ln -sfn $(DYNAMIC) $(INSTALL_LIB)/$(DYNAMIC_LINK)
+       @echo "*** Don't forget to add $(INSTALL_LIB) to /etc/ld.so.conf, and run ldconfig as root. ***"
+       @$(LDCONFIG) || echo "*** Could not run ldconfig ! ***"
+
+# Install the static library
+install-static:: $(STATIC)
+       install -m 755 -d $(INSTALL_LIB)
+       install -m 644 $(STATIC) $(INSTALL_LIB)
 
 clean::
        $(RM_CMD) 
 
 realclean::
        $(RM_CMD) 
 
 clean::
        $(RM_CMD) 
 
 realclean::
        $(RM_CMD) 
-       $(RM) $(STATIC) $(DYNAMIC) $(PROGS) $(EXTRAPROGS)
+       $(RM) $(STATIC) $(DYNAMIC) $(PROGS) $(EXTRAPROGS) libiw* wireless.h
 
 uninstall::
        for f in $(PROGS); do \
 
 uninstall::
        for f in $(PROGS); do \
@@ -156,41 +171,16 @@ uninstall::
        $(RM) $(INSTALL_LIB)/$(DYNAMIC)
        $(RM) $(INSTALL_LIB)/$(DYNAMIC_LINK)
        $(RM) $(INSTALL_INC)/iwlib.h
        $(RM) $(INSTALL_LIB)/$(DYNAMIC)
        $(RM) $(INSTALL_LIB)/$(DYNAMIC_LINK)
        $(RM) $(INSTALL_INC)/iwlib.h
+       $(RM) $(INSTALL_INC)/wireless.h
        for f in $(MANPAGES8); do \
          $(RM) $(INSTALL_MAN)/man8/$$f; \
        done
        for f in $(MANPAGES7); do \
          $(RM) $(INSTALL_MAN)/man7/$$f; \
        done
        for f in $(MANPAGES8); do \
          $(RM) $(INSTALL_MAN)/man8/$$f; \
        done
        for f in $(MANPAGES7); do \
          $(RM) $(INSTALL_MAN)/man7/$$f; \
        done
+       for f in $(MANPAGES5); do \
+         $(RM) $(INSTALL_MAN)/man5/$$f; \
+       done
 
 
-# Versioned install...
-# We rename each of the tool with a suffix corresponding to the version
-# of WE it was compiled with. We use "iwredir" for the redirection...
-
-vinstall:: iwredir install
-       @wev=$(FORCE_WEXT_VERSION) ; \
-       if [ "$$wev" == "" ] ; then \
-         wev=`./iwredir -wev`; \
-       else :; fi ; \
-       echo "Installing tools for WE-$$wev..." ; \
-       for f in $(PROGS); do \
-         mv $(INSTALL_DIR)/$$f $(INSTALL_DIR)/$$f$$wev; \
-       done;
-       install -m 755 iwredir $(INSTALL_DIR)
-       for f in $(PROGS); do \
-         ln $(INSTALL_DIR)/iwredir $(INSTALL_DIR)/$$f; \
-       done;
-
-vuninstall:: uninstall
-       @wev=$(FORCE_WEXT_VERSION) ; \
-       if [ "$$wev" == "" ] ; then \
-         wev=`./iwredir -wev`; \
-       else :; fi ; \
-       for f in $(PROGS); do \
-         rm $(INSTALL_DIR)/$$f$$wev; \
-       done;
-       $(RM) $(INSTALL_DIR)/iwredir;
-
-depend::
-       makedepend -s "# DO NOT DELETE" -- $(INCLUDES) -- $(SRCS)
-# DO NOT DELETE
+# Include dependancies
+-include *.d
index 93886bf..b4bb19b 100644 (file)
@@ -1,21 +1,28 @@
        Wireless Tools
        --------------
 
        Wireless Tools
        --------------
 
-       This package contain the Wireless tools, used to manipulate
-the Wireless Extensions. The Wireless Extension is an interface
+       This package contains the Wireless tools, used to manipulate
+the Wireless Extensions. The Wireless Extensions is an interface
 allowing you to set Wireless LAN specific parameters and get the
 specific stats.
 
 allowing you to set Wireless LAN specific parameters and get the
 specific stats.
 
-web page
+web page :
 --------
        You'll find a lot of useful info on :
                http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
                http://web.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
 
 --------
        You'll find a lot of useful info on :
                http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
                http://web.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
 
+Precompiled version :
+-------------------
+       Most Linux distributions offer precompiled package containing
+these tools. And many of them preinstall them by default. On the other
+hand, installation of this package is (now) easy and allow you to get
+a more up-to-date version.
+
 INSTALL
 -------
 INSTALL
 -------
-       This file contains installation instruction and requirements.
-       A *must* read.
+       This file contains installation instructions and requirements.
+       A *must*-read.
 
 DISTRIBUTION.txt
 ----------------
 
 DISTRIBUTION.txt
 ----------------
@@ -26,28 +33,45 @@ Extensions). Please read it carefully before asking questions.
 Extensions integration in the most common Linux distributions. I need
 your help to complete this file.
 
 Extensions integration in the most common Linux distributions. I need
 your help to complete this file.
 
+HOTPLUG.txt
+-----------
+       This file document how to manage and configure removable
+wireless cards using Hotplug. This is more advanced than the simple
+procedures of DISTRIBUTION.txt. This is currently mostly Debian
+specific, but I hope you will contribute for other distributions.
+
 PCMCIA.txt
 ----------
 PCMCIA.txt
 ----------
-       This file describes how to use Pcmcia init script to configure
-Wireless Extensions and how to use Pcmcia schemes.
+       This file describes how to use PCMCIA init script to configure
+Wireless Extensions and how to use PCMCIA schemes.
 
 man pages (iwconfig.8, iwlist.8, iwpriv.8, iwspy.8)
 ---------
 
 man pages (iwconfig.8, iwlist.8, iwpriv.8, iwspy.8)
 ---------
-       VERY IMPORTANT : I try to keep the man page up to date, so
+       VERY IMPORTANT : I try to keep the man pages up to date, so
 you'd better read them before asking questions.
 you'd better read them before asking questions.
-       ALSO IMPORTANT : Those man pages describe the capacity of the
-tools, no device implement the full range (and drivers usually
+       ALSO IMPORTANT : Those man pages describe the capacities of
+the tools, no device implements the full range (and drivers usually
 implement even less).
 
        As far as I know, the man pages are the most complete, up to
 date and accurate documentation of the wireless tools. An update of
 implement even less).
 
        As far as I know, the man pages are the most complete, up to
 date and accurate documentation of the wireless tools. An update of
-the web page related to Wireless Extension is long overdue. Send
+the web page related to Wireless Extensions is long overdue. Send
 feedback to me.
 feedback to me.
-       The man pages can either be copied in a location where the
+       The man pages can either be copied into a location where the
 command "man" will find them, such as /usr/local/man/man8, or can be
 read locally with the command :
                nroff -man xxx.8 | less
 
 command "man" will find them, such as /usr/local/man/man8, or can be
 read locally with the command :
                nroff -man xxx.8 | less
 
+localised man pages (fr/*)
+-------------------
+       Localised man pages are not made by me, therefore the only
+localisations available are those sent to me by courageous volonteers
+and are expect those man pages to 'lag' compared to the english
+version (i.e. not have all the latest updates). Translating man pages
+is not a very gratifying task, especially due to my broken english,
+and many technical terms don't translate well to other languages, so
+refer to the english version when in doubt.
+
 iwconfig.c
 ----------
        The main wireless tool. Used for device configuration and to see
 iwconfig.c
 ----------
        The main wireless tool. Used for device configuration and to see
@@ -60,9 +84,9 @@ iwlist.c
 
 iwspy.c
 -------
 
 iwspy.c
 -------
-       Mobile IP support test and allow get get stats per MAC address
-(instead of globally). Also, for some driver/device, this is the only
-way to get stats in Ad-Hoc mode.
+       Mobile IP support test and allows get get stats per MAC
+address (instead of globally). Also, for some drivers/devices, this is
+the only way to get stats in Ad-Hoc mode.
 
 iwpriv.c
 --------
 
 iwpriv.c
 --------
@@ -72,19 +96,23 @@ specific to a driver or a device and therefore not part of iwconfig.
 iwgetid.c
 ---------
        Output the ESSID or NWID of the specified device.
 iwgetid.c
 ---------
        Output the ESSID or NWID of the specified device.
-       Can also output it in a form that can be used as a Pcmcia Scheme.
+       Can also output it in a form that can be used as a PCMCIA Scheme.
 
 iwevent.c
 ---------
        Display Wireless Events. This is new, so there is not much support
 in drivers for it yet...
 
 
 iwevent.c
 ---------
        Display Wireless Events. This is new, so there is not much support
 in drivers for it yet...
 
+ifrename.c :
+----------
+       Rename network interfaces based on various selectors.
+
 iwlib.c
 -------
 iwlib.c
 -------
-       The Wireless Tools helper library. May be usefull if you want
+       The Wireless Tools helper library. May be useful if you want
 to create your own applications using Wireless Extensions.
 
 to create your own applications using Wireless Extensions.
 
-Changelog, contributions
+Changelog, contributions :
 ------------------------
        See CHANGELOG.h
 
 ------------------------
        See CHANGELOG.h
 
@@ -94,29 +122,29 @@ wireless.h
 definition used by the drivers and the tools must match, otherwise
 funny things may happen. The tools try to check for that.
        Since Wireless Extensions v12, you can no longer drop this
 definition used by the drivers and the tools must match, otherwise
 funny things may happen. The tools try to check for that.
        Since Wireless Extensions v12, you can no longer drop this
-file in your kernel headers to update the Wireless Extensions, you
+file into your kernel headers to update the Wireless Extensions, you
 need to use the full patches available on my web page. So, the use is
 more if you plan to do some cross compile or something similar.
 need to use the full patches available on my web page. So, the use is
 more if you plan to do some cross compile or something similar.
-       Just for your enjoyement, there is various release of it. If
+       Just for your enjoyment, there are various releases of it. If
 your kernel/drivers are old, you may want to try the older releases...
 
 sample_xxx.c :
 ------------
        Various samples of code showing how to implement some of the
 more tricky feature of Wireless Extensions in your driver.
 your kernel/drivers are old, you may want to try the older releases...
 
 sample_xxx.c :
 ------------
        Various samples of code showing how to implement some of the
 more tricky feature of Wireless Extensions in your driver.
-       Note that there is no guarantee that this code compile, let
-alone work, but it should point you in the proper direction.
+       Note that there is no guarantee that this code compiles, let
+alone works, but it should point you in the proper direction.
        Also, have a look at existing drivers in the Linux kernel.
 
 Other tools :
 -----------
        Also, have a look at existing drivers in the Linux kernel.
 
 Other tools :
 -----------
-       My web page list many other tools using Wireless
+       My web page lists many other tools using Wireless
 Extensions that you may find useful...
        http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html#links
 
 Other questions :
 ---------------
 Extensions that you may find useful...
        http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html#links
 
 Other questions :
 ---------------
-       You have the source, and it is documented. In 99% of the case,
+       You have the source, and it is documented. In 99% of cases,
 you will find your answer there.
 
        Good luck...
 you will find your answer there.
 
        Good luck...
diff --git a/wireless_tools/README.fr b/wireless_tools/README.fr
new file mode 100644 (file)
index 0000000..b71dc48
--- /dev/null
@@ -0,0 +1,162 @@
+       Wireless Tools
+       --------------
+
+       Ce paquetage contient les Wireless Tools (Outils Wireless), utilisé pour
+manipuler les Wireless Extensions. Les Wireless Extensions sont une interface
+vous permettant de manier les paramètres spécifiques aux Wireless LAN (réseaux
+sans fil) et d'obtenir les statistiques spécifiques.
+
+page web :
+--------
+       Vous trouverez beaucoup d'informations utiles sur :
+               http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
+               http://web.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
+
+version pré compilée
+--------------------
+       La plupart des distributions Linux fournit un paquetage pré compilé
+contenant ces outils. Et beaucoup d'entre elles les pré installent par défaut.
+Par ailleurs, l'installation de ce paquetage est (maintenant) facile et vous
+permet d'obtenir une version plus Ã  jour.
+
+INSTALL
+-------
+       Ce fichier contient les instructions et les requis pour l'installation.
+       *Doit* Ãªtre lu.
+
+DISTRIBUTION.txt
+----------------
+       Ce fichier documente la manière de configurer les cartes wireless au
+démarrage avec différentes distributions Linux (en utilisant les Wireless
+Extensions). Veuillez le lire attentivement avant de poser des questions.
+       Dans ce fichier, j'essaye de rassembler toutes les spécificités de
+l'intégration des Wireless Extensions dans les ditributions Linux les plus
+courantes. J'ai besoin de votre aide pour compléter ce fichier.
+
+HOTPLUG.txt
+-----------
+       Ce fichier documente la manière de gérer et configurer les cartes
+wireless Ã©jectables utilisant Hotplug. Il est plus avancé que les simples
+procédures de DISTRIBUTIONS.txt. Pour l'instant, il est principalement orienté
+Debian, mais j'espère que vous contribuerez pour d'autres distributions.
+
+PCMCIA.txt
+----------
+       Ce fichier décrit comment utiliser le script init PCMCIA pour configurer
+les Wireless Extensions et comment utiliser les schemes PCMCIA (NDT : procédures
+automatiques).
+
+pages man (iwconfig.8, iwlist.8, iwpriv.8, iwspy.8)
+---------
+       TRÈS IMPORTANT : J'essaye de garder les pages man Ã  jour, ainsi vous
+devriez les lire avant de poser des questions.
+       TRÈS IMPORTANT : Ces pages man décrivent les fonctionnalités des outils,
+pas un périphérique n'en implémente toute l'étendue (et les pilotes en
+implémentent souvent encore moins).
+
+       Pour autant que je sache, les pages man constituent la plus complète, la
+plus Ã  jour et la plus précise des documentations des Wireless Tools. Une mise
+à jour de la page web concernant les Wireless Extensions a Ã©té faite il y a fort
+longtemps. Envoyez-moi vos retours.
+
+       Les pages man peuvent aussi bien Ãªtre copiées dans un endroit où la
+commande Â« man Â» les trouvera, comme /usr/local/man/man8, ou peut Ãªtre lue
+localement avec la commande :
+               nroff -man xxx.8 | less
+(NDT : ou plus simplement avec Â« man ./xxx.8 Â»)
+
+pages man localisées (fr/*)
+--------------------
+       Les pages de man localisées ne sont pas Ã©crites par moi (NDT\ : ainsi
+que ce document), par conséquent les seules disponibles sont celles qui me sont
+envoyées par de courageux volontaires et il faut s'attendre Ã  ce que ces pages
+man soient en décalage par rapport Ã  la version anglaise (c.-à-d. qu'elles
+n'aient pas toutes les mises Ã  jour). La traduction des pages man n'est pas une
+tâche très gratifiante, sans compter mon anglais bancal et un certain nombre
+de termes techniques difficilement traduisibles vers d'autres langues, donc
+référez-vous Ã  la version anglaise en cas de doute.
+
+iwconfig.c
+----------
+       L'outil wireless principal. Utilisé pour la configuration du matériel et
+pour voir les paramètres wireless les plus communs.
+
+iwlist.c
+--------
+       Affiche une grosse quantité d'information qui ne l'est pas par iwconfig.
+       Par exemple, tous les débits, toutes les fréquences, toutes les clefs...
+
+iwspy.c
+-------
+       Test de support Mobile IP et autorise la récupération de statistiques
+par adresse MAC (au lieu des stats globales). Aussi, pour certains
+pilotes/périphériques, c'est la seule manière d'obtenir des stats en mode
+Ad-Hoc.
+
+iwpriv.c
+--------
+       Manipule les ioctls privées des pilotes (« driver private ioctls Â») :
+tous les paramètres qui sont spécifiques Ã  un pilote ou Ã  un périphérique et
+qui, par conséquent, ne font pas partie de iwconfig.
+
+iwgetid.c
+---------
+       Affiche l'ESSID ou le NWID du périphérique spécifié.
+       Peut aussi l'afficher dans un format pouvant Ãªtre utilisé comme un
+« PCMCIA Scheme Â».
+
+iwevent.c
+---------
+       Affiche les Â« Wireless Events Â» (Événements Wireless). Cela est
+nouveau, il n'y a donc pas encore beaucoup de pilotes qui le supportent...
+
+ifrename.c :
+----------
+       Renomme les interfaces réseau basées sur différents attributs.
+
+iwlib.c
+-------
+       Les librairies Â« helper Â» Wireless Tools. Peuvent Ãªtre utiles si vous
+voulez créer votre propre application en utilisant les Wireless Extensions.
+
+Changelog, contributions :
+------------------------
+       Voir CHANGELOG.h
+
+wireless.h
+----------
+       Définition des Wireless Extensions. Gardez Ã  l'esprit que la définition
+utilisée par les pilotes et les outils (Wireless Tools) doivent correspondre,
+sinon de drôles de choses peuvent arriver. Les outils essayent de le vérifier.
+       Depuis les Wireless Extensions v12, vous ne pouvez plus mettre ce
+fichier dans les entêtes de votre noyau pour mettre Ã  jour les Wireless
+Extensions, vous avez besoin d'utiliser les patches complets disponibles sur ma
+page web. Donc, son utilité est plus pour le cas où vous prévoyez de faire de
+la compilation transverse (if you plan to do some Â« cross compile Â») ou quelque
+chose de similaire.
+Juste pour votre plaisir, il y en a différentes versions. Si vos noyau/pilotes
+sont anciens, vous voudrez peut-être essayer les anciennes versions...
+
+sample_xxx.c :
+------------
+       Différents Ã©chantillons de code montrant comment implémenter quelques
+unes des caractéristiques les plus intéressantes des Wireless Extensions dans
+votre pilote.
+       Notez qu'il n'y a pas d'assurance que ce code compile, laissez-le tel
+quel, mais cela devrait vous orienter dans la bonne direction.
+       Aussi, jetez un Â½il aux pilotes existant dans le noyau Linux.
+
+Autres outils :
+-------------
+       Ma page web liste bien d'autres outils utilisant les Wireless
+Extensions que vous pourriez trouver utiles...
+       http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html#links
+
+Autres questions :
+----------------
+       Vous avez le source, et il est documenté. Dans 99% des cas, vous y
+trouverez votre réponse.
+
+       Bonne chance...
+
+       Jean <jt@hpl.hp.com>
diff --git a/wireless_tools/fr/ifrename.8 b/wireless_tools/fr/ifrename.8
new file mode 100644 (file)
index 0000000..f3b9fd4
--- /dev/null
@@ -0,0 +1,147 @@
+.\" Jean II - HPL - 2004
+.\" ifrename.8
+.\"
+.\" Traduction 2004/08/25 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction        : version 27-pre25
+.TH IFRENAME 8 "01 mars 2004" "wireless-tools" "Manuel du programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+ifrename \- renomme les interfaces réseau basées sur différents critères
+statiques
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.B "ifrename [-c configfile] [-p] [-d]"
+.br
+.B "ifrename [-c configfile] [-i interface] [-n newname]"
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B Ifrename
+est un outil vous permettant d'assigner un nom cohérent Ã  chacune de vos
+interfaces réseau.
+.PP
+Par défaut, les noms d'interface sont dynamiques, et Ã  chaque interface réseau
+est assigné le premier nom disponible
+.RI ( eth0 ", " eth1 "...)."
+L'ordre dans lequel les interfaces réseau sont créées peut varier. Pour les
+interfaces fixes («\ built-in interfaces\ Â»), l'énumération du noyau au
+démarrage peut varier. Pour les interfaces débranchables, l'utilisateur peut les
+brancher dans n'importe quel ordre.
+.PP
+.B Ifrename
+permet Ã  l'utilisateur de décider quel nom une interface réseau aura.
+.B Ifrename 
+peut utiliser différents sélecteurs
+.RI "(«\ " selectors "\ Â»)"
+pour spécifier comment les noms d'interface correspondent aux interfaces réseau
+du système, le plus commun des sélecteurs Ã©tant
+.RI "l'" "adresse MAC"
+de l'interface.
+.PP
+.B Ifrename
+doit Ãªtre lancé avant que les interfaces ne soient démarrées, raison pour
+laquelle il est surtout utile dans divers scripts (init, hotplug), mais il est
+rarement utilisé directement par l'utilisateur. Par défaut,
+.B ifrename 
+renomme toutes les interfaces système présentes en utilisant les correspondances
+définies dans
+.IR /etc/iftab .
+.\"
+.\" PARAMETER part
+.\"
+.SH PARAMÈTRES
+.TP
+.BI "-c " configfile
+Fixe le fichier de configuration Ã  utiliser (par défaut
+.IR /etc/iftab ).
+Le fichier de configuration définit la correspondance entre les sélecteurs et
+les noms d'interface, et il est décrit dans
+.IR iftab (5).
+.br
+Si
+.I configfile
+est Â«\ -\ Â», la configuration est lue depuis stdin.
+.TP
+.B -p
+Sonde (charge) les modules noyau avant de renommer les interfaces. Par
+défaut,
+.B ifrename 
+vérifie seulement les interfaces déjà chargées, et ne charge pas
+automatiquement les modules noyau requis. Cette option autorise une intégration
+en douceur dans les systèmes qui ne chargent pas les modules avant d'appeler
+.BR ifrename .
+.TP
+.B -d
+Active divers bidouillages spécifiques Ã  la
+.BR Debian .
+Combiné avec
+.BR -p ,
+seuls les modules pour les interfaces spécifiées dans
+.I /etc/network/interface
+sont chargés.
+.TP
+.BI "-i " interface
+Renomme seulement
+.RI "l'" interface 
+spécifiée, par opposition Ã  toutes les interfaces présentes sur le système. Le
+nouveau nom de l'interface est affiché.
+.TP
+.BI "-n " newname
+Si utilisé avec
+.IR -i ,
+spécifie le nouveau nom de l'interface. La liste des correspondances depuis le
+fichier de configuration est ignorée. Le nouveau nom peut Ãªtre un joker
+(«\ wildcard\ Â») qui contient une seule '*'.
+.TP
+.B -t
+Active l'absorption («\ takover\ Â») de nom. Cela permet d'échanger un nom
+d'interface entre deux interfaces ou plus.
+.br
+L'absorption permet Ã  une interface de Â«\ voler\ Â» le nom d'une autre
+interface. Cela fonctionne seulement avec le noyau 2.6.X et si l'autre
+interface est désactivée. En conséquence, ce n'est pas compatible avec Hotplug.
+L'autre interface se voit assigner un nom aléatoire, mais peut Ãªtre renommée
+plus tard avec 'ifrename'.
+.br
+Le nombre d'absorptions est limité pour Ã©viter les boucles circulaires, et donc
+certaines situations d'échanges de noms complexes ne seront pas complètement
+traitées.
+.br
+Dans tous les cas, l'échange de noms et l'utilisation de cette caractéristique
+sont découragés, et vous Ãªtes invités Ã  choisir des noms uniques et sans
+ambiguïté pour vos interfaces...
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTEUR
+Jean Tourrilhes \- jt@hpl.hp.com
+.\"
+.\" TRADUCTION part
+.\"
+.SH TRADUCTION
+Maxime CHARPENNE, août 2004 (wireless_tools.27-pre25).
+.\"
+.\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+.\"
+.\" FILES part
+.\"
+.SH FICHIERS
+.I /etc/iftab
+.\"
+.\" SEE ALSO part
+.\"
+.SH VOIR AUSSI
+.BR ifconfig (8),
+.BR ip (8),
+.BR iftab (5).
diff --git a/wireless_tools/fr/iftab.5 b/wireless_tools/fr/iftab.5
new file mode 100644 (file)
index 0000000..21c8936
--- /dev/null
@@ -0,0 +1,196 @@
+.\" Jean II - HPL - 2004
+.\" iftab.5
+.\"
+.\" Traduction 2004/08/25 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction        : version 27-pre25
+.\"
+.TH IFTAB 5 "01 mars 2004" "wireless-tools" "Manuel du Programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+iftab \- informations statiques sur les interfaces réseau
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+Le fichier
+.B /etc/iftab
+contient de l'information descriptive Ã  propos des diverses interfaces réseau.
+.B iftab
+n'est utilisé que par le programme
+.IR ifrename (8)
+pour assigner un nom d'interface réseau cohérent Ã  chaque interface réseau.
+.PP
+.B /etc/iftab
+définit un ensemble de
+.RI "correspondances («\ " mappings "\ Â»)."
+Chaque correspondance contient un nom d'interface et un ensemble de sélecteurs
+(«\ selectors\ Â»). Les sélecteurs permettent Ã 
+.B ifrename
+d'identifier chaque interface réseau du système. Si une interface réseau
+correspond Ã  tous les descripteurs d'une correspondance,
+.B ifrename
+essaye de changer le nom de l'interface par le nom de l'interface donné dans la
+correspondance.
+.\"
+.\" MAPPINGS part
+.\"
+.SH CORRESPONDANCES («\ MAPPINGS\ Â»)
+Chaque correspondance est décrite sur une ligne distincte, elle commence avec
+.IR "interface name" " (nom d'interface),"
+et contient un ensemble de
+.RI "descripteurs («\ " descriptors "\ Â»),"
+séparés par des espaces ou des tabulations.
+.PP
+La relation entre les descripteurs d'une correspondance est un
+.IR "et logique" .
+Une correspondance s'applique Ã  une interface réseau seulement si tous les
+descripteurs s'appliquent. Si une interface réseau ne supporte pas un
+descripteur particulier, elle ne s'appliquera Ã  aucune correspondance qui
+utilise ce descripteur.
+.PP
+Si vous voulez utiliser des descripteurs alternatifs pour un nom d'interface
+(ou logique), spécifiez deux correspondances différentes avec le même nom
+d'interface (une par ligne).
+.B Ifrename
+utilise toujours la première correspondance en commençant par la
+.I fin
+de
+.BR iftab ,
+donc les correspondances les plus restrictives devraient Ãªtre définies en
+dernier.
+.\"
+.\" INTERFACE NAME part
+.\"
+.SH NOM D'INTERFACE
+La première partie de chaque correspondance est un nom d'interface. Si une
+interface réseau correspond Ã  tous les descripteurs d'une correspondance,
+.B ifrename
+essaye de changer le nom de l'interface par le nom de l'interface donné dans la
+correspondance.
+.PP
+Le nom de l'interface d'une correspondance est soit un nom d'interface complet
+(comme
+.IR eth2 " ou " wlan0 )
+ou un motif de nom d'interface contenant un seul caractère joker (comme
+.IR eth* " ou " wlan* ).
+Dans le cas d'un caractère joker («\ wildcard\ Â»), le noyau remplace le
+caractère '*' par le plus petit entier disponible faisant un nom d'interface
+unique.
+.\"
+.\" DESCRIPTORS part
+.\"
+.SH DESCRIPTEURS («\ DESCRIPTORS\ Â»)
+Chaque descripteur est composé d'un nom de descripteur et d'une valeur de
+descripteur. Les descripteurs définissent un attribut statique d'une interface
+réseau, le but Ã©tant d'identifier de manière unique chaque périphérique.
+.PP
+La plupart des utilisateurs n'utiliseront que le sélecteur
+.BR mac ,
+les autres sélecteurs Ã©tant pour une configuration plus spécialisée.
+.TP
+.BI mac " adresse mac"
+Correspond Ã  l'Adresse MAC de l'interface avec l'adresse MAC spécifiée.
+L'adresse MAC de l'interface peut Ãªtre montrée en utilisant
+.IR ifconfig (8)
+ou
+.IR ip (8).
+L'adresse MAC spécifiée peut contenir une '*' pour la correspondance joker
+(«\ wildcard matching\ Â»).
+.br
+C'est le plus commun des sélecteurs, vu que chaque interface possède une
+adresse MAC unique, ce qui permet de les identifier sans ambiguïté.
+.TP
+.BI arp " arp type"
+Fait correspondre le Type ARP («\ ARP Type\ Â») (aussi appelé Â«\ Link Type\ Â»)
+de l'interface avec le type ARP spécifié. Le Type ARP de l'interface peut Ãªtre
+montré en utilisant
+.IR ifconfig (8)
+ou
+.IR ip (8).
+.br
+Ce sélecteur est utile quand un pilote crée plusieurs interfaces réseau pour
+une seule carte réseau.
+.TP
+.BI driver " driver name"
+Fait correspondre le Nom de Pilote («\ Driver Name\ Â») de l'interface avec le
+nom de pilote spécifié. Le Nom de Pilote de l'interface peut Ãªtre montré en
+utilisant
+.IR "ethtool -i" (8).
+.TP
+.BI businfo " bus information"
+Fait correspondre l'Information de Bus («\ Bus Information\ Â») de l'interface
+avec l'information de bus spécifiée. L'Information de Bus de l'interface peut
+être montrée en utilisant
+.IR "ethtool -i" (8).
+.TP
+.BI baseaddress " base address"
+Fait correspondre l'Adresse de Base («\ Base Address\ Â») de l'interface avec
+l'adresse de base spécifiée. L'Adresse de Base de l'interface peut Ãªtre montrée
+en utilisant
+.IR ifconfig (8).
+.br
+Ce sélecteur n'est utile que pour les cartes ISA et EISA car la plupart des
+cartes utilisent l'allocation dynamique pour l'Adresse de Base.
+.TP
+.BI irq " irq line"
+Fait correspondre la Ligne IRQ (interruption) de l'interface avec la ligne IRQ
+spécifiée. La Ligne IRQ de l'interface peut Ãªtre montrée en utilisant
+.IR ifconfig (8).
+.br
+Ce sélecteur n'est habituellement pas suffisant pour identifier de manière
+unique une interface, car les Lignes IRQ peuvent Ãªtre partagées.
+.TP
+.BI iwproto " wireless protocol"
+Fait correspondre le Protocole Wireless de l'interface avec le protocole
+wireless spécifié. Le Protocole Wireless de l'interface peut Ãªtre montré
+en utilisant
+.IR iwconfig (8).
+.br
+Ce sélecteur n'est valable que pour les interfaces wireless et n'est pas
+suffisant pour en identifier une de manière unique.
+.\"
+.\" EXAMPLE part
+.\"
+.SH EXEMPLE
+# Ceci est un commentaire
+.br
+eth2           mac 08:00:09:DE:82:0E
+.br
+eth3           driver wavelan interrupt 15 baseaddress 0x390
+.br
+eth4           driver pcnet32 businfo 0000:02:05.0
+.br
+air*           mac 00:07:0E:* arp 1
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTEUR
+Jean Tourrilhes \- jt@hpl.hp.com
+.\"
+.\" TRADUCTION part
+.\"
+.SH TRADUCTION
+Maxime CHARPENNE, août 2004 (wireless_tools.27-pre25).
+.\"
+.\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+.\"
+.\" FILES part
+.\"
+.SH FICHIERS
+.I /etc/iftab
+.\"
+.\" SEE ALSO part
+.\"
+.SH VOIR AUSSI
+.BR ifrename (8),
+.BR ifconfig (8),
+.BR ip (8),
+.BR iwconfig (8).
diff --git a/wireless_tools/fr/iwconfig.8 b/wireless_tools/fr/iwconfig.8
new file mode 100644 (file)
index 0000000..9e45759
--- /dev/null
@@ -0,0 +1,569 @@
+.\" Jean II - HPLB - 1996 => HPL - 2004
+.\" iwconfig.8
+.\"
+.\" Traduction 2003/07/15 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction        : version 26
+.\" Mise Ã  jour 2004/01/28 : version 27-pre9 (beta)
+.\" Mise Ã  jour 2004/02/26 : version 27-pre11 (alpha)
+.\" Mise Ã  jour 2004/08/23 : version 27-pre25
+.\"
+.TH IWCONFIG 8 "22 juin 2004" "wireless-tools" "Manuel du programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+iwconfig \- configure une interface réseau sans-fil (wireless)
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.BI "iwconfig [" interface ]
+.br
+.BI "iwconfig " interface " [essid " X "] [nwid " N "] [freq " F "] [channel " C ]
+.br
+.BI "                   [sens " S "] [mode " M "] [ap " A "] [nick " NN ]
+.br
+.BI "                   [rate " R "] [rts " RT "] [frag " FT "] [txpower " T ]
+.br
+.BI "                   [enc " E "] [key " K "] [power " P "] [retry " R ]
+.br
+.BI "                   [commit]
+.br
+.BI "iwconfig --help"
+.br
+.BI "iwconfig --version"
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B Iwconfig
+est similaire Ã 
+.IR ifconfig (8),
+mais est dédié aux interfaces wireless. Il est utilisé pour manier les
+paramètres des interfaces réseaux qui sont spécifiques aux opérations wireless
+(par exemple\ : la fréquence).
+.B Iwconfig
+peut aussi Ãªtre utilisé pour afficher ces paramètres, et les statistiques
+concernant le sans fil (extraites de
+.IR /proc/net/wireless ).
+.PP
+Tous ces paramètres et statistiques dépendent du matériel. Chaque pilote ne
+fournira que quelques uns d'entre eux en fonction du support matériel, et
+l'étendue des valeurs peut changer. Veuillez vous référer aux pages man de
+chaque matériel pour plus de détails.
+.\"
+.\" PARAMETER part
+.\"
+.SH PARAMÈTRES
+.TP
+.B essid
+Positionne le ESSID ( ou Network Name - pour certains produits, il peut aussi
+être désigné comme Domain ID). L'ESSID est utilisé pour identifier les cellules
+qui font partie du même réseau virtuel.
+.br
+Par opposition Ã  l'adresse de l'AP ou au NWID qui définissent une seule cellule,
+l'ESSID définit un groupe de cellules connectées via des répéteurs ou via
+l'infrastructure, où l'utilisateur peut Â«\ roamer\ Â» ou errer de manière
+transprente (c.-à-d. changer de cellule sans perdre sa connexion).
+.br
+Avec certaines cartes, vous pouvez désactiver le contrôle du ESSID (ESSID
+promiscuous) avec
+.IR off " ou " any " (et " on
+pour le réactiver).
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 essid any"
+.br
+.I "   iwconfig eth0 essid ""Mon Reseau""
+.TP
+.BR nwid / domain
+Positionne le Network ID (pour certains produits, il peut aussi Ãªtre appelé
+Domain ID). Comme tous les réseaux sans fil adjacents partagent le même médium,
+ce paramètre est utilisé pour les différencier (créer des réseaux logiques
+colocalisés) et pour identifier des noeuds appartenant Ã  la même cellule.
+.br
+Ce paramètre est seulement utilisé par les matériels antérieurs Ã  802.11, la
+norme 802.11 se servant du ESSID et de l'adresse de l'AP pour cette fonction.
+.br
+Avec certaines cartes, vous pouvez désactiver le contrôle du Network ID (NWID
+promiscuous) avec
+.IR off " (et " on
+pour le réactiver).
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 nwid AB34
+.br
+.I "   iwconfig eth0 nwid off"
+.TP
+.BR freq / channel
+Positionne la fréquence d'exploitation ou canal du périphérique. Une valeur
+inférieure Ã  1\ 000 indique un numéro de canal, une valeur supérieure Ã  1\ 000
+est une fréquence en Hz. Vous pouvez ajouter le suffixe k, M ou G Ã  la valeur
+(par exemple, Â«\ 2.46G\ Â» pour la fréquence 2,46\ GHz), ou ajouter suffisamment
+de Â«\ 0\ Â».
+.br
+Les canaux sont habituellement numérotés Ã  partir de 1, et vous pouvez utiliser
+.IR iwlist (8)
+pour obtenir le nombre total de canaux, lister les fréquences disponibles, et
+afficher le fréquence courante comme un canal.
+Suivants les réglementations, certaines fréquences/canaux peuvent ne pas
+être disponibles.
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 freq 2422000000"
+.br
+.I "   iwconfig eth0 freq 2.422G"
+.br
+.I "   iwconfig eth0 channel 3"
+.TP
+.B sens
+Positionne le seuil de sensibilité. C'est le niveau de signal le plus bas pour
+lequel le matériel essaye de réceptionner un paquet, les signaux plus bas sont
+ignorés. Ceci est utilisé pour Ã©viter de recevoir le bruit de fond, donc vous
+devriez le positionner en fonction du niveau de bruit moyen. Les valeurs
+positives sont supposées Ãªtre les valeurs brutes utilisées par le matériel ou
+un pourcentage, les valeurs négatives sont supposées Ãªtre des dBm.
+.br
+Avec certains matériels, ce paramètre contrôle aussi le seuil de report
+(defer threshold) (signal le plus faible pour lequel le matériel considère le
+canal occupé) et le seuil de cession (handover threshold) (niveau de signal pour
+lequel le matériel commence Ã  chercher un nouveau Point d'Accès).
+.br
+.B Exemple :
+.br
+.I "   iwconfig eth0 sens -80"
+.TP
+.B mode
+Positionne le mode de fonctionnement du matériel, qui dépend de la topologie du
+réseau. Le mode peut Ãªtre
+.I Ad-Hoc
+(réseau composé d'une seule cellule et sans Point d'Accès),
+.I Managed
+(un noeud se connecte Ã  un réseau composé de plusieurs Points d'Accès, avec
+roaming ou errance),
+.I Master
+(le noeud est le maître qui synchronise ou agit comme un Point d'Accès),
+.I Repeater
+(le noeud transmet les paquets entre les autres n½uds wireless),
+.I Secondary
+(le noeud agit comme un maître/répéteur supplémentaire),
+.I Monitor
+(le noeud agit comme un moniteur passif et ne fait que recevoir des paquets) ou
+.IR Auto .
+.br
+.B Exemple :
+.br
+.I "   iwconfig eth0 mode Managed"
+.br
+.I "   iwconfig eth0 mode Ad-Hoc"
+.TP
+.B ap
+Force la carte Ã  s'enregistrer auprès du Point d'Accès donné par l'adresse,
+si c'est possible. Quand la qualité de la connexion devient trop mauvaise,
+le pilote peut revenir en mode automatique (la carte sélectionne le meilleur
+Point d'Accès Ã  portée).
+.br
+Vous pouvez aussi utiliser
+.I off
+pour réactiver le mode automatique sans changer le Point d'Accès courant,
+ou vous pouvez utiliser
+.I any
+ou
+.I auto
+pour forcer la carte Ã  se ré associer avec le meilleur Point d'Accès courant.
+.br
+.B Exemple :
+.br
+.I "   iwconfig eth0 ap 00:60:1D:01:23:45"
+.br
+.I "   iwconfig eth0 ap any"
+.br
+.I "   iwconfig eth0 ap off"
+.TP
+.BR nick [name]
+Positionne le surnom (nickname), ou nom de station. Quelques produits
+802.11 le définissent, mais il n'est pas utilisé dans la mesure où les
+protocoles les plus usités (MAC, IP, TCP) ne s'en servent pas en l'état.
+Seuls quelques outils de diagnostic peuvent l'utiliser.
+.br
+.B Exemple :
+.br
+.I "   iwconfig eth0 nickname ""My Linux Node""
+.TP
+.BR rate / bit [rate]
+Pour les cartes supportant plusieurs débits, positionne le débit en b/s. Le
+débit est la vitesse Ã  laquelle les bits sont transmis sur le médium, la
+vitesse du lien pour l'utilisateur est inférieure Ã  cause du partage du médium
+et des diverses entêtes.
+.br
+Vous pouvez ajouter le suffixe k, M ou G Ã  la valeur (multiplicateur décimal\ :
+10^3, 10^6 et 10^9\ b/s), ou ajouter suffisamment de Â«\ 0\ Â». Les valeurs
+en-dessous de 1000 sont spécifiques Ã  la carte, habituellement un index de la
+liste des débit supportés. Utilisez
+.I auto
+pour sélectionner le mode débit automatique (repli Ã  un débit moindre pour
+les canaux bruités), ce qui est le mode par défaut pour la plupart des cartes,
+et
+.I fixed
+pour revenir Ã  des paramètres fixes. Si vous spécifiez une valeur de débit
+et ajoutez
+.IR auto ,
+le driver utilisera tous les débits inférieurs et Ã©gaux Ã  cette valeur.
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 rate 11M"
+.br
+.I "   iwconfig eth0 rate auto"
+.br
+.I "   iwconfig eth0 rate 5.5M auto"
+.TP
+.BR rts [_threshold]
+RTS/CTS ajoute une Â«\ poignée de main\ Â» avant chaque transmission de paquet
+pour Ãªtre sûr que le canal est libre. Cela ajoute des entêtes (NDT\ : données de
+gestion), mais augmente les performances en cas de n½uds cachés ou
+d'un grand nombre de noeuds actifs. Ce paramètre fixe la taille du plus petit
+paquet pour lequel le noeud envoie un RTS\ ; une valeur Ã©gale Ã  la taille
+maximale des paquets inhibe ce mécanisme. Vous pouvez aussi positionner
+ce paramètre sur
+.IR auto ", " fixed " ou " off .
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 rts 250"
+.br
+.I "   iwconfig eth0 rts off"
+.TP
+.BR frag [mentation_threshold]
+La fragmentation permet de découper un paquet IP en une série de plus petits
+fragments transmis par le médium. Dans la plupart des cas, cela ajoute des
+entêtes, mais dans un environnement très bruité, cela réduit les coûts de
+transmission dus aux erreurs et permet aux paquets d'être acheminés malgré
+des séries d'interférences. Ce paramètre fixe la taille de fragment maximale\ ;
+une valeur Ã©gale Ã  la taille maximale de paquet désactive ce procédé. Vous
+pouvez aussi mettre ce paramètre Ã 
+.IR auto ", " fixed " ou " off .
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 frag 512"
+.br
+.I "   iwconfig eth0 frag off"
+.TP
+.BR key / enc [ryption]
+Utilisé pour manipuler les clefs de cryptage ou brouillage et le mode de
+sécurité.
+.br
+Pour mettre la clef courante de cryptage, il suffit d'entrer la clef
+en hexadécimal telle que
+.IR XXXX-XXXX-XXXX-XXXX " ou " XXXXXXXX .
+Pour entrer une autre clef que la clef courante, ajoutez (au début ou Ã  la
+fin)
+.I [index]
+à la clef elle-même (cela ne changera pas la clef active). Vous pouvez aussi
+entrer la clef comme une chaîne ASCII en utilisant le préfixe
+.IR s: .
+Les phrases en tant que mot de passe ne sont actuellement pas supportées.
+.br
+Pour changer la clef active parmi les clefs déjà entrées, il suffit d'entrer
+.RI l' "[index]"
+(sans entrer de valeur de clef).
+.br
+.IR off " et " on
+désactive et réactive le cryptage.
+.br
+Le mode de sécurité peut Ãªtre
+.I open
+ou
+.IR restricted ,
+et sa signification dépend de la carte utilisée. Avec la plupart des cartes,
+le mode
+.I open
+n'utilise pas d'authentification et la carte accepte des sessions non cryptées,
+alors que le mode
+.I restricted
+n'accepte que des sessions cryptées et la carte utilisera l'authentification
+si disponible.
+.br
+Si vous avez besoin de mettre plusieurs clefs, ou de mettre une clef et de
+changer la clef active, vous avez besoin d'utiliser des instructions Ã  clefs
+.RB ( "key" )
+multiples. Les arguments peuvent Ãªtre mis dans n'importe quel ordre, le
+dernier sera prioritaire.
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 key 0123-4567-89"
+.br
+.I "   iwconfig eth0 key [3] 0123-4567-89"
+.br
+.I "   iwconfig eth0 key s:password [2]"
+.br
+.I "   iwconfig eth0 key [2]"
+.br
+.I "   iwconfig eth0 key open"
+.br
+.I "   iwconfig eth0 key off"
+.br
+.I "   iwconfig eth0 key restricted [3] 0123456789"
+.br
+.I "   iwconfig eth0 key 01-23 key 45-67 [4] key [4]"
+.TP
+.BR power
+Utilisé pour manipuler les paramètres et le mode du procédé de gestion
+d'énergie.
+.br
+Pour fixer la période entre les Ã©veils, entrez la
+.IR "period `valeur'" .
+Pour fixer la temporisation avant le retour en veille, entrez la
+.IR "timeout `valeur'" .
+Vous pouvez aussi ajouter les modificateurs
+.IR min " et " max ".
+Par défaut, ces valeurs sont exprimées en secondes, ajoutez le suffixe m ou u
+pour spécifier les valeurs en millisecondes ou microsecondes. Parfois, ces
+valeurs sont sans unité (nombre de périodes de beacon, dwell ou similaire).
+.br
+.IR off " et " on
+désactive et réactive la gestion d'énergie. Enfin, vous pouvez mettre la
+gestion d'énergie en mode
+.I all
+(reçoit tous les paquets),
+.I unicast
+(reçoit seulement les paquets unicast, ignore les paquets multicast et de
+broadcast) et
+.I multicast
+(reçoit seulement les paquets multicast et de broadcast, ignore l'unicast).
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 power period 2"
+.br
+.I "   iwconfig eth0 power 500m unicast"
+.br
+.I "   iwconfig eth0 power timeout 300u all"
+.br
+.I "   iwconfig eth0 power off"
+.br
+.I "   iwconfig eth0 power min period 2 power max period 4"
+.TP
+.BR txpower
+Pour les cartes supportant plusieurs puissances de transmission, règle la
+puissance de transmission en dBm. Si
+.I W
+est la puissance en Watt, la puissance en dBm est
+.IR "P\ =\ 30\ +\ 10.log(W)" .
+Si la valeur est post fixée par
+.IR mW ,
+elle sera automatiquement convertie en dBm.
+.br
+De plus,
+.IR on " et " off
+active et désactive la radio, et
+.IR auto " et " fixed
+active et désactive le contrôle de puissance (si ces fonctions sont
+disponibles).
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 txpower 15"
+.br
+.I "   iwconfig eth0 txpower 30mW"
+.br
+.I "   iwconfig eth0 txpower auto"
+.br
+.I "   iwconfig eth0 txpower off"
+.TP
+.BR retry
+La plupart des cartes supportent les retransmissions MAC (contrôle d'accès
+au médium), et certaines permettent le paramétrage du mécanisme des tentatives
+(en cas d'échec).
+.br
+Pour fixer le nombre maximum d'essais, entrez
+.IR "limit `valeur'" .
+C'est une valeur absolue (sans unité).
+Pour fixer le temps maximum autorisé au mécanisme MAC pour ses tentatives,
+entrez
+.IR "lifetime `valeur'" .
+Par défaut, cette valeur est en secondes, ajouter le suffixe m ou u pour
+spécifier les valeurs en millisecondes ou microsecondes.
+.br
+Vous pouvez aussi ajouter les modificateurs
+.IR min " et " max ".
+Si la carte supporte le mode automatique, ils définissent les limites du
+lifetime, ou les limites inférieure et supérieure (NDT\ : de l'intervalle
+temporel dans lequel le mécanisme MAC est autorisé Ã  réitérer ses tentatives).
+D'autres cartes définissent des valeurs différentes en fonction de la taille
+des paquets, par exemple la norme 802.11 définit une
+.I min limit
+qui est la limite inférieure d'essai (paquets non RTS/CTS).
+.br
+.B Exemples :
+.br
+.I "   iwconfig eth0 retry 16"
+.br
+.I "   iwconfig eth0 retry lifetime 300m"
+.br
+.I "   iwconfig eth0 retry min limit 8"
+.TP
+.BR commit
+Certaines cartes peuvent ne pas appliquer immédiatement les changements
+effectués par les Wireless Extensions (elles peuvent attendre pour prendre en
+compte les changements ou les appliquer seulement quand la carte est montée via
+ifconfig). Cette commande (si disponible) force la carte Ã  appliquer les
+changements en suspens.
+.br
+Cela n'est normalement pas nécessaire, car la carte appliquera Ã©ventuellement
+les changements, mais peut Ãªtre utile pour débuggage.
+.\"
+.\" DISPLAY part
+.\"
+.SH AFFICHAGE
+Pour chaque matériel qui supporte les extensions wireless,
+.I iwconfig
+affiche le nom du
+.B protocole MAC
+utilisé (nom du matériel pour les protocoles propriétaires),
+.RB l' ESSID
+(Network Name), le
+.BR NWID ,
+la
+.B fréquence
+(ou canal), la
+.BR sensibilité ,
+le
+.B mode
+d'exploitation, l'adresse du
+.BR "Point d'Accès",
+le
+.BR débit ,
+le
+.BR "seuil RTS" " (" "RTS threshold" "), le "
+.BR "seuil de fragmentation" " (" "fragmentation threshold" "), la
+.B clef de cryptage
+et les paramètres de
+.BR "gestion de l'énergie" " (" "power management" ")"
+(en fonction de la disponibilité).
+.PP
+Les paramètres affichés ont la même signification et la même valeur que ceux
+que vous pouvez régler, veuillez vous reporter Ã  la précédente partie pour
+leur explication détaillée.
+.br
+Quelques paramètres sont affichés seulement dans une forme abrégée (comme le
+cryptage). Vous devez utiliser
+.IR iwlist (8)
+pour avoir tous les détails.
+.br
+Certains paramètres ont deux modes (comme le débit). Si la valeur est préfixée
+par
+.RB Â«\ =\ Â»,
+cela veut dire que le paramètre est fixé et forcé Ã  cette valeur, s'il est
+préfixé par
+.RB Â«\ :\ Â»,
+le paramètre est en mode automatique et la valeur courante est montrée (et peut
+changer).
+.TP
+.BR "Access Point" / Cell
+Une adresse Ã©gale Ã  00:00:00:00:00:00 signifie que la carte n'a pas réussi Ã 
+s'associer avec un Point d'Accès (le plus souvent une question de
+configuration).
+Le paramètre
+.B Access Point
+sera montré comme une cellule
+.RB ( Cell )
+en mode ad hoc (pour des raisons Ã©videntes), mais il fonctionne néanmoins
+de la même manière.
+.PP
+Si
+.I /proc/net/wireless
+existe,
+.I iwconfig
+affichera aussi son contenu. Il faut noter que ces valeurs dépendent des
+spécifications du pilote et de la carte, vous devrez donc vous référez Ã  la
+documentation du pilote pour une interprétation correcte de ces valeurs.
+.TP
+.B Link quality
+Qualité globale du lien. Peut Ãªtre basé sur le niveau de contention ou des
+interférences, le taux d'erreur de trame ou de bit, la qualité du signal reçu,
+des synchronisations temporelles, ou autre métrique matérielle. C'est une valeur
+agrégat, et dépend totalement du pilote et du matériel.
+.TP
+.B Signal level
+Force du signal reçu (RSSI - force du signal reçu). Cela peut Ãªtre des unités
+arbitraires ou des dBm,
+.I iwconfig
+utilise des méta-informations du pilote pour interpréter les valeurs
+brutes données par
+.I /proc/net/wireless
+et affiche l'unité ou la valeur maximale correspondante (utilise l'arithmétique
+8 bits). En mode
+.I Ad-Hoc
+cela peut Ãªtre indéfini et vous devriez utiliser
+.IR iwspy .
+.TP
+.B Noise level
+Niveau du bruit de fond (quand aucun paquet n'est transmis). Commentaires
+similaires Ã  ceux de
+.BR "Signal level" .
+.TP
+.B Rx invalid nwid
+Nombre de paquets reçus avec un NWID ou ESSID différent. Utilisé pour détecter
+des problèmes de configuration ou l'existence de réseau adjacent (sur la même
+fréquence).
+.TP
+.B Rx invalid crypt
+Nombre de paquets que le matériel a Ã©té incapable de décrypter. Cela peut Ãªtre
+utilisé pour détecter des mauvais paramètres de cryptage.
+.TP
+.B Rx invalid frag
+Nombre de paquets pour lesquels le matériel a Ã©té incapable de ré-assembler
+correctement les fragments de la couche liaison (le plus souvent, il en manque
+un).
+.TP
+.B Tx excessive retries
+Nombre de paquets que la carte n'a pas réussi Ã  envoyer. La plupart des
+protocoles MAC réessaient un certain nombre de fois avant d'abandonner.
+.TP
+.B invalid misc
+Autres paquets perdus en relation avec les opérations spécifiques au sans fil.
+.TP
+.B Missed beacon
+Nombre de beacons périodiques Ã©mis par la Cellule ou le Point d'Accès que nous
+avons manqué. Les beacons sont envoyés Ã  intervalles réguliers pour maintenir la
+coordination de la cellule, l'impossibilité de les recevoir indiquant souvent
+que la carte est hors de portée.
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTEUR
+Jean Tourrilhes \- jt@hpl.hp.com
+.\"
+.\" TRADUCTION part
+.\"
+.SH TRADUCTION
+Maxime CHARPENNE, août 2004 (wireless_tools.27-pre25).
+.\"
+.\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+.\"
+.\" FILES part
+.\"
+.SH FICHIERS
+.I /proc/net/wireless
+.\"
+.\" SEE ALSO part
+.\"
+.SH VOIR AUSSI
+.BR ifconfig (8),
+.BR iwspy (8),
+.BR iwlist (8),
+.BR iwevent (8),
+.BR iwpriv (8),
+.BR wireless (7).
diff --git a/wireless_tools/fr/iwevent.8 b/wireless_tools/fr/iwevent.8
new file mode 100644 (file)
index 0000000..d287c8a
--- /dev/null
@@ -0,0 +1,131 @@
+.\" Jean Tourrilhes - HPL - 2002 - 2004
+.\" iwevent.8
+.\"
+.\" Traduction 2003/08/17 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction        : version 26
+.\" Manuel identique pour la version 27-pre9 (beta)
+.\" Mise Ã  jour 2004/02/26 : version 27-pre11 (alpha)
+.\" Mise Ã  jour 2004/08/23 : version 27-pre25
+.\"
+.TH IWEVENT 8 "23 juin 2004" "net-tools" "Manuel du Programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+iwevent \- Affiche les Ã‰vénements Wireless (Wireless Events) générés par les
+pilotes et les changements de paramètres.
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.BI "iwevent "
+.br
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B iwevent
+affiche les Â«\ Wireless Events\ Â» (événements du système Wireless) reçu par le
+socket RTNetlink. Chaque ligne affiche le Wireless Event spécifique qui décrit
+ce qui s'est passé sur l'interface sans fil spécifiée.
+.br
+Cette commande ne prend aucun argument.
+.\"
+.\" DISPLAY part
+.\"
+.SH AFFICHAGE
+Il y a deux classes de Wireless Events.
+.PP
+La première classe regroupe les Ã©vénements relatifs Ã  un changement des
+paramètres du sans fil sur l'interface (typiquement fait par
+.B iwconfig
+ou un script appelant
+.BR iwconfig ).
+Seuls les paramètres qui peuvent entraîner une perturbation de la connectivité
+sont rapportés. Les Ã©vénements actuellement rapportés changent un des paramètres
+suivants\ :
+.br
+.I "   Network ID"
+.br
+.I "   ESSID"
+.br
+.I "   Frequency"
+.br
+.I "   Mode"
+.br
+.I "   Encryption"
+.br
+Tous ces Ã©vénements seront générer sur toutes les interfaces sans fil par le
+sous-système Â«\ wireless\ Â» du noyau (mais seulement si le pilote a Ã©té converti
+àl'API du nouveau pilote).
+.PP
+La deuxième classe d'événements concerne ceux générés par le matériel, lorsque
+quelque chose arrive ou qu'une tâche s'est terminée. Ces Ã©vénements incluent\ :
+.TP
+.B New Access Point/Cell address
+L'interface a joint un nouveau point d'accès ou cellule ad hoc, ou perdu son
+association avec. Il s'agit de la même adresse MAC affiché par
+.BR iwconfig .
+.TP
+.B Scan request completed
+Une requête de balayage (scanning) a Ã©té achevée, les résultats du Â«\ scan\ Â»
+sont disponibles (voir
+.BR iwlist ).
+.TP
+.B Tx packet dropped
+Un paquet Ã  destination de cette adresse a Ã©té rejeté car l'interface croit que
+ce noeud ne répond plus (habituellement, le seuil maximum des Ã©missions de la
+couche MAC est atteint). C'est habituellement la première indication pouvant
+révéler que le noeud a quitté la cellule ou est hors de portée, mais cela peut
+être due Ã  une atténuation ou une contention excessive.
+.TP
+.B Custom driver event
+Événement spécifique au pilote. Veuillez consulter la documentation du pilote.
+.TP
+.B Registered node
+L'interface a réussi Ã  enregistrer un nouveau client/paire sans fil. Sera
+généré la plupart du temps quand l'interface agit comme un point d'accès (mode
+master).
+.TP
+.B Expired node
+L'enregistrement d'un client/paire sur cette interface a expiré. Sera généré la
+plupart du temps quand l'interface agit comme un point d'accès (mode master).
+.TP
+.B Spy threshold crossed
+La force du signal pour une des adresses de la Â«\ spy list\ Â» (NDT\ : voir
+iwspy(8)) est passé en-dessous du seuil bas, ou est passé au-dessus du seuil
+haut.
+.PP
+La plupart des pilotes wireless génèrent seulement un sous-ensemble de ces
+événements, pas tous, la liste exacte dépendant de la combinaison spécifique
+matériel/pilote. Veuillez consulter la documentation du pilote pour les détails
+de ce qui les génèrent, et utilisez
+.IR iwlist (8)
+pour vérifier ce que le pilote supporte.
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTEUR
+Jean Tourrilhes \- jt@hpl.hp.com
+.\"
+.\" TRADUCTION part
+.\"
+.SH TRADUCTION
+Maxime CHARPENNE, août 2004 (wireless_tools.27-pre25).
+.\"
+\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+.\"
+.\" SEE ALSO part
+.\"
+.SH VOIR AUSSI
+.BR iwconfig (8),
+.BR iwlist (8),
+.BR iwspy (8),
+.BR iwpriv (8),
+.BR wireless (7).
diff --git a/wireless_tools/fr/iwgetid.8 b/wireless_tools/fr/iwgetid.8
new file mode 100644 (file)
index 0000000..3512ddb
--- /dev/null
@@ -0,0 +1,136 @@
+.\" Guus Sliepen - 2001
+.\" Completed and fixed up by Jean Tourrilhes - 2002-2003
+.\" iwgetid.8
+.\"
+.\" Traduction 2003/08/17 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction        : version 26
+.\" Mise Ã  jour 2004/01/29 : version 27-pre9 (beta)
+.\" Manuel identique pour la version 27-pre11 (alpha)
+.\" Mise Ã  jour 2004/08/23 : version 27-pre25
+.\"
+.TH IWGETID 8 "02 décembre 2003" "wireless-tools" "Manuel du Programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+iwgetid \- Rapporte le ESSID, NWID ou l'Adresse de l'AP/Cell (Point d'Accès/\
+Cellule) du réseau sans fil.
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.BI "iwgetid " [interface] " [--raw] [--scheme] [--ap] [--freq]"
+.br
+.BI "                    [--mode] [--protocol] [--channel]
+.br
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B iwgetid
+est utilisé pour trouver le NWID, ESSID ou l'adresse de l'AP ou cellule du
+réseau sans fil utilisé présentement. L'information rapportée est la même
+que celle montrée par
+.BR iwconfig ", mais " iwgetid
+est plus facile Ã  intégrer dans les scripts.
+.br
+Par défaut,
+.B iwgetid
+affichera
+.RI l' ESSID
+de la carte, et si la carte n'a pas d'ESSID, il affichera son
+.IR NWID .
+.br
+Le formatage par défaut de la sortie est embelli.
+.\"
+.\" OPTIONS part
+.\"
+.SH OPTIONS
+.TP
+.B --raw
+Cette option désactive l'embellissement de l'affichage de l'information. Cette
+option est orthogonale aux autres options (sauf
+.BR --scheme ),
+donc, avec la combinaison appropriée des options, il est possible d'afficher
+en brut l'ESSID, l'Adresse de l'AP ou le Mode.
+.br
+Ce format est idéal quand on stocke le résultat de iwgetid comme une variable
+dans les scripts
+.I Shell
+ou
+.IR Perl ,
+ou pour passer le résultat comme argument sur la ligne de commande de
+.BR iwconfig .
+.TP
+.B --scheme
+Cette option est similaire Ã  la précédente, elle désactive l'embellissement de
+l'affichage des données et supprime tous les caractères non alphanumériques
+(comme les caractères d'espacement, la ponctuation et les caractères de
+contrôle).
+.br
+La sortie résultante est un identifiant Pcmcia valide («\ Pcmcia scheme
+identifer\ Â») (qui peut Ãªtre utilisé comme argument de la commande
+.BR "cardctl scheme" ).
+Ce format est aussi idéal quand on utilise le résultat de iwgetid comme un
+sélecteur («\ selector\ Â») dans les scripts
+.I Shell
+ou
+.IR Perl ,
+ou comme un nom de fichier.
+.TP
+.B --ap
+Affiche l'adresse MAC du
+.I Point d'Access
+ou de la
+.I Cellule
+sans fil.
+.TP
+.B --freq
+Affiche la
+.I fréquence
+ou le
+.I canal
+courant utilisé par l'interface.
+.TP
+.B --channel
+Affiche le canal
+.RI ( channel )
+courant utilisé par l'interface. Le canal est déterminé en utilisant la
+fréquence courante et la liste de fréquence fournie par l'interface.
+.TP
+.B --mode
+Affiche le
+.I mode
+courant de l'interface.
+.TP
+.B --protocol
+Affiche le
+.I nom de protocole
+de l'interface. Il permet d'identifer toutes les cartes qui sont compatibles
+entre elles et qui acceptent le même type de configuration.
+.br
+Cela peut aussi Ãªtre utilisé pour
+.I vérifier la compatibilité de Wireless Extension
+sur l'interface, car c'est le seul attribut que tous les pilotes supportant
+Wireless Extension doivent avoir.
+.\"
+.\" TRADUCTION part
+.\"
+.SH TRADUCTION
+Maxime CHARPENNE, août 2004 (wireless_tools.27-pre25).
+.\"
+\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+.\"
+.\" SEE ALSO part
+.\"
+.SH VOIR AUSSI
+.BR iwconfig (8),
+.BR ifconfig (8),
+.BR iwspy (8),
+.BR iwpriv (8).
diff --git a/wireless_tools/fr/iwlist.8 b/wireless_tools/fr/iwlist.8
new file mode 100644 (file)
index 0000000..26eb5c2
--- /dev/null
@@ -0,0 +1,145 @@
+.\" Jean II - HPLB - 96
+.\" iwlist.8
+.\"
+.\" Traduction 2003/08/17 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction        : version 26
+.\" Mise Ã  jour 2004/01/29 : version 27-pre9 (beta)
+.\" Manuel identique pour la version 27-pre11 (alpha)
+.\" Mise Ã  jour 2004/08/23 : version 27-pre25
+.\"
+.TH IWLIST 8 "23 juin 2004" "wireless-tools" "Manuel du Programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+iwlist \- Obtient plus d'informations wireless détaillées depuis une interface wireless
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.BI "iwlist " interface " scanning"
+.br
+.BI "iwlist " interface " frequency"
+.br
+.BI "iwlist " interface " rate"
+.br
+.BI "iwlist " interface " key"
+.br
+.BI "iwlist " interface " power"
+.br
+.BI "iwlist " interface " txpower"
+.br
+.BI "iwlist " interface " retry"
+.br
+.BI "iwlist " interface " event"
+.br
+.BI "iwlist --help"
+.br
+.BI "iwlist --version"
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B Iwlist
+est utilisé pour afficher de l'information additionnelle d'une interface réseau
+wireless qui n'est pas affichée par
+.IR iwconfig (8)
+L'argument principal est utilisé pour sélectionner une catégorie d'information,
+.B iwlist
+affiche dans une forme détaillée toute information relative Ã  cette catégorie,
+y compris les informations déjà montrées par
+.IR iwconfig (8).
+.\"
+.\" PARAMETER part
+.\"
+.SH PARAMÈTRES
+.TP
+.BR scan [ning]
+Donne la liste des Points d'Accès et des cellules Ad-Hoc Ã  portée, et
+optionnellement plein d'autres informations Ã  leur propos (ESSID, Quality,
+Frequency, Mode...). Le type d'information retourné dépend de ce que la carte
+supporte.
+.br
+Le Â«\ Triggering scanning\ Â» est une opération nécessitant les privilèges
+de
+.I root
+et les utilisateurs normaux peuvent juste lire les résultats («\ letf-over scan
+results\ Â»). Par défaut, les paramètres courants du pilote auront une grande
+incidence sur la manière dont le scan est réalisé (la boucle du scan). Aussi,
+cette commande est supposée prendre des arguments supplémentaires pour contrôler
+le comportement du scan, mais cela n'est actuellement pas implémenté.
+.TP
+.BR freq [uency]/ channel
+Donne la liste des fréquences disponibles du périphérique et le nombre de canaux
+définis. Veuillez noter que, habituellement, le pilote retourne le nombre total
+de canaux et seulement les fréquences disponibles dans la région considérée,
+donc il n'y a pas correspondance entre le nombre de fréquences affichées et le
+nombre de canaux.
+.TP
+.BR rate / bit [rate]
+Liste les débits supportés par le périphérique (en b/s).
+.TP
+.BR key / enc [ryption]
+Liste les tailles des clefs de cryptage supportées et affiche toutes
+les clefs de cryptage disponibles dans le périphérique.
+.TP
+.B power
+Liste les divers attributs et modes d'économie d'énergie («\ Power
+Management\ Â») du périphérique.
+.TP
+.B txpower
+Liste les différentes puissances d'émission («\ Transmit Powers\ Â»)
+disponibles dans le périphérique.
+.TP
+.B retry
+Liste les limites des tentatives de transmissions («\ transmit retry limits\ Â»)
+et la durée de vie des tentatives («\ retry lifetime\ Â») du périphériques
+(NDT\ : voir la section
+.B retry
+de iwconfig(8)).
+.TP
+.BR ap / accesspoint / peers
+Donne la liste des Points d'Accès Ã  portée, et optionnellement la qualié de leur
+lien. Cette option est
+.B obsolète
+et est maintenant dépréciée en faveur du support scan (voir ci-dessus), et la
+plupart des pilotes ne le supporte pas.
+.br
+Quelques pilotes peuvent utiliser cette commande pour retourner une
+liste spécifique de Paires («\ Peers\ Â») ou de Points d'Accès, telle que la
+liste des Paires associés/enregistrés avec la carte. Voir la documentation du
+pilote pour plus de détails.
+.TP
+.B event
+Liste les Ã©vénements wireless supportés par le périphérique.
+.TP
+.B --version
+Affiche la version des outils, ainsi que la version courante et recommandée des
+Wireless Extensions pour l'outil et les diverses interfaces sans fil.
+.\"
+.\" TRADUCTION part
+.\"
+.SH TRADUCTION
+Maxime CHARPENNE, août 2004 (wireless_tools.27-pre25).
+.\"
+\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+.\"
+.\" FILES part
+.\"
+.SH FICHIERS
+.I /proc/net/wireless
+.\"
+.\" SEE ALSO part
+.\"
+.SH VOIR AUSSI
+.BR iwconfig (8),
+.BR iwspy (8).
+.BR iwevent (8),
+.BR iwpriv (8),
+.BR wireless (7).
diff --git a/wireless_tools/fr/iwpriv.8 b/wireless_tools/fr/iwpriv.8
new file mode 100644 (file)
index 0000000..5df5220
--- /dev/null
@@ -0,0 +1,156 @@
+.\" Jean II - HPLB - 96
+.\" iwpriv.8
+.\"
+.\" Traduction 2003/08/17 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction     : version 26
+.\" Manuel identique pour version 27-pre9 (beta)
+.\" Manuel identique pour version 27-pre11 (alpha)
+.\"
+.TH IWPRIV 8 "31 octobre 1996" "net-tools" "Manuel du programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+iwpriv \- configure les paramètres optionnels (privés) d'une interface réseau
+sans fil
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.BI "iwpriv [" interface ]
+.br
+.BI "iwpriv " "interface private-command " "[" private-parameters ]
+.br
+.BI "iwpriv " "interface private-command [I] " "[" private-parameters ]
+.br
+.BI "iwpriv " interface " --all"
+.br
+.BI "iwpriv " interface " roam " {on,off}
+.br
+.BI "iwpriv " interface " port " {ad-hoc,managed,N}
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B Iwpriv
+est l'outil Ã  utiliser avec
+.IR iwconfig (8).
+.B Iwpriv
+traite les paramètres et attributs spécifiques Ã  chaque pilote (contrairement
+à
+.I iwconfig
+qui ne s'occupe que des génériques).
+.PP
+Sans argument,
+.B iwpriv
+liste les commandes privées disponibles sur chaque interface, ainsi que les
+paramètres qu'elles requièrent. En utilisant ces informations, l'utilisateur
+peut appliquer ces commandes particulières sur les interfaces spécifiées.
+.PP
+En théorie, la documentation de chaque pilote devrait indiquer comment utiliser
+ces commandes spécifiques et leurs effets.
+.\"
+.\" PARAMETER part
+.\"
+.SH PARAMÈTRES
+.TP
+.IR private-command " [" private-parameters ]
+Exécute la
+.I private-command
+(commande privée) spécifiée sur l'interface.
+.br
+La commande peut Ã©ventuellement prendre ou nécessiter des arguments, et peut
+afficher de l'information. En conséquent, les paramètres de la ligne de
+commande peuvent ou peuvent ne pas Ãªtre nécessaires et doivent correspondre
+aux besoins de la commande. La liste des commandes que
+.B iwpriv
+affiche (quand il est appelé sans paramètre) doit vous donner des indications
+sur ces paramètres.
+.br
+Cependant, vous devriez vous reporter Ã  la documentation du pilote du
+périphérique pour utiliser les commandes correctement, ainsi que connaître
+leurs effets.
+.TP
+.I "private-command [I]" "[" private-parameters ]
+Idem, sauf que
+.I I
+(un entier) est passé Ã  la commande en tant que
+.I "Token Index"
+(indication d'index). Seules quelques commandes utiliseront ce Â«\ Token
+Index\ Â» (la plupart l'ignoreront), et la documentation du pilote devrait
+préciser quand il est nécessaire.
+.TP
+.BR -a / --all
+Exécute et affiche toutes les commandes privées qui ne prennent aucun argument
+(c.-à-d. en lecture seule).
+.TP
+.B roam
+Active ou désactive le Â«\ roaming\ Â», s'il est supporté. Appelle la commande
+privée
+.IR setroam .
+Trouvé dans le pilote
+.I wavelan_cs
+.TP
+.B port
+Lit ou configure le type de port. Appelle les commandes privées
+.IR gport_type ", " sport_type ", " get_port " ou " set_port
+trouvées dans les pilotes
+.IR wavelan2_cs " et " wvlan_cs .
+.\"
+.\" DISPLAY part
+.\"
+.SH AFFICHAGE
+Pour chaque matériel qui supporte les commandes privées,
+.I iwpriv
+affichera la liste des commandes privées disponibles.
+.PP
+Cela inclut le nom de la commande privée, le nombre d'arguments qui peuvent
+être entrés et leur type, ainsi que le nombre d'arguments qui peuvent Ãªtre
+affichés et leur type.
+.PP
+Par exemple, vous pouvez avoir l'affichage suivant\ :
+.br
+.B "eth0      Available private ioctl :"
+.br
+.B "          setqualthr (89F0) : set   1 byte & get   0"
+.br
+.B "          gethisto (89F7) : set   0      & get  16 int"
+.PP
+Cela veut dire que vous pouvez fixer le seuil de qualité et afficher un
+histogramme jusqu'à 16 valeurs avec les commandes suivantes\ :
+.br
+.I "  iwpriv eth0 setqualthr 20"
+.br
+.I "  iwpriv eth0 gethisto"
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTHOR
+Jean Tourrilhes \- jt@hpl.hp.com
+.\"
+.\" TRADUCTION part
+.\"
+.SH TRADUCTION
+Maxime CHARPENNE, août 2003.
+.\"
+\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+.\"
+.\" FILES part
+.\"
+.SH FILES
+.I /proc/net/wireless
+.\"
+.\" SEE ALSO part
+.\"
+.SH SEE ALSO
+.BR iwconfig (8),
+.BR iwlist (8),
+.BR iwevent (8),
+.BR iwspy (8),
+.BR wireless (7).
diff --git a/wireless_tools/fr/iwspy.8 b/wireless_tools/fr/iwspy.8
new file mode 100644 (file)
index 0000000..3bd4e15
--- /dev/null
@@ -0,0 +1,116 @@
+.\" Jean II - HPLB - 96
+.\" iwspy.8
+.\"
+.\" Traduction 2003/08/18 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction        : version 26
+.\" Manuel identique pour la version 27-pre9 (beta)
+.\" Manuel identique pour la version 27-pre11 (alpha)
+.\"
+.TH IWSPY 8 "31 octobre 1996" "net-tools" "Manuel du Programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+iwspy \- Obtenir des statistiques wireless depuis des n½uds donnés
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.BI "iwspy " interface
+.br
+.BI "iwspy " interface " [+] " DNSNAME " | " IPADDR " | " HWADDR " [...]"
+.br
+.BI "iwspy " interface " off"
+.br
+.BI "iwspy " interface " setthr " "low high"
+.br
+.BI "iwspy " interface " getthr"
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B Iwspy
+est utilisé pour fixer une liste d'adresses sur une interface réseau sans fil,
+et obtenir des informations sur la qualité du lien pour chacune d'elles. Ces
+informations sont les mêmes que celles disponibles dans
+.IR /proc/net/wireless "\ :"
+qualité du lien, force du signal et niveau du bruit.
+.PP
+Ces informations sont mises Ã  jour Ã  chaque fois qu'un nouveau paquet est reçu,
+donc chaque adresse de la liste ajoute quelques précisions en plus.
+.PP
+Remarquez que cette fonctionnalité ne marche que pour les n½uds faisant partie
+des cellules sans fil courantes.
+.\"
+.\" PARAMETER part
+.\"
+.SH PARAMÈTRES
+Vous pouvez fixer jusqu'à 8 adresses.
+.TP
+.BR DNSNAME " | " IPADDR
+Paramètre une adresse IP, ou dans certains cas un nom DNS (en utilisant le
+«\ resolver\ Ã‚» de nom). Comme le matériel fonctionne avec des adresses
+matérielles,
+.B iwspy
+traduira les adresses IP grâce Ã 
+.IR ARP .
+Dans certains cas, cette adresse peut ne pas Ãªtre dans le cache ARP et
+.B iwspy
+échouera. Dans cette situation, exécuter
+.IR ping (8)
+vers ces noms/adresses et réessayer.
+.TP
+.B HWADDR
+Paramètre une adresse matérielle (MAC) (cette adresse n'est pas traduite et
+vérifer comme le sont les adresses IP). L'adresse doit contenir deux-points
+.RB ( : )
+pour Ãªtre reconnue comme une adresse matérielle.
+.TP
+.B +
+Ajoute un nouveau jeu d'adresses Ã  la fin de la liste courante au lieu de la
+remplacer. La liste d'adresses est unique pour chaque carte, donc chaque
+utilisateur devrait utiliser cette option pour Ã©viter les conflits.
+.TP
+.B off
+Enlève la liste d'adresses courante et désactive la fonctionnalité de
+scrutation.
+.TP
+.B setthr
+Fixe les seuils de force de signal
+.IR low " (bas) et " high " (haut)"
+pour les Ã©vénements iwspy (pour les pilotes qui le supportent).
+.br
+Chaque fois que la force du signal, pour une des adresses contrôlées avec
+iwspy, passe au-dessous du seuil bas ou au-dessus du seuil haut, un Wireless
+Event est généré.
+.br
+Ceci peut Ãªtre utilisé pour surveiller la qualité du lien sans avoir Ã  lancer
+iwspy périodiquement.
+.TP
+.B getthr
+Récupère les seuils
+.IR low " (bas) et " high " (haut)"
+de la force du signal pour l'événement iwspy.
+.\"
+\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+\"
+.\" FILES part
+.\"
+.SH FICHIERS
+.I /proc/net/wireless
+.\"
+.\" SEE ALSO part
+.\"
+.SH VOIR AUSSI
+.BR iwconfig (8),
+.BR iwlist (8),
+.BR iwevent (8),
+.BR iwpriv (8),
+.BR wireless (7).
+
diff --git a/wireless_tools/fr/wireless.7 b/wireless_tools/fr/wireless.7
new file mode 100644 (file)
index 0000000..63aa8f3
--- /dev/null
@@ -0,0 +1,145 @@
+.\" Jean Tourrilhes - HPL - 2002 - 2004
+.\" wireless.7
+.\"
+.\" Traduction 2004/02/26 Maxime CHARPENNE (voir
+.\" http://www.delafond.org/traducmanfr/)
+.\" 1ère traduction        : version 27-pre11 (alpha)
+.\" Mise Ã  jour 2004/08/24 : version 27-pre25
+.TH WIRELESS 7 "04 mars 2004" "wireless-tools" "Manuel du Programmeur Linux"
+.\"
+.\" NAME part
+.\"
+.SH NOM
+wireless \- Wireless Tools et Wireless Extensions
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.B iwconfig
+.br
+.B iwpriv \-a
+.br
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+Les
+.B Wireless Extensions
+sont une API vous permettant de manipuler les interfaces réseaux Wireless LAN.
+Ils sont composés d'une gamme d'outils et de fichiers de configuration. Ils sont
+plus amplement détaillés dans le Linux Wireless LAN Howto.
+.br
+Les
+.B Wireless Tools
+sont utilisés pour changer la configuration des interfaces réseau LAN wireless
+à la volée, pour obtenir leur configuration courante, pour avoir des
+statistiques et pour les diagnostiquer. Ils sont décrits dans leur propre page
+man, voir ci-dessous pour les références.
+.br
+La
+.B configuration Wireless
+est propre Ã  chaque distribution Linux. Cette page man contiendra Ã  l'avenir
+la procédure de configuration pour quelques distributions les plus communes.
+(quand j'en ai les informations nécessaires). Pour le moment, consultez le
+fichier DISTRIBUTIONS.txt inclus avec le paquetage Wireless Tools.
+.\"
+.\" DEBIAN 3.0 part
+.\"
+.SH DEBIAN 3.0
+Dans la Debian 3.0 (et suivante) vous pouvez configurer les périphériques
+réseaux LAN wireless en utilisant l'outil de configuration réseau
+.BR ifupdown (8).
+.TP
+.B Fichier :
+.I /etc/network/interfaces
+.TP
+.B Format :
+.RI wireless\- "<fonction> <valeur>"
+.br
+wireless\-essid Maison
+.br
+wireless\-mode Ad\-Hoc
+.TP
+.B Voir aussi :
+.I /etc/network/if\-pre\-up.d/wireless\-tools
+.br
+.I /usr/share/doc/wireless\-tools/README.Debian
+.\"
+.\" SuSE 8.0 part
+.\"
+.SH SuSE 8.0
+La SuSE 8.0 (et suivante) a intégré la configuration wireless dans ses
+scripts réseaux.
+.TP
+.B Outils :
+.B Yast2
+.TP
+.B Fichiers :
+.I /etc/sysconfig/network/wireless
+.br
+.I /etc/sysconfig/network/ifcfg\-*
+.TP
+.B Format :
+.RI WIRELESS_ "<fonction>" = "<valeur>"
+.br
+WIRELESS_ESSID="Maison"
+.br
+WIRELESS_MODE=Ad\-Hoc
+.TP
+.B Voir aussi :
+man ifup
+.br
+info scpm
+.\"
+.\" PCMCIA part
+.\"
+.SH SCRIPTS ORIGINAUX PCMCIA
+Si vous utilisez les scripts originaux de configuration du paquetage Pcmcia,
+vous pouvez utiliser cette méthode.
+.TP
+.B Fichier :
+.I /etc/pcmcia/wireless.opts
+.TP
+.B Format :
+*,*,*,*)
+.br
+    ESSID="Maison"
+.br
+    MODE="Ad-Hoc"
+.br
+    ;;
+.TP
+.B Voir aussi :
+.I /etc/pcmcia/wireless
+.br
+Le fichier
+.I PCMCIA.txt
+qui fait partie du paquetage Wireless Tools.
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTEUR
+Jean Tourrilhes \- jt@hpl.hp.com
+.br
+.I http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
+.\"
+.\" TRADUCTION part
+.\"
+.SH TRADUCTION
+Maxime CHARPENNE, août 2004 (wireless-tools.27-pre25).
+.\"
+.\" AVERTISSEMENT part
+.\"
+.SH AVERTISSEMENT SUR LA TRADUCTION
+Il est possible que cette traduction soit imparfaite ou périmée. En cas de
+doute, veuillez vous reporter au document original en langue anglaise fourni
+avec le programme.
+.\"
+.\" SEE ALSO part
+.\"
+.SH VOIR AUSSI
+.BR iwconfig (8),
+.BR iwlist (8),
+.BR iwspy (8),
+.BR iwpriv (8),
+.BR iwevent (8).
diff --git a/wireless_tools/ifrename.8 b/wireless_tools/ifrename.8
new file mode 100644 (file)
index 0000000..28d5f11
--- /dev/null
@@ -0,0 +1,142 @@
+.\" Jean II - HPL - 2004
+.\" ifrename.8
+.\"
+.TH IFRENAME 8 "01 March 2004" "wireless-tools" "Linux Programmer's Manual"
+.\"
+.\" NAME part
+.\"
+.SH NAME
+ifrename \- rename network interfaces based on various static criteria
+.\"
+.\" SYNOPSIS part
+.\"
+.SH SYNOPSIS
+.B "ifrename [-c configfile] [-p] [-d] [-v] [-V] [-D]"
+.br
+.B "ifrename [-c configfile] [-i interface] [-n newname]"
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+.B Ifrename 
+is a tool allowing you to assign a consistent name to each of your
+network interface.
+.PP
+By default, interface names are dynamic, and each network interface is
+assigned the first available name
+.RI ( eth0 ", " eth1 "...)."
+The order network interfaces are created may vary. For built-in
+interfaces, the kernel boot time enumeration may vary. For removable
+interface, the user may plug them in any order.
+.PP
+.B Ifrename
+allow the user to decide what name a network interface will have.
+.B Ifrename 
+can use a variety of
+.I selectors
+to specify how interface names match the network interfaces on the
+system, the most common selector is the interface 
+.IR "MAC address" .
+.PP
+.B Ifrename
+must be run before interfaces are brought up, which is why it's mostly
+useful in various scripts (init, hotplug) but is seldom used directly
+by the user. By default,
+.B ifrename 
+renames all present system interfaces using mappings defined in
+.IR /etc/iftab .
+.\"
+.\" PARAMETER part
+.\"
+.SH PARAMETERS
+.TP
+.BI "-c " configfile
+Set the configuration file to be used (by default 
+.IR /etc/iftab ).
+The configuration file define the mapping between selectors and
+interface names, and is described in
+.IR iftab (5).
+.br
+If
+.I configfile
+is "-", the configuration is read from stdin.
+.TP
+.B -p
+Probe (load) kernel modules before renaming interfaces. By default
+.B ifrename 
+only check interfaces already loaded, and doesn't auto-load the
+required kernel modules. This option enables smooth integration with
+system not loading modules before calling
+.BR ifrename .
+.TP
+.B -d
+Enable various
+.B Debian
+specific hacks. Combined with
+.BR -p ,
+only modules for interfaces specified in
+.I /etc/network/interface
+are loaded.
+.TP
+.BI "-i " interface
+Only rename the specified
+.I interface 
+as opposed to all interfaces on the system. The new interface name is
+printed.
+.TP
+.BI "-n " newname
+When used with
+.IR -i ,
+specify the new name of the interface. The list of mappings from the
+configuration file is bypassed. The new name may be a wildcard
+containing a single '*'.
+.TP
+.B -t
+Enable name takeover support. This allow interface name swapping
+between two or more interfaces.
+.br
+Takeover enable an interface to 'steal' the name of another
+interface. This works only with kernel 2.6.X and if the other
+interface is down. Consequently, this is not compatible with
+Hotplug. The other interface is assigned a random name, but may be
+renamed later with 'ifrename'.
+.br
+The number of takeovers is limited to avoid circular loops, and
+therefore some complex multi-way name swapping situations may not be
+fully processed.
+.br
+In any case, name swapping and the use of this feature is discouraged,
+and you are invited to choose unique and unambiguous names for your
+interfaces...
+.TP
+.B -D
+Dry-run mode. Ifrename won't change any interface, it will only print
+new interface name, if applicable, and return.
+.br
+In dry-run mode, interface name wildcards are not resolved. New
+interface name is printed, even if it is the same as the old name.
+.TP
+.B -V
+Verbose mode. Ifrename will display internal results of parsing its
+configuration file and querying the interfaces selectors. Combined
+with the
+.I dry-run
+option, this is a good way to debug complex configurations or trivial
+problems.
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTHOR
+Jean Tourrilhes \- jt@hpl.hp.com
+.\"
+.\" FILES part
+.\"
+.SH FILES
+.I /etc/iftab
+.\"
+.\" SEE ALSO part
+.\"
+.SH SEE ALSO
+.BR ifconfig (8),
+.BR ip (8),
+.BR iftab (5).
diff --git a/wireless_tools/ifrename.c b/wireless_tools/ifrename.c
new file mode 100644 (file)
index 0000000..7d4ab5b
--- /dev/null
@@ -0,0 +1,2054 @@
+/*
+ *     Wireless Tools
+ *
+ *             Jean II - HPL 04
+ *
+ * Main code for "ifrename". This is tool allows to rename network
+ * interfaces based on various criteria (not only wireless).
+ * You need to link this code against "iwlib.c" and "-lm".
+ *
+ * This file is released under the GPL license.
+ *     Copyright (c) 2004 Jean Tourrilhes <jt@hpl.hp.com>
+ */
+
+/* 
+ * The changelog for ifrename is in the file CHANGELOG.h ;-)
+ *
+ * This work is a nearly complete rewrite of 'nameif.c'.
+ * Original CopyRight of version of 'nameif' I used is :
+ * -------------------------------------------------------
+ * Name Interfaces based on MAC address.
+ * Writen 2000 by Andi Kleen.
+ * Subject to the Gnu Public License, version 2.  
+ * TODO: make it support token ring etc.
+ * $Id: nameif.c,v 1.3 2003/03/06 23:26:52 ecki Exp $
+ * Add hotplug compatibility : ifname -i eth0. Jean II - 03.12.03
+ * Add MAC address wildcard : 01:23:45:*. Jean II - 03.12.03
+ * Add interface name wildcard : wlan*. Jean II - 03.12.03
+ * Add interface name probing for modular systems. Jean II - 18.02.03
+ * -------------------------------------------------------
+ *
+ *     The last 4 patches never made it into the regular version of
+ * 'nameif', and had some 'issues', which is the reason of this rewrite.
+ *     Difference with standard 'nameif' :
+ *     o 'nameif' has only a single selector, the interface MAC address.
+ *     o Modular selector architecture, easily add new selectors.
+ *     o hotplug invocation support.
+ *     o module loading support.
+ *     o MAC address wildcard.
+ *     o Interface name wildcard ('eth*' or 'wlan*').
+ */
+
+/***************************** INCLUDES *****************************/
+
+/* This is needed to enable GNU extensions such as getline & FNM_CASEFOLD */
+#ifndef _GNU_SOURCE 
+#define _GNU_SOURCE
+#endif
+
+#include <getopt.h>            /* getopt_long() */
+#include <linux/sockios.h>     /* SIOCSIFNAME */
+#include <fnmatch.h>           /* fnmatch() */
+//#include <sys/syslog.h>
+
+#include "iwlib.h"             /* Wireless Tools library */
+
+// This would be cool, unfortunately...
+//#include <linux/ethtool.h>   /* Ethtool stuff -> struct ethtool_drvinfo */
+
+/************************ CONSTANTS & MACROS ************************/
+
+/* Our default configuration file */
+const char DEFAULT_CONF[] =            "/etc/iftab"; 
+
+/* Debian stuff */
+const char DEBIAN_CONFIG_FILE[] =      "/etc/network/interfaces";
+
+/* Backward compatibility */
+#ifndef ifr_newname
+#define ifr_newname ifr_ifru.ifru_slave
+#endif
+
+/* Types of selector we support. Must match selector_list */
+const int SELECT_MAC           = 0;    /* Select by MAC address */
+const int SELECT_ETHADDR       = 1;    /* Select by MAC address */
+const int SELECT_ARP           = 2;    /* Select by ARP type */
+const int SELECT_LINKTYPE      = 3;    /* Select by ARP type */
+const int SELECT_DRIVER                = 4;    /* Select by Driver name */
+const int SELECT_BUSINFO       = 5;    /* Select by Bus-Info */
+const int SELECT_FIRMWARE      = 6;    /* Select by Firmware revision */
+const int SELECT_BASEADDR      = 7;    /* Select by HW Base Address */
+const int SELECT_IRQ           = 8;    /* Select by HW Irq line */
+const int SELECT_INTERRUPT     = 9;    /* Select by HW Irq line */
+const int SELECT_IWPROTO       = 10;   /* Select by Wireless Protocol */
+const int SELECT_PCMCIASLOT    = 11;   /* Select by Wireless Protocol */
+#define SELECT_NUM             12
+
+#define HAS_MAC_EXACT  1
+#define HAS_MAC_FILTER 2
+
+const struct ether_addr        zero_mac = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+
+const struct option long_opt[] =
+{ 
+  {"config-file", 1, NULL, 'c' },
+  {"debian", 0, NULL, 'd' },
+  {"dry-run", 0, NULL, 'D' },
+  {"help", 0, NULL, '?' },
+  {"interface", 1, NULL, 'i' },
+  {"newname", 1, NULL, 'n' },
+  {"takeover", 0, NULL, 't' },
+  {"version", 0, NULL, 'v' },
+  {"verbose", 0, NULL, 'V' },
+  {NULL, 0, NULL, '\0' },
+};
+
+/* Pcmcia stab files */
+#define PCMCIA_STAB1   "/var/lib/pcmcia/stab"
+#define PCMCIA_STAB2   "/var/run/stab"
+
+/****************************** TYPES ******************************/
+
+/* Cut'n'paste from ethtool.h */
+#define ETHTOOL_BUSINFO_LEN    32
+/* these strings are set to whatever the driver author decides... */
+struct ethtool_drvinfo {
+       __u32   cmd;
+       char    driver[32];     /* driver short name, "tulip", "eepro100" */
+       char    version[32];    /* driver version string */
+       char    fw_version[32]; /* firmware version string, if applicable */
+       char    bus_info[ETHTOOL_BUSINFO_LEN];  /* Bus info for this IF. */
+                               /* For PCI devices, use pci_dev->slot_name. */
+       char    reserved1[32];
+       char    reserved2[16];
+       __u32   n_stats;        /* number of u64's from ETHTOOL_GSTATS */
+       __u32   testinfo_len;
+       __u32   eedump_len;     /* Size of data from ETHTOOL_GEEPROM (bytes) */
+       __u32   regdump_len;    /* Size of data from ETHTOOL_GREGS (bytes) */
+};
+#define ETHTOOL_GDRVINFO       0x00000003 /* Get driver info. */
+
+/* Description of an interface mapping */
+typedef struct if_mapping
+{ 
+  /* Linked list */
+  struct if_mapping *  next;
+
+  /* Name of this interface */
+  char                 ifname[IFNAMSIZ+1];
+
+  /* Selectors for this interface */
+  int                  active[SELECT_NUM];     /* Selectors active */
+
+  /* Selector data */
+  struct ether_addr    mac;                    /* Exact MAC address, hex */
+  char                 mac_filter[6*3 + 1];    /* WildCard, ascii */
+  unsigned short       hw_type;                /* Link/ARP type */
+  char                 driver[32];             /* driver short name */
+  char         bus_info[ETHTOOL_BUSINFO_LEN];  /* Bus info for this IF. */
+  char                 fw_version[32];         /* Firmware revision */
+  unsigned short       base_addr;              /* HW Base I/O address */ 
+  unsigned char                irq;                    /* HW irq line */
+  char                 iwproto[IFNAMSIZ + 1];  /* Wireless/protocol name */
+  int                  pcmcia_slot;            /* Pcmcia slot */
+} if_mapping; 
+
+/* Prototype for adding a selector to a mapping. Return -1 if invalid value. */
+typedef int (*mapping_add)(struct if_mapping * ifnode,
+                          int *                active,
+                          char *               pos,
+                          size_t               len,
+                          int                  linenum);
+
+/* Prototype for comparing the selector of two mapping. Return 0 if matches. */
+typedef int (*mapping_cmp)(struct if_mapping * ifnode,
+                          struct if_mapping *  target);
+/* Prototype for extracting selector value from live interface */
+typedef int (*mapping_get)(int                 skfd,
+                          const char *         ifname,
+                          struct if_mapping *  target,
+                          int                  flag);
+
+/* How to handle a selector */
+typedef struct mapping_selector
+{
+  char *       name;
+  mapping_add  add_fn;
+  mapping_cmp  cmp_fn;
+  mapping_get  get_fn;
+} mapping_selector;
+
+/**************************** PROTOTYPES ****************************/
+
+static int
+       mapping_addmac(struct if_mapping *      ifnode,
+                      int *                    active,
+                      char *                   pos,
+                      size_t                   len,
+                      int                      linenum);
+static int
+       mapping_cmpmac(struct if_mapping *      ifnode,
+                      struct if_mapping *      target);
+static int
+       mapping_getmac(int                      skfd,
+                      const char *             ifname,
+                      struct if_mapping *      target,
+                      int                      flag);
+static int
+       mapping_addarp(struct if_mapping *      ifnode,
+                      int *                    active,
+                      char *                   pos,
+                      size_t                   len,
+                      int                      linenum);
+static int
+       mapping_cmparp(struct if_mapping *      ifnode,
+                      struct if_mapping *      target);
+static int
+       mapping_getarp(int                      skfd,
+                      const char *             ifname,
+                      struct if_mapping *      target,
+                      int                      flag);
+static int
+       mapping_adddriver(struct if_mapping *   ifnode,
+                         int *                 active,
+                         char *                pos,
+                         size_t                len,
+                         int                   linenum);
+static int
+       mapping_cmpdriver(struct if_mapping *   ifnode,
+                         struct if_mapping *   target);
+static int
+       mapping_addbusinfo(struct if_mapping *  ifnode,
+                          int *                active,
+                          char *               pos,
+                          size_t               len,
+                          int                  linenum);
+static int
+       mapping_cmpbusinfo(struct if_mapping *  ifnode,
+                          struct if_mapping *  target);
+static int
+       mapping_addfirmware(struct if_mapping * ifnode,
+                           int *               active,
+                           char *              pos,
+                           size_t              len,
+                           int                 linenum);
+static int
+       mapping_cmpfirmware(struct if_mapping * ifnode,
+                           struct if_mapping * target);
+static int
+       mapping_getdriverbusinfo(int                    skfd,
+                                const char *           ifname,
+                                struct if_mapping *    target,
+                                int                    flag);
+static int
+       mapping_addbaseaddr(struct if_mapping * ifnode,
+                           int *               active,
+                           char *              pos,
+                           size_t              len,
+                           int                 linenum);
+static int
+       mapping_cmpbaseaddr(struct if_mapping * ifnode,
+                           struct if_mapping * target);
+static int
+       mapping_addirq(struct if_mapping *      ifnode,
+                      int *                    active,
+                      char *                   pos,
+                      size_t                   len,
+                      int                      linenum);
+static int
+       mapping_cmpirq(struct if_mapping *      ifnode,
+                      struct if_mapping *      target);
+static int
+       mapping_getbaseaddrirq(int                      skfd,
+                              const char *             ifname,
+                              struct if_mapping *      target,
+                              int                      flag);
+static int
+       mapping_addiwproto(struct if_mapping *  ifnode,
+                          int *                active,
+                          char *               pos,
+                          size_t               len,
+                          int                  linenum);
+static int
+       mapping_cmpiwproto(struct if_mapping *  ifnode,
+                          struct if_mapping *  target);
+static int
+       mapping_getiwproto(int                  skfd,
+                          const char *         ifname,
+                          struct if_mapping *  target,
+                          int                  flag);
+static int
+       mapping_addpcmciaslot(struct if_mapping *       ifnode,
+                             int *                     active,
+                             char *                    pos,
+                             size_t                    len,
+                             int                       linenum);
+static int
+       mapping_cmppcmciaslot(struct if_mapping *       ifnode,
+                          struct if_mapping *          target);
+static int
+       mapping_getpcmciaslot(int                       skfd,
+                             const char *              ifname,
+                             struct if_mapping *       target,
+                             int                       flag);
+
+/**************************** VARIABLES ****************************/
+
+/* List of mapping read for config file */
+struct if_mapping *    mapping_list = NULL;
+
+/* List of selectors we can handle */
+const struct mapping_selector  selector_list[] =
+{
+  /* MAC address and ARP/Link type from ifconfig */
+  { "mac", &mapping_addmac, &mapping_cmpmac, &mapping_getmac },
+  { "ethaddr", &mapping_addmac, &mapping_cmpmac, &mapping_getmac },
+  { "arp", &mapping_addarp, &mapping_cmparp, &mapping_getarp },
+  { "linktype", &mapping_addarp, &mapping_cmparp, &mapping_getarp },
+  /* Driver name, Bus-Info and firmware rev from ethtool -i */
+  { "driver", &mapping_adddriver, &mapping_cmpdriver,
+    &mapping_getdriverbusinfo },
+  { "businfo", &mapping_addbusinfo, &mapping_cmpbusinfo,
+    &mapping_getdriverbusinfo },
+  { "firmware", &mapping_addfirmware, &mapping_cmpfirmware,
+    &mapping_getdriverbusinfo },
+  /* Base Address and IRQ from ifconfig */
+  { "baseaddress", &mapping_addbaseaddr, &mapping_cmpbaseaddr,
+    &mapping_getbaseaddrirq },
+  { "irq", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq },
+  { "interrupt", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq },
+  /* Wireless Protocol from iwconfig */
+  { "iwproto", &mapping_addiwproto, &mapping_cmpiwproto, &mapping_getiwproto },
+  /* Pcmcia slot from cardmgr */
+  { "pcmciaslot", &mapping_addpcmciaslot, &mapping_cmppcmciaslot, &mapping_getpcmciaslot },
+  /* The Terminator */
+  { NULL, NULL, NULL, NULL },
+};
+const int selector_num = sizeof(selector_list)/sizeof(selector_list[0]);
+
+/* List of active selectors */
+int    selector_active[SELECT_NUM];    /* Selectors active */
+
+/* Takeover support */
+int    force_takeover = 0;     /* Takeover name from other interface */
+int    num_takeover = 0;       /* Number of takeover done */
+
+/* Dry-run support */
+int    dry_run = 0;            /* Just print new name, don't rename */
+
+/* Verbose support (i.e. debugging) */
+int    verbose = 0;
+
+/******************** INTERFACE NAME MANAGEMENT ********************/
+/*
+ * Bunch of low level function for managing interface names.
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare two interface names, with wildcards.
+ * We can't use fnmatch() because we don't want expansion of '[...]'
+ * expressions, '\' sequences and matching of '.'.
+ * We only want to match a single '*' (converted to a %d at that point)
+ * to a numerical value (no ascii).
+ * Return 0 is matches.
+ */
+static int
+if_match_ifname(const char *   pattern,
+               const char *    value)
+{
+  const char * p;
+  const char * v;
+  int          n;
+  int          ret;
+
+  /* Check for a wildcard (converted from '*' to '%d' in mapping_create()) */
+  p = strstr(pattern, "%d");
+
+  /* No wildcard, simple comparison */
+  if(p == NULL)
+    return(strcmp(pattern, value));
+
+  /* Check is prefixes match */
+  n = (p - pattern);
+  ret = strncmp(pattern, value, n);
+  if(ret)
+    return(ret);
+
+  /* Check that value has some digits at this point */
+  v = value + n;
+  if(!isdigit(*v))
+    return(-1);
+
+  /* Skip digits to go to value suffix */
+  do
+    v++;
+  while(isdigit(*v));
+
+  /* Pattern suffix */
+  p += 2;
+
+  /* Compare suffixes */
+  return(strcmp(p, v));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Steal interface name from another interface. This enable interface
+ * name swapping.
+ * This will work :
+ *     1) with kernel 2.6.X
+ *     2) if other interface is down
+ * Because of (2), it won't work with hotplug, but we don't need it
+ * with hotplug, only with static ifaces...
+ */
+static int
+if_takeover_name(int                   skfd,
+                const char *           victimname)
+{
+  char         autoname[IFNAMSIZ+1];
+  int          len;
+  struct ifreq ifr;
+  int          ret;
+
+  /* Compute name for victim interface */
+  len = strlen(victimname);
+  memcpy(autoname, victimname, len + 1);
+  if(len > (IFNAMSIZ - 2))
+    len = IFNAMSIZ - 2;                /* Make sure we have at least two char */
+  len--;                       /* Convert to index */
+  while(isdigit(autoname[len]))
+    len--;                     /* Scrap all trailing digits */
+  strcpy(autoname + len + 1, "%d");
+
+  if(verbose)
+    fprintf(stderr, "Takeover : moving interface `%s' to `%s'.\n",
+           victimname, autoname);
+
+  /* Prepare request */
+  bzero(&ifr, sizeof(struct ifreq));
+  strncpy(ifr.ifr_name, victimname, IFNAMSIZ); 
+  strncpy(ifr.ifr_newname, autoname, IFNAMSIZ); 
+
+  /* Rename victim interface */
+  ret = ioctl(skfd, SIOCSIFNAME, &ifr);
+
+  if(!ret)
+    num_takeover++;
+
+  return(ret);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Ask the kernel to change the name of an interface.
+ * That's what we want to do. All the rest is to make sure we call this
+ * appropriately.
+ */
+static int
+if_set_name(int                        skfd,
+           const char *        oldname,
+           const char *        newname,
+           char *              retname)
+{
+  struct ifreq ifr;
+  int          ret;
+
+  /* The kernel doesn't check is the interface already has the correct
+   * name and may return an error, so check ourselves.
+   * In the case of wildcard, the result can be weird : if oldname='eth0'
+   * and newname='eth*', retname would be 'eth1'.
+   * So, if the oldname value matches the newname pattern, just return
+   * success. */
+  if(!if_match_ifname(newname, oldname))
+    {
+      if(verbose)
+       fprintf(stderr, "Setting : Interface `%s' already matches `%s'.\n",
+               oldname, newname);
+
+      strcpy(retname, oldname);
+      return(0);
+    }
+
+  /* Prepare request */
+  bzero(&ifr, sizeof(struct ifreq));
+  strncpy(ifr.ifr_name, oldname, IFNAMSIZ); 
+  strncpy(ifr.ifr_newname, newname, IFNAMSIZ); 
+
+  /* Do it */
+  ret = ioctl(skfd, SIOCSIFNAME, &ifr);
+
+  /* Takeover support : grab interface name from another interface */
+  if(ret && (errno == EEXIST) && force_takeover)
+    {
+      /* Push things around */
+      ret = if_takeover_name(skfd, newname);
+      if(!ret)
+       /* Second try */
+       ret = ioctl(skfd, SIOCSIFNAME, &ifr);
+    }
+
+  if(!ret)
+    {
+      /* Get the real new name (in case newname is a wildcard) */
+      strcpy(retname, ifr.ifr_newname);
+
+      if(verbose)
+       fprintf(stderr, "Setting : Interface `%s' renamed to `%s'.\n",
+               oldname, retname);
+    }
+
+  return(ret);
+}
+
+/************************ SELECTOR HANDLING ************************/
+/*
+ * Handle the various selector we support
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a MAC address selector to a mapping
+ */
+static int
+mapping_addmac(struct if_mapping *     ifnode,
+              int *                    active,
+              char *                   string,
+              size_t                   len,
+              int                      linenum)
+{
+  size_t       n;
+
+  /* Verify validity of string */
+  if(len >= sizeof(ifnode->mac_filter))
+    { 
+      fprintf(stderr, "MAC address too long at line %d\n", linenum);  
+      return(-1);
+    }
+  n = strspn(string, "0123456789ABCDEFabcdef:*"); 
+  if(n < len)
+    {
+      fprintf(stderr, "Error: Invalid MAC address `%s' at line %d\n",
+             string, linenum);
+      return(-1);
+    }
+
+  /* Copy as filter in all cases */
+  memcpy(ifnode->mac_filter, string, len + 1); 
+
+  /* Check the type of MAC address */
+  if (strchr(ifnode->mac_filter, '*') != NULL)
+    {
+      /* This is a wilcard. Usual format : "01:23:45:*"
+       * Unfortunately, we can't do proper parsing. */
+      ifnode->active[SELECT_MAC] = HAS_MAC_FILTER;
+      active[SELECT_MAC] = HAS_MAC_FILTER;
+    }
+  else
+    {
+      /* Not a wildcard : "01:23:45:67:89:AB" */
+      if(iw_ether_aton(ifnode->mac_filter, &ifnode->mac) != 1)
+       {
+         fprintf(stderr, "Error: Invalid MAC address `%s' at line %d\n",
+                 ifnode->mac_filter, linenum);
+         return(-1);
+       }
+
+      /* Check that it's not NULL */
+      if(!memcmp(&ifnode->mac, &zero_mac, 6))
+       {
+         fprintf(stderr,
+                 "Warning: MAC address is null at line %d, this is dangerous...\n",
+                 linenum);
+       }
+
+      ifnode->active[SELECT_MAC] = HAS_MAC_EXACT;
+      if(active[SELECT_MAC] == 0)
+       active[SELECT_MAC] = HAS_MAC_EXACT;
+    }
+
+  if(verbose)
+    fprintf(stderr,
+           "Parsing : Added %s MAC address `%s' from line %d.\n",
+           ifnode->active[SELECT_MAC] == HAS_MAC_FILTER ? "filter" : "exact",
+           ifnode->mac_filter, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the mac address of two mappings
+ */
+static int
+mapping_cmpmac(struct if_mapping *     ifnode,
+              struct if_mapping *      target)
+{
+  /* Check for wildcard matching */
+  if(ifnode->active[SELECT_MAC] == HAS_MAC_FILTER)
+    /* Do wildcard matching, case insensitive */
+    return(fnmatch(ifnode->mac_filter, target->mac_filter, FNM_CASEFOLD));
+  else
+    /* Exact matching, in hex */
+    return(memcmp(&ifnode->mac.ether_addr_octet, &target->mac.ether_addr_octet,
+                 6));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the MAC address and Link Type of an interface
+ */
+static int
+mapping_getmac(int                     skfd,
+              const char *             ifname,
+              struct if_mapping *      target,
+              int                      flag)
+{
+  int  ret;
+
+  /* Extract MAC address */
+  ret = iw_get_mac_addr(skfd, ifname, &target->mac, &target->hw_type);
+  if(ret < 0)
+    {
+      fprintf(stderr, "Error: Can't read MAC address on interface `%s' : %s\n",
+             ifname, strerror(errno));
+      return(-1);
+    }
+
+  /* Check the type of comparison */
+  if((flag == HAS_MAC_FILTER) || verbose)
+    {
+      /* Convert to ASCII */
+      iw_ether_ntop(&target->mac, target->mac_filter);
+    }
+
+  target->active[SELECT_MAC] = flag;
+  target->active[SELECT_ARP] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Querying %s : Got MAC address `%s' and ARP/Link Type `%d'.\n",
+           ifname, target->mac_filter, target->hw_type);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a ARP/Link type selector to a mapping
+ */
+static int
+mapping_addarp(struct if_mapping *     ifnode,
+              int *                    active,
+              char *                   string,
+              size_t                   len,
+              int                      linenum)
+{
+  size_t       n;
+  unsigned int type;
+
+  /* Verify validity of string, convert to int */
+  n = strspn(string, "0123456789"); 
+  if((n < len) || (sscanf(string, "%d", &type) != 1))
+    {
+      fprintf(stderr, "Error: Invalid ARP/Link Type `%s' at line %d\n",
+             string, linenum);
+      return(-1);
+    }
+
+  ifnode->hw_type = (unsigned short) type;
+  ifnode->active[SELECT_ARP] = 1;
+  active[SELECT_ARP] = 1;
+
+  if(verbose)
+    fprintf(stderr, "Parsing : Added ARP/Link Type `%d' from line %d.\n",
+           ifnode->hw_type, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the ARP/Link type of two mappings
+ */
+static int
+mapping_cmparp(struct if_mapping *     ifnode,
+              struct if_mapping *      target)
+{
+  return(!(ifnode->hw_type == target->hw_type));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the ARP/Link type of an interface
+ */
+static int
+mapping_getarp(int                     skfd,
+              const char *             ifname,
+              struct if_mapping *      target,
+              int                      flag)
+{
+  /* We may have already extracted the MAC address */
+  if(target->active[SELECT_MAC])
+    return(0);
+
+  /* Otherwise just do it */
+  return(mapping_getmac(skfd, ifname, target, flag));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a Driver name selector to a mapping
+ */
+static int
+mapping_adddriver(struct if_mapping *  ifnode,
+                 int *                 active,
+                 char *                string,
+                 size_t                len,
+                 int                   linenum)
+{
+  /* Plain string, minimal verification */
+  if(len >= sizeof(ifnode->driver))
+    { 
+      fprintf(stderr, "Driver name too long at line %d\n", linenum);  
+      return(-1);
+    }
+
+  /* Copy */
+  memcpy(ifnode->driver, string, len + 1); 
+
+  /* Activate */
+  ifnode->active[SELECT_DRIVER] = 1;
+  active[SELECT_DRIVER] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Parsing : Added Driver name `%s' from line %d.\n",
+           ifnode->driver, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the Driver name of two mappings
+ */
+static int
+mapping_cmpdriver(struct if_mapping *  ifnode,
+                 struct if_mapping *   target)
+{
+  /* Do wildcard matching, case insensitive */
+  return(fnmatch(ifnode->driver, target->driver, FNM_CASEFOLD));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a Bus-Info selector to a mapping
+ */
+static int
+mapping_addbusinfo(struct if_mapping * ifnode,
+                  int *                active,
+                  char *               string,
+                  size_t               len,
+                  int                  linenum)
+{
+#if 0
+  size_t       n;
+#endif
+
+  /* Verify validity of string */
+  if(len >= sizeof(ifnode->bus_info))
+    { 
+      fprintf(stderr, "Bus Info too long at line %d\n", linenum);  
+      return(-1);
+    }
+#if 0
+  /* Hum... This doesn's seem true for non-PCI bus-info */
+  n = strspn(string, "0123456789ABCDEFabcdef:.*"); 
+  if(n < len)
+    {
+      fprintf(stderr, "Error: Invalid Bus Info `%s' at line %d\n",
+             string, linenum);
+      return(-1);
+    }
+#endif
+
+  /* Copy */
+  memcpy(ifnode->bus_info, string, len + 1); 
+
+  /* Activate */
+  ifnode->active[SELECT_BUSINFO] = 1;
+  active[SELECT_BUSINFO] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Parsing : Added Bus Info `%s' from line %d.\n",
+           ifnode->bus_info, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the Bus-Info of two mappings
+ */
+static int
+mapping_cmpbusinfo(struct if_mapping * ifnode,
+                  struct if_mapping *  target)
+{
+  /* Do wildcard matching, case insensitive */
+  return(fnmatch(ifnode->bus_info, target->bus_info, FNM_CASEFOLD));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a Firmare revision selector to a mapping
+ */
+static int
+mapping_addfirmware(struct if_mapping *        ifnode,
+                   int *               active,
+                   char *              string,
+                   size_t              len,
+                   int                 linenum)
+{
+  /* Verify validity of string */
+  if(len >= sizeof(ifnode->fw_version))
+    { 
+      fprintf(stderr, "Firmware revision too long at line %d\n", linenum);  
+      return(-1);
+    }
+
+  /* Copy */
+  memcpy(ifnode->fw_version, string, len + 1); 
+
+  /* Activate */
+  ifnode->active[SELECT_FIRMWARE] = 1;
+  active[SELECT_FIRMWARE] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Parsing : Added Firmware Revision `%s' from line %d.\n",
+           ifnode->fw_version, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the Bus-Info of two mappings
+ */
+static int
+mapping_cmpfirmware(struct if_mapping *        ifnode,
+                   struct if_mapping * target)
+{
+  /* Do wildcard matching, case insensitive */
+  return(fnmatch(ifnode->fw_version, target->fw_version, FNM_CASEFOLD));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the Driver name and Bus-Info from a live interface
+ */
+static int
+mapping_getdriverbusinfo(int                   skfd,
+                        const char *           ifname,
+                        struct if_mapping *    target,
+                        int                    flag)
+{
+  struct ifreq ifr;
+  struct ethtool_drvinfo drvinfo;
+  int  ret;
+
+  /* Avoid "Unused parameter" warning */
+  flag = flag;
+
+  /* We may come here twice or more, so do the job only once */
+  if(target->active[SELECT_DRIVER] || target->active[SELECT_BUSINFO]
+     || target->active[SELECT_FIRMWARE])
+    return(0);
+
+  /* Prepare request */
+  bzero(&ifr, sizeof(struct ifreq));
+  bzero(&drvinfo, sizeof(struct ethtool_drvinfo));
+  strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+  drvinfo.cmd = ETHTOOL_GDRVINFO;
+  ifr.ifr_data = (caddr_t) &drvinfo;
+
+  /* Do it */
+  ret = ioctl(skfd, SIOCETHTOOL, &ifr);
+  if(ret < 0)
+    {
+      /* Most drivers don't support that, keep quiet for now */
+      if(verbose)
+       fprintf(stderr,
+               "Error: Can't read driver/bus-info on interface `%s' : %s\n",
+               ifname, strerror(errno));
+      return(-1);
+    }
+
+  /* Copy over */
+  strcpy(target->driver, drvinfo.driver);
+  strcpy(target->bus_info, drvinfo.bus_info);
+  strcpy(target->fw_version, drvinfo.fw_version);
+
+  /* Activate */
+  target->active[SELECT_DRIVER] = 1;
+  target->active[SELECT_BUSINFO] = 1;
+  target->active[SELECT_FIRMWARE] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Querying %s : Got Driver name `%s', Bus Info `%s' and Firmware `%s'.\n",
+           ifname, target->driver, target->bus_info, target->fw_version);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a Base Address selector to a mapping
+ */
+static int
+mapping_addbaseaddr(struct if_mapping *        ifnode,
+                   int *               active,
+                   char *              string,
+                   size_t              len,
+                   int                 linenum)
+{
+  size_t       n;
+  unsigned int address;
+
+  /* Verify validity of string */
+  n = strspn(string, "0123456789ABCDEFabcdefx"); 
+  if((n < len) || (sscanf(string, "0x%X", &address) != 1))
+    {
+      fprintf(stderr, "Error: Invalid Base Address `%s' at line %d\n",
+             string, linenum);
+      return(-1);
+    }
+
+  /* Copy */
+  ifnode->base_addr = (unsigned short) address;
+
+  /* Activate */
+  ifnode->active[SELECT_BASEADDR] = 1;
+  active[SELECT_BASEADDR] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Parsing : Added Base Address `0x%X' from line %d.\n",
+           ifnode->base_addr, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the Base Address of two mappings
+ */
+static int
+mapping_cmpbaseaddr(struct if_mapping *        ifnode,
+                   struct if_mapping * target)
+{
+  /* Do wildcard matching, case insensitive */
+  return(!(ifnode->base_addr == target->base_addr));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a IRQ selector to a mapping
+ */
+static int
+mapping_addirq(struct if_mapping *     ifnode,
+              int *                    active,
+              char *                   string,
+              size_t                   len,
+              int                      linenum)
+{
+  size_t       n;
+  unsigned int irq;
+
+  /* Verify validity of string */
+  n = strspn(string, "0123456789"); 
+  if((n < len) || (sscanf(string, "%d", &irq) != 1))
+    {
+      fprintf(stderr, "Error: Invalid Base Address `%s' at line %d\n",
+             string, linenum);
+      return(-1);
+    }
+
+  /* Copy */
+  ifnode->irq = (unsigned char) irq;
+
+  /* Activate */
+  ifnode->active[SELECT_IRQ] = 1;
+  active[SELECT_IRQ] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Parsing : Added IRQ `%d' from line %d.\n",
+           ifnode->irq, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the IRQ of two mappings
+ */
+static int
+mapping_cmpirq(struct if_mapping *     ifnode,
+              struct if_mapping *      target)
+{
+  /* Do wildcard matching, case insensitive */
+  return(!(ifnode->irq == target->irq));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the Driver name and Bus-Info from a live interface
+ */
+static int
+mapping_getbaseaddrirq(int                     skfd,
+                      const char *             ifname,
+                      struct if_mapping *      target,
+                      int                      flag)
+{
+  struct ifreq ifr;
+  struct ifmap map;            /* hardware setup        */
+  int  ret;
+
+  /* Avoid "Unused parameter" warning */
+  flag = flag;
+
+  /* We may come here twice, so do the job only once */
+  if(target->active[SELECT_BASEADDR] || target->active[SELECT_IRQ])
+    return(0);
+
+  /* Prepare request */
+  bzero(&ifr, sizeof(struct ifreq));
+  bzero(&map, sizeof(struct ifmap));
+  strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+  /* Do it */
+  ret = ioctl(skfd, SIOCGIFMAP, &ifr);
+  if(ret < 0)
+    {
+      /* Don't know if every interface has that, so keep quiet... */
+      if(verbose)
+       fprintf(stderr,
+               "Error: Can't read base address/irq on interface `%s' : %s\n",
+               ifname, strerror(errno));
+      return(-1);
+    }
+
+  /* Copy over, activate */
+  if(ifr.ifr_map.base_addr >= 0x100)
+    {
+      target->base_addr = ifr.ifr_map.base_addr;
+      target->active[SELECT_BASEADDR] = 1;
+    }
+  target->irq = ifr.ifr_map.irq;
+  target->active[SELECT_IRQ] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Querying %s : Got Base Address `0x%X' and IRQ `%d'.\n",
+           ifname, target->base_addr, target->irq);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a Wireless Protocol selector to a mapping
+ */
+static int
+mapping_addiwproto(struct if_mapping * ifnode,
+                  int *                active,
+                  char *               string,
+                  size_t               len,
+                  int                  linenum)
+{
+  /* Verify validity of string */
+  if(len >= sizeof(ifnode->iwproto))
+    { 
+      fprintf(stderr, "Wireless Protocol too long at line %d\n", linenum);  
+      return(-1);
+    }
+
+  /* Copy */
+  memcpy(ifnode->iwproto, string, len + 1); 
+
+  /* Activate */
+  ifnode->active[SELECT_IWPROTO] = 1;
+  active[SELECT_IWPROTO] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Parsing : Added Wireless Protocol `%s' from line %d.\n",
+           ifnode->iwproto, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the Wireless Protocol of two mappings
+ */
+static int
+mapping_cmpiwproto(struct if_mapping * ifnode,
+                  struct if_mapping *  target)
+{
+  /* Do wildcard matching, case insensitive */
+  return(fnmatch(ifnode->iwproto, target->iwproto, FNM_CASEFOLD));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the Wireless Protocol from a live interface
+ */
+static int
+mapping_getiwproto(int                 skfd,
+                  const char *         ifname,
+                  struct if_mapping *  target,
+                  int                  flag)
+{
+  struct iwreq         wrq;
+
+  /* Avoid "Unused parameter" warning */
+  flag = flag;
+
+  /* Get wireless name */
+  if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
+    /* Don't complain about it, Ethernet cards will never support this */
+    return(-1);
+
+  strncpy(target->iwproto, wrq.u.name, IFNAMSIZ);
+  target->iwproto[IFNAMSIZ] = '\0';
+
+  /* Activate */
+  target->active[SELECT_IWPROTO] = 1;
+
+  if(verbose)
+    fprintf(stderr,
+           "Querying %s : Got Wireless Protocol `%s'.\n",
+           ifname, target->iwproto);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Add a Pcmcia Slot selector to a mapping
+ */
+static int
+mapping_addpcmciaslot(struct if_mapping *      ifnode,
+              int *                    active,
+              char *                   string,
+              size_t                   len,
+              int                      linenum)
+{
+  size_t       n;
+
+  /* Verify validity of string, convert to int */
+  n = strspn(string, "0123456789"); 
+  if((n < len) || (sscanf(string, "%d", &ifnode->pcmcia_slot) != 1))
+    {
+      fprintf(stderr, "Error: Invalid Pcmcia Slot `%s' at line %d\n",
+             string, linenum);
+      return(-1);
+    }
+
+  ifnode->active[SELECT_PCMCIASLOT] = 1;
+  active[SELECT_PCMCIASLOT] = 1;
+
+  if(verbose)
+    fprintf(stderr, "Parsing : Added Pcmcia Slot `%d' from line %d.\n",
+           ifnode->pcmcia_slot, linenum);
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the Pcmcia Slot of two mappings
+ */
+static int
+mapping_cmppcmciaslot(struct if_mapping *      ifnode,
+              struct if_mapping *      target)
+{
+  return(!(ifnode->pcmcia_slot == target->pcmcia_slot));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the Pcmcia Slot of an interface
+ * Note that this works only for cards fully managed by cardmgr.
+ * With the kernel pcmcia modules, 32 bits cards (CardBus) are not managed
+ * by cardmgr, and therefore won't have a valid slot number. For those
+ * cards, you should use Bus Info (when the driver exports it).
+ * In the long term, 16 bits card as well will no longer be managed by
+ * cardmgr. Currently, Bus Info for 16 bit cards don't have any information
+ * enabling to locate their physical location on the system, but I hope that
+ * this will change.
+ * When that happen, we can drop this code...
+ */
+static int
+mapping_getpcmciaslot(int                      skfd,
+                     const char *              ifname,
+                     struct if_mapping *       target,
+                     int                       flag)
+{
+  FILE *       stream;
+  char *       linebuf = NULL;
+  size_t       linelen = 0; 
+  int          linenum = 0; 
+
+  /* Avoid "Unused parameter" warning */
+  skfd = skfd;
+  flag = flag;
+
+  /* Open the stab file for reading */
+  stream = fopen(PCMCIA_STAB1, "r");
+  if(!stream) 
+    {
+      /* Try again, alternate location */
+      stream = fopen(PCMCIA_STAB2, "r");
+      if(!stream) 
+       {
+         fprintf(stderr, "Error: Can't open PCMCIA Stab file `%s' or `%s': %s\n",
+                 PCMCIA_STAB1, PCMCIA_STAB2, strerror(errno)); 
+         return(-1);
+       }
+    }
+
+  /* Read each line of file
+   * getline is a GNU extension :-( The buffer is recycled and increased
+   * as needed by getline. */
+  while(getline(&linebuf, &linelen, stream) > 0)
+    {
+      char *                   p;
+      size_t                   n;
+      size_t                   k;
+      int                      pcmcia_slot;
+      int                      i;
+
+      /* Keep track of line number */
+      linenum++;
+
+      /* Get Pcmcia socket number */
+      p = linebuf;
+      while(isspace(*p))
+       ++p; 
+      if(*p == '\0')
+       continue;       /* Line ended */
+      n = strcspn(p, " \t\n");
+      k = strspn(p, "0123456789"); 
+      if((k < n) || (sscanf(p, "%d", &pcmcia_slot) != 1))
+       /* Next line */
+       continue;
+
+      /* Skip socket number */
+      /* Skip socket number ; device class ; driver name ; instance */
+      for(i = 0; i < 4; i++)
+       {
+         /* Skip item */
+         p += n;
+         /* Skip space */
+         p += strspn(p, " \t\n"); 
+         if(*p == '\0')
+           break;      /* Line ended */
+         /* Next item size */
+         n = strcspn(p, " \t\n");
+       }
+      if(*p == '\0')
+       continue;       /* Line ended */
+
+      /* Terminate dev name */
+      p[n] = '\0';
+
+      /* Compare to interface name */
+      if(!strcmp(p, ifname))
+       {
+         /* Save */
+         target->pcmcia_slot = pcmcia_slot;
+
+         /* Activate */
+         target->active[SELECT_PCMCIASLOT] = 1;
+
+         if(verbose)
+           fprintf(stderr,
+                   "Querying %s : Got Pcmcia Slot `%d'.\n",
+                   ifname, target->pcmcia_slot);
+         /* Exit loop, found it */
+         break;
+       }
+
+      /* Finished -> next line */
+    }
+
+  /* Cleanup */
+  free(linebuf);
+
+  return(target->active[SELECT_PCMCIASLOT] ? 0 : -1);
+}
+
+
+/*********************** MAPPING MANAGEMENTS ***********************/
+/*
+ * Manage interface mappings.
+ * Each mapping tell us how to identify a specific interface name.
+ * It is composed of a bunch of selector values.
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Create a new interface mapping and verify its name
+ */
+static struct if_mapping *
+mapping_create(char *  pos,
+              int      len,
+              int      linenum)
+{
+  struct if_mapping *  ifnode;
+  char *               star;
+
+  /* Check overflow. */
+  if(len > IFNAMSIZ)
+    {
+      fprintf(stderr, "Error: Interface name `%.*s' too long at line %d\n",
+             (int) len, pos, linenum);  
+      return(NULL);
+    }
+
+  /* Create mapping, zero it */
+  ifnode = calloc(1, sizeof(if_mapping));
+  if(!ifnode)
+    {
+      fprintf(stderr, "Error: Can't allocate interface mapping.\n");  
+      return(NULL);
+    }
+
+  /* Set the name, terminates it */
+  memcpy(ifnode->ifname, pos, len); 
+  ifnode->ifname[len] = '\0'; 
+
+  /* Check the interface name and issue various pedantic warnings */
+  if((!strcmp(ifnode->ifname, "eth0")) || (!strcmp(ifnode->ifname, "wlan0")))
+    fprintf(stderr,
+           "Warning: Interface name is `%s' at line %d, can't be mapped reliably.\n",
+           ifnode->ifname, linenum);
+  if(strchr(ifnode->ifname, ':'))
+    fprintf(stderr, "Warning: Alias device `%s' at line %d probably can't be mapped.\n",
+           ifnode->ifname, linenum);
+
+  /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
+   * This require specific kernel support (2.6.2-rc1 and later).
+   * We externally use '*', but the kernel doesn't know about that,
+   * so convert it to something it knows about... */
+  star = strchr(ifnode->ifname, '*');
+  if(star != NULL)
+    {
+      /* We need an extra char */
+      if(len >= IFNAMSIZ)
+       {
+         fprintf(stderr,
+                 "Error: Interface wildcard `%s' too long at line %d\n",
+                 ifnode->ifname, linenum);  
+         free(ifnode);
+         return(NULL);
+       }
+
+      /* Replace '*' with '%d' */
+      memmove(star + 2, star + 1, len + 1 - (star - ifnode->ifname));
+      star[0] = '%';
+      star[1] = 'd';
+    }
+
+  if(verbose)
+    fprintf(stderr, "Parsing : Added Mapping `%s' from line %d.\n",
+           ifnode->ifname, linenum);
+
+  /* Done */
+  return(ifnode);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Find the most appropriate selector matching a given selector name
+ */
+static inline const struct mapping_selector *
+selector_find(const char *     string,
+             size_t            slen,
+             int               linenum)
+{
+  const struct mapping_selector *      found = NULL;
+  int                  ambig = 0;
+  int                  i;
+
+  /* Go through all selectors */
+  for(i = 0; selector_list[i].name != NULL; ++i)
+    {
+      /* No match -> next one */
+      if(strncasecmp(selector_list[i].name, string, slen) != 0)
+       continue;
+
+      /* Exact match -> perfect */
+      if(slen == strlen(selector_list[i].name))
+       return &selector_list[i];
+
+      /* Partial match */
+      if(found == NULL)
+       /* First time */
+       found = &selector_list[i];
+      else
+       /* Another time */
+       if (selector_list[i].add_fn != found->add_fn)
+         ambig = 1;
+    }
+
+  if(found == NULL)
+    {
+      fprintf(stderr, "Error: Unknown selector `%.*s' at line %d.\n",
+             (int) slen, string, linenum);
+      return NULL;
+    }
+
+  if(ambig)
+    {
+      fprintf(stderr, "Selector `%.*s'at line %d is ambiguous.\n",
+             (int) slen, string, linenum);
+      return NULL;
+    }
+
+  return found;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Read the configuration file and extract all valid mappings and their
+ * selectors.
+ */
+static int
+mapping_readfile(const char *  filename)
+{
+  FILE *       stream;
+  char *       linebuf = NULL;
+  size_t       linelen = 0; 
+  int          linenum = 0; 
+
+  /* Reset the list of filters */
+  bzero(selector_active, sizeof(selector_active));
+
+  /* Check filename */
+  if(!strcmp(filename, "-"))
+    {
+      /* Read from stdin */
+      stream = stdin;
+
+    }
+  else
+    {
+      /* Open the file for reading */
+      stream = fopen(filename, "r");
+      if(!stream) 
+       {
+         fprintf(stderr, "Error: Can't open configuration file `%s': %s\n",
+                 filename, strerror(errno)); 
+         return(-1);
+       }
+    }
+
+  /* Read each line of file
+   * getline is a GNU extension :-( The buffer is recycled and increased
+   * as needed by getline. */
+  while(getline(&linebuf, &linelen, stream) > 0)
+    {
+      struct if_mapping *      ifnode;
+      char *                   p;
+      char *                   e;
+      size_t                   n;
+      int                      ret = -13;      /* Complain if no selectors */
+
+      /* Keep track of line number */
+      linenum++;
+
+      /* Every comments terminates parsing */
+      if((p = strchr(linebuf,'#')) != NULL)
+       *p = '\0';
+
+      /* Get interface name */
+      p = linebuf;
+      while(isspace(*p))
+       ++p; 
+      if(*p == '\0')
+       continue;       /* Line ended */
+      n = strcspn(p, " \t\n");
+
+      /* Create mapping */
+      ifnode = mapping_create(p, n, linenum);
+      if(!ifnode)
+       continue;       /* Ignore this line */
+      p += n;
+      p += strspn(p, " \t\n"); 
+
+      /* Loop on all selectors */
+      while(*p != '\0')
+       {
+         const struct mapping_selector *       selector = NULL;
+
+         /* Selector name length */
+         n = strcspn(p, " \t\n");
+
+         /* Find it */
+         selector = selector_find(p, n, linenum);
+         if(!selector)
+           {
+             ret = -1;
+             break;
+           }
+
+         /* Get to selector value */
+         p += n;
+         p += strspn(p, " \t\n"); 
+         if(*p == '\0')
+           {
+             fprintf(stderr, "Error: no value for selector `%s' on line %d\n",
+                     selector->name, linenum);
+             ret = -1;
+             break;    /* Line ended */
+           }
+         /* Check for quoted arguments */
+         if(*p == '"')
+           {
+             p++;
+             e = strchr(p, '"');
+             if(e == NULL)
+               {
+                 fprintf(stderr,
+                         "Error: unterminated quoted value on line %d\n",
+                         linenum);
+                 ret = -1;
+                 break;        /* Line ended */
+               }
+             n = e - p;
+             e++;
+           }
+         else
+           {
+             /* Just end at next blank */
+             n = strcspn(p, " \t\n");
+             e = p + n;
+           }
+         /* Make 'e' point past the '\0' we are going to add */
+         if(*e != '\0')
+           e++;
+         /* Terminate selector value */
+         p[n] = '\0';
+
+         /* Add it to the mapping */
+         ret = selector->add_fn(ifnode, selector_active, p, n, linenum);
+         if(ret < 0)
+           break;
+
+         /* Go to next selector */
+         p = e;
+         p += strspn(p, " \t\n"); 
+       }
+
+      /* We add a mapping only if it has at least one selector and if all
+       * selectors were parsed properly. */
+      if(ret < 0)
+       {
+         /* If we have not yet printed an error, now is a good time ;-) */
+         if(ret == -13)
+           fprintf(stderr, "Error: Line %d ignored, no valid selectors\n",
+                   linenum);
+         else
+           fprintf(stderr, "Error: Line %d ignored due to prior errors\n",
+                   linenum);
+
+         free(ifnode);
+       }
+      else
+       {
+         /* Link it in the list */
+         ifnode->next = mapping_list;
+         mapping_list = ifnode;
+       }
+    }
+
+  /* Cleanup */
+  free(linebuf);
+
+  /* Finished reading, close the file */
+  if(stream != stdin)
+    fclose(stream);
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract all the interesting selectors for the interface in consideration
+ */
+static struct if_mapping *
+mapping_extract(int            skfd,
+               const char *    ifname)
+{
+  struct if_mapping *  target;
+  int                  i;
+
+  /* Create mapping, zero it */
+  target = calloc(1, sizeof(if_mapping));
+  if(!target)
+    {
+      fprintf(stderr, "Error: Can't allocate interface mapping.\n");  
+      return(NULL);
+    }
+
+  /* Set the interface name */
+  strcpy(target->ifname, ifname);
+
+  /* Loop on all active selectors */
+  for(i = 0; i < SELECT_NUM; i++)
+    {
+      /* Check if this selector is active */
+      if(selector_active[i] != 0)
+       {
+         /* Extract selector */
+         selector_list[i].get_fn(skfd, ifname, target, selector_active[i]);
+
+         /* Ignore errors. Some mapping may not need all selectors */
+       }
+    }
+
+  return(target);
+} 
+
+/*------------------------------------------------------------------*/
+/*
+ * Find the first mapping in the list matching the one we want.
+ */
+static struct if_mapping *
+mapping_find(struct if_mapping *       target)
+{
+  struct if_mapping *  ifnode;
+  int                  i;
+
+  /* Look over all our mappings */
+  for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next)
+    {
+      int              matches = 1;
+
+      /* Look over all our selectors, all must match */
+      for(i = 0; i < SELECT_NUM; i++)
+       {
+         /* Check if this selector is active */
+         if(ifnode->active[i] != 0)
+           {
+             /* If this selector doesn't match, game over for this mapping */
+             if((target->active[i] == 0) ||
+                (selector_list[i].cmp_fn(ifnode, target) != 0))
+               {
+                 matches = 0;
+                 break;
+               }
+           }
+       }
+
+      /* Check is this mapping was "the one" */
+      if(matches)
+       return(ifnode);
+    }
+
+  /* Not found */
+  return(NULL);
+} 
+
+/************************** MODULE SUPPORT **************************/
+/*
+ * Load all necessary module so that interfaces do exist.
+ * This is necessary for system that are fully modular when
+ * doing the boot time processing, because we need to run before
+ * 'ifup -a'.
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Probe interfaces based on our list of mappings.
+ * This is the default, but usually not the best way to do it.
+ */
+static void
+probe_mappings(int             skfd)
+{
+  struct if_mapping *  ifnode;
+  struct ether_addr    mac;                    /* Exact MAC address, hex */
+  unsigned short       hw_type;
+
+  /* Look over all our mappings */
+  for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next)
+    {
+      /* Can't load wildcards interface name :-( */
+      if(strchr(ifnode->ifname, '%') != NULL)
+       continue;
+
+      if(verbose)
+       fprintf(stderr, "Probing : Trying to load interface [%s]\n",
+               ifnode->ifname);
+
+      /* Trick the kernel into loading the interface.
+       * This allow us to not depend on the exact path and
+       * name of the '/sbin/modprobe' command.
+       * Obviously, we expect this command to 'fail', as
+       * the interface will load with the old/wrong name.
+       */
+      iw_get_mac_addr(skfd, ifnode->ifname, &mac, &hw_type);
+    }
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Probe interfaces based on Debian's config files.
+ * This allow to enly load modules for interfaces the user want active,
+ * all built-in interfaces that should remain unconfigured won't
+ * be probed (and can have mappings).
+ */
+static void
+probe_debian(int               skfd)
+{
+  FILE *               stream;
+  char *               linebuf = NULL;
+  size_t               linelen = 0; 
+  struct ether_addr    mac;                    /* Exact MAC address, hex */
+  unsigned short       hw_type;
+
+  /* Open Debian config file */
+  stream = fopen(DEBIAN_CONFIG_FILE, "r");
+  if(stream == NULL)
+    {
+      fprintf(stderr, "Error: can't open file [%s]\n", DEBIAN_CONFIG_FILE);
+      return;
+    }
+
+  /* Read each line of file
+   * getline is a GNU extension :-( The buffer is recycled and increased
+   * as needed by getline. */
+  while(getline(&linebuf, &linelen, stream) > 0)
+    {
+      char *                   p;
+      char *                   e;
+      size_t                   n;
+
+      /* Check for auto keyword, ignore when commented out */
+      if(!strncasecmp(linebuf, "auto ", 5))
+       {
+         /* Skip "auto" keyword */
+         p = linebuf + 5;
+
+         /* Terminate at first comment */
+         e = strchr(p, '#');
+         if(e != NULL)
+           *e = '\0';
+
+         /* Loop on all interfaces given */
+         while(*p != '\0')
+           {
+             /* Interface name length */
+             n = strcspn(p, " \t\n");
+
+             /* Look for end of interface name */
+             e = p + n;
+             /* Make 'e' point past the '\0' we are going to add */
+             if(*e != '\0')
+               e++;
+             /* Terminate interface name */
+             p[n] = '\0';
+
+             if(verbose)
+               fprintf(stderr, "Probing : Trying to load interface [%s]\n",
+                       p);
+
+             /* Do it ! */
+             iw_get_mac_addr(skfd, p, &mac, &hw_type);
+
+             /* Go to next interface name */
+             p = e;
+             p += strspn(p, " \t\n"); 
+           }
+       }
+    }
+
+  /* Done */
+  fclose(stream);
+  return;
+}
+
+/**************************** MAIN LOGIC ****************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Rename an interface to a specified new name.
+ */
+static int
+process_rename(int     skfd,
+              char *   ifname,
+              char *   pattern)
+{
+  char         newname[IFNAMSIZ+1];
+  char         retname[IFNAMSIZ+1];
+  int          len;
+  char *       star;
+
+  len = strlen(pattern);
+  star = strchr(pattern, '*');
+
+  /* Check newname length, need one extra char for wildcard */
+  if((len + (star != NULL)) > IFNAMSIZ)
+    {
+      fprintf(stderr, "Error: Interface name `%s' too long.\n",
+             pattern);  
+      return(-1);
+    }
+
+  /* Copy to local buffer */
+  memcpy(newname, pattern, len + 1);
+
+  /* Convert wildcard to the proper format */
+  if(star != NULL)
+    {
+      /* Replace '*' with '%d' in the new buffer */
+      star += newname - pattern;
+      memmove(star + 2, star + 1, len + 1 - (star - newname));
+      star[0] = '%';
+      star[1] = 'd';
+    }
+
+
+  /* Change the name of the interface */
+  if(if_set_name(skfd, ifname, newname, retname) < 0)
+    {
+      fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
+             ifname, newname, strerror(errno)); 
+      return(-1);
+    }
+
+  /* Always print out the *new* interface name so that
+   * the calling script can pick it up and know where its interface
+   * has gone. */
+  printf("%s\n", retname);
+
+  /* Done */
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Process a specified interface.
+ */
+static int
+process_ifname(int     skfd,
+              char *   ifname,
+              char *   args[],
+              int      count)
+{
+  struct if_mapping *          target;
+  const struct if_mapping *    mapping;
+  char                         retname[IFNAMSIZ+1];
+
+  /* Avoid "Unused parameter" warning */
+  args = args; count = count;
+
+  /* Get description of this interface */
+  target = mapping_extract(skfd, ifname);
+  if(target == NULL)
+    return(-1);
+
+  /* Find matching mapping */
+  mapping = mapping_find(target);
+  if(mapping == NULL)
+    return(-1);
+
+  /* Check if user want only dry-run.
+   * Note that, in the case of wildcard, we don't resolve the wildcard.
+   * That would be tricky to do... */
+  if(dry_run)
+    {
+      printf("Dry-run : Would rename %s to %s.\n",
+            target->ifname, mapping->ifname);
+      return(0);
+    }
+
+  /* Change the name of the interface */
+  if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
+    {
+      fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
+             target->ifname, mapping->ifname, strerror(errno)); 
+      return(-1);
+    }
+
+  /* Check if called with an explicit interface name */
+  if(!count)
+    {
+      /* Always print out the *new* interface name so that
+       * the calling script can pick it up and know where its interface
+       * has gone. */
+      printf("%s\n", retname);
+    }
+
+  /* Done */
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Process all network interface present on the system.
+ */
+static inline int
+process_iflist(int     skfd,
+              char *   args[],
+              int      count)
+{
+  num_takeover = 0;
+
+  /* Just do it */
+  iw_enum_devices(skfd, &process_ifname, args, count);
+
+  /* If we do any takeover, the interface list grabbed with
+   * iw_enum_devices() may get out of sync with the real interfaces,
+   * and we may miss the victim interface. So, let's go through the
+   * list again.
+   * On the other hand, we may have ping pong between two interfaces,
+   * each claiming the same name, so let's not do it forever...
+   * Two time should be enough for most configs...
+   * Jean II */
+  if(force_takeover && num_takeover)
+    /* Play it again, Sam... */
+    iw_enum_devices(skfd, &process_ifname, args, count);
+
+  /* Done */
+  return(0);
+}
+
+/******************************* MAIN *******************************/
+
+
+/*------------------------------------------------------------------*/
+/*
+ */
+static void
+usage(void)
+{
+  fprintf(stderr, "usage: ifrename [-c configurationfile] [-i ifname] [-p] [-t] [-d] [-D]\n");
+  exit(1); 
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * The main !
+ */
+int
+main(int       argc,
+     char *    argv[]) 
+{
+  const char * conf_file = DEFAULT_CONF;
+  char *       ifname = NULL;
+  char *       newname = NULL;
+  int          use_probe = 0;
+  int          is_debian = 0;
+  int          skfd;
+  int          ret;
+
+  /* Loop over all command line options */
+  while(1)
+    {
+      int c = getopt_long(argc, argv, "c:dDi:n:ptvV", long_opt, NULL);
+      if(c == -1)
+       break;
+
+      switch(c)
+       { 
+       default:
+       case '?':
+         usage(); 
+       case 'c':
+         conf_file = optarg;
+         break;
+       case 'd':
+         is_debian = 1;
+         break;
+       case 'D':
+         dry_run = 1;
+         break;
+       case 'i':
+         ifname = optarg;
+         break;
+       case 'n':
+         newname = optarg;
+         break;
+       case 'p':
+         use_probe = 1;
+         break;
+       case 't':
+         force_takeover = 1;
+         break;
+       case 'v':
+         printf("%-8.16s  Wireless-Tools version %d\n", "ifrename", WT_VERSION);
+         return(0);
+       case 'V':
+         verbose = 1;
+         break;
+       }
+    }
+
+  /* Read the specified/default config file, or stdin. */
+  if(mapping_readfile(conf_file) < 0)
+    return(-1);
+
+  /* Create a channel to the NET kernel. */
+  if((skfd = iw_sockets_open()) < 0)
+    {
+      perror("socket");
+      return(-1);
+    }
+
+  /* Check if interface name was specified with -i. */
+  if(ifname)
+    {
+      /* Check is target name specified */
+      if(newname != NULL)
+       {
+         /* User want to simply rename an interface to a specified name */
+         ret = process_rename(skfd, ifname, newname);
+       }
+      else
+       {
+         /* Rename only this interface based on mappings
+          * Mostly used for HotPlug processing (from /etc/hotplug/net.agent).
+          * Process the network interface specified on the command line,
+          * and return the new name on stdout.
+          */
+         ret = process_ifname(skfd, ifname, NULL, 0);
+       }
+    }
+  else
+    {
+      /* Load all the necesary modules */
+      if(use_probe)
+       {
+         if(is_debian)
+           probe_debian(skfd);
+         else
+           probe_mappings(skfd);
+       }
+
+      /* Rename all system interfaces
+       * Mostly used for boot time processing (from init scripts).
+       */
+      ret = process_iflist(skfd, &newname, 1);
+    }
+
+  /* Cleanup */
+  iw_sockets_close(skfd);
+  return(ret);
+} 
diff --git a/wireless_tools/iftab.5 b/wireless_tools/iftab.5
new file mode 100644 (file)
index 0000000..ca6ef69
--- /dev/null
@@ -0,0 +1,190 @@
+.\" Jean II - HPL - 2004
+.\" iftab.5
+.\"
+.TH IFTAB 5 "01 March 2004" "wireless-tools" "Linux Programmer's Manual"
+.\"
+.\" NAME part
+.\"
+.SH NAME
+iftab \- static information about the network interfaces
+.\"
+.\" DESCRIPTION part
+.\"
+.SH DESCRIPTION
+The file
+.B /etc/iftab
+contains descriptive information about the various network interfaces.
+.B iftab
+is only used by the program
+.IR ifrename (8)
+to assign a consistent network interface name to each network interface.
+.PP
+.B /etc/iftab
+defines a set of
+.IR mappings .
+Each mapping contains an interface name and a set of selectors. The
+selectors allow
+.B ifrename
+to identify each network interface on the system. If a network
+interface matches all descriptors of a mapping,
+.B ifrename
+attempt to change the name of the interface to the interface name
+given by the mapping.
+.\"
+.\" MAPPINGS part
+.\"
+.SH MAPPINGS
+Each mapping is described on a separate line, it starts with an
+.IR "interface name" ,
+and contains a set of
+.IR descriptors ,
+separated by space or tabs.
+.PP
+The relationship between descriptors of a mapping is a
+.IR "logical and" .
+A mapping matches a network interface only is all the descriptors
+match. If a network interface doesn't support a specific descriptor,
+it won't match any mappings using this descriptor.
+.PP
+If you want to use alternate descriptors for an interface name
+(logical or), specify two different mappings with the same interface
+name (one on each line).
+.B Ifrename
+always use the first matching mapping starting from the
+.I end
+of
+.BR iftab ,
+therefore more restrictive mapping should be specified last.
+.\"
+.\" INTERFACE NAME part
+.\"
+.SH INTERFACE NAME
+The first part of each mapping is an interface name. If a network
+interface matches all descriptors of a mapping,
+.B ifrename
+attempt to change the name of the interface to the interface name
+given by the mapping.
+.PP
+The interface name of a mapping is either a plain interface name (such as
+.IR eth2 " or " wlan0 )
+or a interface name pattern containing a single wildcard (such as
+.IR eth* " or " wlan* ).
+In case of wildcard, the kernel replace the '*' with the lowest
+available integer making this interface name unique.
+.\"
+.\" DESCRIPTORS part
+.\"
+.SH DESCRIPTORS
+Each descriptor is composed of a descriptor name and descriptor
+value. Descriptors specify a static attribute of a network interface,
+the goal is to uniquely identify each piece of hardware.
+.PP
+Most users will only use the
+.B mac
+selector, other selectors are for more specialised setup.
+.TP
+.BI mac " mac address"
+Matches the MAC Address of the interface with the specified MAC
+address. The MAC address of the interface can be shown using
+.IR ifconfig (8)
+or
+.IR ip (8).
+The specified MAC address may contain a '*' for wilcard matching.
+.br
+This is the most common selector, as most interfaces have a unique MAC
+address allowing to identify network interfaces without ambiguity.
+However, some interfaces don't have a valid MAC address until they are
+brought up, in such case using this selector is tricky.
+.TP
+.BI arp " arp type"
+Matches the ARP Type (also called Link Type) of the interface with the
+specified ARP type. The ARP Type of the interface can be shown using
+.IR ifconfig (8)
+or
+.IR ip (8).
+.br
+This selector is useful when a driver create multiple network
+interfaces for a single network card.
+.TP
+.BI driver " driver name"
+Matches the Driver Name of the interface with the specified driver
+name. The Driver Name of the interface can be shown using
+.IR "ethtool -i" (8).
+.TP
+.BI businfo " bus information"
+Matches the Bus Information of the interface with the specified bus
+information. The Bus Information of the interface can be shown using
+.IR "ethtool -i" (8).
+.TP
+.BI firmware " firmware revision"
+Matches the Firmware Revision of the interface with the firmware
+revision information. The Firmware Revision of the interface can be
+shown using
+.IR "ethtool -i" (8).
+.TP
+.BI baseaddress " base address"
+Matches the Base Address of the interface with the specified base
+address. The Base Address of the interface can be shown using
+.IR ifconfig (8).
+.br
+Because most cards use dynamic allocation of the Base Address, this
+selector is only useful for ISA and EISA cards.
+.TP
+.BI irq " irq line"
+Matches the IRQ Line (interrupt) of the interface with the specified
+IRQ line. The IRQ Line of the interface can be shown using
+.IR ifconfig (8).
+.br
+Because there are IRQ Lines may be shared, this selector is usually
+not sufficient to uniquely identify an interface.
+.TP
+.BI iwproto " wireless protocol"
+Matches the Wireless Protocol of the interface with the specified
+wireless protocol. The Wireless Protocol of the interface can be shown
+using
+.IR iwconfig (8).
+.br
+This selector is only supported on wireless interfaces and is not
+sufficient to uniquely identify an interface.
+.TP
+.BI pcmciaslot " pcmcia slot"
+Matches the Pcmcia Socket number of the interface with the specified
+slot number. Pcmcia Socket number of the interface can be shown
+using
+.IR "cardctl ident" (8).
+.br
+This selector is usually only supported on 16 bits cards, for 32 bits
+cards it is advised to use the selector
+.BR businfo .
+.\"
+.\" EXAMPLE part
+.\"
+.SH EXAMPLE
+# This is a comment
+.br
+eth2           mac 08:00:09:DE:82:0E
+.br
+eth3           driver wavelan interrupt 15 baseaddress 0x390
+.br
+eth4           driver pcnet32 businfo 0000:02:05.0
+.br
+air*           mac 00:07:0E:* arp 1
+.\"
+.\" AUTHOR part
+.\"
+.SH AUTHOR
+Jean Tourrilhes \- jt@hpl.hp.com
+.\"
+.\" FILES part
+.\"
+.SH FILES
+.I /etc/iftab
+.\"
+.\" SEE ALSO part
+.\"
+.SH SEE ALSO
+.BR ifrename (8),
+.BR ifconfig (8),
+.BR ip (8),
+.BR ethtool (8),
+.BR iwconfig (8).
index fefaa93..a6a7a89 100644 (file)
@@ -1,7 +1,7 @@
-.\" Jean II - HPLB - 96
+.\" Jean II - HPLB - 1996 => HPL - 2004
 .\" iwconfig.8
 .\"
 .\" iwconfig.8
 .\"
-.TH IWCONFIG 8 "31 October 1996" "net-tools" "Linux Programmer's Manual"
+.TH IWCONFIG 8 "22 June 2004" "wireless-tools" "Linux Programmer's Manual"
 .\"
 .\" NAME part
 .\"
 .\"
 .\" NAME part
 .\"
@@ -41,9 +41,9 @@ may also be used to display those parameters, and the wireless
 statistics (extracted from
 .IR /proc/net/wireless ).
 .PP
 statistics (extracted from
 .IR /proc/net/wireless ).
 .PP
-All these parameters and statistics are device dependant. Each driver
-will provide only some of them depending on the hardware support, and
-the range of value may change. Please refer to the man page of each
+All these parameters and statistics are device dependent. Each driver
+will provide only some of them depending on hardware support, and the
+range of values may change. Please refer to the man page of each
 device for details.
 .\"
 .\" PARAMETER part
 device for details.
 .\"
 .\" PARAMETER part
@@ -51,14 +51,16 @@ device for details.
 .SH PARAMETERS
 .TP
 .B essid
 .SH PARAMETERS
 .TP
 .B essid
-Set the ESSID (or Network Name - in some products it may also called
-Domain ID). The ESSID is used to identify cells which are part of the
-same virtual network.
-.br
-As opposed to the NWID which defines a single cell, the ESSID defines
-a group of cell connected via repeaters or infrastructure, where the
-user may roam.  With some card, you may disable the ESSID checking
-(ESSID promiscuous) with
+Set the ESSID (or Network Name - in some products it may also be
+called Domain ID). The ESSID is used to identify cells which are part
+of the same virtual network.
+.br
+As opposed to the AP Address or NWID which define a single cell, the
+ESSID defines a group of cells connected via repeaters or
+infrastructure, where the user may roam transparently.
+.br
+With some cards, you may disable the ESSID checking (ESSID
+promiscuous) with
 .IR off " or " any " (and " on
 to reenable it).
 .br
 .IR off " or " any " (and " on
 to reenable it).
 .br
@@ -69,11 +71,16 @@ to reenable it).
 .I "   iwconfig eth0 essid ""My Network""
 .TP
 .BR nwid / domain
 .I "   iwconfig eth0 essid ""My Network""
 .TP
 .BR nwid / domain
-Set the Network ID (in some products it is also called Domain ID). As
-all adjacent wireless networks share the same medium, this parameter
-is used to differenciate them (create logical colocated networks) and
-identify nodes belonguing to the same cell. With some card, you may
-disable the Network ID checking (NWID promiscuous) with
+Set the Network ID (in some products it may also be called Domain
+ID). As all adjacent wireless networks share the same medium, this
+parameter is used to differenciate them (create logical colocated
+networks) and identify nodes belonging to the same cell.
+.br
+This parameter is only used for pre-802.11 hardware, the 802.11
+protocol uses the ESSID and AP Address for this function.
+.br
+With some cards, you may disable the Network ID checking (NWID
+promiscuous) with
 .IR off " (and " on
 to reenable it).
 .br
 .IR off " (and " on
 to reenable it).
 .br
@@ -84,36 +91,37 @@ to reenable it).
 .I "   iwconfig eth0 nwid off"
 .TP
 .BR freq / channel
 .I "   iwconfig eth0 nwid off"
 .TP
 .BR freq / channel
-Set the operating frequency or channel in the device. Value below 1000
-are the channel number, value over this is the frequency in Hz. You
-must append the suffix k, M or G to the value (for example, "2.46G"
-for 2.46 GHz frequency), or add enough '0'.
-.br
-Channels are usually numbered starting at 1,
-and you may use
-.IR iwpriv (8)
-to get the total number of channels and list the available
-frequencies. Depending on regulations, some frequencies/channels may
-not be available.
+Set the operating frequency or channel in the device. A value below
+1000 indicates a channel number, a value greater than 1000 is a
+frequency in Hz. You may append the suffix k, M or G to the value (for
+example, "2.46G" for 2.46 GHz frequency), or add enough '0'.
+.br
+Channels are usually numbered starting at 1, and you may use
+.IR iwlist (8)
+to get the total number of channels, list the available frequencies,
+and display the current frequency as a channel. Depending on
+regulations, some frequencies/channels may not be available.
 .br
 .B Examples :
 .br
 .br
 .B Examples :
 .br
+.I "   iwconfig eth0 freq 2422000000"
+.br
 .I "   iwconfig eth0 freq 2.422G"
 .br
 .I "   iwconfig eth0 channel 3"
 .TP
 .B sens
 Set the sensitivity threshold. This is the lowest signal level for
 .I "   iwconfig eth0 freq 2.422G"
 .br
 .I "   iwconfig eth0 channel 3"
 .TP
 .B sens
 Set the sensitivity threshold. This is the lowest signal level for
-which we attempt a packet reception, signal lower than this are not
-received. This is used to avoid receiving background noise, so you
+which the hardware attempt packet reception, signals weaker than this
+are ignored. This is used to avoid receiving background noise, so you
 should set it according to the average noise level. Positive values
 are assumed to be the raw value used by the hardware or a percentage,
 negative values are assumed to be dBm.
 .br
 should set it according to the average noise level. Positive values
 are assumed to be the raw value used by the hardware or a percentage,
 negative values are assumed to be dBm.
 .br
-With some hardware, this parameter also control the defer threshold
-(lowest signal level for which we consider the channel busy) and the
-handover threshold (lowest signal level where we stay associated with
-the current access point).
+With some hardware, this parameter also controls the defer threshold
+(lowest signal level for which the hardware consider the channel busy)
+and the handover threshold (signal level where the hardware start
+looking for a new access point).
 .br
 .B Example :
 .br
 .br
 .B Example :
 .br
@@ -122,18 +130,18 @@ the current access point).
 .B mode
 Set the operating mode of the device, which depends on the network
 topology. The mode can be
 .B mode
 Set the operating mode of the device, which depends on the network
 topology. The mode can be
-.I Ad-hoc
+.I Ad-Hoc
 (network composed of only one cell and without Access Point),
 .I Managed
 (node connects to a network composed of many Access Points, with roaming),
 .I Master
 (network composed of only one cell and without Access Point),
 .I Managed
 (node connects to a network composed of many Access Points, with roaming),
 .I Master
-(the node is the synchronisation master or act as an Access Point),
+(the node is the synchronisation master or acts as an Access Point),
 .I Repeater
 .I Repeater
-(the node forward packets between other wireless nodes),
+(the node forwards packets between other wireless nodes),
 .I Secondary
 .I Secondary
-(the node act as a backup master/repeater),
+(the node acts as a backup master/repeater),
 .I Monitor
 .I Monitor
-(the node act as a passive monitor and only receives packets) or
+(the node acts as a passive monitor and only receives packets) or
 .IR Auto .
 .br
 .B Example :
 .IR Auto .
 .br
 .B Example :
@@ -145,8 +153,8 @@ topology. The mode can be
 .B ap
 Force the card to register to the Access Point given by the address,
 if it is possible. When the quality of the connection goes too low,
 .B ap
 Force the card to register to the Access Point given by the address,
 if it is possible. When the quality of the connection goes too low,
-the driver may revert back to automatic mode (the card finds the best
-Access Point in range).
+the driver may revert back to automatic mode (the card selects the
+best Access Point in range).
 .br
 You may also use
 .I off
 .br
 You may also use
 .I off
@@ -155,7 +163,7 @@ or you may use
 .I any
 or
 .I auto
 .I any
 or
 .I auto
-to force the card to reassociate with the current best Access Point.
+to force the card to reassociate with the currently best Access Point.
 .br
 .B Example :
 .br
 .br
 .B Example :
 .br
@@ -166,10 +174,10 @@ to force the card to reassociate with the current best Access Point.
 .I "   iwconfig eth0 ap off"
 .TP
 .BR nick [name]
 .I "   iwconfig eth0 ap off"
 .TP
 .BR nick [name]
-Set the nickname, or the station name. Most 802.11 products do define
+Set the nickname, or the station name. Some 802.11 products do define
 it, but this is not used as far as the protocols (MAC, IP, TCP) are
 it, but this is not used as far as the protocols (MAC, IP, TCP) are
-concerned and completely accessory as far as configuration goes. In
-fact only some diagnostic tools may use it.
+concerned and completely useless as far as configuration goes. Only
+some diagnostic tools may use it.
 .br
 .B Example :
 .br
 .br
 .B Example :
 .br
@@ -179,18 +187,18 @@ fact only some diagnostic tools may use it.
 For cards supporting multiple bit rates, set the bit-rate in b/s. The
 bit-rate is the speed at which bits are transmitted over the medium,
 the user speed of the link is lower due to medium sharing and
 For cards supporting multiple bit rates, set the bit-rate in b/s. The
 bit-rate is the speed at which bits are transmitted over the medium,
 the user speed of the link is lower due to medium sharing and
-overhead.
+various overhead.
 .br
 .br
-You must append the suffix k, M or G to the value (decimal multiplier
-10^3, 10^6 and 10^9 b/s), or add enough '0'. Values below 1000 are
+You may append the suffix k, M or G to the value (decimal multiplier :
+10^3, 10^6 and 10^9 b/s), or add enough '0'. Values below 1000 are
 card specific, usually an index in the bit-rate list. Use
 .I auto
 card specific, usually an index in the bit-rate list. Use
 .I auto
-to select the automatic bit-rate mode (fallback to lower rate on noisy
+to select automatic bit-rate mode (fallback to lower rate on noisy
 channels), which is the default for most cards, and
 .I fixed
 to revert back to fixed setting. If you specify a bit-rate value and append
 .IR auto ,
 channels), which is the default for most cards, and
 .I fixed
 to revert back to fixed setting. If you specify a bit-rate value and append
 .IR auto ,
-the driver will use all bit lower and equal than this value.
+the driver will use all bit-rates lower and equal than this value.
 .br
 .B Examples :
 .br
 .br
 .B Examples :
 .br
@@ -202,11 +210,11 @@ the driver will use all bit lower and equal than this value.
 .TP
 .BR rts [_threshold]
 RTS/CTS adds a handshake before each packet transmission to make sure
 .TP
 .BR rts [_threshold]
 RTS/CTS adds a handshake before each packet transmission to make sure
-that the channel is clear. This adds overhead, but increase
-performance in case of hidden nodes or large number of active
-nodes. This parameters set the size of the smallest packet for which
-the node sends RTS, a value equal to the maximum packet size disable
-the scheme. You may also set this parameter to
+that the channel is clear. This adds overhead, but increases
+performance in case of hidden nodes or large number of active
+nodes. This parameter sets the size of the smallest packet for which
+the node sends RTS ; a value equal to the maximum packet size disable
+the mechanism. You may also set this parameter to
 .IR auto ", " fixed " or " off .
 .br
 .B Examples :
 .IR auto ", " fixed " or " off .
 .br
 .B Examples :
@@ -216,11 +224,12 @@ the scheme. You may also set this parameter to
 .I "   iwconfig eth0 rts off"
 .TP
 .BR frag [mentation_threshold]
 .I "   iwconfig eth0 rts off"
 .TP
 .BR frag [mentation_threshold]
-Fragmentation allow to split a IP packet in a burst of smaller
+Fragmentation allows to split an IP packet in a burst of smaller
 fragments transmitted on the medium. In most cases this adds overhead,
 fragments transmitted on the medium. In most cases this adds overhead,
-but in very noisy environment this reduce the error penalty. This
-parameter set the maximum fragment size, a value equal to the maximum
-packet size disable the scheme. You may also set this parameter to
+but in a very noisy environment this reduces the error penalty and
+allow packets to get through interference bursts. This parameter sets
+the maximum fragment size ; a value equal to the maximum packet size
+disable the mechanism. You may also set this parameter to
 .IR auto ", " fixed " or " off .
 .br
 .B Examples :
 .IR auto ", " fixed " or " off .
 .br
 .B Examples :
@@ -241,7 +250,7 @@ also enter the key as an ASCII string by using the
 .I s:
 prefix. Passphrase is currently not supported.
 .br
 .I s:
 prefix. Passphrase is currently not supported.
 .br
-To change which key is the current active key, just enter
+To change which key is the currently active key, just enter
 .I [index]
 (without entering any key value).
 .br
 .I [index]
 (without entering any key value).
 .br
@@ -252,7 +261,7 @@ The security mode may be
 .I open
 or
 .IR restricted ,
 .I open
 or
 .IR restricted ,
-and its meaning depend on the card used. With most card, in
+and its meaning depends on the card used. With most cards, in
 .I open
 mode no authentication is used and the card may also accept
 non-encrypted sessions, whereas in
 .I open
 mode no authentication is used and the card may also accept
 non-encrypted sessions, whereas in
@@ -264,15 +273,19 @@ If you need to set multiple keys, or set a key and change the active
 key, you need to use multiple
 .B key
 directives. Arguments can be put in any order, the last one will take
 key, you need to use multiple
 .B key
 directives. Arguments can be put in any order, the last one will take
-precendence.
+precedence.
 .br
 .B Examples :
 .br
 .I "   iwconfig eth0 key 0123-4567-89"
 .br
 .br
 .B Examples :
 .br
 .I "   iwconfig eth0 key 0123-4567-89"
 .br
+.I "   iwconfig eth0 key [3] 0123-4567-89"
+.br
 .I "   iwconfig eth0 key s:password [2]"
 .br
 .I "   iwconfig eth0 key s:password [2]"
 .br
-.I "   iwconfig eth0 key [2] open"
+.I "   iwconfig eth0 key [2]"
+.br
+.I "   iwconfig eth0 key open"
 .br
 .I "   iwconfig eth0 key off"
 .br
 .br
 .I "   iwconfig eth0 key off"
 .br
@@ -283,16 +296,16 @@ precendence.
 .BR power
 Used to manipulate power management scheme parameters and mode.
 .br
 .BR power
 Used to manipulate power management scheme parameters and mode.
 .br
-To set the period between wake up, enter
+To set the period between wake ups, enter
 .IR "period `value'" .
 To set the timeout before going back to sleep, enter
 .IR "timeout `value'" .
 You can also add the
 .IR min " and " max
 .IR "period `value'" .
 To set the timeout before going back to sleep, enter
 .IR "timeout `value'" .
 You can also add the
 .IR min " and " max
-modifiers. By defaults, those values are in seconds, append the
-suffix m or u to specify values un milliseconds or
-microseconds. Sometimes, those values are without units (number of
-dwell or the like).
+modifiers. By default, those values are in seconds, append the suffix
+m or u to specify values in milliseconds or microseconds. Sometimes,
+those values are without units (number of beacon periods, dwell or
+similar).
 .br
 .IR off " and " on
 disable and reenable power management. Finally, you may set the power
 .br
 .IR off " and " on
 disable and reenable power management. Finally, you may set the power
@@ -351,11 +364,11 @@ This is an absolute value (without unit).
 The set the maximum length of time the MAC should retry, enter
 .IR "lifetime `value'" .
 By defaults, this value in in seconds, append the suffix m or u to
 The set the maximum length of time the MAC should retry, enter
 .IR "lifetime `value'" .
 By defaults, this value in in seconds, append the suffix m or u to
-specify values un milliseconds or microseconds.
+specify values in milliseconds or microseconds.
 .br
 You can also add the
 .IR min " and " max
 .br
 You can also add the
 .IR min " and " max
-modifiers. If the card support automatic mode, they define the bounds
+modifiers. If the card supports automatic mode, they define the bounds
 of the limit or lifetime. Some other cards define different values
 depending on packet size, for example in 802.11
 .I min limit
 of the limit or lifetime. Some other cards define different values
 depending on packet size, for example in 802.11
 .I min limit
@@ -373,15 +386,15 @@ is the short retry limit (non RTS/CTS packets).
 Some cards may not apply changes done through Wireless Extensions
 immediately (they may wait to agregate the changes or apply it only
 when the card is brought up via ifconfig). This command (when
 Some cards may not apply changes done through Wireless Extensions
 immediately (they may wait to agregate the changes or apply it only
 when the card is brought up via ifconfig). This command (when
-available) force the card to apply all pending changes.
+available) forces the card to apply all pending changes.
 .br
 This is normally not needed, because the card will eventually apply
 .br
 This is normally not needed, because the card will eventually apply
-the changes, but can be usefull for debugging.
+the changes, but can be useful for debugging.
 .\"
 .\" DISPLAY part
 .\"
 .SH DISPLAY
 .\"
 .\" DISPLAY part
 .\"
 .SH DISPLAY
-For each device which support wireless extensions,
+For each device which supports wireless extensions,
 .I iwconfig
 will display the name of the
 .B MAC protocol
 .I iwconfig
 will display the name of the
 .B MAC protocol
@@ -406,15 +419,33 @@ the
 and the
 .B power management
 settings (depending on availability).
 and the
 .B power management
 settings (depending on availability).
+.PP
+The parameters displayed have the same meaning and values as the
+parameter you can set, please refer to the previous part for a
+detailed explanation of them.
 .br
 .br
-See above for explanations of what these parameters mean.
+Some parameters are only displayed in short/abreviated form (such as
+encryption). You may use
+.IR iwlist (8)
+to get all the details.
 .br
 .br
-If the label for some values (such as bitrate) is followed by
+Some parameters have two modes (such as bitrate). If the value is
+prefixed by
 .RB ` = ',
 it means that the parameter is fixed and forced to that value, if it
 .RB ` = ',
 it means that the parameter is fixed and forced to that value, if it
-is followed by
-.RB ` : '
-it is only the current value (device in normal auto mode).
+is prefixed by
+.RB ` : ',
+the parameter is in automatic mode and the current value is shown (and
+may change).
+.TP
+.BR "Access Point" / Cell
+An address equal to 00:00:00:00:00:00 means that the card failed to
+associate with an Access Point (most likely a configuration
+issue). The
+.B Access Point
+parameter will be shown as
+.B Cell
+in ad-hoc mode (for obvious reasons), but otherwise works the same.
 .PP
 If
 .I /proc/net/wireless
 .PP
 If
 .I /proc/net/wireless
@@ -428,7 +459,7 @@ driver documentation for proper interpretation of those values.
 Overall quality of the link. May be based on the level of contention
 or interference, the bit or frame error rate, how good the received
 signal is, some timing synchronisation, or other hardware metric. This
 Overall quality of the link. May be based on the level of contention
 or interference, the bit or frame error rate, how good the received
 signal is, some timing synchronisation, or other hardware metric. This
-is an aggregate value, and depend totally on the driver and hardware.
+is an aggregate value, and depends totally on the driver and hardware.
 .TP
 .B Signal level
 Received signal strength (RSSI - how strong the received signal
 .TP
 .B Signal level
 Received signal strength (RSSI - how strong the received signal
@@ -442,7 +473,7 @@ mode, this may be undefined and you should use
 .IR iwspy .
 .TP
 .B Noise level
 .IR iwspy .
 .TP
 .B Noise level
-Background noise level (when no packet is transmited). Similar
+Background noise level (when no packet is transmitted). Similar
 comments as for
 .BR "Signal level" .
 .TP
 comments as for
 .BR "Signal level" .
 .TP
@@ -461,16 +492,16 @@ re-assemble the link layer fragments (most likely one was missing).
 .TP
 .B Tx excessive retries
 Number of packets that the hardware failed to deliver. Most MAC
 .TP
 .B Tx excessive retries
 Number of packets that the hardware failed to deliver. Most MAC
-protocol will retry the packet a number of time before giving up.
+protocols will retry the packet a number of times before giving up.
 .TP
 .B Invalid misc
 Other packets lost in relation with specific wireless operations.
 .TP
 .B Missed beacon
 Number of periodic beacons from the Cell or the Access Point we have
 .TP
 .B Invalid misc
 Other packets lost in relation with specific wireless operations.
 .TP
 .B Missed beacon
 Number of periodic beacons from the Cell or the Access Point we have
-missed. Beacons are sent at regular interval to maintain the cell
-coordination, failure to receive them usually indicate that we are out
-of range.
+missed. Beacons are sent at regular intervals to maintain the cell
+coordination, failure to receive them usually indicates that the card
+is out of range.
 .\"
 .\" AUTHOR part
 .\"
 .\"
 .\" AUTHOR part
 .\"
index 3fa0611..ace3f8c 100644 (file)
@@ -1,14 +1,14 @@
 /*
  *     Wireless Tools
  *
 /*
  *     Wireless Tools
  *
- *             Jean II - HPLB 97->99 - HPL 99->01
+ *             Jean II - HPLB 97->99 - HPL 99->04
  *
  * Main code for "iwconfig". This is the generic tool for most
  * manipulations...
  * You need to link this code against "iwlib.c" and "-lm".
  *
  * This file is released under the GPL license.
  *
  * Main code for "iwconfig". This is the generic tool for most
  * manipulations...
  * You need to link this code against "iwlib.c" and "-lm".
  *
  * This file is released under the GPL license.
- *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
  */
 
 #include "iwlib.h"             /* Header */
  */
 
 #include "iwlib.h"             /* Header */
@@ -27,6 +27,7 @@ iw_usage(void)
   fprintf(stderr, "                          [mode {managed|ad-hoc|...}\n");
   fprintf(stderr, "                          [freq N.NNNN[k|M|G]]\n");
   fprintf(stderr, "                          [channel N]\n");
   fprintf(stderr, "                          [mode {managed|ad-hoc|...}\n");
   fprintf(stderr, "                          [freq N.NNNN[k|M|G]]\n");
   fprintf(stderr, "                          [channel N]\n");
+  fprintf(stderr, "                          [ap {N|off|auto}]\n");
   fprintf(stderr, "                          [sens N]\n");
   fprintf(stderr, "                          [nick N]\n");
   fprintf(stderr, "                          [rate {N|auto|fixed}]\n");
   fprintf(stderr, "                          [sens N]\n");
   fprintf(stderr, "                          [nick N]\n");
   fprintf(stderr, "                          [rate {N|auto|fixed}]\n");
@@ -57,43 +58,24 @@ get_info(int                        skfd,
 
   memset((char *) info, 0, sizeof(struct wireless_info));
 
 
   memset((char *) info, 0, sizeof(struct wireless_info));
 
-  /* Get wireless name */
-  if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
+  /* Get basic information */
+  if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0)
     {
       /* If no wireless name : no wireless extensions */
       /* But let's check if the interface exists at all */
       struct ifreq ifr;
 
     {
       /* If no wireless name : no wireless extensions */
       /* But let's check if the interface exists at all */
       struct ifreq ifr;
 
-      strcpy(ifr.ifr_name, ifname);
+      strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
       if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
        return(-ENODEV);
       else
        return(-ENOTSUP);
     }
       if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
        return(-ENODEV);
       else
        return(-ENOTSUP);
     }
-  else
-    {
-      strncpy(info->name, wrq.u.name, IFNAMSIZ);
-      info->name[IFNAMSIZ] = '\0';
-    }
 
   /* Get ranges */
   if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
     info->has_range = 1;
 
 
   /* Get ranges */
   if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
     info->has_range = 1;
 
-  /* Get network ID */
-  if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0)
-    {
-      info->has_nwid = 1;
-      memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
-    }
-
-  /* Get frequency / channel */
-  if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
-    {
-      info->has_freq = 1;
-      info->freq = iw_freq2float(&(wrq.u.freq));
-    }
-
   /* Get sensitivity */
   if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
     {
   /* Get sensitivity */
   if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
     {
@@ -101,27 +83,6 @@ get_info(int                        skfd,
       memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
     }
 
       memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
     }
 
-  /* Get encryption information */
-  wrq.u.data.pointer = (caddr_t) info->key;
-  wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
-  wrq.u.data.flags = 0;
-  if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
-    {
-      info->has_key = 1;
-      info->key_size = wrq.u.data.length;
-      info->key_flags = wrq.u.data.flags;
-    }
-
-  /* Get ESSID */
-  wrq.u.essid.pointer = (caddr_t) info->essid;
-  wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
-  wrq.u.essid.flags = 0;
-  if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0)
-    {
-      info->has_essid = 1;
-      info->essid_on = wrq.u.data.flags;
-    }
-
   /* Get AP address */
   if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
     {
   /* Get AP address */
   if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
     {
@@ -158,14 +119,6 @@ get_info(int                       skfd,
       memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
     }
 
       memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
     }
 
-  /* Get operation mode */
-  if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
-    {
-      info->mode = wrq.u.mode;
-      if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
-       info->has_mode = 1;
-    }
-
   /* Get Power Management settings */
   wrq.u.power.flags = 0;
   if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
   /* Get Power Management settings */
   wrq.u.power.flags = 0;
   if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
@@ -174,26 +127,29 @@ get_info(int                      skfd,
       memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
     }
 
       memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
     }
 
-#if WIRELESS_EXT > 9
-  /* Get Transmit Power */
-  if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
+  if((info->has_range) && (info->range.we_version_compiled > 9))
     {
     {
-      info->has_txpower = 1;
-      memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
+      /* Get Transmit Power */
+      if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
+       {
+         info->has_txpower = 1;
+         memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
+       }
     }
     }
-#endif
 
 
-#if WIRELESS_EXT > 10
-  /* Get retry limit/lifetime */
-  if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
+  if((info->has_range) && (info->range.we_version_compiled > 10))
     {
     {
-      info->has_retry = 1;
-      memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
+      /* Get retry limit/lifetime */
+      if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
+       {
+         info->has_retry = 1;
+         memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
+       }
     }
     }
-#endif /* WIRELESS_EXT > 10 */
 
   /* Get stats */
 
   /* Get stats */
-  if(iw_get_stats(skfd, ifname, &(info->stats)) >= 0)
+  if(iw_get_stats(skfd, ifname, &(info->stats),
+                 &info->range, info->has_range) >= 0)
     {
       info->has_stats = 1;
     }
     {
       info->has_stats = 1;
     }
@@ -216,19 +172,19 @@ display_info(struct wireless_info *       info,
   int  tokens = 3;     /* For name */
 
   /* Display device name and wireless name (name of the protocol used) */
   int  tokens = 3;     /* For name */
 
   /* Display device name and wireless name (name of the protocol used) */
-  printf("%-8.8s  %s  ", ifname, info->name);
+  printf("%-8.16s  %s  ", ifname, info->b.name);
 
   /* Display ESSID (extended network), if any */
 
   /* Display ESSID (extended network), if any */
-  if(info->has_essid)
+  if(info->b.has_essid)
     {
     {
-      if(info->essid_on)
+      if(info->b.essid_on)
        {
          /* Does it have an ESSID index ? */
        {
          /* Does it have an ESSID index ? */
-         if((info->essid_on & IW_ENCODE_INDEX) > 1)
-           printf("ESSID:\"%s\" [%d]  ", info->essid,
-                  (info->essid_on & IW_ENCODE_INDEX));
+         if((info->b.essid_on & IW_ENCODE_INDEX) > 1)
+           printf("ESSID:\"%s\" [%d]  ", info->b.essid,
+                  (info->b.essid_on & IW_ENCODE_INDEX));
          else
          else
-           printf("ESSID:\"%s\"  ", info->essid);
+           printf("ESSID:\"%s\"  ", info->b.essid);
        }
       else
        printf("ESSID:off/any  ");
        }
       else
        printf("ESSID:off/any  ");
@@ -239,35 +195,43 @@ display_info(struct wireless_info *       info,
     printf("Nickname:\"%s\"", info->nickname);
 
   /* Formatting */
     printf("Nickname:\"%s\"", info->nickname);
 
   /* Formatting */
-  if(info->has_essid || info->has_nickname)
+  if(info->b.has_essid || info->has_nickname)
     {
       printf("\n          ");
       tokens = 0;
     }
 
   /* Display Network ID */
     {
       printf("\n          ");
       tokens = 0;
     }
 
   /* Display Network ID */
-  if(info->has_nwid)
+  if(info->b.has_nwid)
     {
       /* Note : should display proper number of digit according to info
        * in range structure */
     {
       /* Note : should display proper number of digit according to info
        * in range structure */
-      if(info->nwid.disabled)
+      if(info->b.nwid.disabled)
        printf("NWID:off/any  ");
       else
        printf("NWID:off/any  ");
       else
-       printf("NWID:%X  ", info->nwid.value);
+       printf("NWID:%X  ", info->b.nwid.value);
       tokens +=2;
     }
 
   /* Display the current mode of operation */
       tokens +=2;
     }
 
   /* Display the current mode of operation */
-  if(info->has_mode)
+  if(info->b.has_mode)
     {
     {
-      printf("Mode:%s  ", iw_operation_mode[info->mode]);
+      printf("Mode:%s  ", iw_operation_mode[info->b.mode]);
       tokens +=3;
     }
 
   /* Display frequency / channel */
       tokens +=3;
     }
 
   /* Display frequency / channel */
-  if(info->has_freq)
+  if(info->b.has_freq)
     {
     {
-      iw_print_freq(buffer, info->freq);
+      double           freq = info->b.freq;    /* Frequency/channel */
+      int              channel = -1;           /* Converted to channel */
+      /* Some driver insist of returning channel instead of frequency.
+       * This fixes them up. Note that, driver should still return
+       * frequency, because other tools depend on it. */
+      if(info->has_range && (freq < KILO))
+       channel = iw_channel_to_freq((int) freq, &freq, &info->range);
+      /* Display */
+      iw_print_freq(buffer, sizeof(buffer), freq, -1, info->b.freq_flags);
       printf("%s  ", buffer);
       tokens +=4;
     }
       printf("%s  ", buffer);
       tokens +=4;
     }
@@ -284,11 +248,11 @@ display_info(struct wireless_info *       info,
       tokens +=6;
 
       /* Oups ! No Access Point in Ad-Hoc mode */
       tokens +=6;
 
       /* Oups ! No Access Point in Ad-Hoc mode */
-      if((info->has_mode) && (info->mode == IW_MODE_ADHOC))
+      if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC))
        printf("Cell:");
       else
        printf("Access Point:");
        printf("Cell:");
       else
        printf("Access Point:");
-      printf(" %s  ", iw_pr_ether(buffer, info->ap_addr.sa_data));
+      printf(" %s   ", iw_pr_ether(buffer, info->ap_addr.sa_data));
     }
 
   /* Display the currently used/set bit-rate */
     }
 
   /* Display the currently used/set bit-rate */
@@ -303,11 +267,10 @@ display_info(struct wireless_info *       info,
       tokens +=3;
 
       /* Display it */
       tokens +=3;
 
       /* Display it */
-      iw_print_bitrate(buffer, info->bitrate.value);
+      iw_print_bitrate(buffer, sizeof(buffer), info->bitrate.value);
       printf("Bit Rate%c%s   ", (info->bitrate.fixed ? '=' : ':'), buffer);
     }
 
       printf("Bit Rate%c%s   ", (info->bitrate.fixed ? '=' : ':'), buffer);
     }
 
-#if WIRELESS_EXT > 9
   /* Display the Transmit Power */
   if(info->has_txpower)
     {
   /* Display the Transmit Power */
   if(info->has_txpower)
     {
@@ -319,30 +282,10 @@ display_info(struct wireless_info *       info,
        }
       tokens +=3;
 
        }
       tokens +=3;
 
-      /* Disabled ? */
-      if(info->txpower.disabled)
-       printf("Tx-Power:off   ");
-      else
-       {
-         int           dbm;
-
-         /* Fixed ? */
-         if(info->txpower.fixed)
-           printf("Tx-Power=");
-         else
-           printf("Tx-Power:");
-
-         /* Convert everything to dBm */
-         if(info->txpower.flags & IW_TXPOW_MWATT)
-           dbm = iw_mwatt2dbm(info->txpower.value);
-         else
-           dbm = info->txpower.value;
-
-         /* Display */
-         printf("%d dBm   ", dbm);
-       }
+      /* Display it */
+      iw_print_txpower(buffer, sizeof(buffer), &info->txpower);
+      printf("Tx-Power%c%s   ", (info->txpower.fixed ? '=' : ':'), buffer);
     }
     }
-#endif
 
   /* Display sensitivity */
   if(info->has_sens)
 
   /* Display sensitivity */
   if(info->has_sens)
@@ -374,7 +317,6 @@ display_info(struct wireless_info * info,
   printf("\n          ");
   tokens = 0;
 
   printf("\n          ");
   tokens = 0;
 
-#if WIRELESS_EXT > 10
   /* Display retry limit/lifetime information */
   if(info->has_retry)
     { 
   /* Display retry limit/lifetime information */
   if(info->has_retry)
     { 
@@ -387,7 +329,7 @@ display_info(struct wireless_info * info,
          /* Let's check the value and its type */
          if(info->retry.flags & IW_RETRY_TYPE)
            {
          /* Let's check the value and its type */
          if(info->retry.flags & IW_RETRY_TYPE)
            {
-             iw_print_retry_value(buffer,
+             iw_print_retry_value(buffer, sizeof(buffer),
                                   info->retry.value, info->retry.flags);
              printf("%s", buffer);
            }
                                   info->retry.value, info->retry.flags);
              printf("%s", buffer);
            }
@@ -399,7 +341,6 @@ display_info(struct wireless_info * info,
       printf("   ");
       tokens += 5;     /* Between 3 and 5, depend on flags */
     }
       printf("   ");
       tokens += 5;     /* Between 3 and 5, depend on flags */
     }
-#endif /* WIRELESS_EXT > 10 */
 
   /* Display the RTS threshold */
   if(info->has_rts)
 
   /* Display the RTS threshold */
   if(info->has_rts)
@@ -452,23 +393,24 @@ display_info(struct wireless_info *       info,
 
   /* Display encryption information */
   /* Note : we display only the "current" key, use iwlist to list all keys */
 
   /* Display encryption information */
   /* Note : we display only the "current" key, use iwlist to list all keys */
-  if(info->has_key)
+  if(info->b.has_key)
     {
       printf("Encryption key:");
     {
       printf("Encryption key:");
-      if((info->key_flags & IW_ENCODE_DISABLED) || (info->key_size == 0))
+      if((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0))
        printf("off\n          ");
       else
        {
          /* Display the key */
        printf("off\n          ");
       else
        {
          /* Display the key */
-         iw_print_key(buffer, info->key, info->key_size, info->key_flags);
+         iw_print_key(buffer, sizeof(buffer),
+                      info->b.key, info->b.key_size, info->b.key_flags);
          printf("%s", buffer);
 
          /* Other info... */
          printf("%s", buffer);
 
          /* Other info... */
-         if((info->key_flags & IW_ENCODE_INDEX) > 1)
-           printf(" [%d]", info->key_flags & IW_ENCODE_INDEX);
-         if(info->key_flags & IW_ENCODE_RESTRICTED)
+         if((info->b.key_flags & IW_ENCODE_INDEX) > 1)
+           printf(" [%d]", info->b.key_flags & IW_ENCODE_INDEX);
+         if(info->b.key_flags & IW_ENCODE_RESTRICTED)
            printf("   Security mode:restricted");
            printf("   Security mode:restricted");
-         if(info->key_flags & IW_ENCODE_OPEN)
+         if(info->b.key_flags & IW_ENCODE_OPEN)
            printf("   Security mode:open");
          printf("\n          ");
        }
            printf("   Security mode:open");
          printf("\n          ");
        }
@@ -488,12 +430,13 @@ display_info(struct wireless_info *       info,
          /* Let's check the value and its type */
          if(info->power.flags & IW_POWER_TYPE)
            {
          /* Let's check the value and its type */
          if(info->power.flags & IW_POWER_TYPE)
            {
-             iw_print_pm_value(buffer, info->power.value, info->power.flags);
+             iw_print_pm_value(buffer, sizeof(buffer),
+                               info->power.value, info->power.flags);
              printf("%s  ", buffer);
            }
 
          /* Let's check the mode */
              printf("%s  ", buffer);
            }
 
          /* Let's check the mode */
-         iw_print_pm_mode(buffer, info->power.flags);
+         iw_print_pm_mode(buffer, sizeof(buffer), info->power.flags);
          printf("%s", buffer);
 
          /* Let's check if nothing (simply on) */
          printf("%s", buffer);
 
          /* Let's check if nothing (simply on) */
@@ -506,24 +449,23 @@ display_info(struct wireless_info *       info,
   /* Display statistics */
   if(info->has_stats)
     {
   /* Display statistics */
   if(info->has_stats)
     {
-      info->stats.qual.updated = 0x0;  /* Not that reliable, disable */
-      iw_print_stats(buffer, &info->stats.qual, &info->range, info->has_range);
+      iw_print_stats(buffer, sizeof(buffer),
+                    &info->stats.qual, &info->range, info->has_range);
       printf("Link %s\n", buffer);
 
       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 */
+      if(info->range.we_version_compiled > 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
+       printf("          Rx invalid nwid:%d  invalid crypt:%d  invalid misc:%d\n",
+              info->stats.discard.nwid,
+              info->stats.discard.code,
+              info->stats.discard.misc);
     }
 
   printf("\n");
     }
 
   printf("\n");
@@ -555,12 +497,12 @@ print_info(int            skfd,
       break;
 
     case -ENOTSUP:
       break;
 
     case -ENOTSUP:
-      fprintf(stderr, "%-8.8s  no wireless extensions.\n\n",
+      fprintf(stderr, "%-8.16s  no wireless extensions.\n\n",
              ifname);
       break;
 
     default:
              ifname);
       break;
 
     default:
-      fprintf(stderr, "%-8.8s  %s\n\n", ifname, strerror(-rc));
+      fprintf(stderr, "%-8.16s  %s\n\n", ifname, strerror(-rc));
     }
   return(rc);
 }
     }
   return(rc);
 }
@@ -702,13 +644,48 @@ set_info(int              skfd,           /* The socket */
 
          if(++i >= count)
            ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
 
          if(++i >= count)
            ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
-         if(sscanf(args[i], "%lg", &(freq)) != 1)
-           ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]);
-         if(index(args[i], 'G')) freq *= GIGA;
-         if(index(args[i], 'M')) freq *= MEGA;
-         if(index(args[i], 'k')) freq *= KILO;
+         if(!strcasecmp(args[i], "auto"))
+           {
+             wrq.u.freq.m = -1;
+             wrq.u.freq.e = 0;
+             wrq.u.freq.flags = 0;
+           }
+         else
+           {
+             if(!strcasecmp(args[i], "fixed"))
+               {
+                 /* Get old bitrate */
+                 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFREQ, &wrq,
+                                "Set Bit Rate");
+                 wrq.u.freq.flags = IW_FREQ_FIXED;
+               }
+             else                      /* Should be a numeric value */
+               {
+                 if(sscanf(args[i], "%lg", &(freq)) != 1)
+                   ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]);
+                 if(index(args[i], 'G')) freq *= GIGA;
+                 if(index(args[i], 'M')) freq *= MEGA;
+                 if(index(args[i], 'k')) freq *= KILO;
+
+                 iw_float2freq(freq, &(wrq.u.freq));
 
 
-         iw_float2freq(freq, &(wrq.u.freq));
+                 wrq.u.freq.flags = IW_FREQ_FIXED;
+
+                 /* Check for an additional argument */
+                 if(((i+1) < count) &&
+                    (!strcasecmp(args[i+1], "auto")))
+                   {
+                     wrq.u.freq.flags = 0;
+                     ++i;
+                   }
+                 if(((i+1) < count) &&
+                    (!strcasecmp(args[i+1], "fixed")))
+                   {
+                     wrq.u.freq.flags = IW_FREQ_FIXED;
+                     ++i;
+                   }
+               }
+           }
 
          IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
                         "Set Frequency");
 
          IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
                         "Set Frequency");
@@ -806,14 +783,12 @@ set_info(int              skfd,           /* The socket */
                      ++i;
                      gotone++;
                    }
                      ++i;
                      gotone++;
                    }
-#if WIRELESS_EXT > 15
                  if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
                    {
                      wrq.u.data.flags |= IW_ENCODE_TEMP;
                      ++i;
                      gotone++;
                    }
                  if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
                    {
                      wrq.u.data.flags |= IW_ENCODE_TEMP;
                      ++i;
                      gotone++;
                    }
-#endif
                }
              while(gotone != oldone);
 
                }
              while(gotone != oldone);
 
@@ -1192,7 +1167,6 @@ set_info(int              skfd,           /* The socket */
          continue;
        }
 
          continue;
        }
 
-#if WIRELESS_EXT > 9
       /* ---------- Set Transmit-Power ---------- */
       if(!strncmp(args[i], "txpower", 3))
        {
       /* ---------- Set Transmit-Power ---------- */
       if(!strncmp(args[i], "txpower", 3))
        {
@@ -1209,7 +1183,7 @@ set_info(int              skfd,           /* The socket */
          wrq.u.txpower.value = -1;
          wrq.u.txpower.fixed = 1;
          wrq.u.txpower.disabled = 0;
          wrq.u.txpower.value = -1;
          wrq.u.txpower.fixed = 1;
          wrq.u.txpower.disabled = 0;
-         wrq.u.data.flags = IW_TXPOW_DBM;
+         wrq.u.txpower.flags = IW_TXPOW_DBM;
          if(!strcasecmp(args[i], "off"))
            wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
          else
          if(!strcasecmp(args[i], "off"))
            wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
          else
@@ -1217,52 +1191,73 @@ set_info(int            skfd,           /* The socket */
              wrq.u.txpower.fixed = 0;  /* i.e. use power control */
            else
              {
              wrq.u.txpower.fixed = 0;  /* i.e. use power control */
            else
              {
-               if(!strcasecmp(args[i], "fixed"))
+               if(!strcasecmp(args[i], "on"))
                  {
                    /* Get old tx-power */
                    IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
                                   "Set Tx Power");
                  {
                    /* Get old tx-power */
                    IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
                                   "Set Tx Power");
-                   wrq.u.txpower.fixed = 1;
+                   wrq.u.txpower.disabled = 0;
                  }
                  }
-               else                    /* Should be a numeric value */
+               else
                  {
                  {
-                   int         power;
-                   int         ismwatt = 0;
-
-                   /* Get the value */
-                   if(sscanf(args[i], "%i", &(power)) != 1)
-                     ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW, args[i]);
-
-                   /* Check if milliwatt */
-                   ismwatt = (index(args[i], 'm') != NULL);
-
-                   /* Convert */
-                   if(range.txpower_capa & IW_TXPOW_MWATT)
-                     {
-                       if(!ismwatt)
-                         power = iw_dbm2mwatt(power);
-                       wrq.u.data.flags = IW_TXPOW_MWATT;
-                     }
-                   else
+                   if(!strcasecmp(args[i], "fixed"))
                      {
                      {
-                       if(ismwatt)
-                         power = iw_mwatt2dbm(power);
-                       wrq.u.data.flags = IW_TXPOW_DBM;
-                     }
-                   wrq.u.txpower.value = power;
-
-                   /* Check for an additional argument */
-                   if(((i+1) < count) &&
-                      (!strcasecmp(args[i+1], "auto")))
-                     {
-                       wrq.u.txpower.fixed = 0;
-                       ++i;
+                       /* Get old tx-power */
+                       IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
+                                      "Set Tx Power");
+                       wrq.u.txpower.fixed = 1;
+                       wrq.u.txpower.disabled = 0;
                      }
                      }
-                   if(((i+1) < count) &&
-                      (!strcasecmp(args[i+1], "fixed")))
+                   else                        /* Should be a numeric value */
                      {
                      {
-                       wrq.u.txpower.fixed = 1;
-                       ++i;
+                       int             power;
+                       int             ismwatt = 0;
+
+                       /* Get the value */
+                       if(sscanf(args[i], "%i", &(power)) != 1)
+                         ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW,
+                                        args[i]);
+
+                       /* Check if milliwatt */
+                       ismwatt = (index(args[i], 'm') != NULL);
+
+                       /* Convert */
+                       if(range.txpower_capa & IW_TXPOW_RELATIVE)
+                         {
+                           /* Can't convert */
+                           if(ismwatt)
+                             ABORT_ARG_TYPE("Set Tx Power",
+                                            SIOCSIWTXPOW,
+                                            args[i]);
+                         }
+                       else
+                         if(range.txpower_capa & IW_TXPOW_MWATT)
+                           {
+                             if(!ismwatt)
+                               power = iw_dbm2mwatt(power);
+                             wrq.u.txpower.flags = IW_TXPOW_MWATT;
+                           }
+                         else
+                           {
+                             if(ismwatt)
+                               power = iw_mwatt2dbm(power);
+                             wrq.u.txpower.flags = IW_TXPOW_DBM;
+                           }
+                       wrq.u.txpower.value = power;
+
+                       /* Check for an additional argument */
+                       if(((i+1) < count) &&
+                          (!strcasecmp(args[i+1], "auto")))
+                         {
+                           wrq.u.txpower.fixed = 0;
+                           ++i;
+                         }
+                       if(((i+1) < count) &&
+                          (!strcasecmp(args[i+1], "fixed")))
+                         {
+                           wrq.u.txpower.fixed = 1;
+                           ++i;
+                         }
                      }
                  }
              }
                      }
                  }
              }
@@ -1271,9 +1266,7 @@ set_info(int              skfd,           /* The socket */
                         "Set Tx Power");
          continue;
        }
                         "Set Tx Power");
          continue;
        }
-#endif
 
 
-#if WIRELESS_EXT > 10
       /* ---------- Set Retry limit ---------- */
       if(!strncmp(args[i], "retry", 3))
        {
       /* ---------- Set Retry limit ---------- */
       if(!strncmp(args[i], "retry", 3))
        {
@@ -1343,8 +1336,6 @@ set_info(int              skfd,           /* The socket */
          continue;
        }
 
          continue;
        }
 
-#endif /* WIRELESS_EXT > 10 */
-
       /* ---------- Other ---------- */
       /* Here we have an unrecognised arg... */
       fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
       /* ---------- Other ---------- */
       /* Here we have an unrecognised arg... */
       fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
@@ -1394,7 +1385,7 @@ main(int  argc,
          goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
 
   /* Close the socket. */
          goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
 
   /* Close the socket. */
-  close(skfd);
+  iw_sockets_close(skfd);
 
   return(goterr);
 }
 
   return(goterr);
 }
index 7c17923..7251361 100644 (file)
@@ -1,7 +1,7 @@
-.\" Jean Tourrilhes - HPL - 2002
+.\" Jean Tourrilhes - HPL - 2002 - 2004
 .\" iwevent.8
 .\"
 .\" iwevent.8
 .\"
-.TH IWEVENT 8 "25 January 2002" "net-tools" "Linux Programmer's Manual"
+.TH IWEVENT 8 "23 June 2004" "net-tools" "Linux Programmer's Manual"
 .\"
 .\" NAME part
 .\"
 .\"
 .\" NAME part
 .\"
@@ -69,9 +69,9 @@ available (see
 .B Tx packet dropped
 A packet directed at this address has been dropped because the
 interface believes this node doesn't answer anymore (usually maximum
 .B Tx packet dropped
 A packet directed at this address has been dropped because the
 interface believes this node doesn't answer anymore (usually maximum
-of MAC level retry exceeded). An early indication that the node may
-have left the cell or gone out of range, but may be due to fading or
-excessive contention.
+of MAC level retry exceeded). This is usually an early indication that
+the node may have left the cell or gone out of range, but it may be
+due to fading or excessive contention.
 .TP
 .B Custom driver event
 Event specific to the driver. Please check the driver documentation.
 .TP
 .B Custom driver event
 Event specific to the driver. Please check the driver documentation.
@@ -90,10 +90,12 @@ Point (mode master).
 The signal strength for one of the address in the spy list went under
 the low threshold or went above than the high threshold.
 .PP
 The signal strength for one of the address in the spy list went under
 the low threshold or went above than the high threshold.
 .PP
-Only some of those events will be generated on some wireless
-interfaces by the wireless driver, and their support depend on the
-specific hardware/driver combination. Please refer to driver
-documentation for details.
+Most wireless drivers generate only a subset of those events, not all
+of them, the exact list depends on the specific hardware/driver
+combination. Please refer to driver documentation for details on when
+they are generated, and use
+.IR iwlist (8)
+to check what the driver supports.
 .\"
 .\" AUTHOR part
 .\"
 .\"
 .\" AUTHOR part
 .\"
@@ -106,4 +108,5 @@ Jean Tourrilhes \- jt@hpl.hp.com
 .BR iwconfig (8),
 .BR iwlist (8),
 .BR iwspy (8),
 .BR iwconfig (8),
 .BR iwlist (8),
 .BR iwspy (8),
-.BR iwpriv (8).
+.BR iwpriv (8),
+.BR wireless (7).
index 4b1e6b9..525cb68 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Wireless Tools
  *
 /*
  *     Wireless Tools
  *
- *             Jean II - HPL 99->01
+ *             Jean II - HPL 99->04
  *
  * Main code for "iwevent". This listent for wireless events on rtnetlink.
  * You need to link this code against "iwcommon.c" and "-lm".
  *
  * Main code for "iwevent". This listent for wireless events on rtnetlink.
  * You need to link this code against "iwcommon.c" and "-lm".
@@ -12,7 +12,7 @@
  * about it...
  *
  * This file is released under the GPL license.
  * about it...
  *
  * This file is released under the GPL license.
- *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
  */
 
 /***************************** INCLUDES *****************************/
  */
 
 /***************************** INCLUDES *****************************/
 #define IFLA_WIRELESS  (IFLA_MASTER + 1)
 #endif /* IFLA_WIRELESS */
 
 #define IFLA_WIRELESS  (IFLA_MASTER + 1)
 #endif /* IFLA_WIRELESS */
 
+/****************************** TYPES ******************************/
+
+/*
+ * Static information about wireless interface.
+ * We cache this info for performance reason.
+ */
+typedef struct wireless_iface
+{
+  /* Linked list */
+  struct wireless_iface *      next;
+
+  /* Interface identification */
+  int          ifindex;                /* Interface index == black magic */
+
+  /* Interface data */
+  char                 ifname[IFNAMSIZ + 1];   /* Interface name */
+  struct iw_range      range;                  /* Wireless static data */
+  int                  has_range;
+} wireless_iface;
+
+/**************************** VARIABLES ****************************/
+
+/* Cache of wireless interfaces */
+struct wireless_iface *        interface_cache = NULL;
+
 /************************ RTNETLINK HELPERS ************************/
 /*
  * The following code is extracted from :
 /************************ RTNETLINK HELPERS ************************/
 /*
  * The following code is extracted from :
@@ -97,23 +122,164 @@ static inline int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
        return 0;
 }
 
        return 0;
 }
 
+/******************* WIRELESS INTERFACE DATABASE *******************/
+/*
+ * We keep a few information about each wireless interface on the
+ * system. This avoid to query this info at each event, therefore
+ * reducing overhead.
+ *
+ * Each interface is indexed by the 'ifindex'. As opposed to interface
+ * names, 'ifindex' are never reused (even if you reactivate the same
+ * hardware), so the data we cache will never apply to the wrong
+ * interface.
+ * Because of that, we are pretty lazy when it come to purging the
+ * cache...
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Get name of interface based on interface index...
+ */
+static inline int
+index2name(int         skfd,
+          int          ifindex,
+          char *       name)
+{
+  struct ifreq irq;
+  int          ret = 0;
+
+  memset(name, 0, IFNAMSIZ + 1);
+
+  /* Get interface name */
+  irq.ifr_ifindex = ifindex;
+  if(ioctl(skfd, SIOCGIFNAME, &irq) < 0)
+    ret = -1;
+  else
+    strncpy(name, irq.ifr_name, IFNAMSIZ);
+
+  return(ret);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Get interface data from cache or live interface
+ */
+static struct wireless_iface *
+iw_get_interface_data(int      ifindex)
+{
+  struct wireless_iface *      curr;
+  int                          skfd = -1;      /* ioctl socket */
+
+  /* Search for it in the database */
+  curr = interface_cache;
+  while(curr != NULL)
+    {
+      /* Match ? */
+      if(curr->ifindex == ifindex)
+       {
+         //printf("Cache : found %d-%s\n", curr->ifindex, curr->ifname);
+
+         /* Return */
+         return(curr);
+       }
+      /* Next entry */
+      curr = curr->next;
+    }
+
+  /* Create a channel to the NET kernel. Doesn't happen too often, so
+   * socket creation overhead is minimal... */
+  if((skfd = iw_sockets_open()) < 0)
+    {
+      perror("iw_sockets_open");
+      return(NULL);
+    }
+
+  /* Create new entry, zero, init */
+  curr = calloc(1, sizeof(struct wireless_iface));
+  if(!curr)
+    {
+      fprintf(stderr, "Malloc failed\n");
+      return(NULL);
+    }
+  curr->ifindex = ifindex;
+
+  /* Extract static data */
+  if(index2name(skfd, ifindex, curr->ifname) < 0)
+    {
+      perror("index2name");
+      free(curr);
+      return(NULL);
+    }
+  curr->has_range = (iw_get_range_info(skfd, curr->ifname, &curr->range) >= 0);
+  //printf("Cache : create %d-%s\n", curr->ifindex, curr->ifname);
+
+  /* Done */
+  iw_sockets_close(skfd);
+
+  /* Link it */
+  curr->next = interface_cache;
+  interface_cache = curr;
+
+  return(curr);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Remove interface data from cache (if it exist)
+ */
+static void
+iw_del_interface_data(int      ifindex)
+{
+  struct wireless_iface *      curr;
+  struct wireless_iface *      prev = NULL;
+  struct wireless_iface *      next;
+
+  /* Go through the list, find the interface, kills it */
+  curr = interface_cache;
+  while(curr)
+    {
+      next = curr->next;
+
+      /* Got a match ? */
+      if(curr->ifindex == ifindex)
+       {
+         /* Unlink. Root ? */
+         if(!prev)
+           interface_cache = next;
+         else
+           prev->next = next;
+         //printf("Cache : purge %d-%s\n", curr->ifindex, curr->ifname);
+
+         /* Destroy */
+         free(curr);
+       }
+      else
+       {
+         /* Keep as previous */
+         prev = curr;
+       }
+
+      /* Next entry */
+      curr = next;
+    }
+}
+
 /********************* WIRELESS EVENT DECODING *********************/
 /*
 /********************* WIRELESS EVENT DECODING *********************/
 /*
- * This is the bit I wrote...
+ * Parse the Wireless Event and print it out
  */
 
  */
 
-#if WIRELESS_EXT > 13
 /*------------------------------------------------------------------*/
 /*
  * Print one element from the scanning results
  */
 static inline int
 /*------------------------------------------------------------------*/
 /*
  * Print one element from the scanning results
  */
 static inline int
-print_event_token(struct iw_event *    event,  /* Extracted token */
-                 char *                ifname,
-                 struct iw_range *     iwrange,        /* Range info */
-                 int                   has_iwrange)
+print_event_token(struct iw_event *    event,          /* Extracted token */
+                 struct iw_range *     iw_range,       /* Range info */
+                 int                   has_range)
 {
   char         buffer[128];    /* Temporary buffer */
 {
   char         buffer[128];    /* Temporary buffer */
+  char *       prefix = (IW_IS_GET(event->cmd) ? "New" : "Set");
 
   /* Now, let's decode the event */
   switch(event->cmd)
 
   /* Now, let's decode the event */
   switch(event->cmd)
@@ -122,23 +288,36 @@ print_event_token(struct iw_event *       event,  /* Extracted token */
       /* Events that result from a "SET XXX" operation by the user */
     case SIOCSIWNWID:
       if(event->u.nwid.disabled)
       /* Events that result from a "SET XXX" operation by the user */
     case SIOCSIWNWID:
       if(event->u.nwid.disabled)
-       printf("NWID:off/any\n");
+       printf("Set NWID:off/any\n");
       else
       else
-       printf("NWID:%X\n", event->u.nwid.value);
+       printf("Set NWID:%X\n", event->u.nwid.value);
       break;
     case SIOCSIWFREQ:
       break;
     case SIOCSIWFREQ:
+    case SIOCGIWFREQ:
       {
       {
-       float           freq;                   /* Frequency/channel */
+       double          freq;                   /* Frequency/channel */
+       int             channel = -1;           /* Converted to channel */
        freq = iw_freq2float(&(event->u.freq));
        freq = iw_freq2float(&(event->u.freq));
-       iw_print_freq(buffer, freq);
-       printf("%s\n", buffer);
+       if(has_range)
+         {
+           if(freq < KILO)
+             /* Convert channel to frequency if possible */
+             channel = iw_channel_to_freq((int) freq, &freq, iw_range);
+           else
+             /* Convert frequency to channel if possible */
+             channel = iw_freq_to_channel(freq, iw_range);
+         }
+       iw_print_freq(buffer, sizeof(buffer),
+                     freq, channel, event->u.freq.flags);
+       printf("%s %s\n", prefix, buffer);
       }
       break;
     case SIOCSIWMODE:
       }
       break;
     case SIOCSIWMODE:
-      printf("Mode:%s\n",
+      printf("Set Mode:%s\n",
             iw_operation_mode[event->u.mode]);
       break;
     case SIOCSIWESSID:
             iw_operation_mode[event->u.mode]);
       break;
     case SIOCSIWESSID:
+    case SIOCGIWESSID:
       {
        char essid[IW_ESSID_MAX_SIZE+1];
        if((event->u.essid.pointer) && (event->u.essid.length))
       {
        char essid[IW_ESSID_MAX_SIZE+1];
        if((event->u.essid.pointer) && (event->u.essid.length))
@@ -148,13 +327,13 @@ print_event_token(struct iw_event *       event,  /* Extracted token */
          {
            /* Does it have an ESSID index ? */
            if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)
          {
            /* Does it have an ESSID index ? */
            if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)
-             printf("ESSID:\"%s\" [%d]\n", essid,
+             printf("%s ESSID:\"%s\" [%d]\n", prefix, essid,
                     (event->u.essid.flags & IW_ENCODE_INDEX));
            else
                     (event->u.essid.flags & IW_ENCODE_INDEX));
            else
-             printf("ESSID:\"%s\"\n", essid);
+             printf("%s ESSID:\"%s\"\n", prefix, essid);
          }
        else
          }
        else
-         printf("ESSID:off/any\n");
+         printf("%s ESSID:off/any\n", prefix);
       }
       break;
     case SIOCSIWENCODE:
       }
       break;
     case SIOCSIWENCODE:
@@ -164,13 +343,13 @@ print_event_token(struct iw_event *       event,  /* Extracted token */
          memcpy(key, event->u.essid.pointer, event->u.data.length);
        else
          event->u.data.flags |= IW_ENCODE_NOKEY;
          memcpy(key, event->u.essid.pointer, event->u.data.length);
        else
          event->u.data.flags |= IW_ENCODE_NOKEY;
-       printf("Encryption key:");
+       printf("Set Encryption key:");
        if(event->u.data.flags & IW_ENCODE_DISABLED)
          printf("off\n");
        else
          {
            /* Display the key */
        if(event->u.data.flags & IW_ENCODE_DISABLED)
          printf("off\n");
        else
          {
            /* Display the key */
-           iw_print_key(buffer, key, event->u.data.length,
+           iw_print_key(buffer, sizeof(buffer), key, event->u.data.length,
                         event->u.data.flags);
            printf("%s", buffer);
 
                         event->u.data.flags);
            printf("%s", buffer);
 
@@ -198,7 +377,6 @@ print_event_token(struct iw_event * event,  /* Extracted token */
       printf("Tx packet dropped:%s\n",
             iw_pr_ether(buffer, event->u.addr.sa_data));
       break;
       printf("Tx packet dropped:%s\n",
             iw_pr_ether(buffer, event->u.addr.sa_data));
       break;
-#if WIRELESS_EXT > 14
     case IWEVCUSTOM:
       {
        char custom[IW_CUSTOM_MAX+1];
     case IWEVCUSTOM:
       {
        char custom[IW_CUSTOM_MAX+1];
@@ -216,42 +394,28 @@ print_event_token(struct iw_event *       event,  /* Extracted token */
       printf("Expired node:%s\n",
             iw_pr_ether(buffer, event->u.addr.sa_data));
       break;
       printf("Expired node:%s\n",
             iw_pr_ether(buffer, event->u.addr.sa_data));
       break;
-#endif /* WIRELESS_EXT > 14 */
-#if WIRELESS_EXT > 15
     case SIOCGIWTHRSPY:
       {
        struct iw_thrspy        threshold;
     case SIOCGIWTHRSPY:
       {
        struct iw_thrspy        threshold;
-       int                     skfd;
-       struct iw_range         range;
-       int                     has_range = 0;
        if((event->u.data.pointer) && (event->u.data.length))
          {
            memcpy(&threshold, event->u.data.pointer,
                   sizeof(struct iw_thrspy));
        if((event->u.data.pointer) && (event->u.data.length))
          {
            memcpy(&threshold, event->u.data.pointer,
                   sizeof(struct iw_thrspy));
-           if((skfd = iw_sockets_open()) >= 0)
-             {
-               has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
-               close(skfd);
-             }
            printf("Spy threshold crossed on address:%s\n",
                   iw_pr_ether(buffer, threshold.addr.sa_data));
            printf("Spy threshold crossed on address:%s\n",
                   iw_pr_ether(buffer, threshold.addr.sa_data));
-           threshold.qual.updated = 0x0;       /* Not that reliable, disable */
-           iw_print_stats(buffer, &threshold.qual, &range, has_range);
+           iw_print_stats(buffer, sizeof(buffer),
+                          &threshold.qual, iw_range, has_range);
            printf("                            Link %s\n", buffer);
          }
        else
          printf("Invalid Spy Threshold event\n");
       }
       break;
            printf("                            Link %s\n", buffer);
          }
        else
          printf("Invalid Spy Threshold event\n");
       }
       break;
-#else
-      /* Avoid "Unused parameter" warning */
-      ifname = ifname;
-#endif /* WIRELESS_EXT > 15 */
       /* ----- junk ----- */
       /* other junk not currently in use */
     case SIOCGIWRATE:
       /* ----- junk ----- */
       /* other junk not currently in use */
     case SIOCGIWRATE:
-      iw_print_bitrate(buffer, event->u.bitrate.value);
-      printf("Bit Rate:%s\n", buffer);
+      iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);
+      printf("New Bit Rate:%s\n", buffer);
       break;
     case SIOCGIWNAME:
       printf("Protocol:%-1.16s\n", event->u.name);
       break;
     case SIOCGIWNAME:
       printf("Protocol:%-1.16s\n", event->u.name);
@@ -259,7 +423,8 @@ print_event_token(struct iw_event * event,  /* Extracted token */
     case IWEVQUAL:
       {
        event->u.qual.updated = 0x0;    /* Not that reliable, disable */
     case IWEVQUAL:
       {
        event->u.qual.updated = 0x0;    /* Not that reliable, disable */
-       iw_print_stats(buffer, &event->u.qual, iwrange, has_iwrange);
+       iw_print_stats(buffer, sizeof(buffer),
+                      &event->u.qual, iw_range, has_range);
        printf("Link %s\n", buffer);
        break;
       }
        printf("Link %s\n", buffer);
        break;
       }
@@ -277,7 +442,7 @@ print_event_token(struct iw_event * event,  /* Extracted token */
  * just make sure we read everything...
  */
 static inline int
  * just make sure we read everything...
  */
 static inline int
-print_event_stream(char *      ifname,
+print_event_stream(int         ifindex,
                   char *       data,
                   int          len)
 {
                   char *       data,
                   int          len)
 {
@@ -287,41 +452,42 @@ print_event_stream(char * ifname,
   int                  ret;
   char                 buffer[64];
   struct timeval       recv_time;
   int                  ret;
   char                 buffer[64];
   struct timeval       recv_time;
-#if 0
-  struct iw_range      range;
-  int                  has_range;
-#endif
+  struct wireless_iface *      wireless_data;
 
 
-#if 0
-  has_range = (iw_get_range_info(skfd, ifname, &range) < 0);
-#endif
+  /* Get data from cache */
+  wireless_data = iw_get_interface_data(ifindex);
+  if(wireless_data == NULL)
+    return(-1);
 
 
-  /* In readable form */
+  /* Print received time in readable form */
   gettimeofday(&recv_time, NULL);
   gettimeofday(&recv_time, NULL);
-  iw_print_timeval(buffer, &recv_time);
+  iw_print_timeval(buffer, sizeof(buffer), &recv_time);
 
   iw_init_event_stream(&stream, data, len);
   do
     {
       /* Extract an event and print it */
 
   iw_init_event_stream(&stream, data, len);
   do
     {
       /* Extract an event and print it */
-      ret = iw_extract_event_stream(&stream, &iwe);
+      ret = iw_extract_event_stream(&stream, &iwe,
+                                   wireless_data->range.we_version_compiled);
       if(ret != 0)
        {
          if(i++ == 0)
       if(ret != 0)
        {
          if(i++ == 0)
-           printf("%s   %-8.8s ", buffer, ifname);
+           printf("%s   %-8.16s ", buffer, wireless_data->ifname);
          else
            printf("                           ");
          if(ret > 0)
          else
            printf("                           ");
          if(ret > 0)
-           print_event_token(&iwe, ifname, NULL, 0);
+           print_event_token(&iwe,
+                             &wireless_data->range, wireless_data->has_range);
          else
            printf("(Invalid event)\n");
          else
            printf("(Invalid event)\n");
+         /* Push data out *now*, in case we are redirected to a pipe */
+         fflush(stdout);
        }
     }
   while(ret > 0);
 
   return(0);
 }
        }
     }
   while(ret > 0);
 
   return(0);
 }
-#endif /* WIRELESS_EXT > 13 */
 
 /*********************** RTNETLINK EVENT DUMP***********************/
 /*
 
 /*********************** RTNETLINK EVENT DUMP***********************/
 /*
@@ -333,76 +499,51 @@ print_event_stream(char * ifname,
 /*
  * Respond to a single RTM_NEWLINK event from the rtnetlink socket.
  */
 /*
  * Respond to a single RTM_NEWLINK event from the rtnetlink socket.
  */
-static inline int
-index2name(int index, char *name)
-{
-  int          skfd = -1;      /* generic raw socket desc.     */
-  struct ifreq irq;
-  int          ret = 0;
-
-  memset(name, 0, IFNAMSIZ + 1);
-
-  /* Create a channel to the NET kernel. */
-  if((skfd = iw_sockets_open()) < 0)
-    {
-      perror("socket");
-      exit(-1);
-    }
-
-  /* Get interface name */
-  irq.ifr_ifindex = index;
-  if(ioctl(skfd, SIOCGIFNAME, &irq) < 0)
-    ret = -1;
-  else
-    strncpy(name, irq.ifr_name, IFNAMSIZ);
-
-  close(skfd);
-  return(ret);
-}
-
-
-/*------------------------------------------------------------------*/
-/*
- * Respond to a single RTM_NEWLINK event from the rtnetlink socket.
- */
 static int
 LinkCatcher(struct nlmsghdr *nlh)
 {
   struct ifinfomsg* ifi;
 static int
 LinkCatcher(struct nlmsghdr *nlh)
 {
   struct ifinfomsg* ifi;
-  char ifname[IFNAMSIZ + 1];
 
 #if 0
   fprintf(stderr, "nlmsg_type = %d.\n", nlh->nlmsg_type);
 #endif
 
 
 #if 0
   fprintf(stderr, "nlmsg_type = %d.\n", nlh->nlmsg_type);
 #endif
 
-  if(nlh->nlmsg_type != RTM_NEWLINK)
-    return 0;
-
   ifi = NLMSG_DATA(nlh);
 
   ifi = NLMSG_DATA(nlh);
 
-  /* Get a name... */
-  index2name(ifi->ifi_index, ifname);
-
-#if WIRELESS_EXT > 13
   /* Code is ugly, but sort of works - Jean II */
 
   /* Code is ugly, but sort of works - Jean II */
 
+  /* If interface is getting destoyed */
+  if(nlh->nlmsg_type == RTM_DELLINK)
+    {
+      /* Remove from cache (if in cache) */
+      iw_del_interface_data(ifi->ifi_index);
+      return 0;
+    }
+
+  /* Only keep add/change events */
+  if(nlh->nlmsg_type != RTM_NEWLINK)
+    return 0;
+
   /* Check for attributes */
   /* Check for attributes */
-  if (nlh->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) {
+  if (nlh->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg)))
+    {
       int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg));
       int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg));
-      struct rtattr *attr = (void*)ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
-      while (RTA_OK(attr, attrlen)) {
-       /* Check if the Wireless kind */
-       if(attr->rta_type == IFLA_WIRELESS) {
-         /* Go to display it */
-         print_event_stream(ifname,
-                            (void *)attr + RTA_ALIGN(sizeof(struct rtattr)),
-                            attr->rta_len - RTA_ALIGN(sizeof(struct rtattr)));
+      struct rtattr *attr = (void *) ((char *) ifi +
+                                     NLMSG_ALIGN(sizeof(struct ifinfomsg)));
+
+      while (RTA_OK(attr, attrlen))
+       {
+         /* Check if the Wireless kind */
+         if(attr->rta_type == IFLA_WIRELESS)
+           {
+             /* Go to display it */
+             print_event_stream(ifi->ifi_index,
+                                (char *) attr + RTA_ALIGN(sizeof(struct rtattr)),
+                                attr->rta_len - RTA_ALIGN(sizeof(struct rtattr)));
+           }
+         attr = RTA_NEXT(attr, attrlen);
        }
        }
-       attr = RTA_NEXT(attr, attrlen);
-      }
-  }
-#endif /* WIRELESS_EXT > 13 */
+    }
 
   return 0;
 }
 
   return 0;
 }
@@ -419,7 +560,7 @@ handle_netlink_events(struct rtnl_handle *  rth)
   while(1)
     {
       struct sockaddr_nl sanl;
   while(1)
     {
       struct sockaddr_nl sanl;
-      socklen_t sanllen;
+      socklen_t sanllen = sizeof(struct sockaddr_nl);
 
       struct nlmsghdr *h;
       int amt;
 
       struct nlmsghdr *h;
       int amt;
@@ -457,6 +598,7 @@ handle_netlink_events(struct rtnl_handle *  rth)
          switch(h->nlmsg_type)
            {
            case RTM_NEWLINK:
          switch(h->nlmsg_type)
            {
            case RTM_NEWLINK:
+           case RTM_DELLINK:
              LinkCatcher(h);
              break;
            default:
              LinkCatcher(h);
              break;
            default:
@@ -593,12 +735,7 @@ main(int   argc,
       return(1);
     }
 
       return(1);
     }
 
-#if WIRELESS_EXT > 13
-  fprintf(stderr, "Waiting for Wireless Events...\n");
-#else  /* WIRELESS_EXT > 13 */
-  fprintf(stderr, "Unsupported in Wireless Extensions <= 14 :-(\n");
-  return(-1);
-#endif /* WIRELESS_EXT > 13 */
+  fprintf(stderr, "Waiting for Wireless Events from interfaces...\n");
 
   /* Do what we have to do */
   wait_for_event(&rth);
 
   /* Do what we have to do */
   wait_for_event(&rth);
index 30c8890..bb9d279 100644 (file)
@@ -1,8 +1,8 @@
 .\" Guus Sliepen - 2001
 .\" Guus Sliepen - 2001
-.\" Completed and fixed up by Jean Tourrilhes - 2002
+.\" Completed and fixed up by Jean Tourrilhes - 2002-2003
 .\" iwgetid.8
 .\"
 .\" iwgetid.8
 .\"
-.TH IWGETID 8 "7 August 2001" "net-tools" "Linux Programmer's Manual"
+.TH IWGETID 8 "02 December 2003" "wireless-tools" "Linux Programmer's Manual"
 .\"
 .\" NAME part
 .\"
 .\"
 .\" NAME part
 .\"
@@ -12,9 +12,9 @@ iwgetid \- Report ESSID, NWID or AP/Cell Address of wireless network
 .\" SYNOPSIS part
 .\"
 .SH SYNOPSIS
 .\" SYNOPSIS part
 .\"
 .SH SYNOPSIS
-.BI "iwgetid " [interface] " [--scheme] [--ap] [--freq] [--mode]"
+.BI "iwgetid " [interface] " [--raw] [--scheme] [--ap] [--freq]"
 .br
 .br
-.BI "                   [--protocol]
+.BI "                   [--mode] [--protocol] [--channel]
 .br
 .\"
 .\" DESCRIPTION part
 .br
 .\"
 .\" DESCRIPTION part
@@ -34,26 +34,42 @@ will print the
 of the device, and if the device doesn't have any ESSID it will print
 its
 .IR NWID .
 of the device, and if the device doesn't have any ESSID it will print
 its
 .IR NWID .
+.br
+The default formatting output is pretty-print.
 .\"
 .\" OPTIONS part
 .\"
 .SH OPTIONS
 .TP
 .\"
 .\" OPTIONS part
 .\"
 .SH OPTIONS
 .TP
+.B --raw
+This option disables pretty-printing of the information. This options
+is orthogonal to the other options (except
+.BR --scheme ),
+so with the appropriate combination of options you can print the raw
+ESSID, AP Address or Mode.
+.br
+This format is ideal when storing the result of iwgetid as a
+variable in
+.I Shell
+or
+.I Perl
+scripts or to pass the result as an argument on the command line of
+.BR iwconfig .
+.TP
 .B --scheme
 .B --scheme
-This option disables pretty-printing of the information, only the raw
-ESSID (or NWID, or AP Address) is printed. Also, characters that are
-not alphanumerics (like space, punctuation and control characters) are
-skipped.
+This option is similar to the previous one, it disables
+pretty-printing of the information and remove all characters that are
+not alphanumerics (like space, punctuation and control characters).
 .br
 The resulting output is a valid Pcmcia scheme identifier (that may be
 used as an argument of the command
 .BR "cardctl scheme" ).
 This format is also ideal when using the result of iwgetid as a
 .br
 The resulting output is a valid Pcmcia scheme identifier (that may be
 used as an argument of the command
 .BR "cardctl scheme" ).
 This format is also ideal when using the result of iwgetid as a
-variable in
+selector in
 .I Shell
 or
 .I Perl
 .I Shell
 or
 .I Perl
-scripts.
+scripts, or as a file name.
 .TP
 .B --ap
 Display the MAC address of the Wireless
 .TP
 .B --ap
 Display the MAC address of the Wireless
@@ -68,6 +84,12 @@ or
 .I channel
 used by the interface.
 .TP
 .I channel
 used by the interface.
 .TP
+.B --channel
+Display the current
+.I channel
+used by the interface. The channel is determined using the current
+frequency and the frequency list provided by the interface.
+.TP
 .B --mode
 Display the current
 .I mode
 .B --mode
 Display the current
 .I mode
index 1d74910..f7c5a6d 100644 (file)
@@ -6,21 +6,13 @@
  * Just print the ESSID or NWID...
  *
  * This file is released under the GPL license.
  * Just print the ESSID or NWID...
  *
  * This file is released under the GPL license.
- *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
  */
 
 #include "iwlib.h"             /* Header */
 
 #include <getopt.h>
 
  */
 
 #include "iwlib.h"             /* Header */
 
 #include <getopt.h>
 
-#define FORMAT_DEFAULT 0       /* Nice looking display for the user */
-#define FORMAT_SCHEME  1       /* To be used as a Pcmcia Scheme */
-#define WTYPE_ESSID    0       /* Display ESSID or NWID */
-#define WTYPE_AP       1       /* Display AP/Cell Address */
-#define WTYPE_FREQ     2       /* Display frequency/channel */
-#define WTYPE_MODE     3       /* Display mode */
-#define WTYPE_PROTO    4       /* Display protocol name */
-
 /*
  * Note on Pcmcia Schemes :
  * ----------------------
 /*
  * Note on Pcmcia Schemes :
  * ----------------------
  * Jean II - 29/3/01
  */
 
  * Jean II - 29/3/01
  */
 
-/*************************** SUBROUTINES ***************************/
-/*
- * Just for the heck of it, let's try to not link with iwlib.
- * This will keep the binary small and tiny...
- *
- * Note : maybe it's time to admit that we have lost the battle
- * and we start using iwlib ? Maybe we should default to dynamic
- * lib first...
- */
-
-/*------------------------------------------------------------------*/
-/*
- * Open a socket.
- * Depending on the protocol present, open the right socket. The socket
- * will allow us to talk to the driver.
- */
-int
-iw_sockets_open(void)
-{
-        int ipx_sock = -1;              /* IPX socket                   */
-        int ax25_sock = -1;             /* AX.25 socket                 */
-        int inet_sock = -1;             /* INET socket                  */
-        int ddp_sock = -1;              /* Appletalk DDP socket         */
-
-        /*
-         * Now pick any (exisiting) useful socket family for generic queries
-        * Note : don't open all the socket, only returns when one matches,
-        * all protocols might not be valid.
-        * Workaround by Jim Kaba <jkaba@sarnoff.com>
-        * Note : in 99% of the case, we will just open the inet_sock.
-        * The remaining 1% case are not fully correct...
-         */
-        inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
-        if(inet_sock!=-1)
-                return inet_sock;
-        ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
-        if(ipx_sock!=-1)
-                return ipx_sock;
-        ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
-        if(ax25_sock!=-1)
-                return ax25_sock;
-        ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
-        /*
-         * If this is -1 we have no known network layers and its time to jump.
-         */
-        return ddp_sock;
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Display an Ethernet address in readable format.
- */
-void
-iw_ether_ntop(const struct ether_addr* eth, char* buf)
-{
-  sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
-         eth->ether_addr_octet[0], eth->ether_addr_octet[1],
-         eth->ether_addr_octet[2], eth->ether_addr_octet[3],
-         eth->ether_addr_octet[4], eth->ether_addr_octet[5]);
-}
+/**************************** CONSTANTS ****************************/
 
 
-/*------------------------------------------------------------------*/
-/*
- * Convert our internal representation of frequencies to a floating point.
- */
-double
-iw_freq2float(iwfreq * in)
-{
-#ifdef WE_NOLIBM
-  /* Version without libm : slower */
-  int          i;
-  double       res = (double) in->m;
-  for(i = 0; i < in->e; i++)
-    res *= 10;
-  return(res);
-#else  /* WE_NOLIBM */
-  /* Version with libm : faster */
-  return ((double) in->m) * pow(10,in->e);
-#endif /* WE_NOLIBM */
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Output a frequency with proper scaling
- */
-void
-iw_print_freq(char *   buffer,
-             double    freq)
-{
-  if(freq < KILO)
-    sprintf(buffer, "Channel:%g", freq);
-  else
-    {
-      if(freq >= GIGA)
-       sprintf(buffer, "Frequency:%gGHz", freq / GIGA);
-      else
-       {
-         if(freq >= MEGA)
-           sprintf(buffer, "Frequency:%gMHz", freq / MEGA);
-         else
-           sprintf(buffer, "Frequency:%gkHz", freq / KILO);
-       }
-    }
-}
-
-/*------------------------------------------------------------------*/
-const char * const iw_operation_mode[] = { "Auto",
-                                       "Ad-Hoc",
-                                       "Managed",
-                                       "Master",
-                                       "Repeater",
-                                       "Secondary",
-                                       "Monitor" };
+#define FORMAT_DEFAULT 0       /* Nice looking display for the user */
+#define FORMAT_SCHEME  1       /* To be used as a Pcmcia Scheme */
+#define FORMAT_RAW     2       /* Raw value, for shell scripts */
+#define WTYPE_ESSID    0       /* Display ESSID or NWID */
+#define WTYPE_AP       1       /* Display AP/Cell Address */
+#define WTYPE_FREQ     2       /* Display frequency/channel */
+#define WTYPE_CHANNEL  3       /* Display channel (converted from freq) */
+#define WTYPE_MODE     4       /* Display mode */
+#define WTYPE_PROTO    5       /* Display protocol name */
 
 /************************ DISPLAY ESSID/NWID ************************/
 
 
 /************************ DISPLAY ESSID/NWID ************************/
 
@@ -199,12 +89,14 @@ print_essid(int                    skfd,
   unsigned int         i;
   unsigned int         j;
 
   unsigned int         i;
   unsigned int         j;
 
+  /* Make shure ESSID is NULL terminated */
+  memset(essid, 0, sizeof(essid));
+
   /* Get ESSID */
   /* Get ESSID */
-  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
   wrq.u.essid.pointer = (caddr_t) essid;
   wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
   wrq.u.essid.flags = 0;
   wrq.u.essid.pointer = (caddr_t) essid;
   wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
   wrq.u.essid.flags = 0;
-  if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0)
+  if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0)
     return(-1);
 
   switch(format)
     return(-1);
 
   switch(format)
@@ -220,8 +112,11 @@ print_essid(int                    skfd,
        return(-2);
       printf("%s\n", pessid);
       break;
        return(-2);
       printf("%s\n", pessid);
       break;
+    case FORMAT_RAW:
+      printf("%s\n", essid);
+      break;
     default:
     default:
-      printf("%-8.8s  ESSID:\"%s\"\n", ifname, essid);
+      printf("%-8.16s  ESSID:\"%s\"\n", ifname, essid);
       break;
     }
 
       break;
     }
 
@@ -240,8 +135,7 @@ print_nwid(int              skfd,
   struct iwreq         wrq;
 
   /* Get network ID */
   struct iwreq         wrq;
 
   /* Get network ID */
-  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
-  if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0)
+  if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0)
     return(-1);
 
   switch(format)
     return(-1);
 
   switch(format)
@@ -250,8 +144,11 @@ print_nwid(int             skfd,
       /* Prefix with nwid to avoid name space collisions */
       printf("nwid%X\n", wrq.u.nwid.value);
       break;
       /* Prefix with nwid to avoid name space collisions */
       printf("nwid%X\n", wrq.u.nwid.value);
       break;
+    case FORMAT_RAW:
+      printf("%X\n", wrq.u.nwid.value);
+      break;
     default:
     default:
-      printf("%-8.8s  NWID:%X\n", ifname, wrq.u.nwid.value);
+      printf("%-8.16s  NWID:%X\n", ifname, wrq.u.nwid.value);
       break;
     }
 
       break;
     }
 
@@ -273,8 +170,7 @@ print_ap(int                skfd,
   char                 buffer[64];
 
   /* Get AP Address */
   char                 buffer[64];
 
   /* Get AP Address */
-  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
-  if(ioctl(skfd, SIOCGIWAP, &wrq) < 0)
+  if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) < 0)
     return(-1);
 
   /* Print */
     return(-1);
 
   /* Print */
@@ -284,10 +180,11 @@ print_ap(int              skfd,
     case FORMAT_SCHEME:
       /* I think ':' are not problematic, because Pcmcia scripts
        * seem to handle them properly... */
     case FORMAT_SCHEME:
       /* I think ':' are not problematic, because Pcmcia scripts
        * seem to handle them properly... */
+    case FORMAT_RAW:
       printf("%s\n", buffer);
       break;
     default:
       printf("%s\n", buffer);
       break;
     default:
-      printf("%-8.8s  Access Point/Cell: %s\n", ifname, buffer);
+      printf("%-8.16s  Access Point/Cell: %s\n", ifname, buffer);
       break;
     }
 
       break;
     }
 
@@ -310,8 +207,7 @@ print_freq(int              skfd,
   char                 buffer[64];
 
   /* Get frequency / channel */
   char                 buffer[64];
 
   /* Get frequency / channel */
-  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
-  if(ioctl(skfd, SIOCGIWFREQ, &wrq) < 0)
+  if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
     return(-1);
 
   /* Print */
     return(-1);
 
   /* Print */
@@ -319,11 +215,64 @@ print_freq(int            skfd,
   switch(format)
     {
     case FORMAT_SCHEME:
   switch(format)
     {
     case FORMAT_SCHEME:
+      /* Prefix with freq to avoid name space collisions */
+      printf("freq%g\n", freq);
+      break;
+    case FORMAT_RAW:
       printf("%g\n", freq);
       break;
     default:
       printf("%g\n", freq);
       break;
     default:
-      iw_print_freq(buffer, freq);
-      printf("%-8.8s  %s\n", ifname, buffer);
+      iw_print_freq(buffer, sizeof(buffer), freq, -1, wrq.u.freq.flags);
+      printf("%-8.16s  %s\n", ifname, buffer);
+      break;
+    }
+
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Display the channel (converted from frequency) if possible
+ */
+static int
+print_channel(int              skfd,
+             const char *      ifname,
+             int               format)
+{
+  struct iwreq         wrq;
+  struct iw_range      range;
+  double               freq;
+  int                  channel;
+
+  /* Get frequency / channel */
+  if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
+    return(-1);
+
+  /* Convert to channel */
+  if(iw_get_range_info(skfd, ifname, &range) < 0)
+    return(-2);
+  freq = iw_freq2float(&(wrq.u.freq));
+  if(freq < KILO)
+    channel = (int) freq;
+  else
+    {
+      channel = iw_freq_to_channel(freq, &range);
+      if(channel < 0)
+       return(-3);
+    }
+
+  /* Print */
+  switch(format)
+    {
+    case FORMAT_SCHEME:
+      /* Prefix with freq to avoid name space collisions */
+      printf("channel%d\n", channel);
+      break;
+    case FORMAT_RAW:
+      printf("%d\n", channel);
+      break;
+    default:
+      printf("%-8.16s  Channel:%d\n", ifname, channel);
       break;
     }
 
       break;
     }
 
@@ -342,8 +291,7 @@ print_mode(int              skfd,
   struct iwreq         wrq;
 
   /* Get frequency / channel */
   struct iwreq         wrq;
 
   /* Get frequency / channel */
-  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
-  if(ioctl(skfd, SIOCGIWMODE, &wrq) < 0)
+  if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) < 0)
     return(-1);
   if(wrq.u.mode >= IW_NUM_OPER_MODE)
     return(-2);
     return(-1);
   if(wrq.u.mode >= IW_NUM_OPER_MODE)
     return(-2);
@@ -352,10 +300,17 @@ print_mode(int            skfd,
   switch(format)
     {
     case FORMAT_SCHEME:
   switch(format)
     {
     case FORMAT_SCHEME:
+      /* Strip all white space and stuff */
+      if(wrq.u.mode == IW_MODE_ADHOC)
+       printf("AdHoc\n");
+      else
+       printf("%s\n", iw_operation_mode[wrq.u.mode]);
+      break;
+    case FORMAT_RAW:
       printf("%d\n", wrq.u.mode);
       break;
     default:
       printf("%d\n", wrq.u.mode);
       break;
     default:
-      printf("%-8.8s  Mode:%s\n", ifname, iw_operation_mode[wrq.u.mode]);
+      printf("%-8.16s  Mode:%s\n", ifname, iw_operation_mode[wrq.u.mode]);
       break;
     }
 
       break;
     }
 
@@ -378,8 +333,7 @@ print_protocol(int          skfd,
   unsigned int         j;
 
   /* Get Protocol name */
   unsigned int         j;
 
   /* Get Protocol name */
-  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
-  if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
+  if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
     return(-1);
   strncpy(proto, wrq.u.name, IFNAMSIZ);
   proto[IFNAMSIZ] = '\0';
     return(-1);
   strncpy(proto, wrq.u.name, IFNAMSIZ);
   proto[IFNAMSIZ] = '\0';
@@ -397,8 +351,11 @@ print_protocol(int         skfd,
        return(-2);
       printf("%s\n", pproto);
       break;
        return(-2);
       printf("%s\n", pproto);
       break;
+    case FORMAT_RAW:
+      printf("%s\n", proto);
+      break;
     default:
     default:
-      printf("%-8.8s  Protocol Name:\"%s\"\n", ifname, proto);
+      printf("%-8.16s  Protocol Name:\"%s\"\n", ifname, proto);
       break;
     }
 
       break;
     }
 
@@ -427,6 +384,11 @@ print_one_device(int               skfd,
       ret = print_ap(skfd, ifname, format);
       break;
 
       ret = print_ap(skfd, ifname, format);
       break;
 
+    case WTYPE_CHANNEL:
+      /* Try to print channel */
+      ret = print_channel(skfd, ifname, format);
+      break;
+
     case WTYPE_FREQ:
       /* Try to print frequency */
       ret = print_freq(skfd, ifname, format);
     case WTYPE_FREQ:
       /* Try to print frequency */
       ret = print_freq(skfd, ifname, format);
@@ -458,6 +420,11 @@ print_one_device(int               skfd,
 /*------------------------------------------------------------------*/
 /*
  * Try the various devices until one return something we can use
 /*------------------------------------------------------------------*/
 /*
  * Try the various devices until one return something we can use
+ *
+ * Note : we can't use iw_enum_devices() because we want a different
+ * behaviour :
+ *     1) Stop at the first valid wireless device
+ *     2) Only go through active devices
  */
 static int
 scan_devices(int               skfd,
  */
 static int
 scan_devices(int               skfd,
@@ -498,9 +465,11 @@ iw_usage(int status)
   fputs("Usage iwgetid [OPTIONS] [ifname]\n"
        "  Options are:\n"
        "    -a,--ap       Print the access point address\n"
   fputs("Usage iwgetid [OPTIONS] [ifname]\n"
        "  Options are:\n"
        "    -a,--ap       Print the access point address\n"
+       "    -c,--channel  Print the current channel\n"
        "    -f,--freq     Print the current frequency\n"
        "    -m,--mode     Print the current mode\n"
        "    -p,--protocol Print the protocol name\n"
        "    -f,--freq     Print the current frequency\n"
        "    -m,--mode     Print the current mode\n"
        "    -p,--protocol Print the protocol name\n"
+       "    -r,--raw      Format the output as raw value for shell scripts\n"
        "    -s,--scheme   Format the output as a PCMCIA scheme identifier\n"
        "    -h,--help     Print this message\n",
        status ? stderr : stdout);
        "    -s,--scheme   Format the output as a PCMCIA scheme identifier\n"
        "    -h,--help     Print this message\n",
        status ? stderr : stdout);
@@ -509,10 +478,12 @@ iw_usage(int status)
 
 static const struct option long_opts[] = {
   { "ap", no_argument, NULL, 'a' },
 
 static const struct option long_opts[] = {
   { "ap", no_argument, NULL, 'a' },
+  { "channel", no_argument, NULL, 'c' },
   { "freq", no_argument, NULL, 'f' },
   { "mode", no_argument, NULL, 'm' },
   { "protocol", no_argument, NULL, 'p' },
   { "help", no_argument, NULL, 'h' },
   { "freq", no_argument, NULL, 'f' },
   { "mode", no_argument, NULL, 'm' },
   { "protocol", no_argument, NULL, 'p' },
   { "help", no_argument, NULL, 'h' },
+  { "raw", no_argument, NULL, 'r' },
   { "scheme", no_argument, NULL, 's' },
   { NULL, 0, NULL, 0 }
 };
   { "scheme", no_argument, NULL, 's' },
   { NULL, 0, NULL, 0 }
 };
@@ -532,7 +503,7 @@ main(int    argc,
   int  ret = -1;
 
   /* Check command line arguments */
   int  ret = -1;
 
   /* Check command line arguments */
-  while((opt = getopt_long(argc, argv, "afhmps", long_opts, NULL)) > 0)
+  while((opt = getopt_long(argc, argv, "acfhmprs", long_opts, NULL)) > 0)
     {
       switch(opt)
        {
     {
       switch(opt)
        {
@@ -541,6 +512,11 @@ main(int   argc,
          wtype = WTYPE_AP;
          break;
 
          wtype = WTYPE_AP;
          break;
 
+       case 'c':
+         /* User wants channel only */
+         wtype = WTYPE_CHANNEL;
+         break;
+
        case 'f':
          /* User wants frequency/channel */
          wtype = WTYPE_FREQ;
        case 'f':
          /* User wants frequency/channel */
          wtype = WTYPE_FREQ;
@@ -560,6 +536,11 @@ main(int   argc,
          iw_usage(0);
          break;
 
          iw_usage(0);
          break;
 
+       case 'r':
+         /* User wants a Raw format */
+         format = FORMAT_RAW;
+         break;
+
        case 's':
          /* User wants a Scheme format */
          format = FORMAT_SCHEME;
        case 's':
          /* User wants a Scheme format */
          format = FORMAT_SCHEME;
@@ -595,6 +576,6 @@ main(int    argc,
     }
 
   fflush(stdout);
     }
 
   fflush(stdout);
-  close(skfd);
+  iw_sockets_close(skfd);
   return(ret);
 }
   return(ret);
 }
index ca7aed0..b78882f 100644 (file)
@@ -1,12 +1,12 @@
 /*
  *     Wireless Tools
  *
 /*
  *     Wireless Tools
  *
- *             Jean II - HPLB 97->99 - HPL 99->03
+ *             Jean II - HPLB 97->99 - HPL 99->04
  *
  * Common subroutines to all the wireless tools...
  *
  * This file is released under the GPL license.
  *
  * Common subroutines to all the wireless tools...
  *
  * This file is released under the GPL license.
- *     Copyright (c) 1997-2003 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
  */
 
 /***************************** INCLUDES *****************************/
  */
 
 /***************************** INCLUDES *****************************/
 
 /************************ CONSTANTS & MACROS ************************/
 
 
 /************************ CONSTANTS & MACROS ************************/
 
-/* Various versions information */
-/* Recommended Wireless Extension version */
-#define WE_VERSION     16      /* ### don't forget #warning ### */
-/* Version of Wireless Tools */
-#define WT_VERSION     26
+/*
+ * Constants fof WE-9->15
+ */
+#define IW15_MAX_FREQUENCIES   16
+#define IW15_MAX_BITRATES      8
+#define IW15_MAX_TXPOWER       8
+#define IW15_MAX_ENCODING_SIZES        8
+#define IW15_MAX_SPY           8
+#define IW15_MAX_AP            8
+
+/****************************** TYPES ******************************/
 
 /*
 
 /*
- * Verify a few things about Wireless Extensions.
- * I try to maximise backward and forward compatibility, but things are
- * tricky because I'm fixing bugs and adding new features.
- * Wireless Tools *must* be compiled with the same version of WE
- * as the driver. Sometime, the size or layout of some structure changes,
- * and might produce interesting results.
- * Wireless Tools will usually compile properly against different
- * versions of WE, thanks to the zillions of #ifdefs in my code.
- * Jean II
+ *     Struct iw_range up to WE-15
  */
  */
-#if WIRELESS_EXT < 9
-#error "Wireless Extension v9 or newer required :-("
-#error "Use Wireless Tools v19 or update your kernel headers !"
-#endif
-#if WIRELESS_EXT < WE_VERSION && !defined(WEXT_HEADER)
-#warning "Wireless Extension earlier than v16 detected,"
-#warning "Not all tools features will be compiled in !"
-#warning "No worry, I'll try to make the best of it ;-)"
-#endif
-#if WIRELESS_EXT > WE_VERSION && !defined(WEXT_HEADER)
-#warning "Wireless Extension later than v16 detected,"
-#warning "Maybe you should get a more recent version"
-#warning "of the Wireless Tools package !"
-#endif
+struct iw15_range
+{
+       __u32           throughput;
+       __u32           min_nwid;
+       __u32           max_nwid;
+       __u16           num_channels;
+       __u8            num_frequency;
+       struct iw_freq  freq[IW15_MAX_FREQUENCIES];
+       __s32           sensitivity;
+       struct iw_quality       max_qual;
+       __u8            num_bitrates;
+       __s32           bitrate[IW15_MAX_BITRATES];
+       __s32           min_rts;
+       __s32           max_rts;
+       __s32           min_frag;
+       __s32           max_frag;
+       __s32           min_pmp;
+       __s32           max_pmp;
+       __s32           min_pmt;
+       __s32           max_pmt;
+       __u16           pmp_flags;
+       __u16           pmt_flags;
+       __u16           pm_capa;
+       __u16           encoding_size[IW15_MAX_ENCODING_SIZES];
+       __u8            num_encoding_sizes;
+       __u8            max_encoding_tokens;
+       __u16           txpower_capa;
+       __u8            num_txpower;
+       __s32           txpower[IW15_MAX_TXPOWER];
+       __u8            we_version_compiled;
+       __u8            we_version_source;
+       __u16           retry_capa;
+       __u16           retry_flags;
+       __u16           r_time_flags;
+       __s32           min_retry;
+       __s32           max_retry;
+       __s32           min_r_time;
+       __s32           max_r_time;
+       struct iw_quality       avg_qual;
+};
+
+/*
+ * Union for all the versions of iwrange.
+ * Fortunately, I mostly only add fields at the end, and big-bang
+ * reorganisations are few.
+ */
+union  iw_range_raw
+{
+       struct iw15_range       range15;        /* WE 9->15 */
+       struct iw_range         range;          /* WE 16->current */
+};
+
+/*
+ * Offsets in iw_range struct
+ */
+#define iwr15_off(f)   ( ((char *) &(((struct iw15_range *) NULL)->f)) - \
+                         (char *) NULL)
+#define iwr_off(f)     ( ((char *) &(((struct iw_range *) NULL)->f)) - \
+                         (char *) NULL)
 
 /**************************** VARIABLES ****************************/
 
 
 /**************************** VARIABLES ****************************/
 
+/* Modes as human readable strings */
 const char * const iw_operation_mode[] = { "Auto",
                                        "Ad-Hoc",
                                        "Managed",
 const char * const iw_operation_mode[] = { "Auto",
                                        "Ad-Hoc",
                                        "Managed",
@@ -146,7 +190,7 @@ iw_get_ifname(char *        name,   /* Where to store the name */
  */
 void
 iw_enum_devices(int            skfd,
  */
 void
 iw_enum_devices(int            skfd,
-               iw_enum_handler fn,
+               iw_enum_handler fn,
                char *          args[],
                int             count)
 {
                char *          args[],
                int             count)
 {
@@ -217,77 +261,63 @@ iw_enum_devices(int               skfd,
 
 /*------------------------------------------------------------------*/
 /*
 
 /*------------------------------------------------------------------*/
 /*
- * Get the range information out of the driver
+ * Extract WE version number from /proc/net/wireless
+ * In most cases, you really want to get version information from
+ * the range info (range->we_version_compiled), see below...
+ *
+ * If we have WE-16 and later, the WE version is available at the
+ * end of the header line of the file.
+ * For version prior to that, we can only detect the change from
+ * v11 to v12, so we do an approximate job. Fortunately, v12 to v15
+ * are highly binary compatible (on the struct level).
  */
 int
  */
 int
-iw_get_range_info(int          skfd,
-                 char *        ifname,
-                 iwrange *     range)
+iw_get_kernel_we_version(void)
 {
 {
-  struct iwreq         wrq;
-  char                 buffer[sizeof(iwrange) * 2];    /* Large enough */
+  char         buff[1024];
+  FILE *       fh;
+  char *       p;
+  int          v;
 
 
-  /* Cleanup */
-  memset(buffer, 0, sizeof(buffer));
+  /* Check if /proc/net/wireless is available */
+  fh = fopen(PROC_NET_WIRELESS, "r");
 
 
-  wrq.u.data.pointer = (caddr_t) buffer;
-  wrq.u.data.length = sizeof(buffer);
-  wrq.u.data.flags = 0;
-  if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
-    return(-1);
+  if(fh == NULL)
+    {
+      fprintf(stderr, "Cannot read " PROC_NET_WIRELESS "\n");
+      return(-1);
+    }
 
 
-  /* Copy stuff at the right place, ignore extra */
-  memcpy((char *) range, buffer, sizeof(iwrange));
+  /* Read the first line of buffer */
+  fgets(buff, sizeof(buff), fh);
 
 
-  /* Lots of people have driver and tools out of sync as far as Wireless
-   * Extensions are concerned. It's because /usr/include/linux/wireless.h
-   * and /usr/src/linux/include/linux/wireless.h are different.
-   * We try to catch this stuff here... */
-  if(!iw_ignore_version)
+  if(strstr(buff, "| WE") == NULL)
     {
     {
-      /* For new versions, we can check the version directly, for old versions
-       * we use magic. 300 bytes is a also magic number, don't touch... */
-      if((WIRELESS_EXT > 10) && (wrq.u.data.length >= 300))
-       {
-#if WIRELESS_EXT > 10
-         /* Version verification - for new versions */
-         if(range->we_version_compiled != WIRELESS_EXT)
-           {
-             fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled);
-             fprintf(stderr, "of Wireless Extension, while this program is using version %d.\n", WIRELESS_EXT);
-             fprintf(stderr, "Some things may be broken...\n\n");
-           }
-         /* Driver version verification */
-         if(range->we_version_compiled < range->we_version_source)
-           {
-             fprintf(stderr, "Warning: Driver for device %s recommend version %d of Wireless Extension,\n", ifname, range->we_version_source);
-             fprintf(stderr, "but has been compiled with version %d, therefore some driver features\n", range->we_version_compiled);
-             fprintf(stderr, "may not be available...\n\n");
-           }
-#endif /* WIRELESS_EXT > 10 */
-       }
+      /* Prior to WE16, so explicit version not present */
+
+      /* Black magic */
+      if(strstr(buff, "| Missed") == NULL)
+       v = 11;
       else
       else
-       {
-         /* Version verification - for old versions */
-         if(wrq.u.data.length != sizeof(iwrange))
-           {
-             fprintf(stderr, "Warning: Driver for device %s has been compiled with an ancient version\n", ifname);
-             fprintf(stderr, "of Wireless Extension, while this program is using version %d.\n", WIRELESS_EXT);
-             fprintf(stderr, "Some things may be broken...\n\n");
-           }
-       }
+       v = 15;
+      fclose(fh);
+      return(v);
     }
     }
-  /* Don't complain twice.
-   * In theory, the test apply to each individual driver, but usually
-   * all drivers are compiled from the same kernel, and most often
-   * problem is the system/glibc headers. */
-  iw_ignore_version = 1;
 
 
-  /* Note : we are only trying to catch compile difference, not source.
-   * If the driver source has not been updated to the latest, it doesn't
-   * matter because the new fields are set to zero */
+  /* Read the second line of buffer */
+  fgets(buff, sizeof(buff), fh);
 
 
-  return(0);
+  /* Get to the last separator, to get the version */
+  p = strrchr(buff, '|');
+  if((p == NULL) || (sscanf(p + 1, "%d", &v) != 1))
+    {
+      fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
+      fclose(fh);
+      return(-1);
+    }
+
+  fclose(fh);
+  return(v);
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
@@ -321,7 +351,7 @@ print_iface_version_info(int        skfd,
   if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
     {
       /* Interface support WE (see above), but not IWRANGE */
   if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
     {
       /* Interface support WE (see above), but not IWRANGE */
-      fprintf(stderr, "%-8.8s  Driver has no Wireless Extension version information.\n\n", ifname);
+      fprintf(stderr, "%-8.16s  Driver has no Wireless Extension version information.\n\n", ifname);
       return(0);
     }
 
       return(0);
     }
 
@@ -330,21 +360,18 @@ print_iface_version_info(int      skfd,
 
   /* For new versions, we can check the version directly, for old versions
    * we use magic. 300 bytes is a also magic number, don't touch... */
 
   /* For new versions, we can check the version directly, for old versions
    * we use magic. 300 bytes is a also magic number, don't touch... */
-  if((WIRELESS_EXT > 10) && (wrq.u.data.length >= 300))
+  if(wrq.u.data.length >= 300)
     {
     {
-#if WIRELESS_EXT > 10
-      printf("%-8.8s  Recommend Wireless Extension v%d or later,\n",
+      /* Version is always at the same offset, so it's ok */
+      printf("%-8.16s  Recommend Wireless Extension v%d or later,\n",
             ifname, range->we_version_source);
       printf("          Currently compiled with Wireless Extension v%d.\n\n",
             range->we_version_compiled);
             ifname, range->we_version_source);
       printf("          Currently compiled with Wireless Extension v%d.\n\n",
             range->we_version_compiled);
-#endif /* WIRELESS_EXT > 10 */
     }
   else
     {
     }
   else
     {
-#if 0
-      fprintf(stderr, "%-8.8s  Wireless Extension version too old.\n\n",
+      fprintf(stderr, "%-8.16s  Wireless Extension version too old.\n\n",
                      ifname);
                      ifname);
-#endif
     }
 
 
     }
 
 
@@ -356,13 +383,10 @@ print_iface_version_info(int      skfd,
  * Print the WE versions of the tools.
  */
 int
  * Print the WE versions of the tools.
  */
 int
-iw_print_version_info(char *   toolname)
+iw_print_version_info(const char *     toolname)
 {
   int          skfd;                   /* generic raw socket desc.     */
 {
   int          skfd;                   /* generic raw socket desc.     */
-  char         buff[1024];
-  FILE *       fh;
-  char *       p;
-  int          v;
+  int          we_kernel_version;
 
   /* Create a channel to the NET kernel. */
   if((skfd = iw_sockets_open()) < 0)
 
   /* Create a channel to the NET kernel. */
   if((skfd = iw_sockets_open()) < 0)
@@ -373,64 +397,214 @@ iw_print_version_info(char *     toolname)
 
   /* Information about the tools themselves */
   if(toolname != NULL)
 
   /* Information about the tools themselves */
   if(toolname != NULL)
-    printf("%-8.8s  Version %d\n", toolname, WT_VERSION);
-  printf("          Compatible with Wireless Extension v%d or earlier,\n",
+    printf("%-8.16s  Wireless-Tools version %d\n", toolname, WT_VERSION);
+  printf("          Compatible with Wireless Extension v11 to v%d.\n\n",
         WE_VERSION);
         WE_VERSION);
-  printf("          Currently compiled with Wireless Extension v%d.\n\n",
-        WIRELESS_EXT);
 
 
-  /* Check if /proc/net/wireless is available */
-  fh = fopen(PROC_NET_WIRELESS, "r");
-  if(fh != NULL)
+  /* Get version from kernel */
+  we_kernel_version = iw_get_kernel_we_version();
+  /* Only version >= 16 can be verified, other are guessed */
+  if(we_kernel_version > 15)
+    printf("Kernel    Currently compiled with Wireless Extension v%d.\n\n",
+          we_kernel_version);
+
+  /* Version for each device */
+  iw_enum_devices(skfd, &print_iface_version_info, NULL, 0);
+
+  iw_sockets_close(skfd);
+
+  return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Get the range information out of the driver
+ */
+int
+iw_get_range_info(int          skfd,
+                 const char *  ifname,
+                 iwrange *     range)
+{
+  struct iwreq         wrq;
+  char                 buffer[sizeof(iwrange) * 2];    /* Large enough */
+  union iw_range_raw * range_raw;
+
+  /* Cleanup */
+  bzero(buffer, sizeof(buffer));
+
+  wrq.u.data.pointer = (caddr_t) buffer;
+  wrq.u.data.length = sizeof(buffer);
+  wrq.u.data.flags = 0;
+  if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
+    return(-1);
+
+  /* Point to the buffer */
+  range_raw = (union iw_range_raw *) buffer;
+
+  /* For new versions, we can check the version directly, for old versions
+   * we use magic. 300 bytes is a also magic number, don't touch... */
+  if(wrq.u.data.length < 300)
     {
     {
-      /* Read the first line of buffer */
-      fgets(buff, sizeof(buff), fh);
+      /* That's v10 or earlier. Ouch ! Let's make a guess...*/
+      range_raw->range.we_version_compiled = 9;
+    }
+
+  /* Check how it needs to be processed */
+  if(range_raw->range.we_version_compiled > 15)
+    {
+      /* This is our native format, that's easy... */
+      /* Copy stuff at the right place, ignore extra */
+      memcpy((char *) range, buffer, sizeof(iwrange));
+    }
+  else
+    {
+      /* Zero unknown fields */
+      bzero((char *) range, sizeof(struct iw_range));
+
+      /* Initial part unmoved */
+      memcpy((char *) range,
+            buffer,
+            iwr15_off(num_channels));
+      /* Frequencies pushed futher down towards the end */
+      memcpy((char *) range + iwr_off(num_channels),
+            buffer + iwr15_off(num_channels),
+            iwr15_off(sensitivity) - iwr15_off(num_channels));
+      /* This one moved up */
+      memcpy((char *) range + iwr_off(sensitivity),
+            buffer + iwr15_off(sensitivity),
+            iwr15_off(num_bitrates) - iwr15_off(sensitivity));
+      /* This one goes after avg_qual */
+      memcpy((char *) range + iwr_off(num_bitrates),
+            buffer + iwr15_off(num_bitrates),
+            iwr15_off(min_rts) - iwr15_off(num_bitrates));
+      /* Number of bitrates has changed, put it after */
+      memcpy((char *) range + iwr_off(min_rts),
+            buffer + iwr15_off(min_rts),
+            iwr15_off(txpower_capa) - iwr15_off(min_rts));
+      /* Added encoding_login_index, put it after */
+      memcpy((char *) range + iwr_off(txpower_capa),
+            buffer + iwr15_off(txpower_capa),
+            iwr15_off(txpower) - iwr15_off(txpower_capa));
+      /* Hum... That's an unexpected glitch. Bummer. */
+      memcpy((char *) range + iwr_off(txpower),
+            buffer + iwr15_off(txpower),
+            iwr15_off(avg_qual) - iwr15_off(txpower));
+      /* Avg qual moved up next to max_qual */
+      memcpy((char *) range + iwr_off(avg_qual),
+            buffer + iwr15_off(avg_qual),
+            sizeof(struct iw_quality));
+    }
 
 
-      /* Check if it's WE-16 or later */
-      if(strstr(buff, "| WE") != NULL)
+  /* We are now checking much less than we used to do, because we can
+   * accomodate more WE version. But, there are still cases where things
+   * will break... */
+  if(!iw_ignore_version)
+    {
+      /* We don't like very old version (unfortunately kernel 2.2.X) */
+      if(range->we_version_compiled <= 10)
        {
        {
-         /* Read the second line of buffer */
-         fgets(buff, sizeof(buff), fh);
-
-         /* Get to the last separator, to get the version */
-         p = strrchr(buff, '|');
-         if((p != NULL) && (sscanf(p + 1, "%d", &v) == 1))
-           /* That was it ! */
-           printf("Kernel    Currently compiled with Wireless Extension v%d.\n\n", v);
+         fprintf(stderr, "Warning: Driver for device %s has been compiled with an ancient version\n", ifname);
+         fprintf(stderr, "of Wireless Extension, while this program support version 11 and later.\n");
+         fprintf(stderr, "Some things may be broken...\n\n");
        }
        }
-      /* Cleanup */
-      fclose(fh);
-    }
 
 
-  /* Version for each device */
-  iw_enum_devices(skfd, &print_iface_version_info, NULL, 0);
+      /* We don't like future versions of WE, because we can't cope with
+       * the unknown */
+      if(range->we_version_compiled > WE_VERSION)
+       {
+         fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled);
+         fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_VERSION);
+         fprintf(stderr, "Some things may be broken...\n\n");
+       }
 
 
-  close(skfd);
+      /* Driver version verification */
+      if((range->we_version_compiled > 10) &&
+        (range->we_version_compiled < range->we_version_source))
+       {
+         fprintf(stderr, "Warning: Driver for device %s recommend version %d of Wireless Extension,\n", ifname, range->we_version_source);
+         fprintf(stderr, "but has been compiled with version %d, therefore some driver features\n", range->we_version_compiled);
+         fprintf(stderr, "may not be available...\n\n");
+       }
+      /* Note : we are only trying to catch compile difference, not source.
+       * If the driver source has not been updated to the latest, it doesn't
+       * matter because the new fields are set to zero */
+    }
 
 
-  return 0;
+  /* Don't complain twice.
+   * In theory, the test apply to each individual driver, but usually
+   * all drivers are compiled from the same kernel. */
+  iw_ignore_version = 1;
+
+  return(0);
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Get information about what private ioctls are supported by the driver
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Get information about what private ioctls are supported by the driver
+ *
+ * Note : there is one danger using this function. If it return 0, you
+ * still need to free() the buffer. Beware.
  */
 int
 iw_get_priv_info(int           skfd,
  */
 int
 iw_get_priv_info(int           skfd,
-                char *         ifname,
-                iwprivargs *   priv,
-                int            maxpriv)
+                const char *   ifname,
+                iwprivargs **  ppriv)
 {
   struct iwreq         wrq;
 {
   struct iwreq         wrq;
+  iwprivargs *         priv = NULL;    /* Not allocated yet */
+  int                  maxpriv = 16;   /* Minimum for compatibility WE<13 */
+  iwprivargs *         newpriv;
+
+  /* Some driver may return a very large number of ioctls. Some
+   * others a very small number. We now use a dynamic allocation
+   * of the array to satisfy everybody. Of course, as we don't know
+   * in advance the size of the array, we try various increasing
+   * sizes. Jean II */
+  do
+    {
+      /* (Re)allocate the buffer */
+      newpriv = realloc(priv, maxpriv * sizeof(priv[0]));
+      if(newpriv == NULL)
+       {
+         fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
+         break;
+       }
+      priv = newpriv;
 
 
-  /* Ask the driver */
-  wrq.u.data.pointer = (caddr_t) priv;
-  wrq.u.data.length = maxpriv;
-  wrq.u.data.flags = 0;
-  if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) < 0)
-    return(-1);
+      /* Ask the driver if it's large enough */
+      wrq.u.data.pointer = (caddr_t) priv;
+      wrq.u.data.length = maxpriv;
+      wrq.u.data.flags = 0;
+      if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) >= 0)
+       {
+         /* Success. Pass the buffer by pointer */
+         *ppriv = priv;
+         /* Return the number of ioctls */
+         return(wrq.u.data.length);
+       }
+
+      /* Only E2BIG means the buffer was too small, abort on other errors */
+      if(errno != E2BIG)
+       {
+         /* Most likely "not supported". Don't barf. */
+         break;
+       }
 
 
-  /* Return the number of ioctls */
-  return(wrq.u.data.length);
+      /* Failed. We probably need a bigger buffer. Check if the kernel
+       * gave us any hints. */
+      if(wrq.u.data.length > maxpriv)
+       maxpriv = wrq.u.data.length;
+      else
+       maxpriv *= 2;
+    }
+  while(maxpriv < 1000);
+
+  /* Cleanup */
+  if(priv)
+    free(priv);
+  *ppriv = NULL;
+
+  return(-1);
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
@@ -443,7 +617,7 @@ iw_get_priv_info(int                skfd,
  */
 int
 iw_get_basic_config(int                        skfd,
  */
 int
 iw_get_basic_config(int                        skfd,
-                   char *              ifname,
+                   const char *        ifname,
                    wireless_config *   info)
 {
   struct iwreq         wrq;
                    wireless_config *   info)
 {
   struct iwreq         wrq;
@@ -472,6 +646,7 @@ iw_get_basic_config(int                     skfd,
     {
       info->has_freq = 1;
       info->freq = iw_freq2float(&(wrq.u.freq));
     {
       info->has_freq = 1;
       info->freq = iw_freq2float(&(wrq.u.freq));
+      info->freq_flags = wrq.u.freq.flags;
     }
 
   /* Get encryption information */
     }
 
   /* Get encryption information */
@@ -499,7 +674,7 @@ iw_get_basic_config(int                     skfd,
   if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
     {
       info->mode = wrq.u.mode;
   if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
     {
       info->mode = wrq.u.mode;
-      if((info->mode < 6) && (info->mode >= 0))
+      if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
        info->has_mode = 1;
     }
 
        info->has_mode = 1;
     }
 
@@ -515,7 +690,7 @@ iw_get_basic_config(int                     skfd,
  */
 int
 iw_set_basic_config(int                        skfd,
  */
 int
 iw_set_basic_config(int                        skfd,
-                   char *              ifname,
+                   const char *        ifname,
                    wireless_config *   info)
 {
   struct iwreq         wrq;
                    wireless_config *   info)
 {
   struct iwreq         wrq;
@@ -526,15 +701,18 @@ iw_set_basic_config(int                   skfd,
     /* If no wireless name : no wireless extensions */
     return(-2);
 
     /* 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)
+  /* Set the current mode of operation
+   * Mode need to be first : some settings apply only in a specific mode
+   * (such as frequency).
+   */
+  if(info->has_mode)
     {
     {
-      memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam));
-      wrq.u.nwid.fixed = 1;    /* Hum... When in Rome... */
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+      wrq.u.mode = info->mode;
 
 
-      if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
+      if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
        {
        {
-         fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
+         fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
          ret = -1;
        }
     }
          ret = -1;
        }
     }
@@ -580,6 +758,10 @@ iw_set_basic_config(int                    skfd,
       wrq.u.data.length = info->key_size;
       wrq.u.data.flags = flags;
 
       wrq.u.data.length = info->key_size;
       wrq.u.data.flags = flags;
 
+      /* Compatibility with WE<13 */
+      if(flags & IW_ENCODE_NOKEY)
+       wrq.u.data.pointer = NULL;
+
       if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
        {
          fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
       if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
        {
          fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
@@ -588,29 +770,33 @@ iw_set_basic_config(int                   skfd,
        }
     }
 
        }
     }
 
-  /* Set ESSID (extended network), if available */
-  if(info->has_essid)
+  /* Set Network ID, if available (this is for non-802.11 cards) */
+  if(info->has_nwid)
     {
     {
-      wrq.u.essid.pointer = (caddr_t) info->essid;
-      wrq.u.essid.length = strlen(info->essid) + 1;
-      wrq.u.data.flags = info->essid_on;
+      memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam));
+      wrq.u.nwid.fixed = 1;    /* Hum... When in Rome... */
 
 
-      if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
+      if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
        {
        {
-         fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
+         fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
          ret = -1;
        }
     }
 
          ret = -1;
        }
     }
 
-  /* Set the current mode of operation */
-  if(info->has_mode)
+  /* Set ESSID (extended network), if available.
+   * ESSID need to be last : most device re-perform the scanning/discovery
+   * when this is set, and things like encryption keys are better be
+   * defined if we want to discover the right set of APs/nodes.
+   */
+  if(info->has_essid)
     {
     {
-      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
-      wrq.u.mode = info->mode;
+      wrq.u.essid.pointer = (caddr_t) info->essid;
+      wrq.u.essid.length = strlen(info->essid) + 1;
+      wrq.u.data.flags = info->essid_on;
 
 
-      if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
+      if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
        {
        {
-         fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
+         fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
          ret = -1;
        }
     }
          ret = -1;
        }
     }
@@ -632,14 +818,15 @@ iw_set_basic_config(int                   skfd,
  * but if they interoperate at some level, and also if they accept the
  * same type of config (ESSID vs NWID, freq...).
  * This is supposed to work around the alphabet soup.
  * but if they interoperate at some level, and also if they accept the
  * same type of config (ESSID vs NWID, freq...).
  * This is supposed to work around the alphabet soup.
- * Return 1 if protocols are compatible
+ * Return 1 if protocols are compatible, 0 otherwise
  */
 int
  */
 int
-iw_protocol_compare(char *     protocol1,
-                   char *      protocol2)
+iw_protocol_compare(const char *       protocol1,
+                   const char *        protocol2)
 {
 {
-  char *       dot11 = "IEEE 802.11";
-  char *       dot11_ds = "Dbg";
+  const char * dot11 = "IEEE 802.11";
+  const char * dot11_ds = "Dbg";
+  const char * dot11_5g = "a";
 
   /* If the strings are the same -> easy */
   if(!strncmp(protocol1, protocol2, IFNAMSIZ))
 
   /* If the strings are the same -> easy */
   if(!strncmp(protocol1, protocol2, IFNAMSIZ))
@@ -649,18 +836,34 @@ iw_protocol_compare(char *        protocol1,
   if( (!strncmp(protocol1, dot11, strlen(dot11))) &&
       (!strncmp(protocol2, dot11, strlen(dot11))) )
     {
   if( (!strncmp(protocol1, dot11, strlen(dot11))) &&
       (!strncmp(protocol2, dot11, strlen(dot11))) )
     {
-      char *   sub1 = protocol1 + strlen(dot11);
-      char *   sub2 = protocol2 + strlen(dot11);
-
-      /* Skip optional separator */
-      if(*sub1 == '-')
-       sub1++;
-      if(*sub2 == '-')
-       sub2++;
+      const char *     sub1 = protocol1 + strlen(dot11);
+      const char *     sub2 = protocol2 + strlen(dot11);
+      unsigned int     i;
+      int              isds1 = 0;
+      int              isds2 = 0;
+      int              is5g1 = 0;
+      int              is5g2 = 0;
+
+      /* Check if we find the magic letters telling it's DS compatible */
+      for(i = 0; i < strlen(dot11_ds); i++)
+       {
+         if(strchr(sub1, dot11_ds[i]) != NULL)
+           isds1 = 1;
+         if(strchr(sub2, dot11_ds[i]) != NULL)
+           isds2 = 1;
+       }
+      if(isds1 && isds2)
+       return(1);
 
 
-      /* Check if they are both 2.4 GHz Direct Sequence compatible */
-      if( (strchr(dot11_ds, *sub1) != NULL) &&
-         (strchr(dot11_ds, *sub2) != NULL) )
+      /* Check if we find the magic letters telling it's 5GHz compatible */
+      for(i = 0; i < strlen(dot11_5g); i++)
+       {
+         if(strchr(sub1, dot11_5g[i]) != NULL)
+           is5g1 = 1;
+         if(strchr(sub2, dot11_5g[i]) != NULL)
+           is5g2 = 1;
+       }
+      if(is5g1 && is5g2)
        return(1);
     }
   /* Not compatible */
        return(1);
     }
   /* Not compatible */
@@ -718,7 +921,7 @@ iw_float2freq(double        in,
  * Convert our internal representation of frequencies to a floating point.
  */
 double
  * Convert our internal representation of frequencies to a floating point.
  */
 double
-iw_freq2float(iwfreq * in)
+iw_freq2float(const iwfreq *   in)
 {
 #ifdef WE_NOLIBM
   /* Version without libm : slower */
 {
 #ifdef WE_NOLIBM
   /* Version without libm : slower */
@@ -738,22 +941,67 @@ iw_freq2float(iwfreq *    in)
  * Output a frequency with proper scaling
  */
 void
  * Output a frequency with proper scaling
  */
 void
-iw_print_freq(char *   buffer,
-             double    freq)
+iw_print_freq_value(char *     buffer,
+                   int         buflen,
+                   double      freq)
 {
   if(freq < KILO)
 {
   if(freq < KILO)
-    sprintf(buffer, "Channel:%g", freq);
+    snprintf(buffer, buflen, "%g", freq);
   else
     {
   else
     {
+      char     scale;
+      int      divisor;
+
       if(freq >= GIGA)
       if(freq >= GIGA)
-       sprintf(buffer, "Frequency:%gGHz", freq / GIGA);
+       {
+         scale = 'G';
+         divisor = GIGA;
+       }
       else
        {
          if(freq >= MEGA)
       else
        {
          if(freq >= MEGA)
-           sprintf(buffer, "Frequency:%gMHz", freq / MEGA);
+           {
+             scale = 'M';
+             divisor = MEGA;
+           }
          else
          else
-           sprintf(buffer, "Frequency:%gkHz", freq / KILO);
+           {
+             scale = 'k';
+             divisor = KILO;
+           }
        }
        }
+      snprintf(buffer, buflen, "%g %cHz", freq / divisor, scale);
+    }
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Output a frequency with proper scaling
+ */
+void
+iw_print_freq(char *   buffer,
+             int       buflen,
+             double    freq,
+             int       channel,
+             int       freq_flags)
+{
+  char sep = ((freq_flags & IW_FREQ_FIXED) ? '=' : ':');
+  char vbuf[16];
+
+  /* Print the frequency/channel value */
+  iw_print_freq_value(vbuf, sizeof(vbuf), freq);
+
+  /* Check if channel only */
+  if(freq < KILO)
+    snprintf(buffer, buflen, "Channel%c%s", sep, vbuf);
+  else
+    {
+      /* Frequency. Check if we have a channel as well */
+      if(channel >= 0)
+       snprintf(buffer, buflen, "Frequency%c%s (Channel %d)",
+                sep, vbuf, channel);
+      else
+       snprintf(buffer, buflen, "Frequency%c%s", sep, vbuf);
     }
 }
 
     }
 }
 
@@ -762,8 +1010,8 @@ iw_print_freq(char *       buffer,
  * Convert a frequency to a channel (negative -> error)
  */
 int
  * Convert a frequency to a channel (negative -> error)
  */
 int
-iw_freq_to_channel(double              freq,
-                  struct iw_range *    range)
+iw_freq_to_channel(double                      freq,
+                  const struct iw_range *      range)
 {
   double       ref_freq;
   int          k;
 {
   double       ref_freq;
   int          k;
@@ -784,6 +1032,41 @@ iw_freq_to_channel(double         freq,
   return(-2);
 }
 
   return(-2);
 }
 
+/*------------------------------------------------------------------*/
+/*
+ * Convert a channel to a frequency (negative -> error)
+ * Return the channel on success
+ */
+int
+iw_channel_to_freq(int                         channel,
+                  double *                     pfreq,
+                  const struct iw_range *      range)
+{
+  int          has_freq = 0;
+  int          k;
+
+  /* Check if the driver support only channels or if it has frequencies */
+  for(k = 0; k < range->num_frequency; k++)
+    {
+      if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO))
+       has_freq = 1;
+    }
+  if(!has_freq)
+    return(-1);
+
+  /* Find the correct frequency in the list */
+  for(k = 0; k < range->num_frequency; k++)
+    {
+      if(range->freq[k].i == channel)
+       {
+         *pfreq = iw_freq2float(&(range->freq[k]));
+         return(channel);
+       }
+    }
+  /* Not found */
+  return(-2);
+}
+
 /*********************** BITRATE SUBROUTINES ***********************/
 
 /*------------------------------------------------------------------*/
 /*********************** BITRATE SUBROUTINES ***********************/
 
 /*------------------------------------------------------------------*/
@@ -792,17 +1075,32 @@ iw_freq_to_channel(double                freq,
  */
 void
 iw_print_bitrate(char *        buffer,
  */
 void
 iw_print_bitrate(char *        buffer,
+                int    buflen,
                 int    bitrate)
 {
   double       rate = bitrate;
                 int    bitrate)
 {
   double       rate = bitrate;
+  char         scale;
+  int          divisor;
 
   if(rate >= GIGA)
 
   if(rate >= GIGA)
-    sprintf(buffer, "%gGb/s", rate / GIGA);
+    {
+      scale = 'G';
+      divisor = GIGA;
+    }
   else
   else
-    if(rate >= MEGA)
-      sprintf(buffer, "%gMb/s", rate / MEGA);
-    else
-      sprintf(buffer, "%gkb/s", rate / KILO);
+    {
+      if(rate >= MEGA)
+       {
+         scale = 'M';
+         divisor = MEGA;
+       }
+      else
+       {
+         scale = 'k';
+         divisor = KILO;
+       }
+    }
+  snprintf(buffer, buflen, "%g %cb/s", rate / divisor, scale);
 }
 
 /************************ POWER SUBROUTINES *************************/
 }
 
 /************************ POWER SUBROUTINES *************************/
@@ -863,6 +1161,43 @@ iw_mwatt2dbm(int  in)
 #endif /* WE_NOLIBM */
 }
 
 #endif /* WE_NOLIBM */
 }
 
+/*------------------------------------------------------------------*/
+/*
+ * Output a txpower with proper conversion
+ */
+void
+iw_print_txpower(char *                        buffer,
+                int                    buflen,
+                struct iw_param *      txpower)
+{
+  int          dbm;
+
+  /* Check if disabled */
+  if(txpower->disabled)
+    {
+      snprintf(buffer, buflen, "off");
+    }
+  else
+    {
+      /* Check for relative values */
+      if(txpower->flags & IW_TXPOW_RELATIVE)
+       {
+         snprintf(buffer, buflen, "%d", txpower->value);
+       }
+      else
+       {
+         /* Convert everything to dBm */
+         if(txpower->flags & IW_TXPOW_MWATT)
+           dbm = iw_mwatt2dbm(txpower->value);
+         else
+           dbm = txpower->value;
+
+         /* Display */
+         snprintf(buffer, buflen, "%d dBm", dbm);
+       }
+    }
+}
+
 /********************** STATISTICS SUBROUTINES **********************/
 
 /*------------------------------------------------------------------*/
 /********************** STATISTICS SUBROUTINES **********************/
 
 /*------------------------------------------------------------------*/
@@ -870,76 +1205,84 @@ iw_mwatt2dbm(int in)
  * Read /proc/net/wireless to get the latest statistics
  */
 int
  * Read /proc/net/wireless to get the latest statistics
  */
 int
-iw_get_stats(int       skfd,
-            char *     ifname,
-            iwstats *  stats)
+iw_get_stats(int               skfd,
+            const char *       ifname,
+            iwstats *          stats,
+            const iwrange *    range,
+            int                has_range)
 {
 {
-#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(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0)
-    return(-1);
+  /* Fortunately, we can always detect this condition properly */
+  if((has_range) && (range->we_version_compiled > 11))
+    {
+      struct iwreq             wrq;
+      wrq.u.data.pointer = (caddr_t) stats;
+      wrq.u.data.length = sizeof(struct iw_statistics);
+      wrq.u.data.flags = 1;            /* Clear updated flag */
+      strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+      if(iw_get_ext(skfd, ifname, 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;
-  skfd = skfd; /* Avoid "Unused parameter" warning */
-  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 */
+      /* Format has not changed since WE-12, no conversion */
+      return(0);
+    }
+  else
+    {
+      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);
+             /* No conversion needed */
+             return 0;
+           }
+       }
+      fclose(f);
+      return -1;
+    }
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
@@ -948,40 +1291,99 @@ iw_get_stats(int skfd,
  */
 void
 iw_print_stats(char *          buffer,
  */
 void
 iw_print_stats(char *          buffer,
-              iwqual *         qual,
-              iwrange *        range,
+              int              buflen,
+              const iwqual *   qual,
+              const iwrange *  range,
               int              has_range)
 {
               int              has_range)
 {
+  int          len;
+
+  /* People are very often confused by the 8 bit arithmetic happening
+   * here.
+   * All the values here are encoded in a 8 bit integer. 8 bit integers
+   * are either unsigned [0 ; 255], signed [-128 ; +127] or
+   * negative [-255 ; 0].
+   * Further, on 8 bits, 0x100 == 256 == 0.
+   *
+   * Relative/percent values are always encoded unsigned, between 0 and 255.
+   * Absolute/dBm values are always encoded negative, between -255 and 0.
+   *
+   * How do we separate relative from absolute values ? We use the
+   * range to do that. The range allow to specify the real min/max
+   * of the value. As the range struct only specify one bound of the
+   * value, we assume that the other bound is 0 (zero).
+   * For relative values, range is [0 ; range->max].
+   * For absolute values, range is [range->max ; 0].
+   *
+   * Let's take two example :
+   * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100
+   * 2) value is -54dBm. noise floor of the radio is -104dBm.
+   *    qual->value = -54 = 202 ; range->max_qual.value = -104 = 152
+   *
+   * Jean II
+   */
+
   /* Just do it */
   if(has_range && (qual->level != 0))
     {
   /* Just do it */
   if(has_range && (qual->level != 0))
     {
-      /* If the statistics are in dBm */
+      /* Deal with quality : always a relative value */
+      if(!(qual->updated & IW_QUAL_QUAL_INVALID))
+       {
+         len = snprintf(buffer, buflen, "Quality%c%d/%d  ",
+                        qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':',
+                        qual->qual, range->max_qual.qual);
+         buffer += len;
+         buflen -= len;
+       }
+
+      /* If the statistics are in dBm or relative */
       if(qual->level > range->max_qual.level)
        {
       if(qual->level > range->max_qual.level)
        {
-         /* Statistics are in dBm (absolute power measurement) */
-         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)" : "");
+         /* Deal with signal level in dBm  (absolute power measurement) */
+         if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
+           {
+             len = snprintf(buffer, buflen, "Signal level%c%d dBm  ",
+                            qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
+                            qual->level - 0x100);
+             buffer += len;
+             buflen -= len;
+           }
+
+         /* Deal with noise level in dBm (absolute power measurement) */
+         if(!(qual->updated & IW_QUAL_NOISE_INVALID))
+           {
+             len = snprintf(buffer, buflen, "Noise level%c%d dBm",
+                            qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
+                            qual->noise - 0x100);
+           }
        }
       else
        {
        }
       else
        {
-         /* Statistics are relative values (0 -> max) */
-         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,
-                 (qual->updated & 0x7) ? " (updated)" : "");
+         /* Deal with signal level as relative value (0 -> max) */
+         if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
+           {
+             len = snprintf(buffer, buflen, "Signal level%c%d/%d  ",
+                            qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
+                            qual->level, range->max_qual.level);
+             buffer += len;
+             buflen -= len;
+           }
+
+         /* Deal with noise level as relative value (0 -> max) */
+         if(!(qual->updated & IW_QUAL_NOISE_INVALID))
+           {
+             len = snprintf(buffer, buflen, "Noise level%c%d/%d",
+                            qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
+                            qual->noise, range->max_qual.noise);
+           }
        }
     }
   else
     {
       /* We can't read the range, so we don't know... */
        }
     }
   else
     {
       /* We can't read the range, so we don't know... */
-      sprintf(buffer, "Quality:%d  Signal level:%d  Noise level:%d%s",
-             qual->qual, qual->level, qual->noise,
-             (qual->updated & 0x7) ? " (updated)" : "");
+      snprintf(buffer, buflen,
+              "Quality:%d  Signal level:%d  Noise level:%d",
+              qual->qual, qual->level, qual->noise);
     }
 }
 
     }
 }
 
@@ -992,28 +1394,36 @@ iw_print_stats(char *            buffer,
  * Output the encoding key, with a nice formating
  */
 void
  * Output the encoding key, with a nice formating
  */
 void
-iw_print_key(char *            buffer,
-            unsigned char *    key,
-            int                key_size,
-            int                key_flags)
+iw_print_key(char *                    buffer,
+            int                        buflen,
+            const unsigned char *      key,            /* Must be unsigned */
+            int                        key_size,
+            int                        key_flags)
 {
   int  i;
 
 {
   int  i;
 
+  /* Check buffer size -> 1 bytes => 2 digits + 1/2 separator */
+  if((key_size * 3) > buflen)
+    {
+      snprintf(buffer, buflen, "<too big>");
+      return;
+    }
+
   /* Is the key present ??? */
   if(key_flags & IW_ENCODE_NOKEY)
     {
       /* Nope : print on or dummy */
       if(key_size <= 0)
   /* Is the key present ??? */
   if(key_flags & IW_ENCODE_NOKEY)
     {
       /* Nope : print on or dummy */
       if(key_size <= 0)
-       strcpy(buffer, "on");
+       strcpy(buffer, "on");                   /* Size checked */
       else
        {
       else
        {
-         strcpy(buffer, "**");
+         strcpy(buffer, "**");                 /* Size checked */
          buffer +=2;
          for(i = 1; i < key_size; i++)
            {
              if((i & 0x1) == 0)
          buffer +=2;
          for(i = 1; i < key_size; i++)
            {
              if((i & 0x1) == 0)
-               strcpy(buffer++, "-");
-             strcpy(buffer, "**");
+               strcpy(buffer++, "-");          /* Size checked */
+             strcpy(buffer, "**");             /* Size checked */
              buffer +=2;
            }
        }
              buffer +=2;
            }
        }
@@ -1021,13 +1431,13 @@ iw_print_key(char *             buffer,
   else
     {
       /* Yes : print the key */
   else
     {
       /* Yes : print the key */
-      sprintf(buffer, "%.2X", key[0]);
+      sprintf(buffer, "%.2X", key[0]);         /* Size checked */
       buffer +=2;
       for(i = 1; i < key_size; i++)
        {
          if((i & 0x1) == 0)
       buffer +=2;
       for(i = 1; i < key_size; i++)
        {
          if((i & 0x1) == 0)
-           strcpy(buffer++, "-");
-         sprintf(buffer, "%.2X", key[i]);
+           strcpy(buffer++, "-");              /* Size checked */
+         sprintf(buffer, "%.2X", key[i]);      /* Size checked */
          buffer +=2;
        }
     }
          buffer +=2;
        }
     }
@@ -1039,8 +1449,8 @@ iw_print_key(char *               buffer,
  * ### NOT IMPLEMENTED ###
  * Return size of the key, or 0 (no key) or -1 (error)
  */
  * ### NOT IMPLEMENTED ###
  * Return size of the key, or 0 (no key) or -1 (error)
  */
-int
-iw_pass_key(char *             input,
+static int
+iw_pass_key(const char *       input,
            unsigned char *     key)
 {
   input = input; key = key;
            unsigned char *     key)
 {
   input = input; key = key;
@@ -1054,7 +1464,7 @@ iw_pass_key(char *                input,
  * Return size of the key, or 0 (no key) or -1 (error)
  */
 int
  * Return size of the key, or 0 (no key) or -1 (error)
  */
 int
-iw_in_key(char *               input,
+iw_in_key(const char *         input,
          unsigned char *       key)
 {
   int          keylen = 0;
          unsigned char *       key)
 {
   int          keylen = 0;
@@ -1090,7 +1500,7 @@ iw_in_key(char *          input,
          }
        /* Preserve original buffers (both in & out) */
        hex = buff + IW_ENCODING_TOKEN_MAX;
          }
        /* Preserve original buffers (both in & out) */
        hex = buff + IW_ENCODING_TOKEN_MAX;
-       strcpy(hex, input);
+       strcpy(hex, input);                             /* Size checked */
        out = buff;
 
        /* Parse */
        out = buff;
 
        /* Parse */
@@ -1136,8 +1546,8 @@ iw_in_key(char *          input,
  */
 int
 iw_in_key_full(int             skfd,
  */
 int
 iw_in_key_full(int             skfd,
-              char *           ifname,
-              char *           input,
+              const char *     ifname,
+              const char *     input,
               unsigned char *  key,
               __u16 *          flags)
 {
               unsigned char *  key,
               __u16 *          flags)
 {
@@ -1146,9 +1556,7 @@ iw_in_key_full(int                skfd,
 
   if(!strncmp(input, "l:", 2))
     {
 
   if(!strncmp(input, "l:", 2))
     {
-#if WIRELESS_EXT > 15
       struct iw_range  range;
       struct iw_range  range;
-#endif
 
       /* Extra case : as a login (user:passwd - Cisco LEAP) */
       keylen = strlen(input + 2) + 1;          /* skip "l:", add '\0' */
 
       /* Extra case : as a login (user:passwd - Cisco LEAP) */
       keylen = strlen(input + 2) + 1;          /* skip "l:", add '\0' */
@@ -1166,22 +1574,27 @@ iw_in_key_full(int              skfd,
        }
       *p = '\0';
 
        }
       *p = '\0';
 
-#if WIRELESS_EXT > 15
-      printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
-      if((*flags & IW_ENCODE_INDEX) == 0)
+      /* Extract range info */
+      if(iw_get_range_info(skfd, ifname, &range) < 0)
+       /* Hum... Maybe we should return an error ??? */
+       memset(&range, 0, sizeof(range));
+
+      if(range.we_version_compiled > 15)
        {
        {
-         /* Extract range info */
-         if(iw_get_range_info(skfd, ifname, &range) < 0)
-           memset(&range, 0, sizeof(range));
+
+         printf("flags = %X, index = %X\n",
+                *flags, range.encoding_login_index);
+         if((*flags & IW_ENCODE_INDEX) == 0)
+           {
+             /* Extract range info */
+             if(iw_get_range_info(skfd, ifname, &range) < 0)
+               memset(&range, 0, sizeof(range));
+             printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
+             /* Set the index the driver expects */
+             *flags |= range.encoding_login_index & IW_ENCODE_INDEX;
+           }
          printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
          printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
-         /* Set the index the driver expects */
-         *flags |= range.encoding_login_index & IW_ENCODE_INDEX;
        }
        }
-      printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
-#else
-      /* Avoid "Unused parameter" warning */
-      skfd = skfd; ifname = ifname; flags = flags;
-#endif
     }
   else
     /* Simpler routine above */
     }
   else
     /* Simpler routine above */
@@ -1198,46 +1611,55 @@ iw_in_key_full(int              skfd,
  */
 void
 iw_print_pm_value(char *       buffer,
  */
 void
 iw_print_pm_value(char *       buffer,
+                 int           buflen,
                  int           value,
                  int           flags)
 {
                  int           value,
                  int           flags)
 {
+  /* Check size */
+  if(buflen < 25)
+    {
+      snprintf(buffer, buflen, "<too big>");
+      return;
+    }
+  buflen -= 25;
+
   /* Modifiers */
   if(flags & IW_POWER_MIN)
     {
   /* Modifiers */
   if(flags & IW_POWER_MIN)
     {
-      strcpy(buffer, " min");
+      strcpy(buffer, " min");                          /* Size checked */
       buffer += 4;
     }
   if(flags & IW_POWER_MAX)
     {
       buffer += 4;
     }
   if(flags & IW_POWER_MAX)
     {
-      strcpy(buffer, " max");
+      strcpy(buffer, " max");                          /* Size checked */
       buffer += 4;
     }
 
   /* Type */
   if(flags & IW_POWER_TIMEOUT)
     {
       buffer += 4;
     }
 
   /* Type */
   if(flags & IW_POWER_TIMEOUT)
     {
-      strcpy(buffer, " timeout:");
+      strcpy(buffer, " timeout:");                     /* Size checked */
       buffer += 9;
     }
   else
     {
       buffer += 9;
     }
   else
     {
-      strcpy(buffer, " period:");
+      strcpy(buffer, " period:");                      /* Size checked */
       buffer += 8;
     }
 
   /* Display value without units */
   if(flags & IW_POWER_RELATIVE)
       buffer += 8;
     }
 
   /* Display value without units */
   if(flags & IW_POWER_RELATIVE)
-    sprintf(buffer, "%g", ((double) value) / MEGA);
+    snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
   else
     {
       /* Display value with units */
       if(value >= (int) MEGA)
   else
     {
       /* Display value with units */
       if(value >= (int) MEGA)
-       sprintf(buffer, "%gs", ((double) value) / MEGA);
+       snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
       else
        if(value >= (int) KILO)
       else
        if(value >= (int) KILO)
-         sprintf(buffer, "%gms", ((double) value) / KILO);
+         snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
        else
        else
-         sprintf(buffer, "%dus", value);
+         snprintf(buffer, buflen, "%dus", value);
     }
 }
 
     }
 }
 
@@ -1247,81 +1669,96 @@ iw_print_pm_value(char *        buffer,
  */
 void
 iw_print_pm_mode(char *        buffer,
  */
 void
 iw_print_pm_mode(char *        buffer,
+                int    buflen,
                 int    flags)
 {
                 int    flags)
 {
+  /* Check size */
+  if(buflen < 28)
+    {
+      snprintf(buffer, buflen, "<too big>");
+      return;
+    }
+
   /* Print the proper mode... */
   switch(flags & IW_POWER_MODE)
     {
     case IW_POWER_UNICAST_R:
   /* Print the proper mode... */
   switch(flags & IW_POWER_MODE)
     {
     case IW_POWER_UNICAST_R:
-      strcpy(buffer, "mode:Unicast only received");
+      strcpy(buffer, "mode:Unicast only received");    /* Size checked */
       break;
     case IW_POWER_MULTICAST_R:
       break;
     case IW_POWER_MULTICAST_R:
-      strcpy(buffer, "mode:Multicast only received");
+      strcpy(buffer, "mode:Multicast only received");  /* Size checked */
       break;
     case IW_POWER_ALL_R:
       break;
     case IW_POWER_ALL_R:
-      strcpy(buffer, "mode:All packets received");
+      strcpy(buffer, "mode:All packets received");     /* Size checked */
       break;
     case IW_POWER_FORCE_S:
       break;
     case IW_POWER_FORCE_S:
-      strcpy(buffer, "mode:Force sending");
+      strcpy(buffer, "mode:Force sending");            /* Size checked */
       break;
     case IW_POWER_REPEATER:
       break;
     case IW_POWER_REPEATER:
-      strcpy(buffer, "mode:Repeat multicasts");
+      strcpy(buffer, "mode:Repeat multicasts");                /* Size checked */
       break;
     default:
       break;
     default:
-      strcpy(buffer, "");
+      strcpy(buffer, "");                              /* Size checked */
       break;
     }
 }
 
 /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/
 
       break;
     }
 }
 
 /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/
 
-#if WIRELESS_EXT > 10
 /*------------------------------------------------------------------*/
 /*
  * Output a retry value with all attributes...
  */
 void
 iw_print_retry_value(char *    buffer,
 /*------------------------------------------------------------------*/
 /*
  * Output a retry value with all attributes...
  */
 void
 iw_print_retry_value(char *    buffer,
+                    int        buflen,
                     int        value,
                     int        flags)
 {
                     int        value,
                     int        flags)
 {
+  /* Check buffer size */
+  if(buflen < 18)
+    {
+      snprintf(buffer, buflen, "<too big>");
+      return;
+    }
+  buflen -= 18;
+
   /* Modifiers */
   if(flags & IW_RETRY_MIN)
     {
   /* Modifiers */
   if(flags & IW_RETRY_MIN)
     {
-      strcpy(buffer, " min");
+      strcpy(buffer, " min");                          /* Size checked */
       buffer += 4;
     }
   if(flags & IW_RETRY_MAX)
     {
       buffer += 4;
     }
   if(flags & IW_RETRY_MAX)
     {
-      strcpy(buffer, " max");
+      strcpy(buffer, " max");                          /* Size checked */
       buffer += 4;
     }
 
   /* Type lifetime of limit */
   if(flags & IW_RETRY_LIFETIME)
     {
       buffer += 4;
     }
 
   /* Type lifetime of limit */
   if(flags & IW_RETRY_LIFETIME)
     {
-      strcpy(buffer, " lifetime:");
+      strcpy(buffer, " lifetime:");                    /* Size checked */
       buffer += 10;
 
       /* Display value without units */
       if(flags & IW_POWER_RELATIVE)
       buffer += 10;
 
       /* Display value without units */
       if(flags & IW_POWER_RELATIVE)
-       sprintf(buffer, "%g", ((double) value) / MEGA);
+       snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
       else
        {
          /* Display value with units */
          if(value >= (int) MEGA)
       else
        {
          /* Display value with units */
          if(value >= (int) MEGA)
-           sprintf(buffer, "%gs", ((double) value) / MEGA);
+           snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
          else
            if(value >= (int) KILO)
          else
            if(value >= (int) KILO)
-             sprintf(buffer, "%gms", ((double) value) / KILO);
+             snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
            else
            else
-             sprintf(buffer, "%dus", value);
+             snprintf(buffer, buflen, "%dus", value);
        }
     }
   else
        }
     }
   else
-    sprintf(buffer, " limit:%d", value);
+    snprintf(buffer, buflen, " limit:%d", value);
 }
 }
-#endif /* WIRELESS_EXT > 10 */
 
 /************************* TIME SUBROUTINES *************************/
 
 
 /************************* TIME SUBROUTINES *************************/
 
@@ -1332,12 +1769,13 @@ iw_print_retry_value(char *     buffer,
  */
 void
 iw_print_timeval(char *                        buffer,
  */
 void
 iw_print_timeval(char *                        buffer,
+                int                    buflen,
                 const struct timeval * time)
 {
         int s;
 
        s = (time->tv_sec) % 86400;
                 const struct timeval * time)
 {
         int s;
 
        s = (time->tv_sec) % 86400;
-       sprintf(buffer, "%02d:%02d:%02d.%06u ", 
+       snprintf(buffer, buflen, "%02d:%02d:%02d.%06u ", 
                s / 3600, (s % 3600) / 60, 
                s % 60, (u_int32_t) time->tv_usec);
 }
                s / 3600, (s % 3600) / 60, 
                s % 60, (u_int32_t) time->tv_usec);
 }
@@ -1345,6 +1783,7 @@ iw_print_timeval(char *                   buffer,
 /*********************** ADDRESS SUBROUTINES ************************/
 /*
  * This section is mostly a cut & past from net-tools-1.2.0
 /*********************** ADDRESS SUBROUTINES ************************/
 /*
  * This section is mostly a cut & past from net-tools-1.2.0
+ * (Well... This has evolved over the years)
  * manage address display and input...
  */
 
  * manage address display and input...
  */
 
@@ -1429,6 +1868,31 @@ iw_check_addr_type(int           skfd,
 
 /*------------------------------------------------------------------*/
 /*
 
 /*------------------------------------------------------------------*/
 /*
+ * Ask the kernel for the MAC address of an interface.
+ */
+int
+iw_get_mac_addr(int                    skfd,
+               const char *            ifname,
+               struct ether_addr *     eth,
+               unsigned short *        ptype)
+{
+  struct ifreq ifr;
+  int          ret;
+
+  /* Prepare request */
+  bzero(&ifr, sizeof(struct ifreq));
+  strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+  /* Do it */
+  ret = ioctl(skfd, SIOCGIFHWADDR, &ifr);
+
+  memcpy(eth->ether_addr_octet, ifr.ifr_hwaddr.sa_data, 6); 
+  *ptype = ifr.ifr_hwaddr.sa_family;
+  return(ret);
+}
+
+/*------------------------------------------------------------------*/
+/*
  * Display an Ethernet address in readable format.
  */
 void
  * Display an Ethernet address in readable format.
  */
 void
@@ -1516,21 +1980,21 @@ iw_in_inet(char *name, struct sockaddr *sap)
 {
   struct hostent *hp;
   struct netent *np;
 {
   struct hostent *hp;
   struct netent *np;
-  struct sockaddr_in *sin = (struct sockaddr_in *) sap;
+  struct sockaddr_in *sain = (struct sockaddr_in *) sap;
 
   /* Grmpf. -FvK */
 
   /* Grmpf. -FvK */
-  sin->sin_family = AF_INET;
-  sin->sin_port = 0;
+  sain->sin_family = AF_INET;
+  sain->sin_port = 0;
 
   /* Default is special, meaning 0.0.0.0. */
   if (!strcmp(name, "default")) {
 
   /* Default is special, meaning 0.0.0.0. */
   if (!strcmp(name, "default")) {
-       sin->sin_addr.s_addr = INADDR_ANY;
+       sain->sin_addr.s_addr = INADDR_ANY;
        return(1);
   }
 
   /* Try the NETWORKS database to see if this is a known network. */
   if ((np = getnetbyname(name)) != (struct netent *)NULL) {
        return(1);
   }
 
   /* Try the NETWORKS database to see if this is a known network. */
   if ((np = getnetbyname(name)) != (struct netent *)NULL) {
-       sin->sin_addr.s_addr = htonl(np->n_net);
+       sain->sin_addr.s_addr = htonl(np->n_net);
        strcpy(name, np->n_name);
        return(1);
   }
        strcpy(name, np->n_name);
        return(1);
   }
@@ -1540,7 +2004,7 @@ iw_in_inet(char *name, struct sockaddr *sap)
        errno = h_errno;
        return(-1);
   }
        errno = h_errno;
        return(-1);
   }
-  memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], hp->h_length);
+  memcpy((char *) &sain->sin_addr, (char *) hp->h_addr_list[0], hp->h_length);
   strcpy(name, hp->h_name);
   return(0);
 }
   strcpy(name, hp->h_name);
   return(0);
 }
@@ -1564,7 +2028,7 @@ iw_in_addr(int            skfd,
       /* Check if we have valid interface address type */
       if(iw_check_if_addr_type(skfd, ifname) < 0)
        {
       /* Check if we have valid interface address type */
       if(iw_check_if_addr_type(skfd, ifname) < 0)
        {
-         fprintf(stderr, "%-8.8s  Interface doesn't support IP addresses\n", ifname);
+         fprintf(stderr, "%-8.16s  Interface doesn't support IP addresses\n", ifname);
          return(-1);
        }
 
          return(-1);
        }
 
@@ -1607,7 +2071,7 @@ iw_in_addr(int            skfd,
       /* Check if we have valid mac address type */
       if(iw_check_mac_addr_type(skfd, ifname) < 0)
        {
       /* Check if we have valid mac address type */
       if(iw_check_mac_addr_type(skfd, ifname) < 0)
        {
-         fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n", ifname);
+         fprintf(stderr, "%-8.16s  Interface doesn't support MAC addresses\n", ifname);
          return(-1);
        }
 
          return(-1);
        }
 
@@ -1660,7 +2124,6 @@ iw_get_priv_size(int      args)
  * Those functions help the decoding of events, so are needed only in
  * this case.
  */
  * Those functions help the decoding of events, so are needed only in
  * this case.
  */
-#if WIRELESS_EXT > 13
 
 /* Type of headers we know about (basically union iwreq_data) */
 #define IW_HEADER_TYPE_NULL    0       /* Not available */
 
 /* Type of headers we know about (basically union iwreq_data) */
 #define IW_HEADER_TYPE_NULL    0       /* Not available */
@@ -1751,6 +2214,10 @@ static const int event_type_size[] = {
        IW_EV_QUAL_LEN,         /* IW_HEADER_TYPE_QUAL */
 };
 
        IW_EV_QUAL_LEN,         /* IW_HEADER_TYPE_QUAL */
 };
 
+/* Forward compatibility with WE-19 */
+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
+                         (char *) NULL)
+
 /*------------------------------------------------------------------*/
 /*
  * Initialise the struct stream_descr so that we can extract
 /*------------------------------------------------------------------*/
 /*
  * Initialise the struct stream_descr so that we can extract
@@ -1775,7 +2242,8 @@ iw_init_event_stream(struct stream_descr *        stream, /* Stream of events */
  */
 int
 iw_extract_event_stream(struct stream_descr *  stream, /* Stream of events */
  */
 int
 iw_extract_event_stream(struct stream_descr *  stream, /* Stream of events */
-                       struct iw_event *       iwe)    /* Extracted event */
+                       struct iw_event *       iwe,    /* Extracted event */
+                       int                     we_version)
 {
   int          event_type = 0;
   unsigned int event_len = 1;          /* Invalid */
 {
   int          event_type = 0;
   unsigned int event_len = 1;          /* Invalid */
@@ -1783,6 +2251,9 @@ iw_extract_event_stream(struct stream_descr *     stream, /* Stream of events */
   /* Don't "optimise" the following variable, it will crash */
   unsigned     cmd_index;              /* *MUST* be unsigned */
 
   /* Don't "optimise" the following variable, it will crash */
   unsigned     cmd_index;              /* *MUST* be unsigned */
 
+  /* Unused for now. Will be later on... */
+  we_version = we_version;
+
   /* Check for end of stream */
   if((stream->current + IW_EV_LCP_LEN) > stream->end)
     return(0);
   /* Check for end of stream */
   if((stream->current + IW_EV_LCP_LEN) > stream->end)
     return(0);
@@ -1820,6 +2291,9 @@ iw_extract_event_stream(struct stream_descr *     stream, /* Stream of events */
     }
   /* Unknown events -> event_type=0 => IW_EV_LCP_LEN */
   event_len = event_type_size[event_type];
     }
   /* Unknown events -> event_type=0 => IW_EV_LCP_LEN */
   event_len = event_type_size[event_type];
+  /* Fixup for later version of WE */
+  if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))
+    event_len -= IW_EV_POINT_OFF;
 
   /* Check if we know about this event */
   if(event_len <= IW_EV_LCP_LEN)
 
   /* Check if we know about this event */
   if(event_len <= IW_EV_LCP_LEN)
@@ -1848,7 +2322,12 @@ iw_extract_event_stream(struct stream_descr *    stream, /* Stream of events */
       stream->current += iwe->len;
       return(-2);
     }
       stream->current += iwe->len;
       return(-2);
     }
-  memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
+  /* Fixup for later version of WE */
+  if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))
+    memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
+          pointer, event_len);
+  else
+    memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
 
   /* Skip event in the stream */
   pointer += event_len;
 
   /* Skip event in the stream */
   pointer += event_len;
@@ -1883,4 +2362,301 @@ iw_extract_event_stream(struct stream_descr *   stream, /* Stream of events */
   return(1);
 }
 
   return(1);
 }
 
-#endif /* WIRELESS_EXT > 13 */
+/*********************** SCANNING SUBROUTINES ***********************/
+/*
+ * The Wireless Extension API 14 and greater define Wireless Scanning.
+ * The normal API is complex, this is an easy API that return
+ * a subset of the scanning results. This should be enough for most
+ * applications that want to use Scanning.
+ * If you want to have use the full/normal API, check iwlist.c...
+ *
+ * Precaution when using scanning :
+ * The scanning operation disable normal network traffic, and therefore
+ * you should not abuse of scan.
+ * The scan need to check the presence of network on other frequencies.
+ * While you are checking those other frequencies, you can *NOT* be on
+ * your normal frequency to listen to normal traffic in the cell.
+ * You need typically in the order of one second to actively probe all
+ * 802.11b channels (do the maths). Some cards may do that in background,
+ * to reply to scan commands faster, but they still have to do it.
+ * Leaving the cell for such an extended period of time is pretty bad.
+ * Any kind of streaming/low latency traffic will be impacted, and the
+ * user will perceive it (easily checked with telnet). People trying to
+ * send traffic to you will retry packets and waste bandwidth. Some
+ * applications may be sensitive to those packet losses in weird ways,
+ * and tracing those weird behavior back to scanning may take time.
+ * If you are in ad-hoc mode, if two nodes scan approx at the same
+ * time, they won't see each other, which may create associations issues.
+ * For those reasons, the scanning activity should be limited to
+ * what's really needed, and continuous scanning is a bad idea.
+ * Jean II
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Process/store one element from the scanning results in wireless_scan
+ */
+static inline struct wireless_scan *
+iw_process_scanning_token(struct iw_event *            event,
+                         struct wireless_scan *        wscan)
+{
+  struct wireless_scan *       oldwscan;
+
+  /* Now, let's decode the event */
+  switch(event->cmd)
+    {
+    case SIOCGIWAP:
+      /* New cell description. Allocate new cell descriptor, zero it. */
+      oldwscan = wscan;
+      wscan = (struct wireless_scan *) malloc(sizeof(struct wireless_scan));
+      if(wscan == NULL)
+       return(wscan);
+      /* Link at the end of the list */
+      if(oldwscan != NULL)
+       oldwscan->next = wscan;
+
+      /* Reset it */
+      bzero(wscan, sizeof(struct wireless_scan));
+
+      /* Save cell identifier */
+      wscan->has_ap_addr = 1;
+      memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof (sockaddr));
+      break;
+    case SIOCGIWNWID:
+      wscan->b.has_nwid = 1;
+      memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam));
+      break;
+    case SIOCGIWFREQ:
+      wscan->b.has_freq = 1;
+      wscan->b.freq = iw_freq2float(&(event->u.freq));
+      wscan->b.freq_flags = event->u.freq.flags;
+      break;
+    case SIOCGIWMODE:
+      wscan->b.mode = event->u.mode;
+      if((wscan->b.mode < IW_NUM_OPER_MODE) && (wscan->b.mode >= 0))
+       wscan->b.has_mode = 1;
+      break;
+    case SIOCGIWESSID:
+      wscan->b.has_essid = 1;
+      wscan->b.essid_on = event->u.data.flags;
+      if((event->u.essid.pointer) && (event->u.essid.length))
+       memcpy(wscan->b.essid, event->u.essid.pointer, event->u.essid.length);
+      wscan->b.essid[event->u.essid.length] = '\0';
+      break;
+    case SIOCGIWENCODE:
+      wscan->b.has_key = 1;
+      wscan->b.key_size = event->u.data.length;
+      wscan->b.key_flags = event->u.data.flags;
+      if(event->u.data.pointer)
+       memcpy(wscan->b.key, event->u.essid.pointer, event->u.data.length);
+      else
+       wscan->b.key_flags |= IW_ENCODE_NOKEY;
+      break;
+    case IWEVQUAL:
+      /* We don't get complete stats, only qual */
+      wscan->has_stats = 1;
+      memcpy(&wscan->stats.qual, &event->u.qual, sizeof(iwstats));
+      break;
+    case SIOCGIWRATE:
+      /* Scan may return a list of bitrates. Should we really bother with
+       * an array of bitrates ? Or only the maximum bitrate ? Jean II */
+    case IWEVCUSTOM:
+      /* How can we deal with those sanely ? Jean II */
+    default:
+      break;
+   }   /* switch(event->cmd) */
+
+  return(wscan);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Initiate the scan procedure, and process results.
+ * This is a non-blocking procedure and it will return each time
+ * it would block, returning the amount of time the caller should wait
+ * before calling again.
+ * Return -1 for error, delay to wait for (in ms), or 0 for success.
+ * Error code is in errno
+ */
+int
+iw_process_scan(int                    skfd,
+               char *                  ifname,
+               int                     we_version,
+               wireless_scan_head *    context)
+{
+  struct iwreq         wrq;
+  unsigned char *      buffer = NULL;          /* Results */
+  int                  buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
+  unsigned char *      newbuf;
+
+  /* Don't waste too much time on interfaces (50 * 100 = 5s) */
+  context->retry++;
+  if(context->retry > 50)
+    {
+      errno = ETIME;
+      return(-1);
+    }
+
+  /* If we have not yet initiated scanning on the interface */
+  if(context->retry == 1)
+    {
+      /* Initiate Scan */
+      wrq.u.data.pointer = NULL;               /* Later */
+      wrq.u.data.flags = 0;
+      wrq.u.data.length = 0;
+      if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
+       return(-1);
+      /* Success : now, just wait for event or results */
+      return(250);     /* Wait 250 ms */
+    }
+
+ realloc:
+  /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
+  newbuf = realloc(buffer, buflen);
+  if(newbuf == NULL)
+    {
+      /* man says : If realloc() fails the original block is left untouched */
+      if(buffer)
+       free(buffer);
+      errno = ENOMEM;
+      return(-1);
+    }
+  buffer = newbuf;
+
+  /* Try to read the results */
+  wrq.u.data.pointer = buffer;
+  wrq.u.data.flags = 0;
+  wrq.u.data.length = buflen;
+  if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
+    {
+      /* Check if buffer was too small (WE-17 only) */
+      if((errno == E2BIG) && (we_version > 16))
+       {
+         /* Some driver may return very large scan results, either
+          * because there are many cells, or because they have many
+          * large elements in cells (like IWEVCUSTOM). Most will
+          * only need the regular sized buffer. We now use a dynamic
+          * allocation of the buffer to satisfy everybody. Of course,
+          * as we don't know in advance the size of the array, we try
+          * various increasing sizes. Jean II */
+
+         /* Check if the driver gave us any hints. */
+         if(wrq.u.data.length > buflen)
+           buflen = wrq.u.data.length;
+         else
+           buflen *= 2;
+
+         /* Try again */
+         goto realloc;
+       }
+
+      /* Check if results not available yet */
+      if(errno == EAGAIN)
+       {
+         free(buffer);
+         /* Wait for only 100ms from now on */
+         return(100);  /* Wait 100 ms */
+       }
+
+      free(buffer);
+      /* Bad error, please don't come back... */
+      return(-1);
+    }
+
+  /* We have the results, process them */
+  if(wrq.u.data.length)
+    {
+      struct iw_event          iwe;
+      struct stream_descr      stream;
+      struct wireless_scan *   wscan = NULL;
+      int                      ret;
+#if 0
+      /* Debugging code. In theory useless, because it's debugged ;-) */
+      int      i;
+      printf("Scan result [%02X", buffer[0]);
+      for(i = 1; i < wrq.u.data.length; i++)
+       printf(":%02X", buffer[i]);
+      printf("]\n");
+#endif
+
+      /* Init */
+      iw_init_event_stream(&stream, buffer, wrq.u.data.length);
+      /* This is dangerous, we may leak user data... */
+      context->result = NULL;
+
+      /* Look every token */
+      do
+       {
+         /* Extract an event and print it */
+         ret = iw_extract_event_stream(&stream, &iwe, we_version);
+         if(ret > 0)
+           {
+             /* Convert to wireless_scan struct */
+             wscan = iw_process_scanning_token(&iwe, wscan);
+             /* Check problems */
+             if(wscan == NULL)
+               {
+                 free(buffer);
+                 errno = ENOMEM;
+                 return(-1);
+               }
+             /* Save head of list */
+             if(context->result == NULL)
+               context->result = wscan;
+           }
+       }
+      while(ret > 0);
+    }
+
+  /* Done with this interface - return success */
+  free(buffer);
+  return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Perform a wireless scan on the specified interface.
+ * This is a blocking procedure and it will when the scan is completed
+ * or when an error occur.
+ *
+ * The scan results are given in a linked list of wireless_scan objects.
+ * The caller *must* free the result himself (by walking the list).
+ * If there is an error, -1 is returned and the error code is available
+ * in errno.
+ *
+ * The parameter we_version can be extracted from the range structure
+ * (range.we_version_compiled - see iw_get_range_info()), or using
+ * iw_get_kernel_we_version(). For performance reason, you should
+ * cache this parameter when possible rather than querying it every time.
+ *
+ * Return -1 for error and 0 for success.
+ */
+int
+iw_scan(int                    skfd,
+       char *                  ifname,
+       int                     we_version,
+       wireless_scan_head *    context)
+{
+  int          delay;          /* in ms */
+
+  /* Clean up context. Potential memory leak if(context.result != NULL) */
+  context->result = NULL;
+  context->retry = 0;
+
+  /* Wait until we get results or error */
+  while(1)
+    {
+      /* Try to get scan results */
+      delay = iw_process_scan(skfd, ifname, we_version, context);
+
+      /* Check termination */
+      if(delay <= 0)
+       break;
+
+      /* Wait a bit */
+      usleep(delay * 1000);
+    }
+
+  /* End - return -1 or 0 */
+  return(delay);
+}
index f15edc8..67d6ff1 100644 (file)
@@ -1,12 +1,12 @@
 /*
  *     Wireless Tools
  *
 /*
  *     Wireless Tools
  *
- *             Jean II - HPLB 97->99 - HPL 99->02
+ *             Jean II - HPLB 97->99 - HPL 99->04
  *
  * Common header for the Wireless Extension library...
  *
  * This file is released under the GPL license.
  *
  * Common header for the Wireless Extension library...
  *
  * This file is released under the GPL license.
- *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
  */
 
 #ifndef IWLIB_H
  */
 
 #ifndef IWLIB_H
 #include <linux/socket.h>              /* for "struct sockaddr" et al  */
 #include <linux/if.h>                  /* for IFNAMSIZ and co... */
 
 #include <linux/socket.h>              /* for "struct sockaddr" et al  */
 #include <linux/if.h>                  /* for IFNAMSIZ and co... */
 
-#ifdef WEXT_HEADER
 /* Private copy of Wireless extensions */
 /* Private copy of Wireless extensions */
-#include WEXT_HEADER
-#else  /* !WEXT_HEADER */
-/* System wide Wireless extensions */
-#include <linux/wireless.h>
-#endif /* !WEXT_HEADER */
+#include <wireless.h>
+
+/* Make gcc understant that when we say inline, we mean it.
+ * I really hate when the compiler is trying to be more clever than me,
+ * because in this case gcc is not able to figure out functions with a
+ * single call site, so not only I have to tag those functions inline
+ * by hand, but then it refuse to inline them properly.
+ * Total saving for iwevent : 150B = 0.7%.
+ * Fortunately, in gcc 3.4, they now automatically inline static functions
+ * with a single call site. Hurrah !
+ * Jean II */
+#if __GNUC__ == 3
+#if __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4
+#define inline         inline          __attribute__((always_inline))
+#endif
+#endif /* __GNUC__ */
 
 #ifdef __cplusplus
 extern "C" {
 
 #ifdef __cplusplus
 extern "C" {
@@ -144,6 +154,12 @@ extern "C" {
 
 /************************ CONSTANTS & MACROS ************************/
 
 
 /************************ CONSTANTS & MACROS ************************/
 
+/* Various versions information */
+/* Recommended Wireless Extension version */
+#define WE_VERSION     17
+/* Version of Wireless Tools */
+#define WT_VERSION     27
+
 /* Paths */
 #define PROC_NET_WIRELESS      "/proc/net/wireless"
 #define PROC_NET_DEV           "/proc/net/dev"
 /* Paths */
 #define PROC_NET_WIRELESS      "/proc/net/wireless"
 #define PROC_NET_DEV           "/proc/net/dev"
@@ -176,6 +192,11 @@ extern "C" {
 #define SIOCSIWCOMMIT  SIOCSIWNAME
 #endif /* SIOCSIWCOMMIT */
 
 #define SIOCSIWCOMMIT  SIOCSIWNAME
 #endif /* SIOCSIWCOMMIT */
 
+/* Still more backward compatibility */
+#ifndef IW_FREQ_FIXED
+#define IW_FREQ_FIXED  0x01
+#endif /* IW_FREQ_FIXED */
+
 /****************************** TYPES ******************************/
 
 /* Shortcuts */
 /****************************** TYPES ******************************/
 
 /* Shortcuts */
@@ -188,16 +209,17 @@ typedef struct iw_priv_args       iwprivargs;
 typedef struct sockaddr                sockaddr;
 
 /* Structure for storing all wireless information for each device
 typedef struct sockaddr                sockaddr;
 
 /* Structure for storing all wireless information for each device
- * This is pretty exhaustive... */
-typedef struct wireless_info
+ * 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 + 1];     /* Wireless/protocol name */
   int          has_nwid;
   iwparam      nwid;                   /* Network ID */
   int          has_freq;
   double       freq;                   /* Frequency/channel */
 {
   char         name[IFNAMSIZ + 1];     /* Wireless/protocol name */
   int          has_nwid;
   iwparam      nwid;                   /* Network ID */
   int          has_freq;
   double       freq;                   /* Frequency/channel */
-  int          has_sens;
-  iwparam      sens;                   /* sensitivity */
+  int          freq_flags;
   int          has_key;
   unsigned char        key[IW_ENCODING_TOKEN_MAX];     /* Encoding key used */
   int          key_size;               /* Number of bytes */
   int          has_key;
   unsigned char        key[IW_ENCODING_TOKEN_MAX];     /* Encoding key used */
   int          key_size;               /* Number of bytes */
@@ -205,6 +227,18 @@ typedef struct wireless_info
   int          has_essid;
   int          essid_on;
   char         essid[IW_ESSID_MAX_SIZE + 1];   /* ESSID (extended network) */
   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;
+
+/* Structure for storing all wireless information for each device
+ * This is pretty exhaustive... */
+typedef struct wireless_info
+{
+  struct wireless_config       b;      /* Basic information */
+
+  int          has_sens;
+  iwparam      sens;                   /* sensitivity */
   int          has_nickname;
   char         nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */
   int          has_ap_addr;
   int          has_nickname;
   char         nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */
   int          has_ap_addr;
@@ -215,8 +249,6 @@ typedef struct wireless_info
   iwparam      rts;                    /* RTS threshold in bytes */
   int          has_frag;
   iwparam      frag;                   /* Fragmentation threshold in bytes */
   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;
   int          has_power;
   iwparam      power;                  /* Power management parameters */
   int          has_txpower;
@@ -231,28 +263,36 @@ typedef struct wireless_info
   int          has_range;
 } wireless_info;
 
   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
+/* Structure for storing an entry of a wireless scan.
+ * This is only a subset of all possible information, the flexible
+ * structure of scan results make it impossible to capture all
+ * information in such a static structure. */
+typedef struct wireless_scan
 {
 {
-  char         name[IFNAMSIZ + 1];     /* Wireless/protocol name */
-  int          has_nwid;
-  iwparam      nwid;                   /* Network ID */
-  int          has_freq;
-  double       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;
+  /* Linked list */
+  struct wireless_scan *       next;
+
+  /* Cell identifiaction */
+  int          has_ap_addr;
+  sockaddr     ap_addr;                /* Access point address */
+
+  /* Other information */
+  struct wireless_config       b;      /* Basic information */
+  iwstats      stats;                  /* Signal strength */
+  int          has_stats;
+} wireless_scan;
+
+/*
+ * Context used for non-blocking scan.
+ */
+typedef struct wireless_scan_head
+{
+  wireless_scan *      result;         /* Result of the scan */
+  int                  retry;          /* Retry level */
+} wireless_scan_head;
 
 
+/* Structure used for parsing event streams, such as Wireless Events
+ * and scan results */
 typedef struct stream_descr
 {
   char *       end;            /* End of the stream */
 typedef struct stream_descr
 {
   char *       end;            /* End of the stream */
@@ -282,91 +322,114 @@ void
                        int             count);
 /* --------------------- WIRELESS SUBROUTINES ----------------------*/
 int
                        int             count);
 /* --------------------- WIRELESS SUBROUTINES ----------------------*/
 int
+       iw_get_kernel_we_version(void);
+int
+       iw_print_version_info(const char *      toolname);
+int
        iw_get_range_info(int           skfd,
        iw_get_range_info(int           skfd,
-                         char *        ifname,
+                         const char *  ifname,
                          iwrange *     range);
 int
                          iwrange *     range);
 int
-       iw_print_version_info(char *    toolname);
-int
        iw_get_priv_info(int            skfd,
        iw_get_priv_info(int            skfd,
-                        char *         ifname,
-                        iwprivargs *   priv,
-                        int            maxpriv);
+                        const char *   ifname,
+                        iwprivargs **  ppriv);
 int
        iw_get_basic_config(int                 skfd,
 int
        iw_get_basic_config(int                 skfd,
-                           char *              ifname,
+                           const char *        ifname,
                            wireless_config *   info);
 int
        iw_set_basic_config(int                 skfd,
                            wireless_config *   info);
 int
        iw_set_basic_config(int                 skfd,
-                           char *              ifname,
+                           const char *        ifname,
                            wireless_config *   info);
 /* --------------------- PROTOCOL SUBROUTINES --------------------- */
 int
                            wireless_config *   info);
 /* --------------------- PROTOCOL SUBROUTINES --------------------- */
 int
-       iw_protocol_compare(char *      protocol1,
-                           char *      protocol2);
+       iw_protocol_compare(const char *        protocol1,
+                           const char *        protocol2);
 /* -------------------- FREQUENCY SUBROUTINES --------------------- */
 void
        iw_float2freq(double    in,
 /* -------------------- FREQUENCY SUBROUTINES --------------------- */
 void
        iw_float2freq(double    in,
-                  iwfreq *     out);
+                     iwfreq *  out);
 double
 double
-       iw_freq2float(iwfreq *  in);
+       iw_freq2float(const iwfreq *    in);
+void
+       iw_print_freq_value(char *      buffer,
+                           int         buflen,
+                           double      freq);
 void
        iw_print_freq(char *    buffer,
 void
        iw_print_freq(char *    buffer,
-                     double    freq);
+                     int       buflen,
+                     double    freq,
+                     int       channel,
+                     int       freq_flags);
+int
+       iw_freq_to_channel(double                       freq,
+                          const struct iw_range *      range);
 int
 int
-       iw_freq_to_channel(double               freq,
-                          struct iw_range *    range);
+       iw_channel_to_freq(int                          channel,
+                          double *                     pfreq,
+                          const struct iw_range *      range);
 void
        iw_print_bitrate(char * buffer,
 void
        iw_print_bitrate(char * buffer,
+                        int    buflen,
                         int    bitrate);
 /* ---------------------- POWER SUBROUTINES ----------------------- */
 int
        iw_dbm2mwatt(int        in);
 int
        iw_mwatt2dbm(int        in);
                         int    bitrate);
 /* ---------------------- POWER SUBROUTINES ----------------------- */
 int
        iw_dbm2mwatt(int        in);
 int
        iw_mwatt2dbm(int        in);
+void
+       iw_print_txpower(char *                 buffer,
+                        int                    buflen,
+                        struct iw_param *      txpower);
 /* -------------------- STATISTICS SUBROUTINES -------------------- */
 int
 /* -------------------- STATISTICS SUBROUTINES -------------------- */
 int
-       iw_get_stats(int        skfd,
-                    char *     ifname,
-                    iwstats *  stats);
+       iw_get_stats(int                skfd,
+                    const char *       ifname,
+                    iwstats *          stats,
+                    const iwrange *    range,
+                    int                has_range);
 void
        iw_print_stats(char *           buffer,
 void
        iw_print_stats(char *           buffer,
-                      iwqual *         qual,
-                      iwrange *        range,
+                      int              buflen,
+                      const iwqual *   qual,
+                      const iwrange *  range,
                       int              has_range);
 /* --------------------- ENCODING SUBROUTINES --------------------- */
 void
                       int              has_range);
 /* --------------------- ENCODING SUBROUTINES --------------------- */
 void
-       iw_print_key(char *             buffer,
-                    unsigned char *    key,
-                    int                key_size,
-                    int                key_flags);
+       iw_print_key(char *                     buffer,
+                    int                        buflen,
+                    const unsigned char *      key,
+                    int                        key_size,
+                    int                        key_flags);
 int
 int
-       iw_in_key(char *                input,
+       iw_in_key(const char *          input,
                  unsigned char *       key);
 int
        iw_in_key_full(int              skfd,
                  unsigned char *       key);
 int
        iw_in_key_full(int              skfd,
-                      char *           ifname,
-                      char *           input,
+                      const char *     ifname,
+                      const char *     input,
                       unsigned char *  key,
                       __u16 *          flags);
 /* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */
 void
        iw_print_pm_value(char *        buffer,
                       unsigned char *  key,
                       __u16 *          flags);
 /* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */
 void
        iw_print_pm_value(char *        buffer,
+                         int           buflen,
                          int           value,
                          int           flags);
 void
        iw_print_pm_mode(char *         buffer,
                          int           value,
                          int           flags);
 void
        iw_print_pm_mode(char *         buffer,
+                        int            buflen,
                         int            flags);
 /* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */
                         int            flags);
 /* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */
-#if WIRELESS_EXT > 10
 void
        iw_print_retry_value(char *     buffer,
 void
        iw_print_retry_value(char *     buffer,
+                            int        buflen,
                             int        value,
                             int        flags);
                             int        value,
                             int        flags);
-#endif
 /* ----------------------- TIME SUBROUTINES ----------------------- */
 void
        iw_print_timeval(char *                 buffer,
 /* ----------------------- TIME SUBROUTINES ----------------------- */
 void
        iw_print_timeval(char *                 buffer,
+                        int                    buflen,
                         const struct timeval * time);
 /* --------------------- ADDRESS SUBROUTINES ---------------------- */
 int
                         const struct timeval * time);
 /* --------------------- ADDRESS SUBROUTINES ---------------------- */
 int
@@ -380,6 +443,11 @@ int
        iw_check_addr_type(int          skfd,
                           char *       ifname);
 #endif
        iw_check_addr_type(int          skfd,
                           char *       ifname);
 #endif
+int
+       iw_get_mac_addr(int                     skfd,
+                       const char *            name,
+                       struct ether_addr *     eth,
+                       unsigned short *        ptype);
 void
        iw_ether_ntop(const struct ether_addr* eth, char* buf);
 char*
 void
        iw_ether_ntop(const struct ether_addr* eth, char* buf);
 char*
@@ -397,7 +465,6 @@ int
 int
        iw_get_priv_size(int            args);
 
 int
        iw_get_priv_size(int            args);
 
-#if WIRELESS_EXT > 13
 /* ---------------------- EVENT SUBROUTINES ---------------------- */
 void
        iw_init_event_stream(struct stream_descr *      stream,
 /* ---------------------- EVENT SUBROUTINES ---------------------- */
 void
        iw_init_event_stream(struct stream_descr *      stream,
@@ -405,11 +472,23 @@ void
                             int                        len);
 int
        iw_extract_event_stream(struct stream_descr *   stream,
                             int                        len);
 int
        iw_extract_event_stream(struct stream_descr *   stream,
-                               struct iw_event *       iwe);
-#endif /* WIRELESS_EXT > 13 */
+                               struct iw_event *       iwe,
+                               int                     we_version);
+/* --------------------- SCANNING SUBROUTINES --------------------- */
+int
+       iw_process_scan(int                     skfd,
+                       char *                  ifname,
+                       int                     we_version,
+                       wireless_scan_head *    context);
+int
+       iw_scan(int                     skfd,
+               char *                  ifname,
+               int                     we_version,
+               wireless_scan_head *    context);
 
 /**************************** VARIABLES ****************************/
 
 
 /**************************** VARIABLES ****************************/
 
+/* Modes as human readable strings */
 extern const char * const      iw_operation_mode[];
 #define IW_NUM_OPER_MODE       7
 
 extern const char * const      iw_operation_mode[];
 #define IW_NUM_OPER_MODE       7
 
@@ -429,7 +508,7 @@ extern const char * const   iw_operation_mode[];
  */
 static inline int
 iw_set_ext(int                 skfd,           /* Socket to the kernel */
  */
 static inline int
 iw_set_ext(int                 skfd,           /* Socket to the kernel */
-          char *               ifname,         /* Device name */
+          const char *         ifname,         /* Device name */
           int                  request,        /* WE ID */
           struct iwreq *       pwrq)           /* Fixed part of the request */
 {
           int                  request,        /* WE ID */
           struct iwreq *       pwrq)           /* Fixed part of the request */
 {
@@ -445,7 +524,7 @@ iw_set_ext(int                      skfd,           /* Socket to the kernel */
  */
 static inline int
 iw_get_ext(int                 skfd,           /* Socket to the kernel */
  */
 static inline int
 iw_get_ext(int                 skfd,           /* Socket to the kernel */
-          char *               ifname,         /* Device name */
+          const char *         ifname,         /* Device name */
           int                  request,        /* WE ID */
           struct iwreq *       pwrq)           /* Fixed part of the request */
 {
           int                  request,        /* WE ID */
           struct iwreq *       pwrq)           /* Fixed part of the request */
 {
@@ -456,6 +535,16 @@ iw_get_ext(int                     skfd,           /* Socket to the kernel */
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
+/*
+ * Close the socket used for ioctl.
+ */
+static inline void
+iw_sockets_close(int   skfd)
+{
+  close(skfd);
+}
+
+/*------------------------------------------------------------------*/
 /* Backwards compatability
  * Actually, those form are much easier to use when dealing with
  * struct sockaddr... */
 /* Backwards compatability
  * Actually, those form are much easier to use when dealing with
  * struct sockaddr... */
index 731031b..7b3de73 100644 (file)
@@ -1,21 +1,19 @@
 .\" Jean II - HPLB - 96
 .\" iwlist.8
 .\"
 .\" Jean II - HPLB - 96
 .\" iwlist.8
 .\"
-.TH IWLIST 8 "31 October 1996" "net-tools" "Linux Programmer's Manual"
+.TH IWLIST 8 "23 June 2004" "wireless-tools" "Linux Programmer's Manual"
 .\"
 .\" NAME part
 .\"
 .SH NAME
 .\"
 .\" NAME part
 .\"
 .SH NAME
-iwlist \- Get wireless statistics from specific nodes
+iwlist \- Get more detailed wireless information from a wireless interface
 .\"
 .\" SYNOPSIS part
 .\"
 .SH SYNOPSIS
 .\"
 .\" SYNOPSIS part
 .\"
 .SH SYNOPSIS
-.BI "iwlist " interface " freq"
+.BI "iwlist " interface " scanning"
 .br
 .br
-.BI "iwlist " interface " ap"
-.br
-.BI "iwlist " interface " scan"
+.BI "iwlist " interface " frequency"
 .br
 .BI "iwlist " interface " rate"
 .br
 .br
 .BI "iwlist " interface " rate"
 .br
@@ -27,6 +25,8 @@ iwlist \- Get wireless statistics from specific nodes
 .br
 .BI "iwlist " interface " retry"
 .br
 .br
 .BI "iwlist " interface " retry"
 .br
+.BI "iwlist " interface " event"
+.br
 .BI "iwlist --help"
 .br
 .BI "iwlist --version"
 .BI "iwlist --help"
 .br
 .BI "iwlist --version"
@@ -35,60 +35,71 @@ iwlist \- Get wireless statistics from specific nodes
 .\"
 .SH DESCRIPTION
 .B Iwlist
 .\"
 .SH DESCRIPTION
 .B Iwlist
-is used to display some large chunk of information from a wireless
-network interface that is not displayed by iwconfig. This is typically
-list of parameters.
+is used to display some additional information from a wireless network
+interface that is not displayed by
+.IR iwconfig (8).
+The main argument is used
+to select a category of information,
+.B iwlist
+displays in detailed form all information related to this category,
+including information already shown by
+.IR iwconfig (8).
 .\"
 .\" PARAMETER part
 .\"
 .SH PARAMETERS
 .TP
 .\"
 .\" PARAMETER part
 .\"
 .SH PARAMETERS
 .TP
-.BR freq / channel
-Give the list of available frequencies in the device and the number of
-defined channels. Please note that usually the driver returns the
-total number of channels and only the frequencies available in the
-present locale, so there is no one to one mapping between frequencies
-displayed and channel numbers.
-.TP
 .BR scan [ning]
 Give the list of Access Points and Ad-Hoc cells in range, and
 optionally a whole bunch of information about them (ESSID, Quality,
 .BR scan [ning]
 Give the list of Access Points and Ad-Hoc cells in range, and
 optionally a whole bunch of information about them (ESSID, Quality,
-Frequency, Mode...). The type of information returned depend on what
-the card support.
+Frequency, Mode...). The type of information returned depends on what
+the card supports.
 .br
 .br
-Triggering scanning is a priviledged operation
+Triggering scanning is a privileged operation
 .RI ( root
 .RI ( root
-only) and normal users can only read letf-over scan results. By
+only) and normal users can only read left-over scan results. By
 default, the way scanning is done (the scope of the scan) will be
 impacted by the current setting of the driver. Also, this command is
 supposed to take extra arguments to control the scanning behaviour,
 but this is currently not implemented.
 .TP
 default, the way scanning is done (the scope of the scan) will be
 impacted by the current setting of the driver. Also, this command is
 supposed to take extra arguments to control the scanning behaviour,
 but this is currently not implemented.
 .TP
-.BR ap / accesspoint / peers
-Give the list of Access Points in range, and optionally the quality of
-link to them. This feature is obsolte and now deprecated in favor of
-scanning support (above), and most drivers don't support it.
-.br
-Some drivers may use this command to return a specific list of Peers
-or Access Points, such as the list of Peers associated/registered with
-the card. See your driver documentation for details.
+.BR freq [uency]/ channel
+Give the list of available frequencies in the device and the number of
+defined channels. Please note that usually the driver returns the
+total number of channels and only the frequencies available in the
+present locale, so there is no one-to-one mapping between frequencies
+displayed and channel numbers.
 .TP
 .BR rate / bit [rate]
 List the bit-rates supported by the device.
 .TP
 .BR key / enc [ryption]
 List the encryption key sizes supported and display all the encryption
 .TP
 .BR rate / bit [rate]
 List the bit-rates supported by the device.
 .TP
 .BR key / enc [ryption]
 List the encryption key sizes supported and display all the encryption
-keys availables in the device.
+keys available in the device.
 .TP
 .B power
 List the various Power Management attributes and modes of the device.
 .TP
 .B txpower
 .TP
 .B power
 List the various Power Management attributes and modes of the device.
 .TP
 .B txpower
-List the various Transmit Power available on the device.
+List the various Transmit Powers available on the device.
 .TP
 .B retry
 List the transmit retry limits and retry lifetime on the device.
 .TP
 .TP
 .B retry
 List the transmit retry limits and retry lifetime on the device.
 .TP
+.BR ap / accesspoint / peers
+Give the list of Access Points in range, and optionally the quality of
+link to them. This feature is
+.B obsolete
+and now deprecated in favor of scanning support (above), and most
+drivers don't support it.
+.br
+Some drivers may use this command to return a specific list of Peers
+or Access Points, such as the list of Peers associated/registered with
+the card. See your driver documentation for details.
+.TP
+.B event
+List the wireless events supported by the device.
+.TP
 .B --version
 Display the version of the tools, as well as the recommended and
 current Wireless Extensions version for the tool and the various
 .B --version
 Display the version of the tools, as well as the recommended and
 current Wireless Extensions version for the tool and the various
index 72fec02..d567afa 100644 (file)
@@ -1,14 +1,14 @@
 /*
  *     Wireless Tools
  *
 /*
  *     Wireless Tools
  *
- *             Jean II - HPLB '99 - HPL 99->01
+ *             Jean II - HPLB '99 - HPL 99->04
  *
  * This tool can access various piece of information on the card
  * not part of iwconfig...
  * You need to link this code against "iwlist.c" and "-lm".
  *
  * This file is released under the GPL license.
  *
  * This tool can access various piece of information on the card
  * not part of iwconfig...
  * You need to link this code against "iwlist.c" and "-lm".
  *
  * This file is released under the GPL license.
- *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
  */
 
 #include "iwlib.h"             /* Header */
  */
 
 #include "iwlib.h"             /* Header */
@@ -38,42 +38,35 @@ print_freq_info(int         skfd,
 
   /* Get list of frequencies / channels */
   if(iw_get_range_info(skfd, ifname, &range) < 0)
 
   /* Get list of frequencies / channels */
   if(iw_get_range_info(skfd, ifname, &range) < 0)
-      fprintf(stderr, "%-8.8s  no frequency information.\n\n",
+      fprintf(stderr, "%-8.16s  no frequency information.\n\n",
                      ifname);
   else
     {
       if(range.num_frequency > 0)
        {
                      ifname);
   else
     {
       if(range.num_frequency > 0)
        {
-         printf("%-8.8s  %d channels in total; available frequencies :\n",
+         printf("%-8.16s  %d channels in total; available frequencies :\n",
                 ifname, range.num_channels);
          /* Print them all */
          for(k = 0; k < range.num_frequency; k++)
            {
                 ifname, range.num_channels);
          /* Print them all */
          for(k = 0; k < range.num_frequency; k++)
            {
-             printf("          Channel %.2d : ", range.freq[k].i);
              freq = iw_freq2float(&(range.freq[k]));
              freq = iw_freq2float(&(range.freq[k]));
-             if(freq >= GIGA)
-               printf("%g GHz\n", freq / GIGA);
-             else
-               if(freq >= MEGA)
-                 printf("%g MHz\n", freq / MEGA);
-               else
-                 printf("%g kHz\n", freq / KILO);
+             iw_print_freq_value(buffer, sizeof(buffer), freq);
+             printf("          Channel %.2d : %s\n",
+                    range.freq[k].i, buffer);
            }
        }
       else
            }
        }
       else
-       printf("%-8.8s  %d channels\n",
+       printf("%-8.16s  %d channels\n",
               ifname, range.num_channels);
 
       /* Get current frequency / channel and display it */
       if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
        {
          freq = iw_freq2float(&(wrq.u.freq));
               ifname, range.num_channels);
 
       /* Get current frequency / channel and display it */
       if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
        {
          freq = iw_freq2float(&(wrq.u.freq));
-         iw_print_freq(buffer, freq);
          channel = iw_freq_to_channel(freq, &range);
          channel = iw_freq_to_channel(freq, &range);
-         if(channel >= 0)
-           printf("          Current %s (channel %.2d)\n\n", buffer, channel);
-         else
-           printf("          Current %s\n\n", buffer);
+         iw_print_freq(buffer, sizeof(buffer),
+                       freq, channel, wrq.u.freq.flags);
+         printf("          Current %s\n\n", buffer);
        }
     }
   return(0);
        }
     }
   return(0);
@@ -117,7 +110,7 @@ print_ap_info(int   skfd,
   wrq.u.data.flags = 0;
   if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
     {
   wrq.u.data.flags = 0;
   if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
     {
-      fprintf(stderr, "%-8.8s  Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
+      fprintf(stderr, "%-8.16s  Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
       return(-1);
     }
 
       return(-1);
     }
 
@@ -132,7 +125,7 @@ print_ap_info(int   skfd,
   /* Check if we have valid mac address type */
   if(iw_check_mac_addr_type(skfd, ifname) < 0)
     {
   /* Check if we have valid mac address type */
   if(iw_check_mac_addr_type(skfd, ifname) < 0)
     {
-      fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n\n", ifname);
+      fprintf(stderr, "%-8.16s  Interface doesn't support MAC addresses\n\n", ifname);
       return(-2);
     }
 
       return(-2);
     }
 
@@ -142,16 +135,16 @@ print_ap_info(int skfd,
 
   /* Display it */
   if(n == 0)
 
   /* Display it */
   if(n == 0)
-    printf("%-8.8s  No Peers/Access-Point in range\n", ifname);
+    printf("%-8.16s  No Peers/Access-Point in range\n", ifname);
   else
   else
-    printf("%-8.8s  Peers/Access-Points in range:\n", ifname);
+    printf("%-8.16s  Peers/Access-Points in range:\n", ifname);
   for(i = 0; i < n; i++)
     {
       if(has_qual)
        {
          /* Print stats for this address */
          printf("    %s : ", iw_pr_ether(temp, hwa[i].sa_data));
   for(i = 0; i < n; i++)
     {
       if(has_qual)
        {
          /* Print stats for this address */
          printf("    %s : ", iw_pr_ether(temp, hwa[i].sa_data));
-         iw_print_stats(temp, &qual[i], &range, has_range);
+         iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
          printf("%s\n", temp);
        }
       else
          printf("%s\n", temp);
        }
       else
@@ -184,29 +177,29 @@ print_bitrate_info(int            skfd,
 
   /* Extract range info */
   if(iw_get_range_info(skfd, ifname, &range) < 0)
 
   /* Extract range info */
   if(iw_get_range_info(skfd, ifname, &range) < 0)
-      fprintf(stderr, "%-8.8s  no bit-rate information.\n\n",
+      fprintf(stderr, "%-8.16s  no bit-rate information.\n\n",
                      ifname);
   else
     {
       if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
        {
                      ifname);
   else
     {
       if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
        {
-         printf("%-8.8s  %d available bit-rates :\n",
+         printf("%-8.16s  %d available bit-rates :\n",
                 ifname, range.num_bitrates);
          /* Print them all */
          for(k = 0; k < range.num_bitrates; k++)
            {
                 ifname, range.num_bitrates);
          /* Print them all */
          for(k = 0; k < range.num_bitrates; k++)
            {
-             iw_print_bitrate(buffer, range.bitrate[k]);
+             iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
              /* Maybe this should be %10s */
              printf("\t  %s\n", buffer);
            }
        }
       else
              /* Maybe this should be %10s */
              printf("\t  %s\n", buffer);
            }
        }
       else
-       printf("%-8.8s  No bit-rates ? Please update driver...\n", ifname);
+       printf("%-8.16s  unknown bit-rate information.\n", ifname);
 
       /* Get current bit rate */
       if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
        {
 
       /* Get current bit rate */
       if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
        {
-         iw_print_bitrate(buffer, wrq.u.bitrate.value);
+         iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
          printf("          Current Bit Rate%c%s\n\n",
                 (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
        }
          printf("          Current Bit Rate%c%s\n\n",
                 (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
        }
@@ -237,11 +230,11 @@ print_keys_info(int               skfd,
 
   /* Extract range info */
   if(iw_get_range_info(skfd, ifname, &range) < 0)
 
   /* Extract range info */
   if(iw_get_range_info(skfd, ifname, &range) < 0)
-      fprintf(stderr, "%-8.8s  no encryption keys information.\n\n",
+      fprintf(stderr, "%-8.16s  no encryption keys information.\n\n",
                      ifname);
   else
     {
                      ifname);
   else
     {
-      printf("%-8.8s  ", ifname);
+      printf("%-8.16s  ", ifname);
       /* Print key sizes */
       if((range.num_encoding_sizes > 0) &&
         (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
       /* Print key sizes */
       if((range.num_encoding_sizes > 0) &&
         (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
@@ -271,7 +264,8 @@ print_keys_info(int         skfd,
          else
            {
              /* Display the key */
          else
            {
              /* Display the key */
-             iw_print_key(buffer, key, wrq.u.data.length, wrq.u.data.flags);
+             iw_print_key(buffer, sizeof(buffer),
+                          key, wrq.u.data.length, wrq.u.data.flags);
              printf("\t\t[%d]: %s", k, buffer);
 
              /* Other info... */
              printf("\t\t[%d]: %s", k, buffer);
 
              /* Other info... */
@@ -320,7 +314,8 @@ get_pm_value(int            skfd,
       /* Let's check the value and its type */
       if(pwrq->u.power.flags & IW_POWER_TYPE)
        {
       /* Let's check the value and its type */
       if(pwrq->u.power.flags & IW_POWER_TYPE)
        {
-         iw_print_pm_value(buffer, pwrq->u.power.value, pwrq->u.power.flags);
+         iw_print_pm_value(buffer, sizeof(buffer),
+                           pwrq->u.power.value, pwrq->u.power.flags);
          printf("\n                 %s", buffer);
        }
     }
          printf("\n                 %s", buffer);
        }
     }
@@ -345,13 +340,14 @@ print_pm_info(int         skfd,
   args = args; count = count;
 
   /* Extract range info */
   args = args; count = count;
 
   /* Extract range info */
-  if(iw_get_range_info(skfd, ifname, &range) < 0)
-      fprintf(stderr, "%-8.8s  no power management information.\n\n",
+  if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+     (range.we_version_compiled < 10))
+      fprintf(stderr, "%-8.16s  no power management information.\n\n",
                      ifname);
   else
     {
                      ifname);
   else
     {
-      printf("%-8.8s  ", ifname);
-#if WIRELESS_EXT > 9
+      printf("%-8.16s  ", ifname);
+
       /* Display modes availables */
       if(range.pm_capa & IW_POWER_MODE)
        {
       /* Display modes availables */
       if(range.pm_capa & IW_POWER_MODE)
        {
@@ -377,11 +373,12 @@ print_pm_info(int         skfd,
          else
            printf("Fixed period  ; ");
          /* Print the range */
          else
            printf("Fixed period  ; ");
          /* Print the range */
-         iw_print_pm_value(buffer, range.min_pmp, flags | IW_POWER_MIN);
+         iw_print_pm_value(buffer, sizeof(buffer),
+                           range.min_pmp, flags | IW_POWER_MIN);
          printf("%s\n                          ", buffer);
          printf("%s\n                          ", buffer);
-         iw_print_pm_value(buffer, range.max_pmp, flags | IW_POWER_MAX);
+         iw_print_pm_value(buffer, sizeof(buffer),
+                           range.max_pmp, flags | IW_POWER_MAX);
          printf("%s\n          ", buffer);
          printf("%s\n          ", buffer);
-         
        }
       /* Display min/max timeout availables */
       if(range.pmt_flags & IW_POWER_TIMEOUT)
        }
       /* Display min/max timeout availables */
       if(range.pmt_flags & IW_POWER_TIMEOUT)
@@ -393,13 +390,13 @@ print_pm_info(int         skfd,
          else
            printf("Fixed timeout ; ");
          /* Print the range */
          else
            printf("Fixed timeout ; ");
          /* Print the range */
-         iw_print_pm_value(buffer, range.min_pmt, flags | IW_POWER_MIN);
+         iw_print_pm_value(buffer, sizeof(buffer),
+                           range.min_pmt, flags | IW_POWER_MIN);
          printf("%s\n                          ", buffer);
          printf("%s\n                          ", buffer);
-         iw_print_pm_value(buffer, range.max_pmt, flags | IW_POWER_MAX);
+         iw_print_pm_value(buffer, sizeof(buffer),
+                           range.max_pmt, flags | IW_POWER_MAX);
          printf("%s\n          ", buffer);
          printf("%s\n          ", buffer);
-         
        }
        }
-#endif /* WIRELESS_EXT > 9 */
 
       /* Get current Power Management settings */
       wrq.u.power.flags = 0;
 
       /* Get current Power Management settings */
       wrq.u.power.flags = 0;
@@ -415,7 +412,7 @@ print_pm_info(int           skfd,
              int       pm_mask = 0;
 
              /* Let's check the mode */
              int       pm_mask = 0;
 
              /* Let's check the mode */
-             iw_print_pm_mode(buffer, flags);
+             iw_print_pm_mode(buffer, sizeof(buffer), flags);
              printf("Current %s", buffer);
 
              /* Let's check if nothing (simply on) */
              printf("Current %s", buffer);
 
              /* Let's check if nothing (simply on) */
@@ -426,7 +423,7 @@ print_pm_info(int           skfd,
              /* Let's check the value and its type */
              if(wrq.u.power.flags & IW_POWER_TYPE)
                {
              /* Let's check the value and its type */
              if(wrq.u.power.flags & IW_POWER_TYPE)
                {
-                 iw_print_pm_value(buffer,
+                 iw_print_pm_value(buffer, sizeof(buffer),
                                    wrq.u.power.value, wrq.u.power.flags);
                  printf("%s", buffer);
                }
                                    wrq.u.power.value, wrq.u.power.flags);
                  printf("%s", buffer);
                }
@@ -441,7 +438,6 @@ print_pm_info(int           skfd,
              if(pm_mask)
                get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
 
              if(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 */
              pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
                                          IW_POWER_TYPE));
              /* And if we have both a period and a timeout, ask the other */
              pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
                                          IW_POWER_TYPE));
@@ -461,7 +457,6 @@ print_pm_info(int           skfd,
                  if(pm_mask)
                    get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
                }
                  if(pm_mask)
                    get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
                }
-#endif /* WIRELESS_EXT > 9 */
            }
        }
       printf("\n");
            }
        }
       printf("\n");
@@ -490,49 +485,69 @@ print_txpower_info(int            skfd,
   /* Avoid "Unused parameter" warning */
   args = args; count = count;
 
   /* Avoid "Unused parameter" warning */
   args = args; count = count;
 
-#if WIRELESS_EXT > 9
   /* Extract range info */
   /* Extract range info */
-  if(iw_get_range_info(skfd, ifname, &range) < 0)
-      fprintf(stderr, "%-8.8s  no transmit-power information.\n\n",
+  if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+     (range.we_version_compiled < 10))
+      fprintf(stderr, "%-8.16s  no transmit-power information.\n\n",
                      ifname);
   else
     {
       if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
                      ifname);
   else
     {
       if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
-       printf("%-8.8s  No transmit-powers ? Please update driver...\n\n", ifname);
+       printf("%-8.16s  unknown transmit-power information.\n\n", ifname);
       else
        {
       else
        {
-         printf("%-8.8s  %d available transmit-powers :\n",
+         printf("%-8.16s  %d available transmit-powers :\n",
                 ifname, range.num_txpower);
          /* Print them all */
          for(k = 0; k < range.num_txpower; k++)
            {
                 ifname, range.num_txpower);
          /* Print them all */
          for(k = 0; k < range.num_txpower; k++)
            {
-             if(range.txpower_capa & IW_TXPOW_MWATT)
+             /* Check for relative values */
+             if(range.txpower_capa & IW_TXPOW_RELATIVE)
                {
                {
-                 dbm = iw_mwatt2dbm(range.txpower[k]);
-                 mwatt = range.txpower[k];
+                 printf("\t  %d (no units)\n", range.txpower[k]);
                }
              else
                {
                }
              else
                {
-                 dbm = range.txpower[k];
-                 mwatt = iw_dbm2mwatt(range.txpower[k]);
+                 if(range.txpower_capa & IW_TXPOW_MWATT)
+                   {
+                     dbm = iw_mwatt2dbm(range.txpower[k]);
+                     mwatt = range.txpower[k];
+                   }
+                 else
+                   {
+                     dbm = range.txpower[k];
+                     mwatt = iw_dbm2mwatt(range.txpower[k]);
+                   }
+                 printf("\t  %d dBm  \t(%d mW)\n", dbm, mwatt);
                }
                }
-             printf("\t  %d dBm  \t(%d mW)\n", dbm, mwatt);
            }
            }
+       }
 
 
-         /* Get current Transmit Power */
-         if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
+      /* Get current Transmit Power */
+      if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
+       {
+         printf("          Current Tx-Power");
+         /* Disabled ? */
+         if(wrq.u.txpower.disabled)
+           printf(":off\n\n");
+         else
            {
            {
-             printf("          Current Tx-Power");
-             /* Disabled ? */
-             if(wrq.u.txpower.disabled)
-               printf(":off\n\n");
+             /* Fixed ? */
+             if(wrq.u.txpower.fixed)
+               printf("=");
+             else
+               printf(":");
+             /* Check for relative values */
+             if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
+               {
+                 /* I just hate relative value, because they are
+                  * driver specific, so not very meaningfull to apps.
+                  * But, we have to support that, because
+                  * this is the way hardware is... */
+                 printf("\t  %d (no units)\n", wrq.u.txpower.value);
+               }
              else
                {
              else
                {
-                 /* Fixed ? */
-                 if(wrq.u.txpower.fixed)
-                   printf("=");
-                 else
-                   printf(":");
                  if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
                    {
                      dbm = iw_mwatt2dbm(wrq.u.txpower.value);
                  if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
                    {
                      dbm = iw_mwatt2dbm(wrq.u.txpower.value);
@@ -548,13 +563,11 @@ print_txpower_info(int            skfd,
            }
        }
     }
            }
        }
     }
-#endif /* WIRELESS_EXT > 9 */
   return(0);
 }
 
 /*********************** RETRY LIMIT/LIFETIME ***********************/
 
   return(0);
 }
 
 /*********************** RETRY LIMIT/LIFETIME ***********************/
 
-#if WIRELESS_EXT > 10
 /*------------------------------------------------------------------*/
 /*
  * Print one retry value
 /*------------------------------------------------------------------*/
 /*
  * Print one retry value
@@ -564,7 +577,8 @@ get_retry_value(int         skfd,
                char *          ifname,
                struct iwreq *  pwrq,
                int             flags,
                char *          ifname,
                struct iwreq *  pwrq,
                int             flags,
-               char *          buffer)
+               char *          buffer,
+               int             buflen)
 {
   /* Get Another retry value */
   pwrq->u.retry.flags = flags;
 {
   /* Get Another retry value */
   pwrq->u.retry.flags = flags;
@@ -573,7 +587,7 @@ get_retry_value(int         skfd,
       /* Let's check the value and its type */
       if(pwrq->u.retry.flags & IW_RETRY_TYPE)
        {
       /* Let's check the value and its type */
       if(pwrq->u.retry.flags & IW_RETRY_TYPE)
        {
-         iw_print_retry_value(buffer,
+         iw_print_retry_value(buffer, buflen,
                               pwrq->u.retry.value, pwrq->u.retry.flags);
          printf("%s\n                 ", buffer);
        }
                               pwrq->u.retry.value, pwrq->u.retry.flags);
          printf("%s\n                 ", buffer);
        }
@@ -599,12 +613,13 @@ print_retry_info(int              skfd,
   args = args; count = count;
 
   /* Extract range info */
   args = args; count = count;
 
   /* Extract range info */
-  if(iw_get_range_info(skfd, ifname, &range) < 0)
-      fprintf(stderr, "%-8.8s  no retry limit/lifetime information.\n\n",
-             ifname);
+  if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+     (range.we_version_compiled < 11))
+    fprintf(stderr, "%-8.16s  no retry limit/lifetime information.\n\n",
+           ifname);
   else
     {
   else
     {
-      printf("%-8.8s  ", ifname);
+      printf("%-8.16s  ", ifname);
 
       /* Display min/max limit availables */
       if(range.retry_flags & IW_RETRY_LIMIT)
 
       /* Display min/max limit availables */
       if(range.retry_flags & IW_RETRY_LIMIT)
@@ -616,9 +631,11 @@ print_retry_info(int               skfd,
          else
            printf("Fixed limit    ; ");
          /* Print the range */
          else
            printf("Fixed limit    ; ");
          /* Print the range */
-         iw_print_retry_value(buffer, range.min_retry, flags | IW_RETRY_MIN);
+         iw_print_retry_value(buffer, sizeof(buffer),
+                              range.min_retry, flags | IW_RETRY_MIN);
          printf("%s\n                           ", buffer);
          printf("%s\n                           ", buffer);
-         iw_print_retry_value(buffer, range.max_retry, flags | IW_RETRY_MAX);
+         iw_print_retry_value(buffer, sizeof(buffer),
+                              range.max_retry, flags | IW_RETRY_MAX);
          printf("%s\n          ", buffer);
          
        }
          printf("%s\n          ", buffer);
          
        }
@@ -632,9 +649,11 @@ print_retry_info(int               skfd,
          else
            printf("Fixed lifetime ; ");
          /* Print the range */
          else
            printf("Fixed lifetime ; ");
          /* Print the range */
-         iw_print_retry_value(buffer, range.min_r_time, flags | IW_RETRY_MIN);
+         iw_print_retry_value(buffer, sizeof(buffer),
+                              range.min_r_time, flags | IW_RETRY_MIN);
          printf("%s\n                           ", buffer);
          printf("%s\n                           ", buffer);
-         iw_print_retry_value(buffer, range.max_r_time, flags | IW_RETRY_MAX);
+         iw_print_retry_value(buffer, sizeof(buffer),
+                              range.max_r_time, flags | IW_RETRY_MAX);
          printf("%s\n          ", buffer);
          
        }
          printf("%s\n          ", buffer);
          
        }
@@ -658,9 +677,9 @@ print_retry_info(int                skfd,
              /* Let's check the value and its type */
              if(wrq.u.retry.flags & IW_RETRY_TYPE)
                {
              /* Let's check the value and its type */
              if(wrq.u.retry.flags & IW_RETRY_TYPE)
                {
-                 iw_print_retry_value(buffer,
+                 iw_print_retry_value(buffer, sizeof(buffer),
                                       wrq.u.retry.value, wrq.u.retry.flags);
                                       wrq.u.retry.value, wrq.u.retry.flags);
-                 printf("%s", buffer);
+                 printf("%s\n                 ", buffer);
                }
 
              /* If we have been returned a MIN value, ask for the MAX */
                }
 
              /* If we have been returned a MIN value, ask for the MAX */
@@ -671,7 +690,8 @@ print_retry_info(int                skfd,
                retry_mask = IW_RETRY_MIN;
              /* If we have something to ask for... */
              if(retry_mask)
                retry_mask = IW_RETRY_MIN;
              /* If we have something to ask for... */
              if(retry_mask)
-               get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
+               get_retry_value(skfd, ifname, &wrq, retry_mask,
+                               buffer, sizeof(buffer));
 
              /* And if we have both a period and a timeout, ask the other */
              retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
 
              /* And if we have both a period and a timeout, ask the other */
              retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
@@ -680,7 +700,7 @@ print_retry_info(int                skfd,
                {
                  int   base_mask = retry_mask;
                  flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
                {
                  int   base_mask = retry_mask;
                  flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
-                                         buffer);
+                                         buffer, sizeof(buffer));
                  retry_mask = 0;
 
                  /* If we have been returned a MIN value, ask for the MAX */
                  retry_mask = 0;
 
                  /* If we have been returned a MIN value, ask for the MAX */
@@ -691,7 +711,8 @@ print_retry_info(int                skfd,
                    retry_mask = IW_RETRY_MIN | base_mask;
                  /* If we have something to ask for... */
                  if(retry_mask)
                    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, buffer);
+                   get_retry_value(skfd, ifname, &wrq, retry_mask,
+                                   buffer, sizeof(buffer));
                }
            }
        }
                }
            }
        }
@@ -700,13 +721,17 @@ print_retry_info(int              skfd,
   return(0);
 }
 
   return(0);
 }
 
-#endif /* WIRELESS_EXT > 10 */
-
 /***************************** SCANNING *****************************/
 /*
  * This one behave quite differently from the others
 /***************************** SCANNING *****************************/
 /*
  * This one behave quite differently from the others
+ *
+ * Note that we don't use the scanning capability of iwlib (functions
+ * iw_process_scan() and iw_scan()). The main reason is that
+ * iw_process_scan() return only a subset of the scan data to the caller,
+ * for example custom elements and bitrates are ommited. Here, we
+ * do the complete job...
  */
  */
-#if WIRELESS_EXT > 13
+
 /*------------------------------------------------------------------*/
 /*
  * Print one element from the scanning results
 /*------------------------------------------------------------------*/
 /*
  * Print one element from the scanning results
@@ -714,7 +739,7 @@ print_retry_info(int                skfd,
 static inline int
 print_scanning_token(struct iw_event * event,  /* Extracted token */
                     int                ap_num, /* AP number */
 static inline int
 print_scanning_token(struct iw_event * event,  /* Extracted token */
                     int                ap_num, /* AP number */
-                    struct iw_range *  iwrange,        /* Range info */
+                    struct iw_range *  iw_range,       /* Range info */
                     int                has_range)
 {
   char         buffer[128];    /* Temporary buffer */
                     int                has_range)
 {
   char         buffer[128];    /* Temporary buffer */
@@ -736,8 +761,13 @@ print_scanning_token(struct iw_event *     event,  /* Extracted token */
     case SIOCGIWFREQ:
       {
        double          freq;                   /* Frequency/channel */
     case SIOCGIWFREQ:
       {
        double          freq;                   /* Frequency/channel */
+       int             channel = -1;           /* Converted to channel */
        freq = iw_freq2float(&(event->u.freq));
        freq = iw_freq2float(&(event->u.freq));
-       iw_print_freq(buffer, freq);
+       /* Convert to channel if possible */
+       if(has_range)
+         channel = iw_freq_to_channel(freq, iw_range);
+       iw_print_freq(buffer, sizeof(buffer),
+                     freq, channel, event->u.freq.flags);
        printf("                    %s\n", buffer);
       }
       break;
        printf("                    %s\n", buffer);
       }
       break;
@@ -780,7 +810,7 @@ print_scanning_token(struct iw_event *      event,  /* Extracted token */
        else
          {
            /* Display the key */
        else
          {
            /* Display the key */
-           iw_print_key(buffer, key, event->u.data.length,
+           iw_print_key(buffer, sizeof(buffer), key, event->u.data.length,
                         event->u.data.flags);
            printf("%s", buffer);
 
                         event->u.data.flags);
            printf("%s", buffer);
 
@@ -796,17 +826,16 @@ print_scanning_token(struct iw_event *    event,  /* Extracted token */
       }
       break;
     case SIOCGIWRATE:
       }
       break;
     case SIOCGIWRATE:
-      iw_print_bitrate(buffer, event->u.bitrate.value);
+      iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);
       printf("                    Bit Rate:%s\n", buffer);
       break;
     case IWEVQUAL:
       {
       printf("                    Bit Rate:%s\n", buffer);
       break;
     case IWEVQUAL:
       {
-       event->u.qual.updated = 0x0;    /* Not that reliable, disable */
-       iw_print_stats(buffer, &event->u.qual, iwrange, has_range);
+       iw_print_stats(buffer, sizeof(buffer),
+                      &event->u.qual, iw_range, has_range);
        printf("                    %s\n", buffer);
        break;
       }
        printf("                    %s\n", buffer);
        break;
       }
-#if WIRELESS_EXT > 14
     case IWEVCUSTOM:
       {
        char custom[IW_CUSTOM_MAX+1];
     case IWEVCUSTOM:
       {
        char custom[IW_CUSTOM_MAX+1];
@@ -816,7 +845,6 @@ print_scanning_token(struct iw_event *      event,  /* Extracted token */
        printf("                    Extra:%s\n", custom);
       }
       break;
        printf("                    Extra:%s\n", custom);
       }
       break;
-#endif /* WIRELESS_EXT > 14 */
     default:
       printf("                    (Unknown Wireless Token 0x%04X)\n",
             event->cmd);
     default:
       printf("                    (Unknown Wireless Token 0x%04X)\n",
             event->cmd);
@@ -837,13 +865,27 @@ print_scanning_info(int           skfd,
                    int         count)          /* Args count */
 {
   struct iwreq         wrq;
                    int         count)          /* Args count */
 {
   struct iwreq         wrq;
-  unsigned char                buffer[IW_SCAN_MAX_DATA];       /* Results */
+  unsigned char *      buffer = NULL;          /* Results */
+  int                  buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
+  struct iw_range      range;
+  int                  has_range;
   struct timeval       tv;                             /* Select timeout */
   int                  timeout = 5000000;              /* 5s */
 
   /* Avoid "Unused parameter" warning */
   args = args; count = count;
 
   struct timeval       tv;                             /* Select timeout */
   int                  timeout = 5000000;              /* 5s */
 
   /* Avoid "Unused parameter" warning */
   args = args; count = count;
 
+  /* Get range stuff */
+  has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
+
+  /* Check if the interface could support scanning. */
+  if((!has_range) || (range.we_version_compiled < 14))
+    {
+      fprintf(stderr, "%-8.16s  Interface doesn't support scanning.\n\n",
+             ifname);
+      return(-1);
+    }
+
   /* Init timeout value -> 250ms*/
   tv.tv_sec = 0;
   tv.tv_usec = 250000;
   /* Init timeout value -> 250ms*/
   tv.tv_sec = 0;
   tv.tv_usec = 250000;
@@ -852,15 +894,16 @@ print_scanning_info(int           skfd,
    * Here we should look at the command line args and set the IW_SCAN_ flags
    * properly
    */
    * Here we should look at the command line args and set the IW_SCAN_ flags
    * properly
    */
-  wrq.u.param.flags = IW_SCAN_DEFAULT;
-  wrq.u.param.value = 0;               /* Later */
+  wrq.u.data.pointer = NULL;           /* Later */
+  wrq.u.data.flags = 0;
+  wrq.u.data.length = 0;
 
   /* Initiate Scanning */
   if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
     {
       if(errno != EPERM)
        {
 
   /* Initiate Scanning */
   if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
     {
       if(errno != EPERM)
        {
-         fprintf(stderr, "%-8.8s  Interface doesn't support scanning : %s\n\n",
+         fprintf(stderr, "%-8.16s  Interface doesn't support scanning : %s\n\n",
                  ifname, strerror(errno));
          return(-1);
        }
                  ifname, strerror(errno));
          return(-1);
        }
@@ -869,7 +912,7 @@ print_scanning_info(int             skfd,
        * But, don't wait !!! */
 #if 0
       /* Not cool, it display for non wireless interfaces... */
        * But, don't wait !!! */
 #if 0
       /* Not cool, it display for non wireless interfaces... */
-      fprintf(stderr, "%-8.8s  (Could not trigger scanning, just reading left-over results)\n", ifname);
+      fprintf(stderr, "%-8.16s  (Could not trigger scanning, just reading left-over results)\n", ifname);
 #endif
       tv.tv_usec = 0;
     }
 #endif
       tv.tv_usec = 0;
     }
@@ -903,12 +946,47 @@ print_scanning_info(int           skfd,
       /* Check if there was a timeout */
       if(ret == 0)
        {
       /* Check if there was a timeout */
       if(ret == 0)
        {
+         unsigned char *       newbuf;
+
+       realloc:
+         /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
+         newbuf = realloc(buffer, buflen);
+         if(newbuf == NULL)
+           {
+             if(buffer)
+               free(buffer);
+             fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
+             return(-1);
+           }
+         buffer = newbuf;
+
          /* Try to read the results */
          wrq.u.data.pointer = buffer;
          wrq.u.data.flags = 0;
          /* Try to read the results */
          wrq.u.data.pointer = buffer;
          wrq.u.data.flags = 0;
-         wrq.u.data.length = sizeof(buffer);
+         wrq.u.data.length = buflen;
          if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
            {
          if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
            {
+             /* Check if buffer was too small (WE-17 only) */
+             if((errno == E2BIG) && (range.we_version_compiled > 16))
+               {
+                 /* Some driver may return very large scan results, either
+                  * because there are many cells, or because they have many
+                  * large elements in cells (like IWEVCUSTOM). Most will
+                  * only need the regular sized buffer. We now use a dynamic
+                  * allocation of the buffer to satisfy everybody. Of course,
+                  * as we don't know in advance the size of the array, we try
+                  * various increasing sizes. Jean II */
+
+                 /* Check if the driver gave us any hints. */
+                 if(wrq.u.data.length > buflen)
+                   buflen = wrq.u.data.length;
+                 else
+                   buflen *= 2;
+
+                 /* Try again */
+                 goto realloc;
+               }
+
              /* Check if results not available yet */
              if(errno == EAGAIN)
                {
              /* Check if results not available yet */
              if(errno == EAGAIN)
                {
@@ -921,7 +999,8 @@ print_scanning_info(int             skfd,
                }
 
              /* Bad error */
                }
 
              /* Bad error */
-             fprintf(stderr, "%-8.8s  Failed to read scan data : %s\n\n",
+             free(buffer);
+             fprintf(stderr, "%-8.16s  Failed to read scan data : %s\n\n",
                      ifname, strerror(errno));
              return(-2);
            }
                      ifname, strerror(errno));
              return(-2);
            }
@@ -940,23 +1019,21 @@ print_scanning_info(int          skfd,
       struct stream_descr      stream;
       int                      ap_num = 1;
       int                      ret;
       struct stream_descr      stream;
       int                      ap_num = 1;
       int                      ret;
-      struct iw_range          range;
-      int                      has_range;
 #if 0
       /* Debugging code. In theory useless, because it's debugged ;-) */
       int      i;
 #if 0
       /* Debugging code. In theory useless, because it's debugged ;-) */
       int      i;
-      printf("Scan result [%02X", buffer[0]);
+      printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
       for(i = 1; i < wrq.u.data.length; i++)
        printf(":%02X", buffer[i]);
       printf("]\n");
 #endif
       for(i = 1; i < wrq.u.data.length; i++)
        printf(":%02X", buffer[i]);
       printf("]\n");
 #endif
-      has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
-      printf("%-8.8s  Scan completed :\n", ifname);
+      printf("%-8.16s  Scan completed :\n", ifname);
       iw_init_event_stream(&stream, buffer, wrq.u.data.length);
       do
        {
          /* Extract an event and print it */
       iw_init_event_stream(&stream, buffer, wrq.u.data.length);
       do
        {
          /* Extract an event and print it */
-         ret = iw_extract_event_stream(&stream, &iwe);
+         ret = iw_extract_event_stream(&stream, &iwe,
+                                       range.we_version_compiled);
          if(ret > 0)
            ap_num = print_scanning_token(&iwe, ap_num, &range, has_range);
        }
          if(ret > 0)
            ap_num = print_scanning_token(&iwe, ap_num, &range, has_range);
        }
@@ -964,11 +1041,93 @@ print_scanning_info(int          skfd,
       printf("\n");
     }
   else
       printf("\n");
     }
   else
-    printf("%-8.8s  No scan results\n", ifname);
+    printf("%-8.16s  No scan results\n", ifname);
 
 
+  free(buffer);
+  return(0);
+}
+
+/******************** WIRELESS EVENT CAPABILITY ********************/
+
+static const char *    event_capa_req[] =
+{
+  [SIOCSIWNWID - SIOCIWFIRST] = "Set NWID (kernel generated)",
+  [SIOCSIWFREQ - SIOCIWFIRST] = "Set Frequency/Channel (kernel generated)",
+  [SIOCGIWFREQ - SIOCIWFIRST] = "New Frequency/Channel",
+  [SIOCSIWMODE - SIOCIWFIRST] = "Set Mode (kernel generated)",
+  [SIOCGIWTHRSPY - SIOCIWFIRST] = "Spy threshold crossed",
+  [SIOCGIWAP   - SIOCIWFIRST] = "New Access Point/Cell address - roaming",
+  [SIOCGIWSCAN - SIOCIWFIRST] = "Scan request completed",
+  [SIOCSIWESSID        - SIOCIWFIRST] = "Set ESSID (kernel generated)",
+  [SIOCGIWESSID        - SIOCIWFIRST] = "New ESSID",
+  [SIOCGIWRATE - SIOCIWFIRST] = "New bit-rate",
+  [SIOCSIWENCODE - SIOCIWFIRST] = "Set Encoding (kernel generated)",
+  [SIOCGIWPOWER        - SIOCIWFIRST] = NULL,
+};
+
+static const char *    event_capa_evt[] =
+{
+  [IWEVTXDROP  - IWEVFIRST] = "Tx packet dropped - retry exceeded",
+  [IWEVCUSTOM  - IWEVFIRST] = "Custom driver event",
+  [IWEVREGISTERED - IWEVFIRST] = "Registered node",
+  [IWEVEXPIRED - IWEVFIRST] = "Expired node",
+};
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the number of available transmit powers for the device
+ */
+static int
+print_event_capa_info(int              skfd,
+                     char *            ifname,
+                     char *            args[],         /* Command line args */
+                     int               count)          /* Args count */
+{
+  struct iw_range      range;
+  int                  cmd;
+
+  /* Avoid "Unused parameter" warning */
+  args = args; count = count;
+
+  /* Extract range info */
+  if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+     (range.we_version_compiled < 10))
+      fprintf(stderr, "%-8.16s  no wireless event capability information.\n\n",
+                     ifname);
+  else
+    {
+#if 0
+      /* Debugging ;-) */
+      for(cmd = 0x8B00; cmd < 0x8C0F; cmd++)
+       {
+         int idx = IW_EVENT_CAPA_INDEX(cmd);
+         int mask = IW_EVENT_CAPA_MASK(cmd);
+         printf("0x%X - %d - %X\n", cmd, idx, mask);
+       }
+#endif
+
+      printf("%-8.16s  Wireless Events supported :\n", ifname);
+
+      for(cmd = SIOCIWFIRST; cmd <= SIOCGIWPOWER; cmd++)
+       {
+         int idx = IW_EVENT_CAPA_INDEX(cmd);
+         int mask = IW_EVENT_CAPA_MASK(cmd);
+         if(range.event_capa[idx] & mask)
+           printf("          0x%04X : %s\n",
+                  cmd, event_capa_req[cmd - SIOCIWFIRST]);
+       }
+      for(cmd = IWEVFIRST; cmd <= IWEVEXPIRED; cmd++)
+       {
+         int idx = IW_EVENT_CAPA_INDEX(cmd);
+         int mask = IW_EVENT_CAPA_MASK(cmd);
+         if(range.event_capa[idx] & mask)
+           printf("          0x%04X : %s\n",
+                  cmd, event_capa_evt[cmd - IWEVFIRST]);
+       }
+      printf("\n");
+    }
   return(0);
 }
   return(0);
 }
-#endif /* WIRELESS_EXT > 13 */
 
 /************************* COMMON UTILITIES *************************/
 /*
 
 /************************* COMMON UTILITIES *************************/
 /*
@@ -985,23 +1144,20 @@ typedef struct iwlist_entry {
 } iwlist_cmd;
 
 static const struct iwlist_entry iwlist_cmds[] = {
 } iwlist_cmd;
 
 static const struct iwlist_entry iwlist_cmds[] = {
+  { "scanning",                print_scanning_info,    0, 5 },
   { "frequency",       print_freq_info,        0, 0 },
   { "channel",         print_freq_info,        0, 0 },
   { "frequency",       print_freq_info,        0, 0 },
   { "channel",         print_freq_info,        0, 0 },
-  { "ap",              print_ap_info,          0, 0 },
-  { "accesspoints",    print_ap_info,          0, 0 },
-  { "peers",           print_ap_info,          0, 0 },
   { "bitrate",         print_bitrate_info,     0, 0 },
   { "rate",            print_bitrate_info,     0, 0 },
   { "encryption",      print_keys_info,        0, 0 },
   { "key",             print_keys_info,        0, 0 },
   { "power",           print_pm_info,          0, 0 },
   { "txpower",         print_txpower_info,     0, 0 },
   { "bitrate",         print_bitrate_info,     0, 0 },
   { "rate",            print_bitrate_info,     0, 0 },
   { "encryption",      print_keys_info,        0, 0 },
   { "key",             print_keys_info,        0, 0 },
   { "power",           print_pm_info,          0, 0 },
   { "txpower",         print_txpower_info,     0, 0 },
-#if WIRELESS_EXT > 10
   { "retry",           print_retry_info,       0, 0 },
   { "retry",           print_retry_info,       0, 0 },
-#endif
-#if WIRELESS_EXT > 13
-  { "scanning",                print_scanning_info,    0, 5 },
-#endif
+  { "ap",              print_ap_info,          0, 0 },
+  { "accesspoints",    print_ap_info,          0, 0 },
+  { "peers",           print_ap_info,          0, 0 },
+  { "event",           print_event_capa_info,  0, 0 },
   { NULL, NULL, 0, 0 },
 };
 
   { NULL, NULL, 0, 0 },
 };
 
@@ -1141,7 +1297,7 @@ main(int  argc,
     iw_enum_devices(skfd, iwcmd->fn, args, count);
 
   /* Close the socket. */
     iw_enum_devices(skfd, iwcmd->fn, args, count);
 
   /* Close the socket. */
-  close(skfd);
+  iw_sockets_close(skfd);
 
   return 0;
 }
 
   return 0;
 }
index 1786e4d..59b19bd 100644 (file)
@@ -1,14 +1,14 @@
 /*
  *     Wireless Tools
  *
 /*
  *     Wireless Tools
  *
- *             Jean II - HPLB 97->99 - HPL 99->00
+ *             Jean II - HPLB 97->99 - HPL 99->04
  *
  * Main code for "iwconfig". This is the generic tool for most
  * manipulations...
  * You need to link this code against "iwlib.c" and "-lm".
  *
  * This file is released under the GPL license.
  *
  * Main code for "iwconfig". This is the generic tool for most
  * manipulations...
  * You need to link this code against "iwlib.c" and "-lm".
  *
  * This file is released under the GPL license.
- *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
  */
 
 #include "iwlib.h"             /* Header */
  */
 
 #include "iwlib.h"             /* Header */
 /************************** DOCUMENTATION **************************/
 
 /*
 /************************** DOCUMENTATION **************************/
 
 /*
+ * BASIC PRINCIPLE
+ * ---------------
+ *     Wireless Extension recognise that each wireless device has some
+ * specific features not covered by the standard wireless extensions.
+ * Private wireless ioctls/requests allow a device to export the control
+ * of those device specific features, and allow users to directly interact
+ * with your driver.
+ *     There are many other ways you can implement such functionality :
+ *             o module parameters
+ *             o netlink socket
+ *             o file system (/proc/ or /sysfs/)
+ *             o extra character device (/dev/)
+ *     Private wireless ioctls is one of the simplest implementation,
+ * however it is limited, so you may want to check the alternatives.
+ *
+ *     Like for standard Wireless Extensions, each private wireless
+ * request is identified by an IOCTL NUMBER and carry a certain number
+ * of arguments (SET or GET).
+ *     The driver exports a description of those requests (ioctl number,
+ * request name, set and get arguments). Then, iwpriv uses those request
+ * descriptions to call the appropriate request and handle the
+ * arguments.
+ *
  * IOCTL RANGES :
  * ------------
  *     The initial implementation of iwpriv was using the SIOCDEVPRIVATE
  * IOCTL RANGES :
  * ------------
  *     The initial implementation of iwpriv was using the SIOCDEVPRIVATE
  * worry about collisions with other usages. On the other hand, in the
  * new range, the SET convention is enforced (see below).
  *     The differences are :           SIOCDEVPRIVATE  SIOCIWFIRSTPRIV
  * worry about collisions with other usages. On the other hand, in the
  * new range, the SET convention is enforced (see below).
  *     The differences are :           SIOCDEVPRIVATE  SIOCIWFIRSTPRIV
- *             o availability :        <= 2.5.X        WE > 11 (>= 2.4.13)
+ *             o availability          <= 2.5.X        WE > 11 (>= 2.4.13)
  *             o collisions            yes             no
  *             o SET convention        optional        enforced
  *             o number                16              32
  *
  * NEW DRIVER API :
  * --------------
  *             o collisions            yes             no
  *             o SET convention        optional        enforced
  *             o number                16              32
  *
  * NEW DRIVER API :
  * --------------
- *     Wireless Extension 13 introduce a new driver API. Wireless
+ *     Wireless Extension 13 introduces a new driver API. Wireless
  * Extensions requests can be handled via a iw_handler table instead
  * of through the regular ioctl handler.
  *     The new driver API can be handled only with the new ioctl range
  * Extensions requests can be handled via a iw_handler table instead
  * of through the regular ioctl handler.
  *     The new driver API can be handled only with the new ioctl range
- * and enforce the GET convention (see below).
+ * and enforces the GET convention (see below).
  *     The differences are :           old API         new API
  *             o handler               do_ioctl()      struct iw_handler_def
  *             o SIOCIWFIRSTPRIV       WE > 11         yes
  *             o SIOCDEVPRIVATE        yes             no
  *             o GET convention        optional        enforced
  *     Note that the new API before Wireless Extension 15 contains bugs
  *     The differences are :           old API         new API
  *             o handler               do_ioctl()      struct iw_handler_def
  *             o SIOCIWFIRSTPRIV       WE > 11         yes
  *             o SIOCDEVPRIVATE        yes             no
  *             o GET convention        optional        enforced
  *     Note that the new API before Wireless Extension 15 contains bugs
- * with regards to handling sub-ioctls and addr/float data types.
+ * when handling sub-ioctls and addr/float data types.
+ *
+ * INLINING vs. POINTER :
+ * --------------------
+ *     One of the tricky aspect of the old driver API is how the data
+ * is handled, which is how the driver is supposed to extract the data
+ * passed to it by iwpriv.
+ *     1) If the data has a fixed size (private ioctl definition
+ * has the flag IW_PRIV_SIZE_FIXED) and the byte size of the data is
+ * lower than 16 bytes, the data will be inlined. The driver can extract
+ * data in the field 'u.name' of the struct iwreq.
+ *     2) If the if the data doesn't have a fixed size or is larger than
+ * 16 bytes, the data is passed by pointer. struct iwreq contains a
+ * struct iwpoint with a user space pointer to the data. Appropriate
+ * copy_from/to_user() function should be used.
+ *     
+ *     With the new API, this is handled transparently, the data is
+ * always available as the fourth argument of the request handler
+ * (usually called 'extra').
  *
  * SET/GET CONVENTION :
  * ------------------
  *
  * SET/GET CONVENTION :
  * ------------------
- *     The regular Wireless Extensions use a SET/GET convention, where
- * the low order bit identify a SET (0) or a GET (1) request.
- *     The new ioctl range enforce the SET convention : SET request will
+ *     Simplistic summary :
+ *     o even numbered ioctls are SET, restricted to root, and should not
+ * return arguments (get_args = 0).
+ *     o odd numbered ioctls are GET, authorised to anybody, and should
+ * not expect any arguments (set_args = 0).
+ *
+ *     The regular Wireless Extensions use the SET/GET convention, where
+ * the low order bit identify a SET (0) or a GET (1) request. The private
+ * Wireless Extension is not as restrictive, but still has some
+ * limitations.
+ *     The new ioctl range enforces the SET convention : SET request will
  * be available to root only and can't return any arguments. If you don't
  * like that, just use every other two ioctl.
  *     The new driver API enforce the GET convention : GET request won't
  * be able to accept any arguments (except if its fits within (union
  * be available to root only and can't return any arguments. If you don't
  * like that, just use every other two ioctl.
  *     The new driver API enforce the GET convention : GET request won't
  * be able to accept any arguments (except if its fits within (union
- * iwreq_data)). If you don't like that, just use the old API (aka the
- * ioctl handler).
+ * iwreq_data)). If you don't like that, you can either use the Token Index
+ * support or the old API (aka the ioctl handler).
  *     In any case, it's a good idea to not have ioctl with both SET
  * and GET arguments. If the GET arguments doesn't fit within
  * (union iwreq_data) and SET do, or vice versa, the current code in iwpriv
  * won't work. One exception is if both SET and GET arguments fit within
  * (union iwreq_data), this case should be handled safely in a GET
  * request.
  *     In any case, it's a good idea to not have ioctl with both SET
  * and GET arguments. If the GET arguments doesn't fit within
  * (union iwreq_data) and SET do, or vice versa, the current code in iwpriv
  * won't work. One exception is if both SET and GET arguments fit within
  * (union iwreq_data), this case should be handled safely in a GET
  * request.
+ *     If you don't fully understand those limitations, just follow the
+ * rules of the simplistic summary ;-)
  *
  * SUB-IOCTLS :
  * ----------
  *
  * SUB-IOCTLS :
  * ----------
- *     Wireless Extension 15 introduce sub-ioctls. For some applications,
- * 32 ioctl is not enough, and this simple mechanism allow to increase
- * the number of ioctls by adding a sub-ioctl index to some of the ioctl
- * (so basically a two level addressing).
+ *     Wireless Extension 15 introduces sub-ioctls. For some applications,
+ * 32 ioctls is not enough, and this simple mechanism allows to increase
+ * the number of ioctls by adding a sub-ioctl index to some of the ioctls
+ * (so basically it's a two level addressing).
  *     One might argue that at the point, some other mechanisms might be
  * better, like using a real filesystem abstraction (/proc, driverfs, ...),
  *     One might argue that at the point, some other mechanisms might be
  * better, like using a real filesystem abstraction (/proc, driverfs, ...),
- * but sub-ioctls are simple enough to not have much drawbacks (which means
- * that it's a quick and dirty hack ;-).
+ * but sub-ioctls are simple enough and don't have much drawbacks (which
+ * means that it's a quick and dirty hack ;-).
  *
  *
- *     There is two slightly different variation of the sub-ioctl scheme :
- *     If the payload fit within (union iwreq_data), the first int (4 bytes)
- * is reserved as the sub-ioctl number and the regular payload shifted by
- * 4 bytes.
- *     If the ioctl use (struct iw_point), the sub-ioctl number is in the
- * flags member of the structure.
- *     Then, in your handler you would just extract the sub-ioctl number
- * and do the appropriate processing.
+ *     There are two slightly different variations of the sub-ioctl scheme :
+ *     1) If the payload fits within (union iwreq_data), the first int
+ * (4 bytes) is reserved as the sub-ioctl number and the regular payload
+ * shifted by 4 bytes. The handler must extract the sub-ioctl number,
+ * increment the data pointer and then use it in the usual way.
+ *     2) If the ioctl uses (struct iw_point), the sub-ioctl number is
+ * set in the flags member of the structure. In this case, the handler
+ * should simply get the sub-ioctl number from the flags and process the
+ * data in the usual way.
  *
  *     Sub-ioctls are declared normally in the private definition table,
  *
  *     Sub-ioctls are declared normally in the private definition table,
- * with cmd (first arg) beeing the sub-ioctl number. Then, you need to
- * declare the real ioctl which will process the sub-ioctls with the
- * SAME ARGUMENTS and a NULL NAME.
- *     It could look like, for example :
+ * with cmd (first arg) being the sub-ioctl number. Then, you should
+ * declare the real ioctl, which will process the sub-ioctls, with
+ * the SAME ARGUMENTS and a EMPTY NAME.
+ *     Here's an example of how it could look like :
  * --------------------------------------------
  * --------------------------------------------
-       // --- Raw access to sub-ioctl handlers ---
-       { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_paramN" },
-       { 0x8BE1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_paramN" },
        // --- sub-ioctls handlers ---
        { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
        { 0x8BE1, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
        // --- sub-ioctls handlers ---
        { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
        { 0x8BE1, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
        { 1, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param1" },
        { 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_param2" },
        { 2, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param2" },
        { 1, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param1" },
        { 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_param2" },
        { 2, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param2" },
+       // --- Raw access to sub-ioctl handlers ---
+       { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_paramN" },
+       { 0x8BE1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_paramN" },
  * --------------------------------------------
  *     And iwpriv should do the rest for you ;-)
  *
  * --------------------------------------------
  *     And iwpriv should do the rest for you ;-)
  *
- *     Note that version of iwpriv up to v24 (included) expect at most
+ *     Note that versions of iwpriv up to v24 (included) expect at most
  * 16 ioctls definitions and will likely crash when given more.
  * 16 ioctls definitions and will likely crash when given more.
- *     There is no fix that I can see, apart from recommending an upgrade
- * of Wireless Tools. Wireless Extensions 15 will check this condition, so
- * another workaround is restricting those extra definitions to WE-15.
+ *     There is no fix that I can see, apart from recommending your users
+ * to upgrade their Wireless Tools. Wireless Extensions 15 will check this
+ * condition, so another workaround is restricting those extra definitions
+ * to WE-15.
  *
  *
- *     Another problem is that new API before Wireless Extension 15
- * will get it wrong when passing fixed arguments of 12-15 bytes. It will
+ *     Another problem is that the new API before Wireless Extension 15
+ * has a bug when passing fixed arguments of 12-15 bytes. It will
  * try to get them inline instead of by pointer. You can fool the new API
  * to do the right thing using fake ioctl definitions (but remember that
  * try to get them inline instead of by pointer. You can fool the new API
  * to do the right thing using fake ioctl definitions (but remember that
- * you will get more likely to hit the limit of 16 ioctl definitions).
- *     For safety, use the ioctl handler before v15.
+ * you will be more likely to hit the limit of 16 ioctl definitions).
+ *     To play safe, use the old-style ioctl handler before v15.
  *
  * NEW DATA TYPES (ADDR/FLOAT) :
  * ---------------------------
  *
  * NEW DATA TYPES (ADDR/FLOAT) :
  * ---------------------------
  * However, the new API before v15 won't handle them properly.
  *
  *     The first problem is that the new API won't know their size, so
  * However, the new API before v15 won't handle them properly.
  *
  *     The first problem is that the new API won't know their size, so
- * won't copy them. This can be workaround with a fake ioctl definition.
+ * it won't copy them. This can be workaround with a fake ioctl definition.
  *     The second problem is that a fixed single addr won't be inlined
  * in struct iwreq and will be passed as a pointer. This is due to an
  * off-by-one error, where all fixed data of 16 bytes is considered too
  *     The second problem is that a fixed single addr won't be inlined
  * in struct iwreq and will be passed as a pointer. This is due to an
  * off-by-one error, where all fixed data of 16 bytes is considered too
  *
  * TOKEN INDEX :
  * -----------
  *
  * TOKEN INDEX :
  * -----------
- *     Token index is very similar to sub-ioctl. It allow the user
+ *     Token index is very similar to sub-ioctl. It allows the user
  * to specify an integer index in front of a bunch of other arguments
  * to specify an integer index in front of a bunch of other arguments
- * (addresses, strings, ...).
- *     Token index works only with data passed as pointer, and is
- * otherwise ignored. If your data would fit within struct iwreq, you
- * need to declare the command *without* IW_PRIV_SIZE_FIXED to force
+ * (addresses, strings, ...). It's specified in square brackets on the
+ * iwpriv command line before other arguments.
+ *             > iwpriv eth0 [index] args...
+ *     Token index works only when the data is passed as pointer, and
+ * is otherwise ignored. If your data would fit within struct iwreq, you
+ * should declare the command *without* IW_PRIV_SIZE_FIXED to force
  * this to happen (and check arg number yourself).
  * --------------------------------------------
        // --- Commands that would fit in struct iwreq ---
        { 0x8BE0, IW_PRIV_TYPE_ADDR | 1, 0, "set_param_with_token" },
  * this to happen (and check arg number yourself).
  * --------------------------------------------
        // --- Commands that would fit in struct iwreq ---
        { 0x8BE0, IW_PRIV_TYPE_ADDR | 1, 0, "set_param_with_token" },
-       // --- No problem here ---
+       // --- No problem here (bigger than struct iwreq) ---
        { 0x8BE1, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 2, 0, "again" },
  * --------------------------------------------
  *     The token index feature is pretty transparent, the token index
        { 0x8BE1, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 2, 0, "again" },
  * --------------------------------------------
  *     The token index feature is pretty transparent, the token index
  * (if the user doesn't specify it) will be 0. Token index itself will
  * work with any version of Wireless Extensions.
  *     Token index is not compatible with sub-ioctl (both use the same
  * (if the user doesn't specify it) will be 0. Token index itself will
  * work with any version of Wireless Extensions.
  *     Token index is not compatible with sub-ioctl (both use the same
- * field of struct iw_point). However, token index can be use to offer
+ * field of struct iw_point). However, the token index can be used to offer
  * raw access to the sub-ioctl handlers (if it uses struct iw_point) :
  * --------------------------------------------
        // --- sub-ioctls handler ---
  * raw access to the sub-ioctl handlers (if it uses struct iw_point) :
  * --------------------------------------------
        // --- sub-ioctls handler ---
 static const char *    argtype[] = {
   "     ", "byte ", "char ", "", "int  ", "float", "addr " };
 
 static const char *    argtype[] = {
   "     ", "byte ", "char ", "", "int  ", "float", "addr " };
 
-#define IW_MAX_PRIV_DEF        128
-
-/* Backward compatibility */
-#ifndef IW_PRIV_TYPE_ADDR
-#define IW_PRIV_TYPE_ADDR      0x6000
-#endif /* IW_PRIV_TYPE_ADDR */
-
 /************************* MISC SUBROUTINES **************************/
 
 /*------------------------------------------------------------------*/
 /************************* MISC SUBROUTINES **************************/
 
 /*------------------------------------------------------------------*/
@@ -221,9 +269,9 @@ set_private_cmd(int         skfd,           /* Socket */
   int          offset = 0;     /* Space for sub-ioctl index */
 
   /* Check if we have a token index.
   int          offset = 0;     /* Space for sub-ioctl index */
 
   /* Check if we have a token index.
-   * Do it know so that sub-ioctl takes precendence, and so that we
+   * Do it now so that sub-ioctl takes precendence, and so that we
    * don't have to bother with it later on... */
    * don't have to bother with it later on... */
-  if((count > 1) && (sscanf(args[0], "[%i]", &temp) == 1))
+  if((count >= 1) && (sscanf(args[0], "[%i]", &temp) == 1))
     {
       subcmd = temp;
       args++;
     {
       subcmd = temp;
       args++;
@@ -261,13 +309,15 @@ set_private_cmd(int               skfd,           /* Socket */
 
       /* Save sub-ioctl number */
       subcmd = priv[k].cmd;
 
       /* Save sub-ioctl number */
       subcmd = priv[k].cmd;
-      /* Reserve one int (simplify alignement issues) */
+      /* Reserve one int (simplify alignment issues) */
       offset = sizeof(__u32);
       /* Use real ioctl definition from now on */
       k = j;
 
       offset = sizeof(__u32);
       /* Use real ioctl definition from now on */
       k = j;
 
+#if 0
       printf("<mapping sub-ioctl %s to cmd 0x%X-%d>\n", cmdname,
             priv[k].cmd, subcmd);
       printf("<mapping sub-ioctl %s to cmd 0x%X-%d>\n", cmdname,
             priv[k].cmd, subcmd);
+#endif
     }
 
   /* If we have to set some data */
     }
 
   /* If we have to set some data */
@@ -424,7 +474,7 @@ set_private_cmd(int         skfd,           /* Socket */
       int      j;
       int      n = 0;          /* number of args */
 
       int      j;
       int      n = 0;          /* number of args */
 
-      printf("%-8.8s  %s:", ifname, cmdname);
+      printf("%-8.16s  %s:", ifname, cmdname);
 
       /* Check where is the returned data */
       if((priv[k].get_args & IW_PRIV_SIZE_FIXED) &&
 
       /* Check where is the returned data */
       if((priv[k].get_args & IW_PRIV_SIZE_FIXED) &&
@@ -454,7 +504,7 @@ set_private_cmd(int         skfd,           /* Socket */
 
        case IW_PRIV_TYPE_CHAR:
          /* Display args */
 
        case IW_PRIV_TYPE_CHAR:
          /* Display args */
-         buffer[wrq.u.data.length - 1] = '\0';
+         buffer[n] = '\0';
          printf("%s\n", buffer);
          break;
 
          printf("%s\n", buffer);
          break;
 
@@ -512,31 +562,38 @@ set_private(int           skfd,           /* Socket */
            int         count,          /* Args count */
            char *      ifname)         /* Dev name */
 {
            int         count,          /* Args count */
            char *      ifname)         /* Dev name */
 {
-  iwprivargs   priv[IW_MAX_PRIV_DEF];
+  iwprivargs * priv;
   int          number;         /* Max of private ioctl */
   int          number;         /* Max of private ioctl */
+  int          ret;
 
   /* Read the private ioctls */
 
   /* Read the private ioctls */
-  number = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF);
+  number = iw_get_priv_info(skfd, ifname, &priv);
 
   /* Is there any ? */
   if(number <= 0)
     {
 
   /* Is there any ? */
   if(number <= 0)
     {
-      /* Could skip this message ? */
-      fprintf(stderr, "%-8.8s  no private ioctls.\n\n",
+      /* Should I skip this message ? */
+      fprintf(stderr, "%-8.16s  no private ioctls.\n\n",
              ifname);
              ifname);
+      if(priv)
+       free(priv);
       return(-1);
     }
 
       return(-1);
     }
 
-  return(set_private_cmd(skfd, args + 1, count - 1, ifname, args[0],
-                        priv, number));
+  /* Do it */
+  ret = set_private_cmd(skfd, args + 1, count - 1, ifname, args[0],
+                       priv, number);
+
+  free(priv);
+  return(ret);
 }
 
 /************************ CATALOG FUNCTIONS ************************/
 
 /*------------------------------------------------------------------*/
 /*
 }
 
 /************************ CATALOG FUNCTIONS ************************/
 
 /*------------------------------------------------------------------*/
 /*
- * Print on the screen in a neat fashion all the info we have collected
- * on a device.
+ * Print on the screen in a neat fashion the list of private ioctls
+ * for the device.
  */
 static int
 print_priv_info(int            skfd,
  */
 static int
 print_priv_info(int            skfd,
@@ -545,25 +602,25 @@ print_priv_info(int               skfd,
                int             count)
 {
   int          k;
                int             count)
 {
   int          k;
-  iwprivargs   priv[IW_MAX_PRIV_DEF];
+  iwprivargs * priv;
   int          n;
 
   /* Avoid "Unused parameter" warning */
   args = args; count = count;
 
   /* Read the private ioctls */
   int          n;
 
   /* Avoid "Unused parameter" warning */
   args = args; count = count;
 
   /* Read the private ioctls */
-  n = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF);
+  n = iw_get_priv_info(skfd, ifname, &priv);
 
   /* Is there any ? */
   if(n <= 0)
     {
 
   /* Is there any ? */
   if(n <= 0)
     {
-      /* Could skip this message ? */
-      fprintf(stderr, "%-8.8s  no private ioctls.\n\n",
+      /* Should I skip this message ? */
+      fprintf(stderr, "%-8.16s  no private ioctls.\n\n",
              ifname);
     }
   else
     {
              ifname);
     }
   else
     {
-      printf("%-8.8s  Available private ioctl :\n", ifname);
+      printf("%-8.16s  Available private ioctl :\n", ifname);
       /* Print them all */
       for(k = 0; k < n; k++)
        if(priv[k].name[0] != '\0')
       /* Print them all */
       for(k = 0; k < n; k++)
        if(priv[k].name[0] != '\0')
@@ -575,13 +632,17 @@ print_priv_info(int               skfd,
                 argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]);
       printf("\n");
     }
                 argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]);
       printf("\n");
     }
+
+  /* Cleanup */
+  if(priv)
+    free(priv);
   return(0);
 }
 
 /*------------------------------------------------------------------*/
 /*
   return(0);
 }
 
 /*------------------------------------------------------------------*/
 /*
- * Print on the screen in a neat fashion all the info we have collected
- * on a device.
+ * Print on the screen in a neat fashion the list of private GET ioctl
+ * data for the device and data returned by those.
  */
 static int
 print_priv_all(int             skfd,
  */
 static int
 print_priv_all(int             skfd,
@@ -590,28 +651,28 @@ print_priv_all(int                skfd,
               int              count)
 {
   int          k;
               int              count)
 {
   int          k;
-  iwprivargs   priv[IW_MAX_PRIV_DEF];
+  iwprivargs * priv;
   int          n;
 
   /* Avoid "Unused parameter" warning */
   args = args; count = count;
 
   /* Read the private ioctls */
   int          n;
 
   /* Avoid "Unused parameter" warning */
   args = args; count = count;
 
   /* Read the private ioctls */
-  n = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF);
+  n = iw_get_priv_info(skfd, ifname, &priv);
 
   /* Is there any ? */
   if(n <= 0)
     {
 
   /* Is there any ? */
   if(n <= 0)
     {
-      /* Could skip this message ? */
-      fprintf(stderr, "%-8.8s  no private ioctls.\n\n",
+      /* Should I skip this message ? */
+      fprintf(stderr, "%-8.16s  no private ioctls.\n\n",
              ifname);
     }
   else
     {
              ifname);
     }
   else
     {
-      printf("%-8.8s  Available read-only private ioctl :\n", ifname);
+      printf("%-8.16s  Available read-only private ioctl :\n", ifname);
       /* Print them all */
       for(k = 0; k < n; k++)
       /* Print them all */
       for(k = 0; k < n; k++)
-       /* We call all ioctl that don't have a null name, don't require
+       /* We call all ioctls that don't have a null name, don't require
         * args and return some (avoid triggering "reset" commands) */
        if((priv[k].name[0] != '\0') && (priv[k].set_args == 0) &&
           (priv[k].get_args != 0))
         * args and return some (avoid triggering "reset" commands) */
        if((priv[k].name[0] != '\0') && (priv[k].set_args == 0) &&
           (priv[k].get_args != 0))
@@ -619,13 +680,10 @@ print_priv_all(int                skfd,
                          priv, n);
       printf("\n");
     }
                          priv, n);
       printf("\n");
     }
-#if 0
-  // Debug
-  printf("struct ifreq = %d ; struct iwreq = %d ; IFNAMSIZ = %d\n",
-        sizeof(struct ifreq), sizeof(struct iwreq), IFNAMSIZ);
-  printf("struct iw_freq = %d ; struct sockaddr = %d\n",
-        sizeof(struct iw_freq), sizeof(struct sockaddr));
-#endif
+
+  /* Cleanup */
+  if(priv)
+    free(priv);
   return(0);
 }
 
   return(0);
 }
 
@@ -638,6 +696,8 @@ print_priv_all(int          skfd,
 /*
  * Set roaming mode on and off
  * Found in wavelan_cs driver
 /*
  * Set roaming mode on and off
  * Found in wavelan_cs driver
+ * Note : this is obsolete, most 802.11 devices should use the
+ * SIOCSIWAP request.
  */
 static int
 set_roaming(int                skfd,           /* Socket */
  */
 static int
 set_roaming(int                skfd,           /* Socket */
@@ -649,24 +709,41 @@ set_roaming(int           skfd,           /* Socket */
   struct iwreq         wrq;
   int          i = 0;          /* Start with first arg */
   int          k;
   struct iwreq         wrq;
   int          i = 0;          /* Start with first arg */
   int          k;
-  iwprivargs   priv[IW_MAX_PRIV_DEF];
+  iwprivargs * priv;
   int          number;
   int          number;
+  int          roamcmd;
   char         RoamState;              /* buffer to hold new roam state */
   char         ChangeRoamState=0;      /* whether or not we are going to
                                           change roam states */
 
   /* Read the private ioctls */
   char         RoamState;              /* buffer to hold new roam state */
   char         ChangeRoamState=0;      /* whether or not we are going to
                                           change roam states */
 
   /* Read the private ioctls */
-  number = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF);
+  number = iw_get_priv_info(skfd, ifname, &priv);
 
   /* Is there any ? */
   if(number <= 0)
     {
 
   /* Is there any ? */
   if(number <= 0)
     {
-      /* Could skip this message ? */
-      fprintf(stderr, "%-8.8s  no private ioctls.\n\n",
+      /* Should I skip this message ? */
+      fprintf(stderr, "%-8.16s  no private ioctls.\n\n",
              ifname);
              ifname);
+      if(priv)
+       free(priv);
       return(-1);
     }
 
       return(-1);
     }
 
+  /* Get the ioctl number */
+  k = -1;
+  while((++k < number) && strcmp(priv[k].name, "setroam"));
+  if(k == number)
+    {
+      fprintf(stderr, "This device doesn't support roaming\n");
+      free(priv);
+      return(-1);
+    }
+  roamcmd = priv[k].cmd;
+
+  /* Cleanup */
+  free(priv);
+
   if(count != 1)
     {
       iw_usage();
   if(count != 1)
     {
       iw_usage();
@@ -675,7 +752,7 @@ set_roaming(int             skfd,           /* Socket */
 
   if(!strcasecmp(args[i], "on"))
     {
 
   if(!strcasecmp(args[i], "on"))
     {
-      printf("%-8.8s  enable roaming\n", ifname);
+      printf("%-8.16s  enable roaming\n", ifname);
       if(!number)
        {
          fprintf(stderr, "This device doesn't support roaming\n");
       if(!number)
        {
          fprintf(stderr, "This device doesn't support roaming\n");
@@ -688,7 +765,7 @@ set_roaming(int             skfd,           /* Socket */
     if(!strcasecmp(args[i], "off"))
       {
        i++;
     if(!strcasecmp(args[i], "off"))
       {
        i++;
-       printf("%-8.8s  disable roaming\n",  ifname);
+       printf("%-8.16s  disable roaming\n",  ifname);
        if(!number)
          {
            fprintf(stderr, "This device doesn't support roaming\n");
        if(!number)
          {
            fprintf(stderr, "This device doesn't support roaming\n");
@@ -705,20 +782,13 @@ set_roaming(int           skfd,           /* Socket */
 
   if(ChangeRoamState)
     {
 
   if(ChangeRoamState)
     {
-      k = -1;
-      while((++k < number) && strcmp(priv[k].name, "setroam"));
-      if(k == number)
-       {
-         fprintf(stderr, "This device doesn't support roaming\n");
-         return(-1);
-       }
       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
 
       buffer[0]=RoamState;
 
       memcpy(wrq.u.name, &buffer, IFNAMSIZ);
 
       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
 
       buffer[0]=RoamState;
 
       memcpy(wrq.u.name, &buffer, IFNAMSIZ);
 
-      if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
+      if(ioctl(skfd, roamcmd, &wrq) < 0)
        {
          fprintf(stderr, "Roaming support is broken.\n");
          return(-1);
        {
          fprintf(stderr, "Roaming support is broken.\n");
          return(-1);
@@ -732,6 +802,7 @@ set_roaming(int             skfd,           /* Socket */
 /*
  * Get and set the port type
  * Found in wavelan2_cs and wvlan_cs drivers
 /*
  * Get and set the port type
  * Found in wavelan2_cs and wvlan_cs drivers
+ * TODO : Add support for HostAP ?
  */
 static int
 port_type(int          skfd,           /* Socket */
  */
 static int
 port_type(int          skfd,           /* Socket */
@@ -742,19 +813,21 @@ port_type(int             skfd,           /* Socket */
   struct iwreq wrq;
   int          i = 0;          /* Start with first arg */
   int          k;
   struct iwreq wrq;
   int          i = 0;          /* Start with first arg */
   int          k;
-  iwprivargs   priv[IW_MAX_PRIV_DEF];
+  iwprivargs * priv;
   int          number;
   char         ptype = 0;
   char *       modes[] = { "invalid", "managed (BSS)", "reserved", "ad-hoc" };
 
   /* Read the private ioctls */
   int          number;
   char         ptype = 0;
   char *       modes[] = { "invalid", "managed (BSS)", "reserved", "ad-hoc" };
 
   /* Read the private ioctls */
-  number = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF);
+  number = iw_get_priv_info(skfd, ifname, &priv);
 
   /* Is there any ? */
   if(number <= 0)
     {
 
   /* Is there any ? */
   if(number <= 0)
     {
-      /* Could skip this message ? */
-      fprintf(stderr, "%-8.8s  no private ioctls.\n\n", ifname);
+      /* Should I skip this message ? */
+      fprintf(stderr, "%-8.16s  no private ioctls.\n\n", ifname);
+      if(priv)
+       free(priv);
       return(-1);
     }
 
       return(-1);
     }
 
@@ -768,7 +841,7 @@ port_type(int               skfd,           /* Socket */
       if(k == number)
        {
          fprintf(stderr, "This device doesn't support getting port type\n");
       if(k == number)
        {
          fprintf(stderr, "This device doesn't support getting port type\n");
-         return(-1);
+         goto err;
        }
       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
 
        }
       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
 
@@ -776,21 +849,22 @@ port_type(int             skfd,           /* Socket */
       if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
        {
          fprintf(stderr, "Port type support is broken.\n");
       if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
        {
          fprintf(stderr, "Port type support is broken.\n");
-         exit(0);
+         goto err;
        }
       ptype = *wrq.u.name;
 
       /* Display it */
        }
       ptype = *wrq.u.name;
 
       /* Display it */
-      printf("%-8.8s  Current port mode is %s <port type is %d>.\n\n",
+      printf("%-8.16s  Current port mode is %s <port type is %d>.\n\n",
             ifname, modes[(int) ptype], ptype);
 
             ifname, modes[(int) ptype], ptype);
 
+      free(priv);
       return(0);
     }
 
   if(count != 1)
     {
       iw_usage();
       return(0);
     }
 
   if(count != 1)
     {
       iw_usage();
-      return(-1);
+      goto err;
     }
 
   /* Read it */
     }
 
   /* Read it */
@@ -805,7 +879,7 @@ port_type(int               skfd,           /* Socket */
     if(sscanf(args[i], "%i", (int *) &ptype) != 1)
       {
        iw_usage();
     if(sscanf(args[i], "%i", (int *) &ptype) != 1)
       {
        iw_usage();
-       return(-1);
+       goto err;
       }
   
   k = -1;
       }
   
   k = -1;
@@ -814,7 +888,7 @@ port_type(int               skfd,           /* Socket */
   if(k == number)
     {
       fprintf(stderr, "This device doesn't support setting port type\n");
   if(k == number)
     {
       fprintf(stderr, "This device doesn't support setting port type\n");
-      return(-1);
+      goto err;
     }
   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
 
     }
   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
 
@@ -823,10 +897,15 @@ port_type(int             skfd,           /* Socket */
   if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
     {
       fprintf(stderr, "Invalid port type (or setting not allowed)\n");
   if(ioctl(skfd, priv[k].cmd, &wrq) < 0)
     {
       fprintf(stderr, "Invalid port type (or setting not allowed)\n");
-      return(-1);
+      goto err;
     }
 
     }
 
+  free(priv);
   return(0);
   return(0);
+
+ err:
+  free(priv);
+  return(-1);
 }
 
 /******************************* MAIN ********************************/
 }
 
 /******************************* MAIN ********************************/
@@ -849,7 +928,7 @@ main(int    argc,
       return(-1);
     }
 
       return(-1);
     }
 
-  /* No argument : show the list of all device + info */
+  /* No argument : show the list of all devices + ioctl list */
   if(argc == 1)
     iw_enum_devices(skfd, &print_priv_info, NULL, 0);
   else
   if(argc == 1)
     iw_enum_devices(skfd, &print_priv_info, NULL, 0);
   else
@@ -890,7 +969,7 @@ main(int    argc,
                  goterr = set_private(skfd, argv + 2, argc - 2, argv[1]);
 
   /* Close the socket. */
                  goterr = set_private(skfd, argv + 2, argc - 2, argv[1]);
 
   /* Close the socket. */
-  close(skfd);
+  iw_sockets_close(skfd);
 
   return(goterr);
 }
 
   return(goterr);
 }
diff --git a/wireless_tools/iwredir.8 b/wireless_tools/iwredir.8
deleted file mode 100644 (file)
index 2a4d60b..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-.\" Jean II - HPL - 03
-.\" iwredir.8
-.\"
-.TH IWREDIR 8 "31 October 1996" "net-tools" "Linux Programmer's Manual"
-.\"
-.\" NAME part
-.\"
-.SH NAME
-iwredir \- WE-version wireless tool redirectot
-.\"
-.\" SYNOPSIS part
-.\"
-.SH SYNOPSIS
-.BI "iw" XXX " [ " args " ]"
-.br
-.BI "iwredir -wev
-.\"
-.\" DESCRIPTION part
-.\"
-.SH DESCRIPTION
-.B Iwredir
-is used to enable the use multiple version of the Wireless Tools on
-the same system.
-.B Iwredir
-pick the proper version of the wireless tools based on the version of
-Wireless Extension of the current kernel.
-.PP
-A version of the Wireless Tools need to be compiled for each version
-of Wireless Extensions expected to be used (this require specific
-.I make
-instructions), and each tool name need to be suffixed by the WE
-version (ex.
-.I iwconfig16
-for the binary of iwconfig compiled for Wireless Extension 16).
-.br
-Then,
-.B iwredir
-need to be installed under the name of each of the tool that need
-redirection
-.RI "(" iwconfig ", " iwlist "...)."
-.br
-.B Iwredir
-just adds the version of WE from the current kernel to the name it was
-called and executed the resulting command name. If the user invoque
-.I iwlist
-(that is now replaced with
-.IR iwredir )
-and the current kernel has WE version
-.IR 17 ,
-the final command executed will be
-.IR iwlist17 .
-.br
-.B Iwredir
-will read the Wireless Extension version of the current kernel from
-.IR /proc/net/wireless .
-.PP
-.B Iwredir
-works only for Wireless Extension 16 and later, all previous version
-of WE are assumed to be version 15 or version 11.
-.B Iwredir
-is usually not installed by default and is expected to be used only by
-.I advanced
-users.
-.\"
-.\" PARAMETER part
-.\"
-.SH PARAMETERS
-.TP
-.BR -wev
-Give the Wireless Extension version that
-.B iwredir
-will use for redirection. This is mostly used in the Wireless Tools
-Makefile when doing a versioned installation of the tools.
-.\"
-.\" FILES part
-.\"
-.SH FILES
-.I /proc/net/wireless
-.\"
-.\" SEE ALSO part
-.\"
-.SH SEE ALSO
-.BR iwconfig (8),
-.BR iwlist (8),
-.BR iwspy (8),
-.BR iwevent (8),
-.BR iwpriv (8),
-.BR wireless (7).
-
diff --git a/wireless_tools/iwredir.c b/wireless_tools/iwredir.c
deleted file mode 100644 (file)
index ef99249..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *     Wireless Tools
- *
- *             Jean II - HPL 03
- *
- * Main code for "iwredir". This is a hack to match multiple version
- * of the tools with multiple kernels on the same system...
- *
- * This file is released under the GPL license.
- *     Copyright (c) 2003 Jean Tourrilhes <jt@hpl.hp.com>
- */
-
-/***************************** INCLUDES *****************************/
-
-#include "iwlib.h"             /* Header */
-
-/*********************** VERSION SUBROUTINES ***********************/
-
-/*------------------------------------------------------------------*/
-/*
- * Extract WE version number from /proc/net/wireless
- * If we have WE-16 and later, the WE version is available at the
- * end of the header line of the file.
- * For version prior to that, we can only detect the change from
- * v11 to v12, so we do an approximate job. Fortunately, v12 to v15
- * are highly binary compatible (on the struct level).
- */
-static int
-iw_get_kernel_we_version(void)
-{
-  char         buff[1024];
-  FILE *       fh;
-  char *       p;
-  int          v;
-
-  /* Check if /proc/net/wireless is available */
-  fh = fopen(PROC_NET_WIRELESS, "r");
-
-  if(fh == NULL)
-    {
-      fprintf(stderr, "Cannot read " PROC_NET_WIRELESS "\n");
-      return(-1);
-    }
-
-  /* Read the first line of buffer */
-  fgets(buff, sizeof(buff), fh);
-
-  if(strstr(buff, "| WE") == NULL)
-    {
-      /* Prior to WE16, so explicit version not present */
-
-      /* Black magic */
-      if(strstr(buff, "| Missed") == NULL)
-       v = 11;
-      else
-       v = 15;
-      fclose(fh);
-      return(v);
-    }
-
-  /* Read the second line of buffer */
-  fgets(buff, sizeof(buff), fh);
-
-  /* Get to the last separator, to get the version */
-  p = strrchr(buff, '|');
-  if((p == NULL) || (sscanf(p + 1, "%d", &v) != 1))
-    {
-      fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
-      fclose(fh);
-      return(-1);
-    }
-
-  fclose(fh);
-  return(v);
-}
-
-/******************************* MAIN ********************************/
-
-/*------------------------------------------------------------------*/
-/*
- * The main !
- */
-int
-main(int       argc,
-     char **   argv)
-{
-  int  version = 0;
-  int  goterr = 0;
-  char file[512];
-  int  flen;
-
-  /* Get current version */
-  version = iw_get_kernel_we_version();
-  if(version <= 0)
-    version = 15;      /* We can only read only WE16 and higher */
-
-  /* Special case for Wireless Extension Version... */
-  /* This is mostly used in the Makefile, we use an "unlikely" option
-   * to maximise transparency to the tool we masquerade - Jean II */
-  if((argc > 1) && !strcmp(argv[1], "-wev"))
-    {
-      printf("%d\n", version);
-      return(version);
-    }
-
-  /* Mangle the command name */
-  flen = strlen(argv[0]);
-  if((flen + 3) >= 512)
-    {
-      fprintf(stderr, "Command name too long [%s]\n", argv[0]);
-      return(-1);
-    }
-  memcpy(file, argv[0], flen + 1);
-  sprintf(file + flen, "%d", version);
-
-  /* Execute (won't return) */
-  goterr = execvp(file, argv);
-
-  /* In case of error */
-  fprintf(stderr, "Can't execute command %s: %s\n", file, strerror(errno));
-  return(goterr);
-}
-
-
index 1bc2deb..35f5db9 100644 (file)
@@ -1,13 +1,13 @@
 /*
  *     Wireless Tools
  *
 /*
  *     Wireless Tools
  *
- *             Jean II - HPLB '99
+ *             Jean II - HPLB '99 - HPL 99->04
  *
  * This tool can manipulate the spy list : add addresses and display stat
  * You need to link this code against "iwlib.c" and "-lm".
  *
  * This file is released under the GPL license.
  *
  * This tool can manipulate the spy list : add addresses and display stat
  * You need to link this code against "iwlib.c" and "-lm".
  *
  * This file is released under the GPL license.
- *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
  */
 
 #include "iwlib.h"             /* Header */
  */
 
 #include "iwlib.h"             /* Header */
@@ -44,7 +44,7 @@ print_spy_info(int    skfd,
   wrq.u.data.flags = 0;
   if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
     {
   wrq.u.data.flags = 0;
   if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
     {
-      fprintf(stderr, "%-8.8s  Interface doesn't support wireless statistic collection\n\n", ifname);
+      fprintf(stderr, "%-8.16s  Interface doesn't support wireless statistic collection\n\n", ifname);
       return(-1);
     }
 
       return(-1);
     }
 
@@ -54,7 +54,7 @@ print_spy_info(int    skfd,
   /* Check if we have valid mac address type */
   if(iw_check_mac_addr_type(skfd, ifname) < 0)
     {
   /* Check if we have valid mac address type */
   if(iw_check_mac_addr_type(skfd, ifname) < 0)
     {
-      fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n\n", ifname);
+      fprintf(stderr, "%-8.16s  Interface doesn't support MAC addresses\n\n", ifname);
       return(-2);
     }
 
       return(-2);
     }
 
@@ -64,9 +64,9 @@ print_spy_info(int    skfd,
 
   /* Display it */
   if(n == 0)
 
   /* Display it */
   if(n == 0)
-    printf("%-8.8s  No statistics to collect\n", ifname);
+    printf("%-8.16s  No statistics to collect\n", ifname);
   else
   else
-    printf("%-8.8s  Statistics collected:\n", ifname);
+    printf("%-8.16s  Statistics collected:\n", ifname);
  
   /* The two lists */
   hwa = (struct sockaddr *) buffer;
  
   /* The two lists */
   hwa = (struct sockaddr *) buffer;
@@ -76,25 +76,25 @@ print_spy_info(int  skfd,
     {
       /* Print stats for each address */
       printf("    %s : ", iw_pr_ether(temp, hwa[i].sa_data));
     {
       /* Print stats for each address */
       printf("    %s : ", iw_pr_ether(temp, hwa[i].sa_data));
-      iw_print_stats(temp, &qual[i], &range, has_range);
+      iw_print_stats(temp, sizeof(temp), &qual[i], &range, has_range);
       printf("%s\n", temp);
     }
       printf("%s\n", temp);
     }
-#if WIRELESS_EXT > 11
-  if((n > 0) && (has_range))
+
+  if((n > 0) && (has_range) && (range.we_version_compiled > 11))
     {
       iwstats  stats;
 
       /* Get /proc/net/wireless */
     {
       iwstats  stats;
 
       /* Get /proc/net/wireless */
-      if(iw_get_stats(skfd, ifname, &stats) >= 0)
+      if(iw_get_stats(skfd, ifname, &stats, &range, has_range) >= 0)
        {
        {
-         iw_print_stats(buffer, &stats.qual, &range, has_range);
-         printf("    Link/Cell/AP      : %s\n", buffer);
+         iw_print_stats(temp, sizeof(temp), &stats.qual, &range, has_range);
+         printf("    Link/Cell/AP      : %s\n", temp);
          /* Display the static data */
          /* Display the static data */
-         iw_print_stats(temp, &range.avg_qual, &range, has_range);
+         iw_print_stats(temp, sizeof(temp),
+                        &range.avg_qual, &range, has_range);
          printf("    Typical/Reference : %s\n", temp);
        }
     }
          printf("    Typical/Reference : %s\n", temp);
        }
     }
-#endif /* WIRELESS_EXT > 11 */
 
   printf("\n");
   return(0);
 
   printf("\n");
   return(0);
@@ -110,7 +110,6 @@ get_spy_threshold(int               skfd,           /* The socket */
                  char *        args[],         /* Command line args */
                  int           count)          /* Args count */
 {
                  char *        args[],         /* Command line args */
                  int           count)          /* Args count */
 {
-#if WIRELESS_EXT > 15
   struct iwreq         wrq;
   struct iw_thrspy     threshold;
   iwrange      range;
   struct iwreq         wrq;
   struct iw_thrspy     threshold;
   iwrange      range;
@@ -141,14 +140,14 @@ get_spy_threshold(int             skfd,           /* The socket */
       if(threshold.low.level > range.max_qual.level)
        {
          /* Statistics are in dBm (absolute power measurement) */
       if(threshold.low.level > range.max_qual.level)
        {
          /* Statistics are in dBm (absolute power measurement) */
-         printf("%-8.8s  Low threshold:%d dBm  High threshold:%d dBm\n\n",
+         printf("%-8.16s  Low threshold:%d dBm  High threshold:%d dBm\n\n",
                 ifname,
                 threshold.low.level - 0x100, threshold.high.level - 0x100);
        }
       else
        {
          /* Statistics are relative values (0 -> max) */
                 ifname,
                 threshold.low.level - 0x100, threshold.high.level - 0x100);
        }
       else
        {
          /* Statistics are relative values (0 -> max) */
-         printf("%-8.8s  Low threshold:%d/%d  High threshold:%d/%d\n\n",
+         printf("%-8.16s  Low threshold:%d/%d  High threshold:%d/%d\n\n",
                 ifname,
                 threshold.low.level, range.max_qual.level,
                 threshold.high.level, range.max_qual.level);
                 ifname,
                 threshold.low.level, range.max_qual.level,
                 threshold.high.level, range.max_qual.level);
@@ -157,19 +156,12 @@ get_spy_threshold(int             skfd,           /* The socket */
   else
     {
       /* We can't read the range, so we don't know... */
   else
     {
       /* We can't read the range, so we don't know... */
-      printf("%-8.8s  Low threshold:%d  High threshold:%d\n\n",
+      printf("%-8.16s  Low threshold:%d  High threshold:%d\n\n",
             ifname,
             threshold.low.level, threshold.high.level);
     }
 
   return(0);
             ifname,
             threshold.low.level, threshold.high.level);
     }
 
   return(0);
-#else /* WIRELESS_EXT > 15 */
-  /* Avoid "Unused parameter" warning */
-  skfd = skfd; ifname = ifname; args = args; count = count;
-
-  fprintf(stderr, "Feature not available...\n");
-  return(-1);
-#endif /* WIRELESS_EXT > 15 */
 }
 
 /************************* SETTING ROUTINES **************************/
 }
 
 /************************* SETTING ROUTINES **************************/
@@ -207,12 +199,12 @@ set_spy_info(int          skfd,           /* The socket */
          /* Check if we have valid mac address type */
          if(iw_check_mac_addr_type(skfd, ifname) < 0)
            {
          /* Check if we have valid mac address type */
          if(iw_check_mac_addr_type(skfd, ifname) < 0)
            {
-             fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n", ifname);
+             fprintf(stderr, "%-8.16s  Interface doesn't support MAC addresses\n", ifname);
              return(-1);
            }
 
          wrq.u.data.pointer = (caddr_t) buffer;
              return(-1);
            }
 
          wrq.u.data.pointer = (caddr_t) buffer;
-         wrq.u.data.length = 0;
+         wrq.u.data.length = IW_MAX_SPY;
          wrq.u.data.flags = 0;
          if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
            {
          wrq.u.data.flags = 0;
          if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
            {
@@ -275,7 +267,6 @@ set_spy_threshold(int               skfd,           /* The socket */
                  char *        args[],         /* Command line args */
                  int           count)          /* Args count */
 {
                  char *        args[],         /* Command line args */
                  int           count)          /* Args count */
 {
-#if WIRELESS_EXT > 15
   struct iwreq         wrq;
   struct iw_thrspy     threshold;
   int                  low_thr;
   struct iwreq         wrq;
   struct iw_thrspy     threshold;
   int                  low_thr;
@@ -294,19 +285,19 @@ set_spy_threshold(int             skfd,           /* The socket */
       /* Try to get our threshold */
       if(count < 2)
        {
       /* Try to get our threshold */
       if(count < 2)
        {
-         fprintf(stderr, "%-8.8s  Need two threshold values\n", ifname);
+         fprintf(stderr, "%-8.16s  Need two threshold values\n", ifname);
          return(-1);
        }
       if((sscanf(args[0], "%i", &low_thr) != 1) ||
         (sscanf(args[1], "%i", &high_thr) != 1))
        {
          return(-1);
        }
       if((sscanf(args[0], "%i", &low_thr) != 1) ||
         (sscanf(args[1], "%i", &high_thr) != 1))
        {
-         fprintf(stderr, "%-8.8s  Invalid threshold values\n", ifname);
+         fprintf(stderr, "%-8.16s  Invalid threshold values\n", ifname);
          return(-1);
        }
       /* Basic sanity check */
       if(high_thr < low_thr)
        {
          return(-1);
        }
       /* Basic sanity check */
       if(high_thr < low_thr)
        {
-         fprintf(stderr, "%-8.8s  Inverted threshold range\n", ifname);
+         fprintf(stderr, "%-8.16s  Inverted threshold range\n", ifname);
          return(-1);
        }
       /* Copy thresholds */
          return(-1);
        }
       /* Copy thresholds */
@@ -328,13 +319,6 @@ set_spy_threshold(int              skfd,           /* The socket */
     }
 
   return(0);
     }
 
   return(0);
-#else /* WIRELESS_EXT > 15 */
-  /* Avoid "Unused parameter" warning */
-  skfd = skfd; ifname = ifname; args = args; count = count;
-
-  fprintf(stderr, "Feature not available...\n");
-  return(-1);
-#endif /* WIRELESS_EXT > 15 */
 }
 
 /******************************* MAIN ********************************/
 }
 
 /******************************* MAIN ********************************/
@@ -386,7 +370,7 @@ main(int    argc,
              goterr = set_spy_info(skfd, argv[1], argv + 2, argc - 2);
 
   /* Close the socket. */
              goterr = set_spy_info(skfd, argv[1], argv + 2, argc - 2);
 
   /* Close the socket. */
-  close(skfd);
+  iw_sockets_close(skfd);
 
   return(goterr);
 }
 
   return(goterr);
 }
diff --git a/wireless_tools/wireless.17.h b/wireless_tools/wireless.17.h
new file mode 100644 (file)
index 0000000..794b94a
--- /dev/null
@@ -0,0 +1,773 @@
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version :   17      21.6.04
+ *
+ * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands.  This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ *     # net/core/dev.c (two place + add include)
+ *     # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ *     # net/core/dev.c (two other places)
+ *     # include/linux/netdevice.h (one place)
+ *     # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ *     # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ *     # net/core/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+ *     # net/core/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+/* To minimise problems in user space, I might remove those headers
+ * at some point. Jean II */
+#include <linux/types.h>               /* for "caddr_t" et al          */
+#include <linux/socket.h>              /* for "struct sockaddr" et al  */
+#include <linux/if.h>                  /* for IFNAMSIZ and co... */
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT   17
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ *     Alan Cox start some incompatibles changes. I've integrated a bit more.
+ *     - Encryption renamed to Encode to avoid US regulation problems
+ *     - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ *     - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ *     - Missing encoding definitions in range
+ *     - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ *     - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ *     - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ *     - Changed my e-mail address
+ *     - More 802.11 support (nickname, rate, rts, frag)
+ *     - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ *     - Support for 'mode of operation' (ad-hoc, managed...)
+ *     - Support for unicast and multicast power saving
+ *     - Change encoding to support larger tokens (>64 bits)
+ *     - Updated iw_params (disable, flags) and use it for NWID
+ *     - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ *     - Add PM capability to range structure
+ *     - Add PM modifier : MAX/MIN/RELATIVE
+ *     - Add encoding option : IW_ENCODE_NOKEY
+ *     - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ *     - Add WE version in range (help backward/forward compatibility)
+ *     - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ *     - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ *     - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ *     - Add new statistics (frag, retry, beacon)
+ *     - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ *     - Document creation of new driver API.
+ *     - Extract union iwreq_data from struct iwreq (for new driver API).
+ *     - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ *
+ * V13 to V14
+ * ----------
+ *     - Wireless Events support : define struct iw_event
+ *     - Define additional specific event numbers
+ *     - Add "addr" and "param" fields in union iwreq_data
+ *     - AP scanning stuff (SIOCSIWSCAN and friends)
+ *
+ * V14 to V15
+ * ----------
+ *     - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
+ *     - Make struct iw_freq signed (both m & e), add explicit padding
+ *     - Add IWEVCUSTOM for driver specific event/scanning token
+ *     - Add IW_MAX_GET_SPY for driver returning a lot of addresses
+ *     - Add IW_TXPOW_RANGE for range of Tx Powers
+ *     - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ *     - Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ *     - Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ *     - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ *     - Reshuffle struct iw_range for increases, add filler
+ *     - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ *     - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ *     - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ *     - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ *
+ * V16 to V17
+ * ----------
+ *     - Add flags to frequency -> auto/fixed
+ *     - Document (struct iw_quality *)->updated, add new flags (INVALID)
+ *     - Wireless Event capability in struct iw_range
+ *     - Add support for relative TxPower (yick !)
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Wireless Identification */
+#define SIOCSIWCOMMIT  0x8B00          /* Commit pending changes to driver */
+#define SIOCGIWNAME    0x8B01          /* get name == wireless protocol */
+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
+ * Don't put the name of your driver there, it's useless. */
+
+/* Basic operations */
+#define SIOCSIWNWID    0x8B02          /* set network id (pre-802.11) */
+#define SIOCGIWNWID    0x8B03          /* get network id (the cell) */
+#define SIOCSIWFREQ    0x8B04          /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ    0x8B05          /* get channel/frequency (Hz) */
+#define SIOCSIWMODE    0x8B06          /* set operation mode */
+#define SIOCGIWMODE    0x8B07          /* get operation mode */
+#define SIOCSIWSENS    0x8B08          /* set sensitivity (dBm) */
+#define SIOCGIWSENS    0x8B09          /* get sensitivity (dBm) */
+
+/* Informative stuff */
+#define SIOCSIWRANGE   0x8B0A          /* Unused */
+#define SIOCGIWRANGE   0x8B0B          /* Get range of parameters */
+#define SIOCSIWPRIV    0x8B0C          /* Unused */
+#define SIOCGIWPRIV    0x8B0D          /* get private ioctl interface info */
+#define SIOCSIWSTATS   0x8B0E          /* Unused */
+#define SIOCGIWSTATS   0x8B0F          /* Get /proc/net/wireless stats */
+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
+
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
+#define SIOCSIWSPY     0x8B10          /* set spy addresses */
+#define SIOCGIWSPY     0x8B11          /* get spy info (quality of link) */
+#define SIOCSIWTHRSPY  0x8B12          /* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY  0x8B13          /* get spy threshold */
+
+/* Access Point manipulation */
+#define SIOCSIWAP      0x8B14          /* set access point MAC addresses */
+#define SIOCGIWAP      0x8B15          /* get access point MAC addresses */
+#define SIOCGIWAPLIST  0x8B17          /* Deprecated in favor of scanning */
+#define SIOCSIWSCAN    0x8B18          /* trigger scanning (list cells) */
+#define SIOCGIWSCAN    0x8B19          /* get scanning results */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID   0x8B1A          /* set ESSID (network name) */
+#define SIOCGIWESSID   0x8B1B          /* get ESSID */
+#define SIOCSIWNICKN   0x8B1C          /* set node name/nickname */
+#define SIOCGIWNICKN   0x8B1D          /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE... */
+
+/* Other parameters useful in 802.11 and some other devices */
+#define SIOCSIWRATE    0x8B20          /* set default bit rate (bps) */
+#define SIOCGIWRATE    0x8B21          /* get default bit rate (bps) */
+#define SIOCSIWRTS     0x8B22          /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS     0x8B23          /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG    0x8B24          /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG    0x8B25          /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW   0x8B26          /* set transmit power (dBm) */
+#define SIOCGIWTXPOW   0x8B27          /* get transmit power (dBm) */
+#define SIOCSIWRETRY   0x8B28          /* set retry limits and lifetime */
+#define SIOCGIWRETRY   0x8B29          /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+#define SIOCSIWENCODE  0x8B2A          /* set encoding token & mode */
+#define SIOCGIWENCODE  0x8B2B          /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+#define SIOCSIWPOWER   0x8B2C          /* set Power Management settings */
+#define SIOCGIWPOWER   0x8B2D          /* get Power Management settings */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 32 ioctl are wireless device private, for 16 commands.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+#define SIOCIWFIRSTPRIV        0x8BE0
+#define SIOCIWLASTPRIV 0x8BFF
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'odd' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command). More details in iwpriv.c.
+ * And I repeat : you are not forced to use them with iwpriv, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST    0x8B00
+#define SIOCIWLAST     SIOCIWLASTPRIV          /* 0x8BFF */
+
+/* Even : get (world access), odd : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/* Those are *NOT* ioctls, do not issue request on them !!! */
+/* Most events use the same identifier as ioctl requests */
+
+#define IWEVTXDROP     0x8C00          /* Packet dropped to excessive retry */
+#define IWEVQUAL       0x8C01          /* Quality part of statistics (scan) */
+#define IWEVCUSTOM     0x8C02          /* Driver specific ascii string */
+#define IWEVREGISTERED 0x8C03          /* Discovered a new node (AP mode) */
+#define IWEVEXPIRED    0x8C04          /* Expired a node (AP mode) */
+
+#define IWEVFIRST      0x8C00
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+#define IW_PRIV_TYPE_MASK      0x7000  /* Type of arguments */
+#define IW_PRIV_TYPE_NONE      0x0000
+#define IW_PRIV_TYPE_BYTE      0x1000  /* Char as number */
+#define IW_PRIV_TYPE_CHAR      0x2000  /* Char as character */
+#define IW_PRIV_TYPE_INT       0x4000  /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT     0x5000  /* struct iw_freq */
+#define IW_PRIV_TYPE_ADDR      0x6000  /* struct sockaddr */
+
+#define IW_PRIV_SIZE_FIXED     0x0800  /* Variable or fixed number 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     32
+/* 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                32
+
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER         8
+/* Note : if you more than 8 TXPowers, just set the max and min or
+ * a few of them in the struct iw_range. */
+
+/* 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              64
+
+/* 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) */
+#define IW_MODE_MONITOR        6       /* Passive monitor (listen only) */
+
+/* Statistics flags (bitmask in updated) */
+#define IW_QUAL_QUAL_UPDATED   0x1     /* Value was updated since last read */
+#define IW_QUAL_LEVEL_UPDATED  0x2
+#define IW_QUAL_NOISE_UPDATED  0x4
+#define IW_QUAL_QUAL_INVALID   0x10    /* Driver doesn't provide value */
+#define IW_QUAL_LEVEL_INVALID  0x20
+#define IW_QUAL_NOISE_INVALID  0x40
+
+/* Frequency flags */
+#define IW_FREQ_AUTO           0x00    /* Let the driver decides */
+#define IW_FREQ_FIXED          0x01    /* Force a specific value */
+
+/* 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 */
+#define IW_ENCODE_TEMP         0x0400  /* Temporary key */
+
+/* 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_TYPE          0x00FF  /* Type of value */
+#define IW_TXPOW_DBM           0x0000  /* Value is in dBm */
+#define IW_TXPOW_MWATT         0x0001  /* Value is in mW */
+#define IW_TXPOW_RELATIVE      0x0002  /* Value is in arbitrary units */
+#define IW_TXPOW_RANGE         0x1000  /* Range of value between min/max */
+
+/* Retry limits and lifetime flags available */
+#define IW_RETRY_ON            0x0000  /* No details... */
+#define IW_RETRY_TYPE          0xF000  /* Type of parameter */
+#define IW_RETRY_LIMIT         0x1000  /* Maximum number of retries*/
+#define IW_RETRY_LIFETIME      0x2000  /* Maximum duration of retries in us */
+#define IW_RETRY_MODIFIER      0x000F  /* Modify a parameter */
+#define IW_RETRY_MIN           0x0001  /* Value is a minimum  */
+#define IW_RETRY_MAX           0x0002  /* Value is a maximum */
+#define IW_RETRY_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
+
+/* Scanning request flags */
+#define IW_SCAN_DEFAULT                0x0000  /* Default scan of the driver */
+#define IW_SCAN_ALL_ESSID      0x0001  /* Scan all ESSIDs */
+#define IW_SCAN_THIS_ESSID     0x0002  /* Scan only this ESSID */
+#define IW_SCAN_ALL_FREQ       0x0004  /* Scan all Frequencies */
+#define IW_SCAN_THIS_FREQ      0x0008  /* Scan only this Frequency */
+#define IW_SCAN_ALL_MODE       0x0010  /* Scan all Modes */
+#define IW_SCAN_THIS_MODE      0x0020  /* Scan only this Mode */
+#define IW_SCAN_ALL_RATE       0x0040  /* Scan all Bit-Rates */
+#define IW_SCAN_THIS_RATE      0x0080  /* Scan only this Bit-Rate */
+/* Maximum size of returned data */
+#define IW_SCAN_MAX_DATA       4096    /* In bytes */
+
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX          256     /* In bytes */
+
+/* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+#define IW_EVENT_CAPA_BASE(cmd)                ((cmd >= SIOCIWFIRSTPRIV) ? \
+                                        (cmd - SIOCIWFIRSTPRIV + 0x60) : \
+                                        (cmd - SIOCSIWCOMMIT))
+#define IW_EVENT_CAPA_INDEX(cmd)       (IW_EVENT_CAPA_BASE(cmd) >> 5)
+#define IW_EVENT_CAPA_MASK(cmd)                (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
+/* Event capability constants - event autogenerated by the kernel
+ * This list is valid for most 802.11 devices, customise as needed... */
+#define IW_EVENT_CAPA_K_0      (IW_EVENT_CAPA_MASK(0x8B04) | \
+                                IW_EVENT_CAPA_MASK(0x8B06) | \
+                                IW_EVENT_CAPA_MASK(0x8B1A))
+#define IW_EVENT_CAPA_K_1      (IW_EVENT_CAPA_MASK(0x8B2A))
+/* "Easy" macro to set events in iw_range (less efficient) */
+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
+
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ *     Generic format for most parameters that fit in an int
+ */
+struct iw_param
+{
+  __s32                value;          /* The value of the parameter itself */
+  __u8         fixed;          /* Hardware should not use auto select */
+  __u8         disabled;       /* Disable the feature */
+  __u16                flags;          /* Various specifc flags (if any) */
+};
+
+/*
+ *     For all data larger than 16 octets, we need to use a
+ *     pointer to memory allocated in user space.
+ */
+struct iw_point
+{
+  caddr_t      pointer;        /* Pointer to the data  (in user space) */
+  __u16                length;         /* number of fields or size in bytes */
+  __u16                flags;          /* Optional params */
+};
+
+/*
+ *     A frequency
+ *     For numbers lower than 10^9, we encode the number in 'm' and
+ *     set 'e' to 0
+ *     For number greater than 10^9, we divide it by the lowest power
+ *     of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ *     The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq
+{
+       __s32           m;              /* Mantissa */
+       __s16           e;              /* Exponent */
+       __u8            i;              /* List index (when in range struct) */
+       __u8            flags;          /* Flags (fixed/auto) */
+};
+
+/*
+ *     Quality of the link
+ */
+struct iw_quality
+{
+       __u8            qual;           /* link quality (%retries, SNR,
+                                          %missed beacons or better...) */
+       __u8            level;          /* signal level (dBm) */
+       __u8            noise;          /* noise level (dBm) */
+       __u8            updated;        /* Flags to know if updated */
+};
+
+/*
+ *     Packet discarded in the wireless adapter due to
+ *     "wireless" specific problems...
+ *     Note : the list of counter and statistics in net_device_stats
+ *     is already pretty exhaustive, and you should use that first.
+ *     This is only additional stats...
+ */
+struct iw_discarded
+{
+       __u32           nwid;           /* Rx : Wrong nwid/essid */
+       __u32           code;           /* Rx : Unable to code/decode (WEP) */
+       __u32           fragment;       /* Rx : Can't perform MAC reassembly */
+       __u32           retries;        /* Tx : Max MAC retries num reached */
+       __u32           misc;           /* Others cases */
+};
+
+/*
+ *     Packet/Time period missed in the wireless adapter due to
+ *     "wireless" specific problems...
+ */
+struct iw_missed
+{
+       __u32           beacon;         /* Missed beacons/superframe */
+};
+
+/*
+ *     Quality range (for spy threshold)
+ */
+struct iw_thrspy
+{
+       struct sockaddr         addr;           /* Source address (hw/mac) */
+       struct iw_quality       qual;           /* Quality of the link */
+       struct iw_quality       low;            /* Low threshold */
+       struct iw_quality       high;           /* High threshold */
+};
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics
+{
+       __u16           status;         /* Status
+                                        * - device dependent for now */
+
+       struct iw_quality       qual;           /* Quality of the link
+                                                * (instant/mean/max) */
+       struct iw_discarded     discard;        /* Packet discarded counts */
+       struct iw_missed        miss;           /* Packet missed counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used 
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ */
+union  iwreq_data
+{
+       /* Config - generic */
+       char            name[IFNAMSIZ];
+       /* Name : used to verify the presence of  wireless extensions.
+        * Name of the protocol/provider... */
+
+       struct iw_point essid;          /* Extended network name */
+       struct iw_param nwid;           /* network id (or domain - the cell) */
+       struct iw_freq  freq;           /* frequency or channel :
+                                        * 0-1000 = channel
+                                        * > 1000 = frequency in Hz */
+
+       struct iw_param sens;           /* signal level threshold */
+       struct iw_param bitrate;        /* default bit rate */
+       struct iw_param txpower;        /* default transmit power */
+       struct iw_param rts;            /* RTS threshold threshold */
+       struct iw_param frag;           /* Fragmentation threshold */
+       __u32           mode;           /* Operation mode */
+       struct iw_param retry;          /* Retry limits & lifetime */
+
+       struct iw_point encoding;       /* Encoding stuff : tokens */
+       struct iw_param power;          /* PM duration/timeout */
+       struct iw_quality qual;         /* Quality part of statistics */
+
+       struct sockaddr ap_addr;        /* Access point address */
+       struct sockaddr addr;           /* Destination address (hw/mac) */
+
+       struct iw_param param;          /* Other small parameters */
+       struct iw_point data;           /* Other large parameters */
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+ */
+struct iwreq 
+{
+       union
+       {
+               char    ifrn_name[IFNAMSIZ];    /* if name, e.g. "eth0" */
+       } ifr_ifrn;
+
+       /* Data part (defined just above) */
+       union   iwreq_data      u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ *     For those ioctl which want to exchange mode data that what could
+ *     fit in the above structure...
+ */
+
+/*
+ *     Range of parameters
+ */
+
+struct iw_range
+{
+       /* Informative stuff (to choose between different interface) */
+       __u32           throughput;     /* To give an idea... */
+       /* In theory this value should be the maximum benchmarked
+        * TCP/IP throughput, because with most of these devices the
+        * bit rate is meaningless (overhead an co) to estimate how
+        * fast the connection will go and pick the fastest one.
+        * I suggest people to play with Netperf or any benchmark...
+        */
+
+       /* NWID (or domain id) */
+       __u32           min_nwid;       /* Minimal NWID we are able to set */
+       __u32           max_nwid;       /* Maximal NWID we are able to set */
+
+       /* Old Frequency (backward compat - moved lower ) */
+       __u16           old_num_channels;
+       __u8            old_num_frequency;
+
+       /* Wireless event capability bitmasks */
+       __u32           event_capa[6];
+
+       /* signal level threshold range */
+       __s32           sensitivity;
+
+       /* Quality of link & SNR stuff */
+       /* Quality range (link, level, noise)
+        * If the quality is absolute, it will be in the range [0 ; max_qual],
+        * if the quality is dBm, it will be in the range [max_qual ; 0].
+        * Don't forget that we use 8 bit arithmetics... */
+       struct iw_quality       max_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... */
+       struct iw_quality       avg_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 */
+       /* For drivers that need a "login/passwd" form */
+       __u8    encoding_login_index;   /* token index for login token */
+
+       /* 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 */
+
+       /* 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,
+        * because each entry contain its channel index */
+};
+
+/*
+ * Private ioctl interface information
+ */
+struct iw_priv_args
+{
+       __u32           cmd;            /* Number of the ioctl to issue */
+       __u16           set_args;       /* Type and number of args */
+       __u16           get_args;       /* Type and number of args */
+       char            name[IFNAMSIZ]; /* Name of the extension */
+};
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/*
+ * Wireless events are carried through the rtnetlink socket to user
+ * space. They are encapsulated in the IFLA_WIRELESS field of
+ * a RTM_NEWLINK message.
+ */
+
+/*
+ * A Wireless Event. Contains basically the same data as the ioctl...
+ */
+struct iw_event
+{
+       __u16           len;                    /* Real lenght of this stuff */
+       __u16           cmd;                    /* Wireless IOCTL */
+       union iwreq_data        u;              /* IOCTL fixed payload */
+};
+
+/* Size of the Event prefix (including padding and alignement junk) */
+#define IW_EV_LCP_LEN  (sizeof(struct iw_event) - sizeof(union iwreq_data))
+/* Size of the various events */
+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
+#define IW_EV_POINT_LEN        (IW_EV_LCP_LEN + sizeof(struct iw_point))
+#define IW_EV_PARAM_LEN        (IW_EV_LCP_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
+
+/* Note : in the case of iw_point, the extra data will come at the
+ * end of the event */
+
+#endif /* _LINUX_WIRELESS_H */
index eebb235..7d51dc7 100644 (file)
@@ -1,7 +1,7 @@
-.\" Jean Tourrilhes - HPL - 2002
+.\" Jean Tourrilhes - HPL - 2002 - 2004
 .\" wireless.7
 .\"
 .\" wireless.7
 .\"
-.TH WIRELESS 7 "12 July 2002" "net-tools" "Linux Programmer's Manual"
+.TH WIRELESS 7 "4 March 2004" "wireless-tools" "Linux Programmer's Manual"
 .\"
 .\" NAME part
 .\"
 .\"
 .\" NAME part
 .\"
@@ -13,7 +13,7 @@ wireless \- Wireless Tools and Wireless Extensions
 .SH SYNOPSIS
 .B iwconfig
 .br
 .SH SYNOPSIS
 .B iwconfig
 .br
-.B iwpriv -a
+.B iwpriv \-a
 .br
 .\"
 .\" DESCRIPTION part
 .br
 .\"
 .\" DESCRIPTION part
@@ -23,40 +23,42 @@ The
 .B Wireless Extensions
 is an API allowing you manipulate Wireless LAN networking interfaces.
 It is composed of a variety of tools and configuration files. It is
 .B Wireless Extensions
 is an API allowing you manipulate Wireless LAN networking interfaces.
 It is composed of a variety of tools and configuration files. It is
-documented in more details in the Linux Wireless LAN Howto.
+documented in more detail in the Linux Wireless LAN Howto.
 .br
 The
 .B Wireless Tools
 .br
 The
 .B Wireless Tools
-are use to change configuration on the fly, to get statistics and
-diagnose those interfaces. They are described in their own man page
-(see below).
+are used to change the configuration of wireless LAN networking
+interfaces on the fly, to get their current configuration, to get
+statistics and diagnose them. They are described in their own man
+page, see below for references.
 .br
 .B Wireless configuration
 is specific to each Linux distribution. This man page will contain in
 .br
 .B Wireless configuration
 is specific to each Linux distribution. This man page will contain in
-the future the configuration procedure for a few common distributions
-(when I get the necessary info from them). For the time being, check
-the various files included with the Wireless Tools package.
+the future the configuration procedure for a few common
+distributions. For the time being, check the file DISTRIBUTIONS.txt
+included with the Wireless Tools package.
 .\"
 .\" DEBIAN 3.0 part
 .\"
 .SH DEBIAN 3.0
 .\"
 .\" DEBIAN 3.0 part
 .\"
 .SH DEBIAN 3.0
-Debian 3.0 (and later) has integrated wireless configuration in their
-network scripts.
+In Debian 3.0 (and later) you can configure wireless LAN networking
+devices using the network configuration tool
+.BR ifupdown (8).
 .TP
 .B File :
 .I /etc/network/interfaces
 .TP
 .B Form :
 .TP
 .B File :
 .I /etc/network/interfaces
 .TP
 .B Form :
-.RI wireless_ "<function> <value>"
+.RI wireless\- "<function> <value>"
 .br
 .br
-wireless_essid Home
+wireless\-essid Home
 .br
 .br
-wireless_mode ad_hoc
+wireless\-mode Ad\-Hoc
 .TP
 .B See also :
 .TP
 .B See also :
-.I /etc/network/if-pre-up.d/wireless-tool
+.I /etc/network/if\-pre\-up.d/wireless\-tools
 .br
 .br
-.I /usr/share/doc/wireless.##/README.Debian
+.I /usr/share/doc/wireless\-tools/README.Debian
 .\"
 .\" SuSE 8.0 part
 .\"
 .\"
 .\" SuSE 8.0 part
 .\"
@@ -70,14 +72,14 @@ network scripts.
 .B File :
 .I /etc/sysconfig/network/wireless
 .br
 .B File :
 .I /etc/sysconfig/network/wireless
 .br
-.I /etc/sysconfig/network/ifcfg-*
+.I /etc/sysconfig/network/ifcfg\-*
 .TP
 .B Form :
 .RI WIRELESS_ "<function>" = "<value>"
 .br
 WIRELESS_ESSID="Home"
 .br
 .TP
 .B Form :
 .RI WIRELESS_ "<function>" = "<value>"
 .br
 WIRELESS_ESSID="Home"
 .br
-WIRELESS_MODE=ad_hoc
+WIRELESS_MODE=Ad\-Hoc
 .TP
 .B See also :
 man ifup
 .TP
 .B See also :
 man ifup
@@ -96,9 +98,9 @@ package, you can use this method.
 .B Form :
 *,*,*,*)
 .br
 .B Form :
 *,*,*,*)
 .br
-    ESSID="MY_ESSID"
+    ESSID="Home"
 .br
 .br
-    MODE="Managed"
+    MODE="Ad-Hoc"
 .br
     ;;
 .TP
 .br
     ;;
 .TP
diff --git a/wireless_tools/wireless.h b/wireless_tools/wireless.h
deleted file mode 100644 (file)
index e69de29..0000000