Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
     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 }