Index: uspace/app/nettest1/nettest1.c
===================================================================
--- uspace/app/nettest1/nettest1.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/app/nettest1/nettest1.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -59,16 +59,16 @@
 #define NETTEST1_TEXT  "Networking test 1 - sockets"
 
-static int family = PF_INET;
+static uint16_t family = AF_INET;
 static sock_type_t type = SOCK_DGRAM;
-static char *data;
 static size_t size = 27;
-static int verbose = 0;
+static bool verbose = false;
+static int sockets = 10;
+static int messages = 10;
+static uint16_t port = 7;
 
 static struct sockaddr *address;
 static socklen_t addrlen;
 
-static int sockets;
-static int messages;
-static uint16_t port;
+static char *data;
 
 static void nettest1_print_help(void)
@@ -299,25 +299,13 @@
 int main(int argc, char *argv[])
 {
-	struct sockaddr_in address_in;
-	struct sockaddr_in6 address_in6;
-	dnsr_hostinfo_t *hinfo;
-	uint8_t *address_start;
-
-	int *socket_ids;
-	int index;
-	struct timeval time_before;
-	struct timeval time_after;
-
-	int rc;
-
-	sockets = 10;
-	messages = 10;
-	port = 7;
-
 	/*
 	 * Parse the command line arguments. Stop before the last argument
 	 * if it does not start with dash ('-')
 	 */
-	for (index = 1; (index < argc - 1) || ((index == argc - 1) && (argv[index][0] == '-')); index++) {
+	int index;
+	int rc;
+	
+	for (index = 1; (index < argc - 1) || ((index == argc - 1) &&
+	    (argv[index][0] == '-')); index++) {
 		/* Options should start with dash ('-') */
 		if (argv[index][0] == '-') {
@@ -331,48 +319,55 @@
 	}
 	
-	/* If not before the last argument containing the host */
+	/* The last argument containing the host */
 	if (index >= argc) {
-		printf("Command line error: missing host name\n");
+		printf("Host name missing.\n");
 		nettest1_print_help();
 		return EINVAL;
 	}
-
+	
+	char *addr_s = argv[argc - 1];
+	
+	/* Interpret as address */
+	inet_addr_t addr_addr;
+	rc = inet_addr_parse(addr_s, &addr_addr);
+	
+	if (rc != EOK) {
+		/* Interpret as a host name */
+		dnsr_hostinfo_t *hinfo = NULL;
+		rc = dnsr_name2host(addr_s, &hinfo);
+		
+		if (rc != EOK) {
+			printf("Error resolving host '%s'.\n", addr_s);
+			return EINVAL;
+		}
+		
+		addr_addr = hinfo->addr;
+	}
+	
+	struct sockaddr_in addr;
+	struct sockaddr_in6 addr6;
+	uint16_t af = inet_addr_sockaddr_in(&addr_addr, &addr, &addr6);
+	
+	if (af != family) {
+		printf("Address family does not match explicitly set family.\n");
+		return EINVAL;
+	}
+	
 	/* Prepare the address buffer */
-
-	switch (family) {
-	case PF_INET:
-		address_in.sin_family = AF_INET;
-		address_in.sin_port = htons(port);
-		address = (struct sockaddr *) &address_in;
-		addrlen = sizeof(address_in);
-		address_start = (uint8_t *) &address_in.sin_addr.s_addr;
-		break;
-	case PF_INET6:
-		address_in6.sin6_family = AF_INET6;
-		address_in6.sin6_port = htons(port);
-		address = (struct sockaddr *) &address_in6;
-		addrlen = sizeof(address_in6);
-		address_start = (uint8_t *) &address_in6.sin6_addr.s6_addr;
+	
+	switch (af) {
+	case AF_INET:
+		addr.sin_port = htons(port);
+		address = (struct sockaddr *) &addr;
+		addrlen = sizeof(addr);
+		break;
+	case AF_INET6:
+		addr6.sin6_port = htons(port);
+		address = (struct sockaddr *) &addr6;
+		addrlen = sizeof(addr6);
 		break;
 	default:
 		fprintf(stderr, "Address family is not supported\n");
 		return EAFNOSUPPORT;
-	}
-
-	/* Parse the last argument which should contain the host/address */
-	rc = inet_pton(family, argv[argc - 1], address_start);
-	if (rc != EOK) {
-		/* Try interpreting as a host name */
-		rc = dnsr_name2host(argv[argc - 1], &hinfo);
-		if (rc != EOK) {
-			printf("Error resolving host '%s'.\n", argv[argc - 1]);
-			return rc;
-		}
-		
-		rc = inet_addr_sockaddr_in(&hinfo->addr, &address_in);
-		if (rc != EOK) {
-			printf("Host '%s' not resolved as IPv4 address.\n", argv[argc - 1]);
-			return rc;
-		}
 	}
 	
@@ -406,5 +401,5 @@
 	 * null (\0).
 	 */
-	socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
+	int *socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
 	if (!socket_ids) {
 		fprintf(stderr, "Failed to allocate receive buffer.\n");
@@ -417,4 +412,5 @@
 		printf("Starting tests\n");
 	
+	struct timeval time_before;
 	rc = gettimeofday(&time_before, NULL);
 	if (rc != EOK) {
@@ -428,4 +424,5 @@
 	nettest1_test(socket_ids, sockets, messages);
 	
+	struct timeval time_after;
 	rc = gettimeofday(&time_after, NULL);
 	if (rc != EOK) {
Index: uspace/app/nettest2/nettest2.c
===================================================================
--- uspace/app/nettest2/nettest2.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/app/nettest2/nettest2.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -60,11 +60,11 @@
 #define NETTEST2_TEXT  "Networking test 2 - transfer"
 
-static size_t size;
-static bool verbose;
-static sock_type_t type;
-static int sockets;
-static int messages;
-static int family;
-static uint16_t port;
+static uint16_t family = PF_INET;
+static size_t size = 28;
+static bool verbose = false;
+static sock_type_t type = SOCK_DGRAM;
+static int sockets = 10;
+static int messages = 10;
+static uint16_t port = 7;
 
 static void nettest2_print_help(void)
@@ -234,27 +234,7 @@
 int main(int argc, char *argv[])
 {
-	struct sockaddr *address;
-	struct sockaddr_in address_in;
-	struct sockaddr_in6 address_in6;
-	dnsr_hostinfo_t *hinfo;
-	socklen_t addrlen;
-	uint8_t *address_start;
-
-	int *socket_ids;
-	char *data;
 	int index;
-	struct timeval time_before;
-	struct timeval time_after;
-
 	int rc;
-
-	size = 28;
-	verbose = false;
-	type = SOCK_DGRAM;
-	sockets = 10;
-	messages = 10;
-	family = PF_INET;
-	port = 7;
-
+	
 	/*
 	 * Parse the command line arguments.
@@ -264,5 +244,4 @@
 	for (index = 1; (index < argc - 1) || ((index == argc - 1) &&
 	    (argv[index][0] == '-')); ++index) {
-
 		/* Options should start with dash ('-') */
 		if (argv[index][0] == '-') {
@@ -276,48 +255,58 @@
 	}
 	
-	/* If not before the last argument containing the host */
+	/* The last argument containing the host */
 	if (index >= argc) {
-		printf("Command line error: missing host name\n");
+		printf("Host name missing.\n");
 		nettest2_print_help();
 		return EINVAL;
 	}
-
+	
+	char *addr_s = argv[argc - 1];
+	
+	/* Interpret as address */
+	inet_addr_t addr_addr;
+	rc = inet_addr_parse(addr_s, &addr_addr);
+	
+	if (rc != EOK) {
+		/* Interpret as a host name */
+		dnsr_hostinfo_t *hinfo = NULL;
+		rc = dnsr_name2host(addr_s, &hinfo);
+		
+		if (rc != EOK) {
+			printf("Error resolving host '%s'.\n", addr_s);
+			return EINVAL;
+		}
+		
+		addr_addr = hinfo->addr;
+	}
+	
+	struct sockaddr_in addr;
+	struct sockaddr_in6 addr6;
+	uint16_t af = inet_addr_sockaddr_in(&addr_addr, &addr, &addr6);
+	
+	if (af != family) {
+		printf("Address family does not match explicitly set family.\n");
+		return EINVAL;
+	}
+	
 	/* Prepare the address buffer */
-
-	switch (family) {
-	case PF_INET:
-		address_in.sin_family = AF_INET;
-		address_in.sin_port = htons(port);
-		address = (struct sockaddr *) &address_in;
-		addrlen = sizeof(address_in);
-		address_start = (uint8_t *) &address_in.sin_addr.s_addr;
-		break;
-	case PF_INET6:
-		address_in6.sin6_family = AF_INET6;
-		address_in6.sin6_port = htons(port);
-		address = (struct sockaddr *) &address_in6;
-		addrlen = sizeof(address_in6);
-		address_start = (uint8_t *) &address_in6.sin6_addr.s6_addr;
+	
+	struct sockaddr *address;
+	socklen_t addrlen;
+	
+	switch (af) {
+	case AF_INET:
+		addr.sin_port = htons(port);
+		address = (struct sockaddr *) &addr;
+		addrlen = sizeof(addr);
+		break;
+	case AF_INET6:
+		addr6.sin6_port = htons(port);
+		address = (struct sockaddr *) &addr6;
+		addrlen = sizeof(addr6);
 		break;
 	default:
 		fprintf(stderr, "Address family is not supported\n");
 		return EAFNOSUPPORT;
-	}
-
-	/* Parse the last argument which should contain the host/address */
-	rc = inet_pton(family, argv[argc - 1], address_start);
-	if (rc != EOK) {
-		/* Try interpreting as a host name */
-		rc = dnsr_name2host(argv[argc - 1], &hinfo);
-		if (rc != EOK) {
-			printf("Error resolving host '%s'.\n", argv[argc - 1]);
-			return rc;
-		}
-		
-		rc = inet_addr_sockaddr_in(&hinfo->addr, &address_in);
-		if (rc != EOK) {
-			printf("Host '%s' not resolved as IPv4 address.\n", argv[argc - 1]);
-			return rc;
-		}
 	}
 	
@@ -333,5 +322,5 @@
 	 * null character.
 	 */
-	data = (char *) malloc(size + 1);
+	char *data = (char *) malloc(size + 1);
 	if (!data) {
 		fprintf(stderr, "Failed to allocate data buffer.\n");
@@ -353,9 +342,10 @@
 	 * Allocate count entries plus the terminating null (\0)
 	 */
-	socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
+	int *socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
 	if (!socket_ids) {
 		fprintf(stderr, "Failed to allocate receive buffer.\n");
 		return ENOMEM;
 	}
+	
 	socket_ids[sockets] = 0;
 	
@@ -377,4 +367,5 @@
 		printf("\n");
 	
+	struct timeval time_before;
 	rc = gettimeofday(&time_before, NULL);
 	if (rc != EOK) {
@@ -388,4 +379,5 @@
 		return rc;
 	
+	struct timeval time_after;
 	rc = gettimeofday(&time_after, NULL);
 	if (rc != EOK) {
Index: uspace/app/nettest3/nettest3.c
===================================================================
--- uspace/app/nettest3/nettest3.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/app/nettest3/nettest3.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -84,6 +84,6 @@
 			}
 			
-			rc = inet_addr_sockaddr_in(&hinfo->addr, &addr);
-			if (rc != EOK) {
+			uint16_t af = inet_addr_sockaddr_in(&hinfo->addr, &addr, NULL);
+			if (af != AF_INET) {
 				printf("Host '%s' not resolved as IPv4 address.\n", argv[1]);
 				return rc;
Index: uspace/app/nterm/conn.c
===================================================================
--- uspace/app/nterm/conn.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/app/nterm/conn.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -75,15 +75,15 @@
 int conn_open(const char *addr_s, const char *port_s)
 {
-	struct sockaddr_in addr;
-	dnsr_hostinfo_t *hinfo = NULL;
-	int rc;
-	char *endptr;
-
-	addr.sin_family = AF_INET;
-
-	rc = inet_pton(addr.sin_family, addr_s, (uint8_t *)&addr.sin_addr);
+	int conn_fd = -1;
+	
+	/* Interpret as address */
+	inet_addr_t addr_addr;
+	int rc = inet_addr_parse(addr_s, &addr_addr);
+	
 	if (rc != EOK) {
-		/* Try interpreting as a host name */
+		/* Interpret as a host name */
+		dnsr_hostinfo_t *hinfo = NULL;
 		rc = dnsr_name2host(addr_s, &hinfo);
+		
 		if (rc != EOK) {
 			printf("Error resolving host '%s'.\n", addr_s);
@@ -91,12 +91,13 @@
 		}
 		
-		rc = inet_addr_sockaddr_in(&hinfo->addr, &addr);
-		if (rc != EOK) {
-			printf("Host '%s' not resolved as IPv4 address.\n", addr_s);
-			return rc;
-		}
+		addr_addr = hinfo->addr;
 	}
-
-	addr.sin_port = htons(strtol(port_s, &endptr, 10));
+	
+	struct sockaddr_in addr;
+	struct sockaddr_in6 addr6;
+	uint16_t af = inet_addr_sockaddr_in(&addr_addr, &addr, &addr6);
+	
+	char *endptr;
+	uint16_t port = strtol(port_s, &endptr, 10);
 	if (*endptr != '\0') {
 		printf("Invalid port number %s\n", port_s);
@@ -104,11 +105,24 @@
 	}
 	
+	printf("Connecting to host %s port %u\n", addr_s, port);
+	
 	conn_fd = socket(PF_INET, SOCK_STREAM, 0);
 	if (conn_fd < 0)
 		goto error;
 	
-	printf("Connecting to host %s port %u\n", addr_s, ntohs(addr.sin_port));
+	switch (af) {
+	case AF_INET:
+		addr.sin_port = htons(port);
+		rc = connect(conn_fd, (struct sockaddr *) &addr, sizeof(addr));
+		break;
+	case AF_INET6:
+		addr6.sin6_port = htons(port);
+		rc = connect(conn_fd, (struct sockaddr *) &addr6, sizeof(addr6));
+		break;
+	default:
+		printf("Unknown address family.\n");
+		goto error;
+	}
 	
-	rc = connect(conn_fd, (struct sockaddr *)&addr, sizeof(addr));
 	if (rc != EOK)
 		goto error;
Index: uspace/app/ping/ping.c
===================================================================
--- uspace/app/ping/ping.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/app/ping/ping.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -37,4 +37,5 @@
 #include <errno.h>
 #include <fibril_synch.h>
+#include <net/socket_codes.h>
 #include <inet/dnsr.h>
 #include <inet/addr.h>
@@ -63,6 +64,6 @@
 };
 
-static uint32_t src;
-static uint32_t dest;
+static addr32_t src;
+static addr32_t dest;
 
 static bool ping_repeat = false;
@@ -84,8 +85,8 @@
 {
 	inet_addr_t src_addr;
-	inet_addr_unpack(sdu->src, &src_addr);
+	inet_addr_set(sdu->src, &src_addr);
 	
 	inet_addr_t dest_addr;
-	inet_addr_unpack(sdu->dest, &dest_addr);
+	inet_addr_set(sdu->dest, &dest_addr);
 	
 	char *asrc;
@@ -220,6 +221,6 @@
 	}
 	
-	rc = inet_addr_pack(&dest_addr, &dest);
-	if (rc != EOK) {
+	uint16_t af = inet_addr_get(&dest_addr, &dest, NULL);
+	if (af != AF_INET) {
 		printf(NAME ": Destination '%s' is not an IPv4 address.\n",
 		    argv[argi]);
@@ -235,5 +236,5 @@
 	
 	inet_addr_t src_addr;
-	inet_addr_unpack(src, &src_addr);
+	inet_addr_set(src, &src_addr);
 	
 	rc = inet_addr_format(&src_addr, &asrc);
Index: uspace/lib/c/generic/dnsr.c
===================================================================
--- uspace/lib/c/generic/dnsr.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/generic/dnsr.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -69,45 +69,61 @@
 int dnsr_name2host(const char *name, dnsr_hostinfo_t **rinfo)
 {
+	dnsr_hostinfo_t *info = calloc(1, sizeof(dnsr_hostinfo_t));
+	if (info == NULL)
+		return ENOMEM;
+	
 	async_exch_t *exch = dnsr_exchange_begin();
-	char cname_buf[DNSR_NAME_MAX_SIZE + 1];
-	ipc_call_t cnreply;
-	size_t act_size;
-	dnsr_hostinfo_t *info;
-
+	
 	ipc_call_t answer;
 	aid_t req = async_send_0(exch, DNSR_NAME2HOST, &answer);
-	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
-	aid_t cnreq = async_data_read(exch, cname_buf, DNSR_NAME_MAX_SIZE,
-	    &cnreply);
-
+	
+	int rc = async_data_write_start(exch, name, str_size(name));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+	
+	ipc_call_t answer_addr;
+	aid_t req_addr = async_data_read(exch, &info->addr,
+	    sizeof(inet_addr_t), &answer_addr);
+	
+	sysarg_t retval_addr;
+	async_wait_for(req_addr, &retval_addr);
+	
+	if (retval_addr != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return (int) retval_addr;
+	}
+	
+	ipc_call_t answer_cname;
+	char cname_buf[DNSR_NAME_MAX_SIZE + 1];
+	aid_t req_cname = async_data_read(exch, cname_buf, DNSR_NAME_MAX_SIZE,
+	    &answer_cname);
+	
 	dnsr_exchange_end(exch);
-
-	if (retval != EOK) {
+	
+	sysarg_t retval_cname;
+	async_wait_for(req_cname, &retval_cname);
+	
+	if (retval_cname != EOK) {
 		async_forget(req);
-		async_forget(cnreq);
-		return retval;
+		return (int) retval_cname;
 	}
-
+	
+	sysarg_t retval;
 	async_wait_for(req, &retval);
-	if (retval != EOK) {
-		async_forget(cnreq);
-		return EIO;
-	}
-
-	async_wait_for(cnreq, &retval);
+	
 	if (retval != EOK)
-		return EIO;
-
-	info = calloc(1, sizeof(dnsr_hostinfo_t));
-	if (info == NULL)
-		return ENOMEM;
-
-	act_size = IPC_GET_ARG2(cnreply);
+		return (int) retval;
+	
+	size_t act_size = IPC_GET_ARG2(answer_cname);
 	assert(act_size <= DNSR_NAME_MAX_SIZE);
+	
 	cname_buf[act_size] = '\0';
-
+	
 	info->cname = str_dup(cname_buf);
-	inet_addr_unpack(IPC_GET_ARG1(answer), &info->addr);
-
+	
 	*rinfo = info;
 	return EOK;
Index: uspace/lib/c/generic/inet.c
===================================================================
--- uspace/lib/c/generic/inet.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/generic/inet.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -30,4 +30,5 @@
 #include <assert.h>
 #include <errno.h>
+#include <net/socket_codes.h>
 #include <inet/inet.h>
 #include <ipc/inet.h>
@@ -107,22 +108,36 @@
 int inet_send(inet_dgram_t *dgram, uint8_t ttl, inet_df_t df)
 {
-	uint32_t src;
-	int rc = inet_addr_pack(&dgram->src, &src);
-	if (rc != EOK)
-		return rc;
-	
-	uint32_t dest;
-	rc = inet_addr_pack(&dgram->dest, &dest);
-	if (rc != EOK)
-		return EOK;
-	
-	async_exch_t *exch = async_exchange_begin(inet_sess);
-	
+	addr32_t src_v4;
+	addr128_t src_v6;
+	uint16_t src_af = inet_addr_get(&dgram->src, &src_v4, &src_v6);
+	
+	addr32_t dest_v4;
+	addr128_t dest_v6;
+	uint16_t dest_af = inet_addr_get(&dgram->dest, &dest_v4, &dest_v6);
+	
+	if (src_af != dest_af)
+		return EINVAL;
+	
+	async_exch_t *exch;
 	ipc_call_t answer;
-	aid_t req = async_send_5(exch, INET_SEND, (sysarg_t) src,
-	    (sysarg_t) dest, dgram->tos, ttl, df, &answer);
-	rc = async_data_write_start(exch, dgram->data, dgram->size);
-	
-	async_exchange_end(exch);
+	aid_t req;
+	int rc;
+	
+	switch (src_af) {
+	case AF_INET:
+		exch = async_exchange_begin(inet_sess);
+		
+		req = async_send_5(exch, INET_SEND, (sysarg_t) src_v4,
+		    (sysarg_t) dest_v4, dgram->tos, ttl, df, &answer);
+		rc = async_data_write_start(exch, dgram->data, dgram->size);
+		
+		async_exchange_end(exch);
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		return ENOTSUP;
+	default:
+		return EINVAL;
+	}
 	
 	if (rc != EOK) {
@@ -133,49 +148,94 @@
 	sysarg_t retval;
 	async_wait_for(req, &retval);
-	if (retval != EOK)
-		return retval;
-	
-	return EOK;
+	
+	return (int) retval;
 }
 
 int inet_get_srcaddr(inet_addr_t *remote, uint8_t tos, inet_addr_t *local)
 {
-	uint32_t remote_addr;
-	int rc = inet_addr_pack(remote, &remote_addr);
-	if (rc != EOK)
-		return rc;
-	
-	async_exch_t *exch = async_exchange_begin(inet_sess);
-	
-	sysarg_t local_addr;
-	rc = async_req_2_1(exch, INET_GET_SRCADDR, (sysarg_t) remote_addr,
-	    tos, &local_addr);
-	
-	async_exchange_end(exch);
-	
-	if (rc != EOK)
-		return rc;
-	
-	inet_addr_unpack(local_addr, local);
-	return EOK;
-}
-
-static void inet_ev_recv(ipc_callid_t callid, ipc_call_t *call)
-{
+	addr32_t remote_v4;
+	addr128_t remote_v6;
+	uint16_t remote_af = inet_addr_get(remote, &remote_v4, &remote_v6);
+	
+	async_exch_t *exch;
 	int rc;
+	
+	switch (remote_af) {
+	case AF_INET:
+		exch = async_exchange_begin(inet_sess);
+		
+		sysarg_t local_v4;
+		rc = async_req_2_1(exch, INET_GET_SRCADDR, (sysarg_t) remote_v4,
+		    tos, &local_v4);
+		
+		async_exchange_end(exch);
+		
+		if (rc != EOK)
+			return rc;
+		
+		inet_addr_set(local_v4, local);
+		return EOK;
+	case AF_INET6:
+		// FIXME TODO
+		return ENOTSUP;
+	default:
+		return EINVAL;
+	}
+}
+
+static void inet_ev_recv(ipc_callid_t iid, ipc_call_t *icall)
+{
 	inet_dgram_t dgram;
 	
-	inet_addr_unpack(IPC_GET_ARG1(*call), &dgram.src);
-	inet_addr_unpack(IPC_GET_ARG2(*call), &dgram.dest);
-	dgram.tos = IPC_GET_ARG3(*call);
+	dgram.tos = IPC_GET_ARG1(*icall);
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	int rc = async_data_write_finalize(callid, &dgram.src, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	rc = async_data_write_finalize(callid, &dgram.dest, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
 	
 	rc = async_data_write_accept(&dgram.data, false, 0, 0, 0, &dgram.size);
 	if (rc != EOK) {
-		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
 	
 	rc = inet_ev_ops->recv(&dgram);
-	async_answer_0(callid, rc);
+	async_answer_0(iid, rc);
 }
 
Index: uspace/lib/c/generic/inet/addr.c
===================================================================
--- uspace/lib/c/generic/inet/addr.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/generic/inet/addr.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -39,14 +39,145 @@
 #include <net/inet.h>
 #include <stdio.h>
-
-static inet_addr_t inet_addr_any_addr = {
+#include <malloc.h>
+#include <bitops.h>
+
+#define INET_PREFIXSTRSIZE  5
+
+#if !(defined(__BE__) ^ defined(__LE__))
+	#error The architecture must be either big-endian or little-endian.
+#endif
+
+const addr48_t addr48_broadcast = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static const inet_addr_t inet_addr_any_addr = {
 	.family = AF_INET,
-	.addr = {0, 0, 0, 0}
+	.addr = 0
 };
 
-static inet_addr_t inet_addr_any_addr6 = {
+static const inet_addr_t inet_addr_any_addr6 = {
 	.family = AF_INET6,
-	.addr = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	.addr6 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 };
+
+void addr48(const addr48_t src, addr48_t dst)
+{
+	memcpy(dst, src, 6);
+}
+
+void addr128(const addr128_t src, addr128_t dst)
+{
+	memcpy(dst, src, 16);
+}
+
+void host2addr128_t_be(const addr128_t host, addr128_t be)
+{
+#ifdef __BE__
+	memcpy(be, host, 16);
+#else
+	be[0] = host[15];
+	be[1] = host[14];
+	be[2] = host[13];
+	be[3] = host[12];
+	be[4] = host[11];
+	be[5] = host[10];
+	be[6] = host[9];
+	be[7] = host[8];
+	be[8] = host[7];
+	be[9] = host[6];
+	be[10] = host[5];
+	be[11] = host[4];
+	be[12] = host[3];
+	be[13] = host[2];
+	be[14] = host[1];
+	be[15] = host[0];
+#endif
+}
+
+void addr128_t_be2host(const addr128_t be, addr128_t host)
+{
+#ifdef __BE__
+	memcpy(host, be, 16);
+#else
+	host[0] = be[15];
+	host[1] = be[14];
+	host[2] = be[13];
+	host[3] = be[12];
+	host[4] = be[11];
+	host[5] = be[10];
+	host[6] = be[9];
+	host[7] = be[8];
+	host[8] = be[7];
+	host[9] = be[6];
+	host[10] = be[5];
+	host[11] = be[4];
+	host[12] = be[3];
+	host[13] = be[2];
+	host[14] = be[1];
+	host[15] = be[0];
+#endif
+}
+
+void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
+{
+	addr->family = AF_INET;
+	addr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
+	    ((addr32_t) c << 8) | ((addr32_t) d);
+}
+
+void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+    uint8_t prefix)
+{
+	naddr->family = AF_INET;
+	naddr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
+	    ((addr32_t) c << 8) | ((addr32_t) d);
+	naddr->prefix = prefix;
+}
+
+void inet_addr6(inet_addr_t *addr, uint16_t a, uint16_t b, uint16_t c,
+    uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h)
+{
+	addr->family = AF_INET6;
+	addr->addr6[0] = (a >> 8) & 0xff;
+	addr->addr6[1] = a & 0xff;
+	addr->addr6[2] = (b >> 8) & 0xff;
+	addr->addr6[3] = b & 0xff;
+	addr->addr6[4] = (c >> 8) & 0xff;
+	addr->addr6[5] = c & 0xff;
+	addr->addr6[6] = (d >> 8) & 0xff;
+	addr->addr6[7] = d & 0xff;
+	addr->addr6[8] = (e >> 8) & 0xff;
+	addr->addr6[9] = e & 0xff;
+	addr->addr6[10] = (f >> 8) & 0xff;
+	addr->addr6[11] = f & 0xff;
+	addr->addr6[12] = (g >> 8) & 0xff;
+	addr->addr6[13] = g & 0xff;
+	addr->addr6[14] = (h >> 8) & 0xff;
+	addr->addr6[15] = h & 0xff;
+}
+
+void inet_naddr6(inet_naddr_t *naddr, uint16_t a, uint16_t b, uint16_t c,
+    uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h, uint8_t prefix)
+{
+	naddr->family = AF_INET6;
+	naddr->addr6[0] = (a >> 8) & 0xff;
+	naddr->addr6[1] = a & 0xff;
+	naddr->addr6[2] = (b >> 8) & 0xff;
+	naddr->addr6[3] = b & 0xff;
+	naddr->addr6[4] = (c >> 8) & 0xff;
+	naddr->addr6[5] = c & 0xff;
+	naddr->addr6[6] = (d >> 8) & 0xff;
+	naddr->addr6[7] = d & 0xff;
+	naddr->addr6[8] = (e >> 8) & 0xff;
+	naddr->addr6[9] = e & 0xff;
+	naddr->addr6[10] = (f >> 8) & 0xff;
+	naddr->addr6[11] = f & 0xff;
+	naddr->addr6[12] = (g >> 8) & 0xff;
+	naddr->addr6[13] = g & 0xff;
+	naddr->addr6[14] = (h >> 8) & 0xff;
+	naddr->addr6[15] = h & 0xff;
+	naddr->prefix = prefix;
+}
 
 /** Parse network address family.
@@ -72,6 +203,90 @@
 	}
 	
-	*af = AF_NONE;
 	return EINVAL;
+}
+
+void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr)
+{
+	addr->family = naddr->family;
+	memcpy(addr->addr6, naddr->addr6, 16);
+}
+
+void inet_addr_any(inet_addr_t *addr)
+{
+	addr->family = AF_NONE;
+	memset(addr->addr6, 0, 16);
+}
+
+void inet_naddr_any(inet_naddr_t *naddr)
+{
+	naddr->family = AF_NONE;
+	memset(naddr->addr6, 0, 16);
+	naddr->prefix = 0;
+}
+
+int inet_addr_compare(const inet_addr_t *a, const inet_addr_t *b)
+{
+	if (a->family != b->family)
+		return 0;
+	
+	switch (a->family) {
+	case AF_INET:
+		return (a->addr == b->addr);
+	case AF_INET6:
+		return memcmp(&a->addr6, &b->addr6, 16);
+	default:
+		return 0;
+	}
+}
+
+int inet_addr_is_any(const inet_addr_t *addr)
+{
+	return ((addr->family == 0) ||
+	    (inet_addr_compare(addr, &inet_addr_any_addr)) ||
+	    (inet_addr_compare(addr, &inet_addr_any_addr6)));
+}
+
+int inet_naddr_compare_mask(const inet_naddr_t *naddr, const inet_addr_t *addr)
+{
+	if (naddr->family != addr->family)
+		return 0;
+	
+	switch (naddr->family) {
+	case AF_INET:
+		if (naddr->prefix > 32)
+			return 0;
+		
+		addr32_t mask =
+		    BIT_RANGE(addr32_t, 31, 31 - (naddr->prefix - 1));
+		return ((naddr->addr & mask) == (addr->addr & mask));
+	case AF_INET6:
+		if (naddr->prefix > 128)
+			return 0;
+		
+		size_t pos = 0;
+		for (size_t i = 0; i < 16; i++) {
+			/* Further bits do not matter */
+			if (naddr->prefix < pos)
+				break;
+			
+			if (naddr->prefix - pos > 8) {
+				/* Comparison without masking */
+				if (naddr->addr6[i] != addr->addr6[i])
+					return 0;
+			} else {
+				/* Comparison with masking */
+				uint8_t mask =
+				    BIT_RANGE(uint8_t, 8, 8 - (naddr->prefix - pos - 1));
+				if ((naddr->addr6[i] & mask) != (addr->addr6[i] & mask))
+					return 0;
+			}
+			
+			pos += 8;
+		}
+		
+		return 1;
+	default:
+		return 0;
+	}
 }
 
@@ -90,7 +305,20 @@
 		return rc;
 	
-	rc = inet_pton(addr->family, text, addr->addr);
+	uint8_t buf[16];
+	rc = inet_pton(addr->family, text, buf);
 	if (rc != EOK)
 		return rc;
+	
+	switch (addr->family) {
+	case AF_INET:
+		addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
+		    buf[3];
+		break;
+	case AF_INET6:
+		memcpy(addr->addr6, buf, 16);
+		break;
+	default:
+		return EINVAL;
+	}
 	
 	return EOK;
@@ -117,5 +345,6 @@
 		return rc;
 	
-	rc = inet_pton(naddr->family, text, naddr->addr);
+	uint8_t buf[16];
+	rc = inet_pton(naddr->family, text, buf);
 	*slash = '/';
 	
@@ -124,15 +353,25 @@
 	
 	slash++;
+	uint8_t prefix;
 	
 	switch (naddr->family) {
 	case AF_INET:
-		naddr->prefix = strtoul(slash, &slash, 10);
-		if (naddr->prefix > 32)
+		prefix = strtoul(slash, &slash, 10);
+		if (prefix > 32)
 			return EINVAL;
-		break;
-	case AF_INET6:
-		naddr->prefix = strtoul(slash, &slash, 10);
-		if (naddr->prefix > 128)
+		
+		naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
+		    buf[3];
+		naddr->prefix = prefix;
+		
+		break;
+	case AF_INET6:
+		prefix = strtoul(slash, &slash, 10);
+		if (prefix > 128)
 			return EINVAL;
+		
+		memcpy(naddr->addr6, buf, 16);
+		naddr->prefix = prefix;
+		
 		break;
 	default:
@@ -153,7 +392,7 @@
  *
  */
-int inet_addr_format(inet_addr_t *addr, char **bufp)
-{
-	int rc;
+int inet_addr_format(const inet_addr_t *addr, char **bufp)
+{
+	int rc = 0;
 	
 	switch (addr->family) {
@@ -162,10 +401,14 @@
 		break;
 	case AF_INET:
-		rc = asprintf(bufp, "%u.%u.%u.%u", addr->addr[0],
-		    addr->addr[1], addr->addr[2], addr->addr[3]);
-		break;
-	case AF_INET6:
-		// FIXME TODO
-		return ENOTSUP;
+		rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff,
+		    (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff,
+		    addr->addr & 0xff);
+		break;
+	case AF_INET6:
+		*bufp = (char *) malloc(INET6_ADDRSTRLEN);
+		if (*bufp == NULL)
+			return ENOMEM;
+		
+		return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN);
 	default:
 		return ENOTSUP;
@@ -188,7 +431,8 @@
  *
  */
-int inet_naddr_format(inet_naddr_t *naddr, char **bufp)
-{
-	int rc;
+int inet_naddr_format(const inet_naddr_t *naddr, char **bufp)
+{
+	int rc = 0;
+	char prefix[INET_PREFIXSTRSIZE];
 	
 	switch (naddr->family) {
@@ -197,11 +441,31 @@
 		break;
 	case AF_INET:
-		rc = asprintf(bufp, "%u.%u.%u.%u/%u", naddr->addr[0],
-		    naddr->addr[1], naddr->addr[2], naddr->addr[3],
+		rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8
+		    "/%" PRIu8, (naddr->addr >> 24) & 0xff,
+		    (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff,
+		    naddr->addr & 0xff, naddr->prefix);
+		break;
+	case AF_INET6:
+		*bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
+		if (*bufp == NULL)
+			return ENOMEM;
+		
+		rc = inet_ntop(AF_INET6, naddr->addr6, *bufp,
+		    INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
+		if (rc != EOK) {
+			free(*bufp);
+			return rc;
+		}
+		
+		rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8,
 		    naddr->prefix);
-		break;
-	case AF_INET6:
-		// FIXME TODO
-		return ENOTSUP;
+		if (rc < 0) {
+			free(*bufp);
+			return ENOMEM;
+		}
+		
+		str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix);
+		
+		break;
 	default:
 		return ENOTSUP;
@@ -214,141 +478,107 @@
 }
 
-/** Create packed IPv4 address
- *
- * Convert an IPv4 address to a packed 32 bit representation.
- *
- * @param addr   Source address.
- * @param packed Place to store the packed 32 bit representation.
- *
- * @return EOK on success.
- * @return EINVAL if addr is not an IPv4 address.
- *
- */
-int inet_addr_pack(inet_addr_t *addr, uint32_t *packed)
-{
-	if (addr->family != AF_INET)
-		return EINVAL;
-	
-	*packed = (addr->addr[0] << 24) | (addr->addr[1] << 16) |
-	    (addr->addr[2] << 8) | addr->addr[3];
-	return EOK;
-}
-
-/** Create packed IPv4 address
- *
- * Convert an IPv4 address to a packed 32 bit representation.
- *
- * @param naddr  Source address.
- * @param packed Place to store the packed 32 bit representation.
- * @param prefix Place to store the number of valid bits.
- *
- * @return EOK on success.
- * @return EINVAL if addr is not an IPv4 address.
- *
- */
-int inet_naddr_pack(inet_naddr_t *naddr, uint32_t *packed, uint8_t *prefix)
-{
-	if (naddr->family != AF_INET)
-		return EINVAL;
-	
-	*packed = (naddr->addr[0] << 24) | (naddr->addr[1] << 16) |
-	    (naddr->addr[2] << 8) | naddr->addr[3];
-	*prefix = naddr->prefix;
-	
-	return EOK;
-}
-
-void inet_addr_unpack(uint32_t packed, inet_addr_t *addr)
+uint16_t inet_addr_get(const inet_addr_t *addr, addr32_t *v4, addr128_t *v6)
+{
+	switch (addr->family) {
+	case AF_INET:
+		if (v4 != NULL)
+			*v4 = addr->addr;
+		
+		break;
+	case AF_INET6:
+		if (v6 != NULL)
+			memcpy(*v6, addr->addr6, 16);
+		
+		break;
+	}
+	
+	return addr->family;
+}
+
+uint16_t inet_naddr_get(const inet_naddr_t *naddr, addr32_t *v4, addr128_t *v6,
+    uint8_t *prefix)
+{
+	switch (naddr->family) {
+	case AF_INET:
+		if (v4 != NULL)
+			*v4 = naddr->addr;
+		
+		if (prefix != NULL)
+			*prefix = naddr->prefix;
+		
+		break;
+	case AF_INET6:
+		if (v6 != NULL)
+			memcpy(*v6, naddr->addr6, 16);
+		
+		if (prefix != NULL)
+			*prefix = naddr->prefix;
+		
+		break;
+	}
+	
+	return naddr->family;
+}
+
+void inet_addr_set(addr32_t v4, inet_addr_t *addr)
 {
 	addr->family = AF_INET;
-	addr->addr[0] = (packed >> 24) & 0xff;
-	addr->addr[1] = (packed >> 16) & 0xff;
-	addr->addr[2] = (packed >> 8) & 0xff;
-	addr->addr[3] = packed & 0xff;
-}
-
-void inet_naddr_unpack(uint32_t packed, uint8_t prefix, inet_naddr_t *naddr)
+	addr->addr = v4;
+}
+
+void inet_naddr_set(addr32_t v4, uint8_t prefix, inet_naddr_t *naddr)
 {
 	naddr->family = AF_INET;
-	naddr->addr[0] = (packed >> 24) & 0xff;
-	naddr->addr[1] = (packed >> 16) & 0xff;
-	naddr->addr[2] = (packed >> 8) & 0xff;
-	naddr->addr[3] = packed & 0xff;
+	naddr->addr = v4;
 	naddr->prefix = prefix;
 }
 
-int inet_addr_sockaddr_in(inet_addr_t *addr, sockaddr_in_t *sockaddr_in)
-{
-	uint32_t packed;
-	int rc = inet_addr_pack(addr, &packed);
-	if (rc != EOK)
-		return rc;
-	
-	sockaddr_in->sin_family = AF_INET;
-	sockaddr_in->sin_addr.s_addr = host2uint32_t_be(packed);
-	return EOK;
-}
-
-void inet_naddr_addr(inet_naddr_t *naddr, inet_addr_t *addr)
-{
-	addr->family = naddr->family;
-	memcpy(addr->addr, naddr->addr, INET_ADDR_SIZE);
-}
-
-void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
+void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr)
 {
 	addr->family = AF_INET;
-	addr->addr[0] = a;
-	addr->addr[1] = b;
-	addr->addr[2] = c;
-	addr->addr[3] = d;
-}
-
-void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d,
-    uint8_t prefix)
-{
-	naddr->family = AF_INET;
-	naddr->addr[0] = a;
-	naddr->addr[1] = b;
-	naddr->addr[2] = c;
-	naddr->addr[3] = d;
+	addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr);
+}
+
+void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
+{
+	addr->family = AF_INET6;
+	memcpy(addr->addr6, v6, 16);
+}
+
+void inet_naddr_set6(addr128_t v6, uint8_t prefix, inet_naddr_t *naddr)
+{
+	naddr->family = AF_INET6;
+	memcpy(naddr->addr6, v6, 16);
 	naddr->prefix = prefix;
 }
 
-void inet_addr_any(inet_addr_t *addr)
-{
-	addr->family = 0;
-	memset(addr->addr, 0, INET_ADDR_SIZE);
-}
-
-void inet_naddr_any(inet_naddr_t *naddr)
-{
-	naddr->family = 0;
-	memset(naddr->addr, 0, INET_ADDR_SIZE);
-	naddr->prefix = 0;
-}
-
-int inet_addr_compare(inet_addr_t *a, inet_addr_t *b)
-{
-	if (a->family != b->family)
-		return 0;
-	
-	switch (a->family) {
-	case AF_INET:
-		return ((a->addr[0] == b->addr[0]) && (a->addr[1] == b->addr[1]) &&
-		    (a->addr[2] == b->addr[2]) && (a->addr[3] == b->addr[3]));
-	case AF_INET6:
-		// FIXME TODO
-		return 0;
-	default:
-		return 0;
-	}
-}
-
-int inet_addr_is_any(inet_addr_t *addr)
-{
-	return ((addr->family == 0) ||
-	    (inet_addr_compare(addr, &inet_addr_any_addr)) ||
-	    (inet_addr_compare(addr, &inet_addr_any_addr6)));
+void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6,
+    inet_addr_t *addr)
+{
+	addr->family = AF_INET6;
+	addr128_t_be2host(sockaddr_in6->sin6_addr.s6_addr, addr->addr6);
+}
+
+uint16_t inet_addr_sockaddr_in(const inet_addr_t *addr,
+    sockaddr_in_t *sockaddr_in, sockaddr_in6_t *sockaddr_in6)
+{
+	switch (addr->family) {
+	case AF_INET:
+		if (sockaddr_in != NULL) {
+			sockaddr_in->sin_family = AF_INET;
+			sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr);
+		}
+		
+		break;
+	case AF_INET6:
+		if (sockaddr_in6 != NULL) {
+			sockaddr_in6->sin6_family = AF_INET6;
+			host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr);
+		}
+		
+		break;
+	}
+	
+	return addr->family;
 }
 
Index: uspace/lib/c/generic/inetcfg.c
===================================================================
--- uspace/lib/c/generic/inetcfg.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/generic/inetcfg.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -136,41 +136,136 @@
     sysarg_t link_id, sysarg_t *addr_id)
 {
-	uint32_t naddr_addr;
-	uint8_t naddr_bits;
-	int rc = inet_naddr_pack(naddr, &naddr_addr, &naddr_bits);
-	if (rc != EOK)
-		return rc;
-	
-	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_3(exch, INETCFG_ADDR_CREATE_STATIC,
-	    (sysarg_t) naddr_addr, (sysarg_t) naddr_bits, link_id, &answer);
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, INETCFG_ADDR_CREATE_STATIC, link_id,
+	    &answer);
+	
+	int rc = async_data_write_start(exch, naddr, sizeof(inet_naddr_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+	
+	rc = async_data_write_start(exch, name, str_size(name));
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	*addr_id = IPC_GET_ARG1(answer);
+	
+	return (int) retval;
+}
+
+int inetcfg_addr_delete(sysarg_t addr_id)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	int rc = async_req_1_0(exch, INETCFG_ADDR_DELETE, addr_id);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int inetcfg_addr_get(sysarg_t addr_id, inet_addr_info_t *ainfo)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, INETCFG_ADDR_GET, addr_id, &answer);
+	
+	ipc_call_t answer_naddr;
+	aid_t req_naddr = async_data_read(exch, &ainfo->naddr,
+	    sizeof(inet_naddr_t), &answer_naddr);
+	
+	sysarg_t retval_naddr;
+	async_wait_for(req_naddr, &retval_naddr);
+	
+	if (retval_naddr != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return (int) retval_naddr;
+	}
+	
+	ipc_call_t answer_name;
+	char name_buf[LOC_NAME_MAXLEN + 1];
+	aid_t req_name = async_data_read(exch, name_buf, LOC_NAME_MAXLEN,
+	    &answer_name);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t retval_name;
+	async_wait_for(req_name, &retval_name);
+	
+	if (retval_name != EOK) {
+		async_forget(req);
+		return (int) retval_name;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK)
+		return (int) retval;
+	
+	size_t act_size = IPC_GET_ARG2(answer_name);
+	assert(act_size <= LOC_NAME_MAXLEN);
+	
+	name_buf[act_size] = '\0';
+	
+	ainfo->ilink = IPC_GET_ARG1(answer);
+	ainfo->name = str_dup(name_buf);
+	
+	return EOK;
+}
+
+int inetcfg_addr_get_id(const char *name, sysarg_t link_id, sysarg_t *addr_id)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, INETCFG_ADDR_GET_ID, link_id, &answer);
 	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
-	
-	async_exchange_end(exch);
-	
+
+	async_exchange_end(exch);
+
 	if (retval != EOK) {
 		async_forget(req);
 		return retval;
 	}
-	
+
 	async_wait_for(req, &retval);
 	*addr_id = IPC_GET_ARG1(answer);
-	
-	return (int) retval;
-}
-
-int inetcfg_addr_delete(sysarg_t addr_id)
-{
-	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
-
-	int rc = async_req_1_0(exch, INETCFG_ADDR_DELETE, addr_id);
-	async_exchange_end(exch);
-
-	return rc;
-}
-
-int inetcfg_addr_get(sysarg_t addr_id, inet_addr_info_t *ainfo)
+
+	return retval;
+}
+
+int inetcfg_get_addr_list(sysarg_t **addrs, size_t *count)
+{
+	return inetcfg_get_ids_internal(INETCFG_GET_ADDR_LIST,
+	    0, addrs, count);
+}
+
+int inetcfg_get_link_list(sysarg_t **links, size_t *count)
+{
+	return inetcfg_get_ids_internal(INETCFG_GET_LINK_LIST,
+	    0, links, count);
+}
+
+int inetcfg_get_sroute_list(sysarg_t **sroutes, size_t *count)
+{
+	return inetcfg_get_ids_internal(INETCFG_GET_SROUTE_LIST,
+	    0, sroutes, count);
+}
+
+int inetcfg_link_get(sysarg_t link_id, inet_link_info_t *linfo)
 {
 	ipc_call_t dreply;
@@ -178,83 +273,4 @@
 	size_t act_size;
 	char name_buf[LOC_NAME_MAXLEN + 1];
-	
-	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_1(exch, INETCFG_ADDR_GET, addr_id, &answer);
-	aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN, &dreply);
-	async_wait_for(dreq, &dretval);
-	
-	async_exchange_end(exch);
-	
-	if (dretval != EOK) {
-		async_forget(req);
-		return dretval;
-	}
-	
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	
-	if (retval != EOK)
-		return (int) retval;
-	
-	act_size = IPC_GET_ARG2(dreply);
-	assert(act_size <= LOC_NAME_MAXLEN);
-	
-	name_buf[act_size] = '\0';
-	
-	inet_naddr_unpack(IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
-	    &ainfo->naddr);
-	ainfo->ilink = IPC_GET_ARG3(answer);
-	ainfo->name = str_dup(name_buf);
-	
-	return EOK;
-}
-
-int inetcfg_addr_get_id(const char *name, sysarg_t link_id, sysarg_t *addr_id)
-{
-	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
-
-	ipc_call_t answer;
-	aid_t req = async_send_1(exch, INETCFG_ADDR_GET_ID, link_id, &answer);
-	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
-
-	async_exchange_end(exch);
-
-	if (retval != EOK) {
-		async_forget(req);
-		return retval;
-	}
-
-	async_wait_for(req, &retval);
-	*addr_id = IPC_GET_ARG1(answer);
-
-	return retval;
-}
-
-int inetcfg_get_addr_list(sysarg_t **addrs, size_t *count)
-{
-	return inetcfg_get_ids_internal(INETCFG_GET_ADDR_LIST,
-	    0, addrs, count);
-}
-
-int inetcfg_get_link_list(sysarg_t **links, size_t *count)
-{
-	return inetcfg_get_ids_internal(INETCFG_GET_LINK_LIST,
-	    0, links, count);
-}
-
-int inetcfg_get_sroute_list(sysarg_t **sroutes, size_t *count)
-{
-	return inetcfg_get_ids_internal(INETCFG_GET_SROUTE_LIST,
-	    0, sroutes, count);
-}
-
-int inetcfg_link_get(sysarg_t link_id, inet_link_info_t *linfo)
-{
-	ipc_call_t dreply;
-	sysarg_t dretval;
-	size_t act_size;
-	char name_buf[LOC_NAME_MAXLEN + 1];
 
 	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
@@ -291,34 +307,38 @@
     inet_addr_t *router, sysarg_t *sroute_id)
 {
-	uint32_t dest_addr;
-	uint8_t dest_bits;
-	int rc = inet_naddr_pack(dest, &dest_addr, &dest_bits);
-	if (rc != EOK)
-		return rc;
-	
-	uint32_t router_addr;
-	rc = inet_addr_pack(router, &router_addr);
-	if (rc != EOK)
-		return rc;
-	
-	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_3(exch, INETCFG_SROUTE_CREATE,
-	    (sysarg_t) dest_addr, (sysarg_t) dest_bits, (sysarg_t) router_addr,
-	    &answer);
-	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
-	
-	async_exchange_end(exch);
-	
-	if (retval != EOK) {
-		async_forget(req);
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, INETCFG_SROUTE_CREATE, &answer);
+	
+	int rc = async_data_write_start(exch, dest, sizeof(inet_naddr_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+	
+	rc = async_data_write_start(exch, router, sizeof(inet_addr_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+	
+	rc = async_data_write_start(exch, name, str_size(name));
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
 	*sroute_id = IPC_GET_ARG1(answer);
 	
-	return retval;
+	return (int) retval;
 }
 
@@ -335,21 +355,48 @@
 int inetcfg_sroute_get(sysarg_t sroute_id, inet_sroute_info_t *srinfo)
 {
-	ipc_call_t dreply;
-	sysarg_t dretval;
-	size_t act_size;
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, INETCFG_SROUTE_GET, sroute_id, &answer);
+	
+	ipc_call_t answer_dest;
+	aid_t req_dest = async_data_read(exch, &srinfo->dest,
+	    sizeof(inet_naddr_t), &answer_dest);
+	
+	sysarg_t retval_dest;
+	async_wait_for(req_dest, &retval_dest);
+	
+	if (retval_dest != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return (int) retval_dest;
+	}
+	
+	ipc_call_t answer_router;
+	aid_t req_router = async_data_read(exch, &srinfo->router,
+	    sizeof(inet_addr_t), &answer_router);
+	
+	sysarg_t retval_router;
+	async_wait_for(req_router, &retval_router);
+	
+	if (retval_router != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return (int) retval_router;
+	}
+	
+	ipc_call_t answer_name;
 	char name_buf[LOC_NAME_MAXLEN + 1];
-
-	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_1(exch, INETCFG_SROUTE_GET, sroute_id, &answer);
-	aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN, &dreply);
-	async_wait_for(dreq, &dretval);
-	
-	async_exchange_end(exch);
-	
-	if (dretval != EOK) {
-		async_forget(req);
-		return dretval;
+	aid_t req_name = async_data_read(exch, name_buf, LOC_NAME_MAXLEN,
+	    &answer_name);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t retval_name;
+	async_wait_for(req_name, &retval_name);
+	
+	if (retval_name != EOK) {
+		async_forget(req);
+		return (int) retval_name;
 	}
 	
@@ -360,11 +407,9 @@
 		return (int) retval;
 	
-	act_size = IPC_GET_ARG2(dreply);
+	size_t act_size = IPC_GET_ARG2(answer_name);
 	assert(act_size <= LOC_NAME_MAXLEN);
+	
 	name_buf[act_size] = '\0';
-
-	inet_naddr_unpack(IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
-	    &srinfo->dest);
-	inet_addr_unpack(IPC_GET_ARG3(answer), &srinfo->router);
+	
 	srinfo->name = str_dup(name_buf);
 	
Index: uspace/lib/c/generic/iplink.c
===================================================================
--- uspace/lib/c/generic/iplink.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/generic/iplink.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -86,7 +86,21 @@
 	
 	ipc_call_t answer;
-	aid_t req = async_send_2(exch, IPLINK_SEND, (sysarg_t) sdu->lsrc,
-	    (sysarg_t) sdu->ldest, &answer);
-	int rc = async_data_write_start(exch, sdu->data, sdu->size);
+	aid_t req = async_send_0(exch, IPLINK_SEND, &answer);
+	
+	int rc = async_data_write_start(exch, &sdu->src, sizeof(inet_addr_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+	
+	rc = async_data_write_start(exch, &sdu->dest, sizeof(inet_addr_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+	
+	rc = async_data_write_start(exch, sdu->data, sdu->size);
 	
 	async_exchange_end(exch);
@@ -120,47 +134,61 @@
 int iplink_addr_add(iplink_t *iplink, inet_addr_t *addr)
 {
-	uint32_t addr_addr;
-	int rc = inet_addr_pack(addr, &addr_addr);
-	if (rc != EOK)
-		return rc;
-	
-	async_exch_t *exch = async_exchange_begin(iplink->sess);
-	rc = async_req_1_0(exch, IPLINK_ADDR_ADD, (sysarg_t) addr_addr);
-	async_exchange_end(exch);
-	
-	return rc;
+	async_exch_t *exch = async_exchange_begin(iplink->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, IPLINK_ADDR_ADD, &answer);
+	
+	int rc = async_data_write_start(exch, addr, sizeof(inet_addr_t));
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	return (int) retval;
 }
 
 int iplink_addr_remove(iplink_t *iplink, inet_addr_t *addr)
 {
-	uint32_t addr_addr;
-	int rc = inet_addr_pack(addr, &addr_addr);
-	if (rc != EOK)
-		return rc;
-	
-	async_exch_t *exch = async_exchange_begin(iplink->sess);
-	rc = async_req_1_0(exch, IPLINK_ADDR_REMOVE, (sysarg_t) addr_addr);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-static void iplink_ev_recv(iplink_t *iplink, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	iplink_sdu_t sdu;
-	
-	sdu.lsrc = IPC_GET_ARG1(*call);
-	sdu.ldest = IPC_GET_ARG2(*call);
-	
-	int rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
+	async_exch_t *exch = async_exchange_begin(iplink->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, IPLINK_ADDR_REMOVE, &answer);
+	
+	int rc = async_data_write_start(exch, addr, sizeof(inet_addr_t));
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	return (int) retval;
+}
+
+static void iplink_ev_recv(iplink_t *iplink, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	iplink_recv_sdu_t sdu;
+	
+	uint16_t af = IPC_GET_ARG1(*icall);
+	
+	int rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
+	    &sdu.size);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
 		return;
 	}
 	
-	rc = iplink->ev_ops->recv(iplink, &sdu);
+	rc = iplink->ev_ops->recv(iplink, &sdu, af);
 	free(sdu.data);
-	async_answer_0(callid, rc);
+	async_answer_0(iid, rc);
 }
 
Index: uspace/lib/c/generic/iplink_srv.c
===================================================================
--- uspace/lib/c/generic/iplink_srv.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/generic/iplink_srv.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -34,9 +34,10 @@
  * @brief IP link server stub
  */
+
 #include <errno.h>
 #include <ipc/iplink.h>
 #include <stdlib.h>
 #include <sys/types.h>
-
+#include <inet/addr.h>
 #include <inet/iplink_srv.h>
 
@@ -49,36 +50,111 @@
 }
 
-static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	int rc = srv->ops->addr_add(srv, IPC_GET_ARG1(*call));
-	async_answer_0(callid, rc);
-}
-
-static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	int rc = srv->ops->addr_remove(srv, IPC_GET_ARG1(*call));
-	async_answer_0(callid, rc);
-}
-
-static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	iplink_srv_sdu_t sdu;
-	int rc;
-	
-	sdu.lsrc = IPC_GET_ARG1(*call);
-	sdu.ldest = IPC_GET_ARG2(*call);
-	
-	rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
+static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	inet_addr_t addr;
+	int rc = async_data_write_finalize(callid, &addr, size);
+	if (rc != EOK) {
+		async_answer_0(callid, (sysarg_t) rc);
+		async_answer_0(iid, (sysarg_t) rc);
+	}
+	
+	rc = srv->ops->addr_add(srv, &addr);
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	inet_addr_t addr;
+	int rc = async_data_write_finalize(callid, &addr, size);
+	if (rc != EOK) {
+		async_answer_0(callid, (sysarg_t) rc);
+		async_answer_0(iid, (sysarg_t) rc);
+	}
+	
+	rc = srv->ops->addr_remove(srv, &addr);
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	iplink_sdu_t sdu;
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	int rc = async_data_write_finalize(callid, &sdu.src, size);
+	if (rc != EOK) {
+		async_answer_0(callid, (sysarg_t) rc);
+		async_answer_0(iid, (sysarg_t) rc);
+	}
+	
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	rc = async_data_write_finalize(callid, &sdu.dest, size);
+	if (rc != EOK) {
+		async_answer_0(callid, (sysarg_t) rc);
+		async_answer_0(iid, (sysarg_t) rc);
+	}
+	
+	rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
+	    &sdu.size);
+	if (rc != EOK)
+		return;
 	
 	rc = srv->ops->send(srv, &sdu);
 	free(sdu.data);
-	async_answer_0(callid, rc);
+	async_answer_0(iid, rc);
 }
 
@@ -155,5 +231,5 @@
 }
 
-int iplink_ev_recv(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
+int iplink_ev_recv(iplink_srv_t *srv, iplink_recv_sdu_t *sdu, uint16_t af)
 {
 	if (srv->client_sess == NULL)
@@ -163,6 +239,7 @@
 	
 	ipc_call_t answer;
-	aid_t req = async_send_2(exch, IPLINK_EV_RECV, (sysarg_t) sdu->lsrc,
-	    (sysarg_t) sdu->ldest, &answer);
+	aid_t req = async_send_1(exch, IPLINK_EV_RECV, (sysarg_t) af,
+	    &answer);
+	
 	int rc = async_data_write_start(exch, sdu->data, sdu->size);
 	async_exchange_end(exch);
Index: uspace/lib/c/include/inet/addr.h
===================================================================
--- uspace/lib/c/include/inet/addr.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/include/inet/addr.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -38,11 +38,17 @@
 #include <stdint.h>
 #include <net/in.h>
+#include <net/in6.h>
 
-#define INET_ADDR_SIZE  16
+typedef uint32_t addr32_t;
+typedef uint8_t addr48_t[6];
+typedef uint8_t addr128_t[16];
 
 /** Node address */
 typedef struct {
 	uint16_t family;
-	uint8_t addr[INET_ADDR_SIZE];
+	union {
+		addr32_t addr;
+		addr128_t addr6;
+	};
 } inet_addr_t;
 
@@ -53,5 +59,8 @@
 	
 	/** Address */
-	uint8_t addr[INET_ADDR_SIZE];
+	union {
+		addr32_t addr;
+		addr128_t addr6;
+	};
 	
 	/** Number of valid bits */
@@ -59,20 +68,11 @@
 } inet_naddr_t;
 
-extern int inet_addr_family(const char *, uint16_t *);
+extern const addr48_t addr48_broadcast;
 
-extern int inet_addr_parse(const char *, inet_addr_t *);
-extern int inet_naddr_parse(const char *, inet_naddr_t *);
+extern void addr48(const addr48_t, addr48_t);
+extern void addr128(const addr128_t, addr128_t);
 
-extern int inet_addr_format(inet_addr_t *, char **);
-extern int inet_naddr_format(inet_naddr_t *, char **);
-
-extern int inet_addr_pack(inet_addr_t *, uint32_t *);
-extern int inet_naddr_pack(inet_naddr_t *, uint32_t *, uint8_t *);
-
-extern void inet_addr_unpack(uint32_t, inet_addr_t *);
-extern void inet_naddr_unpack(uint32_t, uint8_t, inet_naddr_t *);
-
-extern int inet_addr_sockaddr_in(inet_addr_t *, sockaddr_in_t *);
-extern void inet_naddr_addr(inet_naddr_t *, inet_addr_t *);
+extern void host2addr128_t_be(const addr128_t, addr128_t);
+extern void addr128_t_be2host(const addr128_t, addr128_t);
 
 extern void inet_addr(inet_addr_t *, uint8_t, uint8_t, uint8_t, uint8_t);
@@ -80,9 +80,40 @@
     uint8_t);
 
+extern void inet_addr6(inet_addr_t *, uint16_t, uint16_t, uint16_t, uint16_t,
+    uint16_t, uint16_t, uint16_t, uint16_t);
+extern void inet_naddr6(inet_naddr_t *, uint16_t, uint16_t, uint16_t, uint16_t,
+    uint16_t, uint16_t, uint16_t, uint16_t, uint8_t);
+
+extern int inet_addr_family(const char *, uint16_t *);
+extern void inet_naddr_addr(const inet_naddr_t *, inet_addr_t *);
+
 extern void inet_addr_any(inet_addr_t *);
 extern void inet_naddr_any(inet_naddr_t *);
 
-extern int inet_addr_compare(inet_addr_t *, inet_addr_t *);
-extern int inet_addr_is_any(inet_addr_t *);
+extern int inet_addr_compare(const inet_addr_t *, const inet_addr_t *);
+extern int inet_addr_is_any(const inet_addr_t *);
+
+extern int inet_naddr_compare_mask(const inet_naddr_t *, const inet_addr_t *);
+
+extern int inet_addr_parse(const char *, inet_addr_t *);
+extern int inet_naddr_parse(const char *, inet_naddr_t *);
+
+extern int inet_addr_format(const inet_addr_t *, char **);
+extern int inet_naddr_format(const inet_naddr_t *, char **);
+
+extern uint16_t inet_addr_get(const inet_addr_t *, addr32_t *, addr128_t *);
+extern uint16_t inet_naddr_get(const inet_naddr_t *, addr32_t *, addr128_t *,
+    uint8_t *);
+
+extern void inet_addr_set(addr32_t, inet_addr_t *);
+extern void inet_naddr_set(addr32_t, uint8_t, inet_naddr_t *);
+extern void inet_sockaddr_in_addr(const sockaddr_in_t *, inet_addr_t *);
+
+extern void inet_addr_set6(addr128_t, inet_addr_t *);
+extern void inet_naddr_set6(addr128_t, uint8_t, inet_naddr_t *);
+extern void inet_sockaddr_in6_addr(const sockaddr_in6_t *, inet_addr_t *);
+
+extern uint16_t inet_addr_sockaddr_in(const inet_addr_t *, sockaddr_in_t *,
+    sockaddr_in6_t *);
 
 #endif
Index: uspace/lib/c/include/inet/iplink.h
===================================================================
--- uspace/lib/c/include/inet/iplink.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/include/inet/iplink.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -47,10 +47,10 @@
 } iplink_t;
 
-/** IPv4 link Service Data Unit */
+/** Internet link Service Data Unit */
 typedef struct {
 	/** Local source address */
-	uint32_t lsrc;
+	inet_addr_t src;
 	/** Local destination address */
-	uint32_t ldest;
+	inet_addr_t dest;
 	/** Serialized IP packet */
 	void *data;
@@ -59,16 +59,14 @@
 } iplink_sdu_t;
 
-/** IPv6 link Service Data Unit */
+/** Internet link receive Service Data Unit */
 typedef struct {
-	/** Target MAC address */
-	uint64_t hwaddr;
-	/** Serialized IP packet */
+	/** Serialized datagram */
 	void *data;
 	/** Size of @c data in bytes */
 	size_t size;
-} iplink_sdu6_t;
+} iplink_recv_sdu_t;
 
 typedef struct iplink_ev_ops {
-	int (*recv)(iplink_t *, iplink_sdu_t *);
+	int (*recv)(iplink_t *, iplink_recv_sdu_t *, uint16_t);
 } iplink_ev_ops_t;
 
Index: uspace/lib/c/include/inet/iplink_srv.h
===================================================================
--- uspace/lib/c/include/inet/iplink_srv.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/lib/c/include/inet/iplink_srv.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -40,4 +40,6 @@
 #include <stdbool.h>
 #include <sys/types.h>
+#include <inet/addr.h>
+#include <inet/iplink.h>
 
 struct iplink_ops;
@@ -51,23 +53,11 @@
 } iplink_srv_t;
 
-/** IP link Service Data Unit */
-typedef struct {
-	/** Local source address */
-	uint32_t lsrc;
-	/** Local destination address */
-	uint32_t ldest;
-	/** Serialized IP packet */
-	void *data;
-	/** Size of @c data in bytes */
-	size_t size;
-} iplink_srv_sdu_t;
-
 typedef struct iplink_ops {
 	int (*open)(iplink_srv_t *);
 	int (*close)(iplink_srv_t *);
-	int (*send)(iplink_srv_t *, iplink_srv_sdu_t *);
+	int (*send)(iplink_srv_t *, iplink_sdu_t *);
 	int (*get_mtu)(iplink_srv_t *, size_t *);
-	int (*addr_add)(iplink_srv_t *, uint32_t);
-	int (*addr_remove)(iplink_srv_t *, uint32_t);
+	int (*addr_add)(iplink_srv_t *, inet_addr_t *);
+	int (*addr_remove)(iplink_srv_t *, inet_addr_t *);
 } iplink_ops_t;
 
@@ -75,5 +65,5 @@
 
 extern int iplink_conn(ipc_callid_t, ipc_call_t *, void *);
-extern int iplink_ev_recv(iplink_srv_t *, iplink_srv_sdu_t *);
+extern int iplink_ev_recv(iplink_srv_t *, iplink_recv_sdu_t *, uint16_t);
 
 #endif
Index: uspace/srv/net/dnsrsrv/dnsrsrv.c
===================================================================
--- uspace/srv/net/dnsrsrv/dnsrsrv.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/dnsrsrv/dnsrsrv.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -84,62 +84,23 @@
 }
 
-static void dnsr_name2host_srv(dnsr_client_t *client, ipc_callid_t callid,
-    ipc_call_t *call)
-{
+static void dnsr_name2host_srv(dnsr_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_get_srvaddr_srv()");
+	
 	char *name;
+	int rc = async_data_write_accept((void **) &name, true, 0,
+	    DNS_NAME_MAX_SIZE, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
 	dns_host_info_t *hinfo;
-	ipc_callid_t rcallid;
-	size_t size;
-	sysarg_t retval;
-	size_t act_size;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_get_srvaddr_srv()");
-
-	rc = async_data_write_accept((void **) &name, true, 0,
-	    DNS_NAME_MAX_SIZE, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	if (!async_data_read_receive(&rcallid, &size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-
 	rc = dns_name2host(name, &hinfo);
 	if (rc != EOK) {
-		async_answer_0(rcallid, rc);
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	uint32_t addr;
-	rc = inet_addr_pack(&hinfo->addr, &addr);
-	if (rc != EOK) {
-		async_answer_0(rcallid, rc);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	act_size = str_size(hinfo->cname);
-	if (act_size > size) {
-		async_answer_0(rcallid, EOVERFLOW);
-		async_answer_0(callid, EOVERFLOW);
-		return;
-	}
-
-	retval = async_data_read_finalize(rcallid, hinfo->cname, act_size);
-	async_answer_1(callid, retval, (sysarg_t) addr);
-
-	dns_hostinfo_destroy(hinfo);
-}
-
-static void dnsr_get_srvaddr_srv(dnsr_client_t *client, ipc_callid_t iid,
-    ipc_call_t *icall)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_get_srvaddr_srv()");
+		async_answer_0(iid, rc);
+		return;
+	}
 	
 	ipc_callid_t callid;
@@ -157,9 +118,59 @@
 	}
 	
+	rc = async_data_read_finalize(callid, &hinfo->addr, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	size_t act_size = str_size(hinfo->cname);
+	if (act_size > size) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	rc = async_data_read_finalize(callid, hinfo->cname, act_size);
+	if (rc != EOK)
+		async_answer_0(callid, rc);
+	
+	async_answer_0(iid, (sysarg_t) rc);
+	
+	dns_hostinfo_destroy(hinfo);
+}
+
+static void dnsr_get_srvaddr_srv(dnsr_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_get_srvaddr_srv()");
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
 	// FIXME locking
 	
-	sysarg_t retval =
-	    async_data_read_finalize(callid, &dns_server_addr, size);
-	async_answer_0(iid, retval);
+	int rc = async_data_read_finalize(callid, &dns_server_addr, size);
+	if (rc != EOK)
+		async_answer_0(callid, rc);
+	
+	async_answer_0(iid, rc);
 }
 
@@ -185,7 +196,9 @@
 	// FIXME locking
 	
-	sysarg_t retval =
-	    async_data_write_finalize(callid, &dns_server_addr, size);
-	async_answer_0(iid, retval);
+	int rc = async_data_write_finalize(callid, &dns_server_addr, size);
+	if (rc != EOK)
+		async_answer_0(callid, rc);
+	
+	async_answer_0(iid, (sysarg_t) rc);
 }
 
Index: uspace/srv/net/dnsrsrv/query.c
===================================================================
--- uspace/srv/net/dnsrsrv/query.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/dnsrsrv/query.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -128,5 +128,5 @@
 
 			info->cname = str_dup(rr->name);
-			inet_addr_unpack(dns_uint32_t_decode(rr->rdata, rr->rdata_size),
+			inet_addr_set(dns_uint32_t_decode(rr->rdata, rr->rdata_size),
 			    &info->addr);
 			
Index: uspace/srv/net/dnsrsrv/transport.c
===================================================================
--- uspace/srv/net/dnsrsrv/transport.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/dnsrsrv/transport.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -183,27 +183,41 @@
 int dns_request(dns_message_t *req, dns_message_t **rresp)
 {
-	int rc;
+	trans_req_t *treq = NULL;
+	
 	void *req_data;
 	size_t req_size;
+	int rc = dns_message_encode(req, &req_data, &req_size);
+	if (rc != EOK)
+		goto error;
+	
 	struct sockaddr_in addr;
-	trans_req_t *treq;
-	int ntry;
-
-	req_data = NULL;
-	treq = NULL;
-
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(DNS_SERVER_PORT);
-	inet_addr_sockaddr_in(&dns_server_addr, &addr);
-
-	rc = dns_message_encode(req, &req_data, &req_size);
-	if (rc != EOK)
-		goto error;
-
-	ntry = 0;
-
+	struct sockaddr_in6 addr6;
+	uint16_t af =
+	    inet_addr_sockaddr_in(&dns_server_addr, &addr, &addr6);
+	
+	struct sockaddr *address;
+	socklen_t addrlen;
+	
+	switch (af) {
+	case AF_INET:
+		addr.sin_port = htons(DNS_SERVER_PORT);
+		address = (struct sockaddr *) &addr;
+		addrlen = sizeof(addr);
+		break;
+	case AF_INET6:
+		addr6.sin6_port = htons(DNS_SERVER_PORT);
+		address = (struct sockaddr *) &addr6;
+		addrlen = sizeof(addr6);
+		break;
+	default:
+		rc = EAFNOSUPPORT;
+		goto error;
+	}
+	
+	size_t ntry = 0;
+	
 	while (ntry < REQ_RETRY_MAX) {
 		rc = sendto(transport_fd, req_data, req_size, 0,
-		    (struct sockaddr *) &addr, sizeof(addr));
+		    (struct sockaddr *) address, addrlen);
 		if (rc != EOK)
 			goto error;
Index: uspace/srv/net/ethip/arp.c
===================================================================
--- uspace/srv/net/ethip/arp.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/arp.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -38,6 +38,7 @@
 #include <io/log.h>
 #include <inet/iplink_srv.h>
+#include <inet/addr.h>
 #include <stdlib.h>
-
+#include <net/socket_codes.h>
 #include "arp.h"
 #include "atrans.h"
@@ -54,53 +55,59 @@
 void arp_received(ethip_nic_t *nic, eth_frame_t *frame)
 {
-	int rc;
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "arp_received()");
+	
 	arp_eth_packet_t packet;
-	arp_eth_packet_t reply;
-	ethip_link_addr_t *laddr;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "arp_received()");
-
-	rc = arp_pdu_decode(frame->data, frame->size, &packet);
+	int rc = arp_pdu_decode(frame->data, frame->size, &packet);
 	if (rc != EOK)
 		return;
-
+	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ARP PDU decoded, opcode=%d, tpa=%x",
 	    packet.opcode, packet.target_proto_addr);
-
-	laddr = ethip_nic_addr_find(nic, packet.target_proto_addr);
-	if (laddr != NULL) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "Request/reply to my address");
-
-		(void) atrans_add(packet.sender_proto_addr,
-		    &packet.sender_hw_addr);
-
-		if (packet.opcode == aop_request) {
-        		reply.opcode = aop_reply;
-        		reply.sender_hw_addr = nic->mac_addr;
-			reply.sender_proto_addr = laddr->addr;
-			reply.target_hw_addr = packet.sender_hw_addr;
-			reply.target_proto_addr = packet.sender_proto_addr;
-
-			arp_send_packet(nic, &reply);
-		}
+	
+	inet_addr_t addr;
+	inet_addr_set(packet.target_proto_addr, &addr);
+	
+	ethip_link_addr_t *laddr = ethip_nic_addr_find(nic, &addr);
+	if (laddr == NULL)
+		return;
+	
+	addr32_t laddr_v4;
+	uint16_t laddr_af = inet_addr_get(&laddr->addr, &laddr_v4, NULL);
+	if (laddr_af != AF_INET)
+		return;
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Request/reply to my address");
+	
+	(void) atrans_add(packet.sender_proto_addr,
+	    packet.sender_hw_addr);
+	
+	if (packet.opcode == aop_request) {
+		arp_eth_packet_t reply;
+		
+		reply.opcode = aop_reply;
+		addr48(nic->mac_addr, reply.sender_hw_addr);
+		reply.sender_proto_addr = laddr_v4;
+		addr48(packet.sender_hw_addr, reply.target_hw_addr);
+		reply.target_proto_addr = packet.sender_proto_addr;
+		
+		arp_send_packet(nic, &reply);
 	}
 }
 
-int arp_translate(ethip_nic_t *nic, uint32_t src_addr, uint32_t ip_addr,
-    mac48_addr_t *mac_addr)
+int arp_translate(ethip_nic_t *nic, addr32_t src_addr, addr32_t ip_addr,
+    addr48_t mac_addr)
 {
-	int rc;
-	arp_eth_packet_t packet;
-
-	rc = atrans_lookup(ip_addr, mac_addr);
+	int rc = atrans_lookup(ip_addr, mac_addr);
 	if (rc == EOK)
 		return EOK;
-
+	
+	arp_eth_packet_t packet;
+	
 	packet.opcode = aop_request;
-	packet.sender_hw_addr = nic->mac_addr;
+	addr48(nic->mac_addr, packet.sender_hw_addr);
 	packet.sender_proto_addr = src_addr;
-	packet.target_hw_addr.addr = MAC48_BROADCAST;
+	addr48(addr48_broadcast, packet.target_hw_addr);
 	packet.target_proto_addr = ip_addr;
-
+	
 	rc = arp_send_packet(nic, &packet);
 	if (rc != EOK)
@@ -128,6 +135,6 @@
 		return rc;
 
-	frame.dest.addr = packet->target_hw_addr.addr;
-	frame.src.addr =  packet->sender_hw_addr.addr;
+	addr48(packet->target_hw_addr, frame.dest);
+	addr48(packet->sender_hw_addr, frame.src);
 	frame.etype_len = ETYPE_ARP;
 	frame.data = pdata;
Index: uspace/srv/net/ethip/arp.h
===================================================================
--- uspace/srv/net/ethip/arp.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/arp.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -39,8 +39,9 @@
 
 #include <inet/iplink_srv.h>
+#include <inet/addr.h>
 #include "ethip.h"
 
 extern void arp_received(ethip_nic_t *, eth_frame_t *);
-extern int arp_translate(ethip_nic_t *, uint32_t, uint32_t, mac48_addr_t *);
+extern int arp_translate(ethip_nic_t *, addr32_t, addr32_t, addr48_t);
 
 #endif
Index: uspace/srv/net/ethip/atrans.c
===================================================================
--- uspace/srv/net/ethip/atrans.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/atrans.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -62,5 +62,5 @@
 }
 
-int atrans_add(uint32_t ip_addr, mac48_addr_t *mac_addr)
+int atrans_add(uint32_t ip_addr, addr48_t mac_addr)
 {
 	ethip_atrans_t *atrans;
@@ -72,5 +72,5 @@
 
 	atrans->ip_addr = ip_addr;
-	atrans->mac_addr = *mac_addr;
+	addr48(mac_addr, atrans->mac_addr);
 
 	fibril_mutex_lock(&atrans_list_lock);
@@ -106,17 +106,15 @@
 }
 
-int atrans_lookup(uint32_t ip_addr, mac48_addr_t *mac_addr)
+int atrans_lookup(uint32_t ip_addr, addr48_t mac_addr)
 {
-	ethip_atrans_t *atrans;
-
 	fibril_mutex_lock(&atrans_list_lock);
-	atrans = atrans_find(ip_addr);
+	ethip_atrans_t *atrans = atrans_find(ip_addr);
 	if (atrans == NULL) {
 		fibril_mutex_unlock(&atrans_list_lock);
 		return ENOENT;
 	}
-
+	
 	fibril_mutex_unlock(&atrans_list_lock);
-	*mac_addr = atrans->mac_addr;
+	addr48(atrans->mac_addr, mac_addr);
 	return EOK;
 }
Index: uspace/srv/net/ethip/atrans.h
===================================================================
--- uspace/srv/net/ethip/atrans.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/atrans.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -39,9 +39,10 @@
 
 #include <inet/iplink_srv.h>
+#include <inet/addr.h>
 #include "ethip.h"
 
-extern int atrans_add(uint32_t, mac48_addr_t *);
+extern int atrans_add(uint32_t, addr48_t);
 extern int atrans_remove(uint32_t);
-extern int atrans_lookup(uint32_t, mac48_addr_t *);
+extern int atrans_lookup(uint32_t, addr48_t);
 extern int atrans_wait_timeout(suseconds_t);
 
Index: uspace/srv/net/ethip/ethip.c
===================================================================
--- uspace/srv/net/ethip/ethip.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/ethip.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -44,5 +44,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-
+#include <net/socket_codes.h>
 #include "arp.h"
 #include "ethip.h"
@@ -55,8 +55,8 @@
 static int ethip_open(iplink_srv_t *srv);
 static int ethip_close(iplink_srv_t *srv);
-static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu);
+static int ethip_send(iplink_srv_t *srv, iplink_sdu_t *sdu);
 static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu);
-static int ethip_addr_add(iplink_srv_t *srv, uint32_t addr);
-static int ethip_addr_remove(iplink_srv_t *srv, uint32_t addr);
+static int ethip_addr_add(iplink_srv_t *srv, inet_addr_t *addr);
+static int ethip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr);
 
 static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
@@ -164,28 +164,48 @@
 }
 
-static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
-{
-	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+static int ethip_send(iplink_srv_t *srv, iplink_sdu_t *sdu)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_send()");
+	
+	ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
+	
+	addr32_t src_v4;
+	addr128_t src_v6;
+	uint16_t src_af = inet_addr_get(&sdu->src, &src_v4, &src_v6);
+	
+	addr32_t dest_v4;
+	addr128_t dest_v6;
+	uint16_t dest_af = inet_addr_get(&sdu->dest, &dest_v4, &dest_v6);
+	
+	if (src_af != dest_af)
+		return EINVAL;
+	
+	int rc;
 	eth_frame_t frame;
+	
+	switch (src_af) {
+	case AF_INET:
+		rc = arp_translate(nic, src_v4, dest_v4, frame.dest);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_WARN, "Failed to look up IPv4 address 0x%"
+			    PRIx32, dest_v4);
+			return rc;
+		}
+		
+		addr48(nic->mac_addr, frame.src);
+		frame.etype_len = ETYPE_IP;
+		frame.data = sdu->data;
+		frame.size = sdu->size;
+		
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		return ENOTSUP;
+	default:
+		return EINVAL;
+	}
+	
 	void *data;
 	size_t size;
-	mac48_addr_t dest_mac_addr;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_send()");
-
-	rc = arp_translate(nic, sdu->lsrc, sdu->ldest, &dest_mac_addr);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Failed to look up IP address 0x%" PRIx32,
-		    sdu->ldest);
-		return rc;
-	}
-
-	frame.dest      = dest_mac_addr;
-	frame.src       = nic->mac_addr;
-	frame.etype_len = ETYPE_IP;
-	frame.data = sdu->data;
-	frame.size = sdu->size;
-
 	rc = eth_pdu_encode(&frame, &data, &size);
 	if (rc != EOK)
@@ -201,18 +221,17 @@
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_received(): srv=%p", srv);
-	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+	ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode");
+	
 	eth_frame_t frame;
-	iplink_srv_sdu_t sdu;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_received()");
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode");
-	rc = eth_pdu_decode(data, size, &frame);
+	int rc = eth_pdu_decode(data, size, &frame);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode failed");
 		return rc;
 	}
-
+	
+	iplink_recv_sdu_t sdu;
+	
 	switch (frame.etype_len) {
 	case ETYPE_ARP:
@@ -221,10 +240,8 @@
 	case ETYPE_IP:
 		log_msg(LOG_DEFAULT, LVL_DEBUG, " - construct SDU");
-		sdu.lsrc = 0;
-		sdu.ldest = 0;
 		sdu.data = frame.data;
 		sdu.size = frame.size;
 		log_msg(LOG_DEFAULT, LVL_DEBUG, " - call iplink_ev_recv");
-		rc = iplink_ev_recv(&nic->iplink, &sdu);
+		rc = iplink_ev_recv(&nic->iplink, &sdu, AF_INET);
 		break;
 	default:
@@ -244,8 +261,6 @@
 }
 
-static int ethip_addr_add(iplink_srv_t *srv, uint32_t addr)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_addr_add(0x%" PRIx32 ")", addr);
-	
+static int ethip_addr_add(iplink_srv_t *srv, inet_addr_t *addr)
+{
 	ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
 	
@@ -253,11 +268,9 @@
 }
 
-static int ethip_addr_remove(iplink_srv_t *srv, uint32_t addr)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_addr_remove(0x%" PRIx32 ")", addr);
-	
-	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
-	
-	return ethip_nic_addr_add(nic, addr);
+static int ethip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr)
+{
+	ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
+	
+	return ethip_nic_addr_remove(nic, addr);
 }
 
Index: uspace/srv/net/ethip/ethip.h
===================================================================
--- uspace/srv/net/ethip/ethip.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/ethip.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -41,19 +41,12 @@
 #include <async.h>
 #include <inet/iplink_srv.h>
+#include <inet/addr.h>
 #include <loc.h>
 #include <sys/types.h>
 
-#define MAC48_BROADCAST 0xffffffffffff
-
 typedef struct {
 	link_t addr_list;
-	uint32_t addr;
+	inet_addr_t addr;
 } ethip_link_addr_t;
-
-/** IEEE MAC-48 identifier */
-typedef struct {
-	/** MAC Address (in lowest 48 bits) */
-	uint64_t addr;
-} mac48_addr_t;
 
 typedef struct ethip_nic {
@@ -67,5 +60,5 @@
 
 	/** MAC address */
-	mac48_addr_t mac_addr;
+	addr48_t mac_addr;
 	/** List of IP addresses configured on this link */
 	list_t addr_list; /* of ethip_link_addr_t */
@@ -75,7 +68,7 @@
 typedef struct {
 	/** Destination Address */
-	mac48_addr_t dest;
+	addr48_t dest;
 	/** Source Address */
-	mac48_addr_t src;
+	addr48_t src;
 	/** Ethertype or Length */
 	uint16_t etype_len;
@@ -102,9 +95,9 @@
 	arp_opcode_t opcode;
 	/** Sender hardware address */
-	mac48_addr_t sender_hw_addr;
+	addr48_t sender_hw_addr;
 	/** Sender protocol address */
 	uint32_t sender_proto_addr;
 	/** Target hardware address */
-	mac48_addr_t target_hw_addr;
+	addr48_t target_hw_addr;
 	/** Target protocol address */
 	uint32_t target_proto_addr;
@@ -115,5 +108,5 @@
 	link_t atrans_list;
 	uint32_t ip_addr;
-	mac48_addr_t mac_addr;
+	addr48_t mac_addr;
 } ethip_atrans_t;
 
Index: uspace/srv/net/ethip/ethip_nic.c
===================================================================
--- uspace/srv/net/ethip/ethip_nic.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/ethip_nic.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -121,5 +121,5 @@
 }
 
-static ethip_link_addr_t *ethip_nic_addr_new(uint32_t addr)
+static ethip_link_addr_t *ethip_nic_addr_new(inet_addr_t *addr)
 {
 	ethip_link_addr_t *laddr = calloc(1, sizeof(ethip_link_addr_t));
@@ -131,5 +131,5 @@
 	
 	link_initialize(&laddr->addr_list);
-	laddr->addr = addr;
+	laddr->addr = *addr;
 	
 	return laddr;
@@ -193,6 +193,6 @@
 		goto error;
 	}
-
-	mac48_decode(nic_address.address, &nic->mac_addr);
+	
+	addr48(nic_address.address, nic->mac_addr);
 
 	rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
@@ -203,6 +203,5 @@
 	}
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Initialized IP link service, MAC = 0x%" PRIx64,
-	    nic->mac_addr.addr);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Initialized IP link service,");
 
 	return EOK;
@@ -335,5 +334,5 @@
 }
 
-int ethip_nic_addr_add(ethip_nic_t *nic, uint32_t addr)
+int ethip_nic_addr_add(ethip_nic_t *nic, inet_addr_t *addr)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_addr_add()");
@@ -347,5 +346,5 @@
 }
 
-int ethip_nic_addr_remove(ethip_nic_t *nic, uint32_t addr)
+int ethip_nic_addr_remove(ethip_nic_t *nic, inet_addr_t *addr)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_addr_remove()");
@@ -361,5 +360,5 @@
 
 ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *nic,
-    uint32_t addr)
+    inet_addr_t *addr)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_addr_find()");
@@ -369,5 +368,5 @@
 		    ethip_link_addr_t, addr_list);
 		
-		if (addr == laddr->addr)
+		if (inet_addr_compare(addr, &laddr->addr))
 			return laddr;
 	}
Index: uspace/srv/net/ethip/ethip_nic.h
===================================================================
--- uspace/srv/net/ethip/ethip_nic.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/ethip_nic.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -39,4 +39,5 @@
 
 #include <ipc/loc.h>
+#include <inet/addr.h>
 #include "ethip.h"
 
@@ -44,7 +45,7 @@
 extern ethip_nic_t *ethip_nic_find_by_iplink_sid(service_id_t);
 extern int ethip_nic_send(ethip_nic_t *, void *, size_t);
-extern int ethip_nic_addr_add(ethip_nic_t *, uint32_t);
-extern int ethip_nic_addr_remove(ethip_nic_t *, uint32_t);
-extern ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *, uint32_t);
+extern int ethip_nic_addr_add(ethip_nic_t *, inet_addr_t *);
+extern int ethip_nic_addr_remove(ethip_nic_t *, inet_addr_t *);
+extern ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *, inet_addr_t *);
 
 #endif
Index: uspace/srv/net/ethip/pdu.c
===================================================================
--- uspace/srv/net/ethip/pdu.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/pdu.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -62,6 +62,6 @@
 
 	hdr = (eth_header_t *)data;
-	mac48_encode(&frame->src, hdr->src);
-	mac48_encode(&frame->dest, hdr->dest);
+	addr48(frame->src, hdr->src);
+	addr48(frame->dest, hdr->dest);
 	hdr->etype_len = host2uint16_t_be(frame->etype_len);
 
@@ -69,7 +69,4 @@
 	    frame->size);
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Encoding Ethernet frame "
-	    "src=%" PRIx64 " dest=%" PRIx64 " etype=%x",
-	    frame->src.addr, frame->dest.addr, frame->etype_len);
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "Encoded Ethernet frame (%zu bytes)", size);
 
@@ -98,6 +95,6 @@
 		return ENOMEM;
 
-	mac48_decode(hdr->src, &frame->src);
-	mac48_decode(hdr->dest, &frame->dest);
+	addr48(hdr->src, frame->src);
+	addr48(hdr->dest, frame->dest);
 	frame->etype_len = uint16_t_be2host(hdr->etype_len);
 
@@ -105,34 +102,7 @@
 	    frame->size);
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Decoding Ethernet frame "
-	    "src=%" PRIx64 " dest=%" PRIx64 " etype=%x",
-	    frame->src.addr, frame->dest.addr, frame->etype_len);
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "Decoded Ethernet frame payload (%zu bytes)", frame->size);
 
 	return EOK;
-}
-
-void mac48_encode(mac48_addr_t *addr, void *buf)
-{
-	uint64_t val;
-	uint8_t *bbuf = (uint8_t *)buf;
-	int i;
-
-	val = addr->addr;
-	for (i = 0; i < MAC48_BYTES; i++)
-		bbuf[i] = (val >> (8 * (MAC48_BYTES - i - 1))) & 0xff;
-}
-
-void mac48_decode(void *data, mac48_addr_t *addr)
-{
-	uint64_t val;
-	uint8_t *bdata = (uint8_t *)data;
-	int i;
-
-	val = 0;
-	for (i = 0; i < MAC48_BYTES; i++)
-		val |= (uint64_t)bdata[i] << (8 * (MAC48_BYTES - i - 1));
-
-	addr->addr = val;
 }
 
@@ -168,8 +138,8 @@
 	pfmt->proto_addr_size = IPV4_ADDR_SIZE;
 	pfmt->opcode = host2uint16_t_be(fopcode);
-	mac48_encode(&packet->sender_hw_addr, pfmt->sender_hw_addr);
+	addr48(packet->sender_hw_addr, pfmt->sender_hw_addr);
 	pfmt->sender_proto_addr =
 	    host2uint32_t_be(packet->sender_proto_addr);
-	mac48_encode(&packet->target_hw_addr, pfmt->target_hw_addr);
+	addr48(packet->target_hw_addr, pfmt->target_hw_addr);
 	pfmt->target_proto_addr =
 	    host2uint32_t_be(packet->target_proto_addr);
@@ -227,8 +197,8 @@
 	}
 
-	mac48_decode(pfmt->sender_hw_addr, &packet->sender_hw_addr);
+	addr48(pfmt->sender_hw_addr, packet->sender_hw_addr);
 	packet->sender_proto_addr =
 	    uint32_t_be2host(pfmt->sender_proto_addr);
-	mac48_decode(pfmt->target_hw_addr, &packet->target_hw_addr);
+	addr48(pfmt->target_hw_addr, packet->target_hw_addr);
 	packet->target_proto_addr =
 	    uint32_t_be2host(pfmt->target_proto_addr);
Index: uspace/srv/net/ethip/pdu.h
===================================================================
--- uspace/srv/net/ethip/pdu.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/pdu.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -42,6 +42,4 @@
 extern int eth_pdu_encode(eth_frame_t *, void **, size_t *);
 extern int eth_pdu_decode(void *, size_t, eth_frame_t *);
-extern void mac48_encode(mac48_addr_t *, void *);
-extern void mac48_decode(void *, mac48_addr_t *);
 extern int arp_pdu_encode(arp_eth_packet_t *, void **, size_t *);
 extern int arp_pdu_decode(void *, size_t, arp_eth_packet_t *);
Index: uspace/srv/net/ethip/std.h
===================================================================
--- uspace/srv/net/ethip/std.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/ethip/std.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -39,4 +39,5 @@
 
 #include <sys/types.h>
+#include <inet/addr.h>
 
 #define ETH_ADDR_SIZE       6
@@ -47,7 +48,7 @@
 typedef struct {
 	/** Destination Address */
-	uint8_t dest[ETH_ADDR_SIZE];
+	addr48_t dest;
 	/** Source Address */
-	uint8_t src[ETH_ADDR_SIZE];
+	addr48_t src;
 	/** Ethertype or Length */
 	uint16_t etype_len;
@@ -67,9 +68,9 @@
 	uint16_t opcode;
 	/** Sender hardware address */
-	uint8_t sender_hw_addr[ETH_ADDR_SIZE];
+	addr48_t sender_hw_addr;
 	/** Sender protocol address */
 	uint32_t sender_proto_addr;
 	/** Target hardware address */
-	uint8_t target_hw_addr[ETH_ADDR_SIZE];
+	addr48_t target_hw_addr;
 	/** Target protocol address */
 	uint32_t target_proto_addr;
@@ -87,6 +88,7 @@
 /** IP Ethertype */
 enum ether_type {
-	ETYPE_ARP = 0x0806,
-	ETYPE_IP  = 0x0800
+	ETYPE_ARP  = 0x0806,
+	ETYPE_IP   = 0x0800,
+	ETYPE_IPV6 = 0x86DD
 };
 
Index: uspace/srv/net/inetsrv/Makefile
===================================================================
--- uspace/srv/net/inetsrv/Makefile	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/Makefile	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -35,5 +35,4 @@
 	inetsrv.c \
 	inet_link.c \
-	inet_util.c \
 	inetcfg.c \
 	inetping.c \
Index: uspace/srv/net/inetsrv/addrobj.c
===================================================================
--- uspace/srv/net/inetsrv/addrobj.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/addrobj.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -42,9 +42,7 @@
 #include <stdlib.h>
 #include <str.h>
-
 #include "addrobj.h"
 #include "inetsrv.h"
 #include "inet_link.h"
-#include "inet_util.h"
 
 static inet_addrobj_t *inet_addrobj_find_by_name_locked(const char *, inet_link_t *);
@@ -106,15 +104,11 @@
 /** Find address object matching address @a addr.
  *
- * @param addr	Address
- * @oaram find	iaf_net to find network (using mask),
- *		iaf_addr to find local address (exact match)
+ * @param addr Address
+ * @oaram find iaf_net to find network (using mask),
+ *             iaf_addr to find local address (exact match)
+ *
  */
 inet_addrobj_t *inet_addrobj_find(inet_addr_t *addr, inet_addrobj_find_t find)
 {
-	uint32_t addr_addr;
-	int rc = inet_addr_pack(addr, &addr_addr);
-	if (rc != EOK)
-		return NULL;
-	
 	fibril_mutex_lock(&addr_list_lock);
 	
@@ -123,12 +117,5 @@
 		    inet_addrobj_t, addr_list);
 		
-		uint32_t naddr_addr;
-		uint8_t naddr_bits;
-		rc = inet_naddr_pack(&naddr->naddr, &naddr_addr, &naddr_bits);
-		if (rc != EOK)
-			continue;
-		
-		uint32_t mask = inet_netmask(naddr_bits);
-		if ((naddr_addr & mask) == (addr_addr & mask)) {
+		if (inet_naddr_compare_mask(&naddr->naddr, addr)) {
 			fibril_mutex_unlock(&addr_list_lock);
 			log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: found %p",
@@ -227,7 +214,5 @@
 	inet_naddr_addr(&addr->naddr, &lsrc_addr);
 	
-	inet_addr_t *ldest_addr = ldest;
-	
-	return inet_link_send_dgram(addr->ilink, &lsrc_addr, ldest_addr, dgram,
+	return inet_link_send_dgram(addr->ilink, &lsrc_addr, ldest, dgram,
 	    proto, ttl, df);
 }
Index: uspace/srv/net/inetsrv/icmp.c
===================================================================
--- uspace/srv/net/inetsrv/icmp.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/icmp.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -40,5 +40,5 @@
 #include <mem.h>
 #include <stdlib.h>
-
+#include <net/socket_codes.h>
 #include "icmp.h"
 #include "icmp_std.h"
@@ -129,11 +129,11 @@
 	inetping_sdu_t sdu;
 	
-	int rc = inet_addr_pack(&dgram->src, &sdu.src);
-	if (rc != EOK)
-		return rc;
+	uint16_t family = inet_addr_get(&dgram->src, &sdu.src, NULL);
+	if (family != AF_INET)
+		return EINVAL;
 	
-	rc = inet_addr_pack(&dgram->dest, &sdu.dest);
-	if (rc != EOK)
-		return rc;
+	family = inet_addr_get(&dgram->dest, &sdu.dest, NULL);
+	if (family != AF_INET)
+		return EINVAL;
 	
 	sdu.seq_no = uint16_t_be2host(reply->seq_no);
@@ -168,6 +168,6 @@
 	inet_dgram_t dgram;
 	
-	inet_addr_unpack(sdu->src, &dgram.src);
-	inet_addr_unpack(sdu->dest, &dgram.dest);
+	inet_addr_set(sdu->src, &dgram.src);
+	inet_addr_set(sdu->dest, &dgram.dest);
 	
 	dgram.tos = ICMP_TOS;
Index: uspace/srv/net/inetsrv/inet_link.c
===================================================================
--- uspace/srv/net/inetsrv/inet_link.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/inet_link.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -43,5 +43,5 @@
 #include <stdlib.h>
 #include <str.h>
-
+#include <net/socket_codes.h>
 #include "addrobj.h"
 #include "inetsrv.h"
@@ -49,6 +49,6 @@
 #include "pdu.h"
 
-static int inet_link_open(service_id_t sid);
-static int inet_iplink_recv(iplink_t *ilink, iplink_sdu_t *sdu);
+static int inet_link_open(service_id_t);
+static int inet_iplink_recv(iplink_t *, iplink_recv_sdu_t *, uint16_t);
 
 static iplink_ev_ops_t inet_iplink_ev_ops = {
@@ -59,11 +59,23 @@
 static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock);
 
-static int inet_iplink_recv(iplink_t *iplink, iplink_sdu_t *sdu)
-{
+static int inet_iplink_recv(iplink_t *iplink, iplink_recv_sdu_t *sdu, uint16_t af)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()");
+	
+	int rc;
 	inet_packet_t packet;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()");
-	rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
+	
+	switch (af) {
+	case AF_INET:
+		rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		return ENOTSUP;
+	default:
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "invalid address family");
+		return EINVAL;
+	}
+	
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "failed decoding PDU");
@@ -228,5 +240,5 @@
 
 	return EOK;
-
+	
 error:
 	if (ilink->iplink != NULL)
@@ -277,18 +289,13 @@
 	
 	iplink_sdu_t sdu;
-	
-	int rc = inet_addr_pack(lsrc, &sdu.lsrc);
-	if (rc != EOK)
-		return rc;
-	
-	rc = inet_addr_pack(ldest, &sdu.ldest);
-	if (rc != EOK)
-		return rc;
-	
 	size_t offs = 0;
+	int rc;
+	
+	sdu.src = *lsrc;
+	sdu.dest = *ldest;
+	
 	do {
+		/* Encode one fragment */
 		size_t roffs;
-		
-		/* Encode one fragment */
 		rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data,
 		    &sdu.size, &roffs);
Index: pace/srv/net/inetsrv/inet_util.c
===================================================================
--- uspace/srv/net/inetsrv/inet_util.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <assert.h>
-#include <bitops.h>
-#include <sys/types.h>
-#include "inet_util.h"
-
-uint32_t inet_netmask(int bits)
-{
-	assert(bits >= 0);
-	assert(bits < 32);
-
-	if (bits == 0)
-		return 0;
-	else
-		return BIT_RANGE(uint32_t, 31, 31 - (bits - 1));
-}
-
-/** @}
- */
Index: pace/srv/net/inetsrv/inet_util.h
===================================================================
--- uspace/srv/net/inetsrv/inet_util.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INET_UTIL_H_
-#define INET_UTIL_H_
-
-#include <sys/types.h>
-
-uint32_t inet_netmask(int bits);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/inetsrv/inetcfg.c
===================================================================
--- uspace/srv/net/inetsrv/inetcfg.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/inetcfg.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -236,29 +236,45 @@
 }
 
-static void inetcfg_addr_create_static_srv(ipc_callid_t callid,
-    ipc_call_t *call)
-{
+static void inetcfg_addr_create_static_srv(ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_create_static_srv()");
+	
+	sysarg_t link_id = IPC_GET_ARG1(*icall);
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	if (size != sizeof(inet_naddr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	inet_naddr_t naddr;
+	int rc = async_data_write_finalize(callid, &naddr, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
 	char *name;
-	inet_naddr_t naddr;
-	sysarg_t link_id;
-	sysarg_t addr_id;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_create_static_srv()");
-
 	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
 	    0, NULL);
 	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	inet_naddr_unpack(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call), &naddr);
-	link_id = IPC_GET_ARG3(*call);
-
-	addr_id = 0;
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	sysarg_t addr_id = 0;
 	rc = inetcfg_addr_create_static(name, &naddr, link_id, &addr_id);
 	free(name);
-	async_answer_1(callid, rc, addr_id);
+	async_answer_1(iid, rc, addr_id);
 }
 
@@ -276,9 +292,9 @@
 }
 
-static void inetcfg_addr_get_srv(ipc_callid_t callid, ipc_call_t *call)
+static void inetcfg_addr_get_srv(ipc_callid_t iid, ipc_call_t *icall)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_get_srv()");
 	
-	sysarg_t addr_id = IPC_GET_ARG1(*call);
+	sysarg_t addr_id = IPC_GET_ARG1(*icall);
 	
 	inet_addr_info_t ainfo;
@@ -288,33 +304,48 @@
 	ainfo.name = NULL;
 	
-	ipc_callid_t rcallid;
-	size_t max_size;
-	
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-	
 	int rc = inetcfg_addr_get(addr_id, &ainfo);
 	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	uint32_t naddr_addr;
-	uint8_t naddr_bits;
-	rc = inet_naddr_pack(&ainfo.naddr, &naddr_addr, &naddr_bits);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	sysarg_t retval = async_data_read_finalize(rcallid, ainfo.name,
-	    min(max_size, str_size(ainfo.name)));
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if (size != sizeof(inet_naddr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	rc = async_data_read_finalize(callid, &ainfo.naddr, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	rc = async_data_read_finalize(callid, ainfo.name,
+	    min(size, str_size(ainfo.name)));
 	free(ainfo.name);
 	
-	async_answer_3(callid, retval, (sysarg_t) naddr_addr,
-	    (sysarg_t) naddr_bits, ainfo.ilink);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	async_answer_1(iid, (sysarg_t) rc, ainfo.ilink);
 }
 
@@ -477,27 +508,63 @@
 }
 
-static void inetcfg_sroute_create_srv(ipc_callid_t callid,
-    ipc_call_t *call)
+static void inetcfg_sroute_create_srv(ipc_callid_t iid,
+    ipc_call_t *icall)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_create_srv()");
+
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	if (size != sizeof(inet_naddr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	inet_naddr_t dest;
+	int rc = async_data_write_finalize(callid, &dest, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	inet_addr_t router;
+	rc = async_data_write_finalize(callid, &router, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
 	
 	char *name;
-	int rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
 	    0, NULL);
 	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	inet_naddr_t dest;
-	inet_addr_t router;
-	
-	inet_naddr_unpack(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call), &dest);
-	inet_addr_unpack(IPC_GET_ARG3(*call), &router);
+		async_answer_0(iid, rc);
+		return;
+	}
 	
 	sysarg_t sroute_id = 0;
 	rc = inetcfg_sroute_create(name, &dest, &router, &sroute_id);
 	free(name);
-	async_answer_1(callid, rc, sroute_id);
+	async_answer_1(iid, rc, sroute_id);
 }
 
@@ -515,9 +582,9 @@
 }
 
-static void inetcfg_sroute_get_srv(ipc_callid_t callid, ipc_call_t *call)
+static void inetcfg_sroute_get_srv(ipc_callid_t iid, ipc_call_t *icall)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_get_srv()");
 	
-	sysarg_t sroute_id = IPC_GET_ARG1(*call);
+	sysarg_t sroute_id = IPC_GET_ARG1(*icall);
 	
 	inet_sroute_info_t srinfo;
@@ -527,39 +594,61 @@
 	srinfo.name = NULL;
 	
-	ipc_callid_t rcallid;
-	size_t max_size;
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-	
 	int rc = inetcfg_sroute_get(sroute_id, &srinfo);
 	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	uint32_t dest_addr;
-	uint8_t dest_bits;
-	rc = inet_naddr_pack(&srinfo.dest, &dest_addr, &dest_bits);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	uint32_t router_addr;
-	rc = inet_addr_pack(&srinfo.router, &router_addr);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	sysarg_t retval = async_data_read_finalize(rcallid, srinfo.name,
-	    min(max_size, str_size(srinfo.name)));
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if (size != sizeof(inet_naddr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	rc = async_data_read_finalize(callid, &srinfo.dest, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if (size != sizeof(inet_addr_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	rc = async_data_read_finalize(callid, &srinfo.router, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	rc = async_data_read_finalize(callid, srinfo.name,
+	    min(size, str_size(srinfo.name)));
 	free(srinfo.name);
 	
-	async_answer_3(callid, retval, (sysarg_t) dest_addr,
-	    (sysarg_t) dest_bits, (sysarg_t) router_addr);
+	async_answer_0(iid, (sysarg_t) rc);
 }
 
Index: uspace/srv/net/inetsrv/inetping.c
===================================================================
--- uspace/srv/net/inetsrv/inetping.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/inetping.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -43,5 +43,5 @@
 #include <stdlib.h>
 #include <sys/types.h>
-
+#include <net/socket_codes.h>
 #include "icmp.h"
 #include "icmp_std.h"
@@ -55,6 +55,4 @@
 static uint16_t inetping_ident = 0;
 
-static inetping_client_t *inetping_client_find(uint16_t);
-
 static int inetping_send(inetping_client_t *client, inetping_sdu_t *sdu)
 {
@@ -62,9 +60,9 @@
 }
 
-static int inetping_get_srcaddr(inetping_client_t *client, uint32_t remote,
-    uint32_t *local)
+static int inetping_get_srcaddr(inetping_client_t *client, addr32_t remote,
+    addr32_t *local)
 {
 	inet_addr_t remote_addr;
-	inet_addr_unpack(remote, &remote_addr);
+	inet_addr_set(remote, &remote_addr);
 	
 	inet_addr_t local_addr;
@@ -73,24 +71,44 @@
 		return rc;
 	
-	return inet_addr_pack(&local_addr, local);
+	uint16_t family = inet_addr_get(&local_addr, local, NULL);
+	if (family != AF_INET)
+		return EINVAL;
+	
+	return EOK;
+}
+
+static inetping_client_t *inetping_client_find(uint16_t ident)
+{
+	fibril_mutex_lock(&client_list_lock);
+	
+	list_foreach(client_list, link) {
+		inetping_client_t *client = list_get_instance(link,
+		    inetping_client_t, client_list);
+		
+		if (client->ident == ident) {
+			fibril_mutex_unlock(&client_list_lock);
+			return client;
+		}
+	}
+	
+	fibril_mutex_unlock(&client_list_lock);
+	return NULL;
 }
 
 int inetping_recv(uint16_t ident, inetping_sdu_t *sdu)
 {
-	inetping_client_t *client;
-	async_exch_t *exch;
-	ipc_call_t answer;
-
-	client = inetping_client_find(ident);
+	inetping_client_t *client = inetping_client_find(ident);
 	if (client == NULL) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "Unknown ICMP ident. Dropping.");
 		return ENOENT;
 	}
-
-	exch = async_exchange_begin(client->sess);
-
+	
+	async_exch_t *exch = async_exchange_begin(client->sess);
+	
+	ipc_call_t answer;
 	aid_t req = async_send_3(exch, INETPING_EV_RECV, (sysarg_t) sdu->src,
 	    (sysarg_t) sdu->dest, sdu->seq_no, &answer);
 	int rc = async_data_write_start(exch, sdu->data, sdu->size);
+	
 	async_exchange_end(exch);
 	
@@ -170,33 +188,13 @@
 }
 
-static inetping_client_t *inetping_client_find(uint16_t ident)
-{
-	fibril_mutex_lock(&client_list_lock);
-
-	list_foreach(client_list, link) {
-		inetping_client_t *client = list_get_instance(link,
-		    inetping_client_t, client_list);
-
-		if (client->ident == ident) {
-			fibril_mutex_unlock(&client_list_lock);
-			return client;
-		}
-	}
-
-	fibril_mutex_unlock(&client_list_lock);
-	return NULL;
-}
-
 void inetping_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	inetping_client_t client;
-	int rc;
-
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_conn()");
-
+	
 	/* Accept the connection */
 	async_answer_0(iid, EOK);
-
-	rc = inetping_client_init(&client);
+	
+	inetping_client_t client;
+	int rc = inetping_client_init(&client);
 	if (rc != EOK)
 		return;
Index: uspace/srv/net/inetsrv/inetsrv.c
===================================================================
--- uspace/srv/net/inetsrv/inetsrv.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/inetsrv.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -46,5 +46,5 @@
 #include <stdlib.h>
 #include <sys/types.h>
-
+#include <net/socket_codes.h>
 #include "addrobj.h"
 #include "icmp.h"
@@ -202,7 +202,9 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_get_srcaddr_srv()");
 	
+	addr32_t remote_v4 = IPC_GET_ARG1(*call);
+	uint8_t tos = IPC_GET_ARG2(*call);
+	
 	inet_addr_t remote;
-	inet_addr_unpack(IPC_GET_ARG1(*call), &remote);
-	uint8_t tos = IPC_GET_ARG2(*call);
+	inet_addr_set(remote_v4, &remote);
 	
 	inet_addr_t local;
@@ -213,12 +215,12 @@
 	}
 	
-	uint32_t local_addr;
-	rc = inet_addr_pack(&local, &local_addr);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
+	addr32_t local_v4;
+	uint16_t family = inet_addr_get(&local, &local_v4, NULL);
+	if (family != AF_INET) {
+		async_answer_0(callid, EINVAL);
 		return;
 	}
 	
-	async_answer_1(callid, rc, (sysarg_t) local_addr);
+	async_answer_1(callid, rc, (sysarg_t) local_v4);
 }
 
@@ -228,8 +230,11 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_send_srv()");
 	
+	addr32_t src_v4 = IPC_GET_ARG1(*call);
+	addr32_t dest_v4 = IPC_GET_ARG2(*call);
+	
 	inet_dgram_t dgram;
 	
-	inet_addr_unpack(IPC_GET_ARG1(*call), &dgram.src);
-	inet_addr_unpack(IPC_GET_ARG2(*call), &dgram.dest);
+	inet_addr_set(src_v4, &dgram.src);
+	inet_addr_set(dest_v4, &dgram.dest);
 	dgram.tos = IPC_GET_ARG3(*call);
 	
@@ -371,33 +376,36 @@
 int inet_ev_recv(inet_client_t *client, inet_dgram_t *dgram)
 {
-	uint32_t src;
-	int rc = inet_addr_pack(&dgram->src, &src);
-	if (rc != EOK)
-		return rc;
-	
-	uint32_t dest;
-	rc = inet_addr_pack(&dgram->dest, &dest);
-	if (rc != EOK)
-		return rc;
-	
 	async_exch_t *exch = async_exchange_begin(client->sess);
 	
 	ipc_call_t answer;
-	aid_t req = async_send_3(exch, INET_EV_RECV, (sysarg_t) src,
-	    (sysarg_t) dest, dgram->tos, &answer);
-	rc = async_data_write_start(exch, dgram->data, dgram->size);
-	async_exchange_end(exch);
-	
-	if (rc != EOK) {
+	aid_t req = async_send_1(exch, INET_EV_RECV, dgram->tos, &answer);
+	
+	int rc = async_data_write_start(exch, &dgram->src, sizeof(inet_addr_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
 		async_forget(req);
 		return rc;
 	}
 	
+	rc = async_data_write_start(exch, &dgram->dest, sizeof(inet_addr_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+	
+	rc = async_data_write_start(exch, dgram->data, dgram->size);
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+	
 	sysarg_t retval;
 	async_wait_for(req, &retval);
-	if (retval != EOK)
-		return retval;
-	
-	return EOK;
+	
+	return (int) retval;
 }
 
Index: uspace/srv/net/inetsrv/pdu.c
===================================================================
--- uspace/srv/net/inetsrv/pdu.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/pdu.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -44,5 +44,5 @@
 #include <mem.h>
 #include <stdlib.h>
-
+#include <net/socket_codes.h>
 #include "inetsrv.h"
 #include "inet_std.h"
@@ -106,13 +106,14 @@
     void **rdata, size_t *rsize, size_t *roffs)
 {
-	uint32_t src_addr;
-	int rc = inet_addr_pack(&packet->src, &src_addr);
-	if (rc != EOK)
-		return rc;
-	
-	uint32_t dest_addr;
-	rc = inet_addr_pack(&packet->dest, &dest_addr);
-	if (rc != EOK)
-		return rc;
+	addr32_t src_v4;
+	addr128_t src_v6;
+	uint16_t src_af = inet_addr_get(&packet->src, &src_v4, &src_v6);
+	
+	addr32_t dest_v4;
+	addr128_t dest_v6;
+	uint16_t dest_af = inet_addr_get(&packet->dest, &dest_v4, &dest_v6);
+	
+	if (src_af != dest_af)
+		return EINVAL;
 	
 	/* Upper bound for fragment offset field */
@@ -123,5 +124,17 @@
 		return ELIMIT;
 	
-	size_t hdr_size = sizeof(ip_header_t);
+	size_t hdr_size;
+	
+	switch (src_af) {
+	case AF_INET:
+		hdr_size = sizeof(ip_header_t);
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		assert(false);
+	default:
+		assert(false);
+	}
+	
 	size_t data_offs = ROUND_UP(hdr_size, 4);
 	
@@ -164,21 +177,34 @@
 	
 	/* Encode header fields */
-	ip_header_t *hdr = (ip_header_t *) data;
-	
-	hdr->ver_ihl = (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t));
-	hdr->tos = packet->tos;
-	hdr->tot_len = host2uint16_t_be(size);
-	hdr->id = host2uint16_t_be(ident);
-	hdr->flags_foff = host2uint16_t_be(flags_foff);
-	hdr->ttl = packet->ttl;
-	hdr->proto = packet->proto;
-	hdr->chksum = 0;
-	hdr->src_addr = host2uint32_t_be(src_addr);
-	hdr->dest_addr = host2uint32_t_be(dest_addr);
-	
-	/* Compute checksum */
-	uint16_t chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *) hdr,
-	    hdr_size);
-	hdr->chksum = host2uint16_t_be(chksum);
+	ip_header_t *hdr;
+	
+	switch (src_af) {
+	case AF_INET:
+		hdr = (ip_header_t *) data;
+		
+		hdr->ver_ihl =
+		    (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t));
+		hdr->tos = packet->tos;
+		hdr->tot_len = host2uint16_t_be(size);
+		hdr->id = host2uint16_t_be(ident);
+		hdr->flags_foff = host2uint16_t_be(flags_foff);
+		hdr->ttl = packet->ttl;
+		hdr->proto = packet->proto;
+		hdr->chksum = 0;
+		hdr->src_addr = host2uint32_t_be(src_v4);
+		hdr->dest_addr = host2uint32_t_be(dest_v4);
+		
+		/* Compute checksum */
+		uint16_t chksum = inet_checksum_calc(INET_CHECKSUM_INIT,
+		    (void *) hdr, hdr_size);
+		hdr->chksum = host2uint16_t_be(chksum);
+		
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		return ENOTSUP;
+	default:
+		assert(false);
+	}
 	
 	/* Copy payload */
@@ -194,12 +220,4 @@
 int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet)
 {
-	ip_header_t *hdr;
-	size_t tot_len;
-	size_t data_offs;
-	uint8_t version;
-	uint16_t ident;
-	uint16_t flags_foff;
-	uint16_t foff;
-
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_pdu_decode()");
 	
@@ -208,15 +226,15 @@
 		return EINVAL;
 	}
-
-	hdr = (ip_header_t *)data;
-
-	version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h, VI_VERSION_l,
-	    hdr->ver_ihl);
+	
+	ip_header_t *hdr = (ip_header_t *) data;
+	
+	uint8_t version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h,
+	    VI_VERSION_l, hdr->ver_ihl);
 	if (version != 4) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "Version (%d) != 4", version);
 		return EINVAL;
 	}
-
-	tot_len = uint16_t_be2host(hdr->tot_len);
+	
+	size_t tot_len = uint16_t_be2host(hdr->tot_len);
 	if (tot_len < sizeof(ip_header_t)) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length too small (%zu)", tot_len);
@@ -229,13 +247,13 @@
 		return EINVAL;
 	}
-
-	ident = uint16_t_be2host(hdr->id);
-	flags_foff = uint16_t_be2host(hdr->flags_foff);
-	foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,
+	
+	uint16_t ident = uint16_t_be2host(hdr->id);
+	uint16_t flags_foff = uint16_t_be2host(hdr->flags_foff);
+	uint16_t foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,
 	    flags_foff);
 	/* XXX Checksum */
-
-	inet_addr_unpack(uint32_t_be2host(hdr->src_addr), &packet->src);
-	inet_addr_unpack(uint32_t_be2host(hdr->dest_addr), &packet->dest);
+	
+	inet_addr_set(uint32_t_be2host(hdr->src_addr), &packet->src);
+	inet_addr_set(uint32_t_be2host(hdr->dest_addr), &packet->dest);
 	packet->tos = hdr->tos;
 	packet->proto = hdr->proto;
@@ -248,7 +266,7 @@
 	
 	/* XXX IP options */
-	data_offs = sizeof(uint32_t) * BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h,
-	    VI_IHL_l, hdr->ver_ihl);
-
+	size_t data_offs = sizeof(uint32_t) *
+	    BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h, VI_IHL_l, hdr->ver_ihl);
+	
 	packet->size = tot_len - data_offs;
 	packet->data = calloc(packet->size, 1);
Index: uspace/srv/net/inetsrv/sroute.c
===================================================================
--- uspace/srv/net/inetsrv/sroute.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/inetsrv/sroute.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -42,9 +42,7 @@
 #include <stdlib.h>
 #include <str.h>
-
 #include "sroute.h"
 #include "inetsrv.h"
 #include "inet_link.h"
-#include "inet_util.h"
 
 static FIBRIL_MUTEX_INITIALIZE(sroute_list_lock);
@@ -97,8 +95,5 @@
 inet_sroute_t *inet_sroute_find(inet_addr_t *addr)
 {
-	uint32_t addr_addr;
-	int rc = inet_addr_pack(addr, &addr_addr);
-	if (rc != EOK)
-		return NULL;
+	uint16_t addr_af = inet_addr_get(addr, NULL, NULL);
 	
 	inet_sroute_t *best = NULL;
@@ -111,8 +106,10 @@
 		    inet_sroute_t, sroute_list);
 		
-		uint32_t dest_addr;
 		uint8_t dest_bits;
-		rc = inet_naddr_pack(&sroute->dest, &dest_addr, &dest_bits);
-		if (rc != EOK)
+		uint16_t dest_af = inet_naddr_get(&sroute->dest, NULL, NULL,
+		    &dest_bits);
+		
+		/* Skip comparison with different address family */
+		if (addr_af != dest_af)
 			continue;
 		
@@ -121,6 +118,5 @@
 			continue;
 		
-		uint32_t mask = inet_netmask(dest_bits);
-		if ((dest_addr & mask) == (addr_addr & mask)) {
+		if (inet_naddr_compare_mask(&sroute->dest, addr)) {
 			log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find: found candidate %p",
 			    sroute);
Index: uspace/srv/net/loopip/loopip.c
===================================================================
--- uspace/srv/net/loopip/loopip.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/loopip/loopip.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -39,4 +39,5 @@
 #include <errno.h>
 #include <inet/iplink_srv.h>
+#include <inet/addr.h>
 #include <io/log.h>
 #include <loc.h>
@@ -48,8 +49,8 @@
 static int loopip_open(iplink_srv_t *srv);
 static int loopip_close(iplink_srv_t *srv);
-static int loopip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu);
+static int loopip_send(iplink_srv_t *srv, iplink_sdu_t *sdu);
 static int loopip_get_mtu(iplink_srv_t *srv, size_t *mtu);
-static int loopip_addr_add(iplink_srv_t *srv, uint32_t addr);
-static int loopip_addr_remove(iplink_srv_t *srv, uint32_t addr);
+static int loopip_addr_add(iplink_srv_t *srv, inet_addr_t *addr);
+static int loopip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr);
 
 static void loopip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
@@ -69,5 +70,7 @@
 typedef struct {
 	link_t link;
-	iplink_srv_sdu_t sdu;
+	
+	uint16_t af;
+	iplink_recv_sdu_t sdu;
 } rqueue_entry_t;
 
@@ -77,7 +80,11 @@
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_recv_fibril(): Wait for one item");
 		link_t *link = prodcons_consume(&loopip_rcv_queue);
-		rqueue_entry_t *rqe = list_get_instance(link, rqueue_entry_t, link);
-
-		(void) iplink_ev_recv(&loopip_iplink, &rqe->sdu);
+		rqueue_entry_t *rqe =
+		    list_get_instance(link, rqueue_entry_t, link);
+		
+		(void) iplink_ev_recv(&loopip_iplink, &rqe->sdu, rqe->af);
+		
+		free(rqe->sdu.data);
+		free(rqe);
 	}
 	
@@ -87,12 +94,7 @@
 static int loopip_init(void)
 {
-	int rc;
-	service_id_t sid;
-	category_id_t iplink_cat;
-	const char *svc_name = "net/loopback";
-	
 	async_set_client_connection(loopip_client_conn);
 	
-	rc = loc_server_register(NAME);
+	int rc = loc_server_register(NAME);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
@@ -105,11 +107,15 @@
 	
 	prodcons_initialize(&loopip_rcv_queue);
-
+	
+	const char *svc_name = "net/loopback";
+	service_id_t sid;
 	rc = loc_service_register(svc_name, &sid);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service %s.", svc_name);
-		return rc;
-	}
-
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service %s.",
+		    svc_name);
+		return rc;
+	}
+	
+	category_id_t iplink_cat;
 	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
@@ -120,5 +126,6 @@
 	rc = loc_service_add_to_cat(sid, iplink_cat);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding %s to category.", svc_name);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding %s to category.",
+		    svc_name);
 		return rc;
 	}
@@ -151,11 +158,20 @@
 }
 
-static int loopip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
-{
-	rqueue_entry_t *rqe;
-
+static int loopip_send(iplink_srv_t *srv, iplink_sdu_t *sdu)
+{
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_send()");
-
-	rqe = calloc(1, sizeof(rqueue_entry_t));
+	
+	addr32_t src_v4;
+	addr128_t src_v6;
+	uint16_t src_af = inet_addr_get(&sdu->src, &src_v4, &src_v6);
+	
+	addr32_t dest_v4;
+	addr128_t dest_v6;
+	uint16_t dest_af = inet_addr_get(&sdu->dest, &dest_v4, &dest_v6);
+	
+	if (src_af != dest_af)
+		return EINVAL;
+	
+	rqueue_entry_t *rqe = calloc(1, sizeof(rqueue_entry_t));
 	if (rqe == NULL)
 		return ENOMEM;
@@ -164,6 +180,5 @@
 	 * Clone SDU
 	 */
-	rqe->sdu.lsrc = sdu->ldest;
-	rqe->sdu.ldest = sdu->lsrc;
+	rqe->af = src_af;
 	rqe->sdu.data = malloc(sdu->size);
 	if (rqe->sdu.data == NULL) {
@@ -190,13 +205,11 @@
 }
 
-static int loopip_addr_add(iplink_srv_t *srv, uint32_t addr)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_addr_add(0x%" PRIx32 ")", addr);
-	return EOK;
-}
-
-static int loopip_addr_remove(iplink_srv_t *srv, uint32_t addr)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_addr_remove(0x%" PRIx32 ")", addr);
+static int loopip_addr_add(iplink_srv_t *srv, inet_addr_t *addr)
+{
+	return EOK;
+}
+
+static int loopip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr)
+{
 	return EOK;
 }
@@ -204,18 +217,17 @@
 int main(int argc, char *argv[])
 {
-	int rc;
-
-	printf(NAME ": HelenOS loopback IP link provider\n");
-
-	if (log_init(NAME) != EOK) {
-		printf(NAME ": Failed to initialize logging.\n");
-		return 1;
+	printf("%s: HelenOS loopback IP link provider\n", NAME);
+	
+	int rc = log_init(NAME);
+	if (rc != EOK) {
+		printf("%s: Failed to initialize logging.\n", NAME);
+		return rc;
 	}
 	
 	rc = loopip_init();
 	if (rc != EOK)
-		return 1;
-
-	printf(NAME ": Accepting connections.\n");
+		return rc;
+	
+	printf("%s: Accepting connections.\n", NAME);
 	task_retval(0);
 	async_manager();
Index: uspace/srv/net/slip/slip.c
===================================================================
--- uspace/srv/net/slip/slip.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/slip/slip.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -38,4 +38,6 @@
 #include <stdint.h>
 #include <loc.h>
+#include <net/socket_codes.h>
+#include <inet/addr.h>
 #include <inet/iplink_srv.h>
 #include <device/char_dev.h>
@@ -50,13 +52,13 @@
 #define SLIP_END	0300
 #define SLIP_ESC	0333
-#define	SLIP_ESC_END	0334
+#define SLIP_ESC_END	0334
 #define SLIP_ESC_ESC	0335
 
 static int slip_open(iplink_srv_t *);
 static int slip_close(iplink_srv_t *);
-static int slip_send(iplink_srv_t *, iplink_srv_sdu_t *);
+static int slip_send(iplink_srv_t *, iplink_sdu_t *);
 static int slip_get_mtu(iplink_srv_t *, size_t *);
-static int slip_addr_add(iplink_srv_t *, uint32_t);
-static int slip_addr_remove(iplink_srv_t *, uint32_t);
+static int slip_addr_add(iplink_srv_t *, inet_addr_t *);
+static int slip_addr_remove(iplink_srv_t *, inet_addr_t *);
 
 static iplink_srv_t slip_iplink;
@@ -118,5 +120,5 @@
 }
 
-int slip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
+int slip_send(iplink_srv_t *srv, iplink_sdu_t *sdu)
 {
 	async_sess_t *sess = (async_sess_t *) srv->arg;
@@ -137,5 +139,5 @@
 		case SLIP_END:
 			write_buffered(sess, SLIP_ESC);
-			write_buffered(sess, SLIP_ESC_END);	
+			write_buffered(sess, SLIP_ESC_END);
 			break;
 		case SLIP_ESC:
@@ -161,5 +163,5 @@
 }
 
-int slip_addr_add(iplink_srv_t *srv, uint32_t addr)
+int slip_addr_add(iplink_srv_t *srv, inet_addr_t *addr)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "slip_addr_add()");
@@ -167,5 +169,5 @@
 }
 
-int slip_addr_remove(iplink_srv_t *srv, uint32_t addr)
+int slip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "slip_addr_remove()");
@@ -207,10 +209,8 @@
 	async_sess_t *sess = (async_sess_t *) arg;
 	static uint8_t recv_final[SLIP_MTU];
-	iplink_srv_sdu_t sdu;
+	iplink_recv_sdu_t sdu;
 	uint8_t ch;
 	int rc;
 
-	sdu.lsrc = 0;
-	sdu.ldest = 0;
 	sdu.data = recv_final;
 
@@ -222,6 +222,6 @@
 				if (sdu.size == 0) {
 					/*
- 					 * Discard the empty SLIP datagram.
- 					 */
+					 * Discard the empty SLIP datagram.
+					 */
 					break;
 				}
@@ -260,5 +260,5 @@
 
 pass:
-		rc = iplink_ev_recv(&slip_iplink, &sdu);
+		rc = iplink_ev_recv(&slip_iplink, &sdu, AF_INET);
 		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_ERROR,
Index: uspace/srv/net/tcp/pdu.c
===================================================================
--- uspace/srv/net/tcp/pdu.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/tcp/pdu.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -40,4 +40,5 @@
 #include <mem.h>
 #include <stdlib.h>
+#include <net/socket_codes.h>
 #include "pdu.h"
 #include "segment.h"
@@ -144,19 +145,33 @@
 }
 
-static void tcp_phdr_setup(tcp_pdu_t *pdu, tcp_phdr_t *phdr)
-{
-	// FIXME: Check for correctness
-	
-	uint32_t src_addr;
-	inet_addr_pack(&pdu->src_addr, &src_addr);
-	
-	uint32_t dest_addr;
-	inet_addr_pack(&pdu->dest_addr, &dest_addr);
-	
-	phdr->src_addr = host2uint32_t_be(src_addr);
-	phdr->dest_addr = host2uint32_t_be(dest_addr);
-	phdr->zero = 0;
-	phdr->protocol = 6; /* XXX Magic number */
-	phdr->tcp_length = host2uint16_t_be(pdu->header_size + pdu->text_size);
+static uint16_t tcp_phdr_setup(tcp_pdu_t *pdu, tcp_phdr_t *phdr)
+{
+	addr32_t src_v4;
+	addr128_t src_v6;
+	uint16_t src_af = inet_addr_get(&pdu->src, &src_v4, &src_v6);
+	
+	addr32_t dest_v4;
+	addr128_t dest_v6;
+	uint16_t dest_af = inet_addr_get(&pdu->dest, &dest_v4, &dest_v6);
+	
+	assert(src_af == dest_af);
+	
+	switch (src_af) {
+	case AF_INET:
+		phdr->src = host2uint32_t_be(src_v4);
+		phdr->dest = host2uint32_t_be(dest_v4);
+		phdr->zero = 0;
+		phdr->protocol = IP_PROTO_TCP;
+		phdr->tcp_length =
+		    host2uint16_t_be(pdu->header_size + pdu->text_size);
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		assert(false);
+	default:
+		assert(false);
+	}
+	
+	return src_af;
 }
 
@@ -243,14 +258,21 @@
 	uint16_t cs_phdr;
 	uint16_t cs_headers;
-	uint16_t cs_all;
 	tcp_phdr_t phdr;
-
-	tcp_phdr_setup(pdu, &phdr);
-	cs_phdr = tcp_checksum_calc(TCP_CHECKSUM_INIT, (void *)&phdr,
-	    sizeof(tcp_phdr_t));
+	
+	uint16_t af = tcp_phdr_setup(pdu, &phdr);
+	switch (af) {
+	case AF_INET:
+		cs_phdr = tcp_checksum_calc(TCP_CHECKSUM_INIT, (void *) &phdr,
+		    sizeof(tcp_phdr_t));
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		assert(false);
+	default:
+		assert(false);
+	}
+	
 	cs_headers = tcp_checksum_calc(cs_phdr, pdu->header, pdu->header_size);
-	cs_all = tcp_checksum_calc(cs_headers, pdu->text, pdu->text_size);
-
-	return cs_all;
+	return tcp_checksum_calc(cs_headers, pdu->text, pdu->text_size);
 }
 
@@ -279,7 +301,7 @@
 
 	sp->local.port = uint16_t_be2host(hdr->dest_port);
-	sp->local.addr = pdu->dest_addr;
+	sp->local.addr = pdu->dest;
 	sp->foreign.port = uint16_t_be2host(hdr->src_port);
-	sp->foreign.addr = pdu->src_addr;
+	sp->foreign.addr = pdu->src;
 
 	*seg = nseg;
@@ -298,6 +320,6 @@
 		return ENOMEM;
 
-	npdu->src_addr = sp->local.addr;
-	npdu->dest_addr = sp->foreign.addr;
+	npdu->src = sp->local.addr;
+	npdu->dest = sp->foreign.addr;
 	tcp_header_encode(sp, seg, &npdu->header, &npdu->header_size);
 
Index: uspace/srv/net/tcp/sock.c
===================================================================
--- uspace/srv/net/tcp/sock.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/tcp/sock.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -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));
Index: uspace/srv/net/tcp/std.h
===================================================================
--- uspace/srv/net/tcp/std.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/tcp/std.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -39,4 +39,7 @@
 
 #include <sys/types.h>
+#include <inet/addr.h>
+
+#define IP_PROTO_TCP  6
 
 /** TCP Header (fixed part) */
@@ -75,7 +78,7 @@
 typedef struct {
 	/** Source address */
-	uint32_t src_addr;
+	uint32_t src;
 	/** Destination address */
-	uint32_t dest_addr;
+	uint32_t dest;
 	/** Zero */
 	uint8_t zero;
Index: uspace/srv/net/tcp/tcp.c
===================================================================
--- uspace/srv/net/tcp/tcp.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/tcp/tcp.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -115,6 +115,6 @@
 	}
 
-	pdu->src_addr = dgram->src;
-	pdu->dest_addr = dgram->dest;
+	pdu->src = dgram->src;
+	pdu->dest = dgram->dest;
 
 	tcp_received_pdu(pdu);
@@ -143,6 +143,6 @@
 	    pdu->text_size);
 
-	dgram.src = pdu->src_addr;
-	dgram.dest = pdu->dest_addr;
+	dgram.src = pdu->src;
+	dgram.dest = pdu->dest;
 	dgram.tos = 0;
 	dgram.data = pdu_raw;
Index: uspace/srv/net/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tcp/tcp_type.h	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/tcp/tcp_type.h	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -306,8 +306,7 @@
 typedef struct {
 	/** Source address */
-	inet_addr_t src_addr;
+	inet_addr_t src;
 	/** Destination address */
-	inet_addr_t dest_addr;
-	
+	inet_addr_t dest;
 	/** Encoded header */
 	void *header;
Index: uspace/srv/net/udp/pdu.c
===================================================================
--- uspace/srv/net/udp/pdu.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/udp/pdu.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -40,5 +40,6 @@
 #include <mem.h>
 #include <stdlib.h>
-
+#include <inet/addr.h>
+#include <net/socket_codes.h>
 #include "msg.h"
 #include "pdu.h"
@@ -84,19 +85,32 @@
 }
 
-static void udp_phdr_setup(udp_pdu_t *pdu, udp_phdr_t *phdr)
-{
-	// FIXME: Check for correctness
-	
-	uint32_t src;
-	inet_addr_pack(&pdu->src, &src);
-	
-	uint32_t dest;
-	inet_addr_pack(&pdu->dest, &dest);
-	
-	phdr->src_addr = host2uint32_t_be(src);
-	phdr->dest_addr = host2uint32_t_be(dest);
-	phdr->zero = 0;
-	phdr->protocol = IP_PROTO_UDP;
-	phdr->udp_length = host2uint16_t_be(pdu->data_size);
+static uint16_t udp_phdr_setup(udp_pdu_t *pdu, udp_phdr_t *phdr)
+{
+	addr32_t src_v4;
+	addr128_t src_v6;
+	uint16_t src_af = inet_addr_get(&pdu->src, &src_v4, &src_v6);
+	
+	addr32_t dest_v4;
+	addr128_t dest_v6;
+	uint16_t dest_af = inet_addr_get(&pdu->dest, &dest_v4, &dest_v6);
+	
+	assert(src_af == dest_af);
+	
+	switch (src_af) {
+	case AF_INET:
+		phdr->src_addr = host2uint32_t_be(src_v4);
+		phdr->dest_addr = host2uint32_t_be(dest_v4);
+		phdr->zero = 0;
+		phdr->protocol = IP_PROTO_UDP;
+		phdr->udp_length = host2uint16_t_be(pdu->data_size);
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		assert(false);
+	default:
+		assert(false);
+	}
+	
+	return src_af;
 }
 
@@ -115,13 +129,20 @@
 {
 	uint16_t cs_phdr;
-	uint16_t cs_all;
 	udp_phdr_t phdr;
-
-	udp_phdr_setup(pdu, &phdr);
-	cs_phdr = udp_checksum_calc(UDP_CHECKSUM_INIT, (void *)&phdr,
-	    sizeof(udp_phdr_t));
-	cs_all = udp_checksum_calc(cs_phdr, pdu->data, pdu->data_size);
-
-	return cs_all;
+	
+	uint16_t af = udp_phdr_setup(pdu, &phdr);
+	switch (af) {
+	case AF_INET:
+		cs_phdr = udp_checksum_calc(UDP_CHECKSUM_INIT, (void *) &phdr,
+		    sizeof(udp_phdr_t));
+		break;
+	case AF_INET6:
+		// FIXME TODO
+		assert(false);
+	default:
+		assert(false);
+	}
+	
+	return udp_checksum_calc(cs_phdr, pdu->data, pdu->data_size);
 }
 
Index: uspace/srv/net/udp/sock.c
===================================================================
--- uspace/srv/net/udp/sock.c	(revision edf0d273d18a4466ab749a9c51b5b32133fb2693)
+++ uspace/srv/net/udp/sock.c	(revision 02a09ed9ab72cd7eb2ca3f11873db078ab906acc)
@@ -159,31 +159,27 @@
 static void udp_sock_bind(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	int rc;
-	struct sockaddr_in *addr;
-	size_t addr_size;
-	socket_core_t *sock_core;
-	udp_sockdata_t *socket;
-	udp_sock_t fsock;
-	udp_error_t urc;
-
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_bind()");
 	log_msg(LOG_DEFAULT, LVL_DEBUG, " - async_data_write_accept");
-
-	addr = NULL;
-
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_size);
+	
+	struct sockaddr_in6 *addr6 = NULL;
+	size_t addr_len;
+	int rc = async_data_write_accept((void **) &addr6, false, 0, 0, 0, &addr_len);
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		goto out;
-	}
-	
-	if (addr_size != sizeof(struct sockaddr_in)) {
+		return;
+	}
+	
+	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;
+	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_bind");
+	
 	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
-	    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
+	    addr6, addr_len, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
 	    last_used_port);
 	if (rc != EOK) {
@@ -193,17 +189,33 @@
 	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_cores_find");
-	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
+	
+	socket_core_t *sock_core = socket_cores_find(&client->sockets,
+	    SOCKET_GET_SOCKET_ID(call));
 	if (sock_core == NULL) {
 		async_answer_0(callid, ENOENT);
 		goto out;
 	}
-
-	socket = (udp_sockdata_t *) sock_core->specific_data;
-	
-	inet_addr_unpack(uint32_t_be2host(addr->sin_addr.s_addr),
-	    &fsock.addr);
-	fsock.port = sock_core->port;
-	urc = udp_uc_set_local(socket->assoc, &fsock);
-
+	
+	udp_sockdata_t *socket =
+	    (udp_sockdata_t *) sock_core->specific_data;
+	
+	udp_sock_t fsocket;
+	
+	fsocket.port = sock_core->port;
+	
+	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:
+		async_answer_0(callid, EINVAL);
+		goto out;
+	}
+	
+	udp_error_t urc = udp_uc_set_local(socket->assoc, &fsocket);
+	
 	switch (urc) {
 	case UDP_EOK:
@@ -225,7 +237,8 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, " - success");
 	async_answer_0(callid, rc);
+	
 out:
-	if (addr != NULL)
-		free(addr);
+	if (addr6 != NULL)
+		free(addr6);
 }
 
@@ -252,28 +265,42 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_send()");
 	
-	struct sockaddr_in *addr = NULL;
-	udp_sock_t fsock;
-	udp_sock_t *fsock_ptr;
+	struct sockaddr_in6 *addr6 = NULL;
+	struct sockaddr_in *addr;
+	udp_sock_t fsocket;
+	udp_sock_t *fsocket_ptr;
 	
 	if (IPC_GET_IMETHOD(call) == NET_SOCKET_SENDTO) {
-		size_t addr_size;
-		int rc = async_data_write_accept((void **) &addr, false,
-		    0, 0, 0, &addr_size);
+		size_t addr_len;
+		int rc = async_data_write_accept((void **) &addr6, false,
+		    0, 0, 0, &addr_len);
 		if (rc != EOK) {
 			async_answer_0(callid, rc);
-			goto out;
-		}
-		
-		if (addr_size != sizeof(struct sockaddr_in)) {
+			return;
+		}
+		
+		if ((addr_len != sizeof(struct sockaddr_in)) &&
+		    (addr_len != sizeof(struct sockaddr_in6))) {
 			async_answer_0(callid, EINVAL);
 			goto out;
 		}
 		
-		inet_addr_unpack(uint32_t_be2host(addr->sin_addr.s_addr),
-		    &fsock.addr);
-		fsock.port = uint16_t_be2host(addr->sin_port);
-		fsock_ptr = &fsock;
+		addr = (struct sockaddr_in *) addr6;
+		
+		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:
+			async_answer_0(callid, EINVAL);
+			goto out;
+		}
+		
+		fsocket.port = uint16_t_be2host(addr->sin_port);
+		fsocket_ptr = &fsocket;
 	} else
-		fsock_ptr = NULL;
+		fsocket_ptr = NULL;
 	
 	int socket_id = SOCKET_GET_SOCKET_ID(call);
@@ -321,5 +348,5 @@
 		inet_addr_t rem_addr;
 		
-		rem_addr = fsock_ptr ? fsock.addr :
+		rem_addr = fsocket_ptr ? fsocket.addr :
 		    socket->assoc->ident.foreign.addr;
 		
@@ -361,5 +388,5 @@
 		
 		udp_error_t urc =
-		    udp_uc_send(socket->assoc, fsock_ptr, buffer, length, 0);
+		    udp_uc_send(socket->assoc, fsocket_ptr, buffer, length, 0);
 		
 		switch (urc) {
@@ -396,35 +423,24 @@
 	
 out:
-	if (addr != NULL)
-		free(addr);
+	if (addr6 != NULL)
+		free(addr6);
 }
 
 static void udp_sock_recvfrom(udp_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;
-	udp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t rcallid;
-	size_t data_len;
-	udp_error_t urc;
-	udp_sock_t *rsock;
-	struct sockaddr_in addr;
-	int rc;
-
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "%p: udp_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 = (udp_sockdata_t *)sock_core->specific_data;
+	
+	udp_sockdata_t *socket =
+	    (udp_sockdata_t *) sock_core->specific_data;
+	
 	fibril_mutex_lock(&socket->lock);
 	
@@ -434,10 +450,11 @@
 		return;
 	}
-
-	(void)flags;
-
+	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): lock recv_buffer lock");
+	
 	fibril_mutex_lock(&socket->recv_buffer_lock);
-	while (socket->recv_buffer_used == 0 && socket->recv_error == UDP_EOK) {
+	
+	while ((socket->recv_buffer_used == 0) &&
+	    (socket->recv_error == UDP_EOK)) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): wait for cv");
 		fibril_condvar_wait(&socket->recv_buffer_cv,
@@ -446,11 +463,12 @@
 	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "Got data in sock recv_buffer");
-
-	rsock = &socket->recv_fsock;
-	data_len = socket->recv_buffer_used;
-	urc = socket->recv_error;
-
+	
+	size_t data_len = socket->recv_buffer_used;
+	udp_error_t urc = socket->recv_error;
+	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "**** recv data_len=%zu", data_len);
-
+	
+	int rc;
+	
 	switch (urc) {
 	case UDP_EOK:
@@ -476,22 +494,72 @@
 		return;
 	}
-
+	
+	ipc_callid_t rcallid;
+	size_t addr_size = 0;
+	
 	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
 		/* Fill address */
-		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;
-		}
-		
-		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)) {
+		udp_sock_t *rsock = &socket->recv_fsock;
+		struct sockaddr_in addr;
+		struct sockaddr_in6 addr6;
+		size_t addr_length;
+		
+		uint16_t addr_af = inet_addr_sockaddr_in(&rsock->addr, &addr,
+		    &addr6);
+		
+		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);
+			
+			addr_size = 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);
+			
+			addr_size = 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);
@@ -499,19 +567,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);
@@ -525,13 +583,17 @@
 	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "data read finalize");
+	
 	rc = async_data_read_finalize(rcallid, socket->recv_buffer, length);
-
-	if (length < data_len && rc == EOK)
+	
+	if ((length < data_len) && (rc == EOK))
 		rc = EOVERFLOW;
 	
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "read_data_length <- %zu", length);
+	
+	ipc_call_t answer;
+	
 	IPC_SET_ARG2(answer, 0);
 	SOCKET_SET_READ_DATA_LENGTH(answer, length);
-	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(addr));
+	SOCKET_SET_ADDRESS_LENGTH(answer, addr_size);
 	async_answer_3(callid, EOK, IPC_GET_ARG1(answer),
 	    IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
@@ -634,4 +696,5 @@
 			log_msg(LOG_DEFAULT, LVL_DEBUG, "[] urc != UDP_EOK, break");
 			fibril_condvar_broadcast(&sock->recv_buffer_cv);
+			fibril_mutex_unlock(&sock->recv_buffer_lock);
 			break;
 		}
