示例#1
0
static bool test_socket_wrapper_dir(struct torture_context *tctx)
{
	backup_env();

	setenv("SOCKET_WRAPPER_DIR", "foo", 1);
	torture_assert_str_equal(tctx, socket_wrapper_dir(), "foo", "setting failed");
	setenv("SOCKET_WRAPPER_DIR", "./foo", 1);
	torture_assert_str_equal(tctx, socket_wrapper_dir(), "foo", "setting failed");
	unsetenv("SOCKET_WRAPPER_DIR");
	torture_assert_str_equal(tctx, socket_wrapper_dir(), NULL, "resetting failed");

	restore_env();

	return true;
}
示例#2
0
static PyObject *py_socket_wrapper_dir(PyObject *self)
{
	const char *dir;

	dir = socket_wrapper_dir();

	return PyString_FromString(dir);
}
示例#3
0
_PUBLIC_ int swrap_socket(int family, int type, int protocol)
{
	struct socket_info *si;
	int fd;

	if (!socket_wrapper_dir()) {
		return real_socket(family, type, protocol);
	}

	switch (family) {
	case AF_INET:
#ifdef HAVE_IPV6
	case AF_INET6:
#endif
		break;
	case AF_UNIX:
		return real_socket(family, type, protocol);
	default:
		errno = EAFNOSUPPORT;
		return -1;
	}

	switch (type) {
	case SOCK_STREAM:
		break;
	case SOCK_DGRAM:
		break;
	default:
		errno = EPROTONOSUPPORT;
		return -1;
	}

#if 0
	switch (protocol) {
	case 0:
		break;
	default:
		errno = EPROTONOSUPPORT;
		return -1;
	}
#endif

	fd = real_socket(AF_UNIX, type, 0);

	if (fd == -1) return -1;

	si = (struct socket_info *)calloc(1, sizeof(struct socket_info));

	si->family = family;
	si->type = type;
	si->protocol = protocol;
	si->fd = fd;

	SWRAP_DLIST_ADD(sockets, si);

	return si->fd;
}
示例#4
0
_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
{
	struct sockaddr_un un_addr;
	int ret;
	struct socket_info *si = find_socket_info(s);
	int bcast = 0;

	if (!si) {
		return real_sendto(s, buf, len, flags, to, tolen);
	}

	if (si->bound == 0) {
		ret = swrap_auto_bind(si);
		if (ret == -1) return -1;
	}

	ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
	if (ret == -1) return -1;

	if (bcast) {
		struct stat st;
		unsigned int iface;
		unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
		char type;

		type = SOCKET_TYPE_CHAR_UDP;

		for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
			snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 
				 socket_wrapper_dir(), type, iface, prt);
			if (stat(un_addr.sun_path, &st) != 0) continue;

			/* ignore the any errors in broadcast sends */
			real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
		}

		swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);

		return len;
	}

	ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));

	/* to give better errors */
	if (ret == -1 && errno == ENOENT) {
		errno = EHOSTUNREACH;
	}

	if (ret == -1) {
		swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
		swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
	} else {
		swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
	}

	return ret;
}
示例#5
0
static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
			       int *bcast)
{
	char type = '\0';
	unsigned int prt;
	unsigned int iface;
	struct stat st;
	int is_bcast = 0;

	if (bcast) *bcast = 0;

	switch (si->family) {
	case AF_INET: {
		const struct sockaddr_in *in = 
		    (const struct sockaddr_in *)inaddr;
		unsigned int addr = ntohl(in->sin_addr.s_addr);
		char u_type = '\0';
		char d_type = '\0';
		char b_type = '\0';
		char a_type = '\0';

		prt = ntohs(in->sin_port);

		switch (si->type) {
		case SOCK_STREAM:
			u_type = SOCKET_TYPE_CHAR_TCP;
			d_type = SOCKET_TYPE_CHAR_TCP;
			break;
		case SOCK_DGRAM:
			u_type = SOCKET_TYPE_CHAR_UDP;
			d_type = SOCKET_TYPE_CHAR_UDP;
			a_type = SOCKET_TYPE_CHAR_UDP;
			b_type = SOCKET_TYPE_CHAR_UDP;
			break;
		}

		if (addr == 0) {
			/* 0.0.0.0 */
		 	is_bcast = 0;
			type = d_type;
			iface = socket_wrapper_default_iface();
		} else if (a_type && addr == 0xFFFFFFFF) {
			/* 255.255.255.255 only udp */
			is_bcast = 2;
			type = a_type;
			iface = socket_wrapper_default_iface();
		} else if (b_type && addr == 0x7FFFFFFF) {
			/* 127.255.255.255 only udp */
			is_bcast = 1;
			type = b_type;
			iface = socket_wrapper_default_iface();
		} else if ((addr & 0xFFFFFF00) == 0x7F000000) {
			/* 127.0.0.X */
			is_bcast = 0;
			type = u_type;
			iface = (addr & 0x000000FF);
		} else {
			errno = EADDRNOTAVAIL;
			return -1;
		}
		break;
	}
#ifdef HAVE_IPV6
	case AF_INET6: {
		const struct sockaddr_in6 *in = 
		    (const struct sockaddr_in6 *)inaddr;
		struct in6_addr cmp;

		switch (si->type) {
		case SOCK_STREAM:
			type = SOCKET_TYPE_CHAR_TCP_V6;
			break;
		case SOCK_DGRAM:
			type = SOCKET_TYPE_CHAR_UDP_V6;
			break;
		}

		/* XXX no multicast/broadcast */

		prt = ntohs(in->sin6_port);

		cmp = in->sin6_addr;
		cmp.s6_addr[15] = 0;
		if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
			iface = socket_wrapper_default_iface();
		} else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
			iface = in->sin6_addr.s6_addr[15];
		} else {
			errno = EADDRNOTAVAIL;
			return -1;
		}

		break;
	}
#endif
	default:
		errno = EADDRNOTAVAIL;
		return -1;
	}


	if (bcast) *bcast = is_bcast;

	if (prt == 0) {
		/* handle auto-allocation of ephemeral ports */
		for (prt = 5001; prt < 10000; prt++) {
			snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
				 socket_wrapper_dir(), type, iface, prt);
			if (stat(un->sun_path, &st) == 0) continue;

			set_port(si->family, prt, si->myname);
			break;
		}
		if (prt == 10000) {
			errno = ENFILE;
			return -1;
		}
	}

	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
		 socket_wrapper_dir(), type, iface, prt);
	return 0;
}
示例#6
0
static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
				int *bcast)
{
	char type = '\0';
	unsigned int prt;
	unsigned int iface;
	int is_bcast = 0;

	if (bcast) *bcast = 0;

	switch (si->family) {
	case AF_INET: {
		const struct sockaddr_in *in = 
		    (const struct sockaddr_in *)inaddr;
		unsigned int addr = ntohl(in->sin_addr.s_addr);
		char u_type = '\0';
		char b_type = '\0';
		char a_type = '\0';

		switch (si->type) {
		case SOCK_STREAM:
			u_type = SOCKET_TYPE_CHAR_TCP;
			break;
		case SOCK_DGRAM:
			u_type = SOCKET_TYPE_CHAR_UDP;
			a_type = SOCKET_TYPE_CHAR_UDP;
			b_type = SOCKET_TYPE_CHAR_UDP;
			break;
		}

		prt = ntohs(in->sin_port);
		if (a_type && addr == 0xFFFFFFFF) {
			/* 255.255.255.255 only udp */
			is_bcast = 2;
			type = a_type;
			iface = socket_wrapper_default_iface();
		} else if (b_type && addr == 0x7FFFFFFF) {
			/* 127.255.255.255 only udp */
			is_bcast = 1;
			type = b_type;
			iface = socket_wrapper_default_iface();
		} else if ((addr & 0xFFFFFF00) == 0x7F000000) {
			/* 127.0.0.X */
			is_bcast = 0;
			type = u_type;
			iface = (addr & 0x000000FF);
		} else {
			errno = ENETUNREACH;
			return -1;
		}
		if (bcast) *bcast = is_bcast;
		break;
	}
#ifdef HAVE_IPV6
	case AF_INET6: {
		const struct sockaddr_in6 *in = 
		    (const struct sockaddr_in6 *)inaddr;
		struct in6_addr cmp;

		switch (si->type) {
		case SOCK_STREAM:
			type = SOCKET_TYPE_CHAR_TCP_V6;
			break;
		case SOCK_DGRAM:
			type = SOCKET_TYPE_CHAR_UDP_V6;
			break;
		}

		/* XXX no multicast/broadcast */

		prt = ntohs(in->sin6_port);

		cmp = in->sin6_addr;
		cmp.s6_addr[15] = 0;
		if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
			iface = in->sin6_addr.s6_addr[15];
		} else {
			errno = ENETUNREACH;
			return -1;
		}

		break;
	}
#endif
	default:
		errno = ENETUNREACH;
		return -1;
	}

	if (prt == 0) {
		errno = EINVAL;
		return -1;
	}

	if (is_bcast) {
		snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 
			 socket_wrapper_dir());
		/* the caller need to do more processing */
		return 0;
	}

	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
		 socket_wrapper_dir(), type, iface, prt);

	return 0;
}
示例#7
0
/* using sendto() or connect() on an unbound socket would give the
   recipient no way to reply, as unlike UDP and TCP, a unix domain
   socket can't auto-assign emphemeral port numbers, so we need to
   assign it here.
   Note: this might change the family from ipv6 to ipv4
*/
static int swrap_auto_bind(struct socket_info *si, int family)
{
	struct sockaddr_un un_addr;
	int i;
	char type;
	int ret;
	int port;
	struct stat st;

	if (autobind_start_init != 1) {
		autobind_start_init = 1;
		autobind_start = getpid();
		autobind_start %= 50000;
		autobind_start += 10000;
	}

	un_addr.sun_family = AF_UNIX;

	switch (family) {
	case AF_INET: {
		struct sockaddr_in in;

		switch (si->type) {
		case SOCK_STREAM:
			type = SOCKET_TYPE_CHAR_TCP;
			break;
		case SOCK_DGRAM:
		    	type = SOCKET_TYPE_CHAR_UDP;
			break;
		default:
		    errno = ESOCKTNOSUPPORT;
		    return -1;
		}

		memset(&in, 0, sizeof(in));
		in.sin_family = AF_INET;
		in.sin_addr.s_addr = htonl(127<<24 | 
					   socket_wrapper_default_iface());

		si->myname_len = sizeof(in);
		si->myname = sockaddr_dup(&in, si->myname_len);
		break;
	}
#ifdef HAVE_IPV6
	case AF_INET6: {
		struct sockaddr_in6 in6;

		if (si->family != family) {
			errno = ENETUNREACH;
			return -1;
		}

		switch (si->type) {
		case SOCK_STREAM:
			type = SOCKET_TYPE_CHAR_TCP_V6;
			break;
		case SOCK_DGRAM:
		    	type = SOCKET_TYPE_CHAR_UDP_V6;
			break;
		default:
			errno = ESOCKTNOSUPPORT;
			return -1;
		}

		memset(&in6, 0, sizeof(in6));
		in6.sin6_family = AF_INET6;
		in6.sin6_addr = *swrap_ipv6();
		in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
		si->myname_len = sizeof(in6);
		si->myname = sockaddr_dup(&in6, si->myname_len);
		break;
	}
#endif
	default:
		errno = ESOCKTNOSUPPORT;
		return -1;
	}

	if (autobind_start > 60000) {
		autobind_start = 10000;
	}

	for (i=0;i<1000;i++) {
		port = autobind_start + i;
		snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), 
			 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
			 type, socket_wrapper_default_iface(), port);
		if (stat(un_addr.sun_path, &st) == 0) continue;
		
		ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
		if (ret == -1) return ret;

		si->tmp_path = strdup(un_addr.sun_path);
		si->bound = 1;
		autobind_start = port + 1;
		break;
	}
	if (i == 1000) {
		errno = ENFILE;
		return -1;
	}

	si->family = family;
	set_port(si->family, port, si->myname);

	return 0;
}
示例#8
0
static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
			       int *bcast)
{
	char u_type = '\0';
	char d_type = '\0';
	char b_type = '\0';
	char a_type = '\0';
	char type = '\0';
	unsigned int addr= ntohl(in->sin_addr.s_addr);
	unsigned int prt = ntohs(in->sin_port);
	unsigned int iface;
	struct stat st;
	int is_bcast = 0;

	if (bcast) *bcast = 0;

	switch (si->type) {
	case SOCK_STREAM:
		u_type = SOCKET_TYPE_CHAR_TCP;
		d_type = SOCKET_TYPE_CHAR_TCP;
		break;
	case SOCK_DGRAM:
		u_type = SOCKET_TYPE_CHAR_UDP;
		d_type = SOCKET_TYPE_CHAR_UDP;
		a_type = SOCKET_TYPE_CHAR_UDP;
		b_type = SOCKET_TYPE_CHAR_UDP;
		break;
	}

	if (addr == 0) {
		/* 0.0.0.0 */
		is_bcast = 0;
		type = d_type;
		iface = socket_wrapper_default_iface();
	} else if (a_type && addr == 0xFFFFFFFF) {
		/* 255.255.255.255 only udp */
		is_bcast = 2;
		type = a_type;
		iface = socket_wrapper_default_iface();
	} else if (b_type && addr == 0x7FFFFFFF) {
		/* 127.255.255.255 only udp */
		is_bcast = 1;
		type = b_type;
		iface = socket_wrapper_default_iface();
	} else if ((addr & 0xFFFFFF00) == 0x7F000000) {
		/* 127.0.0.X */
		is_bcast = 0;
		type = u_type;
		iface = (addr & 0x000000FF);
	} else {
		errno = EADDRNOTAVAIL;
		return -1;
	}

	if (bcast) *bcast = is_bcast;

	if (prt == 0) {
		/* handle auto-allocation of ephemeral ports */
		for (prt = 5001; prt < 10000; prt++) {
			snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
				 socket_wrapper_dir(), type, iface, prt);
			if (stat(un->sun_path, &st) == 0) continue;

			((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
			return 0;
		}
		errno = ENFILE;
		return -1;
	}

	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
		 socket_wrapper_dir(), type, iface, prt);
	return 0;
}
示例#9
0
static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
				int *bcast)
{
	char u_type = '\0';
	char b_type = '\0';
	char a_type = '\0';
	char type = '\0';
	unsigned int addr= ntohl(in->sin_addr.s_addr);
	unsigned int prt = ntohs(in->sin_port);
	unsigned int iface;
	int is_bcast = 0;

	if (bcast) *bcast = 0;

	if (prt == 0) {
		errno = EINVAL;
		return -1;
	}

	switch (si->type) {
	case SOCK_STREAM:
		u_type = SOCKET_TYPE_CHAR_TCP;
		break;
	case SOCK_DGRAM:
		u_type = SOCKET_TYPE_CHAR_UDP;
		a_type = SOCKET_TYPE_CHAR_UDP;
		b_type = SOCKET_TYPE_CHAR_UDP;
		break;
	}

	if (a_type && addr == 0xFFFFFFFF) {
		/* 255.255.255.255 only udp */
		is_bcast = 2;
		type = a_type;
		iface = socket_wrapper_default_iface();
	} else if (b_type && addr == 0x7FFFFFFF) {
		/* 127.255.255.255 only udp */
		is_bcast = 1;
		type = b_type;
		iface = socket_wrapper_default_iface();
	} else if ((addr & 0xFFFFFF00) == 0x7F000000) {
		/* 127.0.0.X */
		is_bcast = 0;
		type = u_type;
		iface = (addr & 0x000000FF);
	} else {
		errno = ENETUNREACH;
		return -1;
	}

	if (bcast) *bcast = is_bcast;

	if (is_bcast) {
		snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 
			 socket_wrapper_dir());
		/* the caller need to do more processing */
		return 0;
	}

	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
		 socket_wrapper_dir(), type, iface, prt);

	return 0;
}