From: chris-kirby Date: Tue, 11 Oct 2016 21:00:06 +0000 (-0600) Subject: v23 X-Git-Url: http://git.osdn.net/view?p=android-x86%2Fexternal-wireless-tools.git;a=commitdiff_plain;h=358fbc0574da2a7a460cfec4628e470e7affc236;ds=sidebyside v23 --- diff --git a/wireless_tools/CHANGELOG.h b/wireless_tools/CHANGELOG.h index e3d5308..67093d6 100644 --- a/wireless_tools/CHANGELOG.h +++ b/wireless_tools/CHANGELOG.h @@ -1,11 +1,12 @@ /* * Wireless Tools * - * Jean II - HPLB 97->99 - HPL 99->01 + * Jean II - HPLB 97->99 - HPL 99->02 * * The changelog... * - * This file is released under the GPL license. + * This files is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ /* --------------------------- HISTORY --------------------------- */ @@ -148,6 +149,30 @@ * o Show typical/average quality in iwspy [iwspy] * o Get Wireless Stats through ioctl instead of /proc [iwlib] * + * wireless 23 : + * ----------- + * o Split iw_check_addr_type() into two functions mac/if [iwlib] + * o iw_in_addr() does appropriate iw_check_xxx itself [iwlib] + * o Allow iwspy on MAC address even if IP doesn't check [iwspy] + * o Allow iwconfig ap on MAC address even if IP doesn't check [iwconfig] + * --- + * o Fix iwlist man page about extra commands [iwlist] + * --- + * o Fix Makefile rules for library compile (more generic) [Makefile] + * --- + * o Set max length for all GET request with a iw_point [various] + * o Fix set IW_PRIV_TYPE_BYTE to be endian/align clean [iwpriv] + * --- + * (From Kernel Jake ) + * o Add '/' at the end of directories to create them [Makefile] + * (From Pavel Roskin ) + * o Replace "cp" with "install" to get permissions proper [Makefile] + * o Install Man-Pages at the proper location [Makefile] + * o Add automatic header selection based on libc/kernel [iwlib.h] + * --- + * o Add "commit" to force parameters on the card [iwconfig] + * o Wrap ioctl() in iw_set/get_ext() wrappers [all] + * o Beautify set request error messages [iwconfig] */ /* ----------------------------- TODO ----------------------------- */ diff --git a/wireless_tools/INSTALL b/wireless_tools/INSTALL index 6093c2e..efa4eca 100644 --- a/wireless_tools/INSTALL +++ b/wireless_tools/INSTALL @@ -16,14 +16,7 @@ You need : Note : CONFIG_NET_RADIO must be enabled o (Optional) A Pcmcia package supporting Wireless Extension o A driver supporting wireless extensions - -> Wavelan isa - -> Wavelan pcmcia - -> Netwave pcmcia - -> Wavelan IEEE pcmcia drivers - -> Aironet MPL driver - -> Proxim RangeLan2/Symphony driver - -> Raylink/WegGear2.4 driver - -> Check my web page for latest list of drivers, + -> Check my web pages for latest list of drivers, otherwise patch your favourite driver... Note : more recent kernels and drivers are likely to support more wireless extension features... @@ -34,16 +27,12 @@ Recommended versions : o Kernel (wireless extension definition) : -> Kernel 2.2.14 onward -> Kernel 2.3.24 onward + -> Kernel 2.4.0 onward o Pcmcia package : -> Pcmcia 3.1.15 onward o Drivers with wireless extension support : - -> Wavelan isa from kernels above - -> Wavelan pcmcia from pcmcia 3.1.1 onward - -> Netwave pcmcia from pcmcia 3.1.2 onward - -> Wavelan IEEE pcmcia GPL driver (wvlan_cs) 1.0.5 onward - -> Aironet MPL driver (airo_cs.c) 1.4 onward - -> Proxim RangeLan2/Symphony driver 1.4.3 onward - -> Raylink/WegGear2.4 driver 1.70 (note : read only) + -> Check my web pages for latest list of drivers, + otherwise patch your favourite driver... Compile wireless tools : ---------------------- @@ -68,12 +57,13 @@ mandatory... Kernel headers (why it doesn't compile) : --------------------------------------- Some changes in the kernel headers and glibc headers are -making my life difficult. - If you have glibc and kernel 2.2.X headers (or greater), that -should be all right. This is the default for most modern distributions. - In the other cases, depending on which version of the kernel -headers (might be different from kernel) and library headers you have, -you need to play with the options at the top of the Makefile. +making my life difficult. We now have a mechanism to automatically +select the proper header based on various bits of information (libc +version & kernel version), but it may fail to do the right thing. + You may also see the message : + "Your kernel/libc combination is not supported" + If this happens to you, you will need to hack the rules at the +top of iwlib.h and send me the patch. The second issue is that some distributions install some independant kernel headers in /usr/include. If you upgrade your diff --git a/wireless_tools/Makefile b/wireless_tools/Makefile index 236acbb..f4e0fcf 100644 --- a/wireless_tools/Makefile +++ b/wireless_tools/Makefile @@ -4,8 +4,9 @@ # Targets to build STATIC=libiw.a -DYNAMIC=libiw.so.22 +DYNAMIC=libiw.so.23 PROGS= iwconfig iwlist iwpriv iwspy iwgetid +MANPAGES=iwconfig.8 iwlist.8 iwpriv.8 iwspy.8 # Composition of the library : OBJS = iwlib.o @@ -16,26 +17,12 @@ IWLIBS=$(OBJS) # 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 +INSTALL_DIR= /usr/local/sbin/ +INSTALL_LIB= /usr/local/lib/ +INSTALL_INC= /usr/local/include/ +INSTALL_MAN= /usr/local/man -# 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, Debian 2.3, RH 7.1 -#HEADERS= -DGLIBC22_HEADERS - -# Kernel headers 2.0.X + Glibc 2.0 - Debian 2.0, RH 5 -# Kernel headers 2.2.X + Glibc 2.1 - Debian 2.2, RH 6.1 -# Kernel headers 2.4.X + Glibc 2.1 - Debian 2.2 upgraded, RH 7.0 -HEADERS= -DGLIBC_HEADERS - -# Kernel headers 2.2.X + Glibc 2.0 - Debian 2.1 -#HEADERS= -DKLUDGE_HEADERS - -# Kernel headers 2.0.X + libc5 - old systems -#HEADERS= -DLIBC5_HEADERS +# Header selection is now supposed to be automatic... # Use private copy of Wireless Extension definition instead of the # system wide one in /usr/include/linux. Use with care. @@ -76,21 +63,24 @@ iwgetid: iwgetid.o $(CC) $(CFLAGS) -o $@ $^ # Compilation of the dynamic library -libiw.so.22: $(OBJS) +$(DYNAMIC): $(OBJS) $(CC) -O2 -shared -o $@ -Wl,-soname,$@ -lm -lc $^ # Compilation of the static library -libiw.a: $(OBJS) +$(STATIC): $(OBJS) $(RM) $@ ar cru $@ $^ ranlib $@ # So crude but so effective ;-) +# Less crude thanks to many contributions ;-) 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) + install -m 755 $(PROGS) $(INSTALL_DIR) + install -m 644 $(STATIC) $(INSTALL_LIB) + install -m 755 $(DYNAMIC) $(INSTALL_LIB) + echo "Don't forget to fix your /etc/ld.so.conf and run ldconfig." + install -m 644 iwlib.h $(INSTALL_INC) + install -m 644 $(MANPAGES) $(INSTALL_MAN)/man8/ clean:: $(RM_CMD) diff --git a/wireless_tools/iwconfig.8 b/wireless_tools/iwconfig.8 index fbc3483..814861f 100644 --- a/wireless_tools/iwconfig.8 +++ b/wireless_tools/iwconfig.8 @@ -20,6 +20,8 @@ iwconfig \- configure a wireless network interface .BI " [rate " R "] [rts " RT "] [frag " FT "] [txpower " T ] .br .BI " [enc " E "] [key " K "] [power " P "] [retry " R ] +.br +.BI " [commit] .\" .\" DESCRIPTION part .\" @@ -324,6 +326,15 @@ is the short retry limit (non RTS/CTS packets). .I " iwconfig eth0 retry lifetime 300m" .br .I " iwconfig eth0 retry min limit 8" +.TP +.BR commit +Some cards may not apply changes done through Wireless Extensions +immediately (they may wait to agregate the changes or apply it only +when the card is brought up). This command (when available) force +the card to apply all pending changes. +.br +This is normally not needed, because the card will eventually apply +the changes, but can be usefull for debugging. .\" .\" DISPLAY part .\" diff --git a/wireless_tools/iwconfig.c b/wireless_tools/iwconfig.c index efc0a43..5b38484 100644 --- a/wireless_tools/iwconfig.c +++ b/wireless_tools/iwconfig.c @@ -5,9 +5,10 @@ * * Main code for "iwconfig". This is the generic tool for most * manipulations... - * You need to link this code against "iwcommon.c" and "-lm". + * You need to link this code against "iwlib.c" and "-lm". * * This file is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ #include "iwlib.h" /* Header */ @@ -33,7 +34,7 @@ iw_usage(void) fprintf(stderr, " [enc NNNN-NNNN]\n"); fprintf(stderr, " [power { period N|timeout N}]\n"); fprintf(stderr, " [txpower N {mW|dBm}]\n"); - exit(1); + fprintf(stderr, " [commit]\n"); } @@ -55,8 +56,7 @@ get_info(int skfd, memset((char *) info, 0, sizeof(struct wireless_info)); /* Get wireless name */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) /* If no wireless name : no wireless extensions */ return(-1); else @@ -67,35 +67,31 @@ get_info(int skfd, info->has_range = 1; /* Get network ID */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, 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) + if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0) { info->has_freq = 1; info->freq = iw_freq2float(&(wrq.u.freq)); } /* Get sensitivity */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0) { info->has_sens = 1; memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam)); } /* 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.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) { info->has_key = 1; info->key_size = wrq.u.data.length; @@ -103,60 +99,53 @@ get_info(int skfd, } /* Get ESSID */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.essid.pointer = (caddr_t) info->essid; - wrq.u.essid.length = 0; + wrq.u.essid.length = IW_ESSID_MAX_SIZE; wrq.u.essid.flags = 0; - if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0) { info->has_essid = 1; info->essid_on = wrq.u.data.flags; } /* Get AP address */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWAP, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0) { info->has_ap_addr = 1; memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr)); } /* Get NickName */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.essid.pointer = (caddr_t) info->nickname; - wrq.u.essid.length = 0; + wrq.u.essid.length = IW_ESSID_MAX_SIZE; wrq.u.essid.flags = 0; - if(ioctl(skfd, SIOCGIWNICKN, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0) if(wrq.u.data.length > 1) info->has_nickname = 1; /* Get bit rate */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWRATE, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0) { info->has_bitrate = 1; memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam)); } /* Get RTS threshold */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0) { info->has_rts = 1; memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam)); } /* Get fragmentation threshold */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0) { info->has_frag = 1; memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam)); } /* Get operation mode */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0) { if((wrq.u.mode < IW_NUM_OPER_MODE) && (wrq.u.mode >= 0)) info->has_mode = 1; @@ -164,9 +153,8 @@ get_info(int skfd, } /* Get Power Management settings */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.power.flags = 0; - if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0) { info->has_power = 1; memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam)); @@ -174,8 +162,7 @@ get_info(int skfd, #if WIRELESS_EXT > 9 /* Get Transmit Power */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWTXPOW, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) { info->has_txpower = 1; memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam)); @@ -184,8 +171,7 @@ get_info(int skfd, #if WIRELESS_EXT > 10 /* Get retry limit/lifetime */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0) { info->has_retry = 1; memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam)); @@ -605,6 +591,66 @@ print_devices(int skfd) /*------------------------------------------------------------------*/ /* + * Macro to handle errors when setting WE + * Print a nice error message and exit... + * We define them as macro so that "return" do the right thing. + * The "do {...} while(0)" is a standard trick + */ +#define ERR_SET_EXT(rname, request) \ + fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \ + rname, request) + +#define ABORT_ARG_NUM(rname, request) \ + do { \ + ERR_SET_EXT(rname, request); \ + fprintf(stderr, " too few arguments.\n"); \ + return(-1); \ + } while(0) + +#define ABORT_ARG_TYPE(rname, request, arg) \ + do { \ + ERR_SET_EXT(rname, request); \ + fprintf(stderr, " invalid argument \"%s\".\n", arg); \ + return(-2); \ + } while(0) + +#define ABORT_ARG_SIZE(rname, request, max) \ + do { \ + ERR_SET_EXT(rname, request); \ + fprintf(stderr, " argument too big (max %d)\n", max); \ + return(-3); \ + } while(0) + +/*------------------------------------------------------------------*/ +/* + * Wrapper to push some Wireless Parameter in the driver + * Use standard wrapper and add pretty error message if fail... + */ +#define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \ + do { \ + if(iw_set_ext(skfd, ifname, request, wrq) < 0) { \ + ERR_SET_EXT(rname, request); \ + fprintf(stderr, " SET failed on device %-1.8s ; %s.\n", \ + ifname, strerror(errno)); \ + return(-5); \ + } } while(0) + +/*------------------------------------------------------------------*/ +/* + * Wrapper to extract some Wireless Parameter out of the driver + * Use standard wrapper and add pretty error message if fail... + */ +#define IW_GET_EXT_ERR(skfd, ifname, request, wrq, rname) \ + do { \ + if(iw_get_ext(skfd, ifname, request, wrq) < 0) { \ + ERR_SET_EXT(rname, request); \ + fprintf(stderr, " GET failed on device %-1.8s ; %s.\n", \ + ifname, strerror(errno)); \ + return(-6); \ + } } while(0) + +/*------------------------------------------------------------------*/ +/* * Set the wireless options requested on command line * This function is too long and probably should be split, * because it look like the perfect definition of spaghetti code, @@ -619,23 +665,32 @@ set_info(int skfd, /* The socket */ struct iwreq wrq; int i; - /* Set dev name */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - - /* if nothing after the device name */ - if(count<1) - iw_usage(); + /* if nothing after the device name - will never happen */ + if(count < 1) + { + fprintf(stderr, "Error : too few arguments.\n"); + return(-1); + } /* The other args on the line specify options to be set... */ for(i = 0; i < count; i++) { + /* ---------- Commit changes to driver ---------- */ + if(!strncmp(args[i], "commit", 6)) + { + /* No args */ + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq, + "Commit changes"); + continue; + } + /* ---------- Set network ID ---------- */ if((!strcasecmp(args[i], "nwid")) || (!strcasecmp(args[i], "domain"))) { i++; if(i >= count) - iw_usage(); + ABORT_ARG_NUM("Set NWID", SIOCSIWNWID); if((!strcasecmp(args[i], "off")) || (!strcasecmp(args[i], "any"))) wrq.u.nwid.disabled = 1; @@ -643,27 +698,21 @@ set_info(int skfd, /* The socket */ if(!strcasecmp(args[i], "on")) { /* Get old nwid */ - if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0) - { - fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno)); - return(-1); - } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq, + "Set NWID"); wrq.u.nwid.disabled = 0; } else if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value)) != 1) - iw_usage(); + ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]); else wrq.u.nwid.disabled = 0; wrq.u.nwid.fixed = 1; - if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno)); - return(-1); - } + /* Set new nwid */ + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq, + "Set NWID"); continue; } @@ -674,20 +723,17 @@ set_info(int skfd, /* The socket */ double freq; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ); if(sscanf(args[i], "%lg", &(freq)) != 1) - iw_usage(); + ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]); if(index(args[i], 'G')) freq *= GIGA; if(index(args[i], 'M')) freq *= MEGA; if(index(args[i], 'k')) freq *= KILO; iw_float2freq(freq, &(wrq.u.freq)); - if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq, + "Set Frequency"); continue; } @@ -695,15 +741,12 @@ set_info(int skfd, /* The socket */ if(!strncmp(args[i], "sens", 4)) { if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS); if(sscanf(args[i], "%d", &(wrq.u.sens.value)) != 1) - iw_usage(); + ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]); - if(ioctl(skfd, SIOCSIWSENS, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWSENS: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq, + "Set Sensitivity"); continue; } @@ -714,7 +757,7 @@ set_info(int skfd, /* The socket */ unsigned char key[IW_ENCODING_TOKEN_MAX]; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE); if(!strcasecmp(args[i], "on")) { @@ -722,12 +765,8 @@ set_info(int skfd, /* The socket */ wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = 0; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0) - { - fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); - return(-1); - } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq, + "Set Encode"); wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */ } else @@ -760,8 +799,8 @@ set_info(int skfd, /* The socket */ buff = malloc(strlen(args[i]) + 1); if(buff == NULL) { - fprintf(stderr, "Setting key : Malloc failed (string too long ?)\n"); - return(-1); + fprintf(stderr, "Set Encode : Malloc failed (string too long ?)\n"); + return(-10); } strcpy(buff, args[i]); @@ -814,18 +853,17 @@ set_info(int skfd, /* The socket */ gotone = 1; } } + /* Pointer is absent in new API */ + if(wrq.u.data.pointer == NULL) + wrq.u.data.flags = IW_ENCODE_NOKEY; if(!gotone) - iw_usage(); + ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]); --i; } - if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", - errno, strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq, + "Set Encode"); continue; } @@ -836,7 +874,7 @@ set_info(int skfd, /* The socket */ i++; if(i >= count) - iw_usage(); + ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID); if((!strcasecmp(args[i], "off")) || (!strcasecmp(args[i], "any"))) { @@ -850,23 +888,15 @@ set_info(int skfd, /* The socket */ wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = 0; wrq.u.essid.flags = 0; - if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0) - { - fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno)); - return(-1); - } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq, + "Set ESSID"); 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", - IW_ESSID_MAX_SIZE, args[i]); - iw_usage(); - } + ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE); else { int temp; @@ -886,11 +916,8 @@ set_info(int skfd, /* The socket */ wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = strlen(essid) + 1; - if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq, + "Set ESSID"); continue; } @@ -898,24 +925,14 @@ set_info(int skfd, /* The socket */ if(!strcasecmp(args[i], "ap")) { if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set AP Address", SIOCSIWAP); - /* Check if we have valid address types */ - 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 */ + /* Get the address and check if the interface supports it */ if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0) - iw_usage(); + ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]); - if(ioctl(skfd, SIOCSIWAP, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWAP: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq, + "Set AP Address"); continue; } @@ -924,21 +941,14 @@ set_info(int skfd, /* The socket */ { i++; if(i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN); if(strlen(args[i]) > IW_ESSID_MAX_SIZE) - { - fprintf(stderr, "Name too long (max %d) : ``%s''\n", - IW_ESSID_MAX_SIZE, args[i]); - iw_usage(); - } + ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE); wrq.u.essid.pointer = (caddr_t) args[i]; wrq.u.essid.length = strlen(args[i]) + 1; - if(ioctl(skfd, SIOCSIWNICKN, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWNICKN: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq, + "Set Nickname"); continue; } @@ -947,7 +957,7 @@ set_info(int skfd, /* The socket */ (!strcmp(args[i], "rate"))) { if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE); if(!strcasecmp(args[i], "auto")) { wrq.u.bitrate.value = -1; @@ -958,12 +968,8 @@ set_info(int skfd, /* The socket */ if(!strcasecmp(args[i], "fixed")) { /* Get old bitrate */ - if(ioctl(skfd, SIOCGIWRATE, &wrq) < 0) - { - fprintf(stderr, "SIOCGIWRATE: %s\n", strerror(errno)); - return(-1); - } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq, + "Set Bit Rate"); wrq.u.bitrate.fixed = 1; } else /* Should be a numeric value */ @@ -971,7 +977,7 @@ set_info(int skfd, /* The socket */ double brate; if(sscanf(args[i], "%lg", &(brate)) != 1) - iw_usage(); + ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]); if(index(args[i], 'G')) brate *= GIGA; if(index(args[i], 'M')) brate *= MEGA; if(index(args[i], 'k')) brate *= KILO; @@ -994,11 +1000,8 @@ set_info(int skfd, /* The socket */ } } - if(ioctl(skfd, SIOCSIWRATE, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWRATE: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq, + "Set Bit Rate"); continue; } @@ -1007,7 +1010,7 @@ set_info(int skfd, /* The socket */ { i++; if(i >= count) - iw_usage(); + ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS); wrq.u.rts.value = -1; wrq.u.rts.fixed = 1; wrq.u.rts.disabled = 0; @@ -1021,25 +1024,18 @@ set_info(int skfd, /* The socket */ if(!strcasecmp(args[i], "fixed")) { /* Get old RTS threshold */ - if(ioctl(skfd, SIOCGIWRTS, &wrq) < 0) - { - fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno)); - return(-1); - } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq, + "Set RTS Threshold"); wrq.u.rts.fixed = 1; } else /* Should be a numeric value */ if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value)) != 1) - iw_usage(); + ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]); } - if(ioctl(skfd, SIOCSIWRTS, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWRTS: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq, + "Set RTS Threshold"); continue; } @@ -1048,7 +1044,7 @@ set_info(int skfd, /* The socket */ { i++; if(i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG); wrq.u.frag.value = -1; wrq.u.frag.fixed = 1; wrq.u.frag.disabled = 0; @@ -1062,25 +1058,20 @@ set_info(int skfd, /* The socket */ if(!strcasecmp(args[i], "fixed")) { /* Get old fragmentation threshold */ - if(ioctl(skfd, SIOCGIWFRAG, &wrq) < 0) - { - fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno)); - return(-1); - } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq, + "Set Fragmentation Threshold"); wrq.u.frag.fixed = 1; } else /* Should be a numeric value */ - if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.frag.value)) + if(sscanf(args[i], "%ld", + (unsigned long *) &(wrq.u.frag.value)) != 1) - iw_usage(); + ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG, + args[i]); } - if(ioctl(skfd, SIOCSIWFRAG, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWFRAG: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq, + "Set Fragmentation Threshold"); continue; } @@ -1091,7 +1082,7 @@ set_info(int skfd, /* The socket */ i++; if(i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Mode", SIOCSIWMODE); if(sscanf(args[i], "%d", &k) != 1) { @@ -1101,14 +1092,11 @@ set_info(int skfd, /* The socket */ k++; } if((k >= IW_NUM_OPER_MODE) || (k < 0)) - iw_usage(); + ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]); wrq.u.mode = k; - if(ioctl(skfd, SIOCSIWMODE, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq, + "Set Mode"); continue; } @@ -1116,7 +1104,7 @@ set_info(int skfd, /* The socket */ if(!strncmp(args[i], "power", 3)) { if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); if(!strcasecmp(args[i], "off")) wrq.u.power.disabled = 1; /* i.e. max size */ @@ -1124,12 +1112,8 @@ set_info(int skfd, /* The socket */ if(!strcasecmp(args[i], "on")) { /* Get old Power info */ - if(ioctl(skfd, SIOCGIWPOWER, &wrq) < 0) - { - fprintf(stderr, "SIOCGIWPOWER: %s\n", strerror(errno)); - return(-1); - } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq, + "Set Power Management"); wrq.u.power.disabled = 0; } else @@ -1145,14 +1129,14 @@ set_info(int skfd, /* The socket */ { wrq.u.power.flags |= IW_POWER_MIN; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } else if(!strcasecmp(args[i], "max")) { wrq.u.power.flags |= IW_POWER_MAX; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } /* Check value type */ @@ -1160,14 +1144,14 @@ set_info(int skfd, /* The socket */ { wrq.u.power.flags |= IW_POWER_PERIOD; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } else if(!strcasecmp(args[i], "timeout")) { wrq.u.power.flags |= IW_POWER_TIMEOUT; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } /* Is there any value to grab ? */ @@ -1203,16 +1187,13 @@ set_info(int skfd, /* The socket */ } } if(!gotone) - iw_usage(); + ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER, + args[i]); --i; } - if(ioctl(skfd, SIOCSIWPOWER, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWPOWER(%d): %s\n", - errno, strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq, + "Set Power Management"); continue; } @@ -1223,14 +1204,13 @@ set_info(int skfd, /* The socket */ struct iw_range range; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW); /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); /* Prepare the request */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.txpower.value = -1; wrq.u.txpower.fixed = 1; wrq.u.txpower.disabled = 0; @@ -1245,12 +1225,8 @@ set_info(int skfd, /* The socket */ if(!strcasecmp(args[i], "fixed")) { /* Get old tx-power */ - if(ioctl(skfd, SIOCGIWTXPOW, &wrq) < 0) - { - fprintf(stderr, "SIOCGIWTXPOW: %s\n", strerror(errno)); - return(-1); - } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq, + "Set Tx Power"); wrq.u.txpower.fixed = 1; } else /* Should be a numeric value */ @@ -1261,7 +1237,7 @@ set_info(int skfd, /* The socket */ /* Get the value */ if(sscanf(args[i], "%ld", (unsigned long *) &(power)) != 1) - iw_usage(); + ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW, args[i]); /* Check if milliwatt */ ismwatt = (index(args[i], 'm') != NULL); @@ -1292,24 +1268,21 @@ set_info(int skfd, /* The socket */ } } - if(ioctl(skfd, SIOCSIWTXPOW, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWTXPOW: %s\n", strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq, + "Set Tx Power"); continue; } #endif #if WIRELESS_EXT > 10 - /* ---------- Set Power Management ---------- */ + /* ---------- Set Retry limit ---------- */ if(!strncmp(args[i], "retry", 3)) { double temp; int gotone = 0; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); /* Default - nope */ wrq.u.retry.flags = IW_RETRY_LIMIT; @@ -1320,14 +1293,14 @@ set_info(int skfd, /* The socket */ { wrq.u.retry.flags |= IW_RETRY_MIN; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } else if(!strcasecmp(args[i], "max")) { wrq.u.retry.flags |= IW_RETRY_MAX; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } /* Check value type */ @@ -1335,14 +1308,14 @@ set_info(int skfd, /* The socket */ { wrq.u.retry.flags |= IW_RETRY_LIMIT; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } else if(!strncasecmp(args[i], "lifetime", 4)) { wrq.u.retry.flags |= IW_RETRY_LIFETIME; if(++i >= count) - iw_usage(); + ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } /* Is there any value to grab ? */ @@ -1362,15 +1335,11 @@ set_info(int skfd, /* The socket */ } if(!gotone) - iw_usage(); + ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]); --i; - if(ioctl(skfd, SIOCSIWRETRY, &wrq) < 0) - { - fprintf(stderr, "SIOCSIWRETRY(%d): %s\n", - errno, strerror(errno)); - return(-1); - } + IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq, + "Set Retry Limit"); continue; } @@ -1378,8 +1347,8 @@ set_info(int skfd, /* The socket */ /* ---------- Other ---------- */ /* Here we have an unrecognised arg... */ - fprintf(stderr, "Invalid argument : %s\n", args[i]); - iw_usage(); + fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n", + args[i]); return(-1); } /* for(index ... */ return(0); diff --git a/wireless_tools/iwgetid.c b/wireless_tools/iwgetid.c index 226c8c5..c550431 100644 --- a/wireless_tools/iwgetid.c +++ b/wireless_tools/iwgetid.c @@ -6,6 +6,7 @@ * Just print the ESSID or NWID... * * This file is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ #include "iwlib.h" /* Header */ diff --git a/wireless_tools/iwlib.c b/wireless_tools/iwlib.c index ed3e357..421f4e1 100644 --- a/wireless_tools/iwlib.c +++ b/wireless_tools/iwlib.c @@ -6,6 +6,7 @@ * Common subroutines to all the wireless tools... * * This file is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ #include "iwlib.h" /* Header */ @@ -74,13 +75,12 @@ iw_get_range_info(int skfd, char buffer[sizeof(iwrange) * 2]; /* Large enough */ /* Cleanup */ - memset(buffer, 0, sizeof(range)); + memset(buffer, 0, sizeof(iwrange) * 2); - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) buffer; - wrq.u.data.length = 0; + wrq.u.data.length = sizeof(iwrange) * 2; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0) return(-1); /* Copy stuff at the right place, ignore extra */ @@ -135,11 +135,10 @@ iw_get_priv_info(int skfd, struct iwreq wrq; /* Ask the driver */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) priv; - wrq.u.data.length = 0; + wrq.u.data.length = 32; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWPRIV, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) < 0) return(-1); /* Return the number of ioctls */ @@ -164,35 +163,31 @@ iw_get_basic_config(int skfd, memset((char *) info, 0, sizeof(struct wireless_config)); /* Get wireless name */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0) + if(iw_get_ext(skfd, ifname, 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) + if(iw_get_ext(skfd, ifname, 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) + if(iw_get_ext(skfd, ifname, 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.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) { info->has_key = 1; info->key_size = wrq.u.data.length; @@ -200,19 +195,17 @@ iw_get_basic_config(int skfd, } /* Get ESSID */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.essid.pointer = (caddr_t) info->essid; - wrq.u.essid.length = 0; + wrq.u.essid.length = IW_ESSID_MAX_SIZE; wrq.u.essid.flags = 0; - if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, 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(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0) { if((wrq.u.mode < 6) && (wrq.u.mode >= 0)) info->has_mode = 1; @@ -238,19 +231,17 @@ iw_set_basic_config(int skfd, int ret = 0; /* Get wireless name (check if interface is valid) */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0) + if(iw_get_ext(skfd, ifname, 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) + if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0) { fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno)); ret = -1; @@ -260,10 +251,9 @@ iw_set_basic_config(int skfd, /* 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) + if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0) { fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); ret = -1; @@ -279,12 +269,11 @@ iw_set_basic_config(int skfd, 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.flags = (flags & (IW_ENCODE_INDEX)) | IW_ENCODE_NOKEY; wrq.u.data.length = 0; - if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0) + if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); @@ -296,12 +285,11 @@ iw_set_basic_config(int skfd, 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) + if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); @@ -312,12 +300,11 @@ iw_set_basic_config(int skfd, /* 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) + if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0) { fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno)); ret = -1; @@ -330,7 +317,7 @@ iw_set_basic_config(int skfd, strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.mode = info->mode; - if(ioctl(skfd, SIOCSIWMODE, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno)); ret = -1; @@ -415,7 +402,7 @@ iw_get_stats(int skfd, 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) + if(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0) return(-1); return(0); @@ -702,48 +689,82 @@ iw_print_retry_value(char * buffer, /*------------------------------------------------------------------*/ /* - * Check if interface support the right address types... + * Check if interface support the right MAC address type... */ int -iw_check_addr_type(int skfd, - char * ifname) +iw_check_mac_addr_type(int skfd, + char * ifname) { struct ifreq ifr; - /* Get the type of interface address */ + /* Get the type of hardware address */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) || - (ifr.ifr_addr.sa_family != AF_INET)) + if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) || + (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)) { /* Deep trouble... */ - fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname); + fprintf(stderr, "Interface %s doesn't support MAC addresses\n", + ifname); return(-1); } #ifdef DEBUG - printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family, - *((unsigned long *) ifr.ifr_addr.sa_data)); + printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family, + pr_ether(ifr.ifr_hwaddr.sa_data)); #endif - /* Get the type of hardware address */ + return(0); +} + + +/*------------------------------------------------------------------*/ +/* + * Check if interface support the right interface address type... + */ +int +iw_check_if_addr_type(int skfd, + char * ifname) +{ + struct ifreq ifr; + + /* Get the type of interface address */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) || - (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)) + if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) || + (ifr.ifr_addr.sa_family != AF_INET)) { /* Deep trouble... */ - fprintf(stderr, "Interface %s doesn't support MAC addresses\n", - ifname); + fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname); return(-1); } #ifdef DEBUG - printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family, - pr_ether(ifr.ifr_hwaddr.sa_data)); + printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family, + *((unsigned long *) ifr.ifr_addr.sa_data)); #endif return(0); } +#if 0 +/*------------------------------------------------------------------*/ +/* + * Check if interface support the right address types... + */ +int +iw_check_addr_type(int skfd, + char * ifname) +{ + /* Check the interface address type */ + if(iw_check_if_addr_type(skfd, ifname) < 0) + return(-1); + + /* Check the interface address type */ + if(iw_check_mac_addr_type(skfd, ifname) < 0) + return(-1); + + return(0); +} +#endif /*------------------------------------------------------------------*/ /* @@ -887,6 +908,13 @@ iw_in_addr(int skfd, struct sockaddr if_address; struct arpreq arp_query; + /* Check if we have valid interface address type */ + if(iw_check_if_addr_type(skfd, ifname) < 0) + { + fprintf(stderr, "%-8.8s Interface doesn't support IP addresses\n", ifname); + return(-1); + } + /* Read interface address */ if(iw_in_inet(bufp, &if_address) < 0) { @@ -922,12 +950,21 @@ iw_in_addr(int skfd, #endif } else /* If it's an hardware address */ - /* Get the hardware address */ - if(iw_in_ether(bufp, sap) < 0) - { - fprintf(stderr, "Invalid hardware address %s\n", bufp); - return(-1); - } + { + /* Check if we have valid mac address type */ + if(iw_check_mac_addr_type(skfd, ifname) < 0) + { + fprintf(stderr, "%-8.8s Interface doesn't support MAC addresses\n", ifname); + return(-1); + } + + /* Get the hardware address */ + if(iw_in_ether(bufp, sap) < 0) + { + fprintf(stderr, "Invalid hardware address %s\n", bufp); + return(-1); + } + } #ifdef DEBUG printf("Hw Address = %s\n", pr_ether(sap->sa_data)); diff --git a/wireless_tools/iwlib.h b/wireless_tools/iwlib.h index 723475b..b195b82 100644 --- a/wireless_tools/iwlib.h +++ b/wireless_tools/iwlib.h @@ -1,11 +1,12 @@ /* * Wireless Tools * - * Jean II - HPLB 97->99 - HPL 99->01 + * Jean II - HPLB 97->99 - HPL 99->02 * * Common header for the Wireless Extension library... * * This file is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ #ifndef IWLIB_H @@ -29,18 +30,59 @@ #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 ;-) */ + * Don't look, you would go blind ;-) */ -#ifdef KLUDGE_HEADERS -#include -#endif /* KLUDGE_HEADERS */ +#ifndef LINUX_VERSION_CODE +#include +#endif -#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 */ +/* Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1 */ +#if defined(__GLIBC__) \ + && __GLIBC__ == 2 \ + && __GLIBC_MINOR__ >= 2 \ + && LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#define GLIBC22_HEADERS + +/* Kernel headers 2.4.X + Glibc 2.1 - Debian 2.2 upgraded, RH 7.0 + * Kernel headers 2.2.X + Glibc 2.1 - Debian 2.2, RH 6.1 */ +#elif defined(__GLIBC__) \ + && __GLIBC__ == 2 \ + && __GLIBC_MINOR__ == 1 \ + && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) +#define GLIBC_HEADERS + +/* Kernel headers 2.2.X + Glibc 2.0 - Debian 2.1 */ +#elif defined(__GLIBC__) \ + && __GLIBC__ == 2 \ + && __GLIBC_MINOR__ == 0 \ + && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0) \ + && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) +#define GLIBC_HEADERS +#define KLUDGE_HEADERS + +/* Note : is it really worth supporting kernel 2.0.X, knowing that + * we require WE v9, which is only available in 2.2.X and higher ? + * I guess one could use 2.0.x with an upgraded wireless.h... */ + +/* Kernel headers 2.0.X + Glibc 2.0 - Debian 2.0, RH 5 */ +#elif defined(__GLIBC__) \ + && __GLIBC__ == 2 \ + && __GLIBC_MINOR__ == 0 \ + && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) \ + && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0) +#define GLIBC_HEADERS + +/* Kernel headers 2.0.X + libc5 - old systems */ +#elif defined(_LINUX_C_LIB_VERSION_MAJOR) \ + && _LINUX_C_LIB_VERSION_MAJOR == 5 \ + && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0) \ + && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) +#define LIBC5_HEADERS + +/* Unsupported combination */ +#else +#error "Your kernel/libc combination is not supported" +#endif #ifdef GLIBC22_HEADERS /* Added by Ross G. Miller , 3/28/01 */ @@ -49,6 +91,16 @@ #include #endif /* GLIBC22_HEADERS */ +#ifdef KLUDGE_HEADERS +#include +#endif /* KLUDGE_HEADERS */ + +#ifdef GLIBC_HEADERS +#include /* For ARPHRD_ETHER */ +#include /* For AF_INET & struct sockaddr */ +#include /* For struct sockaddr_in */ +#endif /* KLUDGE_HEADERS || GLIBC_HEADERS */ + #ifdef LIBC5_HEADERS #include /* For AF_INET & struct sockaddr & socket() */ #include /* For ARPHRD_ETHER */ @@ -67,8 +119,8 @@ #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...\ +#if WIRELESS_EXT < 12 +#warning "Wireless Extension v12 recommended...\ You may update your kernel and/or system headers to get the new features..." #endif @@ -88,12 +140,17 @@ You may update your kernel and/or system headers to get the new features..." #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 +#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 +#endif /* IW_ENCODE_NOKEY */ + +/* More backward compatibility */ +#ifndef SIOCSIWCOMMIT +#define SIOCSIWCOMMIT SIOCSIWNAME +#endif /* SIOCSIWCOMMIT */ /****************************** TYPES ******************************/ @@ -240,8 +297,16 @@ void #endif /* --------------------- ADDRESS SUBROUTINES ---------------------- */ int + iw_check_mac_addr_type(int skfd, + char * ifname); +int + iw_check_if_addr_type(int skfd, + char * ifname); +#if 0 +int iw_check_addr_type(int skfd, char * ifname); +#endif char * iw_pr_ether(char *buffer, unsigned char *ptr); int @@ -262,4 +327,46 @@ int extern const char * iw_operation_mode[]; #define IW_NUM_OPER_MODE 6 +/************************* INLINE FUNTIONS *************************/ +/* + * Function that are so simple that it's more efficient inlining them + */ + +/* + * Note : I've defined wrapper for the ioctl request so that + * it will be easier to migrate to other kernel API if needed + */ + +/*------------------------------------------------------------------*/ +/* + * Wrapper to push some Wireless Parameter in the driver + */ +static inline int +iw_set_ext(int skfd, /* Socket to the kernel */ + char * ifname, /* Device name */ + int request, /* WE ID */ + struct iwreq * pwrq) /* Fixed part of the request */ +{ + /* Set device name */ + strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); + /* Do the request */ + return(ioctl(skfd, request, pwrq)); +} + +/*------------------------------------------------------------------*/ +/* + * Wrapper to extract some Wireless Parameter out of the driver + */ +static inline int +iw_get_ext(int skfd, /* Socket to the kernel */ + char * ifname, /* Device name */ + int request, /* WE ID */ + struct iwreq * pwrq) /* Fixed part of the request */ +{ + /* Set device name */ + strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); + /* Do the request */ + return(ioctl(skfd, request, pwrq)); +} + #endif /* IWLIB_H */ diff --git a/wireless_tools/iwlist.8 b/wireless_tools/iwlist.8 index f362bae..3c86fef 100644 --- a/wireless_tools/iwlist.8 +++ b/wireless_tools/iwlist.8 @@ -17,7 +17,7 @@ iwlist \- Get wireless statistics from specific nodes .br .BI "iwlist " interface " rate" .br -.BI "iwlist " interface " keys" +.BI "iwlist " interface " key" .br .BI "iwlist " interface " power" .br @@ -37,21 +37,21 @@ list of parameters. .\" .SH PARAMETERS .TP -.B freq +.BR freq / channel Give the list of available frequencies in the device and the number of defined channels. Please note that usually the driver returns the total number of channels and only the frequencies available in the present locale, so there is no one to one mapping between frequencies displayed and channel numbers. .TP -.B ap +.BR ap / accesspoint Give the list of Access Points in range, and optionally the quality of link to them. .TP .BR rate / bit [rate] List the bit-rates supported by the device. .TP -.BR keys / enc [ryption] +.BR key / enc [ryption] List the encryption key sizes supported and display all the encryption keys availables in the device. .TP diff --git a/wireless_tools/iwlist.c b/wireless_tools/iwlist.c index 50db6c9..30640e6 100644 --- a/wireless_tools/iwlist.c +++ b/wireless_tools/iwlist.c @@ -5,9 +5,10 @@ * * This tool can access various piece of information on the card * not part of iwconfig... - * You need to link this code against "iwcommon.c" and "-lm". + * You need to link this code against "iwlist.c" and "-lm". * * This file is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ #include "iwlib.h" /* Header */ @@ -80,11 +81,10 @@ print_ap_info(int skfd, int i; /* Collect stats */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) buffer; - wrq.u.data.length = 0; + wrq.u.data.length = IW_MAX_AP; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWAPLIST, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0) { fprintf(stderr, "%-8.8s Interface doesn't have a list of Access Points\n\n", ifname); return; @@ -98,10 +98,10 @@ print_ap_info(int skfd, hwa = (struct sockaddr *) buffer; qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); - /* Check if we have valid address types */ - if(iw_check_addr_type(skfd, ifname) < 0) + /* Check if we have valid mac address type */ + if(iw_check_mac_addr_type(skfd, ifname) < 0) { - fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname); + fprintf(stderr, "%-8.8s Interface doesn't support MAC addresses\n\n", ifname); return; } @@ -212,11 +212,10 @@ print_keys_info(int skfd, printf("%d keys available :\n", range.max_encoding_tokens); for(k = 1; k <= range.max_encoding_tokens; k++) { - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) key; - wrq.u.data.length = 0; + wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = k; - if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); break; @@ -236,11 +235,10 @@ print_keys_info(int skfd, } } /* Print current key and mode */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) key; - wrq.u.data.length = 0; + wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; /* Set index to zero to get current */ - if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); return; @@ -270,9 +268,8 @@ get_pm_value(int skfd, char * buffer) { /* Get Another Power Management value */ - strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); pwrq->u.power.flags = flags; - if(ioctl(skfd, SIOCGIWPOWER, pwrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0) { /* Let's check the value and its type */ if(pwrq->u.power.flags & IW_POWER_TYPE) @@ -354,9 +351,8 @@ print_pm_info(int skfd, #endif /* WIRELESS_EXT > 9 */ /* Get current Power Management settings */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.power.flags = 0; - if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0) { int flags = wrq.u.power.flags; @@ -485,9 +481,8 @@ get_retry_value(int skfd, char * buffer) { /* Get Another retry value */ - strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); pwrq->u.retry.flags = flags; - if(ioctl(skfd, SIOCGIWRETRY, pwrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0) { /* Let's check the value and its type */ if(pwrq->u.retry.flags & IW_RETRY_TYPE) @@ -554,9 +549,8 @@ print_retry_info(int skfd, } /* Get current retry settings */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.retry.flags = 0; - if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0) + if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0) { int flags = wrq.u.retry.flags; @@ -661,7 +655,7 @@ static const struct iwlist_entry iwlist_cmds[] = { { "accesspoints", print_ap_info }, { "bitrate", print_bitrate_info }, { "rate", print_bitrate_info }, - { "encription", print_keys_info }, + { "encryption", print_keys_info }, { "key", print_keys_info }, { "power", print_pm_info }, { "txpower", print_txpower_info }, diff --git a/wireless_tools/iwpriv.c b/wireless_tools/iwpriv.c index 65a0aee..2db4afd 100644 --- a/wireless_tools/iwpriv.c +++ b/wireless_tools/iwpriv.c @@ -5,9 +5,10 @@ * * Main code for "iwconfig". This is the generic tool for most * manipulations... - * You need to link this code against "iwcommon.c" and "-lm". + * You need to link this code against "iwlib.c" and "-lm". * * This file is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ #include "iwlib.h" /* Header */ @@ -38,7 +39,7 @@ print_priv_info(int skfd, char * ifname) { int k; - iwprivargs priv[16]; + iwprivargs priv[32]; int n; char * argtype[] = { " ", "byte", "char", "", "int ", "float" }; @@ -112,6 +113,7 @@ set_private(int skfd, /* Socket */ int k; iwprivargs priv[16]; int number; + int temp; /* Read the private ioctls */ number = iw_get_priv_info(skfd, ifname, priv); @@ -152,8 +154,10 @@ set_private(int skfd, /* Socket */ wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ - for(; i < wrq.u.data.length + 1; i++) - sscanf(args[i], "%d", (int *)(buffer + i - 1)); + for(; i < wrq.u.data.length + 1; i++) { + sscanf(args[i], "%d", &temp); + buffer[i - 1] = (char) temp; + } break; case IW_PRIV_TYPE_INT: diff --git a/wireless_tools/iwspy.c b/wireless_tools/iwspy.c index cd41ccd..57d9b25 100644 --- a/wireless_tools/iwspy.c +++ b/wireless_tools/iwspy.c @@ -4,9 +4,10 @@ * Jean II - HPLB '99 * * This tool can manipulate the spy list : add addresses and display stat - * You need to link this code against "iwcommon.c" and "-lm". + * You need to link this code against "iwlib.c" and "-lm". * * This file is released under the GPL license. + * Copyright (c) 1997-2002 Jean Tourrilhes */ #include "iwlib.h" /* Header */ @@ -33,11 +34,10 @@ print_spy_info(int skfd, int i; /* Collect stats */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) buffer; - wrq.u.data.length = 0; + wrq.u.data.length = IW_MAX_SPY; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) { fprintf(stderr, "%-8.8s Interface doesn't support wireless statistic collection\n\n", ifname); return; @@ -46,12 +46,10 @@ print_spy_info(int skfd, /* Number of addresses */ n = wrq.u.data.length; - - - /* Check if we have valid address types */ - if(iw_check_addr_type(skfd, ifname) < 0) + /* Check if we have valid mac address type */ + if(iw_check_mac_addr_type(skfd, ifname) < 0) { - fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname); + fprintf(stderr, "%-8.8s Interface doesn't support MAC addresses\n\n", ifname); return; } @@ -136,13 +134,6 @@ set_spy_info(int skfd, /* The socket */ i = 0; /* first arg to read */ nbr = 0; /* Number of args readen so far */ - /* Check if we have valid address types */ - if(iw_check_addr_type(skfd, ifname) < 0) - { - fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname); - return(-1); - } - /* "off" : disable functionality (set 0 addresses) */ if(!strcmp(args[0], "off")) i = count; /* hack */ @@ -153,11 +144,17 @@ set_spy_info(int skfd, /* The socket */ char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_SPY]; - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + /* Check if we have valid mac address type */ + if(iw_check_mac_addr_type(skfd, ifname) < 0) + { + fprintf(stderr, "%-8.8s Interface doesn't support MAC addresses\n", ifname); + return(-1); + } + wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = 0; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0) + if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept reading addresses...\n"); fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno)); @@ -174,6 +171,7 @@ set_spy_info(int skfd, /* The socket */ /* Read other args on command line */ while((i < count) && (nbr < IW_MAX_SPY)) { + /* Get the address and check if the interface supports it */ if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0) continue; nbr++; @@ -193,11 +191,10 @@ set_spy_info(int skfd, /* The socket */ } /* Time to do send addresses to the driver */ - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) hw_address; wrq.u.data.length = nbr; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCSIWSPY, &wrq) < 0) + if(iw_set_ext(skfd, ifname, SIOCSIWSPY, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept addresses...\n"); fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno)); diff --git a/wireless_tools/wireless.12.h b/wireless_tools/wireless.12.h new file mode 100644 index 0000000..4183d4a --- /dev/null +++ b/wireless_tools/wireless.12.h @@ -0,0 +1,570 @@ +/* + * This file define a set of standard wireless extensions + * + * Version : 12 5.10.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 12 + +/* + * Changes : + * + * V2 to V3 + * -------- + * Alan Cox start some incompatibles changes. I've integrated a bit more. + * - Encryption renamed to Encode to avoid US regulation problems + * - Frequency changed from float to struct to avoid problems on old 386 + * + * V3 to V4 + * -------- + * - Add sensitivity + * + * V4 to V5 + * -------- + * - Missing encoding definitions in range + * - Access points stuff + * + * V5 to V6 + * -------- + * - 802.11 support (ESSID ioctls) + * + * V6 to V7 + * -------- + * - define IW_ESSID_MAX_SIZE and IW_MAX_AP + * + * V7 to V8 + * -------- + * - Changed my e-mail address + * - More 802.11 support (nickname, rate, rts, frag) + * - List index in frequencies + * + * V8 to V9 + * -------- + * - Support for 'mode of operation' (ad-hoc, managed...) + * - Support for unicast and multicast power saving + * - Change encoding to support larger tokens (>64 bits) + * - Updated iw_params (disable, flags) and use it for NWID + * - Extracted iw_point from iwreq for clarity + * + * V9 to V10 + * --------- + * - Add PM capability to range structure + * - Add PM modifier : MAX/MIN/RELATIVE + * - Add encoding option : IW_ENCODE_NOKEY + * - Add TxPower ioctls (work like TxRate) + * + * V10 to V11 + * ---------- + * - Add WE version in range (help backward/forward compatibility) + * - Add retry ioctls (work like PM) + * + * V11 to V12 + * ---------- + * - Add SIOCSIWSTATS to get /proc/net/wireless programatically + * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space + * - Add new statistics (frag, retry, beacon) + * - Add average quality (for user space calibration) + */ + +/* -------------------------- 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 */ +#define SIOCSIWSTATS 0x8B0E /* Unused */ +#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ + +/* Mobile IP support */ +#define SIOCSIWSPY 0x8B10 /* set spy addresses */ +#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ + +/* Access Point manipulation */ +#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ +#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ +#define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ + +/* 802.11 specific support */ +#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ +#define SIOCGIWESSID 0x8B1B /* get ESSID */ +#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ +#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ +/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit + * within the 'iwreq' structure, so we need to use the 'data' member to + * point to a string in user space, like it is done for RANGE... + * The "flags" member indicate if the ESSID is active or not (promiscuous). + */ + +/* Other parameters useful in 802.11 and some other devices */ +#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ +#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ +#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ +#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ +#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ +#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ +#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ +#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ +#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ +#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ + +/* Encoding stuff (scrambling, hardware security, WEP...) */ +#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ +#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ +/* Power saving stuff (power management, unicast and multicast) */ +#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ +#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ + +/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ + +/* These 16 ioctl are wireless device private. + * Each driver is free to use them for whatever purpose it chooses, + * however the driver *must* export the description of those ioctls + * with SIOCGIWPRIV and *must* use arguments as defined below. + * If you don't follow those rules, DaveM is going to hate you (reason : + * it make mixed 32/64bit operation impossible). + */ +#define SIOCIWFIRSTPRIV 0x8BE0 +#define SIOCIWLASTPRIV 0x8BFF +/* Previously, we were using SIOCDEVPRIVATE, but we 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 SIOCIWLASTPRIV /* 0x8BFF */ + +/* Even : get (world access), odd : set (root access) */ +#define IW_IS_SET(cmd) (!((cmd) & 0x1)) +#define IW_IS_GET(cmd) ((cmd) & 0x1) + +/* ------------------------- PRIVATE INFO ------------------------- */ +/* + * The following is used with SIOCGIWPRIV. It allow a driver to define + * the interface (name, type of data) for its private ioctl. + * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV + */ + +#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ +#define IW_PRIV_TYPE_NONE 0x0000 +#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ +#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ +#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ +#define IW_PRIV_TYPE_FLOAT 0x5000 + +#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ + +#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ + +/* + * Note : if the number of args is fixed and the size < 16 octets, + * instead of passing a pointer we will put args in the iwreq struct... + */ + +/* ----------------------- OTHER CONSTANTS ----------------------- */ + +/* Maximum frequencies in the range struct */ +#define IW_MAX_FREQUENCIES 16 +/* Note : if you have something like 80 frequencies, + * don't increase this constant and don't fill the frequency list. + * The user will be able to set by channel anyway... */ + +/* Maximum bit rates in the range struct */ +#define IW_MAX_BITRATES 8 + +/* Maximum tx powers in the range struct */ +#define IW_MAX_TXPOWER 8 + +/* Maximum of address that you may set with SPY */ +#define IW_MAX_SPY 8 + +/* Maximum of address that you may get in the + list of access points in range */ +#define IW_MAX_AP 8 + +/* Maximum size of the ESSID and NICKN strings */ +#define IW_ESSID_MAX_SIZE 32 + +/* Modes of operation */ +#define IW_MODE_AUTO 0 /* Let the driver decides */ +#define IW_MODE_ADHOC 1 /* Single cell network */ +#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ +#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ +#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ +#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ + +/* Maximum number of size of encoding token available + * they are listed in the range structure */ +#define IW_MAX_ENCODING_SIZES 8 + +/* Maximum size of the encoding token in bytes */ +#define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ + +/* Flags for encoding (along with the token) */ +#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ +#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ +#define IW_ENCODE_MODE 0xF000 /* Modes defined below */ +#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ +#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ +#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ +#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ +#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ + +/* Power management flags available (along with the value, if any) */ +#define IW_POWER_ON 0x0000 /* No details... */ +#define IW_POWER_TYPE 0xF000 /* Type of parameter */ +#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ +#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ +#define IW_POWER_MODE 0x0F00 /* Power Management mode */ +#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ +#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ +#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ +#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ +#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ +#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ +#define IW_POWER_MIN 0x0001 /* Value is a minimum */ +#define IW_POWER_MAX 0x0002 /* Value is a maximum */ +#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ + +/* Transmit Power flags available */ +#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ +#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ + +/* Retry limits and lifetime flags available */ +#define IW_RETRY_ON 0x0000 /* No details... */ +#define IW_RETRY_TYPE 0xF000 /* Type of parameter */ +#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ +#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ +#define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ +#define IW_RETRY_MIN 0x0001 /* Value is a minimum */ +#define IW_RETRY_MAX 0x0002 /* Value is a maximum */ +#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ + +/****************************** TYPES ******************************/ + +/* --------------------------- SUBTYPES --------------------------- */ +/* + * Generic format for most parameters that fit in an int + */ +struct iw_param +{ + __s32 value; /* The value of the parameter itself */ + __u8 fixed; /* Hardware should not use auto select */ + __u8 disabled; /* Disable the feature */ + __u16 flags; /* Various specifc flags (if any) */ +}; + +/* + * For all data larger than 16 octets, we need to use a + * pointer to memory allocated in user space. + */ +struct iw_point +{ + caddr_t pointer; /* Pointer to the data (in user space) */ + __u16 length; /* number of fields or size in bytes */ + __u16 flags; /* Optional params */ +}; + +/* + * A frequency + * For numbers lower than 10^9, we encode the number in 'm' and + * set 'e' to 0 + * For number greater than 10^9, we divide it by the lowest power + * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... + * The power of 10 is in 'e', the result of the division is in 'm'. + */ +struct iw_freq +{ + __u32 m; /* Mantissa */ + __u16 e; /* Exponent */ + __u8 i; /* List index (when in range struct) */ +}; + +/* + * Quality of the link + */ +struct iw_quality +{ + __u8 qual; /* link quality (%retries, SNR, + %missed beacons or better...) */ + __u8 level; /* signal level (dBm) */ + __u8 noise; /* noise level (dBm) */ + __u8 updated; /* Flags to know if updated */ +}; + +/* + * Packet discarded in the wireless adapter due to + * "wireless" specific problems... + * Note : the list of counter and statistics in net_device_stats + * is already pretty exhaustive, and you should use that first. + * This is only additional stats... + */ +struct iw_discarded +{ + __u32 nwid; /* Rx : Wrong nwid/essid */ + __u32 code; /* Rx : Unable to code/decode (WEP) */ + __u32 fragment; /* Rx : Can't perform MAC reassembly */ + __u32 retries; /* Tx : Max MAC retries num reached */ + __u32 misc; /* Others cases */ +}; + +/* + * Packet/Time period missed in the wireless adapter due to + * "wireless" specific problems... + */ +struct iw_missed +{ + __u32 beacon; /* Missed beacons/superframe */ +}; + +/* ------------------------ WIRELESS STATS ------------------------ */ +/* + * Wireless statistics (used for /proc/net/wireless) + */ +struct iw_statistics +{ + __u16 status; /* Status + * - device dependent for now */ + + struct iw_quality qual; /* Quality of the link + * (instant/mean/max) */ + struct iw_discarded discard; /* Packet discarded counts */ + struct iw_missed miss; /* Packet missed counts */ +}; + +/* ------------------------ IOCTL REQUEST ------------------------ */ +/* + * 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 */ + + /* Average quality of link & SNR */ + struct iw_quality avg_qual; /* Quality of the link */ + /* This should contain the average/typical values of the quality + * indicator. This should be the threshold between a "good" and + * a "bad" link (example : monitor going from green to orange). + * Currently, user space apps like quality monitors don't have any + * way to calibrate the measurement. With this, they can split + * the range between 0 and max_qual in different quality level + * (using a geometric subdivision centered on the average). + * I expect that people doing the user space apps will feedback + * us on which value we need to put in each driver... + */ +}; + +/* + * Private ioctl interface information + */ + +struct iw_priv_args +{ + __u32 cmd; /* Number of the ioctl to issue */ + __u16 set_args; /* Type and number of args */ + __u16 get_args; /* Type and number of args */ + char name[IFNAMSIZ]; /* Name of the extension */ +}; + +#endif /* _LINUX_WIRELESS_H */ diff --git a/wireless_tools/wireless.h b/wireless_tools/wireless.h index 4183d4a..fa3c64f 100644 --- a/wireless_tools/wireless.h +++ b/wireless_tools/wireless.h @@ -1,9 +1,10 @@ /* * This file define a set of standard wireless extensions * - * Version : 12 5.10.01 + * Version : 13 6.12.01 * * Authors : Jean Tourrilhes - HPL - + * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H @@ -11,6 +12,8 @@ /************************** DOCUMENTATION **************************/ /* + * Initial APIs (1996 -> onward) : + * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * @@ -27,16 +30,27 @@ * 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) + * # 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) + * # net/core/dev.c (two other places) + * # include/linux/netdevice.h (one place) + * # include/linux/proc_fs.h (one place) * + * New driver API (2001 -> onward) : + * ------------------------------- + * This file is only concerned with the user space API and common definitions. + * The new driver API is defined and documented in : + * # include/net/iw_handler.h + * + * Note as well that /proc/net/wireless implementation has now moved in : + * # include/linux/wireless.c + * + * Other comments : + * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. @@ -54,16 +68,14 @@ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ -/**************************** CONSTANTS ****************************/ - -/* --------------------------- VERSION --------------------------- */ +/***************************** 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 12 +#define WIRELESS_EXT 13 /* * Changes : @@ -123,12 +135,20 @@ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) + * + * V12 to V13 + * ---------- + * - Document creation of new driver API. + * - Extract union iwreq_data from struct iwreq (for new driver API). + * - Rename SIOCSIWNAME as SIOCSIWCOMMIT */ +/**************************** CONSTANTS ****************************/ + /* -------------------------- IOCTL LIST -------------------------- */ /* Basic operations */ -#define SIOCSIWNAME 0x8B00 /* Unused */ +#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ #define SIOCGIWNWID 0x8B03 /* get network id */ @@ -197,7 +217,7 @@ */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF -/* Previously, we were using SIOCDEVPRIVATE, but we know have our +/* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). @@ -414,13 +434,49 @@ struct iw_statistics /* ------------------------ IOCTL REQUEST ------------------------ */ /* + * This structure defines the payload of an ioctl, and is used + * below. + * + * Note that this structure should fit on the memory footprint + * of iwreq (which is the same as ifreq), which mean a max size of + * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... + * You should check this when increasing the structures defined + * above in this file... + */ +union iwreq_data +{ + /* Config - generic */ + char name[IFNAMSIZ]; + /* Name : used to verify the presence of wireless extensions. + * Name of the protocol/provider... */ + + struct iw_point essid; /* Extended network name */ + struct iw_param nwid; /* network id (or domain - the cell) */ + struct iw_freq freq; /* frequency or channel : + * 0-1000 = channel + * > 1000 = frequency in Hz */ + + struct iw_param sens; /* signal level threshold */ + struct iw_param bitrate; /* default bit rate */ + struct iw_param txpower; /* default transmit power */ + struct iw_param rts; /* RTS threshold threshold */ + struct iw_param frag; /* Fragmentation threshold */ + __u32 mode; /* Operation mode */ + struct iw_param retry; /* Retry limits & lifetime */ + + struct iw_point encoding; /* Encoding stuff : tokens */ + struct iw_param power; /* PM duration/timeout */ + + struct sockaddr ap_addr; /* Access point address */ + + struct iw_point data; /* Other large parameters */ +}; + +/* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... - * - * 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... + * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { @@ -429,35 +485,8 @@ struct iwreq 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; + /* Data part (defined just above) */ + union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */