• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

external/wireless-tools


Commit MetaInfo

Revisionc7b2e81e6d53daac413a19d5446ab68b8395c849 (tree)
Zeit2016-10-12 06:17:19
Autorchris-kirby <chris.kirby@hpe....>
Commiterchris-kirby

Log Message

v29

Ändern Zusammenfassung

Diff

--- /dev/null
+++ b/wireless_tools/19-udev-ifrename.rules
@@ -0,0 +1,13 @@
1+# udev rules to properly integrate ifrename.
2+# Renaming is done using /etc/iftab, with full ifrename functionality.
3+# Require udev version 107 or later.
4+# Please double check the path to ifrename, and make sure its available
5+# when udev runs (i.e. on boot partition).
6+
7+# Enable this rule to test with udevtest.
8+#ENV{UDEV_LOG}=="6", SUBSYSTEM=="net", ACTION=="add", IMPORT="/sbin/ifrename -D -V -u -i %k", NAME:="%k"
9+
10+# Main ifrename rule.
11+# If interface is found in /etc/iftab, subsequent rename rules are bypassed.
12+# If interface is not found in /etc/iftab, subsequent rename rules applies.
13+SUBSYSTEM=="net", ACTION=="add", IMPORT="/sbin/ifrename -u -i %k", NAME:="%k"
--- a/wireless_tools/CHANGELOG.h
+++ b/wireless_tools/CHANGELOG.h
@@ -1,7 +1,7 @@
11 /*
22 * Wireless Tools
33 *
4- * Jean II - HPLB 97->99 - HPL 99->04
4+ * Jean II - HPLB 97->99 - HPL 99->07
55 *
66 * The changelog...
77 *
@@ -625,6 +625,121 @@
625625 * o Add WE-20 headers, compile with that as default
626626 * ---
627627 * o Fix 'inline' for gcc-4 as well. Grrr... [iwlib]
628+ *
629+ * wireless 29 :
630+ * -----------
631+ * o Add new power value : 'power saving' [iwconfig/iwlist/iwlib]
632+ * o Optimise getting iwrange when setting TxPower [iwconfig]
633+ * o Optimise displaying current power values (better loop) [iwlist]
634+ * ---
635+ * o Add modulation bitmasks ioctls [iwconfig/iwlist]
636+ * o Add short and long retries [iwconfig/iwlist/iwlib]
637+ * o Fix 'relative' power saving to not be *1000 [iwconfig/iwlib]
638+ * o iw_print_pm_value() require we_version [iwlib]
639+ * o Optimise displaying range power values (subroutine) [iwlist]
640+ * ---
641+ * o Fix 'relative' retry to not be *1000 [iwconfig/iwlib]
642+ * o iw_print_retry_value() require we_version [iwlib]
643+ * o Optimise getting iwrange when setting PowerSaving [iwconfig]
644+ * o Optimise displaying current retry values (better loop) [iwlist]
645+ * o Optimise displaying range retry values (subroutine) [iwlist]
646+ * ---
647+ * o Fix stupid bug in displaying range retry values [iwlist]
648+ * ---
649+ * o Add support for unicast and broadcast bitrates [iwconfig/iwlist]
650+ * ---
651+ * o Replace spaghetti code with real dispatcher in set_info() [iwconfig]
652+ * Code is more readable, maintainable, and save 700 bytes...
653+ * o Drop 'domain' alias for 'nwid'. Obsolete. [iwconfig]
654+ * o Make iw_usage() use dispatcher data instead of hardcoded [iwconfig]
655+ * o Factor out modifier parsing for retry/power [iwconfig]
656+ * o Fix iwmulticall to compile with new dispatcher above [iwmulticall]
657+ * o Add WE_ESSENTIAL compile option to drop 10kB [Makefile]
658+ * ---
659+ * o Update manpages with new features above [man]
660+ * ---
661+ * o Add temp variable to sscanf() to fix 64 bits issues [iwconfig]
662+ * o De-inline get_pm_value/get_retry_value to reduce footprint [iwlist]
663+ * o Optimise iw_print_ie_cipher/iw_print_ie_auth [iwlist]
664+ * o Add "Memory footprint reduction" section in doc [README]
665+ * o Add 'last' scan option for left-over scan [iwlist]
666+ * (From Stavros Markou <smarkou@patras.atmel.com>)
667+ * o Add 'essid' scan option for directed scan [iwlist]
668+ * ---
669+ * (Bug reported by Henrik Brix Andersen <brix@gentoo.org>)
670+ * o Fix segfault on setting bitrate (parse wrong arg) [iwconfig]
671+ * ---
672+ * o Revert 'CC=gcc' to normal [Makefile]
673+ * o Integrate properly patch below [iwlist]
674+ * (From Brian Eaton <eaton.lists@gmail.com>)
675+ * o More WPA support : iwlist auth/wpakeys/genie [iwlist]
676+ * ---
677+ * o Tweak man pages : interface is often optional [iwlist.8/iwspy.8]
678+ * o Drop obsolete port/roam code from [iwpriv]
679+ * (From Pavel Roskin <proski@gnu.org>)
680+ * o Fix bug where all auth masks use iw_auth_capa_name [iwlist]
681+ * (From Dima Ryazanov <someone@berkeley.edu>)
682+ * o Fix iw_scan()/iw_process_scan() for non-root -> EPERM [iwlib]
683+ * (Bug reported by Arkadiusz Miskiewicz <arekm@pld-linux.org>)
684+ * o Fix "iwconfig nickname" (was abreviated) [iwconfig]
685+ * (Bug reported by Charles Plessy)
686+ * o Invalid mode from driver segfault iwlist scan [iwlist]
687+ * (From Aurelien Jacobs <aurel@gnuage.org>)
688+ * o Replace index() with strchr() [iwlib/iwconfig/iwpriv]
689+ * (From Jens Thoms Toerring)
690+ * o Parser/printf/sscanf fixes and optimisation [iwconfig]
691+ * ---
692+ * (From Pavel Roskin <proski@gnu.org>)
693+ * o Fix bug extracting mountpoint of sysfs (wrong field) [ifrename]
694+ * (Suggested by Pavel Roskin <proski@gnu.org>)
695+ * o Read sysfs symlinks transparently [ifrename]
696+ * ---
697+ * o Fix README header to talk about ifrename [README]
698+ * o Add 'prevname' selector for udev compatibility [ifrename]
699+ * o Read parent directory names in SYSFS selector [ifrename]
700+ * o Make dry-run output compatible with udev [ifrename]
701+ * o Update man page with useful SYSFS selectors [iftab.5]
702+ * ---
703+ * o Factorise wildcard rewrite '*'->'%d' to hide it from -D -V [ifrename]
704+ * o Reorganise sysfs description, better wording [iftab.5]
705+ * (Suggested by Pavel Roskin <proski@gnu.org>)
706+ * o Enhance explanation of arp and iwproto [iftab.5]
707+ * ---
708+ * (Bug reported by Johannes Berg <johannes@sipsolutions.net>)
709+ * o Band-aid for the 64->32bit iwevent/iwscan issues [iwlib]
710+ * ---
711+ * o Better band-aid for the 64->32bit iwevent/iwscan issues [iwlib]
712+ * (Suggested by Kay Sievers <kay.sievers@vrfy.org>)
713+ * o Add udev compatible output, print new DEVPATH [ifrename]
714+ * ---
715+ * o Fix DEVPATH output to use the real devpath from udev [ifrename]
716+ * o Add udev rules for ifrename integration [19-udev-ifrename.rules]
717+ * ---
718+ * o Add largest bitrate in easy scan API [iwlib]
719+ * ---
720+ * o Debug version : output IW_EV_LCP_LEN [iwlist]
721+ * ---
722+ * (Bug reported by Santiago Gala/Roy Marples)
723+ * o Fix 64->32bit band-aid on 64 bits, target is local aligned [iwlib]
724+ * ---
725+ * (Bug reported by Santiago Gala/Roy Marples)
726+ * o More fix to the 64->32bit band-aid on 64 bits [iwlib]
727+ * ---
728+ * (Bug reported by Dimitris Kogias)
729+ * o Fix GENIE parsing os chipher/key_mngt [iwlist]
730+ * (Bug reported by Guus Sliepen <guus@debian.org>)
731+ * o Compiler warning on DEBUG code [iwlist]
732+ * ---
733+ * o --version output WE_MAX_VERSION instead of WE_VERSION [iwlib]
734+ * o Change iwstats dBm range to [-192;63] in iw_print_stats() [iwlib.c]
735+ * o Implement iwstats IW_QUAL_RCPI in iw_print_stats() [iwlib.c]
736+ * (Bug reported by Guus Sliepen <guus@sliepen.eu.org>)
737+ * o LINUX_VERSION_CODE removed, only use GENERIC_HEADERS [iwlib.h]
738+ * (Bug reported by Johan Danielsson <joda11147@gmail.com>)
739+ * o Fix OUI type check for WPA 1 IE [iwlist.c]
740+ * ---
741+ * (Bug reported by Florent Daignière)
742+ * o Don't look for "fixed" out of array in set_txpower_info() [iwconfig]
628743 */
629744
630745 /* ----------------------------- TODO ----------------------------- */
@@ -635,10 +750,7 @@
635750 * --------
636751 * Make disable a per encryption key modifier if some hardware
637752 * requires it.
638- *
639- * iwpriv :
640- * ------
641- * Remove 'port' and 'roam' cruft now that we have mode in iwconfig
753+ * IW_QUAL_RCPI
642754 *
643755 * iwspy :
644756 * -----
--- a/wireless_tools/IFRENAME-VS-XXX.txt
+++ b/wireless_tools/IFRENAME-VS-XXX.txt
@@ -79,21 +79,21 @@ interfaces, with rules such as :
7979 http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
8080
8181 Advantages over 'ifrename' :
82- + integrated into 'udev'
8382 + simpler to setup if 'udev' is already properly setup
83+ + automatically generates persistent rules
8484 Drawbacks compared to 'ifrename' :
8585 - Less selectors that 'ifrename'
8686 - Require kernel 2.6.X or later with sysfs support
8787 - Do no support non-hotplug interfaces
8888 - Require 'udev', not everybody uses it (static /dev, devfs)
89- - Does not support module on-demand loading
9089 Comments :
9190 o 'udev' support many selectors, basically all those
92-present in 'sysfs', even if the documentation only show instructions
93-to use the MAC address (which is problematic with virtual devices some
94-drivers - see above). 'ifrename' can also use all selectors present in
95-'sysfs' (like 'udev'), plus some other selectors not present in sysfs
96-that were found to be useful.
91+present in 'sysfs' (excluding symlinks), even if the documentation
92+only show instructions to use the MAC address (which is problematic
93+with virtual devices some drivers - see above). 'ifrename' can also
94+use all selectors present in 'sysfs' (like 'udev'), can use sysfs
95+symlinks and parent directories, plus some other selectors not present
96+in sysfs that were found to be useful.
9797 o Not all interfaces are managed by hotplug. All
9898 virtual devices, such as tunnels and loopbacks, are not associated
9999 with a hardware bus, and therefore are not managed by hotplug. All
@@ -102,7 +102,9 @@ hotplug. 'udev' can't deal with those devices.
102102 o It is common practice on embedded system to use a
103103 static /dev and not 'udev' to save space and boot time. And to not use
104104 hotplug for the same reasons.
105- o 'ifrename' could be better integrated in 'udev', I don't foresee any technical issues.
105+ o 'ifrename' has now a udev compatiblity mode that
106+enables to trivially integrate it into 'udev' as an IMPORT rule. This
107+requires udev version 107 or better and ifrename 29-pre17 or better.
106108
107109 SELECTOR AWARE NETWORK SCRIPTS
108110 ------------------------------
--- a/wireless_tools/INSTALL
+++ b/wireless_tools/INSTALL
@@ -36,17 +36,87 @@ Create a local copy of the tools :
3636 --------------------------------
3737 By default, the package is built with iwlib as a dynamic
3838 library, and the tool will expect to use the default version of libiw
39-on the system.
39+on the system. This means you can't use the tools until they are
40+properly installed.
4041 If you just want to experiment with a "local" version of the
4142 tools, you may want to pass the BUILD_STATIC flag to Makefile. It will
4243 create a self contained version of the tools.
43--------------
44-make clean
45-make BUILD_STATIC='y'
46--------------
44+ -------------
45+ make clean
46+ make BUILD_STATIC='y'
47+ -------------
4748 The resulting binary can be used in the compilation directory
4849 or installed in any place you like.
4950
51+Other useful Makefile options :
52+-----------------------------
53+ PREFIX : where the tools will be installed (default : /usr/local)
54+ CC : Compiler to use (defaul : gcc)
55+ BUILD_STATIC : build tools with a static version of the wireless lib
56+ BUILD_NOLIBM : build tools without mathematical lib (slower)
57+ BUILD_STRIPPING : strip symbols from tools/lib.
58+ BUILD_WE_ESSENTIAL : remove less used and obsolete features.
59+
60+ You can pass those options on the command line of make, or
61+modify the top of the Makefile. You can also set them as environment
62+variable, but this is not recommended.
63+ If you pass those options on the command line, you should pass
64+the same command line options for all invocations of make ("make" and
65+"make install").
66+
67+Memory footprint reduction :
68+--------------------------
69+ The Wireless Tools are used in various embedded systems where
70+memory footprint is a great concern. The Wireless Tools package offer
71+multiple options to customise the compilation depending on the level
72+of features you want.
73+ The list below details the must useful combinations of these
74+options, from the largest footprint to the smallest. Footprint depend
75+on lot's of factor and is purely indicative (version 29-pre7+, i386,
76+glibc, gcc 3.3.5).
77+
78+ 1) Static build
79+ Command line : make BUILD_STATIC='y'
80+ - : Largest footprint
81+ - : libiw not included (other third party tools may depend on it)
82+ Size : ~280 kB
83+
84+ 2) Default build
85+ Command line : make
86+ + : Fully featured version of the tools
87+ - : Largest footprint (except for static version of tools)
88+ Size : ~190 kB (libiw : ~29 kB ; ifrename : ~29 kB)
89+
90+ 3) Stripping (remove function symbols)
91+ Command line : make BUILD_STRIPPING='y'
92+ + : Fully featured version of the tools
93+ - : Still quite large
94+ Size : ~110 kB (libiw : ~23 kB ; ifrename : ~17 kB)
95+
96+ 4) Multicall version (include stripping)
97+ Command line : make iwmulticall ; make install-iwmulticall
98+ + : Fully featured version of the tools
99+ + : Small
100+ - : libiw not included (other third party tools may depend on it)
101+ - : ifrename is not included
102+ Size : ~55 kB
103+
104+ 5) Multicall + Essential
105+ Command line : make BUILD_WE_ESSENTIAL='y' iwmulticall
106+ + : Smaller
107+ - : Some less used features are left out
108+ - : libiw not included (other third party tools may depend on it)
109+ - : ifrename is not included
110+ Size : ~44 kB
111+
112+ 6) iwconfig only + essential + static
113+ Command line : make BUILD_WE_ESSENTIAL='y' BUILD_STATIC='y' BUILD_STRIPPING='y' iwconfig
114+ + : Very small
115+ - : Very limited functionality : no scanning, no event, no iwpriv
116+ - : libiw not included (other third party tools may depend on it)
117+ - : ifrename is not included
118+ Size : ~28 kB
119+
50120 Wireless headers (past history) :
51121 -------------------------------
52122 Previous version of the Wireless Tools had to be compiled with
@@ -63,18 +133,6 @@ you that.
63133 Note that the previous option to make versioned installed of
64134 the tools no longer make sense and therefore is gone.
65135
66-Other useful Makefile options :
67------------------------------
68- PREFIX : where the tools will be installed (default : /usr/local)
69- BUILD_STATIC : build tools with a static version of the wireless lib
70- BUILD_NOLIBM : build tools without mathematical lib (slower)
71- Note that you should pass the same command line options for
72-all invocations of make ("make" and "make install").
73-
74- If you want the absolute minimal footprint, you may want to
75-look into the multicall version of the tools. You can build it with
76-"make iwmulticall" and install it with "make install-iwmulticall".
77-
78136 Old kernel with older Wireless Extensions :
79137 -----------------------------------------
80138 Kernel prior to 2.2.14 : Those kernels include Wireless
--- a/wireless_tools/Makefile
+++ b/wireless_tools/Makefile
@@ -2,31 +2,36 @@
22 ## Please check the configurion parameters below
33 ##
44
5-## Installation directory. By default, go in /usr/local
5+## Installation directory. By default, go in /usr/local.
66 ## Distributions should probably use /, but they probably know better...
77 ifndef PREFIX
88 PREFIX = /usr/local
99 endif
1010
11-## Compiler to use (modify this for cross compile)
11+## Compiler to use (modify this for cross compile).
1212 CC = gcc
13-## Other tools you need to modify for cross compile (static lib only)
13+## Other tools you need to modify for cross compile (static lib only).
1414 AR = ar
1515 RANLIB = ranlib
1616
17-## Uncomment this to build tools using static version of the library
17+## Uncomment this to build tools using static version of the library.
1818 ## Mostly useful for embedded platforms without ldd, or to create
1919 ## a local version (non-root).
2020 # BUILD_STATIC = y
2121
22-## Uncomment this to build without using libm (less efficient)
22+## Uncomment this to build without using libm (less efficient).
2323 ## This is mostly useful for embedded platforms without maths.
2424 # BUILD_NOLIBM = y
2525
26-## Uncomment this to strip binary from symbols. This reduce binary size
26+## Uncomment this to strip binary from symbols. This reduce binary size.
2727 ## by a few percent but make debug worse...
2828 # BUILD_STRIPPING = y
2929
30+## Uncomment this to build with only essential functionality.
31+## This leaves out the less used features and cut in half the tools.
32+## This is mostly useful for embedded platforms without limited feature needs.
33+# BUILD_WE_ESSENTIAL = y
34+
3035 # ***************************************************************************
3136 # ***** Most users should not need to change anything beyond this point *****
3237 # ***************************************************************************
@@ -91,12 +96,17 @@ else
9196 STRIPFLAGS=
9297 endif
9398
99+# Do we want to build with only essential functionality ?
100+ifdef BUILD_WE_ESSENTIAL
101+ WEDEF_FLAG= -DWE_ESSENTIAL=y
102+endif
103+
94104 # Other flags
95105 CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \
96106 -Wpointer-arith -Wcast-qual -Winline -I.
97107 #CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I.
98108 DEPFLAGS=-MMD
99-XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG)
109+XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG) $(WEDEF_FLAG)
100110 PICFLAG=-fPIC
101111
102112 # Standard compilation targets
--- a/wireless_tools/README
+++ b/wireless_tools/README
@@ -1,10 +1,12 @@
1- Wireless Tools
2- --------------
1+ Wireless Tools & IfRename
2+ -------------------------
33
44 This package contains the Wireless tools, used to manipulate
55 the Wireless Extensions. The Wireless Extensions is an interface
66 allowing you to set Wireless LAN specific parameters and get the
77 specific stats.
8+ It also contains the IfRename package, used for advance
9+renaming of network interfaces.
810
911 web page :
1012 --------
@@ -112,6 +114,10 @@ iwlib.c
112114 The Wireless Tools helper library. May be useful if you want
113115 to create your own applications using Wireless Extensions.
114116
117+iwmulticall.c
118+-------------
119+ Multicall version of the tools for embedded systems.
120+
115121 Changelog, contributions :
116122 ------------------------
117123 See CHANGELOG.h
@@ -136,6 +142,10 @@ more tricky features of Wireless Extensions in your driver.
136142 alone works, but it should point you in the proper direction.
137143 Also, have a look at existing drivers in the Linux kernel.
138144
145+19-udev-ifrename.rules :
146+----------------------
147+ udev rules to integrate properly ifrename (udev >= 107).
148+
139149 Other tools :
140150 -----------
141151 My web page lists many other tools using Wireless
--- a/wireless_tools/ifrename.8
+++ b/wireless_tools/ifrename.8
@@ -1,7 +1,7 @@
1-.\" Jean II - HPL - 2004
1+.\" Jean II - HPL - 2004-2007
22 .\" ifrename.8
33 .\"
4-.TH IFRENAME 8 "01 March 2004" "wireless-tools" "Linux Programmer's Manual"
4+.TH IFRENAME 8 "26 February 2007" "wireless-tools" "Linux Programmer's Manual"
55 .\"
66 .\" NAME part
77 .\"
@@ -11,7 +11,7 @@ ifrename \- rename network interfaces based on various static criteria
1111 .\" SYNOPSIS part
1212 .\"
1313 .SH SYNOPSIS
14-.B "ifrename [-c configfile] [-p] [-d] [-v] [-V] [-D]"
14+.B "ifrename [-c configfile] [-p] [-d] [-u] [-v] [-V] [-D]"
1515 .br
1616 .B "ifrename [-c configfile] [-i interface] [-n newname]"
1717 .\"
@@ -124,12 +124,38 @@ In any case, name swapping and the use of this feature is discouraged,
124124 and you are invited to choose unique and unambiguous names for your
125125 interfaces...
126126 .TP
127+.B -u
128+Enable
129+.I udev
130+output mode. This enables proper integration of
131+.B ifrename
132+in the
133+.I udev
134+framework,
135+.BR udevd (8)
136+will use
137+.B ifrename
138+to assign interface names present in
139+.IR /etc/iftab .
140+In this mode the output of ifrename can be parsed
141+directly by
142+.BR udevd (8)
143+as an IMPORT action. This requires
144+.I udev
145+version 107 or later.
146+.TP
127147 .B -D
128148 Dry-run mode. Ifrename won't change any interface, it will only print
129149 new interface name, if applicable, and return.
130150 .br
131151 In dry-run mode, interface name wildcards are not resolved. New
132152 interface name is printed, even if it is the same as the old name.
153+.br
154+Be also aware that some selectors can only be read by root, for
155+example those based on
156+.BR ethtool ),
157+and will fail silently if run by a normal user. In other words,
158+dry-run mode under a standard user may not give the expected result.
133159 .TP
134160 .B -V
135161 Verbose mode. Ifrename will display internal results of parsing its
--- a/wireless_tools/ifrename.c
+++ b/wireless_tools/ifrename.c
@@ -1,14 +1,14 @@
11 /*
22 * Wireless Tools
33 *
4- * Jean II - HPL 04
4+ * Jean II - HPL 04 -> 07
55 *
66 * Main code for "ifrename". This is tool allows to rename network
77 * interfaces based on various criteria (not only wireless).
88 * You need to link this code against "iwlib.c" and "-lm".
99 *
1010 * This file is released under the GPL license.
11- * Copyright (c) 2004 Jean Tourrilhes <jt@hpl.hp.com>
11+ * Copyright (c) 2007 Jean Tourrilhes <jt@hpl.hp.com>
1212 */
1313
1414 /*
@@ -30,7 +30,7 @@
3030 * Difference with standard 'nameif' :
3131 * o 'nameif' has only a single selector, the interface MAC address.
3232 * o Modular selector architecture, easily add new selectors.
33- * o Wide range of selector, including sysfs...
33+ * o Wide range of selector, including sysfs and sysfs symlinks...
3434 * o hotplug invocation support.
3535 * o module loading support.
3636 * o MAC address wildcard.
@@ -82,7 +82,8 @@ const int SELECT_INTERRUPT = 9; /* Select by HW Irq line */
8282 const int SELECT_IWPROTO = 10; /* Select by Wireless Protocol */
8383 const int SELECT_PCMCIASLOT = 11; /* Select by Pcmcia Slot */
8484 const int SELECT_SYSFS = 12; /* Select by sysfs file */
85-#define SELECT_NUM 13
85+const int SELECT_PREVNAME = 13; /* Select by previous interface name */
86+#define SELECT_NUM 14
8687
8788 #define HAS_MAC_EXACT 1
8889 #define HAS_MAC_FILTER 2
@@ -99,6 +100,7 @@ const struct option long_opt[] =
99100 {"interface", 1, NULL, 'i' },
100101 {"newname", 1, NULL, 'n' },
101102 {"takeover", 0, NULL, 't' },
103+ {"udev", 0, NULL, 'u' },
102104 {"version", 0, NULL, 'v' },
103105 {"verbose", 0, NULL, 'V' },
104106 {NULL, 0, NULL, '\0' },
@@ -108,8 +110,8 @@ const struct option long_opt[] =
108110 #define PCMCIA_STAB1 "/var/lib/pcmcia/stab"
109111 #define PCMCIA_STAB2 "/var/run/stab"
110112
111-/* Max number of sysfs file we support */
112-#define SYSFS_MAX_FILE 5
113+/* Max number of sysfs file types we support */
114+#define SYSFS_MAX_FILE 8
113115
114116 /* Userspace headers lag, fix that... */
115117 #ifndef ARPHRD_IEEE1394
@@ -160,6 +162,8 @@ typedef struct if_mapping
160162
161163 /* Name of this interface */
162164 char ifname[IFNAMSIZ+1];
165+ char * sysfs_devpath;
166+ int sysfs_devplen;
163167
164168 /* Selectors for this interface */
165169 int active[SELECT_NUM]; /* Selectors active */
@@ -177,6 +181,7 @@ typedef struct if_mapping
177181 char iwproto[IFNAMSIZ + 1]; /* Wireless/protocol name */
178182 int pcmcia_slot; /* Pcmcia slot */
179183 char * sysfs[SYSFS_MAX_FILE]; /* sysfs selectors */
184+ char prevname[IFNAMSIZ+1]; /* previous interface name */
180185 } if_mapping;
181186
182187 /* Extra parsing information when adding a mapping */
@@ -358,6 +363,21 @@ static int
358363 const char * ifname,
359364 struct if_mapping * target,
360365 int flag);
366+static int
367+ mapping_addprevname(struct if_mapping * ifnode,
368+ int * active,
369+ char * pos,
370+ size_t len,
371+ struct add_extra * extra,
372+ int linenum);
373+static int
374+ mapping_cmpprevname(struct if_mapping * ifnode,
375+ struct if_mapping * target);
376+static int
377+ mapping_getprevname(int skfd,
378+ const char * ifname,
379+ struct if_mapping * target,
380+ int flag);
361381
362382 /**************************** VARIABLES ****************************/
363383
@@ -390,6 +410,8 @@ const struct mapping_selector selector_list[] =
390410 { "pcmciaslot", &mapping_addpcmciaslot, &mapping_cmppcmciaslot, &mapping_getpcmciaslot },
391411 /* sysfs file (udev emulation) */
392412 { "sysfs", &mapping_addsysfs, &mapping_cmpsysfs, &mapping_getsysfs },
413+ /* previous interface name */
414+ { "prevname", &mapping_addprevname, &mapping_cmpprevname, &mapping_getprevname },
393415 /* The Terminator */
394416 { NULL, NULL, NULL, NULL },
395417 };
@@ -419,6 +441,9 @@ int dry_run = 0; /* Just print new name, don't rename */
419441 /* Verbose support (i.e. debugging) */
420442 int verbose = 0;
421443
444+/* udev output support (print new DEVPATH) */
445+int udev_output = 0;
446+
422447 /* sysfs global data */
423448 struct sysfs_metadata sysfs_global =
424449 {
@@ -449,8 +474,8 @@ if_match_ifname(const char * pattern,
449474 int n;
450475 int ret;
451476
452- /* Check for a wildcard (converted from '*' to '%d' in mapping_create()) */
453- p = strstr(pattern, "%d");
477+ /* Check for a wildcard */
478+ p = strchr(pattern, '*');
454479
455480 /* No wildcard, simple comparison */
456481 if(p == NULL)
@@ -473,7 +498,7 @@ if_match_ifname(const char * pattern,
473498 while(isdigit(*v));
474499
475500 /* Pattern suffix */
476- p += 2;
501+ p += 1;
477502
478503 /* Compare suffixes */
479504 return(strcmp(p, v));
@@ -539,6 +564,7 @@ if_set_name(int skfd,
539564 char * retname)
540565 {
541566 struct ifreq ifr;
567+ char * star;
542568 int ret;
543569
544570 /* The kernel doesn't check is the interface already has the correct
@@ -562,6 +588,22 @@ if_set_name(int skfd,
562588 strncpy(ifr.ifr_name, oldname, IFNAMSIZ);
563589 strncpy(ifr.ifr_newname, newname, IFNAMSIZ);
564590
591+ /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
592+ * This require specific kernel support (2.6.2-rc1 and later).
593+ * We externally use '*', but the kernel doesn't know about that,
594+ * so convert it to something it knows about... */
595+ star = strchr(newname, '*');
596+ if(star != NULL)
597+ {
598+ int slen = star - newname;
599+ /* Replace '*' with '%d' in the new buffer */
600+ star = ifr.ifr_newname + slen;
601+ /* Size was checked in process_rename() and mapping_create() */
602+ memmove(star + 2, star + 1, IFNAMSIZ - slen - 2);
603+ star[0] = '%';
604+ star[1] = 'd';
605+ }
606+
565607 /* Do it */
566608 ret = ioctl(skfd, SIOCSIFNAME, &ifr);
567609
@@ -613,7 +655,7 @@ mapping_addmac(struct if_mapping * ifnode,
613655 /* Verify validity of string */
614656 if(len >= sizeof(ifnode->mac_filter))
615657 {
616- fprintf(stderr, "MAC address too long at line %d\n", linenum);
658+ fprintf(stderr, "Error : MAC address too long at line %d\n", linenum);
617659 return(-1);
618660 }
619661 n = strspn(string, "0123456789ABCDEFabcdef:*");
@@ -1544,6 +1586,8 @@ mapping_getsysfs(int skfd,
15441586 int flag)
15451587 {
15461588 FILE * stream;
1589+ char * fname;
1590+ int fnsize;
15471591 char * linebuf = NULL;
15481592 size_t linelen = 0;
15491593 char * sdup;
@@ -1553,83 +1597,116 @@ mapping_getsysfs(int skfd,
15531597 skfd = skfd;
15541598 flag = flag;
15551599
1556- /* Check if we know the root of the sysfs filesystem */
1557- if(sysfs_global.root == NULL)
1600+ /* Check if we know the devpath of this device */
1601+ if(target->sysfs_devpath == NULL)
15581602 {
1559- /* Open the mount file for reading */
1560- stream = fopen("/proc/mounts", "r");
1561- if(!stream)
1562- {
1563- fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n",
1564- strerror(errno));
1565- return(-1);
1566- }
1567-
1568- /* Read each line of file
1569- * getline is a GNU extension :-( The buffer is recycled and increased
1570- * as needed by getline. */
1571- while(getline(&linebuf, &linelen, stream) > 0)
1603+ /* Check if we know the root of the sysfs filesystem */
1604+ if(sysfs_global.root == NULL)
15721605 {
1573- char * p;
1574- size_t n;
1606+ /* Open the mount file for reading */
1607+ stream = fopen("/proc/mounts", "r");
1608+ if(!stream)
1609+ {
1610+ fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n",
1611+ strerror(errno));
1612+ return(-1);
1613+ }
15751614
1576- /* Get the line starting with sysfs */
1577- p = linebuf;
1578- while(isspace(*p))
1579- ++p;
1580- if(!strncasecmp(p, "sysfs ", 6))
1615+ /* Read each line of file
1616+ * getline is a GNU extension :-( The buffer is recycled and
1617+ * increased as needed by getline. */
1618+ while(getline(&linebuf, &linelen, stream) > 0)
15811619 {
1582- /* Find the mount point */
1583- p += 6;
1584- while(isspace(*p))
1585- ++p;
1586- n = strcspn(p, " \t\n");
1587- sdup = strndup(p, n);
1588- if((n == 0) || (sdup == NULL))
1620+ int i;
1621+ char * p;
1622+ size_t n;
1623+ char * token[3];
1624+ size_t toklen[3];
1625+
1626+ /* The format of /proc/mounts is similar to /etc/fstab (5).
1627+ * The first argument is the device. For sysfs, there is no
1628+ * associated device, so this argument is ignored.
1629+ * The second argument is the mount point.
1630+ * The third argument is the filesystem type.
1631+ */
1632+
1633+ /* Extract the first 3 tokens */
1634+ p = linebuf;
1635+ for(i = 0; i < 3; i++)
15891636 {
1590- fprintf(stderr, "Error: Can't parse /proc/mounts file: %s\n",
1591- strerror(errno));
1592- return(-1);
1637+ while(isspace(*p))
1638+ ++p;
1639+ token[i] = p;
1640+ n = strcspn(p, " \t\n");
1641+ toklen[i] = n;
1642+ p += n;
15931643 }
1594- /* Store it */
1595- sysfs_global.root = sdup;
1596- sysfs_global.rlen = n;
1597- break;
1644+ /* Get the filesystem which type is "sysfs" */
1645+ if((n == 5) && (!strncasecmp(token[2], "sysfs", 5)))
1646+ {
1647+ /* Get its mount point */
1648+ n = toklen[1];
1649+ sdup = strndup(token[1], n);
1650+ if((n == 0) || (sdup == NULL))
1651+ {
1652+ fprintf(stderr,
1653+ "Error: Can't parse /proc/mounts file: %s\n",
1654+ strerror(errno));
1655+ return(-1);
1656+ }
1657+ /* Store it */
1658+ sysfs_global.root = sdup;
1659+ sysfs_global.rlen = n;
1660+ break;
1661+ }
1662+ /* Finished -> next line */
15981663 }
1599- /* Finished -> next line */
1600- }
16011664
1602- /* Cleanup */
1603- fclose(stream);
1665+ /* Cleanup */
1666+ fclose(stream);
16041667
1605- /* Check if we found it */
1606- if(sysfs_global.root == NULL)
1668+ /* Check if we found it */
1669+ if(sysfs_global.root == NULL)
1670+ {
1671+ fprintf(stderr,
1672+ "Error: Can't find sysfs in /proc/mounts file\n");
1673+ free(linebuf);
1674+ return(-1);
1675+ }
1676+ }
1677+
1678+ /* Construct devpath for this interface.
1679+ * Reserve enough space to replace name without realloc. */
1680+ fnsize = (sysfs_global.rlen + 11 + IFNAMSIZ + 1);
1681+ fname = malloc(fnsize);
1682+ if(fname == NULL)
16071683 {
1608- fprintf(stderr, "Error: Can't find sysfs in /proc/mounts file\n");
1609- free(linebuf);
1684+ fprintf(stderr, "Error: Can't allocate SYSFS devpath\n");
16101685 return(-1);
16111686 }
1687+ /* Not true devpath for 2.6.20+, but this syslink should work */
1688+ target->sysfs_devplen = sprintf(fname, "%s/class/net/%s",
1689+ sysfs_global.root, ifname);
1690+ target->sysfs_devpath = fname;
16121691 }
16131692
16141693 /* Loop on all sysfs selector */
16151694 for(findex = 0; findex < sysfs_global.filenum; findex++)
16161695 {
1617- char * fname;
1618- int flen;
16191696 char * p;
16201697 ssize_t n;
16211698
16221699 /* Construct complete filename for the sysfs selector */
1623- flen = (sysfs_global.rlen + 11 + strlen(ifname) + 1 +
1624- strlen(sysfs_global.filename[findex]) + 1);
1625- fname = malloc(flen);
1700+ fnsize = (target->sysfs_devplen + 1 +
1701+ strlen(sysfs_global.filename[findex]) + 1);
1702+ fname = malloc(fnsize);
16261703 if(fname == NULL)
16271704 {
16281705 fprintf(stderr, "Error: Can't allocate SYSFS filename\n");
16291706 free(linebuf);
16301707 return(-1);
16311708 }
1632- sprintf(fname, "%s/class/net/%s/%s", sysfs_global.root, ifname,
1709+ sprintf(fname, "%s/%s", target->sysfs_devpath,
16331710 sysfs_global.filename[findex]);
16341711
16351712 /* Open the sysfs file for reading */
@@ -1649,18 +1726,103 @@ mapping_getsysfs(int skfd,
16491726 fclose(stream);
16501727 if(n <= 0)
16511728 {
1652- /* Some sysfs attribute are void for some interface */
1653- if(verbose)
1654- fprintf(stderr, "Error: Can't read file `%s'\n", fname);
1655- /* Next sysfs selector */
1656- continue;
1657- }
1729+ /* Some attributes are just symlinks to another directory.
1730+ * We can read the attributes in that other directory
1731+ * just fine, but sometimes the symlink itself gives a lot
1732+ * of information.
1733+ * Examples : SYSFS{device} and SYSFS{device/driver}
1734+ * In such cases, get the name of the directory pointed to...
1735+ */
1736+ /*
1737+ * I must note that the API for readlink() is very bad,
1738+ * which force us to have this ugly code. Yuck !
1739+ */
1740+ int allocsize = 128; /* 256 = Good start */
1741+ int retry = 16;
1742+ char * linkpath = NULL;
1743+ int pathlen;
16581744
1659- /* Get content, remove trailing '/n', save it */
1660- p = linebuf;
1661- if(p[n - 1] == '\n')
1662- n--;
1663- sdup = strndup(p, n);
1745+ /* Try reading the link with increased buffer size */
1746+ do
1747+ {
1748+ allocsize *= 2;
1749+ linkpath = realloc(linkpath, allocsize);
1750+ pathlen = readlink(fname, linkpath, allocsize);
1751+ /* If we did not hit the buffer limit, success */
1752+ if(pathlen < allocsize)
1753+ break;
1754+ }
1755+ while(retry-- > 0);
1756+
1757+ /* Check for error, most likely ENOENT */
1758+ if(pathlen > 0)
1759+ /* We have a symlink ;-) Terminate the string. */
1760+ linkpath[pathlen] = '\0';
1761+ else
1762+ {
1763+ /* Error ! */
1764+ free(linkpath);
1765+
1766+ /* A lot of information in the sysfs is implicit, given
1767+ * by the position of a file in the tree. It is therefore
1768+ * important to be able to read the various components
1769+ * of a path. For this reason, we resolve '..' to the
1770+ * real name of the parent directory... */
1771+ /* We have at least 11 char, see above */
1772+ if(!strcmp(fname + fnsize - 4, "/.."))
1773+ //if(!strcmp(fname + strlen(fname) - 3, "/.."))
1774+ {
1775+ /* This procedure to get the realpath is not very
1776+ * nice, but it's the "best practice". Hmm... */
1777+ int cwd_fd = open(".", O_RDONLY);
1778+ linkpath = NULL;
1779+ if(cwd_fd > 0)
1780+ {
1781+ int ret = chdir(fname);
1782+ if(ret == 0)
1783+ /* Using getcwd with NULL is a GNU extension. Nice. */
1784+ linkpath = getcwd(NULL, 0);
1785+ /* This may fail, but it's not fatal */
1786+ fchdir(cwd_fd);
1787+ }
1788+ /* Check if we suceeded */
1789+ if(!linkpath)
1790+ {
1791+ free(linkpath);
1792+ if(verbose)
1793+ fprintf(stderr, "Error: Can't read parent directory `%s'\n", fname);
1794+ /* Next sysfs selector */
1795+ continue;
1796+ }
1797+ }
1798+ else
1799+ {
1800+ /* Some sysfs attribute are void for some interface,
1801+ * we may have a real directory, or we may have permission
1802+ * issues... */
1803+ if(verbose)
1804+ fprintf(stderr, "Error: Can't read file `%s'\n", fname);
1805+ /* Next sysfs selector */
1806+ continue;
1807+ }
1808+ }
1809+
1810+ /* Here, we have a link name or a parent directory name */
1811+
1812+ /* Keep only the last component of path name, save it */
1813+ p = basename(linkpath);
1814+ sdup = strdup(p);
1815+ free(linkpath);
1816+ }
1817+ else
1818+ {
1819+ /* This is a regular file (well, pseudo file) */
1820+ /* Get content, remove trailing '/n', save it */
1821+ p = linebuf;
1822+ if(p[n - 1] == '\n')
1823+ n--;
1824+ sdup = strndup(p, n);
1825+ }
16641826 if(sdup == NULL)
16651827 {
16661828 fprintf(stderr, "Error: Can't allocate SYSFS value\n");
@@ -1686,6 +1848,77 @@ mapping_getsysfs(int skfd,
16861848 return(target->active[SELECT_SYSFS] ? 0 : -1);
16871849 }
16881850
1851+/*------------------------------------------------------------------*/
1852+/*
1853+ * Add a Previous Interface Name selector to a mapping
1854+ */
1855+static int
1856+mapping_addprevname(struct if_mapping * ifnode,
1857+ int * active,
1858+ char * string,
1859+ size_t len,
1860+ struct add_extra * extra,
1861+ int linenum)
1862+{
1863+ /* Avoid "Unused parameter" warning */
1864+ extra = extra;
1865+
1866+ /* Verify validity of string */
1867+ if(len >= sizeof(ifnode->prevname))
1868+ {
1869+ fprintf(stderr, "Old Interface Name too long at line %d\n", linenum);
1870+ return(-1);
1871+ }
1872+
1873+ /* Copy */
1874+ memcpy(ifnode->prevname, string, len + 1);
1875+
1876+ /* Activate */
1877+ ifnode->active[SELECT_PREVNAME] = 1;
1878+ active[SELECT_PREVNAME] = 1;
1879+
1880+ if(verbose)
1881+ fprintf(stderr,
1882+ "Parsing : Added Old Interface Name `%s' from line %d.\n",
1883+ ifnode->prevname, linenum);
1884+
1885+ return(0);
1886+}
1887+
1888+/*------------------------------------------------------------------*/
1889+/*
1890+ * Compare the Previous Interface Name of two mappings
1891+ * Note : this one is special.
1892+ */
1893+static int
1894+mapping_cmpprevname(struct if_mapping * ifnode,
1895+ struct if_mapping * target)
1896+{
1897+ /* Do wildcard matching, case insensitive */
1898+ return(fnmatch(ifnode->prevname, target->ifname, FNM_CASEFOLD));
1899+}
1900+
1901+/*------------------------------------------------------------------*/
1902+/*
1903+ * Extract the Previous Interface Name from a live interface
1904+ */
1905+static int
1906+mapping_getprevname(int skfd,
1907+ const char * ifname,
1908+ struct if_mapping * target,
1909+ int flag)
1910+{
1911+ /* Avoid "Unused parameter" warning */
1912+ skfd = skfd; ifname = ifname; flag = flag;
1913+
1914+ /* Don't do anything, it's already in target->ifname ;-) */
1915+
1916+ /* Activate */
1917+ target->active[SELECT_PREVNAME] = 1;
1918+
1919+ return(0);
1920+}
1921+
16891922
16901923 /*********************** MAPPING MANAGEMENTS ***********************/
16911924 /*
@@ -1706,8 +1939,10 @@ mapping_create(char * pos,
17061939 struct if_mapping * ifnode;
17071940 char * star;
17081941
1709- /* Check overflow. */
1710- if(len > IFNAMSIZ)
1942+ star = memchr(pos, '*', len);
1943+
1944+ /* Check overflow, need one extra char for wildcard */
1945+ if((len + (star != NULL)) > IFNAMSIZ)
17111946 {
17121947 fprintf(stderr, "Error: Interface name `%.*s' too long at line %d\n",
17131948 (int) len, pos, linenum);
@@ -1738,29 +1973,6 @@ mapping_create(char * pos,
17381973 fprintf(stderr, "Warning: Alias device `%s' at line %d probably can't be mapped.\n",
17391974 ifnode->ifname, linenum);
17401975
1741- /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
1742- * This require specific kernel support (2.6.2-rc1 and later).
1743- * We externally use '*', but the kernel doesn't know about that,
1744- * so convert it to something it knows about... */
1745- star = strchr(ifnode->ifname, '*');
1746- if(star != NULL)
1747- {
1748- /* We need an extra char */
1749- if(len >= IFNAMSIZ)
1750- {
1751- fprintf(stderr,
1752- "Error: Interface wildcard `%s' too long at line %d\n",
1753- ifnode->ifname, linenum);
1754- free(ifnode);
1755- return(NULL);
1756- }
1757-
1758- /* Replace '*' with '%d' */
1759- memmove(star + 2, star + 1, len + 1 - (star - ifnode->ifname));
1760- star[0] = '%';
1761- star[1] = 'd';
1762- }
1763-
17641976 if(verbose)
17651977 fprintf(stderr, "Parsing : Added Mapping `%s' from line %d.\n",
17661978 ifnode->ifname, linenum);
@@ -2215,37 +2427,23 @@ probe_debian(int skfd)
22152427 static int
22162428 process_rename(int skfd,
22172429 char * ifname,
2218- char * pattern)
2430+ char * newname)
22192431 {
2220- char newname[IFNAMSIZ+1];
22212432 char retname[IFNAMSIZ+1];
22222433 int len;
22232434 char * star;
22242435
2225- len = strlen(pattern);
2226- star = strchr(pattern, '*');
2436+ len = strlen(newname);
2437+ star = strchr(newname, '*');
22272438
22282439 /* Check newname length, need one extra char for wildcard */
22292440 if((len + (star != NULL)) > IFNAMSIZ)
22302441 {
22312442 fprintf(stderr, "Error: Interface name `%s' too long.\n",
2232- pattern);
2443+ newname);
22332444 return(-1);
22342445 }
22352446
2236- /* Copy to local buffer */
2237- memcpy(newname, pattern, len + 1);
2238-
2239- /* Convert wildcard to the proper format */
2240- if(star != NULL)
2241- {
2242- /* Replace '*' with '%d' in the new buffer */
2243- star += newname - pattern;
2244- memmove(star + 2, star + 1, len + 1 - (star - newname));
2245- star[0] = '%';
2246- star[1] = 'd';
2247- }
2248-
22492447 /* Change the name of the interface */
22502448 if(if_set_name(skfd, ifname, newname, retname) < 0)
22512449 {
@@ -2285,6 +2483,24 @@ process_ifname(int skfd,
22852483 if(target == NULL)
22862484 return(-1);
22872485
2486+ /* If udev is calling us, get the real devpath. */
2487+ if(udev_output)
2488+ {
2489+ const char *env;
2490+ /* It's passed to us as an environment variable */
2491+ env = getenv("DEVPATH");
2492+ if(env)
2493+ {
2494+ int env_len = strlen(env);
2495+ target->sysfs_devplen = env_len;
2496+ /* Make enough space for new interface name */
2497+ target->sysfs_devpath = malloc(env_len + IFNAMSIZ + 1);
2498+ if(target->sysfs_devpath != NULL)
2499+ memcpy(target->sysfs_devpath, env, env_len + 1);
2500+ }
2501+ /* We will get a second chance is the user has some sysfs selectors */
2502+ }
2503+
22882504 /* Find matching mapping */
22892505 mapping = mapping_find(target);
22902506 if(mapping == NULL)
@@ -2300,26 +2516,47 @@ process_ifname(int skfd,
23002516 * That would be tricky to do... */
23012517 if(dry_run)
23022518 {
2303- printf("Dry-run : Would rename %s to %s.\n",
2304- target->ifname, mapping->ifname);
2305- return(0);
2519+ strcpy(retname, mapping->ifname);
2520+ fprintf(stderr, "Dry-run : Would rename %s to %s.\n",
2521+ target->ifname, mapping->ifname);
23062522 }
2307-
2308- /* Change the name of the interface */
2309- if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
2523+ else
23102524 {
2311- fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
2312- target->ifname, mapping->ifname, strerror(errno));
2313- return(-1);
2525+ /* Change the name of the interface */
2526+ if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
2527+ {
2528+ fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
2529+ target->ifname, mapping->ifname, strerror(errno));
2530+ return(-1);
2531+ }
23142532 }
23152533
23162534 /* Check if called with an explicit interface name */
23172535 if(print_newname)
23182536 {
2319- /* Always print out the *new* interface name so that
2320- * the calling script can pick it up and know where its interface
2321- * has gone. */
2322- printf("%s\n", retname);
2537+ if(!udev_output)
2538+ /* Always print out the *new* interface name so that
2539+ * the calling script can pick it up and know where its interface
2540+ * has gone. */
2541+ printf("%s\n", retname);
2542+ else
2543+ /* udev likes to call us as an IMPORT action. This means that
2544+ * we need to return udev the environment variables changed.
2545+ * Obviously, we don't want to return anything is nothing changed. */
2546+ if(strcmp(target->ifname, retname))
2547+ {
2548+ char * pos;
2549+ /* Hack */
2550+ if(!target->sysfs_devpath)
2551+ mapping_getsysfs(skfd, ifname, target, 0);
2552+ /* Update devpath. Size is large enough. */
2553+ pos = strrchr(target->sysfs_devpath, '/');
2554+ if((pos != NULL) && (!strcmp(target->ifname, pos + 1)))
2555+ strcpy(pos + 1, retname);
2556+ /* Return new environment variables */
2557+ printf("DEVPATH=%s\nINTERFACE=%s\nINTERFACE_OLD=%s\n",
2558+ target->sysfs_devpath, retname, target->ifname);
2559+ }
23232560 }
23242561
23252562 /* Done */
@@ -2387,7 +2624,7 @@ main(int argc,
23872624 /* Loop over all command line options */
23882625 while(1)
23892626 {
2390- int c = getopt_long(argc, argv, "c:dDi:n:ptvV", long_opt, NULL);
2627+ int c = getopt_long(argc, argv, "c:dDi:n:ptuvV", long_opt, NULL);
23912628 if(c == -1)
23922629 break;
23932630
@@ -2417,6 +2654,9 @@ main(int argc,
24172654 case 't':
24182655 force_takeover = 1;
24192656 break;
2657+ case 'u':
2658+ udev_output = 1;
2659+ break;
24202660 case 'v':
24212661 printf("%-8.16s Wireless-Tools version %d\n", "ifrename", WT_VERSION);
24222662 return(0);
@@ -2449,7 +2689,8 @@ main(int argc,
24492689 else
24502690 {
24512691 /* Rename only this interface based on mappings
2452- * Mostly used for HotPlug processing (from /etc/hotplug/net.agent).
2692+ * Mostly used for HotPlug processing (from /etc/hotplug/net.agent)
2693+ * or udev processing (from a udev IMPORT rule).
24532694 * Process the network interface specified on the command line,
24542695 * and return the new name on stdout.
24552696 */
--- a/wireless_tools/iftab.5
+++ b/wireless_tools/iftab.5
@@ -1,7 +1,7 @@
1-.\" Jean II - HPL - 2004
1+.\" Jean II - HPL - 2004-2007
22 .\" iftab.5
33 .\"
4-.TH IFTAB 5 "01 March 2004" "wireless-tools" "Linux Programmer's Manual"
4+.TH IFTAB 5 "26 February 2007" "wireless-tools" "Linux Programmer's Manual"
55 .\"
66 .\" NAME part
77 .\"
@@ -98,7 +98,9 @@ the goal is to uniquely identify each piece of hardware.
9898 .PP
9999 Most users will only use the
100100 .B mac
101-selector, other selectors are for more specialised setup.
101+selector despite its potential problems, other selectors are for more
102+specialised setup. Most selectors accept a '*' in the selector value
103+for wilcard matching, and most selectors are case insensitive.
102104 .TP
103105 .BI mac " mac address"
104106 Matches the MAC Address of the interface with the specified MAC
@@ -106,19 +108,27 @@ address. The MAC address of the interface can be shown using
106108 .IR ifconfig (8)
107109 or
108110 .IR ip (8).
109-The specified MAC address may contain a '*' for wilcard matching.
110111 .br
111112 This is the most common selector, as most interfaces have a unique MAC
112113 address allowing to identify network interfaces without ambiguity.
113114 However, some interfaces don't have a valid MAC address until they are
114-brought up, in such case using this selector is tricky.
115+brought up, in such case using this selector is tricky or impossible.
115116 .TP
116117 .BI arp " arp type"
117118 Matches the ARP Type (also called Link Type) of the interface with the
118-specified ARP type. The ARP Type of the interface can be shown using
119+specified ARP type as a number. The ARP Type of the interface can be
120+shown using
119121 .IR ifconfig (8)
120122 or
121-.IR ip (8).
123+.IR ip (8),
124+the
125+.B link/ether
126+type correspond to
127+.B 1
128+and the
129+.B link/ieee802.11
130+type correspond to
131+.BR 801 .
122132 .br
123133 This selector is useful when a driver create multiple network
124134 interfaces for a single network card.
@@ -159,7 +169,9 @@ not sufficient to uniquely identify an interface.
159169 Matches the Wireless Protocol of the interface with the specified
160170 wireless protocol. The Wireless Protocol of the interface can be shown
161171 using
162-.IR iwconfig (8).
172+.IR iwconfig (8)
173+or
174+.IR iwgetid (8).
163175 .br
164176 This selector is only supported on wireless interfaces and is not
165177 sufficient to uniquely identify an interface.
@@ -174,21 +186,97 @@ This selector is usually only supported on 16 bits cards, for 32 bits
174186 cards it is advised to use the selector
175187 .BR businfo .
176188 .TP
189+.BI prevname " previous interface name"
190+Matches the name of the interface prior to renaming with the specified
191+oldname.
192+.br
193+This selector should be avoided as the previous interface name may
194+vary depending on various condition. A system/kernel/driver update may
195+change the original name. Then, ifrename or another tool may rename it
196+prior to the execution of this selector.
197+.TP
177198 .BI SYSFS{ filename } " value"
178-Matches the sysfs attribute given by filename to the specified value. sysfs attributes of the interface can be read in one of the directory in the directory
179-.IR /sys/class/net/ .
180-For example, the filename
181-.I address
182-is the MAC address of the device and should be identical to the selector
183-.BR mac .
199+Matches the content the sysfs attribute given by filename to the
200+specified value. For symlinks and parents directories, match the
201+actual directory name of the sysfs attribute given by filename to the
202+specified value.
184203 .br
204+A list of the most useful sysfs attributes is given in the next
205+section.
206+.\"
207+.\" SYSFS DESCRIPTORS part
208+.\"
209+.SH SYSFS DESCRIPTORS
210+Sysfs attributes for a specific interface are located on most systems
211+in the directory named after that interface at
212+.IR /sys/class/net/ .
213+Most sysfs attribute are files, and their values can be read using
214+.IR cat "(1) or " more (1).
215+It is also possible to match attributes in subdirectories.
216+.PP
217+Some sysfs attributes are symlinks, pointing to another directory in
218+sysfs. If the attribute filename is a symlink the sysfs attribute
219+resolves to the name of the directory pointed by the symlink using
220+.IR readlink (1).
221+The location is a directory in the sysfs tree is also important. If
222+the attribute filename ends with
223+.IR /.. ,
224+the sysfs attribute resolves to the real name of the parent directory
225+using
226+.IR pwd (1).
227+.PP
185228 The sysfs filesystem is only supported with 2.6.X kernel and need to
186-be mounted. sysfs selectors are not as efficient as other selectors,
187-therefore they should be avoided for maximum performance.
229+be mounted (usually in
230+.IR /sys ).
231+sysfs selectors are not as efficient as other selectors, therefore
232+they should be avoided for maximum performance.
233+.PP
234+These are common sysfs attributes and their corresponding ifrename
235+descriptors.
236+.TP
237+.BI SYSFS{address} " value"
238+Same as the
239+.B mac
240+descriptor.
241+.TP
242+.BI SYSFS{type} " value"
243+Same as the
244+.B arp
245+descriptor.
246+.TP
247+.BI SYSFS{device} " value"
248+Valid only up to kernel 2.6.20. Same as the
249+.B businfo
250+descriptor.
251+.TP
252+.BI SYSFS{..} " value"
253+Valid only from kernel 2.6.21. Same as the
254+.B businfo
255+descriptor.
256+.TP
257+.BI SYSFS{device/driver} " value"
258+Valid only up to kernel 2.6.20. Same as the
259+.B driver
260+descriptor.
261+.TP
262+.BI SYSFS{../driver} " value"
263+Valid only from kernel 2.6.21. Same as the
264+.B driver
265+descriptor.
266+.TP
267+.BI SYSFS{device/irq} " value"
268+Valid only up to kernel 2.6.20. Same as the
269+.B irq
270+descriptor.
271+.TP
272+.BI SYSFS{../irq} " value"
273+Valid only from kernel 2.6.21. Same as the
274+.B irq
275+descriptor.
188276 .\"
189-.\" EXAMPLE part
277+.\" EXAMPLES part
190278 .\"
191-.SH EXAMPLE
279+.SH EXAMPLES
192280 # This is a comment
193281 .br
194282 eth2 mac 08:00:09:DE:82:0E
@@ -199,7 +287,11 @@ eth4 driver pcnet32 businfo 0000:02:05.0
199287 .br
200288 air* mac 00:07:0E:* arp 1
201289 .br
202-myvpn SYSFS{address} 00:10:83:*
290+myvpn SYSFS{address} 00:10:83:* SYSFS{type} 1
291+.br
292+bcm* SYSFS{device} 0000:03:00.0 SYSFS{device/driver} bcm43xx
293+.br
294+bcm* SYSFS{..} 0000:03:00.0 SYSFS{../driver} bcm43xx
203295 .\"
204296 .\" AUTHOR part
205297 .\"
--- a/wireless_tools/iwconfig.8
+++ b/wireless_tools/iwconfig.8
@@ -1,7 +1,7 @@
11 .\" Jean II - HPLB - 1996 => HPL - 2004
22 .\" iwconfig.8
33 .\"
4-.TH IWCONFIG 8 "09 March 2006" "wireless-tools" "Linux Programmer's Manual"
4+.TH IWCONFIG 8 "30 March 2006" "wireless-tools" "Linux Programmer's Manual"
55 .\"
66 .\" NAME part
77 .\"
@@ -21,7 +21,7 @@ iwconfig \- configure a wireless network interface
2121 .br
2222 .BI " [enc " E "] [key " K "] [power " P "] [retry " R ]
2323 .br
24-.BI " [commit]
24+.BI " [modu " M "] [commit]
2525 .br
2626 .BI "iwconfig --help"
2727 .br
@@ -78,11 +78,10 @@ to escape it.
7878 .br
7979 .I " iwconfig eth0 essid -- ""ANY""
8080 .TP
81-.BR nwid / domain
82-Set the Network ID (in some products it may also be called Domain
83-ID). As all adjacent wireless networks share the same medium, this
84-parameter is used to differenciate them (create logical colocated
85-networks) and identify nodes belonging to the same cell.
81+.BR nwid
82+Set the Network ID. As all adjacent wireless networks share the same
83+medium, this parameter is used to differentiate them (create logical
84+colocated networks) and identify nodes belonging to the same cell.
8685 .br
8786 This parameter is only used for pre-802.11 hardware, the 802.11
8887 protocol uses the ESSID and AP Address for this function.
@@ -285,14 +284,15 @@ behaviour of the retry mechanism.
285284 .br
286285 To set the maximum number of retries, enter
287286 .IR "limit `value'" .
288-This is an absolute value (without unit).
287+This is an absolute value (without unit), and the default (when
288+nothing is specified).
289289 To set the maximum length of time the MAC should retry, enter
290290 .IR "lifetime `value'" .
291291 By defaults, this value in in seconds, append the suffix m or u to
292292 specify values in milliseconds or microseconds.
293293 .br
294294 You can also add the
295-.IR min " and " max
295+.IR short ", " long ", " min " and " max
296296 modifiers. If the card supports automatic mode, they define the bounds
297297 of the limit or lifetime. Some other cards define different values
298298 depending on packet size, for example in 802.11
@@ -305,6 +305,8 @@ is the short retry limit (non RTS/CTS packets).
305305 .br
306306 .I " iwconfig eth0 retry lifetime 300m"
307307 .br
308+.I " iwconfig eth0 retry short 12"
309+.br
308310 .I " iwconfig eth0 retry min limit 8"
309311 .TP
310312 .BR rts [_threshold]
@@ -406,12 +408,14 @@ To set the period between wake ups, enter
406408 .IR "period `value'" .
407409 To set the timeout before going back to sleep, enter
408410 .IR "timeout `value'" .
411+To set the generic level of power saving, enter
412+.IR "saving `value'" .
409413 You can also add the
410414 .IR min " and " max
411415 modifiers. By default, those values are in seconds, append the suffix
412416 m or u to specify values in milliseconds or microseconds. Sometimes,
413-those values are without units (number of beacon periods, dwell or
414-similar).
417+those values are without units (number of beacon periods, dwell,
418+percentage or similar).
415419 .br
416420 .IR off " and " on
417421 disable and reenable power management. Finally, you may set the power
@@ -431,15 +435,43 @@ management mode to
431435 .br
432436 .I " iwconfig eth0 power timeout 300u all"
433437 .br
438+.I " iwconfig eth0 power saving 3"
439+.br
434440 .I " iwconfig eth0 power off"
435441 .br
436442 .I " iwconfig eth0 power min period 2 power max period 4"
437443 .TP
444+.BR modu [lation]
445+Force the card to use a specific set of modulations. Modern cards
446+support various modulations, some which are standard, such as 802.11b
447+or 802.11g, and some proprietary. This command force the card to only
448+use the specific set of modulations listed on the command line. This
449+can be used to fix interoperability issues.
450+.br
451+The list of available modulations depend on the card/driver and can be
452+displayed using
453+.IR "iwlist modulation" .
454+Note that some card/driver may not be able to select each modulation
455+listed independantly, some may come as a group. You may also set this
456+parameter to
457+.IR auto
458+let the card/driver do its best.
459+.br
460+.B Examples :
461+.br
462+.I " iwconfig eth0 modu 11g"
463+.br
464+.I " iwconfig eth0 modu CCK OFDMa"
465+.br
466+.I " iwconfig eth0 modu auto"
467+.TP
438468 .BR commit
439469 Some cards may not apply changes done through Wireless Extensions
440470 immediately (they may wait to aggregate the changes or apply it only
441-when the card is brought up via ifconfig). This command (when
442-available) forces the card to apply all pending changes.
471+when the card is brought up via
472+.IR ifconfig ).
473+This command (when available) forces the card to apply all pending
474+changes.
443475 .br
444476 This is normally not needed, because the card will eventually apply
445477 the changes, but can be useful for debugging.
--- a/wireless_tools/iwconfig.c
+++ b/wireless_tools/iwconfig.c
@@ -1,48 +1,37 @@
11 /*
22 * Wireless Tools
33 *
4- * Jean II - HPLB 97->99 - HPL 99->04
4+ * Jean II - HPLB 97->99 - HPL 99->07
55 *
66 * Main code for "iwconfig". This is the generic tool for most
77 * manipulations...
88 * You need to link this code against "iwlib.c" and "-lm".
99 *
1010 * This file is released under the GPL license.
11- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
11+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
1212 */
1313
1414 #include "iwlib.h" /* Header */
1515
16-/************************* MISC SUBROUTINES **************************/
16+/**************************** CONSTANTS ****************************/
1717
18-/*------------------------------------------------------------------*/
1918 /*
20- * Print usage string
19+ * Error codes defined for setting args
2120 */
22-static void
23-iw_usage(void)
24-{
25- fprintf(stderr,
26- "Usage: iwconfig interface [essid {NN|on|off}]\n"
27- " [nwid {NN|on|off}]\n"
28- " [mode {managed|ad-hoc|...}\n"
29- " [freq N.NNNN[k|M|G]]\n"
30- " [channel N]\n"
31- " [ap {N|off|auto}]\n"
32- " [sens N]\n"
33- " [nick N]\n"
34- " [rate {N|auto|fixed}]\n"
35- " [rts {N|auto|fixed|off}]\n"
36- " [frag {N|auto|fixed|off}]\n"
37- " [enc {NNNN-NNNN|off}]\n"
38- " [power {period N|timeout N}]\n"
39- " [retry {limit N|lifetime N}]\n"
40- " [txpower N {mW|dBm}]\n"
41- " [commit]\n"
42- " Check man pages for more details.\n\n"
43- );
44-}
21+#define IWERR_ARG_NUM -2
22+#define IWERR_ARG_TYPE -3
23+#define IWERR_ARG_SIZE -4
24+#define IWERR_ARG_CONFLICT -5
25+#define IWERR_SET_EXT -6
26+#define IWERR_GET_EXT -7
27+
28+/**************************** VARIABLES ****************************/
4529
30+/*
31+ * Ugly, but deal with errors in set_info() efficiently...
32+ */
33+static int errarg;
34+static int errmax;
4635
4736 /************************* DISPLAY ROUTINES **************************/
4837
@@ -79,13 +68,6 @@ get_info(int skfd,
7968 if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
8069 info->has_range = 1;
8170
82- /* Get sensitivity */
83- if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
84- {
85- info->has_sens = 1;
86- memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
87- }
88-
8971 /* Get AP address */
9072 if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
9173 {
@@ -93,14 +75,6 @@ get_info(int skfd,
9375 memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
9476 }
9577
96- /* Get NickName */
97- wrq.u.essid.pointer = (caddr_t) info->nickname;
98- wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
99- wrq.u.essid.flags = 0;
100- if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
101- if(wrq.u.data.length > 1)
102- info->has_nickname = 1;
103-
10478 /* Get bit rate */
10579 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
10680 {
@@ -108,20 +82,6 @@ get_info(int skfd,
10882 memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
10983 }
11084
111- /* Get RTS threshold */
112- if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
113- {
114- info->has_rts = 1;
115- memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
116- }
117-
118- /* Get fragmentation threshold */
119- if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
120- {
121- info->has_frag = 1;
122- memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
123- }
124-
12585 /* Get Power Management settings */
12686 wrq.u.power.flags = 0;
12787 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
@@ -130,6 +90,22 @@ get_info(int skfd,
13090 memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
13191 }
13292
93+ /* Get stats */
94+ if(iw_get_stats(skfd, ifname, &(info->stats),
95+ &info->range, info->has_range) >= 0)
96+ {
97+ info->has_stats = 1;
98+ }
99+
100+#ifndef WE_ESSENTIAL
101+ /* Get NickName */
102+ wrq.u.essid.pointer = (caddr_t) info->nickname;
103+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
104+ wrq.u.essid.flags = 0;
105+ if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
106+ if(wrq.u.data.length > 1)
107+ info->has_nickname = 1;
108+
133109 if((info->has_range) && (info->range.we_version_compiled > 9))
134110 {
135111 /* Get Transmit Power */
@@ -140,6 +116,13 @@ get_info(int skfd,
140116 }
141117 }
142118
119+ /* Get sensitivity */
120+ if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
121+ {
122+ info->has_sens = 1;
123+ memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
124+ }
125+
143126 if((info->has_range) && (info->range.we_version_compiled > 10))
144127 {
145128 /* Get retry limit/lifetime */
@@ -150,44 +133,20 @@ get_info(int skfd,
150133 }
151134 }
152135
153- /* Get stats */
154- if(iw_get_stats(skfd, ifname, &(info->stats),
155- &info->range, info->has_range) >= 0)
136+ /* Get RTS threshold */
137+ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
156138 {
157- info->has_stats = 1;
139+ info->has_rts = 1;
140+ memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
158141 }
159142
160-#ifdef DISPLAY_WPA
161- /* Note : currently disabled to not bloat iwconfig output. Also,
162- * if does not make total sense to display parameters that we
163- * don't allow (yet) to configure.
164- * For now, use iwlist instead... Jean II */
165-
166- /* Get WPA/802.1x/802.11i security parameters */
167- if((info->has_range) && (info->range.we_version_compiled > 17))
143+ /* Get fragmentation threshold */
144+ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
168145 {
169- wrq.u.param.flags = IW_AUTH_KEY_MGMT;
170- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
171- {
172- info->has_auth_key_mgmt = 1;
173- info->auth_key_mgmt = wrq.u.param.value;
174- }
175-
176- wrq.u.param.flags = IW_AUTH_CIPHER_PAIRWISE;
177- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
178- {
179- info->has_auth_cipher_pairwise = 1;
180- info->auth_cipher_pairwise = wrq.u.param.value;
181- }
182-
183- wrq.u.param.flags = IW_AUTH_CIPHER_GROUP;
184- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
185- {
186- info->has_auth_cipher_group = 1;
187- info->auth_cipher_group = wrq.u.param.value;
188- }
146+ info->has_frag = 1;
147+ memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
189148 }
190-#endif
149+#endif /* WE_ESSENTIAL */
191150
192151 return(0);
193152 }
@@ -225,9 +184,11 @@ display_info(struct wireless_info * info,
225184 printf("ESSID:off/any ");
226185 }
227186
187+#ifndef WE_ESSENTIAL
228188 /* Display NickName (station name), if any */
229189 if(info->has_nickname)
230190 printf("Nickname:\"%s\"", info->nickname);
191+#endif /* WE_ESSENTIAL */
231192
232193 /* Formatting */
233194 if(info->b.has_essid || info->has_nickname)
@@ -236,6 +197,7 @@ display_info(struct wireless_info * info,
236197 tokens = 0;
237198 }
238199
200+#ifndef WE_ESSENTIAL
239201 /* Display Network ID */
240202 if(info->b.has_nwid)
241203 {
@@ -247,6 +209,7 @@ display_info(struct wireless_info * info,
247209 printf("NWID:%X ", info->b.nwid.value);
248210 tokens +=2;
249211 }
212+#endif /* WE_ESSENTIAL */
250213
251214 /* Display the current mode of operation */
252215 if(info->b.has_mode)
@@ -306,6 +269,7 @@ display_info(struct wireless_info * info,
306269 printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
307270 }
308271
272+#ifndef WE_ESSENTIAL
309273 /* Display the Transmit Power */
310274 if(info->has_txpower)
311275 {
@@ -334,10 +298,7 @@ display_info(struct wireless_info * info,
334298 tokens +=4;
335299
336300 /* Fixed ? */
337- if(info->sens.fixed)
338- printf("Sensitivity=");
339- else
340- printf("Sensitivity:");
301+ printf("Sensitivity%c", info->sens.fixed ? '=' : ':');
341302
342303 if(info->has_range)
343304 /* Display in dBm ? */
@@ -348,10 +309,12 @@ display_info(struct wireless_info * info,
348309 else
349310 printf("%d ", info->sens.value);
350311 }
312+#endif /* WE_ESSENTIAL */
351313
352314 printf("\n ");
353315 tokens = 0;
354316
317+#ifndef WE_ESSENTIAL
355318 /* Display retry limit/lifetime information */
356319 if(info->has_retry)
357320 {
@@ -365,7 +328,8 @@ display_info(struct wireless_info * info,
365328 if(info->retry.flags & IW_RETRY_TYPE)
366329 {
367330 iw_print_retry_value(buffer, sizeof(buffer),
368- info->retry.value, info->retry.flags);
331+ info->retry.value, info->retry.flags,
332+ info->range.we_version_compiled);
369333 printf("%s", buffer);
370334 }
371335
@@ -386,12 +350,9 @@ display_info(struct wireless_info * info,
386350 else
387351 {
388352 /* Fixed ? */
389- if(info->rts.fixed)
390- printf("RTS thr=");
391- else
392- printf("RTS thr:");
393-
394- printf("%d B ", info->rts.value);
353+ printf("RTS thr%c%d B ",
354+ info->rts.fixed ? '=' : ':',
355+ info->rts.value);
395356 }
396357 tokens += 3;
397358 }
@@ -413,18 +374,16 @@ display_info(struct wireless_info * info,
413374 else
414375 {
415376 /* Fixed ? */
416- if(info->frag.fixed)
417- printf("Fragment thr=");
418- else
419- printf("Fragment thr:");
420-
421- printf("%d B ", info->frag.value);
377+ printf("Fragment thr%c%d B ",
378+ info->frag.fixed ? '=' : ':',
379+ info->frag.value);
422380 }
423381 }
424382
425383 /* Formating */
426384 if(tokens > 0)
427385 printf("\n ");
386+#endif /* WE_ESSENTIAL */
428387
429388 /* Display encryption information */
430389 /* Note : we display only the "current" key, use iwlist to list all keys */
@@ -451,22 +410,6 @@ display_info(struct wireless_info * info,
451410 printf("\n ");
452411 }
453412
454-#ifdef DISPLAY_WPA
455- /* Display WPA/802.1x/802.11i security parameters */
456- if(info->has_auth_key_mgmt || info->has_auth_cipher_pairwise ||
457- info->has_auth_cipher_group)
458- {
459- printf("Auth params:");
460- if(info->has_auth_key_mgmt)
461- printf(" key_mgmt:0x%X ", info->auth_key_mgmt);
462- if(info->has_auth_cipher_pairwise)
463- printf(" cipher_pairwise:0x%X ", info->auth_cipher_pairwise);
464- if(info->has_auth_cipher_group)
465- printf(" cipher_group:0x%X ", info->auth_cipher_group);
466- printf("\n ");
467- }
468-#endif
469-
470413 /* Display Power Management information */
471414 /* Note : we display only one parameter, period or timeout. If a device
472415 * (such as HiperLan) has both, the user need to use iwlist... */
@@ -482,7 +425,8 @@ display_info(struct wireless_info * info,
482425 if(info->power.flags & IW_POWER_TYPE)
483426 {
484427 iw_print_pm_value(buffer, sizeof(buffer),
485- info->power.value, info->power.flags);
428+ info->power.value, info->power.flags,
429+ info->range.we_version_compiled);
486430 printf("%s ", buffer);
487431 }
488432
@@ -558,864 +502,1403 @@ print_info(int skfd,
558502 return(rc);
559503 }
560504
561-/************************* SETTING ROUTINES **************************/
505+/****************** COMMAND LINE MODIFIERS PARSING ******************/
506+/*
507+ * Factor out the parsing of command line modifiers.
508+ */
562509
563510 /*------------------------------------------------------------------*/
564511 /*
565- * Macro to handle errors when setting WE
566- * Print a nice error message and exit...
567- * We define them as macro so that "return" do the right thing.
568- * The "do {...} while(0)" is a standard trick
512+ * Map command line modifiers to the proper flags...
569513 */
570-#define ERR_SET_EXT(rname, request) \
571- fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \
572- rname, request)
573-
574-#define ABORT_ARG_NUM(rname, request) \
575- do { \
576- ERR_SET_EXT(rname, request); \
577- fprintf(stderr, " too few arguments.\n"); \
578- return(-1); \
579- } while(0)
580-
581-#define ABORT_ARG_TYPE(rname, request, arg) \
582- do { \
583- ERR_SET_EXT(rname, request); \
584- fprintf(stderr, " invalid argument \"%s\".\n", arg); \
585- return(-2); \
586- } while(0)
587-
588-#define ABORT_ARG_SIZE(rname, request, max) \
589- do { \
590- ERR_SET_EXT(rname, request); \
591- fprintf(stderr, " argument too big (max %d)\n", max); \
592- return(-3); \
593- } while(0)
514+typedef struct iwconfig_modifier {
515+ const char * cmd; /* Command line shorthand */
516+ __u16 flag; /* Flags to add */
517+ __u16 exclude; /* Modifiers to exclude */
518+} iwconfig_modifier;
594519
595520 /*------------------------------------------------------------------*/
596521 /*
597- * Wrapper to push some Wireless Parameter in the driver
598- * Use standard wrapper and add pretty error message if fail...
522+ * Modifiers for Power
599523 */
600-#define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \
601- do { \
602- if(iw_set_ext(skfd, ifname, request, wrq) < 0) { \
603- ERR_SET_EXT(rname, request); \
604- fprintf(stderr, " SET failed on device %-1.16s ; %s.\n", \
605- ifname, strerror(errno)); \
606- return(-5); \
607- } } while(0)
524+static const struct iwconfig_modifier iwmod_power[] = {
525+ { "min", IW_POWER_MIN, IW_POWER_MAX },
526+ { "max", IW_POWER_MAX, IW_POWER_MIN },
527+ { "period", IW_POWER_PERIOD, IW_POWER_TIMEOUT | IW_POWER_SAVING },
528+ { "timeout", IW_POWER_TIMEOUT, IW_POWER_PERIOD | IW_POWER_SAVING },
529+ { "saving", IW_POWER_SAVING, IW_POWER_TIMEOUT | IW_POWER_PERIOD },
530+};
531+#define IWMOD_POWER_NUM (sizeof(iwmod_power)/sizeof(iwmod_power[0]))
608532
609533 /*------------------------------------------------------------------*/
610534 /*
611- * Wrapper to extract some Wireless Parameter out of the driver
612- * Use standard wrapper and add pretty error message if fail...
535+ * Modifiers for Retry
613536 */
614-#define IW_GET_EXT_ERR(skfd, ifname, request, wrq, rname) \
615- do { \
616- if(iw_get_ext(skfd, ifname, request, wrq) < 0) { \
617- ERR_SET_EXT(rname, request); \
618- fprintf(stderr, " GET failed on device %-1.16s ; %s.\n", \
619- ifname, strerror(errno)); \
620- return(-6); \
621- } } while(0)
537+#ifndef WE_ESSENTIAL
538+static const struct iwconfig_modifier iwmod_retry[] = {
539+ { "min", IW_RETRY_MIN, IW_RETRY_MAX },
540+ { "max", IW_RETRY_MAX, IW_RETRY_MIN },
541+ { "short", IW_RETRY_SHORT, IW_RETRY_LONG },
542+ { "long", IW_RETRY_LONG, IW_RETRY_SHORT },
543+ { "limit", IW_RETRY_LIMIT, IW_RETRY_LIFETIME },
544+ { "lifetime", IW_RETRY_LIFETIME, IW_RETRY_LIMIT },
545+};
546+#define IWMOD_RETRY_NUM (sizeof(iwmod_retry)/sizeof(iwmod_retry[0]))
547+#endif /* WE_ESSENTIAL */
622548
623549 /*------------------------------------------------------------------*/
624550 /*
625- * Set the wireless options requested on command line
626- * This function is too long and probably should be split,
627- * because it look like the perfect definition of spaghetti code,
628- * but I'm way to lazy
551+ * Parse command line modifiers.
552+ * Return error or number arg parsed.
553+ * Modifiers must be at the beggining of command line.
629554 */
630555 static int
631-set_info(int skfd, /* The socket */
632- char * args[], /* Command line args */
633- int count, /* Args count */
634- char * ifname) /* Dev name */
556+parse_modifiers(char * args[], /* Command line args */
557+ int count, /* Args count */
558+ __u16 * pout, /* Flags to write */
559+ const struct iwconfig_modifier modifier[],
560+ int modnum)
635561 {
636- struct iwreq wrq;
637- int i;
562+ int i = 0;
563+ int k = 0;
564+ __u16 result = 0; /* Default : no flag set */
638565
639- /* if nothing after the device name - will never happen */
640- if(count < 1)
566+ /* Get all modifiers and value types on the command line */
567+ do
641568 {
642- fprintf(stderr, "Error : too few arguments.\n");
643- return(-1);
569+ for(k = 0; k < modnum; k++)
570+ {
571+ /* Check if matches */
572+ if(!strcasecmp(args[i], modifier[k].cmd))
573+ {
574+ /* Check for conflicting flags */
575+ if(result & modifier[k].exclude)
576+ {
577+ errarg = i;
578+ return(IWERR_ARG_CONFLICT);
579+ }
580+ /* Just add it */
581+ result |= modifier[k].flag;
582+ ++i;
583+ break;
584+ }
585+ }
644586 }
587+ /* For as long as current arg matched and not out of args */
588+ while((i < count) && (k < modnum));
589+
590+ /* Check there remains one arg for value */
591+ if(i >= count)
592+ return(IWERR_ARG_NUM);
593+
594+ /* Return result */
595+ *pout = result;
596+ return(i);
597+}
598+
599+
600+/*********************** SETTING SUB-ROUTINES ***********************/
601+/*
602+ * The following functions are use to set some wireless parameters and
603+ * are called by the set dispatcher set_info().
604+ * They take as arguments the remaining of the command line, with
605+ * arguments processed already removed.
606+ * An error is indicated by a negative return value.
607+ * 0 and positive return values indicate the number of args consumed.
608+ */
645609
646- /* The other args on the line specify options to be set... */
647- for(i = 0; i < count; i++)
610+/*------------------------------------------------------------------*/
611+/*
612+ * Set ESSID
613+ */
614+static int
615+set_essid_info(int skfd,
616+ char * ifname,
617+ char * args[], /* Command line args */
618+ int count) /* Args count */
619+{
620+ struct iwreq wrq;
621+ int i = 1;
622+ char essid[IW_ESSID_MAX_SIZE + 1];
623+ int we_kernel_version;
624+
625+ if((!strcasecmp(args[0], "off")) ||
626+ (!strcasecmp(args[0], "any")))
648627 {
649- /* ---------- Commit changes to driver ---------- */
650- if(!strncmp(args[i], "commit", 6))
651- {
652- /* No args */
653- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq,
654- "Commit changes");
655- continue;
656- }
628+ wrq.u.essid.flags = 0;
629+ essid[0] = '\0';
630+ }
631+ else
632+ if(!strcasecmp(args[0], "on"))
633+ {
634+ /* Get old essid */
635+ memset(essid, '\0', sizeof(essid));
636+ wrq.u.essid.pointer = (caddr_t) essid;
637+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
638+ wrq.u.essid.flags = 0;
639+ if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0)
640+ return(IWERR_GET_EXT);
641+ wrq.u.essid.flags = 1;
642+ }
643+ else
644+ {
645+ i = 0;
646+
647+ /* '-' or '--' allow to escape the ESSID string, allowing
648+ * to set it to the string "any" or "off".
649+ * This is a big ugly, but it will do for now */
650+ if((!strcmp(args[0], "-")) || (!strcmp(args[0], "--")))
651+ {
652+ if(++i >= count)
653+ return(IWERR_ARG_NUM);
654+ }
655+
656+ /* Check the size of what the user passed us to avoid
657+ * buffer overflows */
658+ if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
659+ {
660+ errmax = IW_ESSID_MAX_SIZE;
661+ return(IWERR_ARG_SIZE);
662+ }
663+ else
664+ {
665+ int temp;
657666
658- /* ---------- Set network ID ---------- */
659- if((!strcasecmp(args[i], "nwid")) ||
660- (!strcasecmp(args[i], "domain")))
661- {
662- i++;
663- if(i >= count)
664- ABORT_ARG_NUM("Set NWID", SIOCSIWNWID);
665- if((!strcasecmp(args[i], "off")) ||
666- (!strcasecmp(args[i], "any")))
667- wrq.u.nwid.disabled = 1;
668- else
669- if(!strcasecmp(args[i], "on"))
667+ wrq.u.essid.flags = 1;
668+ strcpy(essid, args[i]); /* Size checked, all clear */
669+ i++;
670+
671+ /* Check for ESSID index */
672+ if((i < count) &&
673+ (sscanf(args[i], "[%i]", &temp) == 1) &&
674+ (temp > 0) && (temp < IW_ENCODE_INDEX))
670675 {
671- /* Get old nwid */
672- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq,
673- "Set NWID");
674- wrq.u.nwid.disabled = 0;
676+ wrq.u.essid.flags = temp;
677+ ++i;
675678 }
676- else
677- if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
678- != 1)
679- ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]);
680- else
681- wrq.u.nwid.disabled = 0;
682- wrq.u.nwid.fixed = 1;
683-
684- /* Set new nwid */
685- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq,
686- "Set NWID");
687- continue;
688- }
679+ }
680+ }
689681
690- /* ---------- Set frequency / channel ---------- */
691- if((!strncmp(args[i], "freq", 4)) ||
692- (!strcmp(args[i], "channel")))
693- {
694- double freq;
682+ /* Get version from kernel, device may not have range... */
683+ we_kernel_version = iw_get_kernel_we_version();
695684
696- if(++i >= count)
697- ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
698- if(!strcasecmp(args[i], "auto"))
699- {
700- wrq.u.freq.m = -1;
701- wrq.u.freq.e = 0;
702- wrq.u.freq.flags = 0;
703- }
704- else
705- {
706- if(!strcasecmp(args[i], "fixed"))
707- {
708- /* Get old bitrate */
709- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFREQ, &wrq,
710- "Set Bit Rate");
711- wrq.u.freq.flags = IW_FREQ_FIXED;
712- }
713- else /* Should be a numeric value */
714- {
715- if(sscanf(args[i], "%lg", &(freq)) != 1)
716- ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]);
717- if(index(args[i], 'G')) freq *= GIGA;
718- if(index(args[i], 'M')) freq *= MEGA;
719- if(index(args[i], 'k')) freq *= KILO;
685+ /* Finally set the ESSID value */
686+ wrq.u.essid.pointer = (caddr_t) essid;
687+ wrq.u.essid.length = strlen(essid);
688+ if(we_kernel_version < 21)
689+ wrq.u.essid.length++;
720690
721- iw_float2freq(freq, &(wrq.u.freq));
691+ if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
692+ return(IWERR_SET_EXT);
722693
723- wrq.u.freq.flags = IW_FREQ_FIXED;
694+ /* Var args */
695+ return(i);
696+}
724697
725- /* Check for an additional argument */
726- if(((i+1) < count) &&
727- (!strcasecmp(args[i+1], "auto")))
728- {
729- wrq.u.freq.flags = 0;
730- ++i;
731- }
732- if(((i+1) < count) &&
733- (!strcasecmp(args[i+1], "fixed")))
734- {
735- wrq.u.freq.flags = IW_FREQ_FIXED;
736- ++i;
737- }
738- }
739- }
698+/*------------------------------------------------------------------*/
699+/*
700+ * Set Mode
701+ */
702+static int
703+set_mode_info(int skfd,
704+ char * ifname,
705+ char * args[], /* Command line args */
706+ int count) /* Args count */
707+{
708+ struct iwreq wrq;
709+ unsigned int k; /* Must be unsigned */
740710
741- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
742- "Set Frequency");
743- continue;
744- }
711+ /* Avoid "Unused parameter" warning */
712+ count = count;
713+
714+ /* Check if it is a uint, otherwise get is as a string */
715+ if(sscanf(args[0], "%i", &k) != 1)
716+ {
717+ k = 0;
718+ while((k < IW_NUM_OPER_MODE) &&
719+ strncasecmp(args[0], iw_operation_mode[k], 3))
720+ k++;
721+ }
722+ if(k >= IW_NUM_OPER_MODE)
723+ {
724+ errarg = 0;
725+ return(IWERR_ARG_TYPE);
726+ }
727+
728+ wrq.u.mode = k;
729+ if(iw_set_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
730+ return(IWERR_SET_EXT);
731+
732+ /* 1 arg */
733+ return(1);
734+}
735+
736+/*------------------------------------------------------------------*/
737+/*
738+ * Set frequency/channel
739+ */
740+static int
741+set_freq_info(int skfd,
742+ char * ifname,
743+ char * args[], /* Command line args */
744+ int count) /* Args count */
745+{
746+ struct iwreq wrq;
747+ int i = 1;
745748
746- /* ---------- Set sensitivity ---------- */
747- if(!strncmp(args[i], "sens", 4))
749+ if(!strcasecmp(args[0], "auto"))
750+ {
751+ wrq.u.freq.m = -1;
752+ wrq.u.freq.e = 0;
753+ wrq.u.freq.flags = 0;
754+ }
755+ else
756+ {
757+ if(!strcasecmp(args[0], "fixed"))
748758 {
749- if(++i >= count)
750- ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS);
751- if(sscanf(args[i], "%i", &(wrq.u.sens.value)) != 1)
752- ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]);
753-
754- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq,
755- "Set Sensitivity");
756- continue;
759+ /* Get old frequency */
760+ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
761+ return(IWERR_GET_EXT);
762+ wrq.u.freq.flags = IW_FREQ_FIXED;
757763 }
758-
759- /* ---------- Set encryption stuff ---------- */
760- if((!strncmp(args[i], "enc", 3)) ||
761- (!strcmp(args[i], "key")))
764+ else /* Should be a numeric value */
762765 {
763- unsigned char key[IW_ENCODING_TOKEN_MAX];
764-
765- if(++i >= count)
766- ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE);
766+ double freq;
767+ char * unit;
767768
768- if(!strcasecmp(args[i], "on"))
769+ freq = strtod(args[0], &unit);
770+ if(unit == args[0])
769771 {
770- /* Get old encryption information */
771- wrq.u.data.pointer = (caddr_t) key;
772- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
773- wrq.u.data.flags = 0;
774- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq,
775- "Set Encode");
776- wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
772+ errarg = 0;
773+ return(IWERR_ARG_TYPE);
777774 }
778- else
775+ if(unit != NULL)
779776 {
780- int gotone = 0;
781- int oldone;
782- int keylen;
783- int temp;
784-
785- wrq.u.data.pointer = (caddr_t) NULL;
786- wrq.u.data.flags = 0;
787- wrq.u.data.length = 0;
788-
789- /* Allow arguments in any order (it's safe) */
790- do
791- {
792- oldone = gotone;
793-
794- /* -- Check for the key -- */
795- if(i < count)
796- {
797- keylen = iw_in_key_full(skfd, ifname,
798- args[i], key, &wrq.u.data.flags);
799- if(keylen > 0)
800- {
801- wrq.u.data.length = keylen;
802- wrq.u.data.pointer = (caddr_t) key;
803- ++i;
804- gotone++;
805- }
806- }
807-
808- /* -- Check for token index -- */
809- if((i < count) &&
810- (sscanf(args[i], "[%i]", &temp) == 1) &&
811- (temp > 0) && (temp < IW_ENCODE_INDEX))
812- {
813- wrq.u.encoding.flags |= temp;
814- ++i;
815- gotone++;
816- }
777+ if(unit[0] == 'G') freq *= GIGA;
778+ if(unit[0] == 'M') freq *= MEGA;
779+ if(unit[0] == 'k') freq *= KILO;
780+ }
817781
818- /* -- Check the various flags -- */
819- if((i < count) && (!strcasecmp(args[i], "off")))
820- {
821- wrq.u.data.flags |= IW_ENCODE_DISABLED;
822- ++i;
823- gotone++;
824- }
825- if((i < count) && (!strcasecmp(args[i], "open")))
826- {
827- wrq.u.data.flags |= IW_ENCODE_OPEN;
828- ++i;
829- gotone++;
830- }
831- if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
832- {
833- wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
834- ++i;
835- gotone++;
836- }
837- if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
838- {
839- wrq.u.data.flags |= IW_ENCODE_TEMP;
840- ++i;
841- gotone++;
842- }
843- }
844- while(gotone != oldone);
782+ iw_float2freq(freq, &(wrq.u.freq));
845783
846- /* Pointer is absent in new API */
847- if(wrq.u.data.pointer == NULL)
848- wrq.u.data.flags |= IW_ENCODE_NOKEY;
784+ wrq.u.freq.flags = IW_FREQ_FIXED;
849785
850- /* Check if we have any invalid argument */
851- if(!gotone)
852- ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]);
853- /* Get back to last processed argument */
854- --i;
786+ /* Check for an additional argument */
787+ if((i < count) && (!strcasecmp(args[i], "auto")))
788+ {
789+ wrq.u.freq.flags = 0;
790+ ++i;
855791 }
856-
857- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq,
858- "Set Encode");
859- continue;
860- }
861-
862- /* ---------- Set ESSID ---------- */
863- if(!strcasecmp(args[i], "essid"))
864- {
865- char essid[IW_ESSID_MAX_SIZE + 1];
866- int we_kernel_version;
867-
868- i++;
869- if(i >= count)
870- ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
871- if((!strcasecmp(args[i], "off")) ||
872- (!strcasecmp(args[i], "any")))
792+ if((i < count) && (!strcasecmp(args[i], "fixed")))
873793 {
874- wrq.u.essid.flags = 0;
875- essid[0] = '\0';
794+ wrq.u.freq.flags = IW_FREQ_FIXED;
795+ ++i;
876796 }
877- else
878- if(!strcasecmp(args[i], "on"))
879- {
880- /* Get old essid */
881- memset(essid, '\0', sizeof(essid));
882- wrq.u.essid.pointer = (caddr_t) essid;
883- wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
884- wrq.u.essid.flags = 0;
885- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq,
886- "Set ESSID");
887- wrq.u.essid.flags = 1;
888- }
889- else
890- {
891- /* '-' or '--' allow to escape the ESSID string, allowing
892- * to set it to the string "any" or "off".
893- * This is a big ugly, but it will do for now */
894- if((!strcmp(args[i], "-")) || (!strcmp(args[i], "--")))
895- {
896- i++;
897- if(i >= count)
898- ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
899- }
797+ }
798+ }
900799
901- /* Check the size of what the user passed us to avoid
902- * buffer overflows */
903- if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
904- ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE);
905- else
906- {
907- int temp;
800+ if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
801+ return(IWERR_SET_EXT);
908802
909- wrq.u.essid.flags = 1;
910- strcpy(essid, args[i]); /* Size checked, all clear */
803+ /* Var args */
804+ return(i);
805+}
911806
912- /* Check for ESSID index */
913- if(((i+1) < count) &&
914- (sscanf(args[i+1], "[%i]", &temp) == 1) &&
915- (temp > 0) && (temp < IW_ENCODE_INDEX))
916- {
917- wrq.u.essid.flags = temp;
918- ++i;
919- }
920- }
921- }
807+/*------------------------------------------------------------------*/
808+/*
809+ * Set Bit Rate
810+ */
811+static int
812+set_bitrate_info(int skfd,
813+ char * ifname,
814+ char * args[], /* Command line args */
815+ int count) /* Args count */
816+{
817+ struct iwreq wrq;
818+ int i = 1;
922819
923- /* Get version from kernel, device may not have range... */
924- we_kernel_version = iw_get_kernel_we_version();
925-
926- /* Finally set the ESSID value */
927- wrq.u.essid.pointer = (caddr_t) essid;
928- wrq.u.essid.length = strlen(essid) + 1;
929- if(we_kernel_version > 20)
930- wrq.u.essid.length--;
931- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq,
932- "Set ESSID");
933- continue;
820+ wrq.u.bitrate.flags = 0;
821+ if(!strcasecmp(args[0], "auto"))
822+ {
823+ wrq.u.bitrate.value = -1;
824+ wrq.u.bitrate.fixed = 0;
825+ }
826+ else
827+ {
828+ if(!strcasecmp(args[0], "fixed"))
829+ {
830+ /* Get old bitrate */
831+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) < 0)
832+ return(IWERR_GET_EXT);
833+ wrq.u.bitrate.fixed = 1;
934834 }
935-
936- /* ---------- Set AP address ---------- */
937- if(!strcasecmp(args[i], "ap"))
835+ else /* Should be a numeric value */
938836 {
939- if(++i >= count)
940- ABORT_ARG_NUM("Set AP Address", SIOCSIWAP);
837+ double brate;
838+ char * unit;
941839
942- if((!strcasecmp(args[i], "auto")) ||
943- (!strcasecmp(args[i], "any")))
840+ brate = strtod(args[0], &unit);
841+ if(unit == args[0])
944842 {
945- /* Send a broadcast address */
946- iw_broad_ether(&(wrq.u.ap_addr));
843+ errarg = 0;
844+ return(IWERR_ARG_TYPE);
947845 }
948- else
846+ if(unit != NULL)
949847 {
950- if(!strcasecmp(args[i], "off"))
951- {
952- /* Send a NULL address */
953- iw_null_ether(&(wrq.u.ap_addr));
954- }
955- else
956- {
957- /* Get the address and check if the interface supports it */
958- if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
959- ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]);
960- }
848+ if(unit[0] == 'G') brate *= GIGA;
849+ if(unit[0] == 'M') brate *= MEGA;
850+ if(unit[0] == 'k') brate *= KILO;
961851 }
852+ wrq.u.bitrate.value = (long) brate;
853+ wrq.u.bitrate.fixed = 1;
962854
963- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq,
964- "Set AP Address");
965- continue;
966- }
967-
968- /* ---------- Set NickName ---------- */
969- if(!strncmp(args[i], "nick", 4))
970- {
971- int we_kernel_version;
972-
973- i++;
974- if(i >= count)
975- ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN);
976- if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
977- ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE);
978-
979- we_kernel_version = iw_get_kernel_we_version();
980-
981- wrq.u.essid.pointer = (caddr_t) args[i];
982- wrq.u.essid.length = strlen(args[i]) + 1;
983- if(we_kernel_version > 20)
984- wrq.u.essid.length--;
985- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq,
986- "Set Nickname");
987- continue;
988- }
989-
990- /* ---------- Set Bit-Rate ---------- */
991- if((!strncmp(args[i], "bit", 3)) ||
992- (!strcmp(args[i], "rate")))
993- {
994- if(++i >= count)
995- ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE);
996- if(!strcasecmp(args[i], "auto"))
855+ /* Check for an additional argument */
856+ if((i < count) && (!strcasecmp(args[i], "auto")))
997857 {
998- wrq.u.bitrate.value = -1;
999858 wrq.u.bitrate.fixed = 0;
859+ ++i;
1000860 }
1001- else
861+ if((i < count) && (!strcasecmp(args[i], "fixed")))
1002862 {
1003- if(!strcasecmp(args[i], "fixed"))
1004- {
1005- /* Get old bitrate */
1006- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq,
1007- "Set Bit Rate");
1008- wrq.u.bitrate.fixed = 1;
1009- }
1010- else /* Should be a numeric value */
1011- {
1012- double brate;
1013-
1014- if(sscanf(args[i], "%lg", &(brate)) != 1)
1015- ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]);
1016- if(index(args[i], 'G')) brate *= GIGA;
1017- if(index(args[i], 'M')) brate *= MEGA;
1018- if(index(args[i], 'k')) brate *= KILO;
1019- wrq.u.bitrate.value = (long) brate;
1020- wrq.u.bitrate.fixed = 1;
1021-
1022- /* Check for an additional argument */
1023- if(((i+1) < count) &&
1024- (!strcasecmp(args[i+1], "auto")))
1025- {
1026- wrq.u.bitrate.fixed = 0;
1027- ++i;
1028- }
1029- if(((i+1) < count) &&
1030- (!strcasecmp(args[i+1], "fixed")))
1031- {
1032- wrq.u.bitrate.fixed = 1;
1033- ++i;
1034- }
1035- }
863+ wrq.u.bitrate.fixed = 1;
864+ ++i;
865+ }
866+ if((i < count) && (!strcasecmp(args[i], "unicast")))
867+ {
868+ wrq.u.bitrate.flags |= IW_BITRATE_UNICAST;
869+ ++i;
870+ }
871+ if((i < count) && (!strcasecmp(args[i], "broadcast")))
872+ {
873+ wrq.u.bitrate.flags |= IW_BITRATE_BROADCAST;
874+ ++i;
1036875 }
1037-
1038- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq,
1039- "Set Bit Rate");
1040- continue;
1041876 }
877+ }
878+
879+ if(iw_set_ext(skfd, ifname, SIOCSIWRATE, &wrq) < 0)
880+ return(IWERR_SET_EXT);
881+
882+ /* Var args */
883+ return(i);
884+}
885+
886+/*------------------------------------------------------------------*/
887+/*
888+ * Set encryption
889+ */
890+static int
891+set_enc_info(int skfd,
892+ char * ifname,
893+ char * args[], /* Command line args */
894+ int count) /* Args count */
895+{
896+ struct iwreq wrq;
897+ int i = 1;
898+ unsigned char key[IW_ENCODING_TOKEN_MAX];
1042899
1043- /* ---------- Set RTS threshold ---------- */
1044- if(!strncasecmp(args[i], "rts", 3))
900+ if(!strcasecmp(args[0], "on"))
901+ {
902+ /* Get old encryption information */
903+ wrq.u.data.pointer = (caddr_t) key;
904+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
905+ wrq.u.data.flags = 0;
906+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
907+ return(IWERR_GET_EXT);
908+ wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
909+ }
910+ else
911+ {
912+ int gotone = 0;
913+ int oldone;
914+ int keylen;
915+ int temp;
916+
917+ wrq.u.data.pointer = (caddr_t) NULL;
918+ wrq.u.data.flags = 0;
919+ wrq.u.data.length = 0;
920+ i = 0;
921+
922+ /* Allow arguments in any order (it's safe) */
923+ do
1045924 {
1046- i++;
1047- if(i >= count)
1048- ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS);
1049- wrq.u.rts.value = -1;
1050- wrq.u.rts.fixed = 1;
1051- wrq.u.rts.disabled = 0;
1052- if(!strcasecmp(args[i], "off"))
1053- wrq.u.rts.disabled = 1; /* i.e. max size */
1054- else
1055- if(!strcasecmp(args[i], "auto"))
1056- wrq.u.rts.fixed = 0;
1057- else
1058- {
1059- if(!strcasecmp(args[i], "fixed"))
1060- {
1061- /* Get old RTS threshold */
1062- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq,
1063- "Set RTS Threshold");
1064- wrq.u.rts.fixed = 1;
1065- }
1066- else /* Should be a numeric value */
1067- if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.rts.value))
1068- != 1)
1069- ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]);
925+ oldone = gotone;
926+
927+ /* -- Check for the key -- */
928+ if(i < count)
929+ {
930+ keylen = iw_in_key_full(skfd, ifname,
931+ args[i], key, &wrq.u.data.flags);
932+ if(keylen > 0)
933+ {
934+ wrq.u.data.length = keylen;
935+ wrq.u.data.pointer = (caddr_t) key;
936+ ++i;
937+ gotone++;
938+ }
1070939 }
1071940
1072- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq,
1073- "Set RTS Threshold");
1074- continue;
941+ /* -- Check for token index -- */
942+ if((i < count) &&
943+ (sscanf(args[i], "[%i]", &temp) == 1) &&
944+ (temp > 0) && (temp < IW_ENCODE_INDEX))
945+ {
946+ wrq.u.encoding.flags |= temp;
947+ ++i;
948+ gotone++;
949+ }
950+
951+ /* -- Check the various flags -- */
952+ if((i < count) && (!strcasecmp(args[i], "off")))
953+ {
954+ wrq.u.data.flags |= IW_ENCODE_DISABLED;
955+ ++i;
956+ gotone++;
957+ }
958+ if((i < count) && (!strcasecmp(args[i], "open")))
959+ {
960+ wrq.u.data.flags |= IW_ENCODE_OPEN;
961+ ++i;
962+ gotone++;
963+ }
964+ if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
965+ {
966+ wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
967+ ++i;
968+ gotone++;
969+ }
970+ if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
971+ {
972+ wrq.u.data.flags |= IW_ENCODE_TEMP;
973+ ++i;
974+ gotone++;
975+ }
1075976 }
977+ while(gotone != oldone);
978+
979+ /* Pointer is absent in new API */
980+ if(wrq.u.data.pointer == NULL)
981+ wrq.u.data.flags |= IW_ENCODE_NOKEY;
1076982
1077- /* ---------- Set fragmentation threshold ---------- */
1078- if(!strncmp(args[i], "frag", 4))
983+ /* Check if we have any invalid argument */
984+ if(!gotone)
1079985 {
1080- i++;
1081- if(i >= count)
1082- ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG);
1083- wrq.u.frag.value = -1;
1084- wrq.u.frag.fixed = 1;
1085- wrq.u.frag.disabled = 0;
1086- if(!strcasecmp(args[i], "off"))
1087- wrq.u.frag.disabled = 1; /* i.e. max size */
1088- else
1089- if(!strcasecmp(args[i], "auto"))
1090- wrq.u.frag.fixed = 0;
986+ errarg = 0;
987+ return(IWERR_ARG_TYPE);
988+ }
989+ }
990+
991+ if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
992+ return(IWERR_SET_EXT);
993+
994+ /* Var arg */
995+ return(i);
996+}
997+
998+/*------------------------------------------------------------------*/
999+/*
1000+ * Set Power Management
1001+ */
1002+static int
1003+set_power_info(int skfd,
1004+ char * ifname,
1005+ char * args[], /* Command line args */
1006+ int count) /* Args count */
1007+{
1008+ struct iwreq wrq;
1009+ int i = 1;
1010+
1011+ if(!strcasecmp(args[0], "off"))
1012+ wrq.u.power.disabled = 1; /* i.e. max size */
1013+ else
1014+ if(!strcasecmp(args[0], "on"))
1015+ {
1016+ /* Get old Power info */
1017+ wrq.u.power.flags = 0;
1018+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) < 0)
1019+ return(IWERR_GET_EXT);
1020+ wrq.u.power.disabled = 0;
1021+ }
1022+ else
1023+ {
1024+ double value;
1025+ char * unit;
1026+ int gotone = 0;
1027+
1028+ /* Parse modifiers */
1029+ i = parse_modifiers(args, count, &wrq.u.power.flags,
1030+ iwmod_power, IWMOD_POWER_NUM);
1031+ if(i < 0)
1032+ return(i);
1033+
1034+ wrq.u.power.disabled = 0;
1035+
1036+ /* Is there any value to grab ? */
1037+ value = strtod(args[0], &unit);
1038+ if(unit != args[0])
1039+ {
1040+ struct iw_range range;
1041+ int flags;
1042+ /* Extract range info to handle properly 'relative' */
1043+ if(iw_get_range_info(skfd, ifname, &range) < 0)
1044+ memset(&range, 0, sizeof(range));
1045+
1046+ /* Get the flags to be able to do the proper conversion */
1047+ switch(wrq.u.power.flags & IW_POWER_TYPE)
1048+ {
1049+ case IW_POWER_SAVING:
1050+ flags = range.pms_flags;
1051+ break;
1052+ case IW_POWER_TIMEOUT:
1053+ flags = range.pmt_flags;
1054+ break;
1055+ default:
1056+ flags = range.pmp_flags;
1057+ break;
1058+ }
1059+ /* Check if time or relative */
1060+ if(flags & IW_POWER_RELATIVE)
1061+ {
1062+ if(range.we_version_compiled < 21)
1063+ value *= MEGA;
1064+ else
1065+ wrq.u.power.flags |= IW_POWER_RELATIVE;
1066+ }
10911067 else
10921068 {
1093- if(!strcasecmp(args[i], "fixed"))
1094- {
1095- /* Get old fragmentation threshold */
1096- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq,
1097- "Set Fragmentation Threshold");
1098- wrq.u.frag.fixed = 1;
1099- }
1100- else /* Should be a numeric value */
1101- if(sscanf(args[i], "%li",
1102- (unsigned long *) &(wrq.u.frag.value))
1103- != 1)
1104- ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG,
1105- args[i]);
1106- }
1069+ value *= MEGA; /* default = s */
1070+ if(unit[0] == 'u') value /= MEGA;
1071+ if(unit[0] == 'm') value /= KILO;
1072+ }
1073+ wrq.u.power.value = (long) value;
1074+ /* Set some default type if none */
1075+ if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
1076+ wrq.u.power.flags |= IW_POWER_PERIOD;
1077+ ++i;
1078+ gotone = 1;
1079+ }
1080+
1081+ /* Now, check the mode */
1082+ if(i < count)
1083+ {
1084+ if(!strcasecmp(args[i], "all"))
1085+ wrq.u.power.flags |= IW_POWER_ALL_R;
1086+ if(!strncasecmp(args[i], "unicast", 4))
1087+ wrq.u.power.flags |= IW_POWER_UNICAST_R;
1088+ if(!strncasecmp(args[i], "multicast", 5))
1089+ wrq.u.power.flags |= IW_POWER_MULTICAST_R;
1090+ if(!strncasecmp(args[i], "force", 5))
1091+ wrq.u.power.flags |= IW_POWER_FORCE_S;
1092+ if(!strcasecmp(args[i], "repeat"))
1093+ wrq.u.power.flags |= IW_POWER_REPEATER;
1094+ if(wrq.u.power.flags & IW_POWER_MODE)
1095+ {
1096+ ++i;
1097+ gotone = 1;
1098+ }
1099+ }
1100+ if(!gotone)
1101+ {
1102+ errarg = i;
1103+ return(IWERR_ARG_TYPE);
1104+ }
1105+ }
1106+
1107+ if(iw_set_ext(skfd, ifname, SIOCSIWPOWER, &wrq) < 0)
1108+ return(IWERR_SET_EXT);
1109+
1110+ /* Var args */
1111+ return(i);
1112+}
11071113
1108- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq,
1109- "Set Fragmentation Threshold");
1110- continue;
1111- }
1114+#ifndef WE_ESSENTIAL
1115+/*------------------------------------------------------------------*/
1116+/*
1117+ * Set Nickname
1118+ */
1119+static int
1120+set_nick_info(int skfd,
1121+ char * ifname,
1122+ char * args[], /* Command line args */
1123+ int count) /* Args count */
1124+{
1125+ struct iwreq wrq;
1126+ int we_kernel_version;
1127+
1128+ /* Avoid "Unused parameter" warning */
1129+ count = count;
11121130
1113- /* ---------- Set operation mode ---------- */
1114- if(!strcmp(args[i], "mode"))
1131+ if(strlen(args[0]) > IW_ESSID_MAX_SIZE)
1132+ {
1133+ errmax = IW_ESSID_MAX_SIZE;
1134+ return(IWERR_ARG_SIZE);
1135+ }
1136+
1137+ we_kernel_version = iw_get_kernel_we_version();
1138+
1139+ wrq.u.essid.pointer = (caddr_t) args[0];
1140+ wrq.u.essid.length = strlen(args[0]);
1141+ if(we_kernel_version < 21)
1142+ wrq.u.essid.length++;
1143+
1144+ if(iw_set_ext(skfd, ifname, SIOCSIWNICKN, &wrq) < 0)
1145+ return(IWERR_SET_EXT);
1146+
1147+ /* 1 args */
1148+ return(1);
1149+}
1150+
1151+/*------------------------------------------------------------------*/
1152+/*
1153+ * Set commit
1154+ */
1155+static int
1156+set_nwid_info(int skfd,
1157+ char * ifname,
1158+ char * args[], /* Command line args */
1159+ int count) /* Args count */
1160+{
1161+ struct iwreq wrq;
1162+ unsigned long temp;
1163+
1164+ /* Avoid "Unused parameter" warning */
1165+ count = count;
1166+
1167+ if((!strcasecmp(args[0], "off")) ||
1168+ (!strcasecmp(args[0], "any")))
1169+ wrq.u.nwid.disabled = 1;
1170+ else
1171+ if(!strcasecmp(args[0], "on"))
1172+ {
1173+ /* Get old nwid */
1174+ if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0)
1175+ return(IWERR_GET_EXT);
1176+ wrq.u.nwid.disabled = 0;
1177+ }
1178+ else
1179+ if(sscanf(args[0], "%lX", &(temp)) != 1)
11151180 {
1116- int k;
1181+ errarg = 0;
1182+ return(IWERR_ARG_TYPE);
1183+ }
1184+ else
1185+ {
1186+ wrq.u.nwid.value = temp;
1187+ wrq.u.nwid.disabled = 0;
1188+ }
11171189
1118- i++;
1119- if(i >= count)
1120- ABORT_ARG_NUM("Set Mode", SIOCSIWMODE);
1190+ wrq.u.nwid.fixed = 1;
11211191
1122- if(sscanf(args[i], "%i", &k) != 1)
1192+ /* Set new nwid */
1193+ if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
1194+ return(IWERR_SET_EXT);
1195+
1196+ /* 1 arg */
1197+ return(1);
1198+}
1199+
1200+/*------------------------------------------------------------------*/
1201+/*
1202+ * Set AP Address
1203+ */
1204+static int
1205+set_apaddr_info(int skfd,
1206+ char * ifname,
1207+ char * args[], /* Command line args */
1208+ int count) /* Args count */
1209+{
1210+ struct iwreq wrq;
1211+
1212+ /* Avoid "Unused parameter" warning */
1213+ count = count;
1214+
1215+ if((!strcasecmp(args[0], "auto")) ||
1216+ (!strcasecmp(args[0], "any")))
1217+ {
1218+ /* Send a broadcast address */
1219+ iw_broad_ether(&(wrq.u.ap_addr));
1220+ }
1221+ else
1222+ {
1223+ if(!strcasecmp(args[0], "off"))
1224+ {
1225+ /* Send a NULL address */
1226+ iw_null_ether(&(wrq.u.ap_addr));
1227+ }
1228+ else
1229+ {
1230+ /* Get the address and check if the interface supports it */
1231+ if(iw_in_addr(skfd, ifname, args[0], &(wrq.u.ap_addr)) < 0)
11231232 {
1124- k = 0;
1125- while((k < IW_NUM_OPER_MODE) &&
1126- strncasecmp(args[i], iw_operation_mode[k], 3))
1127- k++;
1233+ errarg = 0;
1234+ return(IWERR_ARG_TYPE);
11281235 }
1129- if((k >= IW_NUM_OPER_MODE) || (k < 0))
1130- ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]);
1131-
1132- wrq.u.mode = k;
1133- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq,
1134- "Set Mode");
1135- continue;
11361236 }
1237+ }
11371238
1138- /* ---------- Set Power Management ---------- */
1139- if(!strncmp(args[i], "power", 3))
1140- {
1141- if(++i >= count)
1142- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1239+ if(iw_set_ext(skfd, ifname, SIOCSIWAP, &wrq) < 0)
1240+ return(IWERR_SET_EXT);
11431241
1144- if(!strcasecmp(args[i], "off"))
1145- wrq.u.power.disabled = 1; /* i.e. max size */
1146- else
1147- if(!strcasecmp(args[i], "on"))
1242+ /* 1 args */
1243+ return(1);
1244+}
1245+
1246+/*------------------------------------------------------------------*/
1247+/*
1248+ * Set Tx Power
1249+ */
1250+static int
1251+set_txpower_info(int skfd,
1252+ char * ifname,
1253+ char * args[], /* Command line args */
1254+ int count) /* Args count */
1255+{
1256+ struct iwreq wrq;
1257+ int i = 1;
1258+
1259+ /* Avoid "Unused parameter" warning */
1260+ args = args; count = count;
1261+
1262+ /* Prepare the request */
1263+ wrq.u.txpower.value = -1;
1264+ wrq.u.txpower.fixed = 1;
1265+ wrq.u.txpower.disabled = 0;
1266+ wrq.u.txpower.flags = IW_TXPOW_DBM;
1267+
1268+ if(!strcasecmp(args[0], "off"))
1269+ wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
1270+ else
1271+ if(!strcasecmp(args[0], "auto"))
1272+ wrq.u.txpower.fixed = 0; /* i.e. use power control */
1273+ else
1274+ {
1275+ if(!strcasecmp(args[0], "on"))
1276+ {
1277+ /* Get old tx-power */
1278+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
1279+ return(IWERR_GET_EXT);
1280+ wrq.u.txpower.disabled = 0;
1281+ }
1282+ else
1283+ {
1284+ if(!strcasecmp(args[0], "fixed"))
11481285 {
1149- /* Get old Power info */
1150- wrq.u.power.flags = 0;
1151- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq,
1152- "Set Power Management");
1153- wrq.u.power.disabled = 0;
1286+ /* Get old tx-power */
1287+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
1288+ return(IWERR_GET_EXT);
1289+ wrq.u.txpower.fixed = 1;
1290+ wrq.u.txpower.disabled = 0;
11541291 }
1155- else
1292+ else /* Should be a numeric value */
11561293 {
1157- double temp;
1158- int gotone = 0;
1159- /* Default - nope */
1160- wrq.u.power.flags = IW_POWER_ON;
1161- wrq.u.power.disabled = 0;
1162-
1163- /* Check value modifier */
1164- if(!strcasecmp(args[i], "min"))
1294+ int power;
1295+ int ismwatt = 0;
1296+ struct iw_range range;
1297+
1298+ /* Extract range info to do proper conversion */
1299+ if(iw_get_range_info(skfd, ifname, &range) < 0)
1300+ memset(&range, 0, sizeof(range));
1301+
1302+ /* Get the value */
1303+ if(sscanf(args[0], "%i", &(power)) != 1)
11651304 {
1166- wrq.u.power.flags |= IW_POWER_MIN;
1167- if(++i >= count)
1168- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1305+ errarg = 0;
1306+ return(IWERR_ARG_TYPE);
11691307 }
1170- else
1171- if(!strcasecmp(args[i], "max"))
1172- {
1173- wrq.u.power.flags |= IW_POWER_MAX;
1174- if(++i >= count)
1175- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1176- }
11771308
1178- /* Check value type */
1179- if(!strcasecmp(args[i], "period"))
1309+ /* Check if milliWatt
1310+ * We authorise a single 'm' as a shorthand for 'mW',
1311+ * on the other hand a 'd' probably means 'dBm'... */
1312+ ismwatt = ((strchr(args[0], 'm') != NULL)
1313+ && (strchr(args[0], 'd') == NULL));
1314+
1315+ /* We could check 'W' alone... Another time... */
1316+
1317+ /* Convert */
1318+ if(range.txpower_capa & IW_TXPOW_RELATIVE)
11801319 {
1181- wrq.u.power.flags |= IW_POWER_PERIOD;
1182- if(++i >= count)
1183- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1320+ /* Can't convert */
1321+ if(ismwatt)
1322+ {
1323+ errarg = 0;
1324+ return(IWERR_ARG_TYPE);
1325+ }
1326+ wrq.u.txpower.flags = IW_TXPOW_RELATIVE;
11841327 }
11851328 else
1186- if(!strcasecmp(args[i], "timeout"))
1329+ if(range.txpower_capa & IW_TXPOW_MWATT)
1330+ {
1331+ if(!ismwatt)
1332+ power = iw_dbm2mwatt(power);
1333+ wrq.u.txpower.flags = IW_TXPOW_MWATT;
1334+ }
1335+ else
11871336 {
1188- wrq.u.power.flags |= IW_POWER_TIMEOUT;
1189- if(++i >= count)
1190- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1337+ if(ismwatt)
1338+ power = iw_mwatt2dbm(power);
1339+ wrq.u.txpower.flags = IW_TXPOW_DBM;
11911340 }
1341+ wrq.u.txpower.value = power;
11921342
1193- /* Is there any value to grab ? */
1194- if(sscanf(args[i], "%lg", &(temp)) == 1)
1343+ /* Check for an additional argument */
1344+ if((i < count) && (!strcasecmp(args[i], "auto")))
11951345 {
1196- temp *= MEGA; /* default = s */
1197- if(index(args[i], 'u')) temp /= MEGA;
1198- if(index(args[i], 'm')) temp /= KILO;
1199- wrq.u.power.value = (long) temp;
1200- if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
1201- wrq.u.power.flags |= IW_POWER_PERIOD;
1346+ wrq.u.txpower.fixed = 0;
12021347 ++i;
1203- gotone = 1;
12041348 }
1205-
1206- /* Now, check the mode */
1207- if(i < count)
1349+ if((i < count) && (!strcasecmp(args[i], "fixed")))
12081350 {
1209- if(!strcasecmp(args[i], "all"))
1210- wrq.u.power.flags |= IW_POWER_ALL_R;
1211- if(!strncasecmp(args[i], "unicast", 4))
1212- wrq.u.power.flags |= IW_POWER_UNICAST_R;
1213- if(!strncasecmp(args[i], "multicast", 5))
1214- wrq.u.power.flags |= IW_POWER_MULTICAST_R;
1215- if(!strncasecmp(args[i], "force", 5))
1216- wrq.u.power.flags |= IW_POWER_FORCE_S;
1217- if(!strcasecmp(args[i], "repeat"))
1218- wrq.u.power.flags |= IW_POWER_REPEATER;
1219- if(wrq.u.power.flags & IW_POWER_MODE)
1220- {
1221- ++i;
1222- gotone = 1;
1223- }
1351+ wrq.u.txpower.fixed = 1;
1352+ ++i;
12241353 }
1225- if(!gotone)
1226- ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER,
1227- args[i]);
1228- --i;
12291354 }
1355+ }
1356+ }
1357+
1358+ if(iw_set_ext(skfd, ifname, SIOCSIWTXPOW, &wrq) < 0)
1359+ return(IWERR_SET_EXT);
12301360
1231- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq,
1232- "Set Power Management");
1233- continue;
1234- }
1361+ /* Var args */
1362+ return(i);
1363+}
12351364
1236- /* ---------- Set Transmit-Power ---------- */
1237- if(!strncmp(args[i], "txpower", 3))
1365+/*------------------------------------------------------------------*/
1366+/*
1367+ * Set Sensitivity
1368+ */
1369+static int
1370+set_sens_info(int skfd,
1371+ char * ifname,
1372+ char * args[], /* Command line args */
1373+ int count) /* Args count */
1374+{
1375+ struct iwreq wrq;
1376+ int temp;
1377+
1378+ /* Avoid "Unused parameter" warning */
1379+ count = count;
1380+
1381+ if(sscanf(args[0], "%i", &(temp)) != 1)
1382+ {
1383+ errarg = 0;
1384+ return(IWERR_ARG_TYPE);
1385+ }
1386+ wrq.u.sens.value = temp;
1387+
1388+ if(iw_set_ext(skfd, ifname, SIOCSIWSENS, &wrq) < 0)
1389+ return(IWERR_SET_EXT);
1390+
1391+ /* 1 arg */
1392+ return(1);
1393+}
1394+
1395+/*------------------------------------------------------------------*/
1396+/*
1397+ * Set Retry Limit
1398+ */
1399+static int
1400+set_retry_info(int skfd,
1401+ char * ifname,
1402+ char * args[], /* Command line args */
1403+ int count) /* Args count */
1404+{
1405+ struct iwreq wrq;
1406+ int i = 0;
1407+ double value;
1408+ char * unit;
1409+
1410+ /* Parse modifiers */
1411+ i = parse_modifiers(args, count, &wrq.u.retry.flags,
1412+ iwmod_retry, IWMOD_RETRY_NUM);
1413+ if(i < 0)
1414+ return(i);
1415+
1416+ /* Add default type if none */
1417+ if((wrq.u.retry.flags & IW_RETRY_TYPE) == 0)
1418+ wrq.u.retry.flags |= IW_RETRY_LIMIT;
1419+
1420+ wrq.u.retry.disabled = 0;
1421+
1422+ /* Is there any value to grab ? */
1423+ value = strtod(args[0], &unit);
1424+ if(unit == args[0])
1425+ {
1426+ errarg = i;
1427+ return(IWERR_ARG_TYPE);
1428+ }
1429+
1430+ /* Limit is absolute, on the other hand lifetime is seconds */
1431+ if(wrq.u.retry.flags & IW_RETRY_LIFETIME)
1432+ {
1433+ struct iw_range range;
1434+ /* Extract range info to handle properly 'relative' */
1435+ if(iw_get_range_info(skfd, ifname, &range) < 0)
1436+ memset(&range, 0, sizeof(range));
1437+
1438+ if(range.r_time_flags & IW_RETRY_RELATIVE)
12381439 {
1239- struct iw_range range;
1240-
1241- if(++i >= count)
1242- ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW);
1243-
1244- /* Extract range info */
1245- if(iw_get_range_info(skfd, ifname, &range) < 0)
1246- memset(&range, 0, sizeof(range));
1247-
1248- /* Prepare the request */
1249- wrq.u.txpower.value = -1;
1250- wrq.u.txpower.fixed = 1;
1251- wrq.u.txpower.disabled = 0;
1252- wrq.u.txpower.flags = IW_TXPOW_DBM;
1253- if(!strcasecmp(args[i], "off"))
1254- wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
1440+ if(range.we_version_compiled < 21)
1441+ value *= MEGA;
12551442 else
1256- if(!strcasecmp(args[i], "auto"))
1257- wrq.u.txpower.fixed = 0; /* i.e. use power control */
1258- else
1259- {
1260- if(!strcasecmp(args[i], "on"))
1261- {
1262- /* Get old tx-power */
1263- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1264- "Set Tx Power");
1265- wrq.u.txpower.disabled = 0;
1266- }
1267- else
1268- {
1269- if(!strcasecmp(args[i], "fixed"))
1270- {
1271- /* Get old tx-power */
1272- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1273- "Set Tx Power");
1274- wrq.u.txpower.fixed = 1;
1275- wrq.u.txpower.disabled = 0;
1276- }
1277- else /* Should be a numeric value */
1278- {
1279- int power;
1280- int ismwatt = 0;
1281-
1282- /* Get the value */
1283- if(sscanf(args[i], "%i", &(power)) != 1)
1284- ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW,
1285- args[i]);
1286-
1287- /* Check if milliWatt
1288- * We authorise a single 'm' as a shorthand for 'mW',
1289- * on the other hand a 'd' probably means 'dBm'... */
1290- ismwatt = ((index(args[i], 'm') != NULL)
1291- && (index(args[i], 'd') == NULL));
1292-
1293- /* We could check 'W' alone... Another time... */
1294-
1295- /* Convert */
1296- if(range.txpower_capa & IW_TXPOW_RELATIVE)
1297- {
1298- /* Can't convert */
1299- if(ismwatt)
1300- ABORT_ARG_TYPE("Set Tx Power",
1301- SIOCSIWTXPOW,
1302- args[i]);
1303- }
1304- else
1305- if(range.txpower_capa & IW_TXPOW_MWATT)
1306- {
1307- if(!ismwatt)
1308- power = iw_dbm2mwatt(power);
1309- wrq.u.txpower.flags = IW_TXPOW_MWATT;
1310- }
1311- else
1312- {
1313- if(ismwatt)
1314- power = iw_mwatt2dbm(power);
1315- wrq.u.txpower.flags = IW_TXPOW_DBM;
1316- }
1317- wrq.u.txpower.value = power;
1318-
1319- /* Check for an additional argument */
1320- if(((i+1) < count) &&
1321- (!strcasecmp(args[i+1], "auto")))
1322- {
1323- wrq.u.txpower.fixed = 0;
1324- ++i;
1325- }
1326- if(((i+1) < count) &&
1327- (!strcasecmp(args[i+1], "fixed")))
1328- {
1329- wrq.u.txpower.fixed = 1;
1330- ++i;
1331- }
1332- }
1333- }
1334- }
1335-
1336- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq,
1337- "Set Tx Power");
1338- continue;
1443+ wrq.u.retry.flags |= IW_RETRY_RELATIVE;
13391444 }
1340-
1341- /* ---------- Set Retry limit ---------- */
1342- if(!strncmp(args[i], "retry", 3))
1445+ else
13431446 {
1344- double temp;
1345- int gotone = 0;
1447+ /* Normalise lifetime */
1448+ value *= MEGA; /* default = s */
1449+ if(unit[0] == 'u') value /= MEGA;
1450+ if(unit[0] == 'm') value /= KILO;
1451+ }
1452+ }
1453+ wrq.u.retry.value = (long) value;
1454+ ++i;
13461455
1347- if(++i >= count)
1348- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1456+ if(iw_set_ext(skfd, ifname, SIOCSIWRETRY, &wrq) < 0)
1457+ return(IWERR_SET_EXT);
13491458
1350- /* Default - nope */
1351- wrq.u.retry.flags = IW_RETRY_LIMIT;
1352- wrq.u.retry.disabled = 0;
1459+ /* Var args */
1460+ return(i);
1461+}
13531462
1354- /* Check value modifier */
1355- if(!strcasecmp(args[i], "min"))
1356- {
1357- wrq.u.retry.flags |= IW_RETRY_MIN;
1358- if(++i >= count)
1359- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1360- }
1361- else
1362- if(!strcasecmp(args[i], "max"))
1463+/*------------------------------------------------------------------*/
1464+/*
1465+ * Set RTS Threshold
1466+ */
1467+static int
1468+set_rts_info(int skfd,
1469+ char * ifname,
1470+ char * args[], /* Command line args */
1471+ int count) /* Args count */
1472+{
1473+ struct iwreq wrq;
1474+
1475+ /* Avoid "Unused parameter" warning */
1476+ count = count;
1477+
1478+ wrq.u.rts.value = -1;
1479+ wrq.u.rts.fixed = 1;
1480+ wrq.u.rts.disabled = 0;
1481+
1482+ if(!strcasecmp(args[0], "off"))
1483+ wrq.u.rts.disabled = 1; /* i.e. max size */
1484+ else
1485+ if(!strcasecmp(args[0], "auto"))
1486+ wrq.u.rts.fixed = 0;
1487+ else
1488+ {
1489+ if(!strcasecmp(args[0], "fixed"))
1490+ {
1491+ /* Get old RTS threshold */
1492+ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) < 0)
1493+ return(IWERR_GET_EXT);
1494+ wrq.u.rts.fixed = 1;
1495+ }
1496+ else
1497+ { /* Should be a numeric value */
1498+ long temp;
1499+ if(sscanf(args[0], "%li", (unsigned long *) &(temp)) != 1)
13631500 {
1364- wrq.u.retry.flags |= IW_RETRY_MAX;
1365- if(++i >= count)
1366- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1501+ errarg = 0;
1502+ return(IWERR_ARG_TYPE);
13671503 }
1504+ wrq.u.rts.value = temp;
1505+ }
1506+ }
13681507
1369- /* Check value type */
1370- if(!strcasecmp(args[i], "limit"))
1371- {
1372- wrq.u.retry.flags |= IW_RETRY_LIMIT;
1373- if(++i >= count)
1374- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1375- }
1376- else
1377- if(!strncasecmp(args[i], "lifetime", 4))
1508+ if(iw_set_ext(skfd, ifname, SIOCSIWRTS, &wrq) < 0)
1509+ return(IWERR_SET_EXT);
1510+
1511+ /* 1 arg */
1512+ return(1);
1513+}
1514+
1515+/*------------------------------------------------------------------*/
1516+/*
1517+ * Set Fragmentation Threshold
1518+ */
1519+static int
1520+set_frag_info(int skfd,
1521+ char * ifname,
1522+ char * args[], /* Command line args */
1523+ int count) /* Args count */
1524+{
1525+ struct iwreq wrq;
1526+
1527+ /* Avoid "Unused parameter" warning */
1528+ count = count;
1529+
1530+ wrq.u.frag.value = -1;
1531+ wrq.u.frag.fixed = 1;
1532+ wrq.u.frag.disabled = 0;
1533+
1534+ if(!strcasecmp(args[0], "off"))
1535+ wrq.u.frag.disabled = 1; /* i.e. max size */
1536+ else
1537+ if(!strcasecmp(args[0], "auto"))
1538+ wrq.u.frag.fixed = 0;
1539+ else
1540+ {
1541+ if(!strcasecmp(args[0], "fixed"))
1542+ {
1543+ /* Get old fragmentation threshold */
1544+ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) < 0)
1545+ return(IWERR_GET_EXT);
1546+ wrq.u.frag.fixed = 1;
1547+ }
1548+ else
1549+ { /* Should be a numeric value */
1550+ long temp;
1551+ if(sscanf(args[0], "%li", &(temp))
1552+ != 1)
13781553 {
1379- wrq.u.retry.flags &= ~IW_RETRY_LIMIT;
1380- wrq.u.retry.flags |= IW_RETRY_LIFETIME;
1381- if(++i >= count)
1382- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1554+ errarg = 0;
1555+ return(IWERR_ARG_TYPE);
13831556 }
1557+ wrq.u.frag.value = temp;
1558+ }
1559+ }
1560+
1561+ if(iw_set_ext(skfd, ifname, SIOCSIWFRAG, &wrq) < 0)
1562+ return(IWERR_SET_EXT);
1563+
1564+ /* 1 arg */
1565+ return(1);
1566+}
1567+
1568+/*------------------------------------------------------------------*/
1569+/*
1570+ * Set Modulation
1571+ */
1572+static int
1573+set_modulation_info(int skfd,
1574+ char * ifname,
1575+ char * args[], /* Command line args */
1576+ int count) /* Args count */
1577+{
1578+ struct iwreq wrq;
1579+ int i = 1;
1580+
1581+ /* Avoid "Unused parameter" warning */
1582+ args = args; count = count;
1583+
1584+ if(!strcasecmp(args[0], "auto"))
1585+ wrq.u.param.fixed = 0; /* i.e. use any modulation */
1586+ else
1587+ {
1588+ if(!strcasecmp(args[0], "fixed"))
1589+ {
1590+ /* Get old modulation */
1591+ if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) < 0)
1592+ return(IWERR_GET_EXT);
1593+ wrq.u.param.fixed = 1;
1594+ }
1595+ else
1596+ {
1597+ int k;
13841598
1385- /* Is there any value to grab ? */
1386- if(sscanf(args[i], "%lg", &(temp)) == 1)
1599+ /* Allow multiple modulations, combine them together */
1600+ wrq.u.param.value = 0x0;
1601+ i = 0;
1602+ do
13871603 {
1388- /* Limit is absolute, on the other hand lifetime is seconds */
1389- if(!(wrq.u.retry.flags & IW_RETRY_LIMIT))
1604+ for(k = 0; k < IW_SIZE_MODUL_LIST; k++)
13901605 {
1391- /* Normalise lifetime */
1392- temp *= MEGA; /* default = s */
1393- if(index(args[i], 'u')) temp /= MEGA;
1394- if(index(args[i], 'm')) temp /= KILO;
1606+ if(!strcasecmp(args[i], iw_modul_list[k].cmd))
1607+ {
1608+ wrq.u.param.value |= iw_modul_list[k].mask;
1609+ ++i;
1610+ break;
1611+ }
13951612 }
1396- wrq.u.retry.value = (long) temp;
1613+ }
1614+ /* For as long as current arg matched and not out of args */
1615+ while((i < count) && (k < IW_SIZE_MODUL_LIST));
1616+
1617+ /* Check we got something */
1618+ if(i == 0)
1619+ {
1620+ errarg = 0;
1621+ return(IWERR_ARG_TYPE);
1622+ }
1623+
1624+ /* Check for an additional argument */
1625+ if((i < count) && (!strcasecmp(args[i], "auto")))
1626+ {
1627+ wrq.u.param.fixed = 0;
1628+ ++i;
1629+ }
1630+ if((i < count) && (!strcasecmp(args[i], "fixed")))
1631+ {
1632+ wrq.u.param.fixed = 1;
13971633 ++i;
1398- gotone = 1;
13991634 }
1635+ }
1636+ }
1637+
1638+ if(iw_set_ext(skfd, ifname, SIOCSIWMODUL, &wrq) < 0)
1639+ return(IWERR_SET_EXT);
1640+
1641+ /* Var args */
1642+ return(i);
1643+}
1644+#endif /* WE_ESSENTIAL */
1645+
1646+/*------------------------------------------------------------------*/
1647+/*
1648+ * Set commit
1649+ */
1650+static int
1651+set_commit_info(int skfd,
1652+ char * ifname,
1653+ char * args[], /* Command line args */
1654+ int count) /* Args count */
1655+{
1656+ struct iwreq wrq;
1657+
1658+ /* Avoid "Unused parameter" warning */
1659+ args = args; count = count;
1660+
1661+ if(iw_set_ext(skfd, ifname, SIOCSIWCOMMIT, &wrq) < 0)
1662+ return(IWERR_SET_EXT);
1663+
1664+ /* No args */
1665+ return(0);
1666+}
14001667
1401- if(!gotone)
1402- ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]);
1403- --i;
1668+/************************** SET DISPATCHER **************************/
1669+/*
1670+ * This is a modified version of the dispatcher in iwlist.
1671+ * The main difference is that here we may have multiple commands per
1672+ * line. Also, most commands here do take arguments, and most often
1673+ * a variable number of them.
1674+ * Therefore, the handler *must* return how many args were consumed...
1675+ *
1676+ * Note that the use of multiple commands per line is not advised
1677+ * in scripts, as it makes error management hard. All commands before
1678+ * the error are executed, but commands after the error are not
1679+ * processed.
1680+ * We also try to give as much clue as possible via stderr to the caller
1681+ * on which command did fail, but if there are two time the same command,
1682+ * you don't know which one failed...
1683+ */
14041684
1405- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq,
1406- "Set Retry Limit");
1407- continue;
1685+/*------------------------------------------------------------------*/
1686+/*
1687+ * Map command line arguments to the proper procedure...
1688+ */
1689+typedef struct iwconfig_entry {
1690+ const char * cmd; /* Command line shorthand */
1691+ iw_enum_handler fn; /* Subroutine */
1692+ int min_count;
1693+ int request; /* WE numerical ID */
1694+ const char * name; /* Human readable string */
1695+ const char * argsname; /* Args as human readable string */
1696+} iwconfig_cmd;
1697+
1698+static const struct iwconfig_entry iwconfig_cmds[] = {
1699+ { "essid", set_essid_info, 1, SIOCSIWESSID,
1700+ "Set ESSID", "{NNN|any|on|off}" },
1701+ { "mode", set_mode_info, 1, SIOCSIWMODE,
1702+ "Set Mode", "{managed|ad-hoc|master|...}" },
1703+ { "freq", set_freq_info, 1, SIOCSIWFREQ,
1704+ "Set Frequency", "N.NNN[k|M|G]" },
1705+ { "channel", set_freq_info, 1, SIOCSIWFREQ,
1706+ "Set Frequency", "N" },
1707+ { "bit", set_bitrate_info, 1, SIOCSIWRATE,
1708+ "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
1709+ { "rate", set_bitrate_info, 1, SIOCSIWRATE,
1710+ "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
1711+ { "enc", set_enc_info, 1, SIOCSIWENCODE,
1712+ "Set Encode", "{NNNN-NNNN|off}" },
1713+ { "key", set_enc_info, 1, SIOCSIWENCODE,
1714+ "Set Encode", "{NNNN-NNNN|off}" },
1715+ { "power", set_power_info, 1, SIOCSIWPOWER,
1716+ "Set Power Management", "{period N|timeout N|saving N|off}" },
1717+#ifndef WE_ESSENTIAL
1718+ { "nickname", set_nick_info, 1, SIOCSIWNICKN,
1719+ "Set Nickname", "NNN" },
1720+ { "nwid", set_nwid_info, 1, SIOCSIWNWID,
1721+ "Set NWID", "{NN|on|off}" },
1722+ { "ap", set_apaddr_info, 1, SIOCSIWAP,
1723+ "Set AP Address", "{N|off|auto}" },
1724+ { "txpower", set_txpower_info, 1, SIOCSIWTXPOW,
1725+ "Set Tx Power", "{NmW|NdBm|off|auto}" },
1726+ { "sens", set_sens_info, 1, SIOCSIWSENS,
1727+ "Set Sensitivity", "N" },
1728+ { "retry", set_retry_info, 1, SIOCSIWRETRY,
1729+ "Set Retry Limit", "{limit N|lifetime N}" },
1730+ { "rts", set_rts_info, 1, SIOCSIWRTS,
1731+ "Set RTS Threshold", "{N|auto|fixed|off}" },
1732+ { "frag", set_frag_info, 1, SIOCSIWFRAG,
1733+ "Set Fragmentation Threshold", "{N|auto|fixed|off}" },
1734+ { "modulation", set_modulation_info, 1, SIOCGIWMODUL,
1735+ "Set Modulation", "{11g|11a|CCK|OFDMg|...}" },
1736+#endif /* WE_ESSENTIAL */
1737+ { "commit", set_commit_info, 0, SIOCSIWCOMMIT,
1738+ "Commit changes", "" },
1739+ { NULL, NULL, 0, 0, NULL, NULL },
1740+};
1741+
1742+/*------------------------------------------------------------------*/
1743+/*
1744+ * Find the most appropriate command matching the command line
1745+ */
1746+static inline const iwconfig_cmd *
1747+find_command(const char * cmd)
1748+{
1749+ const iwconfig_cmd * found = NULL;
1750+ int ambig = 0;
1751+ unsigned int len = strlen(cmd);
1752+ int i;
1753+
1754+ /* Go through all commands */
1755+ for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
1756+ {
1757+ /* No match -> next one */
1758+ if(strncasecmp(iwconfig_cmds[i].cmd, cmd, len) != 0)
1759+ continue;
1760+
1761+ /* Exact match -> perfect */
1762+ if(len == strlen(iwconfig_cmds[i].cmd))
1763+ return &iwconfig_cmds[i];
1764+
1765+ /* Partial match */
1766+ if(found == NULL)
1767+ /* First time */
1768+ found = &iwconfig_cmds[i];
1769+ else
1770+ /* Another time */
1771+ if (iwconfig_cmds[i].fn != found->fn)
1772+ ambig = 1;
1773+ }
1774+
1775+ if(found == NULL)
1776+ {
1777+ fprintf(stderr, "iwconfig: unknown command \"%s\"\n", cmd);
1778+ return NULL;
1779+ }
1780+
1781+ if(ambig)
1782+ {
1783+ fprintf(stderr, "iwconfig: command \"%s\" is ambiguous\n", cmd);
1784+ return NULL;
1785+ }
1786+
1787+ return found;
1788+}
1789+
1790+/*------------------------------------------------------------------*/
1791+/*
1792+ * Set the wireless options requested on command line
1793+ * Find the individual commands and call the appropriate subroutine
1794+ */
1795+static int
1796+set_info(int skfd, /* The socket */
1797+ char * args[], /* Command line args */
1798+ int count, /* Args count */
1799+ char * ifname) /* Dev name */
1800+{
1801+ const iwconfig_cmd * iwcmd;
1802+ int ret;
1803+
1804+ /* Loop until we run out of args... */
1805+ while(count > 0)
1806+ {
1807+ /* find the command matching the keyword */
1808+ iwcmd = find_command(args[0]);
1809+ if(iwcmd == NULL)
1810+ {
1811+ /* Here we have an unrecognised arg... Error already printed out. */
1812+ return(-1);
14081813 }
14091814
1410- /* ---------- Other ---------- */
1411- /* Here we have an unrecognised arg... */
1412- fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
1413- args[i]);
1414- return(-1);
1415- } /* for(index ... */
1815+ /* One arg is consumed (the command name) */
1816+ args++;
1817+ count--;
1818+
1819+ /* Check arg numbers */
1820+ if(count < iwcmd->min_count)
1821+ ret = IWERR_ARG_NUM;
1822+ else
1823+ ret = 0;
1824+
1825+ /* Call the command */
1826+ if(!ret)
1827+ ret = (*iwcmd->fn)(skfd, ifname, args, count);
1828+
1829+ /* Deal with various errors */
1830+ if(ret < 0)
1831+ {
1832+ int request = iwcmd->request;
1833+ if(ret == IWERR_GET_EXT)
1834+ request++; /* Transform the SET into GET */
1835+
1836+ fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n",
1837+ iwcmd->name, request);
1838+ switch(ret)
1839+ {
1840+ case IWERR_ARG_NUM:
1841+ fprintf(stderr, " too few arguments.\n");
1842+ break;
1843+ case IWERR_ARG_TYPE:
1844+ if(errarg < 0)
1845+ errarg = 0;
1846+ if(errarg >= count)
1847+ errarg = count - 1;
1848+ fprintf(stderr, " invalid argument \"%s\".\n", args[errarg]);
1849+ break;
1850+ case IWERR_ARG_SIZE:
1851+ fprintf(stderr, " argument too big (max %d)\n", errmax);
1852+ break;
1853+ case IWERR_ARG_CONFLICT:
1854+ if(errarg < 0)
1855+ errarg = 0;
1856+ if(errarg >= count)
1857+ errarg = count - 1;
1858+ fprintf(stderr, " conflicting argument \"%s\".\n", args[errarg]);
1859+ break;
1860+ case IWERR_SET_EXT:
1861+ fprintf(stderr, " SET failed on device %-1.16s ; %s.\n",
1862+ ifname, strerror(errno));
1863+ break;
1864+ case IWERR_GET_EXT:
1865+ fprintf(stderr, " GET failed on device %-1.16s ; %s.\n",
1866+ ifname, strerror(errno));
1867+ break;
1868+ }
1869+ /* Stop processing, we don't know if we are in a consistent state
1870+ * in reading the command line */
1871+ return(ret);
1872+ }
1873+
1874+ /* Substract consumed args from command line */
1875+ args += ret;
1876+ count -= ret;
1877+
1878+ /* Loop back */
1879+ }
1880+
1881+ /* Done, all done */
14161882 return(0);
14171883 }
14181884
1885+/*------------------------------------------------------------------*/
1886+/*
1887+ * Display help
1888+ */
1889+static inline void
1890+iw_usage(void)
1891+{
1892+ int i;
1893+
1894+ fprintf(stderr, "Usage: iwconfig [interface]\n");
1895+ for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
1896+ fprintf(stderr, " interface %s %s\n",
1897+ iwconfig_cmds[i].cmd, iwconfig_cmds[i].argsname);
1898+ fprintf(stderr, " Check man pages for more details.\n");
1899+}
1900+
1901+
14191902 /******************************* MAIN ********************************/
14201903
14211904 /*------------------------------------------------------------------*/
--- a/wireless_tools/iwlib.c
+++ b/wireless_tools/iwlib.c
@@ -1,12 +1,12 @@
11 /*
22 * Wireless Tools
33 *
4- * Jean II - HPLB 97->99 - HPL 99->04
4+ * Jean II - HPLB 97->99 - HPL 99->07
55 *
66 * Common subroutines to all the wireless tools...
77 *
88 * This file is released under the GPL license.
9- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
9+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
1010 */
1111
1212 /***************************** INCLUDES *****************************/
@@ -99,7 +99,44 @@ const char * const iw_operation_mode[] = { "Auto",
9999 "Master",
100100 "Repeater",
101101 "Secondary",
102- "Monitor" };
102+ "Monitor",
103+ "Unknown/bug" };
104+
105+/* Modulations as human readable strings */
106+const struct iw_modul_descr iw_modul_list[] = {
107+ /* Start with aggregate types, so that they display first */
108+ { IW_MODUL_11AG, "11ag",
109+ "IEEE 802.11a + 802.11g (2.4 & 5 GHz, up to 54 Mb/s)" },
110+ { IW_MODUL_11AB, "11ab",
111+ "IEEE 802.11a + 802.11b (2.4 & 5 GHz, up to 54 Mb/s)" },
112+ { IW_MODUL_11G, "11g", "IEEE 802.11g (2.4 GHz, up to 54 Mb/s)" },
113+ { IW_MODUL_11A, "11a", "IEEE 802.11a (5 GHz, up to 54 Mb/s)" },
114+ { IW_MODUL_11B, "11b", "IEEE 802.11b (2.4 GHz, up to 11 Mb/s)" },
115+
116+ /* Proprietary aggregates */
117+ { IW_MODUL_TURBO | IW_MODUL_11A, "turboa",
118+ "Atheros turbo mode at 5 GHz (up to 108 Mb/s)" },
119+ { IW_MODUL_TURBO | IW_MODUL_11G, "turbog",
120+ "Atheros turbo mode at 2.4 GHz (up to 108 Mb/s)" },
121+ { IW_MODUL_PBCC | IW_MODUL_11B, "11+",
122+ "TI 802.11+ (2.4 GHz, up to 22 Mb/s)" },
123+
124+ /* Individual modulations */
125+ { IW_MODUL_OFDM_G, "OFDMg",
126+ "802.11g higher rates, OFDM at 2.4 GHz (up to 54 Mb/s)" },
127+ { IW_MODUL_OFDM_A, "OFDMa", "802.11a, OFDM at 5 GHz (up to 54 Mb/s)" },
128+ { IW_MODUL_CCK, "CCK", "802.11b higher rates (2.4 GHz, up to 11 Mb/s)" },
129+ { IW_MODUL_DS, "DS", "802.11 Direct Sequence (2.4 GHz, up to 2 Mb/s)" },
130+ { IW_MODUL_FH, "FH", "802.11 Frequency Hopping (2,4 GHz, up to 2 Mb/s)" },
131+
132+ /* Proprietary modulations */
133+ { IW_MODUL_TURBO, "turbo",
134+ "Atheros turbo mode, channel bonding (up to 108 Mb/s)" },
135+ { IW_MODUL_PBCC, "PBCC",
136+ "TI 802.11+ higher rates (2.4 GHz, up to 22 Mb/s)" },
137+ { IW_MODUL_CUSTOM, "custom",
138+ "Driver specific modulation (check driver documentation)" },
139+};
103140
104141 /* Disable runtime version warning in iw_get_range_info() */
105142 int iw_ignore_version = 0;
@@ -407,7 +444,7 @@ iw_print_version_info(const char * toolname)
407444 if(toolname != NULL)
408445 printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION);
409446 printf(" Compatible with Wireless Extension v11 to v%d.\n\n",
410- WE_VERSION);
447+ WE_MAX_VERSION);
411448
412449 /* Get version from kernel */
413450 we_kernel_version = iw_get_kernel_we_version();
@@ -521,7 +558,7 @@ iw_get_range_info(int skfd,
521558 if(range->we_version_compiled > WE_MAX_VERSION)
522559 {
523560 fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled);
524- fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_VERSION);
561+ fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_MAX_VERSION);
525562 fprintf(stderr, "Some things may be broken...\n\n");
526563 }
527564
@@ -681,9 +718,12 @@ iw_get_basic_config(int skfd,
681718 /* Get operation mode */
682719 if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
683720 {
684- info->mode = wrq.u.mode;
685- if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
686- info->has_mode = 1;
721+ info->has_mode = 1;
722+ /* Note : event->u.mode is unsigned, no need to check <= 0 */
723+ if(wrq.u.mode < IW_NUM_OPER_MODE)
724+ info->mode = wrq.u.mode;
725+ else
726+ info->mode = IW_NUM_OPER_MODE; /* Unknown/bug */
687727 }
688728
689729 return(0);
@@ -802,10 +842,10 @@ iw_set_basic_config(int skfd,
802842 we_kernel_version = iw_get_kernel_we_version();
803843
804844 wrq.u.essid.pointer = (caddr_t) info->essid;
805- wrq.u.essid.length = strlen(info->essid) + 1;
845+ wrq.u.essid.length = strlen(info->essid);
806846 wrq.u.data.flags = info->essid_on;
807- if(we_kernel_version > 20)
808- wrq.u.essid.length--;
847+ if(we_kernel_version < 21)
848+ wrq.u.essid.length++;
809849
810850 if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
811851 {
@@ -1320,7 +1360,9 @@ iw_print_stats(char * buffer,
13201360 * Further, on 8 bits, 0x100 == 256 == 0.
13211361 *
13221362 * Relative/percent values are always encoded unsigned, between 0 and 255.
1323- * Absolute/dBm values are always encoded negative, between -255 and 0.
1363+ * Absolute/dBm values are always encoded between -192 and 63.
1364+ * (Note that up to version 28 of Wireless Tools, dBm used to be
1365+ * encoded always negative, between -256 and -1).
13241366 *
13251367 * How do we separate relative from absolute values ?
13261368 * The old way is to use the range to do that. As of WE-19, we have
@@ -1329,7 +1371,7 @@ iw_print_stats(char * buffer,
13291371 * range struct only specify one bound of the value, we assume that
13301372 * the other bound is 0 (zero).
13311373 * For relative values, range is [0 ; range->max].
1332- * For absolute values, range is [range->max ; 0].
1374+ * For absolute values, range is [range->max ; 63].
13331375 *
13341376 * Let's take two example :
13351377 * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100
@@ -1343,7 +1385,8 @@ iw_print_stats(char * buffer,
13431385 * The old way to detect dBm require both the range and a non-null
13441386 * level (which confuse the test). The new way can deal with level of 0
13451387 * because it does an explicit test on the flag. */
1346- if(has_range && ((qual->level != 0) || (qual->updated & IW_QUAL_DBM)))
1388+ if(has_range && ((qual->level != 0)
1389+ || (qual->updated & (IW_QUAL_DBM | IW_QUAL_RCPI))))
13471390 {
13481391 /* Deal with quality : always a relative value */
13491392 if(!(qual->updated & IW_QUAL_QUAL_INVALID))
@@ -1355,16 +1398,17 @@ iw_print_stats(char * buffer,
13551398 buflen -= len;
13561399 }
13571400
1358- /* Check if the statistics are in dBm or relative */
1359- if((qual->updated & IW_QUAL_DBM)
1360- || (qual->level > range->max_qual.level))
1401+ /* Check if the statistics are in RCPI (IEEE 802.11k) */
1402+ if(qual->updated & IW_QUAL_RCPI)
13611403 {
1362- /* Deal with signal level in dBm (absolute power measurement) */
1404+ /* Deal with signal level in RCPI */
1405+ /* RCPI = int{(Power in dBm +110)*2} for 0dbm > Power > -110dBm */
13631406 if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
13641407 {
1365- len = snprintf(buffer, buflen, "Signal level%c%d dBm ",
1408+ double rcpilevel = (qual->level / 2.0) - 110.0;
1409+ len = snprintf(buffer, buflen, "Signal level%c%g dBm ",
13661410 qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1367- qual->level - 0x100);
1411+ rcpilevel);
13681412 buffer += len;
13691413 buflen -= len;
13701414 }
@@ -1372,29 +1416,63 @@ iw_print_stats(char * buffer,
13721416 /* Deal with noise level in dBm (absolute power measurement) */
13731417 if(!(qual->updated & IW_QUAL_NOISE_INVALID))
13741418 {
1375- len = snprintf(buffer, buflen, "Noise level%c%d dBm",
1419+ double rcpinoise = (qual->noise / 2.0) - 110.0;
1420+ len = snprintf(buffer, buflen, "Noise level%c%g dBm",
13761421 qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1377- qual->noise - 0x100);
1422+ rcpinoise);
13781423 }
13791424 }
13801425 else
13811426 {
1382- /* Deal with signal level as relative value (0 -> max) */
1383- if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1427+ /* Check if the statistics are in dBm */
1428+ if((qual->updated & IW_QUAL_DBM)
1429+ || (qual->level > range->max_qual.level))
13841430 {
1385- len = snprintf(buffer, buflen, "Signal level%c%d/%d ",
1386- qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1387- qual->level, range->max_qual.level);
1388- buffer += len;
1389- buflen -= len;
1390- }
1431+ /* Deal with signal level in dBm (absolute power measurement) */
1432+ if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1433+ {
1434+ int dblevel = qual->level;
1435+ /* Implement a range for dBm [-192; 63] */
1436+ if(qual->level >= 64)
1437+ dblevel -= 0x100;
1438+ len = snprintf(buffer, buflen, "Signal level%c%d dBm ",
1439+ qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1440+ dblevel);
1441+ buffer += len;
1442+ buflen -= len;
1443+ }
13911444
1392- /* Deal with noise level as relative value (0 -> max) */
1393- if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1445+ /* Deal with noise level in dBm (absolute power measurement) */
1446+ if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1447+ {
1448+ int dbnoise = qual->noise;
1449+ /* Implement a range for dBm [-192; 63] */
1450+ if(qual->noise >= 64)
1451+ dbnoise -= 0x100;
1452+ len = snprintf(buffer, buflen, "Noise level%c%d dBm",
1453+ qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1454+ dbnoise);
1455+ }
1456+ }
1457+ else
13941458 {
1395- len = snprintf(buffer, buflen, "Noise level%c%d/%d",
1396- qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1397- qual->noise, range->max_qual.noise);
1459+ /* Deal with signal level as relative value (0 -> max) */
1460+ if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1461+ {
1462+ len = snprintf(buffer, buflen, "Signal level%c%d/%d ",
1463+ qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1464+ qual->level, range->max_qual.level);
1465+ buffer += len;
1466+ buflen -= len;
1467+ }
1468+
1469+ /* Deal with noise level as relative value (0 -> max) */
1470+ if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1471+ {
1472+ len = snprintf(buffer, buflen, "Noise level%c%d/%d",
1473+ qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1474+ qual->noise, range->max_qual.noise);
1475+ }
13981476 }
13991477 }
14001478 }
@@ -1644,7 +1722,8 @@ void
16441722 iw_print_pm_value(char * buffer,
16451723 int buflen,
16461724 int value,
1647- int flags)
1725+ int flags,
1726+ int we_version)
16481727 {
16491728 /* Check size */
16501729 if(buflen < 25)
@@ -1674,13 +1753,25 @@ iw_print_pm_value(char * buffer,
16741753 }
16751754 else
16761755 {
1677- strcpy(buffer, " period:"); /* Size checked */
1678- buffer += 8;
1756+ if(flags & IW_POWER_SAVING)
1757+ {
1758+ strcpy(buffer, " saving:"); /* Size checked */
1759+ buffer += 8;
1760+ }
1761+ else
1762+ {
1763+ strcpy(buffer, " period:"); /* Size checked */
1764+ buffer += 8;
1765+ }
16791766 }
16801767
16811768 /* Display value without units */
16821769 if(flags & IW_POWER_RELATIVE)
1683- snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
1770+ {
1771+ if(we_version < 21)
1772+ value /= MEGA;
1773+ snprintf(buffer, buflen, "%d", value);
1774+ }
16841775 else
16851776 {
16861777 /* Display value with units */
@@ -1744,15 +1835,16 @@ void
17441835 iw_print_retry_value(char * buffer,
17451836 int buflen,
17461837 int value,
1747- int flags)
1838+ int flags,
1839+ int we_version)
17481840 {
17491841 /* Check buffer size */
1750- if(buflen < 18)
1842+ if(buflen < 20)
17511843 {
17521844 snprintf(buffer, buflen, "<too big>");
17531845 return;
17541846 }
1755- buflen -= 18;
1847+ buflen -= 20;
17561848
17571849 /* Modifiers */
17581850 if(flags & IW_RETRY_MIN)
@@ -1765,6 +1857,16 @@ iw_print_retry_value(char * buffer,
17651857 strcpy(buffer, " max"); /* Size checked */
17661858 buffer += 4;
17671859 }
1860+ if(flags & IW_RETRY_SHORT)
1861+ {
1862+ strcpy(buffer, " short"); /* Size checked */
1863+ buffer += 6;
1864+ }
1865+ if(flags & IW_RETRY_LONG)
1866+ {
1867+ strcpy(buffer, " long"); /* Size checked */
1868+ buffer += 6;
1869+ }
17681870
17691871 /* Type lifetime of limit */
17701872 if(flags & IW_RETRY_LIFETIME)
@@ -1773,8 +1875,12 @@ iw_print_retry_value(char * buffer,
17731875 buffer += 10;
17741876
17751877 /* Display value without units */
1776- if(flags & IW_POWER_RELATIVE)
1777- snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
1878+ if(flags & IW_RETRY_RELATIVE)
1879+ {
1880+ if(we_version < 21)
1881+ value /= MEGA;
1882+ snprintf(buffer, buflen, "%d", value);
1883+ }
17781884 else
17791885 {
17801886 /* Display value with units */
@@ -2125,7 +2231,7 @@ iw_in_addr(int skfd,
21252231 struct sockaddr *sap)
21262232 {
21272233 /* Check if it is a hardware or IP address */
2128- if(index(bufp, ':') == NULL)
2234+ if(strchr(bufp, ':') == NULL)
21292235 {
21302236 struct sockaddr if_address;
21312237 struct arpreq arp_query;
@@ -2467,6 +2573,12 @@ static const struct iw_ioctl_description standard_ioctl_descr[] = {
24672573 [SIOCGIWPOWER - SIOCIWFIRST] = {
24682574 .header_type = IW_HEADER_TYPE_PARAM,
24692575 },
2576+ [SIOCSIWMODUL - SIOCIWFIRST] = {
2577+ .header_type = IW_HEADER_TYPE_PARAM,
2578+ },
2579+ [SIOCGIWMODUL - SIOCIWFIRST] = {
2580+ .header_type = IW_HEADER_TYPE_PARAM,
2581+ },
24702582 [SIOCSIWGENIE - SIOCIWFIRST] = {
24712583 .header_type = IW_HEADER_TYPE_POINT,
24722584 .token_size = 1,
@@ -2560,17 +2672,17 @@ static const unsigned int standard_event_num = (sizeof(standard_event_descr) /
25602672
25612673 /* Size (in bytes) of various events */
25622674 static const int event_type_size[] = {
2563- IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */
2675+ IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */
25642676 0,
2565- IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
2677+ IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */
25662678 0,
2567- IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */
2568- IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */
2569- IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */
2679+ IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */
2680+ IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */
2681+ IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */
25702682 0,
2571- IW_EV_POINT_LEN, /* Without variable payload */
2572- IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */
2573- IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
2683+ IW_EV_POINT_PK_LEN, /* Without variable payload */
2684+ IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */
2685+ IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */
25742686 };
25752687
25762688 /*------------------------------------------------------------------*/
@@ -2607,29 +2719,26 @@ iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
26072719 /* Don't "optimise" the following variable, it will crash */
26082720 unsigned cmd_index; /* *MUST* be unsigned */
26092721
2610- /* Unused for now. Will be later on... */
2611- we_version = we_version;
2612-
26132722 /* Check for end of stream */
2614- if((stream->current + IW_EV_LCP_LEN) > stream->end)
2723+ if((stream->current + IW_EV_LCP_PK_LEN) > stream->end)
26152724 return(0);
26162725
2617-#if DEBUG
2726+#ifdef DEBUG
26182727 printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n",
26192728 stream->current, stream->value, stream->end);
26202729 #endif
26212730
26222731 /* Extract the event header (to get the event id).
26232732 * Note : the event may be unaligned, therefore copy... */
2624- memcpy((char *) iwe, stream->current, IW_EV_LCP_LEN);
2733+ memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN);
26252734
2626-#if DEBUG
2735+#ifdef DEBUG
26272736 printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n",
26282737 iwe->cmd, iwe->len);
26292738 #endif
26302739
26312740 /* Check invalid events */
2632- if(iwe->len <= IW_EV_LCP_LEN)
2741+ if(iwe->len <= IW_EV_LCP_PK_LEN)
26332742 return(-1);
26342743
26352744 /* Get the type and length of that event */
@@ -2647,28 +2756,28 @@ iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
26472756 }
26482757 if(descr != NULL)
26492758 event_type = descr->header_type;
2650- /* Unknown events -> event_type=0 => IW_EV_LCP_LEN */
2759+ /* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */
26512760 event_len = event_type_size[event_type];
26522761 /* Fixup for earlier version of WE */
26532762 if((we_version <= 18) && (event_type == IW_HEADER_TYPE_POINT))
26542763 event_len += IW_EV_POINT_OFF;
26552764
26562765 /* Check if we know about this event */
2657- if(event_len <= IW_EV_LCP_LEN)
2766+ if(event_len <= IW_EV_LCP_PK_LEN)
26582767 {
26592768 /* Skip to next event */
26602769 stream->current += iwe->len;
26612770 return(2);
26622771 }
2663- event_len -= IW_EV_LCP_LEN;
2772+ event_len -= IW_EV_LCP_PK_LEN;
26642773
26652774 /* Set pointer on data */
26662775 if(stream->value != NULL)
26672776 pointer = stream->value; /* Next value in event */
26682777 else
2669- pointer = stream->current + IW_EV_LCP_LEN; /* First value in event */
2778+ pointer = stream->current + IW_EV_LCP_PK_LEN; /* First value in event */
26702779
2671-#if DEBUG
2780+#ifdef DEBUG
26722781 printf("DBG - event_type = %d, event_len = %d, pointer = %p\n",
26732782 event_type, event_len, pointer);
26742783 #endif
@@ -2681,6 +2790,7 @@ iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
26812790 return(-2);
26822791 }
26832792 /* Fixup for WE-19 and later : pointer no longer in the stream */
2793+ /* Beware of alignement. Dest has local alignement, not packed */
26842794 if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))
26852795 memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
26862796 pointer, event_len);
@@ -2694,7 +2804,7 @@ iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
26942804 if(event_type == IW_HEADER_TYPE_POINT)
26952805 {
26962806 /* Check the length of the payload */
2697- unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_LEN);
2807+ unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN);
26982808 if(extra_len > 0)
26992809 {
27002810 /* Set pointer on variable part (warning : non aligned) */
@@ -2709,9 +2819,35 @@ iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
27092819 /* Those checks are actually pretty hard to trigger,
27102820 * because of the checks done in the kernel... */
27112821
2822+ unsigned int token_len = iwe->u.data.length * descr->token_size;
2823+
2824+ /* Ugly fixup for alignement issues.
2825+ * If the kernel is 64 bits and userspace 32 bits,
2826+ * we have an extra 4+4 bytes.
2827+ * Fixing that in the kernel would break 64 bits userspace. */
2828+ if((token_len != extra_len) && (extra_len >= 4))
2829+ {
2830+ __u16 alt_dlen = *((__u16 *) pointer);
2831+ unsigned int alt_token_len = alt_dlen * descr->token_size;
2832+ if((alt_token_len + 8) == extra_len)
2833+ {
2834+#ifdef DEBUG
2835+ printf("DBG - alt_token_len = %d\n", alt_token_len);
2836+#endif
2837+ /* Ok, let's redo everything */
2838+ pointer -= event_len;
2839+ pointer += 4;
2840+ /* Dest has local alignement, not packed */
2841+ memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
2842+ pointer, event_len);
2843+ pointer += event_len + 4;
2844+ iwe->u.data.pointer = pointer;
2845+ token_len = alt_token_len;
2846+ }
2847+ }
2848+
27122849 /* Discard bogus events which advertise more tokens than
27132850 * what they carry... */
2714- unsigned int token_len = iwe->u.data.length * descr->token_size;
27152851 if(token_len > extra_len)
27162852 iwe->u.data.pointer = NULL; /* Discard paylod */
27172853 /* Check that the advertised token size is not going to
@@ -2722,7 +2858,7 @@ iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
27222858 /* Same for underflows... */
27232859 if(iwe->u.data.length < descr->min_tokens)
27242860 iwe->u.data.pointer = NULL; /* Discard paylod */
2725-#if DEBUG
2861+#ifdef DEBUG
27262862 printf("DBG - extra_len = %d, token_len = %d, token = %d, max = %d, min = %d\n",
27272863 extra_len, token_len, iwe->u.data.length, descr->max_tokens, descr->min_tokens);
27282864 #endif
@@ -2737,6 +2873,25 @@ iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
27372873 }
27382874 else
27392875 {
2876+ /* Ugly fixup for alignement issues.
2877+ * If the kernel is 64 bits and userspace 32 bits,
2878+ * we have an extra 4 bytes.
2879+ * Fixing that in the kernel would break 64 bits userspace. */
2880+ if((stream->value == NULL)
2881+ && ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4)
2882+ || ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) ||
2883+ (event_type == IW_HEADER_TYPE_QUAL))) ))
2884+ {
2885+#ifdef DEBUG
2886+ printf("DBG - alt iwe->len = %d\n", iwe->len - 4);
2887+#endif
2888+ pointer -= event_len;
2889+ pointer += 4;
2890+ /* Beware of alignement. Dest has local alignement, not packed */
2891+ memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
2892+ pointer += event_len;
2893+ }
2894+
27402895 /* Is there more value in the event ? */
27412896 if((pointer + event_len) <= (stream->current + iwe->len))
27422897 /* Go to next value */
@@ -2847,8 +3002,14 @@ iw_process_scanning_token(struct iw_event * event,
28473002 memcpy(&wscan->stats.qual, &event->u.qual, sizeof(struct iw_quality));
28483003 break;
28493004 case SIOCGIWRATE:
2850- /* Scan may return a list of bitrates. Should we really bother with
2851- * an array of bitrates ? Or only the maximum bitrate ? Jean II */
3005+ /* Scan may return a list of bitrates. As we have space for only
3006+ * a single bitrate, we only keep the largest one. */
3007+ if((!wscan->has_maxbitrate) ||
3008+ (event->u.bitrate.value > wscan->maxbitrate.value))
3009+ {
3010+ wscan->has_maxbitrate = 1;
3011+ memcpy(&(wscan->maxbitrate), &(event->u.bitrate), sizeof(iwparam));
3012+ }
28523013 case IWEVCUSTOM:
28533014 /* How can we deal with those sanely ? Jean II */
28543015 default:
@@ -2893,7 +3054,9 @@ iw_process_scan(int skfd,
28933054 wrq.u.data.pointer = NULL; /* Later */
28943055 wrq.u.data.flags = 0;
28953056 wrq.u.data.length = 0;
2896- if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
3057+ /* Remember that as non-root, we will get an EPERM here */
3058+ if((iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
3059+ && (errno != EPERM))
28973060 return(-1);
28983061 /* Success : now, just wait for event or results */
28993062 return(250); /* Wait 250 ms */
@@ -2959,7 +3122,7 @@ iw_process_scan(int skfd,
29593122 struct stream_descr stream;
29603123 struct wireless_scan * wscan = NULL;
29613124 int ret;
2962-#if DEBUG
3125+#ifdef DEBUG
29633126 /* Debugging code. In theory useless, because it's debugged ;-) */
29643127 int i;
29653128 printf("Scan result [%02X", buffer[0]);
--- a/wireless_tools/iwlib.h
+++ b/wireless_tools/iwlib.h
@@ -1,12 +1,12 @@
11 /*
22 * Wireless Tools
33 *
4- * Jean II - HPLB 97->99 - HPL 99->04
4+ * Jean II - HPLB 97->99 - HPL 99->07
55 *
66 * Common header for the Wireless Extension library...
77 *
88 * This file is released under the GPL license.
9- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
9+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
1010 */
1111
1212 #ifndef IWLIB_H
@@ -33,41 +33,17 @@
3333 #include <unistd.h>
3434
3535 /* This is our header selection. Try to hide the mess and the misery :-(
36- * Don't look, you would go blind ;-) */
37-
38-#ifndef LINUX_VERSION_CODE
39-#include <linux/version.h>
40-#endif
41-
42-/* Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1
43- * Kernel headers 2.2.X + Glibc 2.2 - Slackware 8.0 */
44-#if defined(__GLIBC__) \
45- && __GLIBC__ == 2 \
46- && __GLIBC_MINOR__ >= 2 \
47- && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
48-#define HEADERS_GENERIC
49-
50-/* Kernel headers 2.4.X + Glibc 2.1 - Debian 2.2 upgraded, RH 7.0
51- * Kernel headers 2.2.X + Glibc 2.1 - Debian 2.2, RH 6.1 */
52-#elif defined(__GLIBC__) \
53- && __GLIBC__ == 2 \
54- && __GLIBC_MINOR__ == 1 \
55- && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
56-#define HEADERS_GENERIC
57-#define HEADERS_KERNEL
58-
59-/* Unsupported combination */
60-#else
61-#error "Your kernel/libc combination is not supported"
62-#endif
36+ * Don't look, you would go blind ;-)
37+ * Note : compatibility with *old* distributions has been removed,
38+ * you will need Glibc 2.2 and older to compile (which means
39+ * Mandrake 8.0, Debian 2.3, RH 7.1 or older).
40+ */
6341
64-#ifdef HEADERS_GENERIC
65-/* Proposed by Dr. Michael Rietz <rietz@mail.amps.de>, 27.3.2 */
42+/* Set of headers proposed by Dr. Michael Rietz <rietz@mail.amps.de>, 27.3.2 */
6643 #include <net/if_arp.h> /* For ARPHRD_ETHER */
6744 #include <sys/socket.h> /* For AF_INET & struct sockaddr */
6845 #include <netinet/in.h> /* For struct sockaddr_in */
6946 #include <netinet/if_ether.h>
70-#endif /* HEADERS_GENERIC */
7147
7248 /* Fixup to be able to include kernel includes in userspace.
7349 * Basically, kill the sparse annotations... Jean II */
@@ -77,15 +53,9 @@
7753
7854 #include <linux/types.h> /* for "caddr_t" et al */
7955
80-#ifdef HEADERS_KERNEL
81-/* Traditionally we have used kernel headers, included in wireless.h */
82-#include <linux/socket.h> /* for "struct sockaddr" et al */
83-#include <linux/if.h> /* for IFNAMSIZ and co... */
84-#else /* !HEADERS_KERNEL */
8556 /* Glibc systems headers are supposedly less problematic than kernel ones */
8657 #include <sys/socket.h> /* for "struct sockaddr" et al */
8758 #include <net/if.h> /* for IFNAMSIZ and co... */
88-#endif /* !HEADERS_KERNEL */
8959
9060 /* Private copy of Wireless extensions (in this directoty) */
9161 #include "wireless.h"
@@ -126,16 +96,17 @@ extern "C" {
12696
12797 /****************************** DEBUG ******************************/
12898
99+//#define DEBUG 1
129100
130101 /************************ CONSTANTS & MACROS ************************/
131102
132103 /* Various versions information */
133104 /* Recommended Wireless Extension version */
134-#define WE_VERSION 20
105+#define WE_VERSION 21
135106 /* Maximum forward compatibility built in this version of WT */
136-#define WE_MAX_VERSION 21
107+#define WE_MAX_VERSION 22
137108 /* Version of Wireless Tools */
138-#define WT_VERSION 28
109+#define WT_VERSION 29
139110
140111 /* Paths */
141112 #define PROC_NET_WIRELESS "/proc/net/wireless"
@@ -153,6 +124,36 @@ extern "C" {
153124 #define ARPHRD_IEEE80211 801 /* IEEE 802.11 */
154125 #endif /* ARPHRD_IEEE80211 */
155126
127+#ifndef IW_EV_LCP_PK_LEN
128+/* Size of the Event prefix when packed in stream */
129+#define IW_EV_LCP_PK_LEN (4)
130+/* Size of the various events when packed in stream */
131+#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ)
132+#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32))
133+#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
134+#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
135+#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
136+#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
137+#define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4)
138+
139+struct iw_pk_event
140+{
141+ __u16 len; /* Real lenght of this stuff */
142+ __u16 cmd; /* Wireless IOCTL */
143+ union iwreq_data u; /* IOCTL fixed payload */
144+} __attribute__ ((packed));
145+struct iw_pk_point
146+{
147+ void __user *pointer; /* Pointer to the data (in user space) */
148+ __u16 length; /* number of fields or size in bytes */
149+ __u16 flags; /* Optional params */
150+} __attribute__ ((packed));
151+
152+#define IW_EV_LCP_PK2_LEN (sizeof(struct iw_pk_event) - sizeof(union iwreq_data))
153+#define IW_EV_POINT_PK2_LEN (IW_EV_LCP_PK2_LEN + sizeof(struct iw_pk_point) - IW_EV_POINT_OFF)
154+
155+#endif /* IW_EV_LCP_PK_LEN */
156+
156157 /****************************** TYPES ******************************/
157158
158159 /* Shortcuts */
@@ -244,6 +245,8 @@ typedef struct wireless_scan
244245 struct wireless_config b; /* Basic information */
245246 iwstats stats; /* Signal strength */
246247 int has_stats;
248+ iwparam maxbitrate; /* Max bit rate in bps */
249+ int has_maxbitrate;
247250 } wireless_scan;
248251
249252 /*
@@ -271,6 +274,14 @@ typedef int (*iw_enum_handler)(int skfd,
271274 char * args[],
272275 int count);
273276
277+/* Describe a modulation */
278+typedef struct iw_modul_descr
279+{
280+ unsigned int mask; /* Modulation bitmask */
281+ char cmd[8]; /* Short name */
282+ char * verbose; /* Verbose description */
283+} iw_modul_descr;
284+
274285 /**************************** PROTOTYPES ****************************/
275286 /*
276287 * All the functions in iwcommon.c
@@ -379,7 +390,8 @@ void
379390 iw_print_pm_value(char * buffer,
380391 int buflen,
381392 int value,
382- int flags);
393+ int flags,
394+ int we_version);
383395 void
384396 iw_print_pm_mode(char * buffer,
385397 int buflen,
@@ -389,7 +401,8 @@ void
389401 iw_print_retry_value(char * buffer,
390402 int buflen,
391403 int value,
392- int flags);
404+ int flags,
405+ int we_version);
393406 /* ----------------------- TIME SUBROUTINES ----------------------- */
394407 void
395408 iw_print_timeval(char * buffer,
@@ -469,6 +482,11 @@ int
469482 /* Modes as human readable strings */
470483 extern const char * const iw_operation_mode[];
471484 #define IW_NUM_OPER_MODE 7
485+#define IW_NUM_OPER_MODE_EXT 8
486+
487+/* Modulations as human readable strings */
488+extern const struct iw_modul_descr iw_modul_list[];
489+#define IW_SIZE_MODUL_LIST 16
472490
473491 /************************* INLINE FUNTIONS *************************/
474492 /*
--- a/wireless_tools/iwlist.8
+++ b/wireless_tools/iwlist.8
@@ -1,7 +1,7 @@
11 .\" Jean II - HPLB - 96
22 .\" iwlist.8
33 .\"
4-.TH IWLIST 8 "23 June 2004" "wireless-tools" "Linux Programmer's Manual"
4+.TH IWLIST 8 "13 April 2006" "wireless-tools" "Linux Programmer's Manual"
55 .\"
66 .\" NAME part
77 .\"
@@ -11,21 +11,29 @@ iwlist \- Get more detailed wireless information from a wireless interface
1111 .\" SYNOPSIS part
1212 .\"
1313 .SH SYNOPSIS
14-.BI "iwlist " interface " scanning"
14+.BI "iwlist [" interface "] scanning"
1515 .br
16-.BI "iwlist " interface " frequency"
16+.BI "iwlist [" interface "] frequency"
1717 .br
18-.BI "iwlist " interface " rate"
18+.BI "iwlist [" interface "] rate"
1919 .br
20-.BI "iwlist " interface " key"
20+.BI "iwlist [" interface "] keys"
2121 .br
22-.BI "iwlist " interface " power"
22+.BI "iwlist [" interface "] power"
2323 .br
24-.BI "iwlist " interface " txpower"
24+.BI "iwlist [" interface "] txpower"
2525 .br
26-.BI "iwlist " interface " retry"
26+.BI "iwlist [" interface "] retry"
2727 .br
28-.BI "iwlist " interface " event"
28+.BI "iwlist [" interface "] event"
29+.br
30+.BI "iwlist [" interface "] auth"
31+.br
32+.BI "iwlist [" interface "] wpakeys"
33+.br
34+.BI "iwlist [" interface "] genie"
35+.br
36+.BI "iwlist [" interface "] modulation"
2937 .br
3038 .BI "iwlist --help"
3139 .br
@@ -58,10 +66,15 @@ the card supports.
5866 Triggering scanning is a privileged operation
5967 .RI ( root
6068 only) and normal users can only read left-over scan results. By
61-default, the way scanning is done (the scope of the scan) will be
62-impacted by the current setting of the driver. Also, this command is
63-supposed to take extra arguments to control the scanning behaviour,
64-but this is currently not implemented.
69+default, the way scanning is done (the scope of the scan) is dependant
70+on the card and card settings.
71+.br
72+This command take optional arguments, however most drivers will ignore
73+those. The option
74+.B essid
75+is used to specify a scan on a specific ESSID. The option
76+.B last
77+do not trigger a scan and read left-over scan results.
6578 .TP
6679 .BR freq [uency]/ channel
6780 Give the list of available frequencies in the device and the number of
@@ -73,9 +86,9 @@ displayed and channel numbers.
7386 .BR rate / bit [rate]
7487 List the bit-rates supported by the device.
7588 .TP
76-.BR key / enc [ryption]
77-List the encryption key sizes supported and display all the encryption
78-keys available in the device.
89+.BR keys / enc [ryption]
90+List the encryption key sizes supported and list all the encryption
91+keys set in the device.
7992 .TP
8093 .B power
8194 List the various Power Management attributes and modes of the device.
@@ -100,10 +113,27 @@ the card. See your driver documentation for details.
100113 .B event
101114 List the wireless events supported by the device.
102115 .TP
116+.B auth
117+List the WPA authentication parametes curently set.
118+.TP
119+.BR wpa [keys]
120+List all the WPA encryption keys set in the device.
121+.TP
122+.B genie
123+List the Generic Information Elements set in the device (used for WPA
124+support).
125+.TP
126+.BR modu [lation]
127+List the modulations supported by the device and the modulations
128+currently enabled.
129+.TP
103130 .B --version
104131 Display the version of the tools, as well as the recommended and
105132 current Wireless Extensions version for the tool and the various
106133 wireless interfaces.
134+.TP
135+.B --help
136+Display short help message.
107137 .\"
108138 .\" FILES part
109139 .\"
--- a/wireless_tools/iwlist.c
+++ b/wireless_tools/iwlist.c
@@ -1,14 +1,14 @@
11 /*
22 * Wireless Tools
33 *
4- * Jean II - HPLB '99 - HPL 99->04
4+ * Jean II - HPLB '99 - HPL 99->07
55 *
66 * This tool can access various piece of information on the card
77 * not part of iwconfig...
88 * You need to link this code against "iwlist.c" and "-lm".
99 *
1010 * This file is released under the GPL license.
11- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
11+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
1212 */
1313
1414 #include "iwlib.h" /* Header */
@@ -26,758 +26,412 @@ typedef struct iwscan_state
2626 int val_index; /* Value in table 0->(N-1) */
2727 } iwscan_state;
2828
29+/*
30+ * Bit to name mapping
31+ */
32+typedef struct iwmask_name
33+{
34+ unsigned int mask; /* bit mask for the value */
35+ const char * name; /* human readable name for the value */
36+} iwmask_name;
2937
30-/*********************** FREQUENCIES/CHANNELS ***********************/
31-
32-/*------------------------------------------------------------------*/
3338 /*
34- * Print the number of channels and available frequency for the device
39+ * Types of authentication parameters
3540 */
36-static int
37-print_freq_info(int skfd,
38- char * ifname,
39- char * args[], /* Command line args */
40- int count) /* Args count */
41+typedef struct iw_auth_descr
4142 {
42- struct iwreq wrq;
43- struct iw_range range;
44- double freq;
45- int k;
46- int channel;
47- char buffer[128]; /* Temporary buffer */
43+ int value; /* Type of auth value */
44+ const char * label; /* User readable version */
45+ const struct iwmask_name * names; /* Names for this value */
46+ const int num_names; /* Number of names */
47+} iw_auth_descr;
4848
49- /* Avoid "Unused parameter" warning */
50- args = args; count = count;
49+/**************************** CONSTANTS ****************************/
5150
52- /* Get list of frequencies / channels */
53- if(iw_get_range_info(skfd, ifname, &range) < 0)
54- fprintf(stderr, "%-8.16s no frequency information.\n\n",
55- ifname);
56- else
57- {
58- if(range.num_frequency > 0)
59- {
60- printf("%-8.16s %d channels in total; available frequencies :\n",
61- ifname, range.num_channels);
62- /* Print them all */
63- for(k = 0; k < range.num_frequency; k++)
64- {
65- freq = iw_freq2float(&(range.freq[k]));
66- iw_print_freq_value(buffer, sizeof(buffer), freq);
67- printf(" Channel %.2d : %s\n",
68- range.freq[k].i, buffer);
69- }
70- }
71- else
72- printf("%-8.16s %d channels\n",
73- ifname, range.num_channels);
51+#define IW_SCAN_HACK 0x8000
7452
75- /* Get current frequency / channel and display it */
76- if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
77- {
78- freq = iw_freq2float(&(wrq.u.freq));
79- channel = iw_freq_to_channel(freq, &range);
80- iw_print_freq(buffer, sizeof(buffer),
81- freq, channel, wrq.u.freq.flags);
82- printf(" Current %s\n\n", buffer);
83- }
84- }
85- return(0);
86-}
53+#define IW_EXTKEY_SIZE (sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX)
8754
88-/************************ ACCESS POINT LIST ************************/
55+/* ------------------------ WPA CAPA NAMES ------------------------ */
8956 /*
90- * Note : now that we have scanning support, this is depracted and
91- * won't survive long. Actually, next version it's out !
57+ * This is the user readable name of a bunch of WPA constants in wireless.h
58+ * Maybe this should go in iwlib.c ?
9259 */
9360
94-/*------------------------------------------------------------------*/
95-/*
96- * Display the list of ap addresses and the associated stats
97- * Exacly the same as the spy list, only with different IOCTL and messages
98- */
99-static int
100-print_ap_info(int skfd,
101- char * ifname,
102- char * args[], /* Command line args */
103- int count) /* Args count */
104-{
105- struct iwreq wrq;
106- char buffer[(sizeof(struct iw_quality) +
107- sizeof(struct sockaddr)) * IW_MAX_AP];
108- char temp[128];
109- struct sockaddr * hwa;
110- struct iw_quality * qual;
111- iwrange range;
112- int has_range = 0;
113- int has_qual = 0;
114- int n;
115- int i;
61+#ifndef WE_ESSENTIAL
62+#define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0]))
11663
117- /* Avoid "Unused parameter" warning */
118- args = args; count = count;
64+//static const struct iwmask_name iw_enc_mode_name[] = {
65+// { IW_ENCODE_RESTRICTED, "restricted" },
66+// { IW_ENCODE_OPEN, "open" },
67+//};
68+//#define IW_ENC_MODE_NUM IW_ARRAY_LEN(iw_enc_mode_name)
11969
120- /* Collect stats */
121- wrq.u.data.pointer = (caddr_t) buffer;
122- wrq.u.data.length = IW_MAX_AP;
123- wrq.u.data.flags = 0;
124- if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
125- {
126- fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
127- return(-1);
128- }
70+static const struct iwmask_name iw_auth_capa_name[] = {
71+ { IW_ENC_CAPA_WPA, "WPA" },
72+ { IW_ENC_CAPA_WPA2, "WPA2" },
73+ { IW_ENC_CAPA_CIPHER_TKIP, "CIPHER-TKIP" },
74+ { IW_ENC_CAPA_CIPHER_CCMP, "CIPHER-CCMP" },
75+};
76+#define IW_AUTH_CAPA_NUM IW_ARRAY_LEN(iw_auth_capa_name)
77+
78+static const struct iwmask_name iw_auth_cypher_name[] = {
79+ { IW_AUTH_CIPHER_NONE, "none" },
80+ { IW_AUTH_CIPHER_WEP40, "WEP-40" },
81+ { IW_AUTH_CIPHER_TKIP, "TKIP" },
82+ { IW_AUTH_CIPHER_CCMP, "CCMP" },
83+ { IW_AUTH_CIPHER_WEP104, "WEP-104" },
84+};
85+#define IW_AUTH_CYPHER_NUM IW_ARRAY_LEN(iw_auth_cypher_name)
12986
130- /* Number of addresses */
131- n = wrq.u.data.length;
132- has_qual = wrq.u.data.flags;
87+static const struct iwmask_name iw_wpa_ver_name[] = {
88+ { IW_AUTH_WPA_VERSION_DISABLED, "disabled" },
89+ { IW_AUTH_WPA_VERSION_WPA, "WPA" },
90+ { IW_AUTH_WPA_VERSION_WPA2, "WPA2" },
91+};
92+#define IW_WPA_VER_NUM IW_ARRAY_LEN(iw_wpa_ver_name)
13393
134- /* The two lists */
135- hwa = (struct sockaddr *) buffer;
136- qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
94+static const struct iwmask_name iw_auth_key_mgmt_name[] = {
95+ { IW_AUTH_KEY_MGMT_802_1X, "802.1x" },
96+ { IW_AUTH_KEY_MGMT_PSK, "PSK" },
97+};
98+#define IW_AUTH_KEY_MGMT_NUM IW_ARRAY_LEN(iw_auth_key_mgmt_name)
13799
138- /* Check if we have valid mac address type */
139- if(iw_check_mac_addr_type(skfd, ifname) < 0)
140- {
141- fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
142- return(-2);
143- }
100+static const struct iwmask_name iw_auth_alg_name[] = {
101+ { IW_AUTH_ALG_OPEN_SYSTEM, "open" },
102+ { IW_AUTH_ALG_SHARED_KEY, "shared-key" },
103+ { IW_AUTH_ALG_LEAP, "LEAP" },
104+};
105+#define IW_AUTH_ALG_NUM IW_ARRAY_LEN(iw_auth_alg_name)
106+
107+static const struct iw_auth_descr iw_auth_settings[] = {
108+ { IW_AUTH_WPA_VERSION, "WPA version", iw_wpa_ver_name, IW_WPA_VER_NUM },
109+ { IW_AUTH_KEY_MGMT, "Key management", iw_auth_key_mgmt_name, IW_AUTH_KEY_MGMT_NUM },
110+ { IW_AUTH_CIPHER_PAIRWISE, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
111+ { IW_AUTH_CIPHER_GROUP, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
112+ { IW_AUTH_TKIP_COUNTERMEASURES, "TKIP countermeasures", NULL, 0 },
113+ { IW_AUTH_DROP_UNENCRYPTED, "Drop unencrypted", NULL, 0 },
114+ { IW_AUTH_80211_AUTH_ALG, "Authentication algorithm", iw_auth_alg_name, IW_AUTH_ALG_NUM },
115+ { IW_AUTH_RX_UNENCRYPTED_EAPOL, "Receive unencrypted EAPOL", NULL, 0 },
116+ { IW_AUTH_ROAMING_CONTROL, "Roaming control", NULL, 0 },
117+ { IW_AUTH_PRIVACY_INVOKED, "Privacy invoked", NULL, 0 },
118+};
119+#define IW_AUTH_SETTINGS_NUM IW_ARRAY_LEN(iw_auth_settings)
120+
121+/* Values for the IW_ENCODE_ALG_* returned by SIOCSIWENCODEEXT */
122+static const char * iw_encode_alg_name[] = {
123+ "none",
124+ "WEP",
125+ "TKIP",
126+ "CCMP",
127+ "unknown"
128+};
129+#define IW_ENCODE_ALG_NUM IW_ARRAY_LEN(iw_encode_alg_name)
130+
131+#ifndef IW_IE_CIPHER_NONE
132+/* Cypher values in GENIE (pairwise and group) */
133+#define IW_IE_CIPHER_NONE 0
134+#define IW_IE_CIPHER_WEP40 1
135+#define IW_IE_CIPHER_TKIP 2
136+#define IW_IE_CIPHER_WRAP 3
137+#define IW_IE_CIPHER_CCMP 4
138+#define IW_IE_CIPHER_WEP104 5
139+/* Key management in GENIE */
140+#define IW_IE_KEY_MGMT_NONE 0
141+#define IW_IE_KEY_MGMT_802_1X 1
142+#define IW_IE_KEY_MGMT_PSK 2
143+#endif /* IW_IE_CIPHER_NONE */
144+
145+/* Values for the IW_IE_CIPHER_* in GENIE */
146+static const char * iw_ie_cypher_name[] = {
147+ "none",
148+ "WEP-40",
149+ "TKIP",
150+ "WRAP",
151+ "CCMP",
152+ "WEP-104",
153+};
154+#define IW_IE_CYPHER_NUM IW_ARRAY_LEN(iw_ie_cypher_name)
144155
145- /* Get range info if we can */
146- if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
147- has_range = 1;
156+/* Values for the IW_IE_KEY_MGMT_* in GENIE */
157+static const char * iw_ie_key_mgmt_name[] = {
158+ "none",
159+ "802.1x",
160+ "PSK",
161+};
162+#define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name)
148163
149- /* Display it */
150- if(n == 0)
151- printf("%-8.16s No Peers/Access-Point in range\n", ifname);
152- else
153- printf("%-8.16s Peers/Access-Points in range:\n", ifname);
154- for(i = 0; i < n; i++)
164+#endif /* WE_ESSENTIAL */
165+
166+/************************* WPA SUBROUTINES *************************/
167+
168+#ifndef WE_ESSENTIAL
169+/*------------------------------------------------------------------*/
170+/*
171+ * Print all names corresponding to a mask.
172+ * This may want to be used in iw_print_retry_value() ?
173+ */
174+static void
175+iw_print_mask_name(unsigned int mask,
176+ const struct iwmask_name names[],
177+ const unsigned int num_names,
178+ const char * sep)
179+{
180+ unsigned int i;
181+
182+ /* Print out all names for the bitmask */
183+ for(i = 0; i < num_names; i++)
155184 {
156- if(has_qual)
185+ if(mask & names[i].mask)
157186 {
158- /* Print stats for this address */
159- printf(" %s : ", iw_saether_ntop(&hwa[i], temp));
160- iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
161- printf("%s\n", temp);
187+ /* Print out */
188+ printf("%s%s", sep, names[i].name);
189+ /* Remove the bit from the mask */
190+ mask &= ~names[i].mask;
162191 }
163- else
164- /* Only print the address */
165- printf(" %s\n", iw_saether_ntop(&hwa[i], temp));
166192 }
167- printf("\n");
168- return(0);
193+ /* If there is unconsumed bits... */
194+ if(mask != 0)
195+ printf("%sUnknown", sep);
169196 }
170197
171-/***************************** BITRATES *****************************/
172-
173198 /*------------------------------------------------------------------*/
174199 /*
175- * Print the number of available bitrates for the device
200+ * Print the name corresponding to a value, with overflow check.
176201 */
177-static int
178-print_bitrate_info(int skfd,
179- char * ifname,
180- char * args[], /* Command line args */
181- int count) /* Args count */
202+static void
203+iw_print_value_name(unsigned int value,
204+ const char * names[],
205+ const unsigned int num_names)
182206 {
183- struct iwreq wrq;
184- struct iw_range range;
185- int k;
186- char buffer[128];
207+ if(value >= num_names)
208+ printf(" unknown (%d)", value);
209+ else
210+ printf(" %s", names[value]);
211+}
187212
188- /* Avoid "Unused parameter" warning */
189- args = args; count = count;
213+/*------------------------------------------------------------------*/
214+/*
215+ * Parse, and display the results of an unknown IE.
216+ *
217+ */
218+static void
219+iw_print_ie_unknown(unsigned char * iebuf,
220+ int buflen)
221+{
222+ int ielen = iebuf[1] + 2;
223+ int i;
190224
191- /* Extract range info */
192- if(iw_get_range_info(skfd, ifname, &range) < 0)
193- fprintf(stderr, "%-8.16s no bit-rate information.\n\n",
194- ifname);
195- else
196- {
197- if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
198- {
199- printf("%-8.16s %d available bit-rates :\n",
200- ifname, range.num_bitrates);
201- /* Print them all */
202- for(k = 0; k < range.num_bitrates; k++)
203- {
204- iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
205- /* Maybe this should be %10s */
206- printf("\t %s\n", buffer);
207- }
208- }
209- else
210- printf("%-8.16s unknown bit-rate information.\n", ifname);
225+ if(ielen > buflen)
226+ ielen = buflen;
211227
212- /* Get current bit rate */
213- if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
214- {
215- iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
216- printf(" Current Bit Rate%c%s\n\n",
217- (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
218- }
219- }
220- return(0);
228+ printf("Unknown: ");
229+ for(i = 0; i < ielen; i++)
230+ printf("%02X", iebuf[i]);
231+ printf("\n");
221232 }
222233
223-/************************* ENCRYPTION KEYS *************************/
224-
225234 /*------------------------------------------------------------------*/
226235 /*
227- * Print the number of available encryption key for the device
236+ * Parse, and display the results of a WPA or WPA2 IE.
237+ *
228238 */
229-static int
230-print_keys_info(int skfd,
231- char * ifname,
232- char * args[], /* Command line args */
233- int count) /* Args count */
239+static inline void
240+iw_print_ie_wpa(unsigned char * iebuf,
241+ int buflen)
234242 {
235- struct iwreq wrq;
236- struct iw_range range;
237- unsigned char key[IW_ENCODING_TOKEN_MAX];
238- int k;
239- char buffer[128];
243+ int ielen = iebuf[1] + 2;
244+ int offset = 2; /* Skip the IE id, and the length. */
245+ unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
246+ unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
247+ unsigned char * wpa_oui;
248+ int i;
249+ uint16_t ver = 0;
250+ uint16_t cnt = 0;
240251
241- /* Avoid "Unused parameter" warning */
242- args = args; count = count;
252+ if(ielen > buflen)
253+ ielen = buflen;
243254
244- /* Extract range info */
245- if(iw_get_range_info(skfd, ifname, &range) < 0)
246- fprintf(stderr, "%-8.16s no encryption keys information.\n\n",
247- ifname);
248- else
255+#ifdef DEBUG
256+ /* Debugging code. In theory useless, because it's debugged ;-) */
257+ printf("IE raw value %d [%02X", buflen, iebuf[0]);
258+ for(i = 1; i < buflen; i++)
259+ printf(":%02X", iebuf[i]);
260+ printf("]\n");
261+#endif
262+
263+ switch(iebuf[0])
249264 {
250- printf("%-8.16s ", ifname);
251- /* Print key sizes */
252- if((range.num_encoding_sizes > 0) &&
253- (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
265+ case 0x30: /* WPA2 */
266+ /* Check if we have enough data */
267+ if(ielen < 4)
254268 {
255- printf("%d key sizes : %d", range.num_encoding_sizes,
256- range.encoding_size[0] * 8);
257- /* Print them all */
258- for(k = 1; k < range.num_encoding_sizes; k++)
259- printf(", %d", range.encoding_size[k] * 8);
260- printf("bits\n ");
269+ iw_print_ie_unknown(iebuf, buflen);
270+ return;
261271 }
262- /* Print the keys and associate mode */
263- printf("%d keys available :\n", range.max_encoding_tokens);
264- for(k = 1; k <= range.max_encoding_tokens; k++)
265- {
266- wrq.u.data.pointer = (caddr_t) key;
267- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
268- wrq.u.data.flags = k;
269- if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
270- {
271- fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno));
272- break;
273- }
274- if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
275- (wrq.u.data.length == 0))
276- printf("\t\t[%d]: off\n", k);
277- else
278- {
279- /* Display the key */
280- iw_print_key(buffer, sizeof(buffer),
281- key, wrq.u.data.length, wrq.u.data.flags);
282- printf("\t\t[%d]: %s", k, buffer);
283272
284- /* Other info... */
285- printf(" (%d bits)", wrq.u.data.length * 8);
286- printf("\n");
287- }
288- }
289- /* Print current key and mode */
290- wrq.u.data.pointer = (caddr_t) key;
291- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
292- wrq.u.data.flags = 0; /* Set index to zero to get current */
293- if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
294- {
295- /* Note : if above fails, we have already printed an error
296- * message int the loop above */
297- printf(" Current Transmit Key: [%d]\n",
298- wrq.u.data.flags & IW_ENCODE_INDEX);
299- if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
300- printf(" Security mode:restricted\n");
301- if(wrq.u.data.flags & IW_ENCODE_OPEN)
302- printf(" Security mode:open\n");
303- }
273+ wpa_oui = wpa2_oui;
274+ break;
304275
305- /* Print WPA/802.1x/802.11i security parameters */
306- if(range.we_version_compiled > 17)
307- {
308- /* Display advance encryption capabilities */
309- if(range.enc_capa)
310- {
311- const char * auth_string[] = { "WPA",
312- "WPA2",
313- "CIPHER TKIP",
314- "CIPHER CCMP" };
315- const int auth_num = (sizeof(auth_string) /
316- sizeof(auth_string[1]));
317- int i;
318- int mask = 0x1;
319-
320- printf(" Authentication capabilities :\n");
321- for(i = 0; i < auth_num; i++)
322- {
323- if(range.enc_capa & mask)
324- printf("\t\t%s\n", auth_string[i]);
325- mask <<= 1;
326- }
327- }
276+ case 0xdd: /* WPA or else */
277+ wpa_oui = wpa1_oui;
278+
279+ /* Not all IEs that start with 0xdd are WPA.
280+ * So check that the OUI is valid. Note : offset==2 */
281+ if((ielen < 8)
282+ || (memcmp(&iebuf[offset], wpa_oui, 3) != 0)
283+ || (iebuf[offset + 3] != 0x01))
284+ {
285+ iw_print_ie_unknown(iebuf, buflen);
286+ return;
287+ }
328288
329- /* Current values for authentication */
330- wrq.u.param.flags = IW_AUTH_KEY_MGMT;
331- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
332- printf(" Current key_mgmt:0x%X\n",
333- wrq.u.param.value);
334-
335- wrq.u.param.flags = IW_AUTH_CIPHER_PAIRWISE;
336- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
337- printf(" Current cipher_pairwise:0x%X\n",
338- wrq.u.param.value);
339-
340- wrq.u.param.flags = IW_AUTH_CIPHER_GROUP;
341- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
342- printf(" Current cipher_group:0x%X\n",
343- wrq.u.param.value);
344- }
289+ /* Skip the OUI type */
290+ offset += 4;
291+ break;
345292
346- printf("\n\n");
293+ default:
294+ return;
347295 }
348- return(0);
349-}
296+
297+ /* Pick version number (little endian) */
298+ ver = iebuf[offset] | (iebuf[offset + 1] << 8);
299+ offset += 2;
350300
351-/************************* POWER MANAGEMENT *************************/
301+ if(iebuf[0] == 0xdd)
302+ printf("WPA Version %d\n", ver);
303+ if(iebuf[0] == 0x30)
304+ printf("IEEE 802.11i/WPA2 Version %d\n", ver);
352305
353-/*------------------------------------------------------------------*/
354-/*
355- * Print Power Management info for each device
356- */
357-static inline int
358-get_pm_value(int skfd,
359- char * ifname,
360- struct iwreq * pwrq,
361- int flags,
362- char * buffer,
363- int buflen)
364-{
365- /* Get Another Power Management value */
366- pwrq->u.power.flags = flags;
367- if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
306+ /* From here, everything is technically optional. */
307+
308+ /* Check if we are done */
309+ if(ielen < (offset + 4))
368310 {
369- /* Let's check the value and its type */
370- if(pwrq->u.power.flags & IW_POWER_TYPE)
371- {
372- iw_print_pm_value(buffer, buflen,
373- pwrq->u.power.value, pwrq->u.power.flags);
374- printf("\n %s", buffer);
375- }
311+ /* We have a short IE. So we should assume TKIP/TKIP. */
312+ printf(" Group Cipher : TKIP\n");
313+ printf(" Pairwise Cipher : TKIP\n");
314+ return;
315+ }
316+
317+ /* Next we have our group cipher. */
318+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
319+ {
320+ printf(" Group Cipher : Proprietary\n");
376321 }
377- return(pwrq->u.power.flags);
378-}
379-
380-/*------------------------------------------------------------------*/
381-/*
382- * Print Power Management info for each device
383- */
384-static int
385-print_pm_info(int skfd,
386- char * ifname,
387- char * args[], /* Command line args */
388- int count) /* Args count */
389-{
390- struct iwreq wrq;
391- struct iw_range range;
392- char buffer[128];
393-
394- /* Avoid "Unused parameter" warning */
395- args = args; count = count;
396-
397- /* Extract range info */
398- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
399- (range.we_version_compiled < 10))
400- fprintf(stderr, "%-8.16s no power management information.\n\n",
401- ifname);
402322 else
403323 {
404- printf("%-8.16s ", ifname);
324+ printf(" Group Cipher :");
325+ iw_print_value_name(iebuf[offset+3],
326+ iw_ie_cypher_name, IW_IE_CYPHER_NUM);
327+ printf("\n");
328+ }
329+ offset += 4;
405330
406- /* Display modes availables */
407- if(range.pm_capa & IW_POWER_MODE)
408- {
409- printf("Supported modes :\n ");
410- if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
411- printf("\t\to Receive all packets (unicast & multicast)\n ");
412- if(range.pm_capa & IW_POWER_UNICAST_R)
413- printf("\t\to Receive Unicast only (discard multicast)\n ");
414- if(range.pm_capa & IW_POWER_MULTICAST_R)
415- printf("\t\to Receive Multicast only (discard unicast)\n ");
416- if(range.pm_capa & IW_POWER_FORCE_S)
417- printf("\t\to Force sending using Power Management\n ");
418- if(range.pm_capa & IW_POWER_REPEATER)
419- printf("\t\to Repeat multicast\n ");
420- }
421- /* Display min/max period availables */
422- if(range.pmp_flags & IW_POWER_PERIOD)
423- {
424- int flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
425- /* Display if auto or fixed */
426- if(range.pmp_flags & IW_POWER_MIN)
427- printf("Auto period ; ");
428- else
429- printf("Fixed period ; ");
430- /* Print the range */
431- iw_print_pm_value(buffer, sizeof(buffer),
432- range.min_pmp, flags | IW_POWER_MIN);
433- printf("%s\n ", buffer);
434- iw_print_pm_value(buffer, sizeof(buffer),
435- range.max_pmp, flags | IW_POWER_MAX);
436- printf("%s\n ", buffer);
437- }
438- /* Display min/max timeout availables */
439- if(range.pmt_flags & IW_POWER_TIMEOUT)
440- {
441- int flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
442- /* Display if auto or fixed */
443- if(range.pmt_flags & IW_POWER_MIN)
444- printf("Auto timeout ; ");
445- else
446- printf("Fixed timeout ; ");
447- /* Print the range */
448- iw_print_pm_value(buffer, sizeof(buffer),
449- range.min_pmt, flags | IW_POWER_MIN);
450- printf("%s\n ", buffer);
451- iw_print_pm_value(buffer, sizeof(buffer),
452- range.max_pmt, flags | IW_POWER_MAX);
453- printf("%s\n ", buffer);
454- }
331+ /* Check if we are done */
332+ if(ielen < (offset + 2))
333+ {
334+ /* We don't have a pairwise cipher, or auth method. Assume TKIP. */
335+ printf(" Pairwise Ciphers : TKIP\n");
336+ return;
337+ }
455338
456- /* Get current Power Management settings */
457- wrq.u.power.flags = 0;
458- if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
459- {
460- int flags = wrq.u.power.flags;
339+ /* Otherwise, we have some number of pairwise ciphers. */
340+ cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
341+ offset += 2;
342+ printf(" Pairwise Ciphers (%d) :", cnt);
461343
462- /* Is it disabled ? */
463- if(wrq.u.power.disabled)
464- printf("Current mode:off\n ");
465- else
466- {
467- int pm_mask = 0;
344+ if(ielen < (offset + 4*cnt))
345+ return;
468346
469- /* Let's check the mode */
470- iw_print_pm_mode(buffer, sizeof(buffer), flags);
471- printf("Current %s", buffer);
347+ for(i = 0; i < cnt; i++)
348+ {
349+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
350+ {
351+ printf(" Proprietary");
352+ }
353+ else
354+ {
355+ iw_print_value_name(iebuf[offset+3],
356+ iw_ie_cypher_name, IW_IE_CYPHER_NUM);
357+ }
358+ offset+=4;
359+ }
360+ printf("\n");
361+
362+ /* Check if we are done */
363+ if(ielen < (offset + 2))
364+ return;
472365
473- /* Let's check if nothing (simply on) */
474- if((flags & IW_POWER_MODE) == IW_POWER_ON)
475- printf("mode:on");
476- printf("\n ");
366+ /* Now, we have authentication suites. */
367+ cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
368+ offset += 2;
369+ printf(" Authentication Suites (%d) :", cnt);
477370
478- /* Let's check the value and its type */
479- if(wrq.u.power.flags & IW_POWER_TYPE)
480- {
481- iw_print_pm_value(buffer, sizeof(buffer),
482- wrq.u.power.value, wrq.u.power.flags);
483- printf("%s", buffer);
484- }
371+ if(ielen < (offset + 4*cnt))
372+ return;
485373
486- /* If we have been returned a MIN value, ask for the MAX */
487- if(flags & IW_POWER_MIN)
488- pm_mask = IW_POWER_MAX;
489- /* If we have been returned a MAX value, ask for the MIN */
490- if(flags & IW_POWER_MAX)
491- pm_mask = IW_POWER_MIN;
492- /* If we have something to ask for... */
493- if(pm_mask)
494- get_pm_value(skfd, ifname, &wrq, pm_mask,
495- buffer, sizeof(buffer));
496-
497- /* And if we have both a period and a timeout, ask the other */
498- pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
499- IW_POWER_TYPE));
500- if(pm_mask)
501- {
502- int base_mask = pm_mask;
503- flags = get_pm_value(skfd, ifname, &wrq, pm_mask,
504- buffer, sizeof(buffer));
505- pm_mask = 0;
374+ for(i = 0; i < cnt; i++)
375+ {
376+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
377+ {
378+ printf(" Proprietary");
379+ }
380+ else
381+ {
382+ iw_print_value_name(iebuf[offset+3],
383+ iw_ie_key_mgmt_name, IW_IE_KEY_MGMT_NUM);
384+ }
385+ offset+=4;
386+ }
387+ printf("\n");
388+
389+ /* Check if we are done */
390+ if(ielen < (offset + 1))
391+ return;
506392
507- /* If we have been returned a MIN value, ask for the MAX */
508- if(flags & IW_POWER_MIN)
509- pm_mask = IW_POWER_MAX | base_mask;
510- /* If we have been returned a MAX value, ask for the MIN */
511- if(flags & IW_POWER_MAX)
512- pm_mask = IW_POWER_MIN | base_mask;
513- /* If we have something to ask for... */
514- if(pm_mask)
515- get_pm_value(skfd, ifname, &wrq, pm_mask,
516- buffer, sizeof(buffer));
517- }
518- }
519- }
520- printf("\n");
393+ /* Otherwise, we have capabilities bytes.
394+ * For now, we only care about preauth which is in bit position 1 of the
395+ * first byte. (But, preauth with WPA version 1 isn't supposed to be
396+ * allowed.) 8-) */
397+ if(iebuf[offset] & 0x01)
398+ {
399+ printf(" Preauthentication Supported\n");
521400 }
522- return(0);
523401 }
524-
525-/************************** TRANSMIT POWER **************************/
526-
402+
527403 /*------------------------------------------------------------------*/
528404 /*
529- * Print the number of available transmit powers for the device
405+ * Process a generic IE and display the info in human readable form
406+ * for some of the most interesting ones.
407+ * For now, we only decode the WPA IEs.
530408 */
531-static int
532-print_txpower_info(int skfd,
533- char * ifname,
534- char * args[], /* Command line args */
535- int count) /* Args count */
409+static inline void
410+iw_print_gen_ie(unsigned char * buffer,
411+ int buflen)
536412 {
537- struct iwreq wrq;
538- struct iw_range range;
539- int dbm;
540- int mwatt;
541- int k;
542-
543- /* Avoid "Unused parameter" warning */
544- args = args; count = count;
545-
546- /* Extract range info */
547- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
548- (range.we_version_compiled < 10))
549- fprintf(stderr, "%-8.16s no transmit-power information.\n\n",
550- ifname);
551- else
552- {
553- if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
554- printf("%-8.16s unknown transmit-power information.\n\n", ifname);
555- else
556- {
557- printf("%-8.16s %d available transmit-powers :\n",
558- ifname, range.num_txpower);
559- /* Print them all */
560- for(k = 0; k < range.num_txpower; k++)
561- {
562- /* Check for relative values */
563- if(range.txpower_capa & IW_TXPOW_RELATIVE)
564- {
565- printf("\t %d (no units)\n", range.txpower[k]);
566- }
567- else
568- {
569- if(range.txpower_capa & IW_TXPOW_MWATT)
570- {
571- dbm = iw_mwatt2dbm(range.txpower[k]);
572- mwatt = range.txpower[k];
573- }
574- else
575- {
576- dbm = range.txpower[k];
577- mwatt = iw_dbm2mwatt(range.txpower[k]);
578- }
579- printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
580- }
581- }
582- }
583-
584- /* Get current Transmit Power */
585- if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
586- {
587- printf(" Current Tx-Power");
588- /* Disabled ? */
589- if(wrq.u.txpower.disabled)
590- printf(":off\n\n");
591- else
592- {
593- /* Fixed ? */
594- if(wrq.u.txpower.fixed)
595- printf("=");
596- else
597- printf(":");
598- /* Check for relative values */
599- if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
600- {
601- /* I just hate relative value, because they are
602- * driver specific, so not very meaningfull to apps.
603- * But, we have to support that, because
604- * this is the way hardware is... */
605- printf("\t %d (no units)\n", wrq.u.txpower.value);
606- }
607- else
608- {
609- if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
610- {
611- dbm = iw_mwatt2dbm(wrq.u.txpower.value);
612- mwatt = wrq.u.txpower.value;
613- }
614- else
615- {
616- dbm = wrq.u.txpower.value;
617- mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
618- }
619- printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
620- }
621- }
622- }
623- }
624- return(0);
625-}
626-
627-/*********************** RETRY LIMIT/LIFETIME ***********************/
628-
629-/*------------------------------------------------------------------*/
630-/*
631- * Print one retry value
632- */
633-static inline int
634-get_retry_value(int skfd,
635- char * ifname,
636- struct iwreq * pwrq,
637- int flags,
638- char * buffer,
639- int buflen)
640-{
641- /* Get Another retry value */
642- pwrq->u.retry.flags = flags;
643- if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
644- {
645- /* Let's check the value and its type */
646- if(pwrq->u.retry.flags & IW_RETRY_TYPE)
647- {
648- iw_print_retry_value(buffer, buflen,
649- pwrq->u.retry.value, pwrq->u.retry.flags);
650- printf("%s\n ", buffer);
651- }
652- }
653- return(pwrq->u.retry.flags);
654-}
655-
656-/*------------------------------------------------------------------*/
657-/*
658- * Print Retry info for each device
659- */
660-static int
661-print_retry_info(int skfd,
662- char * ifname,
663- char * args[], /* Command line args */
664- int count) /* Args count */
665-{
666- struct iwreq wrq;
667- struct iw_range range;
668- char buffer[128];
669-
670- /* Avoid "Unused parameter" warning */
671- args = args; count = count;
413+ int offset = 0;
672414
673- /* Extract range info */
674- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
675- (range.we_version_compiled < 11))
676- fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n",
677- ifname);
678- else
415+ /* Loop on each IE, each IE is minimum 2 bytes */
416+ while(offset <= (buflen - 2))
679417 {
680- printf("%-8.16s ", ifname);
681-
682- /* Display min/max limit availables */
683- if(range.retry_flags & IW_RETRY_LIMIT)
684- {
685- int flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
686- /* Display if auto or fixed */
687- if(range.retry_flags & IW_RETRY_MIN)
688- printf("Auto limit ; ");
689- else
690- printf("Fixed limit ; ");
691- /* Print the range */
692- iw_print_retry_value(buffer, sizeof(buffer),
693- range.min_retry, flags | IW_RETRY_MIN);
694- printf("%s\n ", buffer);
695- iw_print_retry_value(buffer, sizeof(buffer),
696- range.max_retry, flags | IW_RETRY_MAX);
697- printf("%s\n ", buffer);
698-
699- }
700- /* Display min/max lifetime availables */
701- if(range.r_time_flags & IW_RETRY_LIFETIME)
702- {
703- int flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
704- /* Display if auto or fixed */
705- if(range.r_time_flags & IW_RETRY_MIN)
706- printf("Auto lifetime ; ");
707- else
708- printf("Fixed lifetime ; ");
709- /* Print the range */
710- iw_print_retry_value(buffer, sizeof(buffer),
711- range.min_r_time, flags | IW_RETRY_MIN);
712- printf("%s\n ", buffer);
713- iw_print_retry_value(buffer, sizeof(buffer),
714- range.max_r_time, flags | IW_RETRY_MAX);
715- printf("%s\n ", buffer);
716-
717- }
418+ printf(" IE: ");
718419
719- /* Get current retry settings */
720- wrq.u.retry.flags = 0;
721- if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
420+ /* Check IE type */
421+ switch(buffer[offset])
722422 {
723- int flags = wrq.u.retry.flags;
724-
725- /* Is it disabled ? */
726- if(wrq.u.retry.disabled)
727- printf("Current mode:off\n ");
728- else
729- {
730- int retry_mask = 0;
731-
732- /* Let's check the mode */
733- printf("Current mode:on\n ");
734-
735- /* Let's check the value and its type */
736- if(wrq.u.retry.flags & IW_RETRY_TYPE)
737- {
738- iw_print_retry_value(buffer, sizeof(buffer),
739- wrq.u.retry.value, wrq.u.retry.flags);
740- printf("%s\n ", buffer);
741- }
742-
743- /* If we have been returned a MIN value, ask for the MAX */
744- if(flags & IW_RETRY_MIN)
745- retry_mask = IW_RETRY_MAX;
746- /* If we have been returned a MAX value, ask for the MIN */
747- if(flags & IW_RETRY_MAX)
748- retry_mask = IW_RETRY_MIN;
749- /* If we have something to ask for... */
750- if(retry_mask)
751- get_retry_value(skfd, ifname, &wrq, retry_mask,
752- buffer, sizeof(buffer));
753-
754- /* And if we have both a period and a timeout, ask the other */
755- retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
756- IW_RETRY_TYPE));
757- if(retry_mask)
758- {
759- int base_mask = retry_mask;
760- flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
761- buffer, sizeof(buffer));
762- retry_mask = 0;
763-
764- /* If we have been returned a MIN value, ask for the MAX */
765- if(flags & IW_RETRY_MIN)
766- retry_mask = IW_RETRY_MAX | base_mask;
767- /* If we have been returned a MAX value, ask for the MIN */
768- if(flags & IW_RETRY_MAX)
769- retry_mask = IW_RETRY_MIN | base_mask;
770- /* If we have something to ask for... */
771- if(retry_mask)
772- get_retry_value(skfd, ifname, &wrq, retry_mask,
773- buffer, sizeof(buffer));
774- }
775- }
423+ case 0xdd: /* WPA1 (and other) */
424+ case 0x30: /* WPA2 */
425+ iw_print_ie_wpa(buffer + offset, buflen);
426+ break;
427+ default:
428+ iw_print_ie_unknown(buffer + offset, buflen);
776429 }
777- printf("\n");
430+ /* Skip over this IE to the next one in the list. */
431+ offset += buffer[offset+1] + 2;
778432 }
779- return(0);
780433 }
434+#endif /* WE_ESSENTIAL */
781435
782436 /***************************** SCANNING *****************************/
783437 /*
@@ -792,317 +446,53 @@ print_retry_info(int skfd,
792446
793447 /*------------------------------------------------------------------*/
794448 /*
795- * Parse, and display the results of a WPA or WPA2 IE.
796- *
449+ * Print one element from the scanning results
797450 */
798-static void
799-iw_print_ie_unknown(unsigned char * iebuf,
800- int buflen)
451+static inline void
452+print_scanning_token(struct stream_descr * stream, /* Stream of events */
453+ struct iw_event * event, /* Extracted token */
454+ struct iwscan_state * state,
455+ struct iw_range * iw_range, /* Range info */
456+ int has_range)
801457 {
802- int ielen = iebuf[1] + 2;
803- int i;
804-
805- if(ielen > buflen)
806- ielen = buflen;
807-
808- printf("Unknown: ");
809- for(i = 0; i < ielen; i++)
810- printf("%02X", iebuf[i]);
811- printf("\n");
812-}
458+ char buffer[128]; /* Temporary buffer */
813459
814-/*-----------------------------------------------------------------*/
815-/*
816- * Display the cipher type for the value passed in.
817- *
818- */
819-static inline void
820-iw_print_ie_cipher(unsigned char csuite)
821-{
822- switch (csuite)
460+ /* Now, let's decode the event */
461+ switch(event->cmd)
823462 {
824- case 0x00:
825- printf("None or same as Group ");
463+ case SIOCGIWAP:
464+ printf(" Cell %02d - Address: %s\n", state->ap_num,
465+ iw_saether_ntop(&event->u.ap_addr, buffer));
466+ state->ap_num++;
826467 break;
827-
828- case 0x01:
829- printf("WEP-40 ");
468+ case SIOCGIWNWID:
469+ if(event->u.nwid.disabled)
470+ printf(" NWID:off/any\n");
471+ else
472+ printf(" NWID:%X\n", event->u.nwid.value);
830473 break;
831-
832- case 0x02:
833- printf("TKIP ");
474+ case SIOCGIWFREQ:
475+ {
476+ double freq; /* Frequency/channel */
477+ int channel = -1; /* Converted to channel */
478+ freq = iw_freq2float(&(event->u.freq));
479+ /* Convert to channel if possible */
480+ if(has_range)
481+ channel = iw_freq_to_channel(freq, iw_range);
482+ iw_print_freq(buffer, sizeof(buffer),
483+ freq, channel, event->u.freq.flags);
484+ printf(" %s\n", buffer);
485+ }
834486 break;
835-
836- case 0x03:
837- printf("WRAP ");
487+ case SIOCGIWMODE:
488+ /* Note : event->u.mode is unsigned, no need to check <= 0 */
489+ if(event->u.mode >= IW_NUM_OPER_MODE)
490+ event->u.mode = IW_NUM_OPER_MODE;
491+ printf(" Mode:%s\n",
492+ iw_operation_mode[event->u.mode]);
838493 break;
839-
840- case 0x04:
841- printf("CCMP ");
842- break;
843-
844- case 0x05:
845- printf("WEP-104 ");
846- break;
847-
848- default:
849- printf("Unknown ");
850- break;
851- }
852- }
853-
854-/*------------------------------------------------------------------*/
855-/*
856- * Parse, and display the results of a WPA or WPA2 IE.
857- *
858- */
859-static inline void
860-iw_print_ie_wpa(unsigned char * iebuf,
861- int buflen)
862-{
863- int ielen = iebuf[1] + 2;
864- int offset = 2; /* Skip the IE id, and the length. */
865- unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
866- unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
867- unsigned char * wpa_oui;
868- int i;
869- uint16_t ver = 0;
870- uint16_t cnt = 0;
871-
872- if(ielen > buflen)
873- ielen = buflen;
874-
875- switch(iebuf[0])
876- {
877- case 0x30: /* WPA2 */
878- /* Check if we have enough data */
879- if(ielen < 4)
880- {
881- iw_print_ie_unknown(iebuf, buflen);
882- return;
883- }
884-
885- wpa_oui = wpa2_oui;
886- break;
887-
888- case 0xdd: /* WPA or else */
889- wpa_oui = wpa1_oui;
890-
891- /* Not all IEs that start with 0xdd are WPA.
892- * So check that the OUI is valid. */
893- if((ielen < 8)
894- || ((memcmp(&iebuf[offset], wpa_oui, 3) != 0)
895- && (iebuf[offset+3] == 0x01)))
896- {
897- iw_print_ie_unknown(iebuf, buflen);
898- return;
899- }
900-
901- offset += 4;
902- break;
903-
904- default:
905- return;
906- }
907-
908- /* Pick version number (little endian) */
909- ver = iebuf[offset] | (iebuf[offset + 1] << 8);
910- offset += 2;
911-
912- if(iebuf[0] == 0xdd)
913- printf("WPA Version %d\n", ver);
914- if(iebuf[0] == 0x30)
915- printf("IEEE 802.11i/WPA2 Version %d\n", ver);
916-
917- /* From here, everything is technically optional. */
918-
919- /* Check if we are done */
920- if(ielen < (offset + 4))
921- {
922- /* We have a short IE. So we should assume TKIP/TKIP. */
923- printf(" Group Cipher : TKIP\n");
924- printf(" Pairwise Cipher : TKIP\n");
925- return;
926- }
927-
928- /* Next we have our group cipher. */
929- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
930- {
931- printf(" Group Cipher : Proprietary\n");
932- }
933- else
934- {
935- printf(" Group Cipher : ");
936- iw_print_ie_cipher(iebuf[offset+3]);
937- printf("\n");
938- }
939- offset += 4;
940-
941- /* Check if we are done */
942- if(ielen < (offset + 2))
943- {
944- /* We don't have a pairwise cipher, or auth method. Assume TKIP. */
945- printf(" Pairwise Ciphers (1) : TKIP\n");
946- return;
947- }
948-
949- /* Otherwise, we have some number of pairwise ciphers. */
950- cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
951- offset += 2;
952- printf(" Pairwise Ciphers (%d) : ", cnt);
953-
954- if(ielen < (offset + 4*cnt))
955- return;
956-
957- for(i = 0; i < cnt; i++)
958- {
959- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
960- {
961- printf("Proprietary ");
962- }
963- else
964- {
965- iw_print_ie_cipher(iebuf[offset+3]);
966- }
967- offset+=4;
968- }
969- printf("\n");
970-
971- /* Check if we are done */
972- if(ielen < (offset + 2))
973- return;
974-
975- /* Now, we have authentication suites. */
976- cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
977- offset += 2;
978- printf(" Authentication Suites (%d) : ", cnt);
979-
980- if(ielen < (offset + 4*cnt))
981- return;
982-
983- for(i = 0; i < cnt; i++)
984- {
985- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
986- {
987- printf("Proprietary ");
988- }
989- else
990- {
991- switch(iebuf[offset+3])
992- {
993- case 0x00:
994- printf("Reserved ");
995- break;
996-
997- case 0x01:
998- printf("802.1X ");
999- break;
1000-
1001- case 0x02:
1002- printf("PSK ");
1003- break;
1004-
1005- default:
1006- printf("Unknown ");
1007- break;
1008- }
1009- }
1010- offset+=4;
1011- }
1012- printf("\n");
1013-
1014- /* Check if we are done */
1015- if(ielen < (offset + 1))
1016- return;
1017-
1018- /* Otherwise, we have capabilities bytes.
1019- * For now, we only care about preauth which is in bit position 1 of the
1020- * first byte. (But, preauth with WPA version 1 isn't supposed to be
1021- * allowed.) 8-) */
1022- if(iebuf[offset] & 0x01)
1023- {
1024- printf(" Preauthentication Supported\n");
1025- }
1026-}
1027-
1028-/*------------------------------------------------------------------*/
1029-/*
1030- * Process a generic IE and display the info in human readable form
1031- * for some of the most interesting ones.
1032- * For now, we only decode the WPA IEs.
1033- */
1034-static inline void
1035-iw_print_gen_ie(unsigned char * buffer,
1036- int buflen)
1037-{
1038- int offset = 0;
1039-
1040- /* Loop on each IE, each IE is minimum 2 bytes */
1041- while(offset <= (buflen - 2))
1042- {
1043- printf(" IE: ");
1044-
1045- /* Check IE type */
1046- switch(buffer[offset])
1047- {
1048- case 0xdd: /* WPA1 (and other) */
1049- case 0x30: /* WPA2 */
1050- iw_print_ie_wpa(buffer + offset, buflen);
1051- break;
1052- default:
1053- iw_print_ie_unknown(buffer + offset, buflen);
1054- }
1055- /* Skip over this IE to the next one in the list. */
1056- offset += buffer[offset+1] + 2;
1057- }
1058-}
1059-
1060-/*------------------------------------------------------------------*/
1061-/*
1062- * Print one element from the scanning results
1063- */
1064-static inline void
1065-print_scanning_token(struct stream_descr * stream, /* Stream of events */
1066- struct iw_event * event, /* Extracted token */
1067- struct iwscan_state * state,
1068- struct iw_range * iw_range, /* Range info */
1069- int has_range)
1070-{
1071- char buffer[128]; /* Temporary buffer */
1072-
1073- /* Now, let's decode the event */
1074- switch(event->cmd)
1075- {
1076- case SIOCGIWAP:
1077- printf(" Cell %02d - Address: %s\n", state->ap_num,
1078- iw_saether_ntop(&event->u.ap_addr, buffer));
1079- state->ap_num++;
1080- break;
1081- case SIOCGIWNWID:
1082- if(event->u.nwid.disabled)
1083- printf(" NWID:off/any\n");
1084- else
1085- printf(" NWID:%X\n", event->u.nwid.value);
1086- break;
1087- case SIOCGIWFREQ:
1088- {
1089- double freq; /* Frequency/channel */
1090- int channel = -1; /* Converted to channel */
1091- freq = iw_freq2float(&(event->u.freq));
1092- /* Convert to channel if possible */
1093- if(has_range)
1094- channel = iw_freq_to_channel(freq, iw_range);
1095- iw_print_freq(buffer, sizeof(buffer),
1096- freq, channel, event->u.freq.flags);
1097- printf(" %s\n", buffer);
1098- }
1099- break;
1100- case SIOCGIWMODE:
1101- printf(" Mode:%s\n",
1102- iw_operation_mode[event->u.mode]);
1103- break;
1104- case SIOCGIWNAME:
1105- printf(" Protocol:%-1.16s\n", event->u.name);
494+ case SIOCGIWNAME:
495+ printf(" Protocol:%-1.16s\n", event->u.name);
1106496 break;
1107497 case SIOCGIWESSID:
1108498 {
@@ -1164,230 +554,1111 @@ print_scanning_token(struct stream_descr * stream, /* Stream of events */
1164554 /* Check for termination */
1165555 if(stream->value == NULL)
1166556 {
1167- printf("\n");
1168- state->val_index = 0;
557+ printf("\n");
558+ state->val_index = 0;
559+ }
560+ else
561+ state->val_index++;
562+ break;
563+ case SIOCGIWMODUL:
564+ {
565+ unsigned int modul = event->u.param.value;
566+ int i;
567+ int n = 0;
568+ printf(" Modulations :");
569+ for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
570+ {
571+ if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
572+ {
573+ if((n++ % 8) == 7)
574+ printf("\n ");
575+ else
576+ printf(" ; ");
577+ printf("%s", iw_modul_list[i].cmd);
578+ }
579+ }
580+ printf("\n");
581+ }
582+ break;
583+ case IWEVQUAL:
584+ iw_print_stats(buffer, sizeof(buffer),
585+ &event->u.qual, iw_range, has_range);
586+ printf(" %s\n", buffer);
587+ break;
588+#ifndef WE_ESSENTIAL
589+ case IWEVGENIE:
590+ /* Informations Elements are complex, let's do only some of them */
591+ iw_print_gen_ie(event->u.data.pointer, event->u.data.length);
592+ break;
593+#endif /* WE_ESSENTIAL */
594+ case IWEVCUSTOM:
595+ {
596+ char custom[IW_CUSTOM_MAX+1];
597+ if((event->u.data.pointer) && (event->u.data.length))
598+ memcpy(custom, event->u.data.pointer, event->u.data.length);
599+ custom[event->u.data.length] = '\0';
600+ printf(" Extra:%s\n", custom);
601+ }
602+ break;
603+ default:
604+ printf(" (Unknown Wireless Token 0x%04X)\n",
605+ event->cmd);
606+ } /* switch(event->cmd) */
607+}
608+
609+/*------------------------------------------------------------------*/
610+/*
611+ * Perform a scanning on one device
612+ */
613+static int
614+print_scanning_info(int skfd,
615+ char * ifname,
616+ char * args[], /* Command line args */
617+ int count) /* Args count */
618+{
619+ struct iwreq wrq;
620+ struct iw_scan_req scanopt; /* Options for 'set' */
621+ int scanflags = 0; /* Flags for scan */
622+ unsigned char * buffer = NULL; /* Results */
623+ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
624+ struct iw_range range;
625+ int has_range;
626+ struct timeval tv; /* Select timeout */
627+ int timeout = 15000000; /* 15s */
628+
629+ /* Avoid "Unused parameter" warning */
630+ args = args; count = count;
631+
632+ /* Debugging stuff */
633+ if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN))
634+ {
635+ fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n");
636+ fprintf(stderr, "*** and the following line :\n");
637+ fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n",
638+ IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN);
639+ }
640+
641+ /* Get range stuff */
642+ has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
643+
644+ /* Check if the interface could support scanning. */
645+ if((!has_range) || (range.we_version_compiled < 14))
646+ {
647+ fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n",
648+ ifname);
649+ return(-1);
650+ }
651+
652+ /* Init timeout value -> 250ms between set and first get */
653+ tv.tv_sec = 0;
654+ tv.tv_usec = 250000;
655+
656+ /* Clean up set args */
657+ memset(&scanopt, 0, sizeof(scanopt));
658+
659+ /* Parse command line arguments and extract options.
660+ * Note : when we have enough options, we should use the parser
661+ * from iwconfig... */
662+ while(count > 0)
663+ {
664+ /* One arg is consumed (the option name) */
665+ count--;
666+
667+ /*
668+ * Check for Active Scan (scan with specific essid)
669+ */
670+ if(!strncmp(args[0], "essid", 5))
671+ {
672+ if(count < 1)
673+ {
674+ fprintf(stderr, "Too few arguments for scanning option [%s]\n",
675+ args[0]);
676+ return(-1);
677+ }
678+ args++;
679+ count--;
680+
681+ /* Store the ESSID in the scan options */
682+ scanopt.essid_len = strlen(args[0]);
683+ memcpy(scanopt.essid, args[0], scanopt.essid_len);
684+ /* Initialise BSSID as needed */
685+ if(scanopt.bssid.sa_family == 0)
686+ {
687+ scanopt.bssid.sa_family = ARPHRD_ETHER;
688+ memset(scanopt.bssid.sa_data, 0xff, ETH_ALEN);
689+ }
690+ /* Scan only this ESSID */
691+ scanflags |= IW_SCAN_THIS_ESSID;
692+ }
693+ else
694+ /* Check for last scan result (do not trigger scan) */
695+ if(!strncmp(args[0], "last", 4))
696+ {
697+ /* Hack */
698+ scanflags |= IW_SCAN_HACK;
699+ }
700+ else
701+ {
702+ fprintf(stderr, "Invalid scanning option [%s]\n", args[0]);
703+ return(-1);
704+ }
705+
706+ /* Next arg */
707+ args++;
708+ }
709+
710+ /* Check if we have scan options */
711+ if(scanflags)
712+ {
713+ wrq.u.data.pointer = (caddr_t) &scanopt;
714+ wrq.u.data.length = sizeof(scanopt);
715+ wrq.u.data.flags = scanflags;
716+ }
717+ else
718+ {
719+ wrq.u.data.pointer = NULL;
720+ wrq.u.data.flags = 0;
721+ wrq.u.data.length = 0;
722+ }
723+
724+ /* If only 'last' was specified on command line, don't trigger a scan */
725+ if(scanflags == IW_SCAN_HACK)
726+ {
727+ /* Skip waiting */
728+ tv.tv_usec = 0;
729+ }
730+ else
731+ {
732+ /* Initiate Scanning */
733+ if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
734+ {
735+ if((errno != EPERM) || (scanflags != 0))
736+ {
737+ fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
738+ ifname, strerror(errno));
739+ return(-1);
740+ }
741+ /* If we don't have the permission to initiate the scan, we may
742+ * still have permission to read left-over results.
743+ * But, don't wait !!! */
744+#if 0
745+ /* Not cool, it display for non wireless interfaces... */
746+ fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
747+#endif
748+ tv.tv_usec = 0;
749+ }
750+ }
751+ timeout -= tv.tv_usec;
752+
753+ /* Forever */
754+ while(1)
755+ {
756+ fd_set rfds; /* File descriptors for select */
757+ int last_fd; /* Last fd */
758+ int ret;
759+
760+ /* Guess what ? We must re-generate rfds each time */
761+ FD_ZERO(&rfds);
762+ last_fd = -1;
763+
764+ /* In here, add the rtnetlink fd in the list */
765+
766+ /* Wait until something happens */
767+ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
768+
769+ /* Check if there was an error */
770+ if(ret < 0)
771+ {
772+ if(errno == EAGAIN || errno == EINTR)
773+ continue;
774+ fprintf(stderr, "Unhandled signal - exiting...\n");
775+ return(-1);
776+ }
777+
778+ /* Check if there was a timeout */
779+ if(ret == 0)
780+ {
781+ unsigned char * newbuf;
782+
783+ realloc:
784+ /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
785+ newbuf = realloc(buffer, buflen);
786+ if(newbuf == NULL)
787+ {
788+ if(buffer)
789+ free(buffer);
790+ fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
791+ return(-1);
792+ }
793+ buffer = newbuf;
794+
795+ /* Try to read the results */
796+ wrq.u.data.pointer = buffer;
797+ wrq.u.data.flags = 0;
798+ wrq.u.data.length = buflen;
799+ if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
800+ {
801+ /* Check if buffer was too small (WE-17 only) */
802+ if((errno == E2BIG) && (range.we_version_compiled > 16))
803+ {
804+ /* Some driver may return very large scan results, either
805+ * because there are many cells, or because they have many
806+ * large elements in cells (like IWEVCUSTOM). Most will
807+ * only need the regular sized buffer. We now use a dynamic
808+ * allocation of the buffer to satisfy everybody. Of course,
809+ * as we don't know in advance the size of the array, we try
810+ * various increasing sizes. Jean II */
811+
812+ /* Check if the driver gave us any hints. */
813+ if(wrq.u.data.length > buflen)
814+ buflen = wrq.u.data.length;
815+ else
816+ buflen *= 2;
817+
818+ /* Try again */
819+ goto realloc;
820+ }
821+
822+ /* Check if results not available yet */
823+ if(errno == EAGAIN)
824+ {
825+ /* Restart timer for only 100ms*/
826+ tv.tv_sec = 0;
827+ tv.tv_usec = 100000;
828+ timeout -= tv.tv_usec;
829+ if(timeout > 0)
830+ continue; /* Try again later */
831+ }
832+
833+ /* Bad error */
834+ free(buffer);
835+ fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
836+ ifname, strerror(errno));
837+ return(-2);
838+ }
839+ else
840+ /* We have the results, go to process them */
841+ break;
842+ }
843+
844+ /* In here, check if event and event type
845+ * if scan event, read results. All errors bad & no reset timeout */
846+ }
847+
848+ if(wrq.u.data.length)
849+ {
850+ struct iw_event iwe;
851+ struct stream_descr stream;
852+ struct iwscan_state state = { .ap_num = 1, .val_index = 0 };
853+ int ret;
854+
855+#ifdef DEBUG
856+ /* Debugging code. In theory useless, because it's debugged ;-) */
857+ int i;
858+ printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
859+ for(i = 1; i < wrq.u.data.length; i++)
860+ printf(":%02X", buffer[i]);
861+ printf("]\n");
862+#endif
863+ printf("%-8.16s Scan completed :\n", ifname);
864+ iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
865+ do
866+ {
867+ /* Extract an event and print it */
868+ ret = iw_extract_event_stream(&stream, &iwe,
869+ range.we_version_compiled);
870+ if(ret > 0)
871+ print_scanning_token(&stream, &iwe, &state,
872+ &range, has_range);
873+ }
874+ while(ret > 0);
875+ printf("\n");
876+ }
877+ else
878+ printf("%-8.16s No scan results\n\n", ifname);
879+
880+ free(buffer);
881+ return(0);
882+}
883+
884+/*********************** FREQUENCIES/CHANNELS ***********************/
885+
886+/*------------------------------------------------------------------*/
887+/*
888+ * Print the number of channels and available frequency for the device
889+ */
890+static int
891+print_freq_info(int skfd,
892+ char * ifname,
893+ char * args[], /* Command line args */
894+ int count) /* Args count */
895+{
896+ struct iwreq wrq;
897+ struct iw_range range;
898+ double freq;
899+ int k;
900+ int channel;
901+ char buffer[128]; /* Temporary buffer */
902+
903+ /* Avoid "Unused parameter" warning */
904+ args = args; count = count;
905+
906+ /* Get list of frequencies / channels */
907+ if(iw_get_range_info(skfd, ifname, &range) < 0)
908+ fprintf(stderr, "%-8.16s no frequency information.\n\n",
909+ ifname);
910+ else
911+ {
912+ if(range.num_frequency > 0)
913+ {
914+ printf("%-8.16s %d channels in total; available frequencies :\n",
915+ ifname, range.num_channels);
916+ /* Print them all */
917+ for(k = 0; k < range.num_frequency; k++)
918+ {
919+ freq = iw_freq2float(&(range.freq[k]));
920+ iw_print_freq_value(buffer, sizeof(buffer), freq);
921+ printf(" Channel %.2d : %s\n",
922+ range.freq[k].i, buffer);
923+ }
924+ }
925+ else
926+ printf("%-8.16s %d channels\n",
927+ ifname, range.num_channels);
928+
929+ /* Get current frequency / channel and display it */
930+ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
931+ {
932+ freq = iw_freq2float(&(wrq.u.freq));
933+ channel = iw_freq_to_channel(freq, &range);
934+ iw_print_freq(buffer, sizeof(buffer),
935+ freq, channel, wrq.u.freq.flags);
936+ printf(" Current %s\n\n", buffer);
937+ }
938+ }
939+ return(0);
940+}
941+
942+/***************************** BITRATES *****************************/
943+
944+/*------------------------------------------------------------------*/
945+/*
946+ * Print the number of available bitrates for the device
947+ */
948+static int
949+print_bitrate_info(int skfd,
950+ char * ifname,
951+ char * args[], /* Command line args */
952+ int count) /* Args count */
953+{
954+ struct iwreq wrq;
955+ struct iw_range range;
956+ int k;
957+ char buffer[128];
958+
959+ /* Avoid "Unused parameter" warning */
960+ args = args; count = count;
961+
962+ /* Extract range info */
963+ if(iw_get_range_info(skfd, ifname, &range) < 0)
964+ fprintf(stderr, "%-8.16s no bit-rate information.\n\n",
965+ ifname);
966+ else
967+ {
968+ if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
969+ {
970+ printf("%-8.16s %d available bit-rates :\n",
971+ ifname, range.num_bitrates);
972+ /* Print them all */
973+ for(k = 0; k < range.num_bitrates; k++)
974+ {
975+ iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
976+ /* Maybe this should be %10s */
977+ printf("\t %s\n", buffer);
978+ }
979+ }
980+ else
981+ printf("%-8.16s unknown bit-rate information.\n", ifname);
982+
983+ /* Get current bit rate */
984+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
985+ {
986+ iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
987+ printf(" Current Bit Rate%c%s\n",
988+ (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
989+ }
990+
991+ /* Try to get the broadcast bitrate if it exist... */
992+ if(range.bitrate_capa & IW_BITRATE_BROADCAST)
993+ {
994+ wrq.u.bitrate.flags = IW_BITRATE_BROADCAST;
995+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
996+ {
997+ iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
998+ printf(" Broadcast Bit Rate%c%s\n",
999+ (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
1000+ }
1001+ }
1002+
1003+ printf("\n");
1004+ }
1005+ return(0);
1006+}
1007+
1008+/************************* ENCRYPTION KEYS *************************/
1009+
1010+/*------------------------------------------------------------------*/
1011+/*
1012+ * Print all the available encryption keys for the device
1013+ */
1014+static int
1015+print_keys_info(int skfd,
1016+ char * ifname,
1017+ char * args[], /* Command line args */
1018+ int count) /* Args count */
1019+{
1020+ struct iwreq wrq;
1021+ struct iw_range range;
1022+ unsigned char key[IW_ENCODING_TOKEN_MAX];
1023+ unsigned int k;
1024+ char buffer[128];
1025+
1026+ /* Avoid "Unused parameter" warning */
1027+ args = args; count = count;
1028+
1029+ /* Extract range info */
1030+ if(iw_get_range_info(skfd, ifname, &range) < 0)
1031+ fprintf(stderr, "%-8.16s no encryption keys information.\n\n",
1032+ ifname);
1033+ else
1034+ {
1035+ printf("%-8.16s ", ifname);
1036+ /* Print key sizes */
1037+ if((range.num_encoding_sizes > 0) &&
1038+ (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
1039+ {
1040+ printf("%d key sizes : %d", range.num_encoding_sizes,
1041+ range.encoding_size[0] * 8);
1042+ /* Print them all */
1043+ for(k = 1; k < range.num_encoding_sizes; k++)
1044+ printf(", %d", range.encoding_size[k] * 8);
1045+ printf("bits\n ");
1046+ }
1047+ /* Print the keys and associate mode */
1048+ printf("%d keys available :\n", range.max_encoding_tokens);
1049+ for(k = 1; k <= range.max_encoding_tokens; k++)
1050+ {
1051+ wrq.u.data.pointer = (caddr_t) key;
1052+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
1053+ wrq.u.data.flags = k;
1054+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
1055+ {
1056+ fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno));
1057+ break;
1058+ }
1059+ if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
1060+ (wrq.u.data.length == 0))
1061+ printf("\t\t[%d]: off\n", k);
1062+ else
1063+ {
1064+ /* Display the key */
1065+ iw_print_key(buffer, sizeof(buffer),
1066+ key, wrq.u.data.length, wrq.u.data.flags);
1067+ printf("\t\t[%d]: %s", k, buffer);
1068+
1069+ /* Other info... */
1070+ printf(" (%d bits)", wrq.u.data.length * 8);
1071+ printf("\n");
1072+ }
1073+ }
1074+ /* Print current key index and mode */
1075+ wrq.u.data.pointer = (caddr_t) key;
1076+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
1077+ wrq.u.data.flags = 0; /* Set index to zero to get current */
1078+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
1079+ {
1080+ /* Note : if above fails, we have already printed an error
1081+ * message int the loop above */
1082+ printf(" Current Transmit Key: [%d]\n",
1083+ wrq.u.data.flags & IW_ENCODE_INDEX);
1084+ if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
1085+ printf(" Security mode:restricted\n");
1086+ if(wrq.u.data.flags & IW_ENCODE_OPEN)
1087+ printf(" Security mode:open\n");
1088+ }
1089+
1090+ printf("\n\n");
1091+ }
1092+ return(0);
1093+}
1094+
1095+/************************* POWER MANAGEMENT *************************/
1096+
1097+/*------------------------------------------------------------------*/
1098+/*
1099+ * Print Power Management info for each device
1100+ */
1101+static int
1102+get_pm_value(int skfd,
1103+ char * ifname,
1104+ struct iwreq * pwrq,
1105+ int flags,
1106+ char * buffer,
1107+ int buflen,
1108+ int we_version_compiled)
1109+{
1110+ /* Get Another Power Management value */
1111+ pwrq->u.power.flags = flags;
1112+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
1113+ {
1114+ /* Let's check the value and its type */
1115+ if(pwrq->u.power.flags & IW_POWER_TYPE)
1116+ {
1117+ iw_print_pm_value(buffer, buflen,
1118+ pwrq->u.power.value, pwrq->u.power.flags,
1119+ we_version_compiled);
1120+ printf("\n %s", buffer);
1121+ }
1122+ }
1123+ return(pwrq->u.power.flags);
1124+}
1125+
1126+/*------------------------------------------------------------------*/
1127+/*
1128+ * Print Power Management range for each type
1129+ */
1130+static void
1131+print_pm_value_range(char * name,
1132+ int mask,
1133+ int iwr_flags,
1134+ int iwr_min,
1135+ int iwr_max,
1136+ char * buffer,
1137+ int buflen,
1138+ int we_version_compiled)
1139+{
1140+ if(iwr_flags & mask)
1141+ {
1142+ int flags = (iwr_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
1143+ /* Display if auto or fixed */
1144+ printf("%s %s ; ",
1145+ (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
1146+ name);
1147+ /* Print the range */
1148+ iw_print_pm_value(buffer, buflen,
1149+ iwr_min, flags | IW_POWER_MIN,
1150+ we_version_compiled);
1151+ printf("%s\n ", buffer);
1152+ iw_print_pm_value(buffer, buflen,
1153+ iwr_max, flags | IW_POWER_MAX,
1154+ we_version_compiled);
1155+ printf("%s\n ", buffer);
1156+ }
1157+}
1158+
1159+/*------------------------------------------------------------------*/
1160+/*
1161+ * Power Management types of values
1162+ */
1163+static const unsigned int pm_type_flags[] = {
1164+ IW_POWER_PERIOD,
1165+ IW_POWER_TIMEOUT,
1166+ IW_POWER_SAVING,
1167+};
1168+static const int pm_type_flags_size = (sizeof(pm_type_flags)/sizeof(pm_type_flags[0]));
1169+
1170+/*------------------------------------------------------------------*/
1171+/*
1172+ * Print Power Management info for each device
1173+ */
1174+static int
1175+print_pm_info(int skfd,
1176+ char * ifname,
1177+ char * args[], /* Command line args */
1178+ int count) /* Args count */
1179+{
1180+ struct iwreq wrq;
1181+ struct iw_range range;
1182+ char buffer[128];
1183+
1184+ /* Avoid "Unused parameter" warning */
1185+ args = args; count = count;
1186+
1187+ /* Extract range info */
1188+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1189+ (range.we_version_compiled < 10))
1190+ fprintf(stderr, "%-8.16s no power management information.\n\n",
1191+ ifname);
1192+ else
1193+ {
1194+ printf("%-8.16s ", ifname);
1195+
1196+ /* Display modes availables */
1197+ if(range.pm_capa & IW_POWER_MODE)
1198+ {
1199+ printf("Supported modes :\n ");
1200+ if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
1201+ printf("\t\to Receive all packets (unicast & multicast)\n ");
1202+ if(range.pm_capa & IW_POWER_UNICAST_R)
1203+ printf("\t\to Receive Unicast only (discard multicast)\n ");
1204+ if(range.pm_capa & IW_POWER_MULTICAST_R)
1205+ printf("\t\to Receive Multicast only (discard unicast)\n ");
1206+ if(range.pm_capa & IW_POWER_FORCE_S)
1207+ printf("\t\to Force sending using Power Management\n ");
1208+ if(range.pm_capa & IW_POWER_REPEATER)
1209+ printf("\t\to Repeat multicast\n ");
1210+ }
1211+ /* Display min/max period availables */
1212+ print_pm_value_range("period ", IW_POWER_PERIOD,
1213+ range.pmp_flags, range.min_pmp, range.max_pmp,
1214+ buffer, sizeof(buffer), range.we_version_compiled);
1215+ /* Display min/max timeout availables */
1216+ print_pm_value_range("timeout", IW_POWER_TIMEOUT,
1217+ range.pmt_flags, range.min_pmt, range.max_pmt,
1218+ buffer, sizeof(buffer), range.we_version_compiled);
1219+ /* Display min/max saving availables */
1220+ print_pm_value_range("saving ", IW_POWER_SAVING,
1221+ range.pms_flags, range.min_pms, range.max_pms,
1222+ buffer, sizeof(buffer), range.we_version_compiled);
1223+
1224+ /* Get current Power Management settings */
1225+ wrq.u.power.flags = 0;
1226+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
1227+ {
1228+ int flags = wrq.u.power.flags;
1229+
1230+ /* Is it disabled ? */
1231+ if(wrq.u.power.disabled)
1232+ printf("Current mode:off\n");
1233+ else
1234+ {
1235+ unsigned int pm_type = 0;
1236+ unsigned int pm_mask = 0;
1237+ unsigned int remain_mask = range.pm_capa & IW_POWER_TYPE;
1238+ int i = 0;
1239+
1240+ /* Let's check the mode */
1241+ iw_print_pm_mode(buffer, sizeof(buffer), flags);
1242+ printf("Current %s", buffer);
1243+
1244+ /* Let's check if nothing (simply on) */
1245+ if((flags & IW_POWER_MODE) == IW_POWER_ON)
1246+ printf("mode:on");
1247+
1248+ /* Let's check the value and its type */
1249+ if(wrq.u.power.flags & IW_POWER_TYPE)
1250+ {
1251+ iw_print_pm_value(buffer, sizeof(buffer),
1252+ wrq.u.power.value, wrq.u.power.flags,
1253+ range.we_version_compiled);
1254+ printf("\n %s", buffer);
1255+ }
1256+
1257+ while(1)
1258+ {
1259+ /* Deal with min/max for the current value */
1260+ pm_mask = 0;
1261+ /* If we have been returned a MIN value, ask for the MAX */
1262+ if(flags & IW_POWER_MIN)
1263+ pm_mask = IW_POWER_MAX;
1264+ /* If we have been returned a MAX value, ask for the MIN */
1265+ if(flags & IW_POWER_MAX)
1266+ pm_mask = IW_POWER_MIN;
1267+ /* If we have something to ask for... */
1268+ if(pm_mask)
1269+ {
1270+ pm_mask |= pm_type;
1271+ get_pm_value(skfd, ifname, &wrq, pm_mask,
1272+ buffer, sizeof(buffer),
1273+ range.we_version_compiled);
1274+ }
1275+
1276+ /* Remove current type from mask */
1277+ remain_mask &= ~(wrq.u.power.flags);
1278+
1279+ /* Check what other types we still have to read */
1280+ while(i < pm_type_flags_size)
1281+ {
1282+ pm_type = remain_mask & pm_type_flags[i];
1283+ if(pm_type)
1284+ break;
1285+ i++;
1286+ }
1287+ /* Nothing anymore : exit the loop */
1288+ if(!pm_type)
1289+ break;
1290+
1291+ /* Ask for this other type of value */
1292+ flags = get_pm_value(skfd, ifname, &wrq, pm_type,
1293+ buffer, sizeof(buffer),
1294+ range.we_version_compiled);
1295+ /* Loop back for min/max */
1296+ }
1297+ printf("\n");
1298+ }
1299+ }
1300+ printf("\n");
1301+ }
1302+ return(0);
1303+}
1304+
1305+#ifndef WE_ESSENTIAL
1306+/************************** TRANSMIT POWER **************************/
1307+
1308+/*------------------------------------------------------------------*/
1309+/*
1310+ * Print the number of available transmit powers for the device
1311+ */
1312+static int
1313+print_txpower_info(int skfd,
1314+ char * ifname,
1315+ char * args[], /* Command line args */
1316+ int count) /* Args count */
1317+{
1318+ struct iwreq wrq;
1319+ struct iw_range range;
1320+ int dbm;
1321+ int mwatt;
1322+ int k;
1323+
1324+ /* Avoid "Unused parameter" warning */
1325+ args = args; count = count;
1326+
1327+ /* Extract range info */
1328+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1329+ (range.we_version_compiled < 10))
1330+ fprintf(stderr, "%-8.16s no transmit-power information.\n\n",
1331+ ifname);
1332+ else
1333+ {
1334+ if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
1335+ printf("%-8.16s unknown transmit-power information.\n\n", ifname);
1336+ else
1337+ {
1338+ printf("%-8.16s %d available transmit-powers :\n",
1339+ ifname, range.num_txpower);
1340+ /* Print them all */
1341+ for(k = 0; k < range.num_txpower; k++)
1342+ {
1343+ /* Check for relative values */
1344+ if(range.txpower_capa & IW_TXPOW_RELATIVE)
1345+ {
1346+ printf("\t %d (no units)\n", range.txpower[k]);
1347+ }
1348+ else
1349+ {
1350+ if(range.txpower_capa & IW_TXPOW_MWATT)
1351+ {
1352+ dbm = iw_mwatt2dbm(range.txpower[k]);
1353+ mwatt = range.txpower[k];
1354+ }
1355+ else
1356+ {
1357+ dbm = range.txpower[k];
1358+ mwatt = iw_dbm2mwatt(range.txpower[k]);
1359+ }
1360+ printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
1361+ }
1362+ }
1363+ }
1364+
1365+ /* Get current Transmit Power */
1366+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
1367+ {
1368+ printf(" Current Tx-Power");
1369+ /* Disabled ? */
1370+ if(wrq.u.txpower.disabled)
1371+ printf(":off\n\n");
1372+ else
1373+ {
1374+ /* Fixed ? */
1375+ if(wrq.u.txpower.fixed)
1376+ printf("=");
1377+ else
1378+ printf(":");
1379+ /* Check for relative values */
1380+ if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
1381+ {
1382+ /* I just hate relative value, because they are
1383+ * driver specific, so not very meaningfull to apps.
1384+ * But, we have to support that, because
1385+ * this is the way hardware is... */
1386+ printf("\t %d (no units)\n", wrq.u.txpower.value);
1387+ }
1388+ else
1389+ {
1390+ if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
1391+ {
1392+ dbm = iw_mwatt2dbm(wrq.u.txpower.value);
1393+ mwatt = wrq.u.txpower.value;
1394+ }
1395+ else
1396+ {
1397+ dbm = wrq.u.txpower.value;
1398+ mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
1399+ }
1400+ printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
1401+ }
1402+ }
1403+ }
1404+ }
1405+ return(0);
1406+}
1407+
1408+/*********************** RETRY LIMIT/LIFETIME ***********************/
1409+
1410+/*------------------------------------------------------------------*/
1411+/*
1412+ * Print one retry value
1413+ */
1414+static int
1415+get_retry_value(int skfd,
1416+ char * ifname,
1417+ struct iwreq * pwrq,
1418+ int flags,
1419+ char * buffer,
1420+ int buflen,
1421+ int we_version_compiled)
1422+{
1423+ /* Get Another retry value */
1424+ pwrq->u.retry.flags = flags;
1425+ if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
1426+ {
1427+ /* Let's check the value and its type */
1428+ if(pwrq->u.retry.flags & IW_RETRY_TYPE)
1429+ {
1430+ iw_print_retry_value(buffer, buflen,
1431+ pwrq->u.retry.value, pwrq->u.retry.flags,
1432+ we_version_compiled);
1433+ printf("%s\n ", buffer);
11691434 }
1170- else
1171- state->val_index++;
1172- break;
1173- case IWEVQUAL:
1174- {
1175- iw_print_stats(buffer, sizeof(buffer),
1176- &event->u.qual, iw_range, has_range);
1177- printf(" %s\n", buffer);
1178- break;
1179- }
1180- case IWEVGENIE:
1181- /* Informations Elements are complex, let's do only some of them */
1182- iw_print_gen_ie(event->u.data.pointer, event->u.data.length);
1183- break;
1184- case IWEVCUSTOM:
1185- {
1186- char custom[IW_CUSTOM_MAX+1];
1187- if((event->u.data.pointer) && (event->u.data.length))
1188- memcpy(custom, event->u.data.pointer, event->u.data.length);
1189- custom[event->u.data.length] = '\0';
1190- printf(" Extra:%s\n", custom);
1191- }
1192- break;
1193- default:
1194- printf(" (Unknown Wireless Token 0x%04X)\n",
1195- event->cmd);
1196- } /* switch(event->cmd) */
1435+ }
1436+ return(pwrq->u.retry.flags);
11971437 }
11981438
11991439 /*------------------------------------------------------------------*/
12001440 /*
1201- * Perform a scanning on one device
1441+ * Print Power Management range for each type
1442+ */
1443+static void
1444+print_retry_value_range(char * name,
1445+ int mask,
1446+ int iwr_flags,
1447+ int iwr_min,
1448+ int iwr_max,
1449+ char * buffer,
1450+ int buflen,
1451+ int we_version_compiled)
1452+{
1453+ if(iwr_flags & mask)
1454+ {
1455+ int flags = (iwr_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
1456+ /* Display if auto or fixed */
1457+ printf("%s %s ; ",
1458+ (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
1459+ name);
1460+ /* Print the range */
1461+ iw_print_retry_value(buffer, buflen,
1462+ iwr_min, flags | IW_POWER_MIN,
1463+ we_version_compiled);
1464+ printf("%s\n ", buffer);
1465+ iw_print_retry_value(buffer, buflen,
1466+ iwr_max, flags | IW_POWER_MAX,
1467+ we_version_compiled);
1468+ printf("%s\n ", buffer);
1469+ }
1470+}
1471+
1472+/*------------------------------------------------------------------*/
1473+/*
1474+ * Print Retry info for each device
12021475 */
12031476 static int
1204-print_scanning_info(int skfd,
1205- char * ifname,
1206- char * args[], /* Command line args */
1207- int count) /* Args count */
1477+print_retry_info(int skfd,
1478+ char * ifname,
1479+ char * args[], /* Command line args */
1480+ int count) /* Args count */
12081481 {
12091482 struct iwreq wrq;
1210- unsigned char * buffer = NULL; /* Results */
1211- int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
12121483 struct iw_range range;
1213- int has_range;
1214- struct timeval tv; /* Select timeout */
1215- int timeout = 15000000; /* 15s */
1484+ char buffer[128];
12161485
12171486 /* Avoid "Unused parameter" warning */
12181487 args = args; count = count;
12191488
1220- /* Get range stuff */
1221- has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
1222-
1223- /* Check if the interface could support scanning. */
1224- if((!has_range) || (range.we_version_compiled < 14))
1489+ /* Extract range info */
1490+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1491+ (range.we_version_compiled < 11))
1492+ fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n",
1493+ ifname);
1494+ else
12251495 {
1226- fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n",
1227- ifname);
1228- return(-1);
1229- }
1230-
1231- /* Init timeout value -> 250ms*/
1232- tv.tv_sec = 0;
1233- tv.tv_usec = 250000;
1496+ printf("%-8.16s ", ifname);
12341497
1235- /*
1236- * Here we should look at the command line args and set the IW_SCAN_ flags
1237- * properly
1238- */
1239- wrq.u.data.pointer = NULL; /* Later */
1240- wrq.u.data.flags = 0;
1241- wrq.u.data.length = 0;
1498+ /* Display min/max limit availables */
1499+ print_retry_value_range("limit ", IW_RETRY_LIMIT, range.retry_flags,
1500+ range.min_retry, range.max_retry,
1501+ buffer, sizeof(buffer),
1502+ range.we_version_compiled);
1503+ /* Display min/max lifetime availables */
1504+ print_retry_value_range("lifetime", IW_RETRY_LIFETIME,
1505+ range.r_time_flags,
1506+ range.min_r_time, range.max_r_time,
1507+ buffer, sizeof(buffer),
1508+ range.we_version_compiled);
12421509
1243- /* Initiate Scanning */
1244- if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
1245- {
1246- if(errno != EPERM)
1510+ /* Get current retry settings */
1511+ wrq.u.retry.flags = 0;
1512+ if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
12471513 {
1248- fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
1249- ifname, strerror(errno));
1250- return(-1);
1251- }
1252- /* If we don't have the permission to initiate the scan, we may
1253- * still have permission to read left-over results.
1254- * But, don't wait !!! */
1255-#if 0
1256- /* Not cool, it display for non wireless interfaces... */
1257- fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
1258-#endif
1259- tv.tv_usec = 0;
1260- }
1261- timeout -= tv.tv_usec;
1262-
1263- /* Forever */
1264- while(1)
1265- {
1266- fd_set rfds; /* File descriptors for select */
1267- int last_fd; /* Last fd */
1268- int ret;
1269-
1270- /* Guess what ? We must re-generate rfds each time */
1271- FD_ZERO(&rfds);
1272- last_fd = -1;
1514+ int flags = wrq.u.retry.flags;
12731515
1274- /* In here, add the rtnetlink fd in the list */
1516+ /* Is it disabled ? */
1517+ if(wrq.u.retry.disabled)
1518+ printf("Current mode:off\n ");
1519+ else
1520+ {
1521+ unsigned int retry_type = 0;
1522+ unsigned int retry_mask = 0;
1523+ unsigned int remain_mask = range.retry_capa & IW_RETRY_TYPE;
12751524
1276- /* Wait until something happens */
1277- ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
1525+ /* Let's check the mode */
1526+ printf("Current mode:on\n ");
12781527
1279- /* Check if there was an error */
1280- if(ret < 0)
1281- {
1282- if(errno == EAGAIN || errno == EINTR)
1283- continue;
1284- fprintf(stderr, "Unhandled signal - exiting...\n");
1285- return(-1);
1286- }
1528+ /* Let's check the value and its type */
1529+ if(wrq.u.retry.flags & IW_RETRY_TYPE)
1530+ {
1531+ iw_print_retry_value(buffer, sizeof(buffer),
1532+ wrq.u.retry.value, wrq.u.retry.flags,
1533+ range.we_version_compiled);
1534+ printf("%s\n ", buffer);
1535+ }
12871536
1288- /* Check if there was a timeout */
1289- if(ret == 0)
1290- {
1291- unsigned char * newbuf;
1537+ while(1)
1538+ {
1539+ /* Deal with min/max/short/long for the current value */
1540+ retry_mask = 0;
1541+ /* If we have been returned a MIN value, ask for the MAX */
1542+ if(flags & IW_RETRY_MIN)
1543+ retry_mask = IW_RETRY_MAX;
1544+ /* If we have been returned a MAX value, ask for the MIN */
1545+ if(flags & IW_RETRY_MAX)
1546+ retry_mask = IW_RETRY_MIN;
1547+ /* Same for SHORT and LONG */
1548+ if(flags & IW_RETRY_SHORT)
1549+ retry_mask = IW_RETRY_LONG;
1550+ if(flags & IW_RETRY_LONG)
1551+ retry_mask = IW_RETRY_SHORT;
1552+ /* If we have something to ask for... */
1553+ if(retry_mask)
1554+ {
1555+ retry_mask |= retry_type;
1556+ get_retry_value(skfd, ifname, &wrq, retry_mask,
1557+ buffer, sizeof(buffer),
1558+ range.we_version_compiled);
1559+ }
12921560
1293- realloc:
1294- /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
1295- newbuf = realloc(buffer, buflen);
1296- if(newbuf == NULL)
1297- {
1298- if(buffer)
1299- free(buffer);
1300- fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
1301- return(-1);
1561+ /* And if we have both a limit and a lifetime,
1562+ * ask the other one */
1563+ remain_mask &= ~(wrq.u.retry.flags);
1564+ retry_type = remain_mask;
1565+ /* Nothing anymore : exit the loop */
1566+ if(!retry_type)
1567+ break;
1568+
1569+ /* Ask for this other type of value */
1570+ flags = get_retry_value(skfd, ifname, &wrq, retry_type,
1571+ buffer, sizeof(buffer),
1572+ range.we_version_compiled);
1573+ /* Loop back for min/max/short/long */
1574+ }
13021575 }
1303- buffer = newbuf;
1576+ }
1577+ printf("\n");
1578+ }
1579+ return(0);
1580+}
13041581
1305- /* Try to read the results */
1306- wrq.u.data.pointer = buffer;
1307- wrq.u.data.flags = 0;
1308- wrq.u.data.length = buflen;
1309- if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
1310- {
1311- /* Check if buffer was too small (WE-17 only) */
1312- if((errno == E2BIG) && (range.we_version_compiled > 16))
1313- {
1314- /* Some driver may return very large scan results, either
1315- * because there are many cells, or because they have many
1316- * large elements in cells (like IWEVCUSTOM). Most will
1317- * only need the regular sized buffer. We now use a dynamic
1318- * allocation of the buffer to satisfy everybody. Of course,
1319- * as we don't know in advance the size of the array, we try
1320- * various increasing sizes. Jean II */
1582+/************************ ACCESS POINT LIST ************************/
1583+/*
1584+ * Note : now that we have scanning support, this is depracted and
1585+ * won't survive long. Actually, next version it's out !
1586+ */
13211587
1322- /* Check if the driver gave us any hints. */
1323- if(wrq.u.data.length > buflen)
1324- buflen = wrq.u.data.length;
1325- else
1326- buflen *= 2;
1588+/*------------------------------------------------------------------*/
1589+/*
1590+ * Display the list of ap addresses and the associated stats
1591+ * Exacly the same as the spy list, only with different IOCTL and messages
1592+ */
1593+static int
1594+print_ap_info(int skfd,
1595+ char * ifname,
1596+ char * args[], /* Command line args */
1597+ int count) /* Args count */
1598+{
1599+ struct iwreq wrq;
1600+ char buffer[(sizeof(struct iw_quality) +
1601+ sizeof(struct sockaddr)) * IW_MAX_AP];
1602+ char temp[128];
1603+ struct sockaddr * hwa;
1604+ struct iw_quality * qual;
1605+ iwrange range;
1606+ int has_range = 0;
1607+ int has_qual = 0;
1608+ int n;
1609+ int i;
13271610
1328- /* Try again */
1329- goto realloc;
1330- }
1611+ /* Avoid "Unused parameter" warning */
1612+ args = args; count = count;
13311613
1332- /* Check if results not available yet */
1333- if(errno == EAGAIN)
1334- {
1335- /* Restart timer for only 100ms*/
1336- tv.tv_sec = 0;
1337- tv.tv_usec = 100000;
1338- timeout -= tv.tv_usec;
1339- if(timeout > 0)
1340- continue; /* Try again later */
1341- }
1614+ /* Collect stats */
1615+ wrq.u.data.pointer = (caddr_t) buffer;
1616+ wrq.u.data.length = IW_MAX_AP;
1617+ wrq.u.data.flags = 0;
1618+ if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
1619+ {
1620+ fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
1621+ return(-1);
1622+ }
13421623
1343- /* Bad error */
1344- free(buffer);
1345- fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
1346- ifname, strerror(errno));
1347- return(-2);
1348- }
1349- else
1350- /* We have the results, go to process them */
1351- break;
1352- }
1624+ /* Number of addresses */
1625+ n = wrq.u.data.length;
1626+ has_qual = wrq.u.data.flags;
13531627
1354- /* In here, check if event and event type
1355- * if scan event, read results. All errors bad & no reset timeout */
1628+ /* The two lists */
1629+ hwa = (struct sockaddr *) buffer;
1630+ qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
1631+
1632+ /* Check if we have valid mac address type */
1633+ if(iw_check_mac_addr_type(skfd, ifname) < 0)
1634+ {
1635+ fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
1636+ return(-2);
13561637 }
13571638
1358- if(wrq.u.data.length)
1639+ /* Get range info if we can */
1640+ if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
1641+ has_range = 1;
1642+
1643+ /* Display it */
1644+ if(n == 0)
1645+ printf("%-8.16s No Peers/Access-Point in range\n", ifname);
1646+ else
1647+ printf("%-8.16s Peers/Access-Points in range:\n", ifname);
1648+ for(i = 0; i < n; i++)
13591649 {
1360- struct iw_event iwe;
1361- struct stream_descr stream;
1362- struct iwscan_state state = { .ap_num = 1, .val_index = 0 };
1363- int ret;
1364-
1365-#if 0
1366- /* Debugging code. In theory useless, because it's debugged ;-) */
1367- int i;
1368- printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
1369- for(i = 1; i < wrq.u.data.length; i++)
1370- printf(":%02X", buffer[i]);
1371- printf("]\n");
1372-#endif
1373- printf("%-8.16s Scan completed :\n", ifname);
1374- iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
1375- do
1650+ if(has_qual)
13761651 {
1377- /* Extract an event and print it */
1378- ret = iw_extract_event_stream(&stream, &iwe,
1379- range.we_version_compiled);
1380- if(ret > 0)
1381- print_scanning_token(&stream, &iwe, &state,
1382- &range, has_range);
1652+ /* Print stats for this address */
1653+ printf(" %s : ", iw_saether_ntop(&hwa[i], temp));
1654+ iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
1655+ printf("%s\n", temp);
13831656 }
1384- while(ret > 0);
1385- printf("\n");
1657+ else
1658+ /* Only print the address */
1659+ printf(" %s\n", iw_saether_ntop(&hwa[i], temp));
13861660 }
1387- else
1388- printf("%-8.16s No scan results\n", ifname);
1389-
1390- free(buffer);
1661+ printf("\n");
13911662 return(0);
13921663 }
13931664
@@ -1419,7 +1690,7 @@ static const char * event_capa_evt[] =
14191690
14201691 /*------------------------------------------------------------------*/
14211692 /*
1422- * Print the number of available transmit powers for the device
1693+ * Print the event capability for the device
14231694 */
14241695 static int
14251696 print_event_capa_info(int skfd,
@@ -1440,7 +1711,7 @@ print_event_capa_info(int skfd,
14401711 ifname);
14411712 else
14421713 {
1443-#if 0
1714+#ifdef DEBUG
14441715 /* Debugging ;-) */
14451716 for(cmd = 0x8B00; cmd < 0x8C0F; cmd++)
14461717 {
@@ -1473,6 +1744,296 @@ print_event_capa_info(int skfd,
14731744 return(0);
14741745 }
14751746
1747+/*************************** WPA SUPPORT ***************************/
1748+
1749+/*------------------------------------------------------------------*/
1750+/*
1751+ * Print the authentication parameters for the device
1752+ */
1753+static int
1754+print_auth_info(int skfd,
1755+ char * ifname,
1756+ char * args[], /* Command line args */
1757+ int count) /* Args count */
1758+{
1759+ struct iwreq wrq;
1760+ struct iw_range range;
1761+ unsigned int k;
1762+
1763+ /* Avoid "Unused parameter" warning */
1764+ args = args; count = count;
1765+
1766+ /* Extract range info */
1767+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1768+ (range.we_version_compiled < 18))
1769+ fprintf(stderr, "%-8.16s no authentication information.\n\n",
1770+ ifname);
1771+ else
1772+ {
1773+ /* Print WPA/802.1x/802.11i security parameters */
1774+ if(!range.enc_capa)
1775+ {
1776+ printf("%-8.16s unknown authentication information.\n\n", ifname);
1777+ }
1778+ else
1779+ {
1780+ /* Display advanced encryption capabilities */
1781+ printf("%-8.16s Authentication capabilities :", ifname);
1782+ iw_print_mask_name(range.enc_capa,
1783+ iw_auth_capa_name, IW_AUTH_CAPA_NUM,
1784+ "\n\t\t");
1785+ printf("\n");
1786+
1787+ /* Extract all auth settings */
1788+ for(k = 0; k < IW_AUTH_SETTINGS_NUM; k++)
1789+ {
1790+ wrq.u.param.flags = iw_auth_settings[k].value;
1791+ if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
1792+ {
1793+ printf(" Current %s :", iw_auth_settings[k].label);
1794+ if(iw_auth_settings[k].names != NULL)
1795+ iw_print_mask_name(wrq.u.param.value,
1796+ iw_auth_settings[k].names,
1797+ iw_auth_settings[k].num_names,
1798+ "\n\t\t");
1799+ else
1800+ printf((wrq.u.param.value) ? " yes" : " no");
1801+ printf("\n");
1802+ }
1803+ }
1804+ }
1805+
1806+ printf("\n\n");
1807+ }
1808+ return(0);
1809+}
1810+
1811+/*------------------------------------------------------------------*/
1812+/*
1813+ * Print all the available wpa keys for the device
1814+ */
1815+static int
1816+print_wpakeys_info(int skfd,
1817+ char * ifname,
1818+ char * args[], /* Command line args */
1819+ int count) /* Args count */
1820+{
1821+ struct iwreq wrq;
1822+ struct iw_range range;
1823+ unsigned char extbuf[IW_EXTKEY_SIZE];
1824+ struct iw_encode_ext *extinfo;
1825+ unsigned int k;
1826+ char buffer[128];
1827+
1828+ /* Avoid "Unused parameter" warning */
1829+ args = args; count = count;
1830+
1831+ /* This always point to the same place */
1832+ extinfo = (struct iw_encode_ext *) extbuf;
1833+
1834+ /* Extract range info */
1835+ if(iw_get_range_info(skfd, ifname, &range) < 0)
1836+ fprintf(stderr, "%-8.16s no wpa key information.\n\n",
1837+ ifname);
1838+ else
1839+ {
1840+ printf("%-8.16s ", ifname);
1841+ /* Print key sizes */
1842+ if((range.num_encoding_sizes > 0) &&
1843+ (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
1844+ {
1845+ printf("%d key sizes : %d", range.num_encoding_sizes,
1846+ range.encoding_size[0] * 8);
1847+ /* Print them all */
1848+ for(k = 1; k < range.num_encoding_sizes; k++)
1849+ printf(", %d", range.encoding_size[k] * 8);
1850+ printf("bits\n ");
1851+ }
1852+
1853+ /* Print the keys */
1854+ printf("%d keys available :\n", range.max_encoding_tokens);
1855+ for(k = 1; k <= range.max_encoding_tokens; k++)
1856+ {
1857+ /* Cleanup. Driver may not fill everything */
1858+ memset(extbuf, '\0', IW_EXTKEY_SIZE);
1859+
1860+ /* Get whole struct containing one WPA key */
1861+ wrq.u.data.pointer = (caddr_t) extbuf;
1862+ wrq.u.data.length = IW_EXTKEY_SIZE;
1863+ wrq.u.data.flags = k;
1864+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) < 0)
1865+ {
1866+ fprintf(stderr, "Error reading wpa keys (SIOCGIWENCODEEXT): %s\n", strerror(errno));
1867+ break;
1868+ }
1869+
1870+ /* Sanity check */
1871+ if(wrq.u.data.length <
1872+ (sizeof(struct iw_encode_ext) + extinfo->key_len))
1873+ break;
1874+
1875+ /* Check if key is disabled */
1876+ if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
1877+ (extinfo->key_len == 0))
1878+ printf("\t\t[%d]: off\n", k);
1879+ else
1880+ {
1881+ /* Display the key */
1882+ iw_print_key(buffer, sizeof(buffer),
1883+ extinfo->key, extinfo->key_len, wrq.u.data.flags);
1884+ printf("\t\t[%d]: %s", k, buffer);
1885+
1886+ /* Key size */
1887+ printf(" (%d bits)", extinfo->key_len * 8);
1888+ printf("\n");
1889+
1890+ /* Other info... */
1891+ printf("\t\t Address: %s\n",
1892+ iw_saether_ntop(&extinfo->addr, buffer));
1893+
1894+ printf("\t\t Algorithm:");
1895+ iw_print_value_name(extinfo->alg,
1896+ iw_encode_alg_name, IW_ENCODE_ALG_NUM);
1897+
1898+ printf("\n\t\t Flags: 0x%08x\n", extinfo->ext_flags);
1899+ if (extinfo->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID)
1900+ printf("\t\t tx-seq-valid\n");
1901+ if (extinfo->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1902+ printf("\t\t rx-seq-valid\n");
1903+ if (extinfo->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1904+ printf("\t\t group-key\n");
1905+ }
1906+ }
1907+ /* Print current key index and mode */
1908+ wrq.u.data.pointer = (caddr_t) extbuf;
1909+ wrq.u.data.length = IW_EXTKEY_SIZE;
1910+ wrq.u.data.flags = 0; /* Set index to zero to get current */
1911+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) >= 0)
1912+ {
1913+ /* Note : if above fails, we have already printed an error
1914+ * message int the loop above */
1915+ printf(" Current Transmit Key: [%d]\n",
1916+ wrq.u.data.flags & IW_ENCODE_INDEX);
1917+ if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
1918+ printf(" Security mode:restricted\n");
1919+ if(wrq.u.data.flags & IW_ENCODE_OPEN)
1920+ printf(" Security mode:open\n");
1921+ }
1922+
1923+ printf("\n\n");
1924+ }
1925+ return(0);
1926+}
1927+
1928+/*------------------------------------------------------------------*/
1929+/*
1930+ * Print the Generic IE for the device
1931+ * Note : indentation is broken. We need to fix that.
1932+ */
1933+static int
1934+print_gen_ie_info(int skfd,
1935+ char * ifname,
1936+ char * args[], /* Command line args */
1937+ int count) /* Args count */
1938+{
1939+ struct iwreq wrq;
1940+ unsigned char buf[IW_GENERIC_IE_MAX];
1941+
1942+ /* Avoid "Unused parameter" warning */
1943+ args = args; count = count;
1944+
1945+ wrq.u.data.pointer = (caddr_t)buf;
1946+ wrq.u.data.length = IW_GENERIC_IE_MAX;
1947+ wrq.u.data.flags = 0;
1948+
1949+ if(iw_get_ext(skfd, ifname, SIOCGIWGENIE, &wrq) < 0)
1950+ fprintf(stderr, "%-8.16s no generic IE (%s).\n\n",
1951+ ifname, strerror(errno));
1952+ else
1953+ {
1954+ fprintf(stderr, "%-8.16s\n", ifname);
1955+ if(wrq.u.data.length == 0)
1956+ printf(" empty generic IE\n");
1957+ else
1958+ iw_print_gen_ie(buf, wrq.u.data.length);
1959+ printf("\n");
1960+ }
1961+ return(0);
1962+}
1963+
1964+/**************************** MODULATION ****************************/
1965+
1966+/*------------------------------------------------------------------*/
1967+/*
1968+ * Print Modulation info for each device
1969+ */
1970+static int
1971+print_modul_info(int skfd,
1972+ char * ifname,
1973+ char * args[], /* Command line args */
1974+ int count) /* Args count */
1975+{
1976+ struct iwreq wrq;
1977+ struct iw_range range;
1978+
1979+ /* Avoid "Unused parameter" warning */
1980+ args = args; count = count;
1981+
1982+ /* Extract range info */
1983+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1984+ (range.we_version_compiled < 11))
1985+ fprintf(stderr, "%-8.16s no modulation information.\n\n",
1986+ ifname);
1987+ else
1988+ {
1989+ if(range.modul_capa == 0x0)
1990+ printf("%-8.16s unknown modulation information.\n\n", ifname);
1991+ else
1992+ {
1993+ int i;
1994+ printf("%-8.16s Modulations available :\n", ifname);
1995+
1996+ /* Display each modulation available */
1997+ for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
1998+ {
1999+ if((range.modul_capa & iw_modul_list[i].mask)
2000+ == iw_modul_list[i].mask)
2001+ printf(" %-8s: %s\n",
2002+ iw_modul_list[i].cmd, iw_modul_list[i].verbose);
2003+ }
2004+
2005+ /* Get current modulations settings */
2006+ wrq.u.param.flags = 0;
2007+ if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) >= 0)
2008+ {
2009+ unsigned int modul = wrq.u.param.value;
2010+ int n = 0;
2011+
2012+ printf(" Current modulations %c",
2013+ wrq.u.param.fixed ? '=' : ':');
2014+
2015+ /* Display each modulation enabled */
2016+ for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
2017+ {
2018+ if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
2019+ {
2020+ if((n++ % 8) == 0)
2021+ printf("\n ");
2022+ else
2023+ printf(" ; ");
2024+ printf("%s", iw_modul_list[i].cmd);
2025+ }
2026+ }
2027+
2028+ printf("\n");
2029+ }
2030+ printf("\n");
2031+ }
2032+ }
2033+ return(0);
2034+}
2035+#endif /* WE_ESSENTIAL */
2036+
14762037 /************************* COMMON UTILITIES *************************/
14772038 /*
14782039 * This section was initially written by Michael Tokarev <mjt@tls.msk.ru>
@@ -1484,27 +2045,33 @@ print_event_capa_info(int skfd,
14842045 * Map command line arguments to the proper procedure...
14852046 */
14862047 typedef struct iwlist_entry {
1487- const char *cmd;
1488- iw_enum_handler fn;
1489- int min_count;
1490- int max_count;
2048+ const char * cmd; /* Command line shorthand */
2049+ iw_enum_handler fn; /* Subroutine */
2050+ int max_count;
2051+ const char * argsname; /* Args as human readable string */
14912052 } iwlist_cmd;
14922053
14932054 static const struct iwlist_entry iwlist_cmds[] = {
1494- { "scanning", print_scanning_info, 0, 5 },
1495- { "frequency", print_freq_info, 0, 0 },
1496- { "channel", print_freq_info, 0, 0 },
1497- { "bitrate", print_bitrate_info, 0, 0 },
1498- { "rate", print_bitrate_info, 0, 0 },
1499- { "encryption", print_keys_info, 0, 0 },
1500- { "key", print_keys_info, 0, 0 },
1501- { "power", print_pm_info, 0, 0 },
1502- { "txpower", print_txpower_info, 0, 0 },
1503- { "retry", print_retry_info, 0, 0 },
1504- { "ap", print_ap_info, 0, 0 },
1505- { "accesspoints", print_ap_info, 0, 0 },
1506- { "peers", print_ap_info, 0, 0 },
1507- { "event", print_event_capa_info, 0, 0 },
2055+ { "scanning", print_scanning_info, -1, "[essid NNN] [last]" },
2056+ { "frequency", print_freq_info, 0, NULL },
2057+ { "channel", print_freq_info, 0, NULL },
2058+ { "bitrate", print_bitrate_info, 0, NULL },
2059+ { "rate", print_bitrate_info, 0, NULL },
2060+ { "encryption", print_keys_info, 0, NULL },
2061+ { "keys", print_keys_info, 0, NULL },
2062+ { "power", print_pm_info, 0, NULL },
2063+#ifndef WE_ESSENTIAL
2064+ { "txpower", print_txpower_info, 0, NULL },
2065+ { "retry", print_retry_info, 0, NULL },
2066+ { "ap", print_ap_info, 0, NULL },
2067+ { "accesspoints", print_ap_info, 0, NULL },
2068+ { "peers", print_ap_info, 0, NULL },
2069+ { "event", print_event_capa_info, 0, NULL },
2070+ { "auth", print_auth_info, 0, NULL },
2071+ { "wpakeys", print_wpakeys_info, 0, NULL },
2072+ { "genie", print_gen_ie_info, 0, NULL },
2073+ { "modulation", print_modul_info, 0, NULL },
2074+#endif /* WE_ESSENTIAL */
15082075 { NULL, NULL, 0, 0 },
15092076 };
15102077
@@ -1543,13 +2110,13 @@ find_command(const char * cmd)
15432110
15442111 if(found == NULL)
15452112 {
1546- fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
2113+ fprintf(stderr, "iwlist: unknown command `%s' (check 'iwlist --help').\n", cmd);
15472114 return NULL;
15482115 }
15492116
15502117 if(ambig)
15512118 {
1552- fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
2119+ fprintf(stderr, "iwlist: command `%s' is ambiguous (check 'iwlist --help').\n", cmd);
15532120 return NULL;
15542121 }
15552122
@@ -1562,12 +2129,17 @@ find_command(const char * cmd)
15622129 */
15632130 static void iw_usage(int status)
15642131 {
1565- FILE* f = status ? stderr : stdout;
1566- int i;
2132+ FILE * f = status ? stderr : stdout;
2133+ int i;
2134+
2135+ for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
2136+ {
2137+ fprintf(f, "%s [interface] %s %s\n",
2138+ (i ? " " : "Usage: iwlist"),
2139+ iwlist_cmds[i].cmd,
2140+ iwlist_cmds[i].argsname ? iwlist_cmds[i].argsname : "");
2141+ }
15672142
1568- fprintf(f, "Usage: iwlist [interface] %s\n", iwlist_cmds[0].cmd);
1569- for(i = 1; iwlist_cmds[i].cmd != NULL; ++i)
1570- fprintf(f, " [interface] %s\n", iwlist_cmds[i].cmd);
15712143 exit(status);
15722144 }
15732145
@@ -1588,7 +2160,7 @@ main(int argc,
15882160 int count; /* Number of arguments */
15892161 const iwlist_cmd *iwcmd;
15902162
1591- if(argc == 1 || argc > 3)
2163+ if(argc < 2)
15922164 iw_usage(1);
15932165
15942166 /* Those don't apply to all interfaces */
@@ -1618,14 +2190,10 @@ main(int argc,
16182190 return 1;
16192191
16202192 /* Check arg numbers */
1621- if(count < iwcmd->min_count)
1622- {
1623- fprintf(stderr, "iwlist: command `%s' needs more arguments\n", cmd);
1624- return 1;
1625- }
1626- if(count > iwcmd->max_count)
2193+ if((iwcmd->max_count >= 0) && (count > iwcmd->max_count))
16272194 {
1628- fprintf(stderr, "iwlist: command `%s' needs fewer arguments\n", cmd);
2195+ fprintf(stderr, "iwlist: command `%s' needs fewer arguments (max %d)\n",
2196+ iwcmd->cmd, iwcmd->max_count);
16292197 return 1;
16302198 }
16312199
--- a/wireless_tools/iwmulticall.c
+++ b/wireless_tools/iwmulticall.c
@@ -61,21 +61,27 @@ extern int
6161 /* Get iwconfig in there. Mandatory. */
6262 #define main(args...) main_iwconfig(args)
6363 #define iw_usage(args...) iwconfig_usage(args)
64+#define find_command(args...) iwconfig_find_command(args)
6465 #include "iwconfig.c"
66+#undef find_command
6567 #undef iw_usage
6668 #undef main
6769
6870 /* Get iwlist in there. Scanning support is pretty sweet. */
6971 #define main(args...) main_iwlist(args)
7072 #define iw_usage(args...) iwlist_usage(args)
73+#define find_command(args...) iwlist_find_command(args)
7174 #include "iwlist.c"
75+#undef find_command
7276 #undef iw_usage
7377 #undef main
7478
79+#ifndef WE_ESSENTIAL
7580 /* Get iwspy in there, it's not that big. */
7681 #define main(args...) main_iwspy(args)
7782 #include "iwspy.c"
7883 #undef main
84+#endif /* WE_ESSENTIAL */
7985
8086 /* Get iwpriv in there. Mandatory for HostAP and some other drivers. */
8187 #define main(args...) main_iwpriv(args)
@@ -122,8 +128,10 @@ main(int argc,
122128 return(main_iwconfig(argc, argv));
123129 if(!strcmp(call_name, "iwlist"))
124130 return(main_iwlist(argc, argv));
131+#ifndef WE_ESSENTIAL
125132 if(!strcmp(call_name, "iwspy"))
126133 return(main_iwspy(argc, argv));
134+#endif /* WE_ESSENTIAL */
127135 if(!strcmp(call_name, "iwpriv"))
128136 return(main_iwpriv(argc, argv));
129137 if(!strcmp(call_name, "iwgetid"))
--- a/wireless_tools/iwpriv.8
+++ b/wireless_tools/iwpriv.8
@@ -16,13 +16,9 @@ network interface
1616 .br
1717 .BI "iwpriv " "interface private-command " "[" private-parameters ]
1818 .br
19-.BI "iwpriv " "interface private-command [I] " "[" private-parameters ]
19+.BI "iwpriv " "interface private-command " [ I "] [" private-parameters ]
2020 .br
2121 .BI "iwpriv " interface " --all"
22-.br
23-.BI "iwpriv " interface " roam " {on,off}
24-.br
25-.BI "iwpriv " interface " port " {ad-hoc,managed,N}
2622 .\"
2723 .\" DESCRIPTION part
2824 .\"
@@ -64,7 +60,7 @@ about those parameters.
6460 However you should refer to the device driver documentation for
6561 information on how to properly use the command and the effect.
6662 .TP
67-.I "private-command [I]" "[" private-parameters ]
63+.IR "private-command " [ I "] [" private-parameters ]
6864 Idem, except that
6965 .I I
7066 (an integer) is passed to the command as a
@@ -75,19 +71,6 @@ the driver documentation should tell you when it's needed.
7571 .BR -a / --all
7672 Execute and display all the private commands that don't take any
7773 arguments (i.e. read only).
78-.TP
79-.B roam
80-Enable or disable roaming, if supported. Call the private command
81-.IR setroam .
82-Found in the
83-.I wavelan_cs
84-driver.
85-.TP
86-.B port
87-Read or configure the port type. Call the private commands
88-.IR gport_type ", " sport_type ", " get_port " or " set_port
89-found in the
90-.IR wavelan2_cs " and " wvlan_cs " drivers."
9174 .\"
9275 .\" DISPLAY part
9376 .\"
--- a/wireless_tools/iwpriv.c
+++ b/wireless_tools/iwpriv.c
@@ -1,14 +1,14 @@
11 /*
22 * Wireless Tools
33 *
4- * Jean II - HPLB 97->99 - HPL 99->04
4+ * Jean II - HPLB 97->99 - HPL 99->07
55 *
66 * Main code for "iwconfig". This is the generic tool for most
77 * manipulations...
88 * You need to link this code against "iwlib.c" and "-lm".
99 *
1010 * This file is released under the GPL license.
11- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
11+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
1212 */
1313
1414 #include "iwlib.h" /* Header */
@@ -384,9 +384,9 @@ set_private_cmd(int skfd, /* Socket */
384384 printf("Invalid float [%s]...\n", args[i]);
385385 return(-1);
386386 }
387- if(index(args[i], 'G')) freq *= GIGA;
388- if(index(args[i], 'M')) freq *= MEGA;
389- if(index(args[i], 'k')) freq *= KILO;
387+ if(strchr(args[i], 'G')) freq *= GIGA;
388+ if(strchr(args[i], 'M')) freq *= MEGA;
389+ if(strchr(args[i], 'k')) freq *= KILO;
390390 sscanf(args[i], "%i", &temp);
391391 iw_float2freq(freq, ((struct iw_freq *) buffer) + i);
392392 }
@@ -690,6 +690,7 @@ print_priv_all(int skfd,
690690 * Convenient access to some private ioctls of some devices
691691 */
692692
693+#if 0
693694 /*------------------------------------------------------------------*/
694695 /*
695696 * Set roaming mode on and off
@@ -905,6 +906,7 @@ port_type(int skfd, /* Socket */
905906 free(priv);
906907 return(-1);
907908 }
909+#endif
908910
909911 /******************************* MAIN ********************************/
910912
@@ -954,6 +956,7 @@ main(int argc,
954956 (!strcmp(argv[2], "--all")))
955957 print_priv_all(skfd, argv[1], NULL, 0);
956958 else
959+#if 0
957960 /* Roaming */
958961 if(!strncmp(argv[2], "roam", 4))
959962 goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]);
@@ -962,6 +965,7 @@ main(int argc,
962965 if(!strncmp(argv[2], "port", 4))
963966 goterr = port_type(skfd, argv + 3, argc - 3, argv[1]);
964967 else
968+#endif
965969 /*-------------*/
966970 /* Otherwise, it's a private ioctl */
967971 goterr = set_private(skfd, argv + 2, argc - 2, argv[1]);
--- a/wireless_tools/iwspy.8
+++ b/wireless_tools/iwspy.8
@@ -11,7 +11,7 @@ iwspy \- Get wireless statistics from specific nodes
1111 .\" SYNOPSIS part
1212 .\"
1313 .SH SYNOPSIS
14-.BI "iwspy " interface
14+.BI "iwspy [" interface ]
1515 .br
1616 .BI "iwspy " interface " [+] " DNSNAME " | " IPADDR " | " HWADDR " [...]"
1717 .br
--- a/wireless_tools/sample_pm.c
+++ b/wireless_tools/sample_pm.c
@@ -56,7 +56,10 @@ static int ioctl_set_power(struct net_device *dev,
5656 /* Set period */
5757 if(prq->flags & IW_POWER_PERIOD)
5858 {
59- int period = prq->value/1000000;
59+ int period = prq->value;
60+#if WIRELESS_EXT < 21
61+ period /= 1000000;
62+#endif
6063 /* Hum: check if within bounds... */
6164
6265 /* Activate PM */
@@ -114,12 +117,18 @@ static int ioctl_get_power(struct net_device *dev,
114117 /* By default, the min */
115118 if(!(inc_flags & IW_POWER_MAX))
116119 {
117- prq->value = local->pm_min_period * 1000000;
120+ prq->value = local->pm_min_period;
121+#if WIRELESS_EXT < 21
122+ prq->value *= 1000000;
123+#endif
118124 prq->flags |= IW_POWER_MIN;
119125 }
120126 else
121127 {
122- prq->value = local->pm_max_period * 1000000;
128+ prq->value = local->pm_max_period;
129+#if WIRELESS_EXT < 21
130+ prq->value *= 1000000;
131+#endif
123132 prq->flags |= IW_POWER_MAX;
124133 }
125134 }
@@ -129,7 +138,12 @@ static int ioctl_get_power(struct net_device *dev,
129138 if(inc_flags & (IW_POWER_MIN | IW_POWER_MAX))
130139 return(-EINVAL);
131140 else
132- prq->value = local->pm_period * 1000000;
141+ {
142+ prq->value = local->pm_period;
143+#if WIRELESS_EXT < 21
144+ prq->value *= 1000000;
145+#endif
146+ }
133147 }
134148 }
135149 else
@@ -165,8 +179,13 @@ static int ioctl_get_range(struct net_device *dev,
165179 #endif /* WIRELESS_EXT > 10 */
166180
167181 #if WIRELESS_EXT > 9
182+#if WIRELESS_EXT < 21
168183 range.min_pmp = 1000000; /* 1 units */
169184 range.max_pmp = 12000000; /* 12 units */
185+#else
186+ range.min_pmp = 1; /* 1 units */
187+ range.max_pmp = 12; /* 12 units */
188+#endif
170189 range.min_pmt = 1000; /* 1 ms */
171190 range.max_pmt = 1000000; /* 1 s */
172191 range.pmp_flags = IW_POWER_PERIOD | IW_POWER_RELATIVE |
--- /dev/null
+++ b/wireless_tools/udev.import_devpath.diff
@@ -0,0 +1,39 @@
1+diff -u -p udev-106/udev_rules.j1.c udev-106/udev_rules.c
2+--- udev-106/udev_rules.j1.c 2007-03-15 10:07:51.000000000 -0700
3++++ udev-106/udev_rules.c 2007-03-15 10:09:50.000000000 -0700
4+@@ -186,7 +186,16 @@ static int import_keys_into_env(struct u
5+ linepos = line;
6+ if (get_key(&linepos, &variable, &value) == 0) {
7+ dbg("import '%s=%s'", variable, value);
8+- name_list_key_add(&udev->env_list, variable, value);
9++ /* handle device, renamed by external tool,
10++ * returning new path */
11++ if (strcmp(variable, "DEVPATH") == 0) {
12++ info("updating devpath from '%s' to '%s'",
13++ udev->dev->devpath, value);
14++ sysfs_device_set_values(udev->dev, value,
15++ NULL, NULL);
16++ } else
17++ name_list_key_add(&udev->env_list,
18++ variable, value);
19+ setenv(variable, value, 1);
20+ }
21+ }
22+diff -u -p udev-106/udevtest.j1.c udev-106/udevtest.c
23+--- udev-106/udevtest.j1.c 2007-03-15 10:39:16.000000000 -0700
24++++ udev-106/udevtest.c 2007-03-15 10:42:09.000000000 -0700
25+@@ -59,8 +59,13 @@ int main(int argc, char *argv[], char *e
26+
27+ info("version %s", UDEV_VERSION);
28+ udev_config_init();
29+- if (udev_log_priority < LOG_INFO)
30++ if (udev_log_priority < LOG_INFO) {
31++ char priority[32];
32++
33+ udev_log_priority = LOG_INFO;
34++ sprintf(priority, "%i", udev_log_priority);
35++ setenv("UDEV_LOG", priority, 1);
36++ }
37+
38+ for (i = 1 ; i < argc; i++) {
39+ char *arg = argv[i];
--- /dev/null
+++ b/wireless_tools/wireless.21.h
@@ -0,0 +1,1120 @@
1+/*
2+ * This file define a set of standard wireless extensions
3+ *
4+ * Version : 21 14.3.06
5+ *
6+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
7+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
8+ */
9+
10+#ifndef _LINUX_WIRELESS_H
11+#define _LINUX_WIRELESS_H
12+
13+/************************** DOCUMENTATION **************************/
14+/*
15+ * Initial APIs (1996 -> onward) :
16+ * -----------------------------
17+ * Basically, the wireless extensions are for now a set of standard ioctl
18+ * call + /proc/net/wireless
19+ *
20+ * The entry /proc/net/wireless give statistics and information on the
21+ * driver.
22+ * This is better than having each driver having its entry because
23+ * its centralised and we may remove the driver module safely.
24+ *
25+ * Ioctl are used to configure the driver and issue commands. This is
26+ * better than command line options of insmod because we may want to
27+ * change dynamically (while the driver is running) some parameters.
28+ *
29+ * The ioctl mechanimsm are copied from standard devices ioctl.
30+ * We have the list of command plus a structure descibing the
31+ * data exchanged...
32+ * Note that to add these ioctl, I was obliged to modify :
33+ * # net/core/dev.c (two place + add include)
34+ * # net/ipv4/af_inet.c (one place + add include)
35+ *
36+ * /proc/net/wireless is a copy of /proc/net/dev.
37+ * We have a structure for data passed from the driver to /proc/net/wireless
38+ * Too add this, I've modified :
39+ * # net/core/dev.c (two other places)
40+ * # include/linux/netdevice.h (one place)
41+ * # include/linux/proc_fs.h (one place)
42+ *
43+ * New driver API (2002 -> onward) :
44+ * -------------------------------
45+ * This file is only concerned with the user space API and common definitions.
46+ * The new driver API is defined and documented in :
47+ * # include/net/iw_handler.h
48+ *
49+ * Note as well that /proc/net/wireless implementation has now moved in :
50+ * # net/core/wireless.c
51+ *
52+ * Wireless Events (2002 -> onward) :
53+ * --------------------------------
54+ * Events are defined at the end of this file, and implemented in :
55+ * # net/core/wireless.c
56+ *
57+ * Other comments :
58+ * --------------
59+ * Do not add here things that are redundant with other mechanisms
60+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
61+ * wireless specific.
62+ *
63+ * These wireless extensions are not magic : each driver has to provide
64+ * support for them...
65+ *
66+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
67+ * work in progress. Contact me if you have ideas of improvements...
68+ */
69+
70+/***************************** INCLUDES *****************************/
71+
72+/* This header is used in user-space, therefore need to be sanitised
73+ * for that purpose. Those includes are usually not compatible with glibc.
74+ * To know which includes to use in user-space, check iwlib.h. */
75+#ifdef __KERNEL__
76+#include <linux/types.h> /* for "caddr_t" et al */
77+#include <linux/socket.h> /* for "struct sockaddr" et al */
78+#include <linux/if.h> /* for IFNAMSIZ and co... */
79+#endif /* __KERNEL__ */
80+
81+/***************************** VERSION *****************************/
82+/*
83+ * This constant is used to know the availability of the wireless
84+ * extensions and to know which version of wireless extensions it is
85+ * (there is some stuff that will be added in the future...)
86+ * I just plan to increment with each new version.
87+ */
88+#define WIRELESS_EXT 21
89+
90+/*
91+ * Changes :
92+ *
93+ * V2 to V3
94+ * --------
95+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
96+ * - Encryption renamed to Encode to avoid US regulation problems
97+ * - Frequency changed from float to struct to avoid problems on old 386
98+ *
99+ * V3 to V4
100+ * --------
101+ * - Add sensitivity
102+ *
103+ * V4 to V5
104+ * --------
105+ * - Missing encoding definitions in range
106+ * - Access points stuff
107+ *
108+ * V5 to V6
109+ * --------
110+ * - 802.11 support (ESSID ioctls)
111+ *
112+ * V6 to V7
113+ * --------
114+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
115+ *
116+ * V7 to V8
117+ * --------
118+ * - Changed my e-mail address
119+ * - More 802.11 support (nickname, rate, rts, frag)
120+ * - List index in frequencies
121+ *
122+ * V8 to V9
123+ * --------
124+ * - Support for 'mode of operation' (ad-hoc, managed...)
125+ * - Support for unicast and multicast power saving
126+ * - Change encoding to support larger tokens (>64 bits)
127+ * - Updated iw_params (disable, flags) and use it for NWID
128+ * - Extracted iw_point from iwreq for clarity
129+ *
130+ * V9 to V10
131+ * ---------
132+ * - Add PM capability to range structure
133+ * - Add PM modifier : MAX/MIN/RELATIVE
134+ * - Add encoding option : IW_ENCODE_NOKEY
135+ * - Add TxPower ioctls (work like TxRate)
136+ *
137+ * V10 to V11
138+ * ----------
139+ * - Add WE version in range (help backward/forward compatibility)
140+ * - Add retry ioctls (work like PM)
141+ *
142+ * V11 to V12
143+ * ----------
144+ * - Add SIOCSIWSTATS to get /proc/net/wireless programatically
145+ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
146+ * - Add new statistics (frag, retry, beacon)
147+ * - Add average quality (for user space calibration)
148+ *
149+ * V12 to V13
150+ * ----------
151+ * - Document creation of new driver API.
152+ * - Extract union iwreq_data from struct iwreq (for new driver API).
153+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
154+ *
155+ * V13 to V14
156+ * ----------
157+ * - Wireless Events support : define struct iw_event
158+ * - Define additional specific event numbers
159+ * - Add "addr" and "param" fields in union iwreq_data
160+ * - AP scanning stuff (SIOCSIWSCAN and friends)
161+ *
162+ * V14 to V15
163+ * ----------
164+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
165+ * - Make struct iw_freq signed (both m & e), add explicit padding
166+ * - Add IWEVCUSTOM for driver specific event/scanning token
167+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
168+ * - Add IW_TXPOW_RANGE for range of Tx Powers
169+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
170+ * - Add IW_MODE_MONITOR for passive monitor
171+ *
172+ * V15 to V16
173+ * ----------
174+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
175+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
176+ * - Reshuffle struct iw_range for increases, add filler
177+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
178+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
179+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
180+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
181+ *
182+ * V16 to V17
183+ * ----------
184+ * - Add flags to frequency -> auto/fixed
185+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
186+ * - Wireless Event capability in struct iw_range
187+ * - Add support for relative TxPower (yick !)
188+ *
189+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
190+ * ----------
191+ * - Add support for WPA/WPA2
192+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
193+ * SIOCGIWENCODEEXT)
194+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
195+ * - Add SIOCSIWMLME
196+ * - Add SIOCSIWPMKSA
197+ * - Add struct iw_range bit field for supported encoding capabilities
198+ * - Add optional scan request parameters for SIOCSIWSCAN
199+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
200+ * related parameters (extensible up to 4096 parameter values)
201+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
202+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
203+ *
204+ * V18 to V19
205+ * ----------
206+ * - Remove (struct iw_point *)->pointer from events and streams
207+ * - Remove header includes to help user space
208+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
209+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
210+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
211+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
212+ *
213+ * V20 to V21
214+ * ----------
215+ * - Remove (struct net_device *)->get_wireless_stats()
216+ * - Change length in ESSID and NICK to strlen() instead of strlen()+1
217+ * - Add SIOCSIWMODUL/SIOCGIWMODUL for modulation setting
218+ * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
219+ * - Add IW_POWER_SAVING power type
220+ * - Power/Retry relative values no longer * 100000
221+ * - Add bitrate flags for unicast/broadcast
222+ */
223+
224+/**************************** CONSTANTS ****************************/
225+
226+/* -------------------------- IOCTL LIST -------------------------- */
227+
228+/* Wireless Identification */
229+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
230+#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
231+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
232+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
233+ * Don't put the name of your driver there, it's useless. */
234+
235+/* Basic operations */
236+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */
237+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */
238+#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */
239+#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */
240+#define SIOCSIWMODE 0x8B06 /* set operation mode */
241+#define SIOCGIWMODE 0x8B07 /* get operation mode */
242+#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */
243+#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */
244+
245+/* Informative stuff */
246+#define SIOCSIWRANGE 0x8B0A /* Unused */
247+#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */
248+#define SIOCSIWPRIV 0x8B0C /* Unused */
249+#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
250+#define SIOCSIWSTATS 0x8B0E /* Unused */
251+#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */
252+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
253+ * is never passed to the driver (i.e. the driver will never see it). */
254+
255+/* Spy support (statistics per MAC address - used for Mobile IP support) */
256+#define SIOCSIWSPY 0x8B10 /* set spy addresses */
257+#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
258+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
259+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
260+
261+/* Access Point manipulation */
262+#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
263+#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
264+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */
265+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */
266+#define SIOCGIWSCAN 0x8B19 /* get scanning results */
267+
268+/* 802.11 specific support */
269+#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
270+#define SIOCGIWESSID 0x8B1B /* get ESSID */
271+#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */
272+#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
273+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
274+ * within the 'iwreq' structure, so we need to use the 'data' member to
275+ * point to a string in user space, like it is done for RANGE... */
276+
277+/* Other parameters useful in 802.11 and some other devices */
278+#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
279+#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
280+#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */
281+#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */
282+#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */
283+#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */
284+#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */
285+#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */
286+#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */
287+#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */
288+
289+/* Encoding stuff (scrambling, hardware security, WEP...) */
290+#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */
291+#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */
292+/* Power saving stuff (power management, unicast and multicast) */
293+#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
294+#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
295+/* Modulation bitmask */
296+#define SIOCSIWMODUL 0x8B2E /* set Modulations settings */
297+#define SIOCGIWMODUL 0x8B2F /* get Modulations settings */
298+
299+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
300+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
301+ * fields. More than one IE may be included in the request. Setting the generic
302+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
303+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
304+ * are required to report the used IE as a wireless event, e.g., when
305+ * associating with an AP. */
306+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
307+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
308+
309+/* WPA : IEEE 802.11 MLME requests */
310+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
311+ * struct iw_mlme */
312+/* WPA : Authentication mode parameters */
313+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
314+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
315+
316+/* WPA : Extended version of encoding configuration */
317+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
318+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
319+
320+/* WPA2 : PMKSA cache management */
321+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
322+
323+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
324+
325+/* These 32 ioctl are wireless device private, for 16 commands.
326+ * Each driver is free to use them for whatever purpose it chooses,
327+ * however the driver *must* export the description of those ioctls
328+ * with SIOCGIWPRIV and *must* use arguments as defined below.
329+ * If you don't follow those rules, DaveM is going to hate you (reason :
330+ * it make mixed 32/64bit operation impossible).
331+ */
332+#define SIOCIWFIRSTPRIV 0x8BE0
333+#define SIOCIWLASTPRIV 0x8BFF
334+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
335+ * separate range because of collisions with other tools such as
336+ * 'mii-tool'.
337+ * We now have 32 commands, so a bit more space ;-).
338+ * Also, all 'odd' commands are only usable by root and don't return the
339+ * content of ifr/iwr to user (but you are not obliged to use the set/get
340+ * convention, just use every other two command). More details in iwpriv.c.
341+ * And I repeat : you are not forced to use them with iwpriv, but you
342+ * must be compliant with it.
343+ */
344+
345+/* ------------------------- IOCTL STUFF ------------------------- */
346+
347+/* The first and the last (range) */
348+#define SIOCIWFIRST 0x8B00
349+#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
350+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
351+
352+/* Even : get (world access), odd : set (root access) */
353+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
354+#define IW_IS_GET(cmd) ((cmd) & 0x1)
355+
356+/* ----------------------- WIRELESS EVENTS ----------------------- */
357+/* Those are *NOT* ioctls, do not issue request on them !!! */
358+/* Most events use the same identifier as ioctl requests */
359+
360+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
361+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
362+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
363+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
364+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
365+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
366+ * (scan results); This includes id and
367+ * length fields. One IWEVGENIE may
368+ * contain more than one IE. Scan
369+ * results may contain one or more
370+ * IWEVGENIE events. */
371+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
372+ * (struct iw_michaelmicfailure)
373+ */
374+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
375+ * The data includes id and length
376+ * fields and may contain more than one
377+ * IE. This event is required in
378+ * Managed mode if the driver
379+ * generates its own WPA/RSN IE. This
380+ * should be sent just before
381+ * IWEVREGISTERED event for the
382+ * association. */
383+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
384+ * Response. The data includes id and
385+ * length fields and may contain more
386+ * than one IE. This may be sent
387+ * between IWEVASSOCREQIE and
388+ * IWEVREGISTERED events for the
389+ * association. */
390+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
391+ * pre-authentication
392+ * (struct iw_pmkid_cand) */
393+
394+#define IWEVFIRST 0x8C00
395+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
396+
397+/* ------------------------- PRIVATE INFO ------------------------- */
398+/*
399+ * The following is used with SIOCGIWPRIV. It allow a driver to define
400+ * the interface (name, type of data) for its private ioctl.
401+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
402+ */
403+
404+#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */
405+#define IW_PRIV_TYPE_NONE 0x0000
406+#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
407+#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
408+#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
409+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
410+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
411+
412+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
413+
414+#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
415+
416+/*
417+ * Note : if the number of args is fixed and the size < 16 octets,
418+ * instead of passing a pointer we will put args in the iwreq struct...
419+ */
420+
421+/* ----------------------- OTHER CONSTANTS ----------------------- */
422+
423+/* Maximum frequencies in the range struct */
424+#define IW_MAX_FREQUENCIES 32
425+/* Note : if you have something like 80 frequencies,
426+ * don't increase this constant and don't fill the frequency list.
427+ * The user will be able to set by channel anyway... */
428+
429+/* Maximum bit rates in the range struct */
430+#define IW_MAX_BITRATES 32
431+
432+/* Maximum tx powers in the range struct */
433+#define IW_MAX_TXPOWER 8
434+/* Note : if you more than 8 TXPowers, just set the max and min or
435+ * a few of them in the struct iw_range. */
436+
437+/* Maximum of address that you may set with SPY */
438+#define IW_MAX_SPY 8
439+
440+/* Maximum of address that you may get in the
441+ list of access points in range */
442+#define IW_MAX_AP 64
443+
444+/* Maximum size of the ESSID and NICKN strings */
445+#define IW_ESSID_MAX_SIZE 32
446+
447+/* Modes of operation */
448+#define IW_MODE_AUTO 0 /* Let the driver decides */
449+#define IW_MODE_ADHOC 1 /* Single cell network */
450+#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */
451+#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
452+#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
453+#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
454+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
455+
456+/* Statistics flags (bitmask in updated) */
457+#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
458+#define IW_QUAL_LEVEL_UPDATED 0x02
459+#define IW_QUAL_NOISE_UPDATED 0x04
460+#define IW_QUAL_ALL_UPDATED 0x07
461+#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
462+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
463+#define IW_QUAL_LEVEL_INVALID 0x20
464+#define IW_QUAL_NOISE_INVALID 0x40
465+#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */
466+#define IW_QUAL_ALL_INVALID 0x70
467+
468+/* Frequency flags */
469+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
470+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
471+
472+/* Maximum number of size of encoding token available
473+ * they are listed in the range structure */
474+#define IW_MAX_ENCODING_SIZES 8
475+
476+/* Maximum size of the encoding token in bytes */
477+#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
478+
479+/* Flags for encoding (along with the token) */
480+#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
481+#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
482+#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
483+#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
484+#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
485+#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
486+#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
487+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
488+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
489+
490+/* Power management flags available (along with the value, if any) */
491+#define IW_POWER_ON 0x0000 /* No details... */
492+#define IW_POWER_TYPE 0xF000 /* Type of parameter */
493+#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */
494+#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */
495+#define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/
496+#define IW_POWER_MODE 0x0F00 /* Power Management mode */
497+#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */
498+#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */
499+#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */
500+#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */
501+#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */
502+#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
503+#define IW_POWER_MIN 0x0001 /* Value is a minimum */
504+#define IW_POWER_MAX 0x0002 /* Value is a maximum */
505+#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
506+
507+/* Transmit Power flags available */
508+#define IW_TXPOW_TYPE 0x00FF /* Type of value */
509+#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
510+#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
511+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
512+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
513+
514+/* Retry limits and lifetime flags available */
515+#define IW_RETRY_ON 0x0000 /* No details... */
516+#define IW_RETRY_TYPE 0xF000 /* Type of parameter */
517+#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/
518+#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */
519+#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */
520+#define IW_RETRY_MIN 0x0001 /* Value is a minimum */
521+#define IW_RETRY_MAX 0x0002 /* Value is a maximum */
522+#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
523+#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */
524+#define IW_RETRY_LONG 0x0020 /* Value is for long packets */
525+
526+/* Scanning request flags */
527+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
528+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
529+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
530+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
531+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
532+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
533+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
534+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
535+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
536+/* struct iw_scan_req scan_type */
537+#define IW_SCAN_TYPE_ACTIVE 0
538+#define IW_SCAN_TYPE_PASSIVE 1
539+/* Maximum size of returned data */
540+#define IW_SCAN_MAX_DATA 4096 /* In bytes */
541+
542+/* Max number of char in custom event - use multiple of them if needed */
543+#define IW_CUSTOM_MAX 256 /* In bytes */
544+
545+/* Generic information element */
546+#define IW_GENERIC_IE_MAX 1024
547+
548+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
549+#define IW_MLME_DEAUTH 0
550+#define IW_MLME_DISASSOC 1
551+
552+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
553+#define IW_AUTH_INDEX 0x0FFF
554+#define IW_AUTH_FLAGS 0xF000
555+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
556+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
557+ * parameter that is being set/get to; value will be read/written to
558+ * struct iw_param value field) */
559+#define IW_AUTH_WPA_VERSION 0
560+#define IW_AUTH_CIPHER_PAIRWISE 1
561+#define IW_AUTH_CIPHER_GROUP 2
562+#define IW_AUTH_KEY_MGMT 3
563+#define IW_AUTH_TKIP_COUNTERMEASURES 4
564+#define IW_AUTH_DROP_UNENCRYPTED 5
565+#define IW_AUTH_80211_AUTH_ALG 6
566+#define IW_AUTH_WPA_ENABLED 7
567+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
568+#define IW_AUTH_ROAMING_CONTROL 9
569+#define IW_AUTH_PRIVACY_INVOKED 10
570+
571+/* IW_AUTH_WPA_VERSION values (bit field) */
572+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
573+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
574+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
575+
576+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
577+#define IW_AUTH_CIPHER_NONE 0x00000001
578+#define IW_AUTH_CIPHER_WEP40 0x00000002
579+#define IW_AUTH_CIPHER_TKIP 0x00000004
580+#define IW_AUTH_CIPHER_CCMP 0x00000008
581+#define IW_AUTH_CIPHER_WEP104 0x00000010
582+
583+/* IW_AUTH_KEY_MGMT values (bit field) */
584+#define IW_AUTH_KEY_MGMT_802_1X 1
585+#define IW_AUTH_KEY_MGMT_PSK 2
586+
587+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
588+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
589+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
590+#define IW_AUTH_ALG_LEAP 0x00000004
591+
592+/* IW_AUTH_ROAMING_CONTROL values */
593+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
594+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
595+ * control */
596+
597+/* SIOCSIWENCODEEXT definitions */
598+#define IW_ENCODE_SEQ_MAX_SIZE 8
599+/* struct iw_encode_ext ->alg */
600+#define IW_ENCODE_ALG_NONE 0
601+#define IW_ENCODE_ALG_WEP 1
602+#define IW_ENCODE_ALG_TKIP 2
603+#define IW_ENCODE_ALG_CCMP 3
604+/* struct iw_encode_ext ->ext_flags */
605+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
606+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
607+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
608+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
609+
610+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
611+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
612+#define IW_MICFAILURE_GROUP 0x00000004
613+#define IW_MICFAILURE_PAIRWISE 0x00000008
614+#define IW_MICFAILURE_STAKEY 0x00000010
615+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
616+ */
617+
618+/* Bit field values for enc_capa in struct iw_range */
619+#define IW_ENC_CAPA_WPA 0x00000001
620+#define IW_ENC_CAPA_WPA2 0x00000002
621+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
622+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
623+
624+/* Event capability macros - in (struct iw_range *)->event_capa
625+ * Because we have more than 32 possible events, we use an array of
626+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
627+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
628+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
629+ (cmd - SIOCSIWCOMMIT))
630+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
631+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
632+/* Event capability constants - event autogenerated by the kernel
633+ * This list is valid for most 802.11 devices, customise as needed... */
634+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
635+ IW_EVENT_CAPA_MASK(0x8B06) | \
636+ IW_EVENT_CAPA_MASK(0x8B1A))
637+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
638+/* "Easy" macro to set events in iw_range (less efficient) */
639+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
640+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
641+
642+/* Modulations bitmasks */
643+#define IW_MODUL_ALL 0x00000000 /* Everything supported */
644+#define IW_MODUL_FH 0x00000001 /* Frequency Hopping */
645+#define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */
646+#define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */
647+#define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK)
648+#define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */
649+#define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */
650+#define IW_MODUL_11A (IW_MODUL_OFDM_A)
651+#define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A)
652+#define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */
653+#define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G)
654+#define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A)
655+#define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */
656+/* In here we should define MIMO stuff. Later... */
657+#define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */
658+
659+/* Bitrate flags available */
660+#define IW_BITRATE_TYPE 0x00FF /* Type of value */
661+#define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */
662+#define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */
663+
664+/****************************** TYPES ******************************/
665+
666+/* --------------------------- SUBTYPES --------------------------- */
667+/*
668+ * Generic format for most parameters that fit in an int
669+ */
670+struct iw_param
671+{
672+ __s32 value; /* The value of the parameter itself */
673+ __u8 fixed; /* Hardware should not use auto select */
674+ __u8 disabled; /* Disable the feature */
675+ __u16 flags; /* Various specifc flags (if any) */
676+};
677+
678+/*
679+ * For all data larger than 16 octets, we need to use a
680+ * pointer to memory allocated in user space.
681+ */
682+struct iw_point
683+{
684+ void __user *pointer; /* Pointer to the data (in user space) */
685+ __u16 length; /* number of fields or size in bytes */
686+ __u16 flags; /* Optional params */
687+};
688+
689+/*
690+ * A frequency
691+ * For numbers lower than 10^9, we encode the number in 'm' and
692+ * set 'e' to 0
693+ * For number greater than 10^9, we divide it by the lowest power
694+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
695+ * The power of 10 is in 'e', the result of the division is in 'm'.
696+ */
697+struct iw_freq
698+{
699+ __s32 m; /* Mantissa */
700+ __s16 e; /* Exponent */
701+ __u8 i; /* List index (when in range struct) */
702+ __u8 flags; /* Flags (fixed/auto) */
703+};
704+
705+/*
706+ * Quality of the link
707+ */
708+struct iw_quality
709+{
710+ __u8 qual; /* link quality (%retries, SNR,
711+ %missed beacons or better...) */
712+ __u8 level; /* signal level (dBm) */
713+ __u8 noise; /* noise level (dBm) */
714+ __u8 updated; /* Flags to know if updated */
715+};
716+
717+/*
718+ * Packet discarded in the wireless adapter due to
719+ * "wireless" specific problems...
720+ * Note : the list of counter and statistics in net_device_stats
721+ * is already pretty exhaustive, and you should use that first.
722+ * This is only additional stats...
723+ */
724+struct iw_discarded
725+{
726+ __u32 nwid; /* Rx : Wrong nwid/essid */
727+ __u32 code; /* Rx : Unable to code/decode (WEP) */
728+ __u32 fragment; /* Rx : Can't perform MAC reassembly */
729+ __u32 retries; /* Tx : Max MAC retries num reached */
730+ __u32 misc; /* Others cases */
731+};
732+
733+/*
734+ * Packet/Time period missed in the wireless adapter due to
735+ * "wireless" specific problems...
736+ */
737+struct iw_missed
738+{
739+ __u32 beacon; /* Missed beacons/superframe */
740+};
741+
742+/*
743+ * Quality range (for spy threshold)
744+ */
745+struct iw_thrspy
746+{
747+ struct sockaddr addr; /* Source address (hw/mac) */
748+ struct iw_quality qual; /* Quality of the link */
749+ struct iw_quality low; /* Low threshold */
750+ struct iw_quality high; /* High threshold */
751+};
752+
753+/*
754+ * Optional data for scan request
755+ *
756+ * Note: these optional parameters are controlling parameters for the
757+ * scanning behavior, these do not apply to getting scan results
758+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
759+ * provide a merged results with all BSSes even if the previous scan
760+ * request limited scanning to a subset, e.g., by specifying an SSID.
761+ * Especially, scan results are required to include an entry for the
762+ * current BSS if the driver is in Managed mode and associated with an AP.
763+ */
764+struct iw_scan_req
765+{
766+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
767+ __u8 essid_len;
768+ __u8 num_channels; /* num entries in channel_list;
769+ * 0 = scan all allowed channels */
770+ __u8 flags; /* reserved as padding; use zero, this may
771+ * be used in the future for adding flags
772+ * to request different scan behavior */
773+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
774+ * individual address of a specific BSS */
775+
776+ /*
777+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
778+ * the current ESSID. This allows scan requests for specific ESSID
779+ * without having to change the current ESSID and potentially breaking
780+ * the current association.
781+ */
782+ __u8 essid[IW_ESSID_MAX_SIZE];
783+
784+ /*
785+ * Optional parameters for changing the default scanning behavior.
786+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
787+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
788+ * reasonable default values. min_channel_time defines the time that
789+ * will be used to wait for the first reply on each channel. If no
790+ * replies are received, next channel will be scanned after this. If
791+ * replies are received, total time waited on the channel is defined by
792+ * max_channel_time.
793+ */
794+ __u32 min_channel_time; /* in TU */
795+ __u32 max_channel_time; /* in TU */
796+
797+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
798+};
799+
800+/* ------------------------- WPA SUPPORT ------------------------- */
801+
802+/*
803+ * Extended data structure for get/set encoding (this is used with
804+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
805+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
806+ * only the data contents changes (key data -> this structure, including
807+ * key data).
808+ *
809+ * If the new key is the first group key, it will be set as the default
810+ * TX key. Otherwise, default TX key index is only changed if
811+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
812+ *
813+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
814+ * special "change TX key index" operation which is indicated by setting
815+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
816+ *
817+ * tx_seq/rx_seq are only used when respective
818+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
819+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
820+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
821+ * used only by an Authenticator (AP or an IBSS station) to get the
822+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
823+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
824+ * debugging/testing.
825+ */
826+struct iw_encode_ext
827+{
828+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
829+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
830+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
831+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
832+ * (group) keys or unicast address for
833+ * individual keys */
834+ __u16 alg; /* IW_ENCODE_ALG_* */
835+ __u16 key_len;
836+ __u8 key[0];
837+};
838+
839+/* SIOCSIWMLME data */
840+struct iw_mlme
841+{
842+ __u16 cmd; /* IW_MLME_* */
843+ __u16 reason_code;
844+ struct sockaddr addr;
845+};
846+
847+/* SIOCSIWPMKSA data */
848+#define IW_PMKSA_ADD 1
849+#define IW_PMKSA_REMOVE 2
850+#define IW_PMKSA_FLUSH 3
851+
852+#define IW_PMKID_LEN 16
853+
854+struct iw_pmksa
855+{
856+ __u32 cmd; /* IW_PMKSA_* */
857+ struct sockaddr bssid;
858+ __u8 pmkid[IW_PMKID_LEN];
859+};
860+
861+/* IWEVMICHAELMICFAILURE data */
862+struct iw_michaelmicfailure
863+{
864+ __u32 flags;
865+ struct sockaddr src_addr;
866+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
867+};
868+
869+/* IWEVPMKIDCAND data */
870+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
871+struct iw_pmkid_cand
872+{
873+ __u32 flags; /* IW_PMKID_CAND_* */
874+ __u32 index; /* the smaller the index, the higher the
875+ * priority */
876+ struct sockaddr bssid;
877+};
878+
879+/* ------------------------ WIRELESS STATS ------------------------ */
880+/*
881+ * Wireless statistics (used for /proc/net/wireless)
882+ */
883+struct iw_statistics
884+{
885+ __u16 status; /* Status
886+ * - device dependent for now */
887+
888+ struct iw_quality qual; /* Quality of the link
889+ * (instant/mean/max) */
890+ struct iw_discarded discard; /* Packet discarded counts */
891+ struct iw_missed miss; /* Packet missed counts */
892+};
893+
894+/* ------------------------ IOCTL REQUEST ------------------------ */
895+/*
896+ * This structure defines the payload of an ioctl, and is used
897+ * below.
898+ *
899+ * Note that this structure should fit on the memory footprint
900+ * of iwreq (which is the same as ifreq), which mean a max size of
901+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
902+ * You should check this when increasing the structures defined
903+ * above in this file...
904+ */
905+union iwreq_data
906+{
907+ /* Config - generic */
908+ char name[IFNAMSIZ];
909+ /* Name : used to verify the presence of wireless extensions.
910+ * Name of the protocol/provider... */
911+
912+ struct iw_point essid; /* Extended network name */
913+ struct iw_param nwid; /* network id (or domain - the cell) */
914+ struct iw_freq freq; /* frequency or channel :
915+ * 0-1000 = channel
916+ * > 1000 = frequency in Hz */
917+
918+ struct iw_param sens; /* signal level threshold */
919+ struct iw_param bitrate; /* default bit rate */
920+ struct iw_param txpower; /* default transmit power */
921+ struct iw_param rts; /* RTS threshold threshold */
922+ struct iw_param frag; /* Fragmentation threshold */
923+ __u32 mode; /* Operation mode */
924+ struct iw_param retry; /* Retry limits & lifetime */
925+
926+ struct iw_point encoding; /* Encoding stuff : tokens */
927+ struct iw_param power; /* PM duration/timeout */
928+ struct iw_quality qual; /* Quality part of statistics */
929+
930+ struct sockaddr ap_addr; /* Access point address */
931+ struct sockaddr addr; /* Destination address (hw/mac) */
932+
933+ struct iw_param param; /* Other small parameters */
934+ struct iw_point data; /* Other large parameters */
935+};
936+
937+/*
938+ * The structure to exchange data for ioctl.
939+ * This structure is the same as 'struct ifreq', but (re)defined for
940+ * convenience...
941+ * Do I need to remind you about structure size (32 octets) ?
942+ */
943+struct iwreq
944+{
945+ union
946+ {
947+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
948+ } ifr_ifrn;
949+
950+ /* Data part (defined just above) */
951+ union iwreq_data u;
952+};
953+
954+/* -------------------------- IOCTL DATA -------------------------- */
955+/*
956+ * For those ioctl which want to exchange mode data that what could
957+ * fit in the above structure...
958+ */
959+
960+/*
961+ * Range of parameters
962+ */
963+
964+struct iw_range
965+{
966+ /* Informative stuff (to choose between different interface) */
967+ __u32 throughput; /* To give an idea... */
968+ /* In theory this value should be the maximum benchmarked
969+ * TCP/IP throughput, because with most of these devices the
970+ * bit rate is meaningless (overhead an co) to estimate how
971+ * fast the connection will go and pick the fastest one.
972+ * I suggest people to play with Netperf or any benchmark...
973+ */
974+
975+ /* NWID (or domain id) */
976+ __u32 min_nwid; /* Minimal NWID we are able to set */
977+ __u32 max_nwid; /* Maximal NWID we are able to set */
978+
979+ /* Old Frequency (backward compat - moved lower ) */
980+ __u16 old_num_channels;
981+ __u8 old_num_frequency;
982+
983+ /* Wireless event capability bitmasks */
984+ __u32 event_capa[6];
985+
986+ /* signal level threshold range */
987+ __s32 sensitivity;
988+
989+ /* Quality of link & SNR stuff */
990+ /* Quality range (link, level, noise)
991+ * If the quality is absolute, it will be in the range [0 ; max_qual],
992+ * if the quality is dBm, it will be in the range [max_qual ; 0].
993+ * Don't forget that we use 8 bit arithmetics... */
994+ struct iw_quality max_qual; /* Quality of the link */
995+ /* This should contain the average/typical values of the quality
996+ * indicator. This should be the threshold between a "good" and
997+ * a "bad" link (example : monitor going from green to orange).
998+ * Currently, user space apps like quality monitors don't have any
999+ * way to calibrate the measurement. With this, they can split
1000+ * the range between 0 and max_qual in different quality level
1001+ * (using a geometric subdivision centered on the average).
1002+ * I expect that people doing the user space apps will feedback
1003+ * us on which value we need to put in each driver... */
1004+ struct iw_quality avg_qual; /* Quality of the link */
1005+
1006+ /* Rates */
1007+ __u8 num_bitrates; /* Number of entries in the list */
1008+ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */
1009+
1010+ /* RTS threshold */
1011+ __s32 min_rts; /* Minimal RTS threshold */
1012+ __s32 max_rts; /* Maximal RTS threshold */
1013+
1014+ /* Frag threshold */
1015+ __s32 min_frag; /* Minimal frag threshold */
1016+ __s32 max_frag; /* Maximal frag threshold */
1017+
1018+ /* Power Management duration & timeout */
1019+ __s32 min_pmp; /* Minimal PM period */
1020+ __s32 max_pmp; /* Maximal PM period */
1021+ __s32 min_pmt; /* Minimal PM timeout */
1022+ __s32 max_pmt; /* Maximal PM timeout */
1023+ __u16 pmp_flags; /* How to decode max/min PM period */
1024+ __u16 pmt_flags; /* How to decode max/min PM timeout */
1025+ __u16 pm_capa; /* What PM options are supported */
1026+
1027+ /* Encoder stuff */
1028+ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
1029+ __u8 num_encoding_sizes; /* Number of entry in the list */
1030+ __u8 max_encoding_tokens; /* Max number of tokens */
1031+ /* For drivers that need a "login/passwd" form */
1032+ __u8 encoding_login_index; /* token index for login token */
1033+
1034+ /* Transmit power */
1035+ __u16 txpower_capa; /* What options are supported */
1036+ __u8 num_txpower; /* Number of entries in the list */
1037+ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */
1038+
1039+ /* Wireless Extension version info */
1040+ __u8 we_version_compiled; /* Must be WIRELESS_EXT */
1041+ __u8 we_version_source; /* Last update of source */
1042+
1043+ /* Retry limits and lifetime */
1044+ __u16 retry_capa; /* What retry options are supported */
1045+ __u16 retry_flags; /* How to decode max/min retry limit */
1046+ __u16 r_time_flags; /* How to decode max/min retry life */
1047+ __s32 min_retry; /* Minimal number of retries */
1048+ __s32 max_retry; /* Maximal number of retries */
1049+ __s32 min_r_time; /* Minimal retry lifetime */
1050+ __s32 max_r_time; /* Maximal retry lifetime */
1051+
1052+ /* Frequency */
1053+ __u16 num_channels; /* Number of channels [0; num - 1] */
1054+ __u8 num_frequency; /* Number of entry in the list */
1055+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
1056+ /* Note : this frequency list doesn't need to fit channel numbers,
1057+ * because each entry contain its channel index */
1058+
1059+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
1060+
1061+ /* More power management stuff */
1062+ __s32 min_pms; /* Minimal PM saving */
1063+ __s32 max_pms; /* Maximal PM saving */
1064+ __u16 pms_flags; /* How to decode max/min PM saving */
1065+
1066+ /* All available modulations for driver (hw may support less) */
1067+ __s32 modul_capa; /* IW_MODUL_* bit field */
1068+
1069+ /* More bitrate stuff */
1070+ __u32 bitrate_capa; /* Types of bitrates supported */
1071+};
1072+
1073+/*
1074+ * Private ioctl interface information
1075+ */
1076+
1077+struct iw_priv_args
1078+{
1079+ __u32 cmd; /* Number of the ioctl to issue */
1080+ __u16 set_args; /* Type and number of args */
1081+ __u16 get_args; /* Type and number of args */
1082+ char name[IFNAMSIZ]; /* Name of the extension */
1083+};
1084+
1085+/* ----------------------- WIRELESS EVENTS ----------------------- */
1086+/*
1087+ * Wireless events are carried through the rtnetlink socket to user
1088+ * space. They are encapsulated in the IFLA_WIRELESS field of
1089+ * a RTM_NEWLINK message.
1090+ */
1091+
1092+/*
1093+ * A Wireless Event. Contains basically the same data as the ioctl...
1094+ */
1095+struct iw_event
1096+{
1097+ __u16 len; /* Real lenght of this stuff */
1098+ __u16 cmd; /* Wireless IOCTL */
1099+ union iwreq_data u; /* IOCTL fixed payload */
1100+};
1101+
1102+/* Size of the Event prefix (including padding and alignement junk) */
1103+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data))
1104+/* Size of the various events */
1105+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
1106+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
1107+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
1108+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
1109+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
1110+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
1111+
1112+/* iw_point events are special. First, the payload (extra data) come at
1113+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
1114+ * we omit the pointer, so start at an offset. */
1115+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
1116+ (char *) NULL)
1117+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
1118+ IW_EV_POINT_OFF)
1119+
1120+#endif /* _LINUX_WIRELESS_H */
--- /dev/null
+++ b/wireless_tools/wireless.22.h
@@ -0,0 +1,1139 @@
1+/*
2+ * This file define a set of standard wireless extensions
3+ *
4+ * Version : 22 16.3.07
5+ *
6+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
7+ * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
8+ */
9+
10+#ifndef _LINUX_WIRELESS_H
11+#define _LINUX_WIRELESS_H
12+
13+/************************** DOCUMENTATION **************************/
14+/*
15+ * Initial APIs (1996 -> onward) :
16+ * -----------------------------
17+ * Basically, the wireless extensions are for now a set of standard ioctl
18+ * call + /proc/net/wireless
19+ *
20+ * The entry /proc/net/wireless give statistics and information on the
21+ * driver.
22+ * This is better than having each driver having its entry because
23+ * its centralised and we may remove the driver module safely.
24+ *
25+ * Ioctl are used to configure the driver and issue commands. This is
26+ * better than command line options of insmod because we may want to
27+ * change dynamically (while the driver is running) some parameters.
28+ *
29+ * The ioctl mechanimsm are copied from standard devices ioctl.
30+ * We have the list of command plus a structure descibing the
31+ * data exchanged...
32+ * Note that to add these ioctl, I was obliged to modify :
33+ * # net/core/dev.c (two place + add include)
34+ * # net/ipv4/af_inet.c (one place + add include)
35+ *
36+ * /proc/net/wireless is a copy of /proc/net/dev.
37+ * We have a structure for data passed from the driver to /proc/net/wireless
38+ * Too add this, I've modified :
39+ * # net/core/dev.c (two other places)
40+ * # include/linux/netdevice.h (one place)
41+ * # include/linux/proc_fs.h (one place)
42+ *
43+ * New driver API (2002 -> onward) :
44+ * -------------------------------
45+ * This file is only concerned with the user space API and common definitions.
46+ * The new driver API is defined and documented in :
47+ * # include/net/iw_handler.h
48+ *
49+ * Note as well that /proc/net/wireless implementation has now moved in :
50+ * # net/core/wireless.c
51+ *
52+ * Wireless Events (2002 -> onward) :
53+ * --------------------------------
54+ * Events are defined at the end of this file, and implemented in :
55+ * # net/core/wireless.c
56+ *
57+ * Other comments :
58+ * --------------
59+ * Do not add here things that are redundant with other mechanisms
60+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
61+ * wireless specific.
62+ *
63+ * These wireless extensions are not magic : each driver has to provide
64+ * support for them...
65+ *
66+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
67+ * work in progress. Contact me if you have ideas of improvements...
68+ */
69+
70+/***************************** INCLUDES *****************************/
71+
72+/* This header is used in user-space, therefore need to be sanitised
73+ * for that purpose. Those includes are usually not compatible with glibc.
74+ * To know which includes to use in user-space, check iwlib.h. */
75+#ifdef __KERNEL__
76+#include <linux/types.h> /* for "caddr_t" et al */
77+#include <linux/socket.h> /* for "struct sockaddr" et al */
78+#include <linux/if.h> /* for IFNAMSIZ and co... */
79+#endif /* __KERNEL__ */
80+
81+/***************************** VERSION *****************************/
82+/*
83+ * This constant is used to know the availability of the wireless
84+ * extensions and to know which version of wireless extensions it is
85+ * (there is some stuff that will be added in the future...)
86+ * I just plan to increment with each new version.
87+ */
88+#define WIRELESS_EXT 22
89+
90+/*
91+ * Changes :
92+ *
93+ * V2 to V3
94+ * --------
95+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
96+ * - Encryption renamed to Encode to avoid US regulation problems
97+ * - Frequency changed from float to struct to avoid problems on old 386
98+ *
99+ * V3 to V4
100+ * --------
101+ * - Add sensitivity
102+ *
103+ * V4 to V5
104+ * --------
105+ * - Missing encoding definitions in range
106+ * - Access points stuff
107+ *
108+ * V5 to V6
109+ * --------
110+ * - 802.11 support (ESSID ioctls)
111+ *
112+ * V6 to V7
113+ * --------
114+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
115+ *
116+ * V7 to V8
117+ * --------
118+ * - Changed my e-mail address
119+ * - More 802.11 support (nickname, rate, rts, frag)
120+ * - List index in frequencies
121+ *
122+ * V8 to V9
123+ * --------
124+ * - Support for 'mode of operation' (ad-hoc, managed...)
125+ * - Support for unicast and multicast power saving
126+ * - Change encoding to support larger tokens (>64 bits)
127+ * - Updated iw_params (disable, flags) and use it for NWID
128+ * - Extracted iw_point from iwreq for clarity
129+ *
130+ * V9 to V10
131+ * ---------
132+ * - Add PM capability to range structure
133+ * - Add PM modifier : MAX/MIN/RELATIVE
134+ * - Add encoding option : IW_ENCODE_NOKEY
135+ * - Add TxPower ioctls (work like TxRate)
136+ *
137+ * V10 to V11
138+ * ----------
139+ * - Add WE version in range (help backward/forward compatibility)
140+ * - Add retry ioctls (work like PM)
141+ *
142+ * V11 to V12
143+ * ----------
144+ * - Add SIOCSIWSTATS to get /proc/net/wireless programatically
145+ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
146+ * - Add new statistics (frag, retry, beacon)
147+ * - Add average quality (for user space calibration)
148+ *
149+ * V12 to V13
150+ * ----------
151+ * - Document creation of new driver API.
152+ * - Extract union iwreq_data from struct iwreq (for new driver API).
153+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
154+ *
155+ * V13 to V14
156+ * ----------
157+ * - Wireless Events support : define struct iw_event
158+ * - Define additional specific event numbers
159+ * - Add "addr" and "param" fields in union iwreq_data
160+ * - AP scanning stuff (SIOCSIWSCAN and friends)
161+ *
162+ * V14 to V15
163+ * ----------
164+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
165+ * - Make struct iw_freq signed (both m & e), add explicit padding
166+ * - Add IWEVCUSTOM for driver specific event/scanning token
167+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
168+ * - Add IW_TXPOW_RANGE for range of Tx Powers
169+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
170+ * - Add IW_MODE_MONITOR for passive monitor
171+ *
172+ * V15 to V16
173+ * ----------
174+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
175+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
176+ * - Reshuffle struct iw_range for increases, add filler
177+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
178+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
179+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
180+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
181+ *
182+ * V16 to V17
183+ * ----------
184+ * - Add flags to frequency -> auto/fixed
185+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
186+ * - Wireless Event capability in struct iw_range
187+ * - Add support for relative TxPower (yick !)
188+ *
189+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
190+ * ----------
191+ * - Add support for WPA/WPA2
192+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
193+ * SIOCGIWENCODEEXT)
194+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
195+ * - Add SIOCSIWMLME
196+ * - Add SIOCSIWPMKSA
197+ * - Add struct iw_range bit field for supported encoding capabilities
198+ * - Add optional scan request parameters for SIOCSIWSCAN
199+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
200+ * related parameters (extensible up to 4096 parameter values)
201+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
202+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
203+ *
204+ * V18 to V19
205+ * ----------
206+ * - Remove (struct iw_point *)->pointer from events and streams
207+ * - Remove header includes to help user space
208+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
209+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
210+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
211+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
212+ *
213+ * V19 to V20
214+ * ----------
215+ * - RtNetlink requests support (SET/GET)
216+ *
217+ * V20 to V21
218+ * ----------
219+ * - Remove (struct net_device *)->get_wireless_stats()
220+ * - Change length in ESSID and NICK to strlen() instead of strlen()+1
221+ * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
222+ * - Power/Retry relative values no longer * 100000
223+ * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
224+ *
225+ * V21 to V22
226+ * ----------
227+ * - Prevent leaking of kernel space in stream on 64 bits.
228+ */
229+
230+/**************************** CONSTANTS ****************************/
231+
232+/* -------------------------- IOCTL LIST -------------------------- */
233+
234+/* Wireless Identification */
235+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
236+#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
237+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
238+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
239+ * Don't put the name of your driver there, it's useless. */
240+
241+/* Basic operations */
242+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */
243+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */
244+#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */
245+#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */
246+#define SIOCSIWMODE 0x8B06 /* set operation mode */
247+#define SIOCGIWMODE 0x8B07 /* get operation mode */
248+#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */
249+#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */
250+
251+/* Informative stuff */
252+#define SIOCSIWRANGE 0x8B0A /* Unused */
253+#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */
254+#define SIOCSIWPRIV 0x8B0C /* Unused */
255+#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
256+#define SIOCSIWSTATS 0x8B0E /* Unused */
257+#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */
258+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
259+ * is never passed to the driver (i.e. the driver will never see it). */
260+
261+/* Spy support (statistics per MAC address - used for Mobile IP support) */
262+#define SIOCSIWSPY 0x8B10 /* set spy addresses */
263+#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
264+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
265+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
266+
267+/* Access Point manipulation */
268+#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
269+#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
270+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */
271+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */
272+#define SIOCGIWSCAN 0x8B19 /* get scanning results */
273+
274+/* 802.11 specific support */
275+#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
276+#define SIOCGIWESSID 0x8B1B /* get ESSID */
277+#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */
278+#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
279+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
280+ * within the 'iwreq' structure, so we need to use the 'data' member to
281+ * point to a string in user space, like it is done for RANGE... */
282+
283+/* Other parameters useful in 802.11 and some other devices */
284+#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
285+#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
286+#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */
287+#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */
288+#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */
289+#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */
290+#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */
291+#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */
292+#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */
293+#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */
294+
295+/* Encoding stuff (scrambling, hardware security, WEP...) */
296+#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */
297+#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */
298+/* Power saving stuff (power management, unicast and multicast) */
299+#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
300+#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
301+/* Modulation bitmask */
302+#define SIOCSIWMODUL 0x8B2E /* set Modulations settings */
303+#define SIOCGIWMODUL 0x8B2F /* get Modulations settings */
304+
305+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
306+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
307+ * fields. More than one IE may be included in the request. Setting the generic
308+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
309+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
310+ * are required to report the used IE as a wireless event, e.g., when
311+ * associating with an AP. */
312+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
313+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
314+
315+/* WPA : IEEE 802.11 MLME requests */
316+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
317+ * struct iw_mlme */
318+/* WPA : Authentication mode parameters */
319+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
320+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
321+
322+/* WPA : Extended version of encoding configuration */
323+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
324+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
325+
326+/* WPA2 : PMKSA cache management */
327+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
328+
329+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
330+
331+/* These 32 ioctl are wireless device private, for 16 commands.
332+ * Each driver is free to use them for whatever purpose it chooses,
333+ * however the driver *must* export the description of those ioctls
334+ * with SIOCGIWPRIV and *must* use arguments as defined below.
335+ * If you don't follow those rules, DaveM is going to hate you (reason :
336+ * it make mixed 32/64bit operation impossible).
337+ */
338+#define SIOCIWFIRSTPRIV 0x8BE0
339+#define SIOCIWLASTPRIV 0x8BFF
340+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
341+ * separate range because of collisions with other tools such as
342+ * 'mii-tool'.
343+ * We now have 32 commands, so a bit more space ;-).
344+ * Also, all 'even' commands are only usable by root and don't return the
345+ * content of ifr/iwr to user (but you are not obliged to use the set/get
346+ * convention, just use every other two command). More details in iwpriv.c.
347+ * And I repeat : you are not forced to use them with iwpriv, but you
348+ * must be compliant with it.
349+ */
350+
351+/* ------------------------- IOCTL STUFF ------------------------- */
352+
353+/* The first and the last (range) */
354+#define SIOCIWFIRST 0x8B00
355+#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
356+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
357+
358+/* Odd : get (world access), even : set (root access) */
359+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
360+#define IW_IS_GET(cmd) ((cmd) & 0x1)
361+
362+/* ----------------------- WIRELESS EVENTS ----------------------- */
363+/* Those are *NOT* ioctls, do not issue request on them !!! */
364+/* Most events use the same identifier as ioctl requests */
365+
366+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
367+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
368+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
369+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
370+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
371+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
372+ * (scan results); This includes id and
373+ * length fields. One IWEVGENIE may
374+ * contain more than one IE. Scan
375+ * results may contain one or more
376+ * IWEVGENIE events. */
377+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
378+ * (struct iw_michaelmicfailure)
379+ */
380+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
381+ * The data includes id and length
382+ * fields and may contain more than one
383+ * IE. This event is required in
384+ * Managed mode if the driver
385+ * generates its own WPA/RSN IE. This
386+ * should be sent just before
387+ * IWEVREGISTERED event for the
388+ * association. */
389+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
390+ * Response. The data includes id and
391+ * length fields and may contain more
392+ * than one IE. This may be sent
393+ * between IWEVASSOCREQIE and
394+ * IWEVREGISTERED events for the
395+ * association. */
396+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
397+ * pre-authentication
398+ * (struct iw_pmkid_cand) */
399+
400+#define IWEVFIRST 0x8C00
401+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
402+
403+/* ------------------------- PRIVATE INFO ------------------------- */
404+/*
405+ * The following is used with SIOCGIWPRIV. It allow a driver to define
406+ * the interface (name, type of data) for its private ioctl.
407+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
408+ */
409+
410+#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */
411+#define IW_PRIV_TYPE_NONE 0x0000
412+#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
413+#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
414+#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
415+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
416+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
417+
418+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
419+
420+#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
421+
422+/*
423+ * Note : if the number of args is fixed and the size < 16 octets,
424+ * instead of passing a pointer we will put args in the iwreq struct...
425+ */
426+
427+/* ----------------------- OTHER CONSTANTS ----------------------- */
428+
429+/* Maximum frequencies in the range struct */
430+#define IW_MAX_FREQUENCIES 32
431+/* Note : if you have something like 80 frequencies,
432+ * don't increase this constant and don't fill the frequency list.
433+ * The user will be able to set by channel anyway... */
434+
435+/* Maximum bit rates in the range struct */
436+#define IW_MAX_BITRATES 32
437+
438+/* Maximum tx powers in the range struct */
439+#define IW_MAX_TXPOWER 8
440+/* Note : if you more than 8 TXPowers, just set the max and min or
441+ * a few of them in the struct iw_range. */
442+
443+/* Maximum of address that you may set with SPY */
444+#define IW_MAX_SPY 8
445+
446+/* Maximum of address that you may get in the
447+ list of access points in range */
448+#define IW_MAX_AP 64
449+
450+/* Maximum size of the ESSID and NICKN strings */
451+#define IW_ESSID_MAX_SIZE 32
452+
453+/* Modes of operation */
454+#define IW_MODE_AUTO 0 /* Let the driver decides */
455+#define IW_MODE_ADHOC 1 /* Single cell network */
456+#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */
457+#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
458+#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
459+#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
460+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
461+
462+/* Statistics flags (bitmask in updated) */
463+#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
464+#define IW_QUAL_LEVEL_UPDATED 0x02
465+#define IW_QUAL_NOISE_UPDATED 0x04
466+#define IW_QUAL_ALL_UPDATED 0x07
467+#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
468+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
469+#define IW_QUAL_LEVEL_INVALID 0x20
470+#define IW_QUAL_NOISE_INVALID 0x40
471+#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */
472+#define IW_QUAL_ALL_INVALID 0x70
473+
474+/* Frequency flags */
475+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
476+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
477+
478+/* Maximum number of size of encoding token available
479+ * they are listed in the range structure */
480+#define IW_MAX_ENCODING_SIZES 8
481+
482+/* Maximum size of the encoding token in bytes */
483+#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
484+
485+/* Flags for encoding (along with the token) */
486+#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
487+#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
488+#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
489+#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
490+#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
491+#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
492+#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
493+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
494+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
495+
496+/* Power management flags available (along with the value, if any) */
497+#define IW_POWER_ON 0x0000 /* No details... */
498+#define IW_POWER_TYPE 0xF000 /* Type of parameter */
499+#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */
500+#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */
501+#define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/
502+#define IW_POWER_MODE 0x0F00 /* Power Management mode */
503+#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */
504+#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */
505+#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */
506+#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */
507+#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */
508+#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
509+#define IW_POWER_MIN 0x0001 /* Value is a minimum */
510+#define IW_POWER_MAX 0x0002 /* Value is a maximum */
511+#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
512+
513+/* Transmit Power flags available */
514+#define IW_TXPOW_TYPE 0x00FF /* Type of value */
515+#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
516+#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
517+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
518+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
519+
520+/* Retry limits and lifetime flags available */
521+#define IW_RETRY_ON 0x0000 /* No details... */
522+#define IW_RETRY_TYPE 0xF000 /* Type of parameter */
523+#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/
524+#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */
525+#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */
526+#define IW_RETRY_MIN 0x0001 /* Value is a minimum */
527+#define IW_RETRY_MAX 0x0002 /* Value is a maximum */
528+#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
529+#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */
530+#define IW_RETRY_LONG 0x0020 /* Value is for long packets */
531+
532+/* Scanning request flags */
533+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
534+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
535+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
536+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
537+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
538+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
539+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
540+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
541+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
542+/* struct iw_scan_req scan_type */
543+#define IW_SCAN_TYPE_ACTIVE 0
544+#define IW_SCAN_TYPE_PASSIVE 1
545+/* Maximum size of returned data */
546+#define IW_SCAN_MAX_DATA 4096 /* In bytes */
547+
548+/* Max number of char in custom event - use multiple of them if needed */
549+#define IW_CUSTOM_MAX 256 /* In bytes */
550+
551+/* Generic information element */
552+#define IW_GENERIC_IE_MAX 1024
553+
554+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
555+#define IW_MLME_DEAUTH 0
556+#define IW_MLME_DISASSOC 1
557+#define IW_MLME_AUTH 2
558+#define IW_MLME_ASSOC 3
559+
560+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
561+#define IW_AUTH_INDEX 0x0FFF
562+#define IW_AUTH_FLAGS 0xF000
563+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
564+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
565+ * parameter that is being set/get to; value will be read/written to
566+ * struct iw_param value field) */
567+#define IW_AUTH_WPA_VERSION 0
568+#define IW_AUTH_CIPHER_PAIRWISE 1
569+#define IW_AUTH_CIPHER_GROUP 2
570+#define IW_AUTH_KEY_MGMT 3
571+#define IW_AUTH_TKIP_COUNTERMEASURES 4
572+#define IW_AUTH_DROP_UNENCRYPTED 5
573+#define IW_AUTH_80211_AUTH_ALG 6
574+#define IW_AUTH_WPA_ENABLED 7
575+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
576+#define IW_AUTH_ROAMING_CONTROL 9
577+#define IW_AUTH_PRIVACY_INVOKED 10
578+
579+/* IW_AUTH_WPA_VERSION values (bit field) */
580+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
581+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
582+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
583+
584+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
585+#define IW_AUTH_CIPHER_NONE 0x00000001
586+#define IW_AUTH_CIPHER_WEP40 0x00000002
587+#define IW_AUTH_CIPHER_TKIP 0x00000004
588+#define IW_AUTH_CIPHER_CCMP 0x00000008
589+#define IW_AUTH_CIPHER_WEP104 0x00000010
590+
591+/* IW_AUTH_KEY_MGMT values (bit field) */
592+#define IW_AUTH_KEY_MGMT_802_1X 1
593+#define IW_AUTH_KEY_MGMT_PSK 2
594+
595+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
596+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
597+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
598+#define IW_AUTH_ALG_LEAP 0x00000004
599+
600+/* IW_AUTH_ROAMING_CONTROL values */
601+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
602+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
603+ * control */
604+
605+/* SIOCSIWENCODEEXT definitions */
606+#define IW_ENCODE_SEQ_MAX_SIZE 8
607+/* struct iw_encode_ext ->alg */
608+#define IW_ENCODE_ALG_NONE 0
609+#define IW_ENCODE_ALG_WEP 1
610+#define IW_ENCODE_ALG_TKIP 2
611+#define IW_ENCODE_ALG_CCMP 3
612+/* struct iw_encode_ext ->ext_flags */
613+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
614+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
615+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
616+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
617+
618+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
619+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
620+#define IW_MICFAILURE_GROUP 0x00000004
621+#define IW_MICFAILURE_PAIRWISE 0x00000008
622+#define IW_MICFAILURE_STAKEY 0x00000010
623+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
624+ */
625+
626+/* Bit field values for enc_capa in struct iw_range */
627+#define IW_ENC_CAPA_WPA 0x00000001
628+#define IW_ENC_CAPA_WPA2 0x00000002
629+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
630+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
631+
632+/* Event capability macros - in (struct iw_range *)->event_capa
633+ * Because we have more than 32 possible events, we use an array of
634+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
635+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
636+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
637+ (cmd - SIOCSIWCOMMIT))
638+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
639+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
640+/* Event capability constants - event autogenerated by the kernel
641+ * This list is valid for most 802.11 devices, customise as needed... */
642+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
643+ IW_EVENT_CAPA_MASK(0x8B06) | \
644+ IW_EVENT_CAPA_MASK(0x8B1A))
645+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
646+/* "Easy" macro to set events in iw_range (less efficient) */
647+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
648+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
649+
650+/* Modulations bitmasks */
651+#define IW_MODUL_ALL 0x00000000 /* Everything supported */
652+#define IW_MODUL_FH 0x00000001 /* Frequency Hopping */
653+#define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */
654+#define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */
655+#define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK)
656+#define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */
657+#define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */
658+#define IW_MODUL_11A (IW_MODUL_OFDM_A)
659+#define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A)
660+#define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */
661+#define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G)
662+#define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A)
663+#define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */
664+/* In here we should define MIMO stuff. Later... */
665+#define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */
666+
667+/* Bitrate flags available */
668+#define IW_BITRATE_TYPE 0x00FF /* Type of value */
669+#define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */
670+#define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */
671+
672+/****************************** TYPES ******************************/
673+
674+/* --------------------------- SUBTYPES --------------------------- */
675+/*
676+ * Generic format for most parameters that fit in an int
677+ */
678+struct iw_param
679+{
680+ __s32 value; /* The value of the parameter itself */
681+ __u8 fixed; /* Hardware should not use auto select */
682+ __u8 disabled; /* Disable the feature */
683+ __u16 flags; /* Various specifc flags (if any) */
684+};
685+
686+/*
687+ * For all data larger than 16 octets, we need to use a
688+ * pointer to memory allocated in user space.
689+ */
690+struct iw_point
691+{
692+ void __user *pointer; /* Pointer to the data (in user space) */
693+ __u16 length; /* number of fields or size in bytes */
694+ __u16 flags; /* Optional params */
695+};
696+
697+/*
698+ * A frequency
699+ * For numbers lower than 10^9, we encode the number in 'm' and
700+ * set 'e' to 0
701+ * For number greater than 10^9, we divide it by the lowest power
702+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
703+ * The power of 10 is in 'e', the result of the division is in 'm'.
704+ */
705+struct iw_freq
706+{
707+ __s32 m; /* Mantissa */
708+ __s16 e; /* Exponent */
709+ __u8 i; /* List index (when in range struct) */
710+ __u8 flags; /* Flags (fixed/auto) */
711+};
712+
713+/*
714+ * Quality of the link
715+ */
716+struct iw_quality
717+{
718+ __u8 qual; /* link quality (%retries, SNR,
719+ %missed beacons or better...) */
720+ __u8 level; /* signal level (dBm) */
721+ __u8 noise; /* noise level (dBm) */
722+ __u8 updated; /* Flags to know if updated */
723+};
724+
725+/*
726+ * Packet discarded in the wireless adapter due to
727+ * "wireless" specific problems...
728+ * Note : the list of counter and statistics in net_device_stats
729+ * is already pretty exhaustive, and you should use that first.
730+ * This is only additional stats...
731+ */
732+struct iw_discarded
733+{
734+ __u32 nwid; /* Rx : Wrong nwid/essid */
735+ __u32 code; /* Rx : Unable to code/decode (WEP) */
736+ __u32 fragment; /* Rx : Can't perform MAC reassembly */
737+ __u32 retries; /* Tx : Max MAC retries num reached */
738+ __u32 misc; /* Others cases */
739+};
740+
741+/*
742+ * Packet/Time period missed in the wireless adapter due to
743+ * "wireless" specific problems...
744+ */
745+struct iw_missed
746+{
747+ __u32 beacon; /* Missed beacons/superframe */
748+};
749+
750+/*
751+ * Quality range (for spy threshold)
752+ */
753+struct iw_thrspy
754+{
755+ struct sockaddr addr; /* Source address (hw/mac) */
756+ struct iw_quality qual; /* Quality of the link */
757+ struct iw_quality low; /* Low threshold */
758+ struct iw_quality high; /* High threshold */
759+};
760+
761+/*
762+ * Optional data for scan request
763+ *
764+ * Note: these optional parameters are controlling parameters for the
765+ * scanning behavior, these do not apply to getting scan results
766+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
767+ * provide a merged results with all BSSes even if the previous scan
768+ * request limited scanning to a subset, e.g., by specifying an SSID.
769+ * Especially, scan results are required to include an entry for the
770+ * current BSS if the driver is in Managed mode and associated with an AP.
771+ */
772+struct iw_scan_req
773+{
774+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
775+ __u8 essid_len;
776+ __u8 num_channels; /* num entries in channel_list;
777+ * 0 = scan all allowed channels */
778+ __u8 flags; /* reserved as padding; use zero, this may
779+ * be used in the future for adding flags
780+ * to request different scan behavior */
781+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
782+ * individual address of a specific BSS */
783+
784+ /*
785+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
786+ * the current ESSID. This allows scan requests for specific ESSID
787+ * without having to change the current ESSID and potentially breaking
788+ * the current association.
789+ */
790+ __u8 essid[IW_ESSID_MAX_SIZE];
791+
792+ /*
793+ * Optional parameters for changing the default scanning behavior.
794+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
795+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
796+ * reasonable default values. min_channel_time defines the time that
797+ * will be used to wait for the first reply on each channel. If no
798+ * replies are received, next channel will be scanned after this. If
799+ * replies are received, total time waited on the channel is defined by
800+ * max_channel_time.
801+ */
802+ __u32 min_channel_time; /* in TU */
803+ __u32 max_channel_time; /* in TU */
804+
805+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
806+};
807+
808+/* ------------------------- WPA SUPPORT ------------------------- */
809+
810+/*
811+ * Extended data structure for get/set encoding (this is used with
812+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
813+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
814+ * only the data contents changes (key data -> this structure, including
815+ * key data).
816+ *
817+ * If the new key is the first group key, it will be set as the default
818+ * TX key. Otherwise, default TX key index is only changed if
819+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
820+ *
821+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
822+ * special "change TX key index" operation which is indicated by setting
823+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
824+ *
825+ * tx_seq/rx_seq are only used when respective
826+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
827+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
828+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
829+ * used only by an Authenticator (AP or an IBSS station) to get the
830+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
831+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
832+ * debugging/testing.
833+ */
834+struct iw_encode_ext
835+{
836+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
837+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
838+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
839+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
840+ * (group) keys or unicast address for
841+ * individual keys */
842+ __u16 alg; /* IW_ENCODE_ALG_* */
843+ __u16 key_len;
844+ __u8 key[0];
845+};
846+
847+/* SIOCSIWMLME data */
848+struct iw_mlme
849+{
850+ __u16 cmd; /* IW_MLME_* */
851+ __u16 reason_code;
852+ struct sockaddr addr;
853+};
854+
855+/* SIOCSIWPMKSA data */
856+#define IW_PMKSA_ADD 1
857+#define IW_PMKSA_REMOVE 2
858+#define IW_PMKSA_FLUSH 3
859+
860+#define IW_PMKID_LEN 16
861+
862+struct iw_pmksa
863+{
864+ __u32 cmd; /* IW_PMKSA_* */
865+ struct sockaddr bssid;
866+ __u8 pmkid[IW_PMKID_LEN];
867+};
868+
869+/* IWEVMICHAELMICFAILURE data */
870+struct iw_michaelmicfailure
871+{
872+ __u32 flags;
873+ struct sockaddr src_addr;
874+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
875+};
876+
877+/* IWEVPMKIDCAND data */
878+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
879+struct iw_pmkid_cand
880+{
881+ __u32 flags; /* IW_PMKID_CAND_* */
882+ __u32 index; /* the smaller the index, the higher the
883+ * priority */
884+ struct sockaddr bssid;
885+};
886+
887+/* ------------------------ WIRELESS STATS ------------------------ */
888+/*
889+ * Wireless statistics (used for /proc/net/wireless)
890+ */
891+struct iw_statistics
892+{
893+ __u16 status; /* Status
894+ * - device dependent for now */
895+
896+ struct iw_quality qual; /* Quality of the link
897+ * (instant/mean/max) */
898+ struct iw_discarded discard; /* Packet discarded counts */
899+ struct iw_missed miss; /* Packet missed counts */
900+};
901+
902+/* ------------------------ IOCTL REQUEST ------------------------ */
903+/*
904+ * This structure defines the payload of an ioctl, and is used
905+ * below.
906+ *
907+ * Note that this structure should fit on the memory footprint
908+ * of iwreq (which is the same as ifreq), which mean a max size of
909+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
910+ * You should check this when increasing the structures defined
911+ * above in this file...
912+ */
913+union iwreq_data
914+{
915+ /* Config - generic */
916+ char name[IFNAMSIZ];
917+ /* Name : used to verify the presence of wireless extensions.
918+ * Name of the protocol/provider... */
919+
920+ struct iw_point essid; /* Extended network name */
921+ struct iw_param nwid; /* network id (or domain - the cell) */
922+ struct iw_freq freq; /* frequency or channel :
923+ * 0-1000 = channel
924+ * > 1000 = frequency in Hz */
925+
926+ struct iw_param sens; /* signal level threshold */
927+ struct iw_param bitrate; /* default bit rate */
928+ struct iw_param txpower; /* default transmit power */
929+ struct iw_param rts; /* RTS threshold threshold */
930+ struct iw_param frag; /* Fragmentation threshold */
931+ __u32 mode; /* Operation mode */
932+ struct iw_param retry; /* Retry limits & lifetime */
933+
934+ struct iw_point encoding; /* Encoding stuff : tokens */
935+ struct iw_param power; /* PM duration/timeout */
936+ struct iw_quality qual; /* Quality part of statistics */
937+
938+ struct sockaddr ap_addr; /* Access point address */
939+ struct sockaddr addr; /* Destination address (hw/mac) */
940+
941+ struct iw_param param; /* Other small parameters */
942+ struct iw_point data; /* Other large parameters */
943+};
944+
945+/*
946+ * The structure to exchange data for ioctl.
947+ * This structure is the same as 'struct ifreq', but (re)defined for
948+ * convenience...
949+ * Do I need to remind you about structure size (32 octets) ?
950+ */
951+struct iwreq
952+{
953+ union
954+ {
955+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
956+ } ifr_ifrn;
957+
958+ /* Data part (defined just above) */
959+ union iwreq_data u;
960+};
961+
962+/* -------------------------- IOCTL DATA -------------------------- */
963+/*
964+ * For those ioctl which want to exchange mode data that what could
965+ * fit in the above structure...
966+ */
967+
968+/*
969+ * Range of parameters
970+ */
971+
972+struct iw_range
973+{
974+ /* Informative stuff (to choose between different interface) */
975+ __u32 throughput; /* To give an idea... */
976+ /* In theory this value should be the maximum benchmarked
977+ * TCP/IP throughput, because with most of these devices the
978+ * bit rate is meaningless (overhead an co) to estimate how
979+ * fast the connection will go and pick the fastest one.
980+ * I suggest people to play with Netperf or any benchmark...
981+ */
982+
983+ /* NWID (or domain id) */
984+ __u32 min_nwid; /* Minimal NWID we are able to set */
985+ __u32 max_nwid; /* Maximal NWID we are able to set */
986+
987+ /* Old Frequency (backward compat - moved lower ) */
988+ __u16 old_num_channels;
989+ __u8 old_num_frequency;
990+
991+ /* Wireless event capability bitmasks */
992+ __u32 event_capa[6];
993+
994+ /* signal level threshold range */
995+ __s32 sensitivity;
996+
997+ /* Quality of link & SNR stuff */
998+ /* Quality range (link, level, noise)
999+ * If the quality is absolute, it will be in the range [0 ; max_qual],
1000+ * if the quality is dBm, it will be in the range [max_qual ; 0].
1001+ * Don't forget that we use 8 bit arithmetics... */
1002+ struct iw_quality max_qual; /* Quality of the link */
1003+ /* This should contain the average/typical values of the quality
1004+ * indicator. This should be the threshold between a "good" and
1005+ * a "bad" link (example : monitor going from green to orange).
1006+ * Currently, user space apps like quality monitors don't have any
1007+ * way to calibrate the measurement. With this, they can split
1008+ * the range between 0 and max_qual in different quality level
1009+ * (using a geometric subdivision centered on the average).
1010+ * I expect that people doing the user space apps will feedback
1011+ * us on which value we need to put in each driver... */
1012+ struct iw_quality avg_qual; /* Quality of the link */
1013+
1014+ /* Rates */
1015+ __u8 num_bitrates; /* Number of entries in the list */
1016+ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */
1017+
1018+ /* RTS threshold */
1019+ __s32 min_rts; /* Minimal RTS threshold */
1020+ __s32 max_rts; /* Maximal RTS threshold */
1021+
1022+ /* Frag threshold */
1023+ __s32 min_frag; /* Minimal frag threshold */
1024+ __s32 max_frag; /* Maximal frag threshold */
1025+
1026+ /* Power Management duration & timeout */
1027+ __s32 min_pmp; /* Minimal PM period */
1028+ __s32 max_pmp; /* Maximal PM period */
1029+ __s32 min_pmt; /* Minimal PM timeout */
1030+ __s32 max_pmt; /* Maximal PM timeout */
1031+ __u16 pmp_flags; /* How to decode max/min PM period */
1032+ __u16 pmt_flags; /* How to decode max/min PM timeout */
1033+ __u16 pm_capa; /* What PM options are supported */
1034+
1035+ /* Encoder stuff */
1036+ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
1037+ __u8 num_encoding_sizes; /* Number of entry in the list */
1038+ __u8 max_encoding_tokens; /* Max number of tokens */
1039+ /* For drivers that need a "login/passwd" form */
1040+ __u8 encoding_login_index; /* token index for login token */
1041+
1042+ /* Transmit power */
1043+ __u16 txpower_capa; /* What options are supported */
1044+ __u8 num_txpower; /* Number of entries in the list */
1045+ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */
1046+
1047+ /* Wireless Extension version info */
1048+ __u8 we_version_compiled; /* Must be WIRELESS_EXT */
1049+ __u8 we_version_source; /* Last update of source */
1050+
1051+ /* Retry limits and lifetime */
1052+ __u16 retry_capa; /* What retry options are supported */
1053+ __u16 retry_flags; /* How to decode max/min retry limit */
1054+ __u16 r_time_flags; /* How to decode max/min retry life */
1055+ __s32 min_retry; /* Minimal number of retries */
1056+ __s32 max_retry; /* Maximal number of retries */
1057+ __s32 min_r_time; /* Minimal retry lifetime */
1058+ __s32 max_r_time; /* Maximal retry lifetime */
1059+
1060+ /* Frequency */
1061+ __u16 num_channels; /* Number of channels [0; num - 1] */
1062+ __u8 num_frequency; /* Number of entry in the list */
1063+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
1064+ /* Note : this frequency list doesn't need to fit channel numbers,
1065+ * because each entry contain its channel index */
1066+
1067+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
1068+
1069+ /* More power management stuff */
1070+ __s32 min_pms; /* Minimal PM saving */
1071+ __s32 max_pms; /* Maximal PM saving */
1072+ __u16 pms_flags; /* How to decode max/min PM saving */
1073+
1074+ /* All available modulations for driver (hw may support less) */
1075+ __s32 modul_capa; /* IW_MODUL_* bit field */
1076+
1077+ /* More bitrate stuff */
1078+ __u32 bitrate_capa; /* Types of bitrates supported */
1079+};
1080+
1081+/*
1082+ * Private ioctl interface information
1083+ */
1084+
1085+struct iw_priv_args
1086+{
1087+ __u32 cmd; /* Number of the ioctl to issue */
1088+ __u16 set_args; /* Type and number of args */
1089+ __u16 get_args; /* Type and number of args */
1090+ char name[IFNAMSIZ]; /* Name of the extension */
1091+};
1092+
1093+/* ----------------------- WIRELESS EVENTS ----------------------- */
1094+/*
1095+ * Wireless events are carried through the rtnetlink socket to user
1096+ * space. They are encapsulated in the IFLA_WIRELESS field of
1097+ * a RTM_NEWLINK message.
1098+ */
1099+
1100+/*
1101+ * A Wireless Event. Contains basically the same data as the ioctl...
1102+ */
1103+struct iw_event
1104+{
1105+ __u16 len; /* Real lenght of this stuff */
1106+ __u16 cmd; /* Wireless IOCTL */
1107+ union iwreq_data u; /* IOCTL fixed payload */
1108+};
1109+
1110+/* Size of the Event prefix (including padding and alignement junk) */
1111+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data))
1112+/* Size of the various events */
1113+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
1114+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
1115+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
1116+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
1117+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
1118+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
1119+
1120+/* iw_point events are special. First, the payload (extra data) come at
1121+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
1122+ * we omit the pointer, so start at an offset. */
1123+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
1124+ (char *) NULL)
1125+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
1126+ IW_EV_POINT_OFF)
1127+
1128+/* Size of the Event prefix when packed in stream */
1129+#define IW_EV_LCP_PK_LEN (4)
1130+/* Size of the various events when packed in stream */
1131+#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ)
1132+#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32))
1133+#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
1134+#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
1135+#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
1136+#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
1137+#define IW_EV_POINT_PK_LEN (IW_EV_LCP_LEN + 4)
1138+
1139+#endif /* _LINUX_WIRELESS_H */