From: chris-kirby Date: Tue, 11 Oct 2016 21:03:11 +0000 (-0600) Subject: v24 X-Git-Url: http://git.osdn.net/view?p=android-x86%2Fexternal-wireless-tools.git;a=commitdiff_plain;h=92c266503ddec9d3bd219978c118a77a46dc12d4;ds=sidebyside v24 --- diff --git a/wireless_tools/CHANGELOG.h b/wireless_tools/CHANGELOG.h index 67093d6..cffb6b2 100644 --- a/wireless_tools/CHANGELOG.h +++ b/wireless_tools/CHANGELOG.h @@ -173,6 +173,61 @@ * 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 ) + * 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 , 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 - again !!!) + * o Don't loose flags when setting encryption key [iwconfig] + * o Add [iwevent] + * --- + * (From Casey Carter ) + * 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" ) + * o Use a generic set of header, may end header mess [iwlib] + * (From Casey Carter ) + * 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 ) + * o Always send TxPower flags to the driver [iwconfig] + * (From John M. Choi ) + * o Header definition for Slackware (kernel 2.2/glibc 2.2) [iwlib] */ /* ----------------------------- TODO ----------------------------- */ @@ -190,7 +245,16 @@ * * 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 : * --------------- diff --git a/wireless_tools/INSTALL b/wireless_tools/INSTALL index efa4eca..cf2b323 100644 --- a/wireless_tools/INSTALL +++ b/wireless_tools/INSTALL @@ -73,6 +73,7 @@ the tools from compiling. 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 diff --git a/wireless_tools/Makefile b/wireless_tools/Makefile index f4e0fcf..5de0c9a 100644 --- a/wireless_tools/Makefile +++ b/wireless_tools/Makefile @@ -4,19 +4,25 @@ # 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/ @@ -36,35 +42,41 @@ WE_HEADER= 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) @@ -78,7 +90,8 @@ install:: 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/ @@ -87,7 +100,7 @@ clean:: realclean:: $(RM_CMD) - $(RM) $(STATIC) $(DYNAMIC) $(PROGS) + $(RM) $(STATIC) $(DYNAMIC) $(PROGS) macaddr depend:: makedepend -s "# DO NOT DELETE" -- $(INCLUDES) -- $(SRCS) diff --git a/wireless_tools/README b/wireless_tools/README index 7ac44ab..9391e28 100644 --- a/wireless_tools/README +++ b/wireless_tools/README @@ -15,6 +15,7 @@ web page INSTALL ------- This file contains installation instruction and requirements. + A *must* read. PCMCIA.txt ---------- @@ -26,7 +27,7 @@ man pages (iwconfig.8, iwlist.8, iwpriv.8, iwspy.8) 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 @@ -64,23 +65,33 @@ iwgetid.c Output the ESSID or NWID of the specified device. Can also output it in a form that can be used as a Pcmcia Scheme. +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 diff --git a/wireless_tools/iwconfig.8 b/wireless_tools/iwconfig.8 index 814861f..1e8f323 100644 --- a/wireless_tools/iwconfig.8 +++ b/wireless_tools/iwconfig.8 @@ -135,13 +135,27 @@ topology. The mode can be .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 @@ -175,6 +189,8 @@ the driver will use all bit lower and equal than this value. .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 @@ -330,8 +346,8 @@ is the short retry limit (non RTS/CTS packets). .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. diff --git a/wireless_tools/iwconfig.c b/wireless_tools/iwconfig.c index 5b38484..73e7ec1 100644 --- a/wireless_tools/iwconfig.c +++ b/wireless_tools/iwconfig.c @@ -57,8 +57,17 @@ get_info(int skfd, /* 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); @@ -147,9 +156,9 @@ get_info(int skfd, /* 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 */ @@ -198,7 +207,7 @@ display_info(struct wireless_info * info, { 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) */ @@ -253,20 +262,8 @@ display_info(struct wireless_info * info, /* 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; } @@ -300,20 +297,9 @@ display_info(struct wireless_info * info, } 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 @@ -498,7 +484,7 @@ display_info(struct wireless_info * info, 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 */ @@ -543,48 +529,35 @@ display_info(struct wireless_info * info, * 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 **************************/ @@ -771,62 +744,23 @@ set_info(int skfd, /* The socket */ } 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) && @@ -855,7 +789,7 @@ set_info(int skfd, /* The socket */ } /* 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]); @@ -927,9 +861,26 @@ set_info(int skfd, /* The socket */ 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"); @@ -1243,13 +1194,18 @@ set_info(int skfd, /* The socket */ 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 */ @@ -1364,7 +1320,7 @@ int 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. */ @@ -1376,31 +1332,19 @@ main(int argc, /* 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); diff --git a/wireless_tools/iwevent.8 b/wireless_tools/iwevent.8 new file mode 100644 index 0000000..2a73d6d --- /dev/null +++ b/wireless_tools/iwevent.8 @@ -0,0 +1,89 @@ +.\" 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). diff --git a/wireless_tools/iwevent.c b/wireless_tools/iwevent.c new file mode 100644 index 0000000..6a1de90 --- /dev/null +++ b/wireless_tools/iwevent.c @@ -0,0 +1,539 @@ +/* + * 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 + */ + +/***************************** INCLUDES *****************************/ + +#include "iwlib.h" /* Header */ + +#include +#include + +#include +#include +#include + +/************************ 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, + * ----------------------------------------------- + */ + +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); +} diff --git a/wireless_tools/iwgetid.8 b/wireless_tools/iwgetid.8 new file mode 100644 index 0000000..323ce8c --- /dev/null +++ b/wireless_tools/iwgetid.8 @@ -0,0 +1,67 @@ +.\" 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). diff --git a/wireless_tools/iwgetid.c b/wireless_tools/iwgetid.c index c550431..f573209 100644 --- a/wireless_tools/iwgetid.c +++ b/wireless_tools/iwgetid.c @@ -11,8 +11,12 @@ #include "iwlib.h" /* Header */ +#include + #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 : @@ -61,6 +65,63 @@ * 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 + * 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 ************************/ /*------------------------------------------------------------------*/ @@ -68,15 +129,15 @@ * 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); @@ -89,7 +150,7 @@ print_essid(int skfd, 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])) @@ -98,7 +159,6 @@ print_essid(int skfd, if((j == 0) || (j > 32)) return(-2); printf("%s\n", pessid); - fflush(stdout); break; default: printf("%-8.8s ESSID:\"%s\"\n", ifname, essid); @@ -114,7 +174,7 @@ print_essid(int skfd, */ static int print_nwid(int skfd, - char * ifname, + const char * ifname, int format) { struct iwreq wrq; @@ -129,7 +189,6 @@ print_nwid(int skfd, 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); @@ -139,143 +198,96 @@ print_nwid(int skfd, 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; @@ -283,15 +295,34 @@ scan_ap(int skfd, /* 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 } +}; /*------------------------------------------------------------------*/ /* @@ -301,85 +332,61 @@ int 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); } diff --git a/wireless_tools/iwlib.c b/wireless_tools/iwlib.c index 421f4e1..9d0f575 100644 --- a/wireless_tools/iwlib.c +++ b/wireless_tools/iwlib.c @@ -13,7 +13,7 @@ /**************************** VARIABLES ****************************/ -const char * iw_operation_mode[] = { "Auto", +const char * const iw_operation_mode[] = { "Auto", "Ad-Hoc", "Managed", "Master", @@ -31,33 +31,132 @@ const char * iw_operation_mode[] = { "Auto", 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 - * 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 + * 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 ************************/ @@ -75,10 +174,10 @@ iw_get_range_info(int skfd, 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); @@ -86,7 +185,7 @@ iw_get_range_info(int skfd, /* 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... */ @@ -207,9 +306,9 @@ iw_get_basic_config(int skfd, /* 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); @@ -363,6 +462,51 @@ iw_freq2float(iwfreq * in) 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 *************************/ /*------------------------------------------------------------------*/ @@ -407,7 +551,7 @@ iw_get_stats(int skfd, 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; @@ -523,15 +667,20 @@ iw_print_key(char * buffer, /* 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 @@ -549,6 +698,58 @@ iw_print_key(char * buffer, } } +/*------------------------------------------------------------------*/ +/* + * 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 *******************/ @@ -587,17 +788,17 @@ iw_print_pm_value(char * buffer, /* 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); } } @@ -613,19 +814,19 @@ iw_print_pm_mode(char * buffer, 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: } @@ -681,6 +882,25 @@ iw_print_retry_value(char * buffer, } #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 @@ -710,7 +930,7 @@ iw_check_mac_addr_type(int skfd, #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); @@ -770,15 +990,26 @@ iw_check_addr_type(int skfd, /* * 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; } /*------------------------------------------------------------------*/ @@ -786,84 +1017,64 @@ iw_pr_ether(char * buffer, * 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 */ @@ -946,7 +1157,7 @@ iw_in_addr(int skfd, #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 */ @@ -967,7 +1178,7 @@ iw_in_addr(int skfd, } #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); @@ -977,6 +1188,7 @@ iw_in_addr(int skfd, /*------------------------------------------------------------------*/ /* + * Max size in bytes of an private argument. */ int iw_byte_size(int args) @@ -993,3 +1205,217 @@ 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 */ diff --git a/wireless_tools/iwlib.h b/wireless_tools/iwlib.h index b195b82..475e67e 100644 --- a/wireless_tools/iwlib.h +++ b/wireless_tools/iwlib.h @@ -28,6 +28,9 @@ #include #include #include /* gethostbyname, getnetbyname */ +#include /* struct ether_addr */ +#include /* struct timeval */ +#include /* This is our header selection. Try to hide the mess and the misery :-( * Don't look, you would go blind ;-) */ @@ -36,12 +39,14 @@ #include #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 */ @@ -49,7 +54,8 @@ && __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__) \ @@ -84,6 +90,15 @@ #error "Your kernel/libc combination is not supported" #endif +#ifdef GENERIC_HEADERS +/* Proposed by Dr. Michael Rietz , 27.3.2 */ +/* If this works for all, it might be more stable on the long term - Jean II */ +#include /* For ARPHRD_ETHER */ +#include /* For AF_INET & struct sockaddr */ +#include /* For struct sockaddr_in */ +#include +#endif /* GENERIC_HEADERS */ + #ifdef GLIBC22_HEADERS /* Added by Ross G. Miller , 3/28/01 */ #include /* For ARPHRD_ETHER */ @@ -116,12 +131,13 @@ #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 ******************************/ @@ -129,6 +145,9 @@ You may update your kernel and/or system headers to get the new features..." /************************ CONSTANTS & MACROS ************************/ +/* Paths */ +#define PROC_NET_WIRELESS "/proc/net/wireless" + /* Some usefull constants */ #define KILO 1e3 #define MEGA 1e6 @@ -229,6 +248,20 @@ typedef struct wireless_config 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 @@ -236,6 +269,11 @@ typedef struct wireless_config /* ---------------------- 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, @@ -259,6 +297,12 @@ void 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); @@ -280,6 +324,9 @@ void 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, @@ -295,6 +342,10 @@ void 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, @@ -304,13 +355,15 @@ int 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 @@ -322,14 +375,25 @@ 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 */ /* @@ -369,4 +433,44 @@ iw_get_ext(int skfd, /* Socket to the kernel */ 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 */ diff --git a/wireless_tools/iwlist.8 b/wireless_tools/iwlist.8 index 3c86fef..09a4981 100644 --- a/wireless_tools/iwlist.8 +++ b/wireless_tools/iwlist.8 @@ -15,6 +15,8 @@ iwlist \- Get wireless statistics from specific nodes .br .BI "iwlist " interface " ap" .br +.BI "iwlist " interface " scan" +.br .BI "iwlist " interface " rate" .br .BI "iwlist " interface " key" @@ -46,7 +48,22 @@ displayed and channel numbers. .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. diff --git a/wireless_tools/iwlist.c b/wireless_tools/iwlist.c index 30640e6..0703f3e 100644 --- a/wireless_tools/iwlist.c +++ b/wireless_tools/iwlist.c @@ -12,6 +12,7 @@ */ #include "iwlib.h" /* Header */ +#include /*********************** FREQUENCIES/CHANNELS ***********************/ @@ -19,14 +20,19 @@ /* * 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); @@ -55,6 +61,7 @@ print_freq_info(int skfd, printf("%-8.8s %d channels\n\n", ifname, range.num_channels); } + return(0); } /************************ ACCESS POINT LIST ************************/ @@ -64,9 +71,11 @@ print_freq_info(int skfd, * 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) + @@ -80,6 +89,9 @@ print_ap_info(int skfd, 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; @@ -87,7 +99,7 @@ print_ap_info(int skfd, 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 */ @@ -102,7 +114,7 @@ print_ap_info(int skfd, 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 */ @@ -128,6 +140,7 @@ print_ap_info(int skfd, printf(" %s\n", iw_pr_ether(temp, hwa[i].sa_data)); } printf("\n"); + return(0); } /***************************** BITRATES *****************************/ @@ -136,13 +149,18 @@ print_ap_info(int skfd, /* * 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) @@ -157,21 +175,16 @@ print_bitrate_info(int skfd, /* 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 *************************/ @@ -180,9 +193,11 @@ print_bitrate_info(int skfd, /* * 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; @@ -190,6 +205,9 @@ print_keys_info(int skfd, 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", @@ -241,7 +259,7 @@ print_keys_info(int skfd, 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); @@ -252,6 +270,7 @@ print_keys_info(int skfd, printf("\n\n"); } + return(0); } /************************* POWER MANAGEMENT *************************/ @@ -285,14 +304,19 @@ get_pm_value(int skfd, /* * 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", @@ -365,11 +389,11 @@ print_pm_info(int skfd, /* 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 */ @@ -415,6 +439,7 @@ print_pm_info(int skfd, } printf("\n"); } + return(0); } /************************** TRANSMIT POWER **************************/ @@ -423,15 +448,20 @@ print_pm_info(int skfd, /* * 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) @@ -464,6 +494,7 @@ print_txpower_info(int skfd, printf("%-8.8s No transmit-powers ? Please update driver...\n\n", ifname); } #endif /* WIRELESS_EXT > 9 */ + return(0); } /*********************** RETRY LIMIT/LIFETIME ***********************/ @@ -499,14 +530,19 @@ get_retry_value(int skfd, /* * 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", @@ -606,74 +642,360 @@ print_retry_info(int skfd, } printf("\n"); } + return(0); } #endif /* WIRELESS_EXT > 10 */ -/************************* COMMON UTILITIES *************************/ +/***************************** SCANNING *****************************/ /* - * This section was written by Michael Tokarev + * 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 + * 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 ********************************/ @@ -686,63 +1008,50 @@ int 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) @@ -753,9 +1062,9 @@ main(int argc, /* 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); diff --git a/wireless_tools/iwpriv.c b/wireless_tools/iwpriv.c index 2db4afd..333f98f 100644 --- a/wireless_tools/iwpriv.c +++ b/wireless_tools/iwpriv.c @@ -13,6 +13,11 @@ #include "iwlib.h" /* Header */ +/**************************** CONSTANTS ****************************/ + +static const char * argtype[] = { + " ", "byte", "char", "", "int ", "float" }; + /************************* MISC SUBROUTINES **************************/ /*------------------------------------------------------------------*/ @@ -34,14 +39,18 @@ iw_usage(void) * 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); @@ -56,7 +65,7 @@ print_priv_info(int skfd, 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, @@ -66,33 +75,7 @@ print_priv_info(int skfd, 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 **************************/ @@ -487,7 +470,7 @@ int 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. */ @@ -499,50 +482,30 @@ main(int argc, /* 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); diff --git a/wireless_tools/iwspy.c b/wireless_tools/iwspy.c index 57d9b25..6b02c1b 100644 --- a/wireless_tools/iwspy.c +++ b/wireless_tools/iwspy.c @@ -18,9 +18,11 @@ /* * 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) + @@ -33,6 +35,9 @@ print_spy_info(int skfd, 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; @@ -40,7 +45,7 @@ print_spy_info(int skfd, 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 */ @@ -50,7 +55,7 @@ print_spy_info(int skfd, 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 */ @@ -84,33 +89,7 @@ print_spy_info(int skfd, #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 **************************/ @@ -132,62 +111,64 @@ set_spy_info(int skfd, /* The socket */ /* 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 */ @@ -214,7 +195,7 @@ int 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. */ @@ -226,33 +207,21 @@ main(int argc, /* 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); diff --git a/wireless_tools/macaddr.c b/wireless_tools/macaddr.c index 8c5a93a..5950fd9 100644 --- a/wireless_tools/macaddr.c +++ b/wireless_tools/macaddr.c @@ -11,43 +11,43 @@ * This is released unther the GPL license. */ +#include +#include +#include +#include #include #include #include -#include -#include -#include -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); - } diff --git a/wireless_tools/wireless.13.h b/wireless_tools/wireless.13.h new file mode 100644 index 0000000..fa3c64f --- /dev/null +++ b/wireless_tools/wireless.13.h @@ -0,0 +1,599 @@ +/* + * This file define a set of standard wireless extensions + * + * Version : 13 6.12.01 + * + * Authors : Jean Tourrilhes - HPL - + * 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 /* for "caddr_t" et al */ +#include /* for "struct sockaddr" et al */ +#include /* 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 */ diff --git a/wireless_tools/wireless.14.h b/wireless_tools/wireless.14.h new file mode 100644 index 0000000..226f540 --- /dev/null +++ b/wireless_tools/wireless.14.h @@ -0,0 +1,669 @@ +/* + * This file define a set of standard wireless extensions + * + * Version : 14 25.1.02 + * + * Authors : Jean Tourrilhes - HPL - + * 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 /* for "caddr_t" et al */ +#include /* for "struct sockaddr" et al */ +#include /* 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 */ diff --git a/wireless_tools/wireless.h b/wireless_tools/wireless.h index fa3c64f..e69de29 100644 --- a/wireless_tools/wireless.h +++ b/wireless_tools/wireless.h @@ -1,599 +0,0 @@ -/* - * This file define a set of standard wireless extensions - * - * Version : 13 6.12.01 - * - * Authors : Jean Tourrilhes - HPL - - * 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 /* for "caddr_t" et al */ -#include /* for "struct sockaddr" et al */ -#include /* 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 */