myiwpriv_mywpacli

My iwpriv

bug: wifi_iwpriv() socket close need close

 

#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <linux/types.h> /* for "caddr_t" et al		*/
#include <sys/socket.h> /* For AF_INET & struct sockaddr */
#include <linux/wireless.h>
//#include <net/if.h> /* for IFNAMSIZ and co... */

/*------------------------------------------------------------------*/
/*
 * 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 wifi_get_priv_info(int skfd,
		 const char * ifname,
		 struct iw_priv_args ** ppriv)
{
	struct iwreq wrq;
	struct iw_priv_args *priv = NULL;	/* Not allocated yet */
	struct iw_priv_args *newpriv = NULL;
	int maxpriv = 16;	/* Minimum for compatibility WE<13 */

	/* 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 = (struct iw_priv_args*)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;
		strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
		if(ioctl(skfd, SIOCGIWPRIV, &wrq) >= 0) {
			int n = wrq.u.data.length;
			int k = 0;
			/* Success. Pass the buffer by pointer */
			*ppriv = priv;
			
			/* Is there any ? */
			if(n <= 0) {
				/* Should I skip this message ? */
				fprintf(stderr, "%-8.16s  no private ioctls.\n\n", ifname);
			} else {
				#if 0
				static const char *argtype[] = {"     ", "byte ", "char ", "", "int  ", "float", "addr "};

				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");
				#endif
			}

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

int wifi_iwpriv(char*ifname, char*cmd, char*arg)
{
	static const int families[] = {AF_INET, AF_IPX, AF_AX25, AF_APPLETALK};
	unsigned int i = 0;
	int skfd = -1;

	/*
	* Now pick any (exisiting) useful socket family for generic queries
	* Note : don't open all the socket, only returns when one matches,
	* all protocols might not be valid.
	* Workaround by Jim Kaba <jkaba@sarnoff.com>
	* Note : in 99% of the case, we will just open the inet_sock.
	* The remaining 1% case are not fully correct...
	*/

	/* Try all families we support */
	for(i = 0; i < sizeof(families)/sizeof(int); ++i) {
		/* Try to open the socket, if success returns it */
		skfd = socket(families[i], SOCK_DGRAM, 0);
		if(skfd >= 0)
			break;
	}

	struct iw_priv_args *priv = NULL;
	int number = 0;	      /* Max of private ioctl */
	int ret = -1;

	/* Read the private ioctls */
	number = wifi_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);
	}

	struct iwreq wrq;
	unsigned char buffer[1024];
	int k = -1;	      /* Index in private description table */
	int temp;
	int subcmd = 0;     /* sub-ioctl index */
	int offset = 0;     /* Space for sub-ioctl index */
	int priv_size = 0;

	/* Search the correct ioctl */
	while((++k < number) && strcmp(priv[k].name, cmd));
	if(k == number) {
		fprintf(stderr, "Invalid command : %s\n", cmd);
		return(-1);
	}

	/* Watch out for sub-ioctls ! */
	if(priv[k].cmd < SIOCDEVPRIVATE) {
		fprintf(stdout, "SIOCDEVPRIVATE\n");
		return (-1);
	}


	/* 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:
			break;

		case IW_PRIV_TYPE_INT:
			break;

		case IW_PRIV_TYPE_CHAR:
			/* Size of the string to fetch */
			wrq.u.data.length = strlen(arg) + 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, arg, wrq.u.data.length);
			buffer[sizeof(buffer) - 1] = '\0';
			break;

		case IW_PRIV_TYPE_FLOAT:
			break;

		case IW_PRIV_TYPE_ADDR:
			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",
				cmd, priv[k].set_args & IW_PRIV_SIZE_MASK);
			return(-1);
		}
	} else {
		wrq.u.data.length = 0L;
	}

	strncpy(wrq.ifr_name, ifname, IFNAMSIZ);

	/* Size (in bytes) of various events */
	static const int priv_type_size[] = {
		0,				/* IW_PRIV_TYPE_NONE */
		1,				/* IW_PRIV_TYPE_BYTE */
		1,				/* IW_PRIV_TYPE_CHAR */
		0,				/* Not defined */
		sizeof(__u32),			/* IW_PRIV_TYPE_INT */
		sizeof(struct iw_freq), 	/* IW_PRIV_TYPE_FLOAT */
		sizeof(struct sockaddr),	/* IW_PRIV_TYPE_ADDR */
		0,				/* Not defined */
	};

	priv_size = (priv[k].set_args & IW_PRIV_SIZE_MASK) * (priv_type_size[(priv[k].set_args & IW_PRIV_TYPE_MASK) >> 12]);


	/* 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) &&
		((priv_size + 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) &&
			(priv_size <= 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", cmd, priv[k].cmd, strerror(errno));
		return(-1);
	}

	priv_size = (priv[k].get_args & IW_PRIV_SIZE_MASK) * (priv_type_size[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]);

	/* 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 */

		/* Check where is the returned data */
		if((priv[k].get_args & IW_PRIV_SIZE_FIXED) &&
			(priv_size <= IFNAMSIZ))
		{
			memcpy(buffer, wrq.u.name, IFNAMSIZ);
			n = priv[k].get_args & IW_PRIV_SIZE_MASK;
		} else {
			n = wrq.u.data.length;
		}

		if (n == 0) {
			return 0;
		}

		printf("%-8.16s  %s:", ifname, cmd);

		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: {
			break;
		}

		case IW_PRIV_TYPE_ADDR: {
			break;
		}

		default:
			fprintf(stderr, "Not yet implemented...\n");
			return(-1);
		}
	}   /* if args to set */

	free(priv);
	return(ret);
}

 

 

 

my wpa_cli

 

 

int wifi_wpa_cli(char*ifname, char*cmd, char*buf_ret, int buf_len)
{
	struct sockaddr_un local;
	struct sockaddr_un dest;
	struct timeval tv;
	int skfd = -1, ret = -1;

	AEIDEBUGERROR("%s %s\n", ifname, cmd);
	if ((skfd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
		AEIDEBUGERROR("socket create failed %d:%s\n", errno, strerror(errno));
		return -1;
	}

	local.sun_family = AF_UNIX;
	gettimeofday(&tv, NULL);
	ret = snprintf(local.sun_path, sizeof(local.sun_path), "/tmp/wfd/wpa_ctrl_%ld_%ld", tv.tv_sec, tv.tv_usec);
	if (ret < 0 || (size_t) ret >= sizeof(local.sun_path)) {
		AEIDEBUGERROR("snprintf error\n");
		close(skfd);
		return -1;
	}

	if (bind(skfd, (struct sockaddr *) &local,sizeof(local)) < 0) {
		if (errno == EADDRINUSE) {
			
		}
		AEIDEBUGERROR("bind error %d:%s\n", errno, strerror(errno));
		ret = -1;
		goto exit;
	}

	dest.sun_family = AF_UNIX;
	snprintf(dest.sun_path, sizeof(dest.sun_path), "/var/run/wpa_supplicant/%s", ifname);
	if (connect(skfd, (struct sockaddr *) &dest, sizeof(dest)) < 0) {
		AEIDEBUGERROR("connect to %s error %d:%s\n", dest.sun_path, errno, strerror(errno));
		ret = -1;
		goto exit;
	}

	if (send(skfd, cmd, strlen(cmd), 0) < 0) {
		AEIDEBUGERROR("send %s error %d:%s\n", cmd, errno, strerror(errno));
		ret = -1;
		goto exit;
	}

	if (!buf_ret || buf_len <= 0) {
		ret = 0;
		goto exit;
	}

	fd_set rfds;
	tv.tv_sec = 3;
	tv.tv_usec = 0;
	FD_ZERO(&rfds);
	FD_SET(skfd, &rfds);
	ret = select(skfd + 1, &rfds, NULL, NULL, &tv);
	if (ret > 0 && FD_ISSET(skfd, &rfds)) {
		ret = recv(skfd, buf_ret, buf_len, 0);
		if (ret < 0) {
			AEIDEBUGERROR("recv error %d:%s\n", errno, strerror(errno));
			ret = -1;
			goto exit;
		}
		AEIDEBUGERROR("recv: \n%s\n", buf_ret);
		ret = 0;
	} else {
		AEIDEBUGERROR("select error %d:%s\n", errno, strerror(errno));
		ret = -1;
		goto exit;
	}

exit:
	unlink(local.sun_path);
	if(skfd > 0)
		close(skfd);
	return ret;
}

 

 

 

 

 

 

 

My

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值