From b4660795a5c3dc792473889c326a30e7756e1c3b Mon Sep 17 00:00:00 2001 From: chris-kirby Date: Tue, 11 Oct 2016 14:42:04 -0600 Subject: [PATCH] v19 --- wireless_tools/INSTALL | 35 ++ wireless_tools/Makefile | 30 ++ wireless_tools/README | 31 ++ wireless_tools/compat.h | 96 +++++ wireless_tools/iwcommon.c | 392 +++++++++++++++++ wireless_tools/iwcommon.h | 268 ++++++++++++ wireless_tools/iwconfig | Bin 0 -> 17427 bytes wireless_tools/iwconfig.8 | 123 +++++- wireless_tools/iwconfig.c | 958 ++++++++++++++++++++++++++++++++---------- wireless_tools/iwpriv | Bin 0 -> 12673 bytes wireless_tools/iwpriv.8 | 113 +++++ wireless_tools/iwpriv.c | 646 ++++++++++++++++++++-------- wireless_tools/iwspy | Bin 0 -> 13793 bytes wireless_tools/iwspy.8 | 37 +- wireless_tools/iwspy.c | 770 +++++++++++++++++++++++---------- wireless_tools/wireless.h | 347 +++++++++++++++ wireless_tools/xwireless.c | 241 +++++++++++ wireless_tools/xwireless.make | 53 +++ 18 files changed, 3502 insertions(+), 638 deletions(-) create mode 100644 wireless_tools/INSTALL create mode 100644 wireless_tools/Makefile create mode 100644 wireless_tools/README create mode 100644 wireless_tools/compat.h create mode 100644 wireless_tools/iwcommon.c create mode 100644 wireless_tools/iwcommon.h create mode 100644 wireless_tools/iwconfig create mode 100644 wireless_tools/iwpriv create mode 100644 wireless_tools/iwpriv.8 create mode 100644 wireless_tools/iwspy create mode 100644 wireless_tools/wireless.h create mode 100644 wireless_tools/xwireless.c create mode 100644 wireless_tools/xwireless.make diff --git a/wireless_tools/INSTALL b/wireless_tools/INSTALL new file mode 100644 index 0000000..9f39ed4 --- /dev/null +++ b/wireless_tools/INSTALL @@ -0,0 +1,35 @@ +You need : +-------- + o A kernel supporting wireless extensions + -> from 2.1.17 onward + -> from 2.0.30 onward + -> patch available for 1.2.13 + Note : CONFIG_NET_RADIO must be enabled + o Driver supporting wireless extensions + -> Wavelan isa from kernel 2.1.17 onward + -> Wavelan pcmcia from pcmcia 2.9.2 onward + -> Netwave pcmcia from pcmcia 2.9.12 onward + -> Wavelan IEEE pcmcia drivers + -> Proxim RangeLan2/Symphony driver + -> Patch your favourite driver + Note : more recent kernels and drivers are likely to support + more wireless extension features... + +Compile wireless tools : +---------------------- + In theory, a make should suffice. + In practice, there is big troubles with the headers. 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 buried in iwcommon.h. + + +This package was originally created by: + + Jean + +And is now being maintained by: + Justin Seger + +It seem that I've been taking over ! + Jean diff --git a/wireless_tools/Makefile b/wireless_tools/Makefile new file mode 100644 index 0000000..9764187 --- /dev/null +++ b/wireless_tools/Makefile @@ -0,0 +1,30 @@ +CC = gcc +RM = rm -f + +RM_CMD = $(RM) *.BAK *.bak *.o ,* *~ *.a + +CFLAGS=-O2 -Wall + +PROGS=iwconfig iwpriv iwspy +LIBS=-lm + +all:: $(PROGS) + +.c.o: + $(CC) $(CFLAGS) -c $< + +iwconfig: iwconfig.o iwcommon.o + gcc -O2 -o $@ $^ $(LIBS) + +iwpriv: iwpriv.o iwcommon.o + gcc -O2 -o $@ $^ $(LIBS) + +iwspy: iwspy.o iwcommon.o + gcc -O2 -o $@ $^ $(LIBS) + +clean:: + $(RM_CMD) + +depend:: + makedepend -s "# DO NOT DELETE" -- $(INCLUDES) -- $(SRCS) +# DO NOT DELETE diff --git a/wireless_tools/README b/wireless_tools/README new file mode 100644 index 0000000..4a706b4 --- /dev/null +++ b/wireless_tools/README @@ -0,0 +1,31 @@ + This package contain the Wireless tools, used to manipulate +the Wireless Extensions. The Wireless Extension is an interface +allowing you to set Wireless LAN specific parameters and get the +specific stats. + +iwconfig.c +---------- + The main wireless tool. Used for device configuration. + You need of course to compile it. + This also includes the functionality previously contained in iwpriv.c. + It allows you to access device specific extensions. + +iwspy.c +------- + Mobile IP support test and allow get get stats per MAC address + (instead of globally). + +iwpriv.c +-------- + Manipulate driver private ioctls. + +xwireless.c +----------- + Graphical tool for the Netwave created by Dag Brattli + + + The man page should describe adequately the behaviour of the tools. + The list of changes, credits and errata notes are in +iwcommon.h. Compilation might be tricky. + + Jean diff --git a/wireless_tools/compat.h b/wireless_tools/compat.h new file mode 100644 index 0000000..224e048 --- /dev/null +++ b/wireless_tools/compat.h @@ -0,0 +1,96 @@ +/* This whole file is flaky */ +/* This is all we need to compile and can't find only in linux headers. + * So, I did copy past here... + */ +#define __u8 unsigned char +#define __u16 unsigned short +#define __u32 unsigned long /* Hum, and on Alpha ? */ +#define __u64 unsigned long long /* Unsure about this one */ + +#define IFNAMSIZ 16 +#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ +#define ETH_ALEN 6 /* Octets in one ethernet addr */ + +/* + * Interface request structure used for socket + * ioctl's. All interface ioctl's must have parameter + * definitions which begin with ifr_name. The + * remainder may be interface specific. + */ +struct ifreq +{ +#define IFHWADDRLEN 6 +#define IFNAMSIZ 16 + union + { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_metric; + int ifru_mtu; +#if 0 + struct ifmap ifru_map; +#endif + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + caddr_t ifru_data; + } ifr_ifru; +}; +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ + +/* + * Structure used in SIOCGIFCONF request. + * Used to retrieve interface configuration + * for machine (useful for programs which + * must know all networks accessible). + */ +struct ifconf +{ + int ifc_len; /* size of buffer */ + union + { + caddr_t ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; +}; +#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ +#define ifc_req ifc_ifcu.ifcu_req /* array of structures */ + +/* Internet address. */ +struct in_addr { + __u32 s_addr; +}; + +/* Address to accept any incoming messages. */ +#define INADDR_ANY ((unsigned long int) 0x00000000) + +/* Structure describing an Internet (IP) socket address. */ +#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct sockaddr_in { + short int sin_family; /* Address family */ + unsigned short int sin_port; /* Port number */ + struct in_addr sin_addr; /* Internet address */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - + sizeof(unsigned short int) - sizeof(struct in_addr)]; +}; + +#define ATF_COM 0x02 /* completed entry (ha valid) */ +/* ARP ioctl request. */ +struct arpreq { + struct sockaddr arp_pa; /* protocol address */ + struct sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ + char arp_dev[16]; +}; + diff --git a/wireless_tools/iwcommon.c b/wireless_tools/iwcommon.c new file mode 100644 index 0000000..43de184 --- /dev/null +++ b/wireless_tools/iwcommon.c @@ -0,0 +1,392 @@ +/* + * Wireless Tools + * + * Jean II - HPLB '99 + * + * Common subroutines to all the wireless tools... + */ + +#include "iwcommon.h" /* Header */ + +/************************ SOCKET SUBROUTINES *************************/ + +/*------------------------------------------------------------------*/ +/* + * Open a socket. + * Depending on the protocol present, open the right socket. The socket + * will allow us to talk to the driver. + */ +int +sockets_open(void) +{ + int ipx_sock = -1; /* IPX socket */ + int ax25_sock = -1; /* AX.25 socket */ + int inet_sock = -1; /* INET socket */ + int ddp_sock = -1; /* Appletalk DDP socket */ + + inet_sock=socket(AF_INET, SOCK_DGRAM, 0); + ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0); + ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0); + ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0); + /* + * Now pick any (exisiting) useful socket family for generic queries + */ + if(inet_sock!=-1) + return inet_sock; + if(ipx_sock!=-1) + return ipx_sock; + if(ax25_sock!=-1) + return ax25_sock; + /* + * If this is -1 we have no known network layers and its time to jump. + */ + + return ddp_sock; +} + +/*********************** WIRELESS SUBROUTINES ************************/ + +/*------------------------------------------------------------------*/ +/* + * Get the range information out of the driver + */ +int +get_range_info(int skfd, + char * ifname, + iwrange * range) +{ + struct iwreq wrq; + + strcpy(wrq.ifr_name, ifname); + wrq.u.data.pointer = (caddr_t) range; + wrq.u.data.length = 0; + wrq.u.data.flags = 0; + if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0) + return(-1); + + return(0); +} + +/*------------------------------------------------------------------*/ +/* + * Get information about what private ioctls are supported by the driver + */ +int +get_priv_info(int skfd, + char * ifname, + iwprivargs * priv) +{ + struct iwreq wrq; + + /* Ask the driver */ + strcpy(wrq.ifr_name, ifname); + wrq.u.data.pointer = (caddr_t) priv; + wrq.u.data.length = 0; + wrq.u.data.flags = 0; + if(ioctl(skfd, SIOCGIWPRIV, &wrq) < 0) + return(-1); + + /* Return the number of ioctls */ + return(wrq.u.data.length); +} + +/********************** FREQUENCY SUBROUTINES ***********************/ + +/*------------------------------------------------------------------*/ +/* + * Convert a floating point the our internal representation of + * frequencies. + * The kernel doesn't want to hear about floating point, so we use + * this custom format instead. + */ +void +float2freq(double in, + iwfreq * out) +{ + out->e = (short) (floor(log10(in))); + if(out->e > 8) + { + out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100; + out->e -= 8; + } + else + { + out->m = in; + out->e = 0; + } +} + +/*------------------------------------------------------------------*/ +/* + * Convert our internal representation of frequencies to a floating point. + */ +double +freq2float(iwfreq * in) +{ + return ((double) in->m) * pow(10,in->e); +} + + +/*********************** ADDRESS SUBROUTINES ************************/ +/* + * This section is mostly a cut & past from net-tools-1.2.0 + * manage address display and input... + */ + +/*------------------------------------------------------------------*/ +/* + * Check if interface support the right address types... + */ +int +check_addr_type(int skfd, + char * ifname) +{ + struct ifreq ifr; + + /* Get the type of interface address */ + strcpy(ifr.ifr_name, ifname); + if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) || + (ifr.ifr_addr.sa_family != AF_INET)) + { + /* Deep trouble... */ + fprintf(stderr, "Interface %s doesn't support IP 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)); +#endif + + /* Get the type of hardware address */ + strcpy(ifr.ifr_name, ifname); + if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) || + (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)) + { + /* Deep trouble... */ + fprintf(stderr, "Interface %s doesn't support MAC addresses\n", + ifname); + return(-1); + } + +#ifdef DEBUG + printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family, + pr_ether(ifr.ifr_hwaddr.sa_data)); +#endif + + return(0); +} + + +/*------------------------------------------------------------------*/ +/* + * Display an Ethernet address in readable format. + */ +char * +pr_ether(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) + ); + return(buff); +} + +/*------------------------------------------------------------------*/ +/* + * Input an Ethernet address and convert to binary. + */ +int +in_ether(char *bufp, struct sockaddr *sap) +{ + unsigned char *ptr; + char c, *orig; + int i, val; + + sap->sa_family = ARPHRD_ETHER; + ptr = sap->sa_data; + + i = 0; + orig = bufp; + while((*bufp != '\0') && (i < ETH_ALEN)) { + val = 0; + c = *bufp++; + if (isdigit(c)) val = c - '0'; + else if (c >= 'a' && c <= 'f') val = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') val = c - 'A' + 10; + else { +#ifdef DEBUG + fprintf(stderr, "in_ether(%s): invalid ether address!\n", orig); +#endif + errno = EINVAL; + return(-1); + } + val <<= 4; + c = *bufp++; + if (isdigit(c)) val |= c - '0'; + else if (c >= 'a' && c <= 'f') val |= c - 'a' + 10; + else if (c >= 'A' && c <= 'F') val |= c - 'A' + 10; + else { +#ifdef DEBUG + fprintf(stderr, "in_ether(%s): invalid ether address!\n", orig); +#endif + errno = EINVAL; + return(-1); + } + *ptr++ = (unsigned char) (val & 0377); + i++; + + /* We might get a semicolon here - not required. */ + if (*bufp == ':') { + if (i == ETH_ALEN) { +#ifdef DEBUG + fprintf(stderr, "in_ether(%s): trailing : ignored!\n", + orig) +#endif + ; /* nothing */ + } + bufp++; + } + } + + /* That's it. Any trailing junk? */ + if ((i == ETH_ALEN) && (*bufp != '\0')) { +#ifdef DEBUG + fprintf(stderr, "in_ether(%s): trailing junk!\n", orig); + errno = EINVAL; + return(-1); +#endif + } + +#ifdef DEBUG + fprintf(stderr, "in_ether(%s): %s\n", orig, pr_ether(sap->sa_data)); +#endif + + return(0); +} + +/*------------------------------------------------------------------*/ +/* + * Input an Internet address and convert to binary. + */ +int +in_inet(char *bufp, struct sockaddr *sap) +{ + struct hostent *hp; + struct netent *np; + char *name = bufp; + struct sockaddr_in *sin = (struct sockaddr_in *) sap; + + /* Grmpf. -FvK */ + sin->sin_family = AF_INET; + sin->sin_port = 0; + + /* Default is special, meaning 0.0.0.0. */ + if (!strcmp(name, "default")) { + sin->sin_addr.s_addr = INADDR_ANY; + return(1); + } + + /* Try the NETWORKS database to see if this is a known network. */ + if ((np = getnetbyname(name)) != (struct netent *)NULL) { + sin->sin_addr.s_addr = htonl(np->n_net); + strcpy(name, np->n_name); + return(1); + } + + if ((hp = gethostbyname(name)) == (struct hostent *)NULL) { + errno = h_errno; + return(-1); + } + memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], hp->h_length); + strcpy(name, hp->h_name); + return(0); +} + +/*------------------------------------------------------------------*/ +/* + * Input an address and convert to binary. + */ +int +in_addr(int skfd, + char * ifname, + char * bufp, + struct sockaddr *sap) +{ + /* Check if it is a hardware or IP address */ + if(index(bufp, ':') == NULL) + { + struct sockaddr if_address; + struct arpreq arp_query; + + /* Read interface address */ + if(in_inet(bufp, &if_address) < 0) + { + fprintf(stderr, "Invalid interface address %s\n", bufp); + return(-1); + } + + /* Translate IP addresses to MAC addresses */ + memcpy((char *) &(arp_query.arp_pa), + (char *) &if_address, + sizeof(struct sockaddr)); + arp_query.arp_ha.sa_family = 0; + 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); + if((ioctl(skfd, SIOCGARP, &arp_query) < 0) || + !(arp_query.arp_flags & ATF_COM)) + { + fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n", + bufp, ifname, errno); + return(-1); + } + + /* Store new MAC address */ + memcpy((char *) sap, + (char *) &(arp_query.arp_ha), + sizeof(struct sockaddr)); + +#ifdef DEBUG + printf("IP Address %s => Hw Address = %s\n", + bufp, pr_ether(sap->sa_data)); +#endif + } + else /* If it's an hardware address */ + /* Get the hardware address */ + if(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)); +#endif + + return(0); +} + +/************************* MISC SUBROUTINES **************************/ + +/*------------------------------------------------------------------*/ +/* + */ +int +byte_size(int args) +{ + int ret = args & IW_PRIV_SIZE_MASK; + + if(((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_INT) || + ((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_FLOAT)) + ret <<= 2; + + if((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_NONE) + return 0; + + return ret; +} + diff --git a/wireless_tools/iwcommon.h b/wireless_tools/iwcommon.h new file mode 100644 index 0000000..cfdea27 --- /dev/null +++ b/wireless_tools/iwcommon.h @@ -0,0 +1,268 @@ +/* + * Wireless Tools + * + * Jean II - HPLB '99 + * + * Common header for the wireless tools... + */ + +#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] + */ + +/* ----------------------------- TODO ----------------------------- */ +/* + * One day, maybe... + * + * iwconfig : + * -------- + * Use new 802.11 parameters (rate, rts, frag)... + * + * iwpriv : + * ------ + * ? + * + * iwspy : + * ----- + * ? + * + * Doc & man pages : + * --------------- + * ? + */ + +/***************************** 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 :-( + * Please choose only one of the define... + */ +#define KER2_2_HEADERS /* Kernel 2.2.X + Glibc - ok for most people */ +#undef LINUX_HEADERS /* Kernel 2.0.X + Glibc - Debian 2.0, RH5 */ +#undef LIBC5_HEADERS /* Kernel 2.0.X + libc5 - old systems */ +#undef PRIVATE_HEADERS /* Ugly last resort case */ + +#ifdef KER2_2_HEADERS +#include +#include /* For ARPHRD_ETHER */ +#include /* For AF_INET & struct sockaddr */ +#include /* For struct sockaddr_in */ + +/* Wireless extensions */ +#include + +#endif /* KER2_2_HEADERS */ + +#ifdef LINUX_HEADERS +#include /* For ARPHRD_ETHER */ +#include /* For AF_INET & struct sockaddr */ +#include /* For struct sockaddr_in */ + +/* Wireless extensions */ +#include + +#endif /* LINUX_HEADERS */ + +#ifdef LIBC5_HEADERS +#include /* For AF_INET & struct sockaddr & socket() */ +#include /* For ARPHRD_ETHER */ +#include /* For struct sockaddr_in */ + +/* Wireless extensions */ +#include + +#endif /* LIBC5_HEADERS */ + +#ifdef PRIVATE_HEADERS +#include +#include +#include +#include "compat.h" /* Don't ask ! */ + +/* Wireless extensions */ +#include "wireless.h" + +#endif /* PRIVATE_HEADERS */ + + +/****************************** DEBUG ******************************/ + + +/************************ CONSTANTS & MACROS ************************/ + +/* Some usefull constants */ +#define KILO 1e3 +#define MEGA 1e6 +#define GIGA 1e9 + +/* Some hack */ +#ifndef IW_ESSID_MAX_SIZE +#define IW_ESSID_MAX_SIZE 32 /* Should be in wireless.h */ +#endif +#ifndef IW_MAX_AP +#define IW_MAX_AP 8 /* Should be in wireless.h */ +#endif + +/****************************** TYPES ******************************/ + +/* Shortcuts */ +typedef struct iw_statistics iwstats; +typedef struct iw_range iwrange; +typedef struct iw_freq iwfreq; +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; + int nwid_on; + u_long nwid; /* Network ID */ + int has_freq; + float freq; /* Frequency/channel */ + int has_sens; + int sens; /* sensitivity */ + int has_enc; + int enc_method; /* encoding method or off */ + long long enc_key; /* key used */ + 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; + long bitrate; /* Bit rate in bps */ + int bitrate_fixed; /* Fixed or auto */ + int has_rts; + long rts; /* RTS threshold in bytes */ + int rts_fixed; /* Fixed or auto */ + int has_frag; + long frag; /* Fragmentation threshold in bytes */ + int frag_fixed; /* Fixed or auto */ + + /* 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); +/* --------------------- 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 b/wireless_tools/iwconfig new file mode 100644 index 0000000000000000000000000000000000000000..abc90a675cda82df820057111a87965a5a944263 GIT binary patch literal 17427 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 literal 0 HcmV?d00001 diff --git a/wireless_tools/iwconfig.8 b/wireless_tools/iwconfig.8 index b2e3d60..24c1e50 100644 --- a/wireless_tools/iwconfig.8 +++ b/wireless_tools/iwconfig.8 @@ -13,7 +13,11 @@ iwconfig \- configure a wireless network interface .SH SYNOPSIS .BI "iwconfig [" interface ] .br -.BI "iwconfig " interface " [nwid " N "] [freq " F ] +.BI "iwconfig " interface " [essid " X "] [nwid " N "] [freq " F "] [channel " C ] +.br +.BI " [sens " S "] [enc " E "] [ap " A "] [nick " NN ] +.br +.BI " [rate " R "] [rts " RT "] [frag " FT ] .\" .\" DESCRIPTION part .\" @@ -38,16 +42,101 @@ device for details. .\" .SH PARAMETERS .TP -.B nwid -Set the Network ID (in some products it is also called Domain). As all -adjacent wireless networks share the same medium, this number is used -to differenciate them (create virtual networks). +.B essid +Set the ESSID (or Network Name - in some products it may also called +Domain ID). The ESSID is used to identify cells which are part of the +same virtual network. +.br +As opposed to the NWID which defines a single cell, the ESSID defines +a group of cell connected via repeaters or infrastructure, where the +user may roam. With some card, you may disable the ESSID checking +(ESSID promiscuous) with +.IR off " (and " on +to reenable it). +.TP +.BR nwid / domain +Set the Network ID (in some products it is also called Domain ID). As +all adjacent wireless networks share the same medium, this parameter +is used to differenciate them (create logical colocated networks) and +identify nodes belonguing to the same cell. With some card, you may +disable the Network ID checking (NWID promiscuous) with +.IR off " (and " on +to reenable it). .TP .BR freq / channel Set the operating frequency or channel in the device. Value below 1000 are the channel number, value over this is the frequency in Hz. You -may prepend the suffix k, M or G to the value (for example, "2.46G" -for 2.46 GHz frequency). +must prepend the suffix k, M or G to the value (for example, "2.46G" +for 2.46 GHz frequency), or add enough '0'. +.br +Channels are usually numbered starting at 1, +and you may use +.IR iwpriv (8) +to get the total number of channels and list the available +frequencies. Depending on regulations, some frequencies/channels may +not be available. +.TP +.B sens +Set the sensitivity threshold. This is the lowest signal level for +which we attempt a packet reception, signal lower than this are not +received. This is used to avoid receiving background noise, so you +should set it according to the average noise level. Positive values +are assumed to be the raw value used by the hardware or a percentage, +negative values are assumed to be dBm. +.br +With some hardware, this parameter also control the defer threshold +(lowest signal level for which we consider the channel busy) and the +handover threshold (lowest signal level where we stay associated with +the current access point). +.TP +.B enc +Set the encryption or scrambing key (the syntax is +.IR XXXX-XXXX-XXXX-XXXX " or " XXXXXXXX ). +Used also to control the encryption feature +.RI ( on / off ). +.TP +.B ap +Register to the Access Point given by the address, if it is +possible. When the quality of the connection goes too low, the driver +may revert back to automatic mode. +.TP +.BR nick [ name ] +Set the nickname, or the station name. Most 802.11 products do define +it, but this is not used as far as the protocols (MAC, IP, TCP) are +concerned and completely accessory as far as configuration goes. In +fact only some diagnostic tools may use it. +.TP +.BR rate / bit [ rate ] +For cards supporting multiple bit rates, set the bit-rate in b/s. The +bit-rate is the speed at which bits are transmitted over the medium, +the user speed of the link is lower due to medium sharing and +overhead. +.br +You must prepend the suffix k, M or G to the value (decimal multiplier +: 10^3, 10^6 and 10^9 b/s), or add enough '0'. Values below 1000 are +card specific, usually an index in the bit-rate list. Use +.I auto +to select the automatic bit-rate mode (fallback to lower rate on noisy +channels), which is the default for most cards, and +.I fixed +to revert back to fixed setting. +.TP +.BR rts [ _threshold ] +RTS/CTS adds a handshake before each packet transmission to make sure +that the channel is clear. This adds overhead, but increase +performance in case of hidden nodes or large number of active +nodes. This parameters set the size of the smallest packet for which +the node sends RTS, a value equal to the maximum packet size disable +the scheme. You may also set this parameter to +.IR auto ", " fixed " or " off . +.TP +.BR frag [ mentation_threshold ] +Fragmentation allow to split a IP packet in a burst of smaller +fragments transmitted on the medium. In most cases this adds overhead, +but in very noisy environment this reduce the error penalty. This +parameter set the maximum fragment size, a value equal to the maximum +packet size disable the scheme. You may also set this parameter to +.IR auto ", " fixed " or " off . .\" .\" DISPLAY part .\" @@ -57,10 +146,24 @@ For each device which support wireless extensions, will display the name of the .B MAC protocol used (name of device for proprietary protocols), the -.B NWID -and the +.B ESSID +(Network Name), the +.BR NWID , +the .B frequency -(if available). +(or channel), the +.BR sensitivity , +the +.B Access Point +address, the +.B bit-rate +(with +.B (f) +if fixed), the +.BR "RTS threshold" ", the " "fragmentation threshold" , +and the +.B encryption key +(depending on availability). See above for explanations. .PP If .I /proc/net/wireless diff --git a/wireless_tools/iwconfig.c b/wireless_tools/iwconfig.c index 33bc879..8cb9f0c 100644 --- a/wireless_tools/iwconfig.c +++ b/wireless_tools/iwconfig.c @@ -1,121 +1,47 @@ /* - * Hack my way... Jean II + * Wireless Tools + * + * Jean II - HPLB '99 + * + * Main code for "iwconfig". This is the generic tool for most + * manipulations... + * You need to link this code against "iwcommon.c" and "-lm". */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Some usefull constants */ -#define KILO 1e3 -#define MEGA 1e6 -#define GIGA 1e9 - -typedef struct iw_statistics iwstats; -typedef struct iw_range iwrange; - -/* Structure for storing all wireless information for each device */ -struct wireless_info -{ - char dev[IFNAMSIZ]; /* Interface name (device) */ - char name[12]; /* Wireless name */ - int has_nwid; - int nwid_on; - u_long nwid; /* Network ID */ - int has_freq; - u_long freq; /* Frequency/channel */ - - /* Stats */ - iwstats stats; - int has_stats; - iwrange range; - int has_range; -}; - -int skfd = -1; /* generic raw socket desc. */ -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 */ +#include "iwcommon.h" /* Header */ + +/************************* MISC SUBROUTINES **************************/ +/*------------------------------------------------------------------*/ +/* + * Print usage string + */ static void -usage(void) +iw_usage(void) { - fprintf(stderr, "Usage: iwconfig interface\n"); - fprintf(stderr, " [nwid NN]\n"); - fprintf(stderr, " [freq N.NN (add k, M or G) ]\n"); - fprintf(stderr, " [channel N]\n"); + fprintf(stderr, "Usage: iwconfig interface [essid {NN|on|off}]\n"); + fprintf(stderr, " [nwid {NN|on|off}]\n"); + fprintf(stderr, " [freq N.NNNN[k|M|G]]\n"); + fprintf(stderr, " [channel N]\n"); + fprintf(stderr, " [sens N]\n"); + fprintf(stderr, " [nick N]\n"); + fprintf(stderr, " [rate {N|auto|fixed}]\n"); + fprintf(stderr, " [rts {N|auto|fixed|off}]\n"); + fprintf(stderr, " [frag {N|auto|fixed|off}]\n"); + fprintf(stderr, " [enc NNNN-NNNN]\n"); exit(1); } -static void -print_info(struct wireless_info * info) -{ - /* Display device name */ - printf("%-8.8s ", info->dev); - - /* Display wireless name */ - printf("%s ", info->name); - - /* Display Network ID */ - if(info->has_nwid) - if(info->nwid_on) - printf("NWID:%lX ", info->nwid); - else - printf("NWID:off "); - - /* Display frequency / channel */ - if(info->has_freq) - if(info->freq < KILO) - printf("Channel:%g ", (double) info->freq); - else - if(info->freq > GIGA) - printf("Frequency:%gGHz ", info->freq / GIGA); - else - if(info->freq > MEGA) - printf("Frequency:%gMHz ", info->freq / MEGA); - else - printf("Frequency:%gkHz ", info->freq / KILO); - - printf("\n"); - - if(info->has_stats) - { - if(info->has_range) - printf(" Link quality:%d/%d Signal level:%d/%d Noise level:%d/%d\n", - info->stats.qual.qual, info->range.max_qual.qual, - info->stats.qual.level, info->range.max_qual.level, - info->stats.qual.noise, info->range.max_qual.noise); - else - printf(" Link quality:%d Signal level:%d Noise level:%d\n", - info->stats.qual.qual, - info->stats.qual.level, - info->stats.qual.noise); - - printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n", - info->stats.discard.nwid, - info->stats.discard.crypt, - info->stats.discard.misc); - } - - printf("\n"); -} +/************************* DISPLAY ROUTINES **************************/ -static int if_getstats(char *ifname, iwstats * stats) +/*------------------------------------------------------------------*/ +/* + * 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]; @@ -132,39 +58,42 @@ static int if_getstats(char *ifname, iwstats * stats) bp=strchr(bp,':'); bp++; bp = strtok(bp, " ."); - sscanf(bp, "%X", &stats->status); + sscanf(bp, "%X", (unsigned int *)&stats->status); bp = strtok(NULL, " ."); - sscanf(bp, "%d", &stats->qual.qual); + sscanf(bp, "%d", (unsigned int *)&stats->qual.qual); bp = strtok(NULL, " ."); - sscanf(bp, "%d", &stats->qual.level); + sscanf(bp, "%d", (unsigned int *)&stats->qual.level); bp = strtok(NULL, " ."); - sscanf(bp, "%d", &stats->qual.noise); + sscanf(bp, "%d", (unsigned int *)&stats->qual.noise); bp = strtok(NULL, " ."); sscanf(bp, "%d", &stats->discard.nwid); bp = strtok(NULL, " ."); - sscanf(bp, "%d", &stats->discard.crypt); + sscanf(bp, "%d", &stats->discard.code); bp = strtok(NULL, " ."); sscanf(bp, "%d", &stats->discard.misc); fclose(f); - return; + return 0; } } fclose(f); return 0; } -/* Get wireless informations & config from the device driver */ +/*------------------------------------------------------------------*/ +/* + * 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... + */ static int -get_info(char * ifname, +get_info(int skfd, + char * ifname, struct wireless_info * info) { struct iwreq wrq; memset((char *) info, 0, sizeof(struct wireless_info)); - /* Get device name */ - strcpy(info->dev, ifname); - /* Get wireless name */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0) @@ -187,31 +116,352 @@ get_info(char * ifname, if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0) { info->has_freq = 1; - info->freq = wrq.u.freq; + info->freq = freq2float(&(wrq.u.freq)); } - /* Get stats */ - if(if_getstats(ifname, &(info->stats)) == 0) + /* Get sensitivity */ + strcpy(wrq.ifr_name, ifname); + if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0) { - info->has_stats = 1; + info->has_sens = 1; + info->sens = wrq.u.sensitivity; } - /* Get ranges */ + /* Get encryption information */ + strcpy(wrq.ifr_name, ifname); + if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0) + { + info->has_enc = 1; + info->enc_method = wrq.u.encoding.method; + info->enc_key = wrq.u.encoding.code; + } + +#if WIRELESS_EXT > 5 + /* Get ESSID */ + strcpy(wrq.ifr_name, ifname); + wrq.u.data.pointer = (caddr_t) info->essid; + wrq.u.data.length = 0; + wrq.u.data.flags = 0; + if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0) + { + info->has_essid = 1; + info->essid_on = wrq.u.data.flags; + } + + /* Get AP address */ + strcpy(wrq.ifr_name, ifname); + if(ioctl(skfd, SIOCGIWAP, &wrq) >= 0) + { + info->has_ap_addr = 1; + memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr)); + } +#endif /* WIRELESS_EXT > 5 */ + +#if WIRELESS_EXT > 7 + /* Get NickName */ strcpy(wrq.ifr_name, ifname); - wrq.u.data.pointer = (caddr_t) &(info->range); + wrq.u.data.pointer = (caddr_t) info->nickname; wrq.u.data.length = 0; wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWRANGE, &wrq) >= 0) + if(ioctl(skfd, SIOCGIWNICKN, &wrq) >= 0) + if(wrq.u.data.length > 1) + info->has_nickname = 1; + + /* Get bit rate */ + strcpy(wrq.ifr_name, ifname); + if(ioctl(skfd, SIOCGIWRATE, &wrq) >= 0) + { + info->has_bitrate = 1; + info->bitrate_fixed = wrq.u.bitrate.fixed; + info->bitrate = wrq.u.bitrate.value; + } + + /* Get RTS threshold */ + strcpy(wrq.ifr_name, ifname); + if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0) + { + info->has_rts = 1; + info->rts_fixed = wrq.u.rts.fixed; + info->rts = wrq.u.rts.value; + } + + /* Get fragmentation thershold */ + strcpy(wrq.ifr_name, ifname); + if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0) + { + info->has_frag = 1; + info->frag_fixed = wrq.u.frag.fixed; + info->frag = wrq.u.frag.value; + } +#endif /* WIRELESS_EXT > 7 */ + + /* Get stats */ + if(iw_getstats(ifname, &(info->stats)) == 0) { - info->has_range = 1; + info->has_stats = 1; } + /* Get ranges */ + if(get_range_info(skfd, ifname, &(info->range)) >= 0) + info->has_range = 1; + return(0); } +/*------------------------------------------------------------------*/ +/* + * Print on the screen in a neat fashion all the info we have collected + * on a device. + */ +static void +display_info(struct wireless_info * info, + char * ifname) +{ + /* Display device name and wireless name (name of the protocol used) */ + printf("%-8.8s %s ", ifname, info->name); + + /* Display ESSID (extended network), if any */ + if(info->has_essid) + { + if(info->essid_on) + printf("ESSID:\"%s\" ", info->essid); + else + printf("ESSID:off "); + } + + /* Display NickName (station name), if any */ + if(info->has_nickname) + printf("Nickname:\"%s\"", info->nickname); + + /* Formatting */ + if(info->has_essid || info->has_nickname) + printf("\n "); + + /* Display Network ID */ + if(info->has_nwid) + { + /* Note : should display right number of digit according to info + * in range structure */ + if(info->nwid_on) + printf("NWID:%lX ", info->nwid); + else + printf("NWID:off/any "); + } + + /* Display frequency / channel */ + if(info->has_freq) + { + if(info->freq < KILO) + printf("Channel:%g ", info->freq); + else + { + if(info->freq >= GIGA) + printf("Frequency:%gGHz ", info->freq / GIGA); + else + { + if(info->freq >= MEGA) + printf("Frequency:%gMHz ", info->freq / MEGA); + else + printf("Frequency:%gkHz ", info->freq / KILO); + } + } + } + + /* Display sensitivity */ + if(info->has_sens) + { + if(info->has_range) + /* Display in dBm ? */ + if(info->sens < 0) + printf("Sensitivity:%d dBm ", info->sens); + else + printf("Sensitivity:%d/%d ", info->sens, info->range.sensitivity); + else + printf("Sensitivity:%d ", info->sens); + } + + /* Display the address of the current Access Point */ + if(info->has_ap_addr) + { + /* A bit of clever formatting */ + if((info->has_nwid + 2*info->has_freq + 2*info->has_sens + + !info->has_essid) > 3) + printf("\n "); + + printf("Access Point: %s", pr_ether(info->ap_addr.sa_data)); + } + + printf("\n "); + + /* Display the currently used/set bit-rate */ + if(info->has_bitrate) + { + printf("Bit Rate:"); + if(info->bitrate >= GIGA) + printf("%g Gb/s", info->bitrate / GIGA); + else + if(info->bitrate >= MEGA) + printf("%g Mb/s", info->bitrate / MEGA); + else + printf("%g kb/s", info->bitrate / KILO); + + /* Fixed ? */ + if(info->bitrate_fixed) + printf(" (f) "); + else + printf(" "); + } + + /* Display the RTS threshold */ + if(info->has_rts) + { + printf("RTS thr:%ld B", info->rts); + + /* Fixed ? */ + if(info->rts_fixed) + printf(" (f) "); + else + printf(" "); + } + + /* Display the fragmentation threshold */ + if(info->has_bitrate) + { + printf("Frag thr:%ld B", info->frag); + + /* Fixed ? */ + if(info->frag_fixed) + printf(" (f) "); + else + printf(" "); + } + + /* Formating */ + if((info->has_bitrate) || (info->has_rts) || (info->has_bitrate)) + printf("\n "); + + if(info->has_enc) + { + printf("Encryption key:"); + if(info->enc_method) + { + int i = 0; + u_short parts[4]; + long long key = info->enc_key; + + for(i = 3; i >= 0; i--) + { + parts[i] = key & 0xFFFF; + key >>= 16; + } + + i = 0; + while((parts[i] == 0) && (i < 3)) + i++; + for(; i < 3; i++) + printf("%.4X-", parts[i]); + printf("%.4X", parts[3]); + + if(info->enc_method > 1) + printf(" (%d)", info->enc_method); + printf("\n "); + } + else + printf("off\n "); + } + + if(info->has_stats) + { + if(info->has_range && (info->stats.qual.level != 0)) + /* If the statistics are in dBm */ + if(info->stats.qual.level > info->range.max_qual.level) + printf("Link quality:%d/%d Signal level:%d dBm Noise level:%d dBm\n", + info->stats.qual.qual, info->range.max_qual.qual, + info->stats.qual.level - 0x100, + info->stats.qual.noise - 0x100); + else + /* Statistics are relative values (0 -> max) */ + printf("Link quality:%d/%d Signal level:%d/%d Noise level:%d/%d\n", + info->stats.qual.qual, info->range.max_qual.qual, + info->stats.qual.level, info->range.max_qual.level, + info->stats.qual.noise, info->range.max_qual.noise); + else + /* We can't read the range, so we don't know... */ + printf("Link quality:%d Signal level:%d Noise level:%d\n", + info->stats.qual.qual, + info->stats.qual.level, + info->stats.qual.noise); + + printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n", + info->stats.discard.nwid, + info->stats.discard.code, + info->stats.discard.misc); + } + + printf("\n"); +} + +/*------------------------------------------------------------------*/ +/* + * Print on the screen in a neat fashion all the info we have collected + * on a device. + */ +static void +print_info(int skfd, + char * ifname) +{ + struct wireless_info info; + + if(get_info(skfd, ifname, &info) < 0) + { + fprintf(stderr, "%-8.8s no wireless extensions.\n\n", + ifname); + return; + } + + /* Display it ! */ + display_info(&info, ifname); +} + +/*------------------------------------------------------------------*/ +/* + * Get info on all devices and print it on the screen + */ +static void +print_devices(int skfd) +{ + char buff[1024]; + struct ifconf ifc; + struct ifreq *ifr; + int i; + + /* Get list of active devices */ + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) + { + fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); + return; + } + ifr = ifc.ifc_req; + + /* Print them */ + for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) + print_info(skfd, ifr->ifr_name); +} + +/************************* SETTING ROUTINES **************************/ +/*------------------------------------------------------------------*/ +/* + * Set the wireless options requested on command line + * This function is too long and probably should be split, + * because it look like the perfect definition of spaghetti code, + * but I'm way to lazy + */ static int -set_info(char * args[], /* Command line args */ +set_info(int skfd, /* The socket */ + char * args[], /* Command line args */ int count, /* Args count */ char * ifname) /* Dev name */ { @@ -221,21 +471,41 @@ set_info(char * args[], /* Command line args */ /* Set dev name */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + /* if nothing after the device name */ + if(count<1) + iw_usage(); + /* The other args on the line specify options to be set... */ for(i = 0; i < count; i++) { - /* Set network ID */ - if(!strcmp(args[i], "nwid")) + /* ---------- Set network ID ---------- */ + if((!strcasecmp(args[i], "nwid")) || + (!strcasecmp(args[i], "domain"))) { - if(++i >= count) - usage(); - if(!strcasecmp(args[i], "off")) + i++; + if(i >= count) + iw_usage(); + if((!strcasecmp(args[i], "off")) || + (!strcasecmp(args[i], "any"))) wrq.u.nwid.on = 0; else - if(sscanf(args[i], "%lX", &(wrq.u.nwid.nwid)) != 1) - usage(); + if(!strcasecmp(args[i], "on")) + { + /* Get old nwid */ + if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0) + { + fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno)); + return(-1); + } + strcpy(wrq.ifr_name, ifname); + wrq.u.nwid.on = 1; + } else - wrq.u.nwid.on = 1; + if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.nwid)) + != 1) + iw_usage(); + else + wrq.u.nwid.on = 1; if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0) { @@ -245,133 +515,356 @@ set_info(char * args[], /* Command line args */ continue; } - /* Set frequency / channel */ + /* ---------- Set frequency / channel ---------- */ if((!strncmp(args[i], "freq", 4)) || (!strcmp(args[i], "channel"))) { + double freq; + + if(++i >= count) + iw_usage(); + if(sscanf(args[i], "%lg", &(freq)) != 1) + iw_usage(); + if(index(args[i], 'G')) freq *= GIGA; + if(index(args[i], 'M')) freq *= MEGA; + if(index(args[i], 'k')) freq *= KILO; + + float2freq(freq, &(wrq.u.freq)); + + if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); + return(-1); + } + continue; + } + + /* ---------- Set sensitivity ---------- */ + if(!strncmp(args[i], "sens", 4)) + { + if(++i >= count) + iw_usage(); + if(sscanf(args[i], "%d", &(wrq.u.sensitivity)) != 1) + iw_usage(); + + if(ioctl(skfd, SIOCSIWSENS, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWSENS: %s\n", strerror(errno)); + return(-1); + } + continue; + } + + /* ---------- Set encryption stuff ---------- */ + if(!strncmp(args[i], "enc", 3 )) + { + unsigned long long key = 0; + if(++i >= count) + iw_usage(); + + if(!strcasecmp(args[i], "off")) + wrq.u.encoding.method = 0; + else + { + if(!strcasecmp(args[i], "on")) + { + /* Get old encryption information */ + if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0) + { + fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); + return(-1); + } + strcpy(wrq.ifr_name, ifname); + } + else + { + char * buff; + char * p; + u_long temp; + + p = buff = malloc(strlen(args[i] + 1)); + strcpy(buff, args[i]); + + p = strtok(buff, "-:;.,*#"); + while(p != (char *) NULL) + { + key = key << 16; + if(sscanf(p, "%lX", &temp) != 1) + iw_usage(); + key += temp; + p = strtok((char *) NULL, "-:;.,*#"); + } + + free(buff); + wrq.u.encoding.code = key; + } + /* TODO : check for "(method)" in args list */ + wrq.u.encoding.method = 1; + } + + if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0) { - struct iw_range range; - int k; + fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", + errno, strerror(errno)); + return(-1); + } + continue; + } + +#if WIRELESS_EXT > 5 + /* ---------- Set ESSID ---------- */ + if(!strcasecmp(args[i], "essid")) + { + char essid[IW_ESSID_MAX_SIZE + 1]; - wrq.u.data.pointer = (caddr_t) ⦥ - wrq.u.data.length = 0; + i++; + if(i >= count) + iw_usage(); + if((!strcasecmp(args[i], "off")) || + (!strcasecmp(args[i], "any"))) + { wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0) + essid[0] = '\0'; + } + else + if(!strcasecmp(args[i], "on")) + { + /* Get old essid */ + wrq.u.data.pointer = (caddr_t) essid; + wrq.u.data.length = 0; + wrq.u.data.flags = 0; + if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0) + { + fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno)); + return(-1); + } + strcpy(wrq.ifr_name, ifname); + wrq.u.data.flags = 1; + } + else + if(strlen(args[i]) > IW_ESSID_MAX_SIZE) { - fprintf(stderr, "SIOCGIWRANGE: %s\n", strerror(errno)); - return(-1); + fprintf(stderr, "ESSID too long (max %d): ``%s''\n", + IW_ESSID_MAX_SIZE, args[i]); + iw_usage(); } + else + { + wrq.u.data.flags = 1; + strcpy(essid, args[i]); + } + + wrq.u.data.pointer = (caddr_t) essid; + wrq.u.data.length = strlen(essid) + 1; + if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno)); + return(-1); + } + continue; + } + + /* ---------- Set AP address ---------- */ + if(!strcasecmp(args[i], "ap")) + { + if(++i >= count) + iw_usage(); - printf("%d channels ; available frequencies :", - range.num_channels); - for(k = 0; k < range.num_frequency; k++) - if(range.freq[k] > GIGA) - printf(" %gGHz ", range.freq[k] / GIGA); - else - if(range.freq[k] > MEGA) - printf(" %gMHz ", range.freq[k] / MEGA); - else - printf(" %gkHz ", range.freq[k] / KILO); - printf("\n"); - return; /* no more arg */ + /* Check if we have valid address types */ + if(check_addr_type(skfd, ifname) < 0) + { + fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname); + return(-1); } - if(sscanf(args[i], "%g", &(wrq.u.freq)) != 1) - usage(); - if(index(args[i], 'G')) wrq.u.freq *= GIGA; - if(index(args[i], 'M')) wrq.u.freq *= MEGA; - if(index(args[i], 'k')) wrq.u.freq *= KILO; + /* Get the address */ + if(in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0) + iw_usage(); - if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0) + if(ioctl(skfd, SIOCSIWAP, &wrq) < 0) { - fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); + fprintf(stderr, "SIOCSIWAP: %s\n", strerror(errno)); return(-1); } continue; } +#endif /* WIRELESS_EXT > 5 */ - /* Here we have an unrecognised arg... */ - fprintf(stderr, "Invalid argument : %s\n", args[i]); - usage(); - return(-1); - } /* for(index ... */ - return(0); -} +#if WIRELESS_EXT > 7 + /* ---------- Set NickName ---------- */ + if(!strncmp(args[i], "nick", 4)) + { + i++; + if(i >= count) + iw_usage(); + 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(); + } -static void -print_devices(char *ifname) -{ - char buff[1024]; - struct wireless_info info; - struct ifconf ifc; - struct ifreq *ifr; - int i; + wrq.u.data.pointer = (caddr_t) args[i]; + wrq.u.data.length = strlen(args[i]) + 1; + if(ioctl(skfd, SIOCSIWNICKN, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWNICKN: %s\n", strerror(errno)); + return(-1); + } + continue; + } - if(ifname == (char *)NULL) - { - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) + /* ---------- Set Bit-Rate ---------- */ + if((!strncmp(args[i], "bit", 3)) || + (!strcmp(args[i], "rate"))) { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); - return; + i++; + if(i >= count) + iw_usage(); + if(!strcasecmp(args[i], "auto")) + { + wrq.u.bitrate.value = -1; + wrq.u.bitrate.fixed = 0; + } + else + { + if(!strcasecmp(args[i], "fixed")) + { + /* Get old bitrate */ + if(ioctl(skfd, SIOCGIWRATE, &wrq) < 0) + { + fprintf(stderr, "SIOCGIWRATE: %s\n", strerror(errno)); + return(-1); + } + strcpy(wrq.ifr_name, ifname); + } + else /* Should be a numeric value */ + { + double brate; + + if(sscanf(args[i], "%lg", &(brate)) != 1) + iw_usage(); + if(index(args[i], 'G')) brate *= GIGA; + if(index(args[i], 'M')) brate *= MEGA; + if(index(args[i], 'k')) brate *= KILO; + wrq.u.bitrate.value = (long) brate; + } + wrq.u.bitrate.fixed = 1; + } + + if(ioctl(skfd, SIOCSIWRATE, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWRATE: %s\n", strerror(errno)); + return(-1); + } + continue; } - ifr = ifc.ifc_req; - for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) + /* ---------- Set RTS threshold ---------- */ + if(!strncmp(args[i], "rts", 3)) { - if(get_info(ifr->ifr_name, &info) < 0) + i++; + if(i >= count) + iw_usage(); + if(!strcasecmp(args[i], "auto")) { - /* Could skip this message ? */ - fprintf(stderr, "%-8.8s no wireless extensions.\n\n", - ifr->ifr_name); - continue; + wrq.u.rts.value = -1; + wrq.u.rts.fixed = 0; + } + else + { + if(!strcasecmp(args[i], "fixed")) + { + /* Get old RTS threshold */ + if(ioctl(skfd, SIOCGIWRTS, &wrq) < 0) + { + fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno)); + return(-1); + } + strcpy(wrq.ifr_name, ifname); + } + else + if(!strcasecmp(args[i], "off")) + wrq.u.rts.value = -1; /* i.e. max size */ + else /* Should be a numeric value */ + if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value)) + != 1) + iw_usage(); + + wrq.u.rts.fixed = 1; } - print_info(&info); + if(ioctl(skfd, SIOCSIWRTS, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWRTS: %s\n", strerror(errno)); + return(-1); + } + continue; } - } - else - { - if(get_info(ifname, &info) < 0) + + /* ---------- Set fragmentation threshold ---------- */ + if(!strncmp(args[i], "frag", 4)) { - fprintf(stderr, "%s: no wireless extensions.\n", - ifname); - usage(); + i++; + if(i >= count) + iw_usage(); + if(!strcasecmp(args[i], "auto")) + { + wrq.u.frag.value = -1; + wrq.u.frag.fixed = 0; + } + else + { + if(!strcasecmp(args[i], "fixed")) + { + /* Get old fragmentation threshold */ + if(ioctl(skfd, SIOCGIWFRAG, &wrq) < 0) + { + fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno)); + return(-1); + } + strcpy(wrq.ifr_name, ifname); + } + else + if(!strcasecmp(args[i], "off")) + wrq.u.frag.value = -1; /* i.e. max size */ + else /* Should be a numeric value */ + if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.frag.value)) + != 1) + iw_usage(); + + wrq.u.frag.fixed = 1; + } + + if(ioctl(skfd, SIOCSIWFRAG, &wrq) < 0) + { + fprintf(stderr, "SIOCSIWFRAG: %s\n", strerror(errno)); + return(-1); + } + continue; } - else - print_info(&info); - } +#endif /* WIRELESS_EXT > 7 */ + + /* Here we have an unrecognised arg... */ + fprintf(stderr, "Invalid argument : %s\n", args[i]); + iw_usage(); + return(-1); + } /* for(index ... */ + return(0); } +/******************************* MAIN ********************************/ -static int sockets_open() -{ - 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; -} - +/*------------------------------------------------------------------*/ +/* + * The main ! + */ int main(int argc, char ** argv) { + int skfd = -1; /* generic raw socket desc. */ int goterr = 0; /* Create a channel to the NET kernel. */ @@ -384,7 +877,16 @@ main(int argc, /* No argument : show the list of all device + info */ if(argc == 1) { - print_devices((char *)NULL); + print_devices(skfd); + close(skfd); + exit(0); + } + + /* Special case for help... */ + if((!strncmp(argv[1], "-h", 9)) || + (!strcmp(argv[1], "--help"))) + { + iw_usage(); close(skfd); exit(0); } @@ -392,16 +894,18 @@ main(int argc, /* The device name must be the first argument */ if(argc == 2) { - print_devices(argv[1]); + print_info(skfd, argv[1]); close(skfd); exit(0); } /* The other args on the line specify options to be set... */ - goterr = set_info(argv + 2, argc - 2, argv[1]); + goterr = set_info(skfd, argv + 2, argc - 2, argv[1]); /* Close the socket. */ close(skfd); return(goterr); } + + diff --git a/wireless_tools/iwpriv b/wireless_tools/iwpriv new file mode 100644 index 0000000000000000000000000000000000000000..4657f6723c9980adfd6f1affcd38ccc7178a89c2 GIT binary patch literal 12673 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 Orw3+a<>d}eQvP4(kq7z! literal 0 HcmV?d00001 diff --git a/wireless_tools/iwpriv.8 b/wireless_tools/iwpriv.8 new file mode 100644 index 0000000..8acc2e8 --- /dev/null +++ b/wireless_tools/iwpriv.8 @@ -0,0 +1,113 @@ +.\" Jean II - HPLB - 96 +.\" iwpriv.8 +.\" +.TH IWPRIV 8 "31 October 1996" "net-tools" "Linux Programmer's Manual" +.\" +.\" NAME part +.\" +.SH NAME +iwpriv \- configure optionals (private) parameters of a wireless +network interface +.\" +.\" SYNOPSIS part +.\" +.SH SYNOPSIS +.BI "iwpriv [" interface ] +.br +.BI "iwpriv " interface " " private-command " [" private-parameters ] +.br +.BI "iwpriv " interface " roam " {on,off} +.br +.BI "iwpriv " interface " port " [ N ] +.\" +.\" DESCRIPTION part +.\" +.SH DESCRIPTION +.B Iwpriv +is the companion tool to +.IR iwconfig (8). +.B Iwpriv +deals with parameters and setting specific to each driver (as opposed to +.I iwconfig +which deals with generic ones) and a few commands that doesn't fit well in +.I iwconfig +(like listing the available frequencies). +.PP +Without any argument, +.B iwpriv +list the available private commands available on each interface, and +the parameters that they require. Using this information, the user may +apply those interface specific commands on the specified interface. +.PP +In theory, the documentation of each device driver should indicate how +to use those interface specific commands and their effect. +.\" +.\" PARAMETER part +.\" +.SH PARAMETERS +.TP +.B roam +Enable or disable roaming, if supported. Call the private command +.IR setroam . +Found in the +.I wavelan_cs +driver. +.TP +.B port +Read or configure the port type. Call the private commands +.IR gport_type " and " sport_type . +Found in the +.IR wavelan2_cs " and " wvlan_cs " drivers." +.TP +.I private-command +Execute the specified +.I private-command +on the interface. The command may take or require arguments, and may +display information. Refer to the device driver documentation for +information on how to use and the effect. +.\" +.\" DISPLAY part +.\" +.SH DISPLAY +For each device which support private commands, +.I iwpriv +will display the list of private commands available. +.PP +This include the name of the private command, the number or arguments +that may be set and their type, and the number or arguments that may +be display and their type. +.PP +For example, you may have the following display : +.br +.B "eth0 Available private ioctl :" +.br +.B " setqualthr (89F0) : set 1 byte & get 0" +.br +.B " gethisto (89F7) : set 0 & get 16 int" +.PP +This indicate that you may set the quality threshold and display an +histogram of up to 16 values with the following commands : +.br +.I " iwpriv eth0 setqualthr 20" +.br +.I " iwpriv eth0 gethisto" +.\" +.\" AUTHOR part +.\" +.SH AUTHOR +Jean Tourrilhes \- jt@hplb.hpl.hp.com +.\" +.\" FILES part +.\" +.SH FILES +.I /proc/net/wireless +.\" +.\" SEE ALSO part +.\" +.SH SEE ALSO +.BR ifconfig (8), +.BR iwconfig (8), +.BR iwspy (8), +.BR wavelan (4), +.BR wavelan_cs (4), +.BR xircnw_cs (4). diff --git a/wireless_tools/iwpriv.c b/wireless_tools/iwpriv.c index 32034ba..3e22f4b 100644 --- a/wireless_tools/iwpriv.c +++ b/wireless_tools/iwpriv.c @@ -1,230 +1,524 @@ /* - * Warning : this program need wireless extensions... + * Wireless Tools + * + * Jean II - HPLB '99 + * + * Main code for "iwconfig". This is the generic tool for most + * manipulations... + * You need to link this code against "iwcommon.c" and "-lm". */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int skfd = -1; /* generic raw socket desc. */ -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 */ - -static int sockets_open() + +#include "iwcommon.h" /* Header */ + +/************************* MISC SUBROUTINES **************************/ + +/*------------------------------------------------------------------*/ +/* + * Print usage string + */ +static void +iw_usage(void) { - 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; + fprintf(stderr, "Usage: iwpriv interface [private-command [private-arguments]]\n"); + fprintf(stderr, " interface [roam {on|off}]\n"); + fprintf(stderr, " interface [port [n]]\n"); + exit(1); } -int -byte_size(args) +/************************ GENERIC FUNCTIONS *************************/ + +/*------------------------------------------------------------------*/ +/* + * Print on the screen in a neat fashion all the info we have collected + * on a device. + */ +static void +print_priv_info(int skfd, + char * ifname) { - int ret = args & IW_PRIV_SIZE_MASK; + int k; + iwprivargs priv[16]; + int n; + char * argtype[] = { " ", "byte", "char", "", "int", "float" }; - if(((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_INT) || - ((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_FLOAT)) - ret <<= 2; + /* Read the private ioctls */ + n = get_priv_info(skfd, ifname, priv); + + /* Is there any ? */ + if(n <= 0) + { + /* Could skip this message ? */ + fprintf(stderr, "%-8.8s no private ioctls.\n\n", + ifname); + } + else + { + printf("%-8.8s Available private ioctl :\n", ifname); + /* Print the all */ + for(k = 0; k < n; k++) + printf(" %s (%X) : set %3d %s & get %3d %s\n", + priv[k].name, priv[k].cmd, + priv[k].set_args & IW_PRIV_SIZE_MASK, + argtype[(priv[k].set_args & IW_PRIV_TYPE_MASK) >> 12], + priv[k].get_args & IW_PRIV_SIZE_MASK, + argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]); + printf("\n"); + } +} - if((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_NONE) - return 0; +/*------------------------------------------------------------------*/ +/* + * Get info on all devices and print it on the screen + */ +static void +print_priv_devices(int skfd) +{ + char buff[1024]; + struct ifconf ifc; + struct ifreq *ifr; + int i; + + /* Get list of active devices */ + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) + { + fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); + return; + } + ifr = ifc.ifc_req; - return ret; + /* Print them */ + for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) + print_priv_info(skfd, ifr->ifr_name); } -int -main(int argc, - char ** argv) +/************************* SETTING ROUTINES **************************/ + +/*------------------------------------------------------------------*/ +/* + * Execute a private command on the interface + */ +static int +set_private(int skfd, /* Socket */ + char * args[], /* Command line args */ + int count, /* Args count */ + char * ifname) /* Dev name */ { + u_char buffer[1024]; struct iwreq wrq; - char * ifname = argv[1]; - struct iw_priv_args priv[16]; - int k; + int i = 0; /* Start with first arg */ + int k; + iwprivargs priv[16]; + int number; - if(argc < 2) - exit(0); + /* Read the private ioctls */ + number = get_priv_info(skfd, ifname, priv); - /* Create a channel to the NET kernel. */ - if((skfd = sockets_open()) < 0) + /* Is there any ? */ + if(number <= 0) { - perror("socket"); - exit(-1); + /* Could skip this message ? */ + fprintf(stderr, "%-8.8s no private ioctls.\n\n", + ifname); + return(-1); } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - wrq.u.data.pointer = (caddr_t) priv; - wrq.u.data.length = 0; - wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWPRIV, &wrq) < 0) + /* Search the correct ioctl */ + k = -1; + while((++k < number) && strcmp(priv[k].name, args[i])); + + /* If not found... */ + if(k == number) { - fprintf(stderr, "Interface doesn't provide private interface info...\n"); - fprintf(stderr, "SIOCGIWPRIV: %s\n", strerror(errno)); + fprintf(stderr, "Invalid command : %s\n", args[i]); return(-1); } + + /* Next arg */ + i++; - /* If no args... */ - if(argc < 3) + /* If we have to set some data */ + if((priv[k].set_args & IW_PRIV_TYPE_MASK) && + (priv[k].set_args & IW_PRIV_SIZE_MASK)) { - char * argtype[] = { " ", "byte", "char", "", "int", "float" }; + switch(priv[k].set_args & IW_PRIV_TYPE_MASK) + { + case IW_PRIV_TYPE_BYTE: + /* Number of args to fetch */ + wrq.u.data.length = count - 1; + if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) + 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)); + break; + + case IW_PRIV_TYPE_INT: + /* Number of args to fetch */ + wrq.u.data.length = count - 1; + if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) + 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", ((u_int *) buffer) + i - 1); + break; + + case IW_PRIV_TYPE_CHAR: + if(i < count) + { + /* Size of the string to fetch */ + wrq.u.data.length = strlen(args[i]) + 1; + if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) + wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; - printf("Available private ioctl :\n"); - for(k = 0; k < wrq.u.data.length; k++) - printf("%s (%lX) : set %3d %s & get %3d %s\n", - priv[k].name, priv[k].cmd, - priv[k].set_args & IW_PRIV_SIZE_MASK, - argtype[(priv[k].set_args & IW_PRIV_TYPE_MASK) >> 12], - priv[k].get_args & IW_PRIV_SIZE_MASK, - argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]); + /* Fetch string */ + memcpy(buffer, args[i], wrq.u.data.length); + buffer[sizeof(buffer) - 1] = '\0'; + i++; + } + else + { + wrq.u.data.length = 1; + buffer[0] = '\0'; + } + break; + + default: + fprintf(stderr, "Not yet implemented...\n"); + return(-1); + } + + if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && + (wrq.u.data.length != (priv[k].set_args & IW_PRIV_SIZE_MASK))) + { + printf("The command %s need exactly %d argument...\n", + priv[k].name, priv[k].set_args & IW_PRIV_SIZE_MASK); + return(-1); + } + } /* if args to set */ + else + { + wrq.u.data.length = 0L; } + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + + if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && + (byte_size(priv[k].set_args) < IFNAMSIZ)) + memcpy(wrq.u.name, buffer, IFNAMSIZ); else { - u_char buffer[1024]; + wrq.u.data.pointer = (caddr_t) buffer; + wrq.u.data.flags = 0; + } - /* Seach the correct ioctl */ - k = -1; - while((++k < wrq.u.data.length) && strcmp(priv[k].name, argv[2])) - ; - /* If not found... */ - if(k == wrq.u.data.length) - fprintf(stderr, "Invalid argument : %s\n", argv[2]); - - /* If we have to set some data */ - if((priv[k].set_args & IW_PRIV_TYPE_MASK) && - (priv[k].set_args & IW_PRIV_SIZE_MASK)) - { - int i; + /* Perform the private ioctl */ + if(ioctl(skfd, priv[k].cmd, &wrq) < 0) + { + fprintf(stderr, "Interface doesn't accept private ioctl...\n"); + fprintf(stderr, "%X: %s\n", priv[k].cmd, strerror(errno)); + return(-1); + } - /* Warning : we may have no args to set... */ + /* If we have to get some data */ + if((priv[k].get_args & IW_PRIV_TYPE_MASK) && + (priv[k].get_args & IW_PRIV_SIZE_MASK)) + { + int j; + int n = 0; /* number of args */ - switch(priv[k].set_args & IW_PRIV_TYPE_MASK) - { - case IW_PRIV_TYPE_BYTE: - /* Number of args to fetch */ - wrq.u.data.length = argc - 3; - if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) - wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; + printf("%-8.8s %s:", ifname, priv[k].name); - /* Fetch args */ - for(i = 0; i < wrq.u.data.length; i++) - sscanf(argv[i + 3], "%d", buffer + i); - break; + if((priv[k].get_args & IW_PRIV_SIZE_FIXED) && + (byte_size(priv[k].get_args) < IFNAMSIZ)) + { + memcpy(buffer, wrq.u.name, IFNAMSIZ); + n = priv[k].get_args & IW_PRIV_SIZE_MASK; + } + else + n = wrq.u.data.length; - case IW_PRIV_TYPE_INT: - /* Number of args to fetch */ - wrq.u.data.length = argc - 3; - if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) - wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; + switch(priv[k].get_args & IW_PRIV_TYPE_MASK) + { + case IW_PRIV_TYPE_BYTE: + /* Display args */ + for(j = 0; j < n; j++) + printf("%d ", buffer[j]); + printf("\n"); + break; + + case IW_PRIV_TYPE_INT: + /* Display args */ + for(j = 0; j < n; j++) + printf("%d ", ((u_int *) buffer)[i]); + printf("\n"); + break; + + case IW_PRIV_TYPE_CHAR: + /* Display args */ + buffer[wrq.u.data.length - 1] = '\0'; + printf("%s\n", buffer); + break; + + default: + fprintf(stderr, "Not yet implemented...\n"); + return(-1); + } + } /* if args to set */ - /* Fetch args */ - for(i = 0; i < wrq.u.data.length; i++) - sscanf(argv[i + 3], "%d", ((u_int *) buffer) + i); - break; + return(0); +} - default: - fprintf(stderr, "Not yet implemented...\n"); - return(-1); - } +/********************** PRIVATE IOCTLS MANIPS ***********************/ +/* + * Convenient access to some private ioctls of some devices + */ - if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && - (wrq.u.data.length != (priv[k].set_args & IW_PRIV_SIZE_MASK))) - { - printf("The command %s need exactly %d argument...\n", - priv[k].name, priv[k].set_args & IW_PRIV_SIZE_MASK); - return(-1); - } - } /* if args to set */ - else +/*------------------------------------------------------------------*/ +/* + * Set roaming mode on and off + * Found in wavelan_cs driver + */ +static int +set_roaming(int skfd, /* Socket */ + char * args[], /* Command line args */ + int count, /* Args count */ + char * ifname) /* Dev name */ +{ + u_char buffer[1024]; + struct iwreq wrq; + int i = 0; /* Start with first arg */ + int k; + iwprivargs priv[16]; + int number; + char RoamState; /* buffer to hold new roam state */ + char ChangeRoamState=0; /* whether or not we are going to + change roam states */ + + /* Read the private ioctls */ + number = get_priv_info(skfd, ifname, priv); + + /* Is there any ? */ + if(number <= 0) + { + /* Could skip this message ? */ + fprintf(stderr, "%-8.8s no private ioctls.\n\n", + ifname); + return(-1); + } + + if(count != 1) + iw_usage(); + + if(!strcasecmp(args[i], "on")) + { + printf("%-8.8s enable roaming\n", ifname); + if(!number) { - wrq.u.data.length = 0L; + fprintf(stderr, "This device doesn't support roaming\n"); + return(-1); + } + ChangeRoamState=1; + RoamState=1; + } + else + if(!strcasecmp(args[i], "off")) + { + i++; + printf("%-8.8s disable roaming\n", ifname); + if(!number) + { + fprintf(stderr, "This device doesn't support roaming\n"); + return(-1); + } + ChangeRoamState=1; + RoamState=0; + } + else + { + iw_usage(); + return(-1); + } + + if(ChangeRoamState) + { + k = -1; + while((++k < number) && strcmp(priv[k].name, "setroam")); + if(k == number) + { + fprintf(stderr, "This device doesn't support roaming\n"); + return(-1); } - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && - (byte_size(priv[k].set_args) < IFNAMSIZ)) - memcpy(wrq.u.name, buffer, IFNAMSIZ); - else + buffer[0]=RoamState; + + memcpy(wrq.u.name, &buffer, IFNAMSIZ); + + if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { - wrq.u.data.pointer = (caddr_t) buffer; - wrq.u.data.flags = 0; + fprintf(stderr, "Roaming support is broken.\n"); + exit(0); } + } + i++; - if(ioctl(skfd, priv[k].cmd, &wrq) < 0) + return(i); +} + +/*------------------------------------------------------------------*/ +/* + * Get and set the port type + * Found in wavelan2_cs and wvlan_cs drivers + */ +static int +port_type(int skfd, /* Socket */ + char * args[], /* Command line args */ + int count, /* Args count */ + char * ifname) /* Dev name */ +{ + struct iwreq wrq; + int i = 0; /* Start with first arg */ + int k; + iwprivargs priv[16]; + int number; + char ptype = 0; + + /* Read the private ioctls */ + number = get_priv_info(skfd, ifname, priv); + + /* Is there any ? */ + if(number <= 0) + { + /* Could skip this message ? */ + fprintf(stderr, "%-8.8s no private ioctls.\n\n", ifname); + return(-1); + } + + /* Arguments ? */ + if(count == 0) + { + /* So, we just want to see the current value... */ + k = -1; + while((++k < number) && strcmp(priv[k].name, "gport_type")); + if(k == number) { - fprintf(stderr, "Interface doesn't accept private ioctl...\n"); - fprintf(stderr, "%X: %s\n", priv[k].cmd, strerror(errno)); + fprintf(stderr, "This device doesn't support getting port type\n"); return(-1); } + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - /* If we have to get some data */ - if((priv[k].get_args & IW_PRIV_TYPE_MASK) && - (priv[k].get_args & IW_PRIV_SIZE_MASK)) + /* Get it */ + if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { - int i; - int n; /* number of args */ + fprintf(stderr, "Port type support is broken.\n"); + exit(0); + } + ptype = *wrq.u.name; - if((priv[k].get_args & IW_PRIV_SIZE_FIXED) && - (byte_size(priv[k].get_args) < IFNAMSIZ)) - { - memcpy(buffer, wrq.u.name, IFNAMSIZ); - n = priv[k].get_args & IW_PRIV_SIZE_MASK; - } - else - n = wrq.u.data.length; + /* Display it */ + printf("%-8.8s Port type is %d.\n\n", ifname, ptype); - switch(priv[k].get_args & IW_PRIV_TYPE_MASK) - { - case IW_PRIV_TYPE_BYTE: - /* Display args */ - for(i = 0; i < n; i++) - printf("%d ", buffer[i]); - printf("\n"); - break; - - case IW_PRIV_TYPE_INT: - /* Display args */ - for(i = 0; i < n; i++) - printf("%d ", ((u_int *) buffer)[i]); - printf("\n"); - break; - - default: - fprintf(stderr, "Not yet implemented...\n"); - return(-1); - } + return(0); + } + + if(count != 1) + iw_usage(); + + /* Read it */ + if(sscanf(args[i], "%d", (int *) &ptype) != 1) + iw_usage(); + + k = -1; + while((++k < number) && strcmp(priv[k].name, "sport_type")); + if(k == number) + { + fprintf(stderr, "This device doesn't support setting port type\n"); + return(-1); + } + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + + *(wrq.u.name) = ptype; + + if(ioctl(skfd, priv[k].cmd, &wrq) < 0) + { + fprintf(stderr, "Invalid port type\n"); + exit(0); + } + + i++; + return(i); +} + +/******************************* MAIN ********************************/ + +/*------------------------------------------------------------------*/ +/* + * The main ! + */ +int +main(int argc, + char ** argv) +{ + int skfd = -1; /* generic raw socket desc. */ + int goterr = 0; + + /* Create a channel to the NET kernel. */ + if((skfd = sockets_open()) < 0) + { + perror("socket"); + exit(-1); + } + + /* No argument : show the list of all device + info */ + if(argc == 1) + { + print_priv_devices(skfd); + close(skfd); + exit(0); + } - } /* if args to set */ + /* Special cases take one... */ + /* Help */ + if((!strncmp(argv[1], "-h", 9)) || + (!strcmp(argv[1], "--help"))) + { + iw_usage(); + close(skfd); + exit(0); + } + + /* The device name must be the first argument */ + /* Name only : show for that device only */ + if(argc == 2) + { + print_priv_info(skfd, argv[1]); + close(skfd); + exit(0); + } + + /* Special cases take two... */ + /* Roaming */ + if(!strncmp(argv[2], "roam", 4)) + { + goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]); + close(skfd); + exit(0); + } + + /* Port type */ + if(!strncmp(argv[2], "port", 4)) + { + goterr = port_type(skfd, argv + 3, argc - 3, argv[1]); + close(skfd); + exit(0); + } - } /* if ioctl list else ioctl exec */ + /* Otherwise, it's a private ioctl */ + goterr = set_private(skfd, argv + 2, argc - 2, argv[1]); /* Close the socket. */ close(skfd); diff --git a/wireless_tools/iwspy b/wireless_tools/iwspy new file mode 100644 index 0000000000000000000000000000000000000000..f8577162d4bef6513fd782a9d2f468e92a826597 GIT binary patch literal 13793 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "support.h" - -int skfd = -1; /* generic raw socket desc. */ -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 */ - -static int sockets_open() + +#include "iwcommon.h" /* Header */ + +/************************* DISPLAY ROUTINES **************************/ + +/*------------------------------------------------------------------*/ +/* + * Display the spy list of addresses and the associated stats + */ +static void +print_spy_info(int skfd, + char * ifname) { - 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; + struct iwreq wrq; + char buffer[(sizeof(struct iw_quality) + + sizeof(struct sockaddr)) * IW_MAX_SPY]; + struct sockaddr hwa[IW_MAX_SPY]; + struct iw_quality qual[IW_MAX_SPY]; + iwrange range; + int has_range = 0; + int n; + 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.flags = 0; + if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0) + { + fprintf(stderr, "%-8.8s Interface doesn't support wireless statistic collection\n\n", ifname); + return; + } + + /* Number of addresses */ + n = wrq.u.data.length; + + + + /* Check if we have valid address types */ + if(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) + has_range = 1; + + /* Display it */ + if(n == 0) + printf("%-8.8s No statistics to collect\n", ifname); + else + printf("%-8.8s Statistics collected:\n", ifname); + + /* The two lists */ + + memcpy(hwa, buffer, n * sizeof(struct sockaddr)); + memcpy(qual, buffer + n*sizeof(struct sockaddr), n*sizeof(struct iw_quality)); + + for(i = 0; i < n; i++) + { + if(has_range && (qual[i].level != 0)) + /* If the statistics are in dBm */ + if(qual[i].level > range.max_qual.level) + printf(" %s : Quality %d/%d ; Signal %d dBm ; Noise %d dBm %s\n", + pr_ether(hwa[i].sa_data), + qual[i].qual, range.max_qual.qual, + qual[i].level - 0x100, qual[i].noise - 0x100, + qual[i].updated & 0x7 ? "(updated)" : ""); + else + printf(" %s : Quality %d/%d ; Signal %d/%d ; Noise %d/%d %s\n", + pr_ether(hwa[i].sa_data), + qual[i].qual, range.max_qual.qual, + qual[i].level, range.max_qual.level, + qual[i].noise, range.max_qual.noise, + qual[i].updated & 0x7 ? "(updated)" : ""); + else + printf(" %s : Quality %d ; Signal %d ; Noise %d %s\n", + pr_ether(hwa[i].sa_data), + qual[i].qual, qual[i].level, qual[i].noise, + qual[i].updated & 0x7 ? "(updated)" : ""); + } + printf("\n"); } -int -main(int argc, - char ** argv) +/*------------------------------------------------------------------*/ +/* + * Get info on all devices and print it on the screen + */ +static void +print_spy_devices(int skfd) +{ + char buff[1024]; + struct ifconf ifc; + struct ifreq *ifr; + int i; + + /* Get list of active devices */ + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) + { + fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); + return; + } + ifr = ifc.ifc_req; + + /* Print them */ + for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) + print_spy_info(skfd, ifr->ifr_name); +} + +/*------------------------------------------------------------------*/ +/* + * Print the number of channels and available frequency for the device + */ +static void +print_freq_info(int skfd, + char * ifname) { - struct ifreq ifr; struct iwreq wrq; - struct aftype *ap; - struct hwtype *hw; - char * ifname = argv[1]; + float freq; + struct iw_range range; + int k; + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + wrq.u.data.pointer = (caddr_t) ⦥ + wrq.u.data.length = 0; + wrq.u.data.flags = 0; + if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0) + fprintf(stderr, "%-8.8s no frequency information.\n\n", + ifname); + else + { + if(range.num_frequency > 0) + { + printf("%-8.8s %d channels in total; available frequencies :\n", + ifname, range.num_channels); + /* Print them all */ + for(k = 0; k < range.num_frequency; k++) + { +#if WIRELESS_EXT > 7 + printf("\t Channel %.2d : ", range.freq[k].i); +#else + printf("\t "); +#endif + freq = freq2float(&(range.freq[k])); + if(freq >= GIGA) + printf("%g GHz\n", freq / GIGA); + else + if(freq >= MEGA) + printf("%g MHz\n", freq / MEGA); + else + printf("%g kHz\n", freq / KILO); + } + printf("\n\n"); + } + else + printf("%-8.8s %d channels\n\n", + ifname, range.num_channels); + } +} - if(argc < 2) - exit(0); +/*------------------------------------------------------------------*/ +/* + * 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; - /* Create a channel to the NET kernel. */ - if((skfd = sockets_open()) < 0) + /* Print them */ + for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) + print_freq_info(skfd, ifr->ifr_name); +} + +#if WIRELESS_EXT > 5 +/*------------------------------------------------------------------*/ +/* + * Display the list of ap addresses and the associated stats + * Exacly the same as the spy list, only with different IOCTL and messages + */ +static void +print_ap_info(int skfd, + char * ifname) +{ + struct iwreq wrq; + char buffer[(sizeof(struct iw_quality) + + sizeof(struct sockaddr)) * IW_MAX_AP]; + struct sockaddr * hwa; + struct iw_quality * qual; + iwrange range; + int has_range = 0; + int has_qual = 0; + int n; + 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.flags = 0; + if(ioctl(skfd, SIOCGIWAPLIST, &wrq) < 0) { - perror("socket"); - exit(-1); + fprintf(stderr, "%-8.8s Interface doesn't have a list of Access Points\n\n", ifname); + return; } - /* Get the type of interface address */ - strcpy(ifr.ifr_name, ifname); - if((ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0) || - ((ap = get_afntype(ifr.ifr_addr.sa_family)) == NULL)) + /* Number of addresses */ + n = wrq.u.data.length; + has_qual = wrq.u.data.flags; + + /* The two lists */ + hwa = (struct sockaddr *) buffer; + qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); + + /* Check if we have valid address types */ + if(check_addr_type(skfd, ifname) < 0) { - /* Deep trouble... */ - fprintf(stderr, "Interface %s unavailable\n", ifname); - exit(0); + fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n\n", ifname); + return; } -#ifdef DEBUG - printf("Interface : %d - %s - %s\n", ifr.ifr_addr.sa_family, - ap->name, ap->sprint(&ifr.ifr_addr, 1)); -#endif + /* Get range info if we can */ + if(get_range_info(skfd, ifname, &(range)) >= 0) + has_range = 1; - /* Get the type of hardware address */ - strcpy(ifr.ifr_name, ifname); - if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) || - ((hw = get_hwntype(ifr.ifr_hwaddr.sa_family)) == NULL)) + /* Display it */ + if(n == 0) + printf("%-8.8s No Access Point in range\n", ifname); + else + printf("%-8.8s Access Points in range:\n", ifname); + for(i = 0; i < n; i++) { - /* Deep trouble... */ - fprintf(stderr, "Unable to get hardware address of the interface %s\n", - ifname); - exit(0); + if(has_qual) + if(has_range) + /* If the statistics are in dBm */ + if(qual[i].level > range.max_qual.level) + printf(" %s : Quality %d/%d ; Signal %d dBm ; Noise %d dBm %s\n", + pr_ether(hwa[i].sa_data), + qual[i].qual, range.max_qual.qual, + qual[i].level - 0x100, qual[i].noise - 0x100, + qual[i].updated & 0x7 ? "(updated)" : ""); + else + printf(" %s : Quality %d/%d ; Signal %d/%d ; Noise %d/%d %s\n", + pr_ether(hwa[i].sa_data), + qual[i].qual, range.max_qual.qual, + qual[i].level, range.max_qual.level, + qual[i].noise, range.max_qual.noise, + qual[i].updated & 0x7 ? "(updated)" : ""); + else + printf(" %s : Quality %d ; Signal %d ; Noise %d %s\n", + pr_ether(hwa[i].sa_data), + qual[i].qual, qual[i].level, qual[i].noise, + qual[i].updated & 0x7 ? "(updated)" : ""); + else + printf(" %s\n", pr_ether(hwa[i].sa_data)); } + printf("\n"); +} -#ifdef DEBUG - printf("Hardware : %d - %s - %s\n", ifr.ifr_hwaddr.sa_family, - hw->name, hw->print(ifr.ifr_hwaddr.sa_data)); -#endif +/*------------------------------------------------------------------*/ +/* + * 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); +} +#endif /* WIRELESS_EXT > 5 */ - /* Is there any arguments ? */ - if(argc < 3) - { /* Nope : read out from kernel */ - char buffer[(sizeof(struct iw_quality) + - sizeof(struct sockaddr)) * IW_MAX_SPY]; - struct sockaddr * hwa; - struct iw_quality *qual; - int n; - int i; +#if WIRELESS_EXT > 7 +/*------------------------------------------------------------------*/ +/* + * Print the number of available bitrates for the device + */ +static void +print_bitrate_info(int skfd, + char * ifname) +{ + struct iwreq wrq; + float bitrate; + struct iw_range range; + int k; + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + wrq.u.data.pointer = (caddr_t) ⦥ + wrq.u.data.length = 0; + wrq.u.data.flags = 0; + if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0) + fprintf(stderr, "%-8.8s no bit-rate information.\n\n", + ifname); + else + { + if((range.num_bitrates > 0) && (range.num_bitrates < IW_MAX_BITRATES)) + { + printf("%-8.8s %d available bit-rates :\n", + ifname, range.num_bitrates); + /* Print them all */ + for(k = 0; k < range.num_bitrates; k++) + { + printf("\t "); + bitrate = range.bitrate[k]; + if(bitrate >= GIGA) + printf("%g Gb/s\n", bitrate / GIGA); + else + if(bitrate >= MEGA) + printf("%g Mb/s\n", bitrate / MEGA); + else + printf("%g kb/s\n", bitrate / KILO); + } + printf("\n\n"); + } + else + printf("%-8.8s No bit-rates ? Please update driver...\n\n", ifname); + } +} + +/*------------------------------------------------------------------*/ +/* + * 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); +} +#endif /* WIRELESS_EXT > 7 */ + +/************************* SETTING ROUTINES **************************/ + +/*------------------------------------------------------------------*/ +/* + * Set list of addresses specified on command line in the driver. + */ +static int +set_spy_info(int skfd, /* The socket */ + char * args[], /* Command line args */ + int count, /* Args count */ + char * ifname) /* Dev name */ +{ + struct iwreq wrq; + int i; + int nbr; /* Number of valid addresses */ + struct sockaddr hw_address[IW_MAX_SPY]; + + /* Read command line */ + i = 0; /* first arg to read */ + nbr = 0; /* Number of args readen so far */ + + /* Check if we have valid address types */ + if(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 */ + + /* "+" : add all addresses already in the driver */ + if(!strcmp(args[0], "+")) + { + char buffer[(sizeof(struct iw_quality) + + sizeof(struct sockaddr)) * IW_MAX_SPY]; strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.data.pointer = (caddr_t) buffer; @@ -121,147 +436,162 @@ main(int argc, return(-1); } - n = wrq.u.data.length; + /* Copy old addresses */ + nbr = wrq.u.data.length; + memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr)); - hwa = (struct sockaddr *) buffer; - qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); + i = 1; /* skip the "+" */ + } - for(i = 0; i < n; i++) - printf("%s : Quality %d ; Signal %d ; Noise %d %s\n", - hw->print(hwa[i].sa_data), - qual[i].qual, qual[i].level, qual[i].noise, - qual[i].updated & 0x7 ? "(updated)" : ""); + /* Read other args on command line */ + while((i < count) && (nbr < IW_MAX_SPY)) + { + if(in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0) + continue; + nbr++; } - else - { /* Send addresses to kernel */ - int i; - int nbr; /* Number of valid addresses */ - struct sockaddr hw_address[IW_MAX_SPY]; - struct sockaddr if_address; - struct arpreq arp_query; - - /* Read command line */ - i = 2; /* first arg to read */ - nbr = 0; /* Number of args readen so far */ - - /* "off" : disable functionality (set 0 addresses) */ - if(!strcmp(argv[2], "off")) - i = argc; /* hack */ - - /* "+" : add all addresses already in the driver */ - if(!strcmp(argv[2], "+")) - { - char buffer[(sizeof(struct iw_quality) + - sizeof(struct sockaddr)) * IW_MAX_SPY]; - - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); - wrq.u.data.pointer = (caddr_t) buffer; - wrq.u.data.length = 0; - wrq.u.data.flags = 0; - if(ioctl(skfd, SIOCGIWSPY, &wrq) < 0) - { - fprintf(stderr, "Interface doesn't accept reading addresses...\n"); - fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno)); - return(-1); - } - /* Copy old addresses */ - nbr = wrq.u.data.length; - memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr)); + /* Check the number of addresses */ + if((nbr == 0) && strcmp(args[0], "off")) + { + fprintf(stderr, "No valid addresses found : exiting...\n"); + exit(0); + } - i = 3; /* skip the "+" */ - } + /* Check if there is some remaining arguments */ + if(i < count) + { + fprintf(stderr, "Got only the first %d addresses, remaining discarded\n", IW_MAX_SPY); + } - /* Read other args on command line */ - while((i < argc) && (nbr < IW_MAX_SPY)) - { - /* If it is not a hardware address (prefixed by hw)... */ - if(strcmp(argv[i], "hw")) - { - /* Read interface address */ - if(ap->input(argv[i++], &if_address) < 0) - { - fprintf(stderr, "Invalid interface address %s\n", argv[i - 1]); - continue; - } - - /* Translate IP addresses to MAC addresses */ - memcpy((char *) &(arp_query.arp_pa), - (char *) &if_address, - sizeof(struct sockaddr)); - arp_query.arp_ha.sa_family = 0; - arp_query.arp_flags = 0; - /* The following restrict the search to the interface only */ - strcpy(arp_query.arp_dev, ifname); - if((ioctl(inet_sock, SIOCGARP, &arp_query) < 0) || - !(arp_query.arp_flags & ATF_COM)) - { - fprintf(stderr, "Arp failed for %s... (%d) Try to ping the address before.\n", - ap->sprint(&if_address, 1), errno); - continue; - } - - /* Store new MAC address */ - memcpy((char *) &(hw_address[nbr++]), - (char *) &(arp_query.arp_ha), - sizeof(struct sockaddr)); - -#ifdef DEBUG - printf("IP Address %s => Hw Address = %s - %d\n", - ap->sprint(&if_address, 1), - hw->print(hw_address[nbr - 1].sa_data)); -#endif - } - else /* If it's an hardware address */ - { - if(++i >= argc) - { - fprintf(stderr, "hw must be followed by an address...\n"); - continue; - } - - /* Get the hardware address */ - if(hw->input(argv[i++], &(hw_address[nbr])) < 0) - { - fprintf(stderr, "Invalid hardware address %s\n", argv[i - 1]); - continue; - } - nbr++; - -#ifdef DEBUG - printf("Hw Address = %s - %d\n", - hw->print(hw_address[nbr - 1].sa_data)); -#endif - } - } /* Loop on all addresses */ + /* 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) + { + fprintf(stderr, "Interface doesn't accept addresses...\n"); + fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno)); + return(-1); + } + return(0); +} - /* Check the number of addresses */ - if((nbr == 0) && strcmp(argv[2], "off")) - { - fprintf(stderr, "No valid addresses found : exiting...\n"); - exit(0); - } +/******************************* MAIN ********************************/ - /* Check if there is some remaining arguments */ - if(i < argc) - { - fprintf(stderr, "Got only the first %d addresses, remaining discarded\n", IW_MAX_SPY); - } +/*------------------------------------------------------------------*/ +/* + * The main ! + */ +int +main(int argc, + char ** argv) +{ + int skfd = -1; /* generic raw socket desc. */ + int goterr = 0; - /* 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) - { - fprintf(stderr, "Interface doesn't accept addresses...\n"); - fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno)); - return(-1); - } + /* Create a channel to the NET kernel. */ + if((skfd = sockets_open()) < 0) + { + perror("socket"); + exit(-1); + } + + /* No argument : show the list of all device + info */ + if(argc == 1) + { + print_spy_devices(skfd); + close(skfd); + exit(0); + } + + /* Special cases take one... */ + /* Help */ + if((!strncmp(argv[1], "-h", 9)) || + (!strcmp(argv[1], "--help"))) + { + fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n"); + fprintf(stderr, " interface [freq]\n"); + fprintf(stderr, " interface [ap]\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); + } + +#if WIRELESS_EXT > 5 + /* Access Point list */ + if(!strcasecmp(argv[1], "ap")) + { + print_ap_devices(skfd); + close(skfd); + exit(0); + } +#endif /* WIRELESS_EXT > 5 */ + +#if WIRELESS_EXT > 7 + /* Bit-rate list */ + if((!strncmp(argv[1], "bit", 3)) || + (!strcmp(argv[1], "rate"))) + { + print_bitrate_devices(skfd); + close(skfd); + exit(0); + } +#endif /* WIRELESS_EXT > 7 */ + + /* The device name must be the first argument */ + /* Name only : show spy list for that device only */ + if(argc == 2) + { + print_spy_info(skfd, argv[1]); + close(skfd); + exit(0); + } + + /* 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); + } + +#if WIRELESS_EXT > 5 + /* Access Point list */ + if(!strcasecmp(argv[2], "ap")) + { + print_ap_info(skfd, argv[1]); + close(skfd); + exit(0); + } +#endif /* WIRELESS_EXT > 5 */ + +#if WIRELESS_EXT > 7 + /* Access Point list */ + if((!strncmp(argv[2], "bit", 3)) || + (!strcmp(argv[2], "rate"))) + { + print_bitrate_info(skfd, argv[1]); + close(skfd); + exit(0); + } +#endif /* WIRELESS_EXT > 7 */ + + /* Otherwise, it's a list of address to set in the spy list */ + goterr = set_spy_info(skfd, argv + 2, argc - 2, argv[1]); + /* Close the socket. */ close(skfd); diff --git a/wireless_tools/wireless.h b/wireless_tools/wireless.h new file mode 100644 index 0000000..0be1d51 --- /dev/null +++ b/wireless_tools/wireless.h @@ -0,0 +1,347 @@ +/* + * This file define a set of standard wireless extensions + * + * Version : 7 23.4.99 + * + * Authors : Jean Tourrilhes - HPLB - + */ + +#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 *****************************/ + +#if 0 +#include /* for "caddr_t" et al */ +#include /* for "struct sockaddr" et al */ +#include /* for IFNAMSIZ and co... */ +#endif + +/**************************** 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 6 + +/* + * 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 + */ + +/* -------------------------- IOCTL LIST -------------------------- */ + +/* Basic operations */ +#define SIOCSIWNAME 0x8B00 /* Unused ??? */ +#define SIOCGIWNAME 0x8B01 /* get name */ +#define SIOCSIWNWID 0x8B02 /* set network id */ +#define SIOCGIWNWID 0x8B03 /* get network id */ +#define SIOCSIWFREQ 0x8B04 /* set channel/frequency */ +#define SIOCGIWFREQ 0x8B05 /* get channel/frequency */ +#define SIOCSIWENCODE 0x8B06 /* set encoding info */ +#define SIOCGIWENCODE 0x8B07 /* get encoding info */ +#define SIOCSIWSENS 0x8B08 /* set sensitivity */ +#define SIOCGIWSENS 0x8B09 /* get sensitivity */ + +/* 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 hardware addresses */ +#define SIOCGIWAP 0x8B15 /* get access point hardware 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 */ +/* As the ESSID is a string 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. + */ + +/* ------------------------- IOCTL STUFF ------------------------- */ + +/* The first and the last (range) */ +#define SIOCIWFIRST 0x8B00 +#define SIOCIWLAST 0x8B1B + +/* 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 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 string */ +#define IW_ESSID_MAX_SIZE 32 + +/****************************** TYPES ******************************/ + +/* --------------------------- SUBTYPES --------------------------- */ +/* + * A frequency + * For numbers lower than 10^9, we encode the number in 'mant' and + * set 'exp' to 0 + * For number greater than 10^9, we divide it by a power of 10. + * The power of 10 is in 'exp', the result is in 'mant'. + */ +struct iw_freq +{ + __u32 m; /* Mantissa */ + __u16 e; /* Exponent */ +}; + +/* + * Quality of the link + */ +struct iw_quality +{ + __u8 qual; /* link quality (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 */ +}; + +/* + * Encoding information (setting and so on) + * Encoding might be hardware encryption, scrambing or others + */ +struct iw_encoding +{ + __u8 method; /* Algorithm number / key used */ + __u64 code; /* Data/key used for algorithm */ +}; + + +/* ------------------------ WIRELESS STATS ------------------------ */ +/* + * Wireless statistics (used for /proc/net/wireless) + */ +struct iw_statistics +{ + __u8 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. "en0" */ + } 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 /* network id (or domain) : used to to */ + { /* create logical channels on the air */ + __u32 nwid; /* value */ + __u8 on; /* active/unactive nwid */ + } nwid; + + struct iw_freq freq; /* frequency or channel : + * 0-1000 = channel + * > 1000 = frequency in Hz */ + + struct iw_encoding encoding; /* Encoding stuff */ + + __u32 sensitivity; /* signal level threshold */ + + struct sockaddr ap_addr; /* Access point address */ + + struct /* For all data bigger than 16 octets */ + { + caddr_t pointer; /* Pointer to the data + * (in user space) */ + __u16 length; /* fields or byte size */ + __u16 flags; /* Optional params */ + } data; + } u; +}; + +/* -------------------------- IOCTL DATA -------------------------- */ +/* + * For those ioctl which want to exchange mode data that what could + * fit in the above structure... + */ + +/* + * Range of parameters + */ + +struct iw_range +{ + /* Informative stuff (to choose between different interface) */ + __u32 throughput; /* To give an idea... */ + + /* 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 */ + __u32 sensitivity; + + /* Quality of link & SNR stuff */ + struct iw_quality max_qual; /* Quality of the link */ + + /* Encoder stuff */ + struct iw_encoding max_encoding; /* Encoding max range */ +}; + +/* + * 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/xwireless.c b/wireless_tools/xwireless.c new file mode 100644 index 0000000..dca0d48 --- /dev/null +++ b/wireless_tools/xwireless.c @@ -0,0 +1,241 @@ +/* Xwireless.c, status: experimental, do not distribute!! */ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +char* status[] = { "Scanning","Registering","Best AP","Good AP", + "Poor AP","Active Beacon Search","Static Load Balance", + "Balance Search" }; + +typedef struct privateData { + char *ifname; + Pixel currentColor; + Pixel highColor; + Pixel lowColor; + Pixel criticalColor; + Pixel foreground; + int highValue; + int lowValue; + int delay; + String geometry; + struct iw_statistics stats; + struct iw_range range; +} privateData; + +static XtAppContext app_context; +static Widget scrollbar; +static Widget topLevel; +static Widget label; +static XtIntervalId timerId; +static privateData priv; + +static int getstats(char *ifname, struct iw_statistics *stats) +{ + struct iwreq wrq; + FILE *f=fopen("/proc/net/wireless","r"); + char buf[256]; + char *bp; + if(f==NULL) + return -1; + while(fgets(buf,255,f)) + { + bp=buf; + while(*bp&&isspace(*bp)) + bp++; + if( strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') { + bp=strchr(bp,':'); + bp++; + bp = strtok(bp, " ."); + sscanf(bp, "%X", &stats->status); + bp = strtok(NULL, " ."); + sscanf(bp, "%d", &stats->qual.qual); + bp = strtok(NULL, " ."); + sscanf(bp, "%d", &stats->qual.level); + bp = strtok(NULL, " ."); + sscanf(bp, "%d", &stats->qual.noise); + 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; + } else { + stats->status = -1; + stats->qual.qual = 0; + stats->qual.level = 0; + stats->qual.noise = 0; + } + } + fclose(f); + + /*strcpy(wrq.ifr_name, ifname); + wrq.u.data.pointer = (caddr_t) ⦥ + wrq.u.data.length = 0; + wrq.u.data.flags = 0; + if(ioctl(skfd, SIOCGIWRANGE, &wrq) >= 0) { + info->has_range = 1; + }*/ + + return 0; +} + +static void update( XtPointer client_data, XtIntervalId *id ) +{ + char buf[128]; + static int pixel = -1; + static int lpixel = -1; + static int bpixel = -1; + + getstats( priv.ifname, &(priv.stats)); + + if(status < 8) + sprintf( buf, "%s", status[priv.stats.status] ); + else + sprintf( buf, "%s", "buggy" ); + XtVaSetValues( label, XtNlabel, buf, NULL ); + + if (priv.stats.qual.qual <= priv.lowValue) { + if (pixel != priv.criticalColor) + XtVaSetValues( scrollbar, XtNforeground, + pixel = priv.criticalColor, NULL ); + if (bpixel != priv.criticalColor) + XtVaSetValues( scrollbar, XtNborderColor, + bpixel = priv.criticalColor, NULL ); + } else if (priv.stats.qual.qual <= priv.highValue) { + if (pixel != priv.lowColor) + XtVaSetValues( scrollbar, + XtNforeground, pixel = priv.lowColor, NULL ); + if (bpixel != priv.foreground) + XtVaSetValues( scrollbar, XtNborderColor, + bpixel = priv.foreground, NULL ); + } else { + if (pixel != priv.highColor ) + XtVaSetValues( scrollbar, + XtNforeground, pixel = priv.highColor, NULL ); + } + + XawScrollbarSetThumb( scrollbar, 0.0, priv.stats.qual.qual / 255.0 ); + + timerId = XtAppAddTimeOut( app_context, 1000 , update, app_context ); +} + +#define offset(field) XtOffsetOf( privateData, field ) +static XtResource resources[] = { + { "highColor", XtCForeground, XtRPixel, sizeof(Pixel), + offset(highColor), XtRString, "green" }, + { "lowColor", XtCForeground, XtRPixel, sizeof(Pixel), + offset(lowColor), XtRString, "orange" }, + { "criticalColor", XtCForeground, XtRPixel, sizeof(Pixel), + offset(criticalColor), XtRString, "red" }, + { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offset(foreground), XtRString, XtDefaultForeground }, + { "highValue", XtCValue, XtRInt, sizeof(int), + offset(highValue), XtRImmediate, (XtPointer)50 }, + { "lowValue", XtCValue, XtRInt, sizeof(int), + offset(lowValue), XtRImmediate, (XtPointer)10 }, + { "geometry", XtCString, XtRString, sizeof( String ), + offset(geometry), XtRString, (XtPointer)"10x100" }, + { "delay", XtCValue, XtRInt, sizeof(int), + offset(delay), XtRImmediate, (XtPointer)1 }, +}; + +int main( int argc, char **argv ) { + Cursor cursor; + int c; + Widget form; + XFontStruct *fs; + int fontWidth, fontHeight; + int width = 120; + + /* The device name must be the first argument */ + if(argc < 2) { + printf("Hmm\n"); + } + priv.ifname = argv[1]; + + if( priv.ifname == (char *) NULL) { + printf("Usage: xwireless \n"); + exit(-1); + } + + topLevel = XtVaAppInitialize( &app_context, "Xwireless", + NULL, 0, + &argc, argv, NULL, NULL ); + + XtGetApplicationResources( topLevel, + &priv, + resources, + XtNumber( resources ), + NULL, 0 ); + priv.lowValue = 85; + priv.highValue = 170; + +/* printf( "highColor = %ld\n", priv.highColor ); + printf( "lowColor = %ld\n", priv.lowColor ); + printf( "criticalColor = %ld\n", priv.criticalColor ); + printf( "foreground = %ld\n", priv.foreground ); + printf( "highValue = %d\n", priv.highValue ); + printf( "lowValue = %d\n", priv.lowValue ); + printf( "geometry = %s\n", priv.geometry );*/ + + cursor = XCreateFontCursor( XtDisplay( topLevel ), XC_top_left_arrow ); + + form = XtVaCreateManagedWidget( "form", + formWidgetClass, topLevel, + XtNorientation, XtorientHorizontal, + XtNborderWidth, 0, + XtNdefaultDistance, 2, + NULL ); + + label = XtVaCreateManagedWidget( "label", + labelWidgetClass, form, + XtNleft, XtChainLeft, + XtNinternalHeight, 0, + XtNinternalWidth, 0, + XtNborderWidth, 0, + XtNlabel, "Status", + NULL ); + + XtVaGetValues( label, XtNfont, &fs, NULL ); + fontWidth = fs->max_bounds.width; + fontHeight = fs->max_bounds.ascent + fs->max_bounds.descent; + XtVaSetValues( label, XtNwidth, fontWidth * 8, NULL ); + + scrollbar = XtVaCreateManagedWidget( "scrollbar", + scrollbarWidgetClass, form, + XtNhorizDistance, 3, + XtNfromHoriz, label, + XtNorientation, XtorientHorizontal, + XtNscrollHCursor, cursor, + XtNthickness, fontHeight, + XtNlength, (width > fontWidth*4 - 6) + ? width - fontWidth * 4 - 6 + : fontWidth * 4, + NULL ); + + XawScrollbarSetThumb( scrollbar, 0.0, 0.0 ); +/* XtVaSetValues( scrollbar, + XtNtranslations, XtParseTranslationTable( "" ), NULL ); + */ + XtRealizeWidget( topLevel ); + timerId = XtAppAddTimeOut( app_context, 0, update, app_context ); + XtAppMainLoop( app_context ); + + return 0; +} diff --git a/wireless_tools/xwireless.make b/wireless_tools/xwireless.make new file mode 100644 index 0000000..758d827 --- /dev/null +++ b/wireless_tools/xwireless.make @@ -0,0 +1,53 @@ +# Makefile for Xwireless +CC = gcc +RM = rm -f + +RM_CMD = $(RM) *.BAK *.bak *.o ,* *~ *.a + +INCLUDES = $(SYS_INCLUDES) $(LOCAL_INCLUDES) +LIBRARIES = $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) +LIBPATH = $(SYS_LIBPATH) $(LOCAL_LIBPATH) + +# +# System stuff +# +SYS_INCLUDES = -I/usr/include -I/usr/X11R6/include +SYS_LIBRARIES = -lXaw -lXmu -lXt -lXext -lSM -lICE -lX11 +SYS_LIBPATH = -L/usr/lib -L/usr/local/lib -L/usr/X11R6/lib + +# +# Local stuff +# +LOCAL_INCLUDES = +LOCAL_LIBRARIES = +LOCAL_LIBPATH = + +XTRACFLAGS=-Wall -pipe -I. + +# Uncomment these lines for a production compile +#CFLAGS=-O3 -m486 -fomit-frame-pointer +#LDFLAGS=-s +CFLAGS=-g + +# +# Files to make +# +PROGS=xwireless + +SRCS = $(PROGS).c +OBJS = $(PROGS).o + +all:: $(PROGS) + +xwireless: $(OBJS) + $(CC) $(CFLAGS) -o $@ $(OBJS) $(INCLUDES) $(LIBPATH) $(LIBRARIES) + +.c.o: + $(CC) $(CFLAGS) $(XTRACFLAGS) -c $(INCLUDES) -DNARROWPROTO $< + +clean:: + $(RM_CMD) + +depend:: + makedepend -s "# DO NOT DELETE" -- $(INCLUDES) -- $(SRCS) +# DO NOT DELETE -- 2.11.0