/* * 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 "iwcommon.h" /* Header */ #define CLR "\033[0m" #define BLD "\033[37m\033[1m" #define RED "\033[31m\033[1m" #define CYN "\033[36m\033[1m" #define MAG "\033[35m\033[1m" #define WIDTH 80 /* screen width */ #define SLEEP 500000 /* in microseconds */ /**************************** VARIABLES ****************************/ char * operation_mode[] = { "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary" }; /************************* MISC SUBROUTINES **************************/ /*------------------------------------------------------------------*/ /* * Print usage string */ static void iw_usage(void) { fprintf(stderr, "Usage: iwconfig interface [essid {NN|on|off}]\n"); fprintf(stderr, " [nwid {NN|on|off}]\n"); fprintf(stderr, " [freq N.NNNN[k|M|G]]\n"); fprintf(stderr, " [channel N]\n"); fprintf(stderr, " [sens N]\n"); fprintf(stderr, " [nick N]\n"); fprintf(stderr, " [rate {N|auto|fixed}]\n"); fprintf(stderr, " [rts {N|auto|fixed|off}]\n"); fprintf(stderr, " [frag {N|auto|fixed|off}]\n"); fprintf(stderr, " [enc NNNN-NNNN]\n"); exit(1); } /************************* DISPLAY ROUTINES **************************/ /*------------------------------------------------------------------*/ /* * 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]; char * bp; int t; if(f==NULL) return -1; /* Loop on all devices */ while(fgets(buf,255,f)) { bp=buf; while(*bp&&isspace(*bp)) bp++; /* Is it the good device ? */ if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') { /* Skip ethX: */ bp=strchr(bp,':'); bp++; /* -- status -- */ bp = strtok(bp, " "); sscanf(bp, "%X", &t); stats->status = (unsigned short) t; /* -- link quality -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 1; sscanf(bp, "%d", &t); stats->qual.qual = (unsigned char) t; /* -- signal level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 2; sscanf(bp, "%d", &t); stats->qual.level = (unsigned char) t; /* -- noise level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated += 4; sscanf(bp, "%d", &t); stats->qual.noise = (unsigned char) t; /* -- discarded packets -- */ bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.nwid); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.code); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.misc); fclose(f); return 0; } } fclose(f); return -1; } /*------------------------------------------------------------------*/ /* * Get wireless informations & config from the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to get the settings... */ static int get_info(int skfd, char * ifname, struct wireless_info * info) { struct iwreq wrq; memset((char *) info, 0, sizeof(struct wireless_info)); /* Get wireless name */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0) /* If no wireless name : no wireless extensions */ return(-1); else strcpy(info->name, wrq.u.name); /* Get network ID */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0) { info->has_nwid = 1; memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam)); } /* Get frequency / channel */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0) { info->has_freq = 1; info->freq = freq2float(&(wrq.u.freq)); } /* Get sensitivity */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0) { info->has_sens = 1; memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam)); } /* Get encryption information */ strcpy(wrq.ifr_name, ifname); wrq.u.data.pointer = (caddr_t) info->key; wrq.u.data.length = 0; wrq.u.data.flags = 0; if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0) { info->has_key = 1; info->key_size = wrq.u.data.length; info->key_flags = wrq.u.data.flags; } /* Get ESSID */ strcpy(wrq.ifr_name, ifname); wrq.u.essid.pointer = (caddr_t) info->essid; wrq.u.essid.length = 0; wrq.u.essid.flags = 0; if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0) { info->has_essid = 1; info->essid_on = wrq.u.data.flags; } /* Get 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)); } /* Get NickName */ strcpy(wrq.ifr_name, ifname); wrq.u.essid.pointer = (caddr_t) info->nickname; wrq.u.essid.length = 0; wrq.u.essid.flags = 0; if(ioctl(skfd, SIOCGIWNICKN, &wrq) >= 0) if(wrq.u.data.length > 1) info->has_nickname = 1; /* Get bit rate */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWRATE, &wrq) >= 0) { info->has_bitrate = 1; memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam)); } /* Get RTS threshold */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0) { info->has_rts = 1; memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam)); } /* Get fragmentation threshold */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0) { info->has_frag = 1; memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam)); } /* Get operation mode */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0) { if((wrq.u.mode < 6) && (wrq.u.mode >= 0)) info->has_mode = 1; info->mode = wrq.u.mode; } /* Get Power Management settings */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWPOWER, &wrq) >= 0) { info->has_power = 1; memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam)); } /* Get stats */ if(iw_getstats(ifname, &(info->stats)) >= 0) { 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) { int signal_percent = 0, c, chars; float a, b, x, y; /* Display device name and wireless name (name of the protocol used) */ printf ("\33[H\33[J"); /* yuck */ #ifdef COLOR printf ("\n %s%s%s on device %s%s%s ", MAG, info->name, CLR, MAG, ifname, CLR); #else printf ("\n %s on device %s ", info->name, ifname); #endif /* 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.disabled) printf("NWID:off/any "); else #ifdef COLOR printf ("Network ID : %s%lX%s ", CYN, info->nwid.value, CLR); #else printf ("Network ID : %lX ", info->nwid.value); #endif } /* Display frequency / channel */ if(info->has_freq) { if(info->freq < KILO) #ifdef COLOR printf (" Channel : %s%g%s ", CYN, info->freq, CLR); #else printf (" Channel : %g ", info->freq); #endif 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) { /* Fixed ? */ if(info->sens.fixed) printf("Sensitivity="); else printf("Sensitivity:"); if(info->has_range) /* Display in dBm ? */ if(info->sens.value < 0) printf("%d dBm ", info->sens.value); else printf("%d/%d ", info->sens.value, info->range.sensitivity); else printf("%d ", info->sens.value); } /* Display the current mode of operation */ if(info->has_mode) { /* A bit of clever formatting */ if((info->has_nwid + 2*info->has_freq + 2*info->has_sens + !info->has_essid) > 4) printf("\n "); #ifdef COLOR printf (" Mode : %s%s%s\n", CYN, operation_mode[info->mode], CLR); #else printf(" Mode : %s\n", operation_mode[info->mode]); #endif } /* 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_mode + !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) { /* Fixed ? */ if(info->bitrate.fixed) printf("Bit Rate="); else printf("Bit Rate:"); if(info->bitrate.value >= GIGA) printf("%gGb/s", info->bitrate.value / GIGA); else if(info->bitrate.value >= MEGA) printf("%gMb/s", info->bitrate.value / MEGA); else printf("%gkb/s", info->bitrate.value / KILO); printf(" "); } /* Display the RTS threshold */ if(info->has_rts) { /* Disabled ? */ if(info->rts.disabled) printf("RTS thr:off "); else { /* Fixed ? */ if(info->rts.fixed) printf("RTS thr="); else printf("RTS thr:"); printf("%d B ", info->rts.value); } } /* Display the fragmentation threshold */ if(info->has_frag) { /* Disabled ? */ if(info->frag.disabled) printf("Fragment thr:off "); else { /* Fixed ? */ if(info->frag.fixed) printf("Fragment thr="); else printf("Fragment thr:"); printf("%d B ", info->frag.value); } } /* Formating */ if((info->has_bitrate) || (info->has_rts) || (info->has_bitrate)) printf("\n "); /* Display encryption information */ /* Note : we display only the "current" key, use iwspy to list all keys */ if(info->has_key) { printf("Encryption key:"); if((info->key_flags & IW_ENCODE_DISABLED) || (info->key_size == 0)) printf("off\n "); else { int i; printf("%.2X", info->key[0]); for(i = 1; i < info->key_size; i++) { if((i & 0x1) == 0) printf("-"); printf("%.2X", info->key[i]); } /* Other info... */ if((info->key_flags & IW_ENCODE_INDEX) > 1) printf(" [%d]", info->key_flags & IW_ENCODE_INDEX); if(info->key_flags & IW_ENCODE_RESTRICTED) printf(" Encryption mode:restricted"); if(info->key_flags & IW_ENCODE_OPEN) printf(" Encryption mode:open"); printf("\n "); } } /* Display Power Management information */ /* Note : we display only one parameter, period or timeout. If a device * (such as HiperLan) has both, we would need to be a bit more clever... */ if(info->has_power) /* I hope the device has power ;-) */ { printf("Power Management"); /* Disabled ? */ if(info->power.disabled) printf(":off\n "); else { /* Let's check the value and its type */ if(info->power.flags & IW_POWER_TYPE) { /* Type */ if(info->power.flags & IW_POWER_TIMEOUT) printf(" timeout:"); else printf(" period:"); /* Display value with units */ if(info->power.value >= (int) MEGA) printf("%gs ", ((double) info->power.value) / MEGA); else if(info->power.value >= (int) KILO) printf("%gms ", ((double) info->power.value) / KILO); else printf("%dus ", info->power.value); } /* Let's check the mode */ switch(info->power.flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: printf(" mode:Unicast received"); break; case IW_POWER_MULTICAST_R: printf(" mode:Multicast received"); break; case IW_POWER_ALL_R: printf(" mode:All packets received"); break; case IW_POWER_FORCE_S: printf(" mode:Force sending"); break; case IW_POWER_REPEATER: printf(" mode:Repeat multicasts"); break; default: } /* Let's check if nothing (simply on) */ if(info->power.flags == IW_POWER_ON) printf(":on"); printf("\n "); } } if(info->has_stats) { if(info->has_range && (info->stats.qual.level != 0)) /* Statistics are relative values (0 -> max) */ #ifdef COLOR /* LLDTxMode in BFSK or QFSK - 0=BFSK, 1=QFSK */ printf (" Link Quality : %s%d%s\t(2=QFSK, 1=BFSK)\n", BLD, info->stats.qual.qual, CLR); #else printf (" Link Quality : %d\t(2=QFSK, 1=BFSK)\n", info->stats.qual.qual); #endif a = 100; b = info->range.max_qual.level; c = info->stats.qual.level; signal_percent = (a / b) * c; #ifdef COLOR printf (" Signal Level : %s%d%s\t(Max %s%d%s)\n", BLD, info->stats.qual.level, CLR, BLD, info->range.max_qual.level, CLR); printf (" Noise Level : %s%d%s\t(Max %s%d%s)\n\n", BLD, info->stats.qual.noise, CLR, BLD, info->range.max_qual.noise, CLR); #else printf (" Signal Level : %d\t(Max %d)\n", info->stats.qual.level, info->range.max_qual.level); printf (" Noise Level : %d\t(Max %d)\n\n", info->stats.qual.noise, info->range.max_qual.noise); #endif #ifdef COLOR printf (" Invalid NWID : %s%d%s\n", RED, info->stats.discard.nwid, CLR); printf (" Invalid Crypt : %s%d%s\n", RED, info->stats.discard.code, CLR); printf (" Invalid Misc : %s%d%s\n", RED, info->stats.discard.misc, CLR); #else printf (" Invalid NWID : %d\n", info->stats.discard.nwid); printf (" Invalid Crypt : %d\n", info->stats.discard.code); printf (" Invalid Misc : %d\n", info->stats.discard.misc); #endif } /* bar graph header */ #ifdef COLOR printf ("\n\t\t\tSignal Level Bar Graph %s%d%%%s\n\n", BLD, signal_percent, CLR); #else printf ("\n\t\t\tSignal Level Bar Graph %d%%\n\n", signal_percent); #endif printf ("0%%"); for (x = WIDTH - 6; x != 0; --x) { printf (" "); } printf ("100%%\n"); printf ("|"); for (x = WIDTH - 2; x != 0; --x) { printf (" "); } printf ("|"); x = WIDTH; y = 100; chars = (x / y) * signal_percent; for (y = chars; y != 0; --y) { #ifdef COLOR printf ("%s#", BLD); #else printf ("#"); #endif } #ifdef COLOR printf ("%s\n", CLR); #else printf ("\n"); #endif } /*------------------------------------------------------------------*/ /* * 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(int skfd, /* The socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname) /* Dev name */ { struct iwreq wrq; int i; /* Set dev name */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); /* if nothing after the device name */ 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((!strcasecmp(args[i], "nwid")) || (!strcasecmp(args[i], "domain"))) { i++; if(i >= count) iw_usage(); if((!strcasecmp(args[i], "off")) || (!strcasecmp(args[i], "any"))) wrq.u.nwid.disabled = 1; else if(!strcasecmp(args[i], "on")) { /* Get old nwid */ if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0) { fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno)); return(-1); } strcpy(wrq.ifr_name, ifname); wrq.u.nwid.disabled = 0; } else if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value)) != 1) iw_usage(); else wrq.u.nwid.disabled = 0; wrq.u.nwid.fixed = 1; if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0) { fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno)); return(-1); } continue; } /* ---------- 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.sens.value)) != 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)) || (!strcmp(args[i], "key"))) { unsigned char key[IW_ENCODING_TOKEN_MAX]; if(++i >= count) iw_usage(); if(!strcasecmp(args[i], "on")) { /* Get old encryption information */ wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = 0; wrq.u.data.flags = 0; if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); return(-1); } strcpy(wrq.ifr_name, ifname); wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */ } else { char * buff; char * p; int temp; int k = 0; int gotone = 1; wrq.u.data.pointer = (caddr_t) NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; /* -- Check for the key -- */ if(!strncmp(args[i], "s:", 2)) { /* First case : as an ASCII string */ wrq.u.data.length = strlen(args[i] + 2); if(wrq.u.data.length > IW_ENCODING_TOKEN_MAX) wrq.u.data.length = IW_ENCODING_TOKEN_MAX; strncpy(key, args[i] + 2, wrq.u.data.length); wrq.u.data.pointer = (caddr_t) key; ++i; gotone = 1; } else { /* Second case : has hexadecimal digits */ p = buff = malloc(strlen(args[i]) + 1); strcpy(buff, args[i]); p = strtok(buff, "-:;.,"); while(p != (char *) NULL) { if(sscanf(p, "%2X", &temp) != 1) { gotone = 0; break; } key[k++] = (unsigned char) (temp & 0xFF); if(strlen(p) > 2) /* Token not finished yet */ p += 2; else p = strtok((char *) NULL, "-:;.,"); } free(buff); if(gotone) { ++i; wrq.u.data.length = k; wrq.u.data.pointer = (caddr_t) key; } } /* -- Check for token index -- */ if((i < count) && (sscanf(args[i], "[%d]", &temp) == 1) && (temp > 0) && (temp < IW_ENCODE_INDEX)) { wrq.u.encoding.flags |= temp; ++i; gotone = 1; } /* -- Check the various flags -- */ if(i < count) { if(!strcasecmp(args[i], "off")) wrq.u.data.flags |= IW_ENCODE_DISABLED; if(!strcasecmp(args[i], "open")) wrq.u.data.flags |= IW_ENCODE_OPEN; if(!strncasecmp(args[i], "restricted", 5)) wrq.u.data.flags |= IW_ENCODE_RESTRICTED; if(wrq.u.data.flags & IW_ENCODE_FLAGS) { ++i; gotone = 1; } } if(!gotone) iw_usage(); --i; } if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); return(-1); } continue; } /* ---------- Set ESSID ---------- */ if(!strcasecmp(args[i], "essid")) { char essid[IW_ESSID_MAX_SIZE + 1]; i++; if(i >= count) iw_usage(); if((!strcasecmp(args[i], "off")) || (!strcasecmp(args[i], "any"))) { wrq.u.essid.flags = 0; essid[0] = '\0'; } else if(!strcasecmp(args[i], "on")) { /* Get old essid */ wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = 0; wrq.u.essid.flags = 0; if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0) { fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno)); return(-1); } strcpy(wrq.ifr_name, ifname); wrq.u.essid.flags = 1; } else if(strlen(args[i]) > IW_ESSID_MAX_SIZE) { fprintf(stderr, "ESSID too long (max %d): ``%s''\n", IW_ESSID_MAX_SIZE, args[i]); iw_usage(); } else { wrq.u.essid.flags = 1; strcpy(essid, args[i]); } wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.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(); /* 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); } /* Get the address */ if(in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0) iw_usage(); if(ioctl(skfd, SIOCSIWAP, &wrq) < 0) { fprintf(stderr, "SIOCSIWAP: %s\n", strerror(errno)); return(-1); } continue; } /* ---------- 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(); } wrq.u.essid.pointer = (caddr_t) args[i]; wrq.u.essid.length = strlen(args[i]) + 1; if(ioctl(skfd, SIOCSIWNICKN, &wrq) < 0) { fprintf(stderr, "SIOCSIWNICKN: %s\n", strerror(errno)); return(-1); } continue; } /* ---------- Set Bit-Rate ---------- */ if((!strncmp(args[i], "bit", 3)) || (!strcmp(args[i], "rate"))) { 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); wrq.u.bitrate.fixed = 1; } else /* Should be a numeric value */ { double brate; if(sscanf(args[i], "%lg", &(brate)) != 1) iw_usage(); if(index(args[i], 'G')) brate *= GIGA; if(index(args[i], 'M')) brate *= MEGA; if(index(args[i], 'k')) brate *= KILO; wrq.u.bitrate.value = (long) brate; wrq.u.bitrate.fixed = 1; /* Check for an additional argument */ if(((i+1) < count) && (!strcasecmp(args[i+1], "auto"))) { wrq.u.bitrate.fixed = 0; ++i; } } } if(ioctl(skfd, SIOCSIWRATE, &wrq) < 0) { fprintf(stderr, "SIOCSIWRATE: %s\n", strerror(errno)); return(-1); } continue; } /* ---------- Set RTS threshold ---------- */ if(!strncasecmp(args[i], "rts", 3)) { i++; if(i >= count) iw_usage(); wrq.u.rts.value = -1; wrq.u.rts.fixed = 1; wrq.u.rts.disabled = 0; if(!strcasecmp(args[i], "off")) wrq.u.rts.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[i], "auto")) wrq.u.rts.fixed = 0; else { if(!strcasecmp(args[i], "fixed")) { /* Get old RTS threshold */ if(ioctl(skfd, SIOCGIWRTS, &wrq) < 0) { fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno)); return(-1); } strcpy(wrq.ifr_name, ifname); wrq.u.rts.fixed = 1; } else /* Should be a numeric value */ if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value)) != 1) iw_usage(); } if(ioctl(skfd, SIOCSIWRTS, &wrq) < 0) { fprintf(stderr, "SIOCSIWRTS: %s\n", strerror(errno)); return(-1); } continue; } /* ---------- Set fragmentation threshold ---------- */ if(!strncmp(args[i], "frag", 4)) { i++; if(i >= count) iw_usage(); wrq.u.frag.value = -1; wrq.u.frag.fixed = 1; wrq.u.frag.disabled = 0; if(!strcasecmp(args[i], "off")) wrq.u.frag.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[i], "auto")) wrq.u.frag.fixed = 0; else { if(!strcasecmp(args[i], "fixed")) { /* Get old fragmentation threshold */ if(ioctl(skfd, SIOCGIWFRAG, &wrq) < 0) { fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno)); return(-1); } strcpy(wrq.ifr_name, ifname); wrq.u.frag.fixed = 1; } else /* Should be a numeric value */ if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.frag.value)) != 1) iw_usage(); } if(ioctl(skfd, SIOCSIWFRAG, &wrq) < 0) { fprintf(stderr, "SIOCSIWFRAG: %s\n", strerror(errno)); return(-1); } continue; } /* ---------- Set operation mode ---------- */ if(!strcmp(args[i], "mode")) { int k; i++; if(i >= count) iw_usage(); if(sscanf(args[i], "%d", &k) != 1) { k = 0; while(k < 6 && strncasecmp(args[i], operation_mode[k], 3)) k++; } if((k > 5) || (k < 0)) iw_usage(); wrq.u.mode = k; if(ioctl(skfd, SIOCSIWMODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno)); return(-1); } continue; } /* ---------- Set Power Management ---------- */ if(!strncmp(args[i], "power", 3)) { if(++i >= count) iw_usage(); if(!strcasecmp(args[i], "off")) wrq.u.power.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[i], "on")) { /* Get old Power info */ if(ioctl(skfd, SIOCGIWPOWER, &wrq) < 0) { fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno)); return(-1); } strcpy(wrq.ifr_name, ifname); wrq.u.power.disabled = 0; } else { double temp; int gotone = 0; /* Default - nope */ wrq.u.power.flags = IW_POWER_ON; wrq.u.power.disabled = 0; /* Check value modifier */ if(!strcasecmp(args[i], "period")) { wrq.u.power.flags = IW_POWER_PERIOD; if(++i >= count) iw_usage(); } else if(!strcasecmp(args[i], "timeout")) { wrq.u.power.flags = IW_POWER_TIMEOUT; if(++i >= count) iw_usage(); } /* Is there any value to grab ? */ if(sscanf(args[i], "%lg", &(temp)) == 1) { temp *= MEGA; /* default = s */ if(index(args[i], 'u')) temp /= MEGA; if(index(args[i], 'm')) temp /= KILO; wrq.u.power.value = (long) temp; if(wrq.u.power.flags == IW_POWER_ON) wrq.u.power.flags = IW_POWER_PERIOD; ++i; gotone = 1; } /* Now, check the mode */ if(i < count) { if(!strcasecmp(args[i], "all")) wrq.u.power.flags |= IW_POWER_ALL_R; if(!strncasecmp(args[i], "unicast", 4)) wrq.u.power.flags |= IW_POWER_UNICAST_R; if(!strncasecmp(args[i], "multicast", 5)) wrq.u.power.flags |= IW_POWER_MULTICAST_R; if(!strncasecmp(args[i], "force", 5)) wrq.u.power.flags |= IW_POWER_FORCE_S; if(!strcasecmp(args[i], "repeat")) wrq.u.power.flags |= IW_POWER_REPEATER; if(wrq.u.power.flags & IW_POWER_MODE) { ++i; gotone = 1; } } if(!gotone) iw_usage(); --i; } if(ioctl(skfd, SIOCSIWPOWER, &wrq) < 0) { fprintf(stderr, "SIOCSIWPOWER(%d): %s\n", errno, strerror(errno)); return(-1); } continue; } /* ---------- Other ---------- */ /* Here we have an unrecognised arg... */ fprintf(stderr, "Invalid argument : %s\n", args[i]); iw_usage(); return(-1); } /* for(index ... */ return(0); } /******************************* MAIN ********************************/ /*------------------------------------------------------------------*/ /* * 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. */ if((skfd = sockets_open()) < 0) { perror("socket"); exit(-1); } /* No argument : show the list of all device + info */ if(argc == 1) { print_devices(skfd); close(skfd); exit(0); } /* Special case for help... */ if((!strncmp(argv[1], "-h", 9)) || (!strcmp(argv[1], "--help"))) { iw_usage(); close(skfd); exit(0); } /* The device name must be the first argument */ if(argc == 2) { for (;;) { print_info(skfd, argv[1]); usleep (SLEEP); } close(skfd); exit(0); } /* The other args on the line specify options to be set... */ goterr = set_info(skfd, argv + 2, argc - 2, argv[1]); /* Close the socket. */ close(skfd); return(goterr); }