Exemple #1
0
_PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
{
	struct sockaddr_un un_addr;
	socklen_t un_addrlen = sizeof(un_addr);
	int ret;
	struct socket_info *si = find_socket_info(s);
	struct sockaddr_storage ss;
	socklen_t ss_len = sizeof(ss);

	if (!si) {
		return real_recvfrom(s, buf, len, flags, from, fromlen);
	}

	if (!from) {
		from = (struct sockaddr *)&ss;
		fromlen = &ss_len;
	}

	len = MIN(len, 1500);

	/* irix 6.4 forgets to null terminate the sun_path string :-( */
	memset(&un_addr, 0, sizeof(un_addr));
	ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
	if (ret == -1) 
		return ret;

	if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
				     si->family, from, fromlen) == -1) {
		return -1;
	}

	swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);

	return ret;
}
Exemple #2
0
_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
{
	int ret;
	struct sockaddr_un un_addr;
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_bind(s, myaddr, addrlen);
	}

	si->myname_len = addrlen;
	si->myname = sockaddr_dup(myaddr, addrlen);

	ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
	if (ret == -1) return -1;

	unlink(un_addr.sun_path);

	ret = real_bind(s, (struct sockaddr *)&un_addr,
			sizeof(struct sockaddr_un));

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

	return ret;
}
Exemple #3
0
_PUBLIC_ int swrap_ioctl(int s, int r, void *p)
{
	int ret;
	struct socket_info *si = find_socket_info(s);
	int value;

	if (!si) {
		return real_ioctl(s, r, p);
	}

	ret = real_ioctl(s, r, p);

	switch (r) {
	case FIONREAD:
		value = *((int *)p);
		if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
			swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
		} else if (value == 0) { /* END OF FILE */
			swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
		}
		break;
	}

	return ret;
}
Exemple #4
0
_PUBLIC_ int swrap_close(int fd)
{
	struct socket_info *si = find_socket_info(fd);
	int ret;

	if (!si) {
		return real_close(fd);
	}

	SWRAP_DLIST_REMOVE(sockets, si);

	if (si->myname && si->peername) {
		swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
	}

	ret = real_close(fd);

	if (si->myname && si->peername) {
		swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
		swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
	}

	if (si->path) free(si->path);
	if (si->myname) free(si->myname);
	if (si->peername) free(si->peername);
	if (si->tmp_path) {
		unlink(si->tmp_path);
		free(si->tmp_path);
	}
	free(si);

	return ret;
}
Exemple #5
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;
}
Exemple #6
0
_PUBLIC_ int swrap_listen(int s, int backlog)
{
	int ret;
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_listen(s, backlog);
	}

	ret = real_listen(s, backlog);

	return ret;
}
Exemple #7
0
_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
{
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_getsockname(s, name, addrlen);
	}

	memcpy(name, si->myname, si->myname_len);
	*addrlen = si->myname_len;

	return 0;
}
Exemple #8
0
_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_getsockopt(s, level, optname, optval, optlen);
	}

	if (level == SOL_SOCKET) {
		return real_getsockopt(s, level, optname, optval, optlen);
	} 

	errno = ENOPROTOOPT;
	return -1;
}
_PUBLIC_ int swrap_dup(int oldd)
{
	struct socket_info *si;
	int fd;

	si = find_socket_info(oldd);
	if (si == NULL)
		return real_dup(oldd);

	fd = real_dup(si->fd);
	if (fd < 0)
		return fd;

	return dup_internal(si, fd);
}
_PUBLIC_ int swrap_dup2(int oldd, int newd)
{
	struct socket_info *si_newd, *si_oldd;
	int fd;

	if (newd == oldd)
	    return newd;

	si_oldd = find_socket_info(oldd);
	si_newd = find_socket_info(newd);

	if (si_oldd == NULL && si_newd == NULL)
		return real_dup2(oldd, newd);

	fd = real_dup2(si_oldd->fd, newd);
	if (fd < 0)
		return fd;

	/* close new socket first */
	if (si_newd)
	       	swrap_close(newd);

	return dup_internal(si_oldd, fd);
}
Exemple #11
0
_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
{
	int ret;
	struct sockaddr_un un_addr;
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_connect(s, serv_addr, addrlen);
	}

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

	if (si->family != serv_addr->sa_family) {
		errno = EINVAL;
		return -1;
	}

	ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
	if (ret == -1) return -1;

	swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);

	ret = real_connect(s, (struct sockaddr *)&un_addr, 
			   sizeof(struct sockaddr_un));

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

	if (ret == 0) {
		si->peername_len = addrlen;
		si->peername = sockaddr_dup(serv_addr, addrlen);
		si->connected = 1;

		swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
		swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
	} else {
		swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
	}

	return ret;
}
Exemple #12
0
_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
{
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_getpeername(s, name, addrlen);
	}

	if (!si->peername)
	{
		errno = ENOTCONN;
		return -1;
	}

	memcpy(name, si->peername, si->peername_len);
	*addrlen = si->peername_len;

	return 0;
}
_PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
{
	int ret;
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_recv(s, buf, len, flags);
	}

	ret = real_recv(s, buf, len, flags);
	if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
		swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
	} else if (ret == 0) { /* END OF FILE */
		swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
	} else {
		swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
	}

	return ret;
}
_PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
{
	int ret;
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_send(s, buf, len, flags);
	}

	ret = real_send(s, buf, len, flags);

	if (ret == -1) {
		swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
		swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
	} else {
		swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
	}

	return ret;
}
Exemple #15
0
_PUBLIC_ int swrap_setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen)
{
	struct socket_info *si = find_socket_info(s);

	if (!si) {
		return real_setsockopt(s, level, optname, optval, optlen);
	}

	if (level == SOL_SOCKET) {
		return real_setsockopt(s, level, optname, optval, optlen);
	}

	switch (si->family) {
	case AF_INET:
		return 0;
	default:
		errno = ENOPROTOOPT;
		return -1;
	}
}
Exemple #16
0
_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
	struct socket_info *parent_si, *child_si;
	int fd;
	struct sockaddr_un un_addr;
	socklen_t un_addrlen = sizeof(un_addr);
	struct sockaddr_un un_my_addr;
	socklen_t un_my_addrlen = sizeof(un_my_addr);
	struct sockaddr my_addr;
	socklen_t my_addrlen = sizeof(my_addr);
	int ret;

	parent_si = find_socket_info(s);
	if (!parent_si) {
		return real_accept(s, addr, addrlen);
	}

	memset(&un_addr, 0, sizeof(un_addr));
	memset(&un_my_addr, 0, sizeof(un_my_addr));
	memset(&my_addr, 0, sizeof(my_addr));

	ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
	if (ret == -1) return ret;

	fd = ret;

	ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
				       parent_si->family, addr, addrlen);
	if (ret == -1) {
		close(fd);
		return ret;
	}

	child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
	memset(child_si, 0, sizeof(*child_si));

	child_si->fd = fd;
	child_si->family = parent_si->family;
	child_si->type = parent_si->type;
	child_si->protocol = parent_si->protocol;
	child_si->bound = 1;
	child_si->is_server = 1;

	ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
	if (ret == -1) {
		free(child_si);
		close(fd);
		return ret;
	}

	ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
				       child_si->family, &my_addr, &my_addrlen);
	if (ret == -1) {
		free(child_si);
		close(fd);
		return ret;
	}

	child_si->myname_len = my_addrlen;
	child_si->myname = sockaddr_dup(&my_addr, my_addrlen);

	child_si->peername_len = *addrlen;
	child_si->peername = sockaddr_dup(addr, *addrlen);

	SWRAP_DLIST_ADD(sockets, child_si);

	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);

	return fd;
}
Exemple #17
0
int swrap_writev(int s, const struct iovec *vector, size_t count)
{
	int ret;
	struct socket_info *si = find_socket_info(s);
	struct iovec v;

	if (!si) {
		return real_writev(s, vector, count);
	}

	/* we write 1500 bytes as maximum */
	if (count > 0) {
		size_t i, len = 0;

		for (i=0; i < count; i++) {
			size_t nlen;
			nlen = len + vector[i].iov_len;
			if (nlen > 1500) {
				break;
			}
		}
		count = i;
		if (count == 0) {
			v = vector[0];
			v.iov_len = MIN(v.iov_len, 1500);
			vector = &v;
			count = 1;
		}
	}

	ret = real_writev(s, vector, count);
	if (ret == -1) {
		swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
	} else {
		uint8_t *buf;
		off_t ofs = 0;
		size_t i;
		size_t remain = ret;

		/* we capture it as one single packet */
		buf = (uint8_t *)malloc(ret);
		if (!buf) {
			/* we just not capture the packet */
			errno = 0;
			return ret;
		}

		for (i=0; i < count; i++) {
			size_t this_time = MIN(remain, vector[i].iov_len);
			memcpy(buf + ofs,
			       vector[i].iov_base,
			       this_time);
			ofs += this_time;
			remain -= this_time;
		}

		swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
		free(buf);
	}

	return ret;
}
Exemple #18
0
_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
	struct socket_info *parent_si, *child_si;
	int fd;
	struct sockaddr_un un_addr;
	socklen_t un_addrlen = sizeof(un_addr);
	struct sockaddr_un un_my_addr;
	socklen_t un_my_addrlen = sizeof(un_my_addr);
	struct sockaddr *my_addr;
	socklen_t my_addrlen, len;
	int ret;

	parent_si = find_socket_info(s);
	if (!parent_si) {
		return real_accept(s, addr, addrlen);
	}

	/* 
	 * assume out sockaddr have the same size as the in parent
	 * socket family
	 */
	my_addrlen = socket_length(parent_si->family);
	if (my_addrlen <= 0) {
		errno = EINVAL;
		return -1;
	}

	my_addr = (struct sockaddr *)malloc(my_addrlen);
	if (my_addr == NULL) {
		return -1;
	}

	memset(&un_addr, 0, sizeof(un_addr));
	memset(&un_my_addr, 0, sizeof(un_my_addr));

	ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
	if (ret == -1) {
		free(my_addr);
		return ret;
	}

	fd = ret;

	len = my_addrlen;
	ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
				       parent_si->family, my_addr, &len);
	if (ret == -1) {
		free(my_addr);
		close(fd);
		return ret;
	}

	child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
	memset(child_si, 0, sizeof(*child_si));

	child_si->fd = fd;
	child_si->family = parent_si->family;
	child_si->type = parent_si->type;
	child_si->protocol = parent_si->protocol;
	child_si->bound = 1;
	child_si->is_server = 1;
	child_si->connected = 1;

	child_si->peername_len = len;
	child_si->peername = sockaddr_dup(my_addr, len);

	if (addr != NULL && addrlen != NULL) {
	    *addrlen = len;
	    if (*addrlen >= len)
		memcpy(addr, my_addr, len);
	    *addrlen = 0;
	}

	ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
	if (ret == -1) {
		free(child_si);
		close(fd);
		return ret;
	}

	len = my_addrlen;
	ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
				       child_si->family, my_addr, &len);
	if (ret == -1) {
		free(child_si);
		free(my_addr);
		close(fd);
		return ret;
	}

	child_si->myname_len = len;
	child_si->myname = sockaddr_dup(my_addr, len);
	free(my_addr);

	SWRAP_DLIST_ADD(sockets, child_si);

	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);

	return fd;
}