--- /dev/null
+# udev rules to properly integrate ifrename.
+# Renaming is done using /etc/iftab, with full ifrename functionality.
+# Require udev version 107 or later.
+# Please double check the path to ifrename, and make sure its available
+# when udev runs (i.e. on boot partition).
+
+# Enable this rule to test with udevtest.
+#ENV{UDEV_LOG}=="6", SUBSYSTEM=="net", ACTION=="add", IMPORT="/sbin/ifrename -D -V -u -i %k", NAME:="%k"
+
+# Main ifrename rule.
+# If interface is found in /etc/iftab, subsequent rename rules are bypassed.
+# If interface is not found in /etc/iftab, subsequent rename rules applies.
+SUBSYSTEM=="net", ACTION=="add", IMPORT="/sbin/ifrename -u -i %k", NAME:="%k"
/*
* Wireless Tools
*
- * Jean II - HPLB 97->99 - HPL 99->04
+ * Jean II - HPLB 97->99 - HPL 99->07
*
* The changelog...
*
* o Add WE-20 headers, compile with that as default
* ---
* o Fix 'inline' for gcc-4 as well. Grrr... [iwlib]
+ *
+ * wireless 29 :
+ * -----------
+ * o Add new power value : 'power saving' [iwconfig/iwlist/iwlib]
+ * o Optimise getting iwrange when setting TxPower [iwconfig]
+ * o Optimise displaying current power values (better loop) [iwlist]
+ * ---
+ * o Add modulation bitmasks ioctls [iwconfig/iwlist]
+ * o Add short and long retries [iwconfig/iwlist/iwlib]
+ * o Fix 'relative' power saving to not be *1000 [iwconfig/iwlib]
+ * o iw_print_pm_value() require we_version [iwlib]
+ * o Optimise displaying range power values (subroutine) [iwlist]
+ * ---
+ * o Fix 'relative' retry to not be *1000 [iwconfig/iwlib]
+ * o iw_print_retry_value() require we_version [iwlib]
+ * o Optimise getting iwrange when setting PowerSaving [iwconfig]
+ * o Optimise displaying current retry values (better loop) [iwlist]
+ * o Optimise displaying range retry values (subroutine) [iwlist]
+ * ---
+ * o Fix stupid bug in displaying range retry values [iwlist]
+ * ---
+ * o Add support for unicast and broadcast bitrates [iwconfig/iwlist]
+ * ---
+ * o Replace spaghetti code with real dispatcher in set_info() [iwconfig]
+ * Code is more readable, maintainable, and save 700 bytes...
+ * o Drop 'domain' alias for 'nwid'. Obsolete. [iwconfig]
+ * o Make iw_usage() use dispatcher data instead of hardcoded [iwconfig]
+ * o Factor out modifier parsing for retry/power [iwconfig]
+ * o Fix iwmulticall to compile with new dispatcher above [iwmulticall]
+ * o Add WE_ESSENTIAL compile option to drop 10kB [Makefile]
+ * ---
+ * o Update manpages with new features above [man]
+ * ---
+ * o Add temp variable to sscanf() to fix 64 bits issues [iwconfig]
+ * o De-inline get_pm_value/get_retry_value to reduce footprint [iwlist]
+ * o Optimise iw_print_ie_cipher/iw_print_ie_auth [iwlist]
+ * o Add "Memory footprint reduction" section in doc [README]
+ * o Add 'last' scan option for left-over scan [iwlist]
+ * (From Stavros Markou <smarkou@patras.atmel.com>)
+ * o Add 'essid' scan option for directed scan [iwlist]
+ * ---
+ * (Bug reported by Henrik Brix Andersen <brix@gentoo.org>)
+ * o Fix segfault on setting bitrate (parse wrong arg) [iwconfig]
+ * ---
+ * o Revert 'CC=gcc' to normal [Makefile]
+ * o Integrate properly patch below [iwlist]
+ * (From Brian Eaton <eaton.lists@gmail.com>)
+ * o More WPA support : iwlist auth/wpakeys/genie [iwlist]
+ * ---
+ * o Tweak man pages : interface is often optional [iwlist.8/iwspy.8]
+ * o Drop obsolete port/roam code from [iwpriv]
+ * (From Pavel Roskin <proski@gnu.org>)
+ * o Fix bug where all auth masks use iw_auth_capa_name [iwlist]
+ * (From Dima Ryazanov <someone@berkeley.edu>)
+ * o Fix iw_scan()/iw_process_scan() for non-root -> EPERM [iwlib]
+ * (Bug reported by Arkadiusz Miskiewicz <arekm@pld-linux.org>)
+ * o Fix "iwconfig nickname" (was abreviated) [iwconfig]
+ * (Bug reported by Charles Plessy)
+ * o Invalid mode from driver segfault iwlist scan [iwlist]
+ * (From Aurelien Jacobs <aurel@gnuage.org>)
+ * o Replace index() with strchr() [iwlib/iwconfig/iwpriv]
+ * (From Jens Thoms Toerring)
+ * o Parser/printf/sscanf fixes and optimisation [iwconfig]
+ * ---
+ * (From Pavel Roskin <proski@gnu.org>)
+ * o Fix bug extracting mountpoint of sysfs (wrong field) [ifrename]
+ * (Suggested by Pavel Roskin <proski@gnu.org>)
+ * o Read sysfs symlinks transparently [ifrename]
+ * ---
+ * o Fix README header to talk about ifrename [README]
+ * o Add 'prevname' selector for udev compatibility [ifrename]
+ * o Read parent directory names in SYSFS selector [ifrename]
+ * o Make dry-run output compatible with udev [ifrename]
+ * o Update man page with useful SYSFS selectors [iftab.5]
+ * ---
+ * o Factorise wildcard rewrite '*'->'%d' to hide it from -D -V [ifrename]
+ * o Reorganise sysfs description, better wording [iftab.5]
+ * (Suggested by Pavel Roskin <proski@gnu.org>)
+ * o Enhance explanation of arp and iwproto [iftab.5]
+ * ---
+ * (Bug reported by Johannes Berg <johannes@sipsolutions.net>)
+ * o Band-aid for the 64->32bit iwevent/iwscan issues [iwlib]
+ * ---
+ * o Better band-aid for the 64->32bit iwevent/iwscan issues [iwlib]
+ * (Suggested by Kay Sievers <kay.sievers@vrfy.org>)
+ * o Add udev compatible output, print new DEVPATH [ifrename]
+ * ---
+ * o Fix DEVPATH output to use the real devpath from udev [ifrename]
+ * o Add udev rules for ifrename integration [19-udev-ifrename.rules]
+ * ---
+ * o Add largest bitrate in easy scan API [iwlib]
+ * ---
+ * o Debug version : output IW_EV_LCP_LEN [iwlist]
+ * ---
+ * (Bug reported by Santiago Gala/Roy Marples)
+ * o Fix 64->32bit band-aid on 64 bits, target is local aligned [iwlib]
+ * ---
+ * (Bug reported by Santiago Gala/Roy Marples)
+ * o More fix to the 64->32bit band-aid on 64 bits [iwlib]
+ * ---
+ * (Bug reported by Dimitris Kogias)
+ * o Fix GENIE parsing os chipher/key_mngt [iwlist]
+ * (Bug reported by Guus Sliepen <guus@debian.org>)
+ * o Compiler warning on DEBUG code [iwlist]
+ * ---
+ * o --version output WE_MAX_VERSION instead of WE_VERSION [iwlib]
+ * o Change iwstats dBm range to [-192;63] in iw_print_stats() [iwlib.c]
+ * o Implement iwstats IW_QUAL_RCPI in iw_print_stats() [iwlib.c]
+ * (Bug reported by Guus Sliepen <guus@sliepen.eu.org>)
+ * o LINUX_VERSION_CODE removed, only use GENERIC_HEADERS [iwlib.h]
+ * (Bug reported by Johan Danielsson <joda11147@gmail.com>)
+ * o Fix OUI type check for WPA 1 IE [iwlist.c]
+ * ---
+ * (Bug reported by Florent Daignière)
+ * o Don't look for "fixed" out of array in set_txpower_info() [iwconfig]
*/
/* ----------------------------- TODO ----------------------------- */
* --------
* Make disable a per encryption key modifier if some hardware
* requires it.
- *
- * iwpriv :
- * ------
- * Remove 'port' and 'roam' cruft now that we have mode in iwconfig
+ * IW_QUAL_RCPI
*
* iwspy :
* -----
http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
Advantages over 'ifrename' :
- + integrated into 'udev'
+ simpler to setup if 'udev' is already properly setup
+ + automatically generates persistent rules
Drawbacks compared to 'ifrename' :
- Less selectors that 'ifrename'
- Require kernel 2.6.X or later with sysfs support
- Do no support non-hotplug interfaces
- Require 'udev', not everybody uses it (static /dev, devfs)
- - Does not support module on-demand loading
Comments :
o 'udev' support many selectors, basically all those
-present in 'sysfs', even if the documentation only show instructions
-to use the MAC address (which is problematic with virtual devices some
-drivers - see above). 'ifrename' can also use all selectors present in
-'sysfs' (like 'udev'), plus some other selectors not present in sysfs
-that were found to be useful.
+present in 'sysfs' (excluding symlinks), even if the documentation
+only show instructions to use the MAC address (which is problematic
+with virtual devices some drivers - see above). 'ifrename' can also
+use all selectors present in 'sysfs' (like 'udev'), can use sysfs
+symlinks and parent directories, plus some other selectors not present
+in sysfs that were found to be useful.
o Not all interfaces are managed by hotplug. All
virtual devices, such as tunnels and loopbacks, are not associated
with a hardware bus, and therefore are not managed by hotplug. All
o It is common practice on embedded system to use a
static /dev and not 'udev' to save space and boot time. And to not use
hotplug for the same reasons.
- o 'ifrename' could be better integrated in 'udev', I don't foresee any technical issues.
+ o 'ifrename' has now a udev compatiblity mode that
+enables to trivially integrate it into 'udev' as an IMPORT rule. This
+requires udev version 107 or better and ifrename 29-pre17 or better.
SELECTOR AWARE NETWORK SCRIPTS
------------------------------
--------------------------------
By default, the package is built with iwlib as a dynamic
library, and the tool will expect to use the default version of libiw
-on the system.
+on the system. This means you can't use the tools until they are
+properly installed.
If you just want to experiment with a "local" version of the
tools, you may want to pass the BUILD_STATIC flag to Makefile. It will
create a self contained version of the tools.
--------------
-make clean
-make BUILD_STATIC='y'
--------------
+ -------------
+ make clean
+ make BUILD_STATIC='y'
+ -------------
The resulting binary can be used in the compilation directory
or installed in any place you like.
+Other useful Makefile options :
+-----------------------------
+ PREFIX : where the tools will be installed (default : /usr/local)
+ CC : Compiler to use (defaul : gcc)
+ BUILD_STATIC : build tools with a static version of the wireless lib
+ BUILD_NOLIBM : build tools without mathematical lib (slower)
+ BUILD_STRIPPING : strip symbols from tools/lib.
+ BUILD_WE_ESSENTIAL : remove less used and obsolete features.
+
+ You can pass those options on the command line of make, or
+modify the top of the Makefile. You can also set them as environment
+variable, but this is not recommended.
+ If you pass those options on the command line, you should pass
+the same command line options for all invocations of make ("make" and
+"make install").
+
+Memory footprint reduction :
+--------------------------
+ The Wireless Tools are used in various embedded systems where
+memory footprint is a great concern. The Wireless Tools package offer
+multiple options to customise the compilation depending on the level
+of features you want.
+ The list below details the must useful combinations of these
+options, from the largest footprint to the smallest. Footprint depend
+on lot's of factor and is purely indicative (version 29-pre7+, i386,
+glibc, gcc 3.3.5).
+
+ 1) Static build
+ Command line : make BUILD_STATIC='y'
+ - : Largest footprint
+ - : libiw not included (other third party tools may depend on it)
+ Size : ~280 kB
+
+ 2) Default build
+ Command line : make
+ + : Fully featured version of the tools
+ - : Largest footprint (except for static version of tools)
+ Size : ~190 kB (libiw : ~29 kB ; ifrename : ~29 kB)
+
+ 3) Stripping (remove function symbols)
+ Command line : make BUILD_STRIPPING='y'
+ + : Fully featured version of the tools
+ - : Still quite large
+ Size : ~110 kB (libiw : ~23 kB ; ifrename : ~17 kB)
+
+ 4) Multicall version (include stripping)
+ Command line : make iwmulticall ; make install-iwmulticall
+ + : Fully featured version of the tools
+ + : Small
+ - : libiw not included (other third party tools may depend on it)
+ - : ifrename is not included
+ Size : ~55 kB
+
+ 5) Multicall + Essential
+ Command line : make BUILD_WE_ESSENTIAL='y' iwmulticall
+ + : Smaller
+ - : Some less used features are left out
+ - : libiw not included (other third party tools may depend on it)
+ - : ifrename is not included
+ Size : ~44 kB
+
+ 6) iwconfig only + essential + static
+ Command line : make BUILD_WE_ESSENTIAL='y' BUILD_STATIC='y' BUILD_STRIPPING='y' iwconfig
+ + : Very small
+ - : Very limited functionality : no scanning, no event, no iwpriv
+ - : libiw not included (other third party tools may depend on it)
+ - : ifrename is not included
+ Size : ~28 kB
+
Wireless headers (past history) :
-------------------------------
Previous version of the Wireless Tools had to be compiled with
Note that the previous option to make versioned installed of
the tools no longer make sense and therefore is gone.
-Other useful Makefile options :
------------------------------
- PREFIX : where the tools will be installed (default : /usr/local)
- BUILD_STATIC : build tools with a static version of the wireless lib
- BUILD_NOLIBM : build tools without mathematical lib (slower)
- Note that you should pass the same command line options for
-all invocations of make ("make" and "make install").
-
- If you want the absolute minimal footprint, you may want to
-look into the multicall version of the tools. You can build it with
-"make iwmulticall" and install it with "make install-iwmulticall".
-
Old kernel with older Wireless Extensions :
-----------------------------------------
Kernel prior to 2.2.14 : Those kernels include Wireless
## Please check the configurion parameters below
##
-## Installation directory. By default, go in /usr/local
+## Installation directory. By default, go in /usr/local.
## Distributions should probably use /, but they probably know better...
ifndef PREFIX
PREFIX = /usr/local
endif
-## Compiler to use (modify this for cross compile)
+## Compiler to use (modify this for cross compile).
CC = gcc
-## Other tools you need to modify for cross compile (static lib only)
+## Other tools you need to modify for cross compile (static lib only).
AR = ar
RANLIB = ranlib
-## Uncomment this to build tools using static version of the library
+## Uncomment this to build tools using static version of the library.
## Mostly useful for embedded platforms without ldd, or to create
## a local version (non-root).
# BUILD_STATIC = y
-## Uncomment this to build without using libm (less efficient)
+## Uncomment this to build without using libm (less efficient).
## This is mostly useful for embedded platforms without maths.
# BUILD_NOLIBM = y
-## Uncomment this to strip binary from symbols. This reduce binary size
+## Uncomment this to strip binary from symbols. This reduce binary size.
## by a few percent but make debug worse...
# BUILD_STRIPPING = y
+## Uncomment this to build with only essential functionality.
+## This leaves out the less used features and cut in half the tools.
+## This is mostly useful for embedded platforms without limited feature needs.
+# BUILD_WE_ESSENTIAL = y
+
# ***************************************************************************
# ***** Most users should not need to change anything beyond this point *****
# ***************************************************************************
STRIPFLAGS=
endif
+# Do we want to build with only essential functionality ?
+ifdef BUILD_WE_ESSENTIAL
+ WEDEF_FLAG= -DWE_ESSENTIAL=y
+endif
+
# Other flags
CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \
-Wpointer-arith -Wcast-qual -Winline -I.
#CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I.
DEPFLAGS=-MMD
-XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG)
+XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG) $(WEDEF_FLAG)
PICFLAG=-fPIC
# Standard compilation targets
- Wireless Tools
- --------------
+ Wireless Tools & IfRename
+ -------------------------
This package contains the Wireless tools, used to manipulate
the Wireless Extensions. The Wireless Extensions is an interface
allowing you to set Wireless LAN specific parameters and get the
specific stats.
+ It also contains the IfRename package, used for advance
+renaming of network interfaces.
web page :
--------
The Wireless Tools helper library. May be useful if you want
to create your own applications using Wireless Extensions.
+iwmulticall.c
+-------------
+ Multicall version of the tools for embedded systems.
+
Changelog, contributions :
------------------------
See CHANGELOG.h
alone works, but it should point you in the proper direction.
Also, have a look at existing drivers in the Linux kernel.
+19-udev-ifrename.rules :
+----------------------
+ udev rules to integrate properly ifrename (udev >= 107).
+
Other tools :
-----------
My web page lists many other tools using Wireless
-.\" Jean II - HPL - 2004
+.\" Jean II - HPL - 2004-2007
.\" ifrename.8
.\"
-.TH IFRENAME 8 "01 March 2004" "wireless-tools" "Linux Programmer's Manual"
+.TH IFRENAME 8 "26 February 2007" "wireless-tools" "Linux Programmer's Manual"
.\"
.\" NAME part
.\"
.\" SYNOPSIS part
.\"
.SH SYNOPSIS
-.B "ifrename [-c configfile] [-p] [-d] [-v] [-V] [-D]"
+.B "ifrename [-c configfile] [-p] [-d] [-u] [-v] [-V] [-D]"
.br
.B "ifrename [-c configfile] [-i interface] [-n newname]"
.\"
and you are invited to choose unique and unambiguous names for your
interfaces...
.TP
+.B -u
+Enable
+.I udev
+output mode. This enables proper integration of
+.B ifrename
+in the
+.I udev
+framework,
+.BR udevd (8)
+will use
+.B ifrename
+to assign interface names present in
+.IR /etc/iftab .
+In this mode the output of ifrename can be parsed
+directly by
+.BR udevd (8)
+as an IMPORT action. This requires
+.I udev
+version 107 or later.
+.TP
.B -D
Dry-run mode. Ifrename won't change any interface, it will only print
new interface name, if applicable, and return.
.br
In dry-run mode, interface name wildcards are not resolved. New
interface name is printed, even if it is the same as the old name.
+.br
+Be also aware that some selectors can only be read by root, for
+example those based on
+.BR ethtool ),
+and will fail silently if run by a normal user. In other words,
+dry-run mode under a standard user may not give the expected result.
.TP
.B -V
Verbose mode. Ifrename will display internal results of parsing its
/*
* Wireless Tools
*
- * Jean II - HPL 04
+ * Jean II - HPL 04 -> 07
*
* Main code for "ifrename". This is tool allows to rename network
* interfaces based on various criteria (not only wireless).
* You need to link this code against "iwlib.c" and "-lm".
*
* This file is released under the GPL license.
- * Copyright (c) 2004 Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (c) 2007 Jean Tourrilhes <jt@hpl.hp.com>
*/
/*
* Difference with standard 'nameif' :
* o 'nameif' has only a single selector, the interface MAC address.
* o Modular selector architecture, easily add new selectors.
- * o Wide range of selector, including sysfs...
+ * o Wide range of selector, including sysfs and sysfs symlinks...
* o hotplug invocation support.
* o module loading support.
* o MAC address wildcard.
const int SELECT_IWPROTO = 10; /* Select by Wireless Protocol */
const int SELECT_PCMCIASLOT = 11; /* Select by Pcmcia Slot */
const int SELECT_SYSFS = 12; /* Select by sysfs file */
-#define SELECT_NUM 13
+const int SELECT_PREVNAME = 13; /* Select by previous interface name */
+#define SELECT_NUM 14
#define HAS_MAC_EXACT 1
#define HAS_MAC_FILTER 2
{"interface", 1, NULL, 'i' },
{"newname", 1, NULL, 'n' },
{"takeover", 0, NULL, 't' },
+ {"udev", 0, NULL, 'u' },
{"version", 0, NULL, 'v' },
{"verbose", 0, NULL, 'V' },
{NULL, 0, NULL, '\0' },
#define PCMCIA_STAB1 "/var/lib/pcmcia/stab"
#define PCMCIA_STAB2 "/var/run/stab"
-/* Max number of sysfs file we support */
-#define SYSFS_MAX_FILE 5
+/* Max number of sysfs file types we support */
+#define SYSFS_MAX_FILE 8
/* Userspace headers lag, fix that... */
#ifndef ARPHRD_IEEE1394
/* Name of this interface */
char ifname[IFNAMSIZ+1];
+ char * sysfs_devpath;
+ int sysfs_devplen;
/* Selectors for this interface */
int active[SELECT_NUM]; /* Selectors active */
char iwproto[IFNAMSIZ + 1]; /* Wireless/protocol name */
int pcmcia_slot; /* Pcmcia slot */
char * sysfs[SYSFS_MAX_FILE]; /* sysfs selectors */
+ char prevname[IFNAMSIZ+1]; /* previous interface name */
} if_mapping;
/* Extra parsing information when adding a mapping */
const char * ifname,
struct if_mapping * target,
int flag);
+static int
+ mapping_addprevname(struct if_mapping * ifnode,
+ int * active,
+ char * pos,
+ size_t len,
+ struct add_extra * extra,
+ int linenum);
+static int
+ mapping_cmpprevname(struct if_mapping * ifnode,
+ struct if_mapping * target);
+static int
+ mapping_getprevname(int skfd,
+ const char * ifname,
+ struct if_mapping * target,
+ int flag);
/**************************** VARIABLES ****************************/
{ "pcmciaslot", &mapping_addpcmciaslot, &mapping_cmppcmciaslot, &mapping_getpcmciaslot },
/* sysfs file (udev emulation) */
{ "sysfs", &mapping_addsysfs, &mapping_cmpsysfs, &mapping_getsysfs },
+ /* previous interface name */
+ { "prevname", &mapping_addprevname, &mapping_cmpprevname, &mapping_getprevname },
/* The Terminator */
{ NULL, NULL, NULL, NULL },
};
/* Verbose support (i.e. debugging) */
int verbose = 0;
+/* udev output support (print new DEVPATH) */
+int udev_output = 0;
+
/* sysfs global data */
struct sysfs_metadata sysfs_global =
{
int n;
int ret;
- /* Check for a wildcard (converted from '*' to '%d' in mapping_create()) */
- p = strstr(pattern, "%d");
+ /* Check for a wildcard */
+ p = strchr(pattern, '*');
/* No wildcard, simple comparison */
if(p == NULL)
while(isdigit(*v));
/* Pattern suffix */
- p += 2;
+ p += 1;
/* Compare suffixes */
return(strcmp(p, v));
char * retname)
{
struct ifreq ifr;
+ char * star;
int ret;
/* The kernel doesn't check is the interface already has the correct
strncpy(ifr.ifr_name, oldname, IFNAMSIZ);
strncpy(ifr.ifr_newname, newname, IFNAMSIZ);
+ /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
+ * This require specific kernel support (2.6.2-rc1 and later).
+ * We externally use '*', but the kernel doesn't know about that,
+ * so convert it to something it knows about... */
+ star = strchr(newname, '*');
+ if(star != NULL)
+ {
+ int slen = star - newname;
+ /* Replace '*' with '%d' in the new buffer */
+ star = ifr.ifr_newname + slen;
+ /* Size was checked in process_rename() and mapping_create() */
+ memmove(star + 2, star + 1, IFNAMSIZ - slen - 2);
+ star[0] = '%';
+ star[1] = 'd';
+ }
+
/* Do it */
ret = ioctl(skfd, SIOCSIFNAME, &ifr);
/* Verify validity of string */
if(len >= sizeof(ifnode->mac_filter))
{
- fprintf(stderr, "MAC address too long at line %d\n", linenum);
+ fprintf(stderr, "Error : MAC address too long at line %d\n", linenum);
return(-1);
}
n = strspn(string, "0123456789ABCDEFabcdef:*");
int flag)
{
FILE * stream;
+ char * fname;
+ int fnsize;
char * linebuf = NULL;
size_t linelen = 0;
char * sdup;
skfd = skfd;
flag = flag;
- /* Check if we know the root of the sysfs filesystem */
- if(sysfs_global.root == NULL)
+ /* Check if we know the devpath of this device */
+ if(target->sysfs_devpath == NULL)
{
- /* Open the mount file for reading */
- stream = fopen("/proc/mounts", "r");
- if(!stream)
- {
- fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n",
- strerror(errno));
- return(-1);
- }
-
- /* Read each line of file
- * getline is a GNU extension :-( The buffer is recycled and increased
- * as needed by getline. */
- while(getline(&linebuf, &linelen, stream) > 0)
+ /* Check if we know the root of the sysfs filesystem */
+ if(sysfs_global.root == NULL)
{
- char * p;
- size_t n;
+ /* Open the mount file for reading */
+ stream = fopen("/proc/mounts", "r");
+ if(!stream)
+ {
+ fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n",
+ strerror(errno));
+ return(-1);
+ }
- /* Get the line starting with sysfs */
- p = linebuf;
- while(isspace(*p))
- ++p;
- if(!strncasecmp(p, "sysfs ", 6))
+ /* Read each line of file
+ * getline is a GNU extension :-( The buffer is recycled and
+ * increased as needed by getline. */
+ while(getline(&linebuf, &linelen, stream) > 0)
{
- /* Find the mount point */
- p += 6;
- while(isspace(*p))
- ++p;
- n = strcspn(p, " \t\n");
- sdup = strndup(p, n);
- if((n == 0) || (sdup == NULL))
+ int i;
+ char * p;
+ size_t n;
+ char * token[3];
+ size_t toklen[3];
+
+ /* The format of /proc/mounts is similar to /etc/fstab (5).
+ * The first argument is the device. For sysfs, there is no
+ * associated device, so this argument is ignored.
+ * The second argument is the mount point.
+ * The third argument is the filesystem type.
+ */
+
+ /* Extract the first 3 tokens */
+ p = linebuf;
+ for(i = 0; i < 3; i++)
{
- fprintf(stderr, "Error: Can't parse /proc/mounts file: %s\n",
- strerror(errno));
- return(-1);
+ while(isspace(*p))
+ ++p;
+ token[i] = p;
+ n = strcspn(p, " \t\n");
+ toklen[i] = n;
+ p += n;
}
- /* Store it */
- sysfs_global.root = sdup;
- sysfs_global.rlen = n;
- break;
+ /* Get the filesystem which type is "sysfs" */
+ if((n == 5) && (!strncasecmp(token[2], "sysfs", 5)))
+ {
+ /* Get its mount point */
+ n = toklen[1];
+ sdup = strndup(token[1], n);
+ if((n == 0) || (sdup == NULL))
+ {
+ fprintf(stderr,
+ "Error: Can't parse /proc/mounts file: %s\n",
+ strerror(errno));
+ return(-1);
+ }
+ /* Store it */
+ sysfs_global.root = sdup;
+ sysfs_global.rlen = n;
+ break;
+ }
+ /* Finished -> next line */
}
- /* Finished -> next line */
- }
- /* Cleanup */
- fclose(stream);
+ /* Cleanup */
+ fclose(stream);
- /* Check if we found it */
- if(sysfs_global.root == NULL)
+ /* Check if we found it */
+ if(sysfs_global.root == NULL)
+ {
+ fprintf(stderr,
+ "Error: Can't find sysfs in /proc/mounts file\n");
+ free(linebuf);
+ return(-1);
+ }
+ }
+
+ /* Construct devpath for this interface.
+ * Reserve enough space to replace name without realloc. */
+ fnsize = (sysfs_global.rlen + 11 + IFNAMSIZ + 1);
+ fname = malloc(fnsize);
+ if(fname == NULL)
{
- fprintf(stderr, "Error: Can't find sysfs in /proc/mounts file\n");
- free(linebuf);
+ fprintf(stderr, "Error: Can't allocate SYSFS devpath\n");
return(-1);
}
+ /* Not true devpath for 2.6.20+, but this syslink should work */
+ target->sysfs_devplen = sprintf(fname, "%s/class/net/%s",
+ sysfs_global.root, ifname);
+ target->sysfs_devpath = fname;
}
/* Loop on all sysfs selector */
for(findex = 0; findex < sysfs_global.filenum; findex++)
{
- char * fname;
- int flen;
char * p;
ssize_t n;
/* Construct complete filename for the sysfs selector */
- flen = (sysfs_global.rlen + 11 + strlen(ifname) + 1 +
- strlen(sysfs_global.filename[findex]) + 1);
- fname = malloc(flen);
+ fnsize = (target->sysfs_devplen + 1 +
+ strlen(sysfs_global.filename[findex]) + 1);
+ fname = malloc(fnsize);
if(fname == NULL)
{
fprintf(stderr, "Error: Can't allocate SYSFS filename\n");
free(linebuf);
return(-1);
}
- sprintf(fname, "%s/class/net/%s/%s", sysfs_global.root, ifname,
+ sprintf(fname, "%s/%s", target->sysfs_devpath,
sysfs_global.filename[findex]);
/* Open the sysfs file for reading */
fclose(stream);
if(n <= 0)
{
- /* Some sysfs attribute are void for some interface */
- if(verbose)
- fprintf(stderr, "Error: Can't read file `%s'\n", fname);
- /* Next sysfs selector */
- continue;
- }
+ /* Some attributes are just symlinks to another directory.
+ * We can read the attributes in that other directory
+ * just fine, but sometimes the symlink itself gives a lot
+ * of information.
+ * Examples : SYSFS{device} and SYSFS{device/driver}
+ * In such cases, get the name of the directory pointed to...
+ */
+ /*
+ * I must note that the API for readlink() is very bad,
+ * which force us to have this ugly code. Yuck !
+ */
+ int allocsize = 128; /* 256 = Good start */
+ int retry = 16;
+ char * linkpath = NULL;
+ int pathlen;
- /* Get content, remove trailing '/n', save it */
- p = linebuf;
- if(p[n - 1] == '\n')
- n--;
- sdup = strndup(p, n);
+ /* Try reading the link with increased buffer size */
+ do
+ {
+ allocsize *= 2;
+ linkpath = realloc(linkpath, allocsize);
+ pathlen = readlink(fname, linkpath, allocsize);
+ /* If we did not hit the buffer limit, success */
+ if(pathlen < allocsize)
+ break;
+ }
+ while(retry-- > 0);
+
+ /* Check for error, most likely ENOENT */
+ if(pathlen > 0)
+ /* We have a symlink ;-) Terminate the string. */
+ linkpath[pathlen] = '\0';
+ else
+ {
+ /* Error ! */
+ free(linkpath);
+
+ /* A lot of information in the sysfs is implicit, given
+ * by the position of a file in the tree. It is therefore
+ * important to be able to read the various components
+ * of a path. For this reason, we resolve '..' to the
+ * real name of the parent directory... */
+ /* We have at least 11 char, see above */
+ if(!strcmp(fname + fnsize - 4, "/.."))
+ //if(!strcmp(fname + strlen(fname) - 3, "/.."))
+ {
+ /* This procedure to get the realpath is not very
+ * nice, but it's the "best practice". Hmm... */
+ int cwd_fd = open(".", O_RDONLY);
+ linkpath = NULL;
+ if(cwd_fd > 0)
+ {
+ int ret = chdir(fname);
+ if(ret == 0)
+ /* Using getcwd with NULL is a GNU extension. Nice. */
+ linkpath = getcwd(NULL, 0);
+ /* This may fail, but it's not fatal */
+ fchdir(cwd_fd);
+ }
+ /* Check if we suceeded */
+ if(!linkpath)
+ {
+ free(linkpath);
+ if(verbose)
+ fprintf(stderr, "Error: Can't read parent directory `%s'\n", fname);
+ /* Next sysfs selector */
+ continue;
+ }
+ }
+ else
+ {
+ /* Some sysfs attribute are void for some interface,
+ * we may have a real directory, or we may have permission
+ * issues... */
+ if(verbose)
+ fprintf(stderr, "Error: Can't read file `%s'\n", fname);
+ /* Next sysfs selector */
+ continue;
+ }
+ }
+
+ /* Here, we have a link name or a parent directory name */
+
+ /* Keep only the last component of path name, save it */
+ p = basename(linkpath);
+ sdup = strdup(p);
+ free(linkpath);
+ }
+ else
+ {
+ /* This is a regular file (well, pseudo file) */
+ /* Get content, remove trailing '/n', save it */
+ p = linebuf;
+ if(p[n - 1] == '\n')
+ n--;
+ sdup = strndup(p, n);
+ }
if(sdup == NULL)
{
fprintf(stderr, "Error: Can't allocate SYSFS value\n");
return(target->active[SELECT_SYSFS] ? 0 : -1);
}
+/*------------------------------------------------------------------*/
+/*
+ * Add a Previous Interface Name selector to a mapping
+ */
+static int
+mapping_addprevname(struct if_mapping * ifnode,
+ int * active,
+ char * string,
+ size_t len,
+ struct add_extra * extra,
+ int linenum)
+{
+ /* Avoid "Unused parameter" warning */
+ extra = extra;
+
+ /* Verify validity of string */
+ if(len >= sizeof(ifnode->prevname))
+ {
+ fprintf(stderr, "Old Interface Name too long at line %d\n", linenum);
+ return(-1);
+ }
+
+ /* Copy */
+ memcpy(ifnode->prevname, string, len + 1);
+
+ /* Activate */
+ ifnode->active[SELECT_PREVNAME] = 1;
+ active[SELECT_PREVNAME] = 1;
+
+ if(verbose)
+ fprintf(stderr,
+ "Parsing : Added Old Interface Name `%s' from line %d.\n",
+ ifnode->prevname, linenum);
+
+ return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the Previous Interface Name of two mappings
+ * Note : this one is special.
+ */
+static int
+mapping_cmpprevname(struct if_mapping * ifnode,
+ struct if_mapping * target)
+{
+ /* Do wildcard matching, case insensitive */
+ return(fnmatch(ifnode->prevname, target->ifname, FNM_CASEFOLD));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the Previous Interface Name from a live interface
+ */
+static int
+mapping_getprevname(int skfd,
+ const char * ifname,
+ struct if_mapping * target,
+ int flag)
+{
+ /* Avoid "Unused parameter" warning */
+ skfd = skfd; ifname = ifname; flag = flag;
+
+ /* Don't do anything, it's already in target->ifname ;-) */
+
+ /* Activate */
+ target->active[SELECT_PREVNAME] = 1;
+
+ return(0);
+}
+
/*********************** MAPPING MANAGEMENTS ***********************/
/*
struct if_mapping * ifnode;
char * star;
- /* Check overflow. */
- if(len > IFNAMSIZ)
+ star = memchr(pos, '*', len);
+
+ /* Check overflow, need one extra char for wildcard */
+ if((len + (star != NULL)) > IFNAMSIZ)
{
fprintf(stderr, "Error: Interface name `%.*s' too long at line %d\n",
(int) len, pos, linenum);
fprintf(stderr, "Warning: Alias device `%s' at line %d probably can't be mapped.\n",
ifnode->ifname, linenum);
- /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
- * This require specific kernel support (2.6.2-rc1 and later).
- * We externally use '*', but the kernel doesn't know about that,
- * so convert it to something it knows about... */
- star = strchr(ifnode->ifname, '*');
- if(star != NULL)
- {
- /* We need an extra char */
- if(len >= IFNAMSIZ)
- {
- fprintf(stderr,
- "Error: Interface wildcard `%s' too long at line %d\n",
- ifnode->ifname, linenum);
- free(ifnode);
- return(NULL);
- }
-
- /* Replace '*' with '%d' */
- memmove(star + 2, star + 1, len + 1 - (star - ifnode->ifname));
- star[0] = '%';
- star[1] = 'd';
- }
-
if(verbose)
fprintf(stderr, "Parsing : Added Mapping `%s' from line %d.\n",
ifnode->ifname, linenum);
static int
process_rename(int skfd,
char * ifname,
- char * pattern)
+ char * newname)
{
- char newname[IFNAMSIZ+1];
char retname[IFNAMSIZ+1];
int len;
char * star;
- len = strlen(pattern);
- star = strchr(pattern, '*');
+ len = strlen(newname);
+ star = strchr(newname, '*');
/* Check newname length, need one extra char for wildcard */
if((len + (star != NULL)) > IFNAMSIZ)
{
fprintf(stderr, "Error: Interface name `%s' too long.\n",
- pattern);
+ newname);
return(-1);
}
- /* Copy to local buffer */
- memcpy(newname, pattern, len + 1);
-
- /* Convert wildcard to the proper format */
- if(star != NULL)
- {
- /* Replace '*' with '%d' in the new buffer */
- star += newname - pattern;
- memmove(star + 2, star + 1, len + 1 - (star - newname));
- star[0] = '%';
- star[1] = 'd';
- }
-
/* Change the name of the interface */
if(if_set_name(skfd, ifname, newname, retname) < 0)
{
if(target == NULL)
return(-1);
+ /* If udev is calling us, get the real devpath. */
+ if(udev_output)
+ {
+ const char *env;
+ /* It's passed to us as an environment variable */
+ env = getenv("DEVPATH");
+ if(env)
+ {
+ int env_len = strlen(env);
+ target->sysfs_devplen = env_len;
+ /* Make enough space for new interface name */
+ target->sysfs_devpath = malloc(env_len + IFNAMSIZ + 1);
+ if(target->sysfs_devpath != NULL)
+ memcpy(target->sysfs_devpath, env, env_len + 1);
+ }
+ /* We will get a second chance is the user has some sysfs selectors */
+ }
+
/* Find matching mapping */
mapping = mapping_find(target);
if(mapping == NULL)
* That would be tricky to do... */
if(dry_run)
{
- printf("Dry-run : Would rename %s to %s.\n",
- target->ifname, mapping->ifname);
- return(0);
+ strcpy(retname, mapping->ifname);
+ fprintf(stderr, "Dry-run : Would rename %s to %s.\n",
+ target->ifname, mapping->ifname);
}
-
- /* Change the name of the interface */
- if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
+ else
{
- fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
- target->ifname, mapping->ifname, strerror(errno));
- return(-1);
+ /* Change the name of the interface */
+ if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
+ {
+ fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
+ target->ifname, mapping->ifname, strerror(errno));
+ return(-1);
+ }
}
/* Check if called with an explicit interface name */
if(print_newname)
{
- /* Always print out the *new* interface name so that
- * the calling script can pick it up and know where its interface
- * has gone. */
- printf("%s\n", retname);
+ if(!udev_output)
+ /* Always print out the *new* interface name so that
+ * the calling script can pick it up and know where its interface
+ * has gone. */
+ printf("%s\n", retname);
+ else
+ /* udev likes to call us as an IMPORT action. This means that
+ * we need to return udev the environment variables changed.
+ * Obviously, we don't want to return anything is nothing changed. */
+ if(strcmp(target->ifname, retname))
+ {
+ char * pos;
+ /* Hack */
+ if(!target->sysfs_devpath)
+ mapping_getsysfs(skfd, ifname, target, 0);
+ /* Update devpath. Size is large enough. */
+ pos = strrchr(target->sysfs_devpath, '/');
+ if((pos != NULL) && (!strcmp(target->ifname, pos + 1)))
+ strcpy(pos + 1, retname);
+ /* Return new environment variables */
+ printf("DEVPATH=%s\nINTERFACE=%s\nINTERFACE_OLD=%s\n",
+ target->sysfs_devpath, retname, target->ifname);
+ }
}
/* Done */
/* Loop over all command line options */
while(1)
{
- int c = getopt_long(argc, argv, "c:dDi:n:ptvV", long_opt, NULL);
+ int c = getopt_long(argc, argv, "c:dDi:n:ptuvV", long_opt, NULL);
if(c == -1)
break;
case 't':
force_takeover = 1;
break;
+ case 'u':
+ udev_output = 1;
+ break;
case 'v':
printf("%-8.16s Wireless-Tools version %d\n", "ifrename", WT_VERSION);
return(0);
else
{
/* Rename only this interface based on mappings
- * Mostly used for HotPlug processing (from /etc/hotplug/net.agent).
+ * Mostly used for HotPlug processing (from /etc/hotplug/net.agent)
+ * or udev processing (from a udev IMPORT rule).
* Process the network interface specified on the command line,
* and return the new name on stdout.
*/
-.\" Jean II - HPL - 2004
+.\" Jean II - HPL - 2004-2007
.\" iftab.5
.\"
-.TH IFTAB 5 "01 March 2004" "wireless-tools" "Linux Programmer's Manual"
+.TH IFTAB 5 "26 February 2007" "wireless-tools" "Linux Programmer's Manual"
.\"
.\" NAME part
.\"
.PP
Most users will only use the
.B mac
-selector, other selectors are for more specialised setup.
+selector despite its potential problems, other selectors are for more
+specialised setup. Most selectors accept a '*' in the selector value
+for wilcard matching, and most selectors are case insensitive.
.TP
.BI mac " mac address"
Matches the MAC Address of the interface with the specified MAC
.IR ifconfig (8)
or
.IR ip (8).
-The specified MAC address may contain a '*' for wilcard matching.
.br
This is the most common selector, as most interfaces have a unique MAC
address allowing to identify network interfaces without ambiguity.
However, some interfaces don't have a valid MAC address until they are
-brought up, in such case using this selector is tricky.
+brought up, in such case using this selector is tricky or impossible.
.TP
.BI arp " arp type"
Matches the ARP Type (also called Link Type) of the interface with the
-specified ARP type. The ARP Type of the interface can be shown using
+specified ARP type as a number. The ARP Type of the interface can be
+shown using
.IR ifconfig (8)
or
-.IR ip (8).
+.IR ip (8),
+the
+.B link/ether
+type correspond to
+.B 1
+and the
+.B link/ieee802.11
+type correspond to
+.BR 801 .
.br
This selector is useful when a driver create multiple network
interfaces for a single network card.
Matches the Wireless Protocol of the interface with the specified
wireless protocol. The Wireless Protocol of the interface can be shown
using
-.IR iwconfig (8).
+.IR iwconfig (8)
+or
+.IR iwgetid (8).
.br
This selector is only supported on wireless interfaces and is not
sufficient to uniquely identify an interface.
cards it is advised to use the selector
.BR businfo .
.TP
+.BI prevname " previous interface name"
+Matches the name of the interface prior to renaming with the specified
+oldname.
+.br
+This selector should be avoided as the previous interface name may
+vary depending on various condition. A system/kernel/driver update may
+change the original name. Then, ifrename or another tool may rename it
+prior to the execution of this selector.
+.TP
.BI SYSFS{ filename } " value"
-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
-.IR /sys/class/net/ .
-For example, the filename
-.I address
-is the MAC address of the device and should be identical to the selector
-.BR mac .
+Matches the content the sysfs attribute given by filename to the
+specified value. For symlinks and parents directories, match the
+actual directory name of the sysfs attribute given by filename to the
+specified value.
.br
+A list of the most useful sysfs attributes is given in the next
+section.
+.\"
+.\" SYSFS DESCRIPTORS part
+.\"
+.SH SYSFS DESCRIPTORS
+Sysfs attributes for a specific interface are located on most systems
+in the directory named after that interface at
+.IR /sys/class/net/ .
+Most sysfs attribute are files, and their values can be read using
+.IR cat "(1) or " more (1).
+It is also possible to match attributes in subdirectories.
+.PP
+Some sysfs attributes are symlinks, pointing to another directory in
+sysfs. If the attribute filename is a symlink the sysfs attribute
+resolves to the name of the directory pointed by the symlink using
+.IR readlink (1).
+The location is a directory in the sysfs tree is also important. If
+the attribute filename ends with
+.IR /.. ,
+the sysfs attribute resolves to the real name of the parent directory
+using
+.IR pwd (1).
+.PP
The sysfs filesystem is only supported with 2.6.X kernel and need to
-be mounted. sysfs selectors are not as efficient as other selectors,
-therefore they should be avoided for maximum performance.
+be mounted (usually in
+.IR /sys ).
+sysfs selectors are not as efficient as other selectors, therefore
+they should be avoided for maximum performance.
+.PP
+These are common sysfs attributes and their corresponding ifrename
+descriptors.
+.TP
+.BI SYSFS{address} " value"
+Same as the
+.B mac
+descriptor.
+.TP
+.BI SYSFS{type} " value"
+Same as the
+.B arp
+descriptor.
+.TP
+.BI SYSFS{device} " value"
+Valid only up to kernel 2.6.20. Same as the
+.B businfo
+descriptor.
+.TP
+.BI SYSFS{..} " value"
+Valid only from kernel 2.6.21. Same as the
+.B businfo
+descriptor.
+.TP
+.BI SYSFS{device/driver} " value"
+Valid only up to kernel 2.6.20. Same as the
+.B driver
+descriptor.
+.TP
+.BI SYSFS{../driver} " value"
+Valid only from kernel 2.6.21. Same as the
+.B driver
+descriptor.
+.TP
+.BI SYSFS{device/irq} " value"
+Valid only up to kernel 2.6.20. Same as the
+.B irq
+descriptor.
+.TP
+.BI SYSFS{../irq} " value"
+Valid only from kernel 2.6.21. Same as the
+.B irq
+descriptor.
.\"
-.\" EXAMPLE part
+.\" EXAMPLES part
.\"
-.SH EXAMPLE
+.SH EXAMPLES
# This is a comment
.br
eth2 mac 08:00:09:DE:82:0E
.br
air* mac 00:07:0E:* arp 1
.br
-myvpn SYSFS{address} 00:10:83:*
+myvpn SYSFS{address} 00:10:83:* SYSFS{type} 1
+.br
+bcm* SYSFS{device} 0000:03:00.0 SYSFS{device/driver} bcm43xx
+.br
+bcm* SYSFS{..} 0000:03:00.0 SYSFS{../driver} bcm43xx
.\"
.\" AUTHOR part
.\"
.\" Jean II - HPLB - 1996 => HPL - 2004
.\" iwconfig.8
.\"
-.TH IWCONFIG 8 "09 March 2006" "wireless-tools" "Linux Programmer's Manual"
+.TH IWCONFIG 8 "30 March 2006" "wireless-tools" "Linux Programmer's Manual"
.\"
.\" NAME part
.\"
.br
.BI " [enc " E "] [key " K "] [power " P "] [retry " R ]
.br
-.BI " [commit]
+.BI " [modu " M "] [commit]
.br
.BI "iwconfig --help"
.br
.br
.I " iwconfig eth0 essid -- ""ANY""
.TP
-.BR nwid / domain
-Set the Network ID (in some products it may also be called Domain
-ID). As all adjacent wireless networks share the same medium, this
-parameter is used to differenciate them (create logical colocated
-networks) and identify nodes belonging to the same cell.
+.BR nwid
+Set the Network ID. As all adjacent wireless networks share the same
+medium, this parameter is used to differentiate them (create logical
+colocated networks) and identify nodes belonging to the same cell.
.br
This parameter is only used for pre-802.11 hardware, the 802.11
protocol uses the ESSID and AP Address for this function.
.br
To set the maximum number of retries, enter
.IR "limit `value'" .
-This is an absolute value (without unit).
+This is an absolute value (without unit), and the default (when
+nothing is specified).
To set the maximum length of time the MAC should retry, enter
.IR "lifetime `value'" .
By defaults, this value in in seconds, append the suffix m or u to
specify values in milliseconds or microseconds.
.br
You can also add the
-.IR min " and " max
+.IR short ", " long ", " min " and " max
modifiers. If the card supports automatic mode, they define the bounds
of the limit or lifetime. Some other cards define different values
depending on packet size, for example in 802.11
.br
.I " iwconfig eth0 retry lifetime 300m"
.br
+.I " iwconfig eth0 retry short 12"
+.br
.I " iwconfig eth0 retry min limit 8"
.TP
.BR rts [_threshold]
.IR "period `value'" .
To set the timeout before going back to sleep, enter
.IR "timeout `value'" .
+To set the generic level of power saving, enter
+.IR "saving `value'" .
You can also add the
.IR min " and " max
modifiers. By default, those values are in seconds, append the suffix
m or u to specify values in milliseconds or microseconds. Sometimes,
-those values are without units (number of beacon periods, dwell or
-similar).
+those values are without units (number of beacon periods, dwell,
+percentage or similar).
.br
.IR off " and " on
disable and reenable power management. Finally, you may set the power
.br
.I " iwconfig eth0 power timeout 300u all"
.br
+.I " iwconfig eth0 power saving 3"
+.br
.I " iwconfig eth0 power off"
.br
.I " iwconfig eth0 power min period 2 power max period 4"
.TP
+.BR modu [lation]
+Force the card to use a specific set of modulations. Modern cards
+support various modulations, some which are standard, such as 802.11b
+or 802.11g, and some proprietary. This command force the card to only
+use the specific set of modulations listed on the command line. This
+can be used to fix interoperability issues.
+.br
+The list of available modulations depend on the card/driver and can be
+displayed using
+.IR "iwlist modulation" .
+Note that some card/driver may not be able to select each modulation
+listed independantly, some may come as a group. You may also set this
+parameter to
+.IR auto
+let the card/driver do its best.
+.br
+.B Examples :
+.br
+.I " iwconfig eth0 modu 11g"
+.br
+.I " iwconfig eth0 modu CCK OFDMa"
+.br
+.I " iwconfig eth0 modu auto"
+.TP
.BR commit
Some cards may not apply changes done through Wireless Extensions
immediately (they may wait to aggregate the changes or apply it only
-when the card is brought up via ifconfig). This command (when
-available) forces the card to apply all pending changes.
+when the card is brought up via
+.IR ifconfig ).
+This command (when available) forces the card to apply all pending
+changes.
.br
This is normally not needed, because the card will eventually apply
the changes, but can be useful for debugging.
/*
* Wireless Tools
*
- * Jean II - HPLB 97->99 - HPL 99->04
+ * Jean II - HPLB 97->99 - HPL 99->07
*
* Main code for "iwconfig". This is the generic tool for most
* manipulations...
* You need to link this code against "iwlib.c" and "-lm".
*
* This file is released under the GPL license.
- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
*/
#include "iwlib.h" /* Header */
-/************************* MISC SUBROUTINES **************************/
+/**************************** CONSTANTS ****************************/
-/*------------------------------------------------------------------*/
/*
- * Print usage string
+ * Error codes defined for setting args
*/
-static void
-iw_usage(void)
-{
- fprintf(stderr,
- "Usage: iwconfig interface [essid {NN|on|off}]\n"
- " [nwid {NN|on|off}]\n"
- " [mode {managed|ad-hoc|...}\n"
- " [freq N.NNNN[k|M|G]]\n"
- " [channel N]\n"
- " [ap {N|off|auto}]\n"
- " [sens N]\n"
- " [nick N]\n"
- " [rate {N|auto|fixed}]\n"
- " [rts {N|auto|fixed|off}]\n"
- " [frag {N|auto|fixed|off}]\n"
- " [enc {NNNN-NNNN|off}]\n"
- " [power {period N|timeout N}]\n"
- " [retry {limit N|lifetime N}]\n"
- " [txpower N {mW|dBm}]\n"
- " [commit]\n"
- " Check man pages for more details.\n\n"
- );
-}
+#define IWERR_ARG_NUM -2
+#define IWERR_ARG_TYPE -3
+#define IWERR_ARG_SIZE -4
+#define IWERR_ARG_CONFLICT -5
+#define IWERR_SET_EXT -6
+#define IWERR_GET_EXT -7
+
+/**************************** VARIABLES ****************************/
+/*
+ * Ugly, but deal with errors in set_info() efficiently...
+ */
+static int errarg;
+static int errmax;
/************************* DISPLAY ROUTINES **************************/
if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
info->has_range = 1;
- /* Get sensitivity */
- if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
- {
- info->has_sens = 1;
- memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
- }
-
/* Get AP address */
if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
{
memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
}
- /* Get NickName */
- wrq.u.essid.pointer = (caddr_t) info->nickname;
- wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
- wrq.u.essid.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
- if(wrq.u.data.length > 1)
- info->has_nickname = 1;
-
/* Get bit rate */
if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
{
memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
}
- /* Get RTS threshold */
- if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
- {
- info->has_rts = 1;
- memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
- }
-
- /* Get fragmentation threshold */
- if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
- {
- info->has_frag = 1;
- memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
- }
-
/* Get Power Management settings */
wrq.u.power.flags = 0;
if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
}
+ /* Get stats */
+ if(iw_get_stats(skfd, ifname, &(info->stats),
+ &info->range, info->has_range) >= 0)
+ {
+ info->has_stats = 1;
+ }
+
+#ifndef WE_ESSENTIAL
+ /* Get NickName */
+ wrq.u.essid.pointer = (caddr_t) info->nickname;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
+ wrq.u.essid.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
+ if(wrq.u.data.length > 1)
+ info->has_nickname = 1;
+
if((info->has_range) && (info->range.we_version_compiled > 9))
{
/* Get Transmit Power */
}
}
+ /* Get sensitivity */
+ if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
+ {
+ info->has_sens = 1;
+ memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
+ }
+
if((info->has_range) && (info->range.we_version_compiled > 10))
{
/* Get retry limit/lifetime */
}
}
- /* Get stats */
- if(iw_get_stats(skfd, ifname, &(info->stats),
- &info->range, info->has_range) >= 0)
+ /* Get RTS threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
{
- info->has_stats = 1;
+ info->has_rts = 1;
+ memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
}
-#ifdef DISPLAY_WPA
- /* Note : currently disabled to not bloat iwconfig output. Also,
- * if does not make total sense to display parameters that we
- * don't allow (yet) to configure.
- * For now, use iwlist instead... Jean II */
-
- /* Get WPA/802.1x/802.11i security parameters */
- if((info->has_range) && (info->range.we_version_compiled > 17))
+ /* Get fragmentation threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
{
- wrq.u.param.flags = IW_AUTH_KEY_MGMT;
- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
- {
- info->has_auth_key_mgmt = 1;
- info->auth_key_mgmt = wrq.u.param.value;
- }
-
- wrq.u.param.flags = IW_AUTH_CIPHER_PAIRWISE;
- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
- {
- info->has_auth_cipher_pairwise = 1;
- info->auth_cipher_pairwise = wrq.u.param.value;
- }
-
- wrq.u.param.flags = IW_AUTH_CIPHER_GROUP;
- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
- {
- info->has_auth_cipher_group = 1;
- info->auth_cipher_group = wrq.u.param.value;
- }
+ info->has_frag = 1;
+ memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
}
-#endif
+#endif /* WE_ESSENTIAL */
return(0);
}
printf("ESSID:off/any ");
}
+#ifndef WE_ESSENTIAL
/* Display NickName (station name), if any */
if(info->has_nickname)
printf("Nickname:\"%s\"", info->nickname);
+#endif /* WE_ESSENTIAL */
/* Formatting */
if(info->b.has_essid || info->has_nickname)
tokens = 0;
}
+#ifndef WE_ESSENTIAL
/* Display Network ID */
if(info->b.has_nwid)
{
printf("NWID:%X ", info->b.nwid.value);
tokens +=2;
}
+#endif /* WE_ESSENTIAL */
/* Display the current mode of operation */
if(info->b.has_mode)
printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
}
+#ifndef WE_ESSENTIAL
/* Display the Transmit Power */
if(info->has_txpower)
{
tokens +=4;
/* Fixed ? */
- if(info->sens.fixed)
- printf("Sensitivity=");
- else
- printf("Sensitivity:");
+ printf("Sensitivity%c", info->sens.fixed ? '=' : ':');
if(info->has_range)
/* Display in dBm ? */
else
printf("%d ", info->sens.value);
}
+#endif /* WE_ESSENTIAL */
printf("\n ");
tokens = 0;
+#ifndef WE_ESSENTIAL
/* Display retry limit/lifetime information */
if(info->has_retry)
{
if(info->retry.flags & IW_RETRY_TYPE)
{
iw_print_retry_value(buffer, sizeof(buffer),
- info->retry.value, info->retry.flags);
+ info->retry.value, info->retry.flags,
+ info->range.we_version_compiled);
printf("%s", buffer);
}
else
{
/* Fixed ? */
- if(info->rts.fixed)
- printf("RTS thr=");
- else
- printf("RTS thr:");
-
- printf("%d B ", info->rts.value);
+ printf("RTS thr%c%d B ",
+ info->rts.fixed ? '=' : ':',
+ info->rts.value);
}
tokens += 3;
}
else
{
/* Fixed ? */
- if(info->frag.fixed)
- printf("Fragment thr=");
- else
- printf("Fragment thr:");
-
- printf("%d B ", info->frag.value);
+ printf("Fragment thr%c%d B ",
+ info->frag.fixed ? '=' : ':',
+ info->frag.value);
}
}
/* Formating */
if(tokens > 0)
printf("\n ");
+#endif /* WE_ESSENTIAL */
/* Display encryption information */
/* Note : we display only the "current" key, use iwlist to list all keys */
printf("\n ");
}
-#ifdef DISPLAY_WPA
- /* Display WPA/802.1x/802.11i security parameters */
- if(info->has_auth_key_mgmt || info->has_auth_cipher_pairwise ||
- info->has_auth_cipher_group)
- {
- printf("Auth params:");
- if(info->has_auth_key_mgmt)
- printf(" key_mgmt:0x%X ", info->auth_key_mgmt);
- if(info->has_auth_cipher_pairwise)
- printf(" cipher_pairwise:0x%X ", info->auth_cipher_pairwise);
- if(info->has_auth_cipher_group)
- printf(" cipher_group:0x%X ", info->auth_cipher_group);
- printf("\n ");
- }
-#endif
-
/* Display Power Management information */
/* Note : we display only one parameter, period or timeout. If a device
* (such as HiperLan) has both, the user need to use iwlist... */
if(info->power.flags & IW_POWER_TYPE)
{
iw_print_pm_value(buffer, sizeof(buffer),
- info->power.value, info->power.flags);
+ info->power.value, info->power.flags,
+ info->range.we_version_compiled);
printf("%s ", buffer);
}
return(rc);
}
-/************************* SETTING ROUTINES **************************/
+/****************** COMMAND LINE MODIFIERS PARSING ******************/
+/*
+ * Factor out the parsing of command line modifiers.
+ */
/*------------------------------------------------------------------*/
/*
- * Macro to handle errors when setting WE
- * Print a nice error message and exit...
- * We define them as macro so that "return" do the right thing.
- * The "do {...} while(0)" is a standard trick
+ * Map command line modifiers to the proper flags...
*/
-#define ERR_SET_EXT(rname, request) \
- fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \
- rname, request)
-
-#define ABORT_ARG_NUM(rname, request) \
- do { \
- ERR_SET_EXT(rname, request); \
- fprintf(stderr, " too few arguments.\n"); \
- return(-1); \
- } while(0)
-
-#define ABORT_ARG_TYPE(rname, request, arg) \
- do { \
- ERR_SET_EXT(rname, request); \
- fprintf(stderr, " invalid argument \"%s\".\n", arg); \
- return(-2); \
- } while(0)
-
-#define ABORT_ARG_SIZE(rname, request, max) \
- do { \
- ERR_SET_EXT(rname, request); \
- fprintf(stderr, " argument too big (max %d)\n", max); \
- return(-3); \
- } while(0)
+typedef struct iwconfig_modifier {
+ const char * cmd; /* Command line shorthand */
+ __u16 flag; /* Flags to add */
+ __u16 exclude; /* Modifiers to exclude */
+} iwconfig_modifier;
/*------------------------------------------------------------------*/
/*
- * Wrapper to push some Wireless Parameter in the driver
- * Use standard wrapper and add pretty error message if fail...
+ * Modifiers for Power
*/
-#define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \
- do { \
- if(iw_set_ext(skfd, ifname, request, wrq) < 0) { \
- ERR_SET_EXT(rname, request); \
- fprintf(stderr, " SET failed on device %-1.16s ; %s.\n", \
- ifname, strerror(errno)); \
- return(-5); \
- } } while(0)
+static const struct iwconfig_modifier iwmod_power[] = {
+ { "min", IW_POWER_MIN, IW_POWER_MAX },
+ { "max", IW_POWER_MAX, IW_POWER_MIN },
+ { "period", IW_POWER_PERIOD, IW_POWER_TIMEOUT | IW_POWER_SAVING },
+ { "timeout", IW_POWER_TIMEOUT, IW_POWER_PERIOD | IW_POWER_SAVING },
+ { "saving", IW_POWER_SAVING, IW_POWER_TIMEOUT | IW_POWER_PERIOD },
+};
+#define IWMOD_POWER_NUM (sizeof(iwmod_power)/sizeof(iwmod_power[0]))
/*------------------------------------------------------------------*/
/*
- * Wrapper to extract some Wireless Parameter out of the driver
- * Use standard wrapper and add pretty error message if fail...
+ * Modifiers for Retry
*/
-#define IW_GET_EXT_ERR(skfd, ifname, request, wrq, rname) \
- do { \
- if(iw_get_ext(skfd, ifname, request, wrq) < 0) { \
- ERR_SET_EXT(rname, request); \
- fprintf(stderr, " GET failed on device %-1.16s ; %s.\n", \
- ifname, strerror(errno)); \
- return(-6); \
- } } while(0)
+#ifndef WE_ESSENTIAL
+static const struct iwconfig_modifier iwmod_retry[] = {
+ { "min", IW_RETRY_MIN, IW_RETRY_MAX },
+ { "max", IW_RETRY_MAX, IW_RETRY_MIN },
+ { "short", IW_RETRY_SHORT, IW_RETRY_LONG },
+ { "long", IW_RETRY_LONG, IW_RETRY_SHORT },
+ { "limit", IW_RETRY_LIMIT, IW_RETRY_LIFETIME },
+ { "lifetime", IW_RETRY_LIFETIME, IW_RETRY_LIMIT },
+};
+#define IWMOD_RETRY_NUM (sizeof(iwmod_retry)/sizeof(iwmod_retry[0]))
+#endif /* WE_ESSENTIAL */
/*------------------------------------------------------------------*/
/*
- * Set the wireless options requested on command line
- * This function is too long and probably should be split,
- * because it look like the perfect definition of spaghetti code,
- * but I'm way to lazy
+ * Parse command line modifiers.
+ * Return error or number arg parsed.
+ * Modifiers must be at the beggining of command line.
*/
static int
-set_info(int skfd, /* The socket */
- char * args[], /* Command line args */
- int count, /* Args count */
- char * ifname) /* Dev name */
+parse_modifiers(char * args[], /* Command line args */
+ int count, /* Args count */
+ __u16 * pout, /* Flags to write */
+ const struct iwconfig_modifier modifier[],
+ int modnum)
{
- struct iwreq wrq;
- int i;
+ int i = 0;
+ int k = 0;
+ __u16 result = 0; /* Default : no flag set */
- /* if nothing after the device name - will never happen */
- if(count < 1)
+ /* Get all modifiers and value types on the command line */
+ do
{
- fprintf(stderr, "Error : too few arguments.\n");
- return(-1);
+ for(k = 0; k < modnum; k++)
+ {
+ /* Check if matches */
+ if(!strcasecmp(args[i], modifier[k].cmd))
+ {
+ /* Check for conflicting flags */
+ if(result & modifier[k].exclude)
+ {
+ errarg = i;
+ return(IWERR_ARG_CONFLICT);
+ }
+ /* Just add it */
+ result |= modifier[k].flag;
+ ++i;
+ break;
+ }
+ }
}
+ /* For as long as current arg matched and not out of args */
+ while((i < count) && (k < modnum));
+
+ /* Check there remains one arg for value */
+ if(i >= count)
+ return(IWERR_ARG_NUM);
+
+ /* Return result */
+ *pout = result;
+ return(i);
+}
+
+
+/*********************** SETTING SUB-ROUTINES ***********************/
+/*
+ * The following functions are use to set some wireless parameters and
+ * are called by the set dispatcher set_info().
+ * They take as arguments the remaining of the command line, with
+ * arguments processed already removed.
+ * An error is indicated by a negative return value.
+ * 0 and positive return values indicate the number of args consumed.
+ */
- /* The other args on the line specify options to be set... */
- for(i = 0; i < count; i++)
+/*------------------------------------------------------------------*/
+/*
+ * Set ESSID
+ */
+static int
+set_essid_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
+ char essid[IW_ESSID_MAX_SIZE + 1];
+ int we_kernel_version;
+
+ if((!strcasecmp(args[0], "off")) ||
+ (!strcasecmp(args[0], "any")))
{
- /* ---------- Commit changes to driver ---------- */
- if(!strncmp(args[i], "commit", 6))
- {
- /* No args */
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq,
- "Commit changes");
- continue;
- }
+ wrq.u.essid.flags = 0;
+ essid[0] = '\0';
+ }
+ else
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old essid */
+ memset(essid, '\0', sizeof(essid));
+ wrq.u.essid.pointer = (caddr_t) essid;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
+ wrq.u.essid.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.essid.flags = 1;
+ }
+ else
+ {
+ i = 0;
+
+ /* '-' or '--' allow to escape the ESSID string, allowing
+ * to set it to the string "any" or "off".
+ * This is a big ugly, but it will do for now */
+ if((!strcmp(args[0], "-")) || (!strcmp(args[0], "--")))
+ {
+ if(++i >= count)
+ return(IWERR_ARG_NUM);
+ }
+
+ /* Check the size of what the user passed us to avoid
+ * buffer overflows */
+ if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
+ {
+ errmax = IW_ESSID_MAX_SIZE;
+ return(IWERR_ARG_SIZE);
+ }
+ else
+ {
+ int temp;
- /* ---------- Set network ID ---------- */
- if((!strcasecmp(args[i], "nwid")) ||
- (!strcasecmp(args[i], "domain")))
- {
- i++;
- if(i >= count)
- ABORT_ARG_NUM("Set NWID", SIOCSIWNWID);
- if((!strcasecmp(args[i], "off")) ||
- (!strcasecmp(args[i], "any")))
- wrq.u.nwid.disabled = 1;
- else
- if(!strcasecmp(args[i], "on"))
+ wrq.u.essid.flags = 1;
+ strcpy(essid, args[i]); /* Size checked, all clear */
+ i++;
+
+ /* Check for ESSID index */
+ if((i < count) &&
+ (sscanf(args[i], "[%i]", &temp) == 1) &&
+ (temp > 0) && (temp < IW_ENCODE_INDEX))
{
- /* Get old nwid */
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq,
- "Set NWID");
- wrq.u.nwid.disabled = 0;
+ wrq.u.essid.flags = temp;
+ ++i;
}
- else
- if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
- != 1)
- ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]);
- else
- wrq.u.nwid.disabled = 0;
- wrq.u.nwid.fixed = 1;
-
- /* Set new nwid */
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq,
- "Set NWID");
- continue;
- }
+ }
+ }
- /* ---------- Set frequency / channel ---------- */
- if((!strncmp(args[i], "freq", 4)) ||
- (!strcmp(args[i], "channel")))
- {
- double freq;
+ /* Get version from kernel, device may not have range... */
+ we_kernel_version = iw_get_kernel_we_version();
- if(++i >= count)
- ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
- if(!strcasecmp(args[i], "auto"))
- {
- wrq.u.freq.m = -1;
- wrq.u.freq.e = 0;
- wrq.u.freq.flags = 0;
- }
- else
- {
- if(!strcasecmp(args[i], "fixed"))
- {
- /* Get old bitrate */
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFREQ, &wrq,
- "Set Bit Rate");
- wrq.u.freq.flags = IW_FREQ_FIXED;
- }
- else /* Should be a numeric value */
- {
- if(sscanf(args[i], "%lg", &(freq)) != 1)
- ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]);
- if(index(args[i], 'G')) freq *= GIGA;
- if(index(args[i], 'M')) freq *= MEGA;
- if(index(args[i], 'k')) freq *= KILO;
+ /* Finally set the ESSID value */
+ wrq.u.essid.pointer = (caddr_t) essid;
+ wrq.u.essid.length = strlen(essid);
+ if(we_kernel_version < 21)
+ wrq.u.essid.length++;
- iw_float2freq(freq, &(wrq.u.freq));
+ if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
+ return(IWERR_SET_EXT);
- wrq.u.freq.flags = IW_FREQ_FIXED;
+ /* Var args */
+ return(i);
+}
- /* Check for an additional argument */
- if(((i+1) < count) &&
- (!strcasecmp(args[i+1], "auto")))
- {
- wrq.u.freq.flags = 0;
- ++i;
- }
- if(((i+1) < count) &&
- (!strcasecmp(args[i+1], "fixed")))
- {
- wrq.u.freq.flags = IW_FREQ_FIXED;
- ++i;
- }
- }
- }
+/*------------------------------------------------------------------*/
+/*
+ * Set Mode
+ */
+static int
+set_mode_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ unsigned int k; /* Must be unsigned */
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
- "Set Frequency");
- continue;
- }
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ /* Check if it is a uint, otherwise get is as a string */
+ if(sscanf(args[0], "%i", &k) != 1)
+ {
+ k = 0;
+ while((k < IW_NUM_OPER_MODE) &&
+ strncasecmp(args[0], iw_operation_mode[k], 3))
+ k++;
+ }
+ if(k >= IW_NUM_OPER_MODE)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+
+ wrq.u.mode = k;
+ if(iw_set_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 arg */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set frequency/channel
+ */
+static int
+set_freq_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
- /* ---------- Set sensitivity ---------- */
- if(!strncmp(args[i], "sens", 4))
+ if(!strcasecmp(args[0], "auto"))
+ {
+ wrq.u.freq.m = -1;
+ wrq.u.freq.e = 0;
+ wrq.u.freq.flags = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
{
- if(++i >= count)
- ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS);
- if(sscanf(args[i], "%i", &(wrq.u.sens.value)) != 1)
- ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]);
-
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq,
- "Set Sensitivity");
- continue;
+ /* Get old frequency */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.freq.flags = IW_FREQ_FIXED;
}
-
- /* ---------- Set encryption stuff ---------- */
- if((!strncmp(args[i], "enc", 3)) ||
- (!strcmp(args[i], "key")))
+ else /* Should be a numeric value */
{
- unsigned char key[IW_ENCODING_TOKEN_MAX];
-
- if(++i >= count)
- ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE);
+ double freq;
+ char * unit;
- if(!strcasecmp(args[i], "on"))
+ freq = strtod(args[0], &unit);
+ if(unit == args[0])
{
- /* Get old encryption information */
- wrq.u.data.pointer = (caddr_t) key;
- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
- wrq.u.data.flags = 0;
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq,
- "Set Encode");
- wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
- else
+ if(unit != NULL)
{
- int gotone = 0;
- int oldone;
- int keylen;
- int temp;
-
- wrq.u.data.pointer = (caddr_t) NULL;
- wrq.u.data.flags = 0;
- wrq.u.data.length = 0;
-
- /* Allow arguments in any order (it's safe) */
- do
- {
- oldone = gotone;
-
- /* -- Check for the key -- */
- if(i < count)
- {
- keylen = iw_in_key_full(skfd, ifname,
- args[i], key, &wrq.u.data.flags);
- if(keylen > 0)
- {
- wrq.u.data.length = keylen;
- wrq.u.data.pointer = (caddr_t) key;
- ++i;
- gotone++;
- }
- }
-
- /* -- Check for token index -- */
- if((i < count) &&
- (sscanf(args[i], "[%i]", &temp) == 1) &&
- (temp > 0) && (temp < IW_ENCODE_INDEX))
- {
- wrq.u.encoding.flags |= temp;
- ++i;
- gotone++;
- }
+ if(unit[0] == 'G') freq *= GIGA;
+ if(unit[0] == 'M') freq *= MEGA;
+ if(unit[0] == 'k') freq *= KILO;
+ }
- /* -- Check the various flags -- */
- if((i < count) && (!strcasecmp(args[i], "off")))
- {
- wrq.u.data.flags |= IW_ENCODE_DISABLED;
- ++i;
- gotone++;
- }
- if((i < count) && (!strcasecmp(args[i], "open")))
- {
- wrq.u.data.flags |= IW_ENCODE_OPEN;
- ++i;
- gotone++;
- }
- if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
- {
- wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
- ++i;
- gotone++;
- }
- if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
- {
- wrq.u.data.flags |= IW_ENCODE_TEMP;
- ++i;
- gotone++;
- }
- }
- while(gotone != oldone);
+ iw_float2freq(freq, &(wrq.u.freq));
- /* Pointer is absent in new API */
- if(wrq.u.data.pointer == NULL)
- wrq.u.data.flags |= IW_ENCODE_NOKEY;
+ wrq.u.freq.flags = IW_FREQ_FIXED;
- /* Check if we have any invalid argument */
- if(!gotone)
- ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]);
- /* Get back to last processed argument */
- --i;
+ /* Check for an additional argument */
+ if((i < count) && (!strcasecmp(args[i], "auto")))
+ {
+ wrq.u.freq.flags = 0;
+ ++i;
}
-
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq,
- "Set Encode");
- continue;
- }
-
- /* ---------- Set ESSID ---------- */
- if(!strcasecmp(args[i], "essid"))
- {
- char essid[IW_ESSID_MAX_SIZE + 1];
- int we_kernel_version;
-
- i++;
- if(i >= count)
- ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
- if((!strcasecmp(args[i], "off")) ||
- (!strcasecmp(args[i], "any")))
+ if((i < count) && (!strcasecmp(args[i], "fixed")))
{
- wrq.u.essid.flags = 0;
- essid[0] = '\0';
+ wrq.u.freq.flags = IW_FREQ_FIXED;
+ ++i;
}
- else
- if(!strcasecmp(args[i], "on"))
- {
- /* Get old essid */
- memset(essid, '\0', sizeof(essid));
- wrq.u.essid.pointer = (caddr_t) essid;
- wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
- wrq.u.essid.flags = 0;
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq,
- "Set ESSID");
- wrq.u.essid.flags = 1;
- }
- else
- {
- /* '-' or '--' allow to escape the ESSID string, allowing
- * to set it to the string "any" or "off".
- * This is a big ugly, but it will do for now */
- if((!strcmp(args[i], "-")) || (!strcmp(args[i], "--")))
- {
- i++;
- if(i >= count)
- ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
- }
+ }
+ }
- /* Check the size of what the user passed us to avoid
- * buffer overflows */
- if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
- ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE);
- else
- {
- int temp;
+ if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
+ return(IWERR_SET_EXT);
- wrq.u.essid.flags = 1;
- strcpy(essid, args[i]); /* Size checked, all clear */
+ /* Var args */
+ return(i);
+}
- /* Check for ESSID index */
- if(((i+1) < count) &&
- (sscanf(args[i+1], "[%i]", &temp) == 1) &&
- (temp > 0) && (temp < IW_ENCODE_INDEX))
- {
- wrq.u.essid.flags = temp;
- ++i;
- }
- }
- }
+/*------------------------------------------------------------------*/
+/*
+ * Set Bit Rate
+ */
+static int
+set_bitrate_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
- /* Get version from kernel, device may not have range... */
- we_kernel_version = iw_get_kernel_we_version();
-
- /* Finally set the ESSID value */
- wrq.u.essid.pointer = (caddr_t) essid;
- wrq.u.essid.length = strlen(essid) + 1;
- if(we_kernel_version > 20)
- wrq.u.essid.length--;
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq,
- "Set ESSID");
- continue;
+ wrq.u.bitrate.flags = 0;
+ if(!strcasecmp(args[0], "auto"))
+ {
+ wrq.u.bitrate.value = -1;
+ wrq.u.bitrate.fixed = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old bitrate */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.bitrate.fixed = 1;
}
-
- /* ---------- Set AP address ---------- */
- if(!strcasecmp(args[i], "ap"))
+ else /* Should be a numeric value */
{
- if(++i >= count)
- ABORT_ARG_NUM("Set AP Address", SIOCSIWAP);
+ double brate;
+ char * unit;
- if((!strcasecmp(args[i], "auto")) ||
- (!strcasecmp(args[i], "any")))
+ brate = strtod(args[0], &unit);
+ if(unit == args[0])
{
- /* Send a broadcast address */
- iw_broad_ether(&(wrq.u.ap_addr));
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
- else
+ if(unit != NULL)
{
- if(!strcasecmp(args[i], "off"))
- {
- /* Send a NULL address */
- iw_null_ether(&(wrq.u.ap_addr));
- }
- else
- {
- /* Get the address and check if the interface supports it */
- if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
- ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]);
- }
+ if(unit[0] == 'G') brate *= GIGA;
+ if(unit[0] == 'M') brate *= MEGA;
+ if(unit[0] == 'k') brate *= KILO;
}
+ wrq.u.bitrate.value = (long) brate;
+ wrq.u.bitrate.fixed = 1;
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq,
- "Set AP Address");
- continue;
- }
-
- /* ---------- Set NickName ---------- */
- if(!strncmp(args[i], "nick", 4))
- {
- int we_kernel_version;
-
- i++;
- if(i >= count)
- ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN);
- if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
- ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE);
-
- we_kernel_version = iw_get_kernel_we_version();
-
- wrq.u.essid.pointer = (caddr_t) args[i];
- wrq.u.essid.length = strlen(args[i]) + 1;
- if(we_kernel_version > 20)
- wrq.u.essid.length--;
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq,
- "Set Nickname");
- continue;
- }
-
- /* ---------- Set Bit-Rate ---------- */
- if((!strncmp(args[i], "bit", 3)) ||
- (!strcmp(args[i], "rate")))
- {
- if(++i >= count)
- ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE);
- if(!strcasecmp(args[i], "auto"))
+ /* Check for an additional argument */
+ if((i < count) && (!strcasecmp(args[i], "auto")))
{
- wrq.u.bitrate.value = -1;
wrq.u.bitrate.fixed = 0;
+ ++i;
}
- else
+ if((i < count) && (!strcasecmp(args[i], "fixed")))
{
- if(!strcasecmp(args[i], "fixed"))
- {
- /* Get old bitrate */
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq,
- "Set Bit Rate");
- wrq.u.bitrate.fixed = 1;
- }
- else /* Should be a numeric value */
- {
- double brate;
-
- if(sscanf(args[i], "%lg", &(brate)) != 1)
- ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]);
- if(index(args[i], 'G')) brate *= GIGA;
- if(index(args[i], 'M')) brate *= MEGA;
- if(index(args[i], 'k')) brate *= KILO;
- wrq.u.bitrate.value = (long) brate;
- wrq.u.bitrate.fixed = 1;
-
- /* Check for an additional argument */
- if(((i+1) < count) &&
- (!strcasecmp(args[i+1], "auto")))
- {
- wrq.u.bitrate.fixed = 0;
- ++i;
- }
- if(((i+1) < count) &&
- (!strcasecmp(args[i+1], "fixed")))
- {
- wrq.u.bitrate.fixed = 1;
- ++i;
- }
- }
+ wrq.u.bitrate.fixed = 1;
+ ++i;
+ }
+ if((i < count) && (!strcasecmp(args[i], "unicast")))
+ {
+ wrq.u.bitrate.flags |= IW_BITRATE_UNICAST;
+ ++i;
+ }
+ if((i < count) && (!strcasecmp(args[i], "broadcast")))
+ {
+ wrq.u.bitrate.flags |= IW_BITRATE_BROADCAST;
+ ++i;
}
-
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq,
- "Set Bit Rate");
- continue;
}
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWRATE, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var args */
+ return(i);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set encryption
+ */
+static int
+set_enc_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
+ unsigned char key[IW_ENCODING_TOKEN_MAX];
- /* ---------- Set RTS threshold ---------- */
- if(!strncasecmp(args[i], "rts", 3))
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old encryption information */
+ wrq.u.data.pointer = (caddr_t) key;
+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
+ wrq.u.data.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
+ }
+ else
+ {
+ int gotone = 0;
+ int oldone;
+ int keylen;
+ int temp;
+
+ wrq.u.data.pointer = (caddr_t) NULL;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = 0;
+ i = 0;
+
+ /* Allow arguments in any order (it's safe) */
+ do
{
- i++;
- if(i >= count)
- ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS);
- wrq.u.rts.value = -1;
- wrq.u.rts.fixed = 1;
- wrq.u.rts.disabled = 0;
- if(!strcasecmp(args[i], "off"))
- wrq.u.rts.disabled = 1; /* i.e. max size */
- else
- if(!strcasecmp(args[i], "auto"))
- wrq.u.rts.fixed = 0;
- else
- {
- if(!strcasecmp(args[i], "fixed"))
- {
- /* Get old RTS threshold */
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq,
- "Set RTS Threshold");
- wrq.u.rts.fixed = 1;
- }
- else /* Should be a numeric value */
- if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.rts.value))
- != 1)
- ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]);
+ oldone = gotone;
+
+ /* -- Check for the key -- */
+ if(i < count)
+ {
+ keylen = iw_in_key_full(skfd, ifname,
+ args[i], key, &wrq.u.data.flags);
+ if(keylen > 0)
+ {
+ wrq.u.data.length = keylen;
+ wrq.u.data.pointer = (caddr_t) key;
+ ++i;
+ gotone++;
+ }
}
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq,
- "Set RTS Threshold");
- continue;
+ /* -- Check for token index -- */
+ if((i < count) &&
+ (sscanf(args[i], "[%i]", &temp) == 1) &&
+ (temp > 0) && (temp < IW_ENCODE_INDEX))
+ {
+ wrq.u.encoding.flags |= temp;
+ ++i;
+ gotone++;
+ }
+
+ /* -- Check the various flags -- */
+ if((i < count) && (!strcasecmp(args[i], "off")))
+ {
+ wrq.u.data.flags |= IW_ENCODE_DISABLED;
+ ++i;
+ gotone++;
+ }
+ if((i < count) && (!strcasecmp(args[i], "open")))
+ {
+ wrq.u.data.flags |= IW_ENCODE_OPEN;
+ ++i;
+ gotone++;
+ }
+ if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
+ {
+ wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
+ ++i;
+ gotone++;
+ }
+ if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
+ {
+ wrq.u.data.flags |= IW_ENCODE_TEMP;
+ ++i;
+ gotone++;
+ }
}
+ while(gotone != oldone);
+
+ /* Pointer is absent in new API */
+ if(wrq.u.data.pointer == NULL)
+ wrq.u.data.flags |= IW_ENCODE_NOKEY;
- /* ---------- Set fragmentation threshold ---------- */
- if(!strncmp(args[i], "frag", 4))
+ /* Check if we have any invalid argument */
+ if(!gotone)
{
- i++;
- if(i >= count)
- ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG);
- wrq.u.frag.value = -1;
- wrq.u.frag.fixed = 1;
- wrq.u.frag.disabled = 0;
- if(!strcasecmp(args[i], "off"))
- wrq.u.frag.disabled = 1; /* i.e. max size */
- else
- if(!strcasecmp(args[i], "auto"))
- wrq.u.frag.fixed = 0;
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var arg */
+ return(i);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Power Management
+ */
+static int
+set_power_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
+
+ if(!strcasecmp(args[0], "off"))
+ wrq.u.power.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old Power info */
+ wrq.u.power.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.power.disabled = 0;
+ }
+ else
+ {
+ double value;
+ char * unit;
+ int gotone = 0;
+
+ /* Parse modifiers */
+ i = parse_modifiers(args, count, &wrq.u.power.flags,
+ iwmod_power, IWMOD_POWER_NUM);
+ if(i < 0)
+ return(i);
+
+ wrq.u.power.disabled = 0;
+
+ /* Is there any value to grab ? */
+ value = strtod(args[0], &unit);
+ if(unit != args[0])
+ {
+ struct iw_range range;
+ int flags;
+ /* Extract range info to handle properly 'relative' */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ memset(&range, 0, sizeof(range));
+
+ /* Get the flags to be able to do the proper conversion */
+ switch(wrq.u.power.flags & IW_POWER_TYPE)
+ {
+ case IW_POWER_SAVING:
+ flags = range.pms_flags;
+ break;
+ case IW_POWER_TIMEOUT:
+ flags = range.pmt_flags;
+ break;
+ default:
+ flags = range.pmp_flags;
+ break;
+ }
+ /* Check if time or relative */
+ if(flags & IW_POWER_RELATIVE)
+ {
+ if(range.we_version_compiled < 21)
+ value *= MEGA;
+ else
+ wrq.u.power.flags |= IW_POWER_RELATIVE;
+ }
else
{
- if(!strcasecmp(args[i], "fixed"))
- {
- /* Get old fragmentation threshold */
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq,
- "Set Fragmentation Threshold");
- wrq.u.frag.fixed = 1;
- }
- else /* Should be a numeric value */
- if(sscanf(args[i], "%li",
- (unsigned long *) &(wrq.u.frag.value))
- != 1)
- ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG,
- args[i]);
- }
+ value *= MEGA; /* default = s */
+ if(unit[0] == 'u') value /= MEGA;
+ if(unit[0] == 'm') value /= KILO;
+ }
+ wrq.u.power.value = (long) value;
+ /* Set some default type if none */
+ if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
+ wrq.u.power.flags |= IW_POWER_PERIOD;
+ ++i;
+ gotone = 1;
+ }
+
+ /* Now, check the mode */
+ if(i < count)
+ {
+ if(!strcasecmp(args[i], "all"))
+ wrq.u.power.flags |= IW_POWER_ALL_R;
+ if(!strncasecmp(args[i], "unicast", 4))
+ wrq.u.power.flags |= IW_POWER_UNICAST_R;
+ if(!strncasecmp(args[i], "multicast", 5))
+ wrq.u.power.flags |= IW_POWER_MULTICAST_R;
+ if(!strncasecmp(args[i], "force", 5))
+ wrq.u.power.flags |= IW_POWER_FORCE_S;
+ if(!strcasecmp(args[i], "repeat"))
+ wrq.u.power.flags |= IW_POWER_REPEATER;
+ if(wrq.u.power.flags & IW_POWER_MODE)
+ {
+ ++i;
+ gotone = 1;
+ }
+ }
+ if(!gotone)
+ {
+ errarg = i;
+ return(IWERR_ARG_TYPE);
+ }
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWPOWER, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var args */
+ return(i);
+}
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq,
- "Set Fragmentation Threshold");
- continue;
- }
+#ifndef WE_ESSENTIAL
+/*------------------------------------------------------------------*/
+/*
+ * Set Nickname
+ */
+static int
+set_nick_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int we_kernel_version;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
- /* ---------- Set operation mode ---------- */
- if(!strcmp(args[i], "mode"))
+ if(strlen(args[0]) > IW_ESSID_MAX_SIZE)
+ {
+ errmax = IW_ESSID_MAX_SIZE;
+ return(IWERR_ARG_SIZE);
+ }
+
+ we_kernel_version = iw_get_kernel_we_version();
+
+ wrq.u.essid.pointer = (caddr_t) args[0];
+ wrq.u.essid.length = strlen(args[0]);
+ if(we_kernel_version < 21)
+ wrq.u.essid.length++;
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWNICKN, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 args */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set commit
+ */
+static int
+set_nwid_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ unsigned long temp;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ if((!strcasecmp(args[0], "off")) ||
+ (!strcasecmp(args[0], "any")))
+ wrq.u.nwid.disabled = 1;
+ else
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old nwid */
+ if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.nwid.disabled = 0;
+ }
+ else
+ if(sscanf(args[0], "%lX", &(temp)) != 1)
{
- int k;
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ else
+ {
+ wrq.u.nwid.value = temp;
+ wrq.u.nwid.disabled = 0;
+ }
- i++;
- if(i >= count)
- ABORT_ARG_NUM("Set Mode", SIOCSIWMODE);
+ wrq.u.nwid.fixed = 1;
- if(sscanf(args[i], "%i", &k) != 1)
+ /* Set new nwid */
+ if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 arg */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set AP Address
+ */
+static int
+set_apaddr_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ if((!strcasecmp(args[0], "auto")) ||
+ (!strcasecmp(args[0], "any")))
+ {
+ /* Send a broadcast address */
+ iw_broad_ether(&(wrq.u.ap_addr));
+ }
+ else
+ {
+ if(!strcasecmp(args[0], "off"))
+ {
+ /* Send a NULL address */
+ iw_null_ether(&(wrq.u.ap_addr));
+ }
+ else
+ {
+ /* Get the address and check if the interface supports it */
+ if(iw_in_addr(skfd, ifname, args[0], &(wrq.u.ap_addr)) < 0)
{
- k = 0;
- while((k < IW_NUM_OPER_MODE) &&
- strncasecmp(args[i], iw_operation_mode[k], 3))
- k++;
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
- if((k >= IW_NUM_OPER_MODE) || (k < 0))
- ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]);
-
- wrq.u.mode = k;
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq,
- "Set Mode");
- continue;
}
+ }
- /* ---------- Set Power Management ---------- */
- if(!strncmp(args[i], "power", 3))
- {
- if(++i >= count)
- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+ if(iw_set_ext(skfd, ifname, SIOCSIWAP, &wrq) < 0)
+ return(IWERR_SET_EXT);
- if(!strcasecmp(args[i], "off"))
- wrq.u.power.disabled = 1; /* i.e. max size */
- else
- if(!strcasecmp(args[i], "on"))
+ /* 1 args */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Tx Power
+ */
+static int
+set_txpower_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Prepare the request */
+ wrq.u.txpower.value = -1;
+ wrq.u.txpower.fixed = 1;
+ wrq.u.txpower.disabled = 0;
+ wrq.u.txpower.flags = IW_TXPOW_DBM;
+
+ if(!strcasecmp(args[0], "off"))
+ wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
+ else
+ if(!strcasecmp(args[0], "auto"))
+ wrq.u.txpower.fixed = 0; /* i.e. use power control */
+ else
+ {
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old tx-power */
+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.txpower.disabled = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
{
- /* Get old Power info */
- wrq.u.power.flags = 0;
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq,
- "Set Power Management");
- wrq.u.power.disabled = 0;
+ /* Get old tx-power */
+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.txpower.fixed = 1;
+ wrq.u.txpower.disabled = 0;
}
- else
+ else /* Should be a numeric value */
{
- double temp;
- int gotone = 0;
- /* Default - nope */
- wrq.u.power.flags = IW_POWER_ON;
- wrq.u.power.disabled = 0;
-
- /* Check value modifier */
- if(!strcasecmp(args[i], "min"))
+ int power;
+ int ismwatt = 0;
+ struct iw_range range;
+
+ /* Extract range info to do proper conversion */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ memset(&range, 0, sizeof(range));
+
+ /* Get the value */
+ if(sscanf(args[0], "%i", &(power)) != 1)
{
- wrq.u.power.flags |= IW_POWER_MIN;
- if(++i >= count)
- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
- else
- if(!strcasecmp(args[i], "max"))
- {
- wrq.u.power.flags |= IW_POWER_MAX;
- if(++i >= count)
- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
- }
- /* Check value type */
- if(!strcasecmp(args[i], "period"))
+ /* Check if milliWatt
+ * We authorise a single 'm' as a shorthand for 'mW',
+ * on the other hand a 'd' probably means 'dBm'... */
+ ismwatt = ((strchr(args[0], 'm') != NULL)
+ && (strchr(args[0], 'd') == NULL));
+
+ /* We could check 'W' alone... Another time... */
+
+ /* Convert */
+ if(range.txpower_capa & IW_TXPOW_RELATIVE)
{
- wrq.u.power.flags |= IW_POWER_PERIOD;
- if(++i >= count)
- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+ /* Can't convert */
+ if(ismwatt)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ wrq.u.txpower.flags = IW_TXPOW_RELATIVE;
}
else
- if(!strcasecmp(args[i], "timeout"))
+ if(range.txpower_capa & IW_TXPOW_MWATT)
+ {
+ if(!ismwatt)
+ power = iw_dbm2mwatt(power);
+ wrq.u.txpower.flags = IW_TXPOW_MWATT;
+ }
+ else
{
- wrq.u.power.flags |= IW_POWER_TIMEOUT;
- if(++i >= count)
- ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+ if(ismwatt)
+ power = iw_mwatt2dbm(power);
+ wrq.u.txpower.flags = IW_TXPOW_DBM;
}
+ wrq.u.txpower.value = power;
- /* Is there any value to grab ? */
- if(sscanf(args[i], "%lg", &(temp)) == 1)
+ /* Check for an additional argument */
+ if((i < count) && (!strcasecmp(args[i], "auto")))
{
- temp *= MEGA; /* default = s */
- if(index(args[i], 'u')) temp /= MEGA;
- if(index(args[i], 'm')) temp /= KILO;
- wrq.u.power.value = (long) temp;
- if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
- wrq.u.power.flags |= IW_POWER_PERIOD;
+ wrq.u.txpower.fixed = 0;
++i;
- gotone = 1;
}
-
- /* Now, check the mode */
- if(i < count)
+ if((i < count) && (!strcasecmp(args[i], "fixed")))
{
- if(!strcasecmp(args[i], "all"))
- wrq.u.power.flags |= IW_POWER_ALL_R;
- if(!strncasecmp(args[i], "unicast", 4))
- wrq.u.power.flags |= IW_POWER_UNICAST_R;
- if(!strncasecmp(args[i], "multicast", 5))
- wrq.u.power.flags |= IW_POWER_MULTICAST_R;
- if(!strncasecmp(args[i], "force", 5))
- wrq.u.power.flags |= IW_POWER_FORCE_S;
- if(!strcasecmp(args[i], "repeat"))
- wrq.u.power.flags |= IW_POWER_REPEATER;
- if(wrq.u.power.flags & IW_POWER_MODE)
- {
- ++i;
- gotone = 1;
- }
+ wrq.u.txpower.fixed = 1;
+ ++i;
}
- if(!gotone)
- ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER,
- args[i]);
- --i;
}
+ }
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWTXPOW, &wrq) < 0)
+ return(IWERR_SET_EXT);
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq,
- "Set Power Management");
- continue;
- }
+ /* Var args */
+ return(i);
+}
- /* ---------- Set Transmit-Power ---------- */
- if(!strncmp(args[i], "txpower", 3))
+/*------------------------------------------------------------------*/
+/*
+ * Set Sensitivity
+ */
+static int
+set_sens_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int temp;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ if(sscanf(args[0], "%i", &(temp)) != 1)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ wrq.u.sens.value = temp;
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWSENS, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 arg */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Retry Limit
+ */
+static int
+set_retry_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 0;
+ double value;
+ char * unit;
+
+ /* Parse modifiers */
+ i = parse_modifiers(args, count, &wrq.u.retry.flags,
+ iwmod_retry, IWMOD_RETRY_NUM);
+ if(i < 0)
+ return(i);
+
+ /* Add default type if none */
+ if((wrq.u.retry.flags & IW_RETRY_TYPE) == 0)
+ wrq.u.retry.flags |= IW_RETRY_LIMIT;
+
+ wrq.u.retry.disabled = 0;
+
+ /* Is there any value to grab ? */
+ value = strtod(args[0], &unit);
+ if(unit == args[0])
+ {
+ errarg = i;
+ return(IWERR_ARG_TYPE);
+ }
+
+ /* Limit is absolute, on the other hand lifetime is seconds */
+ if(wrq.u.retry.flags & IW_RETRY_LIFETIME)
+ {
+ struct iw_range range;
+ /* Extract range info to handle properly 'relative' */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ memset(&range, 0, sizeof(range));
+
+ if(range.r_time_flags & IW_RETRY_RELATIVE)
{
- struct iw_range range;
-
- if(++i >= count)
- ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW);
-
- /* Extract range info */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- memset(&range, 0, sizeof(range));
-
- /* Prepare the request */
- wrq.u.txpower.value = -1;
- wrq.u.txpower.fixed = 1;
- wrq.u.txpower.disabled = 0;
- wrq.u.txpower.flags = IW_TXPOW_DBM;
- if(!strcasecmp(args[i], "off"))
- wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
+ if(range.we_version_compiled < 21)
+ value *= MEGA;
else
- if(!strcasecmp(args[i], "auto"))
- wrq.u.txpower.fixed = 0; /* i.e. use power control */
- else
- {
- if(!strcasecmp(args[i], "on"))
- {
- /* Get old tx-power */
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
- "Set Tx Power");
- wrq.u.txpower.disabled = 0;
- }
- else
- {
- if(!strcasecmp(args[i], "fixed"))
- {
- /* Get old tx-power */
- IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
- "Set Tx Power");
- wrq.u.txpower.fixed = 1;
- wrq.u.txpower.disabled = 0;
- }
- else /* Should be a numeric value */
- {
- int power;
- int ismwatt = 0;
-
- /* Get the value */
- if(sscanf(args[i], "%i", &(power)) != 1)
- ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW,
- args[i]);
-
- /* Check if milliWatt
- * We authorise a single 'm' as a shorthand for 'mW',
- * on the other hand a 'd' probably means 'dBm'... */
- ismwatt = ((index(args[i], 'm') != NULL)
- && (index(args[i], 'd') == NULL));
-
- /* We could check 'W' alone... Another time... */
-
- /* Convert */
- if(range.txpower_capa & IW_TXPOW_RELATIVE)
- {
- /* Can't convert */
- if(ismwatt)
- ABORT_ARG_TYPE("Set Tx Power",
- SIOCSIWTXPOW,
- args[i]);
- }
- else
- if(range.txpower_capa & IW_TXPOW_MWATT)
- {
- if(!ismwatt)
- power = iw_dbm2mwatt(power);
- wrq.u.txpower.flags = IW_TXPOW_MWATT;
- }
- else
- {
- if(ismwatt)
- power = iw_mwatt2dbm(power);
- wrq.u.txpower.flags = IW_TXPOW_DBM;
- }
- wrq.u.txpower.value = power;
-
- /* Check for an additional argument */
- if(((i+1) < count) &&
- (!strcasecmp(args[i+1], "auto")))
- {
- wrq.u.txpower.fixed = 0;
- ++i;
- }
- if(((i+1) < count) &&
- (!strcasecmp(args[i+1], "fixed")))
- {
- wrq.u.txpower.fixed = 1;
- ++i;
- }
- }
- }
- }
-
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq,
- "Set Tx Power");
- continue;
+ wrq.u.retry.flags |= IW_RETRY_RELATIVE;
}
-
- /* ---------- Set Retry limit ---------- */
- if(!strncmp(args[i], "retry", 3))
+ else
{
- double temp;
- int gotone = 0;
+ /* Normalise lifetime */
+ value *= MEGA; /* default = s */
+ if(unit[0] == 'u') value /= MEGA;
+ if(unit[0] == 'm') value /= KILO;
+ }
+ }
+ wrq.u.retry.value = (long) value;
+ ++i;
- if(++i >= count)
- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
+ if(iw_set_ext(skfd, ifname, SIOCSIWRETRY, &wrq) < 0)
+ return(IWERR_SET_EXT);
- /* Default - nope */
- wrq.u.retry.flags = IW_RETRY_LIMIT;
- wrq.u.retry.disabled = 0;
+ /* Var args */
+ return(i);
+}
- /* Check value modifier */
- if(!strcasecmp(args[i], "min"))
- {
- wrq.u.retry.flags |= IW_RETRY_MIN;
- if(++i >= count)
- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
- }
- else
- if(!strcasecmp(args[i], "max"))
+/*------------------------------------------------------------------*/
+/*
+ * Set RTS Threshold
+ */
+static int
+set_rts_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ wrq.u.rts.value = -1;
+ wrq.u.rts.fixed = 1;
+ wrq.u.rts.disabled = 0;
+
+ if(!strcasecmp(args[0], "off"))
+ wrq.u.rts.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[0], "auto"))
+ wrq.u.rts.fixed = 0;
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old RTS threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.rts.fixed = 1;
+ }
+ else
+ { /* Should be a numeric value */
+ long temp;
+ if(sscanf(args[0], "%li", (unsigned long *) &(temp)) != 1)
{
- wrq.u.retry.flags |= IW_RETRY_MAX;
- if(++i >= count)
- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
+ wrq.u.rts.value = temp;
+ }
+ }
- /* Check value type */
- if(!strcasecmp(args[i], "limit"))
- {
- wrq.u.retry.flags |= IW_RETRY_LIMIT;
- if(++i >= count)
- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
- }
- else
- if(!strncasecmp(args[i], "lifetime", 4))
+ if(iw_set_ext(skfd, ifname, SIOCSIWRTS, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 arg */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Fragmentation Threshold
+ */
+static int
+set_frag_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ wrq.u.frag.value = -1;
+ wrq.u.frag.fixed = 1;
+ wrq.u.frag.disabled = 0;
+
+ if(!strcasecmp(args[0], "off"))
+ wrq.u.frag.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[0], "auto"))
+ wrq.u.frag.fixed = 0;
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old fragmentation threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.frag.fixed = 1;
+ }
+ else
+ { /* Should be a numeric value */
+ long temp;
+ if(sscanf(args[0], "%li", &(temp))
+ != 1)
{
- wrq.u.retry.flags &= ~IW_RETRY_LIMIT;
- wrq.u.retry.flags |= IW_RETRY_LIFETIME;
- if(++i >= count)
- ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
+ wrq.u.frag.value = temp;
+ }
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWFRAG, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 arg */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Modulation
+ */
+static int
+set_modulation_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ if(!strcasecmp(args[0], "auto"))
+ wrq.u.param.fixed = 0; /* i.e. use any modulation */
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old modulation */
+ if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.param.fixed = 1;
+ }
+ else
+ {
+ int k;
- /* Is there any value to grab ? */
- if(sscanf(args[i], "%lg", &(temp)) == 1)
+ /* Allow multiple modulations, combine them together */
+ wrq.u.param.value = 0x0;
+ i = 0;
+ do
{
- /* Limit is absolute, on the other hand lifetime is seconds */
- if(!(wrq.u.retry.flags & IW_RETRY_LIMIT))
+ for(k = 0; k < IW_SIZE_MODUL_LIST; k++)
{
- /* Normalise lifetime */
- temp *= MEGA; /* default = s */
- if(index(args[i], 'u')) temp /= MEGA;
- if(index(args[i], 'm')) temp /= KILO;
+ if(!strcasecmp(args[i], iw_modul_list[k].cmd))
+ {
+ wrq.u.param.value |= iw_modul_list[k].mask;
+ ++i;
+ break;
+ }
}
- wrq.u.retry.value = (long) temp;
+ }
+ /* For as long as current arg matched and not out of args */
+ while((i < count) && (k < IW_SIZE_MODUL_LIST));
+
+ /* Check we got something */
+ if(i == 0)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+
+ /* Check for an additional argument */
+ if((i < count) && (!strcasecmp(args[i], "auto")))
+ {
+ wrq.u.param.fixed = 0;
+ ++i;
+ }
+ if((i < count) && (!strcasecmp(args[i], "fixed")))
+ {
+ wrq.u.param.fixed = 1;
++i;
- gotone = 1;
}
+ }
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWMODUL, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var args */
+ return(i);
+}
+#endif /* WE_ESSENTIAL */
+
+/*------------------------------------------------------------------*/
+/*
+ * Set commit
+ */
+static int
+set_commit_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWCOMMIT, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* No args */
+ return(0);
+}
- if(!gotone)
- ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]);
- --i;
+/************************** SET DISPATCHER **************************/
+/*
+ * This is a modified version of the dispatcher in iwlist.
+ * The main difference is that here we may have multiple commands per
+ * line. Also, most commands here do take arguments, and most often
+ * a variable number of them.
+ * Therefore, the handler *must* return how many args were consumed...
+ *
+ * Note that the use of multiple commands per line is not advised
+ * in scripts, as it makes error management hard. All commands before
+ * the error are executed, but commands after the error are not
+ * processed.
+ * We also try to give as much clue as possible via stderr to the caller
+ * on which command did fail, but if there are two time the same command,
+ * you don't know which one failed...
+ */
- IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq,
- "Set Retry Limit");
- continue;
+/*------------------------------------------------------------------*/
+/*
+ * Map command line arguments to the proper procedure...
+ */
+typedef struct iwconfig_entry {
+ const char * cmd; /* Command line shorthand */
+ iw_enum_handler fn; /* Subroutine */
+ int min_count;
+ int request; /* WE numerical ID */
+ const char * name; /* Human readable string */
+ const char * argsname; /* Args as human readable string */
+} iwconfig_cmd;
+
+static const struct iwconfig_entry iwconfig_cmds[] = {
+ { "essid", set_essid_info, 1, SIOCSIWESSID,
+ "Set ESSID", "{NNN|any|on|off}" },
+ { "mode", set_mode_info, 1, SIOCSIWMODE,
+ "Set Mode", "{managed|ad-hoc|master|...}" },
+ { "freq", set_freq_info, 1, SIOCSIWFREQ,
+ "Set Frequency", "N.NNN[k|M|G]" },
+ { "channel", set_freq_info, 1, SIOCSIWFREQ,
+ "Set Frequency", "N" },
+ { "bit", set_bitrate_info, 1, SIOCSIWRATE,
+ "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
+ { "rate", set_bitrate_info, 1, SIOCSIWRATE,
+ "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
+ { "enc", set_enc_info, 1, SIOCSIWENCODE,
+ "Set Encode", "{NNNN-NNNN|off}" },
+ { "key", set_enc_info, 1, SIOCSIWENCODE,
+ "Set Encode", "{NNNN-NNNN|off}" },
+ { "power", set_power_info, 1, SIOCSIWPOWER,
+ "Set Power Management", "{period N|timeout N|saving N|off}" },
+#ifndef WE_ESSENTIAL
+ { "nickname", set_nick_info, 1, SIOCSIWNICKN,
+ "Set Nickname", "NNN" },
+ { "nwid", set_nwid_info, 1, SIOCSIWNWID,
+ "Set NWID", "{NN|on|off}" },
+ { "ap", set_apaddr_info, 1, SIOCSIWAP,
+ "Set AP Address", "{N|off|auto}" },
+ { "txpower", set_txpower_info, 1, SIOCSIWTXPOW,
+ "Set Tx Power", "{NmW|NdBm|off|auto}" },
+ { "sens", set_sens_info, 1, SIOCSIWSENS,
+ "Set Sensitivity", "N" },
+ { "retry", set_retry_info, 1, SIOCSIWRETRY,
+ "Set Retry Limit", "{limit N|lifetime N}" },
+ { "rts", set_rts_info, 1, SIOCSIWRTS,
+ "Set RTS Threshold", "{N|auto|fixed|off}" },
+ { "frag", set_frag_info, 1, SIOCSIWFRAG,
+ "Set Fragmentation Threshold", "{N|auto|fixed|off}" },
+ { "modulation", set_modulation_info, 1, SIOCGIWMODUL,
+ "Set Modulation", "{11g|11a|CCK|OFDMg|...}" },
+#endif /* WE_ESSENTIAL */
+ { "commit", set_commit_info, 0, SIOCSIWCOMMIT,
+ "Commit changes", "" },
+ { NULL, NULL, 0, 0, NULL, NULL },
+};
+
+/*------------------------------------------------------------------*/
+/*
+ * Find the most appropriate command matching the command line
+ */
+static inline const iwconfig_cmd *
+find_command(const char * cmd)
+{
+ const iwconfig_cmd * found = NULL;
+ int ambig = 0;
+ unsigned int len = strlen(cmd);
+ int i;
+
+ /* Go through all commands */
+ for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
+ {
+ /* No match -> next one */
+ if(strncasecmp(iwconfig_cmds[i].cmd, cmd, len) != 0)
+ continue;
+
+ /* Exact match -> perfect */
+ if(len == strlen(iwconfig_cmds[i].cmd))
+ return &iwconfig_cmds[i];
+
+ /* Partial match */
+ if(found == NULL)
+ /* First time */
+ found = &iwconfig_cmds[i];
+ else
+ /* Another time */
+ if (iwconfig_cmds[i].fn != found->fn)
+ ambig = 1;
+ }
+
+ if(found == NULL)
+ {
+ fprintf(stderr, "iwconfig: unknown command \"%s\"\n", cmd);
+ return NULL;
+ }
+
+ if(ambig)
+ {
+ fprintf(stderr, "iwconfig: command \"%s\" is ambiguous\n", cmd);
+ return NULL;
+ }
+
+ return found;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set the wireless options requested on command line
+ * Find the individual commands and call the appropriate subroutine
+ */
+static int
+set_info(int skfd, /* The socket */
+ char * args[], /* Command line args */
+ int count, /* Args count */
+ char * ifname) /* Dev name */
+{
+ const iwconfig_cmd * iwcmd;
+ int ret;
+
+ /* Loop until we run out of args... */
+ while(count > 0)
+ {
+ /* find the command matching the keyword */
+ iwcmd = find_command(args[0]);
+ if(iwcmd == NULL)
+ {
+ /* Here we have an unrecognised arg... Error already printed out. */
+ return(-1);
}
- /* ---------- Other ---------- */
- /* Here we have an unrecognised arg... */
- fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
- args[i]);
- return(-1);
- } /* for(index ... */
+ /* One arg is consumed (the command name) */
+ args++;
+ count--;
+
+ /* Check arg numbers */
+ if(count < iwcmd->min_count)
+ ret = IWERR_ARG_NUM;
+ else
+ ret = 0;
+
+ /* Call the command */
+ if(!ret)
+ ret = (*iwcmd->fn)(skfd, ifname, args, count);
+
+ /* Deal with various errors */
+ if(ret < 0)
+ {
+ int request = iwcmd->request;
+ if(ret == IWERR_GET_EXT)
+ request++; /* Transform the SET into GET */
+
+ fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n",
+ iwcmd->name, request);
+ switch(ret)
+ {
+ case IWERR_ARG_NUM:
+ fprintf(stderr, " too few arguments.\n");
+ break;
+ case IWERR_ARG_TYPE:
+ if(errarg < 0)
+ errarg = 0;
+ if(errarg >= count)
+ errarg = count - 1;
+ fprintf(stderr, " invalid argument \"%s\".\n", args[errarg]);
+ break;
+ case IWERR_ARG_SIZE:
+ fprintf(stderr, " argument too big (max %d)\n", errmax);
+ break;
+ case IWERR_ARG_CONFLICT:
+ if(errarg < 0)
+ errarg = 0;
+ if(errarg >= count)
+ errarg = count - 1;
+ fprintf(stderr, " conflicting argument \"%s\".\n", args[errarg]);
+ break;
+ case IWERR_SET_EXT:
+ fprintf(stderr, " SET failed on device %-1.16s ; %s.\n",
+ ifname, strerror(errno));
+ break;
+ case IWERR_GET_EXT:
+ fprintf(stderr, " GET failed on device %-1.16s ; %s.\n",
+ ifname, strerror(errno));
+ break;
+ }
+ /* Stop processing, we don't know if we are in a consistent state
+ * in reading the command line */
+ return(ret);
+ }
+
+ /* Substract consumed args from command line */
+ args += ret;
+ count -= ret;
+
+ /* Loop back */
+ }
+
+ /* Done, all done */
return(0);
}
+/*------------------------------------------------------------------*/
+/*
+ * Display help
+ */
+static inline void
+iw_usage(void)
+{
+ int i;
+
+ fprintf(stderr, "Usage: iwconfig [interface]\n");
+ for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
+ fprintf(stderr, " interface %s %s\n",
+ iwconfig_cmds[i].cmd, iwconfig_cmds[i].argsname);
+ fprintf(stderr, " Check man pages for more details.\n");
+}
+
+
/******************************* MAIN ********************************/
/*------------------------------------------------------------------*/
/*
* Wireless Tools
*
- * Jean II - HPLB 97->99 - HPL 99->04
+ * Jean II - HPLB 97->99 - HPL 99->07
*
* Common subroutines to all the wireless tools...
*
* This file is released under the GPL license.
- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
*/
/***************************** INCLUDES *****************************/
"Master",
"Repeater",
"Secondary",
- "Monitor" };
+ "Monitor",
+ "Unknown/bug" };
+
+/* Modulations as human readable strings */
+const struct iw_modul_descr iw_modul_list[] = {
+ /* Start with aggregate types, so that they display first */
+ { IW_MODUL_11AG, "11ag",
+ "IEEE 802.11a + 802.11g (2.4 & 5 GHz, up to 54 Mb/s)" },
+ { IW_MODUL_11AB, "11ab",
+ "IEEE 802.11a + 802.11b (2.4 & 5 GHz, up to 54 Mb/s)" },
+ { IW_MODUL_11G, "11g", "IEEE 802.11g (2.4 GHz, up to 54 Mb/s)" },
+ { IW_MODUL_11A, "11a", "IEEE 802.11a (5 GHz, up to 54 Mb/s)" },
+ { IW_MODUL_11B, "11b", "IEEE 802.11b (2.4 GHz, up to 11 Mb/s)" },
+
+ /* Proprietary aggregates */
+ { IW_MODUL_TURBO | IW_MODUL_11A, "turboa",
+ "Atheros turbo mode at 5 GHz (up to 108 Mb/s)" },
+ { IW_MODUL_TURBO | IW_MODUL_11G, "turbog",
+ "Atheros turbo mode at 2.4 GHz (up to 108 Mb/s)" },
+ { IW_MODUL_PBCC | IW_MODUL_11B, "11+",
+ "TI 802.11+ (2.4 GHz, up to 22 Mb/s)" },
+
+ /* Individual modulations */
+ { IW_MODUL_OFDM_G, "OFDMg",
+ "802.11g higher rates, OFDM at 2.4 GHz (up to 54 Mb/s)" },
+ { IW_MODUL_OFDM_A, "OFDMa", "802.11a, OFDM at 5 GHz (up to 54 Mb/s)" },
+ { IW_MODUL_CCK, "CCK", "802.11b higher rates (2.4 GHz, up to 11 Mb/s)" },
+ { IW_MODUL_DS, "DS", "802.11 Direct Sequence (2.4 GHz, up to 2 Mb/s)" },
+ { IW_MODUL_FH, "FH", "802.11 Frequency Hopping (2,4 GHz, up to 2 Mb/s)" },
+
+ /* Proprietary modulations */
+ { IW_MODUL_TURBO, "turbo",
+ "Atheros turbo mode, channel bonding (up to 108 Mb/s)" },
+ { IW_MODUL_PBCC, "PBCC",
+ "TI 802.11+ higher rates (2.4 GHz, up to 22 Mb/s)" },
+ { IW_MODUL_CUSTOM, "custom",
+ "Driver specific modulation (check driver documentation)" },
+};
/* Disable runtime version warning in iw_get_range_info() */
int iw_ignore_version = 0;
if(toolname != NULL)
printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION);
printf(" Compatible with Wireless Extension v11 to v%d.\n\n",
- WE_VERSION);
+ WE_MAX_VERSION);
/* Get version from kernel */
we_kernel_version = iw_get_kernel_we_version();
if(range->we_version_compiled > WE_MAX_VERSION)
{
fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled);
- fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_VERSION);
+ fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_MAX_VERSION);
fprintf(stderr, "Some things may be broken...\n\n");
}
/* Get operation mode */
if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
{
- info->mode = wrq.u.mode;
- if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
- info->has_mode = 1;
+ info->has_mode = 1;
+ /* Note : event->u.mode is unsigned, no need to check <= 0 */
+ if(wrq.u.mode < IW_NUM_OPER_MODE)
+ info->mode = wrq.u.mode;
+ else
+ info->mode = IW_NUM_OPER_MODE; /* Unknown/bug */
}
return(0);
we_kernel_version = iw_get_kernel_we_version();
wrq.u.essid.pointer = (caddr_t) info->essid;
- wrq.u.essid.length = strlen(info->essid) + 1;
+ wrq.u.essid.length = strlen(info->essid);
wrq.u.data.flags = info->essid_on;
- if(we_kernel_version > 20)
- wrq.u.essid.length--;
+ if(we_kernel_version < 21)
+ wrq.u.essid.length++;
if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
{
* Further, on 8 bits, 0x100 == 256 == 0.
*
* Relative/percent values are always encoded unsigned, between 0 and 255.
- * Absolute/dBm values are always encoded negative, between -255 and 0.
+ * Absolute/dBm values are always encoded between -192 and 63.
+ * (Note that up to version 28 of Wireless Tools, dBm used to be
+ * encoded always negative, between -256 and -1).
*
* How do we separate relative from absolute values ?
* The old way is to use the range to do that. As of WE-19, we have
* range struct only specify one bound of the value, we assume that
* the other bound is 0 (zero).
* For relative values, range is [0 ; range->max].
- * For absolute values, range is [range->max ; 0].
+ * For absolute values, range is [range->max ; 63].
*
* Let's take two example :
* 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100
* The old way to detect dBm require both the range and a non-null
* level (which confuse the test). The new way can deal with level of 0
* because it does an explicit test on the flag. */
- if(has_range && ((qual->level != 0) || (qual->updated & IW_QUAL_DBM)))
+ if(has_range && ((qual->level != 0)
+ || (qual->updated & (IW_QUAL_DBM | IW_QUAL_RCPI))))
{
/* Deal with quality : always a relative value */
if(!(qual->updated & IW_QUAL_QUAL_INVALID))
buflen -= len;
}
- /* Check if the statistics are in dBm or relative */
- if((qual->updated & IW_QUAL_DBM)
- || (qual->level > range->max_qual.level))
+ /* Check if the statistics are in RCPI (IEEE 802.11k) */
+ if(qual->updated & IW_QUAL_RCPI)
{
- /* Deal with signal level in dBm (absolute power measurement) */
+ /* Deal with signal level in RCPI */
+ /* RCPI = int{(Power in dBm +110)*2} for 0dbm > Power > -110dBm */
if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
{
- len = snprintf(buffer, buflen, "Signal level%c%d dBm ",
+ double rcpilevel = (qual->level / 2.0) - 110.0;
+ len = snprintf(buffer, buflen, "Signal level%c%g dBm ",
qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
- qual->level - 0x100);
+ rcpilevel);
buffer += len;
buflen -= len;
}
/* Deal with noise level in dBm (absolute power measurement) */
if(!(qual->updated & IW_QUAL_NOISE_INVALID))
{
- len = snprintf(buffer, buflen, "Noise level%c%d dBm",
+ double rcpinoise = (qual->noise / 2.0) - 110.0;
+ len = snprintf(buffer, buflen, "Noise level%c%g dBm",
qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
- qual->noise - 0x100);
+ rcpinoise);
}
}
else
{
- /* Deal with signal level as relative value (0 -> max) */
- if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
+ /* Check if the statistics are in dBm */
+ if((qual->updated & IW_QUAL_DBM)
+ || (qual->level > range->max_qual.level))
{
- len = snprintf(buffer, buflen, "Signal level%c%d/%d ",
- qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
- qual->level, range->max_qual.level);
- buffer += len;
- buflen -= len;
- }
+ /* Deal with signal level in dBm (absolute power measurement) */
+ if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
+ {
+ int dblevel = qual->level;
+ /* Implement a range for dBm [-192; 63] */
+ if(qual->level >= 64)
+ dblevel -= 0x100;
+ len = snprintf(buffer, buflen, "Signal level%c%d dBm ",
+ qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
+ dblevel);
+ buffer += len;
+ buflen -= len;
+ }
- /* Deal with noise level as relative value (0 -> max) */
- if(!(qual->updated & IW_QUAL_NOISE_INVALID))
+ /* Deal with noise level in dBm (absolute power measurement) */
+ if(!(qual->updated & IW_QUAL_NOISE_INVALID))
+ {
+ int dbnoise = qual->noise;
+ /* Implement a range for dBm [-192; 63] */
+ if(qual->noise >= 64)
+ dbnoise -= 0x100;
+ len = snprintf(buffer, buflen, "Noise level%c%d dBm",
+ qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
+ dbnoise);
+ }
+ }
+ else
{
- len = snprintf(buffer, buflen, "Noise level%c%d/%d",
- qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
- qual->noise, range->max_qual.noise);
+ /* Deal with signal level as relative value (0 -> max) */
+ if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
+ {
+ len = snprintf(buffer, buflen, "Signal level%c%d/%d ",
+ qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
+ qual->level, range->max_qual.level);
+ buffer += len;
+ buflen -= len;
+ }
+
+ /* Deal with noise level as relative value (0 -> max) */
+ if(!(qual->updated & IW_QUAL_NOISE_INVALID))
+ {
+ len = snprintf(buffer, buflen, "Noise level%c%d/%d",
+ qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
+ qual->noise, range->max_qual.noise);
+ }
}
}
}
iw_print_pm_value(char * buffer,
int buflen,
int value,
- int flags)
+ int flags,
+ int we_version)
{
/* Check size */
if(buflen < 25)
}
else
{
- strcpy(buffer, " period:"); /* Size checked */
- buffer += 8;
+ if(flags & IW_POWER_SAVING)
+ {
+ strcpy(buffer, " saving:"); /* Size checked */
+ buffer += 8;
+ }
+ else
+ {
+ strcpy(buffer, " period:"); /* Size checked */
+ buffer += 8;
+ }
}
/* Display value without units */
if(flags & IW_POWER_RELATIVE)
- snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
+ {
+ if(we_version < 21)
+ value /= MEGA;
+ snprintf(buffer, buflen, "%d", value);
+ }
else
{
/* Display value with units */
iw_print_retry_value(char * buffer,
int buflen,
int value,
- int flags)
+ int flags,
+ int we_version)
{
/* Check buffer size */
- if(buflen < 18)
+ if(buflen < 20)
{
snprintf(buffer, buflen, "<too big>");
return;
}
- buflen -= 18;
+ buflen -= 20;
/* Modifiers */
if(flags & IW_RETRY_MIN)
strcpy(buffer, " max"); /* Size checked */
buffer += 4;
}
+ if(flags & IW_RETRY_SHORT)
+ {
+ strcpy(buffer, " short"); /* Size checked */
+ buffer += 6;
+ }
+ if(flags & IW_RETRY_LONG)
+ {
+ strcpy(buffer, " long"); /* Size checked */
+ buffer += 6;
+ }
/* Type lifetime of limit */
if(flags & IW_RETRY_LIFETIME)
buffer += 10;
/* Display value without units */
- if(flags & IW_POWER_RELATIVE)
- snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
+ if(flags & IW_RETRY_RELATIVE)
+ {
+ if(we_version < 21)
+ value /= MEGA;
+ snprintf(buffer, buflen, "%d", value);
+ }
else
{
/* Display value with units */
struct sockaddr *sap)
{
/* Check if it is a hardware or IP address */
- if(index(bufp, ':') == NULL)
+ if(strchr(bufp, ':') == NULL)
{
struct sockaddr if_address;
struct arpreq arp_query;
[SIOCGIWPOWER - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
+ [SIOCSIWMODUL - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWMODUL - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
[SIOCSIWGENIE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
/* Size (in bytes) of various events */
static const int event_type_size[] = {
- IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */
+ IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */
0,
- IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
+ IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */
0,
- IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */
- IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */
- IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */
+ IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */
+ IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */
+ IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */
0,
- IW_EV_POINT_LEN, /* Without variable payload */
- IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */
- IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
+ IW_EV_POINT_PK_LEN, /* Without variable payload */
+ IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */
+ IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */
};
/*------------------------------------------------------------------*/
/* Don't "optimise" the following variable, it will crash */
unsigned cmd_index; /* *MUST* be unsigned */
- /* Unused for now. Will be later on... */
- we_version = we_version;
-
/* Check for end of stream */
- if((stream->current + IW_EV_LCP_LEN) > stream->end)
+ if((stream->current + IW_EV_LCP_PK_LEN) > stream->end)
return(0);
-#if DEBUG
+#ifdef DEBUG
printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n",
stream->current, stream->value, stream->end);
#endif
/* Extract the event header (to get the event id).
* Note : the event may be unaligned, therefore copy... */
- memcpy((char *) iwe, stream->current, IW_EV_LCP_LEN);
+ memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN);
-#if DEBUG
+#ifdef DEBUG
printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n",
iwe->cmd, iwe->len);
#endif
/* Check invalid events */
- if(iwe->len <= IW_EV_LCP_LEN)
+ if(iwe->len <= IW_EV_LCP_PK_LEN)
return(-1);
/* Get the type and length of that event */
}
if(descr != NULL)
event_type = descr->header_type;
- /* Unknown events -> event_type=0 => IW_EV_LCP_LEN */
+ /* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */
event_len = event_type_size[event_type];
/* Fixup for earlier version of WE */
if((we_version <= 18) && (event_type == IW_HEADER_TYPE_POINT))
event_len += IW_EV_POINT_OFF;
/* Check if we know about this event */
- if(event_len <= IW_EV_LCP_LEN)
+ if(event_len <= IW_EV_LCP_PK_LEN)
{
/* Skip to next event */
stream->current += iwe->len;
return(2);
}
- event_len -= IW_EV_LCP_LEN;
+ event_len -= IW_EV_LCP_PK_LEN;
/* Set pointer on data */
if(stream->value != NULL)
pointer = stream->value; /* Next value in event */
else
- pointer = stream->current + IW_EV_LCP_LEN; /* First value in event */
+ pointer = stream->current + IW_EV_LCP_PK_LEN; /* First value in event */
-#if DEBUG
+#ifdef DEBUG
printf("DBG - event_type = %d, event_len = %d, pointer = %p\n",
event_type, event_len, pointer);
#endif
return(-2);
}
/* Fixup for WE-19 and later : pointer no longer in the stream */
+ /* Beware of alignement. Dest has local alignement, not packed */
if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))
memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
pointer, event_len);
if(event_type == IW_HEADER_TYPE_POINT)
{
/* Check the length of the payload */
- unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_LEN);
+ unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN);
if(extra_len > 0)
{
/* Set pointer on variable part (warning : non aligned) */
/* Those checks are actually pretty hard to trigger,
* because of the checks done in the kernel... */
+ unsigned int token_len = iwe->u.data.length * descr->token_size;
+
+ /* Ugly fixup for alignement issues.
+ * If the kernel is 64 bits and userspace 32 bits,
+ * we have an extra 4+4 bytes.
+ * Fixing that in the kernel would break 64 bits userspace. */
+ if((token_len != extra_len) && (extra_len >= 4))
+ {
+ __u16 alt_dlen = *((__u16 *) pointer);
+ unsigned int alt_token_len = alt_dlen * descr->token_size;
+ if((alt_token_len + 8) == extra_len)
+ {
+#ifdef DEBUG
+ printf("DBG - alt_token_len = %d\n", alt_token_len);
+#endif
+ /* Ok, let's redo everything */
+ pointer -= event_len;
+ pointer += 4;
+ /* Dest has local alignement, not packed */
+ memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
+ pointer, event_len);
+ pointer += event_len + 4;
+ iwe->u.data.pointer = pointer;
+ token_len = alt_token_len;
+ }
+ }
+
/* Discard bogus events which advertise more tokens than
* what they carry... */
- unsigned int token_len = iwe->u.data.length * descr->token_size;
if(token_len > extra_len)
iwe->u.data.pointer = NULL; /* Discard paylod */
/* Check that the advertised token size is not going to
/* Same for underflows... */
if(iwe->u.data.length < descr->min_tokens)
iwe->u.data.pointer = NULL; /* Discard paylod */
-#if DEBUG
+#ifdef DEBUG
printf("DBG - extra_len = %d, token_len = %d, token = %d, max = %d, min = %d\n",
extra_len, token_len, iwe->u.data.length, descr->max_tokens, descr->min_tokens);
#endif
}
else
{
+ /* Ugly fixup for alignement issues.
+ * If the kernel is 64 bits and userspace 32 bits,
+ * we have an extra 4 bytes.
+ * Fixing that in the kernel would break 64 bits userspace. */
+ if((stream->value == NULL)
+ && ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4)
+ || ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) ||
+ (event_type == IW_HEADER_TYPE_QUAL))) ))
+ {
+#ifdef DEBUG
+ printf("DBG - alt iwe->len = %d\n", iwe->len - 4);
+#endif
+ pointer -= event_len;
+ pointer += 4;
+ /* Beware of alignement. Dest has local alignement, not packed */
+ memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
+ pointer += event_len;
+ }
+
/* Is there more value in the event ? */
if((pointer + event_len) <= (stream->current + iwe->len))
/* Go to next value */
memcpy(&wscan->stats.qual, &event->u.qual, sizeof(struct iw_quality));
break;
case SIOCGIWRATE:
- /* Scan may return a list of bitrates. Should we really bother with
- * an array of bitrates ? Or only the maximum bitrate ? Jean II */
+ /* Scan may return a list of bitrates. As we have space for only
+ * a single bitrate, we only keep the largest one. */
+ if((!wscan->has_maxbitrate) ||
+ (event->u.bitrate.value > wscan->maxbitrate.value))
+ {
+ wscan->has_maxbitrate = 1;
+ memcpy(&(wscan->maxbitrate), &(event->u.bitrate), sizeof(iwparam));
+ }
case IWEVCUSTOM:
/* How can we deal with those sanely ? Jean II */
default:
wrq.u.data.pointer = NULL; /* Later */
wrq.u.data.flags = 0;
wrq.u.data.length = 0;
- if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
+ /* Remember that as non-root, we will get an EPERM here */
+ if((iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
+ && (errno != EPERM))
return(-1);
/* Success : now, just wait for event or results */
return(250); /* Wait 250 ms */
struct stream_descr stream;
struct wireless_scan * wscan = NULL;
int ret;
-#if DEBUG
+#ifdef DEBUG
/* Debugging code. In theory useless, because it's debugged ;-) */
int i;
printf("Scan result [%02X", buffer[0]);
/*
* Wireless Tools
*
- * Jean II - HPLB 97->99 - HPL 99->04
+ * Jean II - HPLB 97->99 - HPL 99->07
*
* Common header for the Wireless Extension library...
*
* This file is released under the GPL license.
- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
*/
#ifndef IWLIB_H
#include <unistd.h>
/* This is our header selection. Try to hide the mess and the misery :-(
- * Don't look, you would go blind ;-) */
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-/* Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1
- * Kernel headers 2.2.X + Glibc 2.2 - Slackware 8.0 */
-#if defined(__GLIBC__) \
- && __GLIBC__ == 2 \
- && __GLIBC_MINOR__ >= 2 \
- && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-#define HEADERS_GENERIC
-
-/* Kernel headers 2.4.X + Glibc 2.1 - Debian 2.2 upgraded, RH 7.0
- * Kernel headers 2.2.X + Glibc 2.1 - Debian 2.2, RH 6.1 */
-#elif defined(__GLIBC__) \
- && __GLIBC__ == 2 \
- && __GLIBC_MINOR__ == 1 \
- && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-#define HEADERS_GENERIC
-#define HEADERS_KERNEL
-
-/* Unsupported combination */
-#else
-#error "Your kernel/libc combination is not supported"
-#endif
+ * Don't look, you would go blind ;-)
+ * Note : compatibility with *old* distributions has been removed,
+ * you will need Glibc 2.2 and older to compile (which means
+ * Mandrake 8.0, Debian 2.3, RH 7.1 or older).
+ */
-#ifdef HEADERS_GENERIC
-/* Proposed by Dr. Michael Rietz <rietz@mail.amps.de>, 27.3.2 */
+/* Set of headers proposed by Dr. Michael Rietz <rietz@mail.amps.de>, 27.3.2 */
#include <net/if_arp.h> /* For ARPHRD_ETHER */
#include <sys/socket.h> /* For AF_INET & struct sockaddr */
#include <netinet/in.h> /* For struct sockaddr_in */
#include <netinet/if_ether.h>
-#endif /* HEADERS_GENERIC */
/* Fixup to be able to include kernel includes in userspace.
* Basically, kill the sparse annotations... Jean II */
#include <linux/types.h> /* for "caddr_t" et al */
-#ifdef HEADERS_KERNEL
-/* Traditionally we have used kernel headers, included in wireless.h */
-#include <linux/socket.h> /* for "struct sockaddr" et al */
-#include <linux/if.h> /* for IFNAMSIZ and co... */
-#else /* !HEADERS_KERNEL */
/* Glibc systems headers are supposedly less problematic than kernel ones */
#include <sys/socket.h> /* for "struct sockaddr" et al */
#include <net/if.h> /* for IFNAMSIZ and co... */
-#endif /* !HEADERS_KERNEL */
/* Private copy of Wireless extensions (in this directoty) */
#include "wireless.h"
/****************************** DEBUG ******************************/
+//#define DEBUG 1
/************************ CONSTANTS & MACROS ************************/
/* Various versions information */
/* Recommended Wireless Extension version */
-#define WE_VERSION 20
+#define WE_VERSION 21
/* Maximum forward compatibility built in this version of WT */
-#define WE_MAX_VERSION 21
+#define WE_MAX_VERSION 22
/* Version of Wireless Tools */
-#define WT_VERSION 28
+#define WT_VERSION 29
/* Paths */
#define PROC_NET_WIRELESS "/proc/net/wireless"
#define ARPHRD_IEEE80211 801 /* IEEE 802.11 */
#endif /* ARPHRD_IEEE80211 */
+#ifndef IW_EV_LCP_PK_LEN
+/* Size of the Event prefix when packed in stream */
+#define IW_EV_LCP_PK_LEN (4)
+/* Size of the various events when packed in stream */
+#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ)
+#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32))
+#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
+#define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4)
+
+struct iw_pk_event
+{
+ __u16 len; /* Real lenght of this stuff */
+ __u16 cmd; /* Wireless IOCTL */
+ union iwreq_data u; /* IOCTL fixed payload */
+} __attribute__ ((packed));
+struct iw_pk_point
+{
+ void __user *pointer; /* Pointer to the data (in user space) */
+ __u16 length; /* number of fields or size in bytes */
+ __u16 flags; /* Optional params */
+} __attribute__ ((packed));
+
+#define IW_EV_LCP_PK2_LEN (sizeof(struct iw_pk_event) - sizeof(union iwreq_data))
+#define IW_EV_POINT_PK2_LEN (IW_EV_LCP_PK2_LEN + sizeof(struct iw_pk_point) - IW_EV_POINT_OFF)
+
+#endif /* IW_EV_LCP_PK_LEN */
+
/****************************** TYPES ******************************/
/* Shortcuts */
struct wireless_config b; /* Basic information */
iwstats stats; /* Signal strength */
int has_stats;
+ iwparam maxbitrate; /* Max bit rate in bps */
+ int has_maxbitrate;
} wireless_scan;
/*
char * args[],
int count);
+/* Describe a modulation */
+typedef struct iw_modul_descr
+{
+ unsigned int mask; /* Modulation bitmask */
+ char cmd[8]; /* Short name */
+ char * verbose; /* Verbose description */
+} iw_modul_descr;
+
/**************************** PROTOTYPES ****************************/
/*
* All the functions in iwcommon.c
iw_print_pm_value(char * buffer,
int buflen,
int value,
- int flags);
+ int flags,
+ int we_version);
void
iw_print_pm_mode(char * buffer,
int buflen,
iw_print_retry_value(char * buffer,
int buflen,
int value,
- int flags);
+ int flags,
+ int we_version);
/* ----------------------- TIME SUBROUTINES ----------------------- */
void
iw_print_timeval(char * buffer,
/* Modes as human readable strings */
extern const char * const iw_operation_mode[];
#define IW_NUM_OPER_MODE 7
+#define IW_NUM_OPER_MODE_EXT 8
+
+/* Modulations as human readable strings */
+extern const struct iw_modul_descr iw_modul_list[];
+#define IW_SIZE_MODUL_LIST 16
/************************* INLINE FUNTIONS *************************/
/*
.\" Jean II - HPLB - 96
.\" iwlist.8
.\"
-.TH IWLIST 8 "23 June 2004" "wireless-tools" "Linux Programmer's Manual"
+.TH IWLIST 8 "13 April 2006" "wireless-tools" "Linux Programmer's Manual"
.\"
.\" NAME part
.\"
.\" SYNOPSIS part
.\"
.SH SYNOPSIS
-.BI "iwlist " interface " scanning"
+.BI "iwlist [" interface "] scanning"
.br
-.BI "iwlist " interface " frequency"
+.BI "iwlist [" interface "] frequency"
.br
-.BI "iwlist " interface " rate"
+.BI "iwlist [" interface "] rate"
.br
-.BI "iwlist " interface " key"
+.BI "iwlist [" interface "] keys"
.br
-.BI "iwlist " interface " power"
+.BI "iwlist [" interface "] power"
.br
-.BI "iwlist " interface " txpower"
+.BI "iwlist [" interface "] txpower"
.br
-.BI "iwlist " interface " retry"
+.BI "iwlist [" interface "] retry"
.br
-.BI "iwlist " interface " event"
+.BI "iwlist [" interface "] event"
+.br
+.BI "iwlist [" interface "] auth"
+.br
+.BI "iwlist [" interface "] wpakeys"
+.br
+.BI "iwlist [" interface "] genie"
+.br
+.BI "iwlist [" interface "] modulation"
.br
.BI "iwlist --help"
.br
Triggering scanning is a privileged operation
.RI ( root
only) and normal users can only read left-over scan results. By
-default, the way scanning is done (the scope of the scan) will be
-impacted by the current setting of the driver. Also, this command is
-supposed to take extra arguments to control the scanning behaviour,
-but this is currently not implemented.
+default, the way scanning is done (the scope of the scan) is dependant
+on the card and card settings.
+.br
+This command take optional arguments, however most drivers will ignore
+those. The option
+.B essid
+is used to specify a scan on a specific ESSID. The option
+.B last
+do not trigger a scan and read left-over scan results.
.TP
.BR freq [uency]/ channel
Give the list of available frequencies in the device and the number of
.BR rate / bit [rate]
List the bit-rates supported by the device.
.TP
-.BR key / enc [ryption]
-List the encryption key sizes supported and display all the encryption
-keys available in the device.
+.BR keys / enc [ryption]
+List the encryption key sizes supported and list all the encryption
+keys set in the device.
.TP
.B power
List the various Power Management attributes and modes of the device.
.B event
List the wireless events supported by the device.
.TP
+.B auth
+List the WPA authentication parametes curently set.
+.TP
+.BR wpa [keys]
+List all the WPA encryption keys set in the device.
+.TP
+.B genie
+List the Generic Information Elements set in the device (used for WPA
+support).
+.TP
+.BR modu [lation]
+List the modulations supported by the device and the modulations
+currently enabled.
+.TP
.B --version
Display the version of the tools, as well as the recommended and
current Wireless Extensions version for the tool and the various
wireless interfaces.
+.TP
+.B --help
+Display short help message.
.\"
.\" FILES part
.\"
/*
* Wireless Tools
*
- * Jean II - HPLB '99 - HPL 99->04
+ * Jean II - HPLB '99 - HPL 99->07
*
* This tool can access various piece of information on the card
* not part of iwconfig...
* You need to link this code against "iwlist.c" and "-lm".
*
* This file is released under the GPL license.
- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
*/
#include "iwlib.h" /* Header */
int val_index; /* Value in table 0->(N-1) */
} iwscan_state;
+/*
+ * Bit to name mapping
+ */
+typedef struct iwmask_name
+{
+ unsigned int mask; /* bit mask for the value */
+ const char * name; /* human readable name for the value */
+} iwmask_name;
-/*********************** FREQUENCIES/CHANNELS ***********************/
-
-/*------------------------------------------------------------------*/
/*
- * Print the number of channels and available frequency for the device
+ * Types of authentication parameters
*/
-static int
-print_freq_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
+typedef struct iw_auth_descr
{
- struct iwreq wrq;
- struct iw_range range;
- double freq;
- int k;
- int channel;
- char buffer[128]; /* Temporary buffer */
+ int value; /* Type of auth value */
+ const char * label; /* User readable version */
+ const struct iwmask_name * names; /* Names for this value */
+ const int num_names; /* Number of names */
+} iw_auth_descr;
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
+/**************************** CONSTANTS ****************************/
- /* Get list of frequencies / channels */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- fprintf(stderr, "%-8.16s no frequency information.\n\n",
- ifname);
- else
- {
- if(range.num_frequency > 0)
- {
- printf("%-8.16s %d channels in total; available frequencies :\n",
- ifname, range.num_channels);
- /* Print them all */
- for(k = 0; k < range.num_frequency; k++)
- {
- freq = iw_freq2float(&(range.freq[k]));
- iw_print_freq_value(buffer, sizeof(buffer), freq);
- printf(" Channel %.2d : %s\n",
- range.freq[k].i, buffer);
- }
- }
- else
- printf("%-8.16s %d channels\n",
- ifname, range.num_channels);
+#define IW_SCAN_HACK 0x8000
- /* Get current frequency / channel and display it */
- if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
- {
- freq = iw_freq2float(&(wrq.u.freq));
- channel = iw_freq_to_channel(freq, &range);
- iw_print_freq(buffer, sizeof(buffer),
- freq, channel, wrq.u.freq.flags);
- printf(" Current %s\n\n", buffer);
- }
- }
- return(0);
-}
+#define IW_EXTKEY_SIZE (sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX)
-/************************ ACCESS POINT LIST ************************/
+/* ------------------------ WPA CAPA NAMES ------------------------ */
/*
- * Note : now that we have scanning support, this is depracted and
- * won't survive long. Actually, next version it's out !
+ * This is the user readable name of a bunch of WPA constants in wireless.h
+ * Maybe this should go in iwlib.c ?
*/
-/*------------------------------------------------------------------*/
-/*
- * Display the list of ap addresses and the associated stats
- * Exacly the same as the spy list, only with different IOCTL and messages
- */
-static int
-print_ap_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
-{
- struct iwreq wrq;
- char buffer[(sizeof(struct iw_quality) +
- sizeof(struct sockaddr)) * IW_MAX_AP];
- char temp[128];
- struct sockaddr * hwa;
- struct iw_quality * qual;
- iwrange range;
- int has_range = 0;
- int has_qual = 0;
- int n;
- int i;
+#ifndef WE_ESSENTIAL
+#define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0]))
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
+//static const struct iwmask_name iw_enc_mode_name[] = {
+// { IW_ENCODE_RESTRICTED, "restricted" },
+// { IW_ENCODE_OPEN, "open" },
+//};
+//#define IW_ENC_MODE_NUM IW_ARRAY_LEN(iw_enc_mode_name)
- /* Collect stats */
- wrq.u.data.pointer = (caddr_t) buffer;
- wrq.u.data.length = IW_MAX_AP;
- wrq.u.data.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
- {
- fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
- return(-1);
- }
+static const struct iwmask_name iw_auth_capa_name[] = {
+ { IW_ENC_CAPA_WPA, "WPA" },
+ { IW_ENC_CAPA_WPA2, "WPA2" },
+ { IW_ENC_CAPA_CIPHER_TKIP, "CIPHER-TKIP" },
+ { IW_ENC_CAPA_CIPHER_CCMP, "CIPHER-CCMP" },
+};
+#define IW_AUTH_CAPA_NUM IW_ARRAY_LEN(iw_auth_capa_name)
+
+static const struct iwmask_name iw_auth_cypher_name[] = {
+ { IW_AUTH_CIPHER_NONE, "none" },
+ { IW_AUTH_CIPHER_WEP40, "WEP-40" },
+ { IW_AUTH_CIPHER_TKIP, "TKIP" },
+ { IW_AUTH_CIPHER_CCMP, "CCMP" },
+ { IW_AUTH_CIPHER_WEP104, "WEP-104" },
+};
+#define IW_AUTH_CYPHER_NUM IW_ARRAY_LEN(iw_auth_cypher_name)
- /* Number of addresses */
- n = wrq.u.data.length;
- has_qual = wrq.u.data.flags;
+static const struct iwmask_name iw_wpa_ver_name[] = {
+ { IW_AUTH_WPA_VERSION_DISABLED, "disabled" },
+ { IW_AUTH_WPA_VERSION_WPA, "WPA" },
+ { IW_AUTH_WPA_VERSION_WPA2, "WPA2" },
+};
+#define IW_WPA_VER_NUM IW_ARRAY_LEN(iw_wpa_ver_name)
- /* The two lists */
- hwa = (struct sockaddr *) buffer;
- qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
+static const struct iwmask_name iw_auth_key_mgmt_name[] = {
+ { IW_AUTH_KEY_MGMT_802_1X, "802.1x" },
+ { IW_AUTH_KEY_MGMT_PSK, "PSK" },
+};
+#define IW_AUTH_KEY_MGMT_NUM IW_ARRAY_LEN(iw_auth_key_mgmt_name)
- /* Check if we have valid mac address type */
- if(iw_check_mac_addr_type(skfd, ifname) < 0)
- {
- fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
- return(-2);
- }
+static const struct iwmask_name iw_auth_alg_name[] = {
+ { IW_AUTH_ALG_OPEN_SYSTEM, "open" },
+ { IW_AUTH_ALG_SHARED_KEY, "shared-key" },
+ { IW_AUTH_ALG_LEAP, "LEAP" },
+};
+#define IW_AUTH_ALG_NUM IW_ARRAY_LEN(iw_auth_alg_name)
+
+static const struct iw_auth_descr iw_auth_settings[] = {
+ { IW_AUTH_WPA_VERSION, "WPA version", iw_wpa_ver_name, IW_WPA_VER_NUM },
+ { IW_AUTH_KEY_MGMT, "Key management", iw_auth_key_mgmt_name, IW_AUTH_KEY_MGMT_NUM },
+ { IW_AUTH_CIPHER_PAIRWISE, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
+ { IW_AUTH_CIPHER_GROUP, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
+ { IW_AUTH_TKIP_COUNTERMEASURES, "TKIP countermeasures", NULL, 0 },
+ { IW_AUTH_DROP_UNENCRYPTED, "Drop unencrypted", NULL, 0 },
+ { IW_AUTH_80211_AUTH_ALG, "Authentication algorithm", iw_auth_alg_name, IW_AUTH_ALG_NUM },
+ { IW_AUTH_RX_UNENCRYPTED_EAPOL, "Receive unencrypted EAPOL", NULL, 0 },
+ { IW_AUTH_ROAMING_CONTROL, "Roaming control", NULL, 0 },
+ { IW_AUTH_PRIVACY_INVOKED, "Privacy invoked", NULL, 0 },
+};
+#define IW_AUTH_SETTINGS_NUM IW_ARRAY_LEN(iw_auth_settings)
+
+/* Values for the IW_ENCODE_ALG_* returned by SIOCSIWENCODEEXT */
+static const char * iw_encode_alg_name[] = {
+ "none",
+ "WEP",
+ "TKIP",
+ "CCMP",
+ "unknown"
+};
+#define IW_ENCODE_ALG_NUM IW_ARRAY_LEN(iw_encode_alg_name)
+
+#ifndef IW_IE_CIPHER_NONE
+/* Cypher values in GENIE (pairwise and group) */
+#define IW_IE_CIPHER_NONE 0
+#define IW_IE_CIPHER_WEP40 1
+#define IW_IE_CIPHER_TKIP 2
+#define IW_IE_CIPHER_WRAP 3
+#define IW_IE_CIPHER_CCMP 4
+#define IW_IE_CIPHER_WEP104 5
+/* Key management in GENIE */
+#define IW_IE_KEY_MGMT_NONE 0
+#define IW_IE_KEY_MGMT_802_1X 1
+#define IW_IE_KEY_MGMT_PSK 2
+#endif /* IW_IE_CIPHER_NONE */
+
+/* Values for the IW_IE_CIPHER_* in GENIE */
+static const char * iw_ie_cypher_name[] = {
+ "none",
+ "WEP-40",
+ "TKIP",
+ "WRAP",
+ "CCMP",
+ "WEP-104",
+};
+#define IW_IE_CYPHER_NUM IW_ARRAY_LEN(iw_ie_cypher_name)
- /* Get range info if we can */
- if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
- has_range = 1;
+/* Values for the IW_IE_KEY_MGMT_* in GENIE */
+static const char * iw_ie_key_mgmt_name[] = {
+ "none",
+ "802.1x",
+ "PSK",
+};
+#define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name)
- /* Display it */
- if(n == 0)
- printf("%-8.16s No Peers/Access-Point in range\n", ifname);
- else
- printf("%-8.16s Peers/Access-Points in range:\n", ifname);
- for(i = 0; i < n; i++)
+#endif /* WE_ESSENTIAL */
+
+/************************* WPA SUBROUTINES *************************/
+
+#ifndef WE_ESSENTIAL
+/*------------------------------------------------------------------*/
+/*
+ * Print all names corresponding to a mask.
+ * This may want to be used in iw_print_retry_value() ?
+ */
+static void
+iw_print_mask_name(unsigned int mask,
+ const struct iwmask_name names[],
+ const unsigned int num_names,
+ const char * sep)
+{
+ unsigned int i;
+
+ /* Print out all names for the bitmask */
+ for(i = 0; i < num_names; i++)
{
- if(has_qual)
+ if(mask & names[i].mask)
{
- /* Print stats for this address */
- printf(" %s : ", iw_saether_ntop(&hwa[i], temp));
- iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
- printf("%s\n", temp);
+ /* Print out */
+ printf("%s%s", sep, names[i].name);
+ /* Remove the bit from the mask */
+ mask &= ~names[i].mask;
}
- else
- /* Only print the address */
- printf(" %s\n", iw_saether_ntop(&hwa[i], temp));
}
- printf("\n");
- return(0);
+ /* If there is unconsumed bits... */
+ if(mask != 0)
+ printf("%sUnknown", sep);
}
-/***************************** BITRATES *****************************/
-
/*------------------------------------------------------------------*/
/*
- * Print the number of available bitrates for the device
+ * Print the name corresponding to a value, with overflow check.
*/
-static int
-print_bitrate_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
+static void
+iw_print_value_name(unsigned int value,
+ const char * names[],
+ const unsigned int num_names)
{
- struct iwreq wrq;
- struct iw_range range;
- int k;
- char buffer[128];
+ if(value >= num_names)
+ printf(" unknown (%d)", value);
+ else
+ printf(" %s", names[value]);
+}
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
+/*------------------------------------------------------------------*/
+/*
+ * Parse, and display the results of an unknown IE.
+ *
+ */
+static void
+iw_print_ie_unknown(unsigned char * iebuf,
+ int buflen)
+{
+ int ielen = iebuf[1] + 2;
+ int i;
- /* Extract range info */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- fprintf(stderr, "%-8.16s no bit-rate information.\n\n",
- ifname);
- else
- {
- if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
- {
- printf("%-8.16s %d available bit-rates :\n",
- ifname, range.num_bitrates);
- /* Print them all */
- for(k = 0; k < range.num_bitrates; k++)
- {
- iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
- /* Maybe this should be %10s */
- printf("\t %s\n", buffer);
- }
- }
- else
- printf("%-8.16s unknown bit-rate information.\n", ifname);
+ if(ielen > buflen)
+ ielen = buflen;
- /* Get current bit rate */
- if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
- {
- iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
- printf(" Current Bit Rate%c%s\n\n",
- (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
- }
- }
- return(0);
+ printf("Unknown: ");
+ for(i = 0; i < ielen; i++)
+ printf("%02X", iebuf[i]);
+ printf("\n");
}
-/************************* ENCRYPTION KEYS *************************/
-
/*------------------------------------------------------------------*/
/*
- * Print the number of available encryption key for the device
+ * Parse, and display the results of a WPA or WPA2 IE.
+ *
*/
-static int
-print_keys_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
+static inline void
+iw_print_ie_wpa(unsigned char * iebuf,
+ int buflen)
{
- struct iwreq wrq;
- struct iw_range range;
- unsigned char key[IW_ENCODING_TOKEN_MAX];
- int k;
- char buffer[128];
+ int ielen = iebuf[1] + 2;
+ int offset = 2; /* Skip the IE id, and the length. */
+ unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
+ unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
+ unsigned char * wpa_oui;
+ int i;
+ uint16_t ver = 0;
+ uint16_t cnt = 0;
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
+ if(ielen > buflen)
+ ielen = buflen;
- /* Extract range info */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- fprintf(stderr, "%-8.16s no encryption keys information.\n\n",
- ifname);
- else
+#ifdef DEBUG
+ /* Debugging code. In theory useless, because it's debugged ;-) */
+ printf("IE raw value %d [%02X", buflen, iebuf[0]);
+ for(i = 1; i < buflen; i++)
+ printf(":%02X", iebuf[i]);
+ printf("]\n");
+#endif
+
+ switch(iebuf[0])
{
- printf("%-8.16s ", ifname);
- /* Print key sizes */
- if((range.num_encoding_sizes > 0) &&
- (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
+ case 0x30: /* WPA2 */
+ /* Check if we have enough data */
+ if(ielen < 4)
{
- printf("%d key sizes : %d", range.num_encoding_sizes,
- range.encoding_size[0] * 8);
- /* Print them all */
- for(k = 1; k < range.num_encoding_sizes; k++)
- printf(", %d", range.encoding_size[k] * 8);
- printf("bits\n ");
+ iw_print_ie_unknown(iebuf, buflen);
+ return;
}
- /* Print the keys and associate mode */
- printf("%d keys available :\n", range.max_encoding_tokens);
- for(k = 1; k <= range.max_encoding_tokens; k++)
- {
- wrq.u.data.pointer = (caddr_t) key;
- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
- wrq.u.data.flags = k;
- if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
- {
- fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno));
- break;
- }
- if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
- (wrq.u.data.length == 0))
- printf("\t\t[%d]: off\n", k);
- else
- {
- /* Display the key */
- iw_print_key(buffer, sizeof(buffer),
- key, wrq.u.data.length, wrq.u.data.flags);
- printf("\t\t[%d]: %s", k, buffer);
- /* Other info... */
- printf(" (%d bits)", wrq.u.data.length * 8);
- printf("\n");
- }
- }
- /* Print current key and mode */
- wrq.u.data.pointer = (caddr_t) key;
- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
- wrq.u.data.flags = 0; /* Set index to zero to get current */
- if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
- {
- /* Note : if above fails, we have already printed an error
- * message int the loop above */
- printf(" Current Transmit Key: [%d]\n",
- wrq.u.data.flags & IW_ENCODE_INDEX);
- if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
- printf(" Security mode:restricted\n");
- if(wrq.u.data.flags & IW_ENCODE_OPEN)
- printf(" Security mode:open\n");
- }
+ wpa_oui = wpa2_oui;
+ break;
- /* Print WPA/802.1x/802.11i security parameters */
- if(range.we_version_compiled > 17)
- {
- /* Display advance encryption capabilities */
- if(range.enc_capa)
- {
- const char * auth_string[] = { "WPA",
- "WPA2",
- "CIPHER TKIP",
- "CIPHER CCMP" };
- const int auth_num = (sizeof(auth_string) /
- sizeof(auth_string[1]));
- int i;
- int mask = 0x1;
-
- printf(" Authentication capabilities :\n");
- for(i = 0; i < auth_num; i++)
- {
- if(range.enc_capa & mask)
- printf("\t\t%s\n", auth_string[i]);
- mask <<= 1;
- }
- }
+ case 0xdd: /* WPA or else */
+ wpa_oui = wpa1_oui;
+
+ /* Not all IEs that start with 0xdd are WPA.
+ * So check that the OUI is valid. Note : offset==2 */
+ if((ielen < 8)
+ || (memcmp(&iebuf[offset], wpa_oui, 3) != 0)
+ || (iebuf[offset + 3] != 0x01))
+ {
+ iw_print_ie_unknown(iebuf, buflen);
+ return;
+ }
- /* Current values for authentication */
- wrq.u.param.flags = IW_AUTH_KEY_MGMT;
- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
- printf(" Current key_mgmt:0x%X\n",
- wrq.u.param.value);
-
- wrq.u.param.flags = IW_AUTH_CIPHER_PAIRWISE;
- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
- printf(" Current cipher_pairwise:0x%X\n",
- wrq.u.param.value);
-
- wrq.u.param.flags = IW_AUTH_CIPHER_GROUP;
- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
- printf(" Current cipher_group:0x%X\n",
- wrq.u.param.value);
- }
+ /* Skip the OUI type */
+ offset += 4;
+ break;
- printf("\n\n");
+ default:
+ return;
}
- return(0);
-}
+
+ /* Pick version number (little endian) */
+ ver = iebuf[offset] | (iebuf[offset + 1] << 8);
+ offset += 2;
-/************************* POWER MANAGEMENT *************************/
+ if(iebuf[0] == 0xdd)
+ printf("WPA Version %d\n", ver);
+ if(iebuf[0] == 0x30)
+ printf("IEEE 802.11i/WPA2 Version %d\n", ver);
-/*------------------------------------------------------------------*/
-/*
- * Print Power Management info for each device
- */
-static inline int
-get_pm_value(int skfd,
- char * ifname,
- struct iwreq * pwrq,
- int flags,
- char * buffer,
- int buflen)
-{
- /* Get Another Power Management value */
- pwrq->u.power.flags = flags;
- if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
+ /* From here, everything is technically optional. */
+
+ /* Check if we are done */
+ if(ielen < (offset + 4))
{
- /* Let's check the value and its type */
- if(pwrq->u.power.flags & IW_POWER_TYPE)
- {
- iw_print_pm_value(buffer, buflen,
- pwrq->u.power.value, pwrq->u.power.flags);
- printf("\n %s", buffer);
- }
+ /* We have a short IE. So we should assume TKIP/TKIP. */
+ printf(" Group Cipher : TKIP\n");
+ printf(" Pairwise Cipher : TKIP\n");
+ return;
+ }
+
+ /* Next we have our group cipher. */
+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
+ {
+ printf(" Group Cipher : Proprietary\n");
}
- return(pwrq->u.power.flags);
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Print Power Management info for each device
- */
-static int
-print_pm_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
-{
- struct iwreq wrq;
- struct iw_range range;
- char buffer[128];
-
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
-
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 10))
- fprintf(stderr, "%-8.16s no power management information.\n\n",
- ifname);
else
{
- printf("%-8.16s ", ifname);
+ printf(" Group Cipher :");
+ iw_print_value_name(iebuf[offset+3],
+ iw_ie_cypher_name, IW_IE_CYPHER_NUM);
+ printf("\n");
+ }
+ offset += 4;
- /* Display modes availables */
- if(range.pm_capa & IW_POWER_MODE)
- {
- printf("Supported modes :\n ");
- if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
- printf("\t\to Receive all packets (unicast & multicast)\n ");
- if(range.pm_capa & IW_POWER_UNICAST_R)
- printf("\t\to Receive Unicast only (discard multicast)\n ");
- if(range.pm_capa & IW_POWER_MULTICAST_R)
- printf("\t\to Receive Multicast only (discard unicast)\n ");
- if(range.pm_capa & IW_POWER_FORCE_S)
- printf("\t\to Force sending using Power Management\n ");
- if(range.pm_capa & IW_POWER_REPEATER)
- printf("\t\to Repeat multicast\n ");
- }
- /* Display min/max period availables */
- if(range.pmp_flags & IW_POWER_PERIOD)
- {
- int flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
- /* Display if auto or fixed */
- if(range.pmp_flags & IW_POWER_MIN)
- printf("Auto period ; ");
- else
- printf("Fixed period ; ");
- /* Print the range */
- iw_print_pm_value(buffer, sizeof(buffer),
- range.min_pmp, flags | IW_POWER_MIN);
- printf("%s\n ", buffer);
- iw_print_pm_value(buffer, sizeof(buffer),
- range.max_pmp, flags | IW_POWER_MAX);
- printf("%s\n ", buffer);
- }
- /* Display min/max timeout availables */
- if(range.pmt_flags & IW_POWER_TIMEOUT)
- {
- int flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
- /* Display if auto or fixed */
- if(range.pmt_flags & IW_POWER_MIN)
- printf("Auto timeout ; ");
- else
- printf("Fixed timeout ; ");
- /* Print the range */
- iw_print_pm_value(buffer, sizeof(buffer),
- range.min_pmt, flags | IW_POWER_MIN);
- printf("%s\n ", buffer);
- iw_print_pm_value(buffer, sizeof(buffer),
- range.max_pmt, flags | IW_POWER_MAX);
- printf("%s\n ", buffer);
- }
+ /* Check if we are done */
+ if(ielen < (offset + 2))
+ {
+ /* We don't have a pairwise cipher, or auth method. Assume TKIP. */
+ printf(" Pairwise Ciphers : TKIP\n");
+ return;
+ }
- /* Get current Power Management settings */
- wrq.u.power.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
- {
- int flags = wrq.u.power.flags;
+ /* Otherwise, we have some number of pairwise ciphers. */
+ cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
+ offset += 2;
+ printf(" Pairwise Ciphers (%d) :", cnt);
- /* Is it disabled ? */
- if(wrq.u.power.disabled)
- printf("Current mode:off\n ");
- else
- {
- int pm_mask = 0;
+ if(ielen < (offset + 4*cnt))
+ return;
- /* Let's check the mode */
- iw_print_pm_mode(buffer, sizeof(buffer), flags);
- printf("Current %s", buffer);
+ for(i = 0; i < cnt; i++)
+ {
+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
+ {
+ printf(" Proprietary");
+ }
+ else
+ {
+ iw_print_value_name(iebuf[offset+3],
+ iw_ie_cypher_name, IW_IE_CYPHER_NUM);
+ }
+ offset+=4;
+ }
+ printf("\n");
+
+ /* Check if we are done */
+ if(ielen < (offset + 2))
+ return;
- /* Let's check if nothing (simply on) */
- if((flags & IW_POWER_MODE) == IW_POWER_ON)
- printf("mode:on");
- printf("\n ");
+ /* Now, we have authentication suites. */
+ cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
+ offset += 2;
+ printf(" Authentication Suites (%d) :", cnt);
- /* Let's check the value and its type */
- if(wrq.u.power.flags & IW_POWER_TYPE)
- {
- iw_print_pm_value(buffer, sizeof(buffer),
- wrq.u.power.value, wrq.u.power.flags);
- printf("%s", buffer);
- }
+ if(ielen < (offset + 4*cnt))
+ return;
- /* If we have been returned a MIN value, ask for the MAX */
- if(flags & IW_POWER_MIN)
- pm_mask = IW_POWER_MAX;
- /* If we have been returned a MAX value, ask for the MIN */
- if(flags & IW_POWER_MAX)
- pm_mask = IW_POWER_MIN;
- /* If we have something to ask for... */
- if(pm_mask)
- get_pm_value(skfd, ifname, &wrq, pm_mask,
- buffer, sizeof(buffer));
-
- /* And if we have both a period and a timeout, ask the other */
- pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
- IW_POWER_TYPE));
- if(pm_mask)
- {
- int base_mask = pm_mask;
- flags = get_pm_value(skfd, ifname, &wrq, pm_mask,
- buffer, sizeof(buffer));
- pm_mask = 0;
+ for(i = 0; i < cnt; i++)
+ {
+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
+ {
+ printf(" Proprietary");
+ }
+ else
+ {
+ iw_print_value_name(iebuf[offset+3],
+ iw_ie_key_mgmt_name, IW_IE_KEY_MGMT_NUM);
+ }
+ offset+=4;
+ }
+ printf("\n");
+
+ /* Check if we are done */
+ if(ielen < (offset + 1))
+ return;
- /* If we have been returned a MIN value, ask for the MAX */
- if(flags & IW_POWER_MIN)
- pm_mask = IW_POWER_MAX | base_mask;
- /* If we have been returned a MAX value, ask for the MIN */
- if(flags & IW_POWER_MAX)
- pm_mask = IW_POWER_MIN | base_mask;
- /* If we have something to ask for... */
- if(pm_mask)
- get_pm_value(skfd, ifname, &wrq, pm_mask,
- buffer, sizeof(buffer));
- }
- }
- }
- printf("\n");
+ /* Otherwise, we have capabilities bytes.
+ * For now, we only care about preauth which is in bit position 1 of the
+ * first byte. (But, preauth with WPA version 1 isn't supposed to be
+ * allowed.) 8-) */
+ if(iebuf[offset] & 0x01)
+ {
+ printf(" Preauthentication Supported\n");
}
- return(0);
}
-
-/************************** TRANSMIT POWER **************************/
-
+
/*------------------------------------------------------------------*/
/*
- * Print the number of available transmit powers for the device
+ * Process a generic IE and display the info in human readable form
+ * for some of the most interesting ones.
+ * For now, we only decode the WPA IEs.
*/
-static int
-print_txpower_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
+static inline void
+iw_print_gen_ie(unsigned char * buffer,
+ int buflen)
{
- struct iwreq wrq;
- struct iw_range range;
- int dbm;
- int mwatt;
- int k;
-
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
-
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 10))
- fprintf(stderr, "%-8.16s no transmit-power information.\n\n",
- ifname);
- else
- {
- if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
- printf("%-8.16s unknown transmit-power information.\n\n", ifname);
- else
- {
- printf("%-8.16s %d available transmit-powers :\n",
- ifname, range.num_txpower);
- /* Print them all */
- for(k = 0; k < range.num_txpower; k++)
- {
- /* Check for relative values */
- if(range.txpower_capa & IW_TXPOW_RELATIVE)
- {
- printf("\t %d (no units)\n", range.txpower[k]);
- }
- else
- {
- if(range.txpower_capa & IW_TXPOW_MWATT)
- {
- dbm = iw_mwatt2dbm(range.txpower[k]);
- mwatt = range.txpower[k];
- }
- else
- {
- dbm = range.txpower[k];
- mwatt = iw_dbm2mwatt(range.txpower[k]);
- }
- printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
- }
- }
- }
-
- /* Get current Transmit Power */
- if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
- {
- printf(" Current Tx-Power");
- /* Disabled ? */
- if(wrq.u.txpower.disabled)
- printf(":off\n\n");
- else
- {
- /* Fixed ? */
- if(wrq.u.txpower.fixed)
- printf("=");
- else
- printf(":");
- /* Check for relative values */
- if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
- {
- /* I just hate relative value, because they are
- * driver specific, so not very meaningfull to apps.
- * But, we have to support that, because
- * this is the way hardware is... */
- printf("\t %d (no units)\n", wrq.u.txpower.value);
- }
- else
- {
- if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
- {
- dbm = iw_mwatt2dbm(wrq.u.txpower.value);
- mwatt = wrq.u.txpower.value;
- }
- else
- {
- dbm = wrq.u.txpower.value;
- mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
- }
- printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
- }
- }
- }
- }
- return(0);
-}
-
-/*********************** RETRY LIMIT/LIFETIME ***********************/
-
-/*------------------------------------------------------------------*/
-/*
- * Print one retry value
- */
-static inline int
-get_retry_value(int skfd,
- char * ifname,
- struct iwreq * pwrq,
- int flags,
- char * buffer,
- int buflen)
-{
- /* Get Another retry value */
- pwrq->u.retry.flags = flags;
- if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
- {
- /* Let's check the value and its type */
- if(pwrq->u.retry.flags & IW_RETRY_TYPE)
- {
- iw_print_retry_value(buffer, buflen,
- pwrq->u.retry.value, pwrq->u.retry.flags);
- printf("%s\n ", buffer);
- }
- }
- return(pwrq->u.retry.flags);
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Print Retry info for each device
- */
-static int
-print_retry_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
-{
- struct iwreq wrq;
- struct iw_range range;
- char buffer[128];
-
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
+ int offset = 0;
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 11))
- fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n",
- ifname);
- else
+ /* Loop on each IE, each IE is minimum 2 bytes */
+ while(offset <= (buflen - 2))
{
- printf("%-8.16s ", ifname);
-
- /* Display min/max limit availables */
- if(range.retry_flags & IW_RETRY_LIMIT)
- {
- int flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
- /* Display if auto or fixed */
- if(range.retry_flags & IW_RETRY_MIN)
- printf("Auto limit ; ");
- else
- printf("Fixed limit ; ");
- /* Print the range */
- iw_print_retry_value(buffer, sizeof(buffer),
- range.min_retry, flags | IW_RETRY_MIN);
- printf("%s\n ", buffer);
- iw_print_retry_value(buffer, sizeof(buffer),
- range.max_retry, flags | IW_RETRY_MAX);
- printf("%s\n ", buffer);
-
- }
- /* Display min/max lifetime availables */
- if(range.r_time_flags & IW_RETRY_LIFETIME)
- {
- int flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
- /* Display if auto or fixed */
- if(range.r_time_flags & IW_RETRY_MIN)
- printf("Auto lifetime ; ");
- else
- printf("Fixed lifetime ; ");
- /* Print the range */
- iw_print_retry_value(buffer, sizeof(buffer),
- range.min_r_time, flags | IW_RETRY_MIN);
- printf("%s\n ", buffer);
- iw_print_retry_value(buffer, sizeof(buffer),
- range.max_r_time, flags | IW_RETRY_MAX);
- printf("%s\n ", buffer);
-
- }
+ printf(" IE: ");
- /* Get current retry settings */
- wrq.u.retry.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
+ /* Check IE type */
+ switch(buffer[offset])
{
- int flags = wrq.u.retry.flags;
-
- /* Is it disabled ? */
- if(wrq.u.retry.disabled)
- printf("Current mode:off\n ");
- else
- {
- int retry_mask = 0;
-
- /* Let's check the mode */
- printf("Current mode:on\n ");
-
- /* Let's check the value and its type */
- if(wrq.u.retry.flags & IW_RETRY_TYPE)
- {
- iw_print_retry_value(buffer, sizeof(buffer),
- wrq.u.retry.value, wrq.u.retry.flags);
- printf("%s\n ", buffer);
- }
-
- /* If we have been returned a MIN value, ask for the MAX */
- if(flags & IW_RETRY_MIN)
- retry_mask = IW_RETRY_MAX;
- /* If we have been returned a MAX value, ask for the MIN */
- if(flags & IW_RETRY_MAX)
- retry_mask = IW_RETRY_MIN;
- /* If we have something to ask for... */
- if(retry_mask)
- get_retry_value(skfd, ifname, &wrq, retry_mask,
- buffer, sizeof(buffer));
-
- /* And if we have both a period and a timeout, ask the other */
- retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
- IW_RETRY_TYPE));
- if(retry_mask)
- {
- int base_mask = retry_mask;
- flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
- buffer, sizeof(buffer));
- retry_mask = 0;
-
- /* If we have been returned a MIN value, ask for the MAX */
- if(flags & IW_RETRY_MIN)
- retry_mask = IW_RETRY_MAX | base_mask;
- /* If we have been returned a MAX value, ask for the MIN */
- if(flags & IW_RETRY_MAX)
- retry_mask = IW_RETRY_MIN | base_mask;
- /* If we have something to ask for... */
- if(retry_mask)
- get_retry_value(skfd, ifname, &wrq, retry_mask,
- buffer, sizeof(buffer));
- }
- }
+ case 0xdd: /* WPA1 (and other) */
+ case 0x30: /* WPA2 */
+ iw_print_ie_wpa(buffer + offset, buflen);
+ break;
+ default:
+ iw_print_ie_unknown(buffer + offset, buflen);
}
- printf("\n");
+ /* Skip over this IE to the next one in the list. */
+ offset += buffer[offset+1] + 2;
}
- return(0);
}
+#endif /* WE_ESSENTIAL */
/***************************** SCANNING *****************************/
/*
/*------------------------------------------------------------------*/
/*
- * Parse, and display the results of a WPA or WPA2 IE.
- *
+ * Print one element from the scanning results
*/
-static void
-iw_print_ie_unknown(unsigned char * iebuf,
- int buflen)
+static inline void
+print_scanning_token(struct stream_descr * stream, /* Stream of events */
+ struct iw_event * event, /* Extracted token */
+ struct iwscan_state * state,
+ struct iw_range * iw_range, /* Range info */
+ int has_range)
{
- int ielen = iebuf[1] + 2;
- int i;
-
- if(ielen > buflen)
- ielen = buflen;
-
- printf("Unknown: ");
- for(i = 0; i < ielen; i++)
- printf("%02X", iebuf[i]);
- printf("\n");
-}
+ char buffer[128]; /* Temporary buffer */
-/*-----------------------------------------------------------------*/
-/*
- * Display the cipher type for the value passed in.
- *
- */
-static inline void
-iw_print_ie_cipher(unsigned char csuite)
-{
- switch (csuite)
+ /* Now, let's decode the event */
+ switch(event->cmd)
{
- case 0x00:
- printf("None or same as Group ");
+ case SIOCGIWAP:
+ printf(" Cell %02d - Address: %s\n", state->ap_num,
+ iw_saether_ntop(&event->u.ap_addr, buffer));
+ state->ap_num++;
break;
-
- case 0x01:
- printf("WEP-40 ");
+ case SIOCGIWNWID:
+ if(event->u.nwid.disabled)
+ printf(" NWID:off/any\n");
+ else
+ printf(" NWID:%X\n", event->u.nwid.value);
break;
-
- case 0x02:
- printf("TKIP ");
+ case SIOCGIWFREQ:
+ {
+ double freq; /* Frequency/channel */
+ int channel = -1; /* Converted to channel */
+ freq = iw_freq2float(&(event->u.freq));
+ /* Convert to channel if possible */
+ if(has_range)
+ channel = iw_freq_to_channel(freq, iw_range);
+ iw_print_freq(buffer, sizeof(buffer),
+ freq, channel, event->u.freq.flags);
+ printf(" %s\n", buffer);
+ }
break;
-
- case 0x03:
- printf("WRAP ");
+ case SIOCGIWMODE:
+ /* Note : event->u.mode is unsigned, no need to check <= 0 */
+ if(event->u.mode >= IW_NUM_OPER_MODE)
+ event->u.mode = IW_NUM_OPER_MODE;
+ printf(" Mode:%s\n",
+ iw_operation_mode[event->u.mode]);
break;
-
- case 0x04:
- printf("CCMP ");
- break;
-
- case 0x05:
- printf("WEP-104 ");
- break;
-
- default:
- printf("Unknown ");
- break;
- }
- }
-
-/*------------------------------------------------------------------*/
-/*
- * Parse, and display the results of a WPA or WPA2 IE.
- *
- */
-static inline void
-iw_print_ie_wpa(unsigned char * iebuf,
- int buflen)
-{
- int ielen = iebuf[1] + 2;
- int offset = 2; /* Skip the IE id, and the length. */
- unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
- unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
- unsigned char * wpa_oui;
- int i;
- uint16_t ver = 0;
- uint16_t cnt = 0;
-
- if(ielen > buflen)
- ielen = buflen;
-
- switch(iebuf[0])
- {
- case 0x30: /* WPA2 */
- /* Check if we have enough data */
- if(ielen < 4)
- {
- iw_print_ie_unknown(iebuf, buflen);
- return;
- }
-
- wpa_oui = wpa2_oui;
- break;
-
- case 0xdd: /* WPA or else */
- wpa_oui = wpa1_oui;
-
- /* Not all IEs that start with 0xdd are WPA.
- * So check that the OUI is valid. */
- if((ielen < 8)
- || ((memcmp(&iebuf[offset], wpa_oui, 3) != 0)
- && (iebuf[offset+3] == 0x01)))
- {
- iw_print_ie_unknown(iebuf, buflen);
- return;
- }
-
- offset += 4;
- break;
-
- default:
- return;
- }
-
- /* Pick version number (little endian) */
- ver = iebuf[offset] | (iebuf[offset + 1] << 8);
- offset += 2;
-
- if(iebuf[0] == 0xdd)
- printf("WPA Version %d\n", ver);
- if(iebuf[0] == 0x30)
- printf("IEEE 802.11i/WPA2 Version %d\n", ver);
-
- /* From here, everything is technically optional. */
-
- /* Check if we are done */
- if(ielen < (offset + 4))
- {
- /* We have a short IE. So we should assume TKIP/TKIP. */
- printf(" Group Cipher : TKIP\n");
- printf(" Pairwise Cipher : TKIP\n");
- return;
- }
-
- /* Next we have our group cipher. */
- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
- {
- printf(" Group Cipher : Proprietary\n");
- }
- else
- {
- printf(" Group Cipher : ");
- iw_print_ie_cipher(iebuf[offset+3]);
- printf("\n");
- }
- offset += 4;
-
- /* Check if we are done */
- if(ielen < (offset + 2))
- {
- /* We don't have a pairwise cipher, or auth method. Assume TKIP. */
- printf(" Pairwise Ciphers (1) : TKIP\n");
- return;
- }
-
- /* Otherwise, we have some number of pairwise ciphers. */
- cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
- offset += 2;
- printf(" Pairwise Ciphers (%d) : ", cnt);
-
- if(ielen < (offset + 4*cnt))
- return;
-
- for(i = 0; i < cnt; i++)
- {
- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
- {
- printf("Proprietary ");
- }
- else
- {
- iw_print_ie_cipher(iebuf[offset+3]);
- }
- offset+=4;
- }
- printf("\n");
-
- /* Check if we are done */
- if(ielen < (offset + 2))
- return;
-
- /* Now, we have authentication suites. */
- cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
- offset += 2;
- printf(" Authentication Suites (%d) : ", cnt);
-
- if(ielen < (offset + 4*cnt))
- return;
-
- for(i = 0; i < cnt; i++)
- {
- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
- {
- printf("Proprietary ");
- }
- else
- {
- switch(iebuf[offset+3])
- {
- case 0x00:
- printf("Reserved ");
- break;
-
- case 0x01:
- printf("802.1X ");
- break;
-
- case 0x02:
- printf("PSK ");
- break;
-
- default:
- printf("Unknown ");
- break;
- }
- }
- offset+=4;
- }
- printf("\n");
-
- /* Check if we are done */
- if(ielen < (offset + 1))
- return;
-
- /* Otherwise, we have capabilities bytes.
- * For now, we only care about preauth which is in bit position 1 of the
- * first byte. (But, preauth with WPA version 1 isn't supposed to be
- * allowed.) 8-) */
- if(iebuf[offset] & 0x01)
- {
- printf(" Preauthentication Supported\n");
- }
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Process a generic IE and display the info in human readable form
- * for some of the most interesting ones.
- * For now, we only decode the WPA IEs.
- */
-static inline void
-iw_print_gen_ie(unsigned char * buffer,
- int buflen)
-{
- int offset = 0;
-
- /* Loop on each IE, each IE is minimum 2 bytes */
- while(offset <= (buflen - 2))
- {
- printf(" IE: ");
-
- /* Check IE type */
- switch(buffer[offset])
- {
- case 0xdd: /* WPA1 (and other) */
- case 0x30: /* WPA2 */
- iw_print_ie_wpa(buffer + offset, buflen);
- break;
- default:
- iw_print_ie_unknown(buffer + offset, buflen);
- }
- /* Skip over this IE to the next one in the list. */
- offset += buffer[offset+1] + 2;
- }
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Print one element from the scanning results
- */
-static inline void
-print_scanning_token(struct stream_descr * stream, /* Stream of events */
- struct iw_event * event, /* Extracted token */
- struct iwscan_state * state,
- struct iw_range * iw_range, /* Range info */
- int has_range)
-{
- char buffer[128]; /* Temporary buffer */
-
- /* Now, let's decode the event */
- switch(event->cmd)
- {
- case SIOCGIWAP:
- printf(" Cell %02d - Address: %s\n", state->ap_num,
- iw_saether_ntop(&event->u.ap_addr, buffer));
- state->ap_num++;
- break;
- case SIOCGIWNWID:
- if(event->u.nwid.disabled)
- printf(" NWID:off/any\n");
- else
- printf(" NWID:%X\n", event->u.nwid.value);
- break;
- case SIOCGIWFREQ:
- {
- double freq; /* Frequency/channel */
- int channel = -1; /* Converted to channel */
- freq = iw_freq2float(&(event->u.freq));
- /* Convert to channel if possible */
- if(has_range)
- channel = iw_freq_to_channel(freq, iw_range);
- iw_print_freq(buffer, sizeof(buffer),
- freq, channel, event->u.freq.flags);
- printf(" %s\n", buffer);
- }
- break;
- case SIOCGIWMODE:
- printf(" Mode:%s\n",
- iw_operation_mode[event->u.mode]);
- break;
- case SIOCGIWNAME:
- printf(" Protocol:%-1.16s\n", event->u.name);
+ case SIOCGIWNAME:
+ printf(" Protocol:%-1.16s\n", event->u.name);
break;
case SIOCGIWESSID:
{
/* Check for termination */
if(stream->value == NULL)
{
- printf("\n");
- state->val_index = 0;
+ printf("\n");
+ state->val_index = 0;
+ }
+ else
+ state->val_index++;
+ break;
+ case SIOCGIWMODUL:
+ {
+ unsigned int modul = event->u.param.value;
+ int i;
+ int n = 0;
+ printf(" Modulations :");
+ for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
+ {
+ if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
+ {
+ if((n++ % 8) == 7)
+ printf("\n ");
+ else
+ printf(" ; ");
+ printf("%s", iw_modul_list[i].cmd);
+ }
+ }
+ printf("\n");
+ }
+ break;
+ case IWEVQUAL:
+ iw_print_stats(buffer, sizeof(buffer),
+ &event->u.qual, iw_range, has_range);
+ printf(" %s\n", buffer);
+ break;
+#ifndef WE_ESSENTIAL
+ case IWEVGENIE:
+ /* Informations Elements are complex, let's do only some of them */
+ iw_print_gen_ie(event->u.data.pointer, event->u.data.length);
+ break;
+#endif /* WE_ESSENTIAL */
+ case IWEVCUSTOM:
+ {
+ char custom[IW_CUSTOM_MAX+1];
+ if((event->u.data.pointer) && (event->u.data.length))
+ memcpy(custom, event->u.data.pointer, event->u.data.length);
+ custom[event->u.data.length] = '\0';
+ printf(" Extra:%s\n", custom);
+ }
+ break;
+ default:
+ printf(" (Unknown Wireless Token 0x%04X)\n",
+ event->cmd);
+ } /* switch(event->cmd) */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Perform a scanning on one device
+ */
+static int
+print_scanning_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_scan_req scanopt; /* Options for 'set' */
+ int scanflags = 0; /* Flags for scan */
+ unsigned char * buffer = NULL; /* Results */
+ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
+ struct iw_range range;
+ int has_range;
+ struct timeval tv; /* Select timeout */
+ int timeout = 15000000; /* 15s */
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Debugging stuff */
+ if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN))
+ {
+ fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n");
+ fprintf(stderr, "*** and the following line :\n");
+ fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n",
+ IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN);
+ }
+
+ /* Get range stuff */
+ has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
+
+ /* Check if the interface could support scanning. */
+ if((!has_range) || (range.we_version_compiled < 14))
+ {
+ fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n",
+ ifname);
+ return(-1);
+ }
+
+ /* Init timeout value -> 250ms between set and first get */
+ tv.tv_sec = 0;
+ tv.tv_usec = 250000;
+
+ /* Clean up set args */
+ memset(&scanopt, 0, sizeof(scanopt));
+
+ /* Parse command line arguments and extract options.
+ * Note : when we have enough options, we should use the parser
+ * from iwconfig... */
+ while(count > 0)
+ {
+ /* One arg is consumed (the option name) */
+ count--;
+
+ /*
+ * Check for Active Scan (scan with specific essid)
+ */
+ if(!strncmp(args[0], "essid", 5))
+ {
+ if(count < 1)
+ {
+ fprintf(stderr, "Too few arguments for scanning option [%s]\n",
+ args[0]);
+ return(-1);
+ }
+ args++;
+ count--;
+
+ /* Store the ESSID in the scan options */
+ scanopt.essid_len = strlen(args[0]);
+ memcpy(scanopt.essid, args[0], scanopt.essid_len);
+ /* Initialise BSSID as needed */
+ if(scanopt.bssid.sa_family == 0)
+ {
+ scanopt.bssid.sa_family = ARPHRD_ETHER;
+ memset(scanopt.bssid.sa_data, 0xff, ETH_ALEN);
+ }
+ /* Scan only this ESSID */
+ scanflags |= IW_SCAN_THIS_ESSID;
+ }
+ else
+ /* Check for last scan result (do not trigger scan) */
+ if(!strncmp(args[0], "last", 4))
+ {
+ /* Hack */
+ scanflags |= IW_SCAN_HACK;
+ }
+ else
+ {
+ fprintf(stderr, "Invalid scanning option [%s]\n", args[0]);
+ return(-1);
+ }
+
+ /* Next arg */
+ args++;
+ }
+
+ /* Check if we have scan options */
+ if(scanflags)
+ {
+ wrq.u.data.pointer = (caddr_t) &scanopt;
+ wrq.u.data.length = sizeof(scanopt);
+ wrq.u.data.flags = scanflags;
+ }
+ else
+ {
+ wrq.u.data.pointer = NULL;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = 0;
+ }
+
+ /* If only 'last' was specified on command line, don't trigger a scan */
+ if(scanflags == IW_SCAN_HACK)
+ {
+ /* Skip waiting */
+ tv.tv_usec = 0;
+ }
+ else
+ {
+ /* Initiate Scanning */
+ if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
+ {
+ if((errno != EPERM) || (scanflags != 0))
+ {
+ fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
+ ifname, strerror(errno));
+ return(-1);
+ }
+ /* If we don't have the permission to initiate the scan, we may
+ * still have permission to read left-over results.
+ * But, don't wait !!! */
+#if 0
+ /* Not cool, it display for non wireless interfaces... */
+ fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
+#endif
+ tv.tv_usec = 0;
+ }
+ }
+ timeout -= tv.tv_usec;
+
+ /* Forever */
+ while(1)
+ {
+ fd_set rfds; /* File descriptors for select */
+ int last_fd; /* Last fd */
+ int ret;
+
+ /* Guess what ? We must re-generate rfds each time */
+ FD_ZERO(&rfds);
+ last_fd = -1;
+
+ /* In here, add the rtnetlink fd in the list */
+
+ /* Wait until something happens */
+ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
+
+ /* Check if there was an error */
+ if(ret < 0)
+ {
+ if(errno == EAGAIN || errno == EINTR)
+ continue;
+ fprintf(stderr, "Unhandled signal - exiting...\n");
+ return(-1);
+ }
+
+ /* Check if there was a timeout */
+ if(ret == 0)
+ {
+ unsigned char * newbuf;
+
+ realloc:
+ /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
+ newbuf = realloc(buffer, buflen);
+ if(newbuf == NULL)
+ {
+ if(buffer)
+ free(buffer);
+ fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
+ return(-1);
+ }
+ buffer = newbuf;
+
+ /* Try to read the results */
+ wrq.u.data.pointer = buffer;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = buflen;
+ if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
+ {
+ /* Check if buffer was too small (WE-17 only) */
+ if((errno == E2BIG) && (range.we_version_compiled > 16))
+ {
+ /* Some driver may return very large scan results, either
+ * because there are many cells, or because they have many
+ * large elements in cells (like IWEVCUSTOM). Most will
+ * only need the regular sized buffer. We now use a dynamic
+ * allocation of the buffer to satisfy everybody. Of course,
+ * as we don't know in advance the size of the array, we try
+ * various increasing sizes. Jean II */
+
+ /* Check if the driver gave us any hints. */
+ if(wrq.u.data.length > buflen)
+ buflen = wrq.u.data.length;
+ else
+ buflen *= 2;
+
+ /* Try again */
+ goto realloc;
+ }
+
+ /* Check if results not available yet */
+ if(errno == EAGAIN)
+ {
+ /* Restart timer for only 100ms*/
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ timeout -= tv.tv_usec;
+ if(timeout > 0)
+ continue; /* Try again later */
+ }
+
+ /* Bad error */
+ free(buffer);
+ fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
+ ifname, strerror(errno));
+ return(-2);
+ }
+ else
+ /* We have the results, go to process them */
+ break;
+ }
+
+ /* In here, check if event and event type
+ * if scan event, read results. All errors bad & no reset timeout */
+ }
+
+ if(wrq.u.data.length)
+ {
+ struct iw_event iwe;
+ struct stream_descr stream;
+ struct iwscan_state state = { .ap_num = 1, .val_index = 0 };
+ int ret;
+
+#ifdef DEBUG
+ /* Debugging code. In theory useless, because it's debugged ;-) */
+ int i;
+ printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
+ for(i = 1; i < wrq.u.data.length; i++)
+ printf(":%02X", buffer[i]);
+ printf("]\n");
+#endif
+ printf("%-8.16s Scan completed :\n", ifname);
+ iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
+ do
+ {
+ /* Extract an event and print it */
+ ret = iw_extract_event_stream(&stream, &iwe,
+ range.we_version_compiled);
+ if(ret > 0)
+ print_scanning_token(&stream, &iwe, &state,
+ &range, has_range);
+ }
+ while(ret > 0);
+ printf("\n");
+ }
+ else
+ printf("%-8.16s No scan results\n\n", ifname);
+
+ free(buffer);
+ return(0);
+}
+
+/*********************** FREQUENCIES/CHANNELS ***********************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the number of channels and available frequency for the device
+ */
+static int
+print_freq_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ double freq;
+ int k;
+ int channel;
+ char buffer[128]; /* Temporary buffer */
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Get list of frequencies / channels */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ fprintf(stderr, "%-8.16s no frequency information.\n\n",
+ ifname);
+ else
+ {
+ if(range.num_frequency > 0)
+ {
+ printf("%-8.16s %d channels in total; available frequencies :\n",
+ ifname, range.num_channels);
+ /* Print them all */
+ for(k = 0; k < range.num_frequency; k++)
+ {
+ freq = iw_freq2float(&(range.freq[k]));
+ iw_print_freq_value(buffer, sizeof(buffer), freq);
+ printf(" Channel %.2d : %s\n",
+ range.freq[k].i, buffer);
+ }
+ }
+ else
+ printf("%-8.16s %d channels\n",
+ ifname, range.num_channels);
+
+ /* Get current frequency / channel and display it */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
+ {
+ freq = iw_freq2float(&(wrq.u.freq));
+ channel = iw_freq_to_channel(freq, &range);
+ iw_print_freq(buffer, sizeof(buffer),
+ freq, channel, wrq.u.freq.flags);
+ printf(" Current %s\n\n", buffer);
+ }
+ }
+ return(0);
+}
+
+/***************************** BITRATES *****************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the number of available bitrates for the device
+ */
+static int
+print_bitrate_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ int k;
+ char buffer[128];
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Extract range info */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ fprintf(stderr, "%-8.16s no bit-rate information.\n\n",
+ ifname);
+ else
+ {
+ if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
+ {
+ printf("%-8.16s %d available bit-rates :\n",
+ ifname, range.num_bitrates);
+ /* Print them all */
+ for(k = 0; k < range.num_bitrates; k++)
+ {
+ iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
+ /* Maybe this should be %10s */
+ printf("\t %s\n", buffer);
+ }
+ }
+ else
+ printf("%-8.16s unknown bit-rate information.\n", ifname);
+
+ /* Get current bit rate */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
+ {
+ iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
+ printf(" Current Bit Rate%c%s\n",
+ (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
+ }
+
+ /* Try to get the broadcast bitrate if it exist... */
+ if(range.bitrate_capa & IW_BITRATE_BROADCAST)
+ {
+ wrq.u.bitrate.flags = IW_BITRATE_BROADCAST;
+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
+ {
+ iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
+ printf(" Broadcast Bit Rate%c%s\n",
+ (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
+ }
+ }
+
+ printf("\n");
+ }
+ return(0);
+}
+
+/************************* ENCRYPTION KEYS *************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print all the available encryption keys for the device
+ */
+static int
+print_keys_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ unsigned char key[IW_ENCODING_TOKEN_MAX];
+ unsigned int k;
+ char buffer[128];
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Extract range info */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ fprintf(stderr, "%-8.16s no encryption keys information.\n\n",
+ ifname);
+ else
+ {
+ printf("%-8.16s ", ifname);
+ /* Print key sizes */
+ if((range.num_encoding_sizes > 0) &&
+ (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
+ {
+ printf("%d key sizes : %d", range.num_encoding_sizes,
+ range.encoding_size[0] * 8);
+ /* Print them all */
+ for(k = 1; k < range.num_encoding_sizes; k++)
+ printf(", %d", range.encoding_size[k] * 8);
+ printf("bits\n ");
+ }
+ /* Print the keys and associate mode */
+ printf("%d keys available :\n", range.max_encoding_tokens);
+ for(k = 1; k <= range.max_encoding_tokens; k++)
+ {
+ wrq.u.data.pointer = (caddr_t) key;
+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
+ wrq.u.data.flags = k;
+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
+ {
+ fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno));
+ break;
+ }
+ if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
+ (wrq.u.data.length == 0))
+ printf("\t\t[%d]: off\n", k);
+ else
+ {
+ /* Display the key */
+ iw_print_key(buffer, sizeof(buffer),
+ key, wrq.u.data.length, wrq.u.data.flags);
+ printf("\t\t[%d]: %s", k, buffer);
+
+ /* Other info... */
+ printf(" (%d bits)", wrq.u.data.length * 8);
+ printf("\n");
+ }
+ }
+ /* Print current key index and mode */
+ wrq.u.data.pointer = (caddr_t) key;
+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
+ wrq.u.data.flags = 0; /* Set index to zero to get current */
+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
+ {
+ /* Note : if above fails, we have already printed an error
+ * message int the loop above */
+ printf(" Current Transmit Key: [%d]\n",
+ wrq.u.data.flags & IW_ENCODE_INDEX);
+ if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
+ printf(" Security mode:restricted\n");
+ if(wrq.u.data.flags & IW_ENCODE_OPEN)
+ printf(" Security mode:open\n");
+ }
+
+ printf("\n\n");
+ }
+ return(0);
+}
+
+/************************* POWER MANAGEMENT *************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print Power Management info for each device
+ */
+static int
+get_pm_value(int skfd,
+ char * ifname,
+ struct iwreq * pwrq,
+ int flags,
+ char * buffer,
+ int buflen,
+ int we_version_compiled)
+{
+ /* Get Another Power Management value */
+ pwrq->u.power.flags = flags;
+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
+ {
+ /* Let's check the value and its type */
+ if(pwrq->u.power.flags & IW_POWER_TYPE)
+ {
+ iw_print_pm_value(buffer, buflen,
+ pwrq->u.power.value, pwrq->u.power.flags,
+ we_version_compiled);
+ printf("\n %s", buffer);
+ }
+ }
+ return(pwrq->u.power.flags);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print Power Management range for each type
+ */
+static void
+print_pm_value_range(char * name,
+ int mask,
+ int iwr_flags,
+ int iwr_min,
+ int iwr_max,
+ char * buffer,
+ int buflen,
+ int we_version_compiled)
+{
+ if(iwr_flags & mask)
+ {
+ int flags = (iwr_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
+ /* Display if auto or fixed */
+ printf("%s %s ; ",
+ (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
+ name);
+ /* Print the range */
+ iw_print_pm_value(buffer, buflen,
+ iwr_min, flags | IW_POWER_MIN,
+ we_version_compiled);
+ printf("%s\n ", buffer);
+ iw_print_pm_value(buffer, buflen,
+ iwr_max, flags | IW_POWER_MAX,
+ we_version_compiled);
+ printf("%s\n ", buffer);
+ }
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Power Management types of values
+ */
+static const unsigned int pm_type_flags[] = {
+ IW_POWER_PERIOD,
+ IW_POWER_TIMEOUT,
+ IW_POWER_SAVING,
+};
+static const int pm_type_flags_size = (sizeof(pm_type_flags)/sizeof(pm_type_flags[0]));
+
+/*------------------------------------------------------------------*/
+/*
+ * Print Power Management info for each device
+ */
+static int
+print_pm_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ char buffer[128];
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Extract range info */
+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+ (range.we_version_compiled < 10))
+ fprintf(stderr, "%-8.16s no power management information.\n\n",
+ ifname);
+ else
+ {
+ printf("%-8.16s ", ifname);
+
+ /* Display modes availables */
+ if(range.pm_capa & IW_POWER_MODE)
+ {
+ printf("Supported modes :\n ");
+ if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
+ printf("\t\to Receive all packets (unicast & multicast)\n ");
+ if(range.pm_capa & IW_POWER_UNICAST_R)
+ printf("\t\to Receive Unicast only (discard multicast)\n ");
+ if(range.pm_capa & IW_POWER_MULTICAST_R)
+ printf("\t\to Receive Multicast only (discard unicast)\n ");
+ if(range.pm_capa & IW_POWER_FORCE_S)
+ printf("\t\to Force sending using Power Management\n ");
+ if(range.pm_capa & IW_POWER_REPEATER)
+ printf("\t\to Repeat multicast\n ");
+ }
+ /* Display min/max period availables */
+ print_pm_value_range("period ", IW_POWER_PERIOD,
+ range.pmp_flags, range.min_pmp, range.max_pmp,
+ buffer, sizeof(buffer), range.we_version_compiled);
+ /* Display min/max timeout availables */
+ print_pm_value_range("timeout", IW_POWER_TIMEOUT,
+ range.pmt_flags, range.min_pmt, range.max_pmt,
+ buffer, sizeof(buffer), range.we_version_compiled);
+ /* Display min/max saving availables */
+ print_pm_value_range("saving ", IW_POWER_SAVING,
+ range.pms_flags, range.min_pms, range.max_pms,
+ buffer, sizeof(buffer), range.we_version_compiled);
+
+ /* Get current Power Management settings */
+ wrq.u.power.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
+ {
+ int flags = wrq.u.power.flags;
+
+ /* Is it disabled ? */
+ if(wrq.u.power.disabled)
+ printf("Current mode:off\n");
+ else
+ {
+ unsigned int pm_type = 0;
+ unsigned int pm_mask = 0;
+ unsigned int remain_mask = range.pm_capa & IW_POWER_TYPE;
+ int i = 0;
+
+ /* Let's check the mode */
+ iw_print_pm_mode(buffer, sizeof(buffer), flags);
+ printf("Current %s", buffer);
+
+ /* Let's check if nothing (simply on) */
+ if((flags & IW_POWER_MODE) == IW_POWER_ON)
+ printf("mode:on");
+
+ /* Let's check the value and its type */
+ if(wrq.u.power.flags & IW_POWER_TYPE)
+ {
+ iw_print_pm_value(buffer, sizeof(buffer),
+ wrq.u.power.value, wrq.u.power.flags,
+ range.we_version_compiled);
+ printf("\n %s", buffer);
+ }
+
+ while(1)
+ {
+ /* Deal with min/max for the current value */
+ pm_mask = 0;
+ /* If we have been returned a MIN value, ask for the MAX */
+ if(flags & IW_POWER_MIN)
+ pm_mask = IW_POWER_MAX;
+ /* If we have been returned a MAX value, ask for the MIN */
+ if(flags & IW_POWER_MAX)
+ pm_mask = IW_POWER_MIN;
+ /* If we have something to ask for... */
+ if(pm_mask)
+ {
+ pm_mask |= pm_type;
+ get_pm_value(skfd, ifname, &wrq, pm_mask,
+ buffer, sizeof(buffer),
+ range.we_version_compiled);
+ }
+
+ /* Remove current type from mask */
+ remain_mask &= ~(wrq.u.power.flags);
+
+ /* Check what other types we still have to read */
+ while(i < pm_type_flags_size)
+ {
+ pm_type = remain_mask & pm_type_flags[i];
+ if(pm_type)
+ break;
+ i++;
+ }
+ /* Nothing anymore : exit the loop */
+ if(!pm_type)
+ break;
+
+ /* Ask for this other type of value */
+ flags = get_pm_value(skfd, ifname, &wrq, pm_type,
+ buffer, sizeof(buffer),
+ range.we_version_compiled);
+ /* Loop back for min/max */
+ }
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+ return(0);
+}
+
+#ifndef WE_ESSENTIAL
+/************************** TRANSMIT POWER **************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the number of available transmit powers for the device
+ */
+static int
+print_txpower_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ int dbm;
+ int mwatt;
+ int k;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Extract range info */
+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+ (range.we_version_compiled < 10))
+ fprintf(stderr, "%-8.16s no transmit-power information.\n\n",
+ ifname);
+ else
+ {
+ if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
+ printf("%-8.16s unknown transmit-power information.\n\n", ifname);
+ else
+ {
+ printf("%-8.16s %d available transmit-powers :\n",
+ ifname, range.num_txpower);
+ /* Print them all */
+ for(k = 0; k < range.num_txpower; k++)
+ {
+ /* Check for relative values */
+ if(range.txpower_capa & IW_TXPOW_RELATIVE)
+ {
+ printf("\t %d (no units)\n", range.txpower[k]);
+ }
+ else
+ {
+ if(range.txpower_capa & IW_TXPOW_MWATT)
+ {
+ dbm = iw_mwatt2dbm(range.txpower[k]);
+ mwatt = range.txpower[k];
+ }
+ else
+ {
+ dbm = range.txpower[k];
+ mwatt = iw_dbm2mwatt(range.txpower[k]);
+ }
+ printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
+ }
+ }
+ }
+
+ /* Get current Transmit Power */
+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
+ {
+ printf(" Current Tx-Power");
+ /* Disabled ? */
+ if(wrq.u.txpower.disabled)
+ printf(":off\n\n");
+ else
+ {
+ /* Fixed ? */
+ if(wrq.u.txpower.fixed)
+ printf("=");
+ else
+ printf(":");
+ /* Check for relative values */
+ if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
+ {
+ /* I just hate relative value, because they are
+ * driver specific, so not very meaningfull to apps.
+ * But, we have to support that, because
+ * this is the way hardware is... */
+ printf("\t %d (no units)\n", wrq.u.txpower.value);
+ }
+ else
+ {
+ if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
+ {
+ dbm = iw_mwatt2dbm(wrq.u.txpower.value);
+ mwatt = wrq.u.txpower.value;
+ }
+ else
+ {
+ dbm = wrq.u.txpower.value;
+ mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
+ }
+ printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
+ }
+ }
+ }
+ }
+ return(0);
+}
+
+/*********************** RETRY LIMIT/LIFETIME ***********************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print one retry value
+ */
+static int
+get_retry_value(int skfd,
+ char * ifname,
+ struct iwreq * pwrq,
+ int flags,
+ char * buffer,
+ int buflen,
+ int we_version_compiled)
+{
+ /* Get Another retry value */
+ pwrq->u.retry.flags = flags;
+ if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
+ {
+ /* Let's check the value and its type */
+ if(pwrq->u.retry.flags & IW_RETRY_TYPE)
+ {
+ iw_print_retry_value(buffer, buflen,
+ pwrq->u.retry.value, pwrq->u.retry.flags,
+ we_version_compiled);
+ printf("%s\n ", buffer);
}
- else
- state->val_index++;
- break;
- case IWEVQUAL:
- {
- iw_print_stats(buffer, sizeof(buffer),
- &event->u.qual, iw_range, has_range);
- printf(" %s\n", buffer);
- break;
- }
- case IWEVGENIE:
- /* Informations Elements are complex, let's do only some of them */
- iw_print_gen_ie(event->u.data.pointer, event->u.data.length);
- break;
- case IWEVCUSTOM:
- {
- char custom[IW_CUSTOM_MAX+1];
- if((event->u.data.pointer) && (event->u.data.length))
- memcpy(custom, event->u.data.pointer, event->u.data.length);
- custom[event->u.data.length] = '\0';
- printf(" Extra:%s\n", custom);
- }
- break;
- default:
- printf(" (Unknown Wireless Token 0x%04X)\n",
- event->cmd);
- } /* switch(event->cmd) */
+ }
+ return(pwrq->u.retry.flags);
}
/*------------------------------------------------------------------*/
/*
- * Perform a scanning on one device
+ * Print Power Management range for each type
+ */
+static void
+print_retry_value_range(char * name,
+ int mask,
+ int iwr_flags,
+ int iwr_min,
+ int iwr_max,
+ char * buffer,
+ int buflen,
+ int we_version_compiled)
+{
+ if(iwr_flags & mask)
+ {
+ int flags = (iwr_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
+ /* Display if auto or fixed */
+ printf("%s %s ; ",
+ (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
+ name);
+ /* Print the range */
+ iw_print_retry_value(buffer, buflen,
+ iwr_min, flags | IW_POWER_MIN,
+ we_version_compiled);
+ printf("%s\n ", buffer);
+ iw_print_retry_value(buffer, buflen,
+ iwr_max, flags | IW_POWER_MAX,
+ we_version_compiled);
+ printf("%s\n ", buffer);
+ }
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print Retry info for each device
*/
static int
-print_scanning_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
+print_retry_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
{
struct iwreq wrq;
- unsigned char * buffer = NULL; /* Results */
- int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
struct iw_range range;
- int has_range;
- struct timeval tv; /* Select timeout */
- int timeout = 15000000; /* 15s */
+ char buffer[128];
/* Avoid "Unused parameter" warning */
args = args; count = count;
- /* Get range stuff */
- has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
-
- /* Check if the interface could support scanning. */
- if((!has_range) || (range.we_version_compiled < 14))
+ /* Extract range info */
+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+ (range.we_version_compiled < 11))
+ fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n",
+ ifname);
+ else
{
- fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n",
- ifname);
- return(-1);
- }
-
- /* Init timeout value -> 250ms*/
- tv.tv_sec = 0;
- tv.tv_usec = 250000;
+ printf("%-8.16s ", ifname);
- /*
- * Here we should look at the command line args and set the IW_SCAN_ flags
- * properly
- */
- wrq.u.data.pointer = NULL; /* Later */
- wrq.u.data.flags = 0;
- wrq.u.data.length = 0;
+ /* Display min/max limit availables */
+ print_retry_value_range("limit ", IW_RETRY_LIMIT, range.retry_flags,
+ range.min_retry, range.max_retry,
+ buffer, sizeof(buffer),
+ range.we_version_compiled);
+ /* Display min/max lifetime availables */
+ print_retry_value_range("lifetime", IW_RETRY_LIFETIME,
+ range.r_time_flags,
+ range.min_r_time, range.max_r_time,
+ buffer, sizeof(buffer),
+ range.we_version_compiled);
- /* Initiate Scanning */
- if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
- {
- if(errno != EPERM)
+ /* Get current retry settings */
+ wrq.u.retry.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
{
- fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
- ifname, strerror(errno));
- return(-1);
- }
- /* If we don't have the permission to initiate the scan, we may
- * still have permission to read left-over results.
- * But, don't wait !!! */
-#if 0
- /* Not cool, it display for non wireless interfaces... */
- fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
-#endif
- tv.tv_usec = 0;
- }
- timeout -= tv.tv_usec;
-
- /* Forever */
- while(1)
- {
- fd_set rfds; /* File descriptors for select */
- int last_fd; /* Last fd */
- int ret;
-
- /* Guess what ? We must re-generate rfds each time */
- FD_ZERO(&rfds);
- last_fd = -1;
+ int flags = wrq.u.retry.flags;
- /* In here, add the rtnetlink fd in the list */
+ /* Is it disabled ? */
+ if(wrq.u.retry.disabled)
+ printf("Current mode:off\n ");
+ else
+ {
+ unsigned int retry_type = 0;
+ unsigned int retry_mask = 0;
+ unsigned int remain_mask = range.retry_capa & IW_RETRY_TYPE;
- /* Wait until something happens */
- ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
+ /* Let's check the mode */
+ printf("Current mode:on\n ");
- /* Check if there was an error */
- if(ret < 0)
- {
- if(errno == EAGAIN || errno == EINTR)
- continue;
- fprintf(stderr, "Unhandled signal - exiting...\n");
- return(-1);
- }
+ /* Let's check the value and its type */
+ if(wrq.u.retry.flags & IW_RETRY_TYPE)
+ {
+ iw_print_retry_value(buffer, sizeof(buffer),
+ wrq.u.retry.value, wrq.u.retry.flags,
+ range.we_version_compiled);
+ printf("%s\n ", buffer);
+ }
- /* Check if there was a timeout */
- if(ret == 0)
- {
- unsigned char * newbuf;
+ while(1)
+ {
+ /* Deal with min/max/short/long for the current value */
+ retry_mask = 0;
+ /* If we have been returned a MIN value, ask for the MAX */
+ if(flags & IW_RETRY_MIN)
+ retry_mask = IW_RETRY_MAX;
+ /* If we have been returned a MAX value, ask for the MIN */
+ if(flags & IW_RETRY_MAX)
+ retry_mask = IW_RETRY_MIN;
+ /* Same for SHORT and LONG */
+ if(flags & IW_RETRY_SHORT)
+ retry_mask = IW_RETRY_LONG;
+ if(flags & IW_RETRY_LONG)
+ retry_mask = IW_RETRY_SHORT;
+ /* If we have something to ask for... */
+ if(retry_mask)
+ {
+ retry_mask |= retry_type;
+ get_retry_value(skfd, ifname, &wrq, retry_mask,
+ buffer, sizeof(buffer),
+ range.we_version_compiled);
+ }
- realloc:
- /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
- newbuf = realloc(buffer, buflen);
- if(newbuf == NULL)
- {
- if(buffer)
- free(buffer);
- fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
- return(-1);
+ /* And if we have both a limit and a lifetime,
+ * ask the other one */
+ remain_mask &= ~(wrq.u.retry.flags);
+ retry_type = remain_mask;
+ /* Nothing anymore : exit the loop */
+ if(!retry_type)
+ break;
+
+ /* Ask for this other type of value */
+ flags = get_retry_value(skfd, ifname, &wrq, retry_type,
+ buffer, sizeof(buffer),
+ range.we_version_compiled);
+ /* Loop back for min/max/short/long */
+ }
}
- buffer = newbuf;
+ }
+ printf("\n");
+ }
+ return(0);
+}
- /* Try to read the results */
- wrq.u.data.pointer = buffer;
- wrq.u.data.flags = 0;
- wrq.u.data.length = buflen;
- if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
- {
- /* Check if buffer was too small (WE-17 only) */
- if((errno == E2BIG) && (range.we_version_compiled > 16))
- {
- /* Some driver may return very large scan results, either
- * because there are many cells, or because they have many
- * large elements in cells (like IWEVCUSTOM). Most will
- * only need the regular sized buffer. We now use a dynamic
- * allocation of the buffer to satisfy everybody. Of course,
- * as we don't know in advance the size of the array, we try
- * various increasing sizes. Jean II */
+/************************ ACCESS POINT LIST ************************/
+/*
+ * Note : now that we have scanning support, this is depracted and
+ * won't survive long. Actually, next version it's out !
+ */
- /* Check if the driver gave us any hints. */
- if(wrq.u.data.length > buflen)
- buflen = wrq.u.data.length;
- else
- buflen *= 2;
+/*------------------------------------------------------------------*/
+/*
+ * Display the list of ap addresses and the associated stats
+ * Exacly the same as the spy list, only with different IOCTL and messages
+ */
+static int
+print_ap_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ char buffer[(sizeof(struct iw_quality) +
+ sizeof(struct sockaddr)) * IW_MAX_AP];
+ char temp[128];
+ struct sockaddr * hwa;
+ struct iw_quality * qual;
+ iwrange range;
+ int has_range = 0;
+ int has_qual = 0;
+ int n;
+ int i;
- /* Try again */
- goto realloc;
- }
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
- /* Check if results not available yet */
- if(errno == EAGAIN)
- {
- /* Restart timer for only 100ms*/
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
- timeout -= tv.tv_usec;
- if(timeout > 0)
- continue; /* Try again later */
- }
+ /* Collect stats */
+ wrq.u.data.pointer = (caddr_t) buffer;
+ wrq.u.data.length = IW_MAX_AP;
+ wrq.u.data.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
+ {
+ fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
+ return(-1);
+ }
- /* Bad error */
- free(buffer);
- fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
- ifname, strerror(errno));
- return(-2);
- }
- else
- /* We have the results, go to process them */
- break;
- }
+ /* Number of addresses */
+ n = wrq.u.data.length;
+ has_qual = wrq.u.data.flags;
- /* In here, check if event and event type
- * if scan event, read results. All errors bad & no reset timeout */
+ /* The two lists */
+ hwa = (struct sockaddr *) buffer;
+ qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
+
+ /* Check if we have valid mac address type */
+ if(iw_check_mac_addr_type(skfd, ifname) < 0)
+ {
+ fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
+ return(-2);
}
- if(wrq.u.data.length)
+ /* Get range info if we can */
+ if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
+ has_range = 1;
+
+ /* Display it */
+ if(n == 0)
+ printf("%-8.16s No Peers/Access-Point in range\n", ifname);
+ else
+ printf("%-8.16s Peers/Access-Points in range:\n", ifname);
+ for(i = 0; i < n; i++)
{
- struct iw_event iwe;
- struct stream_descr stream;
- struct iwscan_state state = { .ap_num = 1, .val_index = 0 };
- int ret;
-
-#if 0
- /* Debugging code. In theory useless, because it's debugged ;-) */
- int i;
- printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
- for(i = 1; i < wrq.u.data.length; i++)
- printf(":%02X", buffer[i]);
- printf("]\n");
-#endif
- printf("%-8.16s Scan completed :\n", ifname);
- iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
- do
+ if(has_qual)
{
- /* Extract an event and print it */
- ret = iw_extract_event_stream(&stream, &iwe,
- range.we_version_compiled);
- if(ret > 0)
- print_scanning_token(&stream, &iwe, &state,
- &range, has_range);
+ /* Print stats for this address */
+ printf(" %s : ", iw_saether_ntop(&hwa[i], temp));
+ iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
+ printf("%s\n", temp);
}
- while(ret > 0);
- printf("\n");
+ else
+ /* Only print the address */
+ printf(" %s\n", iw_saether_ntop(&hwa[i], temp));
}
- else
- printf("%-8.16s No scan results\n", ifname);
-
- free(buffer);
+ printf("\n");
return(0);
}
/*------------------------------------------------------------------*/
/*
- * Print the number of available transmit powers for the device
+ * Print the event capability for the device
*/
static int
print_event_capa_info(int skfd,
ifname);
else
{
-#if 0
+#ifdef DEBUG
/* Debugging ;-) */
for(cmd = 0x8B00; cmd < 0x8C0F; cmd++)
{
return(0);
}
+/*************************** WPA SUPPORT ***************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the authentication parameters for the device
+ */
+static int
+print_auth_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ unsigned int k;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Extract range info */
+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+ (range.we_version_compiled < 18))
+ fprintf(stderr, "%-8.16s no authentication information.\n\n",
+ ifname);
+ else
+ {
+ /* Print WPA/802.1x/802.11i security parameters */
+ if(!range.enc_capa)
+ {
+ printf("%-8.16s unknown authentication information.\n\n", ifname);
+ }
+ else
+ {
+ /* Display advanced encryption capabilities */
+ printf("%-8.16s Authentication capabilities :", ifname);
+ iw_print_mask_name(range.enc_capa,
+ iw_auth_capa_name, IW_AUTH_CAPA_NUM,
+ "\n\t\t");
+ printf("\n");
+
+ /* Extract all auth settings */
+ for(k = 0; k < IW_AUTH_SETTINGS_NUM; k++)
+ {
+ wrq.u.param.flags = iw_auth_settings[k].value;
+ if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
+ {
+ printf(" Current %s :", iw_auth_settings[k].label);
+ if(iw_auth_settings[k].names != NULL)
+ iw_print_mask_name(wrq.u.param.value,
+ iw_auth_settings[k].names,
+ iw_auth_settings[k].num_names,
+ "\n\t\t");
+ else
+ printf((wrq.u.param.value) ? " yes" : " no");
+ printf("\n");
+ }
+ }
+ }
+
+ printf("\n\n");
+ }
+ return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print all the available wpa keys for the device
+ */
+static int
+print_wpakeys_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ unsigned char extbuf[IW_EXTKEY_SIZE];
+ struct iw_encode_ext *extinfo;
+ unsigned int k;
+ char buffer[128];
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* This always point to the same place */
+ extinfo = (struct iw_encode_ext *) extbuf;
+
+ /* Extract range info */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ fprintf(stderr, "%-8.16s no wpa key information.\n\n",
+ ifname);
+ else
+ {
+ printf("%-8.16s ", ifname);
+ /* Print key sizes */
+ if((range.num_encoding_sizes > 0) &&
+ (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
+ {
+ printf("%d key sizes : %d", range.num_encoding_sizes,
+ range.encoding_size[0] * 8);
+ /* Print them all */
+ for(k = 1; k < range.num_encoding_sizes; k++)
+ printf(", %d", range.encoding_size[k] * 8);
+ printf("bits\n ");
+ }
+
+ /* Print the keys */
+ printf("%d keys available :\n", range.max_encoding_tokens);
+ for(k = 1; k <= range.max_encoding_tokens; k++)
+ {
+ /* Cleanup. Driver may not fill everything */
+ memset(extbuf, '\0', IW_EXTKEY_SIZE);
+
+ /* Get whole struct containing one WPA key */
+ wrq.u.data.pointer = (caddr_t) extbuf;
+ wrq.u.data.length = IW_EXTKEY_SIZE;
+ wrq.u.data.flags = k;
+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) < 0)
+ {
+ fprintf(stderr, "Error reading wpa keys (SIOCGIWENCODEEXT): %s\n", strerror(errno));
+ break;
+ }
+
+ /* Sanity check */
+ if(wrq.u.data.length <
+ (sizeof(struct iw_encode_ext) + extinfo->key_len))
+ break;
+
+ /* Check if key is disabled */
+ if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
+ (extinfo->key_len == 0))
+ printf("\t\t[%d]: off\n", k);
+ else
+ {
+ /* Display the key */
+ iw_print_key(buffer, sizeof(buffer),
+ extinfo->key, extinfo->key_len, wrq.u.data.flags);
+ printf("\t\t[%d]: %s", k, buffer);
+
+ /* Key size */
+ printf(" (%d bits)", extinfo->key_len * 8);
+ printf("\n");
+
+ /* Other info... */
+ printf("\t\t Address: %s\n",
+ iw_saether_ntop(&extinfo->addr, buffer));
+
+ printf("\t\t Algorithm:");
+ iw_print_value_name(extinfo->alg,
+ iw_encode_alg_name, IW_ENCODE_ALG_NUM);
+
+ printf("\n\t\t Flags: 0x%08x\n", extinfo->ext_flags);
+ if (extinfo->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID)
+ printf("\t\t tx-seq-valid\n");
+ if (extinfo->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
+ printf("\t\t rx-seq-valid\n");
+ if (extinfo->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+ printf("\t\t group-key\n");
+ }
+ }
+ /* Print current key index and mode */
+ wrq.u.data.pointer = (caddr_t) extbuf;
+ wrq.u.data.length = IW_EXTKEY_SIZE;
+ wrq.u.data.flags = 0; /* Set index to zero to get current */
+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) >= 0)
+ {
+ /* Note : if above fails, we have already printed an error
+ * message int the loop above */
+ printf(" Current Transmit Key: [%d]\n",
+ wrq.u.data.flags & IW_ENCODE_INDEX);
+ if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
+ printf(" Security mode:restricted\n");
+ if(wrq.u.data.flags & IW_ENCODE_OPEN)
+ printf(" Security mode:open\n");
+ }
+
+ printf("\n\n");
+ }
+ return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print the Generic IE for the device
+ * Note : indentation is broken. We need to fix that.
+ */
+static int
+print_gen_ie_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ unsigned char buf[IW_GENERIC_IE_MAX];
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ wrq.u.data.pointer = (caddr_t)buf;
+ wrq.u.data.length = IW_GENERIC_IE_MAX;
+ wrq.u.data.flags = 0;
+
+ if(iw_get_ext(skfd, ifname, SIOCGIWGENIE, &wrq) < 0)
+ fprintf(stderr, "%-8.16s no generic IE (%s).\n\n",
+ ifname, strerror(errno));
+ else
+ {
+ fprintf(stderr, "%-8.16s\n", ifname);
+ if(wrq.u.data.length == 0)
+ printf(" empty generic IE\n");
+ else
+ iw_print_gen_ie(buf, wrq.u.data.length);
+ printf("\n");
+ }
+ return(0);
+}
+
+/**************************** MODULATION ****************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * Print Modulation info for each device
+ */
+static int
+print_modul_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ struct iw_range range;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Extract range info */
+ if((iw_get_range_info(skfd, ifname, &range) < 0) ||
+ (range.we_version_compiled < 11))
+ fprintf(stderr, "%-8.16s no modulation information.\n\n",
+ ifname);
+ else
+ {
+ if(range.modul_capa == 0x0)
+ printf("%-8.16s unknown modulation information.\n\n", ifname);
+ else
+ {
+ int i;
+ printf("%-8.16s Modulations available :\n", ifname);
+
+ /* Display each modulation available */
+ for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
+ {
+ if((range.modul_capa & iw_modul_list[i].mask)
+ == iw_modul_list[i].mask)
+ printf(" %-8s: %s\n",
+ iw_modul_list[i].cmd, iw_modul_list[i].verbose);
+ }
+
+ /* Get current modulations settings */
+ wrq.u.param.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) >= 0)
+ {
+ unsigned int modul = wrq.u.param.value;
+ int n = 0;
+
+ printf(" Current modulations %c",
+ wrq.u.param.fixed ? '=' : ':');
+
+ /* Display each modulation enabled */
+ for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
+ {
+ if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
+ {
+ if((n++ % 8) == 0)
+ printf("\n ");
+ else
+ printf(" ; ");
+ printf("%s", iw_modul_list[i].cmd);
+ }
+ }
+
+ printf("\n");
+ }
+ printf("\n");
+ }
+ }
+ return(0);
+}
+#endif /* WE_ESSENTIAL */
+
/************************* COMMON UTILITIES *************************/
/*
* This section was initially written by Michael Tokarev <mjt@tls.msk.ru>
* Map command line arguments to the proper procedure...
*/
typedef struct iwlist_entry {
- const char *cmd;
- iw_enum_handler fn;
- int min_count;
- int max_count;
+ const char * cmd; /* Command line shorthand */
+ iw_enum_handler fn; /* Subroutine */
+ int max_count;
+ const char * argsname; /* Args as human readable string */
} iwlist_cmd;
static const struct iwlist_entry iwlist_cmds[] = {
- { "scanning", print_scanning_info, 0, 5 },
- { "frequency", print_freq_info, 0, 0 },
- { "channel", print_freq_info, 0, 0 },
- { "bitrate", print_bitrate_info, 0, 0 },
- { "rate", print_bitrate_info, 0, 0 },
- { "encryption", print_keys_info, 0, 0 },
- { "key", print_keys_info, 0, 0 },
- { "power", print_pm_info, 0, 0 },
- { "txpower", print_txpower_info, 0, 0 },
- { "retry", print_retry_info, 0, 0 },
- { "ap", print_ap_info, 0, 0 },
- { "accesspoints", print_ap_info, 0, 0 },
- { "peers", print_ap_info, 0, 0 },
- { "event", print_event_capa_info, 0, 0 },
+ { "scanning", print_scanning_info, -1, "[essid NNN] [last]" },
+ { "frequency", print_freq_info, 0, NULL },
+ { "channel", print_freq_info, 0, NULL },
+ { "bitrate", print_bitrate_info, 0, NULL },
+ { "rate", print_bitrate_info, 0, NULL },
+ { "encryption", print_keys_info, 0, NULL },
+ { "keys", print_keys_info, 0, NULL },
+ { "power", print_pm_info, 0, NULL },
+#ifndef WE_ESSENTIAL
+ { "txpower", print_txpower_info, 0, NULL },
+ { "retry", print_retry_info, 0, NULL },
+ { "ap", print_ap_info, 0, NULL },
+ { "accesspoints", print_ap_info, 0, NULL },
+ { "peers", print_ap_info, 0, NULL },
+ { "event", print_event_capa_info, 0, NULL },
+ { "auth", print_auth_info, 0, NULL },
+ { "wpakeys", print_wpakeys_info, 0, NULL },
+ { "genie", print_gen_ie_info, 0, NULL },
+ { "modulation", print_modul_info, 0, NULL },
+#endif /* WE_ESSENTIAL */
{ NULL, NULL, 0, 0 },
};
if(found == NULL)
{
- fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
+ fprintf(stderr, "iwlist: unknown command `%s' (check 'iwlist --help').\n", cmd);
return NULL;
}
if(ambig)
{
- fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
+ fprintf(stderr, "iwlist: command `%s' is ambiguous (check 'iwlist --help').\n", cmd);
return NULL;
}
*/
static void iw_usage(int status)
{
- FILE* f = status ? stderr : stdout;
- int i;
+ FILE * f = status ? stderr : stdout;
+ int i;
+
+ for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
+ {
+ fprintf(f, "%s [interface] %s %s\n",
+ (i ? " " : "Usage: iwlist"),
+ iwlist_cmds[i].cmd,
+ iwlist_cmds[i].argsname ? iwlist_cmds[i].argsname : "");
+ }
- fprintf(f, "Usage: iwlist [interface] %s\n", iwlist_cmds[0].cmd);
- for(i = 1; iwlist_cmds[i].cmd != NULL; ++i)
- fprintf(f, " [interface] %s\n", iwlist_cmds[i].cmd);
exit(status);
}
int count; /* Number of arguments */
const iwlist_cmd *iwcmd;
- if(argc == 1 || argc > 3)
+ if(argc < 2)
iw_usage(1);
/* Those don't apply to all interfaces */
return 1;
/* Check arg numbers */
- if(count < iwcmd->min_count)
- {
- fprintf(stderr, "iwlist: command `%s' needs more arguments\n", cmd);
- return 1;
- }
- if(count > iwcmd->max_count)
+ if((iwcmd->max_count >= 0) && (count > iwcmd->max_count))
{
- fprintf(stderr, "iwlist: command `%s' needs fewer arguments\n", cmd);
+ fprintf(stderr, "iwlist: command `%s' needs fewer arguments (max %d)\n",
+ iwcmd->cmd, iwcmd->max_count);
return 1;
}
/* Get iwconfig in there. Mandatory. */
#define main(args...) main_iwconfig(args)
#define iw_usage(args...) iwconfig_usage(args)
+#define find_command(args...) iwconfig_find_command(args)
#include "iwconfig.c"
+#undef find_command
#undef iw_usage
#undef main
/* Get iwlist in there. Scanning support is pretty sweet. */
#define main(args...) main_iwlist(args)
#define iw_usage(args...) iwlist_usage(args)
+#define find_command(args...) iwlist_find_command(args)
#include "iwlist.c"
+#undef find_command
#undef iw_usage
#undef main
+#ifndef WE_ESSENTIAL
/* Get iwspy in there, it's not that big. */
#define main(args...) main_iwspy(args)
#include "iwspy.c"
#undef main
+#endif /* WE_ESSENTIAL */
/* Get iwpriv in there. Mandatory for HostAP and some other drivers. */
#define main(args...) main_iwpriv(args)
return(main_iwconfig(argc, argv));
if(!strcmp(call_name, "iwlist"))
return(main_iwlist(argc, argv));
+#ifndef WE_ESSENTIAL
if(!strcmp(call_name, "iwspy"))
return(main_iwspy(argc, argv));
+#endif /* WE_ESSENTIAL */
if(!strcmp(call_name, "iwpriv"))
return(main_iwpriv(argc, argv));
if(!strcmp(call_name, "iwgetid"))
.br
.BI "iwpriv " "interface private-command " "[" private-parameters ]
.br
-.BI "iwpriv " "interface private-command [I] " "[" private-parameters ]
+.BI "iwpriv " "interface private-command " [ I "] [" private-parameters ]
.br
.BI "iwpriv " interface " --all"
-.br
-.BI "iwpriv " interface " roam " {on,off}
-.br
-.BI "iwpriv " interface " port " {ad-hoc,managed,N}
.\"
.\" DESCRIPTION part
.\"
However you should refer to the device driver documentation for
information on how to properly use the command and the effect.
.TP
-.I "private-command [I]" "[" private-parameters ]
+.IR "private-command " [ I "] [" private-parameters ]
Idem, except that
.I I
(an integer) is passed to the command as a
.BR -a / --all
Execute and display all the private commands that don't take any
arguments (i.e. read only).
-.TP
-.B roam
-Enable or disable roaming, if supported. Call the private command
-.IR setroam .
-Found in the
-.I wavelan_cs
-driver.
-.TP
-.B port
-Read or configure the port type. Call the private commands
-.IR gport_type ", " sport_type ", " get_port " or " set_port
-found in the
-.IR wavelan2_cs " and " wvlan_cs " drivers."
.\"
.\" DISPLAY part
.\"
/*
* Wireless Tools
*
- * Jean II - HPLB 97->99 - HPL 99->04
+ * Jean II - HPLB 97->99 - HPL 99->07
*
* Main code for "iwconfig". This is the generic tool for most
* manipulations...
* You need to link this code against "iwlib.c" and "-lm".
*
* This file is released under the GPL license.
- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
*/
#include "iwlib.h" /* Header */
printf("Invalid float [%s]...\n", args[i]);
return(-1);
}
- if(index(args[i], 'G')) freq *= GIGA;
- if(index(args[i], 'M')) freq *= MEGA;
- if(index(args[i], 'k')) freq *= KILO;
+ if(strchr(args[i], 'G')) freq *= GIGA;
+ if(strchr(args[i], 'M')) freq *= MEGA;
+ if(strchr(args[i], 'k')) freq *= KILO;
sscanf(args[i], "%i", &temp);
iw_float2freq(freq, ((struct iw_freq *) buffer) + i);
}
* Convenient access to some private ioctls of some devices
*/
+#if 0
/*------------------------------------------------------------------*/
/*
* Set roaming mode on and off
free(priv);
return(-1);
}
+#endif
/******************************* MAIN ********************************/
(!strcmp(argv[2], "--all")))
print_priv_all(skfd, argv[1], NULL, 0);
else
+#if 0
/* Roaming */
if(!strncmp(argv[2], "roam", 4))
goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]);
if(!strncmp(argv[2], "port", 4))
goterr = port_type(skfd, argv + 3, argc - 3, argv[1]);
else
+#endif
/*-------------*/
/* Otherwise, it's a private ioctl */
goterr = set_private(skfd, argv + 2, argc - 2, argv[1]);
.\" SYNOPSIS part
.\"
.SH SYNOPSIS
-.BI "iwspy " interface
+.BI "iwspy [" interface ]
.br
.BI "iwspy " interface " [+] " DNSNAME " | " IPADDR " | " HWADDR " [...]"
.br
/* Set period */
if(prq->flags & IW_POWER_PERIOD)
{
- int period = prq->value/1000000;
+ int period = prq->value;
+#if WIRELESS_EXT < 21
+ period /= 1000000;
+#endif
/* Hum: check if within bounds... */
/* Activate PM */
/* By default, the min */
if(!(inc_flags & IW_POWER_MAX))
{
- prq->value = local->pm_min_period * 1000000;
+ prq->value = local->pm_min_period;
+#if WIRELESS_EXT < 21
+ prq->value *= 1000000;
+#endif
prq->flags |= IW_POWER_MIN;
}
else
{
- prq->value = local->pm_max_period * 1000000;
+ prq->value = local->pm_max_period;
+#if WIRELESS_EXT < 21
+ prq->value *= 1000000;
+#endif
prq->flags |= IW_POWER_MAX;
}
}
if(inc_flags & (IW_POWER_MIN | IW_POWER_MAX))
return(-EINVAL);
else
- prq->value = local->pm_period * 1000000;
+ {
+ prq->value = local->pm_period;
+#if WIRELESS_EXT < 21
+ prq->value *= 1000000;
+#endif
+ }
}
}
else
#endif /* WIRELESS_EXT > 10 */
#if WIRELESS_EXT > 9
+#if WIRELESS_EXT < 21
range.min_pmp = 1000000; /* 1 units */
range.max_pmp = 12000000; /* 12 units */
+#else
+ range.min_pmp = 1; /* 1 units */
+ range.max_pmp = 12; /* 12 units */
+#endif
range.min_pmt = 1000; /* 1 ms */
range.max_pmt = 1000000; /* 1 s */
range.pmp_flags = IW_POWER_PERIOD | IW_POWER_RELATIVE |
--- /dev/null
+diff -u -p udev-106/udev_rules.j1.c udev-106/udev_rules.c
+--- udev-106/udev_rules.j1.c 2007-03-15 10:07:51.000000000 -0700
++++ udev-106/udev_rules.c 2007-03-15 10:09:50.000000000 -0700
+@@ -186,7 +186,16 @@ static int import_keys_into_env(struct u
+ linepos = line;
+ if (get_key(&linepos, &variable, &value) == 0) {
+ dbg("import '%s=%s'", variable, value);
+- name_list_key_add(&udev->env_list, variable, value);
++ /* handle device, renamed by external tool,
++ * returning new path */
++ if (strcmp(variable, "DEVPATH") == 0) {
++ info("updating devpath from '%s' to '%s'",
++ udev->dev->devpath, value);
++ sysfs_device_set_values(udev->dev, value,
++ NULL, NULL);
++ } else
++ name_list_key_add(&udev->env_list,
++ variable, value);
+ setenv(variable, value, 1);
+ }
+ }
+diff -u -p udev-106/udevtest.j1.c udev-106/udevtest.c
+--- udev-106/udevtest.j1.c 2007-03-15 10:39:16.000000000 -0700
++++ udev-106/udevtest.c 2007-03-15 10:42:09.000000000 -0700
+@@ -59,8 +59,13 @@ int main(int argc, char *argv[], char *e
+
+ info("version %s", UDEV_VERSION);
+ udev_config_init();
+- if (udev_log_priority < LOG_INFO)
++ if (udev_log_priority < LOG_INFO) {
++ char priority[32];
++
+ udev_log_priority = LOG_INFO;
++ sprintf(priority, "%i", udev_log_priority);
++ setenv("UDEV_LOG", priority, 1);
++ }
+
+ for (i = 1 ; i < argc; i++) {
+ char *arg = argv[i];
--- /dev/null
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version : 21 14.3.06
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands. This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ * # net/core/dev.c (two place + add include)
+ * # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ * # net/core/dev.c (two other places)
+ * # include/linux/netdevice.h (one place)
+ * # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ * # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ * # net/core/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+ * # net/core/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+/* This header is used in user-space, therefore need to be sanitised
+ * for that purpose. Those includes are usually not compatible with glibc.
+ * To know which includes to use in user-space, check iwlib.h. */
+#ifdef __KERNEL__
+#include <linux/types.h> /* for "caddr_t" et al */
+#include <linux/socket.h> /* for "struct sockaddr" et al */
+#include <linux/if.h> /* for IFNAMSIZ and co... */
+#endif /* __KERNEL__ */
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT 21
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
+ * - Encryption renamed to Encode to avoid US regulation problems
+ * - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ * - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ * - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ * - Changed my e-mail address
+ * - More 802.11 support (nickname, rate, rts, frag)
+ * - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ * - Support for 'mode of operation' (ad-hoc, managed...)
+ * - Support for unicast and multicast power saving
+ * - Change encoding to support larger tokens (>64 bits)
+ * - Updated iw_params (disable, flags) and use it for NWID
+ * - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ * - Add PM capability to range structure
+ * - Add PM modifier : MAX/MIN/RELATIVE
+ * - Add encoding option : IW_ENCODE_NOKEY
+ * - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ * - Add WE version in range (help backward/forward compatibility)
+ * - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ * - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ * - Add new statistics (frag, retry, beacon)
+ * - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ * - Document creation of new driver API.
+ * - Extract union iwreq_data from struct iwreq (for new driver API).
+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ *
+ * V13 to V14
+ * ----------
+ * - Wireless Events support : define struct iw_event
+ * - Define additional specific event numbers
+ * - Add "addr" and "param" fields in union iwreq_data
+ * - AP scanning stuff (SIOCSIWSCAN and friends)
+ *
+ * V14 to V15
+ * ----------
+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
+ * - Make struct iw_freq signed (both m & e), add explicit padding
+ * - Add IWEVCUSTOM for driver specific event/scanning token
+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
+ * - Add IW_TXPOW_RANGE for range of Tx Powers
+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ * - Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ * - Reshuffle struct iw_range for increases, add filler
+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ *
+ * V16 to V17
+ * ----------
+ * - Add flags to frequency -> auto/fixed
+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
+ * - Wireless Event capability in struct iw_range
+ * - Add support for relative TxPower (yick !)
+ *
+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
+ * ----------
+ * - Add support for WPA/WPA2
+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
+ * SIOCGIWENCODEEXT)
+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
+ * - Add SIOCSIWMLME
+ * - Add SIOCSIWPMKSA
+ * - Add struct iw_range bit field for supported encoding capabilities
+ * - Add optional scan request parameters for SIOCSIWSCAN
+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
+ * related parameters (extensible up to 4096 parameter values)
+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
+ *
+ * V18 to V19
+ * ----------
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove header includes to help user space
+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
+ *
+ * V20 to V21
+ * ----------
+ * - Remove (struct net_device *)->get_wireless_stats()
+ * - Change length in ESSID and NICK to strlen() instead of strlen()+1
+ * - Add SIOCSIWMODUL/SIOCGIWMODUL for modulation setting
+ * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ * - Add IW_POWER_SAVING power type
+ * - Power/Retry relative values no longer * 100000
+ * - Add bitrate flags for unicast/broadcast
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Wireless Identification */
+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
+#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
+ * Don't put the name of your driver there, it's useless. */
+
+/* Basic operations */
+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */
+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */
+#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */
+#define SIOCSIWMODE 0x8B06 /* set operation mode */
+#define SIOCGIWMODE 0x8B07 /* get operation mode */
+#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */
+#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */
+
+/* Informative stuff */
+#define SIOCSIWRANGE 0x8B0A /* Unused */
+#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */
+#define SIOCSIWPRIV 0x8B0C /* Unused */
+#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
+#define SIOCSIWSTATS 0x8B0E /* Unused */
+#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */
+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
+
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
+#define SIOCSIWSPY 0x8B10 /* set spy addresses */
+#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
+
+/* Access Point manipulation */
+#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
+#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */
+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */
+#define SIOCGIWSCAN 0x8B19 /* get scanning results */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
+#define SIOCGIWESSID 0x8B1B /* get ESSID */
+#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */
+#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE... */
+
+/* Other parameters useful in 802.11 and some other devices */
+#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
+#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
+#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */
+#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */
+#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */
+#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */
+#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
+#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
+/* Modulation bitmask */
+#define SIOCSIWMODUL 0x8B2E /* set Modulations settings */
+#define SIOCGIWMODUL 0x8B2F /* get Modulations settings */
+
+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
+ * fields. More than one IE may be included in the request. Setting the generic
+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
+ * are required to report the used IE as a wireless event, e.g., when
+ * associating with an AP. */
+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
+
+/* WPA : IEEE 802.11 MLME requests */
+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
+ * struct iw_mlme */
+/* WPA : Authentication mode parameters */
+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
+
+/* WPA : Extended version of encoding configuration */
+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
+
+/* WPA2 : PMKSA cache management */
+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 32 ioctl are wireless device private, for 16 commands.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+#define SIOCIWFIRSTPRIV 0x8BE0
+#define SIOCIWLASTPRIV 0x8BFF
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'odd' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command). More details in iwpriv.c.
+ * And I repeat : you are not forced to use them with iwpriv, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST 0x8B00
+#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
+
+/* Even : get (world access), odd : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/* Those are *NOT* ioctls, do not issue request on them !!! */
+/* Most events use the same identifier as ioctl requests */
+
+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
+ * (scan results); This includes id and
+ * length fields. One IWEVGENIE may
+ * contain more than one IE. Scan
+ * results may contain one or more
+ * IWEVGENIE events. */
+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
+ * (struct iw_michaelmicfailure)
+ */
+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
+ * The data includes id and length
+ * fields and may contain more than one
+ * IE. This event is required in
+ * Managed mode if the driver
+ * generates its own WPA/RSN IE. This
+ * should be sent just before
+ * IWEVREGISTERED event for the
+ * association. */
+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
+ * Response. The data includes id and
+ * length fields and may contain more
+ * than one IE. This may be sent
+ * between IWEVASSOCREQIE and
+ * IWEVREGISTERED events for the
+ * association. */
+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
+ * pre-authentication
+ * (struct iw_pmkid_cand) */
+
+#define IWEVFIRST 0x8C00
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */
+#define IW_PRIV_TYPE_NONE 0x0000
+#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
+#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
+#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
+
+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
+
+#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+#define IW_MAX_FREQUENCIES 32
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+#define IW_MAX_BITRATES 32
+
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER 8
+/* Note : if you more than 8 TXPowers, just set the max and min or
+ * a few of them in the struct iw_range. */
+
+/* Maximum of address that you may set with SPY */
+#define IW_MAX_SPY 8
+
+/* Maximum of address that you may get in the
+ list of access points in range */
+#define IW_MAX_AP 64
+
+/* Maximum size of the ESSID and NICKN strings */
+#define IW_ESSID_MAX_SIZE 32
+
+/* Modes of operation */
+#define IW_MODE_AUTO 0 /* Let the driver decides */
+#define IW_MODE_ADHOC 1 /* Single cell network */
+#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */
+#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
+#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
+#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
+
+/* Statistics flags (bitmask in updated) */
+#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
+#define IW_QUAL_LEVEL_UPDATED 0x02
+#define IW_QUAL_NOISE_UPDATED 0x04
+#define IW_QUAL_ALL_UPDATED 0x07
+#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
+#define IW_QUAL_LEVEL_INVALID 0x20
+#define IW_QUAL_NOISE_INVALID 0x40
+#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */
+#define IW_QUAL_ALL_INVALID 0x70
+
+/* Frequency flags */
+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
+
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+#define IW_MAX_ENCODING_SIZES 8
+
+/* Maximum size of the encoding token in bytes */
+#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
+#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
+#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
+#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
+#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
+#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
+#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
+
+/* Power management flags available (along with the value, if any) */
+#define IW_POWER_ON 0x0000 /* No details... */
+#define IW_POWER_TYPE 0xF000 /* Type of parameter */
+#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */
+#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */
+#define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/
+#define IW_POWER_MODE 0x0F00 /* Power Management mode */
+#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */
+#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */
+#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */
+#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */
+#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
+#define IW_POWER_MIN 0x0001 /* Value is a minimum */
+#define IW_POWER_MAX 0x0002 /* Value is a maximum */
+#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_TYPE 0x00FF /* Type of value */
+#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
+#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
+
+/* Retry limits and lifetime flags available */
+#define IW_RETRY_ON 0x0000 /* No details... */
+#define IW_RETRY_TYPE 0xF000 /* Type of parameter */
+#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/
+#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */
+#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */
+#define IW_RETRY_MIN 0x0001 /* Value is a minimum */
+#define IW_RETRY_MAX 0x0002 /* Value is a maximum */
+#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */
+#define IW_RETRY_LONG 0x0020 /* Value is for long packets */
+
+/* Scanning request flags */
+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
+/* struct iw_scan_req scan_type */
+#define IW_SCAN_TYPE_ACTIVE 0
+#define IW_SCAN_TYPE_PASSIVE 1
+/* Maximum size of returned data */
+#define IW_SCAN_MAX_DATA 4096 /* In bytes */
+
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX 256 /* In bytes */
+
+/* Generic information element */
+#define IW_GENERIC_IE_MAX 1024
+
+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
+#define IW_MLME_DEAUTH 0
+#define IW_MLME_DISASSOC 1
+
+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
+#define IW_AUTH_INDEX 0x0FFF
+#define IW_AUTH_FLAGS 0xF000
+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
+ * parameter that is being set/get to; value will be read/written to
+ * struct iw_param value field) */
+#define IW_AUTH_WPA_VERSION 0
+#define IW_AUTH_CIPHER_PAIRWISE 1
+#define IW_AUTH_CIPHER_GROUP 2
+#define IW_AUTH_KEY_MGMT 3
+#define IW_AUTH_TKIP_COUNTERMEASURES 4
+#define IW_AUTH_DROP_UNENCRYPTED 5
+#define IW_AUTH_80211_AUTH_ALG 6
+#define IW_AUTH_WPA_ENABLED 7
+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
+#define IW_AUTH_ROAMING_CONTROL 9
+#define IW_AUTH_PRIVACY_INVOKED 10
+
+/* IW_AUTH_WPA_VERSION values (bit field) */
+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
+
+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
+#define IW_AUTH_CIPHER_NONE 0x00000001
+#define IW_AUTH_CIPHER_WEP40 0x00000002
+#define IW_AUTH_CIPHER_TKIP 0x00000004
+#define IW_AUTH_CIPHER_CCMP 0x00000008
+#define IW_AUTH_CIPHER_WEP104 0x00000010
+
+/* IW_AUTH_KEY_MGMT values (bit field) */
+#define IW_AUTH_KEY_MGMT_802_1X 1
+#define IW_AUTH_KEY_MGMT_PSK 2
+
+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
+#define IW_AUTH_ALG_LEAP 0x00000004
+
+/* IW_AUTH_ROAMING_CONTROL values */
+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
+ * control */
+
+/* SIOCSIWENCODEEXT definitions */
+#define IW_ENCODE_SEQ_MAX_SIZE 8
+/* struct iw_encode_ext ->alg */
+#define IW_ENCODE_ALG_NONE 0
+#define IW_ENCODE_ALG_WEP 1
+#define IW_ENCODE_ALG_TKIP 2
+#define IW_ENCODE_ALG_CCMP 3
+/* struct iw_encode_ext ->ext_flags */
+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
+
+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
+#define IW_MICFAILURE_GROUP 0x00000004
+#define IW_MICFAILURE_PAIRWISE 0x00000008
+#define IW_MICFAILURE_STAKEY 0x00000010
+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
+ */
+
+/* Bit field values for enc_capa in struct iw_range */
+#define IW_ENC_CAPA_WPA 0x00000001
+#define IW_ENC_CAPA_WPA2 0x00000002
+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
+
+/* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
+ (cmd - SIOCSIWCOMMIT))
+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
+/* Event capability constants - event autogenerated by the kernel
+ * This list is valid for most 802.11 devices, customise as needed... */
+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
+ IW_EVENT_CAPA_MASK(0x8B06) | \
+ IW_EVENT_CAPA_MASK(0x8B1A))
+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
+/* "Easy" macro to set events in iw_range (less efficient) */
+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
+
+/* Modulations bitmasks */
+#define IW_MODUL_ALL 0x00000000 /* Everything supported */
+#define IW_MODUL_FH 0x00000001 /* Frequency Hopping */
+#define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */
+#define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */
+#define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK)
+#define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */
+#define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */
+#define IW_MODUL_11A (IW_MODUL_OFDM_A)
+#define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A)
+#define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */
+#define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G)
+#define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A)
+#define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */
+/* In here we should define MIMO stuff. Later... */
+#define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */
+
+/* Bitrate flags available */
+#define IW_BITRATE_TYPE 0x00FF /* Type of value */
+#define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */
+#define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ * Generic format for most parameters that fit in an int
+ */
+struct iw_param
+{
+ __s32 value; /* The value of the parameter itself */
+ __u8 fixed; /* Hardware should not use auto select */
+ __u8 disabled; /* Disable the feature */
+ __u16 flags; /* Various specifc flags (if any) */
+};
+
+/*
+ * For all data larger than 16 octets, we need to use a
+ * pointer to memory allocated in user space.
+ */
+struct iw_point
+{
+ void __user *pointer; /* Pointer to the data (in user space) */
+ __u16 length; /* number of fields or size in bytes */
+ __u16 flags; /* Optional params */
+};
+
+/*
+ * A frequency
+ * For numbers lower than 10^9, we encode the number in 'm' and
+ * set 'e' to 0
+ * For number greater than 10^9, we divide it by the lowest power
+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ * The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq
+{
+ __s32 m; /* Mantissa */
+ __s16 e; /* Exponent */
+ __u8 i; /* List index (when in range struct) */
+ __u8 flags; /* Flags (fixed/auto) */
+};
+
+/*
+ * Quality of the link
+ */
+struct iw_quality
+{
+ __u8 qual; /* link quality (%retries, SNR,
+ %missed beacons or better...) */
+ __u8 level; /* signal level (dBm) */
+ __u8 noise; /* noise level (dBm) */
+ __u8 updated; /* Flags to know if updated */
+};
+
+/*
+ * Packet discarded in the wireless adapter due to
+ * "wireless" specific problems...
+ * Note : the list of counter and statistics in net_device_stats
+ * is already pretty exhaustive, and you should use that first.
+ * This is only additional stats...
+ */
+struct iw_discarded
+{
+ __u32 nwid; /* Rx : Wrong nwid/essid */
+ __u32 code; /* Rx : Unable to code/decode (WEP) */
+ __u32 fragment; /* Rx : Can't perform MAC reassembly */
+ __u32 retries; /* Tx : Max MAC retries num reached */
+ __u32 misc; /* Others cases */
+};
+
+/*
+ * Packet/Time period missed in the wireless adapter due to
+ * "wireless" specific problems...
+ */
+struct iw_missed
+{
+ __u32 beacon; /* Missed beacons/superframe */
+};
+
+/*
+ * Quality range (for spy threshold)
+ */
+struct iw_thrspy
+{
+ struct sockaddr addr; /* Source address (hw/mac) */
+ struct iw_quality qual; /* Quality of the link */
+ struct iw_quality low; /* Low threshold */
+ struct iw_quality high; /* High threshold */
+};
+
+/*
+ * Optional data for scan request
+ *
+ * Note: these optional parameters are controlling parameters for the
+ * scanning behavior, these do not apply to getting scan results
+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
+ * provide a merged results with all BSSes even if the previous scan
+ * request limited scanning to a subset, e.g., by specifying an SSID.
+ * Especially, scan results are required to include an entry for the
+ * current BSS if the driver is in Managed mode and associated with an AP.
+ */
+struct iw_scan_req
+{
+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
+ __u8 essid_len;
+ __u8 num_channels; /* num entries in channel_list;
+ * 0 = scan all allowed channels */
+ __u8 flags; /* reserved as padding; use zero, this may
+ * be used in the future for adding flags
+ * to request different scan behavior */
+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
+ * individual address of a specific BSS */
+
+ /*
+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
+ * the current ESSID. This allows scan requests for specific ESSID
+ * without having to change the current ESSID and potentially breaking
+ * the current association.
+ */
+ __u8 essid[IW_ESSID_MAX_SIZE];
+
+ /*
+ * Optional parameters for changing the default scanning behavior.
+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
+ * reasonable default values. min_channel_time defines the time that
+ * will be used to wait for the first reply on each channel. If no
+ * replies are received, next channel will be scanned after this. If
+ * replies are received, total time waited on the channel is defined by
+ * max_channel_time.
+ */
+ __u32 min_channel_time; /* in TU */
+ __u32 max_channel_time; /* in TU */
+
+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
+};
+
+/* ------------------------- WPA SUPPORT ------------------------- */
+
+/*
+ * Extended data structure for get/set encoding (this is used with
+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
+ * only the data contents changes (key data -> this structure, including
+ * key data).
+ *
+ * If the new key is the first group key, it will be set as the default
+ * TX key. Otherwise, default TX key index is only changed if
+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
+ *
+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
+ * special "change TX key index" operation which is indicated by setting
+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
+ *
+ * tx_seq/rx_seq are only used when respective
+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
+ * used only by an Authenticator (AP or an IBSS station) to get the
+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
+ * debugging/testing.
+ */
+struct iw_encode_ext
+{
+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+ * (group) keys or unicast address for
+ * individual keys */
+ __u16 alg; /* IW_ENCODE_ALG_* */
+ __u16 key_len;
+ __u8 key[0];
+};
+
+/* SIOCSIWMLME data */
+struct iw_mlme
+{
+ __u16 cmd; /* IW_MLME_* */
+ __u16 reason_code;
+ struct sockaddr addr;
+};
+
+/* SIOCSIWPMKSA data */
+#define IW_PMKSA_ADD 1
+#define IW_PMKSA_REMOVE 2
+#define IW_PMKSA_FLUSH 3
+
+#define IW_PMKID_LEN 16
+
+struct iw_pmksa
+{
+ __u32 cmd; /* IW_PMKSA_* */
+ struct sockaddr bssid;
+ __u8 pmkid[IW_PMKID_LEN];
+};
+
+/* IWEVMICHAELMICFAILURE data */
+struct iw_michaelmicfailure
+{
+ __u32 flags;
+ struct sockaddr src_addr;
+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+};
+
+/* IWEVPMKIDCAND data */
+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
+struct iw_pmkid_cand
+{
+ __u32 flags; /* IW_PMKID_CAND_* */
+ __u32 index; /* the smaller the index, the higher the
+ * priority */
+ struct sockaddr bssid;
+};
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics
+{
+ __u16 status; /* Status
+ * - device dependent for now */
+
+ struct iw_quality qual; /* Quality of the link
+ * (instant/mean/max) */
+ struct iw_discarded discard; /* Packet discarded counts */
+ struct iw_missed miss; /* Packet missed counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ */
+union iwreq_data
+{
+ /* Config - generic */
+ char name[IFNAMSIZ];
+ /* Name : used to verify the presence of wireless extensions.
+ * Name of the protocol/provider... */
+
+ struct iw_point essid; /* Extended network name */
+ struct iw_param nwid; /* network id (or domain - the cell) */
+ struct iw_freq freq; /* frequency or channel :
+ * 0-1000 = channel
+ * > 1000 = frequency in Hz */
+
+ struct iw_param sens; /* signal level threshold */
+ struct iw_param bitrate; /* default bit rate */
+ struct iw_param txpower; /* default transmit power */
+ struct iw_param rts; /* RTS threshold threshold */
+ struct iw_param frag; /* Fragmentation threshold */
+ __u32 mode; /* Operation mode */
+ struct iw_param retry; /* Retry limits & lifetime */
+
+ struct iw_point encoding; /* Encoding stuff : tokens */
+ struct iw_param power; /* PM duration/timeout */
+ struct iw_quality qual; /* Quality part of statistics */
+
+ struct sockaddr ap_addr; /* Access point address */
+ struct sockaddr addr; /* Destination address (hw/mac) */
+
+ struct iw_param param; /* Other small parameters */
+ struct iw_point data; /* Other large parameters */
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+ */
+struct iwreq
+{
+ union
+ {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
+ } ifr_ifrn;
+
+ /* Data part (defined just above) */
+ union iwreq_data u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ * For those ioctl which want to exchange mode data that what could
+ * fit in the above structure...
+ */
+
+/*
+ * Range of parameters
+ */
+
+struct iw_range
+{
+ /* Informative stuff (to choose between different interface) */
+ __u32 throughput; /* To give an idea... */
+ /* In theory this value should be the maximum benchmarked
+ * TCP/IP throughput, because with most of these devices the
+ * bit rate is meaningless (overhead an co) to estimate how
+ * fast the connection will go and pick the fastest one.
+ * I suggest people to play with Netperf or any benchmark...
+ */
+
+ /* NWID (or domain id) */
+ __u32 min_nwid; /* Minimal NWID we are able to set */
+ __u32 max_nwid; /* Maximal NWID we are able to set */
+
+ /* Old Frequency (backward compat - moved lower ) */
+ __u16 old_num_channels;
+ __u8 old_num_frequency;
+
+ /* Wireless event capability bitmasks */
+ __u32 event_capa[6];
+
+ /* signal level threshold range */
+ __s32 sensitivity;
+
+ /* Quality of link & SNR stuff */
+ /* Quality range (link, level, noise)
+ * If the quality is absolute, it will be in the range [0 ; max_qual],
+ * if the quality is dBm, it will be in the range [max_qual ; 0].
+ * Don't forget that we use 8 bit arithmetics... */
+ struct iw_quality max_qual; /* Quality of the link */
+ /* This should contain the average/typical values of the quality
+ * indicator. This should be the threshold between a "good" and
+ * a "bad" link (example : monitor going from green to orange).
+ * Currently, user space apps like quality monitors don't have any
+ * way to calibrate the measurement. With this, they can split
+ * the range between 0 and max_qual in different quality level
+ * (using a geometric subdivision centered on the average).
+ * I expect that people doing the user space apps will feedback
+ * us on which value we need to put in each driver... */
+ struct iw_quality avg_qual; /* Quality of the link */
+
+ /* Rates */
+ __u8 num_bitrates; /* Number of entries in the list */
+ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */
+
+ /* RTS threshold */
+ __s32 min_rts; /* Minimal RTS threshold */
+ __s32 max_rts; /* Maximal RTS threshold */
+
+ /* Frag threshold */
+ __s32 min_frag; /* Minimal frag threshold */
+ __s32 max_frag; /* Maximal frag threshold */
+
+ /* Power Management duration & timeout */
+ __s32 min_pmp; /* Minimal PM period */
+ __s32 max_pmp; /* Maximal PM period */
+ __s32 min_pmt; /* Minimal PM timeout */
+ __s32 max_pmt; /* Maximal PM timeout */
+ __u16 pmp_flags; /* How to decode max/min PM period */
+ __u16 pmt_flags; /* How to decode max/min PM timeout */
+ __u16 pm_capa; /* What PM options are supported */
+
+ /* Encoder stuff */
+ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
+ __u8 num_encoding_sizes; /* Number of entry in the list */
+ __u8 max_encoding_tokens; /* Max number of tokens */
+ /* For drivers that need a "login/passwd" form */
+ __u8 encoding_login_index; /* token index for login token */
+
+ /* Transmit power */
+ __u16 txpower_capa; /* What options are supported */
+ __u8 num_txpower; /* Number of entries in the list */
+ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */
+
+ /* Wireless Extension version info */
+ __u8 we_version_compiled; /* Must be WIRELESS_EXT */
+ __u8 we_version_source; /* Last update of source */
+
+ /* Retry limits and lifetime */
+ __u16 retry_capa; /* What retry options are supported */
+ __u16 retry_flags; /* How to decode max/min retry limit */
+ __u16 r_time_flags; /* How to decode max/min retry life */
+ __s32 min_retry; /* Minimal number of retries */
+ __s32 max_retry; /* Maximal number of retries */
+ __s32 min_r_time; /* Minimal retry lifetime */
+ __s32 max_r_time; /* Maximal retry lifetime */
+
+ /* Frequency */
+ __u16 num_channels; /* Number of channels [0; num - 1] */
+ __u8 num_frequency; /* Number of entry in the list */
+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers,
+ * because each entry contain its channel index */
+
+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
+
+ /* More power management stuff */
+ __s32 min_pms; /* Minimal PM saving */
+ __s32 max_pms; /* Maximal PM saving */
+ __u16 pms_flags; /* How to decode max/min PM saving */
+
+ /* All available modulations for driver (hw may support less) */
+ __s32 modul_capa; /* IW_MODUL_* bit field */
+
+ /* More bitrate stuff */
+ __u32 bitrate_capa; /* Types of bitrates supported */
+};
+
+/*
+ * Private ioctl interface information
+ */
+
+struct iw_priv_args
+{
+ __u32 cmd; /* Number of the ioctl to issue */
+ __u16 set_args; /* Type and number of args */
+ __u16 get_args; /* Type and number of args */
+ char name[IFNAMSIZ]; /* Name of the extension */
+};
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/*
+ * Wireless events are carried through the rtnetlink socket to user
+ * space. They are encapsulated in the IFLA_WIRELESS field of
+ * a RTM_NEWLINK message.
+ */
+
+/*
+ * A Wireless Event. Contains basically the same data as the ioctl...
+ */
+struct iw_event
+{
+ __u16 len; /* Real lenght of this stuff */
+ __u16 cmd; /* Wireless IOCTL */
+ union iwreq_data u; /* IOCTL fixed payload */
+};
+
+/* Size of the Event prefix (including padding and alignement junk) */
+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data))
+/* Size of the various events */
+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
+
+/* iw_point events are special. First, the payload (extra data) come at
+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
+ * we omit the pointer, so start at an offset. */
+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
+ (char *) NULL)
+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
+ IW_EV_POINT_OFF)
+
+#endif /* _LINUX_WIRELESS_H */
--- /dev/null
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version : 22 16.3.07
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands. This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ * # net/core/dev.c (two place + add include)
+ * # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ * # net/core/dev.c (two other places)
+ * # include/linux/netdevice.h (one place)
+ * # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ * # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ * # net/core/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+ * # net/core/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+/* This header is used in user-space, therefore need to be sanitised
+ * for that purpose. Those includes are usually not compatible with glibc.
+ * To know which includes to use in user-space, check iwlib.h. */
+#ifdef __KERNEL__
+#include <linux/types.h> /* for "caddr_t" et al */
+#include <linux/socket.h> /* for "struct sockaddr" et al */
+#include <linux/if.h> /* for IFNAMSIZ and co... */
+#endif /* __KERNEL__ */
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT 22
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
+ * - Encryption renamed to Encode to avoid US regulation problems
+ * - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ * - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ * - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ * - Changed my e-mail address
+ * - More 802.11 support (nickname, rate, rts, frag)
+ * - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ * - Support for 'mode of operation' (ad-hoc, managed...)
+ * - Support for unicast and multicast power saving
+ * - Change encoding to support larger tokens (>64 bits)
+ * - Updated iw_params (disable, flags) and use it for NWID
+ * - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ * - Add PM capability to range structure
+ * - Add PM modifier : MAX/MIN/RELATIVE
+ * - Add encoding option : IW_ENCODE_NOKEY
+ * - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ * - Add WE version in range (help backward/forward compatibility)
+ * - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ * - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ * - Add new statistics (frag, retry, beacon)
+ * - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ * - Document creation of new driver API.
+ * - Extract union iwreq_data from struct iwreq (for new driver API).
+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ *
+ * V13 to V14
+ * ----------
+ * - Wireless Events support : define struct iw_event
+ * - Define additional specific event numbers
+ * - Add "addr" and "param" fields in union iwreq_data
+ * - AP scanning stuff (SIOCSIWSCAN and friends)
+ *
+ * V14 to V15
+ * ----------
+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
+ * - Make struct iw_freq signed (both m & e), add explicit padding
+ * - Add IWEVCUSTOM for driver specific event/scanning token
+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
+ * - Add IW_TXPOW_RANGE for range of Tx Powers
+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ * - Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ * - Reshuffle struct iw_range for increases, add filler
+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ *
+ * V16 to V17
+ * ----------
+ * - Add flags to frequency -> auto/fixed
+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
+ * - Wireless Event capability in struct iw_range
+ * - Add support for relative TxPower (yick !)
+ *
+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
+ * ----------
+ * - Add support for WPA/WPA2
+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
+ * SIOCGIWENCODEEXT)
+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
+ * - Add SIOCSIWMLME
+ * - Add SIOCSIWPMKSA
+ * - Add struct iw_range bit field for supported encoding capabilities
+ * - Add optional scan request parameters for SIOCSIWSCAN
+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
+ * related parameters (extensible up to 4096 parameter values)
+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
+ *
+ * V18 to V19
+ * ----------
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove header includes to help user space
+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
+ *
+ * V19 to V20
+ * ----------
+ * - RtNetlink requests support (SET/GET)
+ *
+ * V20 to V21
+ * ----------
+ * - Remove (struct net_device *)->get_wireless_stats()
+ * - Change length in ESSID and NICK to strlen() instead of strlen()+1
+ * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ * - Power/Retry relative values no longer * 100000
+ * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
+ *
+ * V21 to V22
+ * ----------
+ * - Prevent leaking of kernel space in stream on 64 bits.
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Wireless Identification */
+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
+#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
+ * Don't put the name of your driver there, it's useless. */
+
+/* Basic operations */
+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */
+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */
+#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */
+#define SIOCSIWMODE 0x8B06 /* set operation mode */
+#define SIOCGIWMODE 0x8B07 /* get operation mode */
+#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */
+#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */
+
+/* Informative stuff */
+#define SIOCSIWRANGE 0x8B0A /* Unused */
+#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */
+#define SIOCSIWPRIV 0x8B0C /* Unused */
+#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
+#define SIOCSIWSTATS 0x8B0E /* Unused */
+#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */
+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
+
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
+#define SIOCSIWSPY 0x8B10 /* set spy addresses */
+#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
+
+/* Access Point manipulation */
+#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
+#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */
+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */
+#define SIOCGIWSCAN 0x8B19 /* get scanning results */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
+#define SIOCGIWESSID 0x8B1B /* get ESSID */
+#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */
+#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE... */
+
+/* Other parameters useful in 802.11 and some other devices */
+#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
+#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
+#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */
+#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */
+#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */
+#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */
+#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
+#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
+/* Modulation bitmask */
+#define SIOCSIWMODUL 0x8B2E /* set Modulations settings */
+#define SIOCGIWMODUL 0x8B2F /* get Modulations settings */
+
+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
+ * fields. More than one IE may be included in the request. Setting the generic
+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
+ * are required to report the used IE as a wireless event, e.g., when
+ * associating with an AP. */
+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
+
+/* WPA : IEEE 802.11 MLME requests */
+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
+ * struct iw_mlme */
+/* WPA : Authentication mode parameters */
+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
+
+/* WPA : Extended version of encoding configuration */
+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
+
+/* WPA2 : PMKSA cache management */
+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 32 ioctl are wireless device private, for 16 commands.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+#define SIOCIWFIRSTPRIV 0x8BE0
+#define SIOCIWLASTPRIV 0x8BFF
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'even' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command). More details in iwpriv.c.
+ * And I repeat : you are not forced to use them with iwpriv, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST 0x8B00
+#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
+
+/* Odd : get (world access), even : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/* Those are *NOT* ioctls, do not issue request on them !!! */
+/* Most events use the same identifier as ioctl requests */
+
+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
+ * (scan results); This includes id and
+ * length fields. One IWEVGENIE may
+ * contain more than one IE. Scan
+ * results may contain one or more
+ * IWEVGENIE events. */
+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
+ * (struct iw_michaelmicfailure)
+ */
+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
+ * The data includes id and length
+ * fields and may contain more than one
+ * IE. This event is required in
+ * Managed mode if the driver
+ * generates its own WPA/RSN IE. This
+ * should be sent just before
+ * IWEVREGISTERED event for the
+ * association. */
+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
+ * Response. The data includes id and
+ * length fields and may contain more
+ * than one IE. This may be sent
+ * between IWEVASSOCREQIE and
+ * IWEVREGISTERED events for the
+ * association. */
+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
+ * pre-authentication
+ * (struct iw_pmkid_cand) */
+
+#define IWEVFIRST 0x8C00
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */
+#define IW_PRIV_TYPE_NONE 0x0000
+#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
+#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
+#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
+
+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
+
+#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+#define IW_MAX_FREQUENCIES 32
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+#define IW_MAX_BITRATES 32
+
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER 8
+/* Note : if you more than 8 TXPowers, just set the max and min or
+ * a few of them in the struct iw_range. */
+
+/* Maximum of address that you may set with SPY */
+#define IW_MAX_SPY 8
+
+/* Maximum of address that you may get in the
+ list of access points in range */
+#define IW_MAX_AP 64
+
+/* Maximum size of the ESSID and NICKN strings */
+#define IW_ESSID_MAX_SIZE 32
+
+/* Modes of operation */
+#define IW_MODE_AUTO 0 /* Let the driver decides */
+#define IW_MODE_ADHOC 1 /* Single cell network */
+#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */
+#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
+#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
+#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
+
+/* Statistics flags (bitmask in updated) */
+#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
+#define IW_QUAL_LEVEL_UPDATED 0x02
+#define IW_QUAL_NOISE_UPDATED 0x04
+#define IW_QUAL_ALL_UPDATED 0x07
+#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
+#define IW_QUAL_LEVEL_INVALID 0x20
+#define IW_QUAL_NOISE_INVALID 0x40
+#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */
+#define IW_QUAL_ALL_INVALID 0x70
+
+/* Frequency flags */
+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
+
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+#define IW_MAX_ENCODING_SIZES 8
+
+/* Maximum size of the encoding token in bytes */
+#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
+#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
+#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
+#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
+#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
+#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
+#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
+
+/* Power management flags available (along with the value, if any) */
+#define IW_POWER_ON 0x0000 /* No details... */
+#define IW_POWER_TYPE 0xF000 /* Type of parameter */
+#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */
+#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */
+#define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/
+#define IW_POWER_MODE 0x0F00 /* Power Management mode */
+#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */
+#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */
+#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */
+#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */
+#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
+#define IW_POWER_MIN 0x0001 /* Value is a minimum */
+#define IW_POWER_MAX 0x0002 /* Value is a maximum */
+#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_TYPE 0x00FF /* Type of value */
+#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
+#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
+
+/* Retry limits and lifetime flags available */
+#define IW_RETRY_ON 0x0000 /* No details... */
+#define IW_RETRY_TYPE 0xF000 /* Type of parameter */
+#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/
+#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */
+#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */
+#define IW_RETRY_MIN 0x0001 /* Value is a minimum */
+#define IW_RETRY_MAX 0x0002 /* Value is a maximum */
+#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */
+#define IW_RETRY_LONG 0x0020 /* Value is for long packets */
+
+/* Scanning request flags */
+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
+/* struct iw_scan_req scan_type */
+#define IW_SCAN_TYPE_ACTIVE 0
+#define IW_SCAN_TYPE_PASSIVE 1
+/* Maximum size of returned data */
+#define IW_SCAN_MAX_DATA 4096 /* In bytes */
+
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX 256 /* In bytes */
+
+/* Generic information element */
+#define IW_GENERIC_IE_MAX 1024
+
+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
+#define IW_MLME_DEAUTH 0
+#define IW_MLME_DISASSOC 1
+#define IW_MLME_AUTH 2
+#define IW_MLME_ASSOC 3
+
+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
+#define IW_AUTH_INDEX 0x0FFF
+#define IW_AUTH_FLAGS 0xF000
+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
+ * parameter that is being set/get to; value will be read/written to
+ * struct iw_param value field) */
+#define IW_AUTH_WPA_VERSION 0
+#define IW_AUTH_CIPHER_PAIRWISE 1
+#define IW_AUTH_CIPHER_GROUP 2
+#define IW_AUTH_KEY_MGMT 3
+#define IW_AUTH_TKIP_COUNTERMEASURES 4
+#define IW_AUTH_DROP_UNENCRYPTED 5
+#define IW_AUTH_80211_AUTH_ALG 6
+#define IW_AUTH_WPA_ENABLED 7
+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
+#define IW_AUTH_ROAMING_CONTROL 9
+#define IW_AUTH_PRIVACY_INVOKED 10
+
+/* IW_AUTH_WPA_VERSION values (bit field) */
+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
+
+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
+#define IW_AUTH_CIPHER_NONE 0x00000001
+#define IW_AUTH_CIPHER_WEP40 0x00000002
+#define IW_AUTH_CIPHER_TKIP 0x00000004
+#define IW_AUTH_CIPHER_CCMP 0x00000008
+#define IW_AUTH_CIPHER_WEP104 0x00000010
+
+/* IW_AUTH_KEY_MGMT values (bit field) */
+#define IW_AUTH_KEY_MGMT_802_1X 1
+#define IW_AUTH_KEY_MGMT_PSK 2
+
+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
+#define IW_AUTH_ALG_LEAP 0x00000004
+
+/* IW_AUTH_ROAMING_CONTROL values */
+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
+ * control */
+
+/* SIOCSIWENCODEEXT definitions */
+#define IW_ENCODE_SEQ_MAX_SIZE 8
+/* struct iw_encode_ext ->alg */
+#define IW_ENCODE_ALG_NONE 0
+#define IW_ENCODE_ALG_WEP 1
+#define IW_ENCODE_ALG_TKIP 2
+#define IW_ENCODE_ALG_CCMP 3
+/* struct iw_encode_ext ->ext_flags */
+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
+
+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
+#define IW_MICFAILURE_GROUP 0x00000004
+#define IW_MICFAILURE_PAIRWISE 0x00000008
+#define IW_MICFAILURE_STAKEY 0x00000010
+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
+ */
+
+/* Bit field values for enc_capa in struct iw_range */
+#define IW_ENC_CAPA_WPA 0x00000001
+#define IW_ENC_CAPA_WPA2 0x00000002
+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
+
+/* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
+ (cmd - SIOCSIWCOMMIT))
+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
+/* Event capability constants - event autogenerated by the kernel
+ * This list is valid for most 802.11 devices, customise as needed... */
+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
+ IW_EVENT_CAPA_MASK(0x8B06) | \
+ IW_EVENT_CAPA_MASK(0x8B1A))
+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
+/* "Easy" macro to set events in iw_range (less efficient) */
+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
+
+/* Modulations bitmasks */
+#define IW_MODUL_ALL 0x00000000 /* Everything supported */
+#define IW_MODUL_FH 0x00000001 /* Frequency Hopping */
+#define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */
+#define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */
+#define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK)
+#define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */
+#define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */
+#define IW_MODUL_11A (IW_MODUL_OFDM_A)
+#define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A)
+#define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */
+#define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G)
+#define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A)
+#define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */
+/* In here we should define MIMO stuff. Later... */
+#define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */
+
+/* Bitrate flags available */
+#define IW_BITRATE_TYPE 0x00FF /* Type of value */
+#define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */
+#define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ * Generic format for most parameters that fit in an int
+ */
+struct iw_param
+{
+ __s32 value; /* The value of the parameter itself */
+ __u8 fixed; /* Hardware should not use auto select */
+ __u8 disabled; /* Disable the feature */
+ __u16 flags; /* Various specifc flags (if any) */
+};
+
+/*
+ * For all data larger than 16 octets, we need to use a
+ * pointer to memory allocated in user space.
+ */
+struct iw_point
+{
+ void __user *pointer; /* Pointer to the data (in user space) */
+ __u16 length; /* number of fields or size in bytes */
+ __u16 flags; /* Optional params */
+};
+
+/*
+ * A frequency
+ * For numbers lower than 10^9, we encode the number in 'm' and
+ * set 'e' to 0
+ * For number greater than 10^9, we divide it by the lowest power
+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ * The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq
+{
+ __s32 m; /* Mantissa */
+ __s16 e; /* Exponent */
+ __u8 i; /* List index (when in range struct) */
+ __u8 flags; /* Flags (fixed/auto) */
+};
+
+/*
+ * Quality of the link
+ */
+struct iw_quality
+{
+ __u8 qual; /* link quality (%retries, SNR,
+ %missed beacons or better...) */
+ __u8 level; /* signal level (dBm) */
+ __u8 noise; /* noise level (dBm) */
+ __u8 updated; /* Flags to know if updated */
+};
+
+/*
+ * Packet discarded in the wireless adapter due to
+ * "wireless" specific problems...
+ * Note : the list of counter and statistics in net_device_stats
+ * is already pretty exhaustive, and you should use that first.
+ * This is only additional stats...
+ */
+struct iw_discarded
+{
+ __u32 nwid; /* Rx : Wrong nwid/essid */
+ __u32 code; /* Rx : Unable to code/decode (WEP) */
+ __u32 fragment; /* Rx : Can't perform MAC reassembly */
+ __u32 retries; /* Tx : Max MAC retries num reached */
+ __u32 misc; /* Others cases */
+};
+
+/*
+ * Packet/Time period missed in the wireless adapter due to
+ * "wireless" specific problems...
+ */
+struct iw_missed
+{
+ __u32 beacon; /* Missed beacons/superframe */
+};
+
+/*
+ * Quality range (for spy threshold)
+ */
+struct iw_thrspy
+{
+ struct sockaddr addr; /* Source address (hw/mac) */
+ struct iw_quality qual; /* Quality of the link */
+ struct iw_quality low; /* Low threshold */
+ struct iw_quality high; /* High threshold */
+};
+
+/*
+ * Optional data for scan request
+ *
+ * Note: these optional parameters are controlling parameters for the
+ * scanning behavior, these do not apply to getting scan results
+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
+ * provide a merged results with all BSSes even if the previous scan
+ * request limited scanning to a subset, e.g., by specifying an SSID.
+ * Especially, scan results are required to include an entry for the
+ * current BSS if the driver is in Managed mode and associated with an AP.
+ */
+struct iw_scan_req
+{
+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
+ __u8 essid_len;
+ __u8 num_channels; /* num entries in channel_list;
+ * 0 = scan all allowed channels */
+ __u8 flags; /* reserved as padding; use zero, this may
+ * be used in the future for adding flags
+ * to request different scan behavior */
+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
+ * individual address of a specific BSS */
+
+ /*
+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
+ * the current ESSID. This allows scan requests for specific ESSID
+ * without having to change the current ESSID and potentially breaking
+ * the current association.
+ */
+ __u8 essid[IW_ESSID_MAX_SIZE];
+
+ /*
+ * Optional parameters for changing the default scanning behavior.
+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
+ * reasonable default values. min_channel_time defines the time that
+ * will be used to wait for the first reply on each channel. If no
+ * replies are received, next channel will be scanned after this. If
+ * replies are received, total time waited on the channel is defined by
+ * max_channel_time.
+ */
+ __u32 min_channel_time; /* in TU */
+ __u32 max_channel_time; /* in TU */
+
+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
+};
+
+/* ------------------------- WPA SUPPORT ------------------------- */
+
+/*
+ * Extended data structure for get/set encoding (this is used with
+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
+ * only the data contents changes (key data -> this structure, including
+ * key data).
+ *
+ * If the new key is the first group key, it will be set as the default
+ * TX key. Otherwise, default TX key index is only changed if
+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
+ *
+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
+ * special "change TX key index" operation which is indicated by setting
+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
+ *
+ * tx_seq/rx_seq are only used when respective
+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
+ * used only by an Authenticator (AP or an IBSS station) to get the
+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
+ * debugging/testing.
+ */
+struct iw_encode_ext
+{
+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+ * (group) keys or unicast address for
+ * individual keys */
+ __u16 alg; /* IW_ENCODE_ALG_* */
+ __u16 key_len;
+ __u8 key[0];
+};
+
+/* SIOCSIWMLME data */
+struct iw_mlme
+{
+ __u16 cmd; /* IW_MLME_* */
+ __u16 reason_code;
+ struct sockaddr addr;
+};
+
+/* SIOCSIWPMKSA data */
+#define IW_PMKSA_ADD 1
+#define IW_PMKSA_REMOVE 2
+#define IW_PMKSA_FLUSH 3
+
+#define IW_PMKID_LEN 16
+
+struct iw_pmksa
+{
+ __u32 cmd; /* IW_PMKSA_* */
+ struct sockaddr bssid;
+ __u8 pmkid[IW_PMKID_LEN];
+};
+
+/* IWEVMICHAELMICFAILURE data */
+struct iw_michaelmicfailure
+{
+ __u32 flags;
+ struct sockaddr src_addr;
+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+};
+
+/* IWEVPMKIDCAND data */
+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
+struct iw_pmkid_cand
+{
+ __u32 flags; /* IW_PMKID_CAND_* */
+ __u32 index; /* the smaller the index, the higher the
+ * priority */
+ struct sockaddr bssid;
+};
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics
+{
+ __u16 status; /* Status
+ * - device dependent for now */
+
+ struct iw_quality qual; /* Quality of the link
+ * (instant/mean/max) */
+ struct iw_discarded discard; /* Packet discarded counts */
+ struct iw_missed miss; /* Packet missed counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ */
+union iwreq_data
+{
+ /* Config - generic */
+ char name[IFNAMSIZ];
+ /* Name : used to verify the presence of wireless extensions.
+ * Name of the protocol/provider... */
+
+ struct iw_point essid; /* Extended network name */
+ struct iw_param nwid; /* network id (or domain - the cell) */
+ struct iw_freq freq; /* frequency or channel :
+ * 0-1000 = channel
+ * > 1000 = frequency in Hz */
+
+ struct iw_param sens; /* signal level threshold */
+ struct iw_param bitrate; /* default bit rate */
+ struct iw_param txpower; /* default transmit power */
+ struct iw_param rts; /* RTS threshold threshold */
+ struct iw_param frag; /* Fragmentation threshold */
+ __u32 mode; /* Operation mode */
+ struct iw_param retry; /* Retry limits & lifetime */
+
+ struct iw_point encoding; /* Encoding stuff : tokens */
+ struct iw_param power; /* PM duration/timeout */
+ struct iw_quality qual; /* Quality part of statistics */
+
+ struct sockaddr ap_addr; /* Access point address */
+ struct sockaddr addr; /* Destination address (hw/mac) */
+
+ struct iw_param param; /* Other small parameters */
+ struct iw_point data; /* Other large parameters */
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+ */
+struct iwreq
+{
+ union
+ {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
+ } ifr_ifrn;
+
+ /* Data part (defined just above) */
+ union iwreq_data u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ * For those ioctl which want to exchange mode data that what could
+ * fit in the above structure...
+ */
+
+/*
+ * Range of parameters
+ */
+
+struct iw_range
+{
+ /* Informative stuff (to choose between different interface) */
+ __u32 throughput; /* To give an idea... */
+ /* In theory this value should be the maximum benchmarked
+ * TCP/IP throughput, because with most of these devices the
+ * bit rate is meaningless (overhead an co) to estimate how
+ * fast the connection will go and pick the fastest one.
+ * I suggest people to play with Netperf or any benchmark...
+ */
+
+ /* NWID (or domain id) */
+ __u32 min_nwid; /* Minimal NWID we are able to set */
+ __u32 max_nwid; /* Maximal NWID we are able to set */
+
+ /* Old Frequency (backward compat - moved lower ) */
+ __u16 old_num_channels;
+ __u8 old_num_frequency;
+
+ /* Wireless event capability bitmasks */
+ __u32 event_capa[6];
+
+ /* signal level threshold range */
+ __s32 sensitivity;
+
+ /* Quality of link & SNR stuff */
+ /* Quality range (link, level, noise)
+ * If the quality is absolute, it will be in the range [0 ; max_qual],
+ * if the quality is dBm, it will be in the range [max_qual ; 0].
+ * Don't forget that we use 8 bit arithmetics... */
+ struct iw_quality max_qual; /* Quality of the link */
+ /* This should contain the average/typical values of the quality
+ * indicator. This should be the threshold between a "good" and
+ * a "bad" link (example : monitor going from green to orange).
+ * Currently, user space apps like quality monitors don't have any
+ * way to calibrate the measurement. With this, they can split
+ * the range between 0 and max_qual in different quality level
+ * (using a geometric subdivision centered on the average).
+ * I expect that people doing the user space apps will feedback
+ * us on which value we need to put in each driver... */
+ struct iw_quality avg_qual; /* Quality of the link */
+
+ /* Rates */
+ __u8 num_bitrates; /* Number of entries in the list */
+ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */
+
+ /* RTS threshold */
+ __s32 min_rts; /* Minimal RTS threshold */
+ __s32 max_rts; /* Maximal RTS threshold */
+
+ /* Frag threshold */
+ __s32 min_frag; /* Minimal frag threshold */
+ __s32 max_frag; /* Maximal frag threshold */
+
+ /* Power Management duration & timeout */
+ __s32 min_pmp; /* Minimal PM period */
+ __s32 max_pmp; /* Maximal PM period */
+ __s32 min_pmt; /* Minimal PM timeout */
+ __s32 max_pmt; /* Maximal PM timeout */
+ __u16 pmp_flags; /* How to decode max/min PM period */
+ __u16 pmt_flags; /* How to decode max/min PM timeout */
+ __u16 pm_capa; /* What PM options are supported */
+
+ /* Encoder stuff */
+ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
+ __u8 num_encoding_sizes; /* Number of entry in the list */
+ __u8 max_encoding_tokens; /* Max number of tokens */
+ /* For drivers that need a "login/passwd" form */
+ __u8 encoding_login_index; /* token index for login token */
+
+ /* Transmit power */
+ __u16 txpower_capa; /* What options are supported */
+ __u8 num_txpower; /* Number of entries in the list */
+ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */
+
+ /* Wireless Extension version info */
+ __u8 we_version_compiled; /* Must be WIRELESS_EXT */
+ __u8 we_version_source; /* Last update of source */
+
+ /* Retry limits and lifetime */
+ __u16 retry_capa; /* What retry options are supported */
+ __u16 retry_flags; /* How to decode max/min retry limit */
+ __u16 r_time_flags; /* How to decode max/min retry life */
+ __s32 min_retry; /* Minimal number of retries */
+ __s32 max_retry; /* Maximal number of retries */
+ __s32 min_r_time; /* Minimal retry lifetime */
+ __s32 max_r_time; /* Maximal retry lifetime */
+
+ /* Frequency */
+ __u16 num_channels; /* Number of channels [0; num - 1] */
+ __u8 num_frequency; /* Number of entry in the list */
+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers,
+ * because each entry contain its channel index */
+
+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
+
+ /* More power management stuff */
+ __s32 min_pms; /* Minimal PM saving */
+ __s32 max_pms; /* Maximal PM saving */
+ __u16 pms_flags; /* How to decode max/min PM saving */
+
+ /* All available modulations for driver (hw may support less) */
+ __s32 modul_capa; /* IW_MODUL_* bit field */
+
+ /* More bitrate stuff */
+ __u32 bitrate_capa; /* Types of bitrates supported */
+};
+
+/*
+ * Private ioctl interface information
+ */
+
+struct iw_priv_args
+{
+ __u32 cmd; /* Number of the ioctl to issue */
+ __u16 set_args; /* Type and number of args */
+ __u16 get_args; /* Type and number of args */
+ char name[IFNAMSIZ]; /* Name of the extension */
+};
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/*
+ * Wireless events are carried through the rtnetlink socket to user
+ * space. They are encapsulated in the IFLA_WIRELESS field of
+ * a RTM_NEWLINK message.
+ */
+
+/*
+ * A Wireless Event. Contains basically the same data as the ioctl...
+ */
+struct iw_event
+{
+ __u16 len; /* Real lenght of this stuff */
+ __u16 cmd; /* Wireless IOCTL */
+ union iwreq_data u; /* IOCTL fixed payload */
+};
+
+/* Size of the Event prefix (including padding and alignement junk) */
+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data))
+/* Size of the various events */
+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
+
+/* iw_point events are special. First, the payload (extra data) come at
+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
+ * we omit the pointer, so start at an offset. */
+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
+ (char *) NULL)
+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
+ IW_EV_POINT_OFF)
+
+/* Size of the Event prefix when packed in stream */
+#define IW_EV_LCP_PK_LEN (4)
+/* Size of the various events when packed in stream */
+#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ)
+#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32))
+#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
+#define IW_EV_POINT_PK_LEN (IW_EV_LCP_LEN + 4)
+
+#endif /* _LINUX_WIRELESS_H */