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