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