/* * Set AP Address */ static int set_apaddr_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; /* Avoid "Unused parameter" warning */ count = count; if((!strcasecmp(args[0], "auto")) || (!strcasecmp(args[0], "any"))) { /* Send a broadcast address */ iw_broad_ether(&(wrq.u.ap_addr)); } else { if(!strcasecmp(args[0], "off")) { /* Send a NULL address */ iw_null_ether(&(wrq.u.ap_addr)); } else { /* Get the address and check if the interface supports it */ if(iw_in_addr(skfd, ifname, args[0], &(wrq.u.ap_addr)) < 0) { errarg = 0; return(IWERR_ARG_TYPE); } } } if(iw_set_ext(skfd, ifname, SIOCSIWAP, &wrq) < 0) return(IWERR_SET_EXT); /* 1 args */ return(1); }
/* * 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; /* if nothing after the device name - will never happen */ if(count < 1) { fprintf(stderr, "Error : too few arguments.\n"); return(-1); } /* The other args on the line specify options to be set... */ for(i = 0; i < count; i++) { /* ---------- Commit changes to driver ---------- */ if(!strncmp(args[i], "commit", 6)) { /* No args */ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq, "Commit changes"); continue; } /* ---------- Set network ID ---------- */ if((!strcasecmp(args[i], "nwid")) || (!strcasecmp(args[i], "domain"))) { i++; if(i >= count) ABORT_ARG_NUM("Set NWID", SIOCSIWNWID); if((!strcasecmp(args[i], "off")) || (!strcasecmp(args[i], "any"))) wrq.u.nwid.disabled = 1; else if(!strcasecmp(args[i], "on")) { /* Get old nwid */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq, "Set NWID"); wrq.u.nwid.disabled = 0; } else if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value)) != 1) ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]); else wrq.u.nwid.disabled = 0; wrq.u.nwid.fixed = 1; /* Set new nwid */ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq, "Set NWID"); continue; } /* ---------- Set frequency / channel ---------- */ if((!strncmp(args[i], "freq", 4)) || (!strcmp(args[i], "channel"))) { double freq; if(++i >= count) ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ); if(sscanf(args[i], "%lg", &(freq)) != 1) ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]); if(index(args[i], 'G')) freq *= GIGA; if(index(args[i], 'M')) freq *= MEGA; if(index(args[i], 'k')) freq *= KILO; iw_float2freq(freq, &(wrq.u.freq)); IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq, "Set Frequency"); continue; } /* ---------- Set sensitivity ---------- */ if(!strncmp(args[i], "sens", 4)) { if(++i >= count) ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS); if(sscanf(args[i], "%i", &(wrq.u.sens.value)) != 1) ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]); IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq, "Set Sensitivity"); continue; } /* ---------- Set encryption stuff ---------- */ if((!strncmp(args[i], "enc", 3)) || (!strcmp(args[i], "key"))) { unsigned char key[IW_ENCODING_TOKEN_MAX]; if(++i >= count) ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE); if(!strcasecmp(args[i], "on")) { /* Get old encryption information */ wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq, "Set Encode"); wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */ } else { int gotone = 0; int oldone; int keylen; int temp; wrq.u.data.pointer = (caddr_t) NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; /* Allow arguments in any order (it's safe) */ do { oldone = gotone; /* -- Check for the key -- */ if(i < count) { keylen = iw_in_key_full(skfd, ifname, args[i], key, &wrq.u.data.flags); if(keylen > 0) { wrq.u.data.length = keylen; wrq.u.data.pointer = (caddr_t) key; ++i; gotone++; } } /* -- Check for token index -- */ if((i < count) && (sscanf(args[i], "%i", &temp) == 1) && (temp > 0) && (temp < IW_ENCODE_INDEX)) { wrq.u.encoding.flags |= temp; ++i; gotone++; } /* -- Check the various flags -- */ if((i < count) && (!strcasecmp(args[i], "off"))) { wrq.u.data.flags |= IW_ENCODE_DISABLED; ++i; gotone++; } if((i < count) && (!strcasecmp(args[i], "open"))) { wrq.u.data.flags |= IW_ENCODE_OPEN; ++i; gotone++; } if((i < count) && (!strncasecmp(args[i], "restricted", 5))) { wrq.u.data.flags |= IW_ENCODE_RESTRICTED; ++i; gotone++; } #if WIRELESS_EXT > 15 if((i < count) && (!strncasecmp(args[i], "temporary", 4))) { wrq.u.data.flags |= IW_ENCODE_TEMP; ++i; gotone++; } #endif } while(gotone != oldone); /* Pointer is absent in new API */ if(wrq.u.data.pointer == NULL) wrq.u.data.flags |= IW_ENCODE_NOKEY; /* Check if we have any invalid argument */ if(!gotone) ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]); /* Get back to last processed argument */ --i; } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq, "Set Encode"); continue; } /* ---------- Set ESSID ---------- */ if(!strcasecmp(args[i], "essid")) { char essid[IW_ESSID_MAX_SIZE + 1]; i++; if(i >= count) ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID); 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 = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq, "Set ESSID"); wrq.u.essid.flags = 1; } else { /* '-' allow to escape the ESSID string, allowing * to set it to the string "any" or "off". * This is a big ugly, but it will do for now */ if(!strcmp(args[i], "-")) { i++; if(i >= count) ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID); } /* Check the size of what the user passed us to avoid * buffer overflows */ if(strlen(args[i]) > IW_ESSID_MAX_SIZE) ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE); else { int temp; wrq.u.essid.flags = 1; strcpy(essid, args[i]); /* Size checked, all clear */ /* Check for ESSID index */ if(((i+1) < count) && (sscanf(args[i+1], "[%i]", &temp) == 1) && (temp > 0) && (temp < IW_ENCODE_INDEX)) { wrq.u.essid.flags = temp; ++i; } } } wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = strlen(essid) + 1; IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq, "Set ESSID"); continue; } /* ---------- Set AP address ---------- */ if(!strcasecmp(args[i], "ap")) { if(++i >= count) ABORT_ARG_NUM("Set AP Address", SIOCSIWAP); if((!strcasecmp(args[i], "auto")) || (!strcasecmp(args[i], "any"))) { /* Send a broadcast address */ iw_broad_ether(&(wrq.u.ap_addr)); } else { if(!strcasecmp(args[i], "off")) { /* Send a NULL address */ iw_null_ether(&(wrq.u.ap_addr)); } else { /* Get the address and check if the interface supports it */ if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0) ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]); } } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq, "Set AP Address"); continue; } /* ---------- Set NickName ---------- */ if(!strncmp(args[i], "nick", 4)) { i++; if(i >= count) ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN); if(strlen(args[i]) > IW_ESSID_MAX_SIZE) ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE); wrq.u.essid.pointer = (caddr_t) args[i]; wrq.u.essid.length = strlen(args[i]) + 1; IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq, "Set Nickname"); continue; } /* ---------- Set Bit-Rate ---------- */ if((!strncmp(args[i], "bit", 3)) || (!strcmp(args[i], "rate"))) { if(++i >= count) ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE); if(!strcasecmp(args[i], "auto")) { wrq.u.bitrate.value = -1; wrq.u.bitrate.fixed = 0; } else { if(!strcasecmp(args[i], "fixed")) { /* Get old bitrate */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq, "Set Bit Rate"); wrq.u.bitrate.fixed = 1; } else /* Should be a numeric value */ { double brate; if(sscanf(args[i], "%lg", &(brate)) != 1) ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]); if(index(args[i], 'G')) brate *= GIGA; if(index(args[i], 'M')) brate *= MEGA; if(index(args[i], 'k')) brate *= KILO; wrq.u.bitrate.value = (long) brate; wrq.u.bitrate.fixed = 1; /* Check for an additional argument */ if(((i+1) < count) && (!strcasecmp(args[i+1], "auto"))) { wrq.u.bitrate.fixed = 0; ++i; } if(((i+1) < count) && (!strcasecmp(args[i+1], "fixed"))) { wrq.u.bitrate.fixed = 1; ++i; } } } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq, "Set Bit Rate"); continue; } /* ---------- Set RTS threshold ---------- */ if(!strncasecmp(args[i], "rts", 3)) { i++; if(i >= count) ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS); 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 */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq, "Set RTS Threshold"); wrq.u.rts.fixed = 1; } else /* Should be a numeric value */ if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.rts.value)) != 1) ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]); } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq, "Set RTS Threshold"); continue; } /* ---------- Set fragmentation threshold ---------- */ if(!strncmp(args[i], "frag", 4)) { i++; if(i >= count) ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG); 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 */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq, "Set Fragmentation Threshold"); wrq.u.frag.fixed = 1; } else /* Should be a numeric value */ if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.frag.value)) != 1) ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG, args[i]); } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq, "Set Fragmentation Threshold"); continue; } /* ---------- Set operation mode ---------- */ if(!strcmp(args[i], "mode")) { int k; i++; if(i >= count) ABORT_ARG_NUM("Set Mode", SIOCSIWMODE); if(sscanf(args[i], "%i", &k) != 1) { k = 0; while((k < IW_NUM_OPER_MODE) && strncasecmp(args[i], iw_operation_mode[k], 3)) k++; } if((k >= IW_NUM_OPER_MODE) || (k < 0)) ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]); wrq.u.mode = k; IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq, "Set Mode"); continue; } /* ---------- Set Power Management ---------- */ if(!strncmp(args[i], "power", 3)) { if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); if(!strcasecmp(args[i], "off")) wrq.u.power.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[i], "on")) { /* Get old Power info */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq, "Set Power Management"); 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], "min")) { wrq.u.power.flags |= IW_POWER_MIN; if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } else if(!strcasecmp(args[i], "max")) { wrq.u.power.flags |= IW_POWER_MAX; if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } /* Check value type */ if(!strcasecmp(args[i], "period")) { wrq.u.power.flags |= IW_POWER_PERIOD; if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } else if(!strcasecmp(args[i], "timeout")) { wrq.u.power.flags |= IW_POWER_TIMEOUT; if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } /* 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_TYPE) == 0) wrq.u.power.flags |= IW_POWER_PERIOD; ++i; gotone = 1; } /* Now, check the mode */ if(i < count) { if(!strcasecmp(args[i], "all")) wrq.u.power.flags |= IW_POWER_ALL_R; if(!strncasecmp(args[i], "unicast", 4)) wrq.u.power.flags |= IW_POWER_UNICAST_R; if(!strncasecmp(args[i], "multicast", 5)) wrq.u.power.flags |= IW_POWER_MULTICAST_R; if(!strncasecmp(args[i], "force", 5)) wrq.u.power.flags |= IW_POWER_FORCE_S; if(!strcasecmp(args[i], "repeat")) wrq.u.power.flags |= IW_POWER_REPEATER; if(wrq.u.power.flags & IW_POWER_MODE) { ++i; gotone = 1; } } if(!gotone) ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER, args[i]); --i; } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq, "Set Power Management"); continue; } #if WIRELESS_EXT > 9 /* ---------- Set Transmit-Power ---------- */ if(!strncmp(args[i], "txpower", 3)) { struct iw_range range; if(++i >= count) ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW); /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); /* Prepare the request */ wrq.u.txpower.value = -1; wrq.u.txpower.fixed = 1; wrq.u.txpower.disabled = 0; wrq.u.data.flags = IW_TXPOW_DBM; if(!strcasecmp(args[i], "off")) wrq.u.txpower.disabled = 1; /* i.e. turn radio off */ else if(!strcasecmp(args[i], "auto")) wrq.u.txpower.fixed = 0; /* i.e. use power control */ else { if(!strcasecmp(args[i], "fixed")) { /* Get old tx-power */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq, "Set Tx Power"); wrq.u.txpower.fixed = 1; } else /* Should be a numeric value */ { int power; int ismwatt = 0; /* Get the value */ if(sscanf(args[i], "%i", &(power)) != 1) ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW, args[i]); /* Check if milliwatt */ ismwatt = (index(args[i], 'm') != NULL); /* Convert */ if(range.txpower_capa & IW_TXPOW_MWATT) { if(!ismwatt) power = iw_dbm2mwatt(power); wrq.u.data.flags = IW_TXPOW_MWATT; } else { if(ismwatt) power = iw_mwatt2dbm(power); wrq.u.data.flags = IW_TXPOW_DBM; } wrq.u.txpower.value = power; /* Check for an additional argument */ if(((i+1) < count) && (!strcasecmp(args[i+1], "auto"))) { wrq.u.txpower.fixed = 0; ++i; } if(((i+1) < count) && (!strcasecmp(args[i+1], "fixed"))) { wrq.u.txpower.fixed = 1; ++i; } } } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq, "Set Tx Power"); continue; } #endif #if WIRELESS_EXT > 10 /* ---------- Set Retry limit ---------- */ if(!strncmp(args[i], "retry", 3)) { double temp; int gotone = 0; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); /* Default - nope */ wrq.u.retry.flags = IW_RETRY_LIMIT; wrq.u.retry.disabled = 0; /* Check value modifier */ if(!strcasecmp(args[i], "min")) { wrq.u.retry.flags |= IW_RETRY_MIN; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } else if(!strcasecmp(args[i], "max")) { wrq.u.retry.flags |= IW_RETRY_MAX; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } /* Check value type */ if(!strcasecmp(args[i], "limit")) { wrq.u.retry.flags |= IW_RETRY_LIMIT; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } else if(!strncasecmp(args[i], "lifetime", 4)) { wrq.u.retry.flags &= ~IW_RETRY_LIMIT; wrq.u.retry.flags |= IW_RETRY_LIFETIME; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } /* Is there any value to grab ? */ if(sscanf(args[i], "%lg", &(temp)) == 1) { /* Limit is absolute, on the other hand lifetime is seconds */ if(!(wrq.u.retry.flags & IW_RETRY_LIMIT)) { /* Normalise lifetime */ temp *= MEGA; /* default = s */ if(index(args[i], 'u')) temp /= MEGA; if(index(args[i], 'm')) temp /= KILO; } wrq.u.retry.value = (long) temp; ++i; gotone = 1; } if(!gotone) ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]); --i; IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq, "Set Retry Limit"); continue; } #endif /* WIRELESS_EXT > 10 */ /* ---------- Other ---------- */ /* Here we have an unrecognised arg... */ fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n", args[i]); return(-1); } /* for(index ... */ return(0); }
/* * Execute a private command on the interface */ static int set_private_cmd(int skfd, /* Socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname, /* Dev name */ char * cmdname, /* Command name */ iwprivargs * priv, /* Private ioctl description */ int priv_num) /* Number of descriptions */ { struct iwreq wrq; u_char buffer[8192]; /* Only that big in v25 and later */ int i = 0; /* Start with first command arg */ int k; /* Index in private description table */ int temp; int subcmd = 0; /* sub-ioctl index */ int offset = 0; /* Space for sub-ioctl index */ /* Check if we have a token index. * Do it now so that sub-ioctl takes precedence, and so that we * don't have to bother with it later on... */ if((count >= 1) && (sscanf(args[0], "[%i]", &temp) == 1)) { subcmd = temp; args++; count--; } /* Search the correct ioctl */ k = -1; while((++k < priv_num) && strcmp(priv[k].name, cmdname)); /* If not found... */ if(k == priv_num) { fprintf(stderr, "Invalid command : %s\n", cmdname); return(-1); } /* Watch out for sub-ioctls ! */ if(priv[k].cmd < SIOCDEVPRIVATE) { int j = -1; /* Find the matching *real* ioctl */ while((++j < priv_num) && ((priv[j].name[0] != '\0') || (priv[j].set_args != priv[k].set_args) || (priv[j].get_args != priv[k].get_args))); /* If not found... */ if(j == priv_num) { fprintf(stderr, "Invalid private ioctl definition for : %s\n", cmdname); return(-1); } /* Save sub-ioctl number */ subcmd = priv[k].cmd; /* Reserve one int (simplify alignment issues) */ offset = sizeof(__u32); /* Use real ioctl definition from now on */ k = j; #if 0 printf("<mapping sub-ioctl %s to cmd 0x%X-%d>\n", cmdname, priv[k].cmd, subcmd); #endif } /* If we have to set some data */ if((priv[k].set_args & IW_PRIV_TYPE_MASK) && (priv[k].set_args & IW_PRIV_SIZE_MASK)) { switch(priv[k].set_args & IW_PRIV_TYPE_MASK) { case IW_PRIV_TYPE_BYTE: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { sscanf(args[i], "%i", &temp); buffer[i] = (char) temp; } break; case IW_PRIV_TYPE_INT: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { sscanf(args[i], "%i", &temp); ((__s32 *) buffer)[i] = (__s32) temp; } break; case IW_PRIV_TYPE_CHAR: if(i < count) { /* Size of the string to fetch */ wrq.u.data.length = strlen(args[i]) + 1; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch string */ memcpy(buffer, args[i], wrq.u.data.length); buffer[sizeof(buffer) - 1] = '\0'; i++; } else { wrq.u.data.length = 1; buffer[0] = '\0'; } break; case IW_PRIV_TYPE_FLOAT: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { double freq; if(sscanf(args[i], "%lg", &(freq)) != 1) { printf("Invalid float [%s]...\n", args[i]); return(-1); } if(strchr(args[i], 'G')) freq *= GIGA; if(strchr(args[i], 'M')) freq *= MEGA; if(strchr(args[i], 'k')) freq *= KILO; sscanf(args[i], "%i", &temp); iw_float2freq(freq, ((struct iw_freq *) buffer) + i); } break; case IW_PRIV_TYPE_ADDR: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { if(iw_in_addr(skfd, ifname, args[i], ((struct sockaddr *) buffer) + i) < 0) { printf("Invalid address [%s]...\n", args[i]); return(-1); } } break; default: fprintf(stderr, "Not implemented...\n"); return(-1); } if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && (wrq.u.data.length != (priv[k].set_args & IW_PRIV_SIZE_MASK))) { printf("The command %s needs exactly %d argument(s)...\n", cmdname, priv[k].set_args & IW_PRIV_SIZE_MASK); return(-1); } } /* if args to set */ else { wrq.u.data.length = 0L; } strncpy(wrq.ifr_name, ifname, IFNAMSIZ); /* Those two tests are important. They define how the driver * will have to handle the data */ if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && ((iw_get_priv_size(priv[k].set_args) + offset) <= IFNAMSIZ)) { /* First case : all SET args fit within wrq */ if(offset) wrq.u.mode = subcmd; memcpy(wrq.u.name + offset, buffer, IFNAMSIZ - offset); } else { if((priv[k].set_args == 0) && (priv[k].get_args & IW_PRIV_SIZE_FIXED) && (iw_get_priv_size(priv[k].get_args) <= IFNAMSIZ)) { /* Second case : no SET args, GET args fit within wrq */ if(offset) wrq.u.mode = subcmd; } else { /* Third case : args won't fit in wrq, or variable number of args */ wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.flags = subcmd; } } #if 1 if((priv[k].cmd == 0x8BED) && (wrq.u.data.pointer == (caddr_t) buffer)) wrq.u.data.length = sizeof(buffer); #endif /* Perform the private ioctl */ if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept private ioctl...\n"); fprintf(stderr, "%s (%X): %s\n", cmdname, priv[k].cmd, strerror(errno)); return(-1); } /* If we have to get some data */ if((priv[k].get_args & IW_PRIV_TYPE_MASK) && (priv[k].get_args & IW_PRIV_SIZE_MASK)) { int j; int n = 0; /* number of args */ printf("%-8.16s %s:", ifname, cmdname); /* Check where is the returned data */ if((priv[k].get_args & IW_PRIV_SIZE_FIXED) && (iw_get_priv_size(priv[k].get_args) <= IFNAMSIZ)) { memcpy(buffer, wrq.u.name, IFNAMSIZ); n = priv[k].get_args & IW_PRIV_SIZE_MASK; } else n = wrq.u.data.length; switch(priv[k].get_args & IW_PRIV_TYPE_MASK) { case IW_PRIV_TYPE_BYTE: /* Display args */ for(j = 0; j < n; j++) printf("%d ", buffer[j]); printf("\n"); break; case IW_PRIV_TYPE_INT: /* Display args */ for(j = 0; j < n; j++) printf("%d ", ((__s32 *) buffer)[j]); printf("\n"); break; case IW_PRIV_TYPE_CHAR: /* Display args */ buffer[n] = '\0'; printf("%s\n", buffer); break; case IW_PRIV_TYPE_FLOAT: { double freq; /* Display args */ for(j = 0; j < n; j++) { freq = iw_freq2float(((struct iw_freq *) buffer) + j); if(freq >= GIGA) printf("%gG ", freq / GIGA); else if(freq >= MEGA) printf("%gM ", freq / MEGA); else printf("%gk ", freq / KILO); } printf("\n"); } break; case IW_PRIV_TYPE_ADDR: { char scratch[128]; struct sockaddr * hwa; /* Display args */ for(j = 0; j < n; j++) { hwa = ((struct sockaddr *) buffer) + j; if(j) printf(" %.*s", (int) strlen(cmdname), " "); printf("%s\n", iw_saether_ntop(hwa, scratch)); } } break; default: fprintf(stderr, "Not yet implemented...\n"); return(-1); } } /* if args to set */ return(0); }
/* * Set list of addresses specified on command line in the driver. */ static int set_spy_info(int skfd, /* The socket */ char * ifname, /* Dev name */ char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i; int nbr; /* Number of valid addresses */ struct sockaddr hw_address[IW_MAX_SPY]; /* Read command line */ i = 0; /* first arg to read */ nbr = 0; /* Number of args read so far */ /* "off" : disable functionality (set 0 addresses) */ if(!strcmp(args[0], "off")) i = 1; /* skip the "off" */ else { /* "+" : add all addresses already in the driver */ if(!strcmp(args[0], "+")) { char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_SPY]; /* Check if we have valid mac address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname); return(-1); } wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = IW_MAX_SPY; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept reading addresses...\n"); fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno)); return(-1); } /* Copy old addresses */ nbr = wrq.u.data.length; memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr)); i = 1; /* skip the "+" */ } /* Read other args on command line */ while((i < count) && (nbr < IW_MAX_SPY)) { /* Get the address and check if the interface supports it */ if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0) continue; nbr++; } /* Check the number of addresses */ if(nbr == 0) { fprintf(stderr, "No valid addresses found : exiting...\n"); return(-1); } } /* Check if there is some remaining arguments */ if(i < count) { fprintf(stderr, "Got only the first %d arguments, remaining discarded\n", i); } /* Time to do send addresses to the driver */ wrq.u.data.pointer = (caddr_t) hw_address; wrq.u.data.length = nbr; wrq.u.data.flags = 0; if(iw_set_ext(skfd, ifname, SIOCSIWSPY, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept addresses...\n"); fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno)); return(-1); } return(0); }