您的位置:首页 > 其它

wireless-tools源码分析-iwpriv

2017-02-24 12:19 337 查看
iwpriv是Wireless Extensions 操作的特定驱动。通过iwpriv,可以得到AP的一些参数设置,也可以设置自己的WIFI参数。

[root@root- /]#iwpriv
wlan0     Available private ioctls :
extscan          (8BFA) : set   0 int   & get   2 char
hostcmd          (8BE4) : set 2047 byte  & get 2047 byte
arpfilter        (8BE6) : set 2047 byte  & get 2047 byte
regrdwr          (8BE3) : set 256 char  & get 256 char
sdcmd52rw        (8BFE) : set   7 byte  & get   7 byte
sdcmd53rw        (8BFF) : set   0 char  & get   0 char
setgetconf       (8BEA) : set 2000 byte  & get 2000 byte
getcis           (8BE1) : set   0       & get 512 byte
scantype         (8BEB) : set   8 char  & get   8 char
deauth           (0001) : set   1 addr  & get   0
getNF            (0001) : set   1 int   & get   1 int
getRSSI          (0002) : set   1 int   & get   1 int
bgscan           (0004) : set   1 int   & get   1 int
enable11d        (0005) : set   1 int   & get   1 int
adhocgrate       (0006) : set   1 int   & get   1 int
sdioclock        (0007) : set   1 int   & get   1 int
wmm              (0008) : set   1 int   & get   1 int
uapsdnullgen     (000A) : set   1 int   & get   1 int
setcoalescing    (000B) : set   1 int   & get   1 int
adhocgprot       (000C) : set   1 int   & get   1 int
disable_chsw     (000F) : set   1 int   & get   1 int
setpowercons     (0001) : set   1 int   & get   1 int
wmm_qosinfo      (0002) : set   1 int   & get   1 int
lolisteninter    (0003) : set   1 int   & get   1 int
psnullinterval   (0005) : set   1 int   & get   1 int
bcnmisto         (0006) : set   1 int   & get   1 int
ldocfg           (0008) : set   1 int   & get   1 int
rtsctsctrl       (000F) : set   1 int   & get   1 int
moduletype       (000B) : set   1 int   & get   1 int
autodeepsleep    (000C) : set   1 int   & get   1 int
enhanceps        (000D) : set   1 int   & get   1 int
wakeupmt         (000E) : set   1 int   & get   1 int
setrxant         (0001) : set   1 int   & get   0
settxant         (0002) : set   1 int   & get   0
authalgs         (0004) : set   1 int   & get   0
encryptionmode   (0005) : set   1 int   & get   0
setregioncode    (0006) : set   1 int   & get   0
setlisteninter   (0007) : set   1 int   & get   0
setmultipledtim  (0008) : set   1 int   & get   0
setbcnavg        (0009) : set   1 int   & get   0
setdataavg       (000A) : set   1 int   & get   0
associate        (000B) : set   1 int   & get   0
getregioncode    (0001) : set   0       & get   1 int
getlisteninter   (0002) : set   0       & get   1 int
getmultipledtim  (0003) : set   0       & get   1 int
gettxrate        (0004) : set   0       & get   1 int
getbcnavg        (0005) : set   0       & get   1 int
getdataavg       (0006) : set   0       & get   1 int
getauthtype      (0007) : set   0       & get   1 int
getrsnmode       (0008) : set   0       & get   1 int
act_paircipher   (0009) : set   0       & get   1 int
act_groupcipher  (000A) : set   0       & get   1 int
getdtim          (000B) : set   0       & get   1 int
getrxant         (0001) : set   0       & get  12 char
gettxant         (0002) : set   0       & get  12 char
gettsf           (0003) : set   0       & get  12 char
wpssession       (0004) : set   0       & get  12 char
deepsleep        (8BFB) : set   1 char  & get   6 char
adhocstop        (0004) : set   0       & get   0
radioon          (0001) : set   0       & get   0
radiooff         (0002) : set   0       & get   0
rmaeskey         (0003) : set   0       & get   0
crypto_test      (0006) : set   0       & get   0
reasso-on        (0007) : set   0       & get   0
reasso-off       (0008) : set   0       & get   0
wlanidle-on      (0009) : set   0       & get   0
wlanidle-off     (000A) : set   0       & get   0
softreset        (000C) : set   0       & get   0
sleepparams      (0002) : set  64 char  & get  64 char
requesttpc       (0004) : set  64 char  & get  64 char
powercap         (0005) : set  64 char  & get  64 char
measreq          (000C) : set  64 char  & get  64 char
bca-ts           (0003) : set  64 char  & get  64 char
scanmode         (0006) : set  64 char  & get  64 char
getadhocstatus   (0009) : set  64 char  & get  64 char
setgenie         (000A) : set  64 char  & get  64 char
getgenie         (000B) : set  64 char  & get  64 char
qstatus          (000D) : set  64 char  & get  64 char
ts_status        (000E) : set  64 char  & get  64 char
setaeskey        (0001) : set  32 char  & get   0
getaeskey        (0001) : set   1 int   & get 128 char
version          (0002) : set   1 int   & get 128 char
verext           (0003) : set   1 int   & get 128 char
setwpaie         (8BE0) : set  24 char  & get   0
setband          (0001) : set  10 char  & get   0
setadhocch       (0002) : set  10 char  & get   0
chanswann        (0003) : set  10 char  & get   0
getband          (0001) : set   0       & get  10 char
getadhocch       (0002) : set   0       & get  10 char
getlog           (8BE9) : set   0       & get 512 char
tpccfg           (0001) : set  16 int   & get  16 int
scanprobes       (0006) : set  16 int   & get  16 int
ledgpio          (0005) : set  16 int   & get  16 int
sleeppd          (0007) : set  16 int   & get  16 int
rateadapt        (0008) : set  16 int   & get  16 int
getSNR           (0009) : set  16 int   & get  16 int
getrate          (000A) : set  16 int   & get  16 int
getrxinfo        (000B) : set  16 int   & get  16 int
atimwindow       (000C) : set  16 int   & get  16 int
bcninterval      (000D) : set  16 int   & get  16 int
sdiopullctrl     (000E) : set  16 int   & get  16 int
scantime         (000F) : set  16 int   & get  16 int
sysclock         (0010) : set  16 int   & get  16 int
txcontrol        (0012) : set  16 int   & get  16 int
hscfg            (0014) : set  16 int   & get  16 int
hssetpara        (0015) : set  16 int   & get  16 int
inactoext        (0016) : set  16 int   & get  16 int
dbgscfg          (0017) : set  16 int   & get  16 int
drvdbg           (0018) : set  16 int   & get  16 int
drvdelaymax      (001A) : set  16 int   & get  16 int
intfctrl         (001B) : set  16 int   & get  16 int
setquietie       (001C) : set  16 int   & get  16 int
ctspowerctrl     (001E) : set  16 int   & get  16 int
psmode           (001F) : set  16 int   & get  16 int
setuserscan      (0001) : set 2000 byte  & get 2000 byte
getscantable     (0002) : set 2000 byte  & get 2000 byte
setmrvltlv       (0003) : set 2000 byte  & get 2000 byte
getassocrsp      (0004) : set 2000 byte  & get 2000 byte
addts            (0005) : set 2000 byte  & get 2000 byte
delts            (0006) : set 2000 byte  & get 2000 byte
qconfig          (0007) : set 2000 byte  & get 2000 byte
qstats           (0008) : set 2000 byte  & get 2000 byte
txpktstats       (000C) : set 2000 byte  & get 2000 byte
getcfptable      (0009) : set 2000 byte  & get 2000 byte
mefcfg           (000A) : set 2000 byte  & get 2000 byte
getmem           (000B) : set 2000 byte  & get 2000 byte


iwpriv源码中的main函数,内容如下:

/*------------------------------------------------------------------*/
/*
* The main !
*/
int
main(int    argc,
char **    argv)
{
int skfd;     /* generic raw socket desc. */
int goterr = 0;

/* Create a channel to the NET kernel. */
if((skfd = iw_sockets_open()) < 0)
{
perror("socket");
return(-1);
}

/* No argument : show the list of all devices + ioctl list */
if(argc == 1)
iw_enum_devices(skfd, &print_priv_info, NULL, 0);
else
/* Special cases take one... */
/* All */
if((!strncmp(argv[1], "-a", 2)) || (!strcmp(argv[1], "--all")))
iw_enum_devices(skfd, &print_priv_all, NULL, 0);
else
/* Help */
if((!strncmp(argv[1], "-h", 2)) || (!strcmp(argv[1], "--help")))
iw_usage();
else
/* Version */
if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
goterr = iw_print_version_info("iwpriv");
else
/* The device name must be the first argument */
/* Name only : show for that device only */
if(argc == 2)
print_priv_info(skfd, argv[1], NULL, 0);
else
/* Special cases take two... */
/* All */
if((!strncmp(argv[2], "-a", 2)) ||
(!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]);
else
/* Port type */
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. */
iw_sockets_close(skfd);

return(goterr);
}


iw_enum_devices
函数类似,调用了
print_priv_info
函数做参数。

iw_print_version_info
函数,打印出了wireless的版本信息,wireless extension版本信息和接口驱动的版本信息。

print_priv_info
函数,打印出通过ioctl获取的无线驱动中的设备具有的私有数据和信息。

print_priv_all
函数,打印出通过GET ioctl获取的无线驱动中的设备具有的私有数据和信息。

set_private
函数,通过ioctl来设定无线驱动中关于设备的私有配置和数据。

print_priv_info
函数,内容如下:

/*------------------------------------------------------------------*/
/*
* Print on the screen in a neat fashion the list of private ioctls
* for the device.
*/
static int
print_priv_info(int     skfd,
char *      ifname,
char *      args[],
int     count)
{
int       k;
iwprivargs *  priv;
int       n;

/* Avoid "Unused parameter" warning */
args = args; count = count;

/* Read the private ioctls */
n = iw_get_priv_info(skfd, ifname, &priv);

/* Is there any ? */
if(n <= 0)
{
/* Should I skip this message ? */
fprintf(stderr, "%-8.16s  no private ioctls.\n\n",
ifname);
}
else
{
printf("%-8.16s  Available private ioctls :\n", ifname);
/* Print them all */
for(k = 0; k < n; k++)
if(priv[k].name[0] != '\0')
printf("          %-16.16s (%.4X) : set %3d %s & get %3d %s\n",
priv[k].name, priv[k].cmd,
priv[k].set_args & IW_PRIV_SIZE_MASK,
argtype[(priv[k].set_args & IW_PRIV_TYPE_MASK) >> 12],
priv[k].get_args & IW_PRIV_SIZE_MASK,
argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]);
printf("\n");
}

/* Cleanup */
if(priv)
free(priv);
return(0);
}


使用了
iw_get_priv_info
函数获取数据然后打印输出。

iw_get_priv_info
函数内容如下:

/*------------------------------------------------------------------*/
/*
* Get information about what private ioctls are supported by the driver
*
* Note : there is one danger using this function. If it return 0, you
* still need to free() the buffer. Beware.
*/
int
iw_get_priv_info(int        skfd,
const char *   ifname,
iwprivargs **  ppriv)
{
struct iwreq      wrq;
iwprivargs *      priv = NULL;    /* Not allocated yet */
int           maxpriv = 16;   /* Minimum for compatibility WE<13 */
iwprivargs *      newpriv;

/* Some driver may return a very large number of ioctls. Some
* others a very small number. We now use a dynamic allocation
* of the array to satisfy everybody. Of course, as we don't know
* in advance the size of the array, we try various increasing
* sizes. Jean II */
do
{
/* (Re)allocate the buffer */
newpriv = realloc(priv, maxpriv * sizeof(priv[0]));
if(newpriv == NULL)
{
fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
break;
}
priv = newpriv;

/* Ask the driver if it's large enough */
wrq.u.data.pointer = (caddr_t) priv;
wrq.u.data.length = maxpriv;
wrq.u.data.flags = 0;
if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) >= 0)
{
/* Success. Pass the buffer by pointer */
*ppriv = priv;
/* Return the number of ioctls */
return(wrq.u.data.length);
}

/* Only E2BIG means the buffer was too small, abort on other errors */
if(errno != E2BIG)
{
/* Most likely "not supported". Don't barf. */
break;
}

/* Failed. We probably need a bigger buffer. Check if the kernel
* gave us any hints. */
if(wrq.u.data.length > maxpriv)
maxpriv = wrq.u.data.length;
else
maxpriv *= 2;
}
while(maxpriv < 1000);

/* Cleanup */
if(priv)
free(priv);
*ppriv = NULL;

return(-1);
}


私有数据使用
iwprivargs
结构体,通过
iw_get_ext
函数和参数
SIOCGIWPRIV
和wrq,进行ioctl操作,获取私有数据。

iwprivargs
是定义的
iw_priv_args
结构体,定义如下:

/*
* Private ioctl interface information
*/

struct  iw_priv_args
{
__u32       cmd;        /* Number of the ioctl to issue */
__u16       set_args;   /* Type and number of args */
__u16       get_args;   /* Type and number of args */
char        name[IFNAMSIZ]; /* Name of the extension */
};


iw_print_version_info
函数内容如下;

/*------------------------------------------------------------------*/
/*
* Print the WE versions of the tools.
*/
int
iw_print_version_info(const char *  toolname)
{
int       skfd;           /* generic raw socket desc. */
int       we_kernel_version;

/* Create a channel to the NET kernel. */
if((skfd = iw_sockets_open()) < 0)
{
perror("socket");
return -1;
}

/* Information about the tools themselves */
if(toolname != NULL)
printf("%-8.16s  Wireless-Tools version %d\n", toolname, WT_VERSION);
printf("          Compatible with Wireless Extension v11 to v%d.\n\n",
WE_MAX_VERSION);

/* Get version from kernel */
we_kernel_version = iw_get_kernel_we_version();
/* Only version >= 16 can be verified, other are guessed */
if(we_kernel_version > 15)
printf("Kernel    Currently compiled with Wireless Extension v%d.\n\n",
we_kernel_version);

/* Version for each device */
iw_enum_devices(skfd, &print_iface_version_info, NULL, 0);

iw_sockets_close(skfd);

return 0;
}


可以看到使用了
print_iface_version_info
函数来获取无线驱动接口的版本信息,内容如下:

/*------------------------------------------------------------------*/
/*
* Print the WE versions of the interface.
*/
static int
print_iface_version_info(int    skfd,
char * ifname,
char * args[],     /* Command line args */
int    count)      /* Args count */
{
struct iwreq      wrq;
char          buffer[sizeof(iwrange) * 2];    /* Large enough */
struct iw_range * range;

/* Avoid "Unused parameter" warning */
args = args; count = count;

/* If no wireless name : no wireless extensions.
* This enable us to treat the SIOCGIWRANGE failure below properly. */
if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
return(-1);

/* Cleanup */
memset(buffer, 0, sizeof(buffer));

wrq.u.data.pointer = (caddr_t) buffer;
wrq.u.data.length = sizeof(buffer);
wrq.u.data.flags = 0;
if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
{
/* Interface support WE (see above), but not IWRANGE */
fprintf(stderr, "%-8.16s  Driver has no Wireless Extension version information.\n\n", ifname);
return(0);
}

/* Copy stuff at the right place, ignore extra */
range = (struct iw_range *) buffer;

/* For new versions, we can check the version directly, for old versions
* we use magic. 300 bytes is a also magic number, don't touch... */
if(wrq.u.data.length >= 300)
{
/* Version is always at the same offset, so it's ok */
printf("%-8.16s  Recommend Wireless Extension v%d or later,\n",
ifname, range->we_version_source);
printf("          Currently compiled with Wireless Extension v%d.\n\n",
range->we_version_compiled);
}
else
{
fprintf(stderr, "%-8.16s  Wireless Extension version too old.\n\n",
ifname);
}

return(0);
}


print_priv_all
函数的内容如下:

/*------------------------------------------------------------------*/
/*
* 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,
char *       ifname,
char *       args[],
int      count)
{
int       k;
iwprivargs *  priv;
int       n;

/* Avoid "Unused parameter" warning */
args = args; count = count;

/* Read the private ioctls */
n = iw_get_priv_info(skfd, ifname, &priv);

/* Is there any ? */
if(n <= 0)
{
/* Should I skip this message ? */
fprintf(stderr, "%-8.16s  no private ioctls.\n\n",
ifname);
}
else
{
printf("%-8.16s  Available read-only private ioctl :\n", ifname);
/* Print them all */
for(k = 0; k < n; k++)
/* 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))
set_private_cmd(skfd, NULL, 0, ifname, priv[k].name,
priv, n);
printf("\n");
}

/* Cleanup */
if(priv)
free(priv);
return(0);
}


print_priv_all
函数与
print_priv_info
的不同之处是调用了
set_private_cmd
函数对接口执行了一个私有的获取命令,内容如下:

/*------------------------------------------------------------------*/
/*
* 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[4096];   /* 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;
}
}

/* 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
= '\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);
}


iwpriv的设置通过
set_private
函数来实现,该函数的内容如下:

/*------------------------------------------------------------------*/
/*
* Execute a private command on the interface
*/
static inline int
set_private(int     skfd,       /* Socket */
char *  args[],     /* Command line args */
int     count,      /* Args count */
char *  ifname)     /* Dev name */
{
iwprivargs *  priv;
int       number;     /* Max of private ioctl */
int       ret;

/* Read the private ioctls */
number = iw_get_priv_info(skfd, ifname, &priv);

/* Is there any ? */
if(number <= 0)
{
/* Should I skip this message ? */
fprintf(stderr, "%-8.16s  no private ioctls.\n\n",
ifname);
if(priv)
free(priv);
return(-1);
}

/* Do it */
ret = set_private_cmd(skfd, args + 1, count - 1, ifname, args[0],
priv, number);

free(priv);
return(ret);
}


set_private
函数也是调用了
set_private_cmd
函数来执行ioctl的修改了无线设备驱动的私有配置数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息