Index: uspace/srv/net/inetsrv/inetping.c
===================================================================
--- uspace/srv/net/inetsrv/inetping.c	(revision 5a324d992b3382c26e5d9d448d8c857d73a4a6b4)
+++ uspace/srv/net/inetsrv/inetping.c	(revision 07733961aa0e69f8ccc3a986068ad31674911dbe)
@@ -1,4 +1,5 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2013 Jiri Svoboda
+ * Copyright (c) 2013 Martin Decky
  * All rights reserved.
  *
@@ -45,4 +46,5 @@
 #include <types/inetping.h>
 #include "icmp.h"
+#include "icmpv6.h"
 #include "icmp_std.h"
 #include "inetsrv.h"
@@ -57,23 +59,21 @@
 static int inetping_send(inetping_client_t *client, inetping_sdu_t *sdu)
 {
-	return icmp_ping_send(client->ident, sdu);
-}
-
-static int inetping_get_srcaddr(inetping_client_t *client, addr32_t remote,
-    addr32_t *local)
-{
-	inet_addr_t remote_addr;
-	inet_addr_set(remote, &remote_addr);
-	
-	inet_addr_t local_addr;
-	int rc = inet_get_srcaddr(&remote_addr, ICMP_TOS, &local_addr);
-	if (rc != EOK)
-		return rc;
-	
-	ip_ver_t ver = inet_addr_get(&local_addr, local, NULL);
-	if (ver != ip_v4)
+	if (sdu->src.version != sdu->dest.version)
 		return EINVAL;
-	
-	return EOK;
+
+	switch (sdu->src.version) {
+	case ip_v4:
+		return icmp_ping_send(client->ident, sdu);
+	case ip_v6:
+		return icmpv6_ping_send(client->ident, sdu);
+	default:
+		return EINVAL;
+	}
+}
+
+static int inetping_get_srcaddr(inetping_client_t *client,
+    inet_addr_t *remote, inet_addr_t *local)
+{
+	return inet_get_srcaddr(remote, ICMP_TOS, local);
 }
 
@@ -81,5 +81,5 @@
 {
 	fibril_mutex_lock(&client_list_lock);
-	
+
 	list_foreach(client_list, client_list, inetping_client_t, client) {
 		if (client->ident == ident) {
@@ -88,5 +88,5 @@
 		}
 	}
-	
+
 	fibril_mutex_unlock(&client_list_lock);
 	return NULL;
@@ -100,60 +100,155 @@
 		return ENOENT;
 	}
-	
+
 	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);
-	
-	if (rc != EOK) {
+	aid_t req = async_send_1(exch, INETPING_EV_RECV, sdu->seq_no, &answer);
+
+	int rc = async_data_write_start(exch, &sdu->src, sizeof(sdu->src));
+	if (rc != EOK) {
+		async_exchange_end(exch);
 		async_forget(req);
 		return rc;
 	}
-	
+
+	rc = async_data_write_start(exch, &sdu->dest, sizeof(sdu->dest));
+	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);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
 	sysarg_t retval;
 	async_wait_for(req, &retval);
-	
+
 	return (int) retval;
 }
 
-static void inetping_send_srv(inetping_client_t *client, ipc_callid_t callid,
-    ipc_call_t *call)
-{
+static void inetping_send_srv(inetping_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_send_srv()");
+
 	inetping_sdu_t sdu;
 	int rc;
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_send_srv()");
+	sdu.seq_no = IPC_GET_ARG1(*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(sdu.src)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	rc = async_data_write_finalize(callid, &sdu.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, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (size != sizeof(sdu.dest)) {
+		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, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
 
 	rc = async_data_write_accept((void **) &sdu.data, false, 0, 0, 0,
 	    &sdu.size);
 	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sdu.src = IPC_GET_ARG1(*call);
-	sdu.dest = IPC_GET_ARG2(*call);
-	sdu.seq_no = IPC_GET_ARG3(*call);
+		async_answer_0(iid, rc);
+		return;
+	}
 
 	rc = inetping_send(client, &sdu);
 	free(sdu.data);
 
-	async_answer_0(callid, rc);
+	async_answer_0(iid, rc);
 }
 
 static void inetping_get_srcaddr_srv(inetping_client_t *client,
-    ipc_callid_t callid, ipc_call_t *call)
+    ipc_callid_t iid, ipc_call_t *icall)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_get_srcaddr_srv()");
-	
-	uint32_t remote = IPC_GET_ARG1(*call);
-	uint32_t local = 0;
-	
-	int rc = inetping_get_srcaddr(client, remote, &local);
-	async_answer_1(callid, rc, (sysarg_t) local);
+
+	ipc_callid_t callid;
+	size_t size;
+
+	inet_addr_t local;
+	inet_addr_t remote;
+
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (size != sizeof(remote)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	int rc = async_data_write_finalize(callid, &remote, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	rc = inetping_get_srcaddr(client, &remote, &local);
+	if (rc != EOK) {
+		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(local)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	rc = async_data_read_finalize(callid, &local, size);
+	if (rc != EOK)
+		async_answer_0(callid, rc);
+
+	async_answer_0(iid, rc);
 }
 
@@ -163,13 +258,13 @@
 	if (sess == NULL)
 		return ENOMEM;
-	
+
 	client->sess = sess;
 	link_initialize(&client->client_list);
-	
+
 	fibril_mutex_lock(&client_list_lock);
 	client->ident = ++inetping_ident;
 	list_append(&client->client_list, &client_list);
 	fibril_mutex_unlock(&client_list_lock);
-	
+
 	return EOK;
 }
@@ -179,5 +274,5 @@
 	async_hangup(client->sess);
 	client->sess = NULL;
-	
+
 	fibril_mutex_lock(&client_list_lock);
 	list_remove(&client->client_list);
@@ -188,18 +283,18 @@
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_conn()");
-	
+
 	/* Accept the connection */
 	async_answer_0(iid, EOK);
-	
+
 	inetping_client_t client;
 	int rc = inetping_client_init(&client);
 	if (rc != EOK)
 		return;
-	
+
 	while (true) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		sysarg_t method = IPC_GET_IMETHOD(call);
-		
+
 		if (!method) {
 			/* The other side has hung up */
@@ -207,5 +302,5 @@
 			break;
 		}
-		
+
 		switch (method) {
 		case INETPING_SEND:
@@ -219,5 +314,5 @@
 		}
 	}
-	
+
 	inetping_client_fini(&client);
 }
