Beispiel #1
0
gssize system_recvFrom(gint fd, gpointer buf, size_t n, gint flags,
		struct sockaddr* addr, socklen_t* len) {
	/* TODO flags are ignored */
	/* check if this is a socket */
	if(fd < MIN_DESCRIPTOR){
		errno = EBADF;
		return -1;
	}

	in_addr_t ip = 0;
	in_port_t port = 0;

	Node* node = _system_switchInShadowContext();
	gsize bytes = 0;
	gint result = node_receiveUserData(node, fd, buf, n, &ip, &port, &bytes);
	_system_switchOutShadowContext(node);

	if(result != 0) {
		errno = result;
		return -1;
	}

	/* check if they wanted to know where we got the data from */
	if(addr != NULL && len != NULL && *len >= sizeof(struct sockaddr_in)) {
		struct sockaddr_in* si = (struct sockaddr_in*) addr;
		si->sin_addr.s_addr = ip;
		si->sin_port = port;
		si->sin_family = AF_INET;
		*len = sizeof(struct sockaddr_in);
	}

	return (gssize) bytes;
}
Beispiel #2
0
gint system_epollCtl(gint epollDescriptor, gint operation, gint fileDescriptor,
		struct epoll_event* event) {
	/*
	 * initial checks before passing on to node:
	 * EINVAL if fd is the same as epfd, or the requested operation op is not
	 * supported by this interface
	 */
	if(epollDescriptor == fileDescriptor) {
		errno = EINVAL;
		return -1;
	}

	/* switch into shadow and do the operation */
	Node* node = _system_switchInShadowContext();
	gint result = node_epollControl(node, epollDescriptor, operation, fileDescriptor, event);
	_system_switchOutShadowContext(node);

	/*
	 * When successful, epoll_ctl() returns zero. When an error occurs,
	 * epoll_ctl() returns -1 and errno is set appropriately.
	 */
	if(result != 0) {
		errno = result;
		return -1;
	} else {
		return 0;
	}
}
Beispiel #3
0
gint system_pipe2(gint pipefds[2], gint flags) {
	/* we only support non-blocking sockets, and require
	 * SOCK_NONBLOCK to be set immediately */
	gboolean isBlocking = TRUE;

	/* clear non-blocking flags if set to get true type */
	if(flags & O_NONBLOCK) {
		flags = flags & ~O_NONBLOCK;
		isBlocking = FALSE;
	}
	if(flags & O_CLOEXEC) {
		flags = flags & ~O_CLOEXEC;
		isBlocking = FALSE;
	}

	/* check inputs for what we support */
	if(isBlocking) {
		warning("we only support non-blocking pipes: please bitwise OR 'O_NONBLOCK' with flags");
		errno = EINVAL;
		return -1;
	}

	Node* node = _system_switchInShadowContext();

	gint handle = node_createDescriptor(node, DT_PIPE);

	Channel* channel = (Channel*) node_lookupDescriptor(node, handle);
	gint linkedHandle = channel_getLinkedHandle(channel);

	_system_switchOutShadowContext(node);

	pipefds[0] = handle; /* reader */
	pipefds[1] = linkedHandle; /* writer */
	return 0;
}
Beispiel #4
0
gssize system_sendTo(gint fd, const gpointer buf, gsize n, gint flags,
		const struct sockaddr* addr, socklen_t len) {
	/* TODO flags are ignored */
	/* check if this is a socket */
	if(fd < MIN_DESCRIPTOR){
		errno = EBADF;
		return -1;
	}

	in_addr_t ip = 0;
	in_port_t port = 0;

	/* check if they specified an address to send to */
	if(addr != NULL && len >= sizeof(struct sockaddr_in)) {
		struct sockaddr_in* si = (struct sockaddr_in*) addr;
		ip = si->sin_addr.s_addr;
		port = si->sin_port;
	}

	Node* node = _system_switchInShadowContext();
	gsize bytes = 0;
	gint result = node_sendUserData(node, fd, buf, n, ip, port, &bytes);
	_system_switchOutShadowContext(node);

	if(result != 0) {
		errno = result;
		return -1;
	}
	return (gssize) bytes;
}
Beispiel #5
0
gint system_getHostName(gchar *name, size_t len) {
	Node* node = _system_switchInShadowContext();
	gint result = 0;

//	in_addr_t ip = node_getDefaultIP(node);
//	const gchar* hostname = internetwork_resolveID(worker_getPrivate()->cached_engine->internet, (GQuark)ip);

	if(name != NULL && node != NULL) {

		/* resolve my address to a hostname */
		const gchar* sysname = node_getName(node);

		if(sysname != NULL && len > strlen(sysname)) {
			if(strncpy(name, sysname, len) != NULL) {
				result = 0;
				goto done;
			}
		}
	}
	errno = EFAULT;
	result = -1;

	done:

	_system_switchOutShadowContext(node);
	return result;
}
Beispiel #6
0
gint system_shutdown(gint fd, gint how) {
	Host* node = _system_switchInShadowContext();
	warning("shutdown not implemented");
	_system_switchOutShadowContext(node);
	errno = ENOSYS;
	return -1;
}
Beispiel #7
0
gpointer system_malloc(gsize size) {
	Node* node = _system_switchInShadowContext();
	gpointer ptr = malloc(size);
	tracker_addAllocatedBytes(node_getTracker(node), ptr, size);
	_system_switchOutShadowContext(node);
	return ptr;
}
Beispiel #8
0
gint system_accept(gint fd, struct sockaddr* addr, socklen_t* len) {
	/* check if this is a virtual socket */
	if(fd < MIN_DESCRIPTOR){
		warning("intercepted a non-virtual descriptor");
		errno = EBADF;
		return -1;
	}

	in_addr_t ip = 0;
	in_port_t port = 0;
	gint handle = 0;

	/* direct to node for further checks */
	Node* node = _system_switchInShadowContext();

	gint result = node_acceptNewPeer(node, fd, &ip, &port, &handle);

	_system_switchOutShadowContext(node);

	/* check if there was an error */
	if(result != 0) {
		errno = result;
		return -1;
	}

	if(addr != NULL && len != NULL && *len >= sizeof(struct sockaddr_in)) {
		struct sockaddr_in* ai = (struct sockaddr_in*) addr;
		ai->sin_addr.s_addr = ip;
		ai->sin_port = port;
		ai->sin_family = AF_INET;
		*len = sizeof(struct sockaddr_in);
	}

	return handle;
}
Beispiel #9
0
gssize system_recvMsg(gint fd, struct msghdr* message, gint flags) {
	/* TODO implement */
	Host* node = _system_switchInShadowContext();
	warning("recvmsg not implemented");
	_system_switchOutShadowContext(node);
	errno = ENOSYS;
	return -1;
}
Beispiel #10
0
gssize system_sendMsg(gint fd, const struct msghdr* message, gint flags) {
	/* TODO implement */
	Node* node = _system_switchInShadowContext();
	warning("sendmsg not implemented");
	_system_switchOutShadowContext(node);
	errno = ENOSYS;
	return -1;
}
Beispiel #11
0
gint system_accept4(gint fd, struct sockaddr* addr, socklen_t* len, gint flags) {
	/* just ignore the flags and call accept */
	if(flags) {
		Host* node = _system_switchInShadowContext();
		debug("accept4 ignoring flags argument");
		_system_switchOutShadowContext(node);
	}
	return system_accept(fd, addr, len);
}
Beispiel #12
0
gint system_setSockOpt(gint fd, gint level, gint optname, const gpointer optval,
		socklen_t optlen) {
	Node* node = _system_switchInShadowContext();
	/* @todo: implement socket options */
	debug("setsockopt not implemented. this is probably OK, depending on usage.");
	errno = ENOSYS;
	_system_switchOutShadowContext(node);
	return -1;
}
Beispiel #13
0
gint system_close(gint fd) {
	/* check if this is a socket */
	if(fd < MIN_DESCRIPTOR){
		errno = EBADF;
		return -1;
	}

	Node* node = _system_switchInShadowContext();
	gint r = node_closeUser(node, fd);
	_system_switchOutShadowContext(node);
	return r;
}
Beispiel #14
0
gint system_epollCreate(gint size) {
	/* size should be > 0, but can otherwise be completely ignored */
	if(size < 1) {
		errno = EINVAL;
		return -1;
	}

	/* switch into shadow and create the new descriptor */
	Node* node = _system_switchInShadowContext();
	gint handle = node_createDescriptor(node, DT_EPOLL);
	_system_switchOutShadowContext(node);

	return handle;
}
Beispiel #15
0
gint system_socketPair(gint domain, gint type, gint protocol, gint fds[2]) {
	/* create a pair of connected sockets, i.e. a bi-directional pipe */
	if(domain != AF_UNIX) {
		errno = EAFNOSUPPORT;
		return -1;
	}

	/* only support non-blocking sockets */
	gboolean isBlocking = FALSE;

	/* clear non-blocking flags if set to get true type */
	gint realType = type;
	if(realType & SOCK_NONBLOCK) {
		realType = realType & ~SOCK_NONBLOCK;
		isBlocking = FALSE;
	}
	if(realType & SOCK_CLOEXEC) {
		realType = realType & ~SOCK_CLOEXEC;
		isBlocking = FALSE;
	}

	if(realType != SOCK_STREAM) {
		errno = EPROTONOSUPPORT;
		return -1;
	}

	gint result = 0;
	Host* node = _system_switchInShadowContext();

	if(isBlocking) {
		warning("we only support non-blocking sockets: please bitwise OR 'SOCK_NONBLOCK' with type flags");
		errno = EPROTONOSUPPORT;
		result = -1;
	}

	if(result == 0) {
		gint handle = host_createDescriptor(node, DT_SOCKETPAIR);

		Channel* channel = (Channel*) host_lookupDescriptor(node, handle);
		gint linkedHandle = channel_getLinkedHandle(channel);

		fds[0] = handle;
		fds[1] = linkedHandle;
	}

	_system_switchOutShadowContext(node);
	return result;
}
Beispiel #16
0
gint system_epollPWait(gint epollDescriptor, struct epoll_event* events,
		gint maxevents, gint timeout, const sigset_t* signalSet) {
	/*
	 * this is the same as system_epollWait, except it catches signals in the
	 * signal set. lets just assume we have no signals to worry about.
	 * forward to our regular wait method.
	 *
	 * @warning we dont handle signals
	 */
	if(signalSet) {
		Host* node = _system_switchInShadowContext();
		warning("epollpwait using a signalset is not yet supported");
		_system_switchOutShadowContext(node);
	}
	return system_epollWait(epollDescriptor, events, maxevents, timeout);
}
Beispiel #17
0
gint system_epollWait(gint epollDescriptor, struct epoll_event* eventArray,
		gint eventArrayLength, gint timeout) {
	/*
	 * EINVAL if maxevents is less than or equal to zero.
	 */
	if(eventArrayLength <= 0) {
		errno = EINVAL;
		return -1;
	}

	/* switch to shadow context and try to get events if we have any */
	Node* node = _system_switchInShadowContext();

	/*
	 * initial checks: we can't block, so timeout must be 0. anything else will
	 * cause a warning. if they seriously want to block by passing in -1, then
	 * return interrupt below only if we have no events.
	 *
	 * @note log while in shadow context to get node info in the log
	 */
	if(timeout != 0) {
		warning("Shadow does not block, so the '%i' millisecond timeout will be ignored", timeout);
	}

	gint nEvents = 0;
	gint result = node_epollGetEvents(node, epollDescriptor, eventArray,
			eventArrayLength, &nEvents);
	_system_switchOutShadowContext(node);

	/* check if there was an error */
	if(result != 0) {
		errno = result;
		return -1;
	}

	/*
	 * if we dont have any events and they are trying to block, tell them their
	 * timeout was interrupted.
	 */
	if(timeout != 0 && nEvents <= 0) {
		errno = EINTR;
		return -1;
	}

	/* the event count. zero is fine since they weren't expecting a timer. */
	return nEvents;
}
Beispiel #18
0
gint system_randomBytes(guchar* buf, gint numBytes) {
	Node* node = _system_switchInShadowContext();

	Random* random = node_getRandom(node);
	gint bytesWritten = 0;

	while(numBytes > bytesWritten) {
		gint r = random_nextInt(random);
		gint copyLength = MIN(numBytes-bytesWritten, 4);
		g_memmove(buf+bytesWritten, &r, copyLength);
		bytesWritten += copyLength;
	}

	_system_switchOutShadowContext(node);

	return 1;
}
Beispiel #19
0
gint system_listen(gint fd, gint backlog) {
	/* check if this is a socket */
	if(fd < MIN_DESCRIPTOR){
		errno = EBADF;
		return -1;
	}

	Node* node = _system_switchInShadowContext();
	gint result = node_listenForPeer(node, fd, backlog);
	_system_switchOutShadowContext(node);

	/* check if there was an error */
	if(result != 0) {
		errno = result;
		return -1;
	}

	return 0;
}
Beispiel #20
0
gint system_socket(gint domain, gint type, gint protocol) {
	/* we only support non-blocking sockets, and require
	 * SOCK_NONBLOCK to be set immediately */
	gboolean isBlocking = FALSE;

	/* clear non-blocking flags if set to get true type */
	if(type & SOCK_NONBLOCK) {
		type = type & ~SOCK_NONBLOCK;
		isBlocking = FALSE;
	}
	if(type & SOCK_CLOEXEC) {
		type = type & ~SOCK_CLOEXEC;
		isBlocking = FALSE;
	}

	gint result = 0;
	Host* node = _system_switchInShadowContext();

	/* check inputs for what we support */
	if(isBlocking) {
		warning("we only support non-blocking sockets: please bitwise OR 'SOCK_NONBLOCK' with type flags");
		errno = EPROTONOSUPPORT;
		result = -1;
	} else if (type != SOCK_STREAM && type != SOCK_DGRAM) {
		warning("unsupported socket type \"%i\", we only support SOCK_STREAM and SOCK_DGRAM", type);
		errno = EPROTONOSUPPORT;
		result = -1;
	} else if(domain != AF_INET) {
		warning("trying to create socket with domain \"%i\", we only support PF_INET", domain);
		errno = EAFNOSUPPORT;
		result = -1;
	}

	if(result == 0) {
		/* we are all set to create the socket */
		DescriptorType dtype = type == SOCK_STREAM ? DT_TCPSOCKET : DT_UDPSOCKET;
		result = host_createDescriptor(node, dtype);
	}

	_system_switchOutShadowContext(node);
	return result;
}
Beispiel #21
0
int system_getnameinfo(const struct sockaddr *sa, socklen_t salen,
		char *host, size_t hostlen, char *serv, size_t servlen, int flags) {
	/* FIXME this is not fully implemented */
	if(!sa) {
		return EAI_FAIL;
	}

	gint retval = 0;
	Node* node = _system_switchInShadowContext();

	GQuark convertedIP = (GQuark) (((struct sockaddr_in*)sa)->sin_addr.s_addr);
	const gchar* hostname = internetwork_resolveID(worker_getInternet(), convertedIP);

	if(hostname) {
		g_utf8_strncpy(host, hostname, hostlen);
	} else {
		retval = EAI_NONAME;
	}

	_system_switchOutShadowContext(node);
	return retval;
}
Beispiel #22
0
gint system_ioctl(int fd, unsigned long int request, va_list farg) {
	/* check if this is a socket */
	if(fd < MIN_DESCRIPTOR){
		errno = EBADF;
		return -1;
	}

	gint result = 0;

	/* normally, the type of farg depends on the request */
	Host* node = _system_switchInShadowContext();
	Descriptor* descriptor = host_lookupDescriptor(node, fd);

	if(descriptor) {
		DescriptorType t = descriptor_getType(descriptor);
		if(t == DT_TCPSOCKET || t == DT_UDPSOCKET) {
			Socket* socket = (Socket*) descriptor;
			if(request == SIOCINQ || request == FIONREAD) {
				gsize bufferLength = socket_getInputBufferLength(socket);
				gint* lengthOut = va_arg(farg, int*);
				*lengthOut = (gint)bufferLength;
			} else if (request == SIOCOUTQ || request == TIOCOUTQ) {
Beispiel #23
0
void system_free(gpointer ptr) {
	Node* node = _system_switchInShadowContext();
	free(ptr);
	tracker_removeAllocatedBytes(node_getTracker(node), ptr);
	_system_switchOutShadowContext(node);
}
Beispiel #24
0
gint system_getSockOpt(gint fd, gint level, gint optname, gpointer optval,
		socklen_t* optlen) {
	if(!optlen) {
		errno = EFAULT;
		return -1;
	}

	Host* node = _system_switchInShadowContext();
	Descriptor* descriptor = host_lookupDescriptor(node, fd);

	gint result = 0;

	/* TODO: implement socket options */
	if(descriptor) {
		if(level == SOL_SOCKET || level == SOL_IP || level == SOL_TCP) {
			DescriptorType t = descriptor_getType(descriptor);
			switch (optname) {
				case TCP_INFO: {
					if(t == DT_TCPSOCKET) {
						if(optval) {
							TCP* tcp = (TCP*)descriptor;
							tcp_getInfo(tcp, (struct tcp_info *)optval);
						}
						*optlen = sizeof(struct tcp_info);
						result = 0;
					} else {
						warning("called getsockopt with TCP_INFO on non-TCP socket");
						errno = ENOPROTOOPT;
						result = -1;
					}

					break;
				}

				case SO_SNDBUF: {
					if(*optlen < sizeof(gint)) {
						warning("called getsockopt with SO_SNDBUF with optlen < %i", (gint)(sizeof(gint)));
						errno = EINVAL;
						result = -1;
					} else if (t != DT_TCPSOCKET && t != DT_UDPSOCKET) {
						warning("called getsockopt with SO_SNDBUF on non-socket");
						errno = ENOPROTOOPT;
						result = -1;
					} else {
						if(optval) {
							*((gint*) optval) = (gint) socket_getOutputBufferSize((Socket*)descriptor);
						}
						*optlen = sizeof(gint);
					}
					break;
				}

				case SO_RCVBUF: {
					if(*optlen < sizeof(gint)) {
						warning("called getsockopt with SO_RCVBUF with optlen < %i", (gint)(sizeof(gint)));
						errno = EINVAL;
						result = -1;
					} else if (t != DT_TCPSOCKET && t != DT_UDPSOCKET) {
						warning("called getsockopt with SO_RCVBUF on non-socket");
						errno = ENOPROTOOPT;
						result = -1;
					} else {
						if(optval) {
							*((gint*) optval) = (gint) socket_getInputBufferSize((Socket*)descriptor);
						}
						*optlen = sizeof(gint);
					}
					break;
				}

				case SO_ERROR: {
					if(optval) {
						*((gint*)optval) = 0;
					}
					*optlen = sizeof(gint);

					result = 0;
					break;
				}

				default: {
					warning("getsockopt optname %i not implemented", optname);
					errno = ENOSYS;
					result = -1;
					break;
				}
			}
		} else {
			warning("getsockopt level %i not implemented", level);
			errno = ENOSYS;
			result = -1;
		}
	} else {
		errno = EBADF;
		result = -1;
	}

	_system_switchOutShadowContext(node);
	return result;
}
Beispiel #25
0
gint system_getRandom() {
	Node* node = _system_switchInShadowContext();
	gint r = random_nextInt(node_getRandom(node));
	_system_switchOutShadowContext(node);
	return r;
}
Beispiel #26
0
gint system_getAddrInfo(gchar *name, const gchar *service,
		const struct addrinfo *hgints, struct addrinfo **res) {
	Node* node = _system_switchInShadowContext();

	gint result = 0;

	*res = NULL;
	if(name != NULL && node != NULL) {

		/* node may be a number-and-dots address, or a hostname. lets hope for hostname
		 * and try that first, o/w convert to the in_addr_t and do a second lookup. */
		in_addr_t address = (in_addr_t) internetwork_resolveName(worker_getInternet(), name);

		if(address == 0) {
			/* name was not in hostname format. convert to IP format and try again */
			struct in_addr inaddr;
			gint r = inet_pton(AF_INET, name, &inaddr);

			if(r == 1) {
				/* successful conversion to IP format, now find the real hostname */
				GQuark convertedIP = (GQuark) inaddr.s_addr;
				const gchar* hostname = internetwork_resolveID(worker_getInternet(), convertedIP);

				if(hostname != NULL) {
					/* got it, so convertedIP is a valid IP */
					address = (in_addr_t) convertedIP;
				} else {
					/* name not mapped by resolver... */
					result = EAI_FAIL;
					goto done;
				}
			} else if(r == 0) {
				/* not in correct form... hmmm, too bad i guess */
				result = EAI_NONAME;
				goto done;
			} else {
				/* error occured */
				result = EAI_SYSTEM;
				goto done;
			}
		}

		/* should have address now */
		struct sockaddr_in* sa = g_malloc(sizeof(struct sockaddr_in));
		/* application will expect it in network order */
		// sa->sin_addr.s_addr = (in_addr_t) htonl((guint32)(*addr));
		sa->sin_addr.s_addr = address;
		sa->sin_family = AF_INET; /* libcurl expects this to be set */

		struct addrinfo* ai_out = g_malloc(sizeof(struct addrinfo));
		ai_out->ai_addr = (struct sockaddr*) sa;
		ai_out->ai_addrlen =  sizeof(struct sockaddr_in);
		ai_out->ai_canonname = NULL;
		ai_out->ai_family = AF_INET;
		ai_out->ai_flags = 0;
		ai_out->ai_next = NULL;
		ai_out->ai_protocol = 0;
		ai_out->ai_socktype = SOCK_STREAM;

		*res = ai_out;
		result = 0;
		goto done;
	}

	errno = EINVAL;
	result = EAI_SYSTEM;

	done:
	_system_switchOutShadowContext(node);
	return result;
}
Beispiel #27
0
gint system_setSockOpt(gint fd, gint level, gint optname, const gpointer optval,
		socklen_t optlen) {
	if(!optval) {
		errno = EFAULT;
		return -1;
	}

	Host* node = _system_switchInShadowContext();
	Descriptor* descriptor = host_lookupDescriptor(node, fd);

	gint result = 0;

	/* TODO: implement socket options */
	if(descriptor) {
		if(level == SOL_SOCKET) {
			DescriptorType t = descriptor_getType(descriptor);
			switch (optname) {
				case SO_SNDBUF: {
					if(optlen < sizeof(gint)) {
						warning("called setsockopt with SO_SNDBUF with optlen < %i", (gint)(sizeof(gint)));
						errno = EINVAL;
						result = -1;
					} else if (t != DT_TCPSOCKET && t != DT_UDPSOCKET) {
						warning("called setsockopt with SO_SNDBUF on non-socket");
						errno = ENOPROTOOPT;
						result = -1;
					} else {
						gint v = *((gint*) optval);
						socket_setOutputBufferSize((Socket*)descriptor, (gsize)v*2);
					}
					break;
				}

				case SO_RCVBUF: {
					if(optlen < sizeof(gint)) {
						warning("called setsockopt with SO_RCVBUF with optlen < %i", (gint)(sizeof(gint)));
						errno = EINVAL;
						result = -1;
					} else if (t != DT_TCPSOCKET && t != DT_UDPSOCKET) {
						warning("called setsockopt with SO_RCVBUF on non-socket");
						errno = ENOPROTOOPT;
						result = -1;
					} else {
						gint v = *((gint*) optval);
						socket_setInputBufferSize((Socket*)descriptor, (gsize)v*2);
					}
					break;
				}

				case SO_REUSEADDR: {
					// TODO implement this!
					// XXX Tor actually uses this option!!
					debug("setsockopt SO_REUSEADDR not yet implemented");
					break;
				}

				default: {
					warning("setsockopt optname %i not implemented", optname);
					errno = ENOSYS;
					result = -1;
					break;
				}
			}
		} else {
			warning("setsockopt level %i not implemented", level);
			errno = ENOSYS;
			result = -1;
		}
	} else {
		errno = EBADF;
		result = -1;
	}

	_system_switchOutShadowContext(node);
	return result;
}
Beispiel #28
0
static gint _system_addressHelper(gint fd, const struct sockaddr* addr, socklen_t* len,
		enum SystemCallType type) {
	/* check if this is a virtual socket */
	if(fd < MIN_DESCRIPTOR){
		warning("intercepted a non-virtual descriptor");
		errno = EBADF;
		return -1;
	}

	/* check for proper addr */
	if(addr == NULL) {
		errno = EFAULT;
		return -1;
	}

	if(len == NULL || *len < sizeof(struct sockaddr_in)) {
		errno = EINVAL;
		return -1;
	}

	struct sockaddr_in* saddr = (struct sockaddr_in*) addr;
	in_addr_t ip = saddr->sin_addr.s_addr;
	in_port_t port = saddr->sin_port;
	sa_family_t family = saddr->sin_family;

	/* direct to node for further checks */
	Node* node = _system_switchInShadowContext();

	gint result = EINVAL;
	switch(type) {
		case SCT_BIND: {
			result = node_bindToInterface(node, fd, ip, port);
			break;
		}

		case SCT_CONNECT: {
			result = node_connectToPeer(node, fd, ip, port, family);
			break;
		}

		case SCT_GETPEERNAME:
		case SCT_GETSOCKNAME: {
			result = type == SCT_GETPEERNAME ?
					node_getPeerName(node, fd, &(saddr->sin_addr.s_addr), &(saddr->sin_port)) :
					node_getSocketName(node, fd, &(saddr->sin_addr.s_addr), &(saddr->sin_port));

			if(result == 0) {
				saddr->sin_family = AF_INET;
				*len = sizeof(struct sockaddr_in);
			}

			break;
		}

		default: {
			error("unrecognized system call type");
			break;
		}
	}

	_system_switchOutShadowContext(node);

	/* check if there was an error */
	if(result != 0) {
		errno = result;
		return -1;
	}

	return 0;
}