Index: uspace/lib/c/generic/iplink_srv.c
===================================================================
--- uspace/lib/c/generic/iplink_srv.c	(revision 14938114d2ec7a3b3548c8acfc893a7313130ea1)
+++ uspace/lib/c/generic/iplink_srv.c	(revision 4f64a523695d07f25f0d3382ba626f4d1ec45c79)
@@ -41,5 +41,5 @@
 #include <inet/iplink_srv.h>
 
-static void iplink_get_mtu_srv(iplink_conn_t *conn, ipc_callid_t callid,
+static void iplink_get_mtu_srv(iplink_srv_t *srv, ipc_callid_t callid,
     ipc_call_t *call)
 {
@@ -47,9 +47,9 @@
 	size_t mtu;
 
-	rc = conn->srv->ops->get_mtu(conn, &mtu);
+	rc = srv->ops->get_mtu(srv, &mtu);
 	async_answer_1(callid, rc, mtu);
 }
 
-static void iplink_send_srv(iplink_conn_t *conn, ipc_callid_t callid,
+static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t callid,
     ipc_call_t *call)
 {
@@ -66,7 +66,16 @@
 	}
 
-	rc = conn->srv->ops->send(conn, &sdu);
+	rc = srv->ops->send(srv, &sdu);
 	free(sdu.data);
 	async_answer_0(callid, rc);
+}
+
+void iplink_srv_init(iplink_srv_t *srv)
+{
+	fibril_mutex_initialize(&srv->lock);
+	srv->connected = false;
+	srv->ops = NULL;
+	srv->arg = NULL;
+	srv->client_sess = NULL;
 }
 
@@ -74,6 +83,15 @@
 {
 	iplink_srv_t *srv = (iplink_srv_t *)arg;
-	iplink_conn_t conn;
 	int rc;
+
+	fibril_mutex_lock(&srv->lock);
+	if (srv->connected) {
+		fibril_mutex_unlock(&srv->lock);
+		async_answer_0(iid, EBUSY);
+		return EBUSY;
+	}
+
+	srv->connected = true;
+	fibril_mutex_unlock(&srv->lock);
 
 	/* Accept the connection */
@@ -84,8 +102,7 @@
 		return ENOMEM;
 
-	conn.srv = srv;
-	conn.client_sess = sess;
+	srv->client_sess = sess;
 
-	rc = srv->ops->open(&conn);
+	rc = srv->ops->open(srv);
 	if (rc != EOK)
 		return rc;
@@ -104,8 +121,8 @@
 		switch (method) {
 		case IPLINK_GET_MTU:
-			iplink_get_mtu_srv(&conn, callid, &call);
+			iplink_get_mtu_srv(srv, callid, &call);
 			break;
 		case IPLINK_SEND:
-			iplink_send_srv(&conn, callid, &call);
+			iplink_send_srv(srv, callid, &call);
 			break;
 		default:
@@ -114,10 +131,13 @@
 	}
 
-	return srv->ops->close(&conn);
+	return srv->ops->close(srv);
 }
 
-int iplink_ev_recv(iplink_conn_t *conn, iplink_srv_sdu_t *sdu)
+int iplink_ev_recv(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
 {
-	async_exch_t *exch = async_exchange_begin(conn->client_sess);
+	if (srv->client_sess == NULL)
+		return EIO;
+
+	async_exch_t *exch = async_exchange_begin(srv->client_sess);
 
 	ipc_call_t answer;
Index: uspace/lib/c/include/inet/iplink_srv.h
===================================================================
--- uspace/lib/c/include/inet/iplink_srv.h	(revision 14938114d2ec7a3b3548c8acfc893a7313130ea1)
+++ uspace/lib/c/include/inet/iplink_srv.h	(revision 4f64a523695d07f25f0d3382ba626f4d1ec45c79)
@@ -37,4 +37,6 @@
 
 #include <async.h>
+#include <fibril_synch.h>
+#include <bool.h>
 #include <sys/types.h>
 
@@ -42,12 +44,10 @@
 
 typedef struct {
+	fibril_mutex_t lock;
+	bool connected;
 	struct iplink_ops *ops;
 	void *arg;
+	async_sess_t *client_sess;
 } iplink_srv_t;
-
-typedef struct {
-	iplink_srv_t *srv;
-	async_sess_t *client_sess;
-} iplink_conn_t;
 
 typedef struct {
@@ -68,12 +68,14 @@
 
 typedef struct iplink_ops {
-	int (*open)(iplink_conn_t *);
-	int (*close)(iplink_conn_t *);
-	int (*send)(iplink_conn_t *, iplink_srv_sdu_t *);
-	int (*get_mtu)(iplink_conn_t *, size_t *);
+	int (*open)(iplink_srv_t *);
+	int (*close)(iplink_srv_t *);
+	int (*send)(iplink_srv_t *, iplink_srv_sdu_t *);
+	int (*get_mtu)(iplink_srv_t *, size_t *);
 } iplink_ops_t;
 
+extern void iplink_srv_init(iplink_srv_t *);
+
 extern int iplink_conn(ipc_callid_t, ipc_call_t *, void *);
-extern int iplink_ev_recv(iplink_conn_t *, iplink_srv_sdu_t *);
+extern int iplink_ev_recv(iplink_srv_t *, iplink_srv_sdu_t *);
 
 #endif
Index: uspace/srv/ethip/ethip.c
===================================================================
--- uspace/srv/ethip/ethip.c	(revision 14938114d2ec7a3b3548c8acfc893a7313130ea1)
+++ uspace/srv/ethip/ethip.c	(revision 4f64a523695d07f25f0d3382ba626f4d1ec45c79)
@@ -52,8 +52,8 @@
 #define NAME "eth"
 
-static int ethip_open(iplink_conn_t *conn);
-static int ethip_close(iplink_conn_t *conn);
-static int ethip_send(iplink_conn_t *conn, iplink_srv_sdu_t *sdu);
-static int ethip_get_mtu(iplink_conn_t *conn, size_t *mtu);
+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_get_mtu(iplink_srv_t *srv, size_t *mtu);
 
 static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
@@ -95,4 +95,5 @@
 	log_msg(LVL_DEBUG, "ethip_iplink_init()");
 
+	iplink_srv_init(&nic->iplink);
 	nic->iplink.ops = &ethip_iplink_ops;
 	nic->iplink.arg = nic;
@@ -148,5 +149,5 @@
 }
 
-static int ethip_open(iplink_conn_t *conn)
+static int ethip_open(iplink_srv_t *srv)
 {
 	log_msg(LVL_DEBUG, "ethip_open()");
@@ -154,13 +155,13 @@
 }
 
-static int ethip_close(iplink_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "ethip_open()");
-	return EOK;
-}
-
-static int ethip_send(iplink_conn_t *conn, iplink_srv_sdu_t *sdu)
-{
-	ethip_nic_t *nic = (ethip_nic_t *)conn->srv->arg;
+static int ethip_close(iplink_srv_t *srv)
+{
+	log_msg(LVL_DEBUG, "ethip_close()");
+	return EOK;
+}
+
+static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
 	eth_frame_t frame;
 	void *data;
@@ -188,16 +189,26 @@
 int ethip_received(iplink_srv_t *srv, void *data, size_t size)
 {
+	log_msg(LVL_DEBUG, "ethip_received(): srv=%p", srv);
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
 	eth_frame_t frame;
 	iplink_srv_sdu_t sdu;
 	int rc;
 
+	log_msg(LVL_DEBUG, "ethip_received()");
+
+	log_msg(LVL_DEBUG, " - eth_pdu_decode");
 	rc = eth_pdu_decode(data, size, &frame);
-	if (rc != EOK)
-		return rc;
-
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, " - eth_pdu_decode failed");
+		return rc;
+	}
+
+	log_msg(LVL_DEBUG, " - construct SDU");
+	sdu.lsrc.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 1;
+	sdu.ldest.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 4;
 	sdu.data = frame.data;
 	sdu.size = frame.size;
-	(void) sdu;
-	//rc = iplink_ev_recv(conn, &sdu);
+	log_msg(LVL_DEBUG, " - call iplink_ev_recv");
+	rc = iplink_ev_recv(&nic->iplink, &sdu);
 
 	free(frame.data);
@@ -205,5 +216,5 @@
 }
 
-static int ethip_get_mtu(iplink_conn_t *conn, size_t *mtu)
+static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu)
 {
 	log_msg(LVL_DEBUG, "ethip_get_mtu()");
Index: uspace/srv/ethip/ethip_nic.c
===================================================================
--- uspace/srv/ethip/ethip_nic.c	(revision 14938114d2ec7a3b3548c8acfc893a7313130ea1)
+++ uspace/srv/ethip/ethip_nic.c	(revision 4f64a523695d07f25f0d3382ba626f4d1ec45c79)
@@ -158,11 +158,4 @@
 	}
 
-	rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed activating NIC '%s'.",
-		    nic->svc_name);
-		goto error;
-	}
-
 	log_msg(LVL_DEBUG, "Opened NIC '%s'", nic->svc_name);
 	list_append(&nic->nic_list, &ethip_nic_list);
@@ -172,4 +165,11 @@
 	if (rc != EOK)
 		goto error;
+
+	rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed activating NIC '%s'.",
+		    nic->svc_name);
+		goto error;
+	}
 
 	log_msg(LVL_DEBUG, "Initialized IP link service.");
@@ -205,5 +205,5 @@
 	size_t size;
 
-	log_msg(LVL_DEBUG, "ethip_nic_received()");
+	log_msg(LVL_DEBUG, "ethip_nic_received() nic=%p", nic);
 
 	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
@@ -213,5 +213,7 @@
 	}
 
+	log_msg(LVL_DEBUG, "call ethip_received");
 	rc = ethip_received(&nic->iplink, data, size);
+	log_msg(LVL_DEBUG, "free data");
 	free(data);
 
@@ -228,5 +230,5 @@
 static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	ethip_nic_t *nic;
+	ethip_nic_t *nic = (ethip_nic_t *)arg;
 
 	log_msg(LVL_DEBUG, "ethnip_nic_cb_conn()");
