Index: .bzrignore
===================================================================
--- .bzrignore	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ .bzrignore	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -80,4 +80,5 @@
 uspace/app/wavplay/wavplay
 uspace/app/websrv/websrv
+uspace/app/wifi_supplicant/wifi_supplicant
 uspace/dist/app/barber
 uspace/dist/app/bdsh
@@ -133,5 +134,7 @@
 uspace/dist/app/wavplay
 uspace/dist/app/websrv
+uspace/dist/app/wifi_supplicant
 uspace/dist/drv/ahci/
+uspace/dist/drv/ar9271/
 uspace/dist/drv/ata_bd/
 uspace/dist/drv/cmos-rtc/
@@ -202,4 +205,5 @@
 uspace/drv/block/ahci/ahci
 uspace/drv/block/ata_bd/ata_bd
+uspace/drv/block/ddisk/ddisk
 uspace/drv/bus/isa/isa
 uspace/drv/bus/pci/pciintel/pciintel
@@ -224,4 +228,5 @@
 uspace/drv/platform/pc/pc
 uspace/drv/platform/rootpc/rootpc
+uspace/drv/nic/ar9271/ar9271
 uspace/drv/nic/e1k/e1k
 uspace/drv/nic/ne2k/ne2k
Index: abi/include/abi/proc/uarg.h
===================================================================
--- abi/include/abi/proc/uarg.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ abi/include/abi/proc/uarg.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -42,5 +42,5 @@
 	size_t uspace_stack_size;
 	
-	void (* uspace_thread_function)();
+	void (* uspace_thread_function)(void *);
 	void *uspace_thread_arg;
 	
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ boot/Makefile.common	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -178,7 +178,4 @@
 	$(USPACE_PATH)/app/corecfg/corecfg \
 	$(USPACE_PATH)/app/devctl/devctl \
-	$(USPACE_PATH)/app/dltest/dltest \
-	$(USPACE_PATH)/app/dltest2/dltest2 \
-	$(USPACE_PATH)/app/dload/dload \
 	$(USPACE_PATH)/app/dnscfg/dnscfg \
 	$(USPACE_PATH)/app/dnsres/dnsres \
@@ -208,9 +205,4 @@
 	$(USPACE_PATH)/app/tetris/tetris \
 	$(USPACE_PATH)/app/trace/trace \
-	$(USPACE_PATH)/app/nettest1/nettest1 \
-	$(USPACE_PATH)/app/nettest2/nettest2 \
-	$(USPACE_PATH)/app/nettest3/nettest3 \
-	$(USPACE_PATH)/app/netecho/netecho \
-	$(USPACE_PATH)/app/netspeed/netspeed \
 	$(USPACE_PATH)/app/nterm/nterm \
 	$(USPACE_PATH)/app/ping/ping \
Index: boot/arch/arm32/src/mm.c
===================================================================
--- boot/arch/arm32/src/mm.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ boot/arch/arm32/src/mm.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -193,7 +193,8 @@
 }
 
-static void enable_paging()
-{
-	/* c3   - each two bits controls access to the one of domains (16)
+static void enable_paging(void)
+{
+	/*
+	 * c3   - each two bits controls access to the one of domains (16)
 	 * 0b01 - behave as a client (user) of a domain
 	 */
@@ -232,5 +233,6 @@
 
 /** Start the MMU - initialize page table and enable paging. */
-void mmu_start() {
+void mmu_start(void)
+{
 	disable_paging();
 #ifdef PROCESSOR_ARCH_armv7_a
Index: boot/arch/ppc32/include/asm.h
===================================================================
--- boot/arch/ppc32/include/asm.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ boot/arch/ppc32/include/asm.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -35,5 +35,5 @@
 extern void jump_to_kernel(void *, void *, size_t, void *)
     __attribute__((noreturn));
-extern void real_mode();
+extern void real_mode(void);
 
 #endif
Index: boot/arch/sparc32/src/ambapp.c
===================================================================
--- boot/arch/sparc32/src/ambapp.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ boot/arch/sparc32/src/ambapp.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -58,5 +58,5 @@
 static void ambapp_scan_area(uintptr_t, unsigned int);
 
-void ambapp_scan()
+void ambapp_scan(void)
 {
 	amba_fake = false;
@@ -104,5 +104,5 @@
 }
 
-void ambapp_qemu_fake_scan()
+void ambapp_qemu_fake_scan(void)
 {
 	/* UART */
@@ -134,10 +134,10 @@
 }
 
-bool ambapp_fake()
+bool ambapp_fake(void)
 {
 	return amba_fake;
 }
 
-void ambapp_print_devices()
+void ambapp_print_devices(void)
 {
 	printf("ABMA devices:\n");
Index: boot/arch/sparc32/src/mm.c
===================================================================
--- boot/arch/sparc32/src/mm.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ boot/arch/sparc32/src/mm.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -76,5 +76,5 @@
 }
 
-static void mmu_disable()
+static void mmu_disable(void)
 {
 	uint32_t cr = asi_u32_read(ASI_MMUREGS, 0x000);
Index: boot/generic/include/memstr.h
===================================================================
--- boot/generic/include/memstr.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ boot/generic/include/memstr.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -36,8 +36,11 @@
 
 extern void *memcpy(void *, const void *, size_t)
-    __attribute__ ((optimize("-fno-tree-loop-distribute-patterns")));
+    __attribute__((nonnull(1, 2)))
+    __attribute__((optimize("-fno-tree-loop-distribute-patterns")));
 extern void *memset(void *, int, size_t)
-    __attribute__ ((optimize("-fno-tree-loop-distribute-patterns")));
-extern void *memmove(void *, const void *, size_t);
+    __attribute__((nonnull(1)))
+    __attribute__((optimize("-fno-tree-loop-distribute-patterns")));
+extern void *memmove(void *, const void *, size_t)
+    __attribute__((nonnull(1, 2)));
 
 #endif
Index: kernel/arch/abs32le/src/abs32le.c
===================================================================
--- kernel/arch/abs32le/src/abs32le.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/abs32le/src/abs32le.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -69,5 +69,5 @@
 }
 
-void arch_post_cpu_init()
+void arch_post_cpu_init(void)
 {
 }
Index: kernel/arch/amd64/include/arch/asm.h
===================================================================
--- kernel/arch/amd64/include/arch/asm.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/amd64/include/arch/asm.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -339,5 +339,5 @@
  *
  */
-NO_TRACE static inline void enable_l_apic_in_msr()
+NO_TRACE static inline void enable_l_apic_in_msr(void)
 {
 	asm volatile (
Index: kernel/arch/amd64/src/fpu_context.c
===================================================================
--- kernel/arch/amd64/src/fpu_context.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/amd64/src/fpu_context.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -54,5 +54,5 @@
 }
 
-void fpu_init()
+void fpu_init(void)
 {
 	/* TODO: Zero all SSE, MMX etc. registers */
Index: kernel/arch/arm32/include/arch/cp15.h
===================================================================
--- kernel/arch/arm32/include/arch/cp15.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/arm32/include/arch/cp15.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -47,5 +47,5 @@
 
 #define CONTROL_REG_GEN_READ(name, crn, opc1, crm, opc2) \
-static inline uint32_t name##_read() \
+static inline uint32_t name##_read(void) \
 { \
 	uint32_t val; \
Index: kernel/arch/arm32/include/arch/security_ext.h
===================================================================
--- kernel/arch/arm32/include/arch/security_ext.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/arm32/include/arch/security_ext.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -46,5 +46,5 @@
  * older archs.
  */
-static inline bool sec_ext_is_implemented()
+static inline bool sec_ext_is_implemented(void)
 {
 #ifdef PROCESSOR_ARCH_armv7_a
@@ -60,5 +60,5 @@
  * mode.
  */
-static inline bool sec_ext_is_monitor_mode()
+static inline bool sec_ext_is_monitor_mode(void)
 {
 	return (current_status_reg_read() & MODE_MASK) == MONITOR_MODE;
@@ -75,5 +75,5 @@
  * Look for 'secureworld_exit' in arch/arm/cpu/armv7/omap3/board.c.
  */
-static inline bool sec_ext_is_secure()
+static inline bool sec_ext_is_secure(void)
 {
 	return sec_ext_is_implemented()
Index: kernel/arch/arm32/src/arm32.c
===================================================================
--- kernel/arch/arm32/src/arm32.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/arm32/src/arm32.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -158,5 +158,5 @@
 
 /** Reboot. */
-void arch_reboot()
+void arch_reboot(void)
 {
 	/* not implemented */
Index: kernel/arch/arm32/src/fpu_context.c
===================================================================
--- kernel/arch/arm32/src/fpu_context.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/arm32/src/fpu_context.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -101,4 +101,5 @@
 	FPSCR_EN_ALL = FPSCR_DENORMAL_EN_FLAG | FPSCR_INEXACT_EN_FLAG | FPSCR_UNDERFLOW_EN_FLAG | FPSCR_OVERFLOW_EN_FLAG | FPSCR_ZERO_DIV_EN_FLAG | FPSCR_INVALID_OP_EN_FLAG,
 };
+
 extern uint32_t fpscr_read(void);
 extern void fpscr_write(uint32_t);
@@ -114,7 +115,8 @@
 static void (*restore_context)(fpu_context_t *ctx);
 
-static int fpu_have_coprocessor_access()
-{
-/* The register containing the information (CPACR) is not available on armv6-
+static int fpu_have_coprocessor_access(void)
+{
+/*
+ * The register containing the information (CPACR) is not available on armv6-
  * rely on user decision to use CONFIG_FPU.
  */
@@ -143,7 +145,8 @@
  * @note do we need to call secure monitor here?
  */
-static void fpu_enable_coprocessor_access()
-{
-/* The register containing the information (CPACR) is not available on armv6-
+static void fpu_enable_coprocessor_access(void)
+{
+/*
+ * The register containing the information (CPACR) is not available on armv6-
  * rely on user decision to use CONFIG_FPU.
  */
Index: kernel/arch/ia32/src/fpu_context.c
===================================================================
--- kernel/arch/ia32/src/fpu_context.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/ia32/src/fpu_context.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -125,5 +125,5 @@
 
 /** Initialize x87 FPU. Mask all exceptions. */
-void fpu_init()
+void fpu_init(void)
 {
 	uint32_t help0 = 0;
Index: kernel/arch/ia64/src/mm/vhpt.c
===================================================================
--- kernel/arch/ia64/src/mm/vhpt.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/ia64/src/mm/vhpt.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -82,5 +82,5 @@
 }
 
-void vhpt_invalidate_all()
+void vhpt_invalidate_all(void)
 {
 	memsetb(vhpt_base, VHPT_SIZE, 0);
Index: kernel/arch/mips32/src/debugger.c
===================================================================
--- kernel/arch/mips32/src/debugger.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/mips32/src/debugger.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -288,5 +288,5 @@
  *
  */
-void debugger_init()
+void debugger_init(void)
 {
 	unsigned int i;
Index: kernel/arch/mips32/src/fpu_context.c
===================================================================
--- kernel/arch/mips32/src/fpu_context.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/mips32/src/fpu_context.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -53,5 +53,5 @@
 }
 
-void fpu_init()
+void fpu_init(void)
 {
 	/* TODO: Zero all registers */
Index: kernel/arch/sparc32/src/sparc32.c
===================================================================
--- kernel/arch/sparc32/src/sparc32.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/arch/sparc32/src/sparc32.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -96,5 +96,5 @@
 
 
-void arch_post_cpu_init()
+void arch_post_cpu_init(void)
 {
 }
Index: kernel/generic/include/lib/memfnc.h
===================================================================
--- kernel/generic/include/lib/memfnc.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/include/lib/memfnc.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -46,6 +46,8 @@
 
 extern void *memset(void *, int, size_t)
+    __attribute__((nonnull(1)))
     ATTRIBUTE_OPTIMIZE("-fno-tree-loop-distribute-patterns") DO_NOT_DISCARD;
 extern void *memcpy(void *, const void *, size_t)
+    __attribute__((nonnull(1, 2)))
     ATTRIBUTE_OPTIMIZE("-fno-tree-loop-distribute-patterns") DO_NOT_DISCARD;
 
Index: kernel/generic/include/memstr.h
===================================================================
--- kernel/generic/include/memstr.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/include/memstr.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -48,7 +48,10 @@
 #define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
 
-extern void memsetb(void *, size_t, uint8_t);
-extern void memsetw(void *, size_t, uint16_t);
-extern void *memmove(void *, const void *, size_t) DO_NOT_DISCARD;
+extern void memsetb(void *, size_t, uint8_t)
+    __attribute__((nonnull(1)));
+extern void memsetw(void *, size_t, uint16_t)
+    __attribute__((nonnull(1)));
+extern void *memmove(void *, const void *, size_t)
+    __attribute__((nonnull(1, 2))) DO_NOT_DISCARD;
 
 #endif
Index: kernel/generic/include/mm/slab.h
===================================================================
--- kernel/generic/include/mm/slab.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/include/mm/slab.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -142,5 +142,6 @@
 extern void *malloc(size_t, unsigned int)
     __attribute__((malloc));
-extern void *realloc(void *, size_t, unsigned int);
+extern void *realloc(void *, size_t, unsigned int)
+    __attribute__((warn_unused_result));
 extern void free(void *);
 
Index: kernel/generic/include/typedefs.h
===================================================================
--- kernel/generic/include/typedefs.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/include/typedefs.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -50,5 +50,5 @@
 } atomic_t;
 
-typedef void (* function)();
+typedef void (* function)(void);
 
 typedef uint32_t container_id_t;
Index: kernel/generic/src/ipc/ops/conctmeto.c
===================================================================
--- kernel/generic/src/ipc/ops/conctmeto.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/src/ipc/ops/conctmeto.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -44,4 +44,6 @@
 	int newphid = phone_alloc(TASK);
 
+	/* Remember the phoneid or the error. */
+	call->priv = newphid;
 	if (newphid < 0)
 		return ELIMIT;
@@ -49,5 +51,4 @@
 	/* Set arg5 for server */
 	IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
-	call->priv = newphid;
 
 	return EOK;
@@ -73,8 +74,17 @@
 static int answer_process(call_t *answer)
 {
-	if (IPC_GET_RETVAL(answer->data))
-		phone_dealloc(answer->priv);
-	else
-		IPC_SET_ARG5(answer->data, answer->priv);
+	int newphid = (int) answer->priv;
+
+	if (IPC_GET_RETVAL(answer->data)) {
+		if (newphid >= 0) {
+			/*
+			 * The phone was indeed allocated and now needs
+			 * to be deallocated.
+			 */
+			phone_dealloc(newphid);
+		}
+	} else {
+		IPC_SET_ARG5(answer->data, newphid);
+	}
 	
 	return EOK;
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/src/ipc/sysipc.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -388,15 +388,15 @@
 {
 	call_t *call = get_call(callid);
-	phone_t *phone;
-	bool need_old = answer_need_old(call);
-	bool after_forward = false;
-	ipc_data_t old;
-	int rc;
-
 	if (!call)
 		return ENOENT;
-
+	
+	ipc_data_t old;
+	bool need_old = answer_need_old(call);
 	if (need_old)
 		old = call->data;
+	
+	bool after_forward = false;
+	int rc;
+	phone_t *phone;
 	
 	if (phone_get(phoneid, &phone) != EOK) {
@@ -409,5 +409,5 @@
 		goto error;
 	}
-
+	
 	call->flags |= IPC_CALL_FORWARDED;
 	
Index: kernel/generic/src/lib/func.c
===================================================================
--- kernel/generic/src/lib/func.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/src/lib/func.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -51,5 +51,5 @@
  *
  */
-void halt()
+void halt(void)
 {
 #if (defined(CONFIG_DEBUG)) && (defined(CONFIG_KCONSOLE))
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/src/mm/as.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -834,12 +834,12 @@
 			if ((cond = (bool) node->keys)) {
 				uintptr_t ptr = node->key[node->keys - 1];
-				size_t size =
+				size_t node_size =
 				    (size_t) node->value[node->keys - 1];
 				size_t i = 0;
 				
-				if (overlaps(ptr, P2SZ(size), area->base,
+				if (overlaps(ptr, P2SZ(node_size), area->base,
 				    P2SZ(pages))) {
 					
-					if (ptr + P2SZ(size) <= start_free) {
+					if (ptr + P2SZ(node_size) <= start_free) {
 						/*
 						 * The whole interval fits
@@ -860,5 +860,5 @@
 					i = (start_free - ptr) >> PAGE_WIDTH;
 					if (!used_space_remove(area, start_free,
-					    size - i))
+					    node_size - i))
 						panic("Cannot remove used space.");
 				} else {
@@ -867,5 +867,5 @@
 					 * completely removed.
 					 */
-					if (!used_space_remove(area, ptr, size))
+					if (!used_space_remove(area, ptr, node_size))
 						panic("Cannot remove used space.");
 				}
@@ -887,5 +887,5 @@
 				    area->pages - pages);
 		
-				for (; i < size; i++) {
+				for (; i < node_size; i++) {
 					pte_t *pte = page_mapping_find(as,
 					    ptr + P2SZ(i), false);
Index: kernel/generic/src/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/src/mm/slab.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -610,4 +610,6 @@
     unsigned int kmflag), size_t (*destructor)(void *obj), unsigned int flags)
 {
+	ASSERT(size > 0);
+	
 	memsetb(cache, sizeof(*cache), 0);
 	cache->name = name;
@@ -888,5 +890,5 @@
 	/* Initialize magazine cache */
 	_slab_cache_create(&mag_cache, "slab_magazine_t",
-	    sizeof(slab_magazine_t) + SLAB_MAG_SIZE * sizeof(void*),
+	    sizeof(slab_magazine_t) + SLAB_MAG_SIZE * sizeof(void *),
 	    sizeof(uintptr_t), NULL, NULL, SLAB_CACHE_NOMAGAZINE |
 	    SLAB_CACHE_SLINSIDE);
Index: kernel/generic/src/synch/futex.c
===================================================================
--- kernel/generic/src/synch/futex.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/src/synch/futex.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -400,5 +400,13 @@
 		return (sysarg_t) ENOENT;
 
+#ifdef CONFIG_UDEBUG
+	udebug_stoppable_begin();
+#endif
+
 	int rc = waitq_sleep_timeout(&futex->wq, 0, SYNCH_FLAGS_INTERRUPTIBLE); 
+
+#ifdef CONFIG_UDEBUG
+	udebug_stoppable_end();
+#endif
 
 	return (sysarg_t) rc;
Index: kernel/generic/src/udebug/udebug_ops.c
===================================================================
--- kernel/generic/src/udebug/udebug_ops.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ kernel/generic/src/udebug/udebug_ops.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -375,4 +375,5 @@
 	if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) {
 		mutex_unlock(&TASK->udebug.lock);
+		free(id_buffer);
 		return EINVAL;
 	}
@@ -456,7 +457,4 @@
 int udebug_args_read(thread_t *thread, void **buffer)
 {
-	/* Prepare a buffer to hold the arguments. */
-	sysarg_t *arg_buffer = malloc(6 * sizeof(sysarg_t), 0);
-	
 	/* On success, this will lock t->udebug.lock. */
 	int rc = _thread_op_begin(thread, false);
@@ -471,4 +469,7 @@
 	}
 	
+	/* Prepare a buffer to hold the arguments. */
+	sysarg_t *arg_buffer = malloc(6 * sizeof(sysarg_t), 0);
+	
 	/* Copy to a local buffer before releasing the lock. */
 	memcpy(arg_buffer, thread->udebug.syscall_args, 6 * sizeof(sysarg_t));
@@ -499,7 +500,4 @@
 int udebug_regs_read(thread_t *thread, void **buffer)
 {
-	/* Prepare a buffer to hold the data. */
-	istate_t *state_buf = malloc(sizeof(istate_t), 0);
-	
 	/* On success, this will lock t->udebug.lock */
 	int rc = _thread_op_begin(thread, false);
@@ -512,4 +510,7 @@
 		return EBUSY;
 	}
+	
+	/* Prepare a buffer to hold the data. */
+	istate_t *state_buf = malloc(sizeof(istate_t), 0);
 	
 	/* Copy to the allocated buffer */
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/Makefile	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -77,9 +77,4 @@
 	app/usbinfo \
 	app/vuhid \
-	app/netecho \
-	app/netspeed \
-	app/nettest1 \
-	app/nettest2 \
-	app/nettest3 \
 	app/nic \
 	app/ping \
@@ -235,5 +230,5 @@
 	lib/draw \
 	lib/math \
-	lib/net \
+	lib/nettl \
 	lib/nic \
 	lib/ext4 \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/Makefile.common	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -142,5 +142,4 @@
 LIBHOUND_PREFIX = $(LIB_PREFIX)/hound
 LIBPCM_PREFIX = $(LIB_PREFIX)/pcm
-LIBNET_PREFIX = $(LIB_PREFIX)/net
 LIBNIC_PREFIX = $(LIB_PREFIX)/nic
 LIBIEEE80211_PREFIX = $(LIB_PREFIX)/ieee80211
@@ -158,4 +157,5 @@
 LIBMBR_PREFIX = $(LIB_PREFIX)/mbr
 LIBGPT_PREFIX = $(LIB_PREFIX)/gpt
+LIBNETTL_PREFIX = $(LIB_PREFIX)/nettl
 
 LIBURCU_PREFIX = $(LIB_PREFIX)/urcu
@@ -264,5 +264,5 @@
 
 ifeq ($(CONFIG_LINE_DEBUG),y)
-	GCC_CFLAGS += -g
+	GCC_CFLAGS += -ggdb
 	ICC_CFLAGS += -g
 	CLANG_CFLAGS += -g
Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -108,5 +108,5 @@
 }
 
-static void waitprompt()
+static void waitprompt(void)
 {
 	console_set_pos(console, 0, console_rows-1);
@@ -120,5 +120,5 @@
 }
 
-static void waitkey()
+static void waitkey(void)
 {
 	cons_event_t ev;
@@ -149,5 +149,5 @@
 }
 
-static void newpage()
+static void newpage(void)
 {
 	console_clear(console);
Index: uspace/app/bdsh/input.c
===================================================================
--- uspace/app/bdsh/input.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/app/bdsh/input.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -219,5 +219,5 @@
 }
 
-void print_pipe_usage()
+void print_pipe_usage(void)
 {
 	printf("Invalid syntax!\n");
Index: uspace/app/download/main.c
===================================================================
--- uspace/app/download/main.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/app/download/main.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -36,4 +36,5 @@
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,8 +43,4 @@
 #include <task.h>
 #include <macros.h>
-
-#include <net/in.h>
-#include <net/inet.h>
-#include <net/socket.h>
 
 #include <http/http.h>
Index: pace/app/netecho/Makefile
===================================================================
--- uspace/app/netecho/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,39 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# 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 = ../..
-LIBS = 
-EXTRA_CFLAGS = 
-BINARY = netecho
-
-SOURCES = \
-	netecho.c \
-	print_error.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/netecho/netecho.c
===================================================================
--- uspace/app/netecho/netecho.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,457 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 netecho
- * @{
- */
-
-/** @file
- * Network echo server.
- *
- * Sockets-based server that echoes incomming messages. If stream mode
- * is selected, accepts incoming connections.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <str.h>
-#include <task.h>
-#include <arg_parse.h>
-
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/socket.h>
-#include <net/socket_parse.h>
-
-#include "print_error.h"
-
-#define NAME "netecho"
-
-static int count = -1;
-static int family = PF_INET;
-static sock_type_t type = SOCK_DGRAM;
-static uint16_t port = 7;
-static int backlog = 3;
-static size_t size = 1024;
-static int verbose = 0;
-
-static char *reply = NULL;
-static size_t reply_length;
-
-static char *data;
-
-static void echo_print_help(void)
-{
-	printf(
-	    "Network echo server\n"
-	    "Usage: " NAME " [options]\n"
-	    "Where options are:\n"
-	    "-b backlog | --backlog=size\n"
-	    "\tThe size of the accepted sockets queue. Only for SOCK_STREAM. "
-	    "The default is 3.\n"
-	    "\n"
-	    "-c count | --count=count\n"
-	    "\tThe number of received messages to handle. A negative number "
-	    "means infinity. The default is infinity.\n"
-	    "\n"
-	    "-f protocol_family | --family=protocol_family\n"
-	    "\tThe listenning socket protocol family. Only the PF_INET and "
-	    "PF_INET6 are supported.\n"
-	    "\n"
-	    "-h | --help\n"
-	    "\tShow this application help.\n"
-	    "\n"
-	    "-p port_number | --port=port_number\n"
-	    "\tThe port number the application should listen at. The default "
-	    "is 7.\n"
-	    "\n"
-	    "-r reply_string | --reply=reply_string\n"
-	    "\tThe constant reply string. The default is the original data "
-	    "received.\n"
-	    "\n"
-	    "-s receive_size | --size=receive_size\n"
-	    "\tThe maximum receive data size the application should accept. "
-	    "The default is 1024 bytes.\n"
-	    "\n"
-	    "-t socket_type | --type=socket_type\n"
-	    "\tThe listenning socket type. Only the SOCK_DGRAM and the "
-	    "SOCK_STREAM are supported.\n"
-	    "\n"
-	    "-v | --verbose\n"
-	    "\tShow all output messages.\n"
-	);
-}
-
-static int netecho_parse_option(int argc, char *argv[], int *index)
-{
-	int value;
-	int rc;
-
-	switch (argv[*index][1]) {
-	case 'b':
-		rc = arg_parse_int(argc, argv, index, &backlog, 0);
-		if (rc != EOK)
-			return rc;
-		break;
-	case 'c':
-		rc = arg_parse_int(argc, argv, index, &count, 0);
-		if (rc != EOK)
-			return rc;
-		break;
-	case 'f':
-		rc = arg_parse_name_int(argc, argv, index, &family, 0,
-		    socket_parse_protocol_family);
-		if (rc != EOK)
-			return rc;
-		break;
-	case 'h':
-		echo_print_help();
-		exit(0);
-		break;
-	case 'p':
-		rc = arg_parse_int(argc, argv, index, &value, 0);
-		if (rc != EOK)
-			return rc;
-		port = (uint16_t) value;
-		break;
-	case 'r':
-		rc = arg_parse_string(argc, argv, index, &reply, 0);
-		if (rc != EOK)
-			return rc;
-		break;
-	case 's':
-		rc = arg_parse_int(argc, argv, index, &value, 0);
-		if (rc != EOK)
-			return rc;
-		size = (value >= 0) ? (size_t) value : 0;
-		break;
-	case 't':
-		rc = arg_parse_name_int(argc, argv, index, &value, 0,
-		    socket_parse_socket_type);
-		if (rc != EOK)
-			return rc;
-		type = (sock_type_t) value;
-		break;
-	case 'v':
-		verbose = 1;
-		break;
-	/* Long options with double dash */
-	case '-':
-		if (str_lcmp(argv[*index] + 2, "backlog=", 6) == 0) {
-			rc = arg_parse_int(argc, argv, index, &backlog, 8);
-			if (rc != EOK)
-				return rc;
-		} else if (str_lcmp(argv[*index] + 2, "count=", 6) == 0) {
-			rc = arg_parse_int(argc, argv, index, &count, 8);
-			if (rc != EOK)
-				return rc;
-		} else if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
-			rc = arg_parse_name_int(argc, argv, index, &family, 9,
-			    socket_parse_protocol_family);
-			if (rc != EOK)
-				return rc;
-		} else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
-			echo_print_help();
-			exit(0);
-		} else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
-			rc = arg_parse_int(argc, argv, index, &value, 7);
-			if (rc != EOK)
-				return rc;
-			port = (uint16_t) value;
-		} else if (str_lcmp(argv[*index] + 2, "reply=", 6) == 0) {
-			rc = arg_parse_string(argc, argv, index, &reply, 8);
-			if (rc != EOK)
-				return rc;
-		} else if (str_lcmp(argv[*index] + 2, "size=", 5) == 0) {
-			rc = arg_parse_int(argc, argv, index, &value, 7);
-			if (rc != EOK)
-				return rc;
-			size = (value >= 0) ? (size_t) value : 0;
-		} else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
-			rc = arg_parse_name_int(argc, argv, index, &value, 7,
-			    socket_parse_socket_type);
-			if (rc != EOK)
-				return rc;
-			type = (sock_type_t) value;
-		} else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
-			verbose = 1;
-		} else {
-			echo_print_help();
-			return EINVAL;
-		}
-		break;
-	default:
-		echo_print_help();
-		return EINVAL;
-	}
-
-	return EOK;
-}
-
-/** Echo one message (accept one connection and echo message).
- *
- * @param listening_id	Listening socket.
- * @return		EOK on success or negative error code.
- */
-static int netecho_socket_process_message(int listening_id)
-{
-	uint8_t address_buf[sizeof(struct sockaddr_in6)];
-
-	socklen_t addrlen = sizeof(struct sockaddr_in6);
-	int socket_id;
-	ssize_t rcv_size;
-	size_t length;
-	uint8_t *address_start;
-
-	char address_string[INET6_ADDRSTRLEN];
-	struct sockaddr_in *address_in = (struct sockaddr_in *) address_buf;
-	struct sockaddr_in6 *address_in6 = (struct sockaddr_in6 *) address_buf;
-	struct sockaddr *address = (struct sockaddr *) address_buf;
-
-	int rc;
-
-	if (type == SOCK_STREAM) {
-		/* Accept a socket if a stream socket is used */
-		if (verbose)
-			printf("accept()\n");
-		socket_id = accept(listening_id, (void *) address_buf, &addrlen);
-		if (socket_id <= 0) {
-			socket_print_error(stderr, socket_id, "Socket accept: ", "\n");
-		} else {
-			if (verbose)
-				printf("Socket %d accepted\n", socket_id);
-		}
-
-		assert((size_t) addrlen <= sizeof(address_buf));
-	} else {
-		socket_id = listening_id;
-	}
-
-	/* if the datagram socket is used or the stream socked was accepted */
-	if (socket_id > 0) {
-
-		/* Receive a message to echo */
-		if (verbose)
-			printf("recvfrom()\n");
-		rcv_size = recvfrom(socket_id, data, size, 0, address,
-		    &addrlen);
-		if (rcv_size < 0) {
-			socket_print_error(stderr, rcv_size, "Socket receive: ", "\n");
-		} else {
-			length = (size_t) rcv_size;
-			if (verbose) {
-				/* Print the header */
-
-				/* Get the source port and prepare the address buffer */
-				address_start = NULL;
-				switch (address->sa_family) {
-				case AF_INET:
-					port = ntohs(address_in->sin_port);
-					address_start = (uint8_t *) &address_in->sin_addr.s_addr;
-					break;
-				case AF_INET6:
-					port = ntohs(address_in6->sin6_port);
-					address_start = (uint8_t *) address_in6->sin6_addr.s6_addr;
-					break;
-				default:
-					fprintf(stderr, "Address family %u (%#x) is not supported.\n",
-					    address->sa_family, address->sa_family);
-				}
-
-				/* Parse source address */
-				if (address_start) {
-					rc = inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string));
-					if (rc != EOK) {
-						fprintf(stderr, "Received address error %d\n", rc);
-					} else {
-						data[length] = '\0';
-						printf("Socket %d received %zu bytes from %s:%d\n%s\n",
-						    socket_id, length, address_string, port, data);
-					}
-				}
-			}
-
-			/* Answer the request either with the static reply or the original data */
-			if (type == SOCK_STREAM) {
-				if (verbose)
-					printf("send()\n");
-				rc = send(socket_id, reply ? reply : data, reply ? reply_length : length, 0);
-				if (rc != EOK)
-					socket_print_error(stderr, rc, "Socket send: ", "\n");
-			} else {
-				if (verbose)
-					printf("sendto()\n");
-				rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen);
-				if (rc != EOK)
-					socket_print_error(stderr, rc, "Socket sendto: ", "\n");
-			}
-		}
-
-		/* Close accepted stream socket */
-		if (type == SOCK_STREAM) {
-			rc = closesocket(socket_id);
-			if (rc != EOK)
-				socket_print_error(stderr, rc, "Close socket: ", "\n");
-		}
-
-	}
-
-	return EOK;
-}
-
-
-int main(int argc, char *argv[])
-{
-	struct sockaddr *address;;
-	struct sockaddr_in address_in;
-	struct sockaddr_in6 address_in6;
-	socklen_t addrlen;
-
-	int listening_id;
-	int index;
-	int rc;
-
-	/* Parse command line arguments */
-	for (index = 1; index < argc; ++index) {
-		if (argv[index][0] == '-') {
-			rc = netecho_parse_option(argc, argv, &index);
-			if (rc != EOK)
-				return rc;
-		} else {
-			echo_print_help();
-			return EINVAL;
-		}
-	}
-
-	/* Check buffer size */
-	if (size <= 0) {
-		fprintf(stderr, "Receive size too small (%zu). Using 1024 bytes instead.\n", size);
-		size = 1024;
-	}
-
-	/* size plus the terminating null character. */
-	data = (char *) malloc(size + 1);
-	if (!data) {
-		fprintf(stderr, "Failed to allocate receive buffer.\n");
-		return ENOMEM;
-	}
-
-	/* Set the reply size if set */
-	reply_length = reply ? str_length(reply) : 0;
-
-	/* Prepare the address buffer */
-	switch (family) {
-	case PF_INET:
-		address_in.sin_family = AF_INET;
-		address_in.sin_port = htons(port);
-		address_in.sin_addr.s_addr = INADDR_ANY;
-		address = (struct sockaddr *) &address_in;
-		addrlen = sizeof(address_in);
-		break;
-	case PF_INET6:
-		address_in6.sin6_family = AF_INET6;
-		address_in6.sin6_port = htons(port);
-		address_in6.sin6_addr = in6addr_any;
-		address = (struct sockaddr *) &address_in6;
-		addrlen = sizeof(address_in6);
-		break;
-	default:
-		fprintf(stderr, "Protocol family is not supported\n");
-		return EAFNOSUPPORT;
-	}
-
-	/* Get a listening socket */
-	listening_id = socket(family, type, 0);
-	if (listening_id < 0) {
-		socket_print_error(stderr, listening_id, "Socket create: ", "\n");
-		return listening_id;
-	}
-	
-	/* Bind the listening socket */
-	rc = bind(listening_id, address, addrlen);
-	if (rc != EOK) {
-		socket_print_error(stderr, rc, "Socket bind: ", "\n");
-		return rc;
-	}
-	
-	/* if the stream socket is used */
-	if (type == SOCK_STREAM) {
-		/* Check backlog size */
-		if (backlog <= 0) {
-			fprintf(stderr, "Accepted sockets queue size too small (%zu). Using 3 instead.\n", size);
-			backlog = 3;
-		}
-		
-		/* Set the backlog */
-		rc = listen(listening_id, backlog);
-		if (rc != EOK) {
-			socket_print_error(stderr, rc, "Socket listen: ", "\n");
-			return rc;
-		}
-	}
-
-	if (verbose)
-		printf("Socket %d listenning at %d\n", listening_id, port);
-
-	/*
-	 * do count times
-	 * or indefinitely if set to a negative value
-	 */
-	while (count) {
-		rc = netecho_socket_process_message(listening_id);
-		if (rc != EOK)
-			break;
-
-		/* Decrease count if positive */
-		if (count > 0) {
-			count--;
-			if (verbose)
-				printf("Waiting for next %d message(s)\n", count);
-		}
-	}
-
-	if (verbose)
-		printf("Closing the socket\n");
-
-	/* Close listenning socket */
-	rc = closesocket(listening_id);
-	if (rc != EOK) {
-		socket_print_error(stderr, rc, "Close socket: ", "\n");
-		return rc;
-	}
-
-	if (verbose)
-		printf("Exiting\n");
-
-	return EOK;
-}
-
-/** @}
- */
Index: pace/app/netecho/print_error.c
===================================================================
--- uspace/app/netecho/print_error.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,114 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 net_app
- * @{
- */
-
-/** @file
- * Generic application error printing functions implementation.
- */
-
-#include "print_error.h"
-
-#include <stdio.h>
-#include <errno.h>
-
-/** Prints the error description.
- *
- * Supports socket error codes.
- *
- * @param[in] output The description output stream. May be NULL.
- * @param[in] error_code The error code.
- * @param[in] prefix The error description prefix. May be NULL.
- * @param[in] suffix The error description suffix. May be NULL.
- */
-void print_error(FILE *output, int error_code, const char *prefix, const char *suffix)
-{
-	if(IS_SOCKET_ERROR(error_code))
-		socket_print_error(output, error_code, prefix, suffix);
-}
-
-/** Prints the specific socket error description.
- *
- * @param[in] output The description output stream. May be NULL.
- * @param[in] error_code The socket error code.
- * @param[in] prefix The error description prefix. May be NULL.
- * @param[in] suffix The error description suffix. May be NULL.
- */
-void socket_print_error(FILE *output, int error_code, const char *prefix, const char *suffix)
-{
-	if (!output)
-		return;
-
-	if (prefix)
-		fprintf(output, "%s", prefix);
-
-	switch (error_code) {
-	case ENOTSOCK:
-		fprintf(output, "Not a socket (%d) error", error_code);
-		break;
-	case EPROTONOSUPPORT:
-		fprintf(output, "Protocol not supported (%d) error", error_code);
-		break;
-	case ESOCKTNOSUPPORT:
-		fprintf(output, "Socket type not supported (%d) error", error_code);
-		break;
-	case EPFNOSUPPORT:
-		fprintf(output, "Protocol family not supported (%d) error", error_code);
-		break;
-	case EAFNOSUPPORT:
-		fprintf(output, "Address family not supported (%d) error", error_code);
-		break;
-	case EADDRINUSE:
-		fprintf(output, "Address already in use (%d) error", error_code);
-		break;
-	case ENOTCONN:
-		fprintf(output, "Socket not connected (%d) error", error_code);
-		break;
-	case NO_DATA:
-		fprintf(output, "No data (%d) error", error_code);
-		break;
-	case EINPROGRESS:
-		fprintf(output, "Another operation in progress (%d) error", error_code);
-		break;
-	case EDESTADDRREQ:
-		fprintf(output, "Destination address required (%d) error", error_code);
-	case EAGAIN:
-		fprintf(output, "Try again (%d) error", error_code);
-	default:
-		fprintf(output, "Other (%d) error", error_code);
-	}
-
-	if (suffix)
-		fprintf(output, "%s", suffix);
-}
-
-/** @}
- */
-
Index: pace/app/netecho/print_error.h
===================================================================
--- uspace/app/netecho/print_error.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,63 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 net_app
- * @{
- */
-
-/** @file
- * Generic application error printing functions.
- */
-
-#ifndef NET_APP_PRINT_
-#define NET_APP_PRINT_
-
-#include <stdio.h>
-
-/** Returns whether the error code may be an ICMP error code.
- *
- * @param[in] error_code The error code.
- * @return A value indicating whether the error code may be an ICMP error code.
- */
-#define IS_ICMP_ERROR(error_code)	((error_code) > 0)
-
-/** Returns whether the error code may be socket error code.
- *
- * @param[in] error_code The error code.
- * @return A value indicating whether the error code may be a socket error code.
- */
-#define IS_SOCKET_ERROR(error_code)	((error_code) < 0)
-
-extern void icmp_print_error(FILE *, int, const char *, const char *);
-extern void print_error(FILE *, int, const char *, const char *);
-extern void socket_print_error(FILE *, int, const char *, const char *);
-
-#endif
-
-/** @}
- */
Index: pace/app/netspeed/Makefile
===================================================================
--- uspace/app/netspeed/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2013 Martin Sucha
-# 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 = ../..
-LIBS = 
-EXTRA_CFLAGS = 
-BINARY = netspeed
-
-SOURCES = \
-	netspeed.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/netspeed/netspeed.c
===================================================================
--- uspace/app/netspeed/netspeed.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,290 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Sucha
- * 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 netspeed
- * @{
- */
-
-/** @file
- * Network speed measurement (iperf counterpart)
- *
- */
-
-#include <assert.h>
-#include <inet/dnsr.h>
-#include <net/in.h>
-#include <net/inet.h>
-#include <net/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <str.h>
-#include <str_error.h>
-#include <task.h>
-
-#define NAME "netspeed"
-
-static int server(sock_type_t sock_type, unsigned port, void *buf, size_t bufsize)
-{
-	struct sockaddr_in addr;
-	
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	
-	int rc = inet_pton(AF_INET, "127.0.0.1", (void *)
-	    &addr.sin_addr.s_addr);
-	if (rc != EOK) {
-		fprintf(stderr, "inet_pton failed: %s\n", str_error(rc));
-		return rc;
-	}
-
-	int listen_sd = socket(PF_INET, sock_type, 0);
-	if (listen_sd < 0) {
-		fprintf(stderr, "socket failed: %s\n", str_error(rc));
-		return rc;
-	}
-	
-	rc = bind(listen_sd, (struct sockaddr *) &addr, sizeof(addr));
-	if (rc != EOK) {
-		fprintf(stderr, "bind failed: %s\n", str_error(rc));
-		closesocket(listen_sd);
-		return rc;
-	}
-	
-	rc = listen(listen_sd, 2);
-	if (rc != EOK) {
-		fprintf(stderr, "listen failed: %s\n", str_error(rc));
-		closesocket(listen_sd);
-		return rc;
-	}
-	
-	int conn_sd;
-	struct sockaddr_in raddr;
-	socklen_t raddr_len = sizeof(raddr);
-	if (sock_type == SOCK_STREAM) {
-		conn_sd = accept(listen_sd, (struct sockaddr *) &raddr,
-		    &raddr_len);
-		if (conn_sd < 0) {
-			fprintf(stderr, "accept failed: %s\n", str_error(conn_sd));
-			closesocket(listen_sd);
-			return conn_sd;
-		}
-	} else {
-		conn_sd = listen_sd;
-	}
-	
-	while (true) {
-		rc = recvfrom(conn_sd, buf, bufsize, 0, (struct sockaddr *) &raddr,
-		    &raddr_len);
-		if (rc <= 0) {
-			if (rc < 0)
-				fprintf(stderr, "recvfrom failed: %s\n", str_error(rc));
-			break;
-		}
-	}
-	
-	if (sock_type == SOCK_STREAM)
-		closesocket(conn_sd);
-	closesocket(listen_sd);
-	
-	return rc;
-}
-
-static int client(sock_type_t sock_type, const char *host, unsigned port,
-    unsigned long count, char *buf, size_t bufsize)
-{
-	inet_addr_t iaddr;
-	struct sockaddr *saddr;
-	socklen_t saddrlen;
-	
-	int rc = inet_addr_parse(host, &iaddr);
-	if (rc != EOK) {
-		dnsr_hostinfo_t *hinfo = NULL;
-		rc = dnsr_name2host(host, &hinfo, ip_any);
-		if (rc != EOK) {
-			fprintf(stderr, "Error resolving host '%s'.\n", host);
-			return ENOENT;
-		}
-		
-		iaddr = hinfo->addr;
-	}
-	
-	rc = inet_addr_sockaddr(&iaddr, port, &saddr, &saddrlen);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		fprintf(stderr, "Out of memory.\n");
-		return ENOMEM;
-	}
-	
-	int conn_sd = socket(saddr->sa_family, sock_type, 0);
-	if (conn_sd < 0) {
-		fprintf(stderr, "socket failed: %s\n", str_error(rc));
-		return rc;
-	}
-	
-	if (sock_type == SOCK_STREAM) {
-		rc = connect(conn_sd, saddr, saddrlen);
-		if (rc != EOK) {
-			fprintf(stderr, "connect failed: %s\n", str_error(rc));
-			closesocket(conn_sd);
-			return rc;
-		}
-	}
-	
-	for (size_t pos = 0; pos < bufsize; pos++) {
-		buf[pos] = '0' + (pos % 10);
-	}
-	
-	for (unsigned long i = 0; i < count; i++) {
-		if (sock_type == SOCK_STREAM) {
-			rc = send(conn_sd, buf, bufsize, 0);
-		} else {
-			rc = sendto(conn_sd, buf, bufsize, 0, saddr, saddrlen);
-		}
-		if (rc != EOK) {
-			fprintf(stderr, "send failed: %s\n", str_error(rc));
-			break;
-		}
-	}
-	
-	closesocket(conn_sd);
-	free(saddr);
-	return rc;
-}
-
-static void syntax_print(void)
-{
-	fprintf(stderr, "Usage: netspeed <tcp|udp> server [port] <buffer size>\n");
-	fprintf(stderr, "       netspeed <tcp|udp> client <host> <port> <count> <buffer size>\n");
-}
-
-int main(int argc, char *argv[])
-{
-	if (argc < 3) {
-		syntax_print();
-		return 2;
-	}
-	
-	sock_type_t sock_type;
-	if (str_cmp(argv[1], "tcp") == 0) {
-		sock_type = SOCK_STREAM;
-	} else if (str_cmp(argv[1], "udp") == 0) {
-		sock_type = SOCK_DGRAM;
-	} else {
-		fprintf(stderr, "Invalid socket type\n");
-		syntax_print();
-		return 1;
-	}
-	
-	char *endptr;
-	int arg = 3;
-	unsigned long port = 5001;
-	const char *address;
-	bool is_server;
-	unsigned long count = 0;
-	
-	if (str_cmp(argv[2], "server") == 0) {
-		is_server = true;
-		if (argc < 4) {
-			syntax_print();
-			return 2;
-		}
-		if (argc > 4) {
-			port = strtoul(argv[3], &endptr, 0);
-			if (*endptr != 0) {
-				fprintf(stderr, "Invalid port number\n");
-				syntax_print();
-				return 1;
-			}
-			arg = 4;
-		}
-	}
-	else if (str_cmp(argv[2], "client") == 0) {
-		is_server = false;
-		if (argc < 6) {
-			syntax_print();
-			return 2;
-		}
-		address = argv[3];
-		port = strtoul(argv[4], &endptr, 0);
-		if (*endptr != 0) {
-			fprintf(stderr, "Invalid port number\n");
-			syntax_print();
-			return 1;
-		}
-		
-		count = strtoul(argv[5], &endptr, 0);
-		if (*endptr != 0) {
-			fprintf(stderr, "Invalid count\n");
-			syntax_print();
-			return 1;
-		}
-		
-		arg = 6;
-	}
-	else {
-		fprintf(stderr, "Invalid client/server mode\n");
-		syntax_print();
-		return 2;
-	}
-	
-	if (argc < arg + 1) {
-		syntax_print();
-		return 2;
-	}
-	
-	unsigned long bufsize = strtoul(argv[arg], &endptr, 0);
-	if (*endptr != 0 || bufsize == 0) {
-		fprintf(stderr, "Invalid buffer size\n");
-		syntax_print();
-		return 1;
-	}
-	
-	void *buf = malloc(bufsize);
-	if (buf == NULL) {
-		fprintf(stderr, "Cannot allocate buffer\n");
-		return ENOMEM;
-	}
-	
-	int rc = EOK;
-	if (is_server) {
-		rc = server(sock_type, port, buf, bufsize);
-		if (rc != EOK)
-			fprintf(stderr, "Server failed: %s\n", str_error(rc));
-	} else {
-		rc = client(sock_type, address, port, count, buf, bufsize);
-		if (rc != EOK)
-			fprintf(stderr, "Client failed: %s\n", str_error(rc));
-	}
-	
-	free(buf);
-
-	return rc;
-}
-
-/** @}
- */
Index: pace/app/nettest1/Makefile
===================================================================
--- uspace/app/nettest1/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,40 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# 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 = ../..
-LIBS = 
-EXTRA_CFLAGS = 
-BINARY = nettest1
-
-SOURCES = \
-	nettest1.c \
-	nettest.c \
-	print_error.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/nettest1/nettest.c
===================================================================
--- uspace/app/nettest1/nettest.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,321 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 nettest
- * @{
- */
-
-/** @file
- * Networking test support functions implementation.
- */
-
-#include <stdio.h>
-#include <net/socket.h>
-
-#include "nettest.h"
-#include "print_error.h"
-
-/** Creates new sockets.
- *
- * @param[in] verbose A value indicating whether to print out verbose information.
- * @param[out] socket_ids A field to store the socket identifiers.
- * @param[in] sockets The number of sockets to create. Should be at most the size of the field.
- * @param[in] family The socket address family.
- * @param[in] type The socket type.
- * @return EOK on success.
- * @return Other error codes as defined for the socket() function.
- */
-int sockets_create(int verbose, int *socket_ids, unsigned int sockets,
-    uint16_t family, sock_type_t type)
-{
-	if (verbose)
-		printf("Create\t");
-	
-	fflush(stdout);
-	
-	for (unsigned int index = 0; index < sockets; index++) {
-		socket_ids[index] = socket(family, type, 0);
-		if (socket_ids[index] < 0) {
-			printf("Socket %u (%d) error:\n", index, socket_ids[index]);
-			socket_print_error(stderr, socket_ids[index], "Socket create: ", "\n");
-			return socket_ids[index];
-		}
-		
-		if (verbose)
-			print_mark(index);
-	}
-	
-	return EOK;
-}
-
-/** Closes sockets.
- *
- * @param[in] verbose A value indicating whether to print out verbose information.
- * @param[in] socket_ids A field of stored socket identifiers.
- * @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
- * @return EOK on success.
- * @return Other error codes as defined for the closesocket() function.
- */
-int sockets_close(int verbose, int *socket_ids, unsigned int sockets)
-{
-	if (verbose)
-		printf("\tClose\t");
-	
-	fflush(stdout);
-	
-	for (unsigned int index = 0; index < sockets; index++) {
-		int rc = closesocket(socket_ids[index]);
-		if (rc != EOK) {
-			printf("Socket %u (%d) error:\n", index, socket_ids[index]);
-			socket_print_error(stderr, rc, "Socket close: ", "\n");
-			return rc;
-		}
-		
-		if (verbose)
-			print_mark(index);
-	}
-	
-	return EOK;
-}
-
-/** Connects sockets.
- *
- * @param[in] verbose A value indicating whether to print out verbose information.
- * @param[in] socket_ids A field of stored socket identifiers.
- * @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
- * @param[in] address The destination host address to connect to.
- * @param[in] addrlen The length of the destination address in bytes.
- * @return EOK on success.
- * @return Other error codes as defined for the connect() function.
- */
-int sockets_connect(int verbose, int *socket_ids, unsigned int sockets,
-    struct sockaddr *address, socklen_t addrlen)
-{
-	if (verbose)
-		printf("\tConnect\t");
-	
-	fflush(stdout);
-	
-	for (unsigned int index = 0; index < sockets; index++) {
-		int rc = connect(socket_ids[index], address, addrlen);
-		if (rc != EOK) {
-			socket_print_error(stderr, rc, "Socket connect: ", "\n");
-			return rc;
-		}
-		
-		if (verbose)
-			print_mark(index);
-	}
-	
-	return EOK;
-}
-
-/** Send data via sockets.
- *
- * @param[in] verbose    Print out verbose information.
- * @param[in] socket_ids Stored socket identifiers.
- * @param[in] sockets    Number of sockets.
- * @param[in] address    Destination host address to send data to.
- * @param[in] addrlen    Length of the destination address in bytes.
- * @param[in] data       Data to be sent.
- * @param[in] size       Size of the data in bytes.
- * @param[in] messages   Number of datagrams per socket to be sent.
- * @param[in] type       Socket type.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the sendto() function.
- *
- */
-int sockets_sendto(int verbose, int *socket_ids, unsigned int sockets,
-    struct sockaddr *address, socklen_t addrlen, char *data, size_t size,
-    unsigned int messages, sock_type_t type)
-{
-	if (verbose)
-		printf("\tSendto\t");
-	
-	fflush(stdout);
-	
-	for (unsigned int index = 0; index < sockets; index++) {
-		for (unsigned int message = 0; message < messages; message++) {
-			int rc;
-			
-			switch (type) {
-			case SOCK_STREAM:
-				rc = send(socket_ids[index], data, size, 0);
-				break;
-			case SOCK_DGRAM:
-				rc = sendto(socket_ids[index], data, size, 0, address, addrlen);
-				break;
-			default:
-				rc = EINVAL;
-			}
-			
-			if (rc != EOK) {
-				printf("Socket %u (%d), message %u error:\n",
-				    index, socket_ids[index], message);
-				socket_print_error(stderr, rc, "Socket send: ", "\n");
-				return rc;
-			}
-		}
-		
-		if (verbose)
-			print_mark(index);
-	}
-	
-	return EOK;
-}
-
-/** Receive data via sockets.
- *
- * @param[in]     verbose    Print out verbose information.
- * @param[in]     socket_ids Stored socket identifiers.
- * @param[in]     sockets    Number of sockets.
- * @param[in]     address    Source host address of received datagrams.
- * @param[in,out] addrlen    Maximum length of the source address in bytes.
- *                           The actual size of the source address is set.
- * @param[out]    data       Received data.
- * @param[in]     size       Maximum data size in bytes.
- * @param[in]     messages   Number of datagrams per socket to be received.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the recvfrom() function.
- *
- */
-int sockets_recvfrom(int verbose, int *socket_ids, unsigned int sockets,
-    struct sockaddr *address, socklen_t *addrlen, char *data, size_t size,
-    unsigned int messages)
-{
-	if (verbose)
-		printf("\tRecvfrom\t");
-	
-	fflush(stdout);
-	
-	for (unsigned int index = 0; index < sockets; index++) {
-		for (unsigned int message = 0; message < messages; message++) {
-			int rc = recvfrom(socket_ids[index], data, size, 0, address, addrlen);
-			if (rc < 0) {
-				printf("Socket %u (%d), message %u error:\n",
-				    index, socket_ids[index], message);
-				socket_print_error(stderr, rc, "Socket receive: ", "\n");
-				return rc;
-			}
-		}
-		
-		if (verbose)
-			print_mark(index);
-	}
-	
-	return EOK;
-}
-
-/** Send and receive data via sockets.
- *
- * Each datagram is sent and a reply read consequently.
- * The next datagram is sent after the reply is received.
- *
- * @param[in]     verbose    Print out verbose information.
- * @param[in]     socket_ids Stored socket identifiers.
- * @param[in]     sockets    Number of sockets.
- * @param[in,out] address    Destination host address to send data to.
- *                           The source host address of received datagrams is set.
- * @param[in]     addrlen    Length of the destination address in bytes.
- * @param[in,out] data       Data to be sent. The received data are set.
- * @param[in]     size       Size of the data in bytes.
- * @param[in]     messages   Number of datagrams per socket to be received.
- * @param[in]     type       Socket type.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the recvfrom() function.
- *
- */
-int sockets_sendto_recvfrom(int verbose, int *socket_ids, unsigned int sockets,
-    struct sockaddr *address, socklen_t *addrlen, char *data,
-    size_t size, unsigned int messages, sock_type_t type)
-{
-	if (verbose)
-		printf("\tSendto and recvfrom\t");
-	
-	fflush(stdout);
-	
-	for (unsigned int index = 0; index < sockets; index++) {
-		for (unsigned int message = 0; message < messages; message++) {
-			int rc;
-			
-			switch (type) {
-			case SOCK_STREAM:
-				rc = send(socket_ids[index], data, size, 0);
-				break;
-			case SOCK_DGRAM:
-				rc = sendto(socket_ids[index], data, size, 0, address, *addrlen);
-				break;
-			default:
-				rc = EINVAL;
-			}
-			
-			if (rc != EOK) {
-				printf("Socket %u (%d), message %u error:\n",
-				    index, socket_ids[index], message);
-				socket_print_error(stderr, rc, "Socket send: ", "\n");
-				return rc;
-			}
-			
-			rc = recvfrom(socket_ids[index], data, size, 0, address, addrlen);
-			if (rc < 0) {
-				printf("Socket %u (%d), message %u error:\n",
-				    index, socket_ids[index], message);
-				socket_print_error(stderr, rc, "Socket receive: ", "\n");
-				return rc;
-			}
-		}
-		
-		if (verbose)
-			print_mark(index);
-	}
-	
-	return EOK;
-}
-
-/** Prints a mark.
- *
- * If the index is a multiple of ten, a different mark is printed.
- *
- * @param[in] index The index of the mark to be printed.
- *
- */
-void print_mark(unsigned int index)
-{
-	if ((index + 1) % 10)
-		printf("*");
-	else
-		printf("|");
-	
-	fflush(stdout);
-}
-
-/** @}
- */
Index: pace/app/nettest1/nettest.h
===================================================================
--- uspace/app/nettest1/nettest.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 nettest
- * @{
- */
-
-/** @file
- * Networking test support functions.
- */
-
-#ifndef NET_TEST_
-#define NET_TEST_
-
-#include <net/socket.h>
-
-extern void print_mark(unsigned int);
-extern int sockets_create(int, int *, unsigned int, uint16_t, sock_type_t);
-extern int sockets_close(int, int *, unsigned int);
-extern int sockets_connect(int, int *, unsigned int, struct sockaddr *,
-    socklen_t);
-extern int sockets_sendto(int, int *, unsigned int, struct sockaddr *,
-    socklen_t, char *, size_t, unsigned int, sock_type_t);
-extern int sockets_recvfrom(int, int *, unsigned int, struct sockaddr *,
-    socklen_t *, char *, size_t, unsigned int);
-extern int sockets_sendto_recvfrom(int, int *, unsigned int, struct sockaddr *,
-    socklen_t *, char *, size_t, unsigned int, sock_type_t);
-
-#endif
-
-/** @}
- */
-
Index: pace/app/nettest1/nettest1.c
===================================================================
--- uspace/app/nettest1/nettest1.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,426 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 nettest
- * @{
- */
-
-/** @file
- * Networking test 1 application - sockets.
- */
-
-#include "nettest.h"
-#include "print_error.h"
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <str.h>
-#include <task.h>
-#include <time.h>
-#include <arg_parse.h>
-
-#include <inet/dnsr.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/socket.h>
-#include <net/socket_parse.h>
-
-/** Echo module name. */
-#define NAME  "nettest1"
-
-/** Packet data pattern. */
-#define NETTEST1_TEXT  "Networking test 1 - sockets"
-
-static uint16_t family = AF_NONE;
-static sock_type_t type = SOCK_DGRAM;
-static size_t size = 27;
-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 char *data;
-
-static void nettest1_print_help(void)
-{
-	printf(
-	    "Network Networking test 1 aplication - sockets\n"
-	    "Usage: nettest1 [options] host\n"
-	    "Where options are:\n"
-	    "-f protocol_family | --family=protocol_family\n"
-	    "\tThe listenning socket protocol family. Only the PF_INET and "
-	    "PF_INET6 are supported.\n"
-	    "\n"
-	    "-h | --help\n"
-	    "\tShow this application help.\n"
-	    "\n"
-	    "-m count | --messages=count\n"
-	    "\tThe number of messages to send and receive per socket. The "
-	    "default is 10.\n"
-	    "\n"
-	    "-n sockets | --sockets=count\n"
-	    "\tThe number of sockets to use. The default is 10.\n"
-	    "\n"
-	    "-p port_number | --port=port_number\n"
-	    "\tThe port number the application should send messages to. The "
-	    "default is 7.\n"
-	    "\n"
-	    "-s packet_size | --size=packet_size\n"
-	    "\tThe packet data size the application sends. The default is "
-	    "28 bytes.\n"
-	    "\n"
-	    "-v | --verbose\n"
-	    "\tShow all output messages.\n");
-}
-
-/** Parse one command-line option.
- *
- * @param argc		Number of all command-line arguments.
- * @param argv		All command-line arguments.
- * @param index		Current argument index (in, out).
- */
-static int nettest1_parse_opt(int argc, char *argv[], int *index)
-{
-	int value;
-	int rc;
-	
-	switch (argv[*index][1]) {
-	/*
-	 * Short options with only one letter
-	 */
-	case 'f':
-		rc = arg_parse_name_int(argc, argv, index, &value, 0,
-		    socket_parse_protocol_family);
-		if (rc != EOK)
-			return rc;
-		
-		family = (uint16_t) value;
-		break;
-	case 'h':
-		nettest1_print_help();
-		return EOK;
-	case 'm':
-		rc = arg_parse_int(argc, argv, index, &messages, 0);
-		if (rc != EOK)
-			return rc;
-		
-		break;
-	case 'n':
-		rc = arg_parse_int(argc, argv, index, &sockets, 0);
-		if (rc != EOK)
-			return rc;
-		
-		break;
-	case 'p':
-		rc = arg_parse_int(argc, argv, index, &value, 0);
-		if (rc != EOK)
-			return rc;
-		
-		port = (uint16_t) value;
-		break;
-	case 's':
-		rc = arg_parse_int(argc, argv, index, &value, 0);
-		if (rc != EOK)
-			return rc;
-		
-		size = (value >= 0) ? (size_t) value : 0;
-		break;
-	case 't':
-		rc = arg_parse_name_int(argc, argv, index, &value, 0,
-		    socket_parse_socket_type);
-		if (rc != EOK)
-			return rc;
-		
-		type = (sock_type_t) value;
-		break;
-	case 'v':
-		verbose = 1;
-		break;
-	
-	/*
-	 * Long options with double dash ('-')
-	 */
-	case '-':
-		if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
-			rc = arg_parse_name_int(argc, argv, index, &value, 9,
-			    socket_parse_protocol_family);
-			if (rc != EOK)
-				return rc;
-			
-			family = (uint16_t) value;
-		} else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
-			nettest1_print_help();
-			return EOK;
-		} else if (str_lcmp(argv[*index] + 2, "messages=", 6) == 0) {
-			rc = arg_parse_int(argc, argv, index, &messages, 8);
-			if (rc != EOK)
-				return rc;
-		} else if (str_lcmp(argv[*index] + 2, "sockets=", 6) == 0) {
-			rc = arg_parse_int(argc, argv, index, &sockets, 8);
-			if (rc != EOK)
-				return rc;
-		} else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
-			rc = arg_parse_int(argc, argv, index, &value, 7);
-			if (rc != EOK)
-				return rc;
-			
-			port = (uint16_t) value;
-		} else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
-			rc = arg_parse_name_int(argc, argv, index, &value, 7,
-			    socket_parse_socket_type);
-			if (rc != EOK)
-				return rc;
-			
-			type = (sock_type_t) value;
-		} else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
-			verbose = 1;
-		} else {
-			nettest1_print_help();
-			return EINVAL;
-		}
-		break;
-	default:
-		nettest1_print_help();
-		return EINVAL;
-	}
-	
-	return EOK;
-}
-
-/** Fill buffer with the NETTEST1_TEXT pattern.
- *
- * @param buffer	Data buffer.
- * @param size		Buffer size in bytes.
- */
-static void nettest1_fill_buffer(char *buffer, size_t size)
-{
-	size_t length = 0;
-	while (size > length + sizeof(NETTEST1_TEXT) - 1) {
-		memcpy(buffer + length, NETTEST1_TEXT,
-		    sizeof(NETTEST1_TEXT) - 1);
-		length += sizeof(NETTEST1_TEXT) - 1;
-	}
-	
-	memcpy(buffer + length, NETTEST1_TEXT, size - length);
-	buffer[size] = '\0';
-}
-
-static int nettest1_test(int *socket_ids, int nsockets, int nmessages)
-{
-	if (verbose)
-		printf("%d sockets, %d messages\n", nsockets, nmessages);
-	
-	int rc = sockets_create(verbose, socket_ids, nsockets, family, type);
-	if (rc != EOK)
-		return rc;
-	
-	if (type == SOCK_STREAM) {
-		rc = sockets_connect(verbose, socket_ids, nsockets, address,
-		    addrlen);
-		if (rc != EOK)
-			return rc;
-	}
-	
-	rc = sockets_sendto_recvfrom(verbose, socket_ids, nsockets, address,
-	    &addrlen, data, size, nmessages, type);
-	if (rc != EOK)
-		return rc;
-	
-	rc = sockets_close(verbose, socket_ids, nsockets);
-	if (rc != EOK)
-		return rc;
-	
-	if (verbose)
-		printf("\tOK\n");
-	
-	/****/
-	
-	rc = sockets_create(verbose, socket_ids, nsockets, family, type);
-	if (rc != EOK)
-		return rc;
-	
-	if (type == SOCK_STREAM) {
-		rc = sockets_connect(verbose, socket_ids, nsockets, address,
-		    addrlen);
-		if (rc != EOK)
-			return rc;
-	}
-	
-	rc = sockets_sendto(verbose, socket_ids, nsockets, address, addrlen,
-	    data, size, nmessages, type);
-	if (rc != EOK)
-		return rc;
-	
-	rc = sockets_recvfrom(verbose, socket_ids, nsockets, address, &addrlen,
-	    data, size, nmessages);
-	if (rc != EOK)
-		return rc;
-	
-	rc = sockets_close(verbose, socket_ids, nsockets);
-	if (rc != EOK)
-		return rc;
-	
-	if (verbose)
-		printf("\tOK\n");
-	
-	return EOK;
-}
-
-int main(int argc, char *argv[])
-{
-	/*
-	 * Parse the command line arguments. Stop before the last argument
-	 * if it does not start with dash ('-')
-	 */
-	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] == '-') {
-			rc = nettest1_parse_opt(argc, argv, &index);
-			if (rc != EOK)
-				return rc;
-		} else {
-			nettest1_print_help();
-			return EINVAL;
-		}
-	}
-	
-	/* The last argument containing the host */
-	if (index >= argc) {
-		printf("Host name missing.\n");
-		nettest1_print_help();
-		return EINVAL;
-	}
-	
-	char *host = argv[argc - 1];
-	
-	/* Interpret as address */
-	inet_addr_t iaddr;
-	rc = inet_addr_parse(host, &iaddr);
-	
-	if (rc != EOK) {
-		/* Interpret as a host name */
-		dnsr_hostinfo_t *hinfo = NULL;
-		rc = dnsr_name2host(host, &hinfo, ipver_from_af(family));
-		
-		if (rc != EOK) {
-			printf("Error resolving host '%s'.\n", host);
-			return EINVAL;
-		}
-		
-		iaddr = hinfo->addr;
-	}
-	
-	rc = inet_addr_sockaddr(&iaddr, port, &address, &addrlen);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		printf("Out of memory.\n");
-		return ENOMEM;
-	}
-	
-	if (family == AF_NONE)
-		family = address->sa_family;
-	
-	if (address->sa_family != family) {
-		printf("Address family does not match explicitly set family.\n");
-		return EINVAL;
-	}
-	
-	/* Check data buffer size */
-	if (size <= 0) {
-		fprintf(stderr, "Data buffer size too small (%zu). Using 1024 "
-		    "bytes instead.\n", size);
-		size = 1024;
-	}
-	
-	/*
-	 * Prepare data buffer. Allocate size bytes plus one for the
-	 * trailing null character.
-	 */
-	data = (char *) malloc(size + 1);
-	if (!data) {
-		fprintf(stderr, "Failed to allocate data buffer.\n");
-		return ENOMEM;
-	}
-	nettest1_fill_buffer(data, size);
-	
-	/* Check socket count */
-	if (sockets <= 0) {
-		fprintf(stderr, "Socket count too small (%d). Using "
-		    "2 instead.\n", sockets);
-		sockets = 2;
-	}
-	
-	/*
-	 * Prepare socket buffer. Allocate count fields plus the terminating
-	 * null (\0).
-	 */
-	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;
-	
-	if (verbose)
-		printf("Starting tests\n");
-	
-	struct timeval time_before;
-	gettimeofday(&time_before, NULL);
-	
-	nettest1_test(socket_ids,       1,        1);
-	nettest1_test(socket_ids,       1, messages);
-	nettest1_test(socket_ids, sockets,        1);
-	nettest1_test(socket_ids, sockets, messages);
-	
-	struct timeval time_after;
-	gettimeofday(&time_after, NULL);
-	
-	printf("Tested in %ld microseconds\n", tv_sub_diff(&time_after,
-	    &time_before));
-	
-	free(address);
-	
-	if (verbose)
-		printf("Exiting\n");
-	
-	return EOK;
-}
-
-/** @}
- */
Index: pace/app/nettest1/print_error.c
===================================================================
--- uspace/app/nettest1/print_error.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../netecho/print_error.c
Index: pace/app/nettest1/print_error.h
===================================================================
--- uspace/app/nettest1/print_error.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../netecho/print_error.h
Index: pace/app/nettest2/Makefile
===================================================================
--- uspace/app/nettest2/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,40 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# 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 = ../..
-LIBS = 
-EXTRA_CFLAGS = 
-BINARY = nettest2
-
-SOURCES = \
-	nettest2.c \
-	nettest.c \
-	print_error.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/nettest2/nettest.c
===================================================================
--- uspace/app/nettest2/nettest.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../nettest1/nettest.c
Index: pace/app/nettest2/nettest.h
===================================================================
--- uspace/app/nettest2/nettest.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../nettest1/nettest.h
Index: pace/app/nettest2/nettest2.c
===================================================================
--- uspace/app/nettest2/nettest2.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,407 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 nettest
- * @{
- */
-
-/** @file
- * Networking test 2 application - transfer.
- */
-
-#include "nettest.h"
-#include "print_error.h"
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <str.h>
-#include <task.h>
-#include <time.h>
-#include <arg_parse.h>
-#include <stdbool.h>
-
-#include <inet/dnsr.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/socket.h>
-#include <net/socket_parse.h>
-
-/** Echo module name. */
-#define NAME  "nettest2"
-
-/** Packet data pattern. */
-#define NETTEST2_TEXT  "Networking test 2 - transfer"
-
-static uint16_t family = AF_NONE;
-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)
-{
-	printf(
-	    "Network Networking test 2 aplication - UDP transfer\n"
-	    "Usage: nettest2 [options] host\n"
-	    "Where options are:\n"
-	    "-f protocol_family | --family=protocol_family\n"
-	    "\tThe listenning socket protocol family. Only the PF_INET and "
-	    "PF_INET6 are supported.\n"
-	    "\n"
-	    "-h | --help\n"
-	    "\tShow this application help.\n"
-	    "\n"
-	    "-m count | --messages=count\n"
-	    "\tThe number of messages to send and receive per socket. The "
-	    "default is 10.\n"
-	    "\n"
-	    "-n sockets | --sockets=count\n"
-	    "\tThe number of sockets to use. The default is 10.\n"
-	    "\n"
-	    "-p port_number | --port=port_number\n"
-	    "\tThe port number the application should send messages to. The "
-	    "default is 7.\n"
-	    "\n"
-	    "-s packet_size | --size=packet_size\n"
-	    "\tThe packet data size the application sends. The default is 29 "
-	    "bytes.\n"
-	    "\n"
-	    "-v | --verbose\n"
-	    "\tShow all output messages.\n");
-}
-
-/** Fill buffer with the NETTEST2_TEXT pattern.
- *
- * @param buffer	Data buffer.
- * @param size		Buffer size in bytes.
- */
-static void nettest2_fill_buffer(char *buffer, size_t size)
-{
-	size_t length = 0;
-	while (size > length + sizeof(NETTEST2_TEXT) - 1) {
-		memcpy(buffer + length, NETTEST2_TEXT,
-		    sizeof(NETTEST2_TEXT) - 1);
-		length += sizeof(NETTEST2_TEXT) - 1;
-	}
-	
-	memcpy(buffer + length, NETTEST2_TEXT, size - length);
-	buffer[size] = '\0';
-}
-
-/** Parse one command-line option.
- *
- * @param argc		Number of all command-line arguments.
- * @param argv		All command-line arguments.
- * @param index		Current argument index (in, out).
- */
-static int nettest2_parse_opt(int argc, char *argv[], int *index)
-{
-	int value;
-	int rc;
-	
-	switch (argv[*index][1]) {
-	/*
-	 * Short options with only one letter
-	 */
-	case 'f':
-		rc = arg_parse_name_int(argc, argv, index, &value, 0,
-		    socket_parse_protocol_family);
-		if (rc != EOK)
-			return rc;
-		
-		family = (uint16_t) value;
-		break;
-	case 'h':
-		nettest2_print_help();
-		return EOK;
-	case 'm':
-		rc = arg_parse_int(argc, argv, index, &messages, 0);
-		if (rc != EOK)
-			return rc;
-		
-		break;
-	case 'n':
-		rc = arg_parse_int(argc, argv, index, &sockets, 0);
-		if (rc != EOK)
-			return rc;
-		
-		break;
-	case 'p':
-		rc = arg_parse_int(argc, argv, index, &value, 0);
-		if (rc != EOK)
-			return rc;
-		
-		port = (uint16_t) value;
-		break;
-	case 's':
-		rc = arg_parse_int(argc, argv, index, &value, 0);
-		if (rc != EOK)
-			return rc;
-		
-		size = (value >= 0) ? (size_t) value : 0;
-		break;
-	case 't':
-		rc = arg_parse_name_int(argc, argv, index, &value, 0,
-		    socket_parse_socket_type);
-		if (rc != EOK)
-			return rc;
-		
-		type = (sock_type_t) value;
-		break;
-	case 'v':
-		verbose = true;
-		break;
-	
-	/*
-	 * Long options with double dash ('-')
-	 */
-	case '-':
-		if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
-			rc = arg_parse_name_int(argc, argv, index, &value, 9,
-			    socket_parse_protocol_family);
-			if (rc != EOK)
-				return rc;
-			
-			family = (uint16_t) value;
-		} else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
-			nettest2_print_help();
-			return EOK;
-		} else if (str_lcmp(argv[*index] + 2, "messages=", 6) == 0) {
-			rc = arg_parse_int(argc, argv, index, &messages, 8);
-			if (rc != EOK)
-				return rc;
-		} else if (str_lcmp(argv[*index] + 2, "sockets=", 6) == 0) {
-			rc = arg_parse_int(argc, argv, index, &sockets, 8);
-			if (rc != EOK)
-				return rc;
-		} else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
-			rc = arg_parse_int(argc, argv, index, &value, 7);
-			if (rc != EOK)
-				return rc;
-			
-			port = (uint16_t) value;
-		} else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
-			rc = arg_parse_name_int(argc, argv, index, &value, 7,
-			    socket_parse_socket_type);
-			if (rc != EOK)
-				return rc;
-			
-			type = (sock_type_t) value;
-		} else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
-			verbose = 1;
-		} else {
-			nettest2_print_help();
-			return EINVAL;
-		}
-		break;
-	default:
-		nettest2_print_help();
-		return EINVAL;
-	}
-	
-	return EOK;
-}
-
-int main(int argc, char *argv[])
-{
-	int index;
-	int rc;
-	
-	/*
-	 * 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) {
-		/* Options should start with dash ('-') */
-		if (argv[index][0] == '-') {
-			rc = nettest2_parse_opt(argc, argv, &index);
-			if (rc != EOK)
-				return rc;
-		} else {
-			nettest2_print_help();
-			return EINVAL;
-		}
-	}
-	
-	/* The last argument containing the host */
-	if (index >= argc) {
-		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, ipver_from_af(family));
-		
-		if (rc != EOK) {
-			printf("Error resolving host '%s'.\n", addr_s);
-			return EINVAL;
-		}
-		
-		addr_addr = hinfo->addr;
-	}
-	
-	struct sockaddr *address;
-	socklen_t addrlen;
-	rc = inet_addr_sockaddr(&addr_addr, port, &address, &addrlen);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		printf("Out of memory.\n");
-		return ENOMEM;
-	}
-	
-	if (family == AF_NONE)
-		family = address->sa_family;
-	
-	if (address->sa_family != family) {
-		printf("Address family does not match explicitly set family.\n");
-		return EINVAL;
-	}
-	
-	/* Check data buffer size. */
-	if (size <= 0) {
-		fprintf(stderr, "Data buffer size too small (%zu). Using 1024 "
-		    "bytes instead.\n", size);
-		size = 1024;
-	}
-	
-	/*
-	 * Prepare the buffer. Allocate size bytes plus one for terminating
-	 * null character.
-	 */
-	char *data = (char *) malloc(size + 1);
-	if (!data) {
-		fprintf(stderr, "Failed to allocate data buffer.\n");
-		return ENOMEM;
-	}
-	
-	/* Fill buffer with a pattern. */
-	nettest2_fill_buffer(data, size);
-	
-	/* Check socket count. */
-	if (sockets <= 0) {
-		fprintf(stderr, "Socket count too small (%d). Using "
-		    "2 instead.\n", sockets);
-		sockets = 2;
-	}
-	
-	/*
-	 * Prepare the socket buffer.
-	 * Allocate count entries plus the terminating null (\0)
-	 */
-	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;
-	
-	if (verbose)
-		printf("Starting tests\n");
-	
-	rc = sockets_create(verbose, socket_ids, sockets, family, type);
-	if (rc != EOK)
-		return rc;
-	
-	if (type == SOCK_STREAM) {
-		rc = sockets_connect(verbose, socket_ids, sockets,
-		    address, addrlen);
-		if (rc != EOK)
-			return rc;
-	}
-	
-	if (verbose)
-		printf("\n");
-	
-	struct timeval time_before;
-	gettimeofday(&time_before, NULL);
-	
-	rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address,
-	    &addrlen, data, size, messages, type);
-	if (rc != EOK)
-		return rc;
-	
-	struct timeval time_after;
-	gettimeofday(&time_after, NULL);
-	
-	if (verbose)
-		printf("\tOK\n");
-	
-	printf("sendto + recvfrom tested in %ld microseconds\n",
-	    tv_sub_diff(&time_after, &time_before));
-	
-	gettimeofday(&time_before, NULL);
-	
-	rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen,
-	    data, size, messages, type);
-	if (rc != EOK)
-		return rc;
-	
-	rc = sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen,
-	    data, size, messages);
-	if (rc != EOK)
-		return rc;
-	
-	gettimeofday(&time_after, NULL);
-	
-	if (verbose)
-		printf("\tOK\n");
-	
-	printf("sendto, recvfrom tested in %ld microseconds\n",
-	    tv_sub_diff(&time_after, &time_before));
-	
-	rc = sockets_close(verbose, socket_ids, sockets);
-	if (rc != EOK)
-		return rc;
-	
-	free(address);
-	
-	if (verbose)
-		printf("\nExiting\n");
-	
-	return EOK;
-}
-
-/** @}
- */
Index: pace/app/nettest2/print_error.c
===================================================================
--- uspace/app/nettest2/print_error.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../netecho/print_error.c
Index: pace/app/nettest2/print_error.h
===================================================================
--- uspace/app/nettest2/print_error.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../netecho/print_error.h
Index: pace/app/nettest3/Makefile
===================================================================
--- uspace/app/nettest3/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2011 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 = ../..
-LIBS =
-EXTRA_CFLAGS =
-BINARY = nettest3
-
-SOURCES = \
-	nettest3.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/nettest3/nettest3.c
===================================================================
--- uspace/app/nettest3/nettest3.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,152 +1,0 @@
-/*
- * Copyright (c) 2011 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 nettest
- * @{
- */
-
-/** @file
- * Networking test 3.
- */
-
-#include <async.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <str.h>
-
-#include <inet/dnsr.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/socket.h>
-
-#define BUF_SIZE 32
-
-static char *data;
-static size_t size;
-
-static char buf[BUF_SIZE];
-
-static struct sockaddr *address;
-static socklen_t addrlen;
-
-static uint16_t port;
-
-int main(int argc, char *argv[])
-{
-	int rc;
-	int fd;
-	char *endptr;
-	dnsr_hostinfo_t *hinfo;
-	inet_addr_t addr;
-	char *addr_s;
-
-	port = 7;
-
-	data = (char *) "Hello World!";
-	size = str_size(data);
-
-	/* Connect to local IP address by default */
-	inet_addr(&addr, 127, 0, 0, 1);
-
-	if (argc >= 2) {
-		printf("parsing address '%s'\n", argv[1]);
-		rc = inet_addr_parse(argv[1], &addr);
-		if (rc != EOK) {
-			/* Try interpreting as a host name */
-			rc = dnsr_name2host(argv[1], &hinfo, ip_v4);
-			if (rc != EOK) {
-				printf("Error resolving host '%s'.\n", argv[1]);
-				return rc;
-			}
-
-			addr = hinfo->addr;
-		}
-		rc = inet_addr_format(&addr, &addr_s);
-		if (rc != EOK) {
-			assert(rc == ENOMEM);
-			printf("Out of memory.\n");
-			return rc;
-		}
-		printf("result: rc=%d, ver=%d, addr=%s\n", rc,
-		    addr.version, addr_s);
-		free(addr_s);
-	}
-
-	if (argc >= 3) {
-		printf("parsing port '%s'\n", argv[2]);
-		port = htons(strtoul(argv[2], &endptr, 10));
-		if (*endptr != '\0') {
-			fprintf(stderr, "Error parsing port\n");
-			return 1;
-		}
-	}
-
-	rc = inet_addr_sockaddr(&hinfo->addr, port, &address, &addrlen);
-	if (rc != EOK) {
-		printf("Out of memory.\n");
-		return rc;
-	}
-
-	printf("socket()\n");
-	fd = socket(address->sa_family, SOCK_STREAM, IPPROTO_TCP);
-	printf(" -> %d\n", fd);
-	if (fd < 0)
-		return 1;
-
-	printf("connect()\n");
-	rc = connect(fd, address, addrlen);
-	printf(" -> %d\n", rc);
-	if (rc != 0)
-		return 1;
-
-	printf("send()\n");
-	rc = send(fd, data, size, 0);
-	printf(" -> %d\n", rc);
-	if (rc < 0)
-		return 1;
-
-	do {
-		printf("recv()\n");
-		rc = recv(fd, buf, BUF_SIZE, 0);
-		printf(" -> %d\n", rc);
-	} while (rc > 0);
-
-	async_usleep(1000 * 1000);
-
-	printf("closesocket()\n");
-	rc = closesocket(fd);
-	printf(" -> %d\n", rc);
-
-	free(address);
-
-	return 0;
-}
-
-/** @}
- */
Index: uspace/app/nterm/conn.c
===================================================================
--- uspace/app/nterm/conn.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/app/nterm/conn.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -38,6 +38,6 @@
 #include <fibril.h>
 #include <inet/dnsr.h>
-#include <net/inet.h>
-#include <net/socket.h>
+#include <inet/endpoint.h>
+#include <inet/tcp.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -48,54 +48,63 @@
 #include "nterm.h"
 
-static int conn_fd;
-static fid_t rcv_fid;
+static tcp_t *tcp;
+static tcp_conn_t *conn;
 
 #define RECV_BUF_SIZE 1024
 static uint8_t recv_buf[RECV_BUF_SIZE];
 
-static int rcv_fibril(void *arg)
+static void conn_conn_reset(tcp_conn_t *);
+static void conn_data_avail(tcp_conn_t *);
+
+static tcp_cb_t conn_cb = {
+	.conn_reset = conn_conn_reset,
+	.data_avail = conn_data_avail
+};
+
+static void conn_conn_reset(tcp_conn_t *conn)
 {
-	ssize_t nr;
+	printf("\n[Connection reset]\n");
+}
+
+static void conn_data_avail(tcp_conn_t *conn)
+{
+	int rc;
+	size_t nrecv;
 
 	while (true) {
-		nr = recv(conn_fd, recv_buf, RECV_BUF_SIZE, 0);
-		if (nr < 0)
+		rc = tcp_conn_recv(conn, recv_buf, RECV_BUF_SIZE, &nrecv);
+		if (rc != EOK) {
+			printf("\n[Receive error %d]\n", rc);
 			break;
+		}
 
-		nterm_received(recv_buf, nr);
+		nterm_received(recv_buf, nrecv);
+
+		if (nrecv != RECV_BUF_SIZE)
+			break;
 	}
-
-	if (nr == ENOTCONN)
-		printf("\n[Other side has closed the connection]\n");
-	else
-		printf("'\n[Receive errror (%s)]\n", str_error(nr));
-
-	exit(0);
-	return 0;
 }
 
 int conn_open(const char *host, const char *port_s)
 {
-	int conn_fd = -1;
-	struct sockaddr *saddr = NULL;
-	socklen_t saddrlen;
-	
+	inet_ep2_t epp;
+
 	/* Interpret as address */
 	inet_addr_t iaddr;
 	int rc = inet_addr_parse(host, &iaddr);
-	
+
 	if (rc != EOK) {
 		/* Interpret as a host name */
 		dnsr_hostinfo_t *hinfo = NULL;
 		rc = dnsr_name2host(host, &hinfo, ip_any);
-		
+
 		if (rc != EOK) {
 			printf("Error resolving host '%s'.\n", host);
 			goto error;
 		}
-		
+
 		iaddr = hinfo->addr;
 	}
-	
+
 	char *endptr;
 	uint16_t port = strtol(port_s, &endptr, 10);
@@ -104,37 +113,28 @@
 		goto error;
 	}
-	
-	rc = inet_addr_sockaddr(&iaddr, port, &saddr, &saddrlen);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		printf("Out of memory.\n");
-		return ENOMEM;
-	}
-	
+
+	inet_ep2_init(&epp);
+	epp.remote.addr = iaddr;
+	epp.remote.port = port;
+
 	printf("Connecting to host %s port %u\n", host, port);
-	
-	conn_fd = socket(saddr->sa_family, SOCK_STREAM, 0);
-	if (conn_fd < 0)
-		goto error;
-	
-	rc = connect(conn_fd, saddr, saddrlen);
+
+	rc = tcp_create(&tcp);
 	if (rc != EOK)
 		goto error;
-	
-	rcv_fid = fibril_create(rcv_fibril, NULL);
-	if (rcv_fid == 0)
+
+	rc = tcp_conn_create(tcp, &epp, &conn_cb, NULL, &conn);
+	if (rc != EOK)
 		goto error;
-	
-	fibril_add_ready(rcv_fid);
-	
-	free(saddr);
+
+	rc = tcp_conn_wait_connected(conn);
+	if (rc != EOK)
+		goto error;
+
 	return EOK;
 error:
-	if (conn_fd >= 0) {
-		closesocket(conn_fd);
-		conn_fd = -1;
-	}
-	free(saddr);
-	
+	tcp_conn_destroy(conn);
+	tcp_destroy(tcp);
+
 	return EIO;
 }
@@ -142,8 +142,8 @@
 int conn_send(void *data, size_t size)
 {
-	int rc = send(conn_fd, data, size, 0);
+	int rc = tcp_conn_send(conn, data, size);
 	if (rc != EOK)
 		return EIO;
-	
+
 	return EOK;
 }
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/app/trace/trace.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -730,5 +730,5 @@
 }
 
-static void print_syntax()
+static void print_syntax(void)
 {
 	printf("Syntax:\n");
Index: uspace/app/websrv/websrv.c
===================================================================
--- uspace/app/websrv/websrv.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/app/websrv/websrv.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -44,7 +44,7 @@
 #include <task.h>
 
-#include <net/in.h>
-#include <net/inet.h>
-#include <net/socket.h>
+#include <inet/addr.h>
+#include <inet/endpoint.h>
+#include <inet/tcp.h>
 
 #include <arg_parse.h>
@@ -56,5 +56,4 @@
 
 #define DEFAULT_PORT  8080
-#define BACKLOG_SIZE  3
 
 #define WEB_ROOT  "/data/web"
@@ -62,4 +61,14 @@
 /** Buffer for receiving the request. */
 #define BUFFER_SIZE  1024
+
+static void websrv_new_conn(tcp_listener_t *, tcp_conn_t *);
+
+static tcp_listen_cb_t listen_cb = {
+	.new_conn = websrv_new_conn
+};
+
+static tcp_cb_t conn_cb = {
+	.connected = NULL
+};
 
 static uint16_t port = DEFAULT_PORT;
@@ -122,17 +131,20 @@
 
 /** Receive one character (with buffering) */
-static int recv_char(int fd, char *c)
-{
+static int recv_char(tcp_conn_t *conn, char *c)
+{
+	size_t nrecv;
+	int rc;
+	
 	if (rbuf_out == rbuf_in) {
 		rbuf_out = 0;
 		rbuf_in = 0;
 		
-		ssize_t rc = recv(fd, rbuf, BUFFER_SIZE, 0);
-		if (rc <= 0) {
-			fprintf(stderr, "recv() failed (%zd)\n", rc);
+		rc = tcp_conn_recv_wait(conn, rbuf, BUFFER_SIZE, &nrecv);
+		if (rc != EOK) {
+			fprintf(stderr, "tcp_conn_recv() failed (%d)\n", rc);
 			return rc;
 		}
 		
-		rbuf_in = rc;
+		rbuf_in = nrecv;
 	}
 	
@@ -142,5 +154,5 @@
 
 /** Receive one line with length limit */
-static int recv_line(int fd)
+static int recv_line(tcp_conn_t *conn)
 {
 	char *bp = lbuf;
@@ -149,5 +161,5 @@
 	while (bp < lbuf + BUFFER_SIZE) {
 		char prev = c;
-		int rc = recv_char(fd, &c);
+		int rc = recv_char(conn, &c);
 		
 		if (rc != EOK)
@@ -187,5 +199,5 @@
 }
 
-static int send_response(int conn_sd, const char *msg)
+static int send_response(tcp_conn_t *conn, const char *msg)
 {
 	size_t response_size = str_size(msg);
@@ -194,7 +206,7 @@
 	    fprintf(stderr, "Sending response\n");
 	
-	ssize_t rc = send(conn_sd, (void *) msg, response_size, 0);
-	if (rc < 0) {
-		fprintf(stderr, "send() failed\n");
+	int rc = tcp_conn_send(conn, (void *) msg, response_size);
+	if (rc != EOK) {
+		fprintf(stderr, "tcp_conn_send() failed\n");
 		return rc;
 	}
@@ -203,5 +215,5 @@
 }
 
-static int uri_get(const char *uri, int conn_sd)
+static int uri_get(const char *uri, tcp_conn_t *conn)
 {
 	if (str_cmp(uri, "/") == 0)
@@ -215,5 +227,5 @@
 	int fd = open(fname, O_RDONLY);
 	if (fd < 0) {
-		rc = send_response(conn_sd, msg_not_found);
+		rc = send_response(conn, msg_not_found);
 		free(fname);
 		return rc;
@@ -222,5 +234,5 @@
 	free(fname);
 	
-	rc = send_response(conn_sd, msg_ok);
+	rc = send_response(conn, msg_ok);
 	if (rc != EOK)
 		return rc;
@@ -236,7 +248,7 @@
 		}
 		
-		rc = send(conn_sd, fbuf, nr, 0);
-		if (rc < 0) {
-			fprintf(stderr, "send() failed\n");
+		rc = tcp_conn_send(conn, fbuf, nr);
+		if (rc != EOK) {
+			fprintf(stderr, "tcp_conn_send() failed\n");
 			close(fd);
 			return rc;
@@ -249,7 +261,7 @@
 }
 
-static int req_process(int conn_sd)
-{
-	int rc = recv_line(conn_sd);
+static int req_process(tcp_conn_t *conn)
+{
+	int rc = recv_line(conn);
 	if (rc != EOK) {
 		fprintf(stderr, "recv_line() failed\n");
@@ -261,5 +273,5 @@
 	
 	if (str_lcmp(lbuf, "GET ", 4) != 0) {
-		rc = send_response(conn_sd, msg_not_implemented);
+		rc = send_response(conn, msg_not_implemented);
 		return rc;
 	}
@@ -277,9 +289,9 @@
 	
 	if (!uri_is_valid(uri)) {
-		rc = send_response(conn_sd, msg_bad_request);
-		return rc;
-	}
-	
-	return uri_get(uri, conn_sd);
+		rc = send_response(conn, msg_bad_request);
+		return rc;
+	}
+	
+	return uri_get(uri, conn);
 }
 
@@ -346,10 +358,39 @@
 }
 
+static void websrv_new_conn(tcp_listener_t *lst, tcp_conn_t *conn)
+{
+	int rc;
+	
+	if (verbose)
+		fprintf(stderr, "New connection, waiting for request\n");
+	
+	rbuf_out = 0;
+	rbuf_in = 0;
+	
+	rc = req_process(conn);
+	if (rc != EOK) {
+		fprintf(stderr, "Error processing request (%s)\n",
+		    str_error(rc));
+		return;
+	}
+
+	rc = tcp_conn_send_fin(conn);
+	if (rc != EOK) {
+		fprintf(stderr, "Error sending FIN.\n");
+		return;
+	}
+}
+
 int main(int argc, char *argv[])
 {
+	inet_ep_t ep;
+	tcp_listener_t *lst;
+	tcp_t *tcp;
+	int rc;
+	
 	/* Parse command line arguments */
 	for (int i = 1; i < argc; i++) {
 		if (argv[i][0] == '-') {
-			int rc = parse_option(argc, argv, &i);
+			rc = parse_option(argc, argv, &i);
 			if (rc != EOK)
 				return rc;
@@ -360,40 +401,23 @@
 	}
 	
-	struct sockaddr_in addr;
-	
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	
-	int rc = inet_pton(AF_INET, "127.0.0.1", (void *)
-	    &addr.sin_addr.s_addr);
-	if (rc != EOK) {
-		fprintf(stderr, "Error parsing network address (%s)\n",
-		    str_error(rc));
+	printf("%s: HelenOS web server\n", NAME);
+
+	if (verbose)
+		fprintf(stderr, "Creating listener\n");
+	
+	inet_ep_init(&ep);
+	ep.port = port;
+
+	rc = tcp_create(&tcp);
+	if (rc != EOK) {
+		fprintf(stderr, "Error initializing TCP.\n");
 		return 1;
 	}
-	
-	printf("%s: HelenOS web server\n", NAME);
-
-	if (verbose)
-		fprintf(stderr, "Creating socket\n");
-	
-	int listen_sd = socket(PF_INET, SOCK_STREAM, 0);
-	if (listen_sd < 0) {
-		fprintf(stderr, "Error creating listening socket (%s)\n",
-		    str_error(listen_sd));
+
+	rc = tcp_listener_create(tcp, &ep, &listen_cb, NULL, &conn_cb, NULL,
+	    &lst);
+	if (rc != EOK) {
+		fprintf(stderr, "Error creating listener.\n");
 		return 2;
-	}
-	
-	rc = bind(listen_sd, (struct sockaddr *) &addr, sizeof(addr));
-	if (rc != EOK) {
-		fprintf(stderr, "Error binding socket (%s)\n",
-		    str_error(rc));
-		return 3;
-	}
-	
-	rc = listen(listen_sd, BACKLOG_SIZE);
-	if (rc != EOK) {
-		fprintf(stderr, "listen() failed (%s)\n", str_error(rc));
-		return 4;
 	}
 	
@@ -402,40 +426,5 @@
 
 	task_retval(0);
-
-	while (true) {
-		struct sockaddr_in raddr;
-		socklen_t raddr_len = sizeof(raddr);
-		int conn_sd = accept(listen_sd, (struct sockaddr *) &raddr,
-		    &raddr_len);
-		
-		if (conn_sd < 0) {
-			fprintf(stderr, "accept() failed (%s)\n", str_error(rc));
-			continue;
-		}
-		
-		if (verbose) {
-			fprintf(stderr, "Connection accepted (sd=%d), "
-			    "waiting for request\n", conn_sd);
-		}
-		
-		rbuf_out = 0;
-		rbuf_in = 0;
-		
-		rc = req_process(conn_sd);
-		if (rc != EOK)
-			fprintf(stderr, "Error processing request (%s)\n",
-			    str_error(rc));
-		
-		rc = closesocket(conn_sd);
-		if (rc != EOK) {
-			fprintf(stderr, "Error closing connection socket (%s)\n",
-			    str_error(rc));
-			closesocket(listen_sd);
-			return 5;
-		}
-		
-		if (verbose)
-			fprintf(stderr, "Connection closed\n");
-	}
+	async_manager();
 	
 	/* Not reached */
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -192,5 +192,5 @@
 		if (!tries--) {
 			usb_log_error("Can't remove hub, still running.\n");
-			return EINPROGRESS;
+			return EBUSY;
 		}
 	}
Index: uspace/drv/bus/usb/vhc/devconn.c
===================================================================
--- uspace/drv/bus/usb/vhc/devconn.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/drv/bus/usb/vhc/devconn.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -32,5 +32,5 @@
 
 
-static vhc_virtdev_t *vhc_virtdev_create()
+static vhc_virtdev_t *vhc_virtdev_create(void)
 {
 	vhc_virtdev_t *dev = malloc(sizeof(vhc_virtdev_t));
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/Makefile	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -97,4 +97,7 @@
 	generic/futex.c \
 	generic/inet/addr.c \
+	generic/inet/endpoint.c \
+	generic/inet/tcp.c \
+	generic/inet/udp.c \
 	generic/inet.c \
 	generic/inetcfg.c \
@@ -137,6 +140,4 @@
 	generic/adt/list.c \
 	generic/adt/hash_table.c \
-	generic/adt/dynamic_fifo.c \
-	generic/adt/char_map.c \
 	generic/adt/prodcons.c \
 	generic/time.c \
@@ -145,7 +146,4 @@
 	generic/vfs/vfs.c \
 	generic/vfs/canonify.c \
-	generic/net/inet.c \
-	generic/net/socket_client.c \
-	generic/net/socket_parse.c \
 	generic/setjmp.c \
 	generic/stack.c \
Index: pace/lib/c/generic/adt/char_map.c
===================================================================
--- uspace/lib/c/generic/adt/char_map.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,346 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  Character string to integer map implementation.
- *  @see char_map.h
- */
-
-#include <adt/char_map.h>
-
-#include <errno.h>
-#include <malloc.h>
-#include <mem.h>
-#include <unistd.h>
-
-/** Internal magic value for a consistency check. */
-#define CHAR_MAP_MAGIC_VALUE	0x12345611
-
-/** Adds the value with the key to the map.
- *
- * Creates new nodes to map the key.
- *
- * @param[in,out] map	The character string to integer map.
- * @param[in] identifier The key zero ('\0') terminated character string.
- *			The key character string is processed until the first
- *			terminating zero ('\0') character after the given
- *			length is found.
- * @param[in] length	The key character string length. The parameter may be
- *			zero (0) which means that the string is processed until
- *			the terminating zero ('\0') character is found.
- * @param[in] value	The integral value to be stored for the key character
- *			string.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EEXIST if the key character string is already used.
- */
-static int
-char_map_add_item(char_map_t *map, const uint8_t *identifier, size_t length,
-    const int value)
-{
-	if (map->next == (map->size - 1)) {
-		char_map_t **tmp;
-
-		tmp = (char_map_t **) realloc(map->items,
-		    sizeof(char_map_t *) * 2 * map->size);
-		if (!tmp)
-			return ENOMEM;
-
-		map->size *= 2;
-		map->items = tmp;
-	}
-
-	map->items[map->next] = (char_map_t *) malloc(sizeof(char_map_t));
-	if (!map->items[map->next])
-		return ENOMEM;
-
-	if (char_map_initialize(map->items[map->next]) != EOK) {
-		free(map->items[map->next]);
-		map->items[map->next] = NULL;
-		return ENOMEM;
-	}
-
-	map->items[map->next]->c = *identifier;
-	identifier++;
-	map->next++;
-	if ((length > 1) || ((length == 0) && *identifier)) {
-		map->items[map->next - 1]->value = CHAR_MAP_NULL;
-		return char_map_add_item(map->items[map->next - 1], identifier,
-		    length ? length - 1 : 0, value);
-	} else {
-		map->items[map->next - 1]->value = value;
-	}
-
-	return EOK;
-}
-
-/** Checks if the map is valid.
- *
- * @param[in] map	The character string to integer map.
- * @return		TRUE if the map is valid.
- * @return		FALSE otherwise.
- */
-static int char_map_is_valid(const char_map_t *map)
-{
-	return map && (map->magic == CHAR_MAP_MAGIC_VALUE);
-}
-
-/** Adds the value with the key to the map.
- *
- * @param[in,out] map	The character string to integer map.
- * @param[in] identifier The key zero ('\0') terminated character string. The
- *			key character string is processed until the first
- *			terminating zero ('\0') character after the given
- *			length is found.
- * @param[in] length	The key character string length. The parameter may be
- *			zero (0) which means that the string is processed until
- *			the terminating zero ('\\0') character is found.
- * @param[in] value	The integral value to be stored for the key character
- *			string.
- * @return		EOK on success.
- * @return		EINVAL if the map is not valid.
- * @return		EINVAL if the identifier parameter is NULL.
- * @return		EINVAL if the length parameter zero (0) and the
- *			identifier parameter is an empty character string (the
- *			first character is the terminating zero ('\0')
- *			character.
- * @return		EEXIST if the key character string is already used.
- * @return		Other error codes as defined for the
- *			char_map_add_item() function.
- */
-int
-char_map_add(char_map_t *map, const uint8_t *identifier, size_t length,
-    const int value)
-{
-	if (char_map_is_valid(map) && identifier && (length || *identifier)) {
-		int index;
-
-		for (index = 0; index < map->next; index++) {
-			if (map->items[index]->c != *identifier)
-				continue;
-				
-			identifier++;
-			if((length > 1) || ((length == 0) && *identifier)) {
-				return char_map_add(map->items[index],
-				    identifier, length ? length - 1 : 0, value);
-			} else {
-				if (map->items[index]->value != CHAR_MAP_NULL)
-					return EEXISTS;
-
-				map->items[index]->value = value;
-				return EOK;
-			}
-		}
-		return char_map_add_item(map, identifier, length, value);
-	}
-
-	return EINVAL;
-}
-
-/** Clears and destroys the map.
- *
- * @param[in,out] map	The character string to integer map.
- */
-void char_map_destroy(char_map_t *map)
-{
-	if (char_map_is_valid(map)) {
-		int index;
-
-		map->magic = 0;
-		for (index = 0; index < map->next; index++)
-			char_map_destroy(map->items[index]);
-
-		free(map->items);
-		map->items = NULL;
-	}
-}
-
-/** Returns the node assigned to the key from the map.
- *
- * @param[in] map	The character string to integer map.
- * @param[in] identifier The key zero ('\0') terminated character string. The
- *			key character string is processed until the first
- *			terminating zero ('\0') character after the given length
- *			is found.
- * @param[in] length	The key character string length. The parameter may be
- *			zero (0) which means that the string is processed until
- *			the terminating zero ('\0') character is found.
- * @return		The node holding the integral value assigned to the key
- *			character string.
- * @return		NULL if the key is not assigned a node.
- */
-static char_map_t *
-char_map_find_node(const char_map_t *map, const uint8_t *identifier,
-    size_t length)
-{
-	if (!char_map_is_valid(map))
-		return NULL;
-
-	if (length || *identifier) {
-		int index;
-
-		for (index = 0; index < map->next; index++) {
-			if (map->items[index]->c == *identifier) {
-				identifier++;
-				if (length == 1)
-					return map->items[index];
-
-				return char_map_find_node(map->items[index],
-				    identifier, length ? length - 1 : 0);
-			}
-		}
-
-		return NULL;
-	}
-
-	return (char_map_t *) map;
-}
-
-/** Excludes the value assigned to the key from the map.
- *
- * The entry is cleared from the map.
- *
- * @param[in,out] map	The character string to integer map.
- * @param[in] identifier The key zero ('\0') terminated character string. The
- *			key character string is processed until the first
- *			terminating zero ('\0') character after the given length
- *			is found.
- * @param[in] length	The key character string length. The parameter may be
- *			zero (0) which means that the string is processed until
- *			the terminating zero ('\0') character is found.
- * @return		The integral value assigned to the key character string.
- * @return		CHAR_MAP_NULL if the key is not assigned a value.
- */
-int char_map_exclude(char_map_t *map, const uint8_t *identifier, size_t length)
-{
-	char_map_t *node;
-
-	node = char_map_find_node(map, identifier, length);
-	if (node) {
-		int value;
-
-		value = node->value;
-		node->value = CHAR_MAP_NULL;
-		return value;
-	}
-	return CHAR_MAP_NULL;
-}
-
-/** Returns the value assigned to the key from the map.
- *
- *  @param[in] map	The character string to integer map.
- *  @param[in] identifier The key zero ('\0') terminated character string. The
- *			key character string is processed until the first
- *			terminating zero ('\0') character after the given length
- *			is found.
- *  @param[in] length	The key character string length. The parameter may be
- *			zero (0) which means that the string is processed until
- *			the terminating zero ('\0') character is found.
- *  @return		The integral value assigned to the key character string.
- *  @return		CHAR_MAP_NULL if the key is not assigned a value.
- */
-int char_map_find(const char_map_t *map, const uint8_t *identifier, size_t length)
-{
-	char_map_t *node;
-
-	node = char_map_find_node(map, identifier, length);
-	return node ? node->value : CHAR_MAP_NULL;
-}
-
-/** Initializes the map.
- *
- *  @param[in,out] map	The character string to integer map.
- *  @return		EOK on success.
- *  @return		EINVAL if the map parameter is NULL.
- *  @return		ENOMEM if there is not enough memory left.
- */
-int char_map_initialize(char_map_t *map)
-{
-	if (!map)
-		return EINVAL;
-
-	map->c = '\0';
-	map->value = CHAR_MAP_NULL;
-	map->size = 2;
-	map->next = 0;
-
-	map->items = malloc(sizeof(char_map_t *) * map->size);
-	if (!map->items) {
-		map->magic = 0;
-		return ENOMEM;
-	}
-
-	map->items[map->next] = NULL;
-	map->magic = CHAR_MAP_MAGIC_VALUE;
-
-	return EOK;
-}
-
-/** Adds or updates the value with the key to the map.
- *
- *  @param[in,out] map	The character string to integer map.
- *  @param[in] identifier The key zero ('\0') terminated character string. The
- *			key character string is processed until the first
- *			terminating zero ('\0') character after the given length
- *			is found.
- *  @param[in] length	The key character string length. The parameter may be
- *			zero (0) which means that the string is processed until
- *			the terminating zero ('\0') character is found.
- *  @param[in] value	The integral value to be stored for the key character
- *			string.
- *  @return		EOK on success.
- *  @return		EINVAL if the map is not valid.
- *  @return		EINVAL if the identifier parameter is NULL.
- *  @return		EINVAL if the length parameter zero (0) and the
- *			identifier parameter is an empty character string (the
- *			first character is the terminating zero ('\0) character.
- *  @return		EEXIST if the key character string is already used.
- *  @return		Other error codes as defined for the char_map_add_item()
- *			function.
- */
-int
-char_map_update(char_map_t *map, const uint8_t *identifier, const size_t length,
-    const int value)
-{
-	char_map_t *node;
-
-	node = char_map_find_node(map, identifier, length);
-	if (node) {
-		node->value = value;
-		return EOK;
-	}
-	
-	return char_map_add(map, identifier, length, value);
-}
-
-/** @}
- */
Index: pace/lib/c/generic/adt/dynamic_fifo.c
===================================================================
--- uspace/lib/c/generic/adt/dynamic_fifo.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,206 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- * @{
- */
-
-/** @file
- * Dynamic first in first out positive integer queue implementation.
- */
-
-#include <adt/dynamic_fifo.h>
-
-#include <errno.h>
-#include <malloc.h>
-#include <mem.h>
-
-/** Internal magic value for a consistency check. */
-#define DYN_FIFO_MAGIC_VALUE	0x58627659
-
-/** Returns the next queue index.
- *
- * The queue field is circular.
- *
- * @param[in] fifo	The dynamic queue.
- * @param[in] index	The actual index to be shifted.
- */
-#define NEXT_INDEX(fifo, index)	(((index) + 1) % ((fifo)->size + 1))
-
-/** Checks if the queue is valid.
- *
- * @param[in] fifo	The dynamic queue.
- * @return		TRUE if the queue is valid.
- * @return		FALSE otherwise.
- */
-static int dyn_fifo_is_valid(dyn_fifo_t *fifo)
-{
-	return fifo && (fifo->magic_value == DYN_FIFO_MAGIC_VALUE);
-}
-
-/** Initializes the dynamic queue.
- *
- * @param[in,out] fifo	The dynamic queue.
- * @param[in] size	The initial queue size.
- * @return		EOK on success.
- * @return		EINVAL if the queue is not valid.
- * @return		EBADMEM if the fifo parameter is NULL.
- * @return		ENOMEM if there is not enough memory left.
- */
-int dyn_fifo_initialize(dyn_fifo_t *fifo, int size)
-{
-	if (!fifo)
-		return EBADMEM;
-
-	if (size <= 0)
-		return EINVAL;
-
-	fifo->items = (int *) malloc(sizeof(int) * size + 1);
-	if (!fifo->items)
-		return ENOMEM;
-
-	fifo->size = size;
-	fifo->head = 0;
-	fifo->tail = 0;
-	fifo->magic_value = DYN_FIFO_MAGIC_VALUE;
-
-	return EOK;
-}
-
-/** Appends a new item to the queue end.
- *
- * @param[in,out] fifo	The dynamic queue.
- * @param[in] value	The new item value. Should be positive.
- * @param[in] max_size	The maximum queue size. The queue is not resized beyound
- *			this limit. May be zero or negative to indicate no
- *			limit.
- * @return		EOK on success.
- * @return		EINVAL if the queue is not valid.
- * @return		ENOMEM if there is not enough memory left.
- */
-int dyn_fifo_push(dyn_fifo_t *fifo, int value, int max_size)
-{
-	int *new_items;
-
-	if (!dyn_fifo_is_valid(fifo))
-		return EINVAL;
-
-	if (NEXT_INDEX(fifo, fifo->tail) == fifo->head) {
-		if ((max_size > 0) && ((fifo->size * 2) > max_size)) {
-			if(fifo->size >= max_size)
-				return ENOMEM;
-		} else {
-			max_size = fifo->size * 2;
-		}
-
-		new_items = realloc(fifo->items, sizeof(int) * max_size + 1);
-		if (!new_items)
-			return ENOMEM;
-
-		fifo->items = new_items;
-		if (fifo->tail < fifo->head) {
-			if (fifo->tail < max_size - fifo->size) {
-				memcpy(fifo->items + fifo->size + 1,
-				    fifo->items, fifo->tail * sizeof(int));
-				fifo->tail += fifo->size + 1;
-			} else {
-				memcpy(fifo->items + fifo->size + 1,
-				    fifo->items,
-				    (max_size - fifo->size) * sizeof(int));
-				memcpy(fifo->items,
-				    fifo->items + max_size - fifo->size,
-				    fifo->tail - max_size + fifo->size);
-				fifo->tail -= max_size - fifo->size;
-			}
-		}
-		fifo->size = max_size;
-	}
-
-	fifo->items[fifo->tail] = value;
-	fifo->tail = NEXT_INDEX(fifo, fifo->tail);
-	return EOK;
-}
-
-/** Returns and excludes the first item in the queue.
- *
- * @param[in,out] fifo	The dynamic queue.
- * @return		Value of the first item in the queue.
- * @return		EINVAL if the queue is not valid.
- * @return		ENOENT if the queue is empty.
- */
-int dyn_fifo_pop(dyn_fifo_t *fifo)
-{
-	int value;
-
-	if (!dyn_fifo_is_valid(fifo))
-		return EINVAL;
-
-	if (fifo->head == fifo->tail)
-		return ENOENT;
-
-	value = fifo->items[fifo->head];
-	fifo->head = NEXT_INDEX(fifo, fifo->head);
-	return value;
-}
-
-/** Returns and keeps the first item in the queue.
- *
- * @param[in,out] fifo	The dynamic queue.
- * @return		Value of the first item in the queue.
- * @return		EINVAL if the queue is not valid.
- * @return		ENOENT if the queue is empty.
- */
-int dyn_fifo_value(dyn_fifo_t *fifo)
-{
-	if (!dyn_fifo_is_valid(fifo))
-		return EINVAL;
-
-	if (fifo->head == fifo->tail)
-		return ENOENT;
-
-	return fifo->items[fifo->head];
-}
-
-/** Clears and destroys the queue.
- *
- * @param[in,out] fifo	The dynamic queue.
- * @return		EOK on success.
- * @return		EINVAL if the queue is not valid.
- */
-int dyn_fifo_destroy(dyn_fifo_t *fifo)
-{
-	if (!dyn_fifo_is_valid(fifo))
-		return EINVAL;
-
-	free(fifo->items);
-	fifo->magic_value = 0;
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/generic/fibril.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -57,24 +57,11 @@
 /**
  * This futex serializes access to ready_list,
- * serialized_list and manager_list.
+ * manager_list and fibril_list.
  */
 static futex_t fibril_futex = FUTEX_INITIALIZER;
 
 static LIST_INITIALIZE(ready_list);
-static LIST_INITIALIZE(serialized_list);
 static LIST_INITIALIZE(manager_list);
 static LIST_INITIALIZE(fibril_list);
-
-/** Number of threads that are executing a manager fibril. */
-static int threads_in_manager;
-
-/**
- * Number of threads that are executing a manager fibril
- * and are serialized. Protected by async_futex.
- */
-static int serialized_threads;
-
-/** Fibril-local count of serialization. If > 0, we must not preempt */
-static fibril_local int serialization_count;
 
 /** Function that spans the whole life-cycle of a fibril.
@@ -96,4 +83,5 @@
 	fibril->retval = fibril->func(fibril->arg);
 	
+	futex_down(&async_futex);
 	fibril_switch(FIBRIL_FROM_DEAD);
 	/* Not reached */
@@ -126,12 +114,19 @@
 	
 	fibril->waits_for = NULL;
+
+	futex_lock(&fibril_futex);
 	list_append(&fibril->all_link, &fibril_list);
+	futex_unlock(&fibril_futex);
 	
 	return fibril;
 }
 
-void fibril_teardown(fibril_t *fibril)
-{
+void fibril_teardown(fibril_t *fibril, bool locked)
+{	
+	if (!locked)
+		futex_lock(&fibril_futex);
 	list_remove(&fibril->all_link);
+	if (!locked)
+		futex_unlock(&fibril_futex);
 	tls_free(fibril->tcb);
 	free(fibril);
@@ -140,6 +135,6 @@
 /** Switch from the current fibril.
  *
- * If calling with FIBRIL_TO_MANAGER parameter, the async_futex should be
- * held.
+ * If stype is FIBRIL_TO_MANAGER or FIBRIL_FROM_DEAD, the async_futex must
+ * be held.
  *
  * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,
@@ -153,27 +148,20 @@
 int fibril_switch(fibril_switch_type_t stype)
 {
-	int retval = 0;
-	
-	futex_lock(&fibril_futex);
-	
-	if (stype == FIBRIL_PREEMPT && list_empty(&ready_list))
-		goto ret_0;
-	
-	if (stype == FIBRIL_FROM_MANAGER) {
-		if ((list_empty(&ready_list)) && (list_empty(&serialized_list)))
-			goto ret_0;
-		
-		/*
-		 * Do not preempt if there is not enough threads to run the
-		 * ready fibrils which are not serialized.
-		 */
-		if ((list_empty(&serialized_list)) &&
-		    (threads_in_manager <= serialized_threads)) {
-			goto ret_0;
+	futex_lock(&fibril_futex);
+
+	switch (stype) {
+	case FIBRIL_PREEMPT:
+	case FIBRIL_FROM_MANAGER:
+		if (list_empty(&ready_list)) {
+			futex_unlock(&fibril_futex);
+			return 0;
 		}
-	}
-	
-	/* If we are going to manager and none exists, create it */
-	if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
+		break;
+	case FIBRIL_TO_MANAGER:
+	case FIBRIL_FROM_DEAD:
+		/* Make sure the async_futex is held. */
+		assert((atomic_signed_t) async_futex.val.count <= 0);
+
+		/* If we are going to manager and none exists, create it */
 		while (list_empty(&manager_list)) {
 			futex_unlock(&fibril_futex);
@@ -181,4 +169,5 @@
 			futex_lock(&fibril_futex);
 		}
+		break;
 	}
 	
@@ -188,7 +177,4 @@
 		/* Save current state */
 		if (!context_save(&srcf->ctx)) {
-			if (serialization_count)
-				srcf->flags &= ~FIBRIL_SERIALIZED;
-			
 			if (srcf->clean_after_me) {
 				/*
@@ -208,5 +194,5 @@
 					as_area_destroy(stack);
 				}
-				fibril_teardown(srcf->clean_after_me);
+				fibril_teardown(srcf->clean_after_me, true);
 				srcf->clean_after_me = NULL;
 			}
@@ -215,42 +201,41 @@
 		}
 		
-		/* Save myself to the correct run list */
-		if (stype == FIBRIL_PREEMPT)
+		/* Put the current fibril into the correct run list */
+		switch (stype) {
+		case FIBRIL_PREEMPT:
 			list_append(&srcf->link, &ready_list);
-		else if (stype == FIBRIL_FROM_MANAGER) {
+			break;
+		case FIBRIL_FROM_MANAGER:
 			list_append(&srcf->link, &manager_list);
-			threads_in_manager--;
-		} else {
+			break;
+		default:
+			assert(stype == FIBRIL_TO_MANAGER);
+
 			/*
-			 * If stype == FIBRIL_TO_MANAGER, don't put ourselves to
-			 * any list, we should already be somewhere, or we will
-			 * be lost.
+			 * Don't put the current fibril into any list, it should
+			 * already be somewhere, or it will be lost.
 			 */
+			break;
 		}
 	}
 	
+	fibril_t *dstf;
+
 	/* Choose a new fibril to run */
-	fibril_t *dstf;
-	if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
+	switch (stype) {
+	case FIBRIL_TO_MANAGER:
+	case FIBRIL_FROM_DEAD:
 		dstf = list_get_instance(list_first(&manager_list), fibril_t,
 		    link);
-		if (serialization_count && stype == FIBRIL_TO_MANAGER) {
-			serialized_threads++;
-			srcf->flags |= FIBRIL_SERIALIZED;
-		}
-		threads_in_manager++;
 		
 		if (stype == FIBRIL_FROM_DEAD) 
 			dstf->clean_after_me = srcf;
-	} else {
-		if (!list_empty(&serialized_list)) {
-			dstf = list_get_instance(list_first(&serialized_list),
-			    fibril_t, link);
-			serialized_threads--;
-		} else {
-			dstf = list_get_instance(list_first(&ready_list),
-			    fibril_t, link);
-		}
-	}
+		break;
+	default:
+		dstf = list_get_instance(list_first(&ready_list), fibril_t,
+		    link);
+		break;
+	}
+
 	list_remove(&dstf->link);
 	
@@ -265,8 +250,4 @@
 	context_restore(&dstf->ctx);
 	/* not reached */
-	
-ret_0:
-	futex_unlock(&fibril_futex);
-	return retval;
 }
 
@@ -294,5 +275,5 @@
 	    AS_AREA_LATE_RESERVE);
 	if (fibril->stack == (void *) -1) {
-		fibril_teardown(fibril);
+		fibril_teardown(fibril, false);
 		return 0;
 	}
@@ -321,5 +302,5 @@
 	
 	as_area_destroy(fibril->stack);
-	fibril_teardown(fibril);
+	fibril_teardown(fibril, false);
 }
 
@@ -335,10 +316,5 @@
 	
 	futex_lock(&fibril_futex);
-	
-	if ((fibril->flags & FIBRIL_SERIALIZED))
-		list_append(&fibril->link, &serialized_list);
-	else
-		list_append(&fibril->link, &ready_list);
-	
+	list_append(&fibril->link, &ready_list);
 	futex_unlock(&fibril_futex);
 }
@@ -363,8 +339,6 @@
 {
 	futex_lock(&fibril_futex);
-	
 	if (!list_empty(&manager_list))
 		list_remove(list_first(&manager_list));
-	
 	futex_unlock(&fibril_futex);
 }
@@ -380,29 +354,4 @@
 }
 
-/** Disable preemption
- *
- * If the fibril wants to send several message in a row and does not want to be
- * preempted, it should start async_serialize_start() in the beginning of
- * communication and async_serialize_end() in the end. If it is a true
- * multithreaded application, it should protect the communication channel by a
- * futex as well.
- *
- */
-void fibril_inc_sercount(void)
-{
-	serialization_count++;
-}
-
-/** Restore the preemption counter to the previous state. */
-void fibril_dec_sercount(void)
-{
-	serialization_count--;
-}
-
-int fibril_get_sercount(void)
-{
-	return serialization_count;
-}
-
 /** @}
  */
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/generic/fibril_synch.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -105,7 +105,4 @@
 	fibril_t *f = (fibril_t *) fibril_get_id();
 
-	if (fibril_get_sercount() != 0)
-		abort();
-
 	futex_down(&async_futex);
 	if (fm->counter-- <= 0) {
@@ -197,7 +194,4 @@
 	fibril_t *f = (fibril_t *) fibril_get_id();
 	
-	if (fibril_get_sercount() != 0)
-		abort();
-
 	futex_down(&async_futex);
 	if (frw->writers) {
@@ -224,7 +218,4 @@
 	fibril_t *f = (fibril_t *) fibril_get_id();
 	
-	if (fibril_get_sercount() != 0)
-		abort();
-
 	futex_down(&async_futex);
 	if (frw->writers || frw->readers) {
@@ -461,9 +452,9 @@
 			if (rc == ETIMEOUT && timer->state == fts_active) {
 				timer->state = fts_fired;
-				timer->handler_running = true;
+				timer->handler_fid = fibril_get_id();
 				fibril_mutex_unlock(timer->lockp);
 				timer->fun(timer->arg);
 				fibril_mutex_lock(timer->lockp);
-				timer->handler_running = false;
+				timer->handler_fid = 0;
 			}
 			break;
@@ -477,6 +468,6 @@
 	/* Acknowledge timer fibril has finished cleanup. */
 	timer->state = fts_clean;
+	fibril_condvar_broadcast(&timer->cv);
 	fibril_mutex_unlock(timer->lockp);
-	free(timer);
 
 	return 0;
@@ -525,5 +516,11 @@
 	timer->state = fts_cleanup;
 	fibril_condvar_broadcast(&timer->cv);
+
+	/* Wait for timer fibril to terminate */
+	while (timer->state != fts_clean)
+		fibril_condvar_wait(&timer->cv, timer->lockp);
 	fibril_mutex_unlock(timer->lockp);
+
+	free(timer);
 }
 
@@ -608,6 +605,16 @@
 	assert(fibril_mutex_is_locked(timer->lockp));
 
-	while (timer->handler_running)
+	while (timer->handler_fid != 0) {
+		if (timer->handler_fid == fibril_get_id()) {
+			printf("Deadlock detected.\n");
+			stacktrace_print();
+			printf("Fibril %zx is trying to clear timer %p from "
+			    "inside its handler %p.\n",
+			    fibril_get_id(), timer, timer->fun);
+			abort();
+		}
+
 		fibril_condvar_wait(&timer->cv, timer->lockp);
+	}
 
 	old_state = timer->state;
Index: uspace/lib/c/generic/getopt.c
===================================================================
--- uspace/lib/c/generic/getopt.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/generic/getopt.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -95,11 +95,8 @@
  * Compute the greatest common divisor of a and b.
  */
-static int
-gcd(a, b)
-	int a;
-	int b;
+static int gcd(int a, int b)
 {
 	int c;
-
+	
 	c = a % b;
 	while (c != 0) {
@@ -108,5 +105,5 @@
 		c = a % b;
 	}
-	   
+	
 	return b;
 }
@@ -117,10 +114,6 @@
  * in each block).
  */
-static void
-permute_args(panonopt_start, panonopt_end, opt_end, nargv)
-	int panonopt_start;
-	int panonopt_end;
-	int opt_end;
-	char **nargv;
+static void permute_args(int panonopt_start, int panonopt_end, int opt_end,
+    char **nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
@@ -157,9 +150,5 @@
  *  Returns -2 if -- is found (can be long option or end of options marker).
  */
-static int
-getopt_internal(nargc, nargv, options)
-	int nargc;
-	char **nargv;
-	const char *options;
+static int getopt_internal(int nargc, char **nargv, const char *options)
 {
 	const char *oli;				/* option letter list index */
@@ -299,9 +288,5 @@
  *	Parse argc/argv argument vector.
  */
-int
-getopt(nargc, nargv, options)
-	int nargc;
-	char * const *nargv;
-	const char *options;
+int getopt(int nargc, char * const *nargv, const char *options)
 {
 	int retval;
@@ -332,11 +317,6 @@
  *	Parse argc/argv argument vector.
  */
-int
-getopt_long(nargc, nargv, options, long_options, idx)
-	int nargc;
-	char * const *nargv;
-	const char *options;
-	const struct option *long_options;
-	int *idx;
+int getopt_long(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
 {
 	int retval;
Index: uspace/lib/c/generic/inet.c
===================================================================
--- uspace/lib/c/generic/inet.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/generic/inet.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -177,4 +177,5 @@
 	
 	dgram.tos = IPC_GET_ARG1(*icall);
+	dgram.iplink = IPC_GET_ARG2(*icall);
 	
 	ipc_callid_t callid;
Index: uspace/lib/c/generic/inet/addr.c
===================================================================
--- uspace/lib/c/generic/inet/addr.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/generic/inet/addr.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2013 Jiri Svoboda
+ * Copyright (c) 2013 Martin Decky
  * All rights reserved.
  *
@@ -36,7 +37,5 @@
 #include <errno.h>
 #include <unistd.h>
-#include <net/socket_codes.h>
 #include <inet/addr.h>
-#include <net/inet.h>
 #include <stdio.h>
 #include <malloc.h>
@@ -44,4 +43,6 @@
 
 #define INET_PREFIXSTRSIZE  5
+
+#define INET6_ADDRSTRLEN (8 * 4 + 7 + 1)
 
 #if !(defined(__BE__) ^ defined(__LE__))
@@ -180,59 +181,4 @@
 }
 
-/** Determine address version.
- *
- * @param text Address in common notation.
- * @param af   Place to store address version.
- *
- * @return EOK on success, EINVAL if input is not in valid format.
- *
- */
-static int inet_addr_version(const char *text, ip_ver_t *ver)
-{
-	char *dot = str_chr(text, '.');
-	if (dot != NULL) {
-		*ver = ip_v4;
-		return EOK;
-	}
-
-	char *collon = str_chr(text, ':');
-	if (collon != NULL) {
-		*ver = ip_v6;
-		return EOK;
-	}
-
-	return EINVAL;
-}
-
-static int ipver_af(ip_ver_t ver)
-{
-	switch (ver) {
-	case ip_any:
-		return AF_NONE;
-	case ip_v4:
-		return AF_INET;
-	case ip_v6:
-		return AF_INET6;
-	default:
-		assert(false);
-		return EINVAL;
-	}
-}
-
-ip_ver_t ipver_from_af(int af)
-{
-	switch (af) {
-	case AF_NONE:
-		return ip_any;
-	case AF_INET:
-		return ip_v4;
-	case AF_INET6:
-		return ip_v6;
-	default:
-		assert(false);
-		return EINVAL;
-	}
-}
-
 void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr)
 {
@@ -288,5 +234,5 @@
 	if (naddr->version != addr->version)
 		return 0;
-	
+
 	switch (naddr->version) {
 	case ip_v4:
@@ -315,5 +261,5 @@
 		if (naddr->prefix > 128)
 			return 0;
-		
+
 		size_t pos = 0;
 		for (size_t i = 0; i < 16; i++) {
@@ -321,5 +267,5 @@
 			if (naddr->prefix < pos)
 				break;
-			
+
 			if (naddr->prefix - pos > 8) {
 				/* Comparison without masking */
@@ -333,8 +279,8 @@
 					return 0;
 			}
-			
+
 			pos += 8;
 		}
-		
+
 		return 1;
 	default:
@@ -343,4 +289,137 @@
 }
 
+static int inet_addr_parse_v4(const char *str, inet_addr_t *raddr,
+    int *prefix)
+{
+	uint32_t a = 0;
+	uint8_t b;
+	char *cur = (char *)str;
+	size_t i = 0;
+
+	while (i < 4) {
+		int rc = str_uint8_t(cur, (const char **)&cur, 10, false, &b);
+		if (rc != EOK)
+			return rc;
+
+		a = (a << 8) + b;
+
+		i++;
+
+		if (*cur == '\0')
+			break;
+
+		if (*cur != '.')
+			return EINVAL;
+
+		if (i < 4)
+			cur++;
+	}
+
+	if (prefix != NULL) {
+		*prefix = strtoul(cur, &cur, 10);
+		if (*prefix > 32)
+			return EINVAL;
+	}
+
+	if (i != 4 || (*cur != '\0'))
+		return EINVAL;
+
+	raddr->version = ip_v4;
+	raddr->addr = a;
+
+	return EOK;
+}
+
+static int inet_addr_parse_v6(const char *str, inet_addr_t *raddr, int *prefix)
+{
+	uint8_t data[16];
+
+	memset(data, 0, 16);
+
+	const char *cur = str;
+	size_t i = 0;
+	size_t wildcard_pos = (size_t) -1;
+	size_t wildcard_size = 0;
+
+	/* Handle initial wildcard */
+	if ((str[0] == ':') && (str[1] == ':')) {
+		cur = str + 2;
+		wildcard_pos = 0;
+		wildcard_size = 16;
+
+		/* Handle the unspecified address */
+		if (*cur == '\0')
+			goto success;
+	}
+
+	while (i < 16) {
+		uint16_t bioctet;
+		int rc = str_uint16_t(cur, &cur, 16, false, &bioctet);
+		if (rc != EOK)
+			return rc;
+
+		data[i] = (bioctet >> 8) & 0xff;
+		data[i + 1] = bioctet & 0xff;
+
+		if (wildcard_pos != (size_t) -1) {
+			if (wildcard_size < 2)
+				return EINVAL;
+
+			wildcard_size -= 2;
+		}
+
+		i += 2;
+
+		if (*cur != ':')
+			break;
+
+		if (i < 16) {
+			cur++;
+
+			/* Handle wildcard */
+			if (*cur == ':') {
+				if (wildcard_pos != (size_t) -1)
+					return EINVAL;
+
+				wildcard_pos = i;
+				wildcard_size = 16 - i;
+				cur++;
+
+				if (*cur == '\0' || *cur == '/')
+					break;
+			}
+		}
+	}
+
+	if (prefix != NULL) {
+		if (*cur != '/')
+			return EINVAL;
+		cur++;
+
+		*prefix = strtoul(cur, (char **)&cur, 10);
+		if (*prefix > 128)
+			return EINVAL;
+	}
+
+	if (*cur != '\0')
+		return EINVAL;
+
+	/* Create wildcard positions */
+	if ((wildcard_pos != (size_t) -1) && (wildcard_size > 0)) {
+		size_t wildcard_shift = 16 - wildcard_size;
+
+		for (i = wildcard_pos + wildcard_shift; i > wildcard_pos; i--) {
+			size_t j = i - 1;
+			data[j + wildcard_size] = data[j];
+			data[j] = 0;
+		}
+	}
+
+success:
+	raddr->version = ip_v6;
+	memcpy(raddr->addr6, data, 16);
+	return EOK;
+}
+
 /** Parse node address.
  *
@@ -353,26 +432,15 @@
 int inet_addr_parse(const char *text, inet_addr_t *addr)
 {
-	int rc = inet_addr_version(text, &addr->version);
-	if (rc != EOK)
-		return rc;
-	
-	uint8_t buf[16];
-	rc = inet_pton(ipver_af(addr->version), text, buf);
-	if (rc != EOK)
-		return rc;
-	
-	switch (addr->version) {
-	case ip_v4:
-		addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
-		    buf[3];
-		break;
-	case ip_v6:
-		memcpy(addr->addr6, buf, 16);
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	return EOK;
+	int rc;
+
+	rc = inet_addr_parse_v4(text, addr, NULL);
+	if (rc == EOK)
+		return EOK;
+
+	rc = inet_addr_parse_v6(text, addr, NULL);
+	if (rc == EOK)
+		return EOK;
+
+	return EINVAL;
 }
 
@@ -387,48 +455,97 @@
 int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
 {
-	char *slash = str_chr(text, '/');
-	if (slash == NULL)
-		return EINVAL;
-	
-	*slash = 0;
-	
-	int rc = inet_addr_version(text, &naddr->version);
-	if (rc != EOK)
-		return rc;
-	
-	uint8_t buf[16];
-	rc = inet_pton(ipver_af(naddr->version), text, buf);
-	*slash = '/';
-	
-	if (rc != EOK)
-		return rc;
-	
-	slash++;
-	uint8_t prefix;
-	
-	switch (naddr->version) {
-	case ip_v4:
-		prefix = strtoul(slash, &slash, 10);
-		if (prefix > 32)
+	int rc;
+	inet_addr_t addr;
+	int prefix;
+
+	rc = inet_addr_parse_v4(text, &addr, &prefix);
+	if (rc == EOK) {
+		inet_addr_naddr(&addr, prefix, naddr);
+		return EOK;
+	}
+
+	rc = inet_addr_parse_v6(text, &addr, &prefix);
+	if (rc == EOK) {
+		inet_addr_naddr(&addr, prefix, naddr);
+		return EOK;
+	}
+
+	return EINVAL;
+}
+
+static int inet_addr_format_v4(addr32_t addr, char **bufp)
+{
+	int rc;
+
+	rc = asprintf(bufp, "%u.%u.%u.%u", (addr >> 24) & 0xff,
+	    (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff);
+	if (rc < 0)
+		return ENOMEM;
+
+	return EOK;
+}
+
+static int inet_addr_format_v6(const addr128_t addr, char **bufp)
+{
+	*bufp = (char *) malloc(INET6_ADDRSTRLEN);
+	if (*bufp == NULL)
+		return ENOMEM;
+
+	/* Find the longest zero subsequence */
+
+	uint16_t zeroes[8];
+	uint16_t bioctets[8];
+
+	for (size_t i = 8; i > 0; i--) {
+		size_t j = i - 1;
+
+		bioctets[j] = (addr[j << 1] << 8) | addr[(j << 1) + 1];
+
+		if (bioctets[j] == 0) {
+			zeroes[j] = 1;
+			if (j < 7)
+				zeroes[j] += zeroes[j + 1];
+		} else
+			zeroes[j] = 0;
+	}
+
+	size_t wildcard_pos = (size_t) -1;
+	size_t wildcard_size = 0;
+
+	for (size_t i = 0; i < 8; i++) {
+		if (zeroes[i] > wildcard_size) {
+			wildcard_pos = i;
+			wildcard_size = zeroes[i];
+		}
+	}
+
+	char *cur = *bufp;
+	size_t rest = INET6_ADDRSTRLEN;
+	bool tail_zero = false;
+	int ret;
+
+	for (size_t i = 0; i < 8; i++) {
+		if ((i == wildcard_pos) && (wildcard_size > 1)) {
+			ret = snprintf(cur, rest, ":");
+			i += wildcard_size - 1;
+			tail_zero = true;
+		} else if (i == 0) {
+			ret = snprintf(cur, rest, "%" PRIx16, bioctets[i]);
+			tail_zero = false;
+		} else {
+			ret = snprintf(cur, rest, ":%" PRIx16, bioctets[i]);
+			tail_zero = false;
+		}
+
+		if (ret < 0)
 			return EINVAL;
-		
-		naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
-		    buf[3];
-		naddr->prefix = prefix;
-		
-		break;
-	case ip_v6:
-		prefix = strtoul(slash, &slash, 10);
-		if (prefix > 128)
-			return EINVAL;
-		
-		memcpy(naddr->addr6, buf, 16);
-		naddr->prefix = prefix;
-		
-		break;
-	default:
-		return ENOTSUP;
-	}
-	
+
+		cur += ret;
+		rest -= ret;
+	}
+
+	if (tail_zero)
+		(void) snprintf(cur, rest, ":");
+
 	return EOK;
 }
@@ -446,29 +563,24 @@
 int inet_addr_format(const inet_addr_t *addr, char **bufp)
 {
-	int rc = 0;
-	
+	int rc;
+
+	rc = ENOTSUP;
+
 	switch (addr->version) {
 	case ip_any:
 		rc = asprintf(bufp, "none");
+		if (rc < 0)
+			return ENOMEM;
+		rc = EOK;
 		break;
 	case ip_v4:
-		rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff,
-		    (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff,
-		    addr->addr & 0xff);
+		rc = inet_addr_format_v4(addr->addr, bufp);
 		break;
 	case ip_v6:
-		*bufp = (char *) malloc(INET6_ADDRSTRLEN);
-		if (*bufp == NULL)
-			return ENOMEM;
-		
-		return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN);
-	default:
-		return ENOTSUP;
-	}
-	
-	if (rc < 0)
-		return ENOMEM;
-	
-	return EOK;
+		rc = inet_addr_format_v6(addr->addr6, bufp);
+		break;
+	}
+
+	return rc;
 }
 
@@ -485,47 +597,45 @@
 int inet_naddr_format(const inet_naddr_t *naddr, char **bufp)
 {
-	int rc = 0;
-	char prefix[INET_PREFIXSTRSIZE];
-	
+	int rc;
+	char *astr;
+
+	rc = ENOTSUP;
+
 	switch (naddr->version) {
 	case ip_any:
 		rc = asprintf(bufp, "none");
+		if (rc < 0)
+			return ENOMEM;
+		rc = EOK;
 		break;
 	case ip_v4:
-		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 ip_v6:
-		*bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
-		if (*bufp == NULL)
+		rc = inet_addr_format_v4(naddr->addr, &astr);
+		if (rc != EOK)
 			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);
+
+		rc = asprintf(bufp, "%s/%" PRIu8, astr, naddr->prefix);
 		if (rc < 0) {
-			free(*bufp);
+			free(astr);
 			return ENOMEM;
 		}
-		
-		str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix);
-		
-		break;
-	default:
-		return ENOTSUP;
-	}
-	
-	if (rc < 0)
-		return ENOMEM;
-	
-	return EOK;
+
+		rc = EOK;
+		break;
+	case ip_v6:
+		rc = inet_addr_format_v6(naddr->addr6, &astr);
+		if (rc != EOK)
+			return ENOMEM;
+
+		rc = asprintf(bufp, "%s/%" PRIu8, astr, naddr->prefix);
+		if (rc < 0) {
+			free(astr);
+			return ENOMEM;
+		}
+
+		rc = EOK;
+		break;
+	}
+
+	return rc;
 }
 
@@ -586,10 +696,4 @@
 }
 
-void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr)
-{
-	addr->version = ip_v4;
-	addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr);
-}
-
 void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
 {
@@ -605,76 +709,4 @@
 }
 
-void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6,
-    inet_addr_t *addr)
-{
-	addr->version = ip_v6;
-	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->version) {
-	case ip_v4:
-		if (sockaddr_in != NULL) {
-			sockaddr_in->sin_family = AF_INET;
-			sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr);
-		}
-		break;
-	case ip_v6:
-		if (sockaddr_in6 != NULL) {
-			sockaddr_in6->sin6_family = AF_INET6;
-			host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr);
-		}
-		break;
-	default:
-		assert(false);
-		break;
-	}
-
-	return ipver_af(addr->version);
-}
-
-int inet_addr_sockaddr(const inet_addr_t *addr, uint16_t port,
-    sockaddr_t **nsockaddr, socklen_t *naddrlen)
-{
-	sockaddr_in_t *sa4;
-	sockaddr_in6_t *sa6;
-
-	switch (addr->version) {
-	case ip_v4:
-		sa4 = calloc(1, sizeof(sockaddr_in_t));
-		if (sa4 == NULL)
-			return ENOMEM;
-
-		sa4->sin_family = AF_INET;
-		sa4->sin_port = host2uint16_t_be(port);
-		sa4->sin_addr.s_addr = host2uint32_t_be(addr->addr);
-		if (nsockaddr != NULL)
-			*nsockaddr = (sockaddr_t *)sa4;
-		if (naddrlen != NULL)
-			*naddrlen = sizeof(*sa4);
-		break;
-	case ip_v6:
-		sa6 = calloc(1, sizeof(sockaddr_in6_t));
-		if (sa6 == NULL)
-			return ENOMEM;
-
-		sa6->sin6_family = AF_INET6;
-		sa6->sin6_port = host2uint16_t_be(port);
-		host2addr128_t_be(addr->addr6, sa6->sin6_addr.s6_addr);
-		if (nsockaddr != NULL)
-			*nsockaddr = (sockaddr_t *)sa6;
-		if (naddrlen != NULL)
-			*naddrlen = sizeof(*sa6);
-		break;
-	default:
-		assert(false);
-		break;
-	}
-
-	return EOK;
-}
-
 /** @}
  */
Index: uspace/lib/c/generic/inet/endpoint.c
===================================================================
--- uspace/lib/c/generic/inet/endpoint.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/c/generic/inet/endpoint.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,49 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file Internet endpoint
+ */
+
+#include <inet/endpoint.h>
+#include <mem.h>
+
+void inet_ep_init(inet_ep_t *ep)
+{
+	memset(ep, 0, sizeof(*ep));
+}
+
+void inet_ep2_init(inet_ep2_t *ep2)
+{
+	memset(ep2, 0, sizeof(*ep2));
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/inet/tcp.c
===================================================================
--- uspace/lib/c/generic/inet/tcp.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/c/generic/inet/tcp.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,650 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file TCP API
+ */
+
+#include <errno.h>
+#include <fibril.h>
+#include <inet/endpoint.h>
+#include <inet/tcp.h>
+#include <ipc/services.h>
+#include <ipc/tcp.h>
+#include <stdlib.h>
+
+static void tcp_cb_conn(ipc_callid_t, ipc_call_t *, void *);
+static int tcp_conn_fibril(void *);
+
+/** Incoming TCP connection info */
+typedef struct {
+	tcp_listener_t *lst;
+	tcp_conn_t *conn;
+} tcp_in_conn_t;
+
+static int tcp_callback_create(tcp_t *tcp)
+{
+	async_exch_t *exch = async_exchange_begin(tcp->sess);
+
+	aid_t req = async_send_0(exch, TCP_CALLBACK_CREATE, NULL);
+	int rc = async_connect_to_me(exch, 0, 0, 0, tcp_cb_conn, tcp);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	return retval;
+}
+
+int tcp_create(tcp_t **rtcp)
+{
+	tcp_t *tcp;
+	service_id_t tcp_svcid;
+	int rc;
+
+	tcp = calloc(1, sizeof(tcp_t));
+	if (tcp == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	list_initialize(&tcp->conn);
+	list_initialize(&tcp->listener);
+	fibril_mutex_initialize(&tcp->lock);
+	fibril_condvar_initialize(&tcp->cv);
+
+	rc = loc_service_get_id(SERVICE_NAME_TCP, &tcp_svcid,
+	    IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	tcp->sess = loc_service_connect(EXCHANGE_SERIALIZE, tcp_svcid,
+	    IPC_FLAG_BLOCKING);
+	if (tcp->sess == NULL) {
+		rc = EIO;
+		goto error;
+	}
+
+	rc = tcp_callback_create(tcp);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	*rtcp = tcp;
+	return EOK;
+error:
+	free(tcp);
+	return rc;
+}
+
+void tcp_destroy(tcp_t *tcp)
+{
+	if (tcp == NULL)
+		return;
+
+	async_hangup(tcp->sess);
+
+	fibril_mutex_lock(&tcp->lock);
+	while (!tcp->cb_done)
+		fibril_condvar_wait(&tcp->cv, &tcp->lock);
+	fibril_mutex_unlock(&tcp->lock);
+
+	free(tcp);
+}
+
+static int tcp_conn_new(tcp_t *tcp, sysarg_t id, tcp_cb_t *cb, void *arg,
+    tcp_conn_t **rconn)
+{
+	tcp_conn_t *conn;
+
+	conn = calloc(1, sizeof(tcp_conn_t));
+	if (conn == NULL)
+		return ENOMEM;
+
+	conn->data_avail = false;
+	fibril_mutex_initialize(&conn->lock);
+	fibril_condvar_initialize(&conn->cv);
+
+	conn->tcp = tcp;
+	conn->id = id;
+	conn->cb = cb;
+	conn->cb_arg = arg;
+
+	list_append(&conn->ltcp, &tcp->conn);
+	*rconn = conn;
+
+	return EOK;
+}
+
+int tcp_conn_create(tcp_t *tcp, inet_ep2_t *epp, tcp_cb_t *cb, void *arg,
+    tcp_conn_t **rconn)
+{
+	async_exch_t *exch;
+	ipc_call_t answer;
+	sysarg_t conn_id;
+
+	exch = async_exchange_begin(tcp->sess);
+	aid_t req = async_send_0(exch, TCP_CONN_CREATE, &answer);
+	sysarg_t rc = async_data_write_start(exch, (void *)epp,
+	    sizeof(inet_ep2_t));
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		sysarg_t rc_orig;
+		async_wait_for(req, &rc_orig);
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		goto error;
+	}
+
+	async_wait_for(req, &rc);
+	if (rc != EOK)
+		goto error;
+
+	conn_id = IPC_GET_ARG1(answer);
+
+	rc = tcp_conn_new(tcp, conn_id, cb, arg, rconn);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+error:
+	return (int) rc;
+}
+
+void tcp_conn_destroy(tcp_conn_t *conn)
+{
+	async_exch_t *exch;
+
+	if (conn == NULL)
+		return;
+
+	list_remove(&conn->ltcp);
+
+	exch = async_exchange_begin(conn->tcp->sess);
+	sysarg_t rc = async_req_1_0(exch, TCP_CONN_DESTROY, conn->id);
+	async_exchange_end(exch);
+
+	free(conn);
+	(void) rc;
+}
+
+static int tcp_conn_get(tcp_t *tcp, sysarg_t id, tcp_conn_t **rconn)
+{
+	list_foreach(tcp->conn, ltcp, tcp_conn_t, conn) {
+		if (conn->id == id) {
+			*rconn = conn;
+			return EOK;
+		}
+	}
+
+	return EINVAL;
+}
+
+void *tcp_conn_userptr(tcp_conn_t *conn)
+{
+	return conn->cb_arg;
+}
+
+int tcp_listener_create(tcp_t *tcp, inet_ep_t *ep, tcp_listen_cb_t *lcb,
+    void *larg, tcp_cb_t *cb, void *arg, tcp_listener_t **rlst)
+{
+	async_exch_t *exch;
+	tcp_listener_t *lst;
+	ipc_call_t answer;
+
+	lst = calloc(1, sizeof(tcp_listener_t));
+	if (lst == NULL)
+		return ENOMEM;
+
+	exch = async_exchange_begin(tcp->sess);
+	aid_t req = async_send_0(exch, TCP_LISTENER_CREATE, &answer);
+	sysarg_t rc = async_data_write_start(exch, (void *)ep,
+	    sizeof(inet_ep_t));
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		sysarg_t rc_orig;
+		async_wait_for(req, &rc_orig);
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		goto error;
+	}
+
+	async_wait_for(req, &rc);
+	if (rc != EOK)
+		goto error;
+
+	lst->tcp = tcp;
+	lst->id = IPC_GET_ARG1(answer);
+	lst->lcb = lcb;
+	lst->lcb_arg = larg;
+	lst->cb = cb;
+	lst->cb_arg = arg;
+
+	list_append(&lst->ltcp, &tcp->listener);
+	*rlst = lst;
+
+	return EOK;
+error:
+	free(lst);
+	return (int) rc;
+}
+
+void tcp_listener_destroy(tcp_listener_t *lst)
+{
+	async_exch_t *exch;
+
+	if (lst == NULL)
+		return;
+
+	list_remove(&lst->ltcp);
+
+	exch = async_exchange_begin(lst->tcp->sess);
+	sysarg_t rc = async_req_1_0(exch, TCP_LISTENER_DESTROY, lst->id);
+	async_exchange_end(exch);
+
+	free(lst);
+	(void) rc;
+}
+
+static int tcp_listener_get(tcp_t *tcp, sysarg_t id, tcp_listener_t **rlst)
+{
+	list_foreach(tcp->listener, ltcp, tcp_listener_t, lst) {
+		if (lst->id == id) {
+			*rlst = lst;
+			return EOK;
+		}
+	}
+
+	return EINVAL;
+}
+
+void *tcp_listener_userptr(tcp_listener_t *lst)
+{
+	return lst->lcb_arg;
+}
+
+int tcp_conn_wait_connected(tcp_conn_t *conn)
+{
+	fibril_mutex_lock(&conn->lock);
+	while (!conn->connected && !conn->conn_failed && !conn->conn_reset)
+		fibril_condvar_wait(&conn->cv, &conn->lock);
+
+	if (conn->connected) {
+		fibril_mutex_unlock(&conn->lock);
+		return EOK;
+	} else {
+		assert(conn->conn_failed || conn->conn_reset);
+		fibril_mutex_unlock(&conn->lock);
+		return EIO;
+	}
+}
+
+int tcp_conn_send(tcp_conn_t *conn, const void *data, size_t bytes)
+{
+	async_exch_t *exch;
+	sysarg_t rc;
+
+	exch = async_exchange_begin(conn->tcp->sess);
+	aid_t req = async_send_1(exch, TCP_CONN_SEND, conn->id, NULL);
+
+	rc = async_data_write_start(exch, data, bytes);
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	async_wait_for(req, &rc);
+	return rc;
+}
+
+
+int tcp_conn_send_fin(tcp_conn_t *conn)
+{
+	async_exch_t *exch;
+
+	exch = async_exchange_begin(conn->tcp->sess);
+	sysarg_t rc = async_req_1_0(exch, TCP_CONN_SEND_FIN, conn->id);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int tcp_conn_push(tcp_conn_t *conn)
+{
+	async_exch_t *exch;
+
+	exch = async_exchange_begin(conn->tcp->sess);
+	sysarg_t rc = async_req_1_0(exch, TCP_CONN_PUSH, conn->id);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int tcp_conn_reset(tcp_conn_t *conn)
+{
+	async_exch_t *exch;
+
+	exch = async_exchange_begin(conn->tcp->sess);
+	sysarg_t rc = async_req_1_0(exch, TCP_CONN_RESET, conn->id);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int tcp_conn_recv(tcp_conn_t *conn, void *buf, size_t bsize, size_t *nrecv)
+{
+	async_exch_t *exch;
+	ipc_call_t answer;
+
+	fibril_mutex_lock(&conn->lock);
+	if (!conn->data_avail) {
+		fibril_mutex_unlock(&conn->lock);
+		return EAGAIN;
+	}
+
+	exch = async_exchange_begin(conn->tcp->sess);
+	aid_t req = async_send_1(exch, TCP_CONN_RECV, conn->id, &answer);
+	int rc = async_data_read_start(exch, buf, bsize);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		fibril_mutex_unlock(&conn->lock);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK) {
+		fibril_mutex_unlock(&conn->lock);
+		return retval;
+	}
+
+	*nrecv = IPC_GET_ARG1(answer);
+	fibril_mutex_unlock(&conn->lock);
+	return EOK;
+}
+
+int tcp_conn_recv_wait(tcp_conn_t *conn, void *buf, size_t bsize, size_t *nrecv)
+{
+	async_exch_t *exch;
+	ipc_call_t answer;
+
+again:
+	fibril_mutex_lock(&conn->lock);
+	while (!conn->data_avail) {
+		fibril_condvar_wait(&conn->cv, &conn->lock);
+	}
+
+	exch = async_exchange_begin(conn->tcp->sess);
+	aid_t req = async_send_1(exch, TCP_CONN_RECV_WAIT, conn->id, &answer);
+	int rc = async_data_read_start(exch, buf, bsize);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		if (rc == EAGAIN) {
+			conn->data_avail = false;
+			fibril_mutex_unlock(&conn->lock);
+			goto again;
+		}
+		fibril_mutex_unlock(&conn->lock);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK) {
+		if (rc == EAGAIN) {
+			conn->data_avail = false;
+		}
+		fibril_mutex_unlock(&conn->lock);
+		return retval;
+	}
+
+	*nrecv = IPC_GET_ARG1(answer);
+	fibril_mutex_unlock(&conn->lock);
+	return EOK;
+}
+
+static void tcp_ev_connected(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	tcp_conn_t *conn;
+	sysarg_t conn_id;
+	int rc;
+
+	conn_id = IPC_GET_ARG1(*icall);
+
+	rc = tcp_conn_get(tcp, conn_id, &conn);
+	if (rc != EOK) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	fibril_mutex_lock(&conn->lock);
+	conn->connected = true;
+	fibril_condvar_broadcast(&conn->cv);
+	fibril_mutex_unlock(&conn->lock);
+
+	async_answer_0(iid, EOK);
+}
+
+static void tcp_ev_conn_failed(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	tcp_conn_t *conn;
+	sysarg_t conn_id;
+	int rc;
+
+	conn_id = IPC_GET_ARG1(*icall);
+
+	rc = tcp_conn_get(tcp, conn_id, &conn);
+	if (rc != EOK) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	fibril_mutex_lock(&conn->lock);
+	conn->conn_failed = true;
+	fibril_condvar_broadcast(&conn->cv);
+	fibril_mutex_unlock(&conn->lock);
+
+	async_answer_0(iid, EOK);
+}
+
+static void tcp_ev_conn_reset(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	tcp_conn_t *conn;
+	sysarg_t conn_id;
+	int rc;
+
+	conn_id = IPC_GET_ARG1(*icall);
+
+	rc = tcp_conn_get(tcp, conn_id, &conn);
+	if (rc != EOK) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	fibril_mutex_lock(&conn->lock);
+	conn->conn_reset = true;
+	fibril_condvar_broadcast(&conn->cv);
+	fibril_mutex_unlock(&conn->lock);
+
+	async_answer_0(iid, EOK);
+}
+
+static void tcp_ev_data(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	tcp_conn_t *conn;
+	sysarg_t conn_id;
+	int rc;
+
+	conn_id = IPC_GET_ARG1(*icall);
+
+	rc = tcp_conn_get(tcp, conn_id, &conn);
+	if (rc != EOK) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	conn->data_avail = true;
+	fibril_condvar_broadcast(&conn->cv);
+
+	if (conn->cb != NULL && conn->cb->data_avail != NULL)
+		conn->cb->data_avail(conn);
+
+	async_answer_0(iid, EOK);
+}
+
+static void tcp_ev_urg_data(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	async_answer_0(iid, ENOTSUP);
+}
+
+static void tcp_ev_new_conn(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	tcp_listener_t *lst;
+	tcp_conn_t *conn;
+	sysarg_t lst_id;
+	sysarg_t conn_id;
+	fid_t fid;
+	tcp_in_conn_t *cinfo;
+	int rc;
+
+	lst_id = IPC_GET_ARG1(*icall);
+	conn_id = IPC_GET_ARG2(*icall);
+
+	rc = tcp_listener_get(tcp, lst_id, &lst);
+	if (rc != EOK) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	rc = tcp_conn_new(tcp, conn_id, lst->cb, lst->cb_arg, &conn);
+	if (rc != EOK) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	if (lst->lcb != NULL && lst->lcb->new_conn != NULL) {
+		cinfo = calloc(1, sizeof(tcp_in_conn_t));
+		if (cinfo == NULL) {
+			async_answer_0(iid, ENOMEM);
+			return;
+		}
+
+		cinfo->lst = lst;
+		cinfo->conn = conn;
+
+		fid = fibril_create(tcp_conn_fibril, cinfo);
+		if (fid == 0) {
+			async_answer_0(iid, ENOMEM);
+		}
+
+		fibril_add_ready(fid);
+	}
+
+	async_answer_0(iid, EOK);
+}
+
+static void tcp_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	tcp_t *tcp = (tcp_t *)arg;
+
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* Hangup*/
+			goto out;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case TCP_EV_CONNECTED:
+			tcp_ev_connected(tcp, callid, &call);
+			break;
+		case TCP_EV_CONN_FAILED:
+			tcp_ev_conn_failed(tcp, callid, &call);
+			break;
+		case TCP_EV_CONN_RESET:
+			tcp_ev_conn_reset(tcp, callid, &call);
+			break;
+		case TCP_EV_DATA:
+			tcp_ev_data(tcp, callid, &call);
+			break;
+		case TCP_EV_URG_DATA:
+			tcp_ev_urg_data(tcp, callid, &call);
+			break;
+		case TCP_EV_NEW_CONN:
+			tcp_ev_new_conn(tcp, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+out:
+	fibril_mutex_lock(&tcp->lock);
+	tcp->cb_done = true;
+	fibril_mutex_unlock(&tcp->lock);
+	fibril_condvar_broadcast(&tcp->cv);
+}
+
+/** Fibril for handling incoming TCP connection in background */
+static int tcp_conn_fibril(void *arg)
+{
+	tcp_in_conn_t *cinfo = (tcp_in_conn_t *)arg;
+
+	cinfo->lst->lcb->new_conn(cinfo->lst, cinfo->conn);
+	tcp_conn_destroy(cinfo->conn);
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/inet/udp.c
===================================================================
--- uspace/lib/c/generic/inet/udp.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/c/generic/inet/udp.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,374 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file UDP API
+ */
+
+#include <errno.h>
+#include <inet/endpoint.h>
+#include <inet/udp.h>
+#include <ipc/services.h>
+#include <ipc/udp.h>
+#include <loc.h>
+#include <stdlib.h>
+
+static void udp_cb_conn(ipc_callid_t, ipc_call_t *, void *);
+
+static int udp_callback_create(udp_t *udp)
+{
+	async_exch_t *exch = async_exchange_begin(udp->sess);
+
+	aid_t req = async_send_0(exch, UDP_CALLBACK_CREATE, NULL);
+	int rc = async_connect_to_me(exch, 0, 0, 0, udp_cb_conn, udp);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	return retval;
+}
+
+int udp_create(udp_t **rudp)
+{
+	udp_t *udp;
+	service_id_t udp_svcid;
+	int rc;
+
+	udp = calloc(1, sizeof(udp_t));
+	if (udp == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	list_initialize(&udp->assoc);
+	fibril_mutex_initialize(&udp->lock);
+	fibril_condvar_initialize(&udp->cv);
+
+	rc = loc_service_get_id(SERVICE_NAME_UDP, &udp_svcid,
+	    IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	udp->sess = loc_service_connect(EXCHANGE_SERIALIZE, udp_svcid,
+	    IPC_FLAG_BLOCKING);
+	if (udp->sess == NULL) {
+		rc = EIO;
+		goto error;
+	}
+
+	rc = udp_callback_create(udp);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
+	*rudp = udp;
+	return EOK;
+error:
+	free(udp);
+	return rc;
+}
+
+void udp_destroy(udp_t *udp)
+{
+	if (udp == NULL)
+		return;
+
+	async_hangup(udp->sess);
+
+	fibril_mutex_lock(&udp->lock);
+	while (!udp->cb_done)
+		fibril_condvar_wait(&udp->cv, &udp->lock);
+	fibril_mutex_unlock(&udp->lock);
+
+	free(udp);
+}
+
+int udp_assoc_create(udp_t *udp, inet_ep2_t *ep2, udp_cb_t *cb, void *arg,
+    udp_assoc_t **rassoc)
+{
+	async_exch_t *exch;
+	udp_assoc_t *assoc;
+	ipc_call_t answer;
+
+	assoc = calloc(1, sizeof(udp_assoc_t));
+	if (assoc == NULL)
+		return ENOMEM;
+
+	exch = async_exchange_begin(udp->sess);
+	aid_t req = async_send_0(exch, UDP_ASSOC_CREATE, &answer);
+	sysarg_t rc = async_data_write_start(exch, (void *)ep2,
+	    sizeof(inet_ep2_t));
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		sysarg_t rc_orig;
+		async_wait_for(req, &rc_orig);
+		if (rc_orig != EOK)
+			rc = rc_orig;
+		goto error;
+	}
+
+	async_wait_for(req, &rc);
+	if (rc != EOK)
+		goto error;
+
+	assoc->udp = udp;
+	assoc->id = IPC_GET_ARG1(answer);
+	assoc->cb = cb;
+	assoc->cb_arg = arg;
+
+	list_append(&assoc->ludp, &udp->assoc);
+	*rassoc = assoc;
+
+	return EOK;
+error:
+	free(assoc);
+	return (int) rc;
+}
+
+void udp_assoc_destroy(udp_assoc_t *assoc)
+{
+	async_exch_t *exch;
+
+	if (assoc == NULL)
+		return;
+
+	list_remove(&assoc->ludp);
+
+	exch = async_exchange_begin(assoc->udp->sess);
+	sysarg_t rc = async_req_1_0(exch, UDP_ASSOC_DESTROY, assoc->id);
+	async_exchange_end(exch);
+
+	free(assoc);
+	(void) rc;
+}
+
+int udp_assoc_send_msg(udp_assoc_t *assoc, inet_ep_t *dest, void *data,
+    size_t bytes)
+{
+	async_exch_t *exch;
+
+	exch = async_exchange_begin(assoc->udp->sess);
+	aid_t req = async_send_1(exch, UDP_ASSOC_SEND_MSG, assoc->id, NULL);
+
+	sysarg_t rc = async_data_write_start(exch, (void *)dest,
+	    sizeof(inet_ep_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+
+	rc = async_data_write_start(exch, data, bytes);
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	async_wait_for(req, &rc);
+	return rc;
+}
+
+void *udp_assoc_userptr(udp_assoc_t *assoc)
+{
+	return assoc->cb_arg;
+}
+
+size_t udp_rmsg_size(udp_rmsg_t *rmsg)
+{
+	return rmsg->size;
+}
+
+int udp_rmsg_read(udp_rmsg_t *rmsg, size_t off, void *buf, size_t bsize)
+{
+	async_exch_t *exch;
+	ipc_call_t answer;
+
+	exch = async_exchange_begin(rmsg->udp->sess);
+	aid_t req = async_send_1(exch, UDP_RMSG_READ, off, &answer);
+	int rc = async_data_read_start(exch, buf, bsize);
+	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;
+}
+
+void udp_rmsg_remote_ep(udp_rmsg_t *rmsg, inet_ep_t *ep)
+{
+	*ep = rmsg->remote_ep;
+}
+
+uint8_t udp_rerr_type(udp_rerr_t *rerr)
+{
+	return 0;
+}
+
+uint8_t udp_rerr_code(udp_rerr_t *rerr)
+{
+	return 0;
+}
+
+static int udp_rmsg_info(udp_t *udp, udp_rmsg_t *rmsg)
+{
+	async_exch_t *exch;
+	inet_ep_t ep;
+	ipc_call_t answer;
+
+	exch = async_exchange_begin(udp->sess);
+	aid_t req = async_send_0(exch, UDP_RMSG_INFO, &answer);
+	int rc = async_data_read_start(exch, &ep, sizeof(inet_ep_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;
+
+	rmsg->udp = udp;
+	rmsg->assoc_id = IPC_GET_ARG1(answer);
+	rmsg->size = IPC_GET_ARG2(answer);
+	rmsg->remote_ep = ep;
+	return EOK;
+}
+
+static int udp_rmsg_discard(udp_t *udp)
+{
+	async_exch_t *exch;
+
+	exch = async_exchange_begin(udp->sess);
+	sysarg_t rc = async_req_0_0(exch, UDP_RMSG_DISCARD);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+static int udp_assoc_get(udp_t *udp, sysarg_t id, udp_assoc_t **rassoc)
+{
+	list_foreach(udp->assoc, ludp, udp_assoc_t, assoc) {
+		if (assoc->id == id) {
+			*rassoc = assoc;
+			return EOK;
+		}
+	}
+
+	return EINVAL;
+}
+
+static void udp_ev_data(udp_t *udp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	udp_rmsg_t rmsg;
+	udp_assoc_t *assoc;
+	int rc;
+
+	while (true) {
+		rc = udp_rmsg_info(udp, &rmsg);
+		if (rc != EOK) {
+			break;
+		}
+
+		rc = udp_assoc_get(udp, rmsg.assoc_id, &assoc);
+		if (rc != EOK) {
+			continue;
+		}
+
+		if (assoc->cb != NULL && assoc->cb->recv_msg != NULL)
+			assoc->cb->recv_msg(assoc, &rmsg);
+
+		rc = udp_rmsg_discard(udp);
+		if (rc != EOK) {
+			break;
+		}
+	}
+
+	async_answer_0(iid, EOK);
+}
+
+static void udp_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	udp_t *udp = (udp_t *)arg;
+
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* Hangup */
+			goto out;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case UDP_EV_DATA:
+			udp_ev_data(udp, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+out:
+	fibril_mutex_lock(&udp->lock);
+	udp->cb_done = true;
+	fibril_mutex_unlock(&udp->lock);
+	fibril_condvar_broadcast(&udp->cv);
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/iplink.c
===================================================================
--- uspace/lib/c/generic/iplink.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/generic/iplink.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -47,5 +47,5 @@
 static void iplink_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 
-int iplink_open(async_sess_t *sess, iplink_ev_ops_t *ev_ops,
+int iplink_open(async_sess_t *sess, iplink_ev_ops_t *ev_ops, void *arg,
     iplink_t **riplink)
 {
@@ -56,4 +56,5 @@
 	iplink->sess = sess;
 	iplink->ev_ops = ev_ops;
+	iplink->arg = arg;
 	
 	async_exch_t *exch = async_exchange_begin(sess);
@@ -234,4 +235,9 @@
 	
 	return (int) retval;
+}
+
+void *iplink_get_userptr(iplink_t *iplink)
+{
+	return iplink->arg;
 }
 
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/generic/libc.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -122,5 +122,5 @@
 		__stdio_done();
 		task_retval(status);
-		fibril_teardown(__tcb_get()->fibril_data);
+		fibril_teardown(__tcb_get()->fibril_data, false);
 	}
 	
Index: pace/lib/c/generic/net/inet.c
===================================================================
--- uspace/lib/c/generic/net/inet.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,293 +1,0 @@
-/*
- * Copyright (c) 2013 Martin Decky
- * 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 libc
- *  @{
- */
-
-/** @file
- * Internet protocol address conversion functions implementation.
- */
-
-#include <net/socket_codes.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <inet/addr.h>
-#include <errno.h>
-#include <mem.h>
-#include <stdio.h>
-#include <str.h>
-
-const in6_addr_t in6addr_any = {
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-};
-
-static int inet_ntop4(const uint8_t *data, char *address, size_t length)
-{
-	/* Check output buffer size */
-	if (length < INET_ADDRSTRLEN)
-		return ENOMEM;
-	
-	/* Fill buffer with IPv4 address */
-	snprintf(address, length,
-	    "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8,
-	    data[0], data[1], data[2], data[3]);
-	
-	return EOK;
-}
-
-static int inet_ntop6(const uint8_t *data, char *address, size_t length)
-{
-	/* Check output buffer size */
-	if (length < INET6_ADDRSTRLEN)
-		return ENOMEM;
-	
-	/* Find the longest zero subsequence */
-	
-	uint16_t zeroes[8];
-	uint16_t bioctets[8];
-	
-	for (size_t i = 8; i > 0; i--) {
-		size_t j = i - 1;
-		
-		bioctets[j] = (data[j << 1] << 8) | data[(j << 1) + 1];
-		
-		if (bioctets[j] == 0) {
-			zeroes[j] = 1;
-			if (j < 7)
-				zeroes[j] += zeroes[j + 1];
-		} else
-			zeroes[j] = 0;
-	}
-	
-	size_t wildcard_pos = (size_t) -1;
-	size_t wildcard_size = 0;
-	
-	for (size_t i = 0; i < 8; i++) {
-		if (zeroes[i] > wildcard_size) {
-			wildcard_pos = i;
-			wildcard_size = zeroes[i];
-		}
-	}
-	
-	char *cur = address;
-	size_t rest = length;
-	bool tail_zero = false;
-	int ret;
-	
-	for (size_t i = 0; i < 8; i++) {
-		if ((i == wildcard_pos) && (wildcard_size > 1)) {
-			ret = snprintf(cur, rest, ":");
-			i += wildcard_size - 1;
-			tail_zero = true;
-		} else if (i == 0) {
-			ret = snprintf(cur, rest, "%" PRIx16, bioctets[i]);
-			tail_zero = false;
-		} else {
-			ret = snprintf(cur, rest, ":%" PRIx16, bioctets[i]);
-			tail_zero = false;
-		}
-		
-		if (ret < 0)
-			return EINVAL;
-		
-		cur += ret;
-		rest -= ret;
-	}
-	
-	if (tail_zero) {
-		ret = snprintf(cur, rest, ":");
-		if (ret < 0)
-			return EINVAL;
-	}
-	
-	return EOK;
-}
-
-/** Prints the address into the character buffer.
- *
- * @param[in]  family  Address family.
- * @param[in]  data    Address data.
- * @param[out] address Character buffer to be filled.
- * @param[in]  length  Buffer length.
- *
- * @return EOK on success.
- * @return EINVAL if the data or address parameter is NULL.
- * @return ENOMEM if the character buffer is not long enough.
- * @return ENOTSUP if the address family is not supported.
- *
- */
-int inet_ntop(uint16_t family, const uint8_t *data, char *address, size_t length)
-{
-	switch (family) {
-	case AF_INET:
-		return inet_ntop4(data, address, length);
-	case AF_INET6:
-		return inet_ntop6(data, address, length);
-	default:
-		return ENOTSUP;
-	}
-}
-
-static int inet_pton4(const char *address, uint8_t *data)
-{
-	memset(data, 0, 4);
-	
-	const char *cur = address;
-	size_t i = 0;
-	
-	while (i < 4) {
-		int rc = str_uint8_t(cur, &cur, 10, false, &data[i]);
-		if (rc != EOK)
-			return rc;
-		
-		i++;
-		
-		if (*cur == 0)
-			break;
-		
-		if (*cur != '.')
-			return EINVAL;
-		
-		if (i < 4)
-			cur++;
-	}
-	
-	if ((i == 4) && (*cur != 0))
-		return EINVAL;
-	
-	return EOK;
-}
-
-static int inet_pton6(const char *address, uint8_t *data)
-{
-	memset(data, 0, 16);
-	
-	const char *cur = address;
-	size_t i = 0;
-	size_t wildcard_pos = (size_t) -1;
-	size_t wildcard_size = 0;
-	
-	/* Handle initial wildcard */
-	if ((address[0] == ':') && (address[1] == ':')) {
-		cur = address + 2;
-		wildcard_pos = 0;
-		wildcard_size = 16;
-		
-		/* Handle empty address */
-		if (*cur == 0)
-			return EOK;
-	}
-	
-	while (i < 16) {
-		uint16_t bioctet;
-		int rc = str_uint16_t(cur, &cur, 16, false, &bioctet);
-		if (rc != EOK)
-			return rc;
-		
-		data[i] = (bioctet >> 8) & 0xff;
-		data[i + 1] = bioctet & 0xff;
-		
-		if (wildcard_pos != (size_t) -1) {
-			if (wildcard_size < 2)
-				return EINVAL;
-			
-			wildcard_size -= 2;
-		}
-		
-		i += 2;
-		
-		if (*cur == 0)
-			break;
-		
-		if (*cur != ':')
-			return EINVAL;
-		
-		if (i < 16) {
-			cur++;
-			
-			/* Handle wildcard */
-			if (*cur == ':') {
-				if (wildcard_pos != (size_t) -1)
-					return EINVAL;
-				
-				wildcard_pos = i;
-				wildcard_size = 16 - i;
-				cur++;
-				
-				if (*cur == 0)
-					break;
-			}
-		}
-	}
-	
-	if ((i == 16) && (*cur != 0))
-		return EINVAL;
-	
-	/* Create wildcard positions */
-	if ((wildcard_pos != (size_t) -1) && (wildcard_size > 0)) {
-		size_t wildcard_shift = 16 - wildcard_size;
-		
-		for (i = wildcard_pos + wildcard_shift; i > wildcard_pos; i--) {
-			size_t j = i - 1;
-			data[j + wildcard_size] = data[j];
-			data[j] = 0;
-		}
-	}
-	
-	return EOK;
-}
-
-/** Parses the character string into the address.
- *
- * @param[in]  family  The address family.
- * @param[in]  address The character buffer to be parsed.
- * @param[out] data    The address data to be filled.
- *
- * @return EOK on success.
- * @return EINVAL if the data parameter is NULL.
- * @return ENOENT if the address parameter is NULL.
- * @return ENOTSUP if the address family is not supported.
- *
- */
-int inet_pton(uint16_t family, const char *address, uint8_t *data)
-{
-	switch (family) {
-	case AF_INET:
-		return inet_pton4(address, data);
-	case AF_INET6:
-		return inet_pton6(address, data);
-	default:
-		/** Unknown address family */
-		return ENOTSUP;
-	}
-}
-
-/** @}
- */
Index: pace/lib/c/generic/net/socket_client.c
===================================================================
--- uspace/lib/c/generic/net/socket_client.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,1247 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- * Socket application program interface (API) implementation.
- * @see socket.h for more information.
- * This is a part of the network application library.
- */
-
-#include <assert.h>
-#include <async.h>
-#include <fibril_synch.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <task.h>
-#include <ns.h>
-#include <ipc/services.h>
-#include <ipc/socket.h>
-#include <net/in.h>
-#include <net/socket.h>
-#include <adt/dynamic_fifo.h>
-#include <adt/int_map.h>
-
-/** Initial received packet queue size. */
-#define SOCKET_INITIAL_RECEIVED_SIZE	4
-
-/** Maximum received packet queue size. */
-#define SOCKET_MAX_RECEIVED_SIZE	0
-
-/** Initial waiting sockets queue size. */
-#define SOCKET_INITIAL_ACCEPTED_SIZE	1
-
-/** Maximum waiting sockets queue size. */
-#define SOCKET_MAX_ACCEPTED_SIZE	0
-
-/**
- * Maximum number of random attempts to find a new socket identifier before
- * switching to the sequence.
- */
-#define SOCKET_ID_TRIES			100
-
-/** Type definition of the socket specific data.
- * @see socket
- */
-typedef struct socket socket_t;
-
-/** Socket specific data.
- *
- * Each socket lock locks only its structure part and any number of them may be
- * locked simultaneously.
- */
-struct socket {
-	/** Socket identifier. */
-	int socket_id;
-	/** Parent module session. */
-	async_sess_t *sess;
-	/** Parent module service. */
-	services_t service;
-	/** Socket family */
-	int family;
-
-	/**
-	 * Underlying protocol header size.
-	 * Sending and receiving optimalization.
-	 */
-	size_t header_size;
-
-	/** Packet data fragment size. Sending optimization. */
-	size_t data_fragment_size;
-
-	/**
-	 * Sending safety lock.
-	 * Locks the header_size and data_fragment_size attributes.
-	 */
-	fibril_rwlock_t sending_lock;
-
-	/** Received packets queue. */
-	dyn_fifo_t received;
-
-	/**
-	 * Received packets safety lock.
-	 * Used for receiving and receive notifications.
-	 * Locks the received attribute.
-	 */
-	fibril_mutex_t receive_lock;
-
-	/** Received packets signaling. Signaled upon receive notification. */
-	fibril_condvar_t receive_signal;
-	/** Waiting sockets queue. */
-	dyn_fifo_t accepted;
-
-	/**
-	 * Waiting sockets safety lock.
-	 * Used for accepting and accept notifications.
-	 * Locks the accepted attribute.
-	 */
-	fibril_mutex_t accept_lock;
-
-	/** Waiting sockets signaling. Signaled upon accept notification. */
-	fibril_condvar_t accept_signal;
-
-	/**
-	 * The number of blocked functions called.
-	 * Used while waiting for the received packets or accepted sockets.
-	 */
-	int blocked;
-};
-
-/** Sockets map.
- * Maps socket identifiers to the socket specific data.
- * @see int_map.h
- */
-INT_MAP_DECLARE(sockets, socket_t);
-
-/** Socket client library global data. */
-static struct socket_client_globals {
-	/** TCP module session. */
-	async_sess_t *tcp_sess;
-	/** UDP module session. */
-	async_sess_t *udp_sess;
-
-	/** Active sockets. */
-	sockets_t *sockets;
-
-	/** Safety lock.
-	 * Write lock is used only for adding or removing sockets.
-	 * When locked for writing, no other socket locks need to be locked.
-	 * When locked for reading, any other socket locks may be locked.
-	 * No socket lock may be locked if this lock is unlocked.
-	 */
-	fibril_rwlock_t lock;
-} socket_globals = {
-	.tcp_sess = NULL,
-	.udp_sess = NULL,
-	.sockets = NULL,
-	.lock = FIBRIL_RWLOCK_INITIALIZER(socket_globals.lock)
-};
-
-INT_MAP_IMPLEMENT(sockets, socket_t);
-
-/** Returns the active sockets.
- *
- *  @return		The active sockets.
- */
-static sockets_t *socket_get_sockets(void)
-{
-	if (!socket_globals.sockets) {
-		socket_globals.sockets =
-		    (sockets_t *) malloc(sizeof(sockets_t));
-		if (!socket_globals.sockets)
-			return NULL;
-
-		if (sockets_initialize(socket_globals.sockets) != EOK) {
-			free(socket_globals.sockets);
-			socket_globals.sockets = NULL;
-		}
-
-		srand(task_get_id());
-	}
-
-	return socket_globals.sockets;
-}
-
-/** Default thread for new connections.
- *
- * @param[in] iid   The initial message identifier.
- * @param[in] icall The initial message call structure.
- * @param[in] arg   Local argument.
- *
- */
-static void socket_connection(ipc_callid_t iid, ipc_call_t * icall, void *arg)
-{
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			async_answer_0(callid, 0);
-			return;
-		}
-		
-		int rc;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NET_SOCKET_RECEIVED:
-		case NET_SOCKET_ACCEPTED:
-		case NET_SOCKET_DATA_FRAGMENT_SIZE:
-			fibril_rwlock_read_lock(&socket_globals.lock);
-			
-			/* Find the socket */
-			socket_t *socket = sockets_find(socket_get_sockets(),
-			    SOCKET_GET_SOCKET_ID(call));
-			if (!socket) {
-				rc = ENOTSOCK;
-				fibril_rwlock_read_unlock(&socket_globals.lock);
-				break;
-			}
-			
-			switch (IPC_GET_IMETHOD(call)) {
-			case NET_SOCKET_RECEIVED:
-				fibril_mutex_lock(&socket->receive_lock);
-				/* Push the number of received packet fragments */
-				rc = dyn_fifo_push(&socket->received,
-				    SOCKET_GET_DATA_FRAGMENTS(call),
-				    SOCKET_MAX_RECEIVED_SIZE);
-				if (rc == EOK) {
-					/* Signal the received packet */
-					fibril_condvar_signal(&socket->receive_signal);
-				}
-				fibril_mutex_unlock(&socket->receive_lock);
-				break;
-				
-			case NET_SOCKET_ACCEPTED:
-				/* Push the new socket identifier */
-				fibril_mutex_lock(&socket->accept_lock);
-				rc = dyn_fifo_push(&socket->accepted, 1,
-				    SOCKET_MAX_ACCEPTED_SIZE);
-				if (rc == EOK) {
-					/* Signal the accepted socket */
-					fibril_condvar_signal(&socket->accept_signal);
-				}
-				fibril_mutex_unlock(&socket->accept_lock);
-				break;
-			
-			default:
-				rc = ENOTSUP;
-			}
-			
-			if ((SOCKET_GET_DATA_FRAGMENT_SIZE(call) > 0) &&
-			    (SOCKET_GET_DATA_FRAGMENT_SIZE(call) !=
-			    socket->data_fragment_size)) {
-				fibril_rwlock_write_lock(&socket->sending_lock);
-				
-				/* Set the data fragment size */
-				socket->data_fragment_size =
-				    SOCKET_GET_DATA_FRAGMENT_SIZE(call);
-				
-				fibril_rwlock_write_unlock(&socket->sending_lock);
-			}
-			
-			fibril_rwlock_read_unlock(&socket_globals.lock);
-			break;
-			
-		default:
-			rc = ENOTSUP;
-		}
-		
-		async_answer_0(callid, (sysarg_t) rc);
-	}
-}
-
-/** Return the TCP module session.
- *
- * Connect to the TCP module if necessary.
- *
- * @return The TCP module session.
- *
- */
-static async_sess_t *socket_get_tcp_sess(void)
-{
-	if (socket_globals.tcp_sess == NULL)
-		socket_globals.tcp_sess = service_bind(SERVICE_TCP,
-		    0, 0, SERVICE_TCP, socket_connection);
-	
-	return socket_globals.tcp_sess;
-}
-
-/** Return the UDP module session.
- *
- * Connect to the UDP module if necessary.
- *
- * @return The UDP module session.
- *
- */
-static async_sess_t *socket_get_udp_sess(void)
-{
-	if (socket_globals.udp_sess == NULL)
-		socket_globals.udp_sess = service_bind(SERVICE_UDP,
-		    0, 0, SERVICE_UDP, socket_connection);
-	
-	return socket_globals.udp_sess;
-}
-
-/** Tries to find a new free socket identifier.
- *
- * @return		The new socket identifier.
- * @return		ELIMIT if there is no socket identifier available.
- */
-static int socket_generate_new_id(void)
-{
-	sockets_t *sockets;
-	int socket_id = 0;
-	int count;
-
-	sockets = socket_get_sockets();
-	count = 0;
-
-	do {
-		if (count < SOCKET_ID_TRIES) {
-			socket_id = rand() % INT_MAX;
-			++count;
-		} else if (count == SOCKET_ID_TRIES) {
-			socket_id = 1;
-			++count;
-		/* Only this branch for last_id */
-		} else {
-			if (socket_id < INT_MAX) {
-				++socket_id;
-			} else {
-				return ELIMIT;
-			}
-		}
-	} while (sockets_find(sockets, socket_id));
-	
-	return socket_id;
-}
-
-/** Initializes a new socket specific data.
- *
- * @param[in,out] socket The socket to be initialized.
- * @param[in] socket_id  The new socket identifier.
- * @param[in] sess       The parent module session.
- * @param[in] service    The parent module service.
- */
-static void socket_initialize(socket_t *socket, int socket_id,
-    async_sess_t *sess, services_t service)
-{
-	socket->socket_id = socket_id;
-	socket->sess = sess;
-	socket->service = service;
-	dyn_fifo_initialize(&socket->received, SOCKET_INITIAL_RECEIVED_SIZE);
-	dyn_fifo_initialize(&socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE);
-	fibril_mutex_initialize(&socket->receive_lock);
-	fibril_condvar_initialize(&socket->receive_signal);
-	fibril_mutex_initialize(&socket->accept_lock);
-	fibril_condvar_initialize(&socket->accept_signal);
-	fibril_rwlock_initialize(&socket->sending_lock);
-}
-
-/** Creates a new socket.
- *
- * @param[in] domain	The socket protocol family.
- * @param[in] type	Socket type.
- * @param[in] protocol	Socket protocol.
- * @return		The socket identifier on success.
- * @return		EPFNOTSUPPORT if the protocol family is not supported.
- * @return		ESOCKNOTSUPPORT if the socket type is not supported.
- * @return		EPROTONOSUPPORT if the protocol is not supported.
- * @return		ENOMEM if there is not enough memory left.
- * @return		ELIMIT if there was not a free socket identifier found
- *			this time.
- * @return		Other error codes as defined for the NET_SOCKET message.
- * @return		Other error codes as defined for the
- *			service_bind() function.
- */
-int socket(int domain, int type, int protocol)
-{
-	socket_t *socket;
-	async_sess_t *sess;
-	int socket_id;
-	services_t service;
-	sysarg_t fragment_size;
-	sysarg_t header_size;
-	int rc;
-
-	/* Find the appropriate service */
-	switch (domain) {
-	case PF_INET:
-	case PF_INET6:
-		switch (type) {
-		case SOCK_STREAM:
-			if (!protocol)
-				protocol = IPPROTO_TCP;
-
-			switch (protocol) {
-			case IPPROTO_TCP:
-				sess = socket_get_tcp_sess();
-				service = SERVICE_TCP;
-				break;
-			default:
-				return EPROTONOSUPPORT;
-			}
-
-			break;
-
-		case SOCK_DGRAM:
-			if (!protocol)
-				protocol = IPPROTO_UDP;
-
-			switch (protocol) {
-			case IPPROTO_UDP:
-				sess = socket_get_udp_sess();
-				service = SERVICE_UDP;
-				break;
-			default:
-				return EPROTONOSUPPORT;
-			}
-
-			break;
-
-		case SOCK_RAW:
-		default:
-			return ESOCKTNOSUPPORT;
-		}
-
-		break;
-
-	default:
-		return EPFNOSUPPORT;
-	}
-
-	if (sess == NULL)
-		return ENOENT;
-
-	/* Create a new socket structure */
-	socket = (socket_t *) malloc(sizeof(socket_t));
-	if (!socket)
-		return ENOMEM;
-
-	memset(socket, 0, sizeof(*socket));
-	socket->family = domain;
-	fibril_rwlock_write_lock(&socket_globals.lock);
-
-	/* Request a new socket */
-	socket_id = socket_generate_new_id();
-	if (socket_id <= 0) {
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		free(socket);
-		return socket_id;
-	}
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	rc = (int) async_req_3_3(exch, NET_SOCKET, socket_id, 0, service, NULL,
-	    &fragment_size, &header_size);
-	async_exchange_end(exch);
-	
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		free(socket);
-		return rc;
-	}
-
-	socket->data_fragment_size = (size_t) fragment_size;
-	socket->header_size = (size_t) header_size;
-
-	/* Finish the new socket initialization */
-	socket_initialize(socket, socket_id, sess, service);
-	/* Store the new socket */
-	rc = sockets_add(socket_get_sockets(), socket_id, socket);
-
-	fibril_rwlock_write_unlock(&socket_globals.lock);
-	if (rc < 0) {
-		dyn_fifo_destroy(&socket->received);
-		dyn_fifo_destroy(&socket->accepted);
-		free(socket);
-		
-		exch = async_exchange_begin(sess);
-		async_msg_3(exch, NET_SOCKET_CLOSE, (sysarg_t) socket_id, 0,
-		    service);
-		async_exchange_end(exch);
-		
-		return rc;
-	}
-
-	return socket_id;
-}
-
-/** Sends message to the socket parent module with specified data.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[in] message	The action message.
- * @param[in] arg2	The second message parameter.
- * @param[in] data	The data to be sent.
- * @param[in] datalength The data length.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the data parameter is NULL.
- * @return		NO_DATA if the datalength parameter is zero (0).
- * @return		Other error codes as defined for the spcific message.
- */
-static int
-socket_send_data(int socket_id, sysarg_t message, sysarg_t arg2,
-    const void *data, size_t datalength)
-{
-	socket_t *socket;
-	aid_t message_id;
-	sysarg_t result;
-
-	if (!data)
-		return EBADMEM;
-
-	if (!datalength)
-		return NO_DATA;
-
-	fibril_rwlock_read_lock(&socket_globals.lock);
-
-	/* Find the socket */
-	socket = sockets_find(socket_get_sockets(), socket_id);
-	if (!socket) {
-		fibril_rwlock_read_unlock(&socket_globals.lock);
-		return ENOTSOCK;
-	}
-
-	/* Request the message */
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-	message_id = async_send_3(exch, message,
-	    (sysarg_t) socket->socket_id, arg2, socket->service, NULL);
-	/* Send the address */
-	async_data_write_start(exch, data, datalength);
-	async_exchange_end(exch);
-
-	fibril_rwlock_read_unlock(&socket_globals.lock);
-	async_wait_for(message_id, &result);
-	return (int) result;
-}
-
-/** Binds the socket to a port address.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[in] my_addr	The port address.
- * @param[in] addrlen	The address length.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the my_addr parameter is NULL.
- * @return		NO_DATA if the addlen parameter is zero.
- * @return		Other error codes as defined for the NET_SOCKET_BIND
- *			message.
- */
-int bind(int socket_id, const struct sockaddr * my_addr, socklen_t addrlen)
-{
-	if (addrlen <= 0)
-		return EINVAL;
-
-	/* Send the address */
-	return socket_send_data(socket_id, NET_SOCKET_BIND, 0, my_addr,
-	    (size_t) addrlen);
-}
-
-/** Sets the number of connections waiting to be accepted.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[in] backlog	The maximum number of waiting sockets to be accepted.
- * @return		EOK on success.
- * @return		EINVAL if the backlog parameter is not positive (<=0).
- * @return		ENOTSOCK if the socket is not found.
- * @return		Other error codes as defined for the NET_SOCKET_LISTEN
- *			message.
- */
-int listen(int socket_id, int backlog)
-{
-	socket_t *socket;
-	int result;
-
-	if (backlog <= 0)
-		return EINVAL;
-
-	fibril_rwlock_read_lock(&socket_globals.lock);
-
-	/* Find the socket */
-	socket = sockets_find(socket_get_sockets(), socket_id);
-	if (!socket) {
-		fibril_rwlock_read_unlock(&socket_globals.lock);
-		return ENOTSOCK;
-	}
-
-	/* Request listen backlog change */
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-	result = (int) async_req_3_0(exch, NET_SOCKET_LISTEN,
-	    (sysarg_t) socket->socket_id, (sysarg_t) backlog, socket->service);
-	async_exchange_end(exch);
-
-	fibril_rwlock_read_unlock(&socket_globals.lock);
-	return result;
-}
-
-/** Accepts waiting socket.
- *
- * Blocks until such a socket exists.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[out] cliaddr	The remote client address.
- * @param[in] addrlen	The address length.
- * @return		EOK on success.
- * @return		EBADMEM if the cliaddr or addrlen parameter is NULL.
- * @return		EINVAL if the backlog parameter is not positive (<=0).
- * @return		ENOTSOCK if the socket is not found.
- * @return		Other error codes as defined for the NET_SOCKET_ACCEPT
- *			message.
- */
-int accept(int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen)
-{
-	socket_t *socket;
-	socket_t *new_socket;
-	aid_t message_id;
-	sysarg_t ipc_result;
-	int result;
-	ipc_call_t answer;
-
-	if (!cliaddr || !addrlen)
-		return EBADMEM;
-
-	fibril_rwlock_write_lock(&socket_globals.lock);
-
-	/* Find the socket */
-	socket = sockets_find(socket_get_sockets(), socket_id);
-	if (!socket) {
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		return ENOTSOCK;
-	}
-
-	fibril_mutex_lock(&socket->accept_lock);
-
-	/* Wait for an accepted socket */
-	++ socket->blocked;
-	while (dyn_fifo_value(&socket->accepted) <= 0) {
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		fibril_condvar_wait(&socket->accept_signal, &socket->accept_lock);
-		/* Drop the accept lock to avoid deadlock */
-		fibril_mutex_unlock(&socket->accept_lock);
-		fibril_rwlock_write_lock(&socket_globals.lock);
-		fibril_mutex_lock(&socket->accept_lock);
-	}
-	-- socket->blocked;
-
-	/* Create a new socket */
-	new_socket = (socket_t *) malloc(sizeof(socket_t));
-	if (!new_socket) {
-		fibril_mutex_unlock(&socket->accept_lock);
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		return ENOMEM;
-	}
-	memset(new_socket, 0, sizeof(*new_socket));
-	socket_id = socket_generate_new_id();
-	if (socket_id <= 0) {
-		fibril_mutex_unlock(&socket->accept_lock);
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		free(new_socket);
-		return socket_id;
-	}
-	socket_initialize(new_socket, socket_id, socket->sess,
-	    socket->service);
-	result = sockets_add(socket_get_sockets(), new_socket->socket_id,
-	    new_socket);
-	if (result < 0) {
-		fibril_mutex_unlock(&socket->accept_lock);
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		free(new_socket);
-		return result;
-	}
-
-	/* Request accept */
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-	message_id = async_send_5(exch, NET_SOCKET_ACCEPT,
-	    (sysarg_t) socket->socket_id, 0, socket->service, 0,
-	    new_socket->socket_id, &answer);
-
-	/* Read address */
-	async_data_read_start(exch, cliaddr, *addrlen);
-	async_exchange_end(exch);
-	
-	fibril_rwlock_write_unlock(&socket_globals.lock);
-	async_wait_for(message_id, &ipc_result);
-	result = (int) ipc_result;
-	if (result > 0) {
-		if (result != socket_id)
-			result = EINVAL;
-
-		/* Dequeue the accepted socket if successful */
-		dyn_fifo_pop(&socket->accepted);
-		/* Set address length */
-		*addrlen = SOCKET_GET_ADDRESS_LENGTH(answer);
-		new_socket->data_fragment_size =
-		    SOCKET_GET_DATA_FRAGMENT_SIZE(answer);
-	} else if (result == ENOTSOCK) {
-		/* Empty the queue if no accepted sockets */
-		while (dyn_fifo_pop(&socket->accepted) > 0)
-			;
-	}
-
-	fibril_mutex_unlock(&socket->accept_lock);
-	return result;
-}
-
-/** Connects socket to the remote server.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[in] serv_addr	The remote server address.
- * @param[in] addrlen	The address length.
- * @return		EOK on success.
- * @return		EBADMEM if the serv_addr parameter is NULL.
- * @return		NO_DATA if the addlen parameter is zero.
- * @return		ENOTSOCK if the socket is not found.
- * @return		Other error codes as defined for the NET_SOCKET_CONNECT
- *			message.
- */
-int connect(int socket_id, const struct sockaddr *serv_addr, socklen_t addrlen)
-{
-	if (!serv_addr)
-		return EDESTADDRREQ;
-
-	if (!addrlen)
-		return EDESTADDRREQ;
-
-	/* Send the address */
-	return socket_send_data(socket_id, NET_SOCKET_CONNECT, 0, serv_addr,
-	    addrlen);
-}
-
-/** Clears and destroys the socket.
- *
- * @param[in] socket	The socket to be destroyed.
- */
-static void socket_destroy(socket_t *socket)
-{
-	int accepted_id;
-
-	/* Destroy all accepted sockets */
-	while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0)
-		socket_destroy(sockets_find(socket_get_sockets(), accepted_id));
-
-	dyn_fifo_destroy(&socket->received);
-	dyn_fifo_destroy(&socket->accepted);
-	sockets_exclude(socket_get_sockets(), socket->socket_id, free);
-}
-
-/** Closes the socket.
- *
- * @param[in] socket_id	Socket identifier.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EINPROGRESS if there is another blocking function in
- *			progress.
- * @return		Other error codes as defined for the NET_SOCKET_CLOSE
- *			message.
- */
-int closesocket(int socket_id)
-{
-	socket_t *socket;
-	int rc;
-
-	fibril_rwlock_write_lock(&socket_globals.lock);
-
-	socket = sockets_find(socket_get_sockets(), socket_id);
-	if (!socket) {
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		return ENOTSOCK;
-	}
-	if (socket->blocked) {
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		return EINPROGRESS;
-	}
-
-	/* Request close */
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-	rc = (int) async_req_3_0(exch, NET_SOCKET_CLOSE,
-	    (sysarg_t) socket->socket_id, 0, socket->service);
-	async_exchange_end(exch);
-	
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&socket_globals.lock);
-		return rc;
-	}
-	/* Free the socket structure */
-	socket_destroy(socket);
-
-	fibril_rwlock_write_unlock(&socket_globals.lock);
-	return EOK;
-}
-
-/** Sends data via the socket to the remote address.
- *
- * Binds the socket to a free port if not already connected/bound.
- *
- * @param[in] message	The action message.
- * @param[in] socket_id Socket identifier.
- * @param[in] data	The data to be sent.
- * @param[in] datalength The data length.
- * @param[in] flags	Various send flags.
- * @param[in] toaddr	The destination address. May be NULL for connected
- *			sockets.
- * @param[in] addrlen	The address length. Used only if toaddr is not NULL.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the data or toaddr parameter is NULL.
- * @return		NO_DATA if the datalength or the addrlen parameter is
- *			zero (0).
- * @return		Other error codes as defined for the NET_SOCKET_SENDTO
- *			message.
- */
-static int
-sendto_core(sysarg_t message, int socket_id, const void *data,
-    size_t datalength, int flags, const struct sockaddr *toaddr,
-    socklen_t addrlen)
-{
-	socket_t *socket;
-	aid_t message_id;
-	sysarg_t result;
-	size_t fragments;
-	ipc_call_t answer;
-
-	if (!data)
-		return EBADMEM;
-
-	if (!datalength)
-		return NO_DATA;
-
-	fibril_rwlock_read_lock(&socket_globals.lock);
-
-	/* Find socket */
-	socket = sockets_find(socket_get_sockets(), socket_id);
-	if (!socket) {
-		fibril_rwlock_read_unlock(&socket_globals.lock);
-		return ENOTSOCK;
-	}
-
-	fibril_rwlock_read_lock(&socket->sending_lock);
-
-	/* Compute data fragment count */
-	if (socket->data_fragment_size > 0) {
-		fragments = (datalength + socket->header_size) /
-		    socket->data_fragment_size;
-		if ((datalength + socket->header_size) %
-		    socket->data_fragment_size)
-			++fragments;
-	} else {
-		fragments = 1;
-	}
-
-	/* Request send */
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-	
-	message_id = async_send_5(exch, message,
-	    (sysarg_t) socket->socket_id,
-	    (fragments == 1 ? datalength : socket->data_fragment_size),
-	    socket->service, (sysarg_t) flags, fragments, &answer);
-
-	/* Send the address if given */
-	if (!toaddr ||
-	    (async_data_write_start(exch, toaddr, addrlen) == EOK)) {
-		if (fragments == 1) {
-			/* Send all if only one fragment */
-			async_data_write_start(exch, data, datalength);
-		} else {
-			/* Send the first fragment */
-			async_data_write_start(exch, data,
-			    socket->data_fragment_size - socket->header_size);
-			data = ((const uint8_t *) data) +
-			    socket->data_fragment_size - socket->header_size;
-	
-			/* Send the middle fragments */
-			while (--fragments > 1) {
-				async_data_write_start(exch, data,
-				    socket->data_fragment_size);
-				data = ((const uint8_t *) data) +
-				    socket->data_fragment_size;
-			}
-
-			/* Send the last fragment */
-			async_data_write_start(exch, data,
-			    (datalength + socket->header_size) %
-			    socket->data_fragment_size);
-		}
-	}
-	
-	async_exchange_end(exch);
-
-	async_wait_for(message_id, &result);
-
-	if ((SOCKET_GET_DATA_FRAGMENT_SIZE(answer) > 0) &&
-	    (SOCKET_GET_DATA_FRAGMENT_SIZE(answer) !=
-	    socket->data_fragment_size)) {
-		/* Set the data fragment size */
-		socket->data_fragment_size =
-		    SOCKET_GET_DATA_FRAGMENT_SIZE(answer);
-	}
-
-	fibril_rwlock_read_unlock(&socket->sending_lock);
-	fibril_rwlock_read_unlock(&socket_globals.lock);
-	return (int) result;
-}
-
-/** Sends data via the socket.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[in] data	The data to be sent.
- * @param[in] datalength The data length.
- * @param[in] flags	Various send flags.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the data parameter is NULL.
- * @return		NO_DATA if the datalength parameter is zero.
- * @return		Other error codes as defined for the NET_SOCKET_SEND
- *			message.
- */
-int send(int socket_id, const void *data, size_t datalength, int flags)
-{
-	/* Without the address */
-	return sendto_core(NET_SOCKET_SEND, socket_id, data, datalength, flags,
-	    NULL, 0);
-}
-
-/** Sends data via the socket to the remote address.
- *
- * Binds the socket to a free port if not already connected/bound.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[in] data	The data to be sent.
- * @param[in] datalength The data length.
- * @param[in] flags	Various send flags.
- * @param[in] toaddr	The destination address.
- * @param[in] addrlen	The address length.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the data or toaddr parameter is NULL.
- * @return		NO_DATA if the datalength or the addrlen parameter is
- *			zero.
- * @return		Other error codes as defined for the NET_SOCKET_SENDTO
- *			message.
- */
-int
-sendto(int socket_id, const void *data, size_t datalength, int flags,
-    const struct sockaddr *toaddr, socklen_t addrlen)
-{
-	if (!toaddr)
-		return EDESTADDRREQ;
-
-	if (!addrlen)
-		return EDESTADDRREQ;
-
-	/* With the address */
-	return sendto_core(NET_SOCKET_SENDTO, socket_id, data, datalength,
-	    flags, toaddr, addrlen);
-}
-
-/** Receives data via the socket.
- *
- * @param[in] message	The action message.
- * @param[in] socket_id	Socket identifier.
- * @param[out] data	The data buffer to be filled.
- * @param[in] datalength The data length.
- * @param[in] flags	Various receive flags.
- * @param[out] fromaddr	The source address. May be NULL for connected sockets.
- * @param[in,out] addrlen The address length. The maximum address length is
- *			read. The actual address length is set. Used only if
- *			fromaddr is not NULL.
- * @return		Positive received message size in bytes on success.
- * @return		Zero if no more data (other side closed the connection).
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the data parameter is NULL.
- * @return		NO_DATA if the datalength or addrlen parameter is zero.
- * @return		Other error codes as defined for the spcific message.
- */
-static ssize_t
-recvfrom_core(sysarg_t message, int socket_id, void *data, size_t datalength,
-    int flags, struct sockaddr *fromaddr, socklen_t *addrlen)
-{
-	socket_t *socket;
-	aid_t message_id;
-	sysarg_t ipc_result;
-	int result;
-	size_t fragments;
-	size_t *lengths;
-	size_t index;
-	ipc_call_t answer;
-	ssize_t retval;
-
-	if (!data)
-		return EBADMEM;
-
-	if (!datalength)
-		return NO_DATA;
-
-	if (fromaddr && !addrlen)
-		return EINVAL;
-
-	fibril_rwlock_read_lock(&socket_globals.lock);
-
-	/* Find the socket */
-	socket = sockets_find(socket_get_sockets(), socket_id);
-	if (!socket) {
-		fibril_rwlock_read_unlock(&socket_globals.lock);
-		return ENOTSOCK;
-	}
-
-	fibril_mutex_lock(&socket->receive_lock);
-	/* Wait for a received packet */
-	++socket->blocked;
-	while ((result = dyn_fifo_value(&socket->received)) < 0) {
-		fibril_rwlock_read_unlock(&socket_globals.lock);
-		fibril_condvar_wait(&socket->receive_signal,
-		    &socket->receive_lock);
-
-		/* Drop the receive lock to avoid deadlock */
-		fibril_mutex_unlock(&socket->receive_lock);
-		fibril_rwlock_read_lock(&socket_globals.lock);
-		fibril_mutex_lock(&socket->receive_lock);
-	}
-	--socket->blocked;
-	fragments = (size_t) result;
-
-	if (fragments == 0) {
-		/* No more data, other side has closed the connection. */
-		fibril_mutex_unlock(&socket->receive_lock);
-		fibril_rwlock_read_unlock(&socket_globals.lock);
-		return 0;
-	}
-	
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-
-	/* Prepare lengths if more fragments */
-	if (fragments > 1) {
-		lengths = (size_t *) malloc(sizeof(size_t) * fragments +
-		    sizeof(size_t));
-		if (!lengths) {
-			fibril_mutex_unlock(&socket->receive_lock);
-			fibril_rwlock_read_unlock(&socket_globals.lock);
-			return ENOMEM;
-		}
-
-		/* Request packet data */
-		message_id = async_send_4(exch, message,
-		    (sysarg_t) socket->socket_id, 0, socket->service,
-		    (sysarg_t) flags, &answer);
-
-		/* Read the address if desired */
-		if(!fromaddr ||
-		    (async_data_read_start(exch, fromaddr,
-		    *addrlen) == EOK)) {
-			/* Read the fragment lengths */
-			if (async_data_read_start(exch, lengths,
-			    sizeof(int) * (fragments + 1)) == EOK) {
-				if (lengths[fragments] <= datalength) {
-
-					/* Read all fragments if long enough */
-					for (index = 0; index < fragments;
-					    ++index) {
-						async_data_read_start(exch, data,
-						    lengths[index]);
-						data = ((uint8_t *) data) +
-						    lengths[index];
-					}
-				}
-			}
-		}
-
-		free(lengths);
-	} else { /* fragments == 1 */
-		/* Request packet data */
-		message_id = async_send_4(exch, message,
-		    (sysarg_t) socket->socket_id, 0, socket->service,
-		    (sysarg_t) flags, &answer);
-
-		/* Read the address if desired */
-		if (!fromaddr ||
-		    (async_data_read_start(exch, fromaddr, *addrlen) == EOK)) {
-			/* Read all if only one fragment */
-			async_data_read_start(exch, data, datalength);
-		}
-	}
-	
-	async_exchange_end(exch);
-
-	async_wait_for(message_id, &ipc_result);
-	result = (int) ipc_result;
-	if (result == EOK) {
-		/* Dequeue the received packet */
-		dyn_fifo_pop(&socket->received);
-		/* Return read data length */
-		retval = SOCKET_GET_READ_DATA_LENGTH(answer);
-		/* Set address length */
-		if (fromaddr && addrlen)
-			*addrlen = SOCKET_GET_ADDRESS_LENGTH(answer);
-	} else {
-		retval = (ssize_t) result;
-	}
-
-	fibril_mutex_unlock(&socket->receive_lock);
-	fibril_rwlock_read_unlock(&socket_globals.lock);
-	return retval;
-}
-
-/** Receives data via the socket.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[out] data	The data buffer to be filled.
- * @param[in] datalength The data length.
- * @param[in] flags	Various receive flags.
- * @return		Positive received message size in bytes on success.
- * @return		Zero if no more data (other side closed the connection).
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the data parameter is NULL.
- * @return		NO_DATA if the datalength parameter is zero.
- * @return		Other error codes as defined for the NET_SOCKET_RECV
- *			message.
- */
-ssize_t recv(int socket_id, void *data, size_t datalength, int flags)
-{
-	/* Without the address */
-	return recvfrom_core(NET_SOCKET_RECV, socket_id, data, datalength,
-	    flags, NULL, NULL);
-}
-
-/** Receives data via the socket.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[out] data	The data buffer to be filled.
- * @param[in] datalength The data length.
- * @param[in] flags	Various receive flags.
- * @param[out] fromaddr	The source address.
- * @param[in,out] addrlen The address length. The maximum address length is
- *			read. The actual address length is set.
- * @return		Positive received message size in bytes on success.
- * @return		Zero if no more data (other side closed the connection).
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the data or fromaddr parameter is NULL.
- * @return		NO_DATA if the datalength or addrlen parameter is zero.
- * @return		Other error codes as defined for the NET_SOCKET_RECVFROM
- *			message.
- */
-ssize_t
-recvfrom(int socket_id, void *data, size_t datalength, int flags,
-    struct sockaddr *fromaddr, socklen_t *addrlen)
-{
-	if (!fromaddr)
-		return EBADMEM;
-
-	if (!addrlen)
-		return NO_DATA;
-
-	/* With the address */
-	return recvfrom_core(NET_SOCKET_RECVFROM, socket_id, data, datalength,
-	    flags, fromaddr, addrlen);
-}
-
-/** Gets socket option.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[in] level	The socket options level.
- * @param[in] optname	The socket option to be get.
- * @param[out] value	The value buffer to be filled.
- * @param[in,out] optlen The value buffer length. The maximum length is read.
- *			The actual length is set.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the value or optlen parameter is NULL.
- * @return		NO_DATA if the optlen parameter is zero.
- * @return		Other error codes as defined for the
- *			NET_SOCKET_GETSOCKOPT message.
- */
-int
-getsockopt(int socket_id, int level, int optname, void *value, size_t *optlen)
-{
-	socket_t *socket;
-	aid_t message_id;
-	sysarg_t result;
-
-	if (!value || !optlen)
-		return EBADMEM;
-
-	if (!*optlen)
-		return NO_DATA;
-
-	fibril_rwlock_read_lock(&socket_globals.lock);
-
-	/* Find the socket */
-	socket = sockets_find(socket_get_sockets(), socket_id);
-	if (!socket) {
-		fibril_rwlock_read_unlock(&socket_globals.lock);
-		return ENOTSOCK;
-	}
-
-	/* Request option value */
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-	
-	message_id = async_send_3(exch, NET_SOCKET_GETSOCKOPT,
-	    (sysarg_t) socket->socket_id, (sysarg_t) optname, socket->service,
-	    NULL);
-
-	/* Read the length */
-	if (async_data_read_start(exch, optlen,
-	    sizeof(*optlen)) == EOK) {
-		/* Read the value */
-		async_data_read_start(exch, value, *optlen);
-	}
-	
-	async_exchange_end(exch);
-
-	fibril_rwlock_read_unlock(&socket_globals.lock);
-	async_wait_for(message_id, &result);
-	return (int) result;
-}
-
-/** Sets socket option.
- *
- * @param[in] socket_id	Socket identifier.
- * @param[in] level	The socket options level.
- * @param[in] optname	The socket option to be set.
- * @param[in] value	The value to be set.
- * @param[in] optlen	The value length.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EBADMEM if the value parameter is NULL.
- * @return		NO_DATA if the optlen parameter is zero.
- * @return		Other error codes as defined for the
- *			NET_SOCKET_SETSOCKOPT message.
- */
-int
-setsockopt(int socket_id, int level, int optname, const void *value,
-    size_t optlen)
-{
-	/* Send the value */
-	return socket_send_data(socket_id, NET_SOCKET_SETSOCKOPT,
-	    (sysarg_t) optname, value, optlen);
-}
-
-/** @}
- */
Index: pace/lib/c/generic/net/socket_parse.c
===================================================================
--- uspace/lib/c/generic/net/socket_parse.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,122 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 socket
- * @{
- */
-
-/** @file
- * Command-line argument parsing functions related to networking.
- */
-
-#include <net/socket_parse.h>
-#include <net/socket.h>
-#include <arg_parse.h>
-#include <errno.h>
-#include <str.h>
-
-/** Translate the character string to the address family number.
- *
- * @param[in]  name The address family name.
- * @param[out] af   The corresponding address family number
- *                  or EAFNOSUPPORTED.
- *
- * @return EOK on success.
- * @return ENOTSUP on unsupported address family.
- *
- */
-int socket_parse_address_family(const char *name, int *af)
-{
-	if (str_lcmp(name, "AF_INET6", 8) == 0) {
-		*af = AF_INET6;
-		return EOK;
-	}
-	
-	if (str_lcmp(name, "AF_INET", 7) == 0) {
-		*af = AF_INET;
-		return EOK;
-	}
-	
-	*af = EAFNOSUPPORT;
-	return ENOTSUP;
-}
-
-/** Translate the character string to the protocol family number.
- *
- * @param[in]  name The protocol family name.
- * @param[out] pf   The corresponding protocol family number
- *                  or EPFNOSUPPORTED.
- *
- * @return EOK on success.
- * @return ENOTSUP on unsupported protocol family.
- *
- */
-int socket_parse_protocol_family(const char *name, int *pf)
-{
-	if (str_lcmp(name, "PF_INET6", 8) == 0) {
-		*pf = PF_INET6;
-		return EOK;
-	}
-
-	if (str_lcmp(name, "PF_INET", 7) == 0) {
-		*pf = PF_INET;
-		return EOK;
-	}
-	
-	*pf = EPFNOSUPPORT;
-	return ENOTSUP;
-}
-
-/** Translate the character string to the socket type number.
- *
- * @param[in]  name  The socket type name.
- * @param[out] sockt The corresponding socket type number
- *                   or ESOCKTNOSUPPORT.
- *
- * @return EOK on success.
- * @return ENOTSUP on unsupported socket type.
- *
- */
-int socket_parse_socket_type(const char *name, int *sockt)
-{
-	if (str_lcmp(name, "SOCK_DGRAM", 11) == 0) {
-		*sockt = SOCK_DGRAM;
-		return EOK;
-	}
-	
-	if (str_lcmp(name, "SOCK_STREAM", 12) == 0) {
-		*sockt = SOCK_STREAM;
-		return EOK;
-	}
-	
-	*sockt = ESOCKTNOSUPPORT;
-	return ENOTSUP;
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/thread.c
===================================================================
--- uspace/lib/c/generic/thread.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/generic/thread.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -88,5 +88,5 @@
 #endif
 	
-	fibril_teardown(fibril);
+	fibril_teardown(fibril, false);
 	
 	thread_exit(0);
Index: pace/lib/c/include/adt/char_map.h
===================================================================
--- uspace/lib/c/include/adt/char_map.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,81 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  Character string to integer map.
- */
-
-#ifndef LIBC_CHAR_MAP_H_
-#define LIBC_CHAR_MAP_H_
-
-#include <libarch/types.h>
-
-/** Invalid assigned value used also if an&nbsp;entry does not exist. */
-#define CHAR_MAP_NULL  (-1)
-
-/** Type definition of the character string to integer map.
- *  @see char_map
- */
-typedef struct char_map char_map_t;
-
-/** Character string to integer map item.
- *
- * This structure recursivelly contains itself as a character by character tree.
- * The actually mapped character string consists of all the parent characters
- * and the actual one.
- */
-struct char_map {
-	/** Actually mapped character. */
-	uint8_t c;
-	/** Stored integral value. */
-	int value;
-	/** Next character array size. */
-	int size;
-	/** First free position in the next character array. */
-	int next;
-	/** Next character array. */
-	char_map_t **items;
-	/** Consistency check magic value. */
-	int magic;
-};
-
-extern int char_map_initialize(char_map_t *);
-extern void char_map_destroy(char_map_t *);
-extern int char_map_exclude(char_map_t *, const uint8_t *, size_t);
-extern int char_map_add(char_map_t *, const uint8_t *, size_t, const int);
-extern int char_map_find(const char_map_t *, const uint8_t *, size_t);
-extern int char_map_update(char_map_t *, const uint8_t *, size_t, const int);
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/adt/dynamic_fifo.h
===================================================================
--- uspace/lib/c/include/adt/dynamic_fifo.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- * Dynamic first in first out positive integer queue.
- * Possitive integer values only.
- */
-
-#ifndef LIBC_DYNAMIC_FIFO_H_
-#define LIBC_DYNAMIC_FIFO_H_
-
-/** Type definition of the dynamic fifo queue.
- * @see dyn_fifo
- */
-typedef struct dyn_fifo	dyn_fifo_t;
-
-/** Dynamic first in first out positive integer queue.
- * Possitive integer values only.
- * The queue automatically resizes if needed.
- */
-struct dyn_fifo {
-	/** Stored item field. */
-	int *items;
-	/** Actual field size. */
-	int size;
-	/** First item in the queue index. */
-	int head;
-	/** Last item in the queue index. */
-	int tail;
-	/** Consistency check magic value. */
-	int magic_value;
-};
-
-extern int dyn_fifo_initialize(dyn_fifo_t *, int);
-extern int dyn_fifo_destroy(dyn_fifo_t *);
-extern int dyn_fifo_push(dyn_fifo_t *, int, int);
-extern int dyn_fifo_pop(dyn_fifo_t *);
-extern int dyn_fifo_value(dyn_fifo_t *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/adt/generic_char_map.h
===================================================================
--- uspace/lib/c/include/adt/generic_char_map.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,163 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  Character string to generic type map.
- */
-
-#ifndef LIBC_GENERIC_CHAR_MAP_H_
-#define LIBC_GENERIC_CHAR_MAP_H_
-
-#include <unistd.h>
-#include <errno.h>
-
-#include <adt/char_map.h>
-#include <adt/generic_field.h>
-
-/** Internal magic value for a&nbsp;map consistency check. */
-#define GENERIC_CHAR_MAP_MAGIC_VALUE	0x12345622
-
-/** Generic destructor function pointer. */
-#define DTOR_T(identifier) \
-	void (*identifier)(const void *)
-
-/** Character string to generic type map declaration.
- *  @param[in] name	Name of the map.
- *  @param[in] type	Inner object type.
- */
-#define GENERIC_CHAR_MAP_DECLARE(name, type) \
-	GENERIC_FIELD_DECLARE(name##_items, type) \
-	\
-	typedef	struct name name##_t; \
-	\
-	struct	name { \
-		char_map_t names; \
-		name##_items_t values; \
-		int magic; \
-	}; \
-	\
-	int name##_add(name##_t *, const uint8_t *, const size_t, type *); \
-	int name##_count(name##_t *); \
-	void name##_destroy(name##_t *, DTOR_T()); \
-	void name##_exclude(name##_t *, const uint8_t *, const size_t, DTOR_T()); \
-	type *name##_find(name##_t *, const uint8_t *, const size_t); \
-	int name##_initialize(name##_t *); \
-	int name##_is_valid(name##_t *);
-
-/** Character string to generic type map implementation.
- *
- * Should follow declaration with the same parameters.
- *
- * @param[in] name Name of the map.
- * @param[in] type Inner object type.
- *
- */
-#define GENERIC_CHAR_MAP_IMPLEMENT(name, type) \
-	GENERIC_FIELD_IMPLEMENT(name##_items, type) \
-	\
-	int name##_add(name##_t *map, const uint8_t *name, const size_t length, \
-	     type *value) \
-	{ \
-		int index; \
-		if (!name##_is_valid(map)) \
-			return EINVAL; \
-		index = name##_items_add(&map->values, value); \
-		if (index < 0) \
-			return index; \
-		return char_map_add(&map->names, name, length, index); \
-	} \
-	\
-	int name##_count(name##_t *map) \
-	{ \
-		return name##_is_valid(map) ? \
-		    name##_items_count(&map->values) : -1; \
-	} \
-	\
-	void name##_destroy(name##_t *map, DTOR_T(dtor)) \
-	{ \
-		if (name##_is_valid(map)) { \
-			char_map_destroy(&map->names); \
-			name##_items_destroy(&map->values, dtor); \
-		} \
-	} \
-	\
-	void name##_exclude(name##_t *map, const uint8_t *name, \
-	    const size_t length, DTOR_T(dtor)) \
-	{ \
-		if (name##_is_valid(map)) { \
-			int index; \
-			index = char_map_exclude(&map->names, name, length); \
-			if (index != CHAR_MAP_NULL) \
-				name##_items_exclude_index(&map->values, \
-				     index, dtor); \
-		} \
-	} \
-	\
-	type *name##_find(name##_t *map, const uint8_t *name, \
-	    const size_t length) \
-	{ \
-		if (name##_is_valid(map)) { \
-			int index; \
-			index = char_map_find(&map->names, name, length); \
-			if( index != CHAR_MAP_NULL) \
-				return name##_items_get_index(&map->values, \
-				    index); \
-		} \
-		return NULL; \
-	} \
-	\
-	int name##_initialize(name##_t *map) \
-	{ \
-		int rc; \
-		if (!map) \
-			return EINVAL; \
-		rc = char_map_initialize(&map->names); \
-		if (rc != EOK) \
-			return rc; \
-		rc = name##_items_initialize(&map->values); \
-		if (rc != EOK) { \
-			char_map_destroy(&map->names); \
-			return rc; \
-		} \
-		map->magic = GENERIC_CHAR_MAP_MAGIC_VALUE; \
-		return EOK; \
-	} \
-	\
-	int name##_is_valid(name##_t *map) \
-	{ \
-		return map && (map->magic == GENERIC_CHAR_MAP_MAGIC_VALUE); \
-	}
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/adt/generic_field.h
===================================================================
--- uspace/lib/c/include/adt/generic_field.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,169 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  Generic type field.
- */
-
-#ifndef LIBC_GENERIC_FIELD_H_
-#define LIBC_GENERIC_FIELD_H_
-
-#include <errno.h>
-#include <malloc.h>
-#include <mem.h>
-#include <unistd.h>
-
-/** Internal magic value for a&nbsp;field consistency check. */
-#define GENERIC_FIELD_MAGIC_VALUE		0x55667788
-
-/** Generic destructor function pointer. */
-#define DTOR_T(identifier) \
-	void (*identifier)(const void *)
-
-/** Generic type field declaration.
- *
- * @param[in] name	Name of the field.
- * @param[in] type	Inner object type.
- */
-#define GENERIC_FIELD_DECLARE(name, type) \
-	typedef	struct name name##_t; \
-	\
-	struct	name { \
-		int size; \
-		int next; \
-		type **items; \
-		int magic; \
-	}; \
-	\
-	int name##_add(name##_t *, type *); \
-	int name##_count(name##_t *); \
-	void name##_destroy(name##_t *, DTOR_T()); \
-	void name##_exclude_index(name##_t *, int, DTOR_T()); \
-	type **name##_get_field(name##_t *); \
-	type *name##_get_index(name##_t *, int); \
-	int name##_initialize(name##_t *); \
-	int name##_is_valid(name##_t *);
-
-/** Generic type field implementation.
- *
- * Should follow declaration with the same parameters.
- *
- * @param[in] name	Name of the field.
- * @param[in] type	Inner object type.
- */
-#define GENERIC_FIELD_IMPLEMENT(name, type) \
-	int name##_add(name##_t *field, type *value) \
-	{ \
-		if (name##_is_valid(field)) { \
-			if (field->next == (field->size - 1)) { \
-				type **tmp; \
-				tmp = (type **) realloc(field->items, \
-				    sizeof(type *) * 2 * field->size); \
-				if (!tmp) \
-					return ENOMEM; \
-				field->size *= 2; \
-				field->items = tmp; \
-			} \
-			field->items[field->next] = value; \
-			field->next++; \
-			field->items[field->next] = NULL; \
-			return field->next - 1; \
-		} \
-		return EINVAL; \
-	} \
-	\
-	int name##_count(name##_t *field) \
-	{ \
-		return name##_is_valid(field) ? field->next : -1; \
-	} \
-	\
-	void name##_destroy(name##_t *field, DTOR_T(dtor)) \
-	{ \
-		if (name##_is_valid(field)) { \
-			int index; \
-			field->magic = 0; \
-			if (dtor) { \
-				for (index = 0; index < field->next; index++) { \
-					if (field->items[index]) \
-						dtor(field->items[index]); \
-				} \
-			} \
-			free(field->items); \
-		} \
-	} \
-	 \
-	void name##_exclude_index(name##_t *field, int index, DTOR_T(dtor)) \
-	{ \
-		if (name##_is_valid(field) && (index >= 0) && \
-		    (index < field->next) && (field->items[index])) { \
-			if (dtor) \
-				dtor(field->items[index]); \
-			field->items[index] = NULL; \
-		} \
-	} \
-	 \
-	type *name##_get_index(name##_t *field, int index) \
-	{ \
-		if (name##_is_valid(field) && (index >= 0) && \
-		    (index < field->next) && (field->items[index])) \
-			return field->items[index]; \
-		return NULL; \
-	} \
-	\
-	type **name##_get_field(name##_t *field) \
-	{ \
-		return name##_is_valid(field) ? field->items : NULL; \
-	} \
-	\
-	int name##_initialize(name##_t *field) \
-	{ \
-		if (!field) \
-			return EINVAL; \
-		field->size = 2; \
-		field->next = 0; \
-		field->items = (type **) malloc(sizeof(type *) * field->size); \
-		if (!field->items) \
-			return ENOMEM; \
-		field->items[field->next] = NULL; \
-		field->magic = GENERIC_FIELD_MAGIC_VALUE; \
-		return EOK; \
-	} \
-	\
-	int name##_is_valid(name##_t *field) \
-	{ \
-		return field && (field->magic == GENERIC_FIELD_MAGIC_VALUE); \
-	}
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/adt/int_map.h
===================================================================
--- uspace/lib/c/include/adt/int_map.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,263 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  Integer to generic type map.
- */
-
-#ifndef LIBC_INT_MAP_H_
-#define LIBC_INT_MAP_H_
-
-#include <errno.h>
-#include <malloc.h>
-#include <mem.h>
-#include <unistd.h>
-
-/** Internal magic value for a map consistency check. */
-#define INT_MAP_MAGIC_VALUE		0x11223344
-
-/** Internal magic value for an item consistency check. */
-#define INT_MAP_ITEM_MAGIC_VALUE	0x55667788
-
-/** Generic destructor function pointer. */
-#define DTOR_T(identifier) \
-	void (*identifier)(const void *)
-
-/** Integer to generic type map declaration.
- *
- * @param[in] name	Name of the map.
- * @param[in] type	Inner object type.
- */
-#define INT_MAP_DECLARE(name, type) \
-	typedef	struct name name##_t; \
-	typedef	struct name##_item name##_item_t; \
-	\
-	struct	name##_item { \
-		int key; \
-		type *value; \
-		int magic; \
-	}; \
-	\
-	struct	name { \
-		int size; \
-		int next; \
-		name##_item_t *items; \
-		int magic; \
-	}; \
-	\
-	int name##_add(name##_t *, int, type *); \
-	void name##_clear(name##_t *, DTOR_T()); \
-	int name##_count(name##_t *); \
-	void name##_destroy(name##_t *, DTOR_T()); \
-	void name##_exclude(name##_t *, int, DTOR_T()); \
-	void name##_exclude_index(name##_t *, int, DTOR_T()); \
-	type *name##_find(name##_t *, int); \
-	int name##_update(name##_t *, int, int); \
-	type *name##_get_index(name##_t *, int); \
-	int name##_initialize(name##_t *); \
-	int name##_is_valid(name##_t *); \
-	void name##_item_destroy(name##_item_t *, DTOR_T()); \
-	int name##_item_is_valid(name##_item_t *);
-
-/** Integer to generic type map implementation.
- *
- * Should follow declaration with the same parameters.
- *
- * @param[in] name	Name of the map.
- * @param[in] type	Inner object type.
- */
-#define INT_MAP_IMPLEMENT(name, type) \
-	int name##_add(name##_t *map, int key, type *value) \
-	{ \
-		if (name##_is_valid(map)) { \
-			if (map->next == (map->size - 1)) { \
-				name##_item_t *tmp; \
-				tmp = (name##_item_t *) realloc(map->items, \
-				    sizeof(name##_item_t) * 2 * map->size); \
-				if (!tmp) \
-					return ENOMEM; \
-				map->size *= 2; \
-				map->items = tmp; \
-			} \
-			map->items[map->next].key = key; \
-			map->items[map->next].value = value; \
-			map->items[map->next].magic = INT_MAP_ITEM_MAGIC_VALUE; \
-			++map->next; \
-			map->items[map->next].magic = 0; \
-			return map->next - 1; \
-		} \
-		return EINVAL; \
-	} \
-	\
-	void name##_clear(name##_t *map, DTOR_T(dtor)) \
-	{ \
-		if (name##_is_valid(map)) { \
-			int index; \
-			for (index = 0; index < map->next; ++index) { \
-				if (name##_item_is_valid(&map->items[index])) { \
-					name##_item_destroy( \
-					    &map->items[index], dtor); \
-				} \
-			} \
-			map->next = 0; \
-			map->items[map->next].magic = 0; \
-		} \
-	} \
-	\
-	int name##_count(name##_t *map) \
-	{ \
-		return name##_is_valid(map) ? map->next : -1; \
-	} \
-	\
-	void name##_destroy(name##_t *map, DTOR_T(dtor)) \
-	{ \
-		if (name##_is_valid(map)) { \
-			int index; \
-			map->magic = 0; \
-			for (index = 0; index < map->next; ++index) { \
-				if (name##_item_is_valid(&map->items[index])) { \
-					name##_item_destroy( \
-					    &map->items[index], dtor); \
-				} \
-			} \
-			free(map->items); \
-		} \
-	} \
-	\
-	void name##_exclude(name##_t *map, int key, DTOR_T(dtor)) \
-	{ \
-		if (name##_is_valid(map)) { \
-			int index; \
-			for (index = 0; index < map->next; ++index) { \
-				if (name##_item_is_valid(&map->items[index]) && \
-				    (map->items[index].key == key)) { \
-					name##_item_destroy( \
-					    &map->items[index], dtor); \
-				} \
-			} \
-		} \
-	} \
-	\
-	void name##_exclude_index(name##_t *map, int index, DTOR_T(dtor)) \
-	{ \
-		if (name##_is_valid(map) && (index >= 0) && \
-		    (index < map->next) && \
-		    name##_item_is_valid(&map->items[index])) { \
-			name##_item_destroy(&map->items[index], dtor); \
-		} \
-	} \
-	\
-	type *name##_find(name##_t *map, int key) \
-	{ \
-		if (name##_is_valid(map)) { \
-			int index; \
-			for (index = 0; index < map->next; ++index) { \
-				if (name##_item_is_valid(&map->items[index]) && \
-				    (map->items[index].key == key)) { \
-					return map->items[index].value; \
-				} \
-			} \
-		} \
-		return NULL; \
-	} \
-	\
-	int name##_update(name##_t *map, int key, int new_key) \
-	{ \
-		if (name##_is_valid(map)) { \
-			int index; \
-			for (index = 0; index < map->next; ++index) { \
-				if (name##_item_is_valid(&map->items[index])) { \
-					if (map->items[index].key == new_key) \
-						return EEXIST; \
-					if (map->items[index].key == key) { \
-						map->items[index].key = \
-						    new_key; \
-						return EOK; \
-					} \
-				} \
-			} \
-		} \
-		return ENOENT; \
-	} \
-	\
-	type *name##_get_index(name##_t *map, int index) \
-	{ \
-		if (name##_is_valid(map) && (index >= 0) && \
-		    (index < map->next) && \
-		    name##_item_is_valid(&map->items[index])) { \
-			return map->items[index].value; \
-		} \
-		return NULL; \
-	} \
-	\
-	int name##_initialize(name##_t *map) \
-	{ \
-		if (!map) \
-			return EINVAL; \
-		map->size = 2; \
-		map->next = 0; \
-		map->items = (name##_item_t *) malloc(sizeof(name##_item_t) * \
-		    map->size); \
-		if (!map->items) \
-			return ENOMEM; \
-		map->items[map->next].magic = 0; \
-		map->magic = INT_MAP_MAGIC_VALUE; \
-		return EOK; \
-	} \
-	\
-	int name##_is_valid(name##_t *map) \
-	{ \
-		return map && (map->magic == INT_MAP_MAGIC_VALUE); \
-	} \
-	\
-	void name##_item_destroy(name##_item_t *item, DTOR_T(dtor)) \
-	{ \
-		if (name##_item_is_valid(item)) { \
-			item->magic = 0; \
-			if (item->value) { \
-				if (dtor) \
-					dtor(item->value); \
-				item->value = NULL; \
-			} \
-		} \
-	} \
-	\
-	int name##_item_is_valid(name##_item_t *item) \
-	{ \
-		return item && (item->magic == INT_MAP_ITEM_MAGIC_VALUE); \
-	}
-
-#endif
-
-/** @}
- */
-
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/async.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -108,5 +108,8 @@
 
 #define async_manager() \
-	fibril_switch(FIBRIL_TO_MANAGER)
+	do { \
+		futex_down(&async_futex); \
+		fibril_switch(FIBRIL_FROM_DEAD); \
+	} while (0)
 
 #define async_get_call(data) \
Index: uspace/lib/c/include/errno.h
===================================================================
--- uspace/lib/c/include/errno.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/errno.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -68,40 +68,6 @@
 #define ENAK (-303)
 
-/** An API function is called while another blocking function is in progress. */
-#define EINPROGRESS  (-10036)
-
-/** The socket identifier is not valid. */
-#define ENOTSOCK  (-10038)
-
-/** The destination address required. */
-#define EDESTADDRREQ  (-10039)
-
-/** Protocol is not supported.  */
-#define EPROTONOSUPPORT  (-10043)
-
-/** Socket type is not supported. */
-#define ESOCKTNOSUPPORT  (-10044)
-
-/** Protocol family is not supported. */
-#define EPFNOSUPPORT  (-10046)
-
-/** Address family is not supported. */
-#define EAFNOSUPPORT  (-10047)
-
-/** Address is already in use. */
-#define EADDRINUSE  (-10048)
-
-/** The socket is not connected or bound. */
-#define ENOTCONN  (-10057)
-
-#define ECONNREFUSED  (-10058)
-
-#define ECONNABORTED  (-10059)
-
 /** The requested operation was not performed. Try again later. */
 #define EAGAIN  (-11002)
-
-/** No data. */
-#define NO_DATA (-11004)
 
 #endif
Index: uspace/lib/c/include/fibril.h
===================================================================
--- uspace/lib/c/include/fibril.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/fibril.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -47,6 +47,5 @@
 	} while (0)
 
-#define FIBRIL_SERIALIZED  1
-#define FIBRIL_WRITER      2
+#define FIBRIL_WRITER	1 
 
 struct fibril;
@@ -94,5 +93,5 @@
 extern void fibril_destroy(fid_t fid);
 extern fibril_t *fibril_setup(void);
-extern void fibril_teardown(fibril_t *f);
+extern void fibril_teardown(fibril_t *f, bool locked);
 extern int fibril_switch(fibril_switch_type_t stype);
 extern void fibril_add_ready(fid_t fid);
Index: uspace/lib/c/include/fibril_synch.h
===================================================================
--- uspace/lib/c/include/fibril_synch.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/fibril_synch.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -135,5 +135,6 @@
 	fid_t fibril;
 	fibril_timer_state_t state;
-	bool handler_running;
+	/** FID of fibril executing handler or 0 if handler is not running */
+	fid_t handler_fid;
 
 	suseconds_t delay;
Index: uspace/lib/c/include/inet/addr.h
===================================================================
--- uspace/lib/c/include/inet/addr.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/inet/addr.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -37,7 +37,4 @@
 
 #include <stdint.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/socket.h>
 
 typedef uint32_t addr32_t;
@@ -126,16 +123,7 @@
 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 *);
-
-extern ip_ver_t ipver_from_af(int af);
-extern int inet_addr_sockaddr(const inet_addr_t *, uint16_t, sockaddr_t **,
-    socklen_t *);
 
 #endif
Index: uspace/lib/c/include/inet/endpoint.h
===================================================================
--- uspace/lib/c/include/inet/endpoint.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/c/include/inet/endpoint.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,86 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_ASSOC_H_
+#define LIBC_INET_ASSOC_H_
+
+#include <stdint.h>
+#include <inet/addr.h>
+#include <loc.h>
+
+/** Internet port number ranges
+ *
+ * Port number ranges per RFC 6335 section 6 (Port Number Ranges.
+ * Technically port zero is a system port. But since it is reserved,
+ * we will use it as a special value denoting no port is specified
+ * and we will exclude it from the system port range to disallow
+ * ever assigning it.
+ */
+enum inet_port_ranges {
+	/** Special value meaning no specific port */
+	inet_port_any = 0,
+	/** Lowest system port (a.k.a. well known port) */
+	inet_port_sys_lo = 1,
+	/** Highest system port (a.k.a. well known port) */
+	inet_port_sys_hi = 1023,
+	/** Lowest user port (a.k.a. registered port) */
+	inet_port_user_lo = 1024,
+	/** Highest user port (a.k.a. registered port) */
+	inet_port_user_hi = 49151,
+	/** Lowest dynamic port (a.k.a. private or ephemeral port) */
+	inet_port_dyn_lo = 49152,
+	/** Highest dynamic port (a.k.a. private or ephemeral port) */
+	inet_port_dyn_hi = 65535
+};
+
+/** Internet endpoint (address-port pair), a.k.a. socket */
+typedef struct {
+	inet_addr_t addr;
+	uint16_t port;
+} inet_ep_t;
+
+/** Internet endpoint pair */
+typedef struct {
+	service_id_t local_link;
+	inet_ep_t local;
+	inet_ep_t remote;
+} inet_ep2_t;
+
+extern void inet_ep_init(inet_ep_t *);
+extern void inet_ep2_init(inet_ep2_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/iplink.h
===================================================================
--- uspace/lib/c/include/inet/iplink.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/inet/iplink.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -44,4 +44,5 @@
 	async_sess_t *sess;
 	struct iplink_ev_ops *ev_ops;
+	void *arg;
 } iplink_t;
 
@@ -81,5 +82,5 @@
 } iplink_ev_ops_t;
 
-extern int iplink_open(async_sess_t *, iplink_ev_ops_t *, iplink_t **);
+extern int iplink_open(async_sess_t *, iplink_ev_ops_t *, void *, iplink_t **);
 extern void iplink_close(iplink_t *);
 extern int iplink_send(iplink_t *, iplink_sdu_t *);
@@ -90,4 +91,5 @@
 extern int iplink_get_mac48(iplink_t *, addr48_t *);
 extern int iplink_set_mac48(iplink_t *, addr48_t);
+extern void *iplink_get_userptr(iplink_t *);
 
 #endif
Index: uspace/lib/c/include/inet/tcp.h
===================================================================
--- uspace/lib/c/include/inet/tcp.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/c/include/inet/tcp.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,124 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_TCP_H_
+#define LIBC_INET_TCP_H_
+
+#include <fibril_synch.h>
+#include <inet/addr.h>
+#include <inet/endpoint.h>
+#include <inet/inet.h>
+
+/** TCP connection */
+typedef struct {
+	fibril_mutex_t lock;
+	fibril_condvar_t cv;
+	struct tcp *tcp;
+	link_t ltcp;
+	sysarg_t id;
+	struct tcp_cb *cb;
+	void *cb_arg;
+	/** Some received data available in TCP server */
+	bool data_avail;
+	bool connected;
+	bool conn_failed;
+	bool conn_reset;
+} tcp_conn_t;
+
+/** TCP connection listener */
+typedef struct {
+	struct tcp *tcp;
+	link_t ltcp;
+	sysarg_t id;
+	struct tcp_listen_cb *lcb;
+	void *lcb_arg;
+	struct tcp_cb *cb;
+	void *cb_arg;
+} tcp_listener_t;
+
+/** TCP connection callbacks */
+typedef struct tcp_cb {
+	void (*connected)(tcp_conn_t *);
+	void (*conn_failed)(tcp_conn_t *);
+	void (*conn_reset)(tcp_conn_t *);
+	void (*data_avail)(tcp_conn_t *);
+	void (*urg_data)(tcp_conn_t *);
+} tcp_cb_t;
+
+/** TCP listener callbacks */
+typedef struct tcp_listen_cb {
+	void (*new_conn)(tcp_listener_t *, tcp_conn_t *);
+} tcp_listen_cb_t;
+
+/** TCP service */
+typedef struct tcp {
+	/** TCP session */
+	async_sess_t *sess;
+	/** List of connections */
+	list_t conn; /* of tcp_conn_t */
+	/** List of listeners */
+	list_t listener; /* of tcp_listener_t */
+	/** TCP service lock */
+	fibril_mutex_t lock;
+	/** For waiting on cb_done */
+	fibril_condvar_t cv;
+	/** Set to @a true when callback connection handler has terminated */
+	bool cb_done;
+} tcp_t;
+
+extern int tcp_create(tcp_t **);
+extern void tcp_destroy(tcp_t *);
+extern int tcp_conn_create(tcp_t *, inet_ep2_t *, tcp_cb_t *, void *,
+    tcp_conn_t **);
+extern void tcp_conn_destroy(tcp_conn_t *);
+extern void *tcp_conn_userptr(tcp_conn_t *);
+extern int tcp_listener_create(tcp_t *, inet_ep_t *, tcp_listen_cb_t *, void *,
+    tcp_cb_t *, void *, tcp_listener_t **);
+extern void tcp_listener_destroy(tcp_listener_t *);
+extern void *tcp_listener_userptr(tcp_listener_t *);
+
+extern int tcp_conn_wait_connected(tcp_conn_t *);
+extern int tcp_conn_send(tcp_conn_t *, const void *, size_t);
+extern int tcp_conn_send_fin(tcp_conn_t *);
+extern int tcp_conn_push(tcp_conn_t *);
+extern int tcp_conn_reset(tcp_conn_t *);
+
+extern int tcp_conn_recv(tcp_conn_t *, void *, size_t, size_t *);
+extern int tcp_conn_recv_wait(tcp_conn_t *, void *, size_t, size_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/udp.h
===================================================================
--- uspace/lib/c/include/inet/udp.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/c/include/inet/udp.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,109 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_UDP_H_
+#define LIBC_INET_UDP_H_
+
+#include <async.h>
+#include <fibril_synch.h>
+#include <inet/addr.h>
+#include <inet/endpoint.h>
+#include <inet/inet.h>
+#include <stdbool.h>
+
+/** UDP link state */
+typedef enum {
+	udp_ls_down,
+	udp_ls_up
+} udp_link_state_t;
+
+/** UDP received message */
+typedef struct {
+	struct udp *udp;
+	sysarg_t assoc_id;
+	size_t size;
+	inet_ep_t remote_ep;
+} udp_rmsg_t;
+
+/** UDP received error */
+typedef struct {
+} udp_rerr_t;
+
+/** UDP association */
+typedef struct {
+	struct udp *udp;
+	link_t ludp;
+	sysarg_t id;
+	struct udp_cb *cb;
+	void *cb_arg;
+} udp_assoc_t;
+
+/** UDP callbacks */
+typedef struct udp_cb {
+	void (*recv_msg)(udp_assoc_t *, udp_rmsg_t *);
+	void (*recv_err)(udp_assoc_t *, udp_rerr_t *);
+	void (*link_state)(udp_assoc_t *, udp_link_state_t);
+} udp_cb_t;
+
+/** UDP service */
+typedef struct udp {
+	/** UDP session */
+	async_sess_t *sess;
+	/** List of associations */
+	list_t assoc; /* of udp_assoc_t */
+	/** UDP service lock */
+	fibril_mutex_t lock;
+	/** For waiting on cb_done */
+	fibril_condvar_t cv;
+	/** Set to @a true when callback connection handler has terminated */
+	bool cb_done;
+} udp_t;
+
+extern int udp_create(udp_t **);
+extern void udp_destroy(udp_t *);
+extern int udp_assoc_create(udp_t *, inet_ep2_t *, udp_cb_t *, void *,
+    udp_assoc_t **);
+extern void udp_assoc_destroy(udp_assoc_t *);
+extern int udp_assoc_send_msg(udp_assoc_t *, inet_ep_t *, void *, size_t);
+extern void *udp_assoc_userptr(udp_assoc_t *);
+extern size_t udp_rmsg_size(udp_rmsg_t *);
+extern int udp_rmsg_read(udp_rmsg_t *, size_t, void *, size_t);
+extern void udp_rmsg_remote_ep(udp_rmsg_t *, inet_ep_t *);
+extern uint8_t udp_rerr_type(udp_rerr_t *);
+extern uint8_t udp_rerr_code(udp_rerr_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/ipc/services.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -49,6 +49,4 @@
 	SERVICE_IRC        = FOURCC('i', 'r', 'c', ' '),
 	SERVICE_CLIPBOARD  = FOURCC('c', 'l', 'i', 'p'),
-	SERVICE_UDP        = FOURCC('u', 'd', 'p', ' '),
-	SERVICE_TCP        = FOURCC('t', 'c', 'p', ' ')
 } services_t;
 
@@ -61,4 +59,6 @@
 #define SERVICE_NAME_INETPING6  "net/inetping6"
 #define SERVICE_NAME_NETCONF    "net/netconf"
+#define SERVICE_NAME_UDP	"net/udp"
+#define SERVICE_NAME_TCP	"net/tcp"
 
 #endif
Index: pace/lib/c/include/ipc/socket.h
===================================================================
--- uspace/lib/c/include/ipc/socket.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,227 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- * @{
- */
-
-/** @file
- * Socket messages.
- */
-
-#ifndef LIBC_SOCKET_MESSAGES_H_
-#define LIBC_SOCKET_MESSAGES_H_
-
-/** Socket client messages. */
-typedef enum {
-	/** Creates a new socket. @see socket() */
-	NET_SOCKET = IPC_FIRST_USER_METHOD,
-	/** Binds the socket. @see bind() */
-	NET_SOCKET_BIND,
-	/** Creates a new socket. @see socket() */
-	NET_SOCKET_LISTEN,
-	/** Accepts an incomming connection. @see accept() */
-	NET_SOCKET_ACCEPT,
-	/** Connects the socket. @see connect() */
-	NET_SOCKET_CONNECT,
-	/** Closes the socket. @see closesocket() */
-	NET_SOCKET_CLOSE,
-	/** Sends data via the stream socket. @see send() */
-	NET_SOCKET_SEND,
-	/** Sends data via the datagram socket. @see sendto() */
-	NET_SOCKET_SENDTO,
-	/** Receives data from the stream socket. @see socket() */
-	NET_SOCKET_RECV,
-	/** Receives data from the datagram socket. @see socket() */
-	NET_SOCKET_RECVFROM,
-	/** Gets the socket option. @see getsockopt() */
-	NET_SOCKET_GETSOCKOPT,
-	/** Sets the socket option. @see setsockopt() */
-	NET_SOCKET_SETSOCKOPT,
-	/** New socket for acceptence notification message. */
-	NET_SOCKET_ACCEPTED,
-	/** New data received notification message. */
-	NET_SOCKET_RECEIVED,
-	/** New socket data fragment size notification message. */
-	NET_SOCKET_DATA_FRAGMENT_SIZE
-} socket_messages;
-
-/** @name Socket specific message parameters definitions
- */
-/*@{*/
-
-/** Sets the socket identifier in the message answer.
- * @param[out] answer	The message answer structure.
- */
-#define SOCKET_SET_SOCKET_ID(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG1(answer, argument); \
-	} while (0)
-
-/** Returns the socket identifier message parameter.
- * @param[in] call	The message call structure.
- */
-#define SOCKET_GET_SOCKET_ID(call) \
-	({ \
-		int socket_id = (int) IPC_GET_ARG1(call); \
-		socket_id; \
-	})
-
-/** Sets the read data length in the message answer.
- * @param[out] answer	The message answer structure.
- */
-#define SOCKET_SET_READ_DATA_LENGTH(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG1(answer, argument); \
-	} while (0)
-
-/** Returns the read data length message parameter.
- * @param[in] call	The message call structure.
- */
-#define SOCKET_GET_READ_DATA_LENGTH(call) \
-	({ \
-		int data_length = (int) IPC_GET_ARG1(call); \
-		data_length; \
-	})
-
-/** Returns the backlog message parameter.
- * @param[in] call	The message call structure.
- */
-#define SOCKET_GET_BACKLOG(call) \
-	({ \
-		int backlog = (int) IPC_GET_ARG2(call); \
-		backlog; \
-	})
-
-/** Returns the option level message parameter.
- * @param[in] call	The message call structure.
- */
-#define SOCKET_GET_OPT_LEVEL(call) \
-	({ \
-		int opt_level = (int) IPC_GET_ARG2(call); \
-		opt_level; \
-	})
-
-/** Returns the data fragment size message parameter.
- * @param[in] call	The message call structure.
- */
-#define SOCKET_GET_DATA_FRAGMENT_SIZE(call) \
-	({ \
-		size_t size = (size_t) IPC_GET_ARG2(call); \
-		size; \
-	})
-
-/** Sets the data fragment size in the message answer.
- * @param[out] answer	The message answer structure.
- */
-#define SOCKET_SET_DATA_FRAGMENT_SIZE(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG2(answer, argument); \
-	} while (0)
-
-/** Sets the address length in the message answer.
- * @param[out] answer	The message answer structure.
- */
-#define SOCKET_SET_ADDRESS_LENGTH(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG3(answer, argument);\
-	} while (0)
-
-/** Returns the address length message parameter.
- * @param[in] call	The message call structure.
- */
-#define SOCKET_GET_ADDRESS_LENGTH(call) \
-	({ \
-		socklen_t address_length = (socklen_t) IPC_GET_ARG3(call); \
-		address_length; \
-	})
-
-/** Sets the header size in the message answer.
- * @param[out] answer	The message answer structure.
- */
-#define SOCKET_SET_HEADER_SIZE(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG3(answer, argument); \
-	} while (0)
-
-/** Returns the header size message parameter.
- *  @param[in] call	The message call structure.
- */
-#define SOCKET_GET_HEADER_SIZE(call) \
-	({ \
-		size_t size = (size_t) IPC_GET_ARG3(call); \
-		size; \
-	})
-
-/** Returns the flags message parameter.
- *  @param[in] call	The message call structure.
- */
-#define SOCKET_GET_FLAGS(call) \
-	({ \
-		int flags = (int) IPC_GET_ARG4(call); \
-		flags; \
-	})
-
-/** Returns the option name message parameter.
- *  @param[in] call	The message call structure.
- */
-#define SOCKET_GET_OPT_NAME(call) \
-	({ \
-		int opt_name = (int) IPC_GET_ARG2(call); \
-		opt_name; \
-	})
-
-/** Returns the data fragments message parameter.
- *  @param[in] call	The message call structure.
- */
-#define SOCKET_GET_DATA_FRAGMENTS(call) \
-	({ \
-		int fragments = (int) IPC_GET_ARG5(call); \
-		fragments; \
-	})
-
-/** Returns the new socket identifier message parameter.
- *  @param[in] call	The message call structure.
- */
-#define SOCKET_GET_NEW_SOCKET_ID(call) \
-	({ \
-		int socket_id = (int) IPC_GET_ARG5(call); \
-		socket_id; \
-	})
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/ipc/tcp.h
===================================================================
--- uspace/lib/c/include/ipc/tcp.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/c/include/ipc/tcp.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 Jiri Svobda
+ * 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 libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_TCP_H_
+#define LIBC_IPC_TCP_H_
+
+#include <ipc/common.h>
+
+typedef enum {
+	TCP_CALLBACK_CREATE = IPC_FIRST_USER_METHOD,
+	TCP_CONN_CREATE,
+	TCP_CONN_DESTROY,
+	TCP_LISTENER_CREATE,
+	TCP_LISTENER_DESTROY,
+	TCP_CONN_SEND,
+	TCP_CONN_SEND_FIN,
+	TCP_CONN_PUSH,
+	TCP_CONN_RESET,
+	TCP_CONN_RECV,
+	TCP_CONN_RECV_WAIT
+} tcp_request_t;
+
+typedef enum {
+	TCP_EV_CONNECTED = IPC_FIRST_USER_METHOD,
+	TCP_EV_CONN_FAILED,
+	TCP_EV_CONN_RESET,
+	TCP_EV_DATA,
+	TCP_EV_URG_DATA,
+	TCP_EV_NEW_CONN
+} tcp_event_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/udp.h
===================================================================
--- uspace/lib/c/include/ipc/udp.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/c/include/ipc/udp.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 Jiri Svobda
+ * 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 libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_UDP_H_
+#define LIBC_IPC_UDP_H_
+
+#include <ipc/common.h>
+
+typedef enum {
+	UDP_CALLBACK_CREATE = IPC_FIRST_USER_METHOD,
+	UDP_ASSOC_CREATE,
+	UDP_ASSOC_DESTROY,
+	UDP_ASSOC_SEND_MSG,
+	UDP_RMSG_INFO,
+	UDP_RMSG_READ,
+	UDP_RMSG_DISCARD
+} udp_request_t;
+
+typedef enum {
+	UDP_EV_DATA = IPC_FIRST_USER_METHOD
+} udp_event_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/malloc.h
===================================================================
--- uspace/lib/c/include/malloc.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/malloc.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -44,5 +44,6 @@
 extern void *memalign(const size_t align, const size_t size)
     __attribute__((malloc));
-extern void *realloc(const void *addr, const size_t size);
+extern void *realloc(const void *addr, const size_t size)
+    __attribute__((warn_unused_result));
 extern void free(const void *addr);
 extern void *heap_check(void);
Index: uspace/lib/c/include/mem.h
===================================================================
--- uspace/lib/c/include/mem.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/mem.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -40,9 +40,13 @@
 
 extern void *memset(void *, int, size_t)
+    __attribute__((nonnull(1)))
     ATTRIBUTE_OPTIMIZE("-fno-tree-loop-distribute-patterns");
 extern void *memcpy(void *, const void *, size_t)
+    __attribute__((nonnull(1, 2)))
     ATTRIBUTE_OPTIMIZE("-fno-tree-loop-distribute-patterns");
-extern void *memmove(void *, const void *, size_t);
-extern int memcmp(const void *, const void *, size_t);
+extern void *memmove(void *, const void *, size_t)
+    __attribute__((nonnull(1, 2)));
+extern int memcmp(const void *, const void *, size_t)
+    __attribute__((nonnull(1, 2)));
 
 #endif
Index: pace/lib/c/include/net/in.h
===================================================================
--- uspace/lib/c/include/net/in.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  INET family common definitions.
- */
-
-#ifndef LIBC_IN_H_
-#define LIBC_IN_H_
-
-#include <net/inet.h>
-#include <net/ip_protocols.h>
-#include <sys/types.h>
-
-/** INET string address maximum length. */
-#define INET_ADDRSTRLEN  (4 * 3 + 3 + 1)
-
-#define INADDR_ANY  0
-
-/** INET address. */
-typedef struct in_addr {
-	/** 4 byte IP address. */
-	uint32_t s_addr;
-} in_addr_t;
-
-/** INET socket address.
- * @see sockaddr
- */
-typedef struct sockaddr_in {
-	/** Address family. Should be AF_INET. */
-	uint16_t sin_family;
-	/** Port number. */
-	uint16_t sin_port;
-	/** Internet address. */
-	in_addr_t sin_addr;
-	/** Padding to meet the sockaddr size. */
-	uint8_t sin_zero[8];
-} sockaddr_in_t;
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/in6.h
===================================================================
--- uspace/lib/c/include/net/in6.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,74 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  INET6 family common definitions.
- */
-
-#ifndef LIBC_IN6_H_
-#define LIBC_IN6_H_
-
-#include <net/inet.h>
-#include <net/ip_protocols.h>
-#include <sys/types.h>
-
-/** INET6 string address maximum length. */
-#define INET6_ADDRSTRLEN  (8 * 4 + 7 + 1)
-
-/** INET6 address. */
-typedef struct in6_addr {
-	/** 16 byte IPv6 address. */
-	uint8_t s6_addr[16];
-} in6_addr_t;
-
-/** INET6 socket address.
- * @see sockaddr
- */
-typedef struct sockaddr_in6 {
-	/** Address family. Should be AF_INET6. */
-	uint16_t sin6_family;
-	/** Port number. */
-	uint16_t sin6_port;
-	/** IPv6 flow information. */
-	uint32_t sin6_flowinfo;
-	/** IPv6 address. */
-	struct in6_addr sin6_addr;
-	/** Scope identifier. */
-	uint32_t sin6_scope_id;
-} sockaddr_in6_t;
-
-extern const in6_addr_t in6addr_any;
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/inet.h
===================================================================
--- uspace/lib/c/include/net/inet.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,62 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  Internet common definitions.
- */
-
-#ifndef LIBC_INET_H_
-#define LIBC_INET_H_
-
-#include <sys/types.h>
-#include <byteorder.h>
-
-/** Type definition of the address information.
- * @see addrinfo
- */
-typedef struct addrinfo addrinfo_t;
-
-/** Socket address. */
-typedef struct sockaddr {
-	/** Address family. @see socket.h */
-	uint16_t sa_family;
-	/** 14 byte protocol address. */
-	uint8_t sa_data[14];
-} sockaddr_t;
-
-extern int inet_ntop(uint16_t, const uint8_t *, char *, size_t);
-extern int inet_pton(uint16_t, const char *, uint8_t *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/ip_protocols.h
===================================================================
--- uspace/lib/c/include/net/ip_protocols.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- * Internet protocol numbers according to the on-line IANA - Assigned Protocol
- * numbers:
- *
- * http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml
- */
-
-#ifndef LIBC_IP_PROTOCOLS_H_
-#define LIBC_IP_PROTOCOLS_H_
-
-/** @name IP protocols definitions */
-/*@{*/
-
-#define IPPROTO_ICMP    1
-#define IPPROTO_TCP     6
-#define IPPROTO_UDP     17
-#define IPPROTO_ICMPV6  58
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/socket.h
===================================================================
--- uspace/lib/c/include/net/socket.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  Socket application program interface (API).
- *  This is a part of the network application library.
- *  Based on the BSD socket interface.
- */
-
-#ifndef LIBC_SOCKET_H_
-#define LIBC_SOCKET_H_
-
-#include <net/socket_codes.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <errno.h>
-#include <byteorder.h>
-
-/** @name Socket application programming interface
- */
-/*@{*/
-
-extern int socket(int, int, int);
-extern int bind(int, const struct sockaddr *, socklen_t);
-extern int listen(int, int);
-extern int accept(int, struct sockaddr *, socklen_t *);
-extern int connect(int, const struct sockaddr *, socklen_t);
-extern int closesocket(int);
-extern int send(int, const void *, size_t, int);
-extern int sendto(int, const void *, size_t, int, const struct sockaddr *,
-    socklen_t);
-extern ssize_t recv(int, void *, size_t, int);
-extern ssize_t recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *);
-extern int getsockopt(int, int, int, void *, size_t *);
-extern int setsockopt(int, int, int, const void *, size_t);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/socket_codes.h
===================================================================
--- uspace/lib/c/include/net/socket_codes.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libc
- *  @{
- */
-
-/** @file
- *  Socket codes and definitions.
- *  This is a part of the network application library.
- */
-
-#ifndef LIBC_SOCKET_CODES_H_
-#define LIBC_SOCKET_CODES_H_
-
-#include <sys/types.h>
-
-/** @name Address families definitions */
-/*@{*/
-
-enum {
-	AF_NONE = 0,
-	AF_INET,  /* IPv4 address */
-	AF_INET6  /* IPv6 address */
-};
-
-/*@}*/
-
-/** @name Protocol families definitions
- * Same as address families.
- */
-/*@{*/
-
-#define PF_INET   AF_INET
-#define PF_INET6  AF_INET6
-
-/*@}*/
-
-/** Socket types. */
-typedef enum sock_type {
-	/** Stream (connection oriented) socket. */
-	SOCK_STREAM = 1,
-	/** Datagram (connectionless oriented) socket. */
-	SOCK_DGRAM = 2,
-	/** Raw socket. */
-	SOCK_RAW = 3
-} sock_type_t;
-
-/** Type definition of the socket length. */
-typedef int32_t socklen_t;
-
-/* Socket options */
-
-enum {
-	SOL_SOCKET = 1,
-
-	/* IP link to transmit on */
-	SO_IPLINK
-};
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/socket_parse.h
===================================================================
--- uspace/lib/c/include/net/socket_parse.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,42 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 socket
- * @{
- */
-
-/** @file
- * Command-line argument parsing functions related to networking.
- */
-
-extern int socket_parse_address_family(const char *, int *);
-extern int socket_parse_protocol_family(const char *, int *);
-extern int socket_parse_socket_type(const char *, int *);
-
-/** @}
- */
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/c/include/task.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -60,5 +60,6 @@
 extern int task_spawn(task_id_t *, task_wait_t *, const char *path, int,
     va_list ap);
-extern int task_spawnl(task_id_t *, task_wait_t *, const char *path, ...);
+extern int task_spawnl(task_id_t *, task_wait_t *, const char *path, ...)
+    __attribute__((sentinel));
 
 extern int task_setup_wait(task_id_t, task_wait_t *);
Index: uspace/lib/http/include/http/http.h
===================================================================
--- uspace/lib/http/include/http/http.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/http/include/http/http.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -37,7 +37,7 @@
 #define HTTP_HTTP_H_
 
-#include <net/socket.h>
 #include <adt/list.h>
 #include <inet/addr.h>
+#include <inet/tcp.h>
 
 #include "receive-buffer.h"
@@ -48,7 +48,7 @@
 	inet_addr_t addr;
 
-	bool connected;
-	int conn_sd;
-	
+	tcp_t *tcp;
+	tcp_conn_t *conn;
+
 	size_t buffer_size;
 	receive_buffer_t recv_buffer;
Index: uspace/lib/http/src/http.c
===================================================================
--- uspace/lib/http/src/http.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/http/src/http.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -34,4 +34,5 @@
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -39,6 +40,6 @@
 #include <macros.h>
 
-#include <net/socket.h>
 #include <inet/dnsr.h>
+#include <inet/tcp.h>
 
 #include <http/http.h>
@@ -48,5 +49,12 @@
 {
 	http_t *http = client_data;
-	return recv(http->conn_sd, buf, buf_size, 0);
+	size_t nrecv;
+	int rc;
+
+	rc = tcp_conn_recv_wait(http->conn, buf, buf_size, &nrecv);
+	if (rc != EOK)
+		return rc;
+
+	return nrecv;
 }
 
@@ -77,5 +85,5 @@
 int http_connect(http_t *http)
 {
-	if (http->connected)
+	if (http->conn != NULL)
 		return EBUSY;
 	
@@ -95,19 +103,21 @@
 	}
 	
-	struct sockaddr *saddr;
-	socklen_t saddrlen;
+	inet_ep2_t epp;
 	
-	rc = inet_addr_sockaddr(&http->addr, http->port, &saddr, &saddrlen);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		return ENOMEM;
-	}
+	inet_ep2_init(&epp);
+	epp.remote.addr = http->addr;
+	epp.remote.port = http->port;
 	
-	http->conn_sd = socket(saddr->sa_family, SOCK_STREAM, 0);
-	if (http->conn_sd < 0)
-		return http->conn_sd;
+	rc = tcp_create(&http->tcp);
+	if (rc != EOK)
+		return rc;
 	
-	rc = connect(http->conn_sd, saddr, saddrlen);
-	free(saddr);
+	rc = tcp_conn_create(http->tcp, &epp, NULL, NULL, &http->conn);
+	if (rc != EOK)
+		return rc;
+	
+	rc = tcp_conn_wait_connected(http->conn);
+	if (rc != EOK)
+		return rc;
 	
 	return rc;
@@ -116,8 +126,10 @@
 int http_close(http_t *http)
 {
-	if (!http->connected)
+	if (http->conn == NULL)
 		return EINVAL;
 	
-	return closesocket(http->conn_sd);
+	tcp_conn_destroy(http->conn);
+	tcp_destroy(http->tcp);
+	return EOK;
 }
 
Index: uspace/lib/http/src/request.c
===================================================================
--- uspace/lib/http/src/request.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/http/src/request.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -34,4 +34,5 @@
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -39,5 +40,5 @@
 #include <macros.h>
 
-#include <net/socket.h>
+#include <inet/tcp.h>
 
 #include <http/http.h>
@@ -149,5 +150,5 @@
 		return rc;
 	
-	rc = send(http->conn_sd, buf, buf_size, 0);
+	rc = tcp_conn_send(http->conn, buf, buf_size);
 	free(buf);
 	
Index: uspace/lib/ieee80211/src/ieee80211.c
===================================================================
--- uspace/lib/ieee80211/src/ieee80211.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/ieee80211/src/ieee80211.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -718,5 +718,5 @@
  *
  */
-ieee80211_dev_t *ieee80211_device_create()
+ieee80211_dev_t *ieee80211_device_create(void)
 {
 	return calloc(1, sizeof(ieee80211_dev_t));
Index: pace/lib/net/Makefile
===================================================================
--- uspace/lib/net/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# 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 = libnet
-
-SOURCES = \
-	tl/socket_core.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/lib/net/include/socket_core.h
===================================================================
--- uspace/lib/net/include/socket_core.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,125 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libnet
- *  @{
- */
-
-/** @file
- * Socket common core.
- */
-
-#ifndef LIBNET_SOCKET_CORE_H_
-#define LIBNET_SOCKET_CORE_H_
-
-#include <sys/types.h>
-#include <adt/generic_char_map.h>
-#include <adt/dynamic_fifo.h>
-#include <adt/int_map.h>
-#include <net/in.h>
-#include <async.h>
-
-/** Initial size of the received packet queue. */
-#define SOCKET_INITIAL_RECEIVED_SIZE  4
-
-/** Maximum size of the received packet queue. */
-#define SOCKET_MAX_RECEIVED_SIZE  0
-
-/** Initial size of the sockets for acceptance queue. */
-#define SOCKET_INITIAL_ACCEPTED_SIZE  1
-
-/** Maximum size of the sockets for acceptance queue. */
-#define SOCKET_MAX_ACCEPTEDED_SIZE  0
-
-/** Listening sockets' port map key. */
-#define SOCKET_MAP_KEY_LISTENING  "L"
-
-/** Type definition of the socket core.
- * @see socket_core
- */
-typedef struct socket_core socket_core_t;
-
-/** Type definition of the socket port.
- * @see socket_port
- */
-typedef struct socket_port socket_port_t;
-
-/** Socket core. */
-struct socket_core {
-	/** Socket identifier. */
-	int socket_id;
-	/** Client application session. */
-	async_sess_t *sess;
-	/** Bound port. */
-	int port;
-	/** Sockets for acceptance queue. */
-	dyn_fifo_t accepted;
-	/** Protocol specific data. */
-	void *specific_data;
-	/** Socket ports map key. */
-	const uint8_t *key;
-	/** Length of the Socket ports map key. */
-	size_t key_length;
-};
-
-/** Sockets map.
- * The key is the socket identifier.
- */
-INT_MAP_DECLARE(socket_cores, socket_core_t);
-
-/** Bount port sockets map.
- *
- * The listening socket has the SOCKET_MAP_KEY_LISTENING key identifier whereas
- * the other use the remote addresses.
- */
-GENERIC_CHAR_MAP_DECLARE(socket_port_map, socket_core_t *);
-
-/** Ports map.
- * The key is the port number.
- */
-INT_MAP_DECLARE(socket_ports, socket_port_t);
-
-extern void socket_cores_release(async_sess_t *, socket_cores_t *,
-    socket_ports_t *, void (*)(socket_core_t *));
-extern int socket_bind(socket_cores_t *, socket_ports_t *, int, void *, size_t,
-    int, int, int);
-extern int socket_bind_free_port(socket_ports_t *, socket_core_t *, int, int,
-    int);
-extern int socket_create(socket_cores_t *, async_sess_t *, void *, int *);
-extern int socket_destroy(async_sess_t *, int, socket_cores_t *,
-    socket_ports_t *, void (*)(socket_core_t *));
-extern socket_core_t *socket_port_find(socket_ports_t *, int, const uint8_t *,
-    size_t);
-extern void socket_port_release(socket_ports_t *, socket_core_t *);
-extern int socket_port_add(socket_ports_t *, int, socket_core_t *,
-    const uint8_t *, size_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/tl/socket_core.c
===================================================================
--- uspace/lib/net/tl/socket_core.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,603 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libnet
- * @{
- */
-
-/** @file
- * Socket common core implementation.
- */
-
-#include <socket_core.h>
-#include <net/socket_codes.h>
-#include <net/in.h>
-#include <net/inet.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <adt/dynamic_fifo.h>
-#include <adt/int_map.h>
-
-/**
- * Maximum number of random attempts to find a new socket identifier before
- * switching to the sequence.
- */
-#define SOCKET_ID_TRIES  100
-
-/** Bound port sockets.*/
-struct socket_port {
-	/** The bound sockets map. */
-	socket_port_map_t map;
-	/** The bound sockets count. */
-	int count;
-};
-
-INT_MAP_IMPLEMENT(socket_cores, socket_core_t);
-
-GENERIC_CHAR_MAP_IMPLEMENT(socket_port_map, socket_core_t *);
-
-INT_MAP_IMPLEMENT(socket_ports, socket_port_t);
-
-/** Destroy the socket.
- *
- * If the socket is bound, the port is released.
- * Release all buffered packets, call the release function and remove the
- * socket from the local sockets.
- *
- * @param[in]     sess           Packet server session.
- * @param[in]     socket         Socket to be destroyed.
- * @param[in,out] local_sockets  Local sockets to be updated.
- * @param[in,out] global_sockets Global sockets to be updated.
- * @param[in]     socket_release Client release callback function.
- *
- */
-static void socket_destroy_core(async_sess_t *sess, socket_core_t *socket,
-    socket_cores_t *local_sockets, socket_ports_t *global_sockets,
-    void (* socket_release)(socket_core_t *socket))
-{
-	/* If bound */
-	if (socket->port) {
-		/* Release the port */
-		socket_port_release(global_sockets, socket);
-	}
-	
-	dyn_fifo_destroy(&socket->accepted);
-	
-	if (socket_release)
-		socket_release(socket);
-	
-	socket_cores_exclude(local_sockets, socket->socket_id, free);
-}
-
-/** Destroy local sockets.
- *
- * Release all buffered packets and call the release function for each of the
- * sockets.
- *
- * @param[in]     sess           Packet server session.
- * @param[in]     local_sockets  Local sockets to be destroyed.
- * @param[in,out] global_sockets Global sockets to be updated.
- * @param[in]     socket_release Client release callback function.
- *
- */
-void socket_cores_release(async_sess_t *sess, socket_cores_t *local_sockets,
-    socket_ports_t *global_sockets,
-    void (* socket_release)(socket_core_t *socket))
-{
-	if (!socket_cores_is_valid(local_sockets))
-		return;
-	
-	local_sockets->magic = 0;
-	
-	int index;
-	for (index = 0; index < local_sockets->next; ++index) {
-		if (socket_cores_item_is_valid(&local_sockets->items[index])) {
-			local_sockets->items[index].magic = 0;
-			
-			if (local_sockets->items[index].value) {
-				socket_destroy_core(sess,
-				    local_sockets->items[index].value,
-				    local_sockets, global_sockets,
-				    socket_release);
-				free(local_sockets->items[index].value);
-				local_sockets->items[index].value = NULL;
-			}
-		}
-	}
-	
-	free(local_sockets->items);
-}
-
-/** Adds the socket to a socket port.
- *
- * @param[in,out] socket_port The socket port structure.
- * @param[in] socket	The socket to be added.
- * @param[in] key	The socket key identifier.
- * @param[in] key_length The socket key length.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int
-socket_port_add_core(socket_port_t *socket_port, socket_core_t *socket,
-    const uint8_t *key, size_t key_length)
-{
-	socket_core_t **socket_ref;
-	int rc;
-
-	/* Create a wrapper */
-	socket_ref = malloc(sizeof(*socket_ref));
-	if (!socket_ref)
-		return ENOMEM;
-
-	*socket_ref = socket;
-	/* Add the wrapper */
-	rc = socket_port_map_add(&socket_port->map, key, key_length,
-	    socket_ref);
-	if (rc != EOK) {
-		free(socket_ref);
-		return rc;
-	}
-	
-	++socket_port->count;
-	socket->key = key;
-	socket->key_length = key_length;
-	
-	return EOK;
-}
-
-/** Binds the socket to the port.
- *
- * The SOCKET_MAP_KEY_LISTENING key identifier is used.
- *
- * @param[in] global_sockets The global sockets to be updated.
- * @param[in] socket	The socket to be added.
- * @param[in] port	The port number to be bound to.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			 socket_ports_add() function.
- */
-static int
-socket_bind_insert(socket_ports_t *global_sockets, socket_core_t *socket,
-    int port)
-{
-	socket_port_t *socket_port;
-	int rc;
-
-	/* Create a wrapper */
-	socket_port = malloc(sizeof(*socket_port));
-	if (!socket_port)
-		return ENOMEM;
-
-	socket_port->count = 0;
-	rc = socket_port_map_initialize(&socket_port->map);
-	if (rc != EOK)
-		goto fail;
-	
-	rc = socket_port_add_core(socket_port, socket,
-	    (const uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
-	if (rc != EOK)
-		goto fail;
-	
-	/* Register the incoming port */
-	rc = socket_ports_add(global_sockets, port, socket_port);
-	if (rc < 0)
-		goto fail;
-	
-	socket->port = port;
-	return EOK;
-
-fail:
-	socket_port_map_destroy(&socket_port->map, free);
-	free(socket_port);
-	return rc;
-	
-}
-
-/** Binds the socket to the port.
- *
- * The address port is used if set, a free port is used if not.
- *
- * @param[in] local_sockets The local sockets to be searched.
- * @param[in,out] global_sockets The global sockets to be updated.
- * @param[in] socket_id	The new socket identifier.
- * @param[in] addr	The address to be bound to.
- * @param[in] addrlen	The address length.
- * @param[in] free_ports_start The minimum free port.
- * @param[in] free_ports_end The maximum free port.
- * @param[in] last_used_port The last used free port.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket was not found.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		EADDRINUSE if the port is already in use.
- * @return		Other error codes as defined for the
- *			socket_bind_free_port() function.
- * @return		Other error codes as defined for the
- *			socket_bind_insert() function.
- */
-int
-socket_bind(socket_cores_t *local_sockets, socket_ports_t *global_sockets,
-    int socket_id, void *addr, size_t addrlen, int free_ports_start,
-    int free_ports_end, int last_used_port)
-{
-	socket_core_t *socket;
-	socket_port_t *socket_port;
-	struct sockaddr *address;
-	struct sockaddr_in *address_in;
-
-	if (addrlen < sizeof(struct sockaddr))
-		return EINVAL;
-
-	address = (struct sockaddr *) addr;
-	switch (address->sa_family) {
-	case AF_INET:
-		if (addrlen != sizeof(struct sockaddr_in))
-			return EINVAL;
-		
-		address_in = (struct sockaddr_in *) addr;
-		/* Find the socket */
-		socket = socket_cores_find(local_sockets, socket_id);
-		if (!socket)
-			return ENOTSOCK;
-		
-		/* Bind a free port? */
-		if (address_in->sin_port <= 0)
-			return socket_bind_free_port(global_sockets, socket,
-			     free_ports_start, free_ports_end, last_used_port);
-		
-		/* Try to find the port */
-		socket_port = socket_ports_find(global_sockets,
-		    ntohs(address_in->sin_port));
-		if (socket_port) {
-			/* Already used */
-			return EADDRINUSE;
-		}
-		
-		/* If bound */
-		if (socket->port) {
-			/* Release the port */
-			socket_port_release(global_sockets, socket);
-		}
-		socket->port = -1;
-		
-		return socket_bind_insert(global_sockets, socket,
-		    ntohs(address_in->sin_port));
-		
-	case AF_INET6:
-		// TODO IPv6
-		break;
-	}
-	
-	return EAFNOSUPPORT;
-}
-
-/** Binds the socket to a free port.
- *
- * The first free port is used.
- *
- * @param[in,out] global_sockets The global sockets to be updated.
- * @param[in,out] socket The socket to be bound.
- * @param[in] free_ports_start The minimum free port.
- * @param[in] free_ports_end The maximum free port.
- * @param[in] last_used_port The last used free port.
- * @return		EOK on success.
- * @return		ENOTCONN if no free port was found.
- * @return		Other error codes as defined for the
- *			socket_bind_insert() function.
- */
-int
-socket_bind_free_port(socket_ports_t *global_sockets, socket_core_t *socket,
-    int free_ports_start, int free_ports_end, int last_used_port)
-{
-	int index;
-
-	/* From the last used one */
-	index = last_used_port;
-	
-	do {
-		++index;
-		
-		/* Till the range end */
-		if (index >= free_ports_end) {
-			/* Start from the range beginning */
-			index = free_ports_start - 1;
-			do {
-				++index;
-				/* Till the last used one */
-				if (index >= last_used_port) {
-					/* None found */
-					return ENOTCONN;
-				}
-			} while (socket_ports_find(global_sockets, index));
-			
-			/* Found, break immediately */
-			break;
-		}
-		
-	} while (socket_ports_find(global_sockets, index));
-	
-	return socket_bind_insert(global_sockets, socket, index);
-}
-
-/** Tries to find a new free socket identifier.
- *
- * @param[in] local_sockets The local sockets to be searched.
- * @param[in] positive	A value indicating whether a positive identifier is
- *			requested. A negative identifier is requested if set to
- *			false.
- * @return		The new socket identifier.
- * @return		ELIMIT if there is no socket identifier available.
- */
-static int socket_generate_new_id(socket_cores_t *local_sockets, int positive)
-{
-	int socket_id;
-	int count;
-
-	count = 0;
-#if 0
-	socket_id = socket_globals.last_id;
-#endif
-	do {
-		if (count < SOCKET_ID_TRIES) {
-			socket_id = rand() % INT_MAX;
-			++count;
-		} else if (count == SOCKET_ID_TRIES) {
-			socket_id = 1;
-			++count;
-		/* Only this branch for last_id */
-		} else {
-			if (socket_id < INT_MAX) {
-				++ socket_id;
-#if 0
-			} else if(socket_globals.last_id) {
-				socket_globals.last_id = 0;
-				socket_id = 1;
-#endif
-			} else {
-				return ELIMIT;
-			}
-		}
-	} while (socket_cores_find(local_sockets,
-	    ((positive ? 1 : -1) * socket_id)));
-	
-//	last_id = socket_id
-	return socket_id;
-}
-
-/** Create a new socket.
- *
- * @param[in,out] local_sockets Local sockets to be updated.
- * @param[in]     sess          Application session.
- * @param[in]     specific_data Socket specific data.
- * @param[in,out] socket_id     New socket identifier. A new identifier
- *                              is chosen if set to zero or negative.
- *                              A negative identifier is chosen if set
- *                              to negative.
- *
- * @return EOK on success.
- * @return EINVAL if the socket_id parameter is NULL.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int socket_create(socket_cores_t *local_sockets, async_sess_t* sess,
-    void *specific_data, int *socket_id)
-{
-	socket_core_t *socket;
-	int positive;
-	int rc;
-
-	if (!socket_id)
-		return EINVAL;
-	
-	/* Store the socket */
-	if (*socket_id <= 0) {
-		positive = (*socket_id == 0);
-		*socket_id = socket_generate_new_id(local_sockets, positive);
-		if (*socket_id <= 0)
-			return *socket_id;
-		if (!positive)
-			*socket_id *= -1;
-	} else if(socket_cores_find(local_sockets, *socket_id)) {
-		return EEXIST;
-	}
-	
-	socket = (socket_core_t *) malloc(sizeof(*socket));
-	if (!socket)
-		return ENOMEM;
-	
-	/* Initialize */
-	socket->sess = sess;
-	socket->port = -1;
-	socket->key = NULL;
-	socket->key_length = 0;
-	socket->specific_data = specific_data;
-	
-	rc = dyn_fifo_initialize(&socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE);
-	if (rc != EOK) {
-		free(socket);
-		return rc;
-	}
-	socket->socket_id = *socket_id;
-	rc = socket_cores_add(local_sockets, socket->socket_id, socket);
-	if (rc < 0) {
-		dyn_fifo_destroy(&socket->accepted);
-		free(socket);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/** Destroy the socket.
- *
- * If the socket is bound, the port is released.
- * Release all buffered packets, call the release function and remove the
- * socket from the local sockets.
- *
- * @param[in]     sess           Packet server session.
- * @param[in]     socket_id      Socket identifier.
- * @param[in,out] local_sockets  Local sockets to be updated.
- * @param[in,out] global_sockets Global sockets to be updated.
- * @param[in]     socket_release Client release callback function.
- *
- * @return EOK on success.
- * @return ENOTSOCK if the socket is not found.
- *
- */
-int
-socket_destroy(async_sess_t *sess, int socket_id, socket_cores_t *local_sockets,
-    socket_ports_t *global_sockets,
-    void (*socket_release)(socket_core_t *socket))
-{
-	/* Find the socket */
-	socket_core_t *socket = socket_cores_find(local_sockets, socket_id);
-	if (!socket)
-		return ENOTSOCK;
-	
-	/* Destroy all accepted sockets */
-	int accepted_id;
-	while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0)
-		socket_destroy(sess, accepted_id, local_sockets,
-		    global_sockets, socket_release);
-	
-	socket_destroy_core(sess, socket, local_sockets, global_sockets,
-	    socket_release);
-	
-	return EOK;
-}
-
-/** Finds the bound port socket.
- *
- * @param[in] global_sockets The global sockets to be searched.
- * @param[in] port	The port number.
- * @param[in] key	The socket key identifier.
- * @param[in] key_length The socket key length.
- * @return		The found socket.
- * @return		NULL if no socket was found.
- */
-socket_core_t *
-socket_port_find(socket_ports_t *global_sockets, int port, const uint8_t *key,
-    size_t key_length)
-{
-	socket_port_t *socket_port;
-	socket_core_t **socket_ref;
-
-	socket_port = socket_ports_find(global_sockets, port);
-	if (socket_port && (socket_port->count > 0)) {
-		socket_ref = socket_port_map_find(&socket_port->map, key,
-		    key_length);
-		if (socket_ref)
-			return *socket_ref;
-	}
-	
-	return NULL;
-}
-
-/** Releases the socket port.
- *
- * If the socket is bound the port entry is released.
- * If there are no more port entries the port is release.
- *
- * @param[in] global_sockets The global sockets to be updated.
- * @param[in] socket	The socket to be unbound.
- */
-void
-socket_port_release(socket_ports_t *global_sockets, socket_core_t *socket)
-{
-	socket_port_t *socket_port;
-	socket_core_t **socket_ref;
-
-	if (!socket->port)
-		return;
-	
-	/* Find ports */
-	socket_port = socket_ports_find(global_sockets, socket->port);
-	if (socket_port) {
-		/* Find the socket */
-		socket_ref = socket_port_map_find(&socket_port->map,
-		    socket->key, socket->key_length);
-		
-		if (socket_ref) {
-			--socket_port->count;
-			
-			/* Release if empty */
-			if (socket_port->count <= 0) {
-				/* Destroy the map */
-				socket_port_map_destroy(&socket_port->map, free);
-				/* Release the port */
-				socket_ports_exclude(global_sockets,
-				    socket->port, free);
-			} else {
-				/* Remove */
-				socket_port_map_exclude(&socket_port->map,
-				    socket->key, socket->key_length, free);
-			}
-		}
-	}
-	
-	socket->port = 0;
-	socket->key = NULL;
-	socket->key_length = 0;
-}
-
-/** Adds the socket to an already bound port.
- *
- * @param[in] global_sockets The global sockets to be updated.
- * @param[in] port	The port number to be bound to.
- * @param[in] socket	The socket to be added.
- * @param[in] key	The socket key identifier.
- * @param[in] key_length The socket key length.
- * @return		EOK on success.
- * @return		ENOENT if the port is not already used.
- * @return		Other error codes as defined for the
- *			socket_port_add_core() function.
- */
-int
-socket_port_add(socket_ports_t *global_sockets, int port,
-    socket_core_t *socket, const uint8_t *key, size_t key_length)
-{
-	socket_port_t *socket_port;
-	int rc;
-
-	/* Find ports */
-	socket_port = socket_ports_find(global_sockets, port);
-	if (!socket_port)
-		return ENOENT;
-	
-	/* Add the socket */
-	rc = socket_port_add_core(socket_port, socket, key, key_length);
-	if (rc != EOK)
-		return rc;
-	
-	socket->port = port;
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/lib/nettl/Makefile
===================================================================
--- uspace/lib/nettl/Makefile	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/nettl/Makefile	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -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 cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/nettl/include/nettl/amap.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,103 @@
+/*
+ * 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 <adt/list.h>
+#include <inet/endpoint.h>
+#include <nettl/portrng.h>
+#include <loc.h>
+
+/** Port range for (remote endpoint, local address) */
+typedef struct {
+	/** Link to amap_t.repla */
+	link_t lamap;
+	/** 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 {
+	/** Link to amap_t.laddr */
+	link_t lamap;
+	/** Local address */
+	inet_addr_t laddr;
+	/** Port range */
+	portrng_t *portrng;
+} amap_laddr_t;
+
+/** Port range for local link */
+typedef struct {
+	/** Link to amap_t.llink */
+	link_t lamap;
+	/** 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 */
+	/** Nothing specified (listen on all local adresses) */
+	portrng_t *unspec;
+} 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_match(amap_t *, inet_ep2_t *, void **);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/nettl/include/nettl/portrng.h
===================================================================
--- uspace/lib/nettl/include/nettl/portrng.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/nettl/include/nettl/portrng.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,71 @@
+/*
+ * 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 <stdbool.h>
+#include <stdint.h>
+
+/** Allocated port */
+typedef struct {
+	/** Link to portrng_t.used */
+	link_t lprng;
+	/** Port number */
+	uint16_t pn;
+	/** User argument */
+	void *arg;
+} portrng_port_t;
+
+typedef struct {
+	list_t used; /* of portrng_port_t */
+} 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(portrng_t *, uint16_t, void *,
+    portrng_flags_t, uint16_t *);
+extern int portrng_find_port(portrng_t *, uint16_t, void **);
+extern void portrng_free_port(portrng_t *, uint16_t);
+extern bool portrng_empty(portrng_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/nettl/src/amap.c
===================================================================
--- uspace/lib/nettl/src/amap.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/nettl/src/amap.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,572 @@
+/*
+ * 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 <adt/list.h>
+#include <errno.h>
+#include <inet/addr.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;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_create()");
+
+	map = calloc(1, sizeof(amap_t));
+	if (map == NULL)
+		return ENOMEM;
+
+	rc = portrng_create(&map->unspec);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		free(map);
+		return ENOMEM;
+	}
+
+	list_initialize(&map->repla);
+	list_initialize(&map->laddr);
+	list_initialize(&map->llink);
+
+	*rmap = map;
+	return EOK;
+}
+
+void amap_destroy(amap_t *map)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_destroy()");
+	free(map);
+}
+
+/** Find exact repla */
+static int amap_repla_find(amap_t *map, inet_ep_t *rep, inet_addr_t *la,
+    amap_repla_t **rrepla)
+{
+	char *sraddr, *sladdr;
+
+	(void) inet_addr_format(&rep->addr, &sraddr);
+	(void) inet_addr_format(la, &sladdr);
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_repla_find(): rep=(%s,%" PRIu16
+	    ") la=%s", sraddr, rep->port, sladdr);
+	free(sraddr);
+	free(sladdr);
+
+	list_foreach(map->repla, lamap, amap_repla_t, repla) {
+		(void) inet_addr_format(&repla->rep.addr, &sraddr);
+		(void) inet_addr_format(&repla->laddr, &sladdr);
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_repla_find(): "
+		    "compare to rep=(%s, %" PRIu16 ") la=%s",
+		    sraddr, repla->rep.port, sladdr);
+		free(sraddr);
+		free(sladdr);
+		if (inet_addr_compare(&repla->rep.addr, &rep->addr) &&
+		    repla->rep.port == rep->port &&
+		    inet_addr_compare(&repla->laddr, la)) {
+			*rrepla = repla;
+			return EOK;
+		}
+	}
+
+	*rrepla = NULL;
+	return ENOENT;
+}
+
+static int amap_repla_insert(amap_t *map, inet_ep_t *rep, inet_addr_t *la,
+    amap_repla_t **rrepla)
+{
+	amap_repla_t *repla;
+	int rc;
+
+	repla = calloc(1, sizeof(amap_repla_t));
+	if (repla == NULL) {
+		*rrepla = NULL;
+		return ENOMEM;
+	}
+
+	rc = portrng_create(&repla->portrng);
+	if (rc != EOK) {
+		free(repla);
+		return ENOMEM;
+	}
+
+	repla->rep = *rep;
+	repla->laddr = *la;
+	list_append(&repla->lamap, &map->repla);
+
+	*rrepla = repla;
+	return EOK;
+}
+
+static void amap_repla_remove(amap_t *map, amap_repla_t *repla)
+{
+	list_remove(&repla->lamap);
+	portrng_destroy(repla->portrng);
+	free(repla);
+}
+
+/** Find exact laddr */
+static int amap_laddr_find(amap_t *map, inet_addr_t *addr,
+    amap_laddr_t **rladdr)
+{
+	list_foreach(map->laddr, lamap, amap_laddr_t, laddr) {
+		if (inet_addr_compare(&laddr->laddr, addr)) {
+			*rladdr = laddr;
+			return EOK;
+		}
+	}
+
+	*rladdr = NULL;
+	return ENOENT;
+}
+
+static int amap_laddr_insert(amap_t *map, inet_addr_t *addr,
+    amap_laddr_t **rladdr)
+{
+	amap_laddr_t *laddr;
+	int rc;
+
+	laddr = calloc(1, sizeof(amap_laddr_t));
+	if (laddr == NULL) {
+		*rladdr = NULL;
+		return ENOMEM;
+	}
+
+	rc = portrng_create(&laddr->portrng);
+	if (rc != EOK) {
+		free(laddr);
+		return ENOMEM;
+	}
+
+	laddr->laddr = *addr;
+	list_append(&laddr->lamap, &map->laddr);
+
+	*rladdr = laddr;
+	return EOK;
+}
+
+static void amap_laddr_remove(amap_t *map, amap_laddr_t *laddr)
+{
+	list_remove(&laddr->lamap);
+	portrng_destroy(laddr->portrng);
+	free(laddr);
+}
+
+/** Find exact llink */
+static int amap_llink_find(amap_t *map, sysarg_t link_id,
+    amap_llink_t **rllink)
+{
+	list_foreach(map->llink, lamap, amap_llink_t, llink) {
+		if (llink->llink == link_id) {
+			*rllink = llink;
+			return EOK;
+		}
+	}
+
+	*rllink = NULL;
+	return ENOENT;
+}
+
+static int amap_llink_insert(amap_t *map, sysarg_t link_id,
+    amap_llink_t **rllink)
+{
+	amap_llink_t *llink;
+	int rc;
+
+	llink = calloc(1, sizeof(amap_llink_t));
+	if (llink == NULL) {
+		*rllink = NULL;
+		return ENOMEM;
+	}
+
+	rc = portrng_create(&llink->portrng);
+	if (rc != EOK) {
+		free(llink);
+		return ENOMEM;
+	}
+
+	llink->llink = link_id;
+	list_append(&llink->lamap, &map->llink);
+
+	*rllink = llink;
+	return EOK;
+}
+
+static void amap_llink_remove(amap_t *map, amap_llink_t *llink)
+{
+	list_remove(&llink->lamap);
+	portrng_destroy(llink->portrng);
+	free(llink);
+}
+
+static int amap_insert_repla(amap_t *map, inet_ep2_t *epp, void *arg,
+    amap_flags_t flags, inet_ep2_t *aepp)
+{
+	amap_repla_t *repla;
+	inet_ep2_t mepp;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_insert_repla()");
+
+	rc = amap_repla_find(map, &epp->remote, &epp->local.addr, &repla);
+	if (rc != EOK) {
+		/* New repla */
+		rc = amap_repla_insert(map, &epp->remote, &epp->local.addr,
+		    &repla);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			return rc;
+		}
+	}
+
+	mepp = *epp;
+
+	rc = portrng_alloc(repla->portrng, epp->local.port, arg, flags,
+	    &mepp.local.port);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	*aepp = mepp;
+	return EOK;
+}
+
+static int amap_insert_laddr(amap_t *map, inet_ep2_t *epp, void *arg,
+    amap_flags_t flags, inet_ep2_t *aepp)
+{
+	amap_laddr_t *laddr;
+	inet_ep2_t mepp;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_insert_laddr()");
+
+	rc = amap_laddr_find(map, &epp->local.addr, &laddr);
+	if (rc != EOK) {
+		/* New laddr */
+		rc = amap_laddr_insert(map, &epp->local.addr, &laddr);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			return rc;
+		}
+	}
+
+	mepp = *epp;
+
+	rc = portrng_alloc(laddr->portrng, epp->local.port, arg, flags,
+	    &mepp.local.port);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	*aepp = mepp;
+	return EOK;
+}
+
+static int amap_insert_llink(amap_t *map, inet_ep2_t *epp, void *arg,
+    amap_flags_t flags, inet_ep2_t *aepp)
+{
+	amap_llink_t *llink;
+	inet_ep2_t mepp;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_insert_llink()");
+
+	rc = amap_llink_find(map, epp->local_link, &llink);
+	if (rc != EOK) {
+		/* New llink */
+		rc = amap_llink_insert(map, epp->local_link, &llink);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			return rc;
+		}
+	}
+
+	mepp = *epp;
+
+	rc = portrng_alloc(llink->portrng, epp->local.port, arg, flags,
+	    &mepp.local.port);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	*aepp = mepp;
+	return EOK;
+}
+
+static int amap_insert_unspec(amap_t *map, inet_ep2_t *epp, void *arg,
+    amap_flags_t flags, inet_ep2_t *aepp)
+{
+	inet_ep2_t mepp;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_insert_unspec()");
+	mepp = *epp;
+
+	rc = portrng_alloc(map->unspec, epp->local.port, arg, flags,
+	    &mepp.local.port);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	*aepp = mepp;
+	return EOK;
+}
+
+/** 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)
+{
+	bool raddr, rport, laddr, llink;
+	inet_ep2_t mepp;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_insert()");
+
+	mepp = *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_DEBUG2, "amap_insert: "
+		    "determine local address");
+		rc = inet_get_srcaddr(&epp->remote.addr, 0, &mepp.local.addr);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_insert: "
+			    "cannot determine local address");
+			return rc;
+		}
+	} else {
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_insert: "
+		    "local address specified or remote address not specified");
+	}
+
+	raddr = !inet_addr_is_any(&mepp.remote.addr);
+	rport = mepp.remote.port != inet_port_any;
+	laddr = !inet_addr_is_any(&mepp.local.addr);
+	llink = mepp.local_link != 0;
+
+	if (raddr && rport && laddr && !llink) {
+		return amap_insert_repla(map, &mepp, arg, flags, aepp);
+	} else if (!raddr && !rport && laddr && !llink) {
+		return amap_insert_laddr(map, &mepp, arg, flags, aepp);
+	} else if (!raddr && !rport && !laddr && llink) {
+		return amap_insert_llink(map, &mepp, arg, flags, aepp);
+	} else if (!raddr && !rport && !laddr && !llink) {
+		return amap_insert_unspec(map, &mepp, arg, flags, aepp);
+	} else {
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_insert: invalid "
+		    "combination of raddr=%d rport=%d laddr=%d llink=%d",
+		    raddr, rport, laddr, llink);
+		return EINVAL;
+	}
+
+	return EOK;
+}
+
+static void amap_remove_repla(amap_t *map, inet_ep2_t *epp)
+{
+	amap_repla_t *repla;
+	int rc;
+
+	rc = amap_repla_find(map, &epp->remote, &epp->local.addr, &repla);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_remove_repla: not found");
+		return;
+	}
+
+	portrng_free_port(repla->portrng, epp->local.port);
+
+	if (portrng_empty(repla->portrng))
+		amap_repla_remove(map, repla);
+}
+
+static void amap_remove_laddr(amap_t *map, inet_ep2_t *epp)
+{
+	amap_laddr_t *laddr;
+	int rc;
+
+	rc = amap_laddr_find(map, &epp->local.addr, &laddr);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_remove_laddr: not found");
+		return;
+	}
+
+	portrng_free_port(laddr->portrng, epp->local.port);
+
+	if (portrng_empty(laddr->portrng))
+		amap_laddr_remove(map, laddr);
+}
+
+static void amap_remove_llink(amap_t *map, inet_ep2_t *epp)
+{
+	amap_llink_t *llink;
+	int rc;
+
+	rc = amap_llink_find(map, epp->local_link, &llink);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_remove_llink: not found");
+		return;
+	}
+
+	portrng_free_port(llink->portrng, epp->local.port);
+
+	if (portrng_empty(llink->portrng))
+		amap_llink_remove(map, llink);
+}
+
+static void amap_remove_unspec(amap_t *map, inet_ep2_t *epp)
+{
+	portrng_free_port(map->unspec, epp->local.port);
+}
+
+void amap_remove(amap_t *map, inet_ep2_t *epp)
+{
+	bool raddr, rport, laddr, llink;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_remove()");
+
+	raddr = !inet_addr_is_any(&epp->remote.addr);
+	rport = epp->remote.port != inet_port_any;
+	laddr = !inet_addr_is_any(&epp->local.addr);
+	llink = epp->local_link != 0;
+
+	if (raddr && rport && laddr && !llink) {
+		amap_remove_repla(map, epp);
+	} else if (!raddr && !rport && laddr && !llink) {
+		amap_remove_laddr(map, epp);
+	} else if (!raddr && !rport && !laddr && llink) {
+		amap_remove_llink(map, epp);
+	} else if (!raddr && !rport && !laddr && !llink) {
+		amap_remove_unspec(map, epp);
+	} else {
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_remove: invalid "
+		    "combination of raddr=%d rport=%d laddr=%d llink=%d",
+		    raddr, rport, laddr, llink);
+		return;
+	}
+}
+
+/** Find association matching an endpoint pair.
+ *
+ * Used to find which association to deliver a datagram to.
+ *
+ * @param map	Association map
+ * @param epp	Endpoint pair
+ * @param rarg	Place to store user argument for the matching association.
+ *
+ * @return	EOK on success, ENOENT if not found.
+ */
+int amap_find_match(amap_t *map, inet_ep2_t *epp, void **rarg)
+{
+	int rc;
+	amap_repla_t *repla;
+	amap_laddr_t *laddr;
+	amap_llink_t *llink;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "amap_find_match(llink=%zu)",
+	    epp->local_link);
+
+	/* Remode endpoint, local address */
+	rc = amap_repla_find(map, &epp->remote, &epp->local.addr, &repla);
+	if (rc == EOK) {
+		rc = portrng_find_port(repla->portrng, epp->local.port,
+		    rarg);
+		if (rc == EOK) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG2, "Matched repla / "
+			    "port %" PRIu16, epp->local.port);
+			return EOK;
+		}
+	}
+
+	/* Local address */
+	rc = amap_laddr_find(map, &epp->local.addr, &laddr);
+	if (rc == EOK) {
+		rc = portrng_find_port(laddr->portrng, epp->local.port,
+		    rarg);
+		if (rc == EOK) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG2, "Matched laddr / "
+			    "port %" PRIu16, epp->local.port);
+			return EOK;
+		}
+	}
+
+	/* Local link */
+	rc = amap_llink_find(map, epp->local_link, &llink);
+	if (epp->local_link != 0 && rc == EOK) {
+		rc = portrng_find_port(llink->portrng, epp->local.port,
+		    rarg);
+		if (rc == EOK) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG2, "Matched llink / "
+			    "port %" PRIu16, epp->local.port);
+			return EOK;
+		}
+	}
+
+	/* Unspecified */
+	rc = portrng_find_port(map->unspec, epp->local.port, rarg);
+	if (rc == EOK) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "Matched unspec / port %" PRIu16,
+		    epp->local.port);
+		return EOK;
+	}
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "No match.");
+	return ENOENT;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/nettl/src/portrng.c
===================================================================
--- uspace/lib/nettl/src/portrng.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/lib/nettl/src/portrng.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,169 @@
+/*
+ * 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 <adt/list.h>
+#include <errno.h>
+#include <inet/endpoint.h>
+#include <nettl/portrng.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <io/log.h>
+
+int portrng_create(portrng_t **rpr)
+{
+	portrng_t *pr;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_create() - begin");
+
+	pr = calloc(1, sizeof(portrng_t));
+	if (pr == NULL)
+		return ENOMEM;
+
+	list_initialize(&pr->used);
+	*rpr = pr;
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_create() - end");
+	return EOK;
+}
+
+void portrng_destroy(portrng_t *pr)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_destroy()");
+	assert(list_empty(&pr->used));
+	free(pr);
+}
+
+int portrng_alloc(portrng_t *pr, uint16_t pnum, void *arg,
+    portrng_flags_t flags, uint16_t *apnum)
+{
+	portrng_port_t *p;
+	uint32_t i;
+	bool found;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_alloc() - begin");
+
+	if (pnum == inet_port_any) {
+
+		for (i = inet_port_dyn_lo; i <= inet_port_dyn_hi; i++) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG2, "trying %" PRIu32, i);
+			found = false;
+			list_foreach(pr->used, lprng, portrng_port_t, port) {
+				if (port->pn == pnum) {
+					found = true;
+					break;
+				}
+			}
+
+			if (!found) {
+				pnum = i;
+				break;
+			}
+		}
+
+		if (pnum == inet_port_any) {
+			/* No free port found */
+			return ENOENT;
+		}
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "selected %" PRIu16, pnum);
+	} else {
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "user asked for %" PRIu16, pnum);
+
+		if ((flags & pf_allow_system) == 0 &&
+		    pnum < inet_port_user_lo) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG2, "system port not allowed");
+			return EINVAL;
+		}
+
+		list_foreach(pr->used, lprng, portrng_port_t, port) {
+			if (port->pn == pnum) {
+				log_msg(LOG_DEFAULT, LVL_DEBUG2, "port already used");
+				return EEXISTS;
+			}
+		}
+	}
+
+	p = calloc(1, sizeof(portrng_port_t));
+	if (p == NULL)
+		return ENOMEM;
+
+	p->pn = pnum;
+	p->arg = arg;
+	list_append(&p->lprng, &pr->used);
+	*apnum = pnum;
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_alloc() - end OK pn=%" PRIu16,
+	    pnum);
+	return EOK;
+}
+
+int portrng_find_port(portrng_t *pr, uint16_t pnum, void **rarg)
+{
+	list_foreach(pr->used, lprng, portrng_port_t, port) {
+		if (port->pn == pnum) {
+			*rarg = port->arg;
+			return EOK;
+		}
+	}
+
+	return ENOENT;
+}
+
+void portrng_free_port(portrng_t *pr, uint16_t pnum)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port() - begin");
+	list_foreach(pr->used, lprng, portrng_port_t, port) {
+		if (port->pn == pnum) {
+			list_remove(&port->lprng);
+			free(port);
+			return;
+		}
+	}
+
+	assert(false);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port() - end");
+}
+
+bool portrng_empty(portrng_t *pr)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_empty()");
+	return list_empty(&pr->used);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/lib/pcut/src/run.c
===================================================================
--- uspace/lib/pcut/src/run.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/pcut/src/run.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -73,8 +73,9 @@
 static int default_suite_initialized = 0;
 
-static void init_default_suite_when_needed() {
-	if (default_suite_initialized) {
+static void init_default_suite_when_needed(void)
+{
+	if (default_suite_initialized)
 		return;
-	}
+	
 	default_suite.id = -1;
 	default_suite.kind = PCUT_KIND_TESTSUITE;
@@ -91,11 +92,13 @@
  * @return Always a valid test suite item.
  */
-static pcut_item_t *pcut_find_parent_suite(pcut_item_t *it) {
+static pcut_item_t *pcut_find_parent_suite(pcut_item_t *it)
+{
 	while (it != NULL) {
-		if (it->kind == PCUT_KIND_TESTSUITE) {
+		if (it->kind == PCUT_KIND_TESTSUITE)
 			return it;
-		}
+		
 		it = it->previous;
 	}
+	
 	init_default_suite_when_needed();
 	return &default_suite;
@@ -106,8 +109,8 @@
  * @param func Function to run (can be NULL).
  */
-static void run_setup_teardown(pcut_setup_func_t func) {
-	if (func != NULL) {
+static void run_setup_teardown(pcut_setup_func_t func)
+{
+	if (func != NULL)
 		func();
-	}
 }
 
@@ -119,11 +122,11 @@
  * @param outcome Outcome of the current test.
  */
-static void leave_test(int outcome) {
+static void leave_test(int outcome)
+{
 	PCUT_DEBUG("leave_test(outcome=%d), will_exit=%s", outcome,
-		leave_means_exit ? "yes" : "no");
-	if (leave_means_exit) {
+	    leave_means_exit ? "yes" : "no");
+	if (leave_means_exit)
 		exit(outcome);
-	}
-
+	
 #ifndef PCUT_NO_LONG_JUMP
 	longjmp(start_test_jump, 1);
@@ -138,6 +141,8 @@
  * @param message Message describing the failure.
  */
-void pcut_failed_assertion(const char *message) {
+void pcut_failed_assertion(const char *message)
+{
 	static const char *prev_message = NULL;
+	
 	/*
 	 * The assertion failed. We need to abort the current test,
@@ -145,13 +150,12 @@
 	 * include running the tear-down routine.
 	 */
-	if (print_test_error) {
+	if (print_test_error)
 		pcut_print_fail_message(message);
-	}
-
+	
 	if (execute_teardown_on_failure) {
 		execute_teardown_on_failure = 0;
 		prev_message = message;
 		run_setup_teardown(current_suite->teardown_func);
-
+		
 		/* Tear-down was okay. */
 		if (report_test_result) {
@@ -165,7 +169,7 @@
 		}
 	}
-
+	
 	prev_message = NULL;
-
+	
 	leave_test(TEST_OUTCOME_FAIL); /* No return. */
 }
@@ -176,5 +180,6 @@
  * @return Error status (zero means success).
  */
-static int run_test(pcut_item_t *test) {
+static int run_test(pcut_item_t *test)
+{
 	/*
 	 * Set here as the returning point in case of test failure.
@@ -182,20 +187,19 @@
 	 * test execution.
 	 */
+	
 #ifndef PCUT_NO_LONG_JUMP
 	int test_finished = setjmp(start_test_jump);
-	if (test_finished) {
+	if (test_finished)
 		return 1;
-	}
 #endif
-
-	if (report_test_result) {
+	
+	if (report_test_result)
 		pcut_report_test_start(test);
-	}
-
+	
 	current_suite = pcut_find_parent_suite(test);
 	current_test = test;
-
+	
 	pcut_hook_before_test(test);
-
+	
 	/*
 	 * If anything goes wrong, execute the tear-down function
@@ -203,10 +207,10 @@
 	 */
 	execute_teardown_on_failure = 1;
-
+	
 	/*
 	 * Run the set-up function.
 	 */
 	run_setup_teardown(current_suite->setup_func);
-
+	
 	/*
 	 * The setup function was performed, it is time to run
@@ -214,5 +218,5 @@
 	 */
 	test->test_func();
-
+	
 	/*
 	 * Finally, run the tear-down function. We need to clear
@@ -221,14 +225,13 @@
 	execute_teardown_on_failure = 0;
 	run_setup_teardown(current_suite->teardown_func);
-
+	
 	/*
 	 * If we got here, it means everything went well with
 	 * this test.
 	 */
-	if (report_test_result) {
+	if (report_test_result)
 		pcut_report_test_done(current_test, TEST_OUTCOME_PASS,
-			NULL, NULL, NULL);
-	}
-
+		    NULL, NULL, NULL);
+	
 	return 0;
 }
@@ -242,16 +245,15 @@
  * @return Error status (zero means success).
  */
-int pcut_run_test_forked(pcut_item_t *test) {
-	int rc;
-
+int pcut_run_test_forked(pcut_item_t *test)
+{
 	report_test_result = 0;
 	print_test_error = 1;
 	leave_means_exit = 1;
-
-	rc = run_test(test);
-
+	
+	int rc = run_test(test);
+	
 	current_test = NULL;
 	current_suite = NULL;
-
+	
 	return rc;
 }
@@ -265,16 +267,15 @@
  * @return Error status (zero means success).
  */
-int pcut_run_test_single(pcut_item_t *test) {
-	int rc;
-
+int pcut_run_test_single(pcut_item_t *test)
+{
 	report_test_result = 1;
 	print_test_error = 0;
 	leave_means_exit = 0;
-
-	rc = run_test(test);
-
+	
+	int rc = run_test(test);
+	
 	current_test = NULL;
 	current_suite = NULL;
-
+	
 	return rc;
 }
@@ -285,16 +286,16 @@
  * @return Timeout in seconds.
  */
-int pcut_get_test_timeout(pcut_item_t *test) {
+int pcut_get_test_timeout(pcut_item_t *test)
+{
 	int timeout = PCUT_DEFAULT_TEST_TIMEOUT;
 	pcut_extra_t *extras = test->extras;
-
-
+	
 	while (extras->type != PCUT_EXTRA_LAST) {
-		if (extras->type == PCUT_EXTRA_TIMEOUT) {
+		if (extras->type == PCUT_EXTRA_TIMEOUT)
 			timeout = extras->timeout;
-		}
+		
 		extras++;
 	}
-
+	
 	return timeout;
 }
Index: uspace/lib/posix/include/posix/errno.h
===================================================================
--- uspace/lib/posix/include/posix/errno.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/posix/include/posix/errno.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -69,12 +69,10 @@
 extern int *__posix_errno(void);
 
-#define __TOP_ERRNO (-NO_DATA)
+#define __TOP_ERRNO (-EAGAIN)
 
 enum {
 	POSIX_E2BIG = __TOP_ERRNO + 1,
 	POSIX_EACCES = __TOP_ERRNO + 2,
-	POSIX_EADDRINUSE = -EADDRINUSE,
 	POSIX_EADDRNOTAVAIL = -EADDRNOTAVAIL,
-	POSIX_EAFNOSUPPORT = -EAFNOSUPPORT,
 	POSIX_EAGAIN = -EAGAIN,
 	POSIX_EALREADY = __TOP_ERRNO + 3,
@@ -88,5 +86,4 @@
 	POSIX_ECONNRESET = __TOP_ERRNO + 9,
 	POSIX_EDEADLK = __TOP_ERRNO + 10,
-	POSIX_EDESTADDRREQ = -EDESTADDRREQ,
 	POSIX_EDOM = __TOP_ERRNO + 11,
 	POSIX_EDQUOT = __TOP_ERRNO + 12,
@@ -97,5 +94,4 @@
 	POSIX_EIDRM = __TOP_ERRNO + 16,
 	POSIX_EILSEQ = __TOP_ERRNO + 17,
-	POSIX_EINPROGRESS = -EINPROGRESS,
 	POSIX_EINTR = -EINTR,
 	POSIX_EINVAL = -EINVAL,
@@ -114,5 +110,4 @@
 	POSIX_ENFILE = __TOP_ERRNO + 25,
 	POSIX_ENOBUFS = __TOP_ERRNO + 26,
-	POSIX_ENODATA = -NO_DATA,
 	POSIX_ENODEV = __TOP_ERRNO + 27,
 	POSIX_ENOENT = -ENOENT,
@@ -127,9 +122,7 @@
 	POSIX_ENOSTR = __TOP_ERRNO + 34,
 	POSIX_ENOSYS = __TOP_ERRNO + 35,
-	POSIX_ENOTCONN = -ENOTCONN,
 	POSIX_ENOTDIR = -ENOTDIR,
 	POSIX_ENOTEMPTY = -ENOTEMPTY,
 	POSIX_ENOTRECOVERABLE = __TOP_ERRNO + 36,
-	POSIX_ENOTSOCK = -ENOTSOCK,
 	POSIX_ENOTSUP = -ENOTSUP,
 	POSIX_ENOTTY = __TOP_ERRNO + 37,
@@ -141,5 +134,4 @@
 	POSIX_EPIPE = __TOP_ERRNO + 41,
 	POSIX_EPROTO = __TOP_ERRNO + 42,
-	POSIX_EPROTONOSUPPORT = -EPROTONOSUPPORT,
 	POSIX_EPROTOTYPE = __TOP_ERRNO + 43,
 	POSIX_ERANGE = -ERANGE,
@@ -153,4 +145,12 @@
 	POSIX_EWOULDBLOCK = __TOP_ERRNO + 51,
 	POSIX_EXDEV = -EXDEV,
+	POSIX_EINPROGRESS = __TOP_ERRNO + 52,
+	POSIX_ENOTSOCK = __TOP_ERRNO + 53,
+	POSIX_EDESTADDRREQ = __TOP_ERRNO + 54,
+	POSIX_EPROTONOSUPPORT = __TOP_ERRNO + 55,
+	POSIX_EAFNOSUPPORT = __TOP_ERRNO + 56,
+	POSIX_EADDRINUSE = __TOP_ERRNO + 57,
+	POSIX_ENOTCONN = __TOP_ERRNO + 58,
+	POSIX_ENODATA = __TOP_ERRNO + 59,
 };
 
Index: uspace/lib/posix/include/posix/stdlib.h
===================================================================
--- uspace/lib/posix/include/posix/stdlib.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/posix/include/posix/stdlib.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -116,7 +116,10 @@
 
 /* Memory Allocation */
-extern void *__POSIX_DEF__(malloc)(size_t size);
-extern void *__POSIX_DEF__(calloc)(size_t nelem, size_t elsize);
-extern void *__POSIX_DEF__(realloc)(void *ptr, size_t size);
+extern void *__POSIX_DEF__(malloc)(size_t size)
+    __attribute__((malloc));
+extern void *__POSIX_DEF__(calloc)(size_t nelem, size_t elsize)
+    __attribute__((malloc));
+extern void *__POSIX_DEF__(realloc)(void *ptr, size_t size)
+    __attribute__((warn_unused_result));
 extern void __POSIX_DEF__(free)(void *ptr);
 
Index: uspace/lib/posix/include/posix/string.h
===================================================================
--- uspace/lib/posix/include/posix/string.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/posix/include/posix/string.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -67,7 +67,10 @@
 /* From mem.h */
 // #define bzero(ptr, len)  memset((ptr), 0, (len))
-extern void *memset(void *, int, size_t);
-extern void *memcpy(void *, const void *, size_t);
-extern void *memmove(void *, const void *, size_t);
+extern void *memset(void *, int, size_t)
+    __attribute__((nonnull(1)));
+extern void *memcpy(void *, const void *, size_t)
+    __attribute__((nonnull(1, 2)));
+extern void *memmove(void *, const void *, size_t)
+    __attribute__((nonnull(1, 2)));
 
 
Index: uspace/lib/posix/source/signal.c
===================================================================
--- uspace/lib/posix/source/signal.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/posix/source/signal.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -382,5 +382,5 @@
  * Raise all unblocked previously queued signals.
  */
-static void _dequeue_unblocked_signals()
+static void _dequeue_unblocked_signals(void)
 {
 	link_t *iterator = _signal_queue.head.next;
Index: uspace/lib/usbdev/src/hub.c
===================================================================
--- uspace/lib/usbdev/src/hub.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/lib/usbdev/src/hub.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -151,5 +151,5 @@
  * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
  * @retval EBUSY Failed reserving default USB address.
- * @retval ENOTCONN Problem connecting to the host controller via USB pipe.
+ * @retval ENXIO Problem connecting to the host controller via USB pipe.
  * @retval ESTALL Problem communication with device (either SET_ADDRESS
  *	request or requests for descriptors when creating match ids).
@@ -184,5 +184,5 @@
 	    &dev_conn, hc_conn, USB_ADDRESS_DEFAULT);
 	if (rc != EOK) {
-		rc = ENOTCONN;
+		rc = ENXIO;
 		goto leave_release_free_address;
 	}
@@ -192,5 +192,5 @@
 	rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
 	if (rc != EOK) {
-		rc = ENOTCONN;
+		rc = ENXIO;
 		goto leave_release_free_address;
 	}
@@ -217,5 +217,5 @@
 	rc = usb_pipe_register(&ctrl_pipe, 0);
 	if (rc != EOK) {
-		rc = ENOTCONN;
+		rc = ENXIO;
 		goto leave_release_default_address;
 	}
@@ -278,5 +278,5 @@
 	if (rc != EOK) {
 		/* The child function is already created. */
-		rc = EDESTADDRREQ;
+		rc = EIO;
 		goto leave_release_free_address;
 	}
Index: uspace/srv/bd/sata_bd/sata_bd.c
===================================================================
--- uspace/srv/bd/sata_bd/sata_bd.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/bd/sata_bd/sata_bd.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -147,5 +147,5 @@
  *
  */
-static int get_sata_disks()
+static int get_sata_disks(void)
 {
 	devman_handle_t root_fun;
Index: uspace/srv/hid/remcons/remcons.c
===================================================================
--- uspace/srv/hid/remcons/remcons.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/hid/remcons/remcons.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -44,7 +44,7 @@
 #include <fibril_synch.h>
 #include <task.h>
-#include <net/in.h>
-#include <net/inet.h>
-#include <net/socket.h>
+#include <inet/addr.h>
+#include <inet/endpoint.h>
+#include <inet/tcp.h>
 #include <io/console.h>
 #include <inttypes.h>
@@ -99,4 +99,14 @@
 };
 
+static void remcons_new_conn(tcp_listener_t *lst, tcp_conn_t *conn);
+
+static tcp_listen_cb_t listen_cb = {
+	.new_conn = remcons_new_conn
+};
+
+static tcp_cb_t conn_cb = {
+	.connected = NULL
+};
+
 static telnet_user_t *srv_to_user(con_srv_t *srv)
 {
@@ -111,6 +121,6 @@
 
 	/* Force character mode. */
-	send(user->socket, (void *)telnet_force_character_mode_command,
-	    telnet_force_character_mode_command_count, 0);
+	(void) tcp_conn_send(user->conn, (void *)telnet_force_character_mode_command,
+	    telnet_force_character_mode_command_count);
 
 	return EOK;
@@ -272,11 +282,20 @@
 }
 
-/** Fibril for each accepted socket.
- *
- * @param arg Corresponding @c telnet_user_t structure.
- */
-static int network_user_fibril(void *arg)
-{
-	telnet_user_t *user = arg;
+/** Handle network connection.
+ *
+ * @param lst  Listener
+ * @param conn Connection
+ */
+static void remcons_new_conn(tcp_listener_t *lst, tcp_conn_t *conn)
+{
+	telnet_user_t *user = telnet_user_create(conn);
+	assert(user);
+
+	con_srvs_init(&user->srvs);
+	user->srvs.ops = &con_ops;
+	user->srvs.sarg = user;
+	user->srvs.abort_timeout = 1000;
+
+	telnet_user_add(user);
 
 	int rc = loc_service_register(user->service_name, &user->service_id);
@@ -284,19 +303,19 @@
 		telnet_user_error(user, "Unable to register %s with loc: %s.",
 		    user->service_name, str_error(rc));
-		return EOK;
+		return;
 	}
 
 	telnet_user_log(user, "Service %s registerd with id %" PRIun ".",
 	    user->service_name, user->service_id);
-	
+
 	fid_t spawn_fibril = fibril_create(spawn_task_fibril, user);
 	assert(spawn_fibril);
 	fibril_add_ready(spawn_fibril);
-	
+
 	/* Wait for all clients to exit. */
 	fibril_mutex_lock(&user->guard);
 	while (!user_can_be_destroyed_no_lock(user)) {
 		if (user->task_finished) {
-			closesocket(user->socket);
+			user->conn = NULL;
 			user->socket_closed = true;
 			user->srvs.aborted = true;
@@ -310,5 +329,5 @@
 	}
 	fibril_mutex_unlock(&user->guard);
-	
+
 	rc = loc_service_unregister(user->service_id);
 	if (rc != EOK) {
@@ -320,82 +339,41 @@
 	telnet_user_log(user, "Destroying...");
 	telnet_user_destroy(user);
-
-	return EOK;
 }
 
 int main(int argc, char *argv[])
 {
-	int port = 2223;
-	
+	int rc;
+	tcp_listener_t *lst;
+	tcp_t *tcp;
+	inet_ep_t ep;
+
 	async_set_client_connection(client_connection);
-	int rc = loc_server_register(NAME);
+	rc = loc_server_register(NAME);
 	if (rc != EOK) {
 		fprintf(stderr, "%s: Unable to register server\n", NAME);
 		return rc;
 	}
-	
-	struct sockaddr_in addr;
-	
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	
-	rc = inet_pton(AF_INET, "127.0.0.1", (void *)
-	    &addr.sin_addr.s_addr);
-	if (rc != EOK) {
-		fprintf(stderr, "Error parsing network address: %s.\n",
-		    str_error(rc));
-		return 2;
-	}
-
-	int listen_sd = socket(PF_INET, SOCK_STREAM, 0);
-	if (listen_sd < 0) {
-		fprintf(stderr, "Error creating listening socket: %s.\n",
-		    str_error(listen_sd));
-		return 3;
-	}
-
-	rc = bind(listen_sd, (struct sockaddr *) &addr, sizeof(addr));
-	if (rc != EOK) {
-		fprintf(stderr, "Error binding socket: %s.\n",
-		    str_error(rc));
-		return 4;
-	}
-
-	rc = listen(listen_sd, BACKLOG_SIZE);
-	if (rc != EOK) {
-		fprintf(stderr, "listen() failed: %s.\n", str_error(rc));
-		return 5;
+
+	rc = tcp_create(&tcp);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Error initializing TCP.\n", NAME);
+		return rc;
+	}
+
+	inet_ep_init(&ep);
+	ep.port = 2223;
+
+	rc = tcp_listener_create(tcp, &ep, &listen_cb, NULL, &conn_cb, NULL,
+	    &lst);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Error creating listener.\n", NAME);
+		return rc;
 	}
 
 	printf("%s: HelenOS Remote console service\n", NAME);
 	task_retval(0);
-
-	while (true) {
-		struct sockaddr_in raddr;
-		socklen_t raddr_len = sizeof(raddr);
-		int conn_sd = accept(listen_sd, (struct sockaddr *) &raddr,
-		    &raddr_len);
-
-		if (conn_sd < 0) {
-			fprintf(stderr, "accept() failed: %s.\n",
-			    str_error(rc));
-			continue;
-		}
-
-		telnet_user_t *user = telnet_user_create(conn_sd);
-		assert(user);
-
-		con_srvs_init(&user->srvs);
-		user->srvs.ops = &con_ops;
-		user->srvs.sarg = user;
-		user->srvs.abort_timeout = 1000;
-
-		telnet_user_add(user);
-
-		fid_t fid = fibril_create(network_user_fibril, user);
-		assert(fid);
-		fibril_add_ready(fid);
-	}
-
+	async_manager();
+
+	/* Not reached */
 	return 0;
 }
Index: uspace/srv/hid/remcons/remcons.h
===================================================================
--- uspace/srv/hid/remcons/remcons.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/hid/remcons/remcons.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -38,5 +38,4 @@
 #define NAME       "remcons"
 #define NAMESPACE  "term"
-#define BACKLOG_SIZE  5
 
 #endif
Index: uspace/srv/hid/remcons/user.c
===================================================================
--- uspace/srv/hid/remcons/user.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/hid/remcons/user.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -44,7 +44,5 @@
 #include <fibril_synch.h>
 #include <task.h>
-#include <net/in.h>
-#include <net/inet.h>
-#include <net/socket.h>
+#include <inet/tcp.h>
 #include <io/console.h>
 #include <inttypes.h>
@@ -58,8 +56,8 @@
 /** Create new telnet user.
  *
- * @param socket Socket the user communicates through.
+ * @param conn Incoming connection.
  * @return New telnet user or NULL when out of memory.
  */
-telnet_user_t *telnet_user_create(int socket)
+telnet_user_t *telnet_user_create(tcp_conn_t *conn)
 {
 	static int telnet_user_id_counter = 0;
@@ -78,5 +76,5 @@
 	}
 
-	user->socket = socket;
+	user->conn = conn;
 	user->service_id = (service_id_t) -1;
 	prodcons_initialize(&user->in_events);
@@ -193,13 +191,18 @@
 	/* No more buffered data? */
 	if (user->socket_buffer_len <= user->socket_buffer_pos) {
-		int recv_length = recv(user->socket, user->socket_buffer, BUFFER_SIZE, 0);
-		if ((recv_length == 0) || (recv_length == ENOTCONN)) {
+		int rc;
+		size_t recv_length;
+
+		rc = tcp_conn_recv_wait(user->conn, user->socket_buffer,
+		    BUFFER_SIZE, &recv_length);
+		if (rc != EOK)
+			return rc;
+
+		if (recv_length == 0) {
 			user->socket_closed = true;
 			user->srvs.aborted = true;
 			return ENOENT;
 		}
-		if (recv_length < 0) {
-			return recv_length;
-		}
+
 		user->socket_buffer_len = recv_length;
 		user->socket_buffer_pos = 0;
@@ -359,5 +362,5 @@
 
 
-	int rc = send(user->socket, converted, converted_size, 0);
+	int rc = tcp_conn_send(user->conn, converted, converted_size);
 	free(converted);
 
Index: uspace/srv/hid/remcons/user.h
===================================================================
--- uspace/srv/hid/remcons/user.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/hid/remcons/user.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -38,4 +38,5 @@
 #include <adt/prodcons.h>
 #include <fibril_synch.h>
+#include <inet/tcp.h>
 #include <inttypes.h>
 #include <io/con_srv.h>
@@ -51,6 +52,6 @@
 	/** Internal id, used for creating locfs entries. */
 	int id;
-	/** Associated socket. */
-	int socket;
+	/** Associated connection. */
+	tcp_conn_t *conn;
 	/** Location service id assigned to the virtual terminal. */
 	service_id_t service_id;
@@ -80,5 +81,5 @@
 } telnet_user_t;
 
-extern telnet_user_t *telnet_user_create(int);
+extern telnet_user_t *telnet_user_create(tcp_conn_t *);
 extern void telnet_user_add(telnet_user_t *);
 extern void telnet_user_destroy(telnet_user_t *);
Index: uspace/srv/hid/rfb/main.c
===================================================================
--- uspace/srv/hid/rfb/main.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/hid/rfb/main.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -150,12 +150,4 @@
 }
 
-static int socket_fibril(void *unused)
-{
-	rfb_accept(&rfb);
-	
-	/* Not reached */
-	return EOK;
-}
-
 int main(int argc, char **argv)
 {
@@ -267,12 +259,4 @@
 	}
 	
-	fid_t fib = fibril_create(socket_fibril, NULL);
-	if (!fib) {
-		fprintf(stderr, NAME ": Unable to create socket fibril.\n");
-		return 2;
-	}
-	
-	fibril_add_ready(fib);
-	
 	printf("%s: Accepting connections\n", NAME);
 	task_retval(0);
Index: uspace/srv/hid/rfb/rfb.c
===================================================================
--- uspace/srv/hid/rfb/rfb.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/hid/rfb/rfb.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -31,4 +31,7 @@
 #include <stdlib.h>
 #include <fibril_synch.h>
+#include <inet/addr.h>
+#include <inet/endpoint.h>
+#include <inet/tcp.h>
 #include <inttypes.h>
 #include <str.h>
@@ -38,9 +41,15 @@
 #include <io/log.h>
 
-#include <net/in.h>
-#include <net/inet.h>
-#include <net/socket.h>
-
 #include "rfb.h"
+
+static void rfb_new_conn(tcp_listener_t *, tcp_conn_t *);
+
+static tcp_listen_cb_t listen_cb = {
+	.new_conn = rfb_new_conn
+};
+
+static tcp_cb_t conn_cb = {
+	.connected = NULL
+};
 
 /** Buffer for receiving the request. */
@@ -53,15 +62,18 @@
 
 /** Receive one character (with buffering) */
-static int recv_char(int fd, char *c)
-{
+static int recv_char(tcp_conn_t *conn, char *c)
+{
+	size_t nrecv;
+	int rc;
+
 	if (rbuf_out == rbuf_in) {
 		rbuf_out = 0;
 		rbuf_in = 0;
 		
-		ssize_t rc = recv(fd, rbuf, BUFFER_SIZE, 0);
-		if (rc <= 0)
+		rc = tcp_conn_recv_wait(conn, rbuf, BUFFER_SIZE, &nrecv);
+		if (rc != EOK)
 			return rc;
 		
-		rbuf_in = rc;
+		rbuf_in = nrecv;
 	}
 	
@@ -71,8 +83,8 @@
 
 /** Receive count characters (with buffering) */
-static int recv_chars(int fd, char *c, size_t count)
+static int recv_chars(tcp_conn_t *conn, char *c, size_t count)
 {
 	for (size_t i = 0; i < count; i++) {
-		int rc = recv_char(fd, c);
+		int rc = recv_char(conn, c);
 		if (rc != EOK)
 			return rc;
@@ -82,9 +94,9 @@
 }
 
-static int recv_skip_chars(int fd, size_t count)
+static int recv_skip_chars(tcp_conn_t *conn, size_t count)
 {
 	for (size_t i = 0; i < count; i++) {
 		char c;
-		int rc = recv_char(fd, &c);
+		int rc = recv_char(conn, &c);
 		if (rc != EOK)
 			return rc;
@@ -204,8 +216,8 @@
 }
 
-static int recv_message(int conn_sd, char type, void *buf, size_t size)
+static int recv_message(tcp_conn_t *conn, char type, void *buf, size_t size)
 {
 	memcpy(buf, &type, 1);
-	return recv_chars(conn_sd, ((char *) buf) + 1, size -1);
+	return recv_chars(conn, ((char *) buf) + 1, size -1);
 }
 
@@ -477,5 +489,6 @@
 }
 
-static int rfb_send_framebuffer_update(rfb_t *rfb, int conn_sd, bool incremental)
+static int rfb_send_framebuffer_update(rfb_t *rfb, tcp_conn_t *conn,
+    bool incremental)
 {
 	fibril_mutex_lock(&rfb->lock);
@@ -540,5 +553,5 @@
 	
 	if (!rfb->pixel_format.true_color) {
-		int rc = send(conn_sd, send_palette, send_palette_size, 0);
+		int rc = tcp_conn_send(conn, send_palette, send_palette_size);
 		if (rc != EOK) {
 			free(buf);
@@ -547,5 +560,5 @@
 	}
 	
-	int rc = send(conn_sd, buf, buf_size, 0);
+	int rc = tcp_conn_send(conn, buf, buf_size);
 	free(buf);
 	
@@ -580,8 +593,8 @@
 }
 
-static void rfb_socket_connection(rfb_t *rfb, int conn_sd)
+static void rfb_socket_connection(rfb_t *rfb, tcp_conn_t *conn)
 {
 	/* Version handshake */
-	int rc = send(conn_sd, "RFB 003.008\n", 12, 0);
+	int rc = tcp_conn_send(conn, "RFB 003.008\n", 12);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server version %d", rc);
@@ -590,5 +603,5 @@
 	
 	char client_version[12];
-	rc = recv_chars(conn_sd, client_version, 12);
+	rc = recv_chars(conn, client_version, 12);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client version: %d", rc);
@@ -607,5 +620,5 @@
 	sec_types[0] = 1; /* length */
 	sec_types[1] = RFB_SECURITY_NONE;
-	rc = send(conn_sd, sec_types, 2, 0);
+	rc = tcp_conn_send(conn, sec_types, 2);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN,
@@ -615,5 +628,5 @@
 	
 	char selected_sec_type = 0;
-	rc = recv_char(conn_sd, &selected_sec_type);
+	rc = recv_char(conn, &selected_sec_type);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving security type: %d", rc);
@@ -626,5 +639,5 @@
 	}
 	uint32_t security_result = RFB_SECURITY_HANDSHAKE_OK;
-	rc = send(conn_sd, &security_result, sizeof(uint32_t), 0);
+	rc = tcp_conn_send(conn, &security_result, sizeof(uint32_t));
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending security result: %d", rc);
@@ -634,5 +647,5 @@
 	/* Client init */
 	char shared_flag;
-	rc = recv_char(conn_sd, &shared_flag);
+	rc = recv_char(conn, &shared_flag);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client init: %d", rc);
@@ -657,5 +670,5 @@
 	memcpy(server_init->name, rfb->name, name_length);
 	fibril_mutex_unlock(&rfb->lock);
-	rc = send(conn_sd, server_init, msg_length, 0);
+	rc = tcp_conn_send(conn, server_init, msg_length);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server init: %d", rc);
@@ -665,5 +678,5 @@
 	while (true) {
 		char message_type = 0;
-		rc = recv_char(conn_sd, &message_type);
+		rc = recv_char(conn, &message_type);
 		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_WARN,
@@ -680,5 +693,5 @@
 		switch (message_type) {
 		case RFB_CMSG_SET_PIXEL_FORMAT:
-			recv_message(conn_sd, message_type, &spf, sizeof(spf));
+			recv_message(conn, message_type, &spf, sizeof(spf));
 			rfb_pixel_format_to_host(&spf.pixel_format, &spf.pixel_format);
 			log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received SetPixelFormat message");
@@ -690,10 +703,10 @@
 			break;
 		case RFB_CMSG_SET_ENCODINGS:
-			recv_message(conn_sd, message_type, &se, sizeof(se));
+			recv_message(conn, message_type, &se, sizeof(se));
 			rfb_set_encodings_to_host(&se, &se);
 			log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received SetEncodings message");
 			for (uint16_t i = 0; i < se.count; i++) {
 				int32_t encoding = 0;
-				rc = recv_chars(conn_sd, (char *) &encoding, sizeof(int32_t));
+				rc = recv_chars(conn, (char *) &encoding, sizeof(int32_t));
 				if (rc != EOK)
 					return;
@@ -707,25 +720,25 @@
 			break;
 		case RFB_CMSG_FRAMEBUFFER_UPDATE_REQUEST:
-			recv_message(conn_sd, message_type, &fbur, sizeof(fbur));
+			recv_message(conn, message_type, &fbur, sizeof(fbur));
 			rfb_framebuffer_update_request_to_host(&fbur, &fbur);
 			log_msg(LOG_DEFAULT, LVL_DEBUG2,
 			    "Received FramebufferUpdateRequest message");
-			rfb_send_framebuffer_update(rfb, conn_sd, fbur.incremental);
+			rfb_send_framebuffer_update(rfb, conn, fbur.incremental);
 			break;
 		case RFB_CMSG_KEY_EVENT:
-			recv_message(conn_sd, message_type, &ke, sizeof(ke));
+			recv_message(conn, message_type, &ke, sizeof(ke));
 			rfb_key_event_to_host(&ke, &ke);
 			log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received KeyEvent message");
 			break;
 		case RFB_CMSG_POINTER_EVENT:
-			recv_message(conn_sd, message_type, &pe, sizeof(pe));
+			recv_message(conn, message_type, &pe, sizeof(pe));
 			rfb_pointer_event_to_host(&pe, &pe);
 			log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received PointerEvent message");
 			break;
 		case RFB_CMSG_CLIENT_CUT_TEXT:
-			recv_message(conn_sd, message_type, &cct, sizeof(cct));
+			recv_message(conn, message_type, &cct, sizeof(cct));
 			rfb_client_cut_text_to_host(&cct, &cct);
 			log_msg(LOG_DEFAULT, LVL_DEBUG2, "Received ClientCutText message");
-			recv_skip_chars(conn_sd, cct.length);
+			recv_skip_chars(conn, cct.length);
 			break;
 		default:
@@ -737,64 +750,45 @@
 }
 
-int rfb_listen(rfb_t *rfb, uint16_t port) {
-	struct sockaddr_in addr;
-	
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	
-	int rc = inet_pton(AF_INET, "127.0.0.1", (void *)
-	    &addr.sin_addr.s_addr);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error parsing network address (%s)",
-		    str_error(rc));
-		return rc;
-	}
-
-	int listen_sd = socket(PF_INET, SOCK_STREAM, 0);
-	if (listen_sd < 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating listening socket (%s)",
-		    str_error(listen_sd));
-		return rc;
-	}
-	
-	rc = bind(listen_sd, (struct sockaddr *) &addr, sizeof(addr));
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Error binding socket (%s)",
-		    str_error(rc));
-		return rc;
-	}
-	
-	rc = listen(listen_sd, 2);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "listen() failed (%s)", str_error(rc));
-		return rc;
-	}
-	
-	rfb->listen_sd = listen_sd;
+int rfb_listen(rfb_t *rfb, uint16_t port)
+{
+	tcp_t *tcp = NULL;
+	tcp_listener_t *lst = NULL;
+	inet_ep_t ep;
+	int rc;
+	
+	rc = tcp_create(&tcp);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error initializing TCP.");
+		goto error;
+	}
+	
+	inet_ep_init(&ep);
+	ep.port = port;
+	
+	rc = tcp_listener_create(tcp, &ep, &listen_cb, rfb, &conn_cb, rfb,
+	    &lst);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating listener.");
+		goto error;
+	}
+	
+	rfb->tcp = tcp;
+	rfb->lst = lst;
 	
 	return EOK;
-}
-
-void rfb_accept(rfb_t *rfb)
-{
-	while (true) {
-		struct sockaddr_in raddr;
-		socklen_t raddr_len = sizeof(raddr);
-		int conn_sd = accept(rfb->listen_sd, (struct sockaddr *) &raddr,
-		    &raddr_len);
-		
-		if (conn_sd < 0) {
-			log_msg(LOG_DEFAULT, LVL_WARN, "accept() failed (%s)",
-			    str_error(conn_sd));
-			continue;
-		}
-		
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "Connection accepted");
-		
-		rbuf_out = 0;
-		rbuf_in = 0;
-		
-		rfb_socket_connection(rfb, conn_sd);
-		closesocket(conn_sd);
-	}
-}
+error:
+	tcp_listener_destroy(lst);
+	tcp_destroy(tcp);
+	return rc;
+}
+
+static void rfb_new_conn(tcp_listener_t *lst, tcp_conn_t *conn)
+{
+	rfb_t *rfb = (rfb_t *)tcp_listener_userptr(lst);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Connection accepted");
+
+	rbuf_out = 0;
+	rbuf_in = 0;
+
+	rfb_socket_connection(rfb, conn);
+}
Index: uspace/srv/hid/rfb/rfb.h
===================================================================
--- uspace/srv/hid/rfb/rfb.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/hid/rfb/rfb.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -30,4 +30,5 @@
 #define RFB_H__
 
+#include <inet/tcp.h>
 #include <io/pixelmap.h>
 #include <fibril_synch.h>
@@ -151,5 +152,6 @@
 	rfb_pixel_format_t pixel_format;
 	const char *name;
-	int listen_sd;
+	tcp_t *tcp;
+	tcp_listener_t *lst;
 	pixelmap_t framebuffer;
 	rfb_rectangle_t damage_rect;
@@ -165,5 +167,4 @@
 extern int rfb_set_size(rfb_t *, uint16_t, uint16_t);
 extern int rfb_listen(rfb_t *, uint16_t);
-extern void rfb_accept(rfb_t *);
 
 #endif
Index: uspace/srv/klog/klog.c
===================================================================
--- uspace/srv/klog/klog.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/klog/klog.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -51,5 +51,5 @@
 #include <io/logctl.h>
 
-#define NAME       "klog"
+#define NAME  "klog"
 
 typedef size_t __attribute__ ((aligned(1))) unaligned_size_t;
@@ -98,5 +98,5 @@
  *
  */
-static void producer()
+static void producer(void)
 {
 	int read = klog_read(buffer, BUFFER_SIZE);
Index: uspace/srv/net/dhcp/dhcp.c
===================================================================
--- uspace/srv/net/dhcp/dhcp.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/dhcp/dhcp.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -37,4 +37,5 @@
 #include <adt/list.h>
 #include <bitops.h>
+#include <byteorder.h>
 #include <errno.h>
 #include <fibril_synch.h>
@@ -562,7 +563,4 @@
 	}
 
-	/* XXX Work around multiple simultaneous sessions issue */
-	dhcp_transport_fini(&dlink->dt);
-
 	log_msg(LOG_DEFAULT, LVL_NOTE, "%s: Successfully configured.",
 	    dlink->link_info.name);
Index: uspace/srv/net/dhcp/transport.c
===================================================================
--- uspace/srv/net/dhcp/transport.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/dhcp/transport.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -36,4 +36,5 @@
 
 #include <bitops.h>
+#include <errno.h>
 #include <inet/addr.h>
 #include <inet/dnsr.h>
@@ -41,7 +42,4 @@
 #include <io/log.h>
 #include <loc.h>
-#include <net/in.h>
-#include <net/inet.h>
-#include <net/socket.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -67,19 +65,26 @@
 } dhcp_offer_t;
 
-static int dhcp_recv_fibril(void *);
+static void dhcp_recv_msg(udp_assoc_t *, udp_rmsg_t *);
+static void dhcp_recv_err(udp_assoc_t *, udp_rerr_t *);
+static void dhcp_link_state(udp_assoc_t *, udp_link_state_t);
+
+static udp_cb_t dhcp_transport_cb = {
+	.recv_msg = dhcp_recv_msg,
+	.recv_err = dhcp_recv_err,
+	.link_state = dhcp_link_state
+};
 
 int dhcp_send(dhcp_transport_t *dt, void *msg, size_t size)
 {
-	struct sockaddr_in addr;
+	inet_ep_t ep;
 	int rc;
 
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(dhcp_server_port);
-	addr.sin_addr.s_addr = htonl(addr32_broadcast_all_hosts);
+	inet_ep_init(&ep);
+	ep.port = dhcp_server_port;
+	inet_addr_set(addr32_broadcast_all_hosts, &ep.addr);
 
-	rc = sendto(dt->fd, msg, size, 0,
-	    (struct sockaddr *)&addr, sizeof(addr));
+	rc = udp_assoc_send_msg(dt->assoc, &ep, msg, size);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Sending failed");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed sending message");
 		return rc;
 	}
@@ -88,29 +93,35 @@
 }
 
-static int dhcp_recv_msg(dhcp_transport_t *dt, void **rmsg, size_t *rsize)
+static void dhcp_recv_msg(udp_assoc_t *assoc, udp_rmsg_t *rmsg)
 {
-	struct sockaddr_in src_addr;
-	socklen_t src_addr_size;
-	size_t recv_size;
+	dhcp_transport_t *dt;
+	size_t s;
 	int rc;
 
-	if (dt->fd < 0) {
-		/* Terminated */
-		return EIO;
+	log_msg(LOG_DEFAULT, LVL_NOTE, "dhcp_recv_msg()");
+
+	dt = (dhcp_transport_t *)udp_assoc_userptr(assoc);
+	s = udp_rmsg_size(rmsg);
+	if (s > MAX_MSG_SIZE)
+		s = MAX_MSG_SIZE; /* XXX */
+
+	rc = udp_rmsg_read(rmsg, 0, msgbuf, s);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error receiving message.");
+		return;
 	}
 
-	src_addr_size = sizeof(src_addr);
-	rc = recvfrom(dt->fd, msgbuf, MAX_MSG_SIZE, 0,
-	    (struct sockaddr *)&src_addr, &src_addr_size);
-	if (rc < 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "recvfrom failed (%d)", rc);
-		return rc;
-	}
+	log_msg(LOG_DEFAULT, LVL_NOTE, "dhcp_recv_msg() - call recv_cb");
+	dt->recv_cb(dt->cb_arg, msgbuf, s);
+}
 
-	recv_size = (size_t)rc;
-	*rmsg = msgbuf;
-	*rsize = recv_size;
+static void dhcp_recv_err(udp_assoc_t *assoc, udp_rerr_t *rerr)
+{
+	log_msg(LOG_DEFAULT, LVL_WARN, "Ignoring ICMP error");
+}
 
-	return EOK;
+static void dhcp_link_state(udp_assoc_t *assoc, udp_link_state_t ls)
+{
+	log_msg(LOG_DEFAULT, LVL_NOTE, "Link state change");
 }
 
@@ -118,23 +129,17 @@
     dhcp_recv_cb_t recv_cb, void *arg)
 {
-	int fd;
-	struct sockaddr_in laddr;
-	int fid;
+	udp_t *udp = NULL;
+	udp_assoc_t *assoc = NULL;
+	inet_ep2_t epp;
 	int rc;
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcptransport_init()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcp_transport_init()");
 
-	laddr.sin_family = AF_INET;
-	laddr.sin_port = htons(dhcp_client_port);
-	laddr.sin_addr.s_addr = INADDR_ANY;
+	inet_ep2_init(&epp);
+	epp.local.addr.version = ip_v4;
+	epp.local.port = dhcp_client_port;
+	epp.local_link = link_id;
 
-	fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	if (fd < 0) {
-		rc = EIO;
-		goto error;
-	}
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Bind socket.");
-	rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
+	rc = udp_create(&udp);
 	if (rc != EOK) {
 		rc = EIO;
@@ -142,6 +147,5 @@
 	}
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Set socket options");
-	rc = setsockopt(fd, SOL_SOCKET, SO_IPLINK, &link_id, sizeof(link_id));
+	rc = udp_assoc_create(udp, &epp, &dhcp_transport_cb, dt, &assoc);
 	if (rc != EOK) {
 		rc = EIO;
@@ -149,20 +153,13 @@
 	}
 
-	dt->fd = fd;
+	dt->udp = udp;
+	dt->assoc = assoc;
 	dt->recv_cb = recv_cb;
 	dt->cb_arg = arg;
 
-	fid = fibril_create(dhcp_recv_fibril, dt);
-	if (fid == 0) {
-		rc = ENOMEM;
-		goto error;
-	}
-
-	dt->recv_fid = fid;
-	fibril_add_ready(fid);
-
 	return EOK;
 error:
-	closesocket(fd);
+	udp_assoc_destroy(assoc);
+	udp_destroy(udp);
 	return rc;
 }
@@ -170,26 +167,6 @@
 void dhcp_transport_fini(dhcp_transport_t *dt)
 {
-	closesocket(dt->fd);
-	dt->fd = -1;
-}
-
-static int dhcp_recv_fibril(void *arg)
-{
-	dhcp_transport_t *dt = (dhcp_transport_t *)arg;
-	void *msg;
-	size_t size = (size_t) -1;
-	int rc;
-
-	while (true) {
-		rc = dhcp_recv_msg(dt, &msg, &size);
-		if (rc != EOK)
-			break;
-
-		assert(size != (size_t) -1);
-
-		dt->recv_cb(dt->cb_arg, msg, size);
-	}
-
-	return EOK;
+	udp_assoc_destroy(dt->assoc);
+	udp_destroy(dt->udp);
 }
 
Index: uspace/srv/net/dhcp/transport.h
===================================================================
--- uspace/srv/net/dhcp/transport.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/dhcp/transport.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -38,4 +38,5 @@
 #define TRANSPORT_H
 
+#include <inet/udp.h>
 #include <ipc/loc.h>
 #include <sys/types.h>
@@ -47,12 +48,12 @@
 
 struct dhcp_transport {
-	/** Transport socket */
-	int fd;
+	/** UDP */
+	udp_t *udp;
+	/** UDP association */
+	udp_assoc_t *assoc;
 	/** Receive callback */
 	dhcp_recv_cb_t recv_cb;
 	/** Callback argument */
 	void *cb_arg;
-	/** Receive fibril ID */
-	int recv_fid;
 };
 
Index: uspace/srv/net/dnsrsrv/transport.c
===================================================================
--- uspace/srv/net/dnsrsrv/transport.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/dnsrsrv/transport.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -37,8 +37,8 @@
 #include <errno.h>
 #include <fibril_synch.h>
+#include <inet/addr.h>
+#include <inet/endpoint.h>
+#include <inet/udp.h>
 #include <io/log.h>
-#include <net/in.h>
-#include <net/inet.h>
-#include <net/socket.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -72,6 +72,6 @@
 
 static uint8_t recv_buf[RECV_BUF_SIZE];
-static fid_t recv_fid;
-static int transport_fd = -1;
+static udp_t *transport_udp;
+static udp_assoc_t *transport_assoc;
 
 /** Outstanding requests */
@@ -79,42 +79,39 @@
 static FIBRIL_MUTEX_INITIALIZE(treq_lock);
 
-static int transport_recv_fibril(void *arg);
+static void transport_recv_msg(udp_assoc_t *, udp_rmsg_t *);
+static void transport_recv_err(udp_assoc_t *, udp_rerr_t *);
+static void transport_link_state(udp_assoc_t *, udp_link_state_t);
+
+static udp_cb_t transport_cb = {
+	.recv_msg = transport_recv_msg,
+	.recv_err = transport_recv_err,
+	.link_state = transport_link_state
+};
 
 int transport_init(void)
 {
-	struct sockaddr_in laddr;
-	int fd;
-	fid_t fid;
+	inet_ep2_t epp;
 	int rc;
 
-	laddr.sin_family = AF_INET;
-	laddr.sin_port = htons(12345);
-	laddr.sin_addr.s_addr = INADDR_ANY;
-
-	fd = -1;
-
-	fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	if (fd < 0) {
+	inet_ep2_init(&epp);
+
+	rc = udp_create(&transport_udp);
+	if (rc != EOK) {
 		rc = EIO;
 		goto error;
 	}
 
-	rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
-	if (rc != EOK)
-		goto error;
-
-	transport_fd = fd;
-
-	fid = fibril_create(transport_recv_fibril, NULL);
-	if (fid == 0)
-		goto error;
-
-	fibril_add_ready(fid);
-	recv_fid = fid;
+	rc = udp_assoc_create(transport_udp, &epp, &transport_cb, NULL,
+	    &transport_assoc);
+	if (rc != EOK) {
+		rc = EIO;
+		goto error;
+	}
+
 	return EOK;
 error:
-	log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing network socket.");
-	if (fd >= 0)
-		closesocket(fd);
+	log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing network.");
+	udp_assoc_destroy(transport_assoc);
+	udp_destroy(transport_udp);
 	return rc;
 }
@@ -122,6 +119,6 @@
 void transport_fini(void)
 {
-	if (transport_fd >= 0)
-		closesocket(transport_fd);
+	udp_assoc_destroy(transport_assoc);
+	udp_destroy(transport_udp);
 }
 
@@ -182,7 +179,6 @@
 {
 	trans_req_t *treq = NULL;
-	struct sockaddr *saddr = NULL;
-	socklen_t saddrlen;
-	
+	inet_ep_t ep;
+
 	void *req_data;
 	size_t req_size;
@@ -190,20 +186,17 @@
 	if (rc != EOK)
 		goto error;
-	
-	rc = inet_addr_sockaddr(&dns_server_addr, DNS_SERVER_PORT,
-	    &saddr, &saddrlen);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		goto error;
-	}
-	
+
+	inet_ep_init(&ep);
+	ep.addr = dns_server_addr;
+	ep.port = DNS_SERVER_PORT;
+
 	size_t ntry = 0;
-	
+
 	while (ntry < REQ_RETRY_MAX) {
-		rc = sendto(transport_fd, req_data, req_size, 0,
-		    saddr, saddrlen);
+		rc = udp_assoc_send_msg(transport_assoc, &ep, req_data,
+		    req_size);
 		if (rc != EOK)
 			goto error;
-		
+
 		treq = treq_create(req);
 		if (treq == NULL) {
@@ -211,5 +204,5 @@
 			goto error;
 		}
-		
+
 		fibril_mutex_lock(&treq->done_lock);
 		while (treq->done != true) {
@@ -221,95 +214,86 @@
 			}
 		}
-		
+
 		fibril_mutex_unlock(&treq->done_lock);
-		
+
 		if (rc != ETIMEOUT)
 			break;
 	}
-	
+
 	if (ntry >= REQ_RETRY_MAX) {
 		rc = EIO;
 		goto error;
 	}
-	
+
 	if (treq->status != EOK) {
 		rc = treq->status;
 		goto error;
 	}
-	
+
 	*rresp = treq->resp;
 	treq_destroy(treq);
 	free(req_data);
-	free(saddr);
 	return EOK;
-	
+
 error:
 	if (treq != NULL)
 		treq_destroy(treq);
-	
+
 	free(req_data);
-	free(saddr);
 	return rc;
 }
 
-static int transport_recv_msg(dns_message_t **rresp)
-{
-	struct sockaddr_in src_addr;
-	socklen_t src_addr_size;
-	size_t recv_size;
-	dns_message_t *resp;
-	int rc;
-
-	src_addr_size = sizeof(src_addr);
-	rc = recvfrom(transport_fd, recv_buf, RECV_BUF_SIZE, 0,
-	    (struct sockaddr *)&src_addr, &src_addr_size);
-	if (rc < 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "recvfrom returns error - %d", rc);
-		goto error;
-	}
-
-	recv_size = (size_t)rc;
-
-	rc = dns_message_decode(recv_buf, recv_size, &resp);
-	if (rc != EOK) {
-		rc = EIO;
-		goto error;
-	}
-
-	*rresp = resp;
-	return EOK;
-
-error:
-	return rc;
-}
-
-static int transport_recv_fibril(void *arg)
+static void transport_recv_msg(udp_assoc_t *assoc, udp_rmsg_t *rmsg)
 {
 	dns_message_t *resp = NULL;
 	trans_req_t *treq;
+	size_t size;
+	inet_ep_t remote_ep;
 	int rc;
 
-	while (true) {
-		rc = transport_recv_msg(&resp);
-		if (rc != EOK)
-			continue;
-
-		assert(resp != NULL);
-
-		fibril_mutex_lock(&treq_lock);
-		treq = treq_match_resp(resp);
-		if (treq == NULL) {
-			fibril_mutex_unlock(&treq_lock);
-			continue;
-		}
-
-		list_remove(&treq->lreq);
+	size = udp_rmsg_size(rmsg);
+	if (size > RECV_BUF_SIZE)
+		size = RECV_BUF_SIZE; /* XXX */
+
+	rc = udp_rmsg_read(rmsg, 0, recv_buf, size);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error reading message.");
+		return;
+	}
+
+	udp_rmsg_remote_ep(rmsg, &remote_ep);
+	/* XXX */
+
+	rc = dns_message_decode(recv_buf, size, &resp);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error decoding message.");
+		return;
+	}
+
+	assert(resp != NULL);
+
+	fibril_mutex_lock(&treq_lock);
+	treq = treq_match_resp(resp);
+	if (treq == NULL) {
 		fibril_mutex_unlock(&treq_lock);
-
-		treq_complete(treq, resp);
-	}
-
-	return 0;
-}
+		return;
+	}
+
+	list_remove(&treq->lreq);
+	fibril_mutex_unlock(&treq_lock);
+
+	treq_complete(treq, resp);
+}
+
+static void transport_recv_err(udp_assoc_t *assoc, udp_rerr_t *rerr)
+{
+	log_msg(LOG_DEFAULT, LVL_WARN, "Ignoring ICMP error");
+}
+
+static void transport_link_state(udp_assoc_t *assoc, udp_link_state_t ls)
+{
+	log_msg(LOG_DEFAULT, LVL_NOTE, "Link state change");
+}
+
 
 /** @}
Index: uspace/srv/net/inetsrv/inet_link.c
===================================================================
--- uspace/srv/net/inetsrv/inet_link.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/inetsrv/inet_link.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -73,5 +73,5 @@
 {
 	memcpy(ip_addr, link_local_node_ip, 16);
-	
+
 	ip_addr[8] = mac_addr[0] ^ 0x02;
 	ip_addr[9] = mac_addr[1];
@@ -85,14 +85,19 @@
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()");
-	
+
 	int rc;
 	inet_packet_t packet;
-	
+	inet_link_t *ilink;
+
+	ilink = (inet_link_t *)iplink_get_userptr(iplink);
+
 	switch (ver) {
 	case ip_v4:
-		rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
+		rc = inet_pdu_decode(sdu->data, sdu->size, ilink->svc_id,
+		    &packet);
 		break;
 	case ip_v6:
-		rc = inet_pdu_decode6(sdu->data, sdu->size, &packet);
+		rc = inet_pdu_decode6(sdu->data, sdu->size, ilink->svc_id,
+		    &packet);
 		break;
 	default:
@@ -100,15 +105,16 @@
 		return EINVAL;
 	}
-	
+
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "failed decoding PDU");
 		return rc;
 	}
-	
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "inet_iplink_recv: link_id=%zu", packet.link_id);
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet()");
 	rc = inet_recv_packet(&packet);
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %d", rc);
 	free(packet.data);
-	
+
 	return rc;
 }
@@ -177,5 +183,5 @@
 	}
 
-	rc = iplink_open(ilink->sess, &inet_iplink_ev_ops, &ilink->iplink);
+	rc = iplink_open(ilink->sess, &inet_iplink_ev_ops, ilink, &ilink->iplink);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed opening IP link '%s'",
Index: uspace/srv/net/inetsrv/inetsrv.c
===================================================================
--- uspace/srv/net/inetsrv/inetsrv.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/inetsrv/inetsrv.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -469,8 +469,13 @@
 {
 	async_exch_t *exch = async_exchange_begin(client->sess);
-	
+
 	ipc_call_t answer;
-	aid_t req = async_send_1(exch, INET_EV_RECV, dgram->tos, &answer);
-	
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "inet_ev_recv: iplink=%zu",
+	    dgram->iplink);
+
+	aid_t req = async_send_2(exch, INET_EV_RECV, dgram->tos,
+	    dgram->iplink, &answer);
+
 	int rc = async_data_write_start(exch, &dgram->src, sizeof(inet_addr_t));
 	if (rc != EOK) {
@@ -479,5 +484,5 @@
 		return rc;
 	}
-	
+
 	rc = async_data_write_start(exch, &dgram->dest, sizeof(inet_addr_t));
 	if (rc != EOK) {
@@ -486,17 +491,17 @@
 		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);
-	
+
 	return (int) retval;
 }
@@ -511,5 +516,5 @@
 	if (proto == IP_PROTO_ICMP)
 		return icmp_recv(dgram);
-	
+
 	if (proto == IP_PROTO_ICMPV6)
 		return icmpv6_recv(dgram);
@@ -540,4 +545,5 @@
 		if (packet->offs == 0 && !packet->mf) {
 			/* It is complete deliver it immediately */
+			dgram.iplink = packet->link_id;
 			dgram.src = packet->src;
 			dgram.dest = packet->dest;
Index: uspace/srv/net/inetsrv/inetsrv.h
===================================================================
--- uspace/srv/net/inetsrv/inetsrv.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/inetsrv/inetsrv.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -75,4 +75,6 @@
 
 typedef struct {
+	/** Local link ID */
+	service_id_t link_id;
 	/** Source address */
 	inet_addr_t src;
Index: uspace/srv/net/inetsrv/pdu.c
===================================================================
--- uspace/srv/net/inetsrv/pdu.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/inetsrv/pdu.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -298,7 +298,8 @@
 /** Decode IPv4 datagram
  *
- * @param data   Serialized IPv4 datagram
- * @param size   Length of serialized IPv4 datagram
- * @param packet IP datagram structure to be filled
+ * @param data    Serialized IPv4 datagram
+ * @param size    Length of serialized IPv4 datagram
+ * @param link_id Link on which PDU was received
+ * @param packet  IP datagram structure to be filled
  *
  * @return EOK on success
@@ -307,5 +308,6 @@
  *
  */
-int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet)
+int inet_pdu_decode(void *data, size_t size, service_id_t link_id,
+    inet_packet_t *packet)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_pdu_decode()");
@@ -366,4 +368,5 @@
 	
 	memcpy(packet->data, (uint8_t *) data + data_offs, packet->size);
+	packet->link_id = link_id;
 	
 	return EOK;
@@ -372,7 +375,8 @@
 /** Decode IPv6 datagram
  *
- * @param data   Serialized IPv6 datagram
- * @param size   Length of serialized IPv6 datagram
- * @param packet IP datagram structure to be filled
+ * @param data    Serialized IPv6 datagram
+ * @param size    Length of serialized IPv6 datagram
+ * @param link_id Link on which PDU was received
+ * @param packet  IP datagram structure to be filled
  *
  * @return EOK on success
@@ -381,5 +385,6 @@
  *
  */
-int inet_pdu_decode6(void *data, size_t size, inet_packet_t *packet)
+int inet_pdu_decode6(void *data, size_t size, service_id_t link_id,
+    inet_packet_t *packet)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_pdu_decode6()");
@@ -457,5 +462,5 @@
 	
 	memcpy(packet->data, (uint8_t *) data + data_offs, packet->size);
-	
+	packet->link_id = link_id;
 	return EOK;
 }
Index: uspace/srv/net/inetsrv/pdu.h
===================================================================
--- uspace/srv/net/inetsrv/pdu.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/inetsrv/pdu.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -38,4 +38,5 @@
 #define INET_PDU_H_
 
+#include <loc.h>
 #include <sys/types.h>
 #include "inetsrv.h"
@@ -50,6 +51,6 @@
 extern int inet_pdu_encode6(inet_packet_t *, addr128_t, addr128_t, size_t,
     size_t, void **, size_t *, size_t *);
-extern int inet_pdu_decode(void *, size_t, inet_packet_t *);
-extern int inet_pdu_decode6(void *, size_t, inet_packet_t *);
+extern int inet_pdu_decode(void *, size_t, service_id_t, inet_packet_t *);
+extern int inet_pdu_decode6(void *, size_t, service_id_t, inet_packet_t *);
 
 extern int ndp_pdu_decode(inet_dgram_t *, ndp_packet_t *);
Index: uspace/srv/net/inetsrv/reass.c
===================================================================
--- uspace/srv/net/inetsrv/reass.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/inetsrv/reass.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -325,4 +325,6 @@
 		return ENOMEM;
 
+	/* XXX What if different fragments came from different link? */
+	dgram.iplink = frag->packet.link_id;
 	dgram.size = dgram_size;
 	dgram.src = frag->packet.src;
Index: uspace/srv/net/tcp/Makefile
===================================================================
--- uspace/srv/net/tcp/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/Makefile	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -28,6 +28,11 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+
+LIBS = \
+	$(LIBNETTL_PREFIX)/libnettl.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBNETTL_PREFIX)/include
+
 BINARY = tcp
 
@@ -39,6 +44,6 @@
 	rqueue.c \
 	segment.c \
+	service.c \
 	seq_no.c \
-	sock.c \
 	tcp.c \
 	test.c \
Index: uspace/srv/net/tcp/conn.c
===================================================================
--- uspace/srv/net/tcp/conn.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/conn.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,8 +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"
@@ -55,6 +57,8 @@
 #define TIME_WAIT_TIMEOUT	(2*MAX_SEGMENT_LIFETIME)
 
-LIST_INITIALIZE(conn_list);
-FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
+static LIST_INITIALIZE(conn_list);
+/** Taken after tcp_conn_t lock */
+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);
@@ -62,11 +66,24 @@
 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.
  *
- * @param lsock		Local socket (will be deeply copied)
- * @param fsock		Foreign socket (will be deeply copied)
+ * @param epp		Endpoint pair (will be deeply copied)
  * @return		New connection or NULL
  */
-tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
+tcp_conn_t *tcp_conn_new(inet_ep2_t *epp)
 {
 	tcp_conn_t *conn = NULL;
@@ -121,5 +138,5 @@
 	fibril_condvar_initialize(&conn->cstate_cv);
 
-	conn->cstate_cb = NULL;
+	conn->cb = NULL;
 
 	conn->cstate = st_listen;
@@ -128,7 +145,6 @@
 	conn->ap = ap_passive;
 	conn->fin_is_acked = false;
-	conn->ident.local = *lsock;
-	if (fsock != NULL)
-		conn->ident.foreign = *fsock;
+	if (epp != NULL)
+		conn->ident = *epp;
 
 	return conn;
@@ -184,5 +200,6 @@
 void tcp_conn_addref(tcp_conn_t *conn)
 {
-	log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p)", conn->name, conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p) before=%zu",
+	    conn->name, conn, atomic_get(&conn->refcnt));
 	atomic_inc(&conn->refcnt);
 }
@@ -196,5 +213,6 @@
 void tcp_conn_delref(tcp_conn_t *conn)
 {
-	log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p)", conn->name, conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p) before=%zu",
+	    conn->name, conn, atomic_get(&conn->refcnt));
 
 	if (atomic_predec(&conn->refcnt) == 0)
@@ -237,4 +255,7 @@
 
 	assert(conn->deleted == false);
+	conn->deleted = true;
+	conn->cb = NULL;
+	conn->cb_arg = NULL;
 	tcp_conn_delref(conn);
 }
@@ -244,10 +265,26 @@
  * 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);
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_add: conn=%p", conn);
+
+	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;
 }
 
@@ -259,4 +296,5 @@
 {
 	fibril_mutex_lock(&conn_list_lock);
+	amap_remove(amap, &conn->ident);
 	list_remove(&conn->link);
 	fibril_mutex_unlock(&conn_list_lock);
@@ -275,7 +313,7 @@
 
 	/* Run user callback function */
-	if (conn->cstate_cb != NULL) {
+	if (conn->cb != NULL && conn->cb->cstate_change != NULL) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - run user CB");
-		conn->cstate_cb(conn, conn->cstate_cb_arg);
+		conn->cb->cstate_change(conn, conn->cb_arg, old_state);
 	} else {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - no user CB");
@@ -284,4 +322,5 @@
 	assert(old_state != st_closed);
 	if (nstate == st_closed) {
+		tcp_conn_remove(conn);
 		/* Drop one reference for now being in closed state */
 		tcp_conn_delref(conn);
@@ -332,70 +371,37 @@
 }
 
-/** Match socket with pattern. */
-static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG2,
-	    "tcp_socket_match(sock=(%u), pat=(%u))", sock->port, patt->port);
-	
-	if ((!inet_addr_is_any(&patt->addr)) &&
-	    (!inet_addr_compare(&patt->addr, &sock->addr)))
-		return false;
-
-	if ((patt->port != TCP_PORT_ANY) &&
-	    (patt->port != sock->port))
-		return false;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG2, " -> match");
-
-	return true;
-}
-
-/** Match socket pair with pattern. */
-static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_sockpair_match(%p, %p)", sp, pattern);
-
-	if (!tcp_socket_match(&sp->local, &pattern->local))
-		return false;
-
-	if (!tcp_socket_match(&sp->foreign, &pattern->foreign))
-		return false;
-
-	return true;
-}
-
-/** Find connection structure for specified socket pair.
- *
- * A connection is uniquely identified by a socket pair. Look up our
- * connection map and return connection structure based on socket pair.
+/** Find connection structure for specified endpoint pair.
+ *
+ * A connection is uniquely identified by a endpoint pair. Look up our
+ * connection map and return connection structure based on endpoint pair.
  * The connection reference count is bumped by one.
  *
- * @param sp	Socket pair
+ * @param epp	Endpoint pair
  * @return	Connection structure or NULL if not found.
  */
-tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref(%p)", sp);
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG2, "compare conn (f:(%u), l:(%u))",
-	    sp->foreign.port, sp->local.port);
-	
+tcp_conn_t *tcp_conn_find_ref(inet_ep2_t *epp)
+{
+	int rc;
+	void *arg;
+	tcp_conn_t *conn;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref(%p)", epp);
+
 	fibril_mutex_lock(&conn_list_lock);
-	
-	list_foreach(conn_list, link, tcp_conn_t, conn) {
-		tcp_sockpair_t *csp = &conn->ident;
-		
-		log_msg(LOG_DEFAULT, LVL_DEBUG2, " - with (f:(%u), l:(%u))",
-		    csp->foreign.port, csp->local.port);
-		
-		if (tcp_sockpair_match(sp, csp)) {
-			tcp_conn_addref(conn);
-			fibril_mutex_unlock(&conn_list_lock);
-			return conn;
-		}
-	}
-	
+
+	rc = amap_find_match(amap, epp, &arg);
+	if (rc != EOK) {
+		assert(rc == ENOENT);
+		fibril_mutex_unlock(&conn_list_lock);
+		return NULL;
+	}
+
+	conn = (tcp_conn_t *)arg;
+	tcp_conn_addref(conn);
+
 	fibril_mutex_unlock(&conn_list_lock);
-	return NULL;
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref: got conn=%p",
+	    conn);
+	return conn;
 }
 
@@ -407,6 +413,6 @@
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
+	conn->reset = true;
 	tcp_conn_state_set(conn, st_closed);
-	conn->reset = true;
 
 	tcp_conn_tw_timer_clear(conn);
@@ -877,5 +883,4 @@
 	if (conn->fin_is_acked) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
-		tcp_conn_remove(conn);
 		tcp_conn_state_set(conn, st_closed);
 		return cp_done;
@@ -1006,5 +1011,9 @@
 
 	/* Signal to the receive function that new data has arrived */
-	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+	if (xfer_size > 0) {
+		fibril_condvar_broadcast(&conn->rcv_buf_cv);
+		if (conn->cb != NULL && conn->cb->recv_data != NULL)
+			conn->cb->recv_data(conn, conn->cb_arg);
+	}
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
@@ -1098,4 +1107,6 @@
 		conn->rcv_buf_fin = true;
 		fibril_condvar_broadcast(&conn->rcv_buf_cv);
+		if (conn->cb != NULL && conn->cb->recv_data != NULL)
+			conn->cb->recv_data(conn, conn->cb_arg);
 
 		tcp_segment_delete(seg);
@@ -1168,16 +1179,69 @@
  *
  * @param conn		Connection
- * @param seg		Segment
- */
-void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
-{
+ * @param epp		Endpoint pair on which segment was received
+ * @param seg		Segment
+ */
+void tcp_conn_segment_arrived(tcp_conn_t *conn, inet_ep2_t *epp,
+    tcp_segment_t *seg)
+{
+	inet_ep2_t aepp;
+	inet_ep2_t oldepp;
+	int rc;
+
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_segment_arrived(%p)",
 	    conn->name, seg);
 
+	tcp_conn_lock(conn);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");
+		tcp_unexpected_segment(epp, seg);
+		tcp_conn_unlock(conn);
+		return;
+	}
+
+	if (inet_addr_is_any(&conn->ident.remote.addr) ||
+	    conn->ident.remote.port == inet_port_any ||
+	    inet_addr_is_any(&conn->ident.local.addr)) {
+
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_segment_arrived: "
+		    "Changing connection ID, updating amap.");
+		oldepp = conn->ident;
+
+		/* Need to remove and re-insert connection with new identity */
+		fibril_mutex_lock(&conn_list_lock);
+
+		if (inet_addr_is_any(&conn->ident.remote.addr))
+			conn->ident.remote.addr = epp->remote.addr;
+
+		if (conn->ident.remote.port == inet_port_any)
+			conn->ident.remote.port = epp->remote.port;
+
+		if (inet_addr_is_any(&conn->ident.local.addr))
+			conn->ident.local.addr = epp->local.addr;
+
+		rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp);
+		if (rc != EOK) {
+			assert(rc != EEXISTS);
+			assert(rc == ENOMEM);
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
+			fibril_mutex_unlock(&conn_list_lock);
+			tcp_conn_unlock(conn);
+			return;
+		}
+
+		amap_remove(amap, &oldepp);
+		fibril_mutex_unlock(&conn_list_lock);
+
+		conn->name = (char *) "a";
+	}
+
 	switch (conn->cstate) {
 	case st_listen:
-		tcp_conn_sa_listen(conn, seg); break;
+		tcp_conn_sa_listen(conn, seg);
+		break;
 	case st_syn_sent:
-		tcp_conn_sa_syn_sent(conn, seg); break;
+		tcp_conn_sa_syn_sent(conn, seg);
+		break;
 	case st_syn_received:
 	case st_established:
@@ -1189,9 +1253,12 @@
 	case st_time_wait:
 		/* Process segments in order of sequence number */
-		tcp_conn_sa_queue(conn, seg); break;
+		tcp_conn_sa_queue(conn, seg);
+		break;
 	case st_closed:
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate);
 		assert(false);
 	}
+
+	tcp_conn_unlock(conn);
 }
 
@@ -1216,5 +1283,4 @@
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
-	tcp_conn_remove(conn);
 	tcp_conn_state_set(conn, st_closed);
 
@@ -1263,45 +1329,46 @@
 }
 
-/** Handle unexpected segment received on a socket pair.
+/** Handle unexpected segment received on an endpoint pair.
  *
  * We reply with an RST unless the received segment has RST.
  *
- * @param sp		Socket pair which received the segment
+ * @param sp		Endpoint pair which received the segment
  * @param seg		Unexpected segment
  */
-void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg);
+void tcp_unexpected_segment(inet_ep2_t *epp, tcp_segment_t *seg)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", epp,
+	    seg);
 
 	if ((seg->ctrl & CTL_RST) == 0)
-		tcp_reply_rst(sp, seg);
-}
-
-/** Compute flipped socket pair for response.
- *
- * Flipped socket pair has local and foreign sockets exchanged.
- *
- * @param sp		Socket pair
- * @param fsp		Place to store flipped socket pair
- */
-void tcp_sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp)
-{
-	fsp->local = sp->foreign;
-	fsp->foreign = sp->local;
+		tcp_reply_rst(epp, seg);
+}
+
+/** Compute flipped endpoint pair for response.
+ *
+ * Flipped endpoint pair has local and remote endpoints exchanged.
+ *
+ * @param epp		Endpoint pair
+ * @param fepp		Place to store flipped endpoint pair
+ */
+void tcp_ep2_flipped(inet_ep2_t *epp, inet_ep2_t *fepp)
+{
+	fepp->local = epp->remote;
+	fepp->remote = epp->local;
 }
 
 /** Send RST in response to an incoming segment.
  *
- * @param sp		Socket pair which received the segment
+ * @param epp		Endpoint pair which received the segment
  * @param seg		Incoming segment
  */
-void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
+void tcp_reply_rst(inet_ep2_t *epp, tcp_segment_t *seg)
 {
 	tcp_segment_t *rseg;
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", epp, seg);
 
 	rseg = tcp_segment_make_rst(seg);
-	tcp_transmit_segment(sp, rseg);
+	tcp_transmit_segment(epp, rseg);
 }
 
Index: uspace/srv/net/tcp/conn.h
===================================================================
--- uspace/srv/net/tcp/conn.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/conn.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,10 +36,12 @@
 #define CONN_H
 
+#include <inet/endpoint.h>
 #include <stdbool.h>
 #include "tcp_type.h"
 
-extern tcp_conn_t *tcp_conn_new(tcp_sock_t *, tcp_sock_t *);
+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);
@@ -47,5 +49,5 @@
 extern void tcp_conn_fin_sent(tcp_conn_t *);
 extern void tcp_conn_ack_of_fin_rcvd(tcp_conn_t *);
-extern tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *);
+extern tcp_conn_t *tcp_conn_find_ref(inet_ep2_t *);
 extern void tcp_conn_addref(tcp_conn_t *);
 extern void tcp_conn_delref(tcp_conn_t *);
@@ -53,9 +55,10 @@
 extern void tcp_conn_unlock(tcp_conn_t *);
 extern bool tcp_conn_got_syn(tcp_conn_t *);
-extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_conn_segment_arrived(tcp_conn_t *, inet_ep2_t *,
+    tcp_segment_t *);
 extern void tcp_conn_trim_seg_to_wnd(tcp_conn_t *, tcp_segment_t *);
-extern void tcp_unexpected_segment(tcp_sockpair_t *, tcp_segment_t *);
-extern void tcp_sockpair_flipped(tcp_sockpair_t *, tcp_sockpair_t *);
-extern void tcp_reply_rst(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_unexpected_segment(inet_ep2_t *, tcp_segment_t *);
+extern void tcp_ep2_flipped(inet_ep2_t *, inet_ep2_t *);
+extern void tcp_reply_rst(inet_ep2_t *, tcp_segment_t *);
 
 #endif
Index: uspace/srv/net/tcp/ncsim.c
===================================================================
--- uspace/srv/net/tcp/ncsim.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/ncsim.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,4 +42,5 @@
 #include <async.h>
 #include <errno.h>
+#include <inet/endpoint.h>
 #include <io/log.h>
 #include <stdlib.h>
@@ -65,8 +66,8 @@
 /** Bounce segment through simulator into receive queue.
  *
- * @param sp	Socket pair, oriented for transmission
+ * @param epp	Endpoint pair, oriented for transmission
  * @param seg	Segment
  */
-void tcp_ncsim_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+void tcp_ncsim_bounce_seg(inet_ep2_t *epp, tcp_segment_t *seg)
 {
 	tcp_squeue_entry_t *sqe;
@@ -75,5 +76,5 @@
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ncsim_bounce_seg()");
-	tcp_rqueue_bounce_seg(sp, seg);
+	tcp_rqueue_bounce_seg(epp, seg);
 	return;
 
@@ -92,5 +93,5 @@
 
 	sqe->delay = random() % (1000 * 1000);
-	sqe->sp = *sp;
+	sqe->epp = *epp;
 	sqe->seg = seg;
 
@@ -147,5 +148,5 @@
 
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "NCSim - End Sleep");
-		tcp_rqueue_bounce_seg(&sqe->sp, sqe->seg);
+		tcp_rqueue_bounce_seg(&sqe->epp, sqe->seg);
 		free(sqe);
 	}
Index: uspace/srv/net/tcp/ncsim.h
===================================================================
--- uspace/srv/net/tcp/ncsim.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/ncsim.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,8 +36,9 @@
 #define NCSIM_H
 
+#include <inet/endpoint.h>
 #include "tcp_type.h"
 
 extern void tcp_ncsim_init(void);
-extern void tcp_ncsim_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_ncsim_bounce_seg(inet_ep2_t *, tcp_segment_t *);
 extern void tcp_ncsim_fibril_start(void);
 
Index: uspace/srv/net/tcp/pdu.c
===================================================================
--- uspace/srv/net/tcp/pdu.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/pdu.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -38,4 +38,5 @@
 #include <byteorder.h>
 #include <errno.h>
+#include <inet/endpoint.h>
 #include <mem.h>
 #include <stdlib.h>
@@ -125,11 +126,11 @@
 }
 
-static void tcp_header_setup(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_header_t *hdr)
+static void tcp_header_setup(inet_ep2_t *epp, tcp_segment_t *seg, tcp_header_t *hdr)
 {
 	uint16_t doff_flags;
 	uint16_t doff;
 
-	hdr->src_port = host2uint16_t_be(sp->local.port);
-	hdr->dest_port = host2uint16_t_be(sp->foreign.port);
+	hdr->src_port = host2uint16_t_be(epp->local.port);
+	hdr->dest_port = host2uint16_t_be(epp->remote.port);
 	hdr->seq = host2uint32_t_be(seg->seq);
 	hdr->ack = host2uint32_t_be(seg->ack);
@@ -190,5 +191,5 @@
 }
 
-static int tcp_header_encode(tcp_sockpair_t *sp, tcp_segment_t *seg,
+static int tcp_header_encode(inet_ep2_t *epp, tcp_segment_t *seg,
     void **header, size_t *size)
 {
@@ -199,5 +200,5 @@
 		return ENOMEM;
 
-	tcp_header_setup(sp, seg, hdr);
+	tcp_header_setup(epp, seg, hdr);
 	*header = hdr;
 	*size = sizeof(tcp_header_t);
@@ -293,5 +294,5 @@
 
 /** Decode incoming PDU */
-int tcp_pdu_decode(tcp_pdu_t *pdu, tcp_sockpair_t *sp, tcp_segment_t **seg)
+int tcp_pdu_decode(tcp_pdu_t *pdu, inet_ep2_t *epp, tcp_segment_t **seg)
 {
 	tcp_segment_t *nseg;
@@ -307,8 +308,8 @@
 	hdr = (tcp_header_t *)pdu->header;
 
-	sp->local.port = uint16_t_be2host(hdr->dest_port);
-	sp->local.addr = pdu->dest;
-	sp->foreign.port = uint16_t_be2host(hdr->src_port);
-	sp->foreign.addr = pdu->src;
+	epp->local.port = uint16_t_be2host(hdr->dest_port);
+	epp->local.addr = pdu->dest;
+	epp->remote.port = uint16_t_be2host(hdr->src_port);
+	epp->remote.addr = pdu->src;
 
 	*seg = nseg;
@@ -317,5 +318,5 @@
 
 /** Encode outgoing PDU */
-int tcp_pdu_encode(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_pdu_t **pdu)
+int tcp_pdu_encode(inet_ep2_t *epp, tcp_segment_t *seg, tcp_pdu_t **pdu)
 {
 	tcp_pdu_t *npdu;
@@ -327,7 +328,7 @@
 		return ENOMEM;
 
-	npdu->src = sp->local.addr;
-	npdu->dest = sp->foreign.addr;
-	tcp_header_encode(sp, seg, &npdu->header, &npdu->header_size);
+	npdu->src = epp->local.addr;
+	npdu->dest = epp->remote.addr;
+	tcp_header_encode(epp, seg, &npdu->header, &npdu->header_size);
 
 	text_size = tcp_segment_text_size(seg);
Index: uspace/srv/net/tcp/pdu.h
===================================================================
--- uspace/srv/net/tcp/pdu.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/pdu.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,4 +36,5 @@
 #define PDU_H
 
+#include <inet/endpoint.h>
 #include <sys/types.h>
 #include "std.h"
@@ -42,6 +43,6 @@
 extern tcp_pdu_t *tcp_pdu_create(void *, size_t, void *, size_t);
 extern void tcp_pdu_delete(tcp_pdu_t *);
-extern int tcp_pdu_decode(tcp_pdu_t *, tcp_sockpair_t *, tcp_segment_t **);
-extern int tcp_pdu_encode(tcp_sockpair_t *, tcp_segment_t *, tcp_pdu_t **);
+extern int tcp_pdu_decode(tcp_pdu_t *, inet_ep2_t *, tcp_segment_t **);
+extern int tcp_pdu_encode(inet_ep2_t *, tcp_segment_t *, tcp_pdu_t **);
 
 #endif
Index: uspace/srv/net/tcp/rqueue.c
===================================================================
--- uspace/srv/net/tcp/rqueue.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/rqueue.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -67,10 +67,10 @@
  * This is for testing purposes only.
  *
- * @param sp	Socket pair, oriented for transmission
+ * @param sp	Endpoint pair, oriented for transmission
  * @param seg	Segment
  */
-void tcp_rqueue_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+void tcp_rqueue_bounce_seg(inet_ep2_t *epp, tcp_segment_t *seg)
 {
-	tcp_sockpair_t rident;
+	inet_ep2_t rident;
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_rqueue_bounce_seg()");
@@ -80,5 +80,5 @@
 	tcp_segment_t *dseg;
 
-	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
+	if (tcp_pdu_encode(epp, seg, &pdu) != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. Segment dropped.");
 		return;
@@ -97,5 +97,5 @@
 #else
 	/* Reverse the identification */
-	tcp_sockpair_flipped(sp, &rident);
+	tcp_ep2_flipped(epp, &rident);
 
 	/* Insert segment back into rqueue */
@@ -106,8 +106,8 @@
 /** Insert segment into receive queue.
  *
- * @param sp	Socket pair, oriented for reception
+ * @param epp	Endpoint pair, oriented for reception
  * @param seg	Segment
  */
-void tcp_rqueue_insert_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+void tcp_rqueue_insert_seg(inet_ep2_t *epp, tcp_segment_t *seg)
 {
 	tcp_rqueue_entry_t *rqe;
@@ -122,5 +122,5 @@
 	}
 
-	rqe->sp = *sp;
+	rqe->epp = *epp;
 	rqe->seg = seg;
 
@@ -140,5 +140,5 @@
 		rqe = list_get_instance(link, tcp_rqueue_entry_t, link);
 
-		tcp_as_segment_arrived(&rqe->sp, rqe->seg);
+		tcp_as_segment_arrived(&rqe->epp, rqe->seg);
 		free(rqe);
 	}
Index: uspace/srv/net/tcp/rqueue.h
===================================================================
--- uspace/srv/net/tcp/rqueue.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/rqueue.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,9 +36,10 @@
 #define RQUEUE_H
 
+#include <inet/endpoint.h>
 #include "tcp_type.h"
 
 extern void tcp_rqueue_init(void);
-extern void tcp_rqueue_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
-extern void tcp_rqueue_insert_seg(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_rqueue_bounce_seg(inet_ep2_t *, tcp_segment_t *);
+extern void tcp_rqueue_insert_seg(inet_ep2_t *, tcp_segment_t *);
 extern void tcp_rqueue_handler(void *);
 extern void tcp_rqueue_fibril_start(void);
Index: uspace/srv/net/tcp/service.c
===================================================================
--- uspace/srv/net/tcp/service.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/srv/net/tcp/service.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,987 @@
+/*
+ * 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 HelenOS service implementation
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <inet/endpoint.h>
+#include <inet/inet.h>
+#include <io/log.h>
+#include <ipc/services.h>
+#include <ipc/tcp.h>
+#include <loc.h>
+#include <macros.h>
+#include <stdlib.h>
+
+#include "conn.h"
+#include "service.h"
+#include "tcp_type.h"
+#include "ucall.h"
+
+#define NAME "tcp"
+
+#define MAX_MSG_SIZE DATA_XFER_LIMIT
+
+static void tcp_ev_data(tcp_cconn_t *);
+static void tcp_ev_connected(tcp_cconn_t *);
+static void tcp_ev_conn_failed(tcp_cconn_t *);
+static void tcp_ev_conn_reset(tcp_cconn_t *);
+static void tcp_ev_new_conn(tcp_clst_t *, tcp_cconn_t *);
+
+static void tcp_service_cstate_change(tcp_conn_t *, void *, tcp_cstate_t);
+static void tcp_service_recv_data(tcp_conn_t *, void *);
+static void tcp_service_lst_cstate_change(tcp_conn_t *, void *, tcp_cstate_t);
+
+static int tcp_cconn_create(tcp_client_t *, tcp_conn_t *, tcp_cconn_t **);
+
+static tcp_cb_t tcp_service_cb = {
+	.cstate_change = tcp_service_cstate_change,
+	.recv_data = tcp_service_recv_data
+};
+
+static tcp_cb_t tcp_service_lst_cb = {
+	.cstate_change = tcp_service_lst_cstate_change,
+	.recv_data = NULL
+};
+
+static void tcp_service_cstate_change(tcp_conn_t *conn, void *arg,
+    tcp_cstate_t old_state)
+{
+	tcp_cstate_t nstate;
+	tcp_cconn_t *cconn;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_service_cstate_change()");
+	nstate = conn->cstate;
+	cconn = tcp_uc_get_userptr(conn);
+
+	if ((old_state == st_syn_sent || old_state == st_syn_received) &&
+	    (nstate == st_established)) {
+		/* Connection established */
+		tcp_ev_connected(cconn);
+	}
+
+	if (old_state != st_closed && nstate == st_closed && conn->reset) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_service_cstate_change: "
+		    "Connection reset");
+		/* Connection reset */
+		tcp_ev_conn_reset(cconn);
+	} else {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_service_cstate_change: "
+		    "old_state=%d nstate=%d conn->reset=%d",
+		    old_state, nstate, conn->reset);
+	}
+
+	/* XXX Failed to establish connection */
+	if (0) tcp_ev_conn_failed(cconn);
+}
+
+static void tcp_service_lst_cstate_change(tcp_conn_t *conn, void *arg,
+    tcp_cstate_t old_state)
+{
+	tcp_cstate_t nstate;
+	tcp_clst_t *clst;
+	tcp_cconn_t *cconn;
+	inet_ep2_t epp;
+	int rc;
+	tcp_error_t trc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_service_lst_cstate_change()");
+	nstate = conn->cstate;
+	clst = tcp_uc_get_userptr(conn);
+
+	if ((old_state == st_syn_sent || old_state == st_syn_received) &&
+	    (nstate == st_established)) {
+		/* Connection established */
+		clst->conn = NULL;
+
+		rc = tcp_cconn_create(clst->client, conn, &cconn);
+		if (rc != EOK) {
+			/* XXX Could not create client connection */
+			return;
+		}
+
+		/* XXX Is there a race here (i.e. the connection is already active)? */
+		tcp_uc_set_cb(conn, &tcp_service_cb, cconn);
+
+		/* New incoming connection */
+		tcp_ev_new_conn(clst, cconn);
+	}
+
+	if (old_state != st_closed && nstate == st_closed && conn->reset) {
+		/* Connection reset */
+		/* XXX */
+	}
+
+	/* XXX Failed to establish connection */
+	if (0) {
+		/* XXX */
+	}
+
+	/* Replenish sentinel connection */
+
+	inet_ep2_init(&epp);
+	epp.local = clst->elocal;
+
+	trc = tcp_uc_open(&epp, ap_passive, tcp_open_nonblock,
+	    &conn);
+	if (trc != TCP_EOK) {
+		/* XXX Could not replenish connection */
+		return;
+	}
+
+	conn->name = (char *) "s";
+	clst->conn = conn;
+
+	/* XXX Is there a race here (i.e. the connection is already active)? */
+	tcp_uc_set_cb(conn, &tcp_service_lst_cb, clst);
+}
+
+static void tcp_service_recv_data(tcp_conn_t *conn, void *arg)
+{
+	tcp_cconn_t *cconn = (tcp_cconn_t *)arg;
+
+	tcp_ev_data(cconn);
+}
+
+static void tcp_ev_data(tcp_cconn_t *cconn)
+{
+	async_exch_t *exch;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_data()");
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "client=%p\n", cconn->client);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "sess=%p\n", cconn->client->sess);
+
+	exch = async_exchange_begin(cconn->client->sess);
+	aid_t req = async_send_1(exch, TCP_EV_DATA, cconn->id, NULL);
+	async_exchange_end(exch);
+
+	async_forget(req);
+}
+
+static void tcp_ev_connected(tcp_cconn_t *cconn)
+{
+	async_exch_t *exch;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_connected()");
+
+	exch = async_exchange_begin(cconn->client->sess);
+	aid_t req = async_send_1(exch, TCP_EV_CONNECTED, cconn->id, NULL);
+	async_exchange_end(exch);
+
+	async_forget(req);
+}
+
+static void tcp_ev_conn_failed(tcp_cconn_t *cconn)
+{
+	async_exch_t *exch;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_conn_failed()");
+
+	exch = async_exchange_begin(cconn->client->sess);
+	aid_t req = async_send_1(exch, TCP_EV_CONN_FAILED, cconn->id, NULL);
+	async_exchange_end(exch);
+
+	async_forget(req);
+}
+
+static void tcp_ev_conn_reset(tcp_cconn_t *cconn)
+{
+	async_exch_t *exch;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_conn_reset()");
+
+	exch = async_exchange_begin(cconn->client->sess);
+	aid_t req = async_send_1(exch, TCP_EV_CONN_RESET, cconn->id, NULL);
+	async_exchange_end(exch);
+
+	async_forget(req);
+}
+
+/** New incoming connection */
+static void tcp_ev_new_conn(tcp_clst_t *clst, tcp_cconn_t *cconn)
+{
+	async_exch_t *exch;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_new_conn()");
+
+	exch = async_exchange_begin(clst->client->sess);
+	aid_t req = async_send_2(exch, TCP_EV_NEW_CONN, clst->id, cconn->id,
+	    NULL);
+	async_exchange_end(exch);
+
+	async_forget(req);
+}
+
+static int tcp_cconn_create(tcp_client_t *client, tcp_conn_t *conn,
+    tcp_cconn_t **rcconn)
+{
+	tcp_cconn_t *cconn;
+	sysarg_t id;
+
+	cconn = calloc(1, sizeof(tcp_cconn_t));
+	if (cconn == NULL)
+		return ENOMEM;
+
+	/* Allocate new ID */
+	id = 0;
+	list_foreach (client->cconn, lclient, tcp_cconn_t, cconn) {
+		if (cconn->id >= id)
+			id = cconn->id + 1;
+	}
+
+	cconn->id = id;
+	cconn->client = client;
+	cconn->conn = conn;
+
+	list_append(&cconn->lclient, &client->cconn);
+	*rcconn = cconn;
+	return EOK;
+}
+
+static void tcp_cconn_destroy(tcp_cconn_t *cconn)
+{
+	list_remove(&cconn->lclient);
+	free(cconn);
+}
+
+static int tcp_clistener_create(tcp_client_t *client, tcp_conn_t *conn,
+    tcp_clst_t **rclst)
+{
+	tcp_clst_t *clst;
+	sysarg_t id;
+
+	clst = calloc(1, sizeof(tcp_clst_t));
+	if (clst == NULL)
+		return ENOMEM;
+
+	/* Allocate new ID */
+	id = 0;
+	list_foreach (client->clst, lclient, tcp_clst_t, clst) {
+		if (clst->id >= id)
+			id = clst->id + 1;
+	}
+
+	clst->id = id;
+	clst->client = client;
+	clst->conn = conn;
+
+	list_append(&clst->lclient, &client->clst);
+	*rclst = clst;
+	return EOK;
+}
+
+static void tcp_clistener_destroy(tcp_clst_t *clst)
+{
+	list_remove(&clst->lclient);
+	free(clst);
+}
+
+static int tcp_cconn_get(tcp_client_t *client, sysarg_t id,
+    tcp_cconn_t **rcconn)
+{
+	list_foreach (client->cconn, lclient, tcp_cconn_t, cconn) {
+		if (cconn->id == id) {
+			*rcconn = cconn;
+			return EOK;
+		}
+	}
+
+	return ENOENT;
+}
+
+static int tcp_clistener_get(tcp_client_t *client, sysarg_t id,
+    tcp_clst_t **rclst)
+{
+	list_foreach (client->clst, lclient, tcp_clst_t, clst) {
+		if (clst->id == id) {
+			*rclst = clst;
+			return EOK;
+		}
+	}
+
+	return ENOENT;
+}
+
+
+static int tcp_conn_create_impl(tcp_client_t *client, inet_ep2_t *epp,
+    sysarg_t *rconn_id)
+{
+	tcp_conn_t *conn;
+	tcp_cconn_t *cconn;
+	int rc;
+	tcp_error_t trc;
+	char *slocal;
+	char *sremote;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl");
+
+	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);
+	free(slocal);
+	free(sremote);
+
+	trc = tcp_uc_open(epp, ap_active, tcp_open_nonblock, &conn);
+	if (trc != TCP_EOK)
+		return EIO;
+
+	conn->name = (char *) "c";
+
+	rc = tcp_cconn_create(client, conn, &cconn);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		tcp_conn_delete(conn);
+		return ENOMEM;
+	}
+
+	/* XXX Is there a race here (i.e. the connection is already active)? */
+	tcp_uc_set_cb(conn, &tcp_service_cb, cconn);
+
+	*rconn_id = cconn->id;
+	return EOK;
+}
+
+static int tcp_conn_destroy_impl(tcp_client_t *client, sysarg_t conn_id)
+{
+	tcp_cconn_t *cconn;
+	int rc;
+
+	rc = tcp_cconn_get(client, conn_id, &cconn);
+	if (rc != EOK) {
+		assert(rc == ENOENT);
+		return ENOENT;
+	}
+
+	tcp_uc_close(cconn->conn);
+	tcp_uc_delete(cconn->conn);
+	tcp_cconn_destroy(cconn);
+	return EOK;
+}
+
+static int tcp_listener_create_impl(tcp_client_t *client, inet_ep_t *ep,
+    sysarg_t *rlst_id)
+{
+	tcp_conn_t *conn;
+	tcp_clst_t *clst;
+	inet_ep2_t epp;
+	int rc;
+	tcp_error_t trc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_listener_create_impl");
+
+	inet_ep2_init(&epp);
+	epp.local.addr = ep->addr;
+	epp.local.port = ep->port;
+
+	trc = tcp_uc_open(&epp, ap_passive, tcp_open_nonblock, &conn);
+	if (trc != TCP_EOK)
+		return EIO;
+
+	conn->name = (char *) "s";
+
+	rc = tcp_clistener_create(client, conn, &clst);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		tcp_conn_delete(conn);
+		return ENOMEM;
+	}
+
+	clst->elocal = epp.local;
+
+	/* XXX Is there a race here (i.e. the connection is already active)? */
+	tcp_uc_set_cb(conn, &tcp_service_lst_cb, clst);
+
+	*rlst_id = clst->id;
+	return EOK;
+}
+
+static int tcp_listener_destroy_impl(tcp_client_t *client, sysarg_t lst_id)
+{
+	tcp_clst_t *clst;
+	int rc;
+
+	rc = tcp_clistener_get(client, lst_id, &clst);
+	if (rc != EOK) {
+		assert(rc == ENOENT);
+		return ENOENT;
+	}
+
+//	tcp_uc_close(cconn->conn);
+	tcp_clistener_destroy(clst);
+	return EOK;
+}
+
+static int tcp_conn_send_fin_impl(tcp_client_t *client, sysarg_t conn_id)
+{
+	tcp_cconn_t *cconn;
+	int rc;
+
+	rc = tcp_cconn_get(client, conn_id, &cconn);
+	if (rc != EOK) {
+		assert(rc == ENOENT);
+		return ENOENT;
+	}
+
+	(void) cconn;
+	/* XXX TODO */
+	return EOK;
+}
+
+static int tcp_conn_push_impl(tcp_client_t *client, sysarg_t conn_id)
+{
+	tcp_cconn_t *cconn;
+	int rc;
+
+	rc = tcp_cconn_get(client, conn_id, &cconn);
+	if (rc != EOK) {
+		assert(rc == ENOENT);
+		return ENOENT;
+	}
+
+	(void) cconn;
+	/* XXX TODO */
+	return EOK;
+}
+
+static int tcp_conn_reset_impl(tcp_client_t *client, sysarg_t conn_id)
+{
+	tcp_cconn_t *cconn;
+	int rc;
+
+	rc = tcp_cconn_get(client, conn_id, &cconn);
+	if (rc != EOK) {
+		assert(rc == ENOENT);
+		return ENOENT;
+	}
+
+	tcp_uc_abort(cconn->conn);
+	return EOK;
+}
+
+static int tcp_conn_send_impl(tcp_client_t *client, sysarg_t conn_id,
+    void *data, size_t size)
+{
+	tcp_cconn_t *cconn;
+	int rc;
+
+	rc = tcp_cconn_get(client, conn_id, &cconn);
+	if (rc != EOK)
+		return rc;
+
+	rc = tcp_uc_send(cconn->conn, data, size, 0);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+static int tcp_conn_recv_impl(tcp_client_t *client, sysarg_t conn_id,
+    void *data, size_t size, size_t *nrecv)
+{
+	tcp_cconn_t *cconn;
+	xflags_t xflags;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_impl()");
+
+	rc = tcp_cconn_get(client, conn_id, &cconn);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_impl() - conn not found");
+		return rc;
+	}
+
+	rc = tcp_uc_receive(cconn->conn, data, size, nrecv, &xflags);
+	if (rc != EOK) {
+		switch (rc) {
+		case TCP_EAGAIN:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_impl() - EAGAIN");
+			return EAGAIN;
+		default:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_impl() - trc=%d", rc);
+			return EIO;
+		}
+	}
+
+	return EOK;
+}
+
+static void tcp_callback_create_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_callback_create_srv()");
+
+	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	client->sess = sess;
+	async_answer_0(iid, EOK);
+}
+
+static void tcp_conn_create_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	inet_ep2_t epp;
+	sysarg_t conn_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_srv()");
+
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (size != sizeof(inet_ep2_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	rc = async_data_write_finalize(callid, &epp, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	rc = tcp_conn_create_impl(client, &epp, &conn_id);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	async_answer_1(iid, EOK, conn_id);
+}
+
+static void tcp_conn_destroy_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	sysarg_t conn_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_destroy_srv()");
+
+	conn_id = IPC_GET_ARG1(*icall);
+	rc = tcp_conn_destroy_impl(client, conn_id);
+	async_answer_0(iid, rc);
+}
+
+static void tcp_listener_create_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	inet_ep_t ep;
+	sysarg_t lst_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_listener_create_srv()");
+
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (size != sizeof(inet_ep_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	rc = async_data_write_finalize(callid, &ep, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	rc = tcp_listener_create_impl(client, &ep, &lst_id);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	async_answer_1(iid, EOK, lst_id);
+}
+
+static void tcp_listener_destroy_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	sysarg_t lst_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_listener_destroy_srv()");
+
+	lst_id = IPC_GET_ARG1(*icall);
+	rc = tcp_listener_destroy_impl(client, lst_id);
+	async_answer_0(iid, rc);
+}
+
+static void tcp_conn_send_fin_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	sysarg_t conn_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_send_fin_srv()");
+
+	conn_id = IPC_GET_ARG1(*icall);
+	rc = tcp_conn_send_fin_impl(client, conn_id);
+	async_answer_0(iid, rc);
+}
+
+static void tcp_conn_push_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	sysarg_t conn_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_push_srv()");
+
+	conn_id = IPC_GET_ARG1(*icall);
+	rc = tcp_conn_push_impl(client, conn_id);
+	async_answer_0(iid, rc);
+}
+
+static void tcp_conn_reset_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	sysarg_t conn_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_reset_srv()");
+
+	conn_id = IPC_GET_ARG1(*icall);
+	rc = tcp_conn_reset_impl(client, conn_id);
+	async_answer_0(iid, rc);
+}
+
+static void tcp_conn_send_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	sysarg_t conn_id;
+	void *data;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_send_srv())");
+
+	/* Receive message data */
+
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (size > MAX_MSG_SIZE) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	data = malloc(size);
+	if (data == NULL) {
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+	}
+
+	rc = async_data_write_finalize(callid, data, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		free(data);
+		return;
+	}
+
+	conn_id = IPC_GET_ARG1(*icall);
+
+	rc = tcp_conn_send_impl(client, conn_id, data, size);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		free(data);
+		return;
+	}
+
+	async_answer_0(iid, EOK);
+	free(data);
+}
+
+static void tcp_conn_recv_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	sysarg_t conn_id;
+	size_t size, rsize;
+	void *data;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_srv()");
+
+	conn_id = IPC_GET_ARG1(*icall);
+
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	size = min(size, 16384);
+	data = malloc(size);
+	if (data == NULL) {
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	rc = tcp_conn_recv_impl(client, conn_id, data, size, &rsize);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		free(data);
+		return;
+	}
+
+	rc = async_data_read_finalize(callid, data, size);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		free(data);
+		return;
+	}
+
+	async_answer_1(iid, EOK, rsize);
+	free(data);
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_srv(): OK");
+}
+
+static void tcp_conn_recv_wait_srv(tcp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	sysarg_t conn_id;
+	size_t size, rsize;
+	void *data;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv()");
+
+	conn_id = IPC_GET_ARG1(*icall);
+
+	if (!async_data_read_receive(&callid, &size)) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - data_receive failed");
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	size = min(size, 16384);
+	data = malloc(size);
+	if (data == NULL) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - allocation failed");
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	rc = tcp_conn_recv_impl(client, conn_id, data, size, &rsize);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - recv_impl failed rc=%d", rc);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		free(data);
+		return;
+	}
+
+	rc = async_data_read_finalize(callid, data, size);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - finalize failed");
+		async_answer_0(iid, rc);
+		free(data);
+		return;
+	}
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv(): rsize=%zu", size);
+	async_answer_1(iid, EOK, rsize);
+	free(data);
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv(): OK");
+}
+
+#include <mem.h>
+
+static void tcp_client_init(tcp_client_t *client)
+{
+	memset(client, 0, sizeof(tcp_client_t));
+	client->sess = NULL;
+	list_initialize(&client->cconn);
+	list_initialize(&client->clst);
+}
+
+static void tcp_client_fini(tcp_client_t *client)
+{
+	tcp_cconn_t *cconn;
+	size_t n;
+
+	n = list_count(&client->cconn);
+	if (n != 0) {
+		log_msg(LOG_DEFAULT, LVL_WARN, "Client with %zu active "
+		    "connections closed session", n);
+
+		while (!list_empty(&client->cconn)) {
+			cconn = list_get_instance(list_first(&client->cconn),
+			    tcp_cconn_t, lclient);
+			tcp_uc_close(cconn->conn);
+			tcp_uc_delete(cconn->conn);
+			tcp_cconn_destroy(cconn);
+		}
+	}
+
+	n = list_count(&client->clst);
+	if (n != 0) {
+		log_msg(LOG_DEFAULT, LVL_WARN, "Client with %zu active "
+		    "listeners closed session", n);
+		/* XXX Destroy listeners */
+	}
+
+	if (client->sess != NULL)
+		async_hangup(client->sess);
+}
+
+static void tcp_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	tcp_client_t client;
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_client_conn() - client=%p",
+	    &client);
+
+	tcp_client_init(&client);
+
+	while (true) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_client_conn: wait req");
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_client_conn: method=%d",
+		    (int)method);
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			break;
+		}
+
+		switch (method) {
+		case TCP_CALLBACK_CREATE:
+			tcp_callback_create_srv(&client, callid, &call);
+			break;
+		case TCP_CONN_CREATE:
+			tcp_conn_create_srv(&client, callid, &call);
+			break;
+		case TCP_CONN_DESTROY:
+			tcp_conn_destroy_srv(&client, callid, &call);
+			break;
+		case TCP_LISTENER_CREATE:
+			tcp_listener_create_srv(&client, callid, &call);
+			break;
+		case TCP_LISTENER_DESTROY:
+			tcp_listener_destroy_srv(&client, callid, &call);
+			break;
+		case TCP_CONN_SEND_FIN:
+			tcp_conn_send_fin_srv(&client, callid, &call);
+			break;
+		case TCP_CONN_PUSH:
+			tcp_conn_push_srv(&client, callid, &call);
+			break;
+		case TCP_CONN_RESET:
+			tcp_conn_reset_srv(&client, callid, &call);
+			break;
+		case TCP_CONN_SEND:
+			tcp_conn_send_srv(&client, callid, &call);
+			break;
+		case TCP_CONN_RECV:
+			tcp_conn_recv_srv(&client, callid, &call);
+			break;
+		case TCP_CONN_RECV_WAIT:
+			tcp_conn_recv_wait_srv(&client, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_client_conn TERMINATED");
+	tcp_client_fini(&client);
+}
+
+int tcp_service_init(void)
+{
+	int rc;
+	service_id_t sid;
+
+	async_set_client_connection(tcp_client_conn);
+
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
+		return EIO;
+	}
+
+	rc = loc_service_register(SERVICE_NAME_TCP, &sid);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service.");
+		return EIO;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/service.h
===================================================================
--- uspace/srv/net/tcp/service.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/srv/net/tcp/service.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,43 @@
+/*
+ * 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 HelenOS service implementation
+ */
+
+#ifndef SERVICE_H
+#define SERVICE_H
+
+extern int tcp_service_init(void);
+
+#endif
+
+/** @}
+ */
Index: pace/srv/net/tcp/sock.c
===================================================================
--- uspace/srv/net/tcp/sock.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,1093 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * Copyright (c) 2011 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 Socket provider
- */
-
-#include <async.h>
-#include <errno.h>
-#include <inet/inet.h>
-#include <io/log.h>
-#include <ipc/services.h>
-#include <ipc/socket.h>
-#include <net/socket.h>
-#include <ns.h>
-
-#include "sock.h"
-#include "std.h"
-#include "tcp.h"
-#include "tcp_type.h"
-#include "ucall.h"
-
-#define MAX_BACKLOG 128
-
-/** Free ports pool start. */
-#define TCP_FREE_PORTS_START		1025
-
-/** Free ports pool end. */
-#define TCP_FREE_PORTS_END		65535
-
-static int last_used_port = TCP_FREE_PORTS_START - 1;
-static socket_ports_t gsock;
-
-static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
-static int tcp_sock_recv_fibril(void *arg);
-
-int tcp_sock_init(void)
-{
-	socket_ports_initialize(&gsock);
-	
-	async_set_client_connection(tcp_sock_connection);
-	
-	int rc = service_register(SERVICE_TCP);
-	if (rc != EOK)
-		return EEXIST;
-	
-	return EOK;
-}
-
-static void tcp_free_sock_data(socket_core_t *sock_core)
-{
-	tcp_sockdata_t *socket;
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	(void)socket;
-
-	/* XXX We need to initiate connection cleanup here */
-}
-
-static void tcp_sock_notify_data(socket_core_t *sock_core)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id);
-	async_exch_t *exch = async_exchange_begin(sock_core->sess);
-	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
-	    TCP_SOCK_FRAGMENT_SIZE, 0, 0, 1);
-	async_exchange_end(exch);
-}
-
-static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id);
-	async_exch_t *exch = async_exchange_begin(lsock_core->sess);
-	async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id,
-	    TCP_SOCK_FRAGMENT_SIZE, 0, 0, 0);
-	async_exchange_end(exch);
-}
-
-static int tcp_sock_create(tcp_client_t *client, tcp_sockdata_t **rsock)
-{
-	tcp_sockdata_t *sock;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_create()");
-	*rsock = NULL;
-
-	sock = calloc(1, sizeof(tcp_sockdata_t));
-	if (sock == NULL)
-		return ENOMEM;
-
-	fibril_mutex_initialize(&sock->lock);
-	sock->client = client;
-
-	sock->recv_buffer_used = 0;
-	sock->recv_error = TCP_EOK;
-	fibril_mutex_initialize(&sock->recv_buffer_lock);
-	fibril_condvar_initialize(&sock->recv_buffer_cv);
-	list_initialize(&sock->ready);
-
-	*rsock = sock;
-	return EOK;
-}
-
-static void tcp_sock_uncreate(tcp_sockdata_t *sock)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_uncreate()");
-	free(sock);
-}
-
-static int tcp_sock_finish_setup(tcp_sockdata_t *sock, int *sock_id)
-{
-	socket_core_t *sock_core;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_finish_setup()");
-
-	sock->recv_fibril = fibril_create(tcp_sock_recv_fibril, sock);
-	if (sock->recv_fibril == 0)
-		return ENOMEM;
-
-	rc = socket_create(&sock->client->sockets, sock->client->sess,
-	    sock, sock_id);
-
-	if (rc != EOK) {
-		fibril_destroy(sock->recv_fibril);
-		sock->recv_fibril = 0;
-		return rc;
-	}
-
-	sock_core = socket_cores_find(&sock->client->sockets, *sock_id);
-	assert(sock_core != NULL);
-	sock->sock_core = sock_core;
-
-	return EOK;
-}
-
-static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	tcp_sockdata_t *sock;
-	int sock_id;
-	int rc;
-	ipc_call_t answer;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_socket()");
-
-	rc = tcp_sock_create(client, &sock);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	inet_addr_any(&sock->laddr);
-	sock->lconn = NULL;
-	sock->backlog = 0;
-
-	sock_id = SOCKET_GET_SOCKET_ID(call);
-	rc = tcp_sock_finish_setup(sock, &sock_id);
-	if (rc != EOK) {
-		tcp_sock_uncreate(sock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	SOCKET_SET_SOCKET_ID(answer, sock_id);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE);
-	SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
-	
-	async_answer_3(callid, EOK, IPC_GET_ARG1(answer),
-	    IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
-}
-
-static void tcp_sock_bind(tcp_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;
-	tcp_sockdata_t *socket;
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_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);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		goto out;
-	}
-	
-	if (addr_size != sizeof(struct sockaddr_in)) {
-		async_answer_0(callid, EINVAL);
-		goto out;
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_bind");
-	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
-	    addr, addr_size, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-	    last_used_port);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		goto out;
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_cores_find");
-	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOENT);
-		goto out;
-	}
-	
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	/* XXX Anything to do? */
-	(void) socket;
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - success");
-	async_answer_0(callid, EOK);
-	
-out:
-	if (addr != NULL)
-		free(addr);
-}
-
-static void tcp_sock_listen(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int backlog;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	tcp_conn_t *conn;
-	tcp_sock_lconn_t *lconn;
-	int i;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_listen()");
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	backlog = SOCKET_GET_BACKLOG(call);
-
-	if (backlog < 0) {
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (backlog > MAX_BACKLOG)
-		backlog = MAX_BACKLOG;
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-	
-	if (sock_core->port <= 0) {
-		rc = socket_bind_free_port(&gsock, sock_core,
-		    TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-		    last_used_port);
-		if (rc != EOK) {
-			async_answer_0(callid, rc);
-			return;
-		}
-		
-		last_used_port = sock_core->port;
-	}
-	
-	socket = (tcp_sockdata_t *) sock_core->specific_data;
-	
-	/*
-	 * Prepare @c backlog listening connections.
-	 */
-	fibril_mutex_lock(&socket->lock);
-	
-	socket->backlog = backlog;
-	socket->lconn = calloc(backlog, sizeof(tcp_conn_t *));
-	if (socket->lconn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - open connections");
-	
-	inet_addr_any(&lsocket.addr);
-	lsocket.port = sock_core->port;
-	
-	inet_addr_any(&fsocket.addr);
-	fsocket.port = TCP_PORT_ANY;
-	
-	for (i = 0; i < backlog; i++) {
-
-		lconn = calloc(1, sizeof(tcp_sock_lconn_t));
-		if (lconn == NULL) {
-			/* XXX Clean up */
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, ENOMEM);
-			return;
-		}
-
-		trc = tcp_uc_open(&lsocket, &fsocket, ap_passive,
-		    tcp_open_nonblock, &conn);
-		if (conn == NULL) {
-			/* XXX Clean up */
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, ENOMEM);
-			return;
-		}
-
-		tcp_uc_set_cstate_cb(conn, tcp_sock_cstate_cb, lconn);
-
-		assert(trc == TCP_EOK);
-		conn->name = (char *)"S";
-
-		lconn->conn = conn;
-		lconn->socket = socket;
-		link_initialize(&lconn->ready_list);
-		socket->lconn[i] = lconn;
-	}
-
-	fibril_mutex_unlock(&socket->lock);
-	async_answer_0(callid, EOK);
-}
-
-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;
-	int rc = async_data_write_accept((void **) &addr6, false, 0, 0, 0, &addr_len);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		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;
-	
-	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);
-		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,
-		    TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-		    last_used_port);
-		if (rc != EOK) {
-			async_answer_0(callid, rc);
-			goto out;
-		}
-		
-		last_used_port = sock_core->port;
-	}
-	
-	fibril_mutex_lock(&socket->lock);
-	
-	if (inet_addr_is_any(&socket->laddr)) {
-		/* Determine local IP address */
-		inet_addr_t loc_addr;
-		inet_addr_t 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) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connect: Failed to "
-			    "determine local address.");
-			goto out;
-		}
-		
-		socket->laddr = loc_addr;
-	}
-	
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	
-	lsocket.addr = socket->laddr;
-	lsocket.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:
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		goto out;
-	}
-	
-	fsocket.port = uint16_t_be2host(addr->sin_port);
-	
-	tcp_error_t trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0,
-	    &socket->conn);
-	
-	if (socket->conn != NULL)
-		socket->conn->name = (char *) "C";
-	
-	fibril_mutex_unlock(&socket->lock);
-	
-	switch (trc) {
-	case TCP_EOK:
-		rc = EOK;
-		break;
-	case TCP_ERESET:
-		rc = ECONNREFUSED;
-		break;
-	default:
-		assert(false);
-	}
-	
-	if (rc == EOK)
-		fibril_add_ready(socket->recv_fibril);
-	
-	async_answer_0(callid, rc);
-	
-out:
-	if (addr6 != NULL)
-		free(addr6);
-}
-
-static void tcp_sock_accept(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	ipc_call_t answer;
-	int socket_id;
-	int asock_id;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_sockdata_t *asocket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	tcp_conn_t *conn;
-	tcp_conn_t *rconn;
-	tcp_sock_lconn_t *lconn;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_accept()");
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	asock_id = SOCKET_GET_NEW_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-	
-	if (sock_core->port <= 0) {
-		rc = socket_bind_free_port(&gsock, sock_core,
-		    TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-		    last_used_port);
-		if (rc != EOK) {
-			async_answer_0(callid, rc);
-			return;
-		}
-		
-		last_used_port = sock_core->port;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - verify socket->conn");
-	if (socket->conn != NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (list_empty(&socket->ready)) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-
-	lconn = list_get_instance(list_first(&socket->ready),
-	    tcp_sock_lconn_t, ready_list);
-	list_remove(&lconn->ready_list);
-
-	conn = lconn->conn;
-	tcp_uc_set_cstate_cb(conn, NULL, NULL);
-
-	/* Replenish listening connection */
-
-	inet_addr_any(&lsocket.addr);
-	lsocket.port = sock_core->port;
-	
-	inet_addr_any(&fsocket.addr);
-	fsocket.port = TCP_PORT_ANY;
-
-	trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, tcp_open_nonblock,
-	    &rconn);
-	if (rconn == NULL) {
-		/* XXX Clean up */
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	tcp_uc_set_cstate_cb(rconn, tcp_sock_cstate_cb, lconn);
-
-	assert(trc == TCP_EOK);
-	rconn->name = (char *)"S";
-
-	lconn->conn = rconn;
-
-	/* Allocate socket for accepted connection */
-
-	rc = tcp_sock_create(client, &asocket);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	asocket->conn = conn;
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_accept():create asocket\n");
-
-	rc = tcp_sock_finish_setup(asocket, &asock_id);
-	if (rc != EOK) {
-		tcp_sock_uncreate(asocket);
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	fibril_add_ready(asocket->recv_fibril);
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_accept(): find acore\n");
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE);
-	SOCKET_SET_SOCKET_ID(answer, asock_id);
-	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
-	
-	async_answer_3(callid, asocket->sock_core->socket_id,
-	    IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
-	    IPC_GET_ARG3(answer));
-	
-	/* Push one fragment notification to client's queue */
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_accept(): notify data\n");
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_send(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int fragments;
-	int index;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t wcallid;
-	size_t length;
-	tcp_error_t trc;
-	int rc;
-	
-	uint8_t *buffer = calloc(TCP_SOCK_FRAGMENT_SIZE, 1);
-	if (buffer == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_send()");
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
-	SOCKET_GET_FLAGS(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		goto out;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->conn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-
-	for (index = 0; index < fragments; index++) {
-		if (!async_data_write_receive(&wcallid, &length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			goto out;
-		}
-
-		if (length > TCP_SOCK_FRAGMENT_SIZE)
-			length = TCP_SOCK_FRAGMENT_SIZE;
-
-		rc = async_data_write_finalize(wcallid, buffer, length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			goto out;
-		}
-
-		trc = tcp_uc_send(socket->conn, buffer, length, 0);
-
-		switch (trc) {
-		case TCP_EOK:
-			rc = EOK;
-			break;
-		case TCP_ENOTEXIST:
-			rc = ENOTCONN;
-			break;
-		case TCP_ECLOSING:
-			rc = ENOTCONN;
-			break;
-		case TCP_ERESET:
-			rc = ECONNABORTED;
-			break;
-		default:
-			assert(false);
-		}
-
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			goto out;
-		}
-	}
-
-	IPC_SET_ARG1(answer, 0);
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE);
-	async_answer_2(callid, EOK, IPC_GET_ARG1(answer),
-	    IPC_GET_ARG2(answer));
-	fibril_mutex_unlock(&socket->lock);
-	
-out:
-	free(buffer);
-}
-
-static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_sendto()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void tcp_sock_recvfrom(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
-	
-	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;
-	}
-	
-	tcp_sockdata_t *socket =
-	    (tcp_sockdata_t *) sock_core->specific_data;
-	
-	fibril_mutex_lock(&socket->lock);
-	
-	if (socket->conn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-	
-	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)) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "wait for recv_buffer_cv + recv_buffer_used != 0");
-		fibril_condvar_wait(&socket->recv_buffer_cv,
-		    &socket->recv_buffer_lock);
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Got data in sock recv_buffer");
-	
-	size_t data_len = socket->recv_buffer_used;
-	tcp_error_t trc = socket->recv_error;
-	int rc;
-	
-	switch (trc) {
-	case TCP_EOK:
-		rc = EOK;
-		break;
-	case TCP_ENOTEXIST:
-	case TCP_ECLOSING:
-		rc = ENOTCONN;
-		break;
-	case TCP_ERESET:
-		rc = ECONNABORTED;
-		break;
-	default:
-		assert(false);
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "**** recv result -> %d", rc);
-	
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->recv_buffer_lock);
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	ipc_callid_t rcallid;
-	
-	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
-		/* Fill address */
-		tcp_sock_t *rsock = &socket->conn->ident.foreign;
-		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);
-			
-			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);
-			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);
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-	
-	if (length > data_len)
-		length = data_len;
-	
-	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,
-		    socket->recv_buffer_used);
-		tcp_sock_notify_data(socket->sock_core);
-	}
-	
-	fibril_condvar_broadcast(&socket->recv_buffer_cv);
-	
-	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));
-	
-	fibril_mutex_unlock(&socket->recv_buffer_lock);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_close(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	int i;
-	int rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close()");
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-
-	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;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->conn != NULL) {
-		/* Close connection */
-		trc = tcp_uc_close(socket->conn);
-		if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EBADF);
-			return;
-		}
-	}
-
-	if (socket->lconn != NULL) {
-		/* Close listening connections */
-		for (i = 0; i < socket->backlog; i++) {
-			tcp_uc_set_cstate_cb(socket->lconn[i]->conn, NULL, NULL);
-			trc = tcp_uc_close(socket->lconn[i]->conn);
-			if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
-				fibril_mutex_unlock(&socket->lock);
-				async_answer_0(callid, EBADF);
-				return;
-			}
-
-			free(socket->lconn[i]);
-			socket->lconn[i] = NULL;
-		}
-	}
-
-	/* Grab recv_buffer_lock because of CV wait in tcp_sock_recv_fibril() */
-	fibril_mutex_lock(&socket->recv_buffer_lock);
-	socket->sock_core = NULL;
-	fibril_mutex_unlock(&socket->recv_buffer_lock);
-
-	rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
-	    tcp_free_sock_data);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	fibril_mutex_unlock(&socket->lock);
-	async_answer_0(callid, EOK);
-}
-
-static void tcp_sock_getsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_getsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void tcp_sock_setsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_setsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-/** Called when connection state changes. */
-static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg)
-{
-	tcp_conn_status_t cstatus;
-	tcp_sock_lconn_t *lconn = (tcp_sock_lconn_t *)arg;
-	tcp_sockdata_t *socket = lconn->socket;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_cstate_cb()");
-	fibril_mutex_lock(&socket->lock);
-	assert(conn == lconn->conn);
-
-	tcp_uc_status(conn, &cstatus);
-	if (cstatus.cstate != st_established) {
-		fibril_mutex_unlock(&socket->lock);
-		return;
-	}
-
-	assert_link_not_used(&lconn->ready_list);
-	list_append(&lconn->ready_list, &socket->ready);
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
-
-	/* Push one accept notification to client's queue */
-	tcp_sock_notify_aconn(socket->sock_core);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static int tcp_sock_recv_fibril(void *arg)
-{
-	tcp_sockdata_t *sock = (tcp_sockdata_t *)arg;
-	size_t data_len;
-	xflags_t xflags;
-	tcp_error_t trc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_recv_fibril()");
-
-	fibril_mutex_lock(&sock->recv_buffer_lock);
-
-	while (true) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "call tcp_uc_receive()");
-		while (sock->recv_buffer_used != 0 && sock->sock_core != NULL)
-			fibril_condvar_wait(&sock->recv_buffer_cv,
-			    &sock->recv_buffer_lock);
-
-		trc = tcp_uc_receive(sock->conn, sock->recv_buffer,
-		    TCP_SOCK_FRAGMENT_SIZE, &data_len, &xflags);
-
-		if (trc != TCP_EOK) {
-			sock->recv_error = trc;
-			fibril_condvar_broadcast(&sock->recv_buffer_cv);
-			if (sock->sock_core != NULL)
-				tcp_sock_notify_data(sock->sock_core);
-			break;
-		}
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "got data - broadcast recv_buffer_cv");
-
-		sock->recv_buffer_used = data_len;
-		fibril_condvar_broadcast(&sock->recv_buffer_cv);
-		if (sock->sock_core != NULL)
-			tcp_sock_notify_data(sock->sock_core);
-	}
-
-	fibril_mutex_unlock(&sock->recv_buffer_lock);
-
-	tcp_uc_delete(sock->conn);
-
-	return 0;
-}
-
-static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	tcp_client_t client;
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	socket_cores_initialize(&client.sockets);
-
-	while (true) {
-		callid = async_get_call(&call);
-		if (!IPC_GET_IMETHOD(call))
-			break;
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
-		    (int)IPC_GET_IMETHOD(call));
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case NET_SOCKET:
-			tcp_sock_socket(&client, callid, call);
-			break;
-		case NET_SOCKET_BIND:
-			tcp_sock_bind(&client, callid, call);
-			break;
-		case NET_SOCKET_LISTEN:
-			tcp_sock_listen(&client, callid, call);
-			break;
-		case NET_SOCKET_CONNECT:
-			tcp_sock_connect(&client, callid, call);
-			break;
-		case NET_SOCKET_ACCEPT:
-			tcp_sock_accept(&client, callid, call);
-			break;
-		case NET_SOCKET_SEND:
-			tcp_sock_send(&client, callid, call);
-			break;
-		case NET_SOCKET_SENDTO:
-			tcp_sock_sendto(&client, callid, call);
-			break;
-		case NET_SOCKET_RECV:
-		case NET_SOCKET_RECVFROM:
-			tcp_sock_recvfrom(&client, callid, call);
-			break;
-		case NET_SOCKET_CLOSE:
-			tcp_sock_close(&client, callid, call);
-			break;
-		case NET_SOCKET_GETSOCKOPT:
-			tcp_sock_getsockopt(&client, callid, call);
-			break;
-		case NET_SOCKET_SETSOCKOPT:
-			tcp_sock_setsockopt(&client, callid, call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-
-	/* Clean up */
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connection: Clean up");
-	async_hangup(client.sess);
-	socket_cores_release(NULL, &client.sockets, &gsock, tcp_free_sock_data);
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tcp/sock.h
===================================================================
--- uspace/srv/net/tcp/sock.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2011 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 Socket provider
- */
-
-#ifndef SOCK_H
-#define SOCK_H
-
-#include <async.h>
-
-extern int tcp_sock_init(void);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/tcp/tcp.c
===================================================================
--- uspace/srv/net/tcp/tcp.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/tcp.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,10 +42,12 @@
 #include <io/log.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <task.h>
 
+#include "conn.h"
 #include "ncsim.h"
 #include "pdu.h"
 #include "rqueue.h"
-#include "sock.h"
+#include "service.h"
 #include "std.h"
 #include "tcp.h"
@@ -159,5 +161,5 @@
 {
 	tcp_segment_t *dseg;
-	tcp_sockpair_t rident;
+	inet_ep2_t rident;
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_received_pdu()");
@@ -178,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();
@@ -192,7 +201,7 @@
 	}
 
-	rc = tcp_sock_init();
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing socket service.");
+	rc = tcp_service_init();
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing service.");
 		return ENOENT;
 	}
Index: uspace/srv/net/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tcp/tcp_type.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/tcp_type.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -41,7 +41,7 @@
 #include <fibril.h>
 #include <fibril_synch.h>
-#include <socket_core.h>
 #include <sys/types.h>
 #include <inet/addr.h>
+#include <inet/endpoint.h>
 
 struct tcp_conn;
@@ -90,5 +90,5 @@
 	/* Connection reset */
 	TCP_ERESET,
-	/* Foreign socket unspecified */
+	/* Remote endpoint unspecified */
 	TCP_EUNSPEC,
 	/* Insufficient resources */
@@ -97,5 +97,6 @@
 	TCP_EINVPREC,
 	/* Security/compartment not allowed */
-	TCP_EINVCOMP
+	TCP_EINVCOMP,
+	TCP_EAGAIN
 } tcp_error_t;
 
@@ -112,18 +113,4 @@
 } tcp_control_t;
 
-typedef struct {
-	inet_addr_t addr;
-	uint16_t port;
-} tcp_sock_t;
-
-enum tcp_port {
-	TCP_PORT_ANY = 0
-};
-
-typedef struct {
-	tcp_sock_t local;
-	tcp_sock_t foreign;
-} tcp_sockpair_t;
-
 /** Connection incoming segments queue */
 typedef struct {
@@ -155,4 +142,10 @@
 typedef void (*tcp_cstate_cb_t)(tcp_conn_t *, void *);
 
+/** Connection callbacks */
+typedef struct {
+	void (*cstate_change)(tcp_conn_t *, void *, tcp_cstate_t);
+	void (*recv_data)(tcp_conn_t *, void *);
+} tcp_cb_t;
+
 /** Connection */
 struct tcp_conn {
@@ -160,11 +153,11 @@
 	link_t link;
 
-	/** Connection state change callback function */
-	tcp_cstate_cb_t cstate_cb;
+	/** Connection callbacks function */
+	tcp_cb_t *cb;
 	/** Argument to @c cstate_cb */
-	void *cstate_cb_arg;
-
-	/** Connection identification (local and foreign socket) */
-	tcp_sockpair_t ident;
+	void *cb_arg;
+
+	/** Connection identification (local and remote endpoint) */
+	inet_ep2_t ident;
 
 	/** Active or passive connection */
@@ -274,5 +267,5 @@
 typedef struct {
 	link_t link;
-	tcp_sockpair_t sp;
+	inet_ep2_t epp;
 	tcp_segment_t *seg;
 } tcp_rqueue_entry_t;
@@ -282,5 +275,5 @@
 	link_t link;
 	suseconds_t delay;
-	tcp_sockpair_t sp;
+	inet_ep2_t epp;
 	tcp_segment_t *seg;
 } tcp_squeue_entry_t;
@@ -319,44 +312,38 @@
 } tcp_pdu_t;
 
-typedef struct {
-	async_sess_t *sess;
-	socket_cores_t sockets;
-} tcp_client_t;
-
-#define TCP_SOCK_FRAGMENT_SIZE 1024
-
-typedef struct tcp_sockdata {
-	/** Lock */
-	fibril_mutex_t lock;
-	/** Socket core */
-	socket_core_t *sock_core;
-	/** Client */
-	tcp_client_t *client;
+/** TCP client connection */
+typedef struct tcp_cconn {
 	/** Connection */
 	tcp_conn_t *conn;
-	/** Local address */
-	inet_addr_t laddr;
-	/** Backlog size */
-	int backlog;
-	/** Array of listening connections, @c backlog elements */
-	struct tcp_sock_lconn **lconn;
-	/** List of connections (from lconn) that are ready to be accepted */
-	list_t ready;
-	/** Receiving fibril */
-	fid_t recv_fibril;
-	uint8_t recv_buffer[TCP_SOCK_FRAGMENT_SIZE];
-	size_t recv_buffer_used;
-	fibril_mutex_t recv_buffer_lock;
-	fibril_condvar_t recv_buffer_cv;
-	tcp_error_t recv_error;
-} tcp_sockdata_t;
-
-typedef struct tcp_sock_lconn {
+	/** Connection ID for the client */
+	sysarg_t id;
+	/** Client */
+	struct tcp_client *client;
+	link_t lclient;
+} tcp_cconn_t;
+
+/** TCP client listener */
+typedef struct tcp_clst {
+	/** Local endpoint */
+	inet_ep_t elocal;
+	/** Connection */
 	tcp_conn_t *conn;
-	tcp_sockdata_t *socket;
-	int index;
-	link_t ready_list;
-} tcp_sock_lconn_t;
-
+	/** Listener ID for the client */
+	sysarg_t id;
+	/** Client */
+	struct tcp_client *client;
+	/** Link to tcp_client_t.clst */
+	link_t lclient;
+} tcp_clst_t;
+
+/** TCP client */
+typedef struct tcp_client {
+	/** Client callbac session */
+	async_sess_t *sess;
+	/** Client's connections */
+	list_t cconn; /* of tcp_cconn_t */
+	/** Client's listeners */
+	list_t clst;
+} tcp_client_t;
 
 #endif
Index: uspace/srv/net/tcp/test.c
===================================================================
--- uspace/srv/net/tcp/test.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/test.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -50,6 +50,5 @@
 {
 	tcp_conn_t *conn;
-	tcp_sock_t lsock;
-	tcp_sock_t fsock;
+	inet_ep2_t epp;
 	char rcv_buf[RCV_BUF_SIZE + 1];
 	size_t rcvd;
@@ -57,13 +56,15 @@
 
 	printf("test_srv()\n");
-	
-	inet_addr(&lsock.addr, 127, 0, 0, 1);
-	lsock.port = 80;
-	
-	inet_addr(&fsock.addr, 127, 0, 0, 1);
-	fsock.port = 1024;
-	
+
+	inet_ep2_init(&epp);
+
+	inet_addr(&epp.local.addr, 127, 0, 0, 1);
+	epp.local.port = 80;
+
+	inet_addr(&epp.remote.addr, 127, 0, 0, 1);
+	epp.remote.port = 1024;
+
 	printf("S: User open...\n");
-	tcp_uc_open(&lsock, &fsock, ap_passive, 0, &conn);
+	tcp_uc_open(&epp, ap_passive, 0, &conn);
 	conn->name = (char *) "S";
 
@@ -93,19 +94,20 @@
 {
 	tcp_conn_t *conn;
-	tcp_sock_t lsock;
-	tcp_sock_t fsock;
+	inet_ep2_t epp;
 	const char *msg = "Hello World!";
 
 	printf("test_cli()\n");
-	
-	inet_addr(&lsock.addr, 127, 0, 0, 1);
-	lsock.port = 1024;
-	
-	inet_addr(&fsock.addr, 127, 0, 0, 1);
-	fsock.port = 80;
+
+	inet_ep2_init(&epp);
+
+	inet_addr(&epp.local.addr, 127, 0, 0, 1);
+	epp.local.port = 1024;
+
+	inet_addr(&epp.remote.addr, 127, 0, 0, 1);
+	epp.remote.port = 80;
 
 	async_usleep(1000*1000*3);
 	printf("C: User open...\n");
-	tcp_uc_open(&lsock, &fsock, ap_active, 0, &conn);
+	tcp_uc_open(&epp, ap_active, 0, &conn);
 	conn->name = (char *) "C";
 
Index: uspace/srv/net/tcp/tqueue.c
===================================================================
--- uspace/srv/net/tcp/tqueue.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/tqueue.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -282,10 +282,10 @@
 }
 
-void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
+void tcp_transmit_segment(inet_ep2_t *epp, tcp_segment_t *seg)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG,
-	    "tcp_transmit_segment(f:(%u),l:(%u), %p)",
-	    sp->local.port, sp->foreign.port, seg);
-	
+	    "tcp_transmit_segment(l:(%u),f:(%u), %p)",
+	    epp->local.port, epp->remote.port, seg);
+
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
 	    seg->seq, seg->wnd);
@@ -301,5 +301,5 @@
 	tcp_pdu_t *pdu;
 
-	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
+	if (tcp_pdu_encode(epp, seg, &pdu) != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. Segment dropped.");
 		return;
@@ -351,8 +351,8 @@
 
 	/* Reset retransmission timer */
-	tcp_tqueue_timer_set(tqe->conn);
+	fibril_timer_set_locked(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
+	    retransmit_timeout_func, (void *) conn);
 
 	tcp_conn_unlock(conn);
-	tcp_conn_delref(conn);
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: retransmit_timeout_func(%p) end", conn->name, conn);
Index: uspace/srv/net/tcp/tqueue.h
===================================================================
--- uspace/srv/net/tcp/tqueue.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/tqueue.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,4 +36,5 @@
 #define TQUEUE_H
 
+#include <inet/endpoint.h>
 #include "std.h"
 #include "tcp_type.h"
@@ -48,5 +49,5 @@
 extern void tcp_prepare_transmit_segment(tcp_conn_t *, tcp_segment_t *);
 extern void tcp_conn_transmit_segment(tcp_conn_t *, tcp_segment_t *);
-extern void tcp_transmit_segment(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_transmit_segment(inet_ep2_t *, tcp_segment_t *);
 extern void tcp_header_setup(tcp_conn_t *, tcp_segment_t *, tcp_header_t *);
 extern void tcp_phdr_setup(tcp_conn_t *, tcp_segment_t *, tcp_phdr_t *);
Index: uspace/srv/net/tcp/ucall.c
===================================================================
--- uspace/srv/net/tcp/ucall.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/ucall.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -35,4 +35,5 @@
  */
 
+#include <errno.h>
 #include <fibril_synch.h>
 #include <io/log.h>
@@ -50,6 +51,5 @@
 /** OPEN user call
  *
- * @param lsock		Local socket
- * @param fsock		Foreign socket
+ * @param epp		Endpoint pair
  * @param acpass	Active/passive
  * @param oflags	Open flags
@@ -65,15 +65,21 @@
  * establishment.
  */
-tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
+tcp_error_t tcp_uc_open(inet_ep2_t *epp, acpass_t acpass,
     tcp_open_flags_t oflags, tcp_conn_t **conn)
 {
 	tcp_conn_t *nconn;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
-	    lsock, fsock, acpass == ap_active ? "active" : "passive",
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open(%p, %s, %s, %p)",
+	    epp, acpass == ap_active ? "active" : "passive",
 	    oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
 
-	nconn = tcp_conn_new(lsock, fsock);
-	tcp_conn_add(nconn);
+	nconn = tcp_conn_new(epp);
+	rc = tcp_conn_add(nconn);
+	if (rc != EOK) {
+		tcp_conn_delete(nconn);
+		return TCP_EEXISTS;
+	}
+
 	tcp_conn_lock(nconn);
 
@@ -188,4 +194,6 @@
 	/* Wait for data to become available */
 	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
+		tcp_conn_unlock(conn);
+		return TCP_EAGAIN;
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_receive() - wait for data");
 		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
@@ -250,5 +258,4 @@
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_close - listen/syn_sent");
 		tcp_conn_reset(conn);
-		tcp_conn_remove(conn);
 		tcp_conn_unlock(conn);
 		return TCP_EOK;
@@ -294,11 +301,16 @@
 }
 
-void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
+void tcp_uc_set_cb(tcp_conn_t *conn, tcp_cb_t *cb, void *arg)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_set_cb(%p, %p, %p)",
 	    conn, cb, arg);
 
-	conn->cstate_cb = cb;
-	conn->cstate_cb_arg = arg;
+	conn->cb = cb;
+	conn->cb_arg = arg;
+}
+
+void *tcp_uc_get_userptr(tcp_conn_t *conn)
+{
+	return conn->cb_arg;
 }
 
@@ -308,5 +320,5 @@
 
 /** Segment arrived */
-void tcp_as_segment_arrived(tcp_sockpair_t *sp, tcp_segment_t *seg)
+void tcp_as_segment_arrived(inet_ep2_t *epp, tcp_segment_t *seg)
 {
 	tcp_conn_t *conn;
@@ -314,35 +326,14 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG,
 	    "tcp_as_segment_arrived(f:(%u), l:(%u))",
-	    sp->foreign.port, sp->local.port);
-
-	conn = tcp_conn_find_ref(sp);
+	    epp->remote.port, epp->local.port);
+
+	conn = tcp_conn_find_ref(epp);
 	if (conn == NULL) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "No connection found.");
-		tcp_unexpected_segment(sp, seg);
+		tcp_unexpected_segment(epp, seg);
 		return;
 	}
 
-	tcp_conn_lock(conn);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");
-		tcp_unexpected_segment(sp, seg);
-		tcp_conn_unlock(conn);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	if (inet_addr_is_any(&conn->ident.foreign.addr))
-		conn->ident.foreign.addr = sp->foreign.addr;
-	
-	if (conn->ident.foreign.port == TCP_PORT_ANY)
-		conn->ident.foreign.port = sp->foreign.port;
-	
-	if (inet_addr_is_any(&conn->ident.local.addr))
-		conn->ident.local.addr = sp->local.addr;
-
-	tcp_conn_segment_arrived(conn, seg);
-
-	tcp_conn_unlock(conn);
+	tcp_conn_segment_arrived(conn, epp, seg);
 	tcp_conn_delref(conn);
 }
Index: uspace/srv/net/tcp/ucall.h
===================================================================
--- uspace/srv/net/tcp/ucall.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/tcp/ucall.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,4 +36,5 @@
 #define UCALL_H
 
+#include <inet/endpoint.h>
 #include <sys/types.h>
 #include "tcp_type.h"
@@ -42,5 +43,5 @@
  * User calls
  */
-extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t,
+extern tcp_error_t tcp_uc_open(inet_ep2_t *, acpass_t,
     tcp_open_flags_t, tcp_conn_t **);
 extern tcp_error_t tcp_uc_send(tcp_conn_t *, void *, size_t, xflags_t);
@@ -50,10 +51,11 @@
 extern void tcp_uc_status(tcp_conn_t *, tcp_conn_status_t *);
 extern void tcp_uc_delete(tcp_conn_t *);
-extern void tcp_uc_set_cstate_cb(tcp_conn_t *, tcp_cstate_cb_t, void *);
+extern void tcp_uc_set_cb(tcp_conn_t *, tcp_cb_t *, void *);
+extern void *tcp_uc_get_userptr(tcp_conn_t *);
 
 /*
  * Arriving segments
  */
-extern void tcp_as_segment_arrived(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_as_segment_arrived(inet_ep2_t *, tcp_segment_t *);
 
 /*
Index: uspace/srv/net/udp/Makefile
===================================================================
--- uspace/srv/net/udp/Makefile	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/Makefile	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -28,6 +28,11 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+
+LIBS = \
+	$(LIBNETTL_PREFIX)/libnettl.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBNETTL_PREFIX)/include
+
 BINARY = udp
 
@@ -35,7 +40,6 @@
 	assoc.c \
 	msg.c \
-	sock.c \
 	pdu.c \
-	ucall.c \
+	service.c \
 	udp.c \
 	udp_inet.c
Index: uspace/srv/net/udp/assoc.c
===================================================================
--- uspace/srv/net/udp/assoc.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/assoc.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,7 +36,10 @@
 
 #include <adt/list.h>
+#include <errno.h>
 #include <stdbool.h>
 #include <fibril_synch.h>
+#include <inet/endpoint.h>
 #include <io/log.h>
+#include <nettl/amap.h>
 #include <stdlib.h>
 
@@ -44,23 +47,36 @@
 #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 udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *);
-static int udp_assoc_queue_msg(udp_assoc_t *, udp_sockpair_t *, udp_msg_t *);
-static bool udp_socket_match(udp_sock_t *, udp_sock_t *);
-static bool udp_sockpair_match(udp_sockpair_t *, udp_sockpair_t *);
+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 *);
+static int udp_assoc_queue_msg(udp_assoc_t *, inet_ep2_t *, udp_msg_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.
  *
- * @param lsock		Local socket (will be deeply copied)
- * @param fsock		Foreign socket (will be deeply copied)
+ * @param epp		Endpoint pair (will be copied)
+ * @param cb		Callbacks
+ * @param cb_arg	Callback argument
  * @return		New association or NULL
  */
-udp_assoc_t *udp_assoc_new(udp_sock_t *lsock, udp_sock_t *fsock)
+udp_assoc_t *udp_assoc_new(inet_ep2_t *epp, udp_assoc_cb_t *cb, void *cb_arg)
 {
 	udp_assoc_t *assoc = NULL;
@@ -80,10 +96,9 @@
 	fibril_condvar_initialize(&assoc->rcv_queue_cv);
 
-	if (lsock != NULL)
-		assoc->ident.local = *lsock;
-	
-	if (fsock != NULL)
-		assoc->ident.foreign = *fsock;
-
+	if (epp != NULL)
+		assoc->ident = *epp;
+
+	assoc->cb = cb;
+	assoc->cb_arg = cb_arg;
 	return assoc;
 error:
@@ -166,10 +181,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;
 }
 
@@ -181,4 +210,5 @@
 {
 	fibril_mutex_lock(&assoc_list_lock);
+	amap_remove(amap, &assoc->ident);
 	list_remove(&assoc->link);
 	fibril_mutex_unlock(&assoc_list_lock);
@@ -196,82 +226,52 @@
 	    assoc, iplink);
 	fibril_mutex_lock(&assoc->lock);
-	assoc->ident.iplink = iplink;
+	assoc->ident.local_link = iplink;
 	fibril_mutex_unlock(&assoc->lock);
 }
 
-/** Set foreign socket in association.
- *
- * @param assoc		Association
- * @param fsock		Foreign socket (deeply copied)
- */
-void udp_assoc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_foreign(%p, %p)", assoc, fsock);
-	fibril_mutex_lock(&assoc->lock);
-	assoc->ident.foreign = *fsock;
-	fibril_mutex_unlock(&assoc->lock);
-}
-
-/** Set local socket in association.
- *
- * @param assoc Association
- * @param lsock Local socket (deeply copied)
- *
- */
-void udp_assoc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock);
-	fibril_mutex_lock(&assoc->lock);
-	assoc->ident.local = *lsock;
-	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);
-}
-
 /** Send message to association.
  *
  * @param assoc		Association
- * @param fsock		Foreign socket or NULL not to override @a assoc
+ * @param remote	Remote endpoint or NULL not to override @a assoc
  * @param msg		Message
  *
  * @return		EOK on success
- *			EINVAL if foreign socket is not set
+ *			EINVAL if remote endpoint is not set
  *			ENOMEM if out of resources
  *			EIO if no route to destination exists
  */
-int udp_assoc_send(udp_assoc_t *assoc, udp_sock_t *fsock, udp_msg_t *msg)
+int udp_assoc_send(udp_assoc_t *assoc, inet_ep_t *remote, udp_msg_t *msg)
 {
 	udp_pdu_t *pdu;
-	udp_sockpair_t sp;
+	inet_ep2_t epp;
 	int rc;
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send(%p, %p, %p)",
-	    assoc, fsock, msg);
-
-	/* @a fsock can be used to override the foreign socket */
-	sp = assoc->ident;
-	if (fsock != NULL)
-		sp.foreign = *fsock;
-
-	if ((inet_addr_is_any(&sp.foreign.addr)) ||
-	    (sp.foreign.port == UDP_PORT_ANY))
+	    assoc, remote, msg);
+
+	/* @a remote can be used to override the remote endpoint */
+	epp = assoc->ident;
+	if (remote != NULL)
+		epp.remote = *remote;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - check addr any");
+
+	if ((inet_addr_is_any(&epp.remote.addr)) ||
+	    (epp.remote.port == inet_port_any))
 		return EINVAL;
 
-	rc = udp_pdu_encode(&sp, msg, &pdu);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - check version");
+
+	if (epp.remote.addr.version != epp.local.addr.version)
+		return EINVAL;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - encode pdu");
+
+	rc = udp_pdu_encode(&epp, msg, &pdu);
 	if (rc != EOK)
 		return ENOMEM;
 
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - transmit");
+
 	rc = udp_transmit_pdu(pdu);
 	udp_pdu_delete(pdu);
@@ -280,4 +280,5 @@
 		return EIO;
 
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - success");
 	return EOK;
 }
@@ -287,5 +288,5 @@
  * Pull one message from the association's receive queue.
  */
-int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, udp_sock_t *fsock)
+int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, inet_ep_t *remote)
 {
 	link_t *link;
@@ -303,5 +304,5 @@
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv() - association was reset");
 		fibril_mutex_unlock(&assoc->lock);
-		return ECONNABORTED;
+		return ENXIO;
 	}
 
@@ -313,5 +314,5 @@
 
 	*msg = rqe->msg;
-	*fsock = rqe->sp.foreign;
+	*remote = rqe->epp.remote;
 	free(rqe);
 
@@ -323,12 +324,12 @@
  * Find the association to which the message belongs and queue it.
  */
-void udp_assoc_received(udp_sockpair_t *rsp, udp_msg_t *msg)
+void udp_assoc_received(inet_ep2_t *repp, udp_msg_t *msg)
 {
 	udp_assoc_t *assoc;
 	int rc;
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg);
-
-	assoc = udp_assoc_find_ref(rsp);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", repp, msg);
+
+	assoc = udp_assoc_find_ref(repp);
 	if (assoc == NULL) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "No association found. Message dropped.");
@@ -339,9 +340,15 @@
 	}
 
-	rc = udp_assoc_queue_msg(assoc, rsp, msg);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "Out of memory. Message dropped.");
+	if (0) {
+		rc = udp_assoc_queue_msg(assoc, repp, msg);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Out of memory. Message dropped.");
 		/* XXX Generate ICMP error? */
-	}
+		}
+	}
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "call assoc->cb->recv_msg");
+	assoc->cb->recv_msg(assoc->cb_arg, repp, msg);
+	udp_assoc_delref(assoc);
 }
 
@@ -359,5 +366,5 @@
 }
 
-static int udp_assoc_queue_msg(udp_assoc_t *assoc, udp_sockpair_t *sp,
+static int udp_assoc_queue_msg(udp_assoc_t *assoc, inet_ep2_t *epp,
     udp_msg_t *msg)
 {
@@ -365,5 +372,5 @@
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)",
-	    assoc, sp, msg);
+	    assoc, epp, msg);
 
 	rqe = calloc(1, sizeof(udp_rcv_queue_entry_t));
@@ -372,5 +379,5 @@
 
 	link_initialize(&rqe->link);
-	rqe->sp = *sp;
+	rqe->epp = *epp;
 	rqe->msg = msg;
 
@@ -384,71 +391,34 @@
 }
 
-/** Match socket with pattern. */
-static bool udp_socket_match(udp_sock_t *sock, udp_sock_t *patt)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG,
-	    "udp_socket_match(sock=(%u), pat=(%u))", sock->port, patt->port);
-	
-	if ((!inet_addr_is_any(&patt->addr)) &&
-	    (!inet_addr_compare(&patt->addr, &sock->addr)))
-		return false;
-	
-	if ((patt->port != UDP_PORT_ANY) &&
-	    (patt->port != sock->port))
-		return false;
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " -> match");
-	
-	return true;
-}
-
-/** Match socket pair with pattern. */
-static bool udp_sockpair_match(udp_sockpair_t *sp, udp_sockpair_t *pattern)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sockpair_match(%p, %p)", sp, pattern);
-
-	if (!udp_socket_match(&sp->local, &pattern->local))
-		return false;
-
-	if (!udp_socket_match(&sp->foreign, &pattern->foreign))
-		return false;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Socket pair matched.");
-	return true;
-}
-
-
-/** Find association structure for specified socket pair.
- *
- * An association is uniquely identified by a socket pair. Look up our
- * association map and return association structure based on socket pair.
+/** Find association structure for specified endpoint pair.
+ *
+ * An association is uniquely identified by an endpoint pair. Look up our
+ * association map and return association structure based on endpoint pair.
  * The association reference count is bumped by one.
  *
- * @param sp	Socket pair
+ * @param epp	Endpoint pair
  * @return	Association structure or NULL if not found.
  */
-static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *sp)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_find_ref(%p)", sp);
-	
+static udp_assoc_t *udp_assoc_find_ref(inet_ep2_t *epp)
+{
+	int rc;
+	void *arg;
+	udp_assoc_t *assoc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_find_ref(%p)", epp);
 	fibril_mutex_lock(&assoc_list_lock);
-	
-	list_foreach(assoc_list, link, udp_assoc_t, assoc) {
-		udp_sockpair_t *asp = &assoc->ident;
-		
-		/* Skip unbound associations */
-		if (asp->local.port == UDP_PORT_ANY)
-			continue;
-		
-		if (udp_sockpair_match(sp, asp)) {
-			log_msg(LOG_DEFAULT, LVL_DEBUG, "Returning assoc %p", assoc);
-			udp_assoc_addref(assoc);
-			fibril_mutex_unlock(&assoc_list_lock);
-			return assoc;
-		}
-	}
-	
+
+	rc = amap_find_match(amap, epp, &arg);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		fibril_mutex_unlock(&assoc_list_lock);
+		return NULL;
+	}
+
+	assoc = (udp_assoc_t *)arg;
+	udp_assoc_addref(assoc);
+
 	fibril_mutex_unlock(&assoc_list_lock);
-	return NULL;
+	return assoc;
 }
 
Index: uspace/srv/net/udp/assoc.h
===================================================================
--- uspace/srv/net/udp/assoc.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/assoc.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,21 +36,20 @@
 #define ASSOC_H
 
+#include <inet/endpoint.h>
 #include <ipc/loc.h>
 #include <sys/types.h>
 #include "udp_type.h"
 
-extern udp_assoc_t *udp_assoc_new(udp_sock_t *, udp_sock_t *);
+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_foreign(udp_assoc_t *, udp_sock_t *);
-extern void udp_assoc_set_local(udp_assoc_t *, udp_sock_t *);
-extern void udp_assoc_set_local_port(udp_assoc_t *, uint16_t);
-extern int udp_assoc_send(udp_assoc_t *, udp_sock_t *, udp_msg_t *);
-extern int udp_assoc_recv(udp_assoc_t *, udp_msg_t **, udp_sock_t *);
-extern void udp_assoc_received(udp_sockpair_t *, udp_msg_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 *);
+extern void udp_assoc_received(inet_ep2_t *, udp_msg_t *);
 extern void udp_assoc_reset(udp_assoc_t *);
 
Index: uspace/srv/net/udp/msg.c
===================================================================
--- uspace/srv/net/udp/msg.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/msg.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -50,4 +50,5 @@
 void udp_msg_delete(udp_msg_t *msg)
 {
+	free(msg->data);
 	free(msg);
 }
Index: uspace/srv/net/udp/pdu.c
===================================================================
--- uspace/srv/net/udp/pdu.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/pdu.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -41,5 +41,4 @@
 #include <stdlib.h>
 #include <inet/addr.h>
-#include <net/socket_codes.h>
 #include "msg.h"
 #include "pdu.h"
@@ -163,5 +162,5 @@
 
 /** Decode incoming PDU */
-int udp_pdu_decode(udp_pdu_t *pdu, udp_sockpair_t *sp, udp_msg_t **msg)
+int udp_pdu_decode(udp_pdu_t *pdu, inet_ep2_t *epp, udp_msg_t **msg)
 {
 	udp_msg_t *nmsg;
@@ -180,8 +179,9 @@
 	hdr = (udp_header_t *)pdu->data;
 
-	sp->foreign.port = uint16_t_be2host(hdr->src_port);
-	sp->foreign.addr = pdu->src;
-	sp->local.port = uint16_t_be2host(hdr->dest_port);
-	sp->local.addr = pdu->dest;
+	epp->local_link = pdu->iplink;
+	epp->remote.port = uint16_t_be2host(hdr->src_port);
+	epp->remote.addr = pdu->src;
+	epp->local.port = uint16_t_be2host(hdr->dest_port);
+	epp->local.addr = pdu->dest;
 
 	length = uint16_t_be2host(hdr->length);
@@ -197,6 +197,10 @@
 		return ENOMEM;
 
-	nmsg->data = text;
 	nmsg->data_size = length - sizeof(udp_header_t);
+	nmsg->data = malloc(nmsg->data_size);
+	if (nmsg->data == NULL)
+		return ENOMEM;
+
+	memcpy(nmsg->data, text, nmsg->data_size);
 
 	*msg = nmsg;
@@ -205,5 +209,5 @@
 
 /** Encode outgoing PDU */
-int udp_pdu_encode(udp_sockpair_t *sp, udp_msg_t *msg, udp_pdu_t **pdu)
+int udp_pdu_encode(inet_ep2_t *epp, udp_msg_t *msg, udp_pdu_t **pdu)
 {
 	udp_pdu_t *npdu;
@@ -215,7 +219,7 @@
 		return ENOMEM;
 
-	npdu->iplink = sp->iplink;
-	npdu->src = sp->local.addr;
-	npdu->dest = sp->foreign.addr;
+	npdu->iplink = epp->local_link;
+	npdu->src = epp->local.addr;
+	npdu->dest = epp->remote.addr;
 
 	npdu->data_size = sizeof(udp_header_t) + msg->data_size;
@@ -227,6 +231,6 @@
 
 	hdr = (udp_header_t *)npdu->data;
-	hdr->src_port = host2uint16_t_be(sp->local.port);
-	hdr->dest_port = host2uint16_t_be(sp->foreign.port);
+	hdr->src_port = host2uint16_t_be(epp->local.port);
+	hdr->dest_port = host2uint16_t_be(epp->remote.port);
 	hdr->length = host2uint16_t_be(npdu->data_size);
 	hdr->checksum = 0;
Index: uspace/srv/net/udp/pdu.h
===================================================================
--- uspace/srv/net/udp/pdu.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/pdu.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,4 +36,5 @@
 #define PDU_H
 
+#include <inet/endpoint.h>
 #include <sys/types.h>
 #include "std.h"
@@ -42,6 +43,6 @@
 extern udp_pdu_t *udp_pdu_new(void);
 extern void udp_pdu_delete(udp_pdu_t *);
-extern int udp_pdu_decode(udp_pdu_t *, udp_sockpair_t *, udp_msg_t **);
-extern int udp_pdu_encode(udp_sockpair_t *, udp_msg_t *, udp_pdu_t **);
+extern int udp_pdu_decode(udp_pdu_t *, inet_ep2_t *, udp_msg_t **);
+extern int udp_pdu_encode(inet_ep2_t *, udp_msg_t *, udp_pdu_t **);
 
 #endif
Index: uspace/srv/net/udp/service.c
===================================================================
--- uspace/srv/net/udp/service.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/srv/net/udp/service.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,577 @@
+/*
+ * 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 HelenOS service implementation
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <inet/endpoint.h>
+#include <io/log.h>
+#include <ipc/services.h>
+#include <ipc/udp.h>
+#include <loc.h>
+#include <macros.h>
+#include <stdlib.h>
+
+#include "assoc.h"
+#include "msg.h"
+#include "service.h"
+#include "udp_type.h"
+
+#define NAME "udp"
+
+#define MAX_MSG_SIZE DATA_XFER_LIMIT
+
+static void udp_cassoc_recv_msg(void *, inet_ep2_t *, udp_msg_t *);
+
+static udp_assoc_cb_t udp_cassoc_cb = {
+	.recv_msg = udp_cassoc_recv_msg
+};
+
+static int udp_cassoc_queue_msg(udp_cassoc_t *cassoc, inet_ep2_t *epp,
+    udp_msg_t *msg)
+{
+	udp_crcv_queue_entry_t *rqe;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_cassoc_queue_msg(%p, %p, %p)",
+	    cassoc, epp, msg);
+
+	rqe = calloc(1, sizeof(udp_crcv_queue_entry_t));
+	if (rqe == NULL)
+		return ENOMEM;
+
+	link_initialize(&rqe->link);
+	rqe->epp = *epp;
+	rqe->msg = msg;
+	rqe->cassoc = cassoc;
+
+//	fibril_mutex_lock(&assoc->lock);
+	list_append(&rqe->link, &cassoc->client->crcv_queue);
+//	fibril_mutex_unlock(&assoc->lock);
+
+//	fibril_condvar_broadcast(&assoc->rcv_queue_cv);
+
+	return EOK;
+}
+
+static void udp_ev_data(udp_client_t *client)
+{
+	async_exch_t *exch;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_ev_data()");
+
+	exch = async_exchange_begin(client->sess);
+	aid_t req = async_send_0(exch, UDP_EV_DATA, NULL);
+	async_exchange_end(exch);
+
+	async_forget(req);
+}
+
+static int udp_cassoc_create(udp_client_t *client, udp_assoc_t *assoc,
+    udp_cassoc_t **rcassoc)
+{
+	udp_cassoc_t *cassoc;
+	sysarg_t id;
+
+	cassoc = calloc(1, sizeof(udp_cassoc_t));
+	if (cassoc == NULL)
+		return ENOMEM;
+
+	/* Allocate new ID */
+	id = 0;
+	list_foreach (client->cassoc, lclient, udp_cassoc_t, cassoc) {
+		if (cassoc->id >= id)
+			id = cassoc->id + 1;
+	}
+
+	cassoc->id = id;
+	cassoc->client = client;
+	cassoc->assoc = assoc;
+
+	list_append(&cassoc->lclient, &client->cassoc);
+	*rcassoc = cassoc;
+	return EOK;
+}
+
+static void udp_cassoc_destroy(udp_cassoc_t *cassoc)
+{
+	list_remove(&cassoc->lclient);
+	free(cassoc);
+}
+
+static int udp_cassoc_get(udp_client_t *client, sysarg_t id,
+    udp_cassoc_t **rcassoc)
+{
+	list_foreach (client->cassoc, lclient, udp_cassoc_t, cassoc) {
+		if (cassoc->id == id) {
+			*rcassoc = cassoc;
+			return EOK;
+		}
+	}
+
+	return ENOENT;
+}
+
+static void udp_cassoc_recv_msg(void *arg, inet_ep2_t *epp, udp_msg_t *msg)
+{
+	udp_cassoc_t *cassoc = (udp_cassoc_t *) arg;
+
+	udp_cassoc_queue_msg(cassoc, epp, msg);
+	udp_ev_data(cassoc->client);
+}
+
+static int udp_assoc_create_impl(udp_client_t *client, inet_ep2_t *epp,
+    sysarg_t *rassoc_id)
+{
+	udp_assoc_t *assoc;
+	udp_cassoc_t *cassoc;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_create_impl");
+
+	assoc = udp_assoc_new(epp, NULL, NULL);
+	if (assoc == NULL)
+		return EIO;
+
+	if (epp->local_link != 0)
+		udp_assoc_set_iplink(assoc, epp->local_link);
+
+	rc = udp_cassoc_create(client, assoc, &cassoc);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		udp_assoc_delete(assoc);
+		return ENOMEM;
+	}
+
+	assoc->cb = &udp_cassoc_cb;
+	assoc->cb_arg = cassoc;
+
+	rc = udp_assoc_add(assoc);
+	if (rc != EOK) {
+		udp_cassoc_destroy(cassoc);
+		udp_assoc_delete(assoc);
+		return rc;
+	}
+
+	*rassoc_id = cassoc->id;
+	return EOK;
+}
+
+static int udp_assoc_destroy_impl(udp_client_t *client, sysarg_t assoc_id)
+{
+	udp_cassoc_t *cassoc;
+	int rc;
+
+	rc = udp_cassoc_get(client, assoc_id, &cassoc);
+	if (rc != EOK) {
+		assert(rc == ENOENT);
+		return ENOENT;
+	}
+
+	udp_assoc_remove(cassoc->assoc);
+	udp_assoc_reset(cassoc->assoc);
+	udp_assoc_delete(cassoc->assoc);
+	udp_cassoc_destroy(cassoc);
+	return EOK;
+}
+
+static int udp_assoc_send_msg_impl(udp_client_t *client, sysarg_t assoc_id,
+    inet_ep_t *dest, void *data, size_t size)
+{
+	udp_msg_t msg;
+	udp_cassoc_t *cassoc;
+	int rc;
+
+	rc = udp_cassoc_get(client, assoc_id, &cassoc);
+	if (rc != EOK)
+		return rc;
+
+	msg.data = data;
+	msg.data_size = size;
+	rc = udp_assoc_send(cassoc->assoc, dest, &msg);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+static void udp_callback_create_srv(udp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_callback_create_srv()");
+
+	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	client->sess = sess;
+	async_answer_0(iid, EOK);
+}
+
+static void udp_assoc_create_srv(udp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	inet_ep2_t epp;
+	sysarg_t assoc_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_create_srv()");
+
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (size != sizeof(inet_ep2_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	rc = async_data_write_finalize(callid, &epp, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	rc = udp_assoc_create_impl(client, &epp, &assoc_id);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	async_answer_1(iid, EOK, assoc_id);
+}
+
+static void udp_assoc_destroy_srv(udp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	sysarg_t assoc_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_destroy_srv()");
+
+	assoc_id = IPC_GET_ARG1(*icall);
+	rc = udp_assoc_destroy_impl(client, assoc_id);
+	async_answer_0(iid, rc);
+}
+
+static void udp_assoc_send_msg_srv(udp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	inet_ep_t dest;
+	sysarg_t assoc_id;
+	void *data;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send_msg_srv()");
+
+	/* Receive dest */
+
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (size != sizeof(inet_ep_t)) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	rc = async_data_write_finalize(callid, &dest, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	/* Receive message data */
+
+	if (!async_data_write_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (size > MAX_MSG_SIZE) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	data = malloc(size);
+	if (data == NULL) {
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+	}
+
+	rc = async_data_write_finalize(callid, data, size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		free(data);
+		return;
+	}
+
+	assoc_id = IPC_GET_ARG1(*icall);
+
+	rc = udp_assoc_send_msg_impl(client, assoc_id, &dest, data, size);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		free(data);
+		return;
+	}
+
+	async_answer_0(iid, EOK);
+	free(data);
+}
+
+static udp_crcv_queue_entry_t *udp_rmsg_get_next(udp_client_t *client)
+{
+	link_t *link;
+
+	link = list_first(&client->crcv_queue);
+	if (link == NULL)
+		return NULL;
+
+	return list_get_instance(link, udp_crcv_queue_entry_t, link);
+}
+
+static void udp_rmsg_info_srv(udp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	udp_crcv_queue_entry_t *enext;
+	sysarg_t assoc_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_info_srv()");
+	enext = udp_rmsg_get_next(client);
+
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (enext == NULL) {
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	rc = async_data_read_finalize(callid, &enext->epp.remote,
+	    max(size, (ssize_t)sizeof(inet_ep_t)));
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	assoc_id = enext->cassoc->id;
+	size = enext->msg->data_size;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_info_srv(): assoc_id=%zu, "
+	    "size=%zu", assoc_id, size);
+	async_answer_2(iid, EOK, assoc_id, size);
+}
+
+static void udp_rmsg_read_srv(udp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	ssize_t msg_size;
+	udp_crcv_queue_entry_t *enext;
+	void *data;
+	size_t size;
+	ssize_t off;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_read_srv()");
+	off = IPC_GET_ARG1(*icall);
+
+	enext = udp_rmsg_get_next(client);
+
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+
+	if (enext == NULL) {
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	data = enext->msg->data + off;
+	msg_size = enext->msg->data_size;
+
+	rc = async_data_read_finalize(callid, data, max(msg_size - off,
+	    (ssize_t)size));
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	async_answer_0(iid, EOK);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_read_srv(): OK");
+}
+
+static void udp_rmsg_discard_srv(udp_client_t *client, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	udp_crcv_queue_entry_t *enext;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_discard_srv()");
+
+	enext = udp_rmsg_get_next(client);
+	if (enext == NULL) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "usg_rmsg_discard_srv: enext==NULL");
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	list_remove(&enext->link);
+	udp_msg_delete(enext->msg);
+	free(enext);
+	async_answer_0(iid, EOK);
+}
+
+static void udp_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	udp_client_t client;
+	size_t n;
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn()");
+
+	client.sess = NULL;
+	list_initialize(&client.cassoc);
+	list_initialize(&client.crcv_queue);
+
+	while (true) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: wait req");
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: method=%d",
+		    (int)method);
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			break;
+		}
+
+		switch (method) {
+		case UDP_CALLBACK_CREATE:
+			udp_callback_create_srv(&client, callid, &call);
+			break;
+		case UDP_ASSOC_CREATE:
+			udp_assoc_create_srv(&client, callid, &call);
+			break;
+		case UDP_ASSOC_DESTROY:
+			udp_assoc_destroy_srv(&client, callid, &call);
+			break;
+		case UDP_ASSOC_SEND_MSG:
+			udp_assoc_send_msg_srv(&client, callid, &call);
+			break;
+		case UDP_RMSG_INFO:
+			udp_rmsg_info_srv(&client, callid, &call);
+			break;
+		case UDP_RMSG_READ:
+			udp_rmsg_read_srv(&client, callid, &call);
+			break;
+		case UDP_RMSG_DISCARD:
+			udp_rmsg_discard_srv(&client, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: terminated");
+
+	n = list_count(&client.cassoc);
+	if (n != 0) {
+		log_msg(LOG_DEFAULT, LVL_WARN, "udp_client_conn: "
+		    "Client with %zu active associations closed session.", n);
+		/* XXX Clean up */
+	}
+
+	/* XXX Clean up client receive queue */
+
+	if (client.sess != NULL)
+		async_hangup(client.sess);
+}
+
+int udp_service_init(void)
+{
+	int rc;
+	service_id_t sid;
+
+	async_set_client_connection(udp_client_conn);
+
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
+		return EIO;
+	}
+
+	rc = loc_service_register(SERVICE_NAME_UDP, &sid);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service.");
+		return EIO;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/service.h
===================================================================
--- uspace/srv/net/udp/service.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
+++ uspace/srv/net/udp/service.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -0,0 +1,43 @@
+/*
+ * 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 HelenOS service implementation
+ */
+
+#ifndef SERVICE_H
+#define SERVICE_H
+
+extern int udp_service_init(void);
+
+#endif
+
+/** @}
+ */
Index: pace/srv/net/udp/sock.c
===================================================================
--- uspace/srv/net/udp/sock.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,836 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * Copyright (c) 2013 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 Socket provider
- */
-
-#include <async.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <inet/inet.h>
-#include <io/log.h>
-#include <ipc/services.h>
-#include <ipc/socket.h>
-#include <net/socket.h>
-#include <ns.h>
-
-#include "sock.h"
-#include "std.h"
-#include "udp_type.h"
-#include "ucall.h"
-
-/** Free ports pool start. */
-#define UDP_FREE_PORTS_START		1025
-
-/** Free ports pool end. */
-#define UDP_FREE_PORTS_END		65535
-
-static int last_used_port = UDP_FREE_PORTS_START - 1;
-static socket_ports_t gsock;
-
-static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-static int udp_sock_recv_fibril(void *arg);
-
-int udp_sock_init(void)
-{
-	socket_ports_initialize(&gsock);
-	
-	async_set_client_connection(udp_sock_connection);
-	
-	int rc = service_register(SERVICE_UDP);
-	if (rc != EOK)
-		return EEXIST;
-	
-	return EOK;
-}
-
-static void udp_free_sock_data(socket_core_t *sock_core)
-{
-	udp_sockdata_t *socket;
-
-	socket = (udp_sockdata_t *)sock_core->specific_data;
-	(void)socket;
-
-	/* XXX We need to force the receive fibril to quit */
-}
-
-static void udp_sock_notify_data(socket_core_t *sock_core)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_notify_data(%d)", sock_core->socket_id);
-	async_exch_t *exch = async_exchange_begin(sock_core->sess);
-	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) sock_core->socket_id,
-	    UDP_FRAGMENT_SIZE, 0, 0, 1);
-	async_exchange_end(exch);
-}
-
-static void udp_sock_socket(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	udp_sockdata_t *sock;
-	socket_core_t *sock_core;
-	int sock_id;
-	int rc;
-	ipc_call_t answer;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_socket()");
-	sock = calloc(1, sizeof(udp_sockdata_t));
-	if (sock == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&sock->lock);
-	sock->client = client;
-
-	sock->recv_buffer_used = 0;
-	sock->recv_error = UDP_EOK;
-	fibril_mutex_initialize(&sock->recv_buffer_lock);
-	fibril_condvar_initialize(&sock->recv_buffer_cv);
-
-	rc = udp_uc_create(&sock->assoc);
-	if (rc != EOK) {
-		free(sock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sock->recv_fibril = fibril_create(udp_sock_recv_fibril, sock);
-	if (sock->recv_fibril == 0) {
-		udp_uc_destroy(sock->assoc);
-		free(sock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	sock_id = SOCKET_GET_SOCKET_ID(call);
-	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
-	if (rc != EOK) {
-		fibril_destroy(sock->recv_fibril);
-		udp_uc_destroy(sock->assoc);
-		free(sock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	fibril_add_ready(sock->recv_fibril);
-
-	sock_core = socket_cores_find(&client->sockets, sock_id);
-	assert(sock_core != NULL);
-	sock->sock_core = sock_core;
-	
-	SOCKET_SET_SOCKET_ID(answer, sock_id);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, UDP_FRAGMENT_SIZE);
-	SOCKET_SET_HEADER_SIZE(answer, sizeof(udp_header_t));
-	async_answer_3(callid, EOK, IPC_GET_ARG1(answer),
-	    IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
-}
-
-static void udp_sock_bind(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_bind()");
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - async_data_write_accept");
-	
-	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);
-		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),
-	    addr6, addr_len, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
-	    last_used_port);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		goto out;
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_cores_find");
-	
-	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;
-	}
-	
-	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:
-		rc = EOK;
-		break;
-/*	case TCP_ENOTEXIST:
-		rc = ENOTCONN;
-		break;
-	case TCP_ECLOSING:
-		rc = ENOTCONN;
-		break;
-	case TCP_ERESET:
-		rc = ECONNABORTED;
-		break;*/
-	default:
-		assert(false);
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - success");
-	async_answer_0(callid, rc);
-	
-out:
-	if (addr6 != NULL)
-		free(addr6);
-}
-
-static void udp_sock_listen(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_listen()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_connect(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connect()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_accept(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_accept()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_sendto(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_send()");
-	
-	uint8_t *buffer = calloc(UDP_FRAGMENT_SIZE, 1);
-	if (buffer == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-	
-	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_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_len != sizeof(struct sockaddr_in)) &&
-		    (addr_len != sizeof(struct sockaddr_in6))) {
-			async_answer_0(callid, EINVAL);
-			goto out;
-		}
-		
-		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
-		fsocket_ptr = NULL;
-	
-	int socket_id = SOCKET_GET_SOCKET_ID(call);
-	
-	SOCKET_GET_FLAGS(call);
-	
-	socket_core_t *sock_core =
-	    socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		goto out;
-	}
-	
-	udp_sockdata_t *socket =
-	    (udp_sockdata_t *) sock_core->specific_data;
-	
-	if (sock_core->port <= 0) {
-		/* Implicitly bind socket to port */
-		int rc = socket_bind_free_port(&gsock, sock_core,
-		    UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, last_used_port);
-		if (rc != EOK) {
-			async_answer_0(callid, rc);
-			goto out;
-		}
-		
-		assert(sock_core->port > 0);
-		
-		udp_error_t urc = udp_uc_set_local_port(socket->assoc,
-		    sock_core->port);
-		
-		if (urc != UDP_EOK) {
-			// TODO: better error handling
-			async_answer_0(callid, EINTR);
-			goto out;
-		}
-		
-		last_used_port = sock_core->port;
-	}
-	
-	fibril_mutex_lock(&socket->lock);
-	
-	if (inet_addr_is_any(&socket->assoc->ident.local.addr) &&
-		socket->assoc->ident.iplink == 0) {
-		/* Determine local IP address */
-		inet_addr_t loc_addr;
-		inet_addr_t rem_addr;
-		
-		rem_addr = fsocket_ptr ? fsocket.addr :
-		    socket->assoc->ident.foreign.addr;
-		
-		int rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_sendto: Failed to "
-			    "determine local address.");
-			goto out;
-		}
-		
-		socket->assoc->ident.local.addr = loc_addr;
-	}
-	
-	assert(socket->assoc != NULL);
-	
-	int fragments = SOCKET_GET_DATA_FRAGMENTS(call);
-	for (int index = 0; index < fragments; index++) {
-		ipc_callid_t wcallid;
-		size_t length;
-		
-		if (!async_data_write_receive(&wcallid, &length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			goto out;
-		}
-		
-		if (length > UDP_FRAGMENT_SIZE)
-			length = UDP_FRAGMENT_SIZE;
-		
-		int rc = async_data_write_finalize(wcallid, buffer, length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			goto out;
-		}
-		
-		udp_error_t urc =
-		    udp_uc_send(socket->assoc, fsocket_ptr, buffer, length, 0);
-		
-		switch (urc) {
-		case UDP_EOK:
-			rc = EOK;
-			break;
-		case UDP_ENORES:
-			rc = ENOMEM;
-			break;
-		case UDP_EUNSPEC:
-			rc = EINVAL;
-			break;
-		case UDP_ENOROUTE:
-			rc = EIO;
-			break;
-		default:
-			assert(false);
-		}
-		
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			goto out;
-		}
-	}
-	
-	ipc_call_t answer;
-	
-	IPC_SET_ARG1(answer, 0);
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, UDP_FRAGMENT_SIZE);
-	async_answer_2(callid, EOK, IPC_GET_ARG1(answer),
-	    IPC_GET_ARG2(answer));
-	fibril_mutex_unlock(&socket->lock);
-	
-out:
-	if (addr6 != NULL)
-		free(addr6);
-	
-	free(buffer);
-}
-
-static void udp_sock_recvfrom(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "%p: udp_sock_recv[from]()", client);
-	
-	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;
-	}
-	
-	udp_sockdata_t *socket =
-	    (udp_sockdata_t *) sock_core->specific_data;
-	
-	fibril_mutex_lock(&socket->lock);
-	
-	if (socket->assoc == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-	
-	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)) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): wait for cv");
-		fibril_condvar_wait(&socket->recv_buffer_cv,
-		    &socket->recv_buffer_lock);
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Got data in sock recv_buffer");
-	
-	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:
-		rc = EOK;
-		break;
-/*	case TCP_ENOTEXIST:
-	case TCP_ECLOSING:
-		rc = ENOTCONN;
-		break;
-	case TCP_ERESET:
-		rc = ECONNABORTED;
-		break;*/
-	default:
-		assert(false);
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "**** udp_uc_receive -> %d", rc);
-	
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->recv_buffer_lock);
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	ipc_callid_t rcallid;
-	size_t addr_size = 0;
-	
-	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
-		/* Fill address */
-		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);
-			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);
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-	
-	if (length > data_len)
-		length = data_len;
-	
-	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))
-		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, addr_size);
-	async_answer_3(callid, EOK, IPC_GET_ARG1(answer),
-	    IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
-	
-	socket->recv_buffer_used = 0;
-	
-	fibril_condvar_broadcast(&socket->recv_buffer_cv);
-	fibril_mutex_unlock(&socket->recv_buffer_lock);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void udp_sock_close(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close()");
-	int socket_id = SOCKET_GET_SOCKET_ID(call);
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - find core");
-	socket_core_t *sock_core =
-	    socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - core not found");
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - spec data");
-	udp_sockdata_t *socket =
-	    (udp_sockdata_t *) sock_core->specific_data;
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - lock socket");
-	fibril_mutex_lock(&socket->lock);
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - lock socket buffer");
-	fibril_mutex_lock(&socket->recv_buffer_lock);
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - set socket->sock_core = NULL");
-	socket->sock_core = NULL;
-	fibril_mutex_unlock(&socket->recv_buffer_lock);
-
-	udp_uc_reset(socket->assoc);
-
-	int rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
-	    udp_free_sock_data);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - socket_destroy failed");
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - broadcast recv_buffer_cv");
-	fibril_condvar_broadcast(&socket->recv_buffer_cv);
-
-	fibril_mutex_unlock(&socket->lock);
-	async_answer_0(callid, EOK);
-}
-
-static void udp_sock_getsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_getsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_setsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_setsockopt)");
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - async_data_write_accept");
-	
-	void *data = NULL;
-	size_t data_len;
-	int rc = async_data_write_accept(&data, false, 0, 0, 0, &data_len);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, " - failed accepting data");
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	sysarg_t opt_level = SOL_SOCKET;
-	sysarg_t opt_name = SOCKET_GET_OPT_NAME(call);
-	
-	if (opt_level != SOL_SOCKET || opt_name != SO_IPLINK ||
-	    data_len != sizeof(service_id_t)) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, " - failed opt_level/name/len");
-		log_msg(LOG_DEFAULT, LVL_DEBUG, " - failed opt_level=%d, "
-		    "opt_name=%d, data_len=%zu", (int)opt_level, (int)opt_name,
-		    data_len);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_cores_find");
-	
-	socket_core_t *sock_core = socket_cores_find(&client->sockets,
-	    SOCKET_GET_SOCKET_ID(call));
-	if (sock_core == NULL) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, " - failed getting sock_core");
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	udp_sockdata_t *socket =
-	    (udp_sockdata_t *) sock_core->specific_data;
-	
-	service_id_t iplink = *(service_id_t *)data;
-	udp_uc_set_iplink(socket->assoc, iplink);
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, " - success");
-	async_answer_0(callid, EOK);
-}
-
-
-static int udp_sock_recv_fibril(void *arg)
-{
-	udp_sockdata_t *sock = (udp_sockdata_t *)arg;
-	udp_error_t urc;
-	xflags_t xflags;
-	size_t rcvd;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril()");
-
-	fibril_mutex_lock(&sock->recv_buffer_lock);
-
-	while (true) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "[] wait for rcv buffer empty()");
-		while ((sock->recv_buffer_used != 0) && (sock->sock_core != NULL)) {
-			fibril_condvar_wait(&sock->recv_buffer_cv,
-			    &sock->recv_buffer_lock);
-		}
-
-		fibril_mutex_unlock(&sock->recv_buffer_lock);
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "[] call udp_uc_receive()");
-		urc = udp_uc_receive(sock->assoc, sock->recv_buffer,
-		    UDP_FRAGMENT_SIZE, &rcvd, &xflags, &sock->recv_fsock);
-		fibril_mutex_lock(&sock->recv_buffer_lock);
-		sock->recv_error = urc;
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "[] udp_uc_receive -> %d", urc);
-
-		if (sock->sock_core != NULL)
-			udp_sock_notify_data(sock->sock_core);
-
-		if (urc != UDP_EOK) {
-			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;
-		}
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "[] got data - broadcast recv_buffer_cv");
-
-		sock->recv_buffer_used = rcvd;
-		fibril_condvar_broadcast(&sock->recv_buffer_cv);
-	}
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril() exited loop");
-	udp_uc_destroy(sock->assoc);
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril() terminated");
-
-	return 0;
-}
-
-static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	udp_client_t client;
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: begin");
-
-	client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	socket_cores_initialize(&client.sockets);
-
-	while (true) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: wait");
-		callid = async_get_call(&call);
-		if (!IPC_GET_IMETHOD(call))
-			break;
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: METHOD=%d",
-		    (int)IPC_GET_IMETHOD(call));
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case NET_SOCKET:
-			udp_sock_socket(&client, callid, call);
-			break;
-		case NET_SOCKET_BIND:
-			udp_sock_bind(&client, callid, call);
-			break;
-		case NET_SOCKET_LISTEN:
-			udp_sock_listen(&client, callid, call);
-			break;
-		case NET_SOCKET_CONNECT:
-			udp_sock_connect(&client, callid, call);
-			break;
-		case NET_SOCKET_ACCEPT:
-			udp_sock_accept(&client, callid, call);
-			break;
-		case NET_SOCKET_SEND:
-		case NET_SOCKET_SENDTO:
-			udp_sock_sendto(&client, callid, call);
-			break;
-		case NET_SOCKET_RECV:
-		case NET_SOCKET_RECVFROM:
-			udp_sock_recvfrom(&client, callid, call);
-			break;
-		case NET_SOCKET_CLOSE:
-			udp_sock_close(&client, callid, call);
-			break;
-		case NET_SOCKET_GETSOCKOPT:
-			udp_sock_getsockopt(&client, callid, call);
-			break;
-		case NET_SOCKET_SETSOCKOPT:
-			udp_sock_setsockopt(&client, callid, call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-
-	/* Clean up */
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: Clean up");
-	async_hangup(client.sess);
-	socket_cores_release(NULL, &client.sockets, &gsock, udp_free_sock_data);
-}
-
-/**
- * @}
- */
Index: pace/srv/net/udp/sock.h
===================================================================
--- uspace/srv/net/udp/sock.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,45 +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 udp
- * @{
- */
-/** @file Socket provider
- */
-
-#ifndef SOCK_H
-#define SOCK_H
-
-#include <async.h>
-
-extern int udp_sock_init(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/udp/ucall.c
===================================================================
--- uspace/srv/net/udp/ucall.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,162 +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 tcp
- * @{
- */
-
-/**
- * @file UDP user calls
- */
-
-#include <io/log.h>
-#include <macros.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);
-	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_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_set_foreign(%p, %p)", assoc, fsock);
-
-	udp_assoc_set_foreign(assoc, fsock);
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_set_local(%p, %p)", assoc, lsock);
-	
-	udp_assoc_set_local(assoc, lsock);
-	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, udp_sock_t *fsock, 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, fsock, &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, udp_sock_t *fsock)
-{
-	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, fsock);
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv -> %d", rc);
-	switch (rc) {
-	case EOK:
-		break;
-	case ECONNABORTED:
-		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: pace/srv/net/udp/ucall.h
===================================================================
--- uspace/srv/net/udp/ucall.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ 	(revision )
@@ -1,58 +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 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_foreign(udp_assoc_t *, udp_sock_t *);
-extern udp_error_t udp_uc_set_local(udp_assoc_t *, udp_sock_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 *, udp_sock_t *, void *, size_t,
-    xflags_t);
-extern udp_error_t udp_uc_receive(udp_assoc_t *, void *, size_t, size_t *,
-    xflags_t *, udp_sock_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 fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/udp.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -41,6 +41,7 @@
 #include <task.h>
 
+#include "assoc.h"
+#include "service.h"
 #include "udp_inet.h"
-#include "sock.h"
 
 #define NAME       "udp"
@@ -52,4 +53,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();
 	if (rc != EOK) {
@@ -58,7 +65,7 @@
 	}
 
-	rc = udp_sock_init();
+	rc = udp_service_init();
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing socket service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing UDP service.");
 		return ENOENT;
 	}
Index: uspace/srv/net/udp/udp_inet.c
===================================================================
--- uspace/srv/net/udp/udp_inet.c	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/udp_inet.c	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -64,4 +64,5 @@
 
 	pdu = udp_pdu_new();
+	pdu->iplink = dgram->iplink;
 	pdu->data = dgram->data;
 	pdu->data_size = dgram->size;
@@ -105,5 +106,5 @@
 {
 	udp_msg_t *dmsg;
-	udp_sockpair_t rident;
+	inet_ep2_t rident;
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_received_pdu()");
Index: uspace/srv/net/udp/udp_type.h
===================================================================
--- uspace/srv/net/udp/udp_type.h	(revision fc7bf198e20e68849d91546bbc5a2a24c943840e)
+++ uspace/srv/net/udp/udp_type.h	(revision cf3aee195010da61f58b4c6e8daa8d03620c0a4e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2015 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,8 +36,9 @@
 #define UDP_TYPE_H
 
+#include <async.h>
 #include <fibril.h>
 #include <fibril_synch.h>
+#include <inet/endpoint.h>
 #include <ipc/loc.h>
-#include <socket_core.h>
 #include <sys/types.h>
 #include <inet/addr.h>
@@ -49,5 +50,5 @@
 	/* Insufficient resources */
 	UDP_ENORES,
-	/* Foreign socket unspecified */
+	/* Remote endpoint unspecified */
 	UDP_EUNSPEC,
 	/* No route to destination */
@@ -60,19 +61,4 @@
 	XF_DUMMY = 0x1
 } xflags_t;
-
-enum udp_port {
-	UDP_PORT_ANY = 0
-};
-
-typedef struct {
-	inet_addr_t addr;
-	uint16_t port;
-} udp_sock_t;
-
-typedef struct {
-	service_id_t iplink;
-	udp_sock_t local;
-	udp_sock_t foreign;
-} udp_sockpair_t;
 
 /** Unencoded UDP message (datagram) */
@@ -99,7 +85,6 @@
 
 typedef struct {
-	async_sess_t *sess;
-	socket_cores_t sockets;
-} udp_client_t;
+	void (*recv_msg)(void *, inet_ep2_t *, udp_msg_t *);
+} udp_assoc_cb_t;
 
 /** UDP association
@@ -107,5 +92,5 @@
  * This is a rough equivalent of a TCP connection endpoint. It allows
  * sending and receiving UDP datagrams and it is uniquely identified
- * by a socket pair.
+ * by an endpoint pair.
  */
 typedef struct {
@@ -113,6 +98,6 @@
 	link_t link;
 
-	/** Association identification (local and foreign socket) */
-	udp_sockpair_t ident;
+	/** Association identification (endpoint pair) */
+	inet_ep2_t ident;
 
 	/** True if association was reset by user */
@@ -131,4 +116,7 @@
 	/** Receive queue CV. Broadcast when new datagram is inserted */
 	fibril_condvar_t rcv_queue_cv;
+
+	udp_assoc_cb_t *cb;
+	void *cb_arg;
 } udp_assoc_t;
 
@@ -136,33 +124,42 @@
 } udp_assoc_status_t;
 
-typedef struct udp_sockdata {
-	/** Lock */
-	fibril_mutex_t lock;
-	/** Socket core */
-	socket_core_t *sock_core;
+typedef struct {
+	/** Link to receive queue */
+	link_t link;
+	/** Endpoint pair */
+	inet_ep2_t epp;
+	/** Message */
+	udp_msg_t *msg;
+} udp_rcv_queue_entry_t;
+
+typedef struct udp_cassoc {
+	/** Association */
+	udp_assoc_t *assoc;
+	/** Association ID for the client */
+	sysarg_t id;
 	/** Client */
-	udp_client_t *client;
-	/** Connection */
-	udp_assoc_t *assoc;
-	/** User-configured IP link */
-	service_id_t iplink;
-	/** Receiving fibril */
-	fid_t recv_fibril;
-	uint8_t recv_buffer[UDP_FRAGMENT_SIZE];
-	size_t recv_buffer_used;
-	udp_sock_t recv_fsock;
-	fibril_mutex_t recv_buffer_lock;
-	fibril_condvar_t recv_buffer_cv;
-	udp_error_t recv_error;
-} udp_sockdata_t;
+	struct udp_client *client;
+	link_t lclient;
+} udp_cassoc_t;
 
 typedef struct {
 	/** Link to receive queue */
 	link_t link;
-	/** Socket pair */
-	udp_sockpair_t sp;
+	/** Endpoint pair */
+	inet_ep2_t epp;
 	/** Message */
 	udp_msg_t *msg;
-} udp_rcv_queue_entry_t;
+	/** Client association */
+	udp_cassoc_t *cassoc;
+} udp_crcv_queue_entry_t;
+
+typedef struct udp_client {
+	/** Client callback session */
+	async_sess_t *sess;
+	/** Client assocations */
+	list_t cassoc; /* of udp_cassoc_t */
+	/** Client receive queue */
+	list_t crcv_queue;
+} udp_client_t;
 
 #endif
