X-Git-Url: http://git.osdn.net/view?p=android-x86%2Fexternal-wireless-tools.git;a=blobdiff_plain;f=wireless_tools%2Fiwpriv.c;h=8ee2029535837351c7e0913e1deb3ab4f1a9cd6d;hp=986ffd88e03836ca402e6c1ceaf7c9bbf364d9a8;hb=41b8e9b1157054ddcb90e68f1b12707811c90361;hpb=1b80ed8726aa0f9de14e4231e8d199e5e27ef533 diff --git a/wireless_tools/iwpriv.c b/wireless_tools/iwpriv.c index 986ffd8..8ee2029 100644 --- a/wireless_tools/iwpriv.c +++ b/wireless_tools/iwpriv.c @@ -1,21 +1,44 @@ /* * Wireless Tools * - * Jean II - HPLB 97->99 - HPL 99->00 + * Jean II - HPLB 97->99 - HPL 99->07 * * Main code for "iwconfig". This is the generic tool for most * manipulations... * You need to link this code against "iwlib.c" and "-lm". * * This file is released under the GPL license. - * Copyright (c) 1997-2002 Jean Tourrilhes + * Copyright (c) 1997-2007 Jean Tourrilhes */ -#include "iwlib.h" /* Header */ +#include "iwlib-private.h" /* Private header */ /************************** DOCUMENTATION **************************/ /* + * BASIC PRINCIPLE + * --------------- + * Wireless Extension recognise that each wireless device has some + * specific features not covered by the standard wireless extensions. + * Private wireless ioctls/requests allow a device to export the control + * of those device specific features, and allow users to directly interact + * with your driver. + * There are many other ways you can implement such functionality : + * o module parameters + * o netlink socket + * o file system (/proc/ or /sysfs/) + * o extra character device (/dev/) + * Private wireless ioctls is one of the simplest implementation, + * however it is limited, so you may want to check the alternatives. + * + * Like for standard Wireless Extensions, each private wireless + * request is identified by an IOCTL NUMBER and carry a certain number + * of arguments (SET or GET). + * The driver exports a description of those requests (ioctl number, + * request name, set and get arguments). Then, iwpriv uses those request + * descriptions to call the appropriate request and handle the + * arguments. + * * IOCTL RANGES : * ------------ * The initial implementation of iwpriv was using the SIOCDEVPRIVATE @@ -27,74 +50,99 @@ * worry about collisions with other usages. On the other hand, in the * new range, the SET convention is enforced (see below). * The differences are : SIOCDEVPRIVATE SIOCIWFIRSTPRIV - * o availability : <= 2.5.X WE > 11 (>= 2.4.13) + * o availability <= 2.5.X WE > 11 (>= 2.4.13) * o collisions yes no * o SET convention optional enforced * o number 16 32 * * NEW DRIVER API : * -------------- - * Wireless Extension 13 introduce a new driver API. Wireless + * Wireless Extension 13 introduces a new driver API. Wireless * Extensions requests can be handled via a iw_handler table instead * of through the regular ioctl handler. * The new driver API can be handled only with the new ioctl range - * and enforce the GET convention (see below). + * and enforces the GET convention (see below). * The differences are : old API new API * o handler do_ioctl() struct iw_handler_def * o SIOCIWFIRSTPRIV WE > 11 yes * o SIOCDEVPRIVATE yes no * o GET convention optional enforced * Note that the new API before Wireless Extension 15 contains bugs - * with regards to handling sub-ioctls and addr/float data types. + * when handling sub-ioctls and addr/float data types. + * + * INLINING vs. POINTER : + * -------------------- + * One of the tricky aspect of the old driver API is how the data + * is handled, which is how the driver is supposed to extract the data + * passed to it by iwpriv. + * 1) If the data has a fixed size (private ioctl definition + * has the flag IW_PRIV_SIZE_FIXED) and the byte size of the data is + * lower than 16 bytes, the data will be inlined. The driver can extract + * data in the field 'u.name' of the struct iwreq. + * 2) If the if the data doesn't have a fixed size or is larger than + * 16 bytes, the data is passed by pointer. struct iwreq contains a + * struct iwpoint with a user space pointer to the data. Appropriate + * copy_from/to_user() function should be used. + * + * With the new API, this is handled transparently, the data is + * always available as the fourth argument of the request handler + * (usually called 'extra'). * * SET/GET CONVENTION : * ------------------ - * The regular Wireless Extensions use a SET/GET convention, where - * the low order bit identify a SET (0) or a GET (1) request. - * The new ioctl range enforce the SET convention : SET request will + * Simplistic summary : + * o even numbered ioctls are SET, restricted to root, and should not + * return arguments (get_args = 0). + * o odd numbered ioctls are GET, authorised to anybody, and should + * not expect any arguments (set_args = 0). + * + * The regular Wireless Extensions use the SET/GET convention, where + * the low order bit identify a SET (0) or a GET (1) request. The private + * Wireless Extension is not as restrictive, but still has some + * limitations. + * The new ioctl range enforces the SET convention : SET request will * be available to root only and can't return any arguments. If you don't * like that, just use every other two ioctl. * The new driver API enforce the GET convention : GET request won't * be able to accept any arguments (except if its fits within (union - * iwreq_data)). If you don't like that, just use the old API (aka the - * ioctl handler). + * iwreq_data)). If you don't like that, you can either use the Token Index + * support or the old API (aka the ioctl handler). * In any case, it's a good idea to not have ioctl with both SET * and GET arguments. If the GET arguments doesn't fit within * (union iwreq_data) and SET do, or vice versa, the current code in iwpriv * won't work. One exception is if both SET and GET arguments fit within * (union iwreq_data), this case should be handled safely in a GET * request. + * If you don't fully understand those limitations, just follow the + * rules of the simplistic summary ;-) * * SUB-IOCTLS : * ---------- - * Wireless Extension 15 introduce sub-ioctls. For some applications, - * 32 ioctl is not enough, and this simple mechanism allow to increase - * the number of ioctls by adding a sub-ioctl index to some of the ioctl - * (so basically a two level addressing). + * Wireless Extension 15 introduces sub-ioctls. For some applications, + * 32 ioctls is not enough, and this simple mechanism allows to increase + * the number of ioctls by adding a sub-ioctl index to some of the ioctls + * (so basically it's a two level addressing). * One might argue that at the point, some other mechanisms might be * better, like using a real filesystem abstraction (/proc, driverfs, ...), - * but sub-ioctls are simple enough to not have much drawbacks (which means - * that it's a quick and dirty hack ;-). + * but sub-ioctls are simple enough and don't have much drawbacks (which + * means that it's a quick and dirty hack ;-). * - * There is two slightly different variation of the sub-ioctl scheme : - * If the payload fit within (union iwreq_data), the first int (4 bytes) - * is reserved as the sub-ioctl number and the regular payload shifted by - * 4 bytes. - * If the ioctl use (struct iw_point), the sub-ioctl number is in the - * flags member of the structure. - * Then, in your handler you would just extract the sub-ioctl number - * and do the appropriate processing. + * There are two slightly different variations of the sub-ioctl scheme : + * 1) If the payload fits within (union iwreq_data), the first int + * (4 bytes) is reserved as the sub-ioctl number and the regular payload + * shifted by 4 bytes. The handler must extract the sub-ioctl number, + * increment the data pointer and then use it in the usual way. + * 2) If the ioctl uses (struct iw_point), the sub-ioctl number is + * set in the flags member of the structure. In this case, the handler + * should simply get the sub-ioctl number from the flags and process the + * data in the usual way. * * Sub-ioctls are declared normally in the private definition table, - * with cmd (first arg) beeing the sub-ioctl number. Then, you need to - * declare the real ioctl which will process the sub-ioctls with the - * SAME ARGUMENTS and a NULL NAME. - * It could look like, for example : + * with cmd (first arg) being the sub-ioctl number. Then, you should + * declare the real ioctl, which will process the sub-ioctls, with + * the SAME ARGUMENTS and a EMPTY NAME. + * Here's an example of how it could look like : * -------------------------------------------- - // --- Raw access to sub-ioctl handlers --- - { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_paramN" }, - { 0x8BE1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_paramN" }, // --- sub-ioctls handlers --- { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" }, { 0x8BE1, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" }, @@ -103,21 +151,26 @@ { 1, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param1" }, { 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_param2" }, { 2, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param2" }, + // --- Raw access to sub-ioctl handlers --- + { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_paramN" }, + { 0x8BE1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_paramN" }, * -------------------------------------------- * And iwpriv should do the rest for you ;-) * - * Note that version of iwpriv up to v24 (included) expect at most + * Note that versions of iwpriv up to v24 (included) expect at most * 16 ioctls definitions and will likely crash when given more. - * There is no fix that I can see, apart from recommending an upgrade - * of Wireless Tools. Wireless Extensions 15 will check this condition, so - * another workaround is restricting those extra definitions to WE-15. + * There is no fix that I can see, apart from recommending your users + * to upgrade their Wireless Tools. Wireless Extensions 15 will check this + * condition, so another workaround is restricting those extra definitions + * to WE-15. * - * Another problem is that new API before Wireless Extension 15 - * will get it wrong when passing fixed arguments of 12-15 bytes. It will + * Another problem is that the new API before Wireless Extension 15 + * has a bug when passing fixed arguments of 12-15 bytes. It will * try to get them inline instead of by pointer. You can fool the new API * to do the right thing using fake ioctl definitions (but remember that - * you will get more likely to hit the limit of 16 ioctl definitions). - * For safety, use the ioctl handler before v15. + * you will be more likely to hit the limit of 16 ioctl definitions). + * To play safe, use the old-style ioctl handler before v15. * * NEW DATA TYPES (ADDR/FLOAT) : * --------------------------- @@ -127,7 +180,7 @@ * However, the new API before v15 won't handle them properly. * * The first problem is that the new API won't know their size, so - * won't copy them. This can be workaround with a fake ioctl definition. + * it won't copy them. This can be workaround with a fake ioctl definition. * The second problem is that a fixed single addr won't be inlined * in struct iwreq and will be passed as a pointer. This is due to an * off-by-one error, where all fixed data of 16 bytes is considered too @@ -138,17 +191,19 @@ * * TOKEN INDEX : * ----------- - * Token index is very similar to sub-ioctl. It allow the user + * Token index is very similar to sub-ioctl. It allows the user * to specify an integer index in front of a bunch of other arguments - * (addresses, strings, ...). - * Token index works only with data passed as pointer, and is - * otherwise ignored. If your data would fit within struct iwreq, you - * need to declare the command *without* IW_PRIV_SIZE_FIXED to force + * (addresses, strings, ...). It's specified in square brackets on the + * iwpriv command line before other arguments. + * > iwpriv eth0 [index] args... + * Token index works only when the data is passed as pointer, and + * is otherwise ignored. If your data would fit within struct iwreq, you + * should declare the command *without* IW_PRIV_SIZE_FIXED to force * this to happen (and check arg number yourself). * -------------------------------------------- // --- Commands that would fit in struct iwreq --- { 0x8BE0, IW_PRIV_TYPE_ADDR | 1, 0, "set_param_with_token" }, - // --- No problem here --- + // --- No problem here (bigger than struct iwreq) --- { 0x8BE1, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 2, 0, "again" }, * -------------------------------------------- * The token index feature is pretty transparent, the token index @@ -156,7 +211,7 @@ * (if the user doesn't specify it) will be 0. Token index itself will * work with any version of Wireless Extensions. * Token index is not compatible with sub-ioctl (both use the same - * field of struct iw_point). However, token index can be use to offer + * field of struct iw_point). However, the token index can be used to offer * raw access to the sub-ioctl handlers (if it uses struct iw_point) : * -------------------------------------------- // --- sub-ioctls handler --- @@ -176,13 +231,6 @@ static const char * argtype[] = { " ", "byte ", "char ", "", "int ", "float", "addr " }; -#define IW_MAX_PRIV_DEF 128 - -/* Backward compatibility */ -#ifndef IW_PRIV_TYPE_ADDR -#define IW_PRIV_TYPE_ADDR 0x6000 -#endif /* IW_PRIV_TYPE_ADDR */ - /************************* MISC SUBROUTINES **************************/ /*------------------------------------------------------------------*/ @@ -193,8 +241,6 @@ static void iw_usage(void) { fprintf(stderr, "Usage: iwpriv interface [private-command [private-arguments]]\n"); - fprintf(stderr, " interface [roam {on|off}]\n"); - fprintf(stderr, " interface [port {ad-hoc|managed|N}]\n"); } /************************* SETTING ROUTINES **************************/ @@ -221,9 +267,9 @@ set_private_cmd(int skfd, /* Socket */ int offset = 0; /* Space for sub-ioctl index */ /* Check if we have a token index. - * Do it know so that sub-ioctl takes precendence, and so that we + * 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], "[%d]", &temp) == 1)) + if((count >= 1) && (sscanf(args[0], "[%i]", &temp) == 1)) { subcmd = temp; args++; @@ -261,13 +307,15 @@ set_private_cmd(int skfd, /* Socket */ /* Save sub-ioctl number */ subcmd = priv[k].cmd; - /* Reserve one int (simplify alignement issues) */ + /* Reserve one int (simplify alignment issues) */ offset = sizeof(__u32); /* Use real ioctl definition from now on */ k = j; +#if 0 printf("\n", cmdname, priv[k].cmd, subcmd); +#endif } /* If we have to set some data */ @@ -284,7 +332,7 @@ set_private_cmd(int skfd, /* Socket */ /* Fetch args */ for(; i < wrq.u.data.length; i++) { - sscanf(args[i], "%d", &temp); + sscanf(args[i], "%i", &temp); buffer[i] = (char) temp; } break; @@ -297,7 +345,7 @@ set_private_cmd(int skfd, /* Socket */ /* Fetch args */ for(; i < wrq.u.data.length; i++) { - sscanf(args[i], "%d", &temp); + sscanf(args[i], "%i", &temp); ((__s32 *) buffer)[i] = (__s32) temp; } break; @@ -336,10 +384,10 @@ set_private_cmd(int skfd, /* Socket */ printf("Invalid float [%s]...\n", args[i]); return(-1); } - if(index(args[i], 'G')) freq *= GIGA; - if(index(args[i], 'M')) freq *= MEGA; - if(index(args[i], 'k')) freq *= KILO; - sscanf(args[i], "%d", &temp); + 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; @@ -362,14 +410,14 @@ set_private_cmd(int skfd, /* Socket */ break; default: - fprintf(stderr, "Not yet implemented...\n"); + 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 need exactly %d argument...\n", + printf("The command %s needs exactly %d argument(s)...\n", cmdname, priv[k].set_args & IW_PRIV_SIZE_MASK); return(-1); } @@ -403,7 +451,7 @@ set_private_cmd(int skfd, /* Socket */ } else { - /* Thirst case : args won't fit in wrq, or variable number of args */ + /* 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; } @@ -424,7 +472,7 @@ set_private_cmd(int skfd, /* Socket */ int j; int n = 0; /* number of args */ - printf("%-8.8s %s:", ifname, cmdname); + printf("%-8.16s %s:", ifname, cmdname); /* Check where is the returned data */ if((priv[k].get_args & IW_PRIV_SIZE_FIXED) && @@ -454,7 +502,7 @@ set_private_cmd(int skfd, /* Socket */ case IW_PRIV_TYPE_CHAR: /* Display args */ - buffer[wrq.u.data.length - 1] = '\0'; + buffer[n] = '\0'; printf("%s\n", buffer); break; @@ -488,7 +536,7 @@ set_private_cmd(int skfd, /* Socket */ if(j) printf(" %.*s", (int) strlen(cmdname), " "); - printf("%s\n", iw_pr_ether(scratch, hwa->sa_data)); + printf("%s\n", iw_saether_ntop(hwa, scratch)); } } break; @@ -512,31 +560,38 @@ set_private(int skfd, /* Socket */ int count, /* Args count */ char * ifname) /* Dev name */ { - iwprivargs priv[IW_MAX_PRIV_DEF]; + iwprivargs * priv; int number; /* Max of private ioctl */ + int ret; /* Read the private ioctls */ - number = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF); + number = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(number <= 0) { - /* Could skip this message ? */ - fprintf(stderr, "%-8.8s no private ioctls.\n\n", + /* Should I skip this message ? */ + fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); + if(priv) + free(priv); return(-1); } - return(set_private_cmd(skfd, args + 1, count - 1, ifname, args[0], - priv, number)); + /* Do it */ + ret = set_private_cmd(skfd, args + 1, count - 1, ifname, args[0], + priv, number); + + free(priv); + return(ret); } /************************ CATALOG FUNCTIONS ************************/ /*------------------------------------------------------------------*/ /* - * Print on the screen in a neat fashion all the info we have collected - * on a device. + * Print on the screen in a neat fashion the list of private ioctls + * for the device. */ static int print_priv_info(int skfd, @@ -545,25 +600,25 @@ print_priv_info(int skfd, int count) { int k; - iwprivargs priv[IW_MAX_PRIV_DEF]; + iwprivargs * priv; int n; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Read the private ioctls */ - n = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF); + n = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(n <= 0) { - /* Could skip this message ? */ - fprintf(stderr, "%-8.8s no private ioctls.\n\n", + /* Should I skip this message ? */ + fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); } else { - printf("%-8.8s Available private ioctl :\n", ifname); + printf("%-8.16s Available private ioctls :\n", ifname); /* Print them all */ for(k = 0; k < n; k++) if(priv[k].name[0] != '\0') @@ -575,13 +630,17 @@ print_priv_info(int skfd, argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]); printf("\n"); } + + /* Cleanup */ + if(priv) + free(priv); return(0); } /*------------------------------------------------------------------*/ /* - * Print on the screen in a neat fashion all the info we have collected - * on a device. + * Print on the screen in a neat fashion the list of private GET ioctl + * data for the device and data returned by those. */ static int print_priv_all(int skfd, @@ -590,28 +649,28 @@ print_priv_all(int skfd, int count) { int k; - iwprivargs priv[IW_MAX_PRIV_DEF]; + iwprivargs * priv; int n; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Read the private ioctls */ - n = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF); + n = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(n <= 0) { - /* Could skip this message ? */ - fprintf(stderr, "%-8.8s no private ioctls.\n\n", + /* Should I skip this message ? */ + fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); } else { - printf("%-8.8s Available read-only private ioctl :\n", ifname); + printf("%-8.16s Available read-only private ioctl :\n", ifname); /* Print them all */ for(k = 0; k < n; k++) - /* We call all ioctl that don't have a null name, don't require + /* We call all ioctls that don't have a null name, don't require * args and return some (avoid triggering "reset" commands) */ if((priv[k].name[0] != '\0') && (priv[k].set_args == 0) && (priv[k].get_args != 0)) @@ -619,13 +678,10 @@ print_priv_all(int skfd, priv, n); printf("\n"); } -#if 0 - // Debug - printf("struct ifreq = %d ; struct iwreq = %d ; IFNAMSIZ = %d\n", - sizeof(struct ifreq), sizeof(struct iwreq), IFNAMSIZ); - printf("struct iw_freq = %d ; struct sockaddr = %d\n", - sizeof(struct iw_freq), sizeof(struct sockaddr)); -#endif + + /* Cleanup */ + if(priv) + free(priv); return(0); } @@ -634,10 +690,13 @@ print_priv_all(int skfd, * Convenient access to some private ioctls of some devices */ +#if 0 /*------------------------------------------------------------------*/ /* * Set roaming mode on and off * Found in wavelan_cs driver + * Note : this is obsolete, most 802.11 devices should use the + * SIOCSIWAP request. */ static int set_roaming(int skfd, /* Socket */ @@ -649,24 +708,41 @@ set_roaming(int skfd, /* Socket */ struct iwreq wrq; int i = 0; /* Start with first arg */ int k; - iwprivargs priv[IW_MAX_PRIV_DEF]; + iwprivargs * priv; int number; + int roamcmd; char RoamState; /* buffer to hold new roam state */ char ChangeRoamState=0; /* whether or not we are going to change roam states */ /* Read the private ioctls */ - number = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF); + number = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(number <= 0) { - /* Could skip this message ? */ - fprintf(stderr, "%-8.8s no private ioctls.\n\n", + /* Should I skip this message ? */ + fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); + if(priv) + free(priv); return(-1); } + /* Get the ioctl number */ + k = -1; + while((++k < number) && strcmp(priv[k].name, "setroam")); + if(k == number) + { + fprintf(stderr, "This device doesn't support roaming\n"); + free(priv); + return(-1); + } + roamcmd = priv[k].cmd; + + /* Cleanup */ + free(priv); + if(count != 1) { iw_usage(); @@ -675,7 +751,7 @@ set_roaming(int skfd, /* Socket */ if(!strcasecmp(args[i], "on")) { - printf("%-8.8s enable roaming\n", ifname); + printf("%-8.16s enable roaming\n", ifname); if(!number) { fprintf(stderr, "This device doesn't support roaming\n"); @@ -688,7 +764,7 @@ set_roaming(int skfd, /* Socket */ if(!strcasecmp(args[i], "off")) { i++; - printf("%-8.8s disable roaming\n", ifname); + printf("%-8.16s disable roaming\n", ifname); if(!number) { fprintf(stderr, "This device doesn't support roaming\n"); @@ -705,20 +781,13 @@ set_roaming(int skfd, /* Socket */ if(ChangeRoamState) { - k = -1; - while((++k < number) && strcmp(priv[k].name, "setroam")); - if(k == number) - { - fprintf(stderr, "This device doesn't support roaming\n"); - return(-1); - } strncpy(wrq.ifr_name, ifname, IFNAMSIZ); buffer[0]=RoamState; memcpy(wrq.u.name, &buffer, IFNAMSIZ); - if(ioctl(skfd, priv[k].cmd, &wrq) < 0) + if(ioctl(skfd, roamcmd, &wrq) < 0) { fprintf(stderr, "Roaming support is broken.\n"); return(-1); @@ -732,6 +801,7 @@ set_roaming(int skfd, /* Socket */ /* * Get and set the port type * Found in wavelan2_cs and wvlan_cs drivers + * TODO : Add support for HostAP ? */ static int port_type(int skfd, /* Socket */ @@ -742,19 +812,21 @@ port_type(int skfd, /* Socket */ struct iwreq wrq; int i = 0; /* Start with first arg */ int k; - iwprivargs priv[IW_MAX_PRIV_DEF]; + iwprivargs * priv; int number; char ptype = 0; char * modes[] = { "invalid", "managed (BSS)", "reserved", "ad-hoc" }; /* Read the private ioctls */ - number = iw_get_priv_info(skfd, ifname, priv, IW_MAX_PRIV_DEF); + number = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(number <= 0) { - /* Could skip this message ? */ - fprintf(stderr, "%-8.8s no private ioctls.\n\n", ifname); + /* Should I skip this message ? */ + fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); + if(priv) + free(priv); return(-1); } @@ -768,7 +840,7 @@ port_type(int skfd, /* Socket */ if(k == number) { fprintf(stderr, "This device doesn't support getting port type\n"); - return(-1); + goto err; } strncpy(wrq.ifr_name, ifname, IFNAMSIZ); @@ -776,21 +848,22 @@ port_type(int skfd, /* Socket */ if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Port type support is broken.\n"); - exit(0); + goto err; } ptype = *wrq.u.name; /* Display it */ - printf("%-8.8s Current port mode is %s .\n\n", + printf("%-8.16s Current port mode is %s .\n\n", ifname, modes[(int) ptype], ptype); + free(priv); return(0); } if(count != 1) { iw_usage(); - return(-1); + goto err; } /* Read it */ @@ -802,10 +875,10 @@ port_type(int skfd, /* Socket */ ptype = k; else /* ...or as an integer */ - if(sscanf(args[i], "%d", (int *) &ptype) != 1) + if(sscanf(args[i], "%i", (int *) &ptype) != 1) { iw_usage(); - return(-1); + goto err; } k = -1; @@ -814,7 +887,7 @@ port_type(int skfd, /* Socket */ if(k == number) { fprintf(stderr, "This device doesn't support setting port type\n"); - return(-1); + goto err; } strncpy(wrq.ifr_name, ifname, IFNAMSIZ); @@ -823,11 +896,17 @@ port_type(int skfd, /* Socket */ if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Invalid port type (or setting not allowed)\n"); - return(-1); + goto err; } + free(priv); return(0); + + err: + free(priv); + return(-1); } +#endif /******************************* MAIN ********************************/ @@ -849,7 +928,7 @@ main(int argc, return(-1); } - /* No argument : show the list of all device + info */ + /* No argument : show the list of all devices + ioctl list */ if(argc == 1) iw_enum_devices(skfd, &print_priv_info, NULL, 0); else @@ -877,6 +956,7 @@ main(int argc, (!strcmp(argv[2], "--all"))) print_priv_all(skfd, argv[1], NULL, 0); else +#if 0 /* Roaming */ if(!strncmp(argv[2], "roam", 4)) goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]); @@ -885,12 +965,13 @@ main(int argc, if(!strncmp(argv[2], "port", 4)) goterr = port_type(skfd, argv + 3, argc - 3, argv[1]); else +#endif /*-------------*/ /* Otherwise, it's a private ioctl */ goterr = set_private(skfd, argv + 2, argc - 2, argv[1]); /* Close the socket. */ - close(skfd); + iw_sockets_close(skfd); return(goterr); }