Index: uspace/srv/net/tcp/sock.c
===================================================================
--- uspace/srv/net/tcp/sock.c	(revision 257feec9d30b7aa8ced34c0ef045309a9cc98d3c)
+++ uspace/srv/net/tcp/sock.c	(revision 98abd409db889cb4a1e3a865f6034f5a68f66184)
@@ -354,33 +354,36 @@
 }
 
-static void tcp_sock_connect(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int rc;
-	struct sockaddr_in *addr;
-	int socket_id;
+static void tcp_sock_connect(tcp_client_t *client, ipc_callid_t callid,
+    ipc_call_t call)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connect()");
+	
+	struct sockaddr_in6 *addr6 = NULL;
 	size_t addr_len;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connect()");
-
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
-	if (rc != EOK || addr_len != sizeof(struct sockaddr_in)) {
+	int rc = async_data_write_accept((void **) &addr6, false, 0, 0, 0, &addr_len);
+	if (rc != EOK) {
 		async_answer_0(callid, rc);
 		return;
 	}
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
+	
+	if ((addr_len != sizeof(struct sockaddr_in)) &&
+	    (addr_len != sizeof(struct sockaddr_in6))) {
+		async_answer_0(callid, EINVAL);
+		goto out;
+	}
+	
+	struct sockaddr_in *addr = (struct sockaddr_in *) addr6;
+	
+	int socket_id = SOCKET_GET_SOCKET_ID(call);
+	socket_core_t *sock_core = socket_cores_find(&client->sockets,
+	    socket_id);
 	if (sock_core == NULL) {
 		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
+		goto out;
+	}
+	
+	tcp_sockdata_t *socket =
+	    (tcp_sockdata_t *) sock_core->specific_data;
+	
 	if (sock_core->port <= 0) {
 		rc = socket_bind_free_port(&gsock, sock_core,
@@ -389,12 +392,12 @@
 		if (rc != EOK) {
 			async_answer_0(callid, rc);
-			return;
+			goto out;
 		}
 		
 		last_used_port = sock_core->port;
 	}
-
+	
 	fibril_mutex_lock(&socket->lock);
-
+	
 	if (inet_addr_is_any(&socket->laddr)) {
 		/* Determine local IP address */
@@ -402,6 +405,17 @@
 		inet_addr_t rem_addr;
 		
-		inet_addr_unpack(uint32_t_be2host(addr->sin_addr.s_addr),
-		    &rem_addr);
+		switch (addr->sin_family) {
+		case AF_INET:
+			inet_sockaddr_in_addr(addr, &rem_addr);
+			break;
+		case AF_INET6:
+			inet_sockaddr_in6_addr(addr6, &rem_addr);
+			break;
+		default:
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			goto out;
+		}
+		
 		rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
 		if (rc != EOK) {
@@ -410,5 +424,5 @@
 			log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connect: Failed to "
 			    "determine local address.");
-			return;
+			goto out;
 		}
 		
@@ -416,16 +430,31 @@
 	}
 	
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+	
 	lsocket.addr = socket->laddr;
 	lsocket.port = sock_core->port;
 	
-	inet_addr_unpack(uint32_t_be2host(addr->sin_addr.s_addr),
-	    &fsocket.addr);
+	switch (addr->sin_family) {
+	case AF_INET:
+		inet_sockaddr_in_addr(addr, &fsocket.addr);
+		break;
+	case AF_INET6:
+		inet_sockaddr_in6_addr(addr6, &fsocket.addr);
+		break;
+	default:
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, EINVAL);
+		goto out;
+	}
+	
 	fsocket.port = uint16_t_be2host(addr->sin_port);
-
-	trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0, &socket->conn);
-
+	
+	tcp_error_t trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0,
+	    &socket->conn);
+	
 	if (socket->conn != NULL)
-		socket->conn->name = (char *)"C";
-
+		socket->conn->name = (char *) "C";
+	
 	fibril_mutex_unlock(&socket->lock);
 	
@@ -445,4 +474,8 @@
 	
 	async_answer_0(callid, rc);
+	
+out:
+	if (addr6 != NULL)
+		free(addr6);
 }
 
@@ -662,28 +695,18 @@
 static void tcp_sock_recvfrom(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	int socket_id;
-	int flags;
-	size_t addr_length, length;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t rcallid;
-	size_t data_len;
-	struct sockaddr_in addr;
-	tcp_sock_t *rsock;
-	int rc;
-
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	flags = SOCKET_GET_FLAGS(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
+	
+	int socket_id = SOCKET_GET_SOCKET_ID(call);
+	
+	socket_core_t *sock_core =
+	    socket_cores_find(&client->sockets, socket_id);
 	if (sock_core == NULL) {
 		async_answer_0(callid, ENOTSOCK);
 		return;
 	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	
+	tcp_sockdata_t *socket =
+	    (tcp_sockdata_t *) sock_core->specific_data;
+	
 	fibril_mutex_lock(&socket->lock);
 	
@@ -693,10 +716,10 @@
 		return;
 	}
-
-	(void)flags;
-
+	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_recvfrom(): lock recv_buffer_lock");
+	
 	fibril_mutex_lock(&socket->recv_buffer_lock);
-	while (socket->recv_buffer_used == 0 && socket->recv_error == TCP_EOK) {
+	while ((socket->recv_buffer_used == 0) &&
+	    (socket->recv_error == TCP_EOK)) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "wait for recv_buffer_cv + recv_buffer_used != 0");
 		fibril_condvar_wait(&socket->recv_buffer_cv,
@@ -705,9 +728,10 @@
 	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "Got data in sock recv_buffer");
-
-	data_len = socket->recv_buffer_used;
-	rc = socket->recv_error;
-
-	switch (socket->recv_error) {
+	
+	size_t data_len = socket->recv_buffer_used;
+	tcp_error_t trc = socket->recv_error;
+	int rc;
+	
+	switch (trc) {
 	case TCP_EOK:
 		rc = EOK;
@@ -732,24 +756,67 @@
 		return;
 	}
-
+	
+	ipc_callid_t rcallid;
+	
 	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
 		/* Fill address */
-		rsock = &socket->conn->ident.foreign;
+		tcp_sock_t *rsock = &socket->conn->ident.foreign;
+		struct sockaddr_in addr;
+		struct sockaddr_in6 addr6;
+		size_t addr_length;
 		
-		uint32_t rsock_addr;
-		int rc = inet_addr_pack(&rsock->addr, &rsock_addr);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->recv_buffer_lock);
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			return;
-		}
+		uint16_t addr_af = inet_addr_sockaddr_in(&rsock->addr, &addr,
+		    &addr6);
 		
-		addr.sin_family = AF_INET;
-		addr.sin_addr.s_addr = host2uint32_t_be(rsock_addr);
-		addr.sin_port = host2uint16_t_be(rsock->port);
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read receive");
-		if (!async_data_read_receive(&rcallid, &addr_length)) {
+		switch (addr_af) {
+		case AF_INET:
+			addr.sin_port = host2uint16_t_be(rsock->port);
+			
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read receive");
+			if (!async_data_read_receive(&rcallid, &addr_length)) {
+				fibril_mutex_unlock(&socket->recv_buffer_lock);
+				fibril_mutex_unlock(&socket->lock);
+				async_answer_0(callid, EINVAL);
+				return;
+			}
+			
+			if (addr_length > sizeof(addr))
+				addr_length = sizeof(addr);
+			
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read finalize");
+			rc = async_data_read_finalize(rcallid, &addr, addr_length);
+			if (rc != EOK) {
+				fibril_mutex_unlock(&socket->recv_buffer_lock);
+				fibril_mutex_unlock(&socket->lock);
+				async_answer_0(callid, EINVAL);
+				return;
+			}
+			
+			break;
+		case AF_INET6:
+			addr6.sin6_port = host2uint16_t_be(rsock->port);
+			
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "addr6 read receive");
+			if (!async_data_read_receive(&rcallid, &addr_length)) {
+				fibril_mutex_unlock(&socket->recv_buffer_lock);
+				fibril_mutex_unlock(&socket->lock);
+				async_answer_0(callid, EINVAL);
+				return;
+			}
+			
+			if (addr_length > sizeof(addr6))
+				addr_length = sizeof(addr6);
+			
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "addr6 read finalize");
+			rc = async_data_read_finalize(rcallid, &addr6, addr_length);
+			if (rc != EOK) {
+				fibril_mutex_unlock(&socket->recv_buffer_lock);
+				fibril_mutex_unlock(&socket->lock);
+				async_answer_0(callid, EINVAL);
+				return;
+			}
+			
+			break;
+		default:
 			fibril_mutex_unlock(&socket->recv_buffer_lock);
 			fibril_mutex_unlock(&socket->lock);
@@ -757,19 +824,9 @@
 			return;
 		}
-
-		if (addr_length > sizeof(addr))
-			addr_length = sizeof(addr);
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read finalize");
-		rc = async_data_read_finalize(rcallid, &addr, addr_length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->recv_buffer_lock);
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
 	}
 	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "data read receive");
+	
+	size_t length;
 	if (!async_data_read_receive(&rcallid, &length)) {
 		fibril_mutex_unlock(&socket->recv_buffer_lock);
@@ -783,9 +840,12 @@
 	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "data read finalize");
+	
 	rc = async_data_read_finalize(rcallid, socket->recv_buffer, length);
 	
 	socket->recv_buffer_used -= length;
+	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_recvfrom: %zu left in buffer",
 	    socket->recv_buffer_used);
+	
 	if (socket->recv_buffer_used > 0) {
 		memmove(socket->recv_buffer, socket->recv_buffer + length,
@@ -795,8 +855,10 @@
 	
 	fibril_condvar_broadcast(&socket->recv_buffer_cv);
-
-	if (length < data_len && rc == EOK)
+	
+	if ((length < data_len) && (rc == EOK))
 		rc = EOVERFLOW;
-
+	
+	ipc_call_t answer;
+	
 	SOCKET_SET_READ_DATA_LENGTH(answer, length);
 	async_answer_1(callid, EOK, IPC_GET_ARG1(answer));
