Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/Makefile	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -221,4 +221,5 @@
 	lib/draw \
 	lib/math \
+	lib/nettl \
 	lib/nic \
 	lib/ext4 \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/Makefile.common	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -155,4 +155,5 @@
 LIBMBR_PREFIX = $(LIB_PREFIX)/mbr
 LIBGPT_PREFIX = $(LIB_PREFIX)/gpt
+LIBNETTL_PREFIX = $(LIB_PREFIX)/nettl
 
 LIBURCU_PREFIX = $(LIB_PREFIX)/urcu
Index: uspace/lib/nettl/Makefile
===================================================================
--- uspace/lib/nettl/Makefile	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
+++ uspace/lib/nettl/Makefile	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2015 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.
+#
+
+USPACE_PREFIX = ../..
+EXTRA_CFLAGS = -Iinclude
+LIBRARY = libnettl
+
+SOURCES = \
+	src/amap.c \
+	src/portrng.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/nettl/include/nettl/amap.h
===================================================================
--- uspace/lib/nettl/include/nettl/amap.h	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
+++ uspace/lib/nettl/include/nettl/amap.h	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 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 libnettl
+ * @{
+ */
+/**
+ * @file Association map.
+ */
+
+#ifndef LIBNETTL_AMAP_H_
+#define LIBNETTL_AMAP_H_
+
+#include <inet/endpoint.h>
+#include <nettl/portrng.h>
+#include <loc.h>
+
+/** Port range for (remote endpoint, local address) */
+typedef struct {
+	/** Remote endpoint */
+	inet_ep_t rep;
+	/* Local address */
+	inet_addr_t laddr;
+	/** Port range */
+	portrng_t *portrng;
+} amap_repla_t;
+
+/** Port range for local address */
+typedef struct {
+	/** Local address */
+	inet_addr_t laddr;
+	/** Port range */
+	portrng_t *portrng;
+} amap_laddr_t;
+
+/** Port range for local link */
+typedef struct {
+	/** Local link ID */
+	service_id_t llink;
+	/** Port range */
+	portrng_t *portrng;
+} amap_llink_t;
+
+/** Association map */
+typedef struct {
+	/** Remote endpoint, local address */
+	list_t repla; /* of amap_repla_t */
+	/** Local addresses */
+	list_t laddr; /* of amap_laddr_t */
+	/** Local links */
+	list_t llink; /* of amap_llink_t */
+} amap_t;
+
+typedef enum {
+	/** Allow specifying port number from system range */
+	af_allow_system = 0x1
+} amap_flags_t;
+
+extern int amap_create(amap_t **);
+extern void amap_destroy(amap_t *);
+extern int amap_insert(amap_t *, inet_ep2_t *, void *, amap_flags_t,
+    inet_ep2_t *);
+extern void amap_remove(amap_t *, inet_ep2_t *);
+extern int amap_find(amap_t *, inet_ep2_t *, void **);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/nettl/include/nettl/portrng.h
===================================================================
--- uspace/lib/nettl/include/nettl/portrng.h	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
+++ uspace/lib/nettl/include/nettl/portrng.h	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 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 libnettl
+ * @{
+ */
+/**
+ * @file Port range allocator.
+ */
+
+#ifndef LIBNETTL_PORTRNG_H_
+#define LIBNETTL_PORTRNG_H_
+
+#include <stdint.h>
+
+typedef struct {
+} portrng_t;
+
+typedef enum {
+	pf_allow_system = 0x1
+} portrng_flags_t;
+
+extern int portrng_create(portrng_t **);
+extern void portrng_destroy(portrng_t *);
+extern int portrng_alloc_specific(portrng_t *, uint16_t, void *,
+    portrng_flags_t);
+extern int portrng_alloc_dynamic(portrng_t *, void *, uint16_t *);
+extern void portrng_free_port(portrng_t *, uint16_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/nettl/src/amap.c
===================================================================
--- uspace/lib/nettl/src/amap.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
+++ uspace/lib/nettl/src/amap.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015 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 libnettl
+ * @{
+ */
+
+/**
+ * @file Association map
+ *
+ * Manages allocations of endpoints / endpoint pairs (corresponding to
+ * UDP associations, TCP listeners and TCP connections)
+ */
+
+#include <errno.h>
+#include <inet/inet.h>
+#include <io/log.h>
+#include <nettl/amap.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+int amap_create(amap_t **rmap)
+{
+	amap_t *map;
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_create()");
+
+	map = calloc(1, sizeof(amap_t));
+	if (map == NULL)
+		return ENOMEM;
+
+	return EOK;
+}
+
+void amap_destroy(amap_t *map)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_destroy()");
+	free(map);
+}
+
+/** Insert endpoint pair into map.
+ *
+ * If local endpoint is not fully specified, it is filled in (determine
+ * source address, allocate port number). Checks for conflicting endpoint pair.
+ *
+ * @param map Association map
+ * @param epp Endpoint pair, possibly with local port inet_port_any
+ * @param arg arg User value
+ * @param flags Flags
+ * @param aepp Place to store actual endpoint pair, possibly with allocated port
+ *
+ * @return EOK on success, EEXISTS if conflicting epp exists,
+ *         ENOMEM if out of memory
+ */
+int amap_insert(amap_t *map, inet_ep2_t *epp, void *arg, amap_flags_t flags,
+    inet_ep2_t *aepp)
+{
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_insert()");
+
+	*aepp = *epp;
+
+	/* Fill in local address? */
+	if (!inet_addr_is_any(&epp->remote.addr) &&
+	    inet_addr_is_any(&epp->local.addr)) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_insert: "
+		    "determine local address");
+		rc = inet_get_srcaddr(&epp->remote.addr, 0, &aepp->local.addr);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_insert: "
+			    "cannot determine local address");
+			return rc;
+		}
+	} else {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_insert: "
+		    "local address specified or remote address not specified");
+	}
+
+	/** Allocate local port? */
+	if (aepp->local.port == inet_port_any) {
+		aepp->local.port = inet_port_dyn_lo; /* XXX */
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_insert: allocated local "
+		    "port %" PRIu16, aepp->local.port);
+	} else {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_insert: local "
+		    "port %" PRIu16 " specified", aepp->local.port);
+	}
+
+	return EOK;
+}
+
+void amap_remove(amap_t *map, inet_ep2_t *epp)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_remove()");
+}
+
+int amap_find(amap_t *map, inet_ep2_t *epp, void **rarg)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "amap_find()");
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/nettl/src/portrng.c
===================================================================
--- uspace/lib/nettl/src/portrng.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
+++ uspace/lib/nettl/src/portrng.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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 libnettl
+ * @{
+ */
+
+/**
+ * @file Port range allocator
+ *
+ * Allocates port numbers from IETF port number ranges.
+ */
+
+#include <errno.h>
+#include <nettl/portrng.h>
+#include <stdint.h>
+
+int portrng_create(portrng_t **rpr)
+{
+	return EOK;
+}
+
+void portrng_destroy(portrng_t *pr)
+{
+}
+
+int portrng_alloc_specific(portrng_t *pr, uint16_t pnum, void *arg,
+    portrng_flags_t flags)
+{
+	return EOK;
+}
+
+int portrng_alloc_dynamic(portrng_t *pr, void *arg, uint16_t *rpnum)
+{
+	return EOK;
+}
+
+void portrng_free_port(portrng_t *pr, uint16_t pnum)
+{
+}
+
+/**
+ * @}
+ */
+
Index: uspace/srv/net/tcp/Makefile
===================================================================
--- uspace/srv/net/tcp/Makefile	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/tcp/Makefile	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -28,4 +28,11 @@
 
 USPACE_PREFIX = ../../..
+
+LIBS = \
+	$(LIBNETTL_PREFIX)/libnettl.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBNETTL_PREFIX)/include
+
 BINARY = tcp
 
Index: uspace/srv/net/tcp/conn.c
===================================================================
--- uspace/srv/net/tcp/conn.c	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/tcp/conn.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -36,9 +36,10 @@
 
 #include <adt/list.h>
-#include <stdbool.h>
 #include <errno.h>
 #include <inet/endpoint.h>
 #include <io/log.h>
 #include <macros.h>
+#include <nettl/amap.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include "conn.h"
@@ -56,10 +57,25 @@
 #define TIME_WAIT_TIMEOUT	(2*MAX_SEGMENT_LIFETIME)
 
-LIST_INITIALIZE(conn_list);
-FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
+static LIST_INITIALIZE(conn_list);
+static FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
+static amap_t *amap;
 
 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
 static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
 static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
+
+/** Initialize connections. */
+int tcp_conns_init(void)
+{
+	int rc;
+
+	rc = amap_create(&amap);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		return ENOMEM;
+	}
+
+	return EOK;
+}
 
 /** Create new connection structure.
@@ -246,10 +262,24 @@
  * Add connection to the connection map.
  */
-void tcp_conn_add(tcp_conn_t *conn)
-{
+int tcp_conn_add(tcp_conn_t *conn)
+{
+	inet_ep2_t aepp;
+	int rc;
+
 	tcp_conn_addref(conn);
 	fibril_mutex_lock(&conn_list_lock);
+
+	rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp);
+	if (rc != EOK) {
+		tcp_conn_delref(conn);
+		fibril_mutex_unlock(&conn_list_lock);
+		return rc;
+	}
+
+	conn->ident = aepp;
 	list_append(&conn->link, &conn_list);
 	fibril_mutex_unlock(&conn_list_lock);
+
+	return EOK;
 }
 
@@ -261,4 +291,5 @@
 {
 	fibril_mutex_lock(&conn_list_lock);
+	amap_remove(amap, &conn->ident);
 	list_remove(&conn->link);
 	fibril_mutex_unlock(&conn_list_lock);
Index: uspace/srv/net/tcp/conn.h
===================================================================
--- uspace/srv/net/tcp/conn.h	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/tcp/conn.h	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -40,7 +40,8 @@
 #include "tcp_type.h"
 
+extern int tcp_conns_init(void);
 extern tcp_conn_t *tcp_conn_new(inet_ep2_t *);
 extern void tcp_conn_delete(tcp_conn_t *);
-extern void tcp_conn_add(tcp_conn_t *);
+extern int tcp_conn_add(tcp_conn_t *);
 extern void tcp_conn_remove(tcp_conn_t *);
 extern void tcp_conn_reset(tcp_conn_t *conn);
Index: uspace/srv/net/tcp/service.c
===================================================================
--- uspace/srv/net/tcp/service.c	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/tcp/service.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -335,5 +335,4 @@
 	tcp_conn_t *conn;
 	tcp_cconn_t *cconn;
-	inet_ep2_t cepp;
 	int rc;
 	tcp_error_t trc;
@@ -343,33 +342,6 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl");
 
-	cepp = *epp;
-
-	/* Fill in local address? */
-	if (inet_addr_is_any(&epp->local.addr)) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl: "
-		    "determine local address");
-		rc = inet_get_srcaddr(&epp->remote.addr, 0, &cepp.local.addr);
-		if (rc != EOK) {
-			log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl: "
-			    "cannot determine local address");
-			return rc;
-		}
-	} else {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl: "
-		    "local address specified");
-	}
-
-	/* Allocate local port? */
-	if (cepp.local.port == 0) {
-		cepp.local.port = 49152; /* XXX */
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl: "
-		    "allocated local port %" PRIu16, cepp.local.port);
-	} else {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl: "
-		    "local port %" PRIu16 " specified", cepp.local.port);
-	}
-
-	inet_addr_format(&cepp.local.addr, &slocal);
-	inet_addr_format(&cepp.remote.addr, &sremote);
+	inet_addr_format(&epp->local.addr, &slocal);
+	inet_addr_format(&epp->remote.addr, &sremote);
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create: local=%s remote=%s",
 	    slocal, sremote);
@@ -377,5 +349,5 @@
 	free(sremote);
 
-	trc = tcp_uc_open(&cepp, ap_active, tcp_open_nonblock, &conn);
+	trc = tcp_uc_open(epp, ap_active, tcp_open_nonblock, &conn);
 	if (trc != TCP_EOK)
 		return EIO;
Index: uspace/srv/net/tcp/tcp.c
===================================================================
--- uspace/srv/net/tcp/tcp.c	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/tcp/tcp.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -45,4 +45,5 @@
 #include <task.h>
 
+#include "conn.h"
 #include "ncsim.h"
 #include "pdu.h"
@@ -179,4 +180,11 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_init()");
 
+	rc = tcp_conns_init();
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing connections");
+		return ENOMEM;
+	}
+
 	tcp_rqueue_init();
 	tcp_rqueue_fibril_start();
Index: uspace/srv/net/tcp/ucall.c
===================================================================
--- uspace/srv/net/tcp/ucall.c	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/tcp/ucall.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -35,4 +35,5 @@
  */
 
+#include <errno.h>
 #include <fibril_synch.h>
 #include <io/log.h>
@@ -68,4 +69,5 @@
 {
 	tcp_conn_t *nconn;
+	int rc;
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open(%p, %s, %s, %p)",
@@ -74,5 +76,10 @@
 
 	nconn = tcp_conn_new(epp);
-	tcp_conn_add(nconn);
+	rc = tcp_conn_add(nconn);
+	if (rc != EOK) {
+		tcp_conn_delete(nconn);
+		return TCP_EEXISTS;
+	}
+
 	tcp_conn_lock(nconn);
 
Index: uspace/srv/net/udp/Makefile
===================================================================
--- uspace/srv/net/udp/Makefile	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/udp/Makefile	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -28,4 +28,11 @@
 
 USPACE_PREFIX = ../../..
+
+LIBS = \
+	$(LIBNETTL_PREFIX)/libnettl.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBNETTL_PREFIX)/include
+
 BINARY = udp
 
@@ -35,5 +42,4 @@
 	pdu.c \
 	service.c \
-	ucall.c \
 	udp.c \
 	udp_inet.c
Index: uspace/srv/net/udp/assoc.c
===================================================================
--- uspace/srv/net/udp/assoc.c	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/udp/assoc.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -41,4 +41,5 @@
 #include <inet/endpoint.h>
 #include <io/log.h>
+#include <nettl/amap.h>
 #include <stdlib.h>
 
@@ -46,10 +47,10 @@
 #include "msg.h"
 #include "pdu.h"
-#include "ucall.h"
 #include "udp_inet.h"
 #include "udp_type.h"
 
-LIST_INITIALIZE(assoc_list);
-FIBRIL_MUTEX_INITIALIZE(assoc_list_lock);
+static LIST_INITIALIZE(assoc_list);
+static FIBRIL_MUTEX_INITIALIZE(assoc_list_lock);
+static amap_t *amap;
 
 static udp_assoc_t *udp_assoc_find_ref(inet_ep2_t *);
@@ -57,4 +58,18 @@
 static bool udp_ep_match(inet_ep_t *, inet_ep_t *);
 static bool udp_ep2_match(inet_ep2_t *, inet_ep2_t *);
+
+/** Initialize associations. */
+int udp_assocs_init(void)
+{
+	int rc;
+
+	rc = amap_create(&amap);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		return ENOMEM;
+	}
+
+	return EOK;
+}
 
 /** Create new association structure.
@@ -168,10 +183,24 @@
  * Add association to the association map.
  */
-void udp_assoc_add(udp_assoc_t *assoc)
-{
+int udp_assoc_add(udp_assoc_t *assoc)
+{
+	inet_ep2_t aepp;
+	int rc;
+
 	udp_assoc_addref(assoc);
 	fibril_mutex_lock(&assoc_list_lock);
+
+	rc = amap_insert(amap, &assoc->ident, assoc, af_allow_system, &aepp);
+	if (rc != EOK) {
+		udp_assoc_delref(assoc);
+		fibril_mutex_unlock(&assoc_list_lock);
+		return rc;
+	}
+
+	assoc->ident = aepp;
 	list_append(&assoc->link, &assoc_list);
 	fibril_mutex_unlock(&assoc_list_lock);
+
+	return EOK;
 }
 
@@ -183,4 +212,5 @@
 {
 	fibril_mutex_lock(&assoc_list_lock);
+	amap_remove(amap, &assoc->ident);
 	list_remove(&assoc->link);
 	fibril_mutex_unlock(&assoc_list_lock);
@@ -199,45 +229,4 @@
 	fibril_mutex_lock(&assoc->lock);
 	assoc->ident.local_link = iplink;
-	fibril_mutex_unlock(&assoc->lock);
-}
-
-/** Set remote endpoint in association.
- *
- * @param assoc		Association
- * @param remote	Remote endpoint (deeply copied)
- */
-void udp_assoc_set_remote(udp_assoc_t *assoc, inet_ep_t *remote)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_remote(%p, %p)", assoc, remote);
-	fibril_mutex_lock(&assoc->lock);
-	assoc->ident.remote = *remote;
-	fibril_mutex_unlock(&assoc->lock);
-}
-
-/** Set local endpoint in association.
- *
- * @param assoc Association
- * @param local Local endpoint (deeply copied)
- *
- */
-void udp_assoc_set_local(udp_assoc_t *assoc, inet_ep_t *local)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, local);
-	fibril_mutex_lock(&assoc->lock);
-	assoc->ident.local = *local;
-	fibril_mutex_unlock(&assoc->lock);
-}
-
-/** Set local port in association.
- *
- * @param assoc Association
- * @param lport Local port
- *
- */
-void udp_assoc_set_local_port(udp_assoc_t *assoc, uint16_t lport)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_local(%p, %" PRIu16 ")", assoc, lport);
-	fibril_mutex_lock(&assoc->lock);
-	assoc->ident.local.port = lport;
 	fibril_mutex_unlock(&assoc->lock);
 }
Index: uspace/srv/net/udp/assoc.h
===================================================================
--- uspace/srv/net/udp/assoc.h	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/udp/assoc.h	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -41,14 +41,12 @@
 #include "udp_type.h"
 
+extern int udp_assocs_init(void);
 extern udp_assoc_t *udp_assoc_new(inet_ep2_t *, udp_assoc_cb_t *, void *);
 extern void udp_assoc_delete(udp_assoc_t *);
-extern void udp_assoc_add(udp_assoc_t *);
+extern int udp_assoc_add(udp_assoc_t *);
 extern void udp_assoc_remove(udp_assoc_t *);
 extern void udp_assoc_addref(udp_assoc_t *);
 extern void udp_assoc_delref(udp_assoc_t *);
 extern void udp_assoc_set_iplink(udp_assoc_t *, service_id_t);
-extern void udp_assoc_set_remote(udp_assoc_t *, inet_ep_t *);
-extern void udp_assoc_set_local(udp_assoc_t *, inet_ep_t *);
-extern void udp_assoc_set_local_port(udp_assoc_t *, uint16_t);
 extern int udp_assoc_send(udp_assoc_t *, inet_ep_t *, udp_msg_t *);
 extern int udp_assoc_recv(udp_assoc_t *, udp_msg_t **, inet_ep_t *);
Index: uspace/srv/net/udp/service.c
===================================================================
--- uspace/srv/net/udp/service.c	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/udp/service.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -178,5 +178,10 @@
 	assoc->cb_arg = cassoc;
 
-	udp_assoc_add(assoc);
+	rc = udp_assoc_add(assoc);
+	if (rc != EOK) {
+		udp_cassoc_destroy(cassoc);
+		udp_assoc_delete(assoc);
+		return rc;
+	}
 
 	*rassoc_id = cassoc->id;
Index: uspace/srv/net/udp/ucall.c
===================================================================
--- uspace/srv/net/udp/ucall.c	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ 	(revision )
@@ -1,164 +1,0 @@
-/*
- * Copyright (c) 2015 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 tcp
- * @{
- */
-
-/**
- * @file UDP user calls
- */
-
-#include <errno.h>
-#include <io/log.h>
-#include <macros.h>
-#include <mem.h>
-
-#include "assoc.h"
-#include "msg.h"
-#include "udp_type.h"
-#include "ucall.h"
-
-udp_error_t udp_uc_create(udp_assoc_t **assoc)
-{
-	udp_assoc_t *nassoc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_create()");
-	nassoc = udp_assoc_new(NULL, NULL, NULL);
-	if (nassoc == NULL)
-		return UDP_ENORES;
-
-	udp_assoc_add(nassoc);
-	*assoc = nassoc;
-	return UDP_EOK;
-}
-
-void udp_uc_set_iplink(udp_assoc_t *assoc, service_id_t iplink)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_set_iplink(%p, %zu)",
-	    assoc, iplink);
-
-	udp_assoc_set_iplink(assoc, iplink);
-}
-
-udp_error_t udp_uc_set_remote(udp_assoc_t *assoc, inet_ep_t *ep)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_set_remote(%p, %p)", assoc, ep);
-
-	udp_assoc_set_remote(assoc, ep);
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_set_local(udp_assoc_t *assoc, inet_ep_t *ep)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_set_local(%p, %p)", assoc, ep);
-
-	udp_assoc_set_local(assoc, ep);
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_set_local_port(udp_assoc_t *assoc, uint16_t lport)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_set_local(%p, %" PRIu16 ")", assoc, lport);
-
-	udp_assoc_set_local_port(assoc, lport);
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_send(udp_assoc_t *assoc, inet_ep_t *remote, void *data,
-    size_t size, xflags_t flags)
-{
-	int rc;
-	udp_msg_t msg;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: udp_uc_send()", assoc->name);
-
-	msg.data = data;
-	msg.data_size = size;
-
-	rc = udp_assoc_send(assoc, remote, &msg);
-	switch (rc) {
-	case ENOMEM:
-		return UDP_ENORES;
-	case EINVAL:
-		return UDP_EUNSPEC;
-	case EIO:
-		return UDP_ENOROUTE;
-	}
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_receive(udp_assoc_t *assoc, void *buf, size_t size,
-    size_t *rcvd, xflags_t *xflags, inet_ep_t *remote)
-{
-	size_t xfer_size;
-	udp_msg_t *msg;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: udp_uc_receive()", assoc->name);
-	rc = udp_assoc_recv(assoc, &msg, remote);
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv -> %d", rc);
-	switch (rc) {
-	case EOK:
-		break;
-	case ENXIO:
-		return UDP_ERESET;
-	default:
-		assert(false);
-	}
-
-	xfer_size = min(size, msg->data_size);
-	memcpy(buf, msg->data, xfer_size);
-	*rcvd = xfer_size;
-	udp_msg_delete(msg);
-
-	return UDP_EOK;
-}
-
-void udp_uc_status(udp_assoc_t *assoc, udp_assoc_status_t *astatus)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_status()");
-//	cstatus->cstate = conn->cstate;
-}
-
-void udp_uc_destroy(udp_assoc_t *assoc)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_destroy()");
-	udp_assoc_reset(assoc);
-	udp_assoc_remove(assoc);
-	udp_assoc_delete(assoc);
-}
-
-void udp_uc_reset(udp_assoc_t *assoc)
-{
-	udp_assoc_reset(assoc);
-}
-
-/**
- * @}
- */
Index: uspace/srv/net/udp/ucall.h
===================================================================
--- uspace/srv/net/udp/ucall.h	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * Copyright (c) 2015 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 udp
- * @{
- */
-/** @file UDP user calls
- */
-
-#ifndef UCALL_H
-#define UCALL_H
-
-#include <ipc/loc.h>
-#include <sys/types.h>
-#include "udp_type.h"
-
-extern udp_error_t udp_uc_create(udp_assoc_t **);
-extern void udp_uc_set_iplink(udp_assoc_t *, service_id_t);
-extern udp_error_t udp_uc_set_remote(udp_assoc_t *, inet_ep_t *);
-extern udp_error_t udp_uc_set_local(udp_assoc_t *, inet_ep_t *);
-extern udp_error_t udp_uc_set_local_port(udp_assoc_t *, uint16_t);
-extern udp_error_t udp_uc_send(udp_assoc_t *, inet_ep_t *, void *, size_t,
-    xflags_t);
-extern udp_error_t udp_uc_receive(udp_assoc_t *, void *, size_t, size_t *,
-    xflags_t *, inet_ep_t *);
-extern void udp_uc_status(udp_assoc_t *, udp_assoc_status_t *);
-extern void udp_uc_destroy(udp_assoc_t *);
-extern void udp_uc_reset(udp_assoc_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/udp/udp.c
===================================================================
--- uspace/srv/net/udp/udp.c	(revision 58e9dec38facb087ef357050fc85631d17323e92)
+++ uspace/srv/net/udp/udp.c	(revision 2989c7e1f80ad5fce60e2df203de878926d6c147)
@@ -41,4 +41,5 @@
 #include <task.h>
 
+#include "assoc.h"
 #include "service.h"
 #include "udp_inet.h"
@@ -51,4 +52,10 @@
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_init()");
+
+	rc = udp_assocs_init();
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing associations.");
+		return ENOMEM;
+	}
 
 	rc = udp_inet_init();
