/*
* Wireless Tools
*
- * Jean II - HPLB 97->99 - HPL 99->01
+ * Jean II - HPLB 97->99 - HPL 99->07
*
* Main code for "iwconfig". This is the generic tool for most
* manipulations...
- * You need to link this code against "iwcommon.c" and "-lm".
+ * You need to link this code against "iwlib.c" and "-lm".
*
* This file is released under the GPL license.
+ * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
*/
-#include "iwcommon.h" /* Header */
+#include "iwlib-private.h" /* Private header */
-/**************************** VARIABLES ****************************/
-char * operation_mode[] = { "Auto",
- "Ad-Hoc",
- "Managed",
- "Master",
- "Repeater",
- "Secondary" };
-
-/************************* MISC SUBROUTINES **************************/
+/**************************** CONSTANTS ****************************/
-/*------------------------------------------------------------------*/
/*
- * Print usage string
+ * Error codes defined for setting args
*/
-static void
-iw_usage(void)
-{
- 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");
- exit(1);
-}
-
+#define IWERR_ARG_NUM -2
+#define IWERR_ARG_TYPE -3
+#define IWERR_ARG_SIZE -4
+#define IWERR_ARG_CONFLICT -5
+#define IWERR_SET_EXT -6
+#define IWERR_GET_EXT -7
-/************************* DISPLAY ROUTINES **************************/
+/**************************** VARIABLES ****************************/
-/*------------------------------------------------------------------*/
/*
- * Read /proc/net/wireless to get the latest statistics
+ * Ugly, but deal with errors in set_info() efficiently...
*/
-static int
-iw_getstats(char * ifname,
- iwstats * stats)
-{
- FILE * f=fopen("/proc/net/wireless","r");
- char buf[256];
- char * bp;
- int t;
- if(f==NULL)
- return -1;
- /* Loop on all devices */
- while(fgets(buf,255,f))
- {
- bp=buf;
- while(*bp&&isspace(*bp))
- bp++;
- /* Is it the good device ? */
- if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
- {
- /* Skip ethX: */
- bp=strchr(bp,':');
- bp++;
- /* -- status -- */
- bp = strtok(bp, " ");
- sscanf(bp, "%X", &t);
- stats->status = (unsigned short) t;
- /* -- link quality -- */
- bp = strtok(NULL, " ");
- if(strchr(bp,'.') != NULL)
- stats->qual.updated |= 1;
- sscanf(bp, "%d", &t);
- stats->qual.qual = (unsigned char) t;
- /* -- signal level -- */
- bp = strtok(NULL, " ");
- if(strchr(bp,'.') != NULL)
- stats->qual.updated |= 2;
- sscanf(bp, "%d", &t);
- stats->qual.level = (unsigned char) t;
- /* -- noise level -- */
- bp = strtok(NULL, " ");
- if(strchr(bp,'.') != NULL)
- stats->qual.updated += 4;
- sscanf(bp, "%d", &t);
- stats->qual.noise = (unsigned char) t;
- /* -- discarded packets -- */
- bp = strtok(NULL, " ");
- sscanf(bp, "%d", &stats->discard.nwid);
- bp = strtok(NULL, " ");
- sscanf(bp, "%d", &stats->discard.code);
- bp = strtok(NULL, " ");
- sscanf(bp, "%d", &stats->discard.misc);
- fclose(f);
- return 0;
- }
- }
- fclose(f);
- return -1;
-}
+static int errarg;
+static int errmax;
+
+/************************* DISPLAY ROUTINES **************************/
/*------------------------------------------------------------------*/
/*
memset((char *) info, 0, sizeof(struct wireless_info));
- /* 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);
-
- /* Get ranges */
- if(get_range_info(skfd, ifname, &(info->range)) >= 0)
- info->has_range = 1;
-
- /* Get network ID */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0)
- {
- info->has_nwid = 1;
- memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
- }
-
- /* Get frequency / channel */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0)
- {
- info->has_freq = 1;
- info->freq = freq2float(&(wrq.u.freq));
- }
-
- /* Get sensitivity */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0)
+ /* Get basic information */
+ if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0)
{
- info->has_sens = 1;
- memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
- }
+ /* If no wireless name : no wireless extensions */
+ /* But let's check if the interface exists at all */
+ struct ifreq ifr;
- /* Get encryption information */
- strcpy(wrq.ifr_name, ifname);
- wrq.u.data.pointer = (caddr_t) info->key;
- wrq.u.data.length = 0;
- wrq.u.data.flags = 0;
- if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0)
- {
- info->has_key = 1;
- info->key_size = wrq.u.data.length;
- info->key_flags = wrq.u.data.flags;
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+ if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
+ return(-ENODEV);
+ else
+ return(-ENOTSUP);
}
- /* Get ESSID */
- strcpy(wrq.ifr_name, ifname);
- wrq.u.essid.pointer = (caddr_t) info->essid;
- wrq.u.essid.length = 0;
- wrq.u.essid.flags = 0;
- if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0)
- {
- info->has_essid = 1;
- info->essid_on = wrq.u.data.flags;
- }
+ /* Get ranges */
+ if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
+ info->has_range = 1;
/* Get AP address */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWAP, &wrq) >= 0)
+ if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
{
info->has_ap_addr = 1;
memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
}
- /* Get NickName */
- strcpy(wrq.ifr_name, ifname);
- wrq.u.essid.pointer = (caddr_t) info->nickname;
- wrq.u.essid.length = 0;
- wrq.u.essid.flags = 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)
+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
{
info->has_bitrate = 1;
memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
}
- /* Get RTS threshold */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0)
+ /* Get Power Management settings */
+ wrq.u.power.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
{
- info->has_rts = 1;
- memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
+ info->has_power = 1;
+ memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
}
- /* Get fragmentation threshold */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0)
+ /* Get stats */
+ if(iw_get_stats(skfd, ifname, &(info->stats),
+ &info->range, info->has_range) >= 0)
{
- info->has_frag = 1;
- memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
+ info->has_stats = 1;
}
- /* Get operation mode */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0)
+#ifndef WE_ESSENTIAL
+ /* Get NickName */
+ wrq.u.essid.pointer = (caddr_t) info->nickname;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 2;
+ wrq.u.essid.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
+ if(wrq.u.data.length > 1)
+ info->has_nickname = 1;
+
+ if((info->has_range) && (info->range.we_version_compiled > 9))
{
- if((wrq.u.mode < 6) && (wrq.u.mode >= 0))
- info->has_mode = 1;
- info->mode = wrq.u.mode;
+ /* Get Transmit Power */
+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
+ {
+ info->has_txpower = 1;
+ memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
+ }
}
- /* Get Power Management settings */
- strcpy(wrq.ifr_name, ifname);
- wrq.u.power.flags = 0;
- if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0)
+ /* Get sensitivity */
+ if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
{
- info->has_power = 1;
- memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
+ info->has_sens = 1;
+ memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
}
-#if WIRELESS_EXT > 9
- /* Get Transmit Power */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWTXPOW, &wrq) >= 0)
+ if((info->has_range) && (info->range.we_version_compiled > 10))
{
- info->has_txpower = 1;
- memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
+ /* 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
-#if WIRELESS_EXT > 10
- /* Get retry limit/lifetime */
- strcpy(wrq.ifr_name, ifname);
- if(ioctl(skfd, SIOCGIWRETRY, &wrq) >= 0)
+ /* Get RTS threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
{
- info->has_retry = 1;
- memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
+ info->has_rts = 1;
+ memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
}
-#endif /* WIRELESS_EXT > 10 */
- /* Get stats */
- if(iw_getstats(ifname, &(info->stats)) >= 0)
+ /* Get fragmentation threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
{
- info->has_stats = 1;
+ info->has_frag = 1;
+ memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
}
+#endif /* WE_ESSENTIAL */
return(0);
}
display_info(struct wireless_info * info,
char * ifname)
{
- /* One token is more of less 5 character, 14 tokens per line */
+ char buffer[256]; /* Temporary buffer */
+
+ /* One token is more of less 5 characters, 14 tokens per line */
int tokens = 3; /* For name */
/* Display device name and wireless name (name of the protocol used) */
- printf("%-8.8s %s ", ifname, info->name);
+ printf("%-8.16s %s ", ifname, info->b.name);
/* Display ESSID (extended network), if any */
- if(info->has_essid)
+ if(info->b.has_essid)
{
- if(info->essid_on)
+ if(info->b.essid_on)
{
+ /* Escape the non-printable characters */
+ iw_essid_escape(buffer, info->b.essid, info->b.essid_len);
/* 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));
+ if((info->b.essid_on & IW_ENCODE_INDEX) > 1)
+ printf("ESSID:\"%s\" [%d] ", buffer,
+ (info->b.essid_on & IW_ENCODE_INDEX));
else
- printf("ESSID:\"%s\" ", info->essid);
+ printf("ESSID:\"%s\" ", buffer);
}
else
- printf("ESSID:off ");
+ printf("ESSID:off/any ");
}
+#ifndef WE_ESSENTIAL
/* Display NickName (station name), if any */
if(info->has_nickname)
printf("Nickname:\"%s\"", info->nickname);
+#endif /* WE_ESSENTIAL */
/* Formatting */
- if(info->has_essid || info->has_nickname)
+ if(info->b.has_essid || info->has_nickname)
{
printf("\n ");
tokens = 0;
}
+#ifndef WE_ESSENTIAL
/* Display Network ID */
- if(info->has_nwid)
+ if(info->b.has_nwid)
{
- /* Note : should display right number of digit according to info
+ /* Note : should display proper number of digits according to info
* in range structure */
- if(info->nwid.disabled)
+ if(info->b.nwid.disabled)
printf("NWID:off/any ");
else
- printf("NWID:%X ", info->nwid.value);
+ printf("NWID:%X ", info->b.nwid.value);
tokens +=2;
}
+#endif /* WE_ESSENTIAL */
/* Display the current mode of operation */
- if(info->has_mode)
+ if(info->b.has_mode)
{
- printf("Mode:%s ", operation_mode[info->mode]);
+ printf("Mode:%s ", iw_operation_mode[info->b.mode]);
tokens +=3;
}
/* Display frequency / channel */
- if(info->has_freq)
+ if(info->b.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);
- }
- }
+ double freq = info->b.freq; /* Frequency/channel */
+ int channel = -1; /* Converted to channel */
+ /* Some drivers insist of returning channel instead of frequency.
+ * This fixes them up. Note that, driver should still return
+ * frequency, because other tools depend on it. */
+ if(info->has_range && (freq < KILO))
+ channel = iw_channel_to_freq((int) freq, &freq, &info->range);
+ /* Display */
+ iw_print_freq(buffer, sizeof(buffer), freq, -1, info->b.freq_flags);
+ printf("%s ", buffer);
tokens +=4;
}
tokens +=6;
/* Oups ! No Access Point in Ad-Hoc mode */
- if((info->has_mode) && (info->mode == IW_MODE_ADHOC))
+ if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC))
printf("Cell:");
else
printf("Access Point:");
- printf(" %s", pr_ether(info->ap_addr.sa_data));
+ printf(" %s ", iw_sawap_ntop(&info->ap_addr, buffer));
}
/* Display the currently used/set bit-rate */
}
tokens +=3;
- /* Fixed ? */
- if(info->bitrate.fixed)
- printf("Bit Rate=");
- else
- printf("Bit Rate:");
-
- if(info->bitrate.value >= GIGA)
- printf("%gGb/s", info->bitrate.value / GIGA);
- else
- if(info->bitrate.value >= MEGA)
- printf("%gMb/s", info->bitrate.value / MEGA);
- else
- printf("%gkb/s", info->bitrate.value / KILO);
- printf(" ");
+ /* Display it */
+ iw_print_bitrate(buffer, sizeof(buffer), info->bitrate.value);
+ printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
}
-#if WIRELESS_EXT > 9
+#ifndef WE_ESSENTIAL
/* Display the Transmit Power */
if(info->has_txpower)
{
}
tokens +=3;
- /* Disabled ? */
- if(info->txpower.disabled)
- printf("Tx-Power:off ");
- else
- {
- int dbm;
-
- /* Fixed ? */
- if(info->txpower.fixed)
- printf("Tx-Power=");
- else
- printf("Tx-Power:");
-
- /* Convert everything to dBm */
- if(info->txpower.flags & IW_TXPOW_MWATT)
- dbm = mwatt2dbm(info->txpower.value);
- else
- dbm = info->txpower.value;
-
- /* Display */
- printf("%d dBm ", dbm);
- }
+ /* Display it */
+ iw_print_txpower(buffer, sizeof(buffer), &info->txpower);
+ printf("Tx-Power%c%s ", (info->txpower.fixed ? '=' : ':'), buffer);
}
-#endif
/* Display sensitivity */
if(info->has_sens)
tokens +=4;
/* Fixed ? */
- if(info->sens.fixed)
- printf("Sensitivity=");
- else
- printf("Sensitivity:");
+ printf("Sensitivity%c", info->sens.fixed ? '=' : ':');
if(info->has_range)
/* Display in dBm ? */
else
printf("%d ", info->sens.value);
}
+#endif /* WE_ESSENTIAL */
printf("\n ");
tokens = 0;
-#if WIRELESS_EXT > 10
+#ifndef WE_ESSENTIAL
/* Display retry limit/lifetime information */
if(info->has_retry)
{
{
/* Let's check the value and its type */
if(info->retry.flags & IW_RETRY_TYPE)
- print_retry_value(stdout, info->retry.value, info->retry.flags);
+ {
+ iw_print_retry_value(buffer, sizeof(buffer),
+ info->retry.value, info->retry.flags,
+ info->range.we_version_compiled);
+ printf("%s", buffer);
+ }
/* Let's check if nothing (simply on) */
if(info->retry.flags == IW_RETRY_ON)
printf(" ");
tokens += 5; /* Between 3 and 5, depend on flags */
}
-#endif /* WIRELESS_EXT > 10 */
/* Display the RTS threshold */
if(info->has_rts)
else
{
/* Fixed ? */
- if(info->rts.fixed)
- printf("RTS thr=");
- else
- printf("RTS thr:");
-
- printf("%d B ", info->rts.value);
+ printf("RTS thr%c%d B ",
+ info->rts.fixed ? '=' : ':',
+ info->rts.value);
}
tokens += 3;
}
else
{
/* Fixed ? */
- if(info->frag.fixed)
- printf("Fragment thr=");
- else
- printf("Fragment thr:");
-
- printf("%d B ", info->frag.value);
+ printf("Fragment thr%c%d B ",
+ info->frag.fixed ? '=' : ':',
+ info->frag.value);
}
}
/* Formating */
if(tokens > 0)
printf("\n ");
+#endif /* WE_ESSENTIAL */
/* Display encryption information */
/* Note : we display only the "current" key, use iwlist to list all keys */
- if(info->has_key)
+ if(info->b.has_key)
{
printf("Encryption key:");
- if((info->key_flags & IW_ENCODE_DISABLED) || (info->key_size == 0))
- printf("off\n ");
+ if((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0))
+ printf("off");
else
{
/* Display the key */
- print_key(stdout, info->key, info->key_size, info->key_flags);
+ iw_print_key(buffer, sizeof(buffer),
+ info->b.key, info->b.key_size, info->b.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 ");
+ if((info->b.key_flags & IW_ENCODE_INDEX) > 1)
+ printf(" [%d]", info->b.key_flags & IW_ENCODE_INDEX);
+ if(info->b.key_flags & IW_ENCODE_RESTRICTED)
+ printf(" Security mode:restricted");
+ if(info->b.key_flags & IW_ENCODE_OPEN)
+ printf(" Security mode:open");
}
+ printf("\n ");
}
/* Display Power Management information */
printf("Power Management");
/* Disabled ? */
if(info->power.disabled)
- printf(":off\n ");
+ printf(":off");
else
{
/* Let's check the value and its type */
if(info->power.flags & IW_POWER_TYPE)
- print_pm_value(stdout, info->power.value, info->power.flags);
+ {
+ iw_print_pm_value(buffer, sizeof(buffer),
+ info->power.value, info->power.flags,
+ info->range.we_version_compiled);
+ printf("%s ", buffer);
+ }
/* Let's check the mode */
- print_pm_mode(stdout, info->power.flags);
+ iw_print_pm_mode(buffer, sizeof(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 ");
}
+ printf("\n ");
}
/* Display statistics */
if(info->has_stats)
{
- info->stats.qual.updated = 0x0; /* Not that reliable, disable */
- printf("Link ");
- print_stats(stdout, &info->stats.qual, &info->range, info->has_range);
-
- printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
- info->stats.discard.nwid,
- info->stats.discard.code,
- info->stats.discard.misc);
+ iw_print_stats(buffer, sizeof(buffer),
+ &info->stats.qual, &info->range, info->has_range);
+ printf("Link %s\n", buffer);
+
+ if(info->range.we_version_compiled > 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
+ 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
+static int
print_info(int skfd,
- char * ifname)
+ char * ifname,
+ char * args[],
+ int count)
{
struct wireless_info info;
+ int rc;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
- if(get_info(skfd, ifname, &info) < 0)
+ rc = get_info(skfd, ifname, &info);
+ switch(rc)
{
- fprintf(stderr, "%-8.8s no wireless extensions.\n\n",
+ case 0: /* Success */
+ /* Display it ! */
+ display_info(&info, ifname);
+ break;
+
+ case -ENOTSUP:
+ fprintf(stderr, "%-8.16s no wireless extensions.\n\n",
ifname);
- return;
- }
+ break;
- /* Display it ! */
- display_info(&info, ifname);
+ default:
+ fprintf(stderr, "%-8.16s %s\n\n", ifname, strerror(-rc));
+ }
+ return(rc);
}
+/****************** COMMAND LINE MODIFIERS PARSING ******************/
+/*
+ * Factor out the parsing of command line modifiers.
+ */
+
/*------------------------------------------------------------------*/
/*
- * Get info on all devices and print it on the screen
+ * Map command line modifiers to the proper flags...
*/
-static void
-print_devices(int skfd)
+typedef struct iwconfig_modifier {
+ const char * cmd; /* Command line shorthand */
+ __u16 flag; /* Flags to add */
+ __u16 exclude; /* Modifiers to exclude */
+} iwconfig_modifier;
+
+/*------------------------------------------------------------------*/
+/*
+ * Modifiers for Power
+ */
+static const struct iwconfig_modifier iwmod_power[] = {
+ { "min", IW_POWER_MIN, IW_POWER_MAX },
+ { "max", IW_POWER_MAX, IW_POWER_MIN },
+ { "period", IW_POWER_PERIOD, IW_POWER_TIMEOUT | IW_POWER_SAVING },
+ { "timeout", IW_POWER_TIMEOUT, IW_POWER_PERIOD | IW_POWER_SAVING },
+ { "saving", IW_POWER_SAVING, IW_POWER_TIMEOUT | IW_POWER_PERIOD },
+};
+#define IWMOD_POWER_NUM (sizeof(iwmod_power)/sizeof(iwmod_power[0]))
+
+/*------------------------------------------------------------------*/
+/*
+ * Modifiers for Retry
+ */
+#ifndef WE_ESSENTIAL
+static const struct iwconfig_modifier iwmod_retry[] = {
+ { "min", IW_RETRY_MIN, IW_RETRY_MAX },
+ { "max", IW_RETRY_MAX, IW_RETRY_MIN },
+ { "short", IW_RETRY_SHORT, IW_RETRY_LONG },
+ { "long", IW_RETRY_LONG, IW_RETRY_SHORT },
+ { "limit", IW_RETRY_LIMIT, IW_RETRY_LIFETIME },
+ { "lifetime", IW_RETRY_LIFETIME, IW_RETRY_LIMIT },
+};
+#define IWMOD_RETRY_NUM (sizeof(iwmod_retry)/sizeof(iwmod_retry[0]))
+#endif /* WE_ESSENTIAL */
+
+/*------------------------------------------------------------------*/
+/*
+ * Parse command line modifiers.
+ * Return error or number arg parsed.
+ * Modifiers must be at the beggining of command line.
+ */
+static int
+parse_modifiers(char * args[], /* Command line args */
+ int count, /* Args count */
+ __u16 * pout, /* Flags to write */
+ const struct iwconfig_modifier modifier[],
+ int modnum)
{
- char buff[1024];
- struct ifconf ifc;
- struct ifreq *ifr;
- int i;
+ int i = 0;
+ int k = 0;
+ __u16 result = 0; /* Default : no flag set */
- /* Get list of active devices */
- ifc.ifc_len = sizeof(buff);
- ifc.ifc_buf = buff;
- if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
+ /* Get all modifiers and value types on the command line */
+ do
{
- fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
- return;
+ for(k = 0; k < modnum; k++)
+ {
+ /* Check if matches */
+ if(!strcasecmp(args[i], modifier[k].cmd))
+ {
+ /* Check for conflicting flags */
+ if(result & modifier[k].exclude)
+ {
+ errarg = i;
+ return(IWERR_ARG_CONFLICT);
+ }
+ /* Just add it */
+ result |= modifier[k].flag;
+ ++i;
+ break;
+ }
+ }
}
- ifr = ifc.ifc_req;
+ /* For as long as current arg matched and not out of args */
+ while((i < count) && (k < modnum));
- /* Print them */
- for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
- print_info(skfd, ifr->ifr_name);
+ /* Check there remains one arg for value */
+ if(i >= count)
+ return(IWERR_ARG_NUM);
+
+ /* Return result */
+ *pout = result;
+ return(i);
}
-/************************* SETTING ROUTINES **************************/
+
+/*********************** SETTING SUB-ROUTINES ***********************/
+/*
+ * The following functions are use to set some wireless parameters and
+ * are called by the set dispatcher set_info().
+ * They take as arguments the remaining of the command line, with
+ * arguments processed already removed.
+ * An error is indicated by a negative return value.
+ * 0 and positive return values indicate the number of args consumed.
+ */
/*------------------------------------------------------------------*/
/*
- * 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
+ * Set ESSID
*/
static int
-set_info(int skfd, /* The socket */
- char * args[], /* Command line args */
- int count, /* Args count */
- char * ifname) /* Dev name */
+set_essid_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
{
struct iwreq wrq;
- int i;
+ int i = 1;
+ char essid[4*IW_ESSID_MAX_SIZE + 1];
+ int essid_len;
+ int essid_index;
+ int we_kernel_version;
+
+ if((!strcasecmp(args[0], "off")) ||
+ (!strcasecmp(args[0], "any")))
+ {
+ wrq.u.essid.flags = 0;
+ essid[0] = '\0';
+ essid_len = 0;
+ }
+ else
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old essid */
+ memset(essid, '\0', sizeof(essid));
+ wrq.u.essid.pointer = (caddr_t) essid;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 2;
+ wrq.u.essid.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.essid.flags = 1;
+ essid_len = wrq.u.essid.length;
+ }
+ else
+ {
+ i = 0;
+
+ /* '-' or '--' allow to escape the ESSID string, allowing
+ * to set it to the string "any" or "off".
+ * This is a big ugly, but it will do for now */
+ if((!strcmp(args[0], "-")) || (!strcmp(args[0], "--")))
+ {
+ if(++i >= count)
+ return(IWERR_ARG_NUM);
+ essid_len = strlen(args[i]);
+ }
+
+ /* First size check : check if ot fits in our internal buffer.
+ * We do a two pass size check because of unescaping */
+ if(strlen(args[i]) > (4*IW_ESSID_MAX_SIZE))
+ {
+ errmax = IW_ESSID_MAX_SIZE;
+ return(IWERR_ARG_SIZE);
+ }
+
+ /* Unescape the ESSID to allow the user to enter weird chars */
+ essid_len = iw_essid_unescape(essid, args[i]);
+
+ /* Check the size to see if it fits the API. */
+ if(essid_len > IW_ESSID_MAX_SIZE)
+ {
+ errmax = IW_ESSID_MAX_SIZE;
+ return(IWERR_ARG_SIZE);
+ }
+
+ wrq.u.essid.flags = 1;
+ i++;
+
+ /* Check for ESSID index */
+ if((i < count) &&
+ (sscanf(args[i], "[%i]", &essid_index) == 1) &&
+ (essid_index > 0) && (essid_index < IW_ENCODE_INDEX))
+ {
+ wrq.u.essid.flags = essid_index;
+ ++i;
+ }
+ }
+
+ /* Get version from kernel, device may not have range... */
+ we_kernel_version = iw_get_kernel_we_version();
+
+ /* Finally set the ESSID value */
+ wrq.u.essid.pointer = (caddr_t) essid;
+ wrq.u.essid.length = essid_len;
+ if(we_kernel_version < 21)
+ wrq.u.essid.length++;
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var args */
+ return(i);
+}
- /* Set dev name */
- strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+/*------------------------------------------------------------------*/
+/*
+ * Set Mode
+ */
+static int
+set_mode_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ unsigned int k; /* Must be unsigned */
- /* if nothing after the device name */
- if(count<1)
- iw_usage();
+ /* Avoid "Unused parameter" warning */
+ count = count;
- /* The other args on the line specify options to be set... */
- for(i = 0; i < count; i++)
+ /* Check if it is a uint, otherwise get is as a string */
+ if(sscanf(args[0], "%i", &k) != 1)
{
- /* ---------- Set network ID ---------- */
- if((!strcasecmp(args[i], "nwid")) ||
- (!strcasecmp(args[i], "domain")))
- {
- i++;
- if(i >= count)
- iw_usage();
- if((!strcasecmp(args[i], "off")) ||
- (!strcasecmp(args[i], "any")))
- wrq.u.nwid.disabled = 1;
- else
- 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.disabled = 0;
- }
- else
- if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
- != 1)
- iw_usage();
- 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);
- }
- continue;
- }
+ k = 0;
+ while((k < IW_NUM_OPER_MODE) &&
+ strncasecmp(args[0], iw_operation_mode[k], 3))
+ k++;
+ }
+ if(k >= IW_NUM_OPER_MODE)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
- /* ---------- Set frequency / channel ---------- */
- if((!strncmp(args[i], "freq", 4)) ||
- (!strcmp(args[i], "channel")))
- {
- double freq;
+ wrq.u.mode = k;
+ if(iw_set_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
+ return(IWERR_SET_EXT);
- 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;
+ /* 1 arg */
+ return(1);
+}
- float2freq(freq, &(wrq.u.freq));
+/*------------------------------------------------------------------*/
+/*
+ * Set frequency/channel
+ */
+static int
+set_freq_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
- if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
- {
- fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
- return(-1);
- }
- continue;
+ if(!strcasecmp(args[0], "auto"))
+ {
+ wrq.u.freq.m = -1;
+ wrq.u.freq.e = 0;
+ wrq.u.freq.flags = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old frequency */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.freq.flags = IW_FREQ_FIXED;
}
-
- /* ---------- Set sensitivity ---------- */
- if(!strncmp(args[i], "sens", 4))
+ else /* Should be a numeric value */
{
- if(++i >= count)
- iw_usage();
- if(sscanf(args[i], "%d", &(wrq.u.sens.value)) != 1)
- iw_usage();
+ double freq;
+ char * unit;
- if(ioctl(skfd, SIOCSIWSENS, &wrq) < 0)
+ freq = strtod(args[0], &unit);
+ if(unit == args[0])
{
- fprintf(stderr, "SIOCSIWSENS: %s\n", strerror(errno));
- return(-1);
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ if(unit != NULL)
+ {
+ if(unit[0] == 'G') freq *= GIGA;
+ if(unit[0] == 'M') freq *= MEGA;
+ if(unit[0] == 'k') freq *= KILO;
}
- continue;
- }
- /* ---------- Set encryption stuff ---------- */
- if((!strncmp(args[i], "enc", 3)) ||
- (!strcmp(args[i], "key")))
- {
- unsigned char key[IW_ENCODING_TOKEN_MAX];
+ iw_float2freq(freq, &(wrq.u.freq));
- if(++i >= count)
- iw_usage();
+ wrq.u.freq.flags = IW_FREQ_FIXED;
- if(!strcasecmp(args[i], "on"))
+ /* Check for an additional argument */
+ if((i < count) && (!strcasecmp(args[i], "auto")))
{
- /* Get old encryption information */
- wrq.u.data.pointer = (caddr_t) key;
- wrq.u.data.length = 0;
- wrq.u.data.flags = 0;
- if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
- {
- fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
- return(-1);
- }
- strcpy(wrq.ifr_name, ifname);
- wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
+ wrq.u.freq.flags = 0;
+ ++i;
}
- else
+ if((i < count) && (!strcasecmp(args[i], "fixed")))
{
- char * buff;
- char * p;
- int temp;
- int k = 0;
- int gotone = 1;
-
- wrq.u.data.pointer = (caddr_t) NULL;
- wrq.u.data.flags = 0;
- wrq.u.data.length = 0;
-
- /* -- Check for the key -- */
- if(!strncmp(args[i], "s:", 2))
- {
- /* First case : as an ASCII string */
- wrq.u.data.length = strlen(args[i] + 2);
- if(wrq.u.data.length > IW_ENCODING_TOKEN_MAX)
- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
- strncpy(key, args[i] + 2, wrq.u.data.length);
- wrq.u.data.pointer = (caddr_t) key;
- ++i;
- gotone = 1;
- }
- else
- {
- /* Second case : has hexadecimal digits */
- p = buff = malloc(strlen(args[i]) + 1);
- strcpy(buff, args[i]);
+ wrq.u.freq.flags = IW_FREQ_FIXED;
+ ++i;
+ }
+ }
+ }
- p = strtok(buff, "-:;.,");
- while(p != (char *) NULL)
- {
- if(sscanf(p, "%2X", &temp) != 1)
- {
- gotone = 0;
- break;
- }
- key[k++] = (unsigned char) (temp & 0xFF);
- if(strlen(p) > 2) /* Token not finished yet */
- p += 2;
- else
- p = strtok((char *) NULL, "-:;.,");
- }
- free(buff);
+ if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
+ return(IWERR_SET_EXT);
- if(gotone)
- {
- ++i;
- wrq.u.data.length = k;
- wrq.u.data.pointer = (caddr_t) key;
- }
- }
+ /* Var args */
+ return(i);
+}
- /* -- 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;
- }
+/*------------------------------------------------------------------*/
+/*
+ * Set Bit Rate
+ */
+static int
+set_bitrate_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 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;
- }
- }
+ wrq.u.bitrate.flags = 0;
+ if(!strcasecmp(args[0], "auto"))
+ {
+ wrq.u.bitrate.value = -1;
+ wrq.u.bitrate.fixed = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old bitrate */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.bitrate.fixed = 1;
+ }
+ else /* Should be a numeric value */
+ {
+ double brate;
+ char * unit;
- if(!gotone)
- iw_usage();
- --i;
+ brate = strtod(args[0], &unit);
+ if(unit == args[0])
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
-
- if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0)
+ if(unit != NULL)
{
- fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
- errno, strerror(errno));
- return(-1);
+ if(unit[0] == 'G') brate *= GIGA;
+ if(unit[0] == 'M') brate *= MEGA;
+ if(unit[0] == 'k') brate *= KILO;
}
- continue;
- }
-
- /* ---------- Set ESSID ---------- */
- if(!strcasecmp(args[i], "essid"))
- {
- char essid[IW_ESSID_MAX_SIZE + 1];
+ wrq.u.bitrate.value = (long) brate;
+ wrq.u.bitrate.fixed = 1;
- i++;
- if(i >= count)
- iw_usage();
- if((!strcasecmp(args[i], "off")) ||
- (!strcasecmp(args[i], "any")))
+ /* Check for an additional argument */
+ if((i < count) && (!strcasecmp(args[i], "auto")))
{
- wrq.u.essid.flags = 0;
- essid[0] = '\0';
+ wrq.u.bitrate.fixed = 0;
+ ++i;
}
- 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;
- if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0)
- {
- fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno));
- return(-1);
- }
- strcpy(wrq.ifr_name, ifname);
- wrq.u.essid.flags = 1;
- }
- else
- if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
- {
- fprintf(stderr, "ESSID too long (max %d): ``%s''\n",
- IW_ESSID_MAX_SIZE, args[i]);
- iw_usage();
- }
- else
- {
- int temp;
-
- wrq.u.essid.flags = 1;
- strcpy(essid, args[i]);
-
- /* 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;
- if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0)
+ if((i < count) && (!strcasecmp(args[i], "fixed")))
{
- fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
- return(-1);
+ wrq.u.bitrate.fixed = 1;
+ ++i;
}
- continue;
- }
-
- /* ---------- Set AP address ---------- */
- if(!strcasecmp(args[i], "ap"))
- {
- if(++i >= count)
- iw_usage();
-
- /* Check if we have valid address types */
- if(check_addr_type(skfd, ifname) < 0)
+ if((i < count) && (!strcasecmp(args[i], "unicast")))
{
- fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname);
- return(-1);
+ wrq.u.bitrate.flags |= IW_BITRATE_UNICAST;
+ ++i;
}
-
- /* Get the address */
- if(in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
- iw_usage();
-
- if(ioctl(skfd, SIOCSIWAP, &wrq) < 0)
+ if((i < count) && (!strcasecmp(args[i], "broadcast")))
{
- fprintf(stderr, "SIOCSIWAP: %s\n", strerror(errno));
- return(-1);
+ wrq.u.bitrate.flags |= IW_BITRATE_BROADCAST;
+ ++i;
}
- continue;
}
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWRATE, &wrq) < 0)
+ return(IWERR_SET_EXT);
- /* ---------- Set NickName ---------- */
- if(!strncmp(args[i], "nick", 4))
+ /* Var args */
+ return(i);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set encryption
+ */
+static int
+set_enc_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
+ unsigned char key[IW_ENCODING_TOKEN_MAX];
+
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old encryption information */
+ wrq.u.data.pointer = (caddr_t) key;
+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
+ wrq.u.data.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */
+ }
+ else
+ {
+ int gotone = 0;
+ int oldone;
+ int keylen;
+ int temp;
+
+ wrq.u.data.pointer = (caddr_t) NULL;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = 0;
+ i = 0;
+
+ /* Allow arguments in any order (it's safe) */
+ do
{
- i++;
- if(i >= count)
- iw_usage();
- if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
+ oldone = gotone;
+
+ /* -- Check for the key -- */
+ if(i < count)
{
- fprintf(stderr, "Name too long (max %d) : ``%s''\n",
- IW_ESSID_MAX_SIZE, args[i]);
- iw_usage();
+ keylen = iw_in_key_full(skfd, ifname,
+ args[i], key, &wrq.u.data.flags);
+ if(keylen > 0)
+ {
+ wrq.u.data.length = keylen;
+ wrq.u.data.pointer = (caddr_t) key;
+ ++i;
+ gotone++;
+ }
}
- wrq.u.essid.pointer = (caddr_t) args[i];
- wrq.u.essid.length = strlen(args[i]) + 1;
- if(ioctl(skfd, SIOCSIWNICKN, &wrq) < 0)
+ /* -- Check for token index -- */
+ if((i < count) &&
+ (sscanf(args[i], "[%i]", &temp) == 1) &&
+ (temp > 0) && (temp < IW_ENCODE_INDEX))
{
- fprintf(stderr, "SIOCSIWNICKN: %s\n", strerror(errno));
- return(-1);
+ wrq.u.encoding.flags |= temp;
+ ++i;
+ gotone++;
}
- continue;
- }
- /* ---------- Set Bit-Rate ---------- */
- if((!strncmp(args[i], "bit", 3)) ||
- (!strcmp(args[i], "rate")))
- {
- if(++i >= count)
- iw_usage();
- if(!strcasecmp(args[i], "auto"))
+ /* -- Check the various flags -- */
+ if((i < count) && (!strcasecmp(args[i], "off")))
{
- wrq.u.bitrate.value = -1;
- wrq.u.bitrate.fixed = 0;
+ wrq.u.data.flags |= IW_ENCODE_DISABLED;
+ ++i;
+ gotone++;
}
- else
+ if((i < count) && (!strcasecmp(args[i], "open")))
{
- 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);
- wrq.u.bitrate.fixed = 1;
- }
- 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;
-
- /* 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;
- }
- }
+ wrq.u.data.flags |= IW_ENCODE_OPEN;
+ ++i;
+ gotone++;
}
-
- if(ioctl(skfd, SIOCSIWRATE, &wrq) < 0)
+ if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
{
- fprintf(stderr, "SIOCSIWRATE: %s\n", strerror(errno));
- return(-1);
- }
- continue;
- }
-
- /* ---------- Set RTS threshold ---------- */
- if(!strncasecmp(args[i], "rts", 3))
- {
- i++;
- if(i >= count)
- iw_usage();
- 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 */
- if(ioctl(skfd, SIOCGIWRTS, &wrq) < 0)
- {
- fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno));
- return(-1);
- }
- strcpy(wrq.ifr_name, ifname);
- wrq.u.rts.fixed = 1;
- }
- else /* Should be a numeric value */
- if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value))
- != 1)
- iw_usage();
+ wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
+ ++i;
+ gotone++;
}
-
- if(ioctl(skfd, SIOCSIWRTS, &wrq) < 0)
+ if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
{
- fprintf(stderr, "SIOCSIWRTS: %s\n", strerror(errno));
- return(-1);
+ wrq.u.data.flags |= IW_ENCODE_TEMP;
+ ++i;
+ gotone++;
}
- continue;
}
+ while(gotone != oldone);
- /* ---------- Set fragmentation threshold ---------- */
- if(!strncmp(args[i], "frag", 4))
+ /* Pointer is absent in new API */
+ if(wrq.u.data.pointer == NULL)
+ wrq.u.data.flags |= IW_ENCODE_NOKEY;
+
+ /* Check if we have any invalid argument */
+ if(!gotone)
{
- i++;
- if(i >= count)
- iw_usage();
- 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;
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var arg */
+ return(i);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Power Management
+ */
+static int
+set_power_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
+
+ if(!strcasecmp(args[0], "off"))
+ wrq.u.power.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old Power info */
+ wrq.u.power.flags = 0;
+ if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.power.disabled = 0;
+ }
+ else
+ {
+ double value;
+ char * unit;
+ int gotone = 0;
+
+ /* Parse modifiers */
+ i = parse_modifiers(args, count, &wrq.u.power.flags,
+ iwmod_power, IWMOD_POWER_NUM);
+ if(i < 0)
+ return(i);
+
+ wrq.u.power.disabled = 0;
+
+ /* Is there any value to grab ? */
+ value = strtod(args[i], &unit);
+ if(unit != args[i])
+ {
+ struct iw_range range;
+ int flags;
+ /* Extract range info to handle properly 'relative' */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ memset(&range, 0, sizeof(range));
+
+ /* Get the flags to be able to do the proper conversion */
+ switch(wrq.u.power.flags & IW_POWER_TYPE)
+ {
+ case IW_POWER_SAVING:
+ flags = range.pms_flags;
+ break;
+ case IW_POWER_TIMEOUT:
+ flags = range.pmt_flags;
+ break;
+ default:
+ flags = range.pmp_flags;
+ break;
+ }
+ /* Check if time or relative */
+ if(flags & IW_POWER_RELATIVE)
+ {
+ if(range.we_version_compiled < 21)
+ value *= MEGA;
+ else
+ wrq.u.power.flags |= IW_POWER_RELATIVE;
+ }
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);
- wrq.u.frag.fixed = 1;
- }
- else /* Should be a numeric value */
- if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.frag.value))
- != 1)
- iw_usage();
- }
+ value *= MEGA; /* default = s */
+ if(unit[0] == 'u') value /= MEGA;
+ if(unit[0] == 'm') value /= KILO;
+ }
+ wrq.u.power.value = (long) value;
+ /* Set some default type if none */
+ 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)
+ {
+ errarg = i;
+ return(IWERR_ARG_TYPE);
+ }
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWPOWER, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var args */
+ return(i);
+}
- if(ioctl(skfd, SIOCSIWFRAG, &wrq) < 0)
- {
- fprintf(stderr, "SIOCSIWFRAG: %s\n", strerror(errno));
- return(-1);
- }
- continue;
- }
+#ifndef WE_ESSENTIAL
+/*------------------------------------------------------------------*/
+/*
+ * Set Nickname
+ */
+static int
+set_nick_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int we_kernel_version;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ if(strlen(args[0]) > IW_ESSID_MAX_SIZE)
+ {
+ errmax = IW_ESSID_MAX_SIZE;
+ return(IWERR_ARG_SIZE);
+ }
+
+ we_kernel_version = iw_get_kernel_we_version();
+
+ wrq.u.essid.pointer = (caddr_t) args[0];
+ wrq.u.essid.length = strlen(args[0]);
+ if(we_kernel_version < 21)
+ wrq.u.essid.length++;
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWNICKN, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 args */
+ return(1);
+}
- /* ---------- Set operation mode ---------- */
- if(!strcmp(args[i], "mode"))
+/*------------------------------------------------------------------*/
+/*
+ * Set commit
+ */
+static int
+set_nwid_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ unsigned long temp;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ if((!strcasecmp(args[0], "off")) ||
+ (!strcasecmp(args[0], "any")))
+ wrq.u.nwid.disabled = 1;
+ else
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old nwid */
+ if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.nwid.disabled = 0;
+ }
+ else
+ if(sscanf(args[0], "%lX", &(temp)) != 1)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ else
{
- int k;
+ wrq.u.nwid.value = temp;
+ wrq.u.nwid.disabled = 0;
+ }
- i++;
- if(i >= count)
- iw_usage();
+ wrq.u.nwid.fixed = 1;
- if(sscanf(args[i], "%d", &k) != 1)
- {
- k = 0;
- while(k < 6 && strncasecmp(args[i], operation_mode[k], 3))
- k++;
- }
- if((k > 5) || (k < 0))
- iw_usage();
+ /* Set new nwid */
+ if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 arg */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set AP Address
+ */
+static int
+set_apaddr_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
- wrq.u.mode = k;
- if(ioctl(skfd, SIOCSIWMODE, &wrq) < 0)
+ if((!strcasecmp(args[0], "auto")) ||
+ (!strcasecmp(args[0], "any")))
+ {
+ /* Send a broadcast address */
+ iw_broad_ether(&(wrq.u.ap_addr));
+ }
+ else
+ {
+ if(!strcasecmp(args[0], "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[0], &(wrq.u.ap_addr)) < 0)
{
- fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
- return(-1);
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
- continue;
}
+ }
- /* ---------- Set Power Management ---------- */
- if(!strncmp(args[i], "power", 3))
- {
- if(++i >= count)
- iw_usage();
+ if(iw_set_ext(skfd, ifname, SIOCSIWAP, &wrq) < 0)
+ return(IWERR_SET_EXT);
- if(!strcasecmp(args[i], "off"))
- wrq.u.power.disabled = 1; /* i.e. max size */
- else
- if(!strcasecmp(args[i], "on"))
+ /* 1 args */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Tx Power
+ */
+static int
+set_txpower_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ /* Prepare the request */
+ wrq.u.txpower.value = -1;
+ wrq.u.txpower.fixed = 1;
+ wrq.u.txpower.disabled = 0;
+ wrq.u.txpower.flags = IW_TXPOW_DBM;
+
+ if(!strcasecmp(args[0], "off"))
+ wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
+ else
+ if(!strcasecmp(args[0], "auto"))
+ wrq.u.txpower.fixed = 0; /* i.e. use power control */
+ else
+ {
+ if(!strcasecmp(args[0], "on"))
+ {
+ /* Get old tx-power */
+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.txpower.disabled = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
{
- /* Get old Power info */
- if(ioctl(skfd, SIOCGIWPOWER, &wrq) < 0)
- {
- fprintf(stderr, "SIOCGIWPOWER: %s\n", strerror(errno));
- return(-1);
- }
- strcpy(wrq.ifr_name, ifname);
- wrq.u.power.disabled = 0;
+ /* Get old tx-power */
+ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.txpower.fixed = 1;
+ wrq.u.txpower.disabled = 0;
}
- else
+ else /* Should be a numeric value */
{
- 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"))
+ int power;
+ int ismwatt = 0;
+ struct iw_range range;
+
+ /* Extract range info to do proper conversion */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ memset(&range, 0, sizeof(range));
+
+ /* Get the value */
+ if(sscanf(args[0], "%i", &(power)) != 1)
{
- wrq.u.power.flags |= IW_POWER_MIN;
- if(++i >= count)
- iw_usage();
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
- else
- if(!strcasecmp(args[i], "max"))
- {
- wrq.u.power.flags |= IW_POWER_MAX;
- if(++i >= count)
- iw_usage();
- }
- /* Check value type */
- if(!strcasecmp(args[i], "period"))
+ /* Check if milliWatt
+ * We authorise a single 'm' as a shorthand for 'mW',
+ * on the other hand a 'd' probably means 'dBm'... */
+ ismwatt = ((strchr(args[0], 'm') != NULL)
+ && (strchr(args[0], 'd') == NULL));
+
+ /* We could check 'W' alone... Another time... */
+
+ /* Convert */
+ if(range.txpower_capa & IW_TXPOW_RELATIVE)
{
- wrq.u.power.flags |= IW_POWER_PERIOD;
- if(++i >= count)
- iw_usage();
+ /* Can't convert */
+ if(ismwatt)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ wrq.u.txpower.flags = IW_TXPOW_RELATIVE;
}
else
- if(!strcasecmp(args[i], "timeout"))
+ if(range.txpower_capa & IW_TXPOW_MWATT)
+ {
+ if(!ismwatt)
+ power = iw_dbm2mwatt(power);
+ wrq.u.txpower.flags = IW_TXPOW_MWATT;
+ }
+ else
{
- wrq.u.power.flags |= IW_POWER_TIMEOUT;
- if(++i >= count)
- iw_usage();
+ if(ismwatt)
+ power = iw_mwatt2dbm(power);
+ wrq.u.txpower.flags = IW_TXPOW_DBM;
}
+ wrq.u.txpower.value = power;
- /* Is there any value to grab ? */
- if(sscanf(args[i], "%lg", &(temp)) == 1)
+ /* Check for an additional argument */
+ if((i < count) && (!strcasecmp(args[i], "auto")))
{
- 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;
+ wrq.u.txpower.fixed = 0;
++i;
- gotone = 1;
}
-
- /* Now, check the mode */
- if(i < count)
+ if((i < count) && (!strcasecmp(args[i], "fixed")))
{
- 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;
- }
+ wrq.u.txpower.fixed = 1;
+ ++i;
}
- if(!gotone)
- iw_usage();
- --i;
}
+ }
+ }
- if(ioctl(skfd, SIOCSIWPOWER, &wrq) < 0)
- {
- fprintf(stderr, "SIOCSIWPOWER(%d): %s\n",
- errno, strerror(errno));
- return(-1);
- }
- continue;
- }
+ if(iw_set_ext(skfd, ifname, SIOCSIWTXPOW, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var args */
+ return(i);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Sensitivity
+ */
+static int
+set_sens_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int temp;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ if(sscanf(args[0], "%i", &(temp)) != 1)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ wrq.u.sens.value = temp;
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWSENS, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* 1 arg */
+ return(1);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set Retry Limit
+ */
+static int
+set_retry_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 0;
+ double value;
+ char * unit;
+
+ /* Parse modifiers */
+ i = parse_modifiers(args, count, &wrq.u.retry.flags,
+ iwmod_retry, IWMOD_RETRY_NUM);
+ if(i < 0)
+ return(i);
+
+ /* Add default type if none */
+ if((wrq.u.retry.flags & IW_RETRY_TYPE) == 0)
+ wrq.u.retry.flags |= IW_RETRY_LIMIT;
+
+ wrq.u.retry.disabled = 0;
+
+ /* Is there any value to grab ? */
+ value = strtod(args[i], &unit);
+ if(unit == args[i])
+ {
+ errarg = i;
+ return(IWERR_ARG_TYPE);
+ }
-#if WIRELESS_EXT > 9
- /* ---------- Set Transmit-Power ---------- */
- if(!strncmp(args[i], "txpower", 3))
+ /* Limit is absolute, on the other hand lifetime is seconds */
+ if(wrq.u.retry.flags & IW_RETRY_LIFETIME)
+ {
+ struct iw_range range;
+ /* Extract range info to handle properly 'relative' */
+ if(iw_get_range_info(skfd, ifname, &range) < 0)
+ memset(&range, 0, sizeof(range));
+
+ if(range.r_time_flags & IW_RETRY_RELATIVE)
{
- struct iw_range range;
-
- if(++i >= count)
- iw_usage();
-
- /* Extract range info */
- if(get_range_info(skfd, ifname, &range) < 0)
- memset(&range, 0, sizeof(range));
-
- /* Prepare the request */
- strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
- wrq.u.txpower.value = -1;
- wrq.u.txpower.fixed = 1;
- wrq.u.txpower.disabled = 0;
- wrq.u.data.flags = IW_TXPOW_DBM;
- if(!strcasecmp(args[i], "off"))
- wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
+ if(range.we_version_compiled < 21)
+ value *= MEGA;
else
- if(!strcasecmp(args[i], "auto"))
- wrq.u.txpower.fixed = 0; /* i.e. use power control */
- else
+ wrq.u.retry.flags |= IW_RETRY_RELATIVE;
+ }
+ else
+ {
+ /* Normalise lifetime */
+ value *= MEGA; /* default = s */
+ if(unit[0] == 'u') value /= MEGA;
+ if(unit[0] == 'm') value /= KILO;
+ }
+ }
+ wrq.u.retry.value = (long) value;
+ ++i;
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWRETRY, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var args */
+ return(i);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set RTS Threshold
+ */
+static int
+set_rts_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ wrq.u.rts.value = -1;
+ wrq.u.rts.fixed = 1;
+ wrq.u.rts.disabled = 0;
+
+ if(!strcasecmp(args[0], "off"))
+ wrq.u.rts.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[0], "auto"))
+ wrq.u.rts.fixed = 0;
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old RTS threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.rts.fixed = 1;
+ }
+ else
+ { /* Should be a numeric value */
+ long temp;
+ if(sscanf(args[0], "%li", (unsigned long *) &(temp)) != 1)
{
- if(!strcasecmp(args[i], "fixed"))
- {
- /* Get old tx-power */
- if(ioctl(skfd, SIOCGIWTXPOW, &wrq) < 0)
- {
- fprintf(stderr, "SIOCGIWTXPOW: %s\n", strerror(errno));
- return(-1);
- }
- strcpy(wrq.ifr_name, ifname);
- wrq.u.txpower.fixed = 1;
- }
- else /* Should be a numeric value */
- {
- int power;
- int ismwatt = 0;
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
+ }
+ wrq.u.rts.value = temp;
+ }
+ }
- /* Get the value */
- if(sscanf(args[i], "%ld",
- (unsigned long *) &(power)) != 1)
- iw_usage();
+ if(iw_set_ext(skfd, ifname, SIOCSIWRTS, &wrq) < 0)
+ return(IWERR_SET_EXT);
- /* Check if milliwatt */
- ismwatt = (index(args[i], 'm') != NULL);
+ /* 1 arg */
+ return(1);
+}
- /* Convert */
- if(!ismwatt && (range.txpower_capa & IW_TXPOW_MWATT))
- {
- power = dbm2mwatt(power);
- wrq.u.data.flags = IW_TXPOW_MWATT;
- }
- if(ismwatt && !(range.txpower_capa & IW_TXPOW_MWATT))
- power = mwatt2dbm(power);
- wrq.u.bitrate.value = power;
+/*------------------------------------------------------------------*/
+/*
+ * Set Fragmentation Threshold
+ */
+static int
+set_frag_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
- /* 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;
- }
- }
+ /* Avoid "Unused parameter" warning */
+ count = count;
+
+ wrq.u.frag.value = -1;
+ wrq.u.frag.fixed = 1;
+ wrq.u.frag.disabled = 0;
+
+ if(!strcasecmp(args[0], "off"))
+ wrq.u.frag.disabled = 1; /* i.e. max size */
+ else
+ if(!strcasecmp(args[0], "auto"))
+ wrq.u.frag.fixed = 0;
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old fragmentation threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.frag.fixed = 1;
+ }
+ else
+ { /* Should be a numeric value */
+ long temp;
+ if(sscanf(args[0], "%li", &(temp))
+ != 1)
+ {
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
+ wrq.u.frag.value = temp;
+ }
+ }
- if(ioctl(skfd, SIOCSIWTXPOW, &wrq) < 0)
- {
- fprintf(stderr, "SIOCSIWTXPOW: %s\n", strerror(errno));
- return(-1);
- }
- continue;
- }
-#endif
+ if(iw_set_ext(skfd, ifname, SIOCSIWFRAG, &wrq) < 0)
+ return(IWERR_SET_EXT);
-#if WIRELESS_EXT > 10
- /* ---------- Set Power Management ---------- */
- if(!strncmp(args[i], "retry", 3))
- {
- double temp;
- int gotone = 0;
+ /* 1 arg */
+ return(1);
+}
- if(++i >= count)
- iw_usage();
+/*------------------------------------------------------------------*/
+/*
+ * Set Modulation
+ */
+static int
+set_modulation_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+ int i = 1;
- /* Default - nope */
- wrq.u.retry.flags = IW_RETRY_LIMIT;
- wrq.u.retry.disabled = 0;
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
- /* Check value modifier */
- if(!strcasecmp(args[i], "min"))
+ if(!strcasecmp(args[0], "auto"))
+ wrq.u.param.fixed = 0; /* i.e. use any modulation */
+ else
+ {
+ if(!strcasecmp(args[0], "fixed"))
+ {
+ /* Get old modulation */
+ if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) < 0)
+ return(IWERR_GET_EXT);
+ wrq.u.param.fixed = 1;
+ }
+ else
+ {
+ int k;
+
+ /* Allow multiple modulations, combine them together */
+ wrq.u.param.value = 0x0;
+ i = 0;
+ do
{
- wrq.u.retry.flags |= IW_RETRY_MIN;
- if(++i >= count)
- iw_usage();
+ for(k = 0; k < IW_SIZE_MODUL_LIST; k++)
+ {
+ if(!strcasecmp(args[i], iw_modul_list[k].cmd))
+ {
+ wrq.u.param.value |= iw_modul_list[k].mask;
+ ++i;
+ break;
+ }
+ }
}
- else
- if(!strcasecmp(args[i], "max"))
- {
- wrq.u.retry.flags |= IW_RETRY_MAX;
- if(++i >= count)
- iw_usage();
- }
+ /* For as long as current arg matched and not out of args */
+ while((i < count) && (k < IW_SIZE_MODUL_LIST));
- /* Check value type */
- if(!strcasecmp(args[i], "limit"))
+ /* Check we got something */
+ if(i == 0)
{
- wrq.u.retry.flags |= IW_RETRY_LIMIT;
- if(++i >= count)
- iw_usage();
+ errarg = 0;
+ return(IWERR_ARG_TYPE);
}
- else
- if(!strncasecmp(args[i], "lifetime", 4))
- {
- wrq.u.retry.flags |= IW_RETRY_LIFETIME;
- if(++i >= count)
- iw_usage();
- }
- /* Is there any value to grab ? */
- if(sscanf(args[i], "%lg", &(temp)) == 1)
+ /* Check for an additional argument */
+ if((i < count) && (!strcasecmp(args[i], "auto")))
{
- /* 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;
+ wrq.u.param.fixed = 0;
++i;
- gotone = 1;
}
+ if((i < count) && (!strcasecmp(args[i], "fixed")))
+ {
+ wrq.u.param.fixed = 1;
+ ++i;
+ }
+ }
+ }
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWMODUL, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* Var args */
+ return(i);
+}
+#endif /* WE_ESSENTIAL */
+
+/*------------------------------------------------------------------*/
+/*
+ * Set commit
+ */
+static int
+set_commit_info(int skfd,
+ char * ifname,
+ char * args[], /* Command line args */
+ int count) /* Args count */
+{
+ struct iwreq wrq;
+
+ /* Avoid "Unused parameter" warning */
+ args = args; count = count;
+
+ if(iw_set_ext(skfd, ifname, SIOCSIWCOMMIT, &wrq) < 0)
+ return(IWERR_SET_EXT);
+
+ /* No args */
+ return(0);
+}
- if(!gotone)
- iw_usage();
- --i;
+/************************** SET DISPATCHER **************************/
+/*
+ * This is a modified version of the dispatcher in iwlist.
+ * The main difference is that here we may have multiple commands per
+ * line. Also, most commands here do take arguments, and most often
+ * a variable number of them.
+ * Therefore, the handler *must* return how many args were consumed...
+ *
+ * Note that the use of multiple commands per line is not advised
+ * in scripts, as it makes error management hard. All commands before
+ * the error are executed, but commands after the error are not
+ * processed.
+ * We also try to give as much clue as possible via stderr to the caller
+ * on which command did fail, but if there are two time the same command,
+ * you don't know which one failed...
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Map command line arguments to the proper procedure...
+ */
+typedef struct iwconfig_entry {
+ const char * cmd; /* Command line shorthand */
+ iw_enum_handler fn; /* Subroutine */
+ int min_count;
+ int request; /* WE numerical ID */
+ const char * name; /* Human readable string */
+ const char * argsname; /* Args as human readable string */
+} iwconfig_cmd;
+
+static const struct iwconfig_entry iwconfig_cmds[] = {
+ { "essid", set_essid_info, 1, SIOCSIWESSID,
+ "Set ESSID", "{NNN|any|on|off}" },
+ { "mode", set_mode_info, 1, SIOCSIWMODE,
+ "Set Mode", "{managed|ad-hoc|master|...}" },
+ { "freq", set_freq_info, 1, SIOCSIWFREQ,
+ "Set Frequency", "N.NNN[k|M|G]" },
+ { "channel", set_freq_info, 1, SIOCSIWFREQ,
+ "Set Frequency", "N" },
+ { "bit", set_bitrate_info, 1, SIOCSIWRATE,
+ "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
+ { "rate", set_bitrate_info, 1, SIOCSIWRATE,
+ "Set Bit Rate", "{N[k|M|G]|auto|fixed}" },
+ { "enc", set_enc_info, 1, SIOCSIWENCODE,
+ "Set Encode", "{NNNN-NNNN|off}" },
+ { "key", set_enc_info, 1, SIOCSIWENCODE,
+ "Set Encode", "{NNNN-NNNN|off}" },
+ { "power", set_power_info, 1, SIOCSIWPOWER,
+ "Set Power Management", "{period N|timeout N|saving N|off}" },
+#ifndef WE_ESSENTIAL
+ { "nickname", set_nick_info, 1, SIOCSIWNICKN,
+ "Set Nickname", "NNN" },
+ { "nwid", set_nwid_info, 1, SIOCSIWNWID,
+ "Set NWID", "{NN|on|off}" },
+ { "ap", set_apaddr_info, 1, SIOCSIWAP,
+ "Set AP Address", "{N|off|auto}" },
+ { "txpower", set_txpower_info, 1, SIOCSIWTXPOW,
+ "Set Tx Power", "{NmW|NdBm|off|auto}" },
+ { "sens", set_sens_info, 1, SIOCSIWSENS,
+ "Set Sensitivity", "N" },
+ { "retry", set_retry_info, 1, SIOCSIWRETRY,
+ "Set Retry Limit", "{limit N|lifetime N}" },
+ { "rts", set_rts_info, 1, SIOCSIWRTS,
+ "Set RTS Threshold", "{N|auto|fixed|off}" },
+ { "frag", set_frag_info, 1, SIOCSIWFRAG,
+ "Set Fragmentation Threshold", "{N|auto|fixed|off}" },
+ { "modulation", set_modulation_info, 1, SIOCGIWMODUL,
+ "Set Modulation", "{11g|11a|CCK|OFDMg|...}" },
+#endif /* WE_ESSENTIAL */
+ { "commit", set_commit_info, 0, SIOCSIWCOMMIT,
+ "Commit changes", "" },
+ { NULL, NULL, 0, 0, NULL, NULL },
+};
+
+/*------------------------------------------------------------------*/
+/*
+ * Find the most appropriate command matching the command line
+ */
+static inline const iwconfig_cmd *
+find_command(const char * cmd)
+{
+ const iwconfig_cmd * found = NULL;
+ int ambig = 0;
+ unsigned int len = strlen(cmd);
+ int i;
+
+ /* Go through all commands */
+ for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
+ {
+ /* No match -> next one */
+ if(strncasecmp(iwconfig_cmds[i].cmd, cmd, len) != 0)
+ continue;
+
+ /* Exact match -> perfect */
+ if(len == strlen(iwconfig_cmds[i].cmd))
+ return &iwconfig_cmds[i];
+
+ /* Partial match */
+ if(found == NULL)
+ /* First time */
+ found = &iwconfig_cmds[i];
+ else
+ /* Another time */
+ if (iwconfig_cmds[i].fn != found->fn)
+ ambig = 1;
+ }
+
+ if(found == NULL)
+ {
+ fprintf(stderr, "iwconfig: unknown command \"%s\"\n", cmd);
+ return NULL;
+ }
+
+ if(ambig)
+ {
+ fprintf(stderr, "iwconfig: command \"%s\" is ambiguous\n", cmd);
+ return NULL;
+ }
+
+ return found;
+}
- if(ioctl(skfd, SIOCSIWRETRY, &wrq) < 0)
+/*------------------------------------------------------------------*/
+/*
+ * Set the wireless options requested on command line
+ * Find the individual commands and call the appropriate subroutine
+ */
+static int
+set_info(int skfd, /* The socket */
+ char * args[], /* Command line args */
+ int count, /* Args count */
+ char * ifname) /* Dev name */
+{
+ const iwconfig_cmd * iwcmd;
+ int ret;
+
+ /* Loop until we run out of args... */
+ while(count > 0)
+ {
+ /* find the command matching the keyword */
+ iwcmd = find_command(args[0]);
+ if(iwcmd == NULL)
+ {
+ /* Here we have an unrecognised arg... Error already printed out. */
+ return(-1);
+ }
+
+ /* One arg is consumed (the command name) */
+ args++;
+ count--;
+
+ /* Check arg numbers */
+ if(count < iwcmd->min_count)
+ ret = IWERR_ARG_NUM;
+ else
+ ret = 0;
+
+ /* Call the command */
+ if(!ret)
+ ret = (*iwcmd->fn)(skfd, ifname, args, count);
+
+ /* Deal with various errors */
+ if(ret < 0)
+ {
+ int request = iwcmd->request;
+ if(ret == IWERR_GET_EXT)
+ request++; /* Transform the SET into GET */
+
+ fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n",
+ iwcmd->name, request);
+ switch(ret)
{
- fprintf(stderr, "SIOCSIWRETRY(%d): %s\n",
- errno, strerror(errno));
- return(-1);
+ case IWERR_ARG_NUM:
+ fprintf(stderr, " too few arguments.\n");
+ break;
+ case IWERR_ARG_TYPE:
+ if(errarg < 0)
+ errarg = 0;
+ if(errarg >= count)
+ errarg = count - 1;
+ fprintf(stderr, " invalid argument \"%s\".\n", args[errarg]);
+ break;
+ case IWERR_ARG_SIZE:
+ fprintf(stderr, " argument too big (max %d)\n", errmax);
+ break;
+ case IWERR_ARG_CONFLICT:
+ if(errarg < 0)
+ errarg = 0;
+ if(errarg >= count)
+ errarg = count - 1;
+ fprintf(stderr, " conflicting argument \"%s\".\n", args[errarg]);
+ break;
+ case IWERR_SET_EXT:
+ fprintf(stderr, " SET failed on device %-1.16s ; %s.\n",
+ ifname, strerror(errno));
+ break;
+ case IWERR_GET_EXT:
+ fprintf(stderr, " GET failed on device %-1.16s ; %s.\n",
+ ifname, strerror(errno));
+ break;
}
- continue;
+ /* Stop processing, we don't know if we are in a consistent state
+ * in reading the command line */
+ return(ret);
}
-#endif /* WIRELESS_EXT > 10 */
+ /* Substract consumed args from command line */
+ args += ret;
+ count -= ret;
- /* ---------- Other ---------- */
- /* Here we have an unrecognised arg... */
- fprintf(stderr, "Invalid argument : %s\n", args[i]);
- iw_usage();
- return(-1);
- } /* for(index ... */
+ /* Loop back */
+ }
+
+ /* Done, all done */
return(0);
}
+/*------------------------------------------------------------------*/
+/*
+ * Display help
+ */
+static inline void
+iw_usage(void)
+{
+ int i;
+
+ fprintf(stderr, "Usage: iwconfig [interface]\n");
+ for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i)
+ fprintf(stderr, " interface %s %s\n",
+ iwconfig_cmds[i].cmd, iwconfig_cmds[i].argsname);
+ fprintf(stderr, " Check man pages for more details.\n");
+}
+
+
/******************************* MAIN ********************************/
/*------------------------------------------------------------------*/
main(int argc,
char ** argv)
{
- int skfd = -1; /* generic raw socket desc. */
+ int skfd; /* generic raw socket desc. */
int goterr = 0;
/* Create a channel to the NET kernel. */
- 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(skfd);
- close(skfd);
- exit(0);
- }
-
- /* Special case for help... */
- if((!strncmp(argv[1], "-h", 9)) ||
- (!strcmp(argv[1], "--help")))
- {
+ iw_enum_devices(skfd, &print_info, NULL, 0);
+ else
+ /* Special case for help... */
+ if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
iw_usage();
- close(skfd);
- exit(0);
- }
-
- /* The device name must be the first argument */
- if(argc == 2)
- {
- print_info(skfd, argv[1]);
- close(skfd);
- exit(0);
- }
+ else
+ /* Special case for version... */
+ if(!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
+ goterr = iw_print_version_info("iwconfig");
+ else
+ {
+ /* '--' escape device name */
+ if((argc > 2) && !strcmp(argv[1], "--"))
+ {
+ argv++;
+ argc--;
+ }
- /* The other args on the line specify options to be set... */
- goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
+ /* The device name must be the first argument */
+ if(argc == 2)
+ goterr = 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);
+ iw_sockets_close(skfd);
return(goterr);
}