示例#1
0
static int
dup_internal(const struct socket_info *si_oldd, int fd)
{
	struct socket_info *si_newd;

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

	si_newd->fd = fd;

	si_newd->family = si_oldd->family;
	si_newd->type = si_oldd->type;
	si_newd->protocol = si_oldd->protocol;
	si_newd->bound = si_oldd->bound;
	si_newd->bcast = si_oldd->bcast;
	if (si_oldd->path)
		si_newd->path = strdup(si_oldd->path);
	if (si_oldd->tmp_path)
		si_newd->tmp_path = strdup(si_oldd->tmp_path);
	si_newd->myname =
	    sockaddr_dup(si_oldd->myname, si_oldd->myname_len);
	si_newd->myname_len = si_oldd->myname_len;
	si_newd->peername =
	    sockaddr_dup(si_oldd->peername, si_oldd->peername_len);
	si_newd->peername_len = si_oldd->peername_len;

	si_newd->io = si_oldd->io;

	SWRAP_DLIST_ADD(sockets, si_newd);

	return fd;
}
示例#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;
}
示例#3
0
static iodev_t *
tcp_create(iodev_t *dev, struct sockaddr *local, struct sockaddr *remote, size_t bufsize, int with_linebuf) {
    // First create the basic (slightly larger) config
    iodev_cfg_t *cfg = iodev_alloc_cfg(sizeof(tcp_cfg_t), "tcp", tcp_free_cfg);
    iodev_t *tcp = iodev_init(dev, cfg, bufsize);

    // Initialise the extras
    tcp_cfg_t *tcfg = tcp_getcfg(tcp);
    tcfg->addrlen = local != NULL ? sockaddr_len(local) : remote != NULL ? sockaddr_len(remote) : 0;
    tcfg->local = sockaddr_dup(local);
    tcfg->remote = sockaddr_dup(remote);
    if (with_linebuf)
        dev->linebuf = stringstore_init(NULL);

    // default functions
    tcp->open = tcp_open;
    tcp->close = tcp_close;
    tcp->configure = tcp_configure;

    return tcp;
}
示例#4
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;
}
示例#5
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;
}
示例#6
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;
}
示例#7
0
/****************************************************************************
this one is for AIX (tested on 4.2)
****************************************************************************/
int rep_getifaddrs(struct ifaddrs **ifap)
{
	char buff[8192];
	int fd, i;
	struct ifconf ifc;
	struct ifreq *ifr=NULL;
	struct ifaddrs *curif;
	struct ifaddrs *lastif = NULL;

	*ifap = NULL;

	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
		return -1;
	}

	ifc.ifc_len = sizeof(buff);
	ifc.ifc_buf = buff;

	if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
		close(fd);
		return -1;
	}

	ifr = ifc.ifc_req;

	/* Loop through interfaces */
	i = ifc.ifc_len;

	while (i > 0) {
		unsigned int inc;

		inc = ifr->ifr_addr.sa_len;

		curif = calloc(1, sizeof(struct ifaddrs));
		if (lastif == NULL) {
			*ifap = curif;
		} else {
			lastif->ifa_next = curif;
		}

		curif->ifa_name = strdup(ifr->ifr_name);
		curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr);
		curif->ifa_dstaddr = NULL;
		curif->ifa_data = NULL;
		curif->ifa_netmask = NULL;
		curif->ifa_next = NULL;

		if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
			goto fail;
		}

		curif->ifa_flags = (unsigned short)ifr->ifr_flags;

		/*
		 * The rest is requested only for AF_INET, for portability and
		 * compatiblilty (see e.g. https://linux.die.net/man/7/netdevice)
		 */

		if (curif->ifa_addr->sa_family == AF_INET) {
			if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
				goto fail;
			}
			curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);

			if (curif->ifa_flags & IFF_BROADCAST) {
				if (ioctl(fd, SIOCGIFBRDADDR, ifr) != 0) {
					goto fail;
				}
				/*
				 * OS/2 TCP/IP 4.21 is known to leave this field zeroed but return the
				 * correct address. We assume that it's so if ioctl succeeds and family
				 * matches what it should be.
				 */
				if (ifr->ifr_broadaddr.sa_len == 0 &&
						ifr->ifr_broadaddr.sa_family == curif->ifa_addr->sa_family) {
					ifr->ifr_broadaddr.sa_len = sizeof(struct sockaddr_in);
				}
				curif->ifa_broadaddr = sockaddr_dup(&ifr->ifr_broadaddr);
			} else if (curif->ifa_flags & IFF_POINTOPOINT) {
				if (ioctl(fd, SIOCGIFDSTADDR, ifr) != 0) {
					goto fail;
				}
				/*
				 * OS/2 TCP/IP 4.21 is known to leave this field zeroed but return the
				 * correct address. We assume that it's so if ioctl succeeds and family
				 * matches what it should be.
				 */
				if (ifr->ifr_dstaddr.sa_len == 0 &&
						ifr->ifr_dstaddr.sa_family == curif->ifa_addr->sa_family) {
					ifr->ifr_dstaddr.sa_len = sizeof(struct sockaddr_in);
				}
				curif->ifa_dstaddr = sockaddr_dup(&ifr->ifr_dstaddr);
			}
		}

		lastif = curif;

		/*
		 * Patch from Archie Cobbs ([email protected]).  The
		 * addresses in the SIOCGIFCONF interface list have a
		 * minimum size. Usually this doesn't matter, but if
		 * your machine has tunnel interfaces, etc. that have
		 * a zero length "link address", this does matter.  */

		if (inc < sizeof(ifr->ifr_addr))
			inc = sizeof(ifr->ifr_addr);
		inc += IFNAMSIZ;

		ifr = (struct ifreq*) (((char*) ifr) + inc);
		i -= inc;
	}

	close(fd);
	return 0;

fail:
	close(fd);
	freeifaddrs(*ifap);
	return -1;
}
示例#8
0
int rep_getifaddrs(struct ifaddrs **ifap)
{
	struct ifconf ifc;
	char buff[8192];
	int fd, i, n;
	struct ifreq *ifr=NULL;
	struct in_addr ipaddr;
	struct in_addr nmask;
	char *iname;
	struct ifaddrs *curif;
	struct ifaddrs *lastif = NULL;

	*ifap = NULL;

	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
		return -1;
	}
  
	ifc.ifc_len = sizeof(buff);
	ifc.ifc_buf = buff;

	if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
		close(fd);
		return -1;
	} 

	ifr = ifc.ifc_req;
  
	n = ifc.ifc_len / sizeof(struct ifreq);

	/* Loop through interfaces, looking for given IP address */
	for (i=n-1; i>=0; i--) {
		if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) == -1) {
			freeifaddrs(*ifap);
			return -1;
		}

		curif = calloc(1, sizeof(struct ifaddrs));
		curif->ifa_name = strdup(ifr[i].ifr_name);
		curif->ifa_flags = ifr[i].ifr_flags;
		curif->ifa_dstaddr = NULL;
		curif->ifa_data = NULL;
		curif->ifa_next = NULL;

		curif->ifa_addr = NULL;
		if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != -1) {
			curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr);
		}

		curif->ifa_netmask = NULL;
		if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != -1) {
			curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr);
		}

		if (lastif == NULL) {
			*ifap = curif;
		} else {
			lastif->ifa_next = curif;
		}
		lastif = curif;
	}

	close(fd);

	return 0;
}  
示例#9
0
/****************************************************************************
this one is for AIX (tested on 4.2)
****************************************************************************/
int rep_getifaddrs(struct ifaddrs **ifap)
{
	char buff[8192];
	int fd, i;
	struct ifconf ifc;
	struct ifreq *ifr=NULL;
	struct in_addr ipaddr;
	struct in_addr nmask;
	char *iname;
	struct ifaddrs *curif;
	struct ifaddrs *lastif = NULL;

	*ifap = NULL;

	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
		return -1;
	}

	ifc.ifc_len = sizeof(buff);
	ifc.ifc_buf = buff;

	if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
		close(fd);
		return -1;
	}

	ifr = ifc.ifc_req;

	/* Loop through interfaces */
	i = ifc.ifc_len;

	while (i > 0) {
		uint_t inc;

		inc = ifr->ifr_addr.sa_len;

		if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
			freeaddrinfo(*ifap);
			return -1;
		}

		curif = calloc(1, sizeof(struct ifaddrs));
		if (lastif == NULL) {
			*ifap = curif;
		} else {
			lastif->ifa_next = curif;
		}

		curif->ifa_name = strdup(ifr->ifr_name);
		curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr);
		curif->ifa_dstaddr = NULL;
		curif->ifa_data = NULL;
		curif->ifa_netmask = NULL;
		curif->ifa_next = NULL;

		if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
			freeaddrinfo(*ifap);
			return -1;
		}

		curif->ifa_flags = ifr->ifr_flags;

		if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
			freeaddrinfo(*ifap);
			return -1;
		}

		curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);

		lastif = curif;

	next:
		/*
		 * Patch from Archie Cobbs ([email protected]).  The
		 * addresses in the SIOCGIFCONF interface list have a
		 * minimum size. Usually this doesn't matter, but if
		 * your machine has tunnel interfaces, etc. that have
		 * a zero length "link address", this does matter.  */

		if (inc < sizeof(ifr->ifr_addr))
			inc = sizeof(ifr->ifr_addr);
		inc += IFNAMSIZ;

		ifr = (struct ifreq*) (((char*) ifr) + inc);
		i -= inc;
	}

	close(fd);
	return 0;
}
示例#10
0
/****************************************************************************
this should cover most of the streams based systems
Thanks to [email protected] for several ideas in this code
****************************************************************************/
int rep_getifaddrs(struct ifaddrs **ifap)
{
	struct ifreq ifreq;
	struct strioctl strioctl;
	char buff[8192];
	int fd, i, n;
	struct ifreq *ifr=NULL;
	struct in_addr ipaddr;
	struct in_addr nmask;
	char *iname;
	struct ifaddrs *curif;
	struct ifaddrs *lastif = NULL;

	*ifap = NULL;

	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
		return -1;
	}
  
	strioctl.ic_cmd = SIOCGIFCONF;
	strioctl.ic_dp  = buff;
	strioctl.ic_len = sizeof(buff);
	if (ioctl(fd, I_STR, &strioctl) < 0) {
		close(fd);
		return -1;
	} 

	/* we can ignore the possible sizeof(int) here as the resulting
	   number of interface structures won't change */
	n = strioctl.ic_len / sizeof(struct ifreq);

	/* we will assume that the kernel returns the length as an int
           at the start of the buffer if the offered size is a
           multiple of the structure size plus an int */
	if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) {
		ifr = (struct ifreq *)(buff + sizeof(int));  
	} else {
		ifr = (struct ifreq *)buff;  
	}

	/* Loop through interfaces */

	for (i = 0; i<n; i++) {
		ifreq = ifr[i];
  
		curif = calloc(1, sizeof(struct ifaddrs));
		if (lastif == NULL) {
			*ifap = curif;
		} else {
			lastif->ifa_next = curif;
		}

		strioctl.ic_cmd = SIOCGIFFLAGS;
		strioctl.ic_dp  = (char *)&ifreq;
		strioctl.ic_len = sizeof(struct ifreq);
		if (ioctl(fd, I_STR, &strioctl) != 0) {
			freeifaddrs(*ifap);
			return -1;
		}

		curif->ifa_flags = ifreq.ifr_flags;
		
		strioctl.ic_cmd = SIOCGIFADDR;
		strioctl.ic_dp  = (char *)&ifreq;
		strioctl.ic_len = sizeof(struct ifreq);
		if (ioctl(fd, I_STR, &strioctl) != 0) {
			freeifaddrs(*ifap);
			return -1;
		}

		curif->ifa_name = strdup(ifreq.ifr_name);
		curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr);
		curif->ifa_dstaddr = NULL;
		curif->ifa_data = NULL;
		curif->ifa_next = NULL;
		curif->ifa_netmask = NULL;

		strioctl.ic_cmd = SIOCGIFNETMASK;
		strioctl.ic_dp  = (char *)&ifreq;
		strioctl.ic_len = sizeof(struct ifreq);
		if (ioctl(fd, I_STR, &strioctl) != 0) {
			freeifaddrs(*ifap);
			return -1;
		}

		curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr);

		lastif = curif;
	}

	close(fd);

	return 0;
}
示例#11
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;
}