⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iwpriv.c

📁 iwconfig iwlist iwpriv
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	Wireless Tools * *		Jean II - HPLB 97->99 - HPL 99->00 * * 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 <jt@hpl.hp.com> */#include "iwlib.h"		/* Header *//************************** DOCUMENTATION **************************//* * IOCTL RANGES : * ------------ *	The initial implementation of iwpriv was using the SIOCDEVPRIVATE * ioctl range (up to 16 ioctls - driver specific). However, this was * causing some compatibility problems with other usages of those * ioctls, and those ioctls are supposed to be removed. *	Therefore, I created a new ioctl range, at SIOCIWFIRSTPRIV. Those * ioctls are specific to Wireless Extensions, so you don't have to * 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 collisions		yes		no *		o SET convention	optional	enforced *		o number		16		32 * * NEW DRIVER API : * -------------- *	Wireless Extension 13 introduce 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). *	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. * * 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 * 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). *	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. * * 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). *	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 ;-). * *	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. * *	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 : * --------------------------------------------	// --- 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, "" },	// --- sub-ioctls definitions ---	{ 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_param1" },	{ 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" }, * -------------------------------------------- *	And iwpriv should do the rest for you ;-) * *	Note that version 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. * *	Another problem is that new API before Wireless Extension 15 * will get it wrong 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. * * NEW DATA TYPES (ADDR/FLOAT) : * --------------------------- *	Wireless Tools 25 introduce two new data types, addr and float, * corresponding to struct sockaddr and struct iwfreq. *	Those types are properly handled with Wireless Extensions 15. * 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. *	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 * big to fit in struct iwreq. * *	For those reasons, I would recommend to use the ioctl handler * before v15 when manipulating those data. * * TOKEN INDEX : * ----------- *	Token index is very similar to sub-ioctl. It allow 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 * 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 ---	{ 0x8BE1, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 2, 0, "again" }, * -------------------------------------------- *	The token index feature is pretty transparent, the token index * will just be in the flags member of (struct iw_point). Default value * (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 * raw access to the sub-ioctl handlers (if it uses struct iw_point) : * --------------------------------------------	// --- sub-ioctls handler ---	{ 0x8BE0, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "" },	// --- sub-ioctls definitions ---	{ 0, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "setaddr" },	{ 1, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "deladdr" },	// --- raw access with token index (+ iwreq workaround) ---	{ 0x8BE0, IW_PRIV_TYPE_ADDR | 1, 0, "rawaddr" }, * -------------------------------------------- * * Jean II *//**************************** CONSTANTS ****************************/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 **************************//*------------------------------------------------------------------*//* * Print usage string */static voidiw_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 **************************//*------------------------------------------------------------------*//* * Execute a private command on the interface */static intset_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 know so that sub-ioctl takes precendence, 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 alignement issues) */      offset = sizeof(__u32);      /* Use real ioctl definition from now on */      k = j;      printf("<mapping sub-ioctl %s to cmd 0x%X-%d>\n", cmdname,	     priv[k].cmd, subcmd);    }  /* 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(index(args[i], 'G')) freq *= GIGA;	    if(index(args[i], 'M')) freq *= MEGA;	    if(index(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 yet 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",		 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	{	  /* Thirst 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.8s  %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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -