/*
- * Hack my way... Jean II
+ * Wireless Tools
+ *
+ * Jean II - HPLB 97->99 - HPL 99->01
+ *
+ * Main code for "iwconfig". This is the generic tool for most
+ * manipulations...
+ * You need to link this code against "iwlib.c" and "-lm".
+ *
+ * This file is released under the GPL license.
+ * Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
*/
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <linux/netdevice.h>
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/ipx.h>
-#include <linux/wireless.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/* 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 "iwlib.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");
- exit(1);
+ 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");
+ fprintf(stderr, " [power { period N|timeout N}]\n");
+ fprintf(stderr, " [txpower N {mW|dBm}]\n");
+ fprintf(stderr, " [commit]\n");
}
+/************************* DISPLAY ROUTINES **************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * 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(int skfd,
+ char * ifname,
+ struct wireless_info * info)
+{
+ struct iwreq wrq;
+
+ memset((char *) info, 0, sizeof(struct wireless_info));
+
+ /* Get wireless name */
+ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
+ {
+ /* If no wireless name : no wireless extensions */
+ /* But let's check if the interface exists at all */
+ struct ifreq ifr;
+
+ strcpy(ifr.ifr_name, ifname);
+ if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
+ return(-ENODEV);
+ else
+ return(-ENOTSUP);
+ }
+ else
+ strcpy(info->name, wrq.u.name);
+
+ /* Get ranges */
+ if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
+ info->has_range = 1;
+
+ /* Get network ID */
+ if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0)
+ {
+ info->has_nwid = 1;
+ memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
+ }
+
+ /* Get frequency / channel */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
+ {
+ info->has_freq = 1;
+ info->freq = iw_freq2float(&(wrq.u.freq));
+ }
+
+ /* Get sensitivity */
+ if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
+ {
+ info->has_sens = 1;
+ memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
+ }
+
+ /* Get encryption information */
+ wrq.u.data.pointer = (caddr_t) info->key;
+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
+ wrq.u.data.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
+ {
+ info->has_key = 1;
+ info->key_size = wrq.u.data.length;
+ info->key_flags = wrq.u.data.flags;
+ }
+
+ /* Get ESSID */
+ wrq.u.essid.pointer = (caddr_t) info->essid;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE;
+ wrq.u.essid.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0)
+ {
+ info->has_essid = 1;
+ info->essid_on = wrq.u.data.flags;
+ }
+
+ /* Get AP address */
+ if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
+ {
+ info->has_ap_addr = 1;
+ memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
+ }
+
+ /* Get NickName */
+ wrq.u.essid.pointer = (caddr_t) info->nickname;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE;
+ wrq.u.essid.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
+ if(wrq.u.data.length > 1)
+ info->has_nickname = 1;
+
+ /* Get bit rate */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
+ {
+ info->has_bitrate = 1;
+ memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
+ }
+
+ /* Get RTS threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
+ {
+ info->has_rts = 1;
+ memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
+ }
+
+ /* Get fragmentation threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
+ {
+ info->has_frag = 1;
+ memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
+ }
+
+ /* Get operation mode */
+ if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
+ {
+ info->mode = wrq.u.mode;
+ if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
+ info->has_mode = 1;
+ }
+
+ /* Get Power Management settings */
+ wrq.u.power.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
+ {
+ info->has_power = 1;
+ memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
+ }
+
+#if WIRELESS_EXT > 9
+ /* Get Transmit Power */
+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
+ {
+ info->has_txpower = 1;
+ memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
+ }
+#endif
+
+#if WIRELESS_EXT > 10
+ /* Get retry limit/lifetime */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
+ {
+ info->has_retry = 1;
+ memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
+ }
+#endif /* WIRELESS_EXT > 10 */
+
+ /* Get stats */
+ if(iw_get_stats(skfd, ifname, &(info->stats)) >= 0)
+ {
+ info->has_stats = 1;
+ }
+
+ return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print on the screen in a neat fashion all the info we have collected
+ * on a device.
+ */
static void
-print_info(struct wireless_info * info)
+display_info(struct wireless_info * info,
+ char * ifname)
{
- /* Display device name */
- printf("%-8.8s ", info->dev);
+ char buffer[128]; /* Temporary buffer */
+
+ /* One token is more of less 5 characters, 14 tokens per line */
+ int tokens = 3; /* For name */
- /* Display wireless name */
- printf("%s ", info->name);
+ /* 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)
+ {
+ /* Does it have an ESSID index ? */
+ if((info->essid_on & IW_ENCODE_INDEX) > 1)
+ printf("ESSID:\"%s\" [%d] ", info->essid,
+ (info->essid_on & IW_ENCODE_INDEX));
+ else
+ printf("ESSID:\"%s\" ", info->essid);
+ }
+ else
+ printf("ESSID:off/any ");
+ }
+
+ /* 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 ");
+ tokens = 0;
+ }
/* Display Network ID */
if(info->has_nwid)
- if(info->nwid_on)
- printf("NWID:%lX ", info->nwid);
- else
- printf("NWID:off ");
+ {
+ /* Note : should display proper number of digit according to info
+ * in range structure */
+ if(info->nwid.disabled)
+ printf("NWID:off/any ");
+ else
+ printf("NWID:%X ", info->nwid.value);
+ tokens +=2;
+ }
+
+ /* Display the current mode of operation */
+ if(info->has_mode)
+ {
+ printf("Mode:%s ", iw_operation_mode[info->mode]);
+ tokens +=3;
+ }
/* 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);
+ {
+ iw_print_freq(buffer, info->freq);
+ printf("%s ", buffer);
+ tokens +=4;
+ }
+
+ /* Display the address of the current Access Point */
+ if(info->has_ap_addr)
+ {
+ /* A bit of clever formatting */
+ if(tokens > 8)
+ {
+ printf("\n ");
+ tokens = 0;
+ }
+ tokens +=6;
+
+ /* Oups ! No Access Point in Ad-Hoc mode */
+ if((info->has_mode) && (info->mode == IW_MODE_ADHOC))
+ printf("Cell:");
else
- if(info->freq > MEGA)
- printf("Frequency:%gMHz ", info->freq / MEGA);
- else
- printf("Frequency:%gkHz ", info->freq / KILO);
+ printf("Access Point:");
+ printf(" %s", iw_pr_ether(buffer, info->ap_addr.sa_data));
+ }
- printf("\n");
+ /* Display the currently used/set bit-rate */
+ if(info->has_bitrate)
+ {
+ /* A bit of clever formatting */
+ if(tokens > 11)
+ {
+ printf("\n ");
+ tokens = 0;
+ }
+ tokens +=3;
- if(info->has_stats)
+ /* Display it */
+ iw_print_bitrate(buffer, info->bitrate.value);
+ printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
+ }
+
+#if WIRELESS_EXT > 9
+ /* Display the Transmit Power */
+ if(info->has_txpower)
{
- 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);
+ /* A bit of clever formatting */
+ if(tokens > 11)
+ {
+ printf("\n ");
+ tokens = 0;
+ }
+ tokens +=3;
+
+ /* Disabled ? */
+ if(info->txpower.disabled)
+ printf("Tx-Power:off ");
else
- printf(" Link quality:%d Signal level:%d Noise level:%d\n",
- info->stats.qual.qual,
- info->stats.qual.level,
- info->stats.qual.noise);
+ {
+ int dbm;
- printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
- info->stats.discard.nwid,
- info->stats.discard.crypt,
- info->stats.discard.misc);
+ /* Fixed ? */
+ if(info->txpower.fixed)
+ printf("Tx-Power=");
+ else
+ printf("Tx-Power:");
+
+ /* Convert everything to dBm */
+ if(info->txpower.flags & IW_TXPOW_MWATT)
+ dbm = iw_mwatt2dbm(info->txpower.value);
+ else
+ dbm = info->txpower.value;
+
+ /* Display */
+ printf("%d dBm ", dbm);
+ }
}
+#endif
- printf("\n");
-}
+ /* Display sensitivity */
+ if(info->has_sens)
+ {
+ /* A bit of clever formatting */
+ if(tokens > 10)
+ {
+ printf("\n ");
+ tokens = 0;
+ }
+ tokens +=4;
-static int if_getstats(char *ifname, iwstats * stats)
-{
- 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.crypt);
- bp = strtok(NULL, " .");
- sscanf(bp, "%d", &stats->discard.misc);
- fclose(f);
- return;
- }
- }
- fclose(f);
- return 0;
-}
+ /* Fixed ? */
+ if(info->sens.fixed)
+ printf("Sensitivity=");
+ else
+ printf("Sensitivity:");
-/* Get wireless informations & config from the device driver */
-static int
-get_info(char * ifname,
- struct wireless_info * info)
-{
- struct iwreq wrq;
+ if(info->has_range)
+ /* Display in dBm ? */
+ if(info->sens.value < 0)
+ printf("%d dBm ", info->sens.value);
+ else
+ printf("%d/%d ", info->sens.value, info->range.sensitivity);
+ else
+ printf("%d ", info->sens.value);
+ }
- memset((char *) info, 0, sizeof(struct wireless_info));
+ printf("\n ");
+ tokens = 0;
- /* Get device name */
- strcpy(info->dev, ifname);
+#if WIRELESS_EXT > 10
+ /* Display retry limit/lifetime information */
+ if(info->has_retry)
+ {
+ printf("Retry");
+ /* Disabled ? */
+ if(info->retry.disabled)
+ printf(":off");
+ else
+ {
+ /* Let's check the value and its type */
+ if(info->retry.flags & IW_RETRY_TYPE)
+ {
+ iw_print_retry_value(buffer,
+ info->retry.value, info->retry.flags);
+ printf("%s", buffer);
+ }
- /* Get wireless name */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
- /* If no wireless name : no wireless extensions */
- return(-1);
- else
- strcpy(info->name, wrq.u.name);
+ /* Let's check if nothing (simply on) */
+ if(info->retry.flags == IW_RETRY_ON)
+ printf(":on");
+ }
+ printf(" ");
+ tokens += 5; /* Between 3 and 5, depend on flags */
+ }
+#endif /* WIRELESS_EXT > 10 */
- /* Get network ID */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0)
+ /* Display the RTS threshold */
+ if(info->has_rts)
{
- info->has_nwid = 1;
- info->nwid_on = wrq.u.nwid.on;
- info->nwid = wrq.u.nwid.nwid;
+ /* Disabled ? */
+ if(info->rts.disabled)
+ printf("RTS thr:off ");
+ else
+ {
+ /* Fixed ? */
+ if(info->rts.fixed)
+ printf("RTS thr=");
+ else
+ printf("RTS thr:");
+
+ printf("%d B ", info->rts.value);
+ }
+ tokens += 3;
}
- /* Get frequency / channel */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0)
+ /* Display the fragmentation threshold */
+ if(info->has_frag)
{
- info->has_freq = 1;
- info->freq = wrq.u.freq;
+ /* A bit of clever formatting */
+ if(tokens > 10)
+ {
+ printf("\n ");
+ tokens = 0;
+ }
+ tokens +=4;
+
+ /* Disabled ? */
+ if(info->frag.disabled)
+ printf("Fragment thr:off");
+ else
+ {
+ /* Fixed ? */
+ if(info->frag.fixed)
+ printf("Fragment thr=");
+ else
+ printf("Fragment thr:");
+
+ printf("%d B ", info->frag.value);
+ }
}
- /* Get stats */
- if(if_getstats(ifname, &(info->stats)) == 0)
+ /* Formating */
+ if(tokens > 0)
+ printf("\n ");
+
+ /* Display encryption information */
+ /* Note : we display only the "current" key, use iwlist to list all keys */
+ if(info->has_key)
{
- info->has_stats = 1;
+ printf("Encryption key:");
+ if((info->key_flags & IW_ENCODE_DISABLED) || (info->key_size == 0))
+ printf("off\n ");
+ else
+ {
+ /* Display the key */
+ iw_print_key(buffer, info->key, info->key_size, info->key_flags);
+ printf("%s", buffer);
+
+ /* Other info... */
+ if((info->key_flags & IW_ENCODE_INDEX) > 1)
+ printf(" [%d]", info->key_flags & IW_ENCODE_INDEX);
+ if(info->key_flags & IW_ENCODE_RESTRICTED)
+ printf(" Encryption mode:restricted");
+ if(info->key_flags & IW_ENCODE_OPEN)
+ printf(" Encryption mode:open");
+ printf("\n ");
+ }
}
- /* Get ranges */
- strcpy(wrq.ifr_name, ifname);
- wrq.u.data.pointer = (caddr_t) &(info->range);
- wrq.u.data.length = 0;
- wrq.u.data.flags = 0;
- if(ioctl(skfd, SIOCGIWRANGE, &wrq) >= 0)
+ /* Display Power Management information */
+ /* Note : we display only one parameter, period or timeout. If a device
+ * (such as HiperLan) has both, the user need to use iwlist... */
+ if(info->has_power) /* I hope the device has power ;-) */
+ {
+ printf("Power Management");
+ /* Disabled ? */
+ if(info->power.disabled)
+ printf(":off\n ");
+ else
+ {
+ /* Let's check the value and its type */
+ if(info->power.flags & IW_POWER_TYPE)
+ {
+ iw_print_pm_value(buffer, info->power.value, info->power.flags);
+ printf("%s ", buffer);
+ }
+
+ /* Let's check the mode */
+ iw_print_pm_mode(buffer, info->power.flags);
+ printf("%s", buffer);
+
+ /* Let's check if nothing (simply on) */
+ if(info->power.flags == IW_POWER_ON)
+ printf(":on");
+ printf("\n ");
+ }
+ }
+
+ /* Display statistics */
+ if(info->has_stats)
{
- info->has_range = 1;
+ info->stats.qual.updated = 0x0; /* Not that reliable, disable */
+ iw_print_stats(buffer, &info->stats.qual, &info->range, info->has_range);
+ printf("Link %s\n", buffer);
+
+#if WIRELESS_EXT > 11
+ printf(" Rx invalid nwid:%d Rx invalid crypt:%d Rx invalid frag:%d\n Tx excessive retries:%d Invalid misc:%d Missed beacon:%d\n",
+ info->stats.discard.nwid,
+ info->stats.discard.code,
+ info->stats.discard.fragment,
+ info->stats.discard.retries,
+ info->stats.discard.misc,
+ info->stats.miss.beacon);
+#else /* WIRELESS_EXT > 11 */
+ printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
+ info->stats.discard.nwid,
+ info->stats.discard.code,
+ info->stats.discard.misc);
+#endif /* WIRELESS_EXT > 11 */
}
- return(0);
+ printf("\n");
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print on the screen in a neat fashion all the info we have collected
+ * on a device.
+ */
+static int
+print_info(int skfd,
+ char * ifname,
+ char * args[],
+ int count)
+{
+ struct wireless_info info;
+ int rc;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ rc = get_info(skfd, ifname, &info);
+ switch(rc)
+ {
+ case 0: /* Success */
+ /* Display it ! */
+ display_info(&info, ifname);
+ break;
+
+ case -ENOTSUP:
+ fprintf(stderr, "%-8.8s no wireless extensions.\n\n",
+ ifname);
+ break;
+
+ default:
+ fprintf(stderr, "%-8.8s %s\n\n", ifname, strerror(-rc));
+ }
+ return(rc);
}
+/************************* SETTING ROUTINES **************************/
+/*------------------------------------------------------------------*/
+/*
+ * Macro to handle errors when setting WE
+ * Print a nice error message and exit...
+ * We define them as macro so that "return" do the right thing.
+ * The "do {...} while(0)" is a standard trick
+ */
+#define ERR_SET_EXT(rname, request) \
+ fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \
+ rname, request)
+
+#define ABORT_ARG_NUM(rname, request) \
+ do { \
+ ERR_SET_EXT(rname, request); \
+ fprintf(stderr, " too few arguments.\n"); \
+ return(-1); \
+ } while(0)
+
+#define ABORT_ARG_TYPE(rname, request, arg) \
+ do { \
+ ERR_SET_EXT(rname, request); \
+ fprintf(stderr, " invalid argument \"%s\".\n", arg); \
+ return(-2); \
+ } while(0)
+
+#define ABORT_ARG_SIZE(rname, request, max) \
+ do { \
+ ERR_SET_EXT(rname, request); \
+ fprintf(stderr, " argument too big (max %d)\n", max); \
+ return(-3); \
+ } while(0)
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to push some Wireless Parameter in the driver
+ * Use standard wrapper and add pretty error message if fail...
+ */
+#define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \
+ do { \
+ if(iw_set_ext(skfd, ifname, request, wrq) < 0) { \
+ ERR_SET_EXT(rname, request); \
+ fprintf(stderr, " SET failed on device %-1.8s ; %s.\n", \
+ ifname, strerror(errno)); \
+ return(-5); \
+ } } while(0)
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to extract some Wireless Parameter out of the driver
+ * Use standard wrapper and add pretty error message if fail...
+ */
+#define IW_GET_EXT_ERR(skfd, ifname, request, wrq, rname) \
+ do { \
+ if(iw_get_ext(skfd, ifname, request, wrq) < 0) { \
+ ERR_SET_EXT(rname, request); \
+ fprintf(stderr, " GET failed on device %-1.8s ; %s.\n", \
+ ifname, strerror(errno)); \
+ return(-6); \
+ } } while(0)
+
+/*------------------------------------------------------------------*/
+/*
+ * Set the wireless options requested on command line
+ * This function is too long and probably should be split,
+ * because it look like the perfect definition of spaghetti code,
+ * 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 */
{
struct iwreq wrq;
int i;
- /* Set dev name */
- strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ /* if nothing after the device name - will never happen */
+ if(count < 1)
+ {
+ fprintf(stderr, "Error : too few arguments.\n");
+ return(-1);
+ }
/* The other args on the line specify options to be set... */
for(i = 0; i < count; i++)
{
- /* Set network ID */
- if(!strcmp(args[i], "nwid"))
+ /* ---------- Commit changes to driver ---------- */
+ if(!strncmp(args[i], "commit", 6))
{
- if(++i >= count)
- usage();
- if(!strcasecmp(args[i], "off"))
- wrq.u.nwid.on = 0;
+ /* No args */
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq,
+ "Commit changes");
+ continue;
+ }
+
+ /* ---------- Set network ID ---------- */
+ if((!strcasecmp(args[i], "nwid")) ||
+ (!strcasecmp(args[i], "domain")))
+ {
+ i++;
+ if(i >= count)
+ ABORT_ARG_NUM("Set NWID", SIOCSIWNWID);
+ if((!strcasecmp(args[i], "off")) ||
+ (!strcasecmp(args[i], "any")))
+ wrq.u.nwid.disabled = 1;
else
- if(sscanf(args[i], "%lX", &(wrq.u.nwid.nwid)) != 1)
- usage();
+ if(!strcasecmp(args[i], "on"))
+ {
+ /* Get old nwid */
+ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq,
+ "Set NWID");
+ wrq.u.nwid.disabled = 0;
+ }
else
- wrq.u.nwid.on = 1;
+ if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
+ != 1)
+ ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]);
+ else
+ wrq.u.nwid.disabled = 0;
+ wrq.u.nwid.fixed = 1;
- if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0)
- {
- fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
- return(-1);
- }
+ /* Set new nwid */
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq,
+ "Set NWID");
continue;
}
- /* Set frequency / channel */
+ /* ---------- Set frequency / channel ---------- */
if((!strncmp(args[i], "freq", 4)) ||
(!strcmp(args[i], "channel")))
{
+ double freq;
+
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
+ if(sscanf(args[i], "%lg", &(freq)) != 1)
+ ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]);
+ if(index(args[i], 'G')) freq *= GIGA;
+ if(index(args[i], 'M')) freq *= MEGA;
+ if(index(args[i], 'k')) freq *= KILO;
+
+ iw_float2freq(freq, &(wrq.u.freq));
+
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
+ "Set Frequency");
+ continue;
+ }
+
+ /* ---------- Set sensitivity ---------- */
+ if(!strncmp(args[i], "sens", 4))
+ {
if(++i >= count)
- {
- struct iw_range range;
- int k;
+ ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS);
+ if(sscanf(args[i], "%d", &(wrq.u.sens.value)) != 1)
+ ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]);
+
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq,
+ "Set Sensitivity");
+ continue;
+ }
+
+ /* ---------- Set encryption stuff ---------- */
+ if((!strncmp(args[i], "enc", 3)) ||
+ (!strcmp(args[i], "key")))
+ {
+ unsigned char key[IW_ENCODING_TOKEN_MAX];
- wrq.u.data.pointer = (caddr_t) ⦥
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE);
+
+ if(!strcasecmp(args[i], "on"))
+ {
+ /* Get old encryption information */
+ wrq.u.data.pointer = (caddr_t) key;
wrq.u.data.length = 0;
wrq.u.data.flags = 0;
- if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0)
+ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq,
+ "Set Encode");
+ wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
+ }
+ else
+ {
+ int gotone = 1;
+ int keylen;
+ int temp;
+
+ wrq.u.data.pointer = (caddr_t) NULL;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = 0;
+
+ /* -- Check for the key -- */
+ keylen = iw_in_key(args[i], key);
+ if(keylen > 0)
{
- fprintf(stderr, "SIOCGIWRANGE: %s\n", strerror(errno));
- return(-1);
+ wrq.u.data.length = keylen;
+ wrq.u.data.pointer = (caddr_t) key;
+ ++i;
+ gotone = 1;
}
- 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 for token index -- */
+ if((i < count) &&
+ (sscanf(args[i], "[%d]", &temp) == 1) &&
+ (temp > 0) && (temp < IW_ENCODE_INDEX))
+ {
+ wrq.u.encoding.flags |= temp;
+ ++i;
+ gotone = 1;
+ }
+
+ /* -- Check the various flags -- */
+ if(i < count)
+ {
+ if(!strcasecmp(args[i], "off"))
+ wrq.u.data.flags |= IW_ENCODE_DISABLED;
+ if(!strcasecmp(args[i], "open"))
+ wrq.u.data.flags |= IW_ENCODE_OPEN;
+ if(!strncasecmp(args[i], "restricted", 5))
+ wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
+ if(wrq.u.data.flags & IW_ENCODE_FLAGS)
+ {
+ ++i;
+ gotone = 1;
+ }
+ }
+ /* Pointer is absent in new API */
+ if(wrq.u.data.pointer == NULL)
+ wrq.u.data.flags |= IW_ENCODE_NOKEY;
+
+ if(!gotone)
+ ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]);
+ --i;
}
- 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;
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq,
+ "Set Encode");
+ continue;
+ }
- if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
+ /* ---------- Set ESSID ---------- */
+ if(!strcasecmp(args[i], "essid"))
+ {
+ char essid[IW_ESSID_MAX_SIZE + 1];
+
+ i++;
+ if(i >= count)
+ ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
+ if((!strcasecmp(args[i], "off")) ||
+ (!strcasecmp(args[i], "any")))
{
- fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
- return(-1);
+ wrq.u.essid.flags = 0;
+ essid[0] = '\0';
}
+ else
+ if(!strcasecmp(args[i], "on"))
+ {
+ /* Get old essid */
+ wrq.u.essid.pointer = (caddr_t) essid;
+ wrq.u.essid.length = 0;
+ wrq.u.essid.flags = 0;
+ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq,
+ "Set ESSID");
+ wrq.u.essid.flags = 1;
+ }
+ else
+ /* Check the size of what the user passed us to avoid
+ * buffer overflows */
+ if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
+ ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE);
+ else
+ {
+ int temp;
+
+ wrq.u.essid.flags = 1;
+ strcpy(essid, args[i]); /* Size checked, all clear */
+
+ /* Check for ESSID index */
+ if(((i+1) < count) &&
+ (sscanf(args[i+1], "[%d]", &temp) == 1) &&
+ (temp > 0) && (temp < IW_ENCODE_INDEX))
+ {
+ wrq.u.essid.flags = temp;
+ ++i;
+ }
+ }
+
+ wrq.u.essid.pointer = (caddr_t) essid;
+ wrq.u.essid.length = strlen(essid) + 1;
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq,
+ "Set ESSID");
continue;
}
- /* Here we have an unrecognised arg... */
- fprintf(stderr, "Invalid argument : %s\n", args[i]);
- usage();
- return(-1);
- } /* for(index ... */
- return(0);
-}
+ /* ---------- Set AP address ---------- */
+ if(!strcasecmp(args[i], "ap"))
+ {
+ if(++i >= count)
+ ABORT_ARG_NUM("Set AP Address", SIOCSIWAP);
-static void
-print_devices(char *ifname)
-{
- char buff[1024];
- struct wireless_info info;
- struct ifconf ifc;
- struct ifreq *ifr;
- int i;
+ if((!strcasecmp(args[i], "auto")) ||
+ (!strcasecmp(args[i], "any")))
+ {
+ /* Send a broadcast address */
+ iw_broad_ether(&(wrq.u.ap_addr));
+ }
+ else
+ {
+ if(!strcasecmp(args[i], "off"))
+ {
+ /* Send a NULL address */
+ iw_null_ether(&(wrq.u.ap_addr));
+ }
+ else
+ {
+ /* Get the address and check if the interface supports it */
+ if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
+ ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]);
+ }
+ }
- if(ifname == (char *)NULL)
- {
- ifc.ifc_len = sizeof(buff);
- ifc.ifc_buf = buff;
- if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq,
+ "Set AP Address");
+ continue;
+ }
+
+ /* ---------- Set NickName ---------- */
+ if(!strncmp(args[i], "nick", 4))
{
- fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
- return;
+ i++;
+ if(i >= count)
+ ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN);
+ if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
+ ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE);
+
+ wrq.u.essid.pointer = (caddr_t) args[i];
+ wrq.u.essid.length = strlen(args[i]) + 1;
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq,
+ "Set Nickname");
+ continue;
}
- ifr = ifc.ifc_req;
- for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
+ /* ---------- Set Bit-Rate ---------- */
+ if((!strncmp(args[i], "bit", 3)) ||
+ (!strcmp(args[i], "rate")))
{
- if(get_info(ifr->ifr_name, &info) < 0)
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE);
+ if(!strcasecmp(args[i], "auto"))
{
- /* Could skip this message ? */
- fprintf(stderr, "%-8.8s no wireless extensions.\n\n",
- ifr->ifr_name);
- continue;
+ wrq.u.bitrate.value = -1;
+ wrq.u.bitrate.fixed = 0;
}
+ else
+ {
+ if(!strcasecmp(args[i], "fixed"))
+ {
+ /* Get old bitrate */
+ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq,
+ "Set Bit Rate");
+ wrq.u.bitrate.fixed = 1;
+ }
+ else /* Should be a numeric value */
+ {
+ double brate;
- print_info(&info);
+ if(sscanf(args[i], "%lg", &(brate)) != 1)
+ ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]);
+ if(index(args[i], 'G')) brate *= GIGA;
+ if(index(args[i], 'M')) brate *= MEGA;
+ if(index(args[i], 'k')) brate *= KILO;
+ wrq.u.bitrate.value = (long) brate;
+ wrq.u.bitrate.fixed = 1;
+
+ /* Check for an additional argument */
+ if(((i+1) < count) &&
+ (!strcasecmp(args[i+1], "auto")))
+ {
+ wrq.u.bitrate.fixed = 0;
+ ++i;
+ }
+ if(((i+1) < count) &&
+ (!strcasecmp(args[i+1], "fixed")))
+ {
+ wrq.u.bitrate.fixed = 1;
+ ++i;
+ }
+ }
+ }
+
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq,
+ "Set Bit Rate");
+ continue;
}
- }
- else
- {
- if(get_info(ifname, &info) < 0)
+
+ /* ---------- Set RTS threshold ---------- */
+ if(!strncasecmp(args[i], "rts", 3))
{
- fprintf(stderr, "%s: no wireless extensions.\n",
- ifname);
- usage();
+ i++;
+ if(i >= count)
+ ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS);
+ wrq.u.rts.value = -1;
+ wrq.u.rts.fixed = 1;
+ wrq.u.rts.disabled = 0;
+ if(!strcasecmp(args[i], "off"))
+ wrq.u.rts.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[i], "auto"))
+ wrq.u.rts.fixed = 0;
+ else
+ {
+ if(!strcasecmp(args[i], "fixed"))
+ {
+ /* Get old RTS threshold */
+ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq,
+ "Set RTS Threshold");
+ wrq.u.rts.fixed = 1;
+ }
+ else /* Should be a numeric value */
+ if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value))
+ != 1)
+ ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]);
+ }
+
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq,
+ "Set RTS Threshold");
+ continue;
}
- else
- print_info(&info);
- }
-}
+ /* ---------- Set fragmentation threshold ---------- */
+ if(!strncmp(args[i], "frag", 4))
+ {
+ i++;
+ if(i >= count)
+ ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG);
+ wrq.u.frag.value = -1;
+ wrq.u.frag.fixed = 1;
+ wrq.u.frag.disabled = 0;
+ if(!strcasecmp(args[i], "off"))
+ wrq.u.frag.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[i], "auto"))
+ wrq.u.frag.fixed = 0;
+ else
+ {
+ if(!strcasecmp(args[i], "fixed"))
+ {
+ /* Get old fragmentation threshold */
+ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq,
+ "Set Fragmentation Threshold");
+ wrq.u.frag.fixed = 1;
+ }
+ else /* Should be a numeric value */
+ if(sscanf(args[i], "%ld",
+ (unsigned long *) &(wrq.u.frag.value))
+ != 1)
+ ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG,
+ args[i]);
+ }
+
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq,
+ "Set Fragmentation Threshold");
+ continue;
+ }
-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;
+ /* ---------- Set operation mode ---------- */
+ if(!strcmp(args[i], "mode"))
+ {
+ int k;
+
+ i++;
+ if(i >= count)
+ ABORT_ARG_NUM("Set Mode", SIOCSIWMODE);
+
+ if(sscanf(args[i], "%d", &k) != 1)
+ {
+ k = 0;
+ while((k < IW_NUM_OPER_MODE) &&
+ strncasecmp(args[i], iw_operation_mode[k], 3))
+ k++;
+ }
+ if((k >= IW_NUM_OPER_MODE) || (k < 0))
+ ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]);
+
+ wrq.u.mode = k;
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq,
+ "Set Mode");
+ continue;
+ }
+
+ /* ---------- Set Power Management ---------- */
+ if(!strncmp(args[i], "power", 3))
+ {
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+
+ if(!strcasecmp(args[i], "off"))
+ wrq.u.power.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[i], "on"))
+ {
+ /* Get old Power info */
+ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq,
+ "Set Power Management");
+ wrq.u.power.disabled = 0;
+ }
+ else
+ {
+ double temp;
+ int gotone = 0;
+ /* Default - nope */
+ wrq.u.power.flags = IW_POWER_ON;
+ wrq.u.power.disabled = 0;
+
+ /* Check value modifier */
+ if(!strcasecmp(args[i], "min"))
+ {
+ wrq.u.power.flags |= IW_POWER_MIN;
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+ }
+ else
+ if(!strcasecmp(args[i], "max"))
+ {
+ wrq.u.power.flags |= IW_POWER_MAX;
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+ }
+
+ /* Check value type */
+ if(!strcasecmp(args[i], "period"))
+ {
+ wrq.u.power.flags |= IW_POWER_PERIOD;
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+ }
+ else
+ if(!strcasecmp(args[i], "timeout"))
+ {
+ wrq.u.power.flags |= IW_POWER_TIMEOUT;
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
+ }
+
+ /* Is there any value to grab ? */
+ if(sscanf(args[i], "%lg", &(temp)) == 1)
+ {
+ temp *= MEGA; /* default = s */
+ if(index(args[i], 'u')) temp /= MEGA;
+ if(index(args[i], 'm')) temp /= KILO;
+ wrq.u.power.value = (long) temp;
+ if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
+ wrq.u.power.flags |= IW_POWER_PERIOD;
+ ++i;
+ gotone = 1;
+ }
+
+ /* Now, check the mode */
+ if(i < count)
+ {
+ if(!strcasecmp(args[i], "all"))
+ wrq.u.power.flags |= IW_POWER_ALL_R;
+ if(!strncasecmp(args[i], "unicast", 4))
+ wrq.u.power.flags |= IW_POWER_UNICAST_R;
+ if(!strncasecmp(args[i], "multicast", 5))
+ wrq.u.power.flags |= IW_POWER_MULTICAST_R;
+ if(!strncasecmp(args[i], "force", 5))
+ wrq.u.power.flags |= IW_POWER_FORCE_S;
+ if(!strcasecmp(args[i], "repeat"))
+ wrq.u.power.flags |= IW_POWER_REPEATER;
+ if(wrq.u.power.flags & IW_POWER_MODE)
+ {
+ ++i;
+ gotone = 1;
+ }
+ }
+ if(!gotone)
+ ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER,
+ args[i]);
+ --i;
+ }
+
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq,
+ "Set Power Management");
+ continue;
+ }
+
+#if WIRELESS_EXT > 9
+ /* ---------- Set Transmit-Power ---------- */
+ if(!strncmp(args[i], "txpower", 3))
+ {
+ struct iw_range range;
+
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW);
+
+ /* Extract range info */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ memset(&range, 0, sizeof(range));
+
+ /* Prepare the request */
+ wrq.u.txpower.value = -1;
+ wrq.u.txpower.fixed = 1;
+ wrq.u.txpower.disabled = 0;
+ wrq.u.data.flags = IW_TXPOW_DBM;
+ if(!strcasecmp(args[i], "off"))
+ wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
+ else
+ if(!strcasecmp(args[i], "auto"))
+ wrq.u.txpower.fixed = 0; /* i.e. use power control */
+ else
+ {
+ if(!strcasecmp(args[i], "fixed"))
+ {
+ /* Get old tx-power */
+ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
+ "Set Tx Power");
+ wrq.u.txpower.fixed = 1;
+ }
+ else /* Should be a numeric value */
+ {
+ int power;
+ int ismwatt = 0;
+
+ /* Get the value */
+ if(sscanf(args[i], "%ld",
+ (unsigned long *) &(power)) != 1)
+ ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW, args[i]);
+
+ /* Check if milliwatt */
+ ismwatt = (index(args[i], 'm') != NULL);
+
+ /* Convert */
+ if(range.txpower_capa & IW_TXPOW_MWATT)
+ {
+ if(!ismwatt)
+ power = iw_dbm2mwatt(power);
+ wrq.u.data.flags = IW_TXPOW_MWATT;
+ }
+ else
+ {
+ if(ismwatt)
+ power = iw_mwatt2dbm(power);
+ wrq.u.data.flags = IW_TXPOW_DBM;
+ }
+ wrq.u.bitrate.value = power;
+
+ /* Check for an additional argument */
+ if(((i+1) < count) &&
+ (!strcasecmp(args[i+1], "auto")))
+ {
+ wrq.u.txpower.fixed = 0;
+ ++i;
+ }
+ if(((i+1) < count) &&
+ (!strcasecmp(args[i+1], "fixed")))
+ {
+ wrq.u.txpower.fixed = 1;
+ ++i;
+ }
+ }
+ }
+
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq,
+ "Set Tx Power");
+ continue;
+ }
+#endif
+
+#if WIRELESS_EXT > 10
+ /* ---------- Set Retry limit ---------- */
+ if(!strncmp(args[i], "retry", 3))
+ {
+ double temp;
+ int gotone = 0;
+
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
+
+ /* Default - nope */
+ wrq.u.retry.flags = IW_RETRY_LIMIT;
+ wrq.u.retry.disabled = 0;
+
+ /* Check value modifier */
+ if(!strcasecmp(args[i], "min"))
+ {
+ wrq.u.retry.flags |= IW_RETRY_MIN;
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
+ }
+ else
+ if(!strcasecmp(args[i], "max"))
+ {
+ wrq.u.retry.flags |= IW_RETRY_MAX;
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
+ }
+
+ /* Check value type */
+ if(!strcasecmp(args[i], "limit"))
+ {
+ wrq.u.retry.flags |= IW_RETRY_LIMIT;
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
+ }
+ else
+ if(!strncasecmp(args[i], "lifetime", 4))
+ {
+ wrq.u.retry.flags |= IW_RETRY_LIFETIME;
+ if(++i >= count)
+ ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
+ }
+
+ /* Is there any value to grab ? */
+ if(sscanf(args[i], "%lg", &(temp)) == 1)
+ {
+ /* Limit is absolute, on the other hand lifetime is seconds */
+ if(!(wrq.u.retry.flags & IW_RETRY_LIMIT))
+ {
+ /* Normalise lifetime */
+ temp *= MEGA; /* default = s */
+ if(index(args[i], 'u')) temp /= MEGA;
+ if(index(args[i], 'm')) temp /= KILO;
+ }
+ wrq.u.retry.value = (long) temp;
+ ++i;
+ gotone = 1;
+ }
+
+ if(!gotone)
+ ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]);
+ --i;
+
+ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq,
+ "Set Retry Limit");
+ continue;
+ }
+
+#endif /* WIRELESS_EXT > 10 */
+
+ /* ---------- Other ---------- */
+ /* Here we have an unrecognised arg... */
+ fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
+ args[i]);
+ return(-1);
+ } /* for(index ... */
+ return(0);
}
-
+
+/******************************* MAIN ********************************/
+
+/*------------------------------------------------------------------*/
+/*
+ * The main !
+ */
int
main(int argc,
char ** argv)
{
+ int skfd; /* generic raw socket desc. */
int goterr = 0;
/* Create a channel to the NET kernel. */
- if((skfd = sockets_open()) < 0)
+ if((skfd = iw_sockets_open()) < 0)
{
perror("socket");
exit(-1);
/* No argument : show the list of all device + info */
if(argc == 1)
- {
- print_devices((char *)NULL);
- close(skfd);
- exit(0);
- }
-
- /* The device name must be the first argument */
- if(argc == 2)
- {
- print_devices(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]);
+ iw_enum_devices(skfd, &print_info, NULL, 0);
+ else
+ /* Special case for help... */
+ if((!strncmp(argv[1], "-h", 9)) ||
+ (!strcmp(argv[1], "--help")))
+ iw_usage();
+ else
+ /* The device name must be the first argument */
+ if(argc == 2)
+ print_info(skfd, argv[1], NULL, 0);
+ else
+ /* The other args on the line specify options to be set... */
+ goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
/* Close the socket. */
close(skfd);