Index: uspace/lib/c/generic/iplink_srv.c
===================================================================
--- uspace/lib/c/generic/iplink_srv.c	(revision 4802dd7d8d17cb02ec8f79547ffde538bb8c6736)
+++ uspace/lib/c/generic/iplink_srv.c	(revision c3b25985a33ea9ae992d45cc6df7c7a892242e79)
@@ -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>
 
@@ -44,53 +45,178 @@
     ipc_call_t *call)
 {
+	size_t mtu;
+	int rc = srv->ops->get_mtu(srv, &mtu);
+	async_answer_1(callid, rc, mtu);
+}
+
+static void iplink_get_mac48_srv(iplink_srv_t *srv, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	addr48_t mac;
+	int rc = srv->ops->get_mac48(srv, &mac);
+	if (rc != EOK) {
+		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(addr48_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	rc = async_data_read_finalize(callid, &mac, size);
+	if (rc != EOK)
+		async_answer_0(callid, rc);
+	
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void iplink_set_mac48_srv(iplink_srv_t *srv, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
 	int rc;
-	size_t mtu;
-
-	rc = srv->ops->get_mtu(srv, &mtu);
-	async_answer_1(callid, rc, mtu);
-}
-
-static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	int rc;
-	iplink_srv_addr_t addr;
-
-	addr.ipv4 = IPC_GET_ARG1(*call);
-
+	size_t size;
+	addr48_t mac;
+	ipc_callid_t callid;
+
+	rc = async_data_write_receive(&callid, &size);
+	if (rc != EOK) {
+		async_answer_0(callid, (sysarg_t) rc);
+		async_answer_0(iid, (sysarg_t) rc);
+	}
+
+	rc = srv->ops->set_mac48(srv, &mac);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	rc = async_data_read_finalize(callid, &mac, sizeof(addr48_t));
+	if (rc != EOK)
+		async_answer_0(callid, rc);
+	
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+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(callid, rc);
-}
-
-static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	int rc;
-	iplink_srv_addr_t addr;
-
-	addr.ipv4 = IPC_GET_ARG1(*call);
-
+	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(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.ipv4 = IPC_GET_ARG1(*call);
-	sdu.ldest.ipv4 = 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;
-	}
-
+	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;
+	
+	sdu.src = IPC_GET_ARG1(*icall);
+	sdu.dest = IPC_GET_ARG2(*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 = srv->ops->send(srv, &sdu);
 	free(sdu.data);
-	async_answer_0(callid, rc);
+	async_answer_0(iid, rc);
+}
+
+static void iplink_send6_srv(iplink_srv_t *srv, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	iplink_sdu6_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(addr48_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	int 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) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	rc = srv->ops->send6(srv, &sdu);
+	free(sdu.data);
+	async_answer_0(iid, rc);
 }
 
@@ -106,7 +232,7 @@
 int iplink_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	iplink_srv_t *srv = (iplink_srv_t *)arg;
+	iplink_srv_t *srv = (iplink_srv_t *) arg;
 	int rc;
-
+	
 	fibril_mutex_lock(&srv->lock);
 	if (srv->connected) {
@@ -115,41 +241,50 @@
 		return EBUSY;
 	}
-
+	
 	srv->connected = true;
 	fibril_mutex_unlock(&srv->lock);
-
+	
 	/* Accept the connection */
 	async_answer_0(iid, EOK);
-
+	
 	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
 	if (sess == NULL)
 		return ENOMEM;
-
+	
 	srv->client_sess = sess;
-
+	
 	rc = srv->ops->open(srv);
 	if (rc != EOK)
 		return rc;
-
+	
 	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 */
-		    	fibril_mutex_lock(&srv->lock);
+			fibril_mutex_lock(&srv->lock);
 			srv->connected = false;
-		    	fibril_mutex_unlock(&srv->lock);
+			fibril_mutex_unlock(&srv->lock);
 			async_answer_0(callid, EOK);
 			break;
 		}
-
+		
 		switch (method) {
 		case IPLINK_GET_MTU:
 			iplink_get_mtu_srv(srv, callid, &call);
 			break;
+		case IPLINK_GET_MAC48:
+			iplink_get_mac48_srv(srv, callid, &call);
+			break;
+		case IPLINK_SET_MAC48:
+			iplink_set_mac48_srv(srv, callid, &call);
+			break;
 		case IPLINK_SEND:
 			iplink_send_srv(srv, callid, &call);
+			break;
+		case IPLINK_SEND6:
+			iplink_send6_srv(srv, callid, &call);
 			break;
 		case IPLINK_ADDR_ADD:
@@ -163,31 +298,59 @@
 		}
 	}
-
+	
 	return srv->ops->close(srv);
 }
 
-int iplink_ev_recv(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
+/* XXX Version should be part of @a sdu */
+int iplink_ev_recv(iplink_srv_t *srv, iplink_recv_sdu_t *sdu, ip_ver_t ver)
 {
 	if (srv->client_sess == NULL)
 		return EIO;
-
+	
 	async_exch_t *exch = async_exchange_begin(srv->client_sess);
-
+	
 	ipc_call_t answer;
-	aid_t req = async_send_2(exch, IPLINK_EV_RECV, sdu->lsrc.ipv4,
-	    sdu->ldest.ipv4, &answer);
+	aid_t req = async_send_1(exch, IPLINK_EV_RECV, (sysarg_t)ver,
+	    &answer);
+	
 	int 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);
 	if (retval != EOK)
 		return retval;
-
+	
+	return EOK;
+}
+
+int iplink_ev_change_addr(iplink_srv_t *srv, addr48_t *addr)
+{
+	if (srv->client_sess == NULL)
+		return EIO;
+	
+	async_exch_t *exch = async_exchange_begin(srv->client_sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, IPLINK_EV_CHANGE_ADDR, &answer);
+	
+	int rc = async_data_write_start(exch, addr, sizeof(addr48_t));
+	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;
 }
