/*
- * Hack my way... Jean II
+ * Wireless Tools
+ *
+ * Jean II - HPLB '99
+ *
+ * Main code for "iwconfig". This is the generic tool for most
+ * manipulations...
+ * You need to link this code against "iwcommon.c" and "-lm".
*/
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <linux/netdevice.h>
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/ipx.h>
-#include <linux/wireless.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/* Some usefull constants */
-#define KILO 1e3
-#define MEGA 1e6
-#define GIGA 1e9
-
-typedef struct iw_statistics iwstats;
-typedef struct iw_range iwrange;
-
-/* Structure for storing all wireless information for each device */
-struct wireless_info
-{
- char dev[IFNAMSIZ]; /* Interface name (device) */
- char name[12]; /* Wireless name */
- int has_nwid;
- int nwid_on;
- u_long nwid; /* Network ID */
- int has_freq;
- u_long freq; /* Frequency/channel */
-
- /* Stats */
- iwstats stats;
- int has_stats;
- iwrange range;
- int has_range;
-};
-
-int skfd = -1; /* generic raw socket desc. */
-int ipx_sock = -1; /* IPX socket */
-int ax25_sock = -1; /* AX.25 socket */
-int inet_sock = -1; /* INET socket */
-int ddp_sock = -1; /* Appletalk DDP socket */
+#include "iwcommon.h" /* Header */
+
+/************************* MISC SUBROUTINES **************************/
+/*------------------------------------------------------------------*/
+/*
+ * Print usage string
+ */
static void
-usage(void)
+iw_usage(void)
{
- fprintf(stderr, "Usage: iwconfig interface\n");
- fprintf(stderr, " [nwid NN]\n");
- fprintf(stderr, " [freq N.NN (add k, M or G) ]\n");
- fprintf(stderr, " [channel N]\n");
+ fprintf(stderr, "Usage: iwconfig interface [essid {NN|on|off}]\n");
+ fprintf(stderr, " [nwid {NN|on|off}]\n");
+ fprintf(stderr, " [freq N.NNNN[k|M|G]]\n");
+ fprintf(stderr, " [channel N]\n");
+ fprintf(stderr, " [sens N]\n");
+ fprintf(stderr, " [nick N]\n");
+ fprintf(stderr, " [rate {N|auto|fixed}]\n");
+ fprintf(stderr, " [rts {N|auto|fixed|off}]\n");
+ fprintf(stderr, " [frag {N|auto|fixed|off}]\n");
+ fprintf(stderr, " [enc NNNN-NNNN]\n");
exit(1);
}
-static void
-print_info(struct wireless_info * info)
-{
- /* Display device name */
- printf("%-8.8s ", info->dev);
-
- /* Display wireless name */
- printf("%s ", info->name);
-
- /* Display Network ID */
- if(info->has_nwid)
- if(info->nwid_on)
- printf("NWID:%lX ", info->nwid);
- else
- printf("NWID:off ");
-
- /* Display frequency / channel */
- if(info->has_freq)
- if(info->freq < KILO)
- printf("Channel:%g ", (double) info->freq);
- else
- if(info->freq > GIGA)
- printf("Frequency:%gGHz ", info->freq / GIGA);
- else
- if(info->freq > MEGA)
- printf("Frequency:%gMHz ", info->freq / MEGA);
- else
- printf("Frequency:%gkHz ", info->freq / KILO);
-
- printf("\n");
-
- if(info->has_stats)
- {
- if(info->has_range)
- printf(" Link quality:%d/%d Signal level:%d/%d Noise level:%d/%d\n",
- info->stats.qual.qual, info->range.max_qual.qual,
- info->stats.qual.level, info->range.max_qual.level,
- info->stats.qual.noise, info->range.max_qual.noise);
- else
- printf(" Link quality:%d Signal level:%d Noise level:%d\n",
- info->stats.qual.qual,
- info->stats.qual.level,
- info->stats.qual.noise);
-
- printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
- info->stats.discard.nwid,
- info->stats.discard.crypt,
- info->stats.discard.misc);
- }
-
- printf("\n");
-}
+/************************* DISPLAY ROUTINES **************************/
-static int if_getstats(char *ifname, iwstats * stats)
+/*------------------------------------------------------------------*/
+/*
+ * Read /proc/net/wireless to get the latest statistics
+ */
+static int
+iw_getstats(char * ifname,
+ iwstats * stats)
{
FILE *f=fopen("/proc/net/wireless","r");
char buf[256];
bp=strchr(bp,':');
bp++;
bp = strtok(bp, " .");
- sscanf(bp, "%X", &stats->status);
+ sscanf(bp, "%X", (unsigned int *)&stats->status);
bp = strtok(NULL, " .");
- sscanf(bp, "%d", &stats->qual.qual);
+ sscanf(bp, "%d", (unsigned int *)&stats->qual.qual);
bp = strtok(NULL, " .");
- sscanf(bp, "%d", &stats->qual.level);
+ sscanf(bp, "%d", (unsigned int *)&stats->qual.level);
bp = strtok(NULL, " .");
- sscanf(bp, "%d", &stats->qual.noise);
+ sscanf(bp, "%d", (unsigned int *)&stats->qual.noise);
bp = strtok(NULL, " .");
sscanf(bp, "%d", &stats->discard.nwid);
bp = strtok(NULL, " .");
- sscanf(bp, "%d", &stats->discard.crypt);
+ sscanf(bp, "%d", &stats->discard.code);
bp = strtok(NULL, " .");
sscanf(bp, "%d", &stats->discard.misc);
fclose(f);
- return;
+ return 0;
}
}
fclose(f);
return 0;
}
-/* Get wireless informations & config from the device driver */
+/*------------------------------------------------------------------*/
+/*
+ * Get wireless informations & config from the device driver
+ * We will call all the classical wireless ioctl on the driver through
+ * the socket to know what is supported and to get the settings...
+ */
static int
-get_info(char * ifname,
+get_info(int skfd,
+ char * ifname,
struct wireless_info * info)
{
struct iwreq wrq;
memset((char *) info, 0, sizeof(struct wireless_info));
- /* Get device name */
- strcpy(info->dev, ifname);
-
/* Get wireless name */
strcpy(wrq.ifr_name, ifname);
if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0)
{
info->has_freq = 1;
- info->freq = wrq.u.freq;
+ info->freq = freq2float(&(wrq.u.freq));
}
- /* Get stats */
- if(if_getstats(ifname, &(info->stats)) == 0)
+ /* Get sensitivity */
+ strcpy(wrq.ifr_name, ifname);
+ if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0)
{
- info->has_stats = 1;
+ info->has_sens = 1;
+ info->sens = wrq.u.sensitivity;
}
- /* Get ranges */
+ /* Get encryption information */
+ strcpy(wrq.ifr_name, ifname);
+ if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0)
+ {
+ info->has_enc = 1;
+ info->enc_method = wrq.u.encoding.method;
+ info->enc_key = wrq.u.encoding.code;
+ }
+
+#if WIRELESS_EXT > 5
+ /* Get ESSID */
+ strcpy(wrq.ifr_name, ifname);
+ wrq.u.data.pointer = (caddr_t) info->essid;
+ wrq.u.data.length = 0;
+ wrq.u.data.flags = 0;
+ if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0)
+ {
+ info->has_essid = 1;
+ info->essid_on = wrq.u.data.flags;
+ }
+
+ /* Get AP address */
+ strcpy(wrq.ifr_name, ifname);
+ if(ioctl(skfd, SIOCGIWAP, &wrq) >= 0)
+ {
+ info->has_ap_addr = 1;
+ memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
+ }
+#endif /* WIRELESS_EXT > 5 */
+
+#if WIRELESS_EXT > 7
+ /* Get NickName */
strcpy(wrq.ifr_name, ifname);
- wrq.u.data.pointer = (caddr_t) &(info->range);
+ wrq.u.data.pointer = (caddr_t) info->nickname;
wrq.u.data.length = 0;
wrq.u.data.flags = 0;
- if(ioctl(skfd, SIOCGIWRANGE, &wrq) >= 0)
+ if(ioctl(skfd, SIOCGIWNICKN, &wrq) >= 0)
+ if(wrq.u.data.length > 1)
+ info->has_nickname = 1;
+
+ /* Get bit rate */
+ strcpy(wrq.ifr_name, ifname);
+ if(ioctl(skfd, SIOCGIWRATE, &wrq) >= 0)
+ {
+ info->has_bitrate = 1;
+ info->bitrate_fixed = wrq.u.bitrate.fixed;
+ info->bitrate = wrq.u.bitrate.value;
+ }
+
+ /* Get RTS threshold */
+ strcpy(wrq.ifr_name, ifname);
+ if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0)
+ {
+ info->has_rts = 1;
+ info->rts_fixed = wrq.u.rts.fixed;
+ info->rts = wrq.u.rts.value;
+ }
+
+ /* Get fragmentation thershold */
+ strcpy(wrq.ifr_name, ifname);
+ if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0)
+ {
+ info->has_frag = 1;
+ info->frag_fixed = wrq.u.frag.fixed;
+ info->frag = wrq.u.frag.value;
+ }
+#endif /* WIRELESS_EXT > 7 */
+
+ /* Get stats */
+ if(iw_getstats(ifname, &(info->stats)) == 0)
{
- info->has_range = 1;
+ info->has_stats = 1;
}
+ /* Get ranges */
+ if(get_range_info(skfd, ifname, &(info->range)) >= 0)
+ info->has_range = 1;
+
return(0);
}
+/*------------------------------------------------------------------*/
+/*
+ * Print on the screen in a neat fashion all the info we have collected
+ * on a device.
+ */
+static void
+display_info(struct wireless_info * info,
+ char * ifname)
+{
+ /* Display device name and wireless name (name of the protocol used) */
+ printf("%-8.8s %s ", ifname, info->name);
+
+ /* Display ESSID (extended network), if any */
+ if(info->has_essid)
+ {
+ if(info->essid_on)
+ printf("ESSID:\"%s\" ", info->essid);
+ else
+ printf("ESSID:off ");
+ }
+
+ /* Display NickName (station name), if any */
+ if(info->has_nickname)
+ printf("Nickname:\"%s\"", info->nickname);
+
+ /* Formatting */
+ if(info->has_essid || info->has_nickname)
+ printf("\n ");
+
+ /* Display Network ID */
+ if(info->has_nwid)
+ {
+ /* Note : should display right number of digit according to info
+ * in range structure */
+ if(info->nwid_on)
+ printf("NWID:%lX ", info->nwid);
+ else
+ printf("NWID:off/any ");
+ }
+
+ /* Display frequency / channel */
+ if(info->has_freq)
+ {
+ if(info->freq < KILO)
+ printf("Channel:%g ", info->freq);
+ else
+ {
+ if(info->freq >= GIGA)
+ printf("Frequency:%gGHz ", info->freq / GIGA);
+ else
+ {
+ if(info->freq >= MEGA)
+ printf("Frequency:%gMHz ", info->freq / MEGA);
+ else
+ printf("Frequency:%gkHz ", info->freq / KILO);
+ }
+ }
+ }
+
+ /* Display sensitivity */
+ if(info->has_sens)
+ {
+ if(info->has_range)
+ /* Display in dBm ? */
+ if(info->sens < 0)
+ printf("Sensitivity:%d dBm ", info->sens);
+ else
+ printf("Sensitivity:%d/%d ", info->sens, info->range.sensitivity);
+ else
+ printf("Sensitivity:%d ", info->sens);
+ }
+
+ /* Display the address of the current Access Point */
+ if(info->has_ap_addr)
+ {
+ /* A bit of clever formatting */
+ if((info->has_nwid + 2*info->has_freq + 2*info->has_sens
+ + !info->has_essid) > 3)
+ printf("\n ");
+
+ printf("Access Point: %s", pr_ether(info->ap_addr.sa_data));
+ }
+
+ printf("\n ");
+
+ /* Display the currently used/set bit-rate */
+ if(info->has_bitrate)
+ {
+ printf("Bit Rate:");
+ if(info->bitrate >= GIGA)
+ printf("%g Gb/s", info->bitrate / GIGA);
+ else
+ if(info->bitrate >= MEGA)
+ printf("%g Mb/s", info->bitrate / MEGA);
+ else
+ printf("%g kb/s", info->bitrate / KILO);
+
+ /* Fixed ? */
+ if(info->bitrate_fixed)
+ printf(" (f) ");
+ else
+ printf(" ");
+ }
+
+ /* Display the RTS threshold */
+ if(info->has_rts)
+ {
+ printf("RTS thr:%ld B", info->rts);
+
+ /* Fixed ? */
+ if(info->rts_fixed)
+ printf(" (f) ");
+ else
+ printf(" ");
+ }
+
+ /* Display the fragmentation threshold */
+ if(info->has_bitrate)
+ {
+ printf("Frag thr:%ld B", info->frag);
+
+ /* Fixed ? */
+ if(info->frag_fixed)
+ printf(" (f) ");
+ else
+ printf(" ");
+ }
+
+ /* Formating */
+ if((info->has_bitrate) || (info->has_rts) || (info->has_bitrate))
+ printf("\n ");
+
+ if(info->has_enc)
+ {
+ printf("Encryption key:");
+ if(info->enc_method)
+ {
+ int i = 0;
+ u_short parts[4];
+ long long key = info->enc_key;
+
+ for(i = 3; i >= 0; i--)
+ {
+ parts[i] = key & 0xFFFF;
+ key >>= 16;
+ }
+
+ i = 0;
+ while((parts[i] == 0) && (i < 3))
+ i++;
+ for(; i < 3; i++)
+ printf("%.4X-", parts[i]);
+ printf("%.4X", parts[3]);
+
+ if(info->enc_method > 1)
+ printf(" (%d)", info->enc_method);
+ printf("\n ");
+ }
+ else
+ printf("off\n ");
+ }
+
+ if(info->has_stats)
+ {
+ if(info->has_range && (info->stats.qual.level != 0))
+ /* If the statistics are in dBm */
+ if(info->stats.qual.level > info->range.max_qual.level)
+ printf("Link quality:%d/%d Signal level:%d dBm Noise level:%d dBm\n",
+ info->stats.qual.qual, info->range.max_qual.qual,
+ info->stats.qual.level - 0x100,
+ info->stats.qual.noise - 0x100);
+ else
+ /* Statistics are relative values (0 -> max) */
+ printf("Link quality:%d/%d Signal level:%d/%d Noise level:%d/%d\n",
+ info->stats.qual.qual, info->range.max_qual.qual,
+ info->stats.qual.level, info->range.max_qual.level,
+ info->stats.qual.noise, info->range.max_qual.noise);
+ else
+ /* We can't read the range, so we don't know... */
+ printf("Link quality:%d Signal level:%d Noise level:%d\n",
+ info->stats.qual.qual,
+ info->stats.qual.level,
+ info->stats.qual.noise);
+
+ printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
+ info->stats.discard.nwid,
+ info->stats.discard.code,
+ info->stats.discard.misc);
+ }
+
+ printf("\n");
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Print on the screen in a neat fashion all the info we have collected
+ * on a device.
+ */
+static void
+print_info(int skfd,
+ char * ifname)
+{
+ struct wireless_info info;
+
+ if(get_info(skfd, ifname, &info) < 0)
+ {
+ fprintf(stderr, "%-8.8s no wireless extensions.\n\n",
+ ifname);
+ return;
+ }
+
+ /* Display it ! */
+ display_info(&info, ifname);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Get info on all devices and print it on the screen
+ */
+static void
+print_devices(int skfd)
+{
+ char buff[1024];
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ int i;
+
+ /* Get list of active devices */
+ ifc.ifc_len = sizeof(buff);
+ ifc.ifc_buf = buff;
+ if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
+ {
+ fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
+ return;
+ }
+ ifr = ifc.ifc_req;
+
+ /* Print them */
+ for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
+ print_info(skfd, ifr->ifr_name);
+}
+
+/************************* SETTING ROUTINES **************************/
+/*------------------------------------------------------------------*/
+/*
+ * Set the wireless options requested on command line
+ * This function is too long and probably should be split,
+ * because it look like the perfect definition of spaghetti code,
+ * but I'm way to lazy
+ */
static int
-set_info(char * args[], /* Command line args */
+set_info(int skfd, /* The socket */
+ char * args[], /* Command line args */
int count, /* Args count */
char * ifname) /* Dev name */
{
/* Set dev name */
strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ /* if nothing after the device name */
+ if(count<1)
+ iw_usage();
+
/* The other args on the line specify options to be set... */
for(i = 0; i < count; i++)
{
- /* Set network ID */
- if(!strcmp(args[i], "nwid"))
+ /* ---------- Set network ID ---------- */
+ if((!strcasecmp(args[i], "nwid")) ||
+ (!strcasecmp(args[i], "domain")))
{
- if(++i >= count)
- usage();
- if(!strcasecmp(args[i], "off"))
+ i++;
+ if(i >= count)
+ iw_usage();
+ if((!strcasecmp(args[i], "off")) ||
+ (!strcasecmp(args[i], "any")))
wrq.u.nwid.on = 0;
else
- if(sscanf(args[i], "%lX", &(wrq.u.nwid.nwid)) != 1)
- usage();
+ if(!strcasecmp(args[i], "on"))
+ {
+ /* Get old nwid */
+ if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno));
+ return(-1);
+ }
+ strcpy(wrq.ifr_name, ifname);
+ wrq.u.nwid.on = 1;
+ }
else
- wrq.u.nwid.on = 1;
+ if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.nwid))
+ != 1)
+ iw_usage();
+ else
+ wrq.u.nwid.on = 1;
if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0)
{
continue;
}
- /* Set frequency / channel */
+ /* ---------- Set frequency / channel ---------- */
if((!strncmp(args[i], "freq", 4)) ||
(!strcmp(args[i], "channel")))
{
+ double freq;
+
+ if(++i >= count)
+ iw_usage();
+ if(sscanf(args[i], "%lg", &(freq)) != 1)
+ iw_usage();
+ if(index(args[i], 'G')) freq *= GIGA;
+ if(index(args[i], 'M')) freq *= MEGA;
+ if(index(args[i], 'k')) freq *= KILO;
+
+ float2freq(freq, &(wrq.u.freq));
+
+ if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
+ return(-1);
+ }
+ continue;
+ }
+
+ /* ---------- Set sensitivity ---------- */
+ if(!strncmp(args[i], "sens", 4))
+ {
+ if(++i >= count)
+ iw_usage();
+ if(sscanf(args[i], "%d", &(wrq.u.sensitivity)) != 1)
+ iw_usage();
+
+ if(ioctl(skfd, SIOCSIWSENS, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWSENS: %s\n", strerror(errno));
+ return(-1);
+ }
+ continue;
+ }
+
+ /* ---------- Set encryption stuff ---------- */
+ if(!strncmp(args[i], "enc", 3 ))
+ {
+ unsigned long long key = 0;
+
if(++i >= count)
+ iw_usage();
+
+ if(!strcasecmp(args[i], "off"))
+ wrq.u.encoding.method = 0;
+ else
+ {
+ if(!strcasecmp(args[i], "on"))
+ {
+ /* Get old encryption information */
+ if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
+ return(-1);
+ }
+ strcpy(wrq.ifr_name, ifname);
+ }
+ else
+ {
+ char * buff;
+ char * p;
+ u_long temp;
+
+ p = buff = malloc(strlen(args[i] + 1));
+ strcpy(buff, args[i]);
+
+ p = strtok(buff, "-:;.,*#");
+ while(p != (char *) NULL)
+ {
+ key = key << 16;
+ if(sscanf(p, "%lX", &temp) != 1)
+ iw_usage();
+ key += temp;
+ p = strtok((char *) NULL, "-:;.,*#");
+ }
+
+ free(buff);
+ wrq.u.encoding.code = key;
+ }
+ /* TODO : check for "(method)" in args list */
+ wrq.u.encoding.method = 1;
+ }
+
+ if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0)
{
- struct iw_range range;
- int k;
+ fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
+ errno, strerror(errno));
+ return(-1);
+ }
+ continue;
+ }
+
+#if WIRELESS_EXT > 5
+ /* ---------- Set ESSID ---------- */
+ if(!strcasecmp(args[i], "essid"))
+ {
+ char essid[IW_ESSID_MAX_SIZE + 1];
- wrq.u.data.pointer = (caddr_t) ⦥
- wrq.u.data.length = 0;
+ i++;
+ if(i >= count)
+ iw_usage();
+ if((!strcasecmp(args[i], "off")) ||
+ (!strcasecmp(args[i], "any")))
+ {
wrq.u.data.flags = 0;
- if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0)
+ essid[0] = '\0';
+ }
+ else
+ if(!strcasecmp(args[i], "on"))
+ {
+ /* Get old essid */
+ wrq.u.data.pointer = (caddr_t) essid;
+ wrq.u.data.length = 0;
+ wrq.u.data.flags = 0;
+ if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno));
+ return(-1);
+ }
+ strcpy(wrq.ifr_name, ifname);
+ wrq.u.data.flags = 1;
+ }
+ else
+ if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
{
- fprintf(stderr, "SIOCGIWRANGE: %s\n", strerror(errno));
- return(-1);
+ fprintf(stderr, "ESSID too long (max %d): ``%s''\n",
+ IW_ESSID_MAX_SIZE, args[i]);
+ iw_usage();
}
+ else
+ {
+ wrq.u.data.flags = 1;
+ strcpy(essid, args[i]);
+ }
+
+ wrq.u.data.pointer = (caddr_t) essid;
+ wrq.u.data.length = strlen(essid) + 1;
+ if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
+ return(-1);
+ }
+ continue;
+ }
+
+ /* ---------- Set AP address ---------- */
+ if(!strcasecmp(args[i], "ap"))
+ {
+ if(++i >= count)
+ iw_usage();
- printf("%d channels ; available frequencies :",
- range.num_channels);
- for(k = 0; k < range.num_frequency; k++)
- if(range.freq[k] > GIGA)
- printf(" %gGHz ", range.freq[k] / GIGA);
- else
- if(range.freq[k] > MEGA)
- printf(" %gMHz ", range.freq[k] / MEGA);
- else
- printf(" %gkHz ", range.freq[k] / KILO);
- printf("\n");
- return; /* no more arg */
+ /* Check if we have valid address types */
+ if(check_addr_type(skfd, ifname) < 0)
+ {
+ fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname);
+ return(-1);
}
- if(sscanf(args[i], "%g", &(wrq.u.freq)) != 1)
- usage();
- if(index(args[i], 'G')) wrq.u.freq *= GIGA;
- if(index(args[i], 'M')) wrq.u.freq *= MEGA;
- if(index(args[i], 'k')) wrq.u.freq *= KILO;
+ /* Get the address */
+ if(in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
+ iw_usage();
- if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
+ if(ioctl(skfd, SIOCSIWAP, &wrq) < 0)
{
- fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
+ fprintf(stderr, "SIOCSIWAP: %s\n", strerror(errno));
return(-1);
}
continue;
}
+#endif /* WIRELESS_EXT > 5 */
- /* Here we have an unrecognised arg... */
- fprintf(stderr, "Invalid argument : %s\n", args[i]);
- usage();
- return(-1);
- } /* for(index ... */
- return(0);
-}
+#if WIRELESS_EXT > 7
+ /* ---------- Set NickName ---------- */
+ if(!strncmp(args[i], "nick", 4))
+ {
+ i++;
+ if(i >= count)
+ iw_usage();
+ if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
+ {
+ fprintf(stderr, "Name too long (max %d) : ``%s''\n",
+ IW_ESSID_MAX_SIZE, args[i]);
+ iw_usage();
+ }
-static void
-print_devices(char *ifname)
-{
- char buff[1024];
- struct wireless_info info;
- struct ifconf ifc;
- struct ifreq *ifr;
- int i;
+ wrq.u.data.pointer = (caddr_t) args[i];
+ wrq.u.data.length = strlen(args[i]) + 1;
+ if(ioctl(skfd, SIOCSIWNICKN, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWNICKN: %s\n", strerror(errno));
+ return(-1);
+ }
+ continue;
+ }
- if(ifname == (char *)NULL)
- {
- ifc.ifc_len = sizeof(buff);
- ifc.ifc_buf = buff;
- if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
+ /* ---------- Set Bit-Rate ---------- */
+ if((!strncmp(args[i], "bit", 3)) ||
+ (!strcmp(args[i], "rate")))
{
- fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
- return;
+ i++;
+ if(i >= count)
+ iw_usage();
+ if(!strcasecmp(args[i], "auto"))
+ {
+ wrq.u.bitrate.value = -1;
+ wrq.u.bitrate.fixed = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[i], "fixed"))
+ {
+ /* Get old bitrate */
+ if(ioctl(skfd, SIOCGIWRATE, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCGIWRATE: %s\n", strerror(errno));
+ return(-1);
+ }
+ strcpy(wrq.ifr_name, ifname);
+ }
+ else /* Should be a numeric value */
+ {
+ double brate;
+
+ if(sscanf(args[i], "%lg", &(brate)) != 1)
+ iw_usage();
+ if(index(args[i], 'G')) brate *= GIGA;
+ if(index(args[i], 'M')) brate *= MEGA;
+ if(index(args[i], 'k')) brate *= KILO;
+ wrq.u.bitrate.value = (long) brate;
+ }
+ wrq.u.bitrate.fixed = 1;
+ }
+
+ if(ioctl(skfd, SIOCSIWRATE, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWRATE: %s\n", strerror(errno));
+ return(-1);
+ }
+ continue;
}
- ifr = ifc.ifc_req;
- for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
+ /* ---------- Set RTS threshold ---------- */
+ if(!strncmp(args[i], "rts", 3))
{
- if(get_info(ifr->ifr_name, &info) < 0)
+ i++;
+ if(i >= count)
+ iw_usage();
+ if(!strcasecmp(args[i], "auto"))
{
- /* Could skip this message ? */
- fprintf(stderr, "%-8.8s no wireless extensions.\n\n",
- ifr->ifr_name);
- continue;
+ wrq.u.rts.value = -1;
+ wrq.u.rts.fixed = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[i], "fixed"))
+ {
+ /* Get old RTS threshold */
+ if(ioctl(skfd, SIOCGIWRTS, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno));
+ return(-1);
+ }
+ strcpy(wrq.ifr_name, ifname);
+ }
+ else
+ if(!strcasecmp(args[i], "off"))
+ wrq.u.rts.value = -1; /* i.e. max size */
+ else /* Should be a numeric value */
+ if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value))
+ != 1)
+ iw_usage();
+
+ wrq.u.rts.fixed = 1;
}
- print_info(&info);
+ if(ioctl(skfd, SIOCSIWRTS, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWRTS: %s\n", strerror(errno));
+ return(-1);
+ }
+ continue;
}
- }
- else
- {
- if(get_info(ifname, &info) < 0)
+
+ /* ---------- Set fragmentation threshold ---------- */
+ if(!strncmp(args[i], "frag", 4))
{
- fprintf(stderr, "%s: no wireless extensions.\n",
- ifname);
- usage();
+ i++;
+ if(i >= count)
+ iw_usage();
+ if(!strcasecmp(args[i], "auto"))
+ {
+ wrq.u.frag.value = -1;
+ wrq.u.frag.fixed = 0;
+ }
+ else
+ {
+ if(!strcasecmp(args[i], "fixed"))
+ {
+ /* Get old fragmentation threshold */
+ if(ioctl(skfd, SIOCGIWFRAG, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno));
+ return(-1);
+ }
+ strcpy(wrq.ifr_name, ifname);
+ }
+ else
+ if(!strcasecmp(args[i], "off"))
+ wrq.u.frag.value = -1; /* i.e. max size */
+ else /* Should be a numeric value */
+ if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.frag.value))
+ != 1)
+ iw_usage();
+
+ wrq.u.frag.fixed = 1;
+ }
+
+ if(ioctl(skfd, SIOCSIWFRAG, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWFRAG: %s\n", strerror(errno));
+ return(-1);
+ }
+ continue;
}
- else
- print_info(&info);
- }
+#endif /* WIRELESS_EXT > 7 */
+
+ /* Here we have an unrecognised arg... */
+ fprintf(stderr, "Invalid argument : %s\n", args[i]);
+ iw_usage();
+ return(-1);
+ } /* for(index ... */
+ return(0);
}
+/******************************* MAIN ********************************/
-static int sockets_open()
-{
- inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
- ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
- ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
- ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
- /*
- * Now pick any (exisiting) useful socket family for generic queries
- */
- if(inet_sock!=-1)
- return inet_sock;
- if(ipx_sock!=-1)
- return ipx_sock;
- if(ax25_sock!=-1)
- return ax25_sock;
- /*
- * If this is -1 we have no known network layers and its time to jump.
- */
-
- return ddp_sock;
-}
-
+/*------------------------------------------------------------------*/
+/*
+ * The main !
+ */
int
main(int argc,
char ** argv)
{
+ int skfd = -1; /* generic raw socket desc. */
int goterr = 0;
/* Create a channel to the NET kernel. */
/* No argument : show the list of all device + info */
if(argc == 1)
{
- print_devices((char *)NULL);
+ print_devices(skfd);
+ close(skfd);
+ exit(0);
+ }
+
+ /* Special case for help... */
+ if((!strncmp(argv[1], "-h", 9)) ||
+ (!strcmp(argv[1], "--help")))
+ {
+ iw_usage();
close(skfd);
exit(0);
}
/* The device name must be the first argument */
if(argc == 2)
{
- print_devices(argv[1]);
+ print_info(skfd, argv[1]);
close(skfd);
exit(0);
}
/* The other args on the line specify options to be set... */
- goterr = set_info(argv + 2, argc - 2, argv[1]);
+ goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
/* Close the socket. */
close(skfd);
return(goterr);
}
+
+