From: chris-kirby Date: Tue, 11 Oct 2016 20:57:54 +0000 (-0600) Subject: v22 X-Git-Url: http://git.osdn.net/view?p=android-x86%2Fexternal-wireless-tools.git;a=commitdiff_plain;h=fb1188c580d9ff90cc4d80d2bedb03e86b463057 v22 --- diff --git a/wireless_tools/CHANGELOG.h b/wireless_tools/CHANGELOG.h new file mode 100644 index 0000000..e3d5308 --- /dev/null +++ b/wireless_tools/CHANGELOG.h @@ -0,0 +1,177 @@ +/* + * Wireless Tools + * + * Jean II - HPLB 97->99 - HPL 99->01 + * + * The changelog... + * + * This file is released under the GPL license. + */ + +/* --------------------------- HISTORY --------------------------- */ +/* + * wireless 16 : (Jean Tourrilhes) + * ----------- + * o iwconfig, iwpriv & iwspy + * + * wireless 17 : (Justin Seger) + * ----------- + * o Compile under glibc fix + * o merge iwpriv in iwconfig + * o Add Wavelan roaming support + * o Update man page of iwconfig + * + * wireless 18 : + * ----------- + * (From Andreas Neuhaus ) + * o Many fix to remove "core dumps" in iwconfig + * o Remove useless headers in iwconfig + * o CHAR wide private ioctl + * (From Jean Tourrilhes) + * o Create iwcommon.h and iwcommon.c + * o Separate iwpriv again for user interface issues + * The folllowing didn't make sense and crashed : + * iwconfig eth0 priv sethisto 12 15 nwid 100 + * o iwspy no longer depend on net-tools-1.2.0 + * o Reorganisation of the code, cleanup + * o Add ESSID stuff in iwconfig + * o Add display of level & noise in dBm (stats in iwconfig) + * o Update man page of iwconfig and iwpriv + * o Add xwireless (didn't check if it compiles) + * (From Dean W. Gehnert ) + * o Minor fixes + * (Jan Rafaj ) + * o Cosmetic changes (sensitivity relative, freq list) + * o Frequency computation on double + * o Compile clean on libc5 + * (From Jean Tourrilhes) + * o Move listing of frequencies to iwspy + * o Add AP address stuff in iwconfig + * o Add AP list stuff in iwspy + * + * wireless 19 : + * ----------- + * (From Jean Tourrilhes) + * o Allow for sensitivity in dBm (if < 0) [iwconfig] + * o Formatting changes in displaying ap address in [iwconfig] + * o Slightly improved man pages and usage display + * o Add channel number for each frequency in list [iwspy] + * o Add nickname... [iwconfig] + * o Add "port" private ioctl shortcut [iwpriv] + * o If signal level = 0, no range or dBms [iwconfig] + * o I think I now got set/get char strings right in [iwpriv] + * (From Thomas Ekstrom ) + * o Fix a very obscure bug in [iwspy] + * + * wireless 20 : + * ----------- + * (From Jean Tourrilhes) + * o Remove all #ifdef WIRELESS ugliness, but add a #error : + * we require Wireless Extensions 9 or nothing ! [all] + * o Switch to new 'nwid' definition (specific -> iw_param) [iwconfig] + * o Rewriten totally the encryption support [iwconfig] + * - Multiple keys, through key index + * - Flexible/multiple key size, and remove 64bits upper limit + * - Open/Restricted modes + * - Enter keys as ASCII strings + * o List key sizes supported and all keys in [iwspy] + * o Mode of operation support (ad-hoc, managed...) [iwconfig] + * o Use '=' to indicate fixed instead of ugly '(f)' [iwconfig] + * o Ability to disable RTS & frag (off), now the right way [iwconfig] + * o Auto as an input modifier for bitrate [iwconfig] + * o Power Management support [iwconfig] + * - set timeout or period and its value + * - Reception mode (unicast/multicast/all) + * o Updated man pages with all that ;-) + * + * wireless 21 : + * ----------- + * (from Alan McReynolds ) + * o Use proper macros for compilation directives [Makefile] + * (From Jean Tourrilhes) + * o Put licensing info everywhere (almost). Yes, it's GPL ! + * o Document the use of /etc/pcmcia/wireless.opts + * o Add min/max modifiers to power management parameters [iwconfig] + * -> requested by Lee Keyser-Allen for the Spectrum24 driver + * o Optionally output a second power management parameter [iwconfig] + * --- + * o Common subroutines to display stats & power saving info [iwcommon] + * o Display all power management info, capability and values [iwspy] + * --- + * o Optional index for ESSID (for Aironet driver) [iwcommon] + * o IW_ENCODE_NOKEY for write only keys [iwconfig/iwspy] + * o Common subrouting to print encoding keys [iwspy] + * --- + * o Transmit Power stuff (dBm + mW) [iwconfig/iwspy] + * o Cleaner formatting algorithm when displaying params [iwconfig] + * --- + * o Fix get_range_info() and use it everywhere - Should fix core dumps. + * o Catch WE version differences between tools and driver and + * warn user. Thanks to Tobias Ringstrom for the tip... [iwcommon] + * o Add Retry limit and lifetime support. [iwconfig/iwlist] + * o Display "Cell:" instead of "Access Point:" in ad-hoc mode [iwconfig] + * o Header fix for glibc2.2 by Ross G. Miller + * o Move header selection flags in Makefile [iwcommon/Makefile] + * o Spin-off iwlist.c from iwspy.c. iwspy is now much smaller + * After moving this bit of code all over the place, from iwpriv + * to iwconfig to iwspy, it now has a home of its own... [iwspy/iwlist] + * o Wrote quick'n'dirty iwgetid. + * o Remove output of second power management parameter [iwconfig] + * Please use iwlist, I don't want to bloat iwconfig + * --- + * o Fix bug in display ints - "Allen Miu" [iwpriv] + * + * wireless 22 : + * ----------- + * (From Jim Kaba ) + * o Fix socket_open to not open all types of sockets [iwcommon] + * (From Michael Tokarev ) + * o Rewrite main (top level) + command line parsing of [iwlist] + * (From Jean Tourrilhes) + * o Set commands should return proper success flag [iwspy/iwpriv] + * requested by Michael Tokarev + * --- + * (From Torgeir Hansen ) + * o Replace "strcpy(wrq.ifr_name," with strncpy to avoid buffer + * overflows. This is OK because the kernel use strncmp... + * --- + * o Move operation_mode in iwcommon and add NUM_OPER_MODE [iwconfig] + * o print_stats, print_key, ... use char * instead if FILE * [iwcommon] + * o Add `iw_' prefix to avoid namespace pollution [iwcommon] + * o Add iw_get_basic_config() and iw_set_basic_config() [iwcommon] + * o Move iw_getstats from iwconfig to iwcommon [iwcommon] + * o Move changelog to CHANGELOG.h [iwcommon] + * o Rename iwcommon.* into iwlib.* [iwcommon->iwlib] + * o Compile iwlib. as a dynamic or static library [Makefile] + * o Allow the tools to be compiled with the dynamic library [Makefile] + * --- Update to Wireless Extension 12 --- + * o Show typical/average quality in iwspy [iwspy] + * o Get Wireless Stats through ioctl instead of /proc [iwlib] + * + */ + +/* ----------------------------- TODO ----------------------------- */ +/* + * One day, maybe... + * + * iwconfig : + * -------- + * Make disable a per encryption key modifier if some hardware + * requires it. + * + * iwpriv : + * ------ + * Remove 'port' and 'roam' cruft now that we have mode in iwconfig + * + * iwspy : + * ----- + * - + * + * Doc & man pages : + * --------------- + * Update main doc. + * + * Other : + * ----- + * What about some graphical tools ? + */ diff --git a/wireless_tools/Makefile b/wireless_tools/Makefile index b7f7550..236acbb 100644 --- a/wireless_tools/Makefile +++ b/wireless_tools/Makefile @@ -3,16 +3,27 @@ # # Targets to build +STATIC=libiw.a +DYNAMIC=libiw.so.22 PROGS= iwconfig iwlist iwpriv iwspy iwgetid +# 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 + # Installation directory. By default, go in local. # Distributions should probably use /usr/sbin, but they probably know better... INSTALL_DIR= /usr/local/sbin +INSTALL_LIB= /usr/local/lib +INSTALL_INC= /usr/local/include # This is our header selection. Try to hide the mess and the misery :-( # Please choose *only one* of the define... -# Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0 */ +# Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1 #HEADERS= -DGLIBC22_HEADERS # Kernel headers 2.0.X + Glibc 2.0 - Debian 2.0, RH 5 @@ -42,38 +53,51 @@ RM_CMD = $(RM) *.BAK *.bak *.o ,* *~ *.a CFLAGS=-O2 -Wall $(HEADERS) $(WE_HEADER) -LIBS=-lm +LIBS=$(IWLIBS) -lm -all:: $(PROGS) +all:: $(STATIC) $(DYNAMIC) $(PROGS) .c.o: $(CC) $(CFLAGS) -c $< -iwconfig: iwconfig.o iwcommon.o - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +iwconfig: iwconfig.o $(OBJS) + $(CC) $(CFLAGS) -o $@ $< $(LIBS) -iwlist: iwlist.o iwcommon.o - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +iwlist: iwlist.o $(OBJS) + $(CC) $(CFLAGS) -o $@ $< $(LIBS) -iwpriv: iwpriv.o iwcommon.o - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +iwpriv: iwpriv.o $(OBJS) + $(CC) $(CFLAGS) -o $@ $< $(LIBS) -iwspy: iwspy.o iwcommon.o - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +iwspy: iwspy.o $(OBJS) + $(CC) $(CFLAGS) -o $@ $< $(LIBS) iwgetid: iwgetid.o $(CC) $(CFLAGS) -o $@ $^ +# Compilation of the dynamic library +libiw.so.22: $(OBJS) + $(CC) -O2 -shared -o $@ -Wl,-soname,$@ -lm -lc $^ + +# Compilation of the static library +libiw.a: $(OBJS) + $(RM) $@ + ar cru $@ $^ + ranlib $@ + # So crude but so effective ;-) install:: cp $(PROGS) $(INSTALL_DIR) + cp $(STATIC) $(DYNAMIC) $(INSTALL_LIB) + echo "Don't forget to fix you /etc/ld.so.conf and run ldconfig." + cp iwlib.h $(INSTALL_INC) clean:: $(RM_CMD) realclean:: $(RM_CMD) - $(RM) $(PROGS) + $(RM) $(STATIC) $(DYNAMIC) $(PROGS) depend:: makedepend -s "# DO NOT DELETE" -- $(INCLUDES) -- $(SRCS) diff --git a/wireless_tools/iwcommon.h b/wireless_tools/iwcommon.h deleted file mode 100644 index 1c23c41..0000000 --- a/wireless_tools/iwcommon.h +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Wireless Tools - * - * Jean II - HPLB 97->99 - HPL 99->00 - * - * Common header for the wireless tools... - * - * This file is released under the GPL license. - */ - -#ifndef IWCOMMON_H -#define IWCOMMON_H - -/************************** DOCUMENTATION **************************/ -/* - * None ? Todo... - */ - -/* --------------------------- HISTORY --------------------------- */ -/* - * wireless 16 : (Jean Tourrilhes) - * ----------- - * o iwconfig, iwpriv & iwspy - * - * wireless 17 : (Justin Seger) - * ----------- - * o Compile under glibc fix - * o merge iwpriv in iwconfig - * o Add Wavelan roaming support - * o Update man page of iwconfig - * - * wireless 18 : - * ----------- - * (From Andreas Neuhaus ) - * o Many fix to remove "core dumps" in iwconfig - * o Remove useless headers in iwconfig - * o CHAR wide private ioctl - * (From Jean Tourrilhes) - * o Create iwcommon.h and iwcommon.c - * o Separate iwpriv again for user interface issues - * The folllowing didn't make sense and crashed : - * iwconfig eth0 priv sethisto 12 15 nwid 100 - * o iwspy no longer depend on net-tools-1.2.0 - * o Reorganisation of the code, cleanup - * o Add ESSID stuff in iwconfig - * o Add display of level & noise in dBm (stats in iwconfig) - * o Update man page of iwconfig and iwpriv - * o Add xwireless (didn't check if it compiles) - * (From Dean W. Gehnert ) - * o Minor fixes - * (Jan Rafaj ) - * o Cosmetic changes (sensitivity relative, freq list) - * o Frequency computation on double - * o Compile clean on libc5 - * (From Jean Tourrilhes) - * o Move listing of frequencies to iwspy - * o Add AP address stuff in iwconfig - * o Add AP list stuff in iwspy - * - * wireless 19 : - * ----------- - * (From Jean Tourrilhes) - * o Allow for sensitivity in dBm (if < 0) [iwconfig] - * o Formatting changes in displaying ap address in [iwconfig] - * o Slightly improved man pages and usage display - * o Add channel number for each frequency in list [iwspy] - * o Add nickname... [iwconfig] - * o Add "port" private ioctl shortcut [iwpriv] - * o If signal level = 0, no range or dBms [iwconfig] - * o I think I now got set/get char strings right in [iwpriv] - * (From Thomas Ekstrom ) - * o Fix a very obscure bug in [iwspy] - * - * wireless 20 : - * ----------- - * (From Jean Tourrilhes) - * o Remove all #ifdef WIRELESS ugliness, but add a #error : - * we require Wireless Extensions 9 or nothing ! [all] - * o Switch to new 'nwid' definition (specific -> iw_param) [iwconfig] - * o Rewriten totally the encryption support [iwconfig] - * - Multiple keys, through key index - * - Flexible/multiple key size, and remove 64bits upper limit - * - Open/Restricted modes - * - Enter keys as ASCII strings - * o List key sizes supported and all keys in [iwspy] - * o Mode of operation support (ad-hoc, managed...) [iwconfig] - * o Use '=' to indicate fixed instead of ugly '(f)' [iwconfig] - * o Ability to disable RTS & frag (off), now the right way [iwconfig] - * o Auto as an input modifier for bitrate [iwconfig] - * o Power Management support [iwconfig] - * - set timeout or period and its value - * - Reception mode (unicast/multicast/all) - * o Updated man pages with all that ;-) - * - * wireless 21 : - * ----------- - * (from Alan McReynolds ) - * o Use proper macros for compilation directives [Makefile] - * (From Jean Tourrilhes) - * o Put licensing info everywhere (almost). Yes, it's GPL ! - * o Document the use of /etc/pcmcia/wireless.opts - * o Add min/max modifiers to power management parameters [iwconfig] - * -> requested by Lee Keyser-Allen for the Spectrum24 driver - * o Optionally output a second power management parameter [iwconfig] - * --- - * o Common subroutines to display stats & power saving info [iwcommon] - * o Display all power management info, capability and values [iwspy] - * --- - * o Optional index for ESSID (for Aironet driver) [iwcommon] - * o IW_ENCODE_NOKEY for write only keys [iwconfig/iwspy] - * o Common subrouting to print encoding keys [iwspy] - * --- - * o Transmit Power stuff (dBm + mW) [iwconfig/iwspy] - * o Cleaner formatting algorithm when displaying params [iwconfig] - * --- - * o Fix get_range_info() and use it everywhere - Should fix core dumps. - * o Catch WE version differences between tools and driver and - * warn user. Thanks to Tobias Ringstrom for the tip... [iwcommon] - * o Add Retry limit and lifetime support. [iwconfig/iwlist] - * o Display "Cell:" instead of "Access Point:" in ad-hoc mode [iwconfig] - * o Header fix for glibc2.2 by Ross G. Miller - * o Move header selection flags in Makefile [iwcommon/Makefile] - * o Spin-off iwlist.c from iwspy.c. iwspy is now much smaller - * After moving this bit of code all over the place, from iwpriv - * to iwconfig to iwspy, it now has a home of its own... [iwspy/iwlist] - * o Wrote quick'n'dirty iwgetid. - * o Remove output of second power management parameter [iwconfig] - * Please use iwlist, I don't want to bloat iwconfig - * --- - * o Fix bug in display ints - "Allen Miu" [iwpriv] - */ - -/* ----------------------------- TODO ----------------------------- */ -/* - * One day, maybe... - * - * iwconfig : - * -------- - * Make disable a per encryption key modifier if some hardware - * requires it. - * - * iwpriv : - * ------ - * Remove 'port' and 'roam' cruft now that we have mode in iwconfig - * - * iwspy : - * ----- - * - - * - * Doc & man pages : - * --------------- - * Update main doc. - * - * Other : - * ----- - * What about some graphical tools ? - */ - -/***************************** INCLUDES *****************************/ - -/* Standard headers */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* gethostbyname, getnetbyname */ - -/* This is our header selection. Try to hide the mess and the misery :-( - * The selection has been moved in the Makefile, here we have only - * the ugly part. Don't look, you would go blind ;-) */ - -#ifdef KLUDGE_HEADERS -#include -#endif /* KLUDGE_HEADERS */ - -#if defined(KLUDGE_HEADERS) || defined(GLIBC_HEADERS) -#include /* For ARPHRD_ETHER */ -#include /* For AF_INET & struct sockaddr */ -#include /* For struct sockaddr_in */ -#endif /* KLUDGE_HEADERS || GLIBC_HEADERS */ - -#ifdef GLIBC22_HEADERS -/* Added by Ross G. Miller , 3/28/01 */ -#include /* For ARPHRD_ETHER */ -#include /* For AF_INET & struct sockaddr */ -#include -#endif /* GLIBC22_HEADERS */ - -#ifdef LIBC5_HEADERS -#include /* For AF_INET & struct sockaddr & socket() */ -#include /* For ARPHRD_ETHER */ -#include /* For struct sockaddr_in */ -#endif /* LIBC5_HEADERS */ - -#ifdef PRIVATE_WE_HEADER -/* Private copy of Wireless extensions */ -#include "wireless.h" -#else /* PRIVATE_WE_HEADER */ -/* System wide Wireless extensions */ -#include -#endif /* PRIVATE_WE_HEADER */ - -#if WIRELESS_EXT < 9 -#error "Wireless Extension v9 or newer required :-(\ -Use Wireless Tools v19 or update your kernel headers" -#endif -#if WIRELESS_EXT < 11 -#warning "Wireless Extension v11 recommended...\ -You may update your kernel and/or system headers to get the new features..." -#endif - -/****************************** DEBUG ******************************/ - - -/************************ CONSTANTS & MACROS ************************/ - -/* Some usefull constants */ -#define KILO 1e3 -#define MEGA 1e6 -#define GIGA 1e9 - -/* Backward compatibility for Wireless Extension 9 */ -#ifndef IW_POWER_MODIFIER -#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 */ -#endif IW_POWER_MODIFIER - -#ifndef IW_ENCODE_NOKEY -#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not here */ -#define IW_ENCODE_MODE 0xF000 /* Modes defined below */ -#endif IW_ENCODE_NOKEY - -/****************************** TYPES ******************************/ - -/* Shortcuts */ -typedef struct iw_statistics iwstats; -typedef struct iw_range iwrange; -typedef struct iw_param iwparam; -typedef struct iw_freq iwfreq; -typedef struct iw_quality iwqual; -typedef struct iw_priv_args iwprivargs; -typedef struct sockaddr sockaddr; - -/* Structure for storing all wireless information for each device */ -typedef struct wireless_info -{ - char name[IFNAMSIZ]; /* Wireless/protocol name */ - int has_nwid; - iwparam nwid; /* Network ID */ - int has_freq; - float freq; /* Frequency/channel */ - int has_sens; - iwparam sens; /* sensitivity */ - int has_key; - unsigned char key[IW_ENCODING_TOKEN_MAX]; /* Encoding key used */ - int key_size; /* Number of bytes */ - int key_flags; /* Various flags */ - int has_essid; - int essid_on; - char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID (extended network) */ - int has_nickname; - char nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */ - int has_ap_addr; - sockaddr ap_addr; /* Access point address */ - int has_bitrate; - iwparam bitrate; /* Bit rate in bps */ - int has_rts; - iwparam rts; /* RTS threshold in bytes */ - int has_frag; - iwparam frag; /* Fragmentation threshold in bytes */ - int has_mode; - int mode; /* Operation mode */ - int has_power; - iwparam power; /* Power management parameters */ - int has_txpower; - iwparam txpower; /* Transmit Power in dBm */ - int has_retry; - iwparam retry; /* Retry limit or lifetime */ - - /* Stats */ - iwstats stats; - int has_stats; - iwrange range; - int has_range; -} wireless_info; - -/**************************** PROTOTYPES ****************************/ -/* - * All the functions in iwcommon.c - */ -/* ---------------------- SOCKET SUBROUTINES -----------------------*/ -int - sockets_open(void); -/* --------------------- WIRELESS SUBROUTINES ----------------------*/ -int - get_range_info(int skfd, - char * ifname, - iwrange * range); -int - get_priv_info(int skfd, - char * ifname, - iwprivargs * priv); -/* -------------------- FREQUENCY SUBROUTINES --------------------- */ -void - float2freq(double in, - iwfreq * out); -double - freq2float(iwfreq * in); -/* ---------------------- POWER SUBROUTINES ----------------------- */ -int - dbm2mwatt(int in); -int - mwatt2dbm(int in); -/* -------------------- STATISTICS SUBROUTINES -------------------- */ -void - print_stats(FILE * stream, - iwqual * qual, - iwrange * range, - int has_range); -/* --------------------- ENCODING SUBROUTINES --------------------- */ -void - print_key(FILE * stream, - unsigned char * key, - int key_size, - int key_flags); -/* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */ -void - print_pm_value(FILE * stream, - int value, - int flags); -void - print_pm_mode(FILE * stream, - int flags); -/* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */ -#if WIRELESS_EXT > 10 -void - print_retry_value(FILE * stream, - int value, - int flags); -#endif -/* --------------------- ADDRESS SUBROUTINES ---------------------- */ -int - check_addr_type(int skfd, - char * ifname); -char * - pr_ether(unsigned char *ptr); -int - in_ether(char *bufp, struct sockaddr *sap); -int - in_inet(char *bufp, struct sockaddr *sap); -int - in_addr(int skfd, - char * ifname, - char * bufp, - struct sockaddr *sap); -/* ----------------------- MISC SUBROUTINES ------------------------ */ -int - byte_size(int args); - -/**************************** VARIABLES ****************************/ - -#endif /* IWCOMMON_H */ diff --git a/wireless_tools/iwconfig.c b/wireless_tools/iwconfig.c index b70c049..efc0a43 100644 --- a/wireless_tools/iwconfig.c +++ b/wireless_tools/iwconfig.c @@ -10,15 +10,7 @@ * This file is released under the GPL license. */ -#include "iwcommon.h" /* Header */ - -/**************************** VARIABLES ****************************/ -char * operation_mode[] = { "Auto", - "Ad-Hoc", - "Managed", - "Master", - "Repeater", - "Secondary" }; +#include "iwlib.h" /* Header */ /************************* MISC SUBROUTINES **************************/ @@ -49,69 +41,6 @@ iw_usage(void) /*------------------------------------------------------------------*/ /* - * Read /proc/net/wireless to get the latest statistics - */ -static int -iw_getstats(char * ifname, - iwstats * stats) -{ - FILE * f=fopen("/proc/net/wireless","r"); - char buf[256]; - char * bp; - int t; - if(f==NULL) - return -1; - /* Loop on all devices */ - while(fgets(buf,255,f)) - { - bp=buf; - while(*bp&&isspace(*bp)) - bp++; - /* Is it the good device ? */ - if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') - { - /* Skip ethX: */ - bp=strchr(bp,':'); - bp++; - /* -- status -- */ - bp = strtok(bp, " "); - sscanf(bp, "%X", &t); - stats->status = (unsigned short) t; - /* -- link quality -- */ - bp = strtok(NULL, " "); - if(strchr(bp,'.') != NULL) - stats->qual.updated |= 1; - sscanf(bp, "%d", &t); - stats->qual.qual = (unsigned char) t; - /* -- signal level -- */ - bp = strtok(NULL, " "); - if(strchr(bp,'.') != NULL) - stats->qual.updated |= 2; - sscanf(bp, "%d", &t); - stats->qual.level = (unsigned char) t; - /* -- noise level -- */ - bp = strtok(NULL, " "); - if(strchr(bp,'.') != NULL) - stats->qual.updated += 4; - sscanf(bp, "%d", &t); - stats->qual.noise = (unsigned char) t; - /* -- discarded packets -- */ - bp = strtok(NULL, " "); - sscanf(bp, "%d", &stats->discard.nwid); - bp = strtok(NULL, " "); - sscanf(bp, "%d", &stats->discard.code); - bp = strtok(NULL, " "); - sscanf(bp, "%d", &stats->discard.misc); - fclose(f); - return 0; - } - } - fclose(f); - return -1; -} - -/*------------------------------------------------------------------*/ -/* * Get wireless informations & config from the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to get the settings... @@ -126,7 +55,7 @@ get_info(int skfd, memset((char *) info, 0, sizeof(struct wireless_info)); /* Get wireless name */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0) /* If no wireless name : no wireless extensions */ return(-1); @@ -134,11 +63,11 @@ get_info(int skfd, strcpy(info->name, wrq.u.name); /* Get ranges */ - if(get_range_info(skfd, ifname, &(info->range)) >= 0) + if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0) info->has_range = 1; /* Get network ID */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0) { info->has_nwid = 1; @@ -146,15 +75,15 @@ get_info(int skfd, } /* Get frequency / channel */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0) { info->has_freq = 1; - info->freq = freq2float(&(wrq.u.freq)); + info->freq = iw_freq2float(&(wrq.u.freq)); } /* Get sensitivity */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0) { info->has_sens = 1; @@ -162,7 +91,7 @@ get_info(int skfd, } /* Get encryption information */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) info->key; wrq.u.data.length = 0; wrq.u.data.flags = 0; @@ -174,7 +103,7 @@ get_info(int skfd, } /* Get ESSID */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.essid.pointer = (caddr_t) info->essid; wrq.u.essid.length = 0; wrq.u.essid.flags = 0; @@ -185,7 +114,7 @@ get_info(int skfd, } /* Get AP address */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWAP, &wrq) >= 0) { info->has_ap_addr = 1; @@ -193,7 +122,7 @@ get_info(int skfd, } /* Get NickName */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.essid.pointer = (caddr_t) info->nickname; wrq.u.essid.length = 0; wrq.u.essid.flags = 0; @@ -202,7 +131,7 @@ get_info(int skfd, info->has_nickname = 1; /* Get bit rate */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWRATE, &wrq) >= 0) { info->has_bitrate = 1; @@ -210,7 +139,7 @@ get_info(int skfd, } /* Get RTS threshold */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0) { info->has_rts = 1; @@ -218,7 +147,7 @@ get_info(int skfd, } /* Get fragmentation threshold */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0) { info->has_frag = 1; @@ -226,16 +155,16 @@ get_info(int skfd, } /* Get operation mode */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0) { - if((wrq.u.mode < 6) && (wrq.u.mode >= 0)) + if((wrq.u.mode < IW_NUM_OPER_MODE) && (wrq.u.mode >= 0)) info->has_mode = 1; info->mode = wrq.u.mode; } /* Get Power Management settings */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.power.flags = 0; if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0) { @@ -245,7 +174,7 @@ get_info(int skfd, #if WIRELESS_EXT > 9 /* Get Transmit Power */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWTXPOW, &wrq) >= 0) { info->has_txpower = 1; @@ -255,7 +184,7 @@ get_info(int skfd, #if WIRELESS_EXT > 10 /* Get retry limit/lifetime */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0) { info->has_retry = 1; @@ -264,7 +193,7 @@ get_info(int skfd, #endif /* WIRELESS_EXT > 10 */ /* Get stats */ - if(iw_getstats(ifname, &(info->stats)) >= 0) + if(iw_get_stats(skfd, ifname, &(info->stats)) >= 0) { info->has_stats = 1; } @@ -281,6 +210,8 @@ static void display_info(struct wireless_info * info, char * ifname) { + char buffer[128]; /* Temporary buffer */ + /* One token is more of less 5 character, 14 tokens per line */ int tokens = 3; /* For name */ @@ -300,7 +231,7 @@ display_info(struct wireless_info * info, printf("ESSID:\"%s\" ", info->essid); } else - printf("ESSID:off "); + printf("ESSID:off/any "); } /* Display NickName (station name), if any */ @@ -317,7 +248,7 @@ display_info(struct wireless_info * info, /* Display Network ID */ if(info->has_nwid) { - /* Note : should display right number of digit according to info + /* Note : should display proper number of digit according to info * in range structure */ if(info->nwid.disabled) printf("NWID:off/any "); @@ -329,7 +260,7 @@ display_info(struct wireless_info * info, /* Display the current mode of operation */ if(info->has_mode) { - printf("Mode:%s ", operation_mode[info->mode]); + printf("Mode:%s ", iw_operation_mode[info->mode]); tokens +=3; } @@ -369,7 +300,7 @@ display_info(struct wireless_info * info, printf("Cell:"); else printf("Access Point:"); - printf(" %s", pr_ether(info->ap_addr.sa_data)); + printf(" %s", iw_pr_ether(buffer, info->ap_addr.sa_data)); } /* Display the currently used/set bit-rate */ @@ -426,7 +357,7 @@ display_info(struct wireless_info * info, /* Convert everything to dBm */ if(info->txpower.flags & IW_TXPOW_MWATT) - dbm = mwatt2dbm(info->txpower.value); + dbm = iw_mwatt2dbm(info->txpower.value); else dbm = info->txpower.value; @@ -478,7 +409,11 @@ display_info(struct wireless_info * info, { /* Let's check the value and its type */ if(info->retry.flags & IW_RETRY_TYPE) - print_retry_value(stdout, info->retry.value, info->retry.flags); + { + iw_print_retry_value(buffer, + info->retry.value, info->retry.flags); + printf("%s", buffer); + } /* Let's check if nothing (simply on) */ if(info->retry.flags == IW_RETRY_ON) @@ -548,7 +483,8 @@ display_info(struct wireless_info * info, else { /* Display the key */ - print_key(stdout, info->key, info->key_size, info->key_flags); + iw_print_key(buffer, info->key, info->key_size, info->key_flags); + printf("%s", buffer); /* Other info... */ if((info->key_flags & IW_ENCODE_INDEX) > 1) @@ -574,10 +510,14 @@ display_info(struct wireless_info * info, { /* Let's check the value and its type */ if(info->power.flags & IW_POWER_TYPE) - print_pm_value(stdout, info->power.value, info->power.flags); + { + iw_print_pm_value(buffer, info->power.value, info->power.flags); + printf("%s", buffer); + } /* Let's check the mode */ - print_pm_mode(stdout, info->power.flags); + iw_print_pm_mode(buffer, info->power.flags); + printf("%s", buffer); /* Let's check if nothing (simply on) */ if(info->power.flags == IW_POWER_ON) @@ -590,13 +530,23 @@ display_info(struct wireless_info * info, if(info->has_stats) { info->stats.qual.updated = 0x0; /* Not that reliable, disable */ - printf("Link "); - print_stats(stdout, &info->stats.qual, &info->range, info->has_range); + iw_print_stats(buffer, &info->stats.qual, &info->range, info->has_range); + printf("Link %s\n", buffer); +#if WIRELESS_EXT > 11 + printf(" Rx invalid nwid:%d Rx invalid crypt:%d Rx invalid frag:%d\n Tx excessive retries:%d Invalid misc:%d Missed beacon:%d\n", + info->stats.discard.nwid, + info->stats.discard.code, + info->stats.discard.fragment, + info->stats.discard.retries, + info->stats.discard.misc, + info->stats.miss.beacon); +#else /* WIRELESS_EXT > 11 */ printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n", info->stats.discard.nwid, info->stats.discard.code, info->stats.discard.misc); +#endif /* WIRELESS_EXT > 11 */ } printf("\n"); @@ -698,7 +648,7 @@ set_info(int skfd, /* The socket */ fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno)); return(-1); } - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.nwid.disabled = 0; } else @@ -731,7 +681,7 @@ set_info(int skfd, /* The socket */ if(index(args[i], 'M')) freq *= MEGA; if(index(args[i], 'k')) freq *= KILO; - float2freq(freq, &(wrq.u.freq)); + iw_float2freq(freq, &(wrq.u.freq)); if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0) { @@ -777,7 +727,7 @@ set_info(int skfd, /* The socket */ fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); return(-1); } - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */ } else @@ -806,12 +756,17 @@ set_info(int skfd, /* The socket */ } else { - /* Second case : has hexadecimal digits */ - p = buff = malloc(strlen(args[i]) + 1); + /* Second case : as hexadecimal digits */ + buff = malloc(strlen(args[i]) + 1); + if(buff == NULL) + { + fprintf(stderr, "Setting key : Malloc failed (string too long ?)\n"); + return(-1); + } strcpy(buff, args[i]); p = strtok(buff, "-:;.,"); - while(p != (char *) NULL) + while((p != (char *) NULL) && (k < IW_ENCODING_TOKEN_MAX)) { if(sscanf(p, "%2X", &temp) != 1) { @@ -900,10 +855,12 @@ set_info(int skfd, /* The socket */ fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno)); return(-1); } - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.essid.flags = 1; } else + /* Check the size of what the user passed us to avoid + * buffer overflows */ if(strlen(args[i]) > IW_ESSID_MAX_SIZE) { fprintf(stderr, "ESSID too long (max %d): ``%s''\n", @@ -915,7 +872,7 @@ set_info(int skfd, /* The socket */ int temp; wrq.u.essid.flags = 1; - strcpy(essid, args[i]); + strcpy(essid, args[i]); /* Size checked, all clear */ /* Check for ESSID index */ if(((i+1) < count) && @@ -944,14 +901,14 @@ set_info(int skfd, /* The socket */ iw_usage(); /* Check if we have valid address types */ - if(check_addr_type(skfd, ifname) < 0) + if(iw_check_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname); return(-1); } /* Get the address */ - if(in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0) + if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0) iw_usage(); if(ioctl(skfd, SIOCSIWAP, &wrq) < 0) @@ -1006,7 +963,7 @@ set_info(int skfd, /* The socket */ fprintf(stderr, "SIOCGIWRATE: %s\n", strerror(errno)); return(-1); } - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.bitrate.fixed = 1; } else /* Should be a numeric value */ @@ -1069,7 +1026,7 @@ set_info(int skfd, /* The socket */ fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno)); return(-1); } - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.rts.fixed = 1; } else /* Should be a numeric value */ @@ -1110,7 +1067,7 @@ set_info(int skfd, /* The socket */ fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno)); return(-1); } - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.frag.fixed = 1; } else /* Should be a numeric value */ @@ -1139,10 +1096,11 @@ set_info(int skfd, /* The socket */ if(sscanf(args[i], "%d", &k) != 1) { k = 0; - while(k < 6 && strncasecmp(args[i], operation_mode[k], 3)) + while((k < IW_NUM_OPER_MODE) && + strncasecmp(args[i], iw_operation_mode[k], 3)) k++; } - if((k > 5) || (k < 0)) + if((k >= IW_NUM_OPER_MODE) || (k < 0)) iw_usage(); wrq.u.mode = k; @@ -1171,7 +1129,7 @@ set_info(int skfd, /* The socket */ fprintf(stderr, "SIOCGIWPOWER: %s\n", strerror(errno)); return(-1); } - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.power.disabled = 0; } else @@ -1268,7 +1226,7 @@ set_info(int skfd, /* The socket */ iw_usage(); /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); /* Prepare the request */ @@ -1292,7 +1250,7 @@ set_info(int skfd, /* The socket */ fprintf(stderr, "SIOCGIWTXPOW: %s\n", strerror(errno)); return(-1); } - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.txpower.fixed = 1; } else /* Should be a numeric value */ @@ -1311,11 +1269,11 @@ set_info(int skfd, /* The socket */ /* Convert */ if(!ismwatt && (range.txpower_capa & IW_TXPOW_MWATT)) { - power = dbm2mwatt(power); + power = iw_dbm2mwatt(power); wrq.u.data.flags = IW_TXPOW_MWATT; } if(ismwatt && !(range.txpower_capa & IW_TXPOW_MWATT)) - power = mwatt2dbm(power); + power = iw_mwatt2dbm(power); wrq.u.bitrate.value = power; /* Check for an additional argument */ @@ -1441,7 +1399,7 @@ main(int argc, int goterr = 0; /* Create a channel to the NET kernel. */ - if((skfd = sockets_open()) < 0) + if((skfd = iw_sockets_open()) < 0) { perror("socket"); exit(-1); diff --git a/wireless_tools/iwgetid.c b/wireless_tools/iwgetid.c index ef3ea8d..226c8c5 100644 --- a/wireless_tools/iwgetid.c +++ b/wireless_tools/iwgetid.c @@ -8,7 +8,7 @@ * This file is released under the GPL license. */ -#include "iwcommon.h" /* Header */ +#include "iwlib.h" /* Header */ #define FORMAT_DEFAULT 0 /* Nice looking display for the user */ #define FORMAT_SCHEME 1 /* To be used as a Pcmcia Scheme */ @@ -78,7 +78,7 @@ print_essid(int skfd, int j; /* Get ESSID */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = 0; wrq.u.essid.flags = 0; @@ -119,7 +119,7 @@ print_nwid(int skfd, struct iwreq wrq; /* Get network ID */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0) return(-1); @@ -185,15 +185,14 @@ scan_devices(int skfd, * Display an Ethernet address in readable format. */ char * -pr_ether(unsigned char *ptr) +pr_ether(char * buffer, + unsigned char *ptr) { - static char buff[64]; - - sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X", - (ptr[0] & 0xFF), (ptr[1] & 0xFF), (ptr[2] & 0xFF), - (ptr[3] & 0xFF), (ptr[4] & 0xFF), (ptr[5] & 0xFF) + 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(buff); + return(buffer); } /*------------------------------------------------------------------*/ @@ -242,15 +241,16 @@ print_ap(int skfd, int format) { struct iwreq wrq; + char buffer[64]; /* Get network ID */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWAP, &wrq) < 0) return(-1); /* Print */ printf("%-8.8s Access Point: %s\n", ifname, - pr_ether(wrq.u.ap_addr.sa_data)); + pr_ether(buffer, wrq.u.ap_addr.sa_data)); return(0); } diff --git a/wireless_tools/iwcommon.c b/wireless_tools/iwlib.c similarity index 52% rename from wireless_tools/iwcommon.c rename to wireless_tools/iwlib.c index 0b2be07..ed3e357 100644 --- a/wireless_tools/iwcommon.c +++ b/wireless_tools/iwlib.c @@ -1,14 +1,23 @@ /* * Wireless Tools * - * Jean II - HPLB 97->99 - HPL 99->00 + * Jean II - HPLB 97->99 - HPL 99->01 * * Common subroutines to all the wireless tools... * * This file is released under the GPL license. */ -#include "iwcommon.h" /* Header */ +#include "iwlib.h" /* Header */ + +/**************************** VARIABLES ****************************/ + +const char * iw_operation_mode[] = { "Auto", + "Ad-Hoc", + "Managed", + "Master", + "Repeater", + "Secondary" }; /************************ SOCKET SUBROUTINES *************************/ @@ -19,31 +28,35 @@ * will allow us to talk to the driver. */ int -sockets_open(void) +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 */ - - 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; + 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; } /*********************** WIRELESS SUBROUTINES ************************/ @@ -53,9 +66,9 @@ sockets_open(void) * Get the range information out of the driver */ int -get_range_info(int skfd, - char * ifname, - iwrange * range) +iw_get_range_info(int skfd, + char * ifname, + iwrange * range) { struct iwreq wrq; char buffer[sizeof(iwrange) * 2]; /* Large enough */ @@ -63,7 +76,7 @@ get_range_info(int skfd, /* Cleanup */ memset(buffer, 0, sizeof(range)); - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = 0; wrq.u.data.flags = 0; @@ -115,14 +128,14 @@ get_range_info(int skfd, * Get information about what private ioctls are supported by the driver */ int -get_priv_info(int skfd, - char * ifname, - iwprivargs * priv) +iw_get_priv_info(int skfd, + char * ifname, + iwprivargs * priv) { struct iwreq wrq; /* Ask the driver */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) priv; wrq.u.data.length = 0; wrq.u.data.flags = 0; @@ -133,6 +146,200 @@ get_priv_info(int skfd, return(wrq.u.data.length); } +/*------------------------------------------------------------------*/ +/* + * Get essential wireless config from the device driver + * We will call all the classical wireless ioctl on the driver through + * the socket to know what is supported and to get the settings... + * Note : compare to the version in iwconfig, we extract only + * what's *really* needed to configure a device... + */ +int +iw_get_basic_config(int skfd, + char * ifname, + wireless_config * info) +{ + struct iwreq wrq; + + memset((char *) info, 0, sizeof(struct wireless_config)); + + /* Get wireless name */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0) + /* If no wireless name : no wireless extensions */ + return(-1); + else + strcpy(info->name, wrq.u.name); + + /* Get network ID */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0) + { + info->has_nwid = 1; + memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam)); + } + + /* Get frequency / channel */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0) + { + info->has_freq = 1; + info->freq = iw_freq2float(&(wrq.u.freq)); + } + + /* Get encryption information */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + wrq.u.data.pointer = (caddr_t) info->key; + wrq.u.data.length = 0; + wrq.u.data.flags = 0; + if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0) + { + info->has_key = 1; + info->key_size = wrq.u.data.length; + info->key_flags = wrq.u.data.flags; + } + + /* Get ESSID */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + wrq.u.essid.pointer = (caddr_t) info->essid; + wrq.u.essid.length = 0; + wrq.u.essid.flags = 0; + if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0) + { + info->has_essid = 1; + info->essid_on = wrq.u.data.flags; + } + + /* Get operation mode */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0) + { + if((wrq.u.mode < 6) && (wrq.u.mode >= 0)) + info->has_mode = 1; + info->mode = wrq.u.mode; + } + + return(0); +} + +/*------------------------------------------------------------------*/ +/* + * Set essential wireless config in the device driver + * We will call all the classical wireless ioctl on the driver through + * the socket to know what is supported and to set the settings... + * We support only the restricted set as above... + */ +int +iw_set_basic_config(int skfd, + char * ifname, + wireless_config * info) +{ + struct iwreq wrq; + int ret = 0; + + /* Get wireless name (check if interface is valid) */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0) + /* If no wireless name : no wireless extensions */ + return(-2); + + /* Set Network ID, if available (this is for non-802.11 cards) */ + if(info->has_nwid) + { + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam)); + wrq.u.nwid.fixed = 1; /* Hum... When in Rome... */ + + if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno)); + ret = -1; + } + } + + /* Set frequency / channel */ + if(info->has_freq) + { + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + iw_float2freq(info->freq, &(wrq.u.freq)); + + if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); + ret = -1; + } + } + + /* Set encryption information */ + if(info->has_key) + { + int flags = info->key_flags; + + /* Check if there is a key index */ + if((flags & IW_ENCODE_INDEX) > 0) + { + /* Set the index */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + wrq.u.data.pointer = (caddr_t) NULL; + wrq.u.data.flags = flags & (IW_ENCODE_INDEX); + wrq.u.data.length = 0; + + if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", + errno, strerror(errno)); + ret = -1; + } + } + + /* Mask out index to minimise probability of reject when setting key */ + flags = flags & (~IW_ENCODE_INDEX); + + /* Set the key itself (set current key in this case) */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + wrq.u.data.pointer = (caddr_t) info->key; + wrq.u.data.length = info->key_size; + wrq.u.data.flags = flags; + + if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", + errno, strerror(errno)); + ret = -1; + } + } + + /* Set ESSID (extended network), if available */ + if(info->has_essid) + { + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + wrq.u.essid.pointer = (caddr_t) info->essid; + wrq.u.essid.length = strlen(info->essid) + 1; + wrq.u.data.flags = info->essid_on; + + if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno)); + ret = -1; + } + } + + /* Set the current mode of operation */ + if(info->has_mode) + { + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + wrq.u.mode = info->mode; + + if(ioctl(skfd, SIOCSIWMODE, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno)); + ret = -1; + } + } + + return(ret); +} + /********************** FREQUENCY SUBROUTINES ***********************/ /*------------------------------------------------------------------*/ @@ -143,8 +350,8 @@ get_priv_info(int skfd, * this custom format instead. */ void -float2freq(double in, - iwfreq * out) +iw_float2freq(double in, + iwfreq * out) { out->e = (short) (floor(log10(in))); if(out->e > 8) @@ -164,7 +371,7 @@ float2freq(double in, * Convert our internal representation of frequencies to a floating point. */ double -freq2float(iwfreq * in) +iw_freq2float(iwfreq * in) { return ((double) in->m) * pow(10,in->e); } @@ -176,7 +383,7 @@ freq2float(iwfreq * in) * Convert a value in dBm to a value in milliWatt. */ int -dbm2mwatt(int in) +iw_dbm2mwatt(int in) { return((int) (floor(pow(10.0, (((double) in) / 10.0))))); } @@ -186,7 +393,7 @@ dbm2mwatt(int in) * Convert a value in milliWatt to a value in dBm. */ int -mwatt2dbm(int in) +iw_mwatt2dbm(int in) { return((int) (ceil(10.0 * log10((double) in)))); } @@ -195,13 +402,89 @@ mwatt2dbm(int in) /*------------------------------------------------------------------*/ /* + * Read /proc/net/wireless to get the latest statistics + */ +int +iw_get_stats(int skfd, + char * ifname, + iwstats * stats) +{ +#if WIRELESS_EXT > 11 + struct iwreq wrq; + wrq.u.data.pointer = (caddr_t) stats; + wrq.u.data.length = 0; + wrq.u.data.flags = 1; /* Clear updated flag */ + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if(ioctl(skfd, SIOCGIWSTATS, &wrq) < 0) + return(-1); + + return(0); +#else /* WIRELESS_EXT > 11 */ + FILE * f=fopen("/proc/net/wireless","r"); + char buf[256]; + char * bp; + int t; + if(f==NULL) + return -1; + /* Loop on all devices */ + while(fgets(buf,255,f)) + { + bp=buf; + while(*bp&&isspace(*bp)) + bp++; + /* Is it the good device ? */ + if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') + { + /* Skip ethX: */ + bp=strchr(bp,':'); + bp++; + /* -- status -- */ + bp = strtok(bp, " "); + sscanf(bp, "%X", &t); + stats->status = (unsigned short) t; + /* -- link quality -- */ + bp = strtok(NULL, " "); + if(strchr(bp,'.') != NULL) + stats->qual.updated |= 1; + sscanf(bp, "%d", &t); + stats->qual.qual = (unsigned char) t; + /* -- signal level -- */ + bp = strtok(NULL, " "); + if(strchr(bp,'.') != NULL) + stats->qual.updated |= 2; + sscanf(bp, "%d", &t); + stats->qual.level = (unsigned char) t; + /* -- noise level -- */ + bp = strtok(NULL, " "); + if(strchr(bp,'.') != NULL) + stats->qual.updated += 4; + sscanf(bp, "%d", &t); + stats->qual.noise = (unsigned char) t; + /* -- discarded packets -- */ + bp = strtok(NULL, " "); + sscanf(bp, "%d", &stats->discard.nwid); + bp = strtok(NULL, " "); + sscanf(bp, "%d", &stats->discard.code); + bp = strtok(NULL, " "); + sscanf(bp, "%d", &stats->discard.misc); + fclose(f); + return 0; + } + } + fclose(f); + return -1; +#endif /* WIRELESS_EXT > 11 */ +} + +/*------------------------------------------------------------------*/ +/* * Output the link statistics, taking care of formating */ void -print_stats(FILE * stream, - iwqual * qual, - iwrange * range, - int has_range) +iw_print_stats(char * buffer, + iwqual * qual, + iwrange * range, + int has_range) { /* Just do it */ if(has_range && (qual->level != 0)) @@ -210,8 +493,8 @@ print_stats(FILE * stream, if(qual->level > range->max_qual.level) { /* Statistics are in dBm (absolute power measurement) */ - fprintf(stream, - "Quality:%d/%d Signal level:%d dBm Noise level:%d dBm%s\n", + sprintf(buffer, + "Quality:%d/%d Signal level:%d dBm Noise level:%d dBm%s", qual->qual, range->max_qual.qual, qual->level - 0x100, qual->noise - 0x100, (qual->updated & 0x7) ? " (updated)" : ""); @@ -219,8 +502,8 @@ print_stats(FILE * stream, else { /* Statistics are relative values (0 -> max) */ - fprintf(stream, - "Quality:%d/%d Signal level:%d/%d Noise level:%d/%d%s\n", + sprintf(buffer, + "Quality:%d/%d Signal level:%d/%d Noise level:%d/%d%s", qual->qual, range->max_qual.qual, qual->level, range->max_qual.level, qual->noise, range->max_qual.noise, @@ -230,7 +513,7 @@ print_stats(FILE * stream, else { /* We can't read the range, so we don't know... */ - fprintf(stream, "Quality:%d Signal level:%d Noise level:%d%s\n", + sprintf(buffer, "Quality:%d Signal level:%d Noise level:%d%s", qual->qual, qual->level, qual->noise, (qual->updated & 0x7) ? " (updated)" : ""); } @@ -243,10 +526,10 @@ print_stats(FILE * stream, * Output the encoding key, with a nice formating */ void -print_key(FILE * stream, - unsigned char * key, - int key_size, - int key_flags) +iw_print_key(char * buffer, + unsigned char * key, + int key_size, + int key_flags) { int i; @@ -254,23 +537,27 @@ print_key(FILE * stream, if(key_flags & IW_ENCODE_NOKEY) { /* Nope : print dummy */ - printf("**"); + strcpy(buffer, "**"); + buffer +=2; for(i = 1; i < key_size; i++) { if((i & 0x1) == 0) - printf("-"); - printf("**"); + strcpy(buffer++, "-"); + strcpy(buffer, "**"); + buffer +=2; } } else { /* Yes : print the key */ - printf("%.2X", key[0]); + sprintf(buffer, "%.2X", key[0]); + buffer +=2; for(i = 1; i < key_size; i++) { if((i & 0x1) == 0) - printf("-"); - printf("%.2X", key[i]); + strcpy(buffer++, "-"); + sprintf(buffer, "%.2X", key[i]); + buffer +=2; } } } @@ -283,35 +570,47 @@ print_key(FILE * stream, * Output a power management value with all attributes... */ void -print_pm_value(FILE * stream, - int value, - int flags) +iw_print_pm_value(char * buffer, + int value, + int flags) { /* Modifiers */ if(flags & IW_POWER_MIN) - fprintf(stream, " min"); + { + strcpy(buffer, " min"); + buffer += 4; + } if(flags & IW_POWER_MAX) - fprintf(stream, " max"); + { + strcpy(buffer, " max"); + buffer += 4; + } /* Type */ if(flags & IW_POWER_TIMEOUT) - fprintf(stream, " timeout:"); + { + strcpy(buffer, " timeout:"); + buffer += 9; + } else - fprintf(stream, " period:"); + { + strcpy(buffer, " period:"); + buffer += 8; + } /* Display value without units */ if(flags & IW_POWER_RELATIVE) - fprintf(stream, "%g ", ((double) value) / MEGA); + sprintf(buffer, "%g ", ((double) value) / MEGA); else { /* Display value with units */ if(value >= (int) MEGA) - fprintf(stream, "%gs ", ((double) value) / MEGA); + sprintf(buffer, "%gs ", ((double) value) / MEGA); else if(value >= (int) KILO) - fprintf(stream, "%gms ", ((double) value) / KILO); + sprintf(buffer, "%gms ", ((double) value) / KILO); else - fprintf(stream, "%dus ", value); + sprintf(buffer, "%dus ", value); } } @@ -320,26 +619,26 @@ print_pm_value(FILE * stream, * Output a power management mode */ void -print_pm_mode(FILE * stream, - int flags) +iw_print_pm_mode(char * buffer, + int flags) { /* Print the proper mode... */ switch(flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: - fprintf(stream, " mode:Unicast only received"); + strcpy(buffer, " mode:Unicast only received"); break; case IW_POWER_MULTICAST_R: - fprintf(stream, " mode:Multicast only received"); + strcpy(buffer, " mode:Multicast only received"); break; case IW_POWER_ALL_R: - fprintf(stream, " mode:All packets received"); + strcpy(buffer, " mode:All packets received"); break; case IW_POWER_FORCE_S: - fprintf(stream, " mode:Force sending"); + strcpy(buffer, " mode:Force sending"); break; case IW_POWER_REPEATER: - fprintf(stream, " mode:Repeat multicasts"); + strcpy(buffer, " mode:Repeat multicasts"); break; default: } @@ -353,38 +652,45 @@ print_pm_mode(FILE * stream, * Output a retry value with all attributes... */ void -print_retry_value(FILE * stream, - int value, - int flags) +iw_print_retry_value(char * buffer, + int value, + int flags) { /* Modifiers */ if(flags & IW_RETRY_MIN) - fprintf(stream, " min"); + { + strcpy(buffer, " min"); + buffer += 4; + } if(flags & IW_RETRY_MAX) - fprintf(stream, " max"); + { + strcpy(buffer, " max"); + buffer += 4; + } /* Type lifetime of limit */ if(flags & IW_RETRY_LIFETIME) { - fprintf(stream, " lifetime:"); + strcpy(buffer, " lifetime:"); + buffer += 10; /* Display value without units */ if(flags & IW_POWER_RELATIVE) - fprintf(stream, "%g", ((double) value) / MEGA); + sprintf(buffer, "%g", ((double) value) / MEGA); else { /* Display value with units */ if(value >= (int) MEGA) - fprintf(stream, "%gs", ((double) value) / MEGA); + sprintf(buffer, "%gs", ((double) value) / MEGA); else if(value >= (int) KILO) - fprintf(stream, "%gms", ((double) value) / KILO); + sprintf(buffer, "%gms", ((double) value) / KILO); else - fprintf(stream, "%dus", value); + sprintf(buffer, "%dus", value); } } else - fprintf(stream, " limit:%d", value); + sprintf(buffer, " limit:%d", value); } #endif /* WIRELESS_EXT > 10 */ @@ -399,13 +705,13 @@ print_retry_value(FILE * stream, * Check if interface support the right address types... */ int -check_addr_type(int skfd, - char * ifname) +iw_check_addr_type(int skfd, + char * ifname) { struct ifreq ifr; /* Get the type of interface address */ - strcpy(ifr.ifr_name, ifname); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) || (ifr.ifr_addr.sa_family != AF_INET)) { @@ -420,7 +726,7 @@ check_addr_type(int skfd, #endif /* Get the type of hardware address */ - strcpy(ifr.ifr_name, ifname); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) || (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)) { @@ -444,15 +750,14 @@ check_addr_type(int skfd, * Display an Ethernet address in readable format. */ char * -pr_ether(unsigned char *ptr) +iw_pr_ether(char * buffer, + unsigned char * ptr) { - static char buff[64]; - - sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X", - (ptr[0] & 0xFF), (ptr[1] & 0xFF), (ptr[2] & 0xFF), - (ptr[3] & 0xFF), (ptr[4] & 0xFF), (ptr[5] & 0xFF) + 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(buff); + return(buffer); } /*------------------------------------------------------------------*/ @@ -460,7 +765,7 @@ pr_ether(unsigned char *ptr) * Input an Ethernet address and convert to binary. */ int -in_ether(char *bufp, struct sockaddr *sap) +iw_in_ether(char *bufp, struct sockaddr *sap) { unsigned char *ptr; char c, *orig; @@ -533,7 +838,7 @@ in_ether(char *bufp, struct sockaddr *sap) * Input an Internet address and convert to binary. */ int -in_inet(char *bufp, struct sockaddr *sap) +iw_in_inet(char *bufp, struct sockaddr *sap) { struct hostent *hp; struct netent *np; @@ -571,10 +876,10 @@ in_inet(char *bufp, struct sockaddr *sap) * Input an address and convert to binary. */ int -in_addr(int skfd, - char * ifname, - char * bufp, - struct sockaddr *sap) +iw_in_addr(int skfd, + char * ifname, + char * bufp, + struct sockaddr *sap) { /* Check if it is a hardware or IP address */ if(index(bufp, ':') == NULL) @@ -583,7 +888,7 @@ in_addr(int skfd, struct arpreq arp_query; /* Read interface address */ - if(in_inet(bufp, &if_address) < 0) + if(iw_in_inet(bufp, &if_address) < 0) { fprintf(stderr, "Invalid interface address %s\n", bufp); return(-1); @@ -597,7 +902,7 @@ in_addr(int skfd, arp_query.arp_flags = 0; /* The following restrict the search to the interface only */ /* For old kernels which complain, just comment it... */ - strcpy(arp_query.arp_dev, ifname); + strncpy(arp_query.arp_dev, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGARP, &arp_query) < 0) || !(arp_query.arp_flags & ATF_COM)) { @@ -618,7 +923,7 @@ in_addr(int skfd, } else /* If it's an hardware address */ /* Get the hardware address */ - if(in_ether(bufp, sap) < 0) + if(iw_in_ether(bufp, sap) < 0) { fprintf(stderr, "Invalid hardware address %s\n", bufp); return(-1); @@ -637,7 +942,7 @@ in_addr(int skfd, /* */ int -byte_size(int args) +iw_byte_size(int args) { int ret = args & IW_PRIV_SIZE_MASK; diff --git a/wireless_tools/iwlib.h b/wireless_tools/iwlib.h new file mode 100644 index 0000000..723475b --- /dev/null +++ b/wireless_tools/iwlib.h @@ -0,0 +1,265 @@ +/* + * Wireless Tools + * + * Jean II - HPLB 97->99 - HPL 99->01 + * + * Common header for the Wireless Extension library... + * + * This file is released under the GPL license. + */ + +#ifndef IWLIB_H +#define IWLIB_H + +/*#include "CHANGELOG.h"*/ + +/***************************** INCLUDES *****************************/ + +/* Standard headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* gethostbyname, getnetbyname */ + +/* This is our header selection. Try to hide the mess and the misery :-( + * The selection has been moved in the Makefile, here we have only + * the ugly part. Don't look, you would go blind ;-) */ + +#ifdef KLUDGE_HEADERS +#include +#endif /* KLUDGE_HEADERS */ + +#if defined(KLUDGE_HEADERS) || defined(GLIBC_HEADERS) +#include /* For ARPHRD_ETHER */ +#include /* For AF_INET & struct sockaddr */ +#include /* For struct sockaddr_in */ +#endif /* KLUDGE_HEADERS || GLIBC_HEADERS */ + +#ifdef GLIBC22_HEADERS +/* Added by Ross G. Miller , 3/28/01 */ +#include /* For ARPHRD_ETHER */ +#include /* For AF_INET & struct sockaddr */ +#include +#endif /* GLIBC22_HEADERS */ + +#ifdef LIBC5_HEADERS +#include /* For AF_INET & struct sockaddr & socket() */ +#include /* For ARPHRD_ETHER */ +#include /* For struct sockaddr_in */ +#endif /* LIBC5_HEADERS */ + +#ifdef PRIVATE_WE_HEADER +/* Private copy of Wireless extensions */ +#include "wireless.h" +#else /* PRIVATE_WE_HEADER */ +/* System wide Wireless extensions */ +#include +#endif /* PRIVATE_WE_HEADER */ + +#if WIRELESS_EXT < 9 +#error "Wireless Extension v9 or newer required :-(\ +Use Wireless Tools v19 or update your kernel headers" +#endif +#if WIRELESS_EXT < 11 +#warning "Wireless Extension v11 recommended...\ +You may update your kernel and/or system headers to get the new features..." +#endif + +/****************************** DEBUG ******************************/ + + +/************************ CONSTANTS & MACROS ************************/ + +/* Some usefull constants */ +#define KILO 1e3 +#define MEGA 1e6 +#define GIGA 1e9 + +/* Backward compatibility for Wireless Extension 9 */ +#ifndef IW_POWER_MODIFIER +#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 */ +#endif IW_POWER_MODIFIER + +#ifndef IW_ENCODE_NOKEY +#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not here */ +#define IW_ENCODE_MODE 0xF000 /* Modes defined below */ +#endif IW_ENCODE_NOKEY + +/****************************** TYPES ******************************/ + +/* Shortcuts */ +typedef struct iw_statistics iwstats; +typedef struct iw_range iwrange; +typedef struct iw_param iwparam; +typedef struct iw_freq iwfreq; +typedef struct iw_quality iwqual; +typedef struct iw_priv_args iwprivargs; +typedef struct sockaddr sockaddr; + +/* Structure for storing all wireless information for each device + * This is pretty exhaustive... */ +typedef struct wireless_info +{ + char name[IFNAMSIZ]; /* Wireless/protocol name */ + int has_nwid; + iwparam nwid; /* Network ID */ + int has_freq; + float freq; /* Frequency/channel */ + int has_sens; + iwparam sens; /* sensitivity */ + int has_key; + unsigned char key[IW_ENCODING_TOKEN_MAX]; /* Encoding key used */ + int key_size; /* Number of bytes */ + int key_flags; /* Various flags */ + int has_essid; + int essid_on; + char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID (extended network) */ + int has_nickname; + char nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */ + int has_ap_addr; + sockaddr ap_addr; /* Access point address */ + int has_bitrate; + iwparam bitrate; /* Bit rate in bps */ + int has_rts; + iwparam rts; /* RTS threshold in bytes */ + int has_frag; + iwparam frag; /* Fragmentation threshold in bytes */ + int has_mode; + int mode; /* Operation mode */ + int has_power; + iwparam power; /* Power management parameters */ + int has_txpower; + iwparam txpower; /* Transmit Power in dBm */ + int has_retry; + iwparam retry; /* Retry limit or lifetime */ + + /* Stats */ + iwstats stats; + int has_stats; + iwrange range; + int has_range; +} wireless_info; + +/* Structure for storing all wireless information for each device + * This is a cut down version of the one above, containing only + * the things *truly* needed to configure a card. + * Don't add other junk, I'll remove it... */ +typedef struct wireless_config +{ + char name[IFNAMSIZ]; /* Wireless/protocol name */ + int has_nwid; + iwparam nwid; /* Network ID */ + int has_freq; + float freq; /* Frequency/channel */ + int has_key; + unsigned char key[IW_ENCODING_TOKEN_MAX]; /* Encoding key used */ + int key_size; /* Number of bytes */ + int key_flags; /* Various flags */ + int has_essid; + int essid_on; + char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID (extended network) */ + int has_mode; + int mode; /* Operation mode */ +} wireless_config; + +/**************************** PROTOTYPES ****************************/ +/* + * All the functions in iwcommon.c + */ +/* ---------------------- SOCKET SUBROUTINES -----------------------*/ +int + iw_sockets_open(void); +/* --------------------- WIRELESS SUBROUTINES ----------------------*/ +int + iw_get_range_info(int skfd, + char * ifname, + iwrange * range); +int + iw_get_priv_info(int skfd, + char * ifname, + iwprivargs * priv); +int + iw_get_basic_config(int skfd, + char * ifname, + wireless_config * info); +int + iw_set_basic_config(int skfd, + char * ifname, + wireless_config * info); +/* -------------------- FREQUENCY SUBROUTINES --------------------- */ +void + iw_float2freq(double in, + iwfreq * out); +double + iw_freq2float(iwfreq * in); +/* ---------------------- POWER SUBROUTINES ----------------------- */ +int + iw_dbm2mwatt(int in); +int + iw_mwatt2dbm(int in); +/* -------------------- STATISTICS SUBROUTINES -------------------- */ +int + iw_get_stats(int skfd, + char * ifname, + iwstats * stats); +void + iw_print_stats(char * buffer, + iwqual * qual, + iwrange * range, + int has_range); +/* --------------------- ENCODING SUBROUTINES --------------------- */ +void + iw_print_key(char * buffer, + unsigned char * key, + int key_size, + int key_flags); +/* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */ +void + iw_print_pm_value(char * buffer, + int value, + int flags); +void + iw_print_pm_mode(char * buffer, + int flags); +/* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */ +#if WIRELESS_EXT > 10 +void + iw_print_retry_value(char * buffer, + int value, + int flags); +#endif +/* --------------------- ADDRESS SUBROUTINES ---------------------- */ +int + iw_check_addr_type(int skfd, + char * ifname); +char * + iw_pr_ether(char *buffer, unsigned char *ptr); +int + iw_in_ether(char *bufp, struct sockaddr *sap); +int + iw_in_inet(char *bufp, struct sockaddr *sap); +int + iw_in_addr(int skfd, + char * ifname, + char * bufp, + struct sockaddr * sap); +/* ----------------------- MISC SUBROUTINES ------------------------ */ +int + iw_byte_size(int args); + +/**************************** VARIABLES ****************************/ + +extern const char * iw_operation_mode[]; +#define IW_NUM_OPER_MODE 6 + +#endif /* IWLIB_H */ diff --git a/wireless_tools/iwlist.c b/wireless_tools/iwlist.c index b8284af..50db6c9 100644 --- a/wireless_tools/iwlist.c +++ b/wireless_tools/iwlist.c @@ -10,7 +10,7 @@ * This file is released under the GPL license. */ -#include "iwcommon.h" /* Header */ +#include "iwlib.h" /* Header */ /*********************** FREQUENCIES/CHANNELS ***********************/ @@ -26,7 +26,7 @@ print_freq_info(int skfd, struct iw_range range; int k; - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no frequency information.\n\n", ifname); else @@ -39,7 +39,7 @@ print_freq_info(int skfd, for(k = 0; k < range.num_frequency; k++) { printf("\t Channel %.2d : ", range.freq[k].i); - freq = freq2float(&(range.freq[k])); + freq = iw_freq2float(&(range.freq[k])); if(freq >= GIGA) printf("%g GHz\n", freq / GIGA); else @@ -56,33 +56,6 @@ print_freq_info(int skfd, } } -/*------------------------------------------------------------------*/ -/* - * Get frequency info on all devices and print it on the screen - */ -static void -print_freq_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_freq_info(skfd, ifr->ifr_name); -} - /************************ ACCESS POINT LIST ************************/ /*------------------------------------------------------------------*/ @@ -92,11 +65,12 @@ print_freq_devices(int skfd) */ static void print_ap_info(int skfd, - char * ifname) + char * ifname) { struct iwreq wrq; char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_AP]; + char temp[128]; struct sockaddr * hwa; struct iw_quality * qual; iwrange range; @@ -125,14 +99,14 @@ print_ap_info(int skfd, qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); /* Check if we have valid address types */ - if(check_addr_type(skfd, ifname) < 0) + if(iw_check_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname); return; } /* Get range info if we can */ - if(get_range_info(skfd, ifname, &(range)) >= 0) + if(iw_get_range_info(skfd, ifname, &(range)) >= 0) has_range = 1; /* Display it */ @@ -145,43 +119,17 @@ print_ap_info(int skfd, if(has_qual) { /* Print stats for this address */ - printf(" %s : ", pr_ether(hwa[i].sa_data)); - print_stats(stdout, &qual[i], &range, has_range); + printf(" %s : ", iw_pr_ether(temp, hwa[i].sa_data)); + iw_print_stats(temp, &qual[i], &range, has_range); + printf("%s\n", temp); } else /* Only print the address */ - printf(" %s\n", pr_ether(hwa[i].sa_data)); + printf(" %s\n", iw_pr_ether(temp, hwa[i].sa_data)); } printf("\n"); } -/*------------------------------------------------------------------*/ -/* - * Get list of AP on all devices and print it on the screen - */ -static void -print_ap_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_ap_info(skfd, ifr->ifr_name); -} - /***************************** BITRATES *****************************/ /*------------------------------------------------------------------*/ @@ -197,7 +145,7 @@ print_bitrate_info(int skfd, int k; /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no bit-rate information.\n\n", ifname); else @@ -226,33 +174,6 @@ print_bitrate_info(int skfd, } } -/*------------------------------------------------------------------*/ -/* - * Get bit-rate info on all devices and print it on the screen - */ -static void -print_bitrate_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_bitrate_info(skfd, ifr->ifr_name); -} - /************************* ENCRYPTION KEYS *************************/ /*------------------------------------------------------------------*/ @@ -267,9 +188,10 @@ print_keys_info(int skfd, struct iw_range range; unsigned char key[IW_ENCODING_TOKEN_MAX]; int k; + char buffer[128]; /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no encryption keys information.\n\n", ifname); else @@ -290,7 +212,7 @@ print_keys_info(int skfd, printf("%d keys available :\n", range.max_encoding_tokens); for(k = 1; k <= range.max_encoding_tokens; k++) { - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = 0; wrq.u.data.flags = k; @@ -305,8 +227,8 @@ print_keys_info(int skfd, else { /* Display the key */ - printf("\t\t[%d]: ", k); - print_key(stdout, key, wrq.u.data.length, wrq.u.data.flags); + iw_print_key(buffer, key, wrq.u.data.length, wrq.u.data.flags); + printf("\t\t[%d]: %s", k, buffer); /* Other info... */ printf(" (%d bits)", wrq.u.data.length * 8); @@ -314,7 +236,7 @@ print_keys_info(int skfd, } } /* Print current key and mode */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = 0; wrq.u.data.flags = 0; /* Set index to zero to get current */ @@ -334,33 +256,6 @@ print_keys_info(int skfd, } } -/*------------------------------------------------------------------*/ -/* - * Get encryption info on all devices and print it on the screen - */ -static void -print_keys_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_keys_info(skfd, ifr->ifr_name); -} - /************************* POWER MANAGEMENT *************************/ /*------------------------------------------------------------------*/ @@ -371,18 +266,19 @@ static inline int get_pm_value(int skfd, char * ifname, struct iwreq * pwrq, - int flags) + int flags, + char * buffer) { /* Get Another Power Management value */ - strcpy(pwrq->ifr_name, ifname); + strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); pwrq->u.power.flags = flags; if(ioctl(skfd, SIOCGIWPOWER, pwrq) >= 0) { /* Let's check the value and its type */ if(pwrq->u.power.flags & IW_POWER_TYPE) { - printf("\n "); - print_pm_value(stdout, pwrq->u.power.value, pwrq->u.power.flags); + iw_print_pm_value(buffer, pwrq->u.power.value, pwrq->u.power.flags); + printf("\n %s", buffer); } } return(pwrq->u.power.flags); @@ -398,9 +294,10 @@ print_pm_info(int skfd, { struct iwreq wrq; struct iw_range range; + char buffer[128]; /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no power management information.\n\n", ifname); else @@ -432,10 +329,10 @@ print_pm_info(int skfd, else printf("Fixed period ; "); /* Print the range */ - print_pm_value(stdout, range.min_pmp, flags | IW_POWER_MIN); - printf("\n "); - print_pm_value(stdout, range.max_pmp, flags | IW_POWER_MAX); - printf("\n "); + iw_print_pm_value(buffer, range.min_pmp, flags | IW_POWER_MIN); + printf("%s\n ", buffer); + iw_print_pm_value(buffer, range.max_pmp, flags | IW_POWER_MAX); + printf("%s\n ", buffer); } /* Display min/max timeout availables */ @@ -448,16 +345,16 @@ print_pm_info(int skfd, else printf("Fixed timeout ; "); /* Print the range */ - print_pm_value(stdout, range.min_pmt, flags | IW_POWER_MIN); - printf("\n "); - print_pm_value(stdout, range.max_pmt, flags | IW_POWER_MAX); - printf("\n "); + iw_print_pm_value(buffer, range.min_pmt, flags | IW_POWER_MIN); + printf("%s\n ", buffer); + iw_print_pm_value(buffer, range.max_pmt, flags | IW_POWER_MAX); + printf("%s\n ", buffer); } #endif /* WIRELESS_EXT > 9 */ /* Get current Power Management settings */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.power.flags = 0; if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0) { @@ -471,8 +368,8 @@ print_pm_info(int skfd, int pm_mask = 0; /* Let's check the mode */ - printf("Current"); - print_pm_mode(stdout, flags); + iw_print_pm_mode(buffer, flags); + printf("Current%s", buffer); /* Let's check if nothing (simply on) */ if((flags & IW_POWER_MODE) == IW_POWER_ON) @@ -481,7 +378,11 @@ print_pm_info(int skfd, /* Let's check the value and its type */ if(wrq.u.power.flags & IW_POWER_TYPE) - print_pm_value(stdout, wrq.u.power.value, wrq.u.power.flags); + { + iw_print_pm_value(buffer, + wrq.u.power.value, wrq.u.power.flags); + printf("%s", buffer); + } /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_POWER_MIN) @@ -491,7 +392,7 @@ print_pm_info(int skfd, pm_mask = IW_POWER_MIN; /* If we have something to ask for... */ if(pm_mask) - get_pm_value(skfd, ifname, &wrq, pm_mask); + get_pm_value(skfd, ifname, &wrq, pm_mask, buffer); #if WIRELESS_EXT > 9 /* And if we have both a period and a timeout, ask the other */ @@ -500,7 +401,7 @@ print_pm_info(int skfd, if(pm_mask) { int base_mask = pm_mask; - flags = get_pm_value(skfd, ifname, &wrq, pm_mask); + flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer); pm_mask = 0; /* If we have been returned a MIN value, ask for the MAX */ @@ -511,7 +412,7 @@ print_pm_info(int skfd, pm_mask = IW_POWER_MIN | base_mask; /* If we have something to ask for... */ if(pm_mask) - get_pm_value(skfd, ifname, &wrq, pm_mask); + get_pm_value(skfd, ifname, &wrq, pm_mask, buffer); } #endif /* WIRELESS_EXT > 9 */ } @@ -520,33 +421,6 @@ print_pm_info(int skfd, } } -/*------------------------------------------------------------------*/ -/* - * Get Power Management info on all devices and print it on the screen - */ -static void -print_pm_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_pm_info(skfd, ifr->ifr_name); -} - /************************** TRANSMIT POWER **************************/ /*------------------------------------------------------------------*/ @@ -564,7 +438,7 @@ print_txpower_info(int skfd, #if WIRELESS_EXT > 9 /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no transmit-power information.\n\n", ifname); else @@ -578,13 +452,13 @@ print_txpower_info(int skfd, { if(range.txpower_capa & IW_TXPOW_MWATT) { - dbm = mwatt2dbm(range.txpower[k]); + dbm = iw_mwatt2dbm(range.txpower[k]); mwatt = range.txpower[k]; } else { dbm = range.txpower[k]; - mwatt = dbm2mwatt(range.txpower[k]); + mwatt = iw_dbm2mwatt(range.txpower[k]); } printf("\t %d dBm \t(%d mW)\n", dbm, mwatt); } @@ -596,33 +470,6 @@ print_txpower_info(int skfd, #endif /* WIRELESS_EXT > 9 */ } -/*------------------------------------------------------------------*/ -/* - * Get tx-power info on all devices and print it on the screen - */ -static void -print_txpower_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_txpower_info(skfd, ifr->ifr_name); -} - /*********************** RETRY LIMIT/LIFETIME ***********************/ #if WIRELESS_EXT > 10 @@ -634,18 +481,20 @@ static inline int get_retry_value(int skfd, char * ifname, struct iwreq * pwrq, - int flags) + int flags, + char * buffer) { /* Get Another retry value */ - strcpy(pwrq->ifr_name, ifname); + strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); pwrq->u.retry.flags = flags; if(ioctl(skfd, SIOCGIWRETRY, pwrq) >= 0) { /* Let's check the value and its type */ if(pwrq->u.retry.flags & IW_RETRY_TYPE) { - printf("\n "); - print_retry_value(stdout, pwrq->u.retry.value, pwrq->u.retry.flags); + iw_print_retry_value(buffer, + pwrq->u.retry.value, pwrq->u.retry.flags); + printf("%s\n ", buffer); } } return(pwrq->u.retry.flags); @@ -657,13 +506,14 @@ get_retry_value(int skfd, */ static void print_retry_info(int skfd, - char * ifname) + char * ifname) { struct iwreq wrq; struct iw_range range; + char buffer[128]; /* Extract range info */ - if(get_range_info(skfd, ifname, &range) < 0) + if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.8s no retry limit/lifetime information.\n\n", ifname); else @@ -680,10 +530,10 @@ print_retry_info(int skfd, else printf("Fixed limit ; "); /* Print the range */ - print_retry_value(stdout, range.min_retry, flags | IW_RETRY_MIN); - printf("\n "); - print_retry_value(stdout, range.max_retry, flags | IW_RETRY_MAX); - printf("\n "); + iw_print_retry_value(buffer, range.min_retry, flags | IW_RETRY_MIN); + printf("%s\n ", buffer); + iw_print_retry_value(buffer, range.max_retry, flags | IW_RETRY_MAX); + printf("%s\n ", buffer); } /* Display min/max lifetime availables */ @@ -696,15 +546,15 @@ print_retry_info(int skfd, else printf("Fixed lifetime ; "); /* Print the range */ - print_retry_value(stdout, range.min_r_time, flags | IW_RETRY_MIN); - printf("\n "); - print_retry_value(stdout, range.max_r_time, flags | IW_RETRY_MAX); - printf("\n "); + iw_print_retry_value(buffer, range.min_r_time, flags | IW_RETRY_MIN); + printf("%s\n ", buffer); + iw_print_retry_value(buffer, range.max_r_time, flags | IW_RETRY_MAX); + printf("%s\n ", buffer); } /* Get current retry settings */ - strcpy(wrq.ifr_name, ifname); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.retry.flags = 0; if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0) { @@ -722,7 +572,11 @@ print_retry_info(int skfd, /* Let's check the value and its type */ if(wrq.u.retry.flags & IW_RETRY_TYPE) - print_retry_value(stdout, wrq.u.retry.value, wrq.u.retry.flags); + { + iw_print_retry_value(buffer, + wrq.u.retry.value, wrq.u.retry.flags); + printf("%s", buffer); + } /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_RETRY_MIN) @@ -732,7 +586,7 @@ print_retry_info(int skfd, retry_mask = IW_RETRY_MIN; /* If we have something to ask for... */ if(retry_mask) - get_retry_value(skfd, ifname, &wrq, retry_mask); + get_retry_value(skfd, ifname, &wrq, retry_mask, buffer); /* And if we have both a period and a timeout, ask the other */ retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) & @@ -740,7 +594,8 @@ print_retry_info(int skfd, if(retry_mask) { int base_mask = retry_mask; - flags = get_retry_value(skfd, ifname, &wrq, retry_mask); + flags = get_retry_value(skfd, ifname, &wrq, retry_mask, + buffer); retry_mask = 0; /* If we have been returned a MIN value, ask for the MAX */ @@ -751,7 +606,7 @@ print_retry_info(int skfd, retry_mask = IW_RETRY_MIN | base_mask; /* If we have something to ask for... */ if(retry_mask) - get_retry_value(skfd, ifname, &wrq, retry_mask); + get_retry_value(skfd, ifname, &wrq, retry_mask, buffer); } } } @@ -759,12 +614,19 @@ print_retry_info(int skfd, } } +#endif /* WIRELESS_EXT > 10 */ + +/************************* COMMON UTILITIES *************************/ +/* + * This section was written by Michael Tokarev + */ + /*------------------------------------------------------------------*/ /* - * Get retry info on all devices and print it on the screen + * Enumerate devices and call specified routine */ static void -print_retry_devices(int skfd) +enum_devices(int skfd, void (*fn)(int skfd, char *ifname)) { char buff[1024]; struct ifconf ifc; @@ -783,9 +645,42 @@ print_retry_devices(int skfd) /* Print them */ for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) - print_retry_info(skfd, ifr->ifr_name); + (*fn)(skfd, ifr->ifr_name); +} + +/* command list */ +typedef struct iwlist_entry { + const char *cmd; + void (*fn)(int skfd, char *ifname); +} 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 }, + { "encription", print_keys_info }, + { "key", print_keys_info }, + { "power", print_pm_info }, + { "txpower", print_txpower_info }, +#if WIRELESS_EXT > 10 + { "retry", print_retry_info }, +#endif + { NULL, 0 }, +}; + +/* Display help */ +static void usage(FILE *f) +{ + int i; + for(i = 0; iwlist_cmds[i].cmd != NULL; ++i) + fprintf(f, "%s [interface] %s\n", + i ? " " : + "Usage: iwlist", + iwlist_cmds[i].cmd); } -#endif /* WIRELESS_EXT > 10 */ /******************************* MAIN ********************************/ @@ -798,154 +693,78 @@ main(int argc, char ** argv) { int skfd = -1; /* generic raw socket desc. */ + char *dev; /* device name */ + char *cmd; /* command */ + int i; - /* Create a channel to the NET kernel. */ - if((skfd = sockets_open()) < 0) - { - perror("socket"); - exit(-1); - } - - /* Help */ - if((argc == 1) || (argc > 3) || - (!strncmp(argv[1], "-h", 9)) || (!strcmp(argv[1], "--help"))) - { - fprintf(stderr, "Usage: iwlist [interface] freq\n"); - fprintf(stderr, " [interface] ap\n"); - fprintf(stderr, " [interface] bitrate\n"); - fprintf(stderr, " [interface] keys\n"); - fprintf(stderr, " [interface] power\n"); - fprintf(stderr, " [interface] txpower\n"); - fprintf(stderr, " [interface] retries\n"); - close(skfd); - exit(0); - } - - /* Frequency list */ - if((!strncmp(argv[1], "freq", 4)) || - (!strncmp(argv[1], "channel", 7))) - { - print_freq_devices(skfd); - close(skfd); - exit(0); - } - - /* Access Point list */ - if(!strcasecmp(argv[1], "ap")) - { - print_ap_devices(skfd); - close(skfd); - exit(0); - } - - /* Bit-rate list */ - if((!strncmp(argv[1], "bit", 3)) || - (!strcmp(argv[1], "rate"))) - { - print_bitrate_devices(skfd); - close(skfd); - exit(0); - } - - /* Encryption key list */ - if((!strncmp(argv[1], "enc", 3)) || - (!strncmp(argv[1], "key", 3))) - { - print_keys_devices(skfd); - close(skfd); - exit(0); - } - - /* Power Management list */ - if(!strncmp(argv[1], "power", 3)) - { - print_pm_devices(skfd); - close(skfd); - exit(0); - } - - /* Transmit Power list */ - if(!strncmp(argv[1], "txpower", 3)) - { - print_txpower_devices(skfd); - close(skfd); - exit(0); - } - -#if WIRELESS_EXT > 10 - /* Retry limit/lifetime */ - if(!strncmp(argv[1], "retry", 4)) - { - print_retry_devices(skfd); - close(skfd); - exit(0); - } -#endif - - /* Special cases take two... */ - /* Frequency list */ - if((!strncmp(argv[2], "freq", 4)) || - (!strncmp(argv[2], "channel", 7))) - { - print_freq_info(skfd, argv[1]); - close(skfd); - exit(0); - } - - /* Access Point list */ - if(!strcasecmp(argv[2], "ap")) + if(argc == 1 || argc > 3) { - print_ap_info(skfd, argv[1]); - close(skfd); - exit(0); + usage(stderr); + return 1; } - - /* Bit-rate list */ - if((!strncmp(argv[2], "bit", 3)) || - (!strcmp(argv[2], "rate"))) + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { - print_bitrate_info(skfd, argv[1]); - close(skfd); - exit(0); + usage(stdout); + return 0; } - - /* Encryption key list */ - if((!strncmp(argv[2], "enc", 3)) || - (!strncmp(argv[2], "key", 3))) + if (argc == 2) { - print_keys_info(skfd, argv[1]); - close(skfd); - exit(0); + cmd = argv[1]; + dev = NULL; } - - /* Power Management list */ - if(!strncmp(argv[2], "power", 3)) + else { - print_pm_info(skfd, argv[1]); - close(skfd); - exit(0); - } + cmd = argv[2]; + dev = argv[1]; + } + + /* 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; + } - /* Transmit Power list */ - if(!strncmp(argv[2], "txpower", 3)) + /* Create a channel to the NET kernel. */ + if((skfd = iw_sockets_open()) < 0) { - print_txpower_info(skfd, argv[1]); - close(skfd); - exit(0); + perror("socket"); + return -1; } -#if WIRELESS_EXT > 10 - /* Retry limit/lifetime */ - if(!strncmp(argv[2], "retry", 4)) - { - print_retry_info(skfd, argv[1]); - close(skfd); - exit(0); - } -#endif + /* do the actual work */ + if (dev) + (*iwlist_cmds[i].fn)(skfd, dev); + else + enum_devices(skfd, iwlist_cmds[i].fn); /* Close the socket. */ close(skfd); - return(1); + return 0; } diff --git a/wireless_tools/iwpriv.c b/wireless_tools/iwpriv.c index de98613..65a0aee 100644 --- a/wireless_tools/iwpriv.c +++ b/wireless_tools/iwpriv.c @@ -10,7 +10,7 @@ * This file is released under the GPL license. */ -#include "iwcommon.h" /* Header */ +#include "iwlib.h" /* Header */ /************************* MISC SUBROUTINES **************************/ @@ -24,7 +24,6 @@ iw_usage(void) fprintf(stderr, "Usage: iwpriv interface [private-command [private-arguments]]\n"); fprintf(stderr, " interface [roam {on|off}]\n"); fprintf(stderr, " interface [port {ad-hoc|managed|N}]\n"); - exit(1); } /************************ GENERIC FUNCTIONS *************************/ @@ -41,10 +40,10 @@ print_priv_info(int skfd, int k; iwprivargs priv[16]; int n; - char * argtype[] = { " ", "byte", "char", "", "int", "float" }; + char * argtype[] = { " ", "byte", "char", "", "int ", "float" }; /* Read the private ioctls */ - n = get_priv_info(skfd, ifname, priv); + n = iw_get_priv_info(skfd, ifname, priv); /* Is there any ? */ if(n <= 0) @@ -115,7 +114,7 @@ set_private(int skfd, /* Socket */ int number; /* Read the private ioctls */ - number = get_priv_info(skfd, ifname, priv); + number = iw_get_priv_info(skfd, ifname, priv); /* Is there any ? */ if(number <= 0) @@ -209,7 +208,7 @@ set_private(int skfd, /* Socket */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && - (byte_size(priv[k].set_args) < IFNAMSIZ)) + (iw_byte_size(priv[k].set_args) < IFNAMSIZ)) memcpy(wrq.u.name, buffer, IFNAMSIZ); else { @@ -235,7 +234,7 @@ set_private(int skfd, /* Socket */ printf("%-8.8s %s:", ifname, priv[k].name); if((priv[k].get_args & IW_PRIV_SIZE_FIXED) && - (byte_size(priv[k].get_args) < IFNAMSIZ)) + (iw_byte_size(priv[k].get_args) < IFNAMSIZ)) { memcpy(buffer, wrq.u.name, IFNAMSIZ); n = priv[k].get_args & IW_PRIV_SIZE_MASK; @@ -301,7 +300,7 @@ set_roaming(int skfd, /* Socket */ change roam states */ /* Read the private ioctls */ - number = get_priv_info(skfd, ifname, priv); + number = iw_get_priv_info(skfd, ifname, priv); /* Is there any ? */ if(number <= 0) @@ -313,7 +312,10 @@ set_roaming(int skfd, /* Socket */ } if(count != 1) - iw_usage(); + { + iw_usage(); + return(-1); + } if(!strcasecmp(args[i], "on")) { @@ -363,12 +365,11 @@ set_roaming(int skfd, /* Socket */ if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Roaming support is broken.\n"); - exit(0); + return(-1); } } - i++; - return(i); + return(0); } /*------------------------------------------------------------------*/ @@ -391,7 +392,7 @@ port_type(int skfd, /* Socket */ char * modes[] = { "invalid", "managed (BSS)", "reserved", "ad-hoc" }; /* Read the private ioctls */ - number = get_priv_info(skfd, ifname, priv); + number = iw_get_priv_info(skfd, ifname, priv); /* Is there any ? */ if(number <= 0) @@ -431,7 +432,10 @@ port_type(int skfd, /* Socket */ } if(count != 1) - iw_usage(); + { + iw_usage(); + return(-1); + } /* Read it */ /* As a string... */ @@ -443,7 +447,10 @@ port_type(int skfd, /* Socket */ else /* ...or as an integer */ if(sscanf(args[i], "%d", (int *) &ptype) != 1) - iw_usage(); + { + iw_usage(); + return(-1); + } k = -1; while((++k < number) && strcmp(priv[k].name, "sport_type") && @@ -460,11 +467,10 @@ port_type(int skfd, /* Socket */ if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Invalid port type (or setting not allowed)\n"); - exit(0); + return(-1); } - i++; - return(i); + return(0); } /******************************* MAIN ********************************/ @@ -481,10 +487,10 @@ main(int argc, int goterr = 0; /* Create a channel to the NET kernel. */ - if((skfd = sockets_open()) < 0) + if((skfd = iw_sockets_open()) < 0) { perror("socket"); - exit(-1); + return(-1); } /* No argument : show the list of all device + info */ @@ -492,7 +498,7 @@ main(int argc, { print_priv_devices(skfd); close(skfd); - exit(0); + return(0); } /* Special cases take one... */ @@ -502,7 +508,7 @@ main(int argc, { iw_usage(); close(skfd); - exit(0); + return(0); } /* The device name must be the first argument */ @@ -511,7 +517,7 @@ main(int argc, { print_priv_info(skfd, argv[1]); close(skfd); - exit(0); + return(0); } /* Special cases take two... */ @@ -520,7 +526,7 @@ main(int argc, { goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]); close(skfd); - exit(0); + return(goterr); } /* Port type */ @@ -528,7 +534,7 @@ main(int argc, { goterr = port_type(skfd, argv + 3, argc - 3, argv[1]); close(skfd); - exit(0); + return(goterr); } /* Otherwise, it's a private ioctl */ @@ -537,5 +543,5 @@ main(int argc, /* Close the socket. */ close(skfd); - return(1); + return(goterr); } diff --git a/wireless_tools/iwspy.c b/wireless_tools/iwspy.c index ead9a62..cd41ccd 100644 --- a/wireless_tools/iwspy.c +++ b/wireless_tools/iwspy.c @@ -9,7 +9,7 @@ * This file is released under the GPL license. */ -#include "iwcommon.h" /* Header */ +#include "iwlib.h" /* Header */ /************************* DISPLAY ROUTINES **************************/ @@ -24,6 +24,7 @@ print_spy_info(int skfd, struct iwreq wrq; char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_SPY]; + char temp[128]; struct sockaddr hwa[IW_MAX_SPY]; struct iw_quality qual[IW_MAX_SPY]; iwrange range; @@ -48,14 +49,14 @@ print_spy_info(int skfd, /* Check if we have valid address types */ - if(check_addr_type(skfd, ifname) < 0) + if(iw_check_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname); return; } /* Get range info if we can */ - if(get_range_info(skfd, ifname, &(range)) >= 0) + if(iw_get_range_info(skfd, ifname, &(range)) >= 0) has_range = 1; /* Display it */ @@ -72,9 +73,18 @@ print_spy_info(int skfd, for(i = 0; i < n; i++) { /* Print stats for each address */ - printf(" %s : ", pr_ether(hwa[i].sa_data)); - print_stats(stdout, &qual[i], &range, has_range); + printf(" %s : ", iw_pr_ether(temp, hwa[i].sa_data)); + iw_print_stats(temp, &qual[i], &range, has_range); + printf("%s\n", temp); } +#if WIRELESS_EXT > 11 + if((n > 0) && (has_range)) + { + iw_print_stats(temp, &range.avg_qual, &range, has_range); + printf(" typical/average : %s\n", temp); + } +#endif /* WIRELESS_EXT > 11 */ + printf("\n"); } @@ -127,7 +137,7 @@ set_spy_info(int skfd, /* The socket */ nbr = 0; /* Number of args readen so far */ /* Check if we have valid address types */ - if(check_addr_type(skfd, ifname) < 0) + if(iw_check_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname); return(-1); @@ -164,7 +174,7 @@ set_spy_info(int skfd, /* The socket */ /* Read other args on command line */ while((i < count) && (nbr < IW_MAX_SPY)) { - if(in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0) + if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0) continue; nbr++; } @@ -173,7 +183,7 @@ set_spy_info(int skfd, /* The socket */ if((nbr == 0) && strcmp(args[0], "off")) { fprintf(stderr, "No valid addresses found : exiting...\n"); - exit(0); + return(-1); } /* Check if there is some remaining arguments */ @@ -211,10 +221,10 @@ main(int argc, int goterr = 0; /* Create a channel to the NET kernel. */ - if((skfd = sockets_open()) < 0) + if((skfd = iw_sockets_open()) < 0) { perror("socket"); - exit(-1); + return(-1); } /* No argument : show the list of all device + info */ @@ -222,7 +232,7 @@ main(int argc, { print_spy_devices(skfd); close(skfd); - exit(0); + return(0); } /* Special cases take one... */ @@ -231,10 +241,8 @@ main(int argc, (!strcmp(argv[1], "--help"))) { fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n"); - fprintf(stderr, " interface [freq]\n"); - fprintf(stderr, " interface [ap]\n"); close(skfd); - exit(0); + return(0); } /* The device name must be the first argument */ @@ -243,7 +251,7 @@ main(int argc, { print_spy_info(skfd, argv[1]); close(skfd); - exit(0); + return(0); } /* Otherwise, it's a list of address to set in the spy list */ @@ -252,5 +260,5 @@ main(int argc, /* Close the socket. */ close(skfd); - return(1); + return(goterr); } diff --git a/wireless_tools/macaddr.c b/wireless_tools/macaddr.c new file mode 100644 index 0000000..8c5a93a --- /dev/null +++ b/wireless_tools/macaddr.c @@ -0,0 +1,53 @@ +/* + * macaddr + * + * Program to return the MAC address of an Ethernet + * adapter. This was written to help configure the + * adapter based on the MAC address rather than the + * name. + * + * Version 1.0 Eric Dittman 2001-10-19 + * + * This is released unther the GPL license. + */ + +#include +#include +#include +#include +#include +#include + +int main(int argc, char** argv) { + + int devsock; + struct ifreq ifbuffer; + int i; + + if (argc != 2) { + printf("Usage: macaddr interface\n"); + exit(1); + } + + devsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (devsock == -1) { + printf("Failed opening socket\n"); + exit (1); + } + + memset(&ifbuffer, 0, sizeof(ifbuffer)); + strcpy(ifbuffer.ifr_name, argv[1]); + if (ioctl(devsock, SIOCGIFHWADDR, &ifbuffer) == -1) { + printf("There is no MACADDR for %s\n", argv[1]); + exit(1); + } + close (devsock); + + for (i = 0; i < IFHWADDRLEN; i++) + printf("%02X", (unsigned char) ifbuffer.ifr_ifru.ifru_hwaddr.sa_data[i]); + printf("\n"); + + exit(0); + +} diff --git a/wireless_tools/wireless.11.h b/wireless_tools/wireless.11.h new file mode 100644 index 0000000..fe42409 --- /dev/null +++ b/wireless_tools/wireless.11.h @@ -0,0 +1,510 @@ +/* + * This file define a set of standard wireless extensions + * + * Version : 11 28.3.01 + * + * Authors : Jean Tourrilhes - HPL - + */ + +#ifndef _LINUX_WIRELESS_H +#define _LINUX_WIRELESS_H + +/************************** DOCUMENTATION **************************/ +/* + * 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) + * + * 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... */ + +/**************************** CONSTANTS ****************************/ + +/* --------------------------- 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 11 + +/* + * 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) + */ + +/* -------------------------- IOCTL LIST -------------------------- */ + +/* Basic operations */ +#define SIOCSIWNAME 0x8B00 /* Unused */ +#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 */ + +/* 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 usefull 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 */ + +/* ------------------------- IOCTL STUFF ------------------------- */ + +/* The first and the last (range) */ +#define SIOCIWFIRST 0x8B00 +#define SIOCIWLAST 0x8B30 + +/* 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 SIOCDEVPRIVATE -> SIOCDEVPRIVATE + 0xF + */ + +#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 alocated 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 or better...) */ + __u8 level; /* signal level */ + __u8 noise; /* noise level */ + __u8 updated; /* Flags to know if updated */ +}; + +/* + * Packet discarded in the wireless adapter due to + * "wireless" specific problems... + */ +struct iw_discarded +{ + __u32 nwid; /* Wrong nwid */ + __u32 code; /* Unable to code/decode */ + __u32 misc; /* Others cases */ +}; + +/* ------------------------ 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 */ +}; + +/* ------------------------ IOCTL REQUEST ------------------------ */ +/* + * The structure to exchange data for ioctl. + * This structure is the same as 'struct ifreq', but (re)defined for + * convenience... + * + * Note that it should fit on the same memory footprint ! + * You should check this when increasing the above structures (16 octets) + * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... + */ +struct iwreq +{ + union + { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ + } ifr_ifrn; + + /* Data part */ + union + { + /* 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 */ + } 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 */ +}; + +/* + * 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.h b/wireless_tools/wireless.h index fe42409..4183d4a 100644 --- a/wireless_tools/wireless.h +++ b/wireless_tools/wireless.h @@ -1,7 +1,7 @@ /* * This file define a set of standard wireless extensions * - * Version : 11 28.3.01 + * Version : 12 5.10.01 * * Authors : Jean Tourrilhes - HPL - */ @@ -63,7 +63,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 11 +#define WIRELESS_EXT 12 /* * Changes : @@ -116,6 +116,13 @@ * ---------- * - 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) */ /* -------------------------- IOCTL LIST -------------------------- */ @@ -137,6 +144,8 @@ #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 */ @@ -158,7 +167,7 @@ * The "flags" member indicate if the ESSID is active or not (promiscuous). */ -/* Other parameters usefull in 802.11 and some other devices */ +/* 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) */ @@ -177,11 +186,33 @@ #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 know 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 0x8B30 +#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) @@ -191,7 +222,7 @@ /* * 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 SIOCDEVPRIVATE -> SIOCDEVPRIVATE + 0xF + * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ @@ -305,7 +336,7 @@ struct iw_param /* * For all data larger than 16 octets, we need to use a - * pointer to memory alocated in user space. + * pointer to memory allocated in user space. */ struct iw_point { @@ -334,23 +365,38 @@ struct iw_freq */ struct iw_quality { - __u8 qual; /* link quality (%retries, SNR or better...) */ - __u8 level; /* signal level */ - __u8 noise; /* noise level */ + __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; /* Wrong nwid */ - __u32 code; /* Unable to code/decode */ + __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) @@ -363,6 +409,7 @@ struct iw_statistics 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 ------------------------ */ @@ -493,6 +540,19 @@ struct iw_range __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... + */ }; /*