Index: abi/include/ipc/methods.h
===================================================================
--- abi/include/ipc/methods.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ abi/include/ipc/methods.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -72,5 +72,5 @@
 #define IPC_M_CONNECTION_CLONE  1
 
-/** Protocol for CONNECT - ME
+/** Protocol for establishing a cloned connection.
  *
  * Through this call, the recipient learns about the new cloned connection.
@@ -81,7 +81,7 @@
  *
  */
-#define IPC_M_CONNECT_ME  2
-
-/** Protocol for CONNECT - TO - ME
+#define IPC_M_CLONE_ESTABLISH  2
+
+/** Protocol for initializing callback connections.
  *
  * Calling process asks the callee to create a callback connection,
@@ -102,5 +102,5 @@
 #define IPC_M_CONNECT_TO_ME  3
 
-/** Protocol for CONNECT - ME - TO
+/** Protocol for initializing new foward connections.
  *
  * Calling process asks the callee to create for him a new connection.
@@ -183,5 +183,5 @@
  * - ARG1 - recipient's phone to the third party task
  */
-#define IPC_M_STATE_CHANGE_AUTHORIZE	9
+#define IPC_M_STATE_CHANGE_AUTHORIZE  9
 
 /** Debug the recipient.
@@ -190,5 +190,5 @@
  *
  */
-#define IPC_M_DEBUG 10
+#define IPC_M_DEBUG  10
 
 /** Last system IPC method */
Index: boot/Makefile
===================================================================
--- boot/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ boot/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -66,7 +66,4 @@
 		cp "$$file" "$(DIST_PATH)/app/" ; \
 	done
-	for file in $(NET_CFG) ; do \
-		cp "$$file" "$(DIST_PATH)/cfg/net/" ; \
-	done
 	for drv in $(RD_DRVS) ; do \
 		drv_dir="`dirname "$$drv"`" ; \
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ boot/Makefile.common	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -98,5 +98,5 @@
 	$(USPACE_PATH)/srv/bd/part/guid_part/g_part \
 	$(USPACE_PATH)/srv/bd/part/mbr_part/mbr_part \
-	$(USPACE_PATH)/srv/clip/clip \
+	$(USPACE_PATH)/srv/clipboard/clipboard \
 	$(USPACE_PATH)/srv/fs/tmpfs/tmpfs \
 	$(USPACE_PATH)/srv/fs/fat/fat \
@@ -106,13 +106,10 @@
 	$(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
 	$(USPACE_PATH)/srv/hid/remcons/remcons \
+	$(USPACE_PATH)/srv/net/ethip/ethip \
+	$(USPACE_PATH)/srv/net/inet/inet \
+	$(USPACE_PATH)/srv/net/loopip/loopip \
+	$(USPACE_PATH)/srv/net/tcp/tcp \
+	$(USPACE_PATH)/srv/net/udp/udp \
 	$(USPACE_PATH)/srv/taskmon/taskmon \
-	$(USPACE_PATH)/srv/net/nil/eth/eth \
-	$(USPACE_PATH)/srv/net/nil/nildummy/nildummy \
-	$(USPACE_PATH)/srv/net/il/arp/arp \
-	$(USPACE_PATH)/srv/net/il/ip/ip \
-	$(USPACE_PATH)/srv/net/tl/icmp/icmp \
-	$(USPACE_PATH)/srv/net/tl/udp/udp \
-	$(USPACE_PATH)/srv/net/tl/tcp/tcp \
-	$(USPACE_PATH)/srv/net/net/net \
 	$(USPACE_PATH)/srv/devman/devman
 
@@ -123,5 +120,4 @@
 	test/test2 \
 	test/test3 \
-	nic/lo \
 	nic/ne2k \
 	nic/e1k \
@@ -161,4 +157,5 @@
 	$(USPACE_PATH)/app/edit/edit \
 	$(USPACE_PATH)/app/ext2info/ext2info \
+	$(USPACE_PATH)/app/inetcfg/inetcfg \
 	$(USPACE_PATH)/app/kill/kill \
 	$(USPACE_PATH)/app/killall/killall \
@@ -204,12 +201,4 @@
 endif
 
-ifneq ($(CONFIG_BAREBONE),y)
-NET_CFG = \
-	$(USPACE_PATH)/srv/net/cfg/general \
-	$(USPACE_PATH)/srv/net/cfg/lo.nic \
-	$(USPACE_PATH)/srv/net/cfg/ne2k.nic \
-	$(USPACE_PATH)/srv/net/cfg/e1k.nic
-endif
-
 COMPONENTS = \
 	$(KERNEL_PATH)/kernel.bin \
Index: boot/arch/arm32/Makefile.inc
===================================================================
--- boot/arch/arm32/Makefile.inc	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ boot/arch/arm32/Makefile.inc	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -42,6 +42,6 @@
 
 RD_SRVS_ESSENTIAL += \
-	$(USPACE_PATH)/srv/hid/s3c24xx_ts/s3c24ts \
-	$(USPACE_PATH)/srv/hw/char/s3c24xx_uart/s3c24ser
+	$(USPACE_PATH)/srv/hid/s3c24xx_ts/s3c24xx_ts \
+	$(USPACE_PATH)/srv/hw/char/s3c24xx_uart/s3c24xx_uart
 
 RD_SRVS_NON_ESSENTIAL += \
Index: boot/generic/src/printf_core.c
===================================================================
--- boot/generic/src/printf_core.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ boot/generic/src/printf_core.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -210,5 +210,5 @@
 	/* Print leading spaces. */
 	size_t strw = str_length(str);
-	if (precision == 0)
+	if ((precision == 0) || (precision > strw))
 		precision = strw;
 	
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ kernel/generic/src/ipc/sysipc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -111,5 +111,5 @@
 	switch (imethod) {
 	case IPC_M_CONNECTION_CLONE:
-	case IPC_M_CONNECT_ME:
+	case IPC_M_CLONE_ESTABLISH:
 	case IPC_M_PHONE_HUNGUP:
 		/* This message is meant only for the original recipient. */
@@ -160,5 +160,5 @@
 	switch (IPC_GET_IMETHOD(call->data)) {
 	case IPC_M_CONNECTION_CLONE:
-	case IPC_M_CONNECT_ME:
+	case IPC_M_CLONE_ESTABLISH:
 	case IPC_M_CONNECT_TO_ME:
 	case IPC_M_CONNECT_ME_TO:
@@ -225,5 +225,5 @@
 			mutex_unlock(&phone->lock);
 		}
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME) {
+	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CLONE_ESTABLISH) {
 		phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
 		
@@ -459,5 +459,5 @@
 		break;
 	}
-	case IPC_M_CONNECT_ME:
+	case IPC_M_CLONE_ESTABLISH:
 		IPC_SET_ARG5(call->data, (sysarg_t) phone);
 		break;
Index: kernel/generic/src/printf/printf_core.c
===================================================================
--- kernel/generic/src/printf/printf_core.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ kernel/generic/src/printf/printf_core.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -284,5 +284,5 @@
 	/* Print leading spaces. */
 	size_t strw = str_length(str);
-	if (precision == 0)
+	if ((precision == 0) || (precision > strw))
 		precision = strw;
 	
@@ -332,5 +332,5 @@
 	/* Print leading spaces. */
 	size_t strw = wstr_length(str);
-	if (precision == 0)
+	if ((precision == 0) || (precision > strw))
 		precision = strw;
 	
Index: kernel/test/print/print1.c
===================================================================
--- kernel/test/print/print1.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ kernel/test/print/print1.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -41,5 +41,5 @@
 	
 	TPRINTF("Testing printf(\"%%8.10s\", \"text\"):\n");
-	TPRINTF("Expected output: \"text\"\n");
+	TPRINTF("Expected output: \"    text\"\n");
 	TPRINTF("Real output:     \"%8.10s\"\n\n", "text");
 	
@@ -48,4 +48,8 @@
 	TPRINTF("Real output:     \"%8.10s\"\n\n", "very long text");
 	
+	TPRINTF("Testing printf(\"%%-*.*s\", 7, 7, \"text\"):\n");
+	TPRINTF("Expected output: \"text   \"\n");
+	TPRINTF("Real output:     \"%-*.*s\"\n\n", 7, 7, "text");
+	
 	return NULL;
 }
Index: tools/imgutil.py
===================================================================
--- tools/imgutil.py	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ tools/imgutil.py	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -92,7 +92,10 @@
 		if name in exclude_names:
 			continue
+		
 		item = ItemToPack(path, name)
+		
 		if not (item.is_dir or item.is_file):
 			continue
+		
 		yield item
 
@@ -102,7 +105,9 @@
 	inf = open(item.path, 'rb')
 	rd = 0
+	
 	while (rd < item.size):
 		data = bytes(inf.read(chunk_size))
 		yield data
 		rd += len(data)
+	
 	inf.close()
Index: tools/mkfat.py
===================================================================
--- tools/mkfat.py	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ tools/mkfat.py	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -168,106 +168,125 @@
 """
 
-LFN_ENTRY = """little:
-	uint8_t pos
-	uint16_t name1[5]
-	uint8_t attr
-	uint8_t type
-	uint8_t csum
-	uint16_t name2[6]
-	uint16_t fc
-	uint16_t name3[2]
-"""
-
-# Global variable to hold the file names in 8.3 format. Needed to 
-# keep track of "number" when creating a short fname from a LFN.
-name83_list = []
-
-def name83(fname):
-	"Create a 8.3 name for the given fname"
-
-	# FIXME: filter illegal characters
-	parts = fname.split('.')
-	
-	name = ''
-	ext = ''
-	lfn = False
-
-	if len(fname) > 11 :
+LFN_DIR_ENTRY = """little:
+	uint8_t seq                /* sequence number */
+	char name1[10]             /* first part of the name */
+	uint8_t attr               /* attributes */
+	uint8_t rec_type           /* LFN record type */
+	uint8_t checksum           /* LFN checksum */
+	char name2[12]             /* second part of the name */
+	uint16_t cluster           /* cluster */
+	char name3[4]              /* third part of the name */
+"""
+
+lchars = set(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+              'U', 'V', 'W', 'X', 'Y', 'Z',
+              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+              '!', '#', '$', '%', '&', '\'', '(', ')', '-', '@',
+              '^', '_', '`', '{', '}', '~', '.'])
+
+def fat_lchars(name):
+	"Filter FAT legal characters"
+	
+	filtered_name = ''
+	filtered = False
+	
+	for char in name.encode('ascii', 'replace').upper():
+		if char in lchars:
+			filtered_name += char
+		else:
+			filtered_name += b'_'
+			filtered = True
+	
+	return (filtered_name, filtered)
+
+def fat_name83(name, name83_list):
+	"Create a 8.3 name for the given name"
+	
+	ascii_name, lfn = fat_lchars(name)
+	ascii_parts = ascii_name.split('.')
+	
+	short_name = ''
+	short_ext = ''
+	
+	if len(ascii_name) > 11:
 		lfn = True
-
-	if len(parts) > 0:
-		name = parts[0]
-		if len(name) > 8 :
+	
+	if len(ascii_parts) > 0:
+		short_name = ascii_parts[0]
+		if len(short_name) > 8:
 			lfn = True
-
-	if len(parts) > 1 :
-		ext = parts[-1]
-		if len(ext) > 3 :
+	
+	if len(ascii_parts) > 1:
+		short_ext = ascii_parts[-1]
+		if len(short_ext) > 3:
 			lfn = True
-
-	if len(parts) > 2 :
+	
+	if len(ascii_parts) > 2:
 		lfn = True
-
-	if (lfn == False) :
-		return (name.ljust(8)[0:8], ext.ljust(3)[0:3], False)
-
+	
+	if lfn == False:
+		name83_list.append(short_name + '.' + short_ext)
+		return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], False)
+	
 	# For filenames with multiple extensions, we treat the last one
 	# as the actual extension. The rest of the filename is stripped
 	# of dots and concatenated to form the short name
-	for _name in parts[1:-1]:
-		name = name + _name		
-
-	global name83_list
-	for number in range(1, 10000) :
-		number_str = '~' + str(number)
-
-		if len(name) + len(number_str) > 8 :
-			name = name[0:8 - len(number_str)]
-
-		name = name + number_str;
-
-		if (name + ext) not in name83_list :
+	for part in ascii_parts[1:-1]:
+		short_name += part
+	
+	for number in range(1, 999999):
+		number_str = ('~' + str(number)).upper()
+		
+		if len(short_name) + len(number_str) > 8:
+			short_name = short_name[0:8 - len(number_str)]
+		
+		short_name += number_str;
+		
+		if not (short_name + '.' + short_ext) in name83_list:
 			break
-			
-	name83_list.append(name + ext)	
-
-	return (name.ljust(8)[0:8], ext.ljust(3)[0:3], True)
-
-def get_utf16(name, l) :
-	"Create a int array out of a string which we can store in uint16_t arrays"
-
-	bs = [0xFFFF for i in range(l)]
-
-	for i in range(len(name)) :
-		bs[i] = ord(name[i])
-	
-	if (len(name) < l) :
-		bs[len(name)] = 0;
-	
-	return bs
-
-def create_lfn_entry((name, index)) :
-	entry = xstruct.create(LFN_ENTRY)
-
-	entry.name1 = get_utf16(name[0:5], 5)
-	entry.name2 = get_utf16(name[5:11], 6)
-	entry.name3 = get_utf16(name[11:13], 2)
-	entry.pos = index
-
-	entry.attr = 0xF
-	entry.fc = 0
-	entry.type = 0
-
-	return entry
-
-def create_dirent(name, directory, cluster, size):
+	
+	name83_list.append(short_name + '.' + short_ext)
+	return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], True)
+
+def create_lfn_dirent(name, seq, checksum):
+	"Create LFN directory entry"
+	
+	entry = xstruct.create(LFN_DIR_ENTRY)
+	name_rest = name[26:]
+	
+	if len(name_rest) > 0:
+		entry.seq = seq
+	else:
+		entry.seq = seq | 0x40
+	
+	entry.name1 = name[0:10]
+	entry.name2 = name[10:22]
+	entry.name3 = name[22:26]
+	
+	entry.attr = 0x0F
+	entry.rec_type = 0
+	entry.checksum = checksum
+	entry.cluster = 0
+	
+	return (entry, name_rest)
+
+def lfn_checksum(name):
+	"Calculate LFN checksum"
+	
+	checksum = 0
+	for i in range(0, 11):
+		checksum = (((checksum & 1) << 7) + (checksum >> 1) + ord(name[i])) & 0xFF
+	
+	return checksum
+
+def create_dirent(name, name83_list, directory, cluster, size):
+	short_name, short_ext, lfn = fat_name83(name, name83_list)
 	
 	dir_entry = xstruct.create(DIR_ENTRY)
 	
-	dir_entry.name, dir_entry.ext, lfn = name83(name)
-
-	dir_entry.name = dir_entry.name.upper().encode('ascii')
-	dir_entry.ext = dir_entry.ext.upper().encode('ascii')
-
+	dir_entry.name = short_name
+	dir_entry.ext = short_ext
+	
 	if (directory):
 		dir_entry.attr = 0x30
@@ -289,26 +308,19 @@
 		dir_entry.size = size
 	
-
 	if not lfn:
 		return [dir_entry]
-
-	n = len(name) / 13 + 1
-	names = [(name[i * 13: (i + 1) * 13 + 1], i + 1) for i in range(n)]
-
-	entries = sorted(map (create_lfn_entry, names), reverse = True, key = lambda e : e.pos)
-	entries[0].pos |= 0x40
-
-	fname11 = dir_entry.name + dir_entry.ext
-
-	csum = 0
-	for i in range(0, 11) :
-		csum = ((csum & 1) << 7) + (csum  >> 1) + ord(fname11[i])
-		csum = csum & 0xFF
-	
-	for e in entries :
-		e.csum = csum;
-	
-	entries.append(dir_entry)
-
+	
+	long_name = name.encode('utf_16_le')
+	entries = [dir_entry]
+	
+	seq = 1
+	checksum = lfn_checksum(dir_entry.name + dir_entry.ext)
+	
+	while len(long_name) > 0:
+		long_entry, long_name = create_lfn_dirent(long_name, seq, checksum)
+		entries.append(long_entry)
+		seq += 1
+	
+	entries.reverse()
 	return entries
 
@@ -355,9 +367,10 @@
 	
 	directory = []
-	
-	if (not head):
+	name83_list = []
+	
+	if not head:
 		# Directory cluster preallocation
 		empty_cluster = fat.index(0)
-		fat[empty_cluster] = 0xffff
+		fat[empty_cluster] = 0xFFFF
 		
 		directory.append(create_dot_dirent(empty_cluster))
@@ -366,13 +379,13 @@
 		empty_cluster = 0
 	
-	for item in listdir_items(root):		
+	for item in listdir_items(root):
 		if item.is_file:
 			rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters)
-			directory.extend(create_dirent(item.name, False, rv[0], rv[1]))
+			directory.extend(create_dirent(item.name, name83_list, False, rv[0], rv[1]))
 		elif item.is_dir:
 			rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
-			directory.extend(create_dirent(item.name, True, rv[0], rv[1]))
-	
-	if (head):
+			directory.extend(create_dirent(item.name, name83_list, True, rv[0], rv[1]))
+	
+	if head:
 		outf.seek(root_start)
 		for dir_entry in directory:
@@ -431,5 +444,5 @@
 	extra_bytes = int(sys.argv[1])
 	
-	path = os.path.abspath(sys.argv[2])
+	path = os.path.abspath(sys.argv[2].decode())
 	if (not os.path.isdir(path)):
 		print("<PATH> must be a directory")
@@ -529,5 +542,5 @@
 	
 	outf.close()
-	
+
 if __name__ == '__main__':
 	main()
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -42,4 +42,5 @@
 	app/getterm \
 	app/init \
+	app/inetcfg \
 	app/kill \
 	app/killall \
@@ -71,8 +72,13 @@
 	app/mkbd \
 	app/date \
-	srv/clip \
+	srv/clipboard \
 	srv/loc \
 	srv/devman \
 	srv/loader \
+	srv/net/ethip \
+	srv/net/inet \
+	srv/net/loopip \
+	srv/net/tcp \
+	srv/net/udp \
 	srv/ns \
 	srv/taskmon \
@@ -97,12 +103,4 @@
 	srv/hid/remcons \
 	srv/hw/char/s3c24xx_uart \
-	srv/net/il/arp \
-	srv/net/il/ip \
-	srv/net/tl/icmp \
-	srv/net/tl/udp \
-	srv/net/tl/tcp \
-	srv/net/nil/eth \
-	srv/net/nil/nildummy \
-	srv/net/net \
 	drv/infrastructure/root \
 	drv/infrastructure/rootvirt \
@@ -123,5 +121,4 @@
 	drv/bus/usb/usbmid \
 	drv/bus/usb/vhc \
-	drv/nic/lo \
 	drv/nic/ne2k \
 	drv/nic/e1k \
Index: uspace/app/inetcfg/Makefile
===================================================================
--- uspace/app/inetcfg/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/app/inetcfg/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+BINARY = inetcfg
+
+SOURCES = \
+	inetcfg.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/inetcfg/inetcfg.c
===================================================================
--- uspace/app/inetcfg/inetcfg.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/app/inetcfg/inetcfg.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,515 @@
+/*
+ * 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 inetcfg
+ * @{
+ */
+/** @file Internet configuration utility.
+ *
+ * Controls the internet service (@c inet).
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <inet/inetcfg.h>
+#include <loc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <str_error.h>
+#include <sys/types.h>
+
+#define NAME "inetcfg"
+
+static void print_syntax(void)
+{
+	printf("syntax:\n");
+	printf("\t" NAME " create <addr>/<width> <link-name> <addr-name>\n");
+	printf("\t" NAME " delete <link-name> <addr-name>\n");
+	printf("\t" NAME " add-sr <dest-addr>/<width> <router-addr> <route-name>\n");
+	printf("\t" NAME " del-sr <route-name>\n");
+}
+
+static int naddr_parse(const char *text, inet_naddr_t *naddr)
+{
+	unsigned long a[4], bits;
+	char *cp = (char *)text;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		a[i] = strtoul(cp, &cp, 10);
+		if (*cp != '.')
+			return EINVAL;
+		++cp;
+	}
+
+	a[3] = strtoul(cp, &cp, 10);
+	if (*cp != '/')
+		return EINVAL;
+	++cp;
+
+	bits = strtoul(cp, &cp, 10);
+	if (*cp != '\0')
+		return EINVAL;
+
+	naddr->ipv4 = 0;
+	for (i = 0; i < 4; i++) {
+		if (a[i] > 255)
+			return EINVAL;
+		naddr->ipv4 = (naddr->ipv4 << 8) | a[i];
+	}
+
+	if (bits > 31)
+		return EINVAL;
+
+	naddr->bits = bits;
+	return EOK;
+}
+
+static int addr_parse(const char *text, inet_addr_t *addr)
+{
+	unsigned long a[4];
+	char *cp = (char *)text;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		a[i] = strtoul(cp, &cp, 10);
+		if (*cp != '.')
+			return EINVAL;
+		++cp;
+	}
+
+	a[3] = strtoul(cp, &cp, 10);
+	if (*cp != '\0')
+		return EINVAL;
+
+	addr->ipv4 = 0;
+	for (i = 0; i < 4; i++) {
+		if (a[i] > 255)
+			return EINVAL;
+		addr->ipv4 = (addr->ipv4 << 8) | a[i];
+	}
+
+	return EOK;
+}
+
+static int naddr_format(inet_naddr_t *naddr, char **bufp)
+{
+	int rc;
+
+	rc = asprintf(bufp, "%d.%d.%d.%d/%d", naddr->ipv4 >> 24,
+	    (naddr->ipv4 >> 16) & 0xff, (naddr->ipv4 >> 8) & 0xff,
+	    naddr->ipv4 & 0xff, naddr->bits);
+
+	if (rc < 0)
+		return ENOMEM;
+
+	return EOK;
+}
+
+static int addr_format(inet_addr_t *addr, char **bufp)
+{
+	int rc;
+
+	rc = asprintf(bufp, "%d.%d.%d.%d", addr->ipv4 >> 24,
+	    (addr->ipv4 >> 16) & 0xff, (addr->ipv4 >> 8) & 0xff,
+	    addr->ipv4 & 0xff);
+
+	if (rc < 0)
+		return ENOMEM;
+
+	return EOK;
+}
+
+static int addr_create_static(int argc, char *argv[])
+{
+	char *aobj_name;
+	char *addr_spec;
+	char *link_name;
+
+	inet_naddr_t naddr;
+	sysarg_t link_id;
+	sysarg_t addr_id;
+	int rc;
+
+	if (argc < 3) {
+		printf(NAME ": Missing arguments.\n");
+		print_syntax();
+		return EINVAL;
+	}
+
+	if (argc > 3) {
+		printf(NAME ": Too many arguments.\n");
+		print_syntax();
+		return EINVAL;
+	}
+
+	addr_spec = argv[0];
+	link_name = argv[1];
+	aobj_name = argv[2];
+
+	rc = loc_service_get_id(link_name, &link_id, 0);
+	if (rc != EOK) {
+		printf(NAME ": Service '%s' not found (%d).\n", link_name, rc);
+		return ENOENT;
+	}
+
+	rc = naddr_parse(addr_spec, &naddr);
+	if (rc != EOK) {
+		printf(NAME ": Invalid network address format '%s'.\n",
+		    addr_spec);
+		return EINVAL;
+	}
+
+	rc = inetcfg_addr_create_static(aobj_name, &naddr, link_id, &addr_id);
+	if (rc != EOK) {
+		printf(NAME ": Failed creating static address '%s' (%d)\n",
+		    aobj_name, rc);
+		return EIO;
+	}
+
+	return EOK;
+}
+
+static int addr_delete(int argc, char *argv[])
+{
+	char *aobj_name;
+	char *link_name;
+	sysarg_t link_id;
+	sysarg_t addr_id;
+	int rc;
+
+	if (argc < 2) {
+		printf(NAME ": Missing arguments.\n");
+		print_syntax();
+		return EINVAL;
+	}
+
+	if (argc > 2) {
+		printf(NAME ": Too many arguments.\n");
+		print_syntax();
+		return EINVAL;
+	}
+
+	link_name = argv[0];
+	aobj_name = argv[1];
+
+	rc = loc_service_get_id(link_name, &link_id, 0);
+	if (rc != EOK) {
+		printf(NAME ": Service '%s' not found (%d).\n", link_name, rc);
+		return ENOENT;
+	}
+
+	rc = inetcfg_addr_get_id(aobj_name, link_id, &addr_id);
+	if (rc != EOK) {
+		printf(NAME ": Address '%s' not found (%d).\n", aobj_name, rc);
+		return ENOENT;
+	}
+
+	rc = inetcfg_addr_delete(addr_id);
+	if (rc != EOK) {
+		printf(NAME ": Failed deleting address '%s' (%d)\n", aobj_name,
+		    rc);
+		return EIO;
+	}
+
+	return EOK;
+}
+
+static int sroute_create(int argc, char *argv[])
+{
+	char *dest_str;
+	char *router_str;
+	char *route_name;
+
+	inet_naddr_t dest;
+	inet_addr_t router;
+	sysarg_t sroute_id;
+	int rc;
+
+	if (argc < 3) {
+		printf(NAME ": Missing arguments.\n");
+		print_syntax();
+		return EINVAL;
+	}
+
+	if (argc > 3) {
+		printf(NAME ": Too many arguments.\n");
+		print_syntax();
+		return EINVAL;
+	}
+
+	dest_str   = argv[0];
+	router_str = argv[1];
+	route_name = argv[2];
+
+	rc = naddr_parse(dest_str, &dest);
+	if (rc != EOK) {
+		printf(NAME ": Invalid network address format '%s'.\n",
+		    dest_str);
+		return EINVAL;
+	}
+
+	rc = addr_parse(router_str, &router);
+	if (rc != EOK) {
+		printf(NAME ": Invalid address format '%s'.\n", router_str);
+		return EINVAL;
+	}
+
+	rc = inetcfg_sroute_create(route_name, &dest, &router, &sroute_id);
+	if (rc != EOK) {
+		printf(NAME ": Failed creating static route '%s' (%d)\n",
+		    route_name, rc);
+		return EIO;
+	}
+
+	return EOK;
+}
+
+static int sroute_delete(int argc, char *argv[])
+{
+	char *route_name;
+	sysarg_t sroute_id;
+	int rc;
+
+	if (argc < 1) {
+		printf(NAME ": Missing arguments.\n");
+		print_syntax();
+		return EINVAL;
+	}
+
+	if (argc > 1) {
+		printf(NAME ": Too many arguments.\n");
+		print_syntax();
+		return EINVAL;
+	}
+
+	route_name = argv[0];
+
+	rc = inetcfg_sroute_get_id(route_name, &sroute_id);
+	if (rc != EOK) {
+		printf(NAME ": Static route '%s' not found (%d).\n",
+		    route_name, rc);
+		return ENOENT;
+	}
+
+	rc = inetcfg_sroute_delete(sroute_id);
+	if (rc != EOK) {
+		printf(NAME ": Failed deleting static route '%s' (%d)\n",
+		    route_name, rc);
+		return EIO;
+	}
+
+	return EOK;
+}
+
+static int addr_list(void)
+{
+	sysarg_t *addr_list;
+	inet_addr_info_t ainfo;
+	inet_link_info_t linfo;
+
+	size_t count;
+	size_t i;
+	int rc;
+	char *astr;
+
+	rc = inetcfg_get_addr_list(&addr_list, &count);
+	if (rc != EOK) {
+		printf(NAME ": Failed getting address list.\n");
+		return rc;
+	}
+
+	printf("Configured addresses:\n");
+
+	ainfo.name = linfo.name = astr = NULL;
+
+	for (i = 0; i < count; i++) {
+		rc = inetcfg_addr_get(addr_list[i], &ainfo);
+		if (rc != EOK) {
+			printf("Failed getting properties of address %zu.\n",
+			    (size_t)addr_list[i]);
+			ainfo.name = NULL;
+			continue;
+		}
+
+		rc = inetcfg_link_get(ainfo.ilink, &linfo);
+		if (rc != EOK) {
+			printf("Failed getting properties of link %zu.\n",
+			    (size_t)ainfo.ilink);
+			linfo.name = NULL;
+			continue;
+		}
+
+		rc = naddr_format(&ainfo.naddr, &astr);
+		if (rc != EOK) {
+			printf("Memory allocation failed.\n");
+			astr = NULL;
+			goto out;
+		}
+
+		printf("    %s %s %s %zu\n", astr, linfo.name,
+		    ainfo.name, linfo.def_mtu);
+
+		free(ainfo.name);
+		free(linfo.name);
+		free(astr);
+
+		ainfo.name = linfo.name = astr = NULL;
+	}
+
+	if (count == 0)
+		printf("    None\n");
+out:
+	if (ainfo.name != NULL)
+		free(ainfo.name);
+	if (linfo.name != NULL)
+		free(linfo.name);
+	if (astr != NULL)
+		free(astr);
+
+	free(addr_list);
+
+	return EOK;
+}
+
+static int sroute_list(void)
+{
+	sysarg_t *sroute_list;
+	inet_sroute_info_t srinfo;
+
+	size_t count;
+	size_t i;
+	int rc;
+	char *dest_str;
+	char *router_str;
+
+	rc = inetcfg_get_sroute_list(&sroute_list, &count);
+	if (rc != EOK) {
+		printf(NAME ": Failed getting address list.\n");
+		return rc;
+	}
+
+	printf("Static routes:\n");
+
+	srinfo.name = dest_str = router_str = NULL;
+
+	for (i = 0; i < count; i++) {
+		rc = inetcfg_sroute_get(sroute_list[i], &srinfo);
+		if (rc != EOK) {
+			printf("Failed getting properties of static route %zu.\n",
+			    (size_t)sroute_list[i]);
+			srinfo.name = NULL;
+			continue;
+		}
+
+		rc = naddr_format(&srinfo.dest, &dest_str);
+		if (rc != EOK) {
+			printf("Memory allocation failed.\n");
+			dest_str = NULL;
+			goto out;
+		}
+
+		rc = addr_format(&srinfo.router, &router_str);
+		if (rc != EOK) {
+			printf("Memory allocation failed.\n");
+			router_str = NULL;
+			goto out;
+		}
+
+		printf("    %s %s %s\n", dest_str, router_str, srinfo.name);
+
+		free(srinfo.name);
+		free(dest_str);
+		free(router_str);
+
+		router_str = srinfo.name = dest_str = NULL;
+	}
+
+	if (count == 0)
+		printf("    None\n");
+out:
+	if (srinfo.name != NULL)
+		free(srinfo.name);
+	if (dest_str != NULL)
+		free(dest_str);
+	if (router_str != NULL)
+		free(router_str);
+
+	free(sroute_list);
+
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+
+	rc = inetcfg_init();
+	if (rc != EOK) {
+		printf(NAME ": Failed connecting to internet service (%d).\n",
+		    rc);
+		return 1;
+	}
+
+	if (argc < 2) {
+		rc = addr_list();
+		if (rc != EOK)
+			return 1;
+		rc = sroute_list();
+		if (rc != EOK)
+			return 1;
+		return 0;
+	}
+
+	if (str_cmp(argv[1], "create") == 0) {
+		rc = addr_create_static(argc - 2, argv + 2);
+		if (rc != EOK)
+			return 1;
+	} else if (str_cmp(argv[1], "delete") == 0) {
+		rc = addr_delete(argc - 2, argv + 2);
+		if (rc != EOK)
+			return 1;
+	} else if (str_cmp(argv[1], "add-sr") == 0) {
+		rc = sroute_create(argc - 2, argv + 2);
+		if (rc != EOK)
+			return 1;
+	} else if (str_cmp(argv[1], "del-sr") == 0) {
+		rc = sroute_delete(argc - 2, argv + 2);
+		if (rc != EOK)
+			return 1;
+	} else {
+		printf(NAME ": Unknown command '%s'.\n", argv[1]);
+		print_syntax();
+		return 1;
+	}
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/init/init.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -302,8 +302,12 @@
 	spawn("/srv/obio");
 	srv_start("/srv/cuda_adb");
-	srv_start("/srv/s3c24ser");
-	srv_start("/srv/s3c24ts");
-	
-	spawn("/srv/net");
+	srv_start("/srv/s3c24xx_uart");
+	srv_start("/srv/s3c24xx_ts");
+	
+	spawn("/srv/loopip");
+	spawn("/srv/ethip");
+	spawn("/srv/inet");
+	spawn("/srv/tcp");
+	spawn("/srv/udp");
 	
 	spawn("/srv/fb");
@@ -311,5 +315,5 @@
 	console("hid/input", "hid/fb0");
 	
-	spawn("/srv/clip");
+	spawn("/srv/clipboard");
 	spawn("/srv/remcons");
 	
Index: uspace/app/netecho/netecho.c
===================================================================
--- uspace/app/netecho/netecho.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/netecho/netecho.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -373,4 +373,5 @@
 		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);
Index: uspace/app/netecho/print_error.c
===================================================================
--- uspace/app/netecho/print_error.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/netecho/print_error.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -40,69 +40,7 @@
 #include <errno.h>
 
-#include <net/icmp_codes.h>
-
-/** Prints the specific ICMP error description.
- *
- * @param[in] output The description output stream. May be NULL.
- * @param[in] error_code The ICMP error code.
- * @param[in] prefix The error description prefix. May be NULL.
- * @param[in] suffix The error description suffix. May be NULL.
- */
-void icmp_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 ICMP_DEST_UNREACH:
-		fprintf(output, "ICMP Destination Unreachable (%d) error", error_code);
-		break;
-	case ICMP_SOURCE_QUENCH:
-		fprintf(output, "ICMP Source Quench (%d) error", error_code);
-		break;
-	case ICMP_REDIRECT:
-		fprintf(output, "ICMP Redirect (%d) error", error_code);
-		break;
-	case ICMP_ALTERNATE_ADDR:
-		fprintf(output, "ICMP Alternate Host Address (%d) error", error_code);
-		break;
-	case ICMP_ROUTER_ADV:
-		fprintf(output, "ICMP Router Advertisement (%d) error", error_code);
-		break;
-	case ICMP_ROUTER_SOL:
-		fprintf(output, "ICMP Router Solicitation (%d) error", error_code);
-		break;
-	case ICMP_TIME_EXCEEDED:
-		fprintf(output, "ICMP Time Exceeded (%d) error", error_code);
-		break;
-	case ICMP_PARAMETERPROB:
-		fprintf(output, "ICMP Paramenter Problem (%d) error", error_code);
-		break;
-	case ICMP_CONVERSION_ERROR:
-		fprintf(output, "ICMP Datagram Conversion Error (%d) error", error_code);
-		break;
-	case ICMP_REDIRECT_MOBILE:
-		fprintf(output, "ICMP Mobile Host Redirect (%d) error", error_code);
-		break;
-	case ICMP_SKIP:
-		fprintf(output, "ICMP SKIP (%d) error", error_code);
-		break;
-	case ICMP_PHOTURIS:
-		fprintf(output, "ICMP Photuris (%d) error", error_code);
-		break;
-	default:
-		fprintf(output, "Other (%d) error", error_code);
-	}
-
-	if (suffix)
-		fprintf(output, "%s", suffix);
-}
-
 /** Prints the error description.
  *
- * Supports ICMP and socket error codes.
+ * Supports socket error codes.
  *
  * @param[in] output The description output stream. May be NULL.
@@ -113,7 +51,5 @@
 void print_error(FILE *output, int error_code, const char *prefix, const char *suffix)
 {
-	if (IS_ICMP_ERROR(error_code))
-		icmp_print_error(output, error_code, prefix, suffix);
-	else if(IS_SOCKET_ERROR(error_code))
+	if(IS_SOCKET_ERROR(error_code))
 		socket_print_error(output, error_code, prefix, suffix);
 }
Index: uspace/app/ping/Makefile
===================================================================
--- uspace/app/ping/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/ping/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -1,5 +1,4 @@
 #
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
+# Copyright (c) 2012 Jiri Svoboda
 # All rights reserved.
 #
@@ -29,11 +28,8 @@
 
 USPACE_PREFIX = ../..
-LIBS = 
-EXTRA_CFLAGS = 
 BINARY = ping
 
 SOURCES = \
-	ping.c \
-	print_error.c
+	ping.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/ping/ping.c
===================================================================
--- uspace/app/ping/ping.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/ping/ping.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2012 Jiri Svoboda
  * All rights reserved.
  *
@@ -30,366 +30,259 @@
  * @{
  */
-
-/** @file
- * Packet Internet Network Grouper.
+/** @file ICMP echo utility.
  */
 
 #include <async.h>
+#include <bool.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <inet/inetping.h>
+#include <io/console.h>
 #include <stdio.h>
-#include <str.h>
-#include <task.h>
-#include <time.h>
-#include <ipc/services.h>
-#include <str_error.h>
-#include <errno.h>
-#include <arg_parse.h>
-
-#include <net/icmp_api.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/socket_parse.h>
-#include <net/ip_codes.h>
-
-#include "print_error.h"
-
-#define NAME  "ping"
-
-#define CL_OK           0
-#define CL_USAGE        -1
-#define CL_MISSING      -2
-#define CL_INVALID      -3
-#define CL_UNSUPPORTED  -4
-#define CL_ERROR        -5
-
-/** Ping configuration
- *
- */
-typedef struct {
-	bool verbose;               /**< Verbose printouts. */
-	size_t size;                /**< Outgoing packet size. */
-	unsigned int count;         /**< Number of packets to send. */
-	suseconds_t timeout;        /**< Reply wait timeout. */
-	int af;                     /**< Address family. */
-	ip_tos_t tos;               /**< Type of service. */
-	ip_ttl_t ttl;               /**< Time-to-live. */
-	bool fragments;             /**< Fragmentation. */
-	
-	char *dest_addr;            /**< Destination address. */
-	struct sockaddr_in dest;    /**< IPv4 destionation. */
-	struct sockaddr_in6 dest6;  /**< IPv6 destionation. */
-	
-	struct sockaddr *dest_raw;  /**< Raw destination address. */
-	socklen_t dest_len;         /**< Raw destination address length. */
-	
-	/** Converted address string. */
-	char dest_str[INET6_ADDRSTRLEN];
-} ping_config_t;
-
-
-static void usage(void)
-{
-	printf(
-	    "Usage: ping [-c count] [-s size] [-W timeout] [-f family] [-t ttl]\n" \
-	    "            [-Q tos] [--dont_fragment] destination\n" \
-	    "\n" \
-	    "Options:\n" \
-	    "\t-c count\n" \
-	    "\t--count=count\n" \
-	    "\t\tNumber of outgoing packets (default: 4)\n" \
-	    "\n" \
-	    "\t-s size\n" \
-	    "\t--size=bytes\n" \
-	    "\t\tOutgoing packet size (default: 56 bytes)\n" \
-	    "\n" \
-	    "\t-W timeout\n" \
-	    "\t--timeout=ms\n" \
-	    "\t\tReply wait timeout (default: 3000 ms)\n" \
-	    "\n" \
-	    "\t-f family\n" \
-	    "\t--family=family\n" \
-	    "\t\tDestination address family, AF_INET or AF_INET6 (default: AF_INET)\n" \
-	    "\n" \
-	    "\t-t ttl\n" \
-	    "\t--ttl=ttl\n" \
-	    "\t\tOutgoing packet time-to-live (default: 0)\n" \
-	    "\n" \
-	    "\t-Q tos\n" \
-	    "\t--tos=tos\n" \
-	    "\t\tOutgoing packet type of service (default: 0)\n" \
-	    "\n" \
-	    "\t--dont_fragment\n" \
-	    "\t\tDisable packet fragmentation (default: enabled)\n" \
-	    "\n" \
-	    "\t-v\n" \
-	    "\t--verbose\n" \
-	    "\t\tVerbose operation\n" \
-	    "\n" \
-	    "\t-h\n" \
-	    "\t--help\n" \
-	    "\t\tPrint this usage information\n"
-	);
-}
-
-static int args_parse(int argc, char *argv[], ping_config_t *config)
-{
-	if (argc < 2)
-		return CL_USAGE;
-	
+#include <stdlib.h>
+#include <sys/types.h>
+
+#define NAME "ping"
+
+/** Delay between subsequent ping requests in microseconds */
+#define PING_DELAY (1000 * 1000)
+
+/** Ping request timeout in microseconds */
+#define PING_TIMEOUT (1000 * 1000)
+
+static int ping_ev_recv(inetping_sdu_t *);
+
+static bool done = false;
+static FIBRIL_CONDVAR_INITIALIZE(done_cv);
+static FIBRIL_MUTEX_INITIALIZE(done_lock);
+
+static inetping_ev_ops_t ev_ops = {
+	.recv = ping_ev_recv
+};
+
+static inet_addr_t src_addr;
+static inet_addr_t dest_addr;
+
+static bool ping_repeat = false;
+
+static void print_syntax(void)
+{
+	printf("syntax: " NAME " [-r] <addr>\n");
+}
+
+static int addr_parse(const char *text, inet_addr_t *addr)
+{
+	unsigned long a[4];
+	char *cp = (char *)text;
 	int i;
-	int ret;
-	
-	for (i = 1; i < argc; i++) {
-		
-		/* Not an option */
-		if (argv[i][0] != '-')
+
+	for (i = 0; i < 3; i++) {
+		a[i] = strtoul(cp, &cp, 10);
+		if (*cp != '.')
+			return EINVAL;
+		++cp;
+	}
+
+	a[3] = strtoul(cp, &cp, 10);
+	if (*cp != '\0')
+		return EINVAL;
+
+	addr->ipv4 = 0;
+	for (i = 0; i < 4; i++) {
+		if (a[i] > 255)
+			return EINVAL;
+		addr->ipv4 = (addr->ipv4 << 8) | a[i];
+	}
+
+	return EOK;
+}
+
+static int addr_format(inet_addr_t *addr, char **bufp)
+{
+	int rc;
+
+	rc = asprintf(bufp, "%d.%d.%d.%d", addr->ipv4 >> 24,
+	    (addr->ipv4 >> 16) & 0xff, (addr->ipv4 >> 8) & 0xff,
+	    addr->ipv4 & 0xff);
+
+	if (rc < 0)
+		return ENOMEM;
+
+	return EOK;
+}
+
+static void ping_signal_done(void)
+{
+	fibril_mutex_lock(&done_lock);
+	done = true;
+	fibril_mutex_unlock(&done_lock);
+	fibril_condvar_broadcast(&done_cv);
+}
+
+static int ping_ev_recv(inetping_sdu_t *sdu)
+{
+	char *asrc, *adest;
+	int rc;
+
+	rc = addr_format(&sdu->src, &asrc);
+	if (rc != EOK)
+		return ENOMEM;
+
+	rc = addr_format(&sdu->dest, &adest);
+	if (rc != EOK) {
+		free(asrc);
+		return ENOMEM;
+	}
+	printf("Received ICMP echo reply: from %s to %s, seq. no %u, "
+	    "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size);
+
+	if (!ping_repeat) {
+		ping_signal_done();
+	}
+
+	free(asrc);
+	free(adest);
+	return EOK;
+}
+
+static int ping_send(uint16_t seq_no)
+{
+	inetping_sdu_t sdu;
+	int rc;
+
+	sdu.src = src_addr;
+	sdu.dest = dest_addr;
+	sdu.seq_no = seq_no;
+	sdu.data = (void *) "foo";
+	sdu.size = 3;
+
+	rc = inetping_send(&sdu);
+	if (rc != EOK) {
+		printf(NAME ": Failed sending echo request (%d).\n", rc);
+		return rc;
+	}
+
+	return EOK;
+}
+
+static int transmit_fibril(void *arg)
+{
+	uint16_t seq_no = 0;
+
+	while (true) {
+		fibril_mutex_lock(&done_lock);
+		if (done) {
+			fibril_mutex_unlock(&done_lock);
+			return 0;
+		}
+		fibril_mutex_unlock(&done_lock);
+
+		(void) ping_send(++seq_no);
+		async_usleep(PING_DELAY);
+	}
+
+	return 0;
+}
+
+static int input_fibril(void *arg)
+{
+	console_ctrl_t *con;
+	kbd_event_t ev;
+
+	con = console_init(stdin, stdout);
+	printf("[Press Ctrl-Q to quit]\n");
+
+	while (true) {
+		if (!console_get_kbd_event(con, &ev))
 			break;
-		
-		/* Options terminator */
-		if (str_cmp(argv[i], "--") == 0) {
-			i++;
-			break;
-		}
-		
-		int off;
-		
-		/* Usage */
-		if ((off = arg_parse_short_long(argv[i], "-h", "--help")) != -1)
-			return CL_USAGE;
-		
-		/* Verbose */
-		if ((off = arg_parse_short_long(argv[i], "-v", "--verbose")) != -1) {
-			config->verbose = true;
-			continue;
-		}
-		
-		/* Don't fragment */
-		if (str_cmp(argv[i], "--dont_fragment") == 0) {
-			config->fragments = false;
-			continue;
-		}
-		
-		/* Count */
-		if ((off = arg_parse_short_long(argv[i], "-c", "--count=")) != -1) {
-			int tmp;
-			ret = arg_parse_int(argc, argv, &i, &tmp, off);
-			
-			if ((ret != EOK) || (tmp < 0))
-				return i;
-			
-			config->count = (unsigned int) tmp;
-			continue;
-		}
-		
-		/* Outgoing packet size */
-		if ((off = arg_parse_short_long(argv[i], "-s", "--size=")) != -1) {
-			int tmp;
-			ret = arg_parse_int(argc, argv, &i, &tmp, off);
-			
-			if ((ret != EOK) || (tmp < 0))
-				return i;
-			
-			config->size = (size_t) tmp;
-			continue;
-		}
-		
-		/* Reply wait timeout */
-		if ((off = arg_parse_short_long(argv[i], "-W", "--timeout=")) != -1) {
-			int tmp;
-			ret = arg_parse_int(argc, argv, &i, &tmp, off);
-			
-			if ((ret != EOK) || (tmp < 0))
-				return i;
-			
-			config->timeout = (suseconds_t) tmp;
-			continue;
-		}
-		
-		/* Address family */
-		if ((off = arg_parse_short_long(argv[i], "-f", "--family=")) != -1) {
-			ret = arg_parse_name_int(argc, argv, &i, &config->af, off,
-			    socket_parse_address_family);
-			
-			if (ret != EOK)
-				return i;
-			
-			continue;
-		}
-		
-		/* Type of service */
-		if ((off = arg_parse_short_long(argv[i], "-Q", "--tos=")) != -1) {
-			int tmp;
-			ret = arg_parse_name_int(argc, argv, &i, &tmp, off,
-			    socket_parse_address_family);
-			
-			if ((ret != EOK) || (tmp < 0))
-				return i;
-			
-			config->tos = (ip_tos_t) tmp;
-			continue;
-		}
-		
-		/* Time to live */
-		if ((off = arg_parse_short_long(argv[i], "-t", "--ttl=")) != -1) {
-			int tmp;
-			ret = arg_parse_name_int(argc, argv, &i, &tmp, off,
-			    socket_parse_address_family);
-			
-			if ((ret != EOK) || (tmp < 0))
-				return i;
-			
-			config->ttl = (ip_ttl_t) tmp;
-			continue;
-		}
-	}
-	
-	if (i >= argc)
-		return CL_MISSING;
-	
-	config->dest_addr = argv[i];
-	
-	/* Resolve destionation address */
-	switch (config->af) {
-	case AF_INET:
-		config->dest_raw = (struct sockaddr *) &config->dest;
-		config->dest_len = sizeof(config->dest);
-		config->dest.sin_family = config->af;
-		ret = inet_pton(config->af, config->dest_addr,
-		    (uint8_t *) &config->dest.sin_addr.s_addr);
-		break;
-	case AF_INET6:
-		config->dest_raw = (struct sockaddr *) &config->dest6;
-		config->dest_len = sizeof(config->dest6);
-		config->dest6.sin6_family = config->af;
-		ret = inet_pton(config->af, config->dest_addr,
-		    (uint8_t *) &config->dest6.sin6_addr.s6_addr);
-		break;
-	default:
-		return CL_UNSUPPORTED;
-	}
-	
-	if (ret != EOK)
-		return CL_INVALID;
-	
-	/* Convert destination address back to string */
-	switch (config->af) {
-	case AF_INET:
-		ret = inet_ntop(config->af,
-		    (uint8_t *) &config->dest.sin_addr.s_addr,
-		    config->dest_str, sizeof(config->dest_str));
-		break;
-	case AF_INET6:
-		ret = inet_ntop(config->af,
-		    (uint8_t *) &config->dest6.sin6_addr.s6_addr,
-		    config->dest_str, sizeof(config->dest_str));
-		break;
-	default:
-		return CL_UNSUPPORTED;
-	}
-	
-	if (ret != EOK)
-		return CL_ERROR;
-	
-	return CL_OK;
+
+		if (ev.type == KEY_PRESS && (ev.mods & (KM_ALT | KM_SHIFT)) ==
+		    0 && (ev.mods & KM_CTRL) != 0) {
+			/* Ctrl+key */
+			if (ev.key == KC_Q) {
+				ping_signal_done();
+				return 0;
+			}
+		}
+	}
+
+	return 0;
 }
 
 int main(int argc, char *argv[])
 {
-	ping_config_t config;
-	
-	/* Default configuration */
-	config.verbose = false;
-	config.size = 56;
-	config.count = 4;
-	config.timeout = 3000;
-	config.af = AF_INET;
-	config.tos = 0;
-	config.ttl = 0;
-	config.fragments = true;
-	
-	int ret = args_parse(argc, argv, &config);
-	
-	switch (ret) {
-	case CL_OK:
-		break;
-	case CL_USAGE:
-		usage();
-		return 0;
-	case CL_MISSING:
-		fprintf(stderr, "%s: Destination address missing\n", NAME);
-		return 1;
-	case CL_INVALID:
-		fprintf(stderr, "%s: Destination address '%s' invalid or malformed\n",
-		    NAME, config.dest_addr);
-		return 2;
-	case CL_UNSUPPORTED:
-		fprintf(stderr, "%s: Destination address '%s' unsupported\n",
-		    NAME, config.dest_addr);
-		return 3;
-	case CL_ERROR:
-		fprintf(stderr, "%s: Destination address '%s' error\n",
-		    NAME, config.dest_addr);
-		return 4;
-	default:
-		fprintf(stderr, "%s: Unknown or invalid option '%s'\n", NAME,
-		    argv[ret]);
-		return 5;
-	}
-	
-	printf("PING %s (%s) %zu(%zu) bytes of data\n", config.dest_addr,
-	    config.dest_str, config.size, config.size);
-	
-	async_sess_t *sess = icmp_connect_module();
-	if (!sess) {
-		fprintf(stderr, "%s: Unable to connect to ICMP service (%s)\n", NAME,
-		    str_error(errno));
-		return errno;
-	}
-	
-	unsigned int seq;
-	for (seq = 0; seq < config.count; seq++) {
-		struct timeval t0;
-		ret = gettimeofday(&t0, NULL);
-		if (ret != EOK) {
-			fprintf(stderr, "%s: gettimeofday failed (%s)\n", NAME,
-			    str_error(ret));
-			
-			async_hangup(sess);
-			return ret;
-		}
-		
-		/* Ping! */
-		int result = icmp_echo_msg(sess, config.size, config.timeout,
-		    config.ttl, config.tos, !config.fragments, config.dest_raw,
-		    config.dest_len);
-		
-		struct timeval t1;
-		ret = gettimeofday(&t1, NULL);
-		if (ret != EOK) {
-			fprintf(stderr, "%s: gettimeofday failed (%s)\n", NAME,
-			    str_error(ret));
-			
-			async_hangup(sess);
-			return ret;
-		}
-		
-		suseconds_t elapsed = tv_sub(&t1, &t0);
-		
-		switch (result) {
-		case ICMP_ECHO:
-			printf("%zu bytes from ? (?): icmp_seq=%u ttl=? time=%ld.%04ld\n",
-				config.size, seq, elapsed / 1000, elapsed % 1000);
-			break;
-		case ETIMEOUT:
-			printf("%zu bytes from ? (?): icmp_seq=%u Timed out\n",
-				config.size, seq);
-			break;
-		default:
-			print_error(stdout, result, NULL, "\n");
-		}
-	}
-	
-	async_hangup(sess);
-	
+	int rc;
+	int argi;
+
+	rc = inetping_init(&ev_ops);
+	if (rc != EOK) {
+		printf(NAME ": Failed connecting to internet ping service "
+		    "(%d).\n", rc);
+		return 1;
+	}
+
+	argi = 1;
+	if (argi < argc && str_cmp(argv[argi], "-r") == 0) {
+		ping_repeat = true;
+		++argi;
+	} else {
+		ping_repeat = false;
+	}
+
+	if (argc - argi != 1) {
+		print_syntax();
+		return 1;
+	}
+
+	/* Parse destination address */
+	rc = addr_parse(argv[argi], &dest_addr);
+	if (rc != EOK) {
+		printf(NAME ": Invalid address format.\n");
+		print_syntax();
+		return 1;
+	}
+
+	/* Determine source address */
+	rc = inetping_get_srcaddr(&dest_addr, &src_addr);
+	if (rc != EOK) {
+		printf(NAME ": Failed determining source address.\n");
+		return 1;
+	}
+
+	fid_t fid;
+
+	if (ping_repeat) {
+		fid = fibril_create(transmit_fibril, NULL);
+		if (fid == 0) {
+			printf(NAME ": Failed creating transmit fibril.\n");
+			return 1;
+		}
+
+		fibril_add_ready(fid);
+
+		fid = fibril_create(input_fibril, NULL);
+		if (fid == 0) {
+			printf(NAME ": Failed creating input fibril.\n");
+			return 1;
+		}
+
+		fibril_add_ready(fid);
+	} else {
+		ping_send(1);
+	}
+
+	fibril_mutex_lock(&done_lock);
+	rc = EOK;
+	while (!done && rc != ETIMEOUT) {
+		rc = fibril_condvar_wait_timeout(&done_cv, &done_lock,
+			ping_repeat ? 0 : PING_TIMEOUT);
+	}
+	fibril_mutex_unlock(&done_lock);
+
+	if (rc == ETIMEOUT) {
+		printf(NAME ": Echo request timed out.\n");
+		return 1;
+	}
+
 	return 0;
 }
Index: pace/app/ping/print_error.c
===================================================================
--- uspace/app/ping/print_error.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../netecho/print_error.c
Index: pace/app/ping/print_error.h
===================================================================
--- uspace/app/ping/print_error.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../netecho/print_error.h
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/tester/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -50,4 +50,5 @@
 	vfs/vfs1.c \
 	ipc/ping_pong.c \
+	ipc/starve.c \
 	loop/loop1.c \
 	mm/common.c \
Index: uspace/app/tester/ipc/starve.c
===================================================================
--- uspace/app/tester/ipc/starve.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/app/tester/ipc/starve.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <io/console.h>
+#include <async.h>
+#include "../tester.h"
+
+#define DURATION_SECS      30
+
+const char *test_starve_ipc(void)
+{
+	const char *err = NULL;
+	console_ctrl_t *console = console_init(stdin, stdout);
+	if (console == NULL) {
+		return "Failed to init connection with console.";
+	}
+	
+	struct timeval start;
+	if (gettimeofday(&start, NULL) != 0) {
+		err = "Failed getting the time";
+		goto leave;
+	}
+	
+	TPRINTF("Intensive computation shall be imagined (for %ds)...\n", DURATION_SECS);
+	TPRINTF("Press a key to terminate prematurely...\n");
+	while (true) {
+		struct timeval now;
+		if (gettimeofday(&now, NULL) != 0) {
+			err = "Failed getting the time";
+			goto leave;
+		}
+		
+		if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L)
+			break;
+		
+		kbd_event_t ev;
+		suseconds_t timeout = 0;
+		bool has_event = console_get_kbd_event_timeout(console, &ev, &timeout);
+		if (has_event && (ev.type == KEY_PRESS)) {
+			TPRINTF("Key %d pressed, terminating.\n", ev.key);
+			break;
+		}
+	}
+
+	// FIXME - unless a key was pressed, the answer leaked as no one
+	// will wait for it.
+	// We cannot use async_forget() directly, though. Something like
+	// console_forget_pending_kbd_event() shall come here.
+
+	TPRINTF("Terminating...\n");
+
+leave:
+	console_done(console);
+
+	return err;
+}
Index: uspace/app/tester/ipc/starve.def
===================================================================
--- uspace/app/tester/ipc/starve.def	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/app/tester/ipc/starve.def	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,6 @@
+{
+	"starve",
+	"Demonstrate starving IPC",
+	&test_starve_ipc,
+	true
+},
Index: uspace/app/tester/print/print1.c
===================================================================
--- uspace/app/tester/print/print1.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/tester/print/print1.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -42,5 +42,5 @@
 	
 	TPRINTF("Testing printf(\"%%8.10s\", \"text\"):\n");
-	TPRINTF("Expected output: \"text\"\n");
+	TPRINTF("Expected output: \"    text\"\n");
 	TPRINTF("Real output:     \"%8.10s\"\n\n", "text");
 	
@@ -49,4 +49,8 @@
 	TPRINTF("Real output:     \"%8.10s\"\n\n", "very long text");
 	
+	TPRINTF("Testing printf(\"%%-*.*s\", 7, 7, \"text\"):\n");
+	TPRINTF("Expected output: \"text   \"\n");
+	TPRINTF("Real output:     \"%-*.*s\"\n\n", 7, 7, "text");
+	
 	return NULL;
 }
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/tester/tester.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -60,4 +60,5 @@
 #include "vfs/vfs1.def"
 #include "ipc/ping_pong.def"
+#include "ipc/starve.def"
 #include "loop/loop1.def"
 #include "mm/malloc1.def"
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/tester/tester.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -93,4 +93,5 @@
 extern const char *test_vfs1(void);
 extern const char *test_ping_pong(void);
+extern const char *test_starve_ipc(void);
 extern const char *test_loop1(void);
 extern const char *test_malloc1(void);
Index: uspace/app/top/screen.c
===================================================================
--- uspace/app/top/screen.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/top/screen.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -37,4 +37,5 @@
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <io/console.h>
 #include <io/style.h>
@@ -43,4 +44,5 @@
 #include <stats.h>
 #include <inttypes.h>
+#include <macros.h>
 #include "screen.h"
 #include "top.h"
@@ -48,10 +50,13 @@
 #define USEC_COUNT  1000000
 
-static sysarg_t warn_col = 0;
-static sysarg_t warn_row = 0;
 static suseconds_t timeleft = 0;
 
 console_ctrl_t *console;
 
+static sysarg_t warning_col = 0;
+static sysarg_t warning_row = 0;
+static suseconds_t warning_timeleft = 0;
+static char *warning_text = NULL;
+
 static void screen_style_normal(void)
 {
@@ -64,4 +69,10 @@
 	console_flush(console);
 	console_set_style(console, STYLE_INVERTED);
+}
+
+static void screen_style_emphasis(void)
+{
+	console_flush(console);
+	console_set_style(console, STYLE_EMPHASIS);
 }
 
@@ -126,4 +137,7 @@
 void screen_done(void)
 {
+	free(warning_text);
+	warning_text = NULL;
+
 	screen_restart(true);
 	
@@ -277,18 +291,51 @@
 }
 
-static inline void print_tasks_head(void)
+static inline void print_help_head(void)
 {
 	screen_style_inverted();
-	printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]"
-	    " [%%user] [%%kern] [name");
+	printf("Help");
 	screen_newline();
 	screen_style_normal();
 }
 
-static inline void print_tasks(data_t *data)
-{
-	sysarg_t cols;
-	sysarg_t rows;
-	screen_get_size(&cols, &rows);
+static inline void print_help(void)
+{
+	sysarg_t cols;
+	sysarg_t rows;
+	screen_get_size(&cols, &rows);
+	
+	screen_newline();
+	
+	printf("Operation modes:");
+	screen_newline();
+	
+	printf(" t .. tasks statistics");
+	screen_newline();
+	
+	printf(" i .. IPC statistics");
+	screen_newline();
+	
+	printf(" e .. exceptions statistics");
+	screen_newline();
+	
+	printf("      a .. toggle display of all/hot exceptions");
+	screen_newline();
+
+	printf(" h .. toggle this help screen");
+	screen_newline();
+
+	screen_newline();
+
+	printf("Other keys:");
+	screen_newline();
+	
+	printf(" s .. choose column to sort by");
+	screen_newline();
+	
+	printf(" r .. toggle reversed sorting");
+	screen_newline();
+	
+	printf(" q .. quit");
+	screen_newline();
 	
 	sysarg_t col;
@@ -296,32 +343,4 @@
 	screen_get_pos(&col, &row);
 	
-	size_t i;
-	for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {
-		stats_task_t *task = data->tasks + data->tasks_map[i];
-		perc_task_t *perc = data->tasks_perc + data->tasks_map[i];
-		
-		uint64_t resmem;
-		const char *resmem_suffix;
-		bin_order_suffix(task->resmem, &resmem, &resmem_suffix, true);
-		
-		uint64_t virtmem;
-		const char *virtmem_suffix;
-		bin_order_suffix(task->virtmem, &virtmem, &virtmem_suffix, true);
-		
-		printf("%-8" PRIu64 " %7zu %7" PRIu64 "%s ",
-		    task->task_id, task->threads, resmem, resmem_suffix);
-		print_percent(perc->resmem, 2);
-		printf(" %6" PRIu64 "%s ", virtmem, virtmem_suffix);
-		print_percent(perc->virtmem, 2);
-		puts(" ");
-		print_percent(perc->ucycles, 2);
-		puts(" ");
-		print_percent(perc->kcycles, 2);
-		puts(" ");
-		print_string(task->name);
-		
-		screen_newline();
-	}
-	
 	while (row < rows) {
 		screen_newline();
@@ -330,14 +349,30 @@
 }
 
-static inline void print_ipc_head(void)
-{
+static inline void print_table_head(const table_t *table)
+{
+	sysarg_t cols;
+	sysarg_t rows;
+	screen_get_size(&cols, &rows);
+
 	screen_style_inverted();
-	printf("[taskid] [cls snt] [cls rcv] [ans snt]"
-	    " [ans rcv] [irq rcv] [forward] [name");
+	for (size_t i = 0; i < table->num_columns; i++) {
+		const char *name = table->columns[i].name;
+		int width = table->columns[i].width;
+		if (i != 0) {
+			puts(" ");
+		}
+		if (width == 0) {
+			sysarg_t col;
+			sysarg_t row;
+			screen_get_pos(&col, &row);
+			width = cols - col - 1;
+		}
+		printf("[%-*.*s]", width - 2, width - 2, name);
+	}
 	screen_newline();
 	screen_style_normal();
 }
 
-static inline void print_ipc(data_t *data)
+static inline void print_table(const table_t *table)
 {
 	sysarg_t cols;
@@ -350,44 +385,58 @@
 	
 	size_t i;
-	for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {
-		uint64_t call_sent;
-		uint64_t call_received;
-		uint64_t answer_sent;
-		uint64_t answer_received;
-		uint64_t irq_notif_received;
-		uint64_t forwarded;
-		
-		char call_sent_suffix;
-		char call_received_suffix;
-		char answer_sent_suffix;
-		char answer_received_suffix;
-		char irq_notif_received_suffix;
-		char forwarded_suffix;
-		
-		order_suffix(data->tasks[i].ipc_info.call_sent, &call_sent,
-		    &call_sent_suffix);
-		order_suffix(data->tasks[i].ipc_info.call_received,
-		    &call_received, &call_received_suffix);
-		order_suffix(data->tasks[i].ipc_info.answer_sent,
-		    &answer_sent, &answer_sent_suffix);
-		order_suffix(data->tasks[i].ipc_info.answer_received,
-		    &answer_received, &answer_received_suffix);
-		order_suffix(data->tasks[i].ipc_info.irq_notif_received,
-		    &irq_notif_received, &irq_notif_received_suffix);
-		order_suffix(data->tasks[i].ipc_info.forwarded, &forwarded,
-		    &forwarded_suffix);
-		
-		printf("%-8" PRIu64 " %8" PRIu64 "%c %8" PRIu64 "%c"
-		     " %8" PRIu64 "%c %8" PRIu64 "%c %8" PRIu64 "%c"
-		     " %8" PRIu64 "%c ", data->tasks[i].task_id,
-		     call_sent, call_sent_suffix,
-		     call_received, call_received_suffix,
-		     answer_sent, answer_sent_suffix,
-		     answer_received, answer_received_suffix,
-		     irq_notif_received, irq_notif_received_suffix,
-		     forwarded, forwarded_suffix);
-		print_string(data->tasks[i].name);
-		
-		screen_newline();
+	for (i = 0; (i < table->num_fields) && (row < rows); i++) {
+		size_t column_index = i % table->num_columns;
+		int width = table->columns[column_index].width;
+		field_t *field = &table->fields[i];
+
+		if (column_index != 0) {
+			puts(" ");
+		}
+
+		if (width == 0) {
+			screen_get_pos(&col, &row);
+			width = cols - col - 1;
+		}
+
+		switch (field->type) {
+		case FIELD_EMPTY:
+			printf("%*s", width, "");
+			break;
+		case FIELD_UINT:
+			printf("%*" PRIu64, width, field->uint);
+			break;
+		case FIELD_UINT_SUFFIX_BIN: {
+			uint64_t val = field->uint;
+			const char *suffix;
+			width -= 3;
+			bin_order_suffix(val, &val, &suffix, true);
+			printf("%*" PRIu64 "%s", width, val, suffix);
+			break;
+		}
+		case FIELD_UINT_SUFFIX_DEC: {
+			uint64_t val = field->uint;
+			char suffix;
+			width -= 1;
+			order_suffix(val, &val, &suffix);
+			printf("%*" PRIu64 "%c", width, val, suffix);
+			break;
+		}
+		case FIELD_PERCENT:
+			width -= 5; /* nnn.% */
+			if (width > 2) {
+				printf("%*s", width - 2, "");
+				width = 2;
+			}
+			print_percent(field->fixed, width);
+			break;
+		case FIELD_STRING:
+			printf("%-*.*s", width, width, field->string);
+			break;
+		}
+
+		if (column_index == table->num_columns - 1) {
+			screen_newline();
+			row++;
+		}
 	}
 	
@@ -398,13 +447,5 @@
 }
 
-static inline void print_excs_head(void)
-{
-	screen_style_inverted();
-	printf("[exc   ] [count   ] [%%count] [cycles  ] [%%cycles] [description");
-	screen_newline();
-	screen_style_normal();
-}
-
-static inline void print_excs(data_t *data)
+static inline void print_sort(table_t *table)
 {
 	sysarg_t cols;
@@ -415,28 +456,8 @@
 	sysarg_t row;
 	screen_get_pos(&col, &row);
-	
-	size_t i;
-	for (i = 0; (i < data->exceptions_count) && (row < rows); i++) {
-		/* Filter-out cold exceptions if not instructed otherwise */
-		if ((!excs_all) && (!data->exceptions[i].hot))
-			continue;
-		
-		uint64_t count;
-		uint64_t cycles;
-		
-		char count_suffix;
-		char cycles_suffix;
-		
-		order_suffix(data->exceptions[i].count, &count, &count_suffix);
-		order_suffix(data->exceptions[i].cycles, &cycles, &cycles_suffix);
-		
-		printf("%-8u %9" PRIu64 "%c  ",
-		     data->exceptions[i].id, count, count_suffix);
-		print_percent(data->exceptions_perc[i].count, 2);
-		printf(" %9" PRIu64 "%c   ", cycles, cycles_suffix);
-		print_percent(data->exceptions_perc[i].cycles, 2);
-		puts(" ");
-		print_string(data->exceptions[i].desc);
-		
+
+	size_t num = min(table->num_columns, rows - row);
+	for (size_t i = 0; i < num; i++) {
+		printf("%c - %s", table->columns[i].key, table->columns[i].name);
 		screen_newline();
 		row++;
@@ -449,37 +470,16 @@
 }
 
-static void print_help(void)
-{
-	sysarg_t cols;
-	sysarg_t rows;
-	screen_get_size(&cols, &rows);
-	
-	sysarg_t col;
-	sysarg_t row;
-	screen_get_pos(&col, &row);
-	
-	screen_newline();
-	
-	printf("Operation modes:");
-	screen_newline();
-	
-	printf(" t .. tasks statistics");
-	screen_newline();
-	
-	printf(" i .. IPC statistics");
-	screen_newline();
-	
-	printf(" e .. exceptions statistics");
-	screen_newline();
-	
-	printf("      a .. toggle display of all/hot exceptions");
-	screen_newline();
-	
-	row += 6;
-	
-	while (row < rows) {
-		screen_newline();
-		row++;
-	}
+static inline void print_warning(void)
+{
+	screen_get_pos(&warning_col, &warning_row);
+	if (warning_timeleft > 0) {
+		screen_style_emphasis();
+		print_string(warning_text);
+		screen_style_normal();
+	} else {
+		free(warning_text);
+		warning_text = NULL;
+	}
+	screen_newline();
 }
 
@@ -492,24 +492,16 @@
 	print_cpu_info(data);
 	print_physmem_info(data);
-	
-	/* Empty row for warnings */
-	screen_get_pos(&warn_col, &warn_row);
-	screen_newline();
-	
-	switch (op_mode) {
-	case OP_TASKS:
-		print_tasks_head();
-		print_tasks(data);
+	print_warning();
+	
+	switch (screen_mode) {
+	case SCREEN_TABLE:
+		print_table_head(&data->table);
+		print_table(&data->table);
 		break;
-	case OP_IPC:
-		print_ipc_head();
-		print_ipc(data);
+	case SCREEN_SORT:
+		print_sort(&data->table);
 		break;
-	case OP_EXCS:
-		print_excs_head();
-		print_excs(data);
-		break;
-	case OP_HELP:
-		print_tasks_head();
+	case SCREEN_HELP:
+		print_help_head();
 		print_help();
 	}
@@ -518,14 +510,25 @@
 }
 
-void print_warning(const char *fmt, ...)
-{
-	screen_moveto(warn_col, warn_row);
-	
+void show_warning(const char *fmt, ...)
+{
+	sysarg_t cols;
+	sysarg_t rows;
+	screen_get_size(&cols, &rows);
+
+	size_t warning_text_size = 1 + cols * sizeof(*warning_text);
+	free(warning_text);
+	warning_text = malloc(warning_text_size);
+	if (!warning_text)
+		return;
+
 	va_list args;
 	va_start(args, fmt);
-	vprintf(fmt, args);
+	vsnprintf(warning_text, warning_text_size, fmt, args);
 	va_end(args);
 	
-	screen_newline();
+	warning_timeleft = 2 * USEC_COUNT;
+
+	screen_moveto(warning_col, warning_row);
+	print_warning();
 	console_flush(console);
 }
@@ -555,8 +558,10 @@
 		kbd_event_t event;
 		
+		warning_timeleft -= timeleft;
 		if (!console_get_kbd_event_timeout(console, &event, &timeleft)) {
 			timeleft = 0;
 			return -1;
 		}
+		warning_timeleft += timeleft;
 		
 		if (event.type == KEY_PRESS)
Index: uspace/app/top/screen.h
===================================================================
--- uspace/app/top/screen.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/top/screen.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -43,5 +43,5 @@
 extern void screen_done(void);
 extern void print_data(data_t *);
-extern void print_warning(const char *, ...);
+extern void show_warning(const char *, ...);
 
 extern int tgetchar(unsigned int);
Index: uspace/app/top/top.c
===================================================================
--- uspace/app/top/top.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/top/top.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -55,7 +55,80 @@
 #define MINUTE  60
 
-op_mode_t op_mode = OP_TASKS;
-sort_mode_t sort_mode = SORT_TASK_CYCLES;
-bool excs_all = false;
+typedef enum {
+	OP_TASKS,
+	OP_IPC,
+	OP_EXCS,
+} op_mode_t;
+
+static const column_t task_columns[] = {
+	{"taskid",   't',  8},
+	{"thrds",    'h',  7},
+	{"resident", 'r', 10},
+	{"%resi",    'R',  7},
+	{"virtual",  'v',  9},
+	{"%virt",    'V',  7},
+	{"%user",    'U',  7},
+	{"%kern",    'K',  7},
+	{"name",     'd',  0},
+};
+
+enum {
+	TASK_COL_ID = 0,
+	TASK_COL_NUM_THREADS,
+	TASK_COL_RESIDENT,
+	TASK_COL_PERCENT_RESIDENT,
+	TASK_COL_VIRTUAL,
+	TASK_COL_PERCENT_VIRTUAL,
+	TASK_COL_PERCENT_USER,
+	TASK_COL_PERCENT_KERNEL,
+	TASK_COL_NAME,
+	TASK_NUM_COLUMNS,
+};
+
+static const column_t ipc_columns[] = {
+	{"taskid",  't', 8},
+	{"cls snt", 'c', 9},
+	{"cls rcv", 'C', 9},
+	{"ans snt", 'a', 9},
+	{"ans rcv", 'A', 9},
+	{"forward", 'f', 9},
+	{"name",    'd', 0},
+};
+
+enum {
+	IPC_COL_TASKID = 0,
+	IPC_COL_CLS_SNT,
+	IPC_COL_CLS_RCV,
+	IPC_COL_ANS_SNT,
+	IPC_COL_ANS_RCV,
+	IPC_COL_FORWARD,
+	IPC_COL_NAME,
+	IPC_NUM_COLUMNS,
+};
+
+static const column_t exception_columns[] = {
+	{"exc",         'e',  8},
+	{"count",       'n', 10},
+	{"%count",      'N',  8},
+	{"cycles",      'c', 10},
+	{"%cycles",     'C',  9},
+	{"description", 'd',  0},
+};
+
+enum {
+	EXCEPTION_COL_ID = 0,
+	EXCEPTION_COL_COUNT,
+	EXCEPTION_COL_PERCENT_COUNT,
+	EXCEPTION_COL_CYCLES,
+	EXCEPTION_COL_PERCENT_CYCLES,
+	EXCEPTION_COL_DESCRIPTION,
+	EXCEPTION_NUM_COLUMNS,
+};
+
+screen_mode_t screen_mode = SCREEN_TABLE;
+static op_mode_t op_mode = OP_TASKS;
+static size_t sort_column = TASK_COL_PERCENT_USER;
+static int sort_reverse = -1;
+static bool excs_all = false;
 
 static const char *read_data(data_t *target)
@@ -67,5 +140,4 @@
 	target->tasks = NULL;
 	target->tasks_perc = NULL;
-	target->tasks_map = NULL;
 	target->threads = NULL;
 	target->exceptions = NULL;
@@ -76,4 +148,9 @@
 	target->ecycles_diff = NULL;
 	target->ecount_diff = NULL;
+	target->table.name = NULL;
+	target->table.num_columns = 0;
+	target->table.columns = NULL;
+	target->table.num_fields = 0;
+	target->table.fields = NULL;
 	
 	/* Get current time */
@@ -117,9 +194,4 @@
 	if (target->tasks_perc == NULL)
 		return "Not enough memory for task utilization";
-	
-	target->tasks_map =
-	    (size_t *) calloc(target->tasks_count, sizeof(size_t));
-	if (target->tasks_map == NULL)
-		return "Not enough memory for task map";
 	
 	/* Get threads */
@@ -289,29 +361,172 @@
 static int cmp_data(void *a, void *b, void *arg)
 {
-	size_t ia = *((size_t *) a);
-	size_t ib = *((size_t *) b);
-	data_t *data = (data_t *) arg;
-	
-	uint64_t acycles = data->ucycles_diff[ia] + data->kcycles_diff[ia];
-	uint64_t bcycles = data->ucycles_diff[ib] + data->kcycles_diff[ib];
-	
-	if (acycles > bcycles)
-		return -1;
-	
-	if (acycles < bcycles)
-		return 1;
-	
+	field_t *fa = (field_t *)a + sort_column;
+	field_t *fb = (field_t *)b + sort_column;
+	
+	if (fa->type > fb->type)
+		return 1 * sort_reverse;
+
+	if (fa->type < fb->type)
+		return -1 * sort_reverse;
+
+	switch (fa->type) {
+	case FIELD_EMPTY:
+		return 0;
+	case FIELD_UINT_SUFFIX_BIN: /* fallthrough */
+	case FIELD_UINT_SUFFIX_DEC: /* fallthrough */
+	case FIELD_UINT:
+		if (fa->uint > fb->uint)
+			return 1 * sort_reverse;
+		if (fa->uint < fb->uint)
+			return -1 * sort_reverse;
+		return 0;
+	case FIELD_PERCENT:
+		if (fa->fixed.upper * fb->fixed.lower
+		    > fb->fixed.upper * fa->fixed.lower)
+			return 1 * sort_reverse;
+		if (fa->fixed.upper * fb->fixed.lower
+		    < fb->fixed.upper * fa->fixed.lower)
+			return -1 * sort_reverse;
+		return 0;
+	case FIELD_STRING:
+		return str_cmp(fa->string, fb->string) * sort_reverse;
+	}
+
 	return 0;
 }
 
-static void sort_data(data_t *data)
-{
-	size_t i;
-	
-	for (i = 0; i < data->tasks_count; i++)
-		data->tasks_map[i] = i;
-	
-	qsort((void *) data->tasks_map, data->tasks_count,
-	    sizeof(size_t), cmp_data, (void *) data);
+static void sort_table(table_t *table)
+{
+	if (sort_column >= table->num_columns)
+		sort_column = 0;
+	/* stable sort is probably best, so we use gsort */
+	gsort((void *) table->fields, table->num_fields / table->num_columns,
+	    sizeof(field_t) * table->num_columns, cmp_data, NULL);
+}
+
+static const char *fill_task_table(data_t *data)
+{
+	data->table.name = "Tasks";
+	data->table.num_columns = TASK_NUM_COLUMNS;
+	data->table.columns = task_columns;
+	data->table.num_fields = data->tasks_count * TASK_NUM_COLUMNS;
+	data->table.fields = calloc(data->table.num_fields,
+	    sizeof(field_t));
+	if (data->table.fields == NULL)
+		return "Not enough memory for table fields";
+
+	field_t *field = data->table.fields;
+	for (size_t i = 0; i < data->tasks_count; i++) {
+		stats_task_t *task = &data->tasks[i];
+		perc_task_t *perc = &data->tasks_perc[i];
+		field[TASK_COL_ID].type = FIELD_UINT;
+		field[TASK_COL_ID].uint = task->task_id;
+		field[TASK_COL_NUM_THREADS].type = FIELD_UINT;
+		field[TASK_COL_NUM_THREADS].uint = task->threads;
+		field[TASK_COL_RESIDENT].type = FIELD_UINT_SUFFIX_BIN;
+		field[TASK_COL_RESIDENT].uint = task->resmem;
+		field[TASK_COL_PERCENT_RESIDENT].type = FIELD_PERCENT;
+		field[TASK_COL_PERCENT_RESIDENT].fixed = perc->resmem;
+		field[TASK_COL_VIRTUAL].type = FIELD_UINT_SUFFIX_BIN;
+		field[TASK_COL_VIRTUAL].uint = task->virtmem;
+		field[TASK_COL_PERCENT_VIRTUAL].type = FIELD_PERCENT;
+		field[TASK_COL_PERCENT_VIRTUAL].fixed = perc->virtmem;
+		field[TASK_COL_PERCENT_USER].type = FIELD_PERCENT;
+		field[TASK_COL_PERCENT_USER].fixed = perc->ucycles;
+		field[TASK_COL_PERCENT_KERNEL].type = FIELD_PERCENT;
+		field[TASK_COL_PERCENT_KERNEL].fixed = perc->kcycles;
+		field[TASK_COL_NAME].type = FIELD_STRING;
+		field[TASK_COL_NAME].string = task->name;
+		field += TASK_NUM_COLUMNS;
+	}
+
+	return NULL;
+}
+
+static const char *fill_ipc_table(data_t *data)
+{
+	data->table.name = "IPC";
+	data->table.num_columns = IPC_NUM_COLUMNS;
+	data->table.columns = ipc_columns;
+	data->table.num_fields = data->tasks_count * IPC_NUM_COLUMNS;
+	data->table.fields = calloc(data->table.num_fields,
+	    sizeof(field_t));
+	if (data->table.fields == NULL)
+		return "Not enough memory for table fields";
+
+	field_t *field = data->table.fields;
+	for (size_t i = 0; i < data->tasks_count; i++) {
+		field[IPC_COL_TASKID].type = FIELD_UINT;
+		field[IPC_COL_TASKID].uint = data->tasks[i].task_id;
+		field[IPC_COL_CLS_SNT].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_CLS_SNT].uint = data->tasks[i].ipc_info.call_sent;
+		field[IPC_COL_CLS_RCV].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_CLS_RCV].uint = data->tasks[i].ipc_info.call_received;
+		field[IPC_COL_ANS_SNT].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_ANS_SNT].uint = data->tasks[i].ipc_info.answer_sent;
+		field[IPC_COL_ANS_RCV].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_ANS_RCV].uint = data->tasks[i].ipc_info.answer_received;
+		field[IPC_COL_FORWARD].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_FORWARD].uint = data->tasks[i].ipc_info.forwarded;
+		field[IPC_COL_NAME].type = FIELD_STRING;
+		field[IPC_COL_NAME].string = data->tasks[i].name;
+		field += IPC_NUM_COLUMNS;
+	}
+
+	return NULL;
+}
+
+static const char *fill_exception_table(data_t *data)
+{
+	data->table.name = "Exceptions";
+	data->table.num_columns = EXCEPTION_NUM_COLUMNS;
+	data->table.columns = exception_columns;
+	data->table.num_fields = data->exceptions_count *
+	    EXCEPTION_NUM_COLUMNS;
+	data->table.fields = calloc(data->table.num_fields, sizeof(field_t));
+	if (data->table.fields == NULL)
+		return "Not enough memory for table fields";
+
+	field_t *field = data->table.fields;
+	for (size_t i = 0; i < data->exceptions_count; i++) {
+		if (!excs_all && !data->exceptions[i].hot)
+			continue;
+		field[EXCEPTION_COL_ID].type = FIELD_UINT;
+		field[EXCEPTION_COL_ID].uint = data->exceptions[i].id;
+		field[EXCEPTION_COL_COUNT].type = FIELD_UINT_SUFFIX_DEC;
+		field[EXCEPTION_COL_COUNT].uint = data->exceptions[i].count;
+		field[EXCEPTION_COL_PERCENT_COUNT].type = FIELD_PERCENT;
+		field[EXCEPTION_COL_PERCENT_COUNT].fixed = data->exceptions_perc[i].count;
+		field[EXCEPTION_COL_CYCLES].type = FIELD_UINT_SUFFIX_DEC;
+		field[EXCEPTION_COL_CYCLES].uint = data->exceptions[i].cycles;
+		field[EXCEPTION_COL_PERCENT_CYCLES].type = FIELD_PERCENT;
+		field[EXCEPTION_COL_PERCENT_CYCLES].fixed = data->exceptions_perc[i].cycles;
+		field[EXCEPTION_COL_DESCRIPTION].type = FIELD_STRING;
+		field[EXCEPTION_COL_DESCRIPTION].string = data->exceptions[i].desc;
+		field += EXCEPTION_NUM_COLUMNS;
+	}
+
+	/* in case any cold exceptions were ignored */
+	data->table.num_fields = field - data->table.fields;
+
+	return NULL;
+}
+
+static const char *fill_table(data_t *data)
+{
+	if (data->table.fields != NULL) {
+		free(data->table.fields);
+		data->table.fields = NULL;
+	}
+
+	switch (op_mode) {
+	case OP_TASKS:
+		return fill_task_table(data);
+	case OP_IPC:
+		return fill_ipc_table(data);
+	case OP_EXCS:
+		return fill_exception_table(data);
+	}
+	return NULL;
 }
 
@@ -356,4 +571,7 @@
 	if (target->ecount_diff != NULL)
 		free(target->ecount_diff);
+
+	if (target->table.fields != NULL)
+		free(target->table.fields);
 }
 
@@ -367,65 +585,94 @@
 	printf("Reading initial data...\n");
 	
-	if ((ret = read_data(&data_prev)) != NULL)
+	if ((ret = read_data(&data)) != NULL)
 		goto out;
 	
 	/* Compute some rubbish to have initialised values */
-	compute_percentages(&data_prev, &data_prev);
+	compute_percentages(&data, &data);
 	
 	/* And paint screen until death */
 	while (true) {
 		int c = tgetchar(UPDATE_INTERVAL);
-		if (c < 0) {
+
+		if (c < 0) { /* timeout */
+			data_prev = data;
 			if ((ret = read_data(&data)) != NULL) {
-				free_data(&data);
+				free_data(&data_prev);
 				goto out;
 			}
 			
 			compute_percentages(&data_prev, &data);
-			sort_data(&data);
-			print_data(&data);
 			free_data(&data_prev);
-			data_prev = data;
-			
-			continue;
-		}
-		
+
+			c = -1;
+		}
+
+		if (screen_mode == SCREEN_HELP && c >= 0) {
+			if (c == 'h' || c == '?')
+				c = -1;
+			/* go back to table and handle the key */
+			screen_mode = SCREEN_TABLE;
+		}
+
+		if (screen_mode == SCREEN_SORT && c >= 0) {
+			for (size_t i = 0; i < data.table.num_columns; i++) {
+				if (data.table.columns[i].key == c) {
+					sort_column = i;
+					screen_mode = SCREEN_TABLE;
+				}
+			}
+
+			c = -1;
+		}
+
 		switch (c) {
-			case 't':
-				print_warning("Showing task statistics");
-				op_mode = OP_TASKS;
+		case -1: /* do nothing */
+			break;
+		case 't':
+			op_mode = OP_TASKS;
+			break;
+		case 'i':
+			op_mode = OP_IPC;
+			break;
+		case 'e':
+			op_mode = OP_EXCS;
+			break;
+		case 's':
+			screen_mode = SCREEN_SORT;
+			break;
+		case 'r':
+			sort_reverse = -sort_reverse;
+			break;
+		case 'h':
+		case '?':
+			screen_mode = SCREEN_HELP;
+			break;
+		case 'q':
+			goto out;
+		case 'a':
+			if (op_mode == OP_EXCS) {
+				excs_all = !excs_all;
+				if (excs_all)
+					show_warning("Showing all exceptions");
+				else
+					show_warning("Showing only hot exceptions");
 				break;
-			case 'i':
-				print_warning("Showing IPC statistics");
-				op_mode = OP_IPC;
-				break;
-			case 'e':
-				print_warning("Showing exception statistics");
-				op_mode = OP_EXCS;
-				break;
-			case 'h':
-				print_warning("Showing help");
-				op_mode = OP_HELP;
-				break;
-			case 'q':
-				goto out;
-			case 'a':
-				if (op_mode == OP_EXCS) {
-					excs_all = !excs_all;
-					if (excs_all)
-						print_warning("Showing all exceptions");
-					else
-						print_warning("Showing only hot exceptions");
-					break;
-				}
-			default:
-				print_warning("Unknown command \"%c\", use \"h\" for help", c);
-				break;
-		}
+			}
+			/* fallthrough */
+		default:
+			show_warning("Unknown command \"%c\", use \"h\" for help", c);
+			continue; /* don't redraw */
+		}
+
+		if ((ret = fill_table(&data)) != NULL) {
+			goto out;
+		}
+		sort_table(&data.table);
+		print_data(&data);
 	}
 	
 out:
 	screen_done();
-	free_data(&data_prev);
+	free_data(&data);
 	
 	if (ret != NULL) {
Index: uspace/app/top/top.h
===================================================================
--- uspace/app/top/top.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/top/top.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -51,17 +51,10 @@
 
 typedef enum {
-	OP_TASKS,
-	OP_IPC,
-	OP_EXCS,
-	OP_HELP
-} op_mode_t;
+	SCREEN_TABLE,
+	SCREEN_SORT,
+	SCREEN_HELP,
+} screen_mode_t;
 
-typedef enum {
-	SORT_TASK_CYCLES
-} sort_mode_t;
-
-extern op_mode_t op_mode;
-extern sort_mode_t sort_mode;
-extern bool excs_all;
+extern screen_mode_t screen_mode;
 
 typedef struct {
@@ -87,4 +80,32 @@
 } perc_exc_t;
 
+typedef enum {
+	FIELD_EMPTY, FIELD_UINT, FIELD_UINT_SUFFIX_BIN, FIELD_UINT_SUFFIX_DEC,
+	FIELD_PERCENT, FIELD_STRING
+} field_type_t;
+
+typedef struct {
+	field_type_t type;
+	union {
+		fixed_float fixed;
+		uint64_t uint;
+		const char *string;
+	};
+} field_t;
+
+typedef struct {
+	const char *name;
+	char key;
+	int width;
+} column_t;
+
+typedef struct {
+	const char *name;
+	size_t num_columns;
+	const column_t *columns;
+	size_t num_fields;
+	field_t *fields;
+} table_t;
+
 typedef struct {
 	time_t hours;
@@ -107,5 +128,4 @@
 	stats_task_t *tasks;
 	perc_task_t *tasks_perc;
-	size_t *tasks_map;
 	
 	size_t threads_count;
@@ -122,4 +142,6 @@
 	uint64_t *ecycles_diff;
 	uint64_t *ecount_diff;
+
+	table_t table;
 } data_t;
 
Index: uspace/app/trace/ipc_desc.c
===================================================================
--- uspace/app/trace/ipc_desc.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/app/trace/ipc_desc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -39,13 +39,14 @@
 ipc_m_desc_t ipc_methods[] = {
 	/* System methods */
-	{ IPC_M_PHONE_HUNGUP,  "PHONE_HUNGUP" },
-	{ IPC_M_CONNECT_ME,    "CONNECT_ME" },
-	{ IPC_M_CONNECT_ME_TO, "CONNECT_ME_TO" },
-	{ IPC_M_CONNECT_TO_ME, "CONNECT_TO_ME" },
-	{ IPC_M_SHARE_OUT,     "SHARE_OUT" },
-	{ IPC_M_SHARE_IN,      "SHARE_IN" },
-	{ IPC_M_DATA_WRITE,    "DATA_WRITE" },
-	{ IPC_M_DATA_READ,     "DATA_READ" },
-	{ IPC_M_DEBUG,         "DEBUG" },
+	{ IPC_M_PHONE_HUNGUP,     "PHONE_HUNGUP" },
+	{ IPC_M_CONNECTION_CLONE, "CONNECTION_CLONE" },
+	{ IPC_M_CLONE_ESTABLISH,  "CLONE_ESTABLISH" },
+	{ IPC_M_CONNECT_ME_TO,    "CONNECT_ME_TO" },
+	{ IPC_M_CONNECT_TO_ME,    "CONNECT_TO_ME" },
+	{ IPC_M_SHARE_OUT,        "SHARE_OUT" },
+	{ IPC_M_SHARE_IN,         "SHARE_IN" },
+	{ IPC_M_DATA_WRITE,       "DATA_WRITE" },
+	{ IPC_M_DATA_READ,        "DATA_READ" },
+	{ IPC_M_DEBUG,            "DEBUG" },
 	
 	/* Terminating entry */
Index: uspace/drv/bus/usb/vhc/conndev.c
===================================================================
--- uspace/drv/bus/usb/vhc/conndev.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/drv/bus/usb/vhc/conndev.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -69,5 +69,5 @@
 	
 	if (data_request == 0) {
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		return;
 	}
Index: uspace/drv/infrastructure/rootvirt/devices.def
===================================================================
--- uspace/drv/infrastructure/rootvirt/devices.def	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/drv/infrastructure/rootvirt/devices.def	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -4,10 +4,4 @@
  * Unless the list is empty, the last item shall be followed by a comma.
  */
-
-/* Loopback network interface */
-{
-    .name = "lo",
-    .match_id = "virtual&loopback"
-},
 
 #ifdef CONFIG_TEST_DRIVERS
Index: uspace/drv/nic/e1k/Makefile
===================================================================
--- uspace/drv/nic/e1k/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/drv/nic/e1k/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -28,6 +28,6 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a $(LIBNIC_PREFIX)/libnic.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNIC_PREFIX)/libnic.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNIC_PREFIX)/include
 BINARY = e1k
 
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/drv/nic/e1k/e1k.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -49,5 +49,4 @@
 #include <device/pci.h>
 #include <nic.h>
-#include <nil_remote.h>
 #include <ops/nic.h>
 #include "e1k.h"
Index: pace/drv/nic/lo/Makefile
===================================================================
--- uspace/drv/nic/lo/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2011 Radim Vansa
-# 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 = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a $(LIBNIC_PREFIX)/libnic.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include
-BINARY = lo
-
-SOURCES = \
-	lo.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/nic/lo/lo.c
===================================================================
--- uspace/drv/nic/lo/lo.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,163 +1,0 @@
-/*
- * Copyright (c) 2011 Radim Vansa
- * 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 drv_lo
- * @brief Loopback virtual device driver
- * @{
- */
-/**
- * @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <async.h>
-#include <nic.h>
-
-#define NAME  "lo"
-
-static nic_address_t lo_addr = {
-	.address = {0, 0, 0, 0, 0, 0}
-};
-
-static ddf_dev_ops_t lo_dev_ops;
-
-static nic_device_info_t lo_info = {
-	.vendor_name = "HelenOS",
-	.model_name = "loopback",
-	.part_number = "N/A (virtual device)",
-	.serial_number = "N/A (virtual device)"
-};
-
-static void lo_send_frame(nic_t *nic_data, void *data, size_t size)
-{
-	nic_report_send_ok(nic_data, 1, size);
-	nic_received_noneth_frame(nic_data, data, size);
-}
-
-static int lo_set_address(ddf_fun_t *fun, const nic_address_t *address)
-{
-	printf("%s: Set loopback HW to " PRIMAC "\n", NAME,
-	    ARGSMAC(address->address));
-	return ENOTSUP;
-}
-
-static int lo_get_device_info(ddf_fun_t *fun, nic_device_info_t *info)
-{
-	assert(info);
-	memcpy(info, &lo_info, sizeof(nic_device_info_t));
-	return EOK;
-}
-
-static int lo_dev_add(ddf_dev_t *dev)
-{
-	ddf_fun_t *fun = NULL;
-	bool bound = false;
-	
-	nic_t *nic = nic_create_and_bind(dev);
-	if (nic == NULL) {
-		printf("%s: Failed to initialize\n", NAME);
-		return ENOMEM;
-	}
-	
-	dev->driver_data = nic;
-	nic_set_send_frame_handler(nic, lo_send_frame);
-	
-	int rc = nic_connect_to_services(nic);
-	if (rc != EOK) {
-		printf("%s: Failed to connect to services\n", NAME);
-		goto error;
-	}
-	
-	fun = ddf_fun_create(nic_get_ddf_dev(nic), fun_exposed, "port0");
-	if (fun == NULL) {
-		printf("%s: Failed creating function\n", NAME);
-		rc = ENOMEM;
-		goto error;
-	}
-	nic_set_ddf_fun(nic, fun);
-	fun->ops = &lo_dev_ops;
-	fun->driver_data = nic;
-	
-	rc = nic_report_address(nic, &lo_addr);
-	if (rc != EOK) {
-		printf("%s: Failed to setup loopback address\n", NAME);
-		goto error;
-	}
-	
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		printf("%s: Failed binding function\n", NAME);
-		goto error;
-	}
-	bound = true;
-	
-	rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC);
-	if (rc != EOK)
-		goto error;
-	
-	printf("%s: Adding loopback device '%s'\n", NAME, dev->name);
-	return EOK;
-	
-error:
-	if (bound)
-		ddf_fun_unbind(fun);
-	
-	if (fun != NULL)
-		ddf_fun_destroy(fun);
-	
-	nic_unbind_and_destroy(dev);
-	return rc;
-}
-
-static nic_iface_t lo_nic_iface;
-
-static driver_ops_t lo_driver_ops = {
-	.dev_add = lo_dev_add,
-};
-
-static driver_t lo_driver = {
-	.name = NAME,
-	.driver_ops = &lo_driver_ops
-};
-
-int main(int argc, char *argv[])
-{
-	nic_driver_init(NAME);
-	nic_driver_implement(&lo_driver_ops, &lo_dev_ops, &lo_nic_iface);
-	lo_nic_iface.set_address = lo_set_address;
-	lo_nic_iface.get_device_info = lo_get_device_info;
-	
-	return ddf_driver_main(&lo_driver);
-}
-
-/** @}
- */
Index: pace/drv/nic/lo/lo.ma
===================================================================
--- uspace/drv/nic/lo/lo.ma	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 virtual&loopback
Index: uspace/drv/nic/ne2k/Makefile
===================================================================
--- uspace/drv/nic/ne2k/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/drv/nic/ne2k/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -28,6 +28,6 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a $(LIBNIC_PREFIX)/libnic.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNIC_PREFIX)/libnic.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNIC_PREFIX)/include
 BINARY = ne2k
 
Index: uspace/drv/nic/rtl8139/Makefile
===================================================================
--- uspace/drv/nic/rtl8139/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/drv/nic/rtl8139/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -28,6 +28,6 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a $(LIBNIC_PREFIX)/libnic.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNIC_PREFIX)/libnic.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBNIC_PREFIX)/include
 BINARY = rtl8139
 
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -44,6 +44,4 @@
 #include <sysinfo.h>
 #include <ipc/ns.h>
-
-#include <net_checksum.h>
 
 #include <str.h>
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -88,4 +88,7 @@
 	generic/task.c \
 	generic/futex.c \
+	generic/inet.c \
+	generic/inetcfg.c \
+	generic/inetping.c \
 	generic/io/asprintf.c \
 	generic/io/io.c \
@@ -98,4 +101,6 @@
 	generic/io/printf_core.c \
 	generic/io/console.c \
+	generic/iplink.c \
+	generic/iplink_srv.c \
 	generic/malloc.c \
 	generic/sysinfo.c \
@@ -109,5 +114,4 @@
 	generic/adt/hash_set.c \
 	generic/adt/dynamic_fifo.c \
-	generic/adt/measured_strings.c \
 	generic/adt/char_map.c \
 	generic/adt/prodcons.c \
@@ -119,8 +123,5 @@
 	generic/vfs/canonify.c \
 	generic/net/inet.c \
-	generic/net/icmp_common.c \
-	generic/net/icmp_api.c \
 	generic/net/modules.c \
-	generic/net/packet.c \
 	generic/net/socket_client.c \
 	generic/net/socket_parse.c \
Index: pace/lib/c/generic/adt/measured_strings.c
===================================================================
--- uspace/lib/c/generic/adt/measured_strings.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,421 +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 with measured length implementation.
- * @see measured_strings.h
- */
-
-#include <adt/measured_strings.h>
-#include <malloc.h>
-#include <mem.h>
-#include <unistd.h>
-#include <errno.h>
-#include <async.h>
-
-/** Creates a new measured string bundled with a copy of the given string
- * itself as one memory block.
- *
- * If the measured string is being freed, whole memory block is freed.
- * The measured string should be used only as a constant.
- *
- * @param[in] string	The initial character string to be stored.
- * @param[in] length	The length of the given string without the terminating
- *			zero ('\0') character. If the length is zero, the actual
- *			length is computed. The given length is used and
- *			appended with the terminating zero ('\0') character
- *			otherwise.
- * @return		The new bundled character string with measured length.
- * @return		NULL if there is not enough memory left.
- */
-measured_string_t *
-measured_string_create_bulk(const uint8_t *string, size_t length)
-{
-	measured_string_t *new;
-
-	if (length == 0) {
-		while (string[length])
-			length++;
-	}
-	new = (measured_string_t *) malloc(sizeof(measured_string_t) +
-	    (sizeof(uint8_t) * (length + 1)));
-	if (!new)
-		return NULL;
-
-	new->length = length;
-	new->value = ((uint8_t *) new) + sizeof(measured_string_t);
-	/* Append terminating zero explicitly - to be safe */
-	memcpy(new->value, string, new->length);
-	new->value[new->length] = '\0';
-
-	return new;
-}
-
-/** Copies the given measured string with separated header and data parts.
- *
- * @param[in] source	The source measured string to be copied.
- * @return		The copy of the given measured string.
- * @return		NULL if the source parameter is NULL.
- * @return		NULL if there is not enough memory left.
- */
-measured_string_t *measured_string_copy(measured_string_t *source)
-{
-	measured_string_t *new;
-
-	if (!source)
-		return NULL;
-
-	new = (measured_string_t *) malloc(sizeof(measured_string_t));
-	if (new) {
-		new->value = (uint8_t *) malloc(source->length + 1);
-		if (new->value) {
-			new->length = source->length;
-			memcpy(new->value, source->value, new->length);
-			new->value[new->length] = '\0';
-			return new;
-		}
-		free(new);
-	}
-
-	return NULL;
-}
-
-/** Receives a measured strings array from a calling module.
- *
- * Creates the array and the data memory blocks.
- * This method should be used only while processing IPC messages as the array
- * size has to be negotiated in advance.
- *
- *  @param[out] strings	The received measured strings array.
- *  @param[out] data	The measured strings data. This memory block stores the
- *			actual character strings.
- *  @param[in] count	The size of the measured strings array.
- *  @return		EOK on success.
- *  @return		EINVAL if the strings or data parameter is NULL.
- *  @return		EINVAL if the count parameter is zero (0).
- *  @return		EINVAL if the sent array differs in size.
- *  @return		EINVAL if there is inconsistency in sent measured
- *			strings' lengths (should not occur).
- *  @return		ENOMEM if there is not enough memory left.
- *  @return		Other error codes as defined for the
- *			async_data_write_finalize() function.
- */
-int
-measured_strings_receive(measured_string_t **strings, uint8_t **data,
-    size_t count)
-{
-	size_t *lengths;
-	size_t index;
-	size_t length;
-	uint8_t *next;
-	ipc_callid_t callid;
-	int rc;
-
-	if ((!strings) || (!data) || (count <= 0))
-		return EINVAL;
-
-	lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
-	if (!lengths)
-		return ENOMEM;
-
-	if ((!async_data_write_receive(&callid, &length)) ||
-	    (length != sizeof(size_t) * (count + 1))) {
-		free(lengths);
-		return EINVAL;
-	}
-	rc = async_data_write_finalize(callid, lengths, length);
-	if (rc != EOK) {
-		free(lengths);
-		return rc;
-	}
-
-	*data = malloc(lengths[count]);
-	if (!*data) {
-		free(lengths);
-		return ENOMEM;
-	}
-	(*data)[lengths[count] - 1] = '\0';
-
-	*strings = (measured_string_t *) malloc(sizeof(measured_string_t) *
-	    count);
-	if (!*strings) {
-		free(lengths);
-		free(*data);
-		return ENOMEM;
-	}
-
-	next = *data;
-	for (index = 0; index < count; index++) {
-		(*strings)[index].length = lengths[index];
-		if (lengths[index] > 0) {
-			if (!async_data_write_receive(&callid, &length) ||
-			    (length != lengths[index])) {
-				free(*data);
-				free(*strings);
-				free(lengths);
-				return EINVAL;
-			}
-			rc = async_data_write_finalize(callid, next,
-			    lengths[index]);
-			if (rc != EOK) {
-				free(*data);
-				free(*strings);
-				free(lengths);
-				return rc;
-			}
-			(*strings)[index].value = next;
-			next += lengths[index];
-			*next++ = '\0';
-		} else {
-			(*strings)[index].value = NULL;
-		}
-	}
-
-	free(lengths);
-	return EOK;
-}
-
-/** Computes the lengths of the measured strings in the given array.
- *
- * @param[in] strings	The measured strings array to be processed.
- * @param[in] count	The measured strings array size.
- * @return		The computed sizes array.
- * @return		NULL if there is not enough memory left.
- */
-static size_t *prepare_lengths(const measured_string_t *strings, size_t count)
-{
-	size_t *lengths;
-	size_t index;
-	size_t length;
-
-	lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
-	if (!lengths)
-		return NULL;
-
-	length = 0;
-	for (index = 0; index < count; index++) {
-		lengths[index] = strings[index].length;
-		length += lengths[index] + 1;
-	}
-	lengths[count] = length;
-	return lengths;
-}
-
-/** Replies the given measured strings array to a calling module.
- *
- * This method should be used only while processing IPC messages as the array
- * size has to be negotiated in advance.
- *
- * @param[in] strings	The measured strings array to be transferred.
- * @param[in] count	The measured strings array size.
- * @return		EOK on success.
- * @return		EINVAL if the strings parameter is NULL.
- * @return		EINVAL if the count parameter is zero (0).
- * @return		EINVAL if the calling module does not accept the given
- *			array size.
- * @return		EINVAL if there is inconsistency in sent measured
- *			strings' lengths (should not occur).
- * @return		Other error codes as defined for the
- *			async_data_read_finalize() function.
- */
-int measured_strings_reply(const measured_string_t *strings, size_t count)
-{
-	size_t *lengths;
-	size_t index;
-	size_t length;
-	ipc_callid_t callid;
-	int rc;
-
-	if ((!strings) || (count <= 0))
-		return EINVAL;
-
-	lengths = prepare_lengths(strings, count);
-	if (!lengths)
-		return ENOMEM;
-
-	if (!async_data_read_receive(&callid, &length) ||
-	    (length != sizeof(size_t) * (count + 1))) {
-		free(lengths);
-		return EINVAL;
-	}
-	rc = async_data_read_finalize(callid, lengths, length);
-	if (rc != EOK) {
-		free(lengths);
-		return rc;
-	}
-	free(lengths);
-
-	for (index = 0; index < count; index++) {
-		if (strings[index].length > 0) {
-			if (!async_data_read_receive(&callid, &length) ||
-			    (length != strings[index].length)) {
-				return EINVAL;
-			}
-			rc = async_data_read_finalize(callid,
-			    strings[index].value, strings[index].length);
-			if (rc != EOK)
-				return rc;
-		}
-	}
-
-	return EOK;
-}
-
-/** Receives a measured strings array from another module.
- *
- * Creates the array and the data memory blocks.
- * This method should be used only following other IPC messages as the array
- * size has to be negotiated in advance.
- *
- * @param[in] exch	Exchange.
- * @param[out] strings	The returned measured strings array.
- * @param[out] data	The measured strings data. This memory block stores the
- *			actual character strings.
- * @param[in] count	The size of the measured strings array.
- * @return		EOK on success.
- * @return		EINVAL if the strings or data parameter is NULL.
- * @return		EINVAL if the exch or count parameter is invalid.
- * @return		EINVAL if the sent array differs in size.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			async_data_read_start() function.
- */
-int measured_strings_return(async_exch_t *exch, measured_string_t **strings,
-    uint8_t **data, size_t count)
-{
-	size_t *lengths;
-	size_t index;
-	uint8_t *next;
-	int rc;
-
-	if ((exch == NULL) || (!strings) || (!data) || (count <= 0))
-		return EINVAL;
-
-	lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
-	if (!lengths)
-		return ENOMEM;
-
-	rc = async_data_read_start(exch, lengths,
-	    sizeof(size_t) * (count + 1));
-	if (rc != EOK) {
-		free(lengths);
-		return rc;
-	}
-
-	*data = malloc(lengths[count]);
-	if (!*data) {
-		free(lengths);
-		return ENOMEM;
-	}
-
-	*strings = (measured_string_t *) malloc(sizeof(measured_string_t) *
-	    count);
-	if (!*strings) {
-		free(lengths);
-		free(*data);
-		return ENOMEM;
-	}
-
-	next = *data;
-	for (index = 0; index < count; index++) {
-		(*strings)[index].length = lengths[index];
-		if (lengths[index] > 0) {
-			rc = async_data_read_start(exch, next, lengths[index]);
-			if (rc != EOK) {
-			    	free(lengths);
-				free(data);
-				free(strings);
-				return rc;
-			}
-			(*strings)[index].value = next;
-			next += lengths[index];
-			*next++ = '\0';
-		} else {
-			(*strings)[index].value = NULL;
-		}
-	}
-
-	free(lengths);
-	return EOK;
-}
-
-/** Sends the given measured strings array to another module.
- *
- * This method should be used only following other IPC messages as the array
- * size has to be negotiated in advance.
- *
- * @param[in] exch	Exchange.
- * @param[in] strings	The measured strings array to be transferred.
- * @param[in] count	The measured strings array size.
- * @return		EOK on success.
- * @return		EINVAL if the strings parameter is NULL.
- * @return		EINVAL if the exch or count parameter is invalid.
- * @return		Other error codes as defined for the
- *			async_data_write_start() function.
- */
-int measured_strings_send(async_exch_t *exch, const measured_string_t *strings,
-    size_t count)
-{
-	size_t *lengths;
-	size_t index;
-	int rc;
-
-	if ((exch == NULL) || (!strings) || (count <= 0))
-		return EINVAL;
-
-	lengths = prepare_lengths(strings, count);
-	if (!lengths)
-		return ENOMEM;
-
-	rc = async_data_write_start(exch, lengths,
-	    sizeof(size_t) * (count + 1));
-	if (rc != EOK) {
-		free(lengths);
-		return rc;
-	}
-
-	free(lengths);
-
-	for (index = 0; index < count; index++) {
-		if (strings[index].length > 0) {
-			rc = async_data_write_start(exch, strings[index].value,
-			    strings[index].length);
-			if (rc != EOK)
-				return rc;
-		}
-	}
-
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/async.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -189,4 +189,10 @@
 	/** If reply was received. */
 	bool done;
+
+	/** If the message / reply should be discarded on arrival. */
+	bool forget;
+
+	/** If already destroyed. */
+	bool destroyed;
 	
 	/** Pointer to where the answer data is stored. */
@@ -240,4 +246,52 @@
 /** Identifier of the incoming connection handled by the current fibril. */
 static fibril_local connection_t *fibril_connection;
+
+static void to_event_initialize(to_event_t *to)
+{
+	struct timeval tv = { 0, 0 };
+
+	to->inlist = false;
+	to->occurred = false;
+	link_initialize(&to->link);
+	to->expires = tv;
+}
+
+static void wu_event_initialize(wu_event_t *wu)
+{
+	wu->inlist = false;
+	link_initialize(&wu->link);
+}
+
+void awaiter_initialize(awaiter_t *aw)
+{
+	aw->fid = 0;
+	aw->active = false;
+	to_event_initialize(&aw->to_event);
+	wu_event_initialize(&aw->wu_event);
+}
+
+static amsg_t *amsg_create(void)
+{
+	amsg_t *msg;
+
+	msg = malloc(sizeof(amsg_t));
+	if (msg) {
+		msg->done = false;
+		msg->forget = false;
+		msg->destroyed = false;
+		msg->dataptr = NULL;
+		msg->retval = (sysarg_t) EINVAL;
+		awaiter_initialize(&msg->wdata);
+	}
+
+	return msg;
+}
+
+static void amsg_destroy(amsg_t *msg)
+{
+	assert(!msg->destroyed);
+	msg->destroyed = true;
+	free(msg);
+}
 
 static void *default_client_data_constructor(void)
@@ -892,5 +946,5 @@
 	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_CONNECT_ME:
+	case IPC_M_CLONE_ESTABLISH:
 	case IPC_M_CONNECT_ME_TO:
 		/* Open new connection with fibril, etc. */
@@ -963,4 +1017,5 @@
 		
 		suseconds_t timeout;
+		unsigned int flags = SYNCH_FLAGS_NONE;
 		if (!list_empty(&timeout_list)) {
 			awaiter_t *waiter = list_get_instance(
@@ -973,17 +1028,30 @@
 				futex_up(&async_futex);
 				handle_expired_timeouts();
-				continue;
-			} else
+				/*
+				 * Notice that even if the event(s) already
+				 * expired (and thus the other fibril was
+				 * supposed to be running already),
+				 * we check for incoming IPC.
+				 *
+				 * Otherwise, a fibril that continuously
+				 * creates (almost) expired events could
+				 * prevent IPC retrieval from the kernel.
+				 */
+				timeout = 0;
+				flags = SYNCH_FLAGS_NON_BLOCKING;
+
+			} else {
 				timeout = tv_sub(&waiter->to_event.expires, &tv);
-		} else
+				futex_up(&async_futex);
+			}
+		} else {
+			futex_up(&async_futex);
 			timeout = SYNCH_NO_TIMEOUT;
-		
-		futex_up(&async_futex);
+		}
 		
 		atomic_inc(&threads_in_ipc_wait);
 		
 		ipc_call_t call;
-		ipc_callid_t callid = ipc_wait_cycle(&call, timeout,
-		    SYNCH_FLAGS_NONE);
+		ipc_callid_t callid = ipc_wait_cycle(&call, timeout, flags);
 		
 		atomic_dec(&threads_in_ipc_wait);
@@ -1100,9 +1168,13 @@
 	
 	msg->done = true;
-	if (!msg->wdata.active) {
+
+	if (msg->forget) {
+		assert(msg->wdata.active);
+		amsg_destroy(msg);
+	} else if (!msg->wdata.active) {
 		msg->wdata.active = true;
 		fibril_add_ready(msg->wdata.fid);
 	}
-	
+
 	futex_up(&async_futex);
 }
@@ -1131,17 +1203,9 @@
 		return 0;
 	
-	amsg_t *msg = malloc(sizeof(amsg_t));
+	amsg_t *msg = amsg_create();
 	if (msg == NULL)
 		return 0;
 	
-	msg->done = false;
 	msg->dataptr = dataptr;
-	
-	msg->wdata.to_event.inlist = false;
-	
-	/*
-	 * We may sleep in the next method,
-	 * but it will use its own means
-	 */
 	msg->wdata.active = true;
 	
@@ -1177,18 +1241,9 @@
 		return 0;
 	
-	amsg_t *msg = malloc(sizeof(amsg_t));
-	
+	amsg_t *msg = amsg_create();
 	if (msg == NULL)
 		return 0;
 	
-	msg->done = false;
 	msg->dataptr = dataptr;
-	
-	msg->wdata.to_event.inlist = false;
-	
-	/*
-	 * We may sleep in the next method,
-	 * but it will use its own means
-	 */
 	msg->wdata.active = true;
 	
@@ -1213,4 +1268,8 @@
 	
 	futex_down(&async_futex);
+
+	assert(!msg->forget);
+	assert(!msg->destroyed);
+
 	if (msg->done) {
 		futex_up(&async_futex);
@@ -1231,8 +1290,12 @@
 		*retval = msg->retval;
 	
-	free(msg);
+	amsg_destroy(msg);
 }
 
 /** Wait for a message sent by the async framework, timeout variant.
+ *
+ * If the wait times out, the caller may choose to either wait again by calling
+ * async_wait_for() or async_wait_timeout(), or forget the message via
+ * async_forget().
  *
  * @param amsgid  Hash of the message to wait for.
@@ -1249,10 +1312,10 @@
 	
 	amsg_t *msg = (amsg_t *) amsgid;
-	
-	/* TODO: Let it go through the event read at least once */
-	if (timeout < 0)
-		return ETIMEOUT;
-	
+
 	futex_down(&async_futex);
+
+	assert(!msg->forget);
+	assert(!msg->destroyed);
+
 	if (msg->done) {
 		futex_up(&async_futex);
@@ -1260,7 +1323,31 @@
 	}
 	
+	/*
+	 * Negative timeout is converted to zero timeout to avoid
+	 * using tv_add with negative augmenter.
+	 */
+	if (timeout < 0)
+		timeout = 0;
+
 	gettimeofday(&msg->wdata.to_event.expires, NULL);
 	tv_add(&msg->wdata.to_event.expires, timeout);
 	
+	/*
+	 * Current fibril is inserted as waiting regardless of the
+	 * "size" of the timeout.
+	 *
+	 * Checking for msg->done and immediately bailing out when
+	 * timeout == 0 would mean that the manager fibril would never
+	 * run (consider single threaded program).
+	 * Thus the IPC answer would be never retrieved from the kernel.
+	 *
+	 * Notice that the actual delay would be very small because we
+	 * - switch to manager fibril
+	 * - the manager sees expired timeout
+	 * - and thus adds us back to ready queue
+	 * - manager switches back to some ready fibril
+	 *   (prior it, it checks for incoming IPC).
+	 *
+	 */
 	msg->wdata.fid = fibril_get_id();
 	msg->wdata.active = false;
@@ -1279,8 +1366,32 @@
 		*retval = msg->retval;
 	
-	free(msg);
+	amsg_destroy(msg);
 	
 	return 0;
 }
+ 
+/** Discard the message / reply on arrival.
+ *
+ * The message will be marked to be discarded once the reply arrives in
+ * reply_received(). It is not allowed to call async_wait_for() or
+ * async_wait_timeout() on this message after a call to this function.
+ *
+ * @param amsgid  Hash of the message to forget.
+ */
+void async_forget(aid_t amsgid)
+{
+	amsg_t *msg = (amsg_t *) amsgid;
+
+	assert(msg);
+	assert(!msg->forget);
+	assert(!msg->destroyed);
+
+	futex_down(&async_futex);
+	if (msg->done)
+		amsg_destroy(msg);
+	else 
+		msg->forget = true;
+	futex_up(&async_futex);
+}
 
 /** Wait for specified time.
@@ -1293,11 +1404,9 @@
 void async_usleep(suseconds_t timeout)
 {
-	amsg_t *msg = malloc(sizeof(amsg_t));
-	
+	amsg_t *msg = amsg_create();
 	if (!msg)
 		return;
 	
 	msg->wdata.fid = fibril_get_id();
-	msg->wdata.active = false;
 	
 	gettimeofday(&msg->wdata.to_event.expires, NULL);
@@ -1313,5 +1422,5 @@
 	/* Futex is up automatically after fibril_switch() */
 	
-	free(msg);
+	amsg_destroy(msg);
 }
 
@@ -1559,7 +1668,7 @@
 }
 
-/** Wrapper for making IPC_M_CONNECT_ME calls using the async framework.
- *
- * Ask through for a cloned connection to some service.
+/** Wrapper for making IPC_M_CLONE_ESTABLISH calls using the async framework.
+ *
+ * Ask for a cloned connection to some service.
  *
  * @param mgmt Exchange management style.
@@ -1569,5 +1678,5 @@
  *
  */
-async_sess_t *async_connect_me(exch_mgmt_t mgmt, async_exch_t *exch)
+async_sess_t *async_clone_establish(exch_mgmt_t mgmt, async_exch_t *exch)
 {
 	if (exch == NULL) {
@@ -1584,6 +1693,6 @@
 	ipc_call_t result;
 	
-	amsg_t *msg = malloc(sizeof(amsg_t));
-	if (msg == NULL) {
+	amsg_t *msg = amsg_create();
+	if (!msg) {
 		free(sess);
 		errno = ENOMEM;
@@ -1591,16 +1700,8 @@
 	}
 	
-	msg->done = false;
 	msg->dataptr = &result;
-	
-	msg->wdata.to_event.inlist = false;
-	
-	/*
-	 * We may sleep in the next method,
-	 * but it will use its own means
-	 */
 	msg->wdata.active = true;
 	
-	ipc_call_async_0(exch->phone, IPC_M_CONNECT_ME, msg,
+	ipc_call_async_0(exch->phone, IPC_M_CLONE_ESTABLISH, msg,
 	    reply_received, true);
 	
@@ -1643,17 +1744,9 @@
 	ipc_call_t result;
 	
-	amsg_t *msg = malloc(sizeof(amsg_t));
-	if (msg == NULL)
+	amsg_t *msg = amsg_create();
+	if (!msg)
 		return ENOENT;
 	
-	msg->done = false;
 	msg->dataptr = &result;
-	
-	msg->wdata.to_event.inlist = false;
-	
-	/*
-	 * We may sleep in the next method,
-	 * but it will use its own means
-	 */
 	msg->wdata.active = true;
 	
@@ -2251,5 +2344,5 @@
 	    IPC_FF_ROUTE_FROM_ME);
 	if (retval != EOK) {
-		async_wait_for(msg, NULL);
+		async_forget(msg);
 		ipc_answer_0(callid, retval);
 		return retval;
@@ -2445,5 +2538,5 @@
 	    IPC_FF_ROUTE_FROM_ME);
 	if (retval != EOK) {
-		async_wait_for(msg, NULL);
+		async_forget(msg);
 		ipc_answer_0(callid, retval);
 		return retval;
Index: uspace/lib/c/generic/device/nic.c
===================================================================
--- uspace/lib/c/generic/device/nic.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/device/nic.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -65,5 +65,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -94,5 +94,5 @@
 	rc = async_connect_to_me(exch, 0, 0, 0, cfun, carg);
 	if (rc != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return rc;
 	}
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/devman.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -188,5 +188,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -226,5 +226,5 @@
 	if (retval != EOK) {
 		devman_exchange_end(exch);
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -242,6 +242,6 @@
 		if (retval != EOK) {
 			devman_exchange_end(exch);
-			async_wait_for(req2, NULL);
-			async_wait_for(req, NULL);
+			async_forget(req2);
+			async_forget(req);
 			return retval;
 		}
@@ -250,5 +250,5 @@
 		if (retval != EOK) {
 			devman_exchange_end(exch);
-			async_wait_for(req, NULL);
+			async_forget(req);
 			return retval;
 		}
@@ -283,5 +283,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -386,5 +386,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -423,5 +423,5 @@
 	
 	if (dretval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return dretval;
 	}
@@ -488,5 +488,5 @@
 	
 	if (rc != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return rc;
 	}
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/fibril_synch.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -112,8 +112,7 @@
 		awaiter_t wdata;
 
+		awaiter_initialize(&wdata);
 		wdata.fid = fibril_get_id();
-		wdata.active = false;
 		wdata.wu_event.inlist = true;
-		link_initialize(&wdata.wu_event.link);
 		list_append(&wdata.wu_event.link, &fm->waiters);
 		check_for_deadlock(&fm->oi);
@@ -205,8 +204,7 @@
 		awaiter_t wdata;
 
+		awaiter_initialize(&wdata);
 		wdata.fid = (fid_t) f;
-		wdata.active = false;
 		wdata.wu_event.inlist = true;
-		link_initialize(&wdata.wu_event.link);
 		f->flags &= ~FIBRIL_WRITER;
 		list_append(&wdata.wu_event.link, &frw->waiters);
@@ -233,8 +231,7 @@
 		awaiter_t wdata;
 
+		awaiter_initialize(&wdata);
 		wdata.fid = (fid_t) f;
-		wdata.active = false;
 		wdata.wu_event.inlist = true;
-		link_initialize(&wdata.wu_event.link);
 		f->flags |= FIBRIL_WRITER;
 		list_append(&wdata.wu_event.link, &frw->waiters);
@@ -375,13 +372,8 @@
 		return ETIMEOUT;
 
+	awaiter_initialize(&wdata);
 	wdata.fid = fibril_get_id();
-	wdata.active = false;
-	
 	wdata.to_event.inlist = timeout > 0;
-	wdata.to_event.occurred = false;
-	link_initialize(&wdata.to_event.link);
-
 	wdata.wu_event.inlist = true;
-	link_initialize(&wdata.wu_event.link);
 
 	futex_down(&async_futex);
Index: uspace/lib/c/generic/inet.c
===================================================================
--- uspace/lib/c/generic/inet.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/generic/inet.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+
+#include <async.h>
+#include <assert.h>
+#include <errno.h>
+#include <inet/inet.h>
+#include <ipc/inet.h>
+#include <ipc/services.h>
+#include <loc.h>
+
+static void inet_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static async_sess_t *inet_sess = NULL;
+static inet_ev_ops_t *inet_ev_ops = NULL;
+static uint8_t inet_protocol = 0;
+
+static int inet_callback_create(void)
+{
+	async_exch_t *exch = async_exchange_begin(inet_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, INET_CALLBACK_CREATE, &answer);
+	int rc = async_connect_to_me(exch, 0, 0, 0, inet_cb_conn, NULL);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+static int inet_set_proto(uint8_t protocol)
+{
+	int rc;
+
+	async_exch_t *exch = async_exchange_begin(inet_sess);
+	rc = async_req_1_0(exch, INET_SET_PROTO, protocol);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int inet_init(uint8_t protocol, inet_ev_ops_t *ev_ops)
+{
+	service_id_t inet_svc;
+	int rc;
+
+	assert(inet_sess == NULL);
+	assert(inet_ev_ops == NULL);
+	assert(inet_protocol == 0);
+
+	rc = loc_service_get_id(SERVICE_NAME_INET, &inet_svc,
+	    IPC_FLAG_BLOCKING);
+	if (rc != EOK)
+		return ENOENT;
+
+	inet_sess = loc_service_connect(EXCHANGE_SERIALIZE, inet_svc,
+	    IPC_FLAG_BLOCKING);
+	if (inet_sess == NULL)
+		return ENOENT;
+
+	if (inet_set_proto(protocol) != EOK) {
+		async_hangup(inet_sess);
+		inet_sess = NULL;
+		return EIO;
+	}
+
+	if (inet_callback_create() != EOK) {
+		async_hangup(inet_sess);
+		inet_sess = NULL;
+		return EIO;
+	}
+
+	inet_protocol = protocol;
+	inet_ev_ops = ev_ops;
+
+	return EOK;
+}
+
+int inet_send(inet_dgram_t *dgram, uint8_t ttl, inet_df_t df)
+{
+	async_exch_t *exch = async_exchange_begin(inet_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_5(exch, INET_SEND, dgram->src.ipv4,
+	    dgram->dest.ipv4, dgram->tos, ttl, df, &answer);
+	int 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);
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+int inet_get_srcaddr(inet_addr_t *remote, uint8_t tos, inet_addr_t *local)
+{
+	sysarg_t local_addr;
+	async_exch_t *exch = async_exchange_begin(inet_sess);
+
+	int rc = async_req_2_1(exch, INET_GET_SRCADDR, remote->ipv4,
+	    tos, &local_addr);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	local->ipv4 = local_addr;
+	return EOK;
+}
+
+static void inet_ev_recv(ipc_callid_t callid, ipc_call_t *call)
+{
+	int rc;
+	inet_dgram_t dgram;
+
+	dgram.src.ipv4 = IPC_GET_ARG1(*call);
+	dgram.dest.ipv4 = IPC_GET_ARG2(*call);
+	dgram.tos = IPC_GET_ARG3(*call);
+
+	rc = async_data_write_accept(&dgram.data, false, 0, 0, 0, &dgram.size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	rc = inet_ev_ops->recv(&dgram);
+	async_answer_0(callid, rc);
+}
+
+static void inet_cb_conn(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)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case INET_EV_RECV:
+			inet_ev_recv(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/inetcfg.c
===================================================================
--- uspace/lib/c/generic/inetcfg.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/generic/inetcfg.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,377 @@
+/*
+ * 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.
+ */
+
+#include <async.h>
+#include <assert.h>
+#include <errno.h>
+#include <inet/inetcfg.h>
+#include <ipc/inet.h>
+#include <ipc/services.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <str.h>
+
+static async_sess_t *inetcfg_sess = NULL;
+
+static int inetcfg_get_ids_once(sysarg_t method, sysarg_t arg1,
+    sysarg_t *id_buf, size_t buf_size, size_t *act_size)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	int rc = async_data_read_start(exch, id_buf, buf_size);
+
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	if (retval != EOK) {
+		return retval;
+	}
+
+	*act_size = IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Get list of IDs.
+ *
+ * Returns an allocated array of service IDs.
+ *
+ * @param method	IPC method
+ * @param arg1		IPC argument 1
+ * @param data		Place to store pointer to array of IDs
+ * @param count		Place to store number of IDs
+ * @return 		EOK on success or negative error code
+ */
+static int inetcfg_get_ids_internal(sysarg_t method, sysarg_t arg1,
+    sysarg_t **data, size_t *count)
+{
+	*data = NULL;
+	*count = 0;
+
+	size_t act_size = 0;
+	int rc = inetcfg_get_ids_once(method, arg1, NULL, 0,
+	    &act_size);
+	if (rc != EOK)
+		return rc;
+
+	size_t alloc_size = act_size;
+	service_id_t *ids = malloc(alloc_size);
+	if (ids == NULL)
+		return ENOMEM;
+
+	while (true) {
+		rc = inetcfg_get_ids_once(method, arg1, ids, alloc_size,
+		    &act_size);
+		if (rc != EOK)
+			return rc;
+
+		if (act_size <= alloc_size)
+			break;
+
+		alloc_size = act_size;
+		ids = realloc(ids, alloc_size);
+		if (ids == NULL)
+			return ENOMEM;
+	}
+
+	*count = act_size / sizeof(sysarg_t);
+	*data = ids;
+	return EOK;
+}
+
+int inetcfg_init(void)
+{
+	service_id_t inet_svc;
+	int rc;
+
+	assert(inetcfg_sess == NULL);
+
+	rc = loc_service_get_id(SERVICE_NAME_INETCFG, &inet_svc,
+	    IPC_FLAG_BLOCKING);
+	if (rc != EOK)
+		return ENOENT;
+
+	inetcfg_sess = loc_service_connect(EXCHANGE_SERIALIZE, inet_svc,
+	    IPC_FLAG_BLOCKING);
+	if (inetcfg_sess == NULL)
+		return ENOENT;
+
+	return EOK;
+}
+
+int inetcfg_addr_create_static(const char *name, inet_naddr_t *naddr,
+    sysarg_t link_id, sysarg_t *addr_id)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_3(exch, INETCFG_ADDR_CREATE_STATIC, naddr->ipv4,
+	    naddr->bits, link_id, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+
+	async_exchange_end(exch);
+
+	if (retval != EOK) {
+		async_forget(req);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+	*addr_id = IPC_GET_ARG1(answer);
+
+	return retval;
+}
+
+int inetcfg_addr_delete(sysarg_t addr_id)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	int rc = async_req_1_0(exch, INETCFG_ADDR_DELETE, addr_id);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int inetcfg_addr_get(sysarg_t addr_id, inet_addr_info_t *ainfo)
+{
+	ipc_call_t dreply;
+	sysarg_t dretval;
+	size_t act_size;
+	char name_buf[LOC_NAME_MAXLEN + 1];
+
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, INETCFG_ADDR_GET, addr_id, &answer);
+	aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN, &dreply);
+	async_wait_for(dreq, &dretval);
+
+	async_exchange_end(exch);
+
+	if (dretval != EOK) {
+		async_forget(req);
+		return dretval;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	if (retval != EOK)
+		return retval;
+
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= LOC_NAME_MAXLEN);
+	name_buf[act_size] = '\0';
+
+	ainfo->naddr.ipv4 = IPC_GET_ARG1(answer);
+	ainfo->naddr.bits = IPC_GET_ARG2(answer);
+	ainfo->ilink = IPC_GET_ARG3(answer);
+	ainfo->name = str_dup(name_buf);
+
+	return EOK;
+}
+
+int inetcfg_addr_get_id(const char *name, sysarg_t link_id, sysarg_t *addr_id)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, INETCFG_ADDR_GET_ID, link_id, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+
+	async_exchange_end(exch);
+
+	if (retval != EOK) {
+		async_forget(req);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+	*addr_id = IPC_GET_ARG1(answer);
+
+	return retval;
+}
+
+int inetcfg_get_addr_list(sysarg_t **addrs, size_t *count)
+{
+	return inetcfg_get_ids_internal(INETCFG_GET_ADDR_LIST,
+	    0, addrs, count);
+}
+
+int inetcfg_get_link_list(sysarg_t **links, size_t *count)
+{
+	return inetcfg_get_ids_internal(INETCFG_GET_LINK_LIST,
+	    0, links, count);
+}
+
+int inetcfg_get_sroute_list(sysarg_t **sroutes, size_t *count)
+{
+	return inetcfg_get_ids_internal(INETCFG_GET_SROUTE_LIST,
+	    0, sroutes, count);
+}
+
+int inetcfg_link_get(sysarg_t link_id, inet_link_info_t *linfo)
+{
+	ipc_call_t dreply;
+	sysarg_t dretval;
+	size_t act_size;
+	char name_buf[LOC_NAME_MAXLEN + 1];
+
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, INETCFG_LINK_GET, link_id, &answer);
+	aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN, &dreply);
+	async_wait_for(dreq, &dretval);
+
+	async_exchange_end(exch);
+
+	if (dretval != EOK) {
+		async_forget(req);
+		return dretval;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	if (retval != EOK)
+		return retval;
+
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= LOC_NAME_MAXLEN);
+	name_buf[act_size] = '\0';
+
+	linfo->name = str_dup(name_buf);
+	linfo->def_mtu = IPC_GET_ARG1(answer);
+
+	return EOK;
+}
+
+int inetcfg_sroute_create(const char *name, inet_naddr_t *dest,
+    inet_addr_t *router, sysarg_t *sroute_id)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_3(exch, INETCFG_SROUTE_CREATE,
+	    dest->ipv4, dest->bits, router->ipv4, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+
+	async_exchange_end(exch);
+
+	if (retval != EOK) {
+		async_forget(req);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+	*sroute_id = IPC_GET_ARG1(answer);
+
+	return retval;
+}
+
+int inetcfg_sroute_delete(sysarg_t sroute_id)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	int rc = async_req_1_0(exch, INETCFG_SROUTE_DELETE, sroute_id);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int inetcfg_sroute_get(sysarg_t sroute_id, inet_sroute_info_t *srinfo)
+{
+	ipc_call_t dreply;
+	sysarg_t dretval;
+	size_t act_size;
+	char name_buf[LOC_NAME_MAXLEN + 1];
+
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, INETCFG_SROUTE_GET, sroute_id, &answer);
+	aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN, &dreply);
+	async_wait_for(dreq, &dretval);
+
+	async_exchange_end(exch);
+
+	if (dretval != EOK) {
+		async_forget(req);
+		return dretval;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	if (retval != EOK)
+		return retval;
+
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= LOC_NAME_MAXLEN);
+	name_buf[act_size] = '\0';
+
+	srinfo->dest.ipv4 = IPC_GET_ARG1(answer);
+	srinfo->dest.bits = IPC_GET_ARG2(answer);
+	srinfo->router.ipv4 = IPC_GET_ARG3(answer);
+	srinfo->name = str_dup(name_buf);
+
+	return EOK;
+}
+
+int inetcfg_sroute_get_id(const char *name, sysarg_t *sroute_id)
+{
+	async_exch_t *exch = async_exchange_begin(inetcfg_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, INETCFG_SROUTE_GET_ID, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+
+	async_exchange_end(exch);
+
+	if (retval != EOK) {
+		async_forget(req);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+	*sroute_id = IPC_GET_ARG1(answer);
+
+	return retval;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/inetping.c
===================================================================
--- uspace/lib/c/generic/inetping.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/generic/inetping.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+#include <async.h>
+#include <assert.h>
+#include <errno.h>
+#include <inet/inetping.h>
+#include <ipc/inet.h>
+#include <ipc/services.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <str.h>
+
+static void inetping_cb_conn(ipc_callid_t, ipc_call_t *, void *);
+static void inetping_ev_recv(ipc_callid_t, ipc_call_t *);
+
+static async_sess_t *inetping_sess = NULL;
+static inetping_ev_ops_t *inetping_ev_ops;
+
+int inetping_init(inetping_ev_ops_t *ev_ops)
+{
+	service_id_t inetping_svc;
+	int rc;
+
+	assert(inetping_sess == NULL);
+
+	inetping_ev_ops = ev_ops;
+
+	rc = loc_service_get_id(SERVICE_NAME_INETPING, &inetping_svc,
+	    IPC_FLAG_BLOCKING);
+	if (rc != EOK)
+		return ENOENT;
+
+	inetping_sess = loc_service_connect(EXCHANGE_SERIALIZE, inetping_svc,
+	    IPC_FLAG_BLOCKING);
+	if (inetping_sess == NULL)
+		return ENOENT;
+
+	async_exch_t *exch = async_exchange_begin(inetping_sess);
+
+	rc = async_connect_to_me(exch, 0, 0, 0, inetping_cb_conn, NULL);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_hangup(inetping_sess);
+		inetping_sess = NULL;
+		return rc;
+	}
+
+	return EOK;
+}
+
+int inetping_send(inetping_sdu_t *sdu)
+{
+	async_exch_t *exch = async_exchange_begin(inetping_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_3(exch, INETPING_SEND, sdu->src.ipv4,
+	    sdu->dest.ipv4, sdu->seq_no, &answer);
+	sysarg_t retval = async_data_write_start(exch, sdu->data, sdu->size);
+
+	async_exchange_end(exch);
+
+	if (retval != EOK) {
+		async_forget(req);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+	return retval;
+}
+
+int inetping_get_srcaddr(inet_addr_t *remote, inet_addr_t *local)
+{
+	sysarg_t local_addr;
+	async_exch_t *exch = async_exchange_begin(inetping_sess);
+
+	int rc = async_req_1_1(exch, INETPING_GET_SRCADDR, remote->ipv4,
+	    &local_addr);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	local->ipv4 = local_addr;
+	return EOK;
+}
+
+static void inetping_ev_recv(ipc_callid_t callid, ipc_call_t *call)
+{
+	int rc;
+	inetping_sdu_t sdu;
+
+	sdu.src.ipv4 = IPC_GET_ARG1(*call);
+	sdu.dest.ipv4 = IPC_GET_ARG2(*call);
+	sdu.seq_no = IPC_GET_ARG3(*call);
+
+	rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	rc = inetping_ev_ops->recv(&sdu);
+	free(sdu.data);
+	async_answer_0(callid, rc);
+}
+
+static void inetping_cb_conn(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)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case INETPING_EV_RECV:
+			inetping_ev_recv(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/printf_core.c
===================================================================
--- uspace/lib/c/generic/io/printf_core.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/io/printf_core.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -283,5 +283,5 @@
 	/* Print leading spaces. */
 	size_t strw = str_length(str);
-	if (precision == 0)
+	if ((precision == 0) || (precision > strw))
 		precision = strw;
 	
@@ -331,5 +331,5 @@
 	/* Print leading spaces. */
 	size_t strw = wstr_length(str);
-	if (precision == 0)
+	if ((precision == 0) || (precision > strw))
 		precision = strw;
 	
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/ipc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -647,9 +647,9 @@
  *
  */
-int ipc_connect_me(int phoneid)
+int ipc_clone_establish(int phoneid)
 {
 	sysarg_t newphid;
-	int res = ipc_call_sync_0_5(phoneid, IPC_M_CONNECT_ME, NULL, NULL,
-	    NULL, NULL, &newphid);
+	int res = ipc_call_sync_0_5(phoneid, IPC_M_CLONE_ESTABLISH, NULL,
+	    NULL, NULL, NULL, &newphid);
 	if (res)
 		return res;
Index: uspace/lib/c/generic/iplink.c
===================================================================
--- uspace/lib/c/generic/iplink.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/generic/iplink.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,187 @@
+/*
+ * 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 libc
+ * @{
+ */
+/**
+ * @file
+ * @brief IP link client stub
+ */
+
+#include <async.h>
+#include <assert.h>
+#include <errno.h>
+#include <inet/iplink.h>
+#include <ipc/iplink.h>
+#include <ipc/services.h>
+#include <loc.h>
+#include <stdlib.h>
+
+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,
+    iplink_t **riplink)
+{
+	iplink_t *iplink = NULL;
+	int rc;
+
+	iplink = calloc(1, sizeof(iplink_t));
+	if (iplink == NULL)
+		return ENOMEM;
+
+	iplink->sess = sess;
+	iplink->ev_ops = ev_ops;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	rc = async_connect_to_me(exch, 0, 0, 0, iplink_cb_conn, iplink);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		goto error;
+
+	*riplink = iplink;
+	return EOK;
+
+error:
+	if (iplink != NULL)
+		free(iplink);
+
+	return rc;
+}
+
+void iplink_close(iplink_t *iplink)
+{
+	/* XXX Synchronize with iplink_cb_conn */
+	free(iplink);
+}
+
+int iplink_send(iplink_t *iplink, iplink_sdu_t *sdu)
+{
+	async_exch_t *exch = async_exchange_begin(iplink->sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, IPLINK_SEND, sdu->lsrc.ipv4,
+	    sdu->ldest.ipv4, &answer);
+	int rc = async_data_write_start(exch, sdu->data, sdu->size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+int iplink_get_mtu(iplink_t *iplink, size_t *rmtu)
+{
+	sysarg_t mtu;
+	async_exch_t *exch = async_exchange_begin(iplink->sess);
+
+	int rc = async_req_0_1(exch, IPLINK_GET_MTU, &mtu);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	*rmtu = mtu;
+	return EOK;
+}
+
+int iplink_addr_add(iplink_t *iplink, iplink_addr_t *addr)
+{
+	async_exch_t *exch = async_exchange_begin(iplink->sess);
+
+	int rc = async_req_1_0(exch, IPLINK_ADDR_ADD, (sysarg_t)addr->ipv4);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int iplink_addr_remove(iplink_t *iplink, iplink_addr_t *addr)
+{
+	async_exch_t *exch = async_exchange_begin(iplink->sess);
+
+	int rc = async_req_1_0(exch, IPLINK_ADDR_REMOVE, (sysarg_t)addr->ipv4);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+static void iplink_ev_recv(iplink_t *iplink, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	iplink_sdu_t sdu;
+
+	sdu.lsrc.ipv4 = IPC_GET_ARG1(*call);
+	sdu.ldest.ipv4 = IPC_GET_ARG2(*call);
+
+	rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	rc = iplink->ev_ops->recv(iplink, &sdu);
+	free(sdu.data);
+	async_answer_0(callid, rc);
+}
+
+static void iplink_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	iplink_t *iplink = (iplink_t *)arg;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case IPLINK_EV_RECV:
+			iplink_ev_recv(iplink, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/iplink_srv.c
===================================================================
--- uspace/lib/c/generic/iplink_srv.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/generic/iplink_srv.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,193 @@
+/*
+ * 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 libc
+ * @{
+ */
+/**
+ * @file
+ * @brief IP link server stub
+ */
+#include <errno.h>
+#include <ipc/iplink.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <inet/iplink_srv.h>
+
+static void iplink_get_mtu_srv(iplink_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	size_t mtu;
+
+	rc = srv->ops->get_mtu(srv, &mtu);
+	async_answer_1(callid, rc, mtu);
+}
+
+static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	iplink_srv_addr_t addr;
+
+	addr.ipv4 = IPC_GET_ARG1(*call);
+
+	rc = srv->ops->addr_add(srv, &addr);
+	async_answer_0(callid, rc);
+}
+
+static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	iplink_srv_addr_t addr;
+
+	addr.ipv4 = IPC_GET_ARG1(*call);
+
+	rc = srv->ops->addr_remove(srv, &addr);
+	async_answer_0(callid, rc);
+}
+
+static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	iplink_srv_sdu_t sdu;
+	int rc;
+
+	sdu.lsrc.ipv4 = IPC_GET_ARG1(*call);
+	sdu.ldest.ipv4 = IPC_GET_ARG2(*call);
+
+	rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	rc = srv->ops->send(srv, &sdu);
+	free(sdu.data);
+	async_answer_0(callid, rc);
+}
+
+void iplink_srv_init(iplink_srv_t *srv)
+{
+	fibril_mutex_initialize(&srv->lock);
+	srv->connected = false;
+	srv->ops = NULL;
+	srv->arg = NULL;
+	srv->client_sess = NULL;
+}
+
+int iplink_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	iplink_srv_t *srv = (iplink_srv_t *)arg;
+	int rc;
+
+	fibril_mutex_lock(&srv->lock);
+	if (srv->connected) {
+		fibril_mutex_unlock(&srv->lock);
+		async_answer_0(iid, EBUSY);
+		return EBUSY;
+	}
+
+	srv->connected = true;
+	fibril_mutex_unlock(&srv->lock);
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL)
+		return ENOMEM;
+
+	srv->client_sess = sess;
+
+	rc = srv->ops->open(srv);
+	if (rc != EOK)
+		return rc;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			break;
+		}
+
+		switch (method) {
+		case IPLINK_GET_MTU:
+			iplink_get_mtu_srv(srv, callid, &call);
+			break;
+		case IPLINK_SEND:
+			iplink_send_srv(srv, callid, &call);
+			break;
+		case IPLINK_ADDR_ADD:
+			iplink_addr_add_srv(srv, callid, &call);
+			break;
+		case IPLINK_ADDR_REMOVE:
+			iplink_addr_remove_srv(srv, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+
+	return srv->ops->close(srv);
+}
+
+int iplink_ev_recv(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
+{
+	if (srv->client_sess == NULL)
+		return EIO;
+
+	async_exch_t *exch = async_exchange_begin(srv->client_sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, IPLINK_EV_RECV, sdu->lsrc.ipv4,
+	    sdu->ldest.ipv4, &answer);
+	int rc = async_data_write_start(exch, sdu->data, sdu->size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/loader.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -101,5 +101,5 @@
 	
 	if (rc != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return (int) rc;
 	}
@@ -139,5 +139,5 @@
 	
 	if (rc != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return (int) rc;
 	}
@@ -177,5 +177,5 @@
 	
 	if (rc != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return (int) rc;
 	}
@@ -236,5 +236,5 @@
 	
 	if (rc != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return (int) rc;
 	}
@@ -281,5 +281,5 @@
 
 	if (rc != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return (int) rc;
 	}
Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/loc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -246,5 +246,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -285,5 +285,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -352,5 +352,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -401,5 +401,5 @@
 	
 	if (dretval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return dretval;
 	}
@@ -471,5 +471,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -520,5 +520,5 @@
 	
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -683,5 +683,5 @@
 		
 		if (rc != EOK) {
-			async_wait_for(req, NULL);
+			async_forget(req);
 			free(devs);
 			return 0;
@@ -732,5 +732,5 @@
 		
 		if (rc != EOK) {
-			async_wait_for(req, NULL);
+			async_forget(req);
 			free(devs);
 			return 0;
@@ -760,5 +760,5 @@
 	
 	if (rc != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return rc;
 	}
Index: pace/lib/c/generic/net/icmp_api.c
===================================================================
--- uspace/lib/c/generic/net/icmp_api.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,100 +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
- * ICMP application interface implementation.
- * @see icmp_api.h
- */
-
-#include <net/icmp_api.h>
-#include <net/socket_codes.h>
-#include <net/inet.h>
-#include <net/modules.h>
-#include <net/ip_codes.h>
-#include <async.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <ipc/services.h>
-#include <ipc/icmp.h>
-
-/** Requests an echo message.
- *
- * Sends a packet with specified parameters to the target host and waits for the
- * reply upto the given timeout. Blocks the caller until the reply or the
- * timeout occurs.
- *
- * @param[in] sess The ICMP session.
- * @param[in] size	The message data length in bytes.
- * @param[in] timeout	The timeout in milliseconds.
- * @param[in] ttl	The time to live.
- * @param[in] tos	The type of service.
- * @param[in] dont_fragment The value indicating whether the datagram must not
- *			be fragmented. Is used as a MTU discovery.
- * @param[in] addr	The target host address.
- * @param[in] addrlen	The torget host address length.
- * @return		ICMP_ECHO on success.
- * @return		ETIMEOUT if the reply has not arrived before the
- *			timeout.
- * @return		ICMP type of the received error notification.
- * @return		EINVAL if the addrlen parameter is less or equal to
- *			zero.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EPARTY if there was an internal error.
- */
-int
-icmp_echo_msg(async_sess_t *sess, size_t size, mseconds_t timeout, ip_ttl_t ttl,
-    ip_tos_t tos, int dont_fragment, const struct sockaddr *addr,
-    socklen_t addrlen)
-{
-	aid_t message_id;
-	sysarg_t result;
-
-	if (addrlen <= 0)
-		return EINVAL;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	message_id = async_send_5(exch, NET_ICMP_ECHO, size, timeout, ttl,
-	    tos, (sysarg_t) dont_fragment, NULL);
-	
-	/* Send the address */
-	async_data_write_start(exch, addr, (size_t) addrlen);
-	
-	async_exchange_end(exch);
-
-	async_wait_for(message_id, &result);
-	return (int) result;
-}
-
-/** @}
- */
Index: pace/lib/c/generic/net/icmp_common.c
===================================================================
--- uspace/lib/c/generic/net/icmp_common.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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
- * ICMP common interface implementation.
- * @see icmp_common.h
- */
-
-#include <net/modules.h>
-#include <net/icmp_common.h>
-#include <ipc/services.h>
-#include <ipc/icmp.h>
-#include <sys/time.h>
-#include <async.h>
-
-/** Connect to the ICMP module.
- *
- * @return ICMP module session.
- *
- */
-async_sess_t *icmp_connect_module(void)
-{
-	return connect_to_service(SERVICE_ICMP);
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/net/modules.c
===================================================================
--- uspace/lib/c/generic/net/modules.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/net/modules.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -93,4 +93,17 @@
 }
 
+/** Connect to the needed module.
+ *
+ * @param[in] need Needed module service.
+ *
+ * @return Session to the needed service.
+ * @return NULL if the connection timeouted.
+ *
+ */
+static async_sess_t *connect_to_service(services_t need)
+{
+	return service_connect_blocking(EXCHANGE_SERIALIZE, need, 0, 0);
+}
+
 /** Create bidirectional connection with the needed module service and register
  * the message receiver.
@@ -129,49 +142,4 @@
 }
 
-/** Connect to the needed module.
- *
- * @param[in] need Needed module service.
- *
- * @return Session to the needed service.
- * @return NULL if the connection timeouted.
- *
- */
-async_sess_t *connect_to_service(services_t need)
-{
-	return service_connect_blocking(EXCHANGE_SERIALIZE, need, 0, 0);
-}
-
-/** Reply the data to the other party.
- *
- * @param[in] data        The data buffer to be sent.
- * @param[in] data_length The buffer length.
- *
- * @return EOK on success.
- * @return EINVAL if the client does not expect the data.
- * @return EOVERFLOW if the client does not expect all the data.
- *         Only partial data are transfered.
- * @return Other error codes as defined for the
- *         async_data_read_finalize() function.
- *
- */
-int data_reply(void *data, size_t data_length)
-{
-	size_t length;
-	ipc_callid_t callid;
-	
-	/* Fetch the request */
-	if (!async_data_read_receive(&callid, &length))
-		return EINVAL;
-	
-	/* Check the requested data size */
-	if (length < data_length) {
-		async_data_read_finalize(callid, data, length);
-		return EOVERFLOW;
-	}
-	
-	/* Send the data */
-	return async_data_read_finalize(callid, data, data_length);
-}
-
 /** Refresh answer structure and argument count.
  *
Index: pace/lib/c/generic/net/packet.c
===================================================================
--- uspace/lib/c/generic/net/packet.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,451 +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
- *  Packet map and queue implementation.
- *  This file has to be compiled with both the packet server and the client.
- */
-
-#include <assert.h>
-#include <malloc.h>
-#include <mem.h>
-#include <fibril_synch.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/mman.h>
-
-#include <adt/hash_table.h>
-#include <net/packet.h>
-#include <net/packet_header.h>
-
-/** Packet hash table size. */
-#define PACKET_HASH_TABLE_SIZE  128
-
-/** Packet map global data. */
-static struct {
-	/** Safety lock. */
-	fibril_rwlock_t lock;
-	/** Packet map. */
-	hash_table_t packet_map;
-	/** Packet map operations */
-	hash_table_operations_t operations;
-} pm_globals;
-
-typedef struct {
-	link_t link;
-	packet_t *packet;
-} pm_entry_t;
-
-/**
- * Hash function for the packet mapping hash table
- */
-static hash_index_t pm_hash(unsigned long key[])
-{
-	return (hash_index_t) key[0] % PACKET_HASH_TABLE_SIZE;
-}
-
-/**
- * Key compare function for the packet mapping hash table
- */
-static int pm_compare(unsigned long key[], hash_count_t keys, link_t *link)
-{
-	pm_entry_t *entry = list_get_instance(link, pm_entry_t, link);
-	return entry->packet->packet_id == key[0];
-}
-
-/**
- * Remove callback for the packet mapping hash table
- */
-static void pm_remove_callback(link_t *link)
-{
-	pm_entry_t *entry = list_get_instance(link, pm_entry_t, link);
-	free(entry);
-}
-
-/**
- * Wrapper used when destroying the whole table
- */
-static void pm_free_wrapper(link_t *link, void *ignored)
-{
-	pm_entry_t *entry = list_get_instance(link, pm_entry_t, link);
-	free(entry);
-}
-
-
-/** Initializes the packet map.
- *
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- */
-int pm_init(void)
-{
-	int rc = EOK;
-
-	fibril_rwlock_initialize(&pm_globals.lock);
-	
-	fibril_rwlock_write_lock(&pm_globals.lock);
-	
-	pm_globals.operations.hash = pm_hash;
-	pm_globals.operations.compare = pm_compare;
-	pm_globals.operations.remove_callback = pm_remove_callback;
-
-	if (!hash_table_create(&pm_globals.packet_map, PACKET_HASH_TABLE_SIZE, 1,
-	    &pm_globals.operations))
-		rc = ENOMEM;
-	
-	fibril_rwlock_write_unlock(&pm_globals.lock);
-	
-	return rc;
-}
-
-/** Finds the packet mapping.
- *
- * @param[in] packet_id Packet identifier to be found.
- *
- * @return The found packet reference.
- * @return NULL if the mapping does not exist.
- *
- */
-packet_t *pm_find(packet_id_t packet_id)
-{
-	if (!packet_id)
-		return NULL;
-	
-	fibril_rwlock_read_lock(&pm_globals.lock);
-	
-	unsigned long key = packet_id;
-	link_t *link = hash_table_find(&pm_globals.packet_map, &key);
-	
-	packet_t *packet;
-	if (link != NULL) {
-		pm_entry_t *entry =
-		    hash_table_get_instance(link, pm_entry_t, link);
-		packet = entry->packet;
-	} else
-		packet = NULL;
-	
-	fibril_rwlock_read_unlock(&pm_globals.lock);
-	return packet;
-}
-
-/** Adds the packet mapping.
- *
- * @param[in] packet Packet to be remembered.
- *
- * @return EOK on success.
- * @return EINVAL if the packet is not valid.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int pm_add(packet_t *packet)
-{
-	if (!packet_is_valid(packet))
-		return EINVAL;
-	
-	fibril_rwlock_write_lock(&pm_globals.lock);
-	
-	pm_entry_t *entry = malloc(sizeof(pm_entry_t));
-	if (entry == NULL) {
-		fibril_rwlock_write_unlock(&pm_globals.lock);
-		return ENOMEM;
-	}
-	
-	entry->packet = packet;
-	
-	unsigned long key = packet->packet_id;
-	hash_table_insert(&pm_globals.packet_map, &key, &entry->link);
-	
-	fibril_rwlock_write_unlock(&pm_globals.lock);
-	
-	return EOK;
-}
-
-/** Remove the packet mapping
- *
- * @param[in] packet The packet to be removed
- *
- */
-void pm_remove(packet_t *packet)
-{
-	assert(packet_is_valid(packet));
-	
-	fibril_rwlock_write_lock(&pm_globals.lock);
-	
-	unsigned long key = packet->packet_id;
-	hash_table_remove(&pm_globals.packet_map, &key, 1);
-	
-	fibril_rwlock_write_unlock(&pm_globals.lock);
-}
-
-/** Release the packet map. */
-void pm_destroy(void)
-{
-	fibril_rwlock_write_lock(&pm_globals.lock);
-	hash_table_apply(&pm_globals.packet_map, pm_free_wrapper, NULL);
-	hash_table_destroy(&pm_globals.packet_map);
-	/* Leave locked */
-}
-
-/** Add packet to the sorted queue.
- *
- * The queue is sorted in the ascending order.
- * The packet is inserted right before the packets of the same order value.
- *
- * @param[in,out] first First packet of the queue. Sets the first
- *                      packet of the queue. The original first packet
- *                      may be shifted by the new packet.
- * @param[in] packet    Packet to be added.
- * @param[in] order     Packet order value.
- * @param[in] metric    Metric value of the packet.
- *
- * @return EOK on success.
- * @return EINVAL if the first parameter is NULL.
- * @return EINVAL if the packet is not valid.
- *
- */
-int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric)
-{
-	if ((!first) || (!packet_is_valid(packet)))
-		return EINVAL;
-	
-	pq_set_order(packet, order, metric);
-	if (packet_is_valid(*first)) {
-		packet_t *cur = *first;
-		
-		do {
-			if (cur->order < order) {
-				if (cur->next)
-					cur = pm_find(cur->next);
-				else {
-					cur->next = packet->packet_id;
-					packet->previous = cur->packet_id;
-					
-					return EOK;
-				}
-			} else {
-				packet->previous = cur->previous;
-				packet->next = cur->packet_id;
-				
-				cur->previous = packet->packet_id;
-				cur = pm_find(packet->previous);
-				
-				if (cur)
-					cur->next = packet->packet_id;
-				else
-					*first = packet;
-				
-				return EOK;
-			}
-		} while (packet_is_valid(cur));
-	}
-	
-	*first = packet;
-	return EOK;
-}
-
-/** Finds the packet with the given order.
- *
- * @param[in] first	The first packet of the queue.
- * @param[in] order	The packet order value.
- * @return		The packet with the given order.
- * @return		NULL if the first packet is not valid.
- * @return		NULL if the packet is not found.
- */
-packet_t *pq_find(packet_t *packet, size_t order)
-{
-	packet_t *item;
-
-	if (!packet_is_valid(packet))
-		return NULL;
-
-	item = packet;
-	do {
-		if (item->order == order)
-			return item;
-
-		item = pm_find(item->next);
-	} while (item && (item != packet) && packet_is_valid(item));
-
-	return NULL;
-}
-
-/** Inserts packet after the given one.
- *
- * @param[in] packet	The packet in the queue.
- * @param[in] new_packet The new packet to be inserted.
- * @return		EOK on success.
- * @return		EINVAL if etiher of the packets is invalid.
- */
-int pq_insert_after(packet_t *packet, packet_t *new_packet)
-{
-	packet_t *item;
-
-	if (!packet_is_valid(packet) || !packet_is_valid(new_packet))
-		return EINVAL;
-
-	new_packet->previous = packet->packet_id;
-	new_packet->next = packet->next;
-	item = pm_find(packet->next);
-	if (item)
-		item->previous = new_packet->packet_id;
-	packet->next = new_packet->packet_id;
-
-	return EOK;
-}
-
-/** Detach the packet from the queue.
- *
- * @param[in] packet	The packet to be detached.
- * @return		The next packet in the queue. If the packet is the first
- *			one of the queue, this becomes the new first one.
- * @return		NULL if there is no packet left.
- * @return		NULL if the packet is not valid.
- */
-packet_t *pq_detach(packet_t *packet)
-{
-	packet_t *next;
-	packet_t *previous;
-
-	if (!packet_is_valid(packet))
-		return NULL;
-
-	next = pm_find(packet->next);
-	if (next)
-		next->previous = packet->previous;
-	
-	previous = pm_find(packet->previous);
-	if (previous)
-		previous->next = packet->next ;
-	
-	packet->previous = 0;
-	packet->next = 0;
-	return next;
-}
-
-/** Sets the packet order and metric attributes.
- *
- * @param[in] packeti	The packet to be set.
- * @param[in] order	The packet order value.
- * @param[in] metric	The metric value of the packet.
- * @return		EOK on success.
- * @return		EINVAL if the packet is invalid.
- */
-int pq_set_order(packet_t *packet, size_t order, size_t metric)
-{
-	if (!packet_is_valid(packet))
-		return EINVAL;
-
-	packet->order = order;
-	packet->metric = metric;
-	return EOK;
-}
-
-/** Sets the packet order and metric attributes.
- *
- * @param[in] packet	The packet to be set.
- * @param[out] order	The packet order value.
- * @param[out] metric	The metric value of the packet.
- * @return		EOK on success.
- * @return		EINVAL if the packet is invalid.
- */
-int pq_get_order(packet_t *packet, size_t *order, size_t *metric)
-{
-	if (!packet_is_valid(packet))
-		return EINVAL;
-
-	if (order)
-		*order = packet->order;
-
-	if (metric)
-		*metric = packet->metric;
-
-	return EOK;
-}
-
-/** Releases the whole queue.
- *
- * Detaches all packets of the queue and calls the packet_release() for each of
- * them.
- *
- * @param[in] first	The first packet of the queue.
- * @param[in] packet_release The releasing function called for each of the
- *			packets after its detachment.
- */
-void pq_destroy(packet_t *first, void (*packet_release)(packet_t *packet))
-{
-	packet_t *actual;
-	packet_t *next;
-
-	actual = first;
-	while (packet_is_valid(actual)) {
-		next = pm_find(actual->next);
-		actual->next = 0;
-		actual->previous = 0;
-		if(packet_release)
-			packet_release(actual);
-		actual = next;
-	}
-}
-
-/** Returns the next packet in the queue.
- *
- * @param[in] packet	The packet queue member.
- * @return		The next packet in the queue.
- * @return		NULL if there is no next packet.
- * @return		NULL if the packet is not valid.
- */
-packet_t *pq_next(packet_t *packet)
-{
-	if (!packet_is_valid(packet))
-		return NULL;
-
-	return pm_find(packet->next);
-}
-
-/** Returns the previous packet in the queue.
- *
- * @param[in] packet	The packet queue member.
- * @return		The previous packet in the queue.
- * @return		NULL if there is no previous packet.
- * @return		NULL if the packet is not valid.
- */
-packet_t *pq_previous(packet_t *packet)
-{
-	if (!packet_is_valid(packet))
-		return NULL;
-
-	return pm_find(packet->previous);
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/private/async.h
===================================================================
--- uspace/lib/c/generic/private/async.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/generic/private/async.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -81,4 +81,6 @@
 } awaiter_t;
 
+extern void awaiter_initialize(awaiter_t *);
+
 extern void __async_init(void);
 extern void async_insert_timeout(awaiter_t *);
Index: pace/lib/c/include/adt/measured_strings.h
===================================================================
--- uspace/lib/c/include/adt/measured_strings.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,76 +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 with measured length.
- * The structure has been designed for serialization of character strings
- * between modules.
- */
-
-#ifndef LIBC_MEASURED_STRINGS_H_
-#define LIBC_MEASURED_STRINGS_H_
-
-#include <sys/types.h>
-#include <async.h>
-
-/** Type definition of the character string with measured length.
- * @see measured_string
- */
-typedef struct measured_string measured_string_t;
-
-/** Character string with measured length.
- *
- * This structure has been designed for serialization of character strings
- * between modules.
- */
-struct measured_string {
-	/** Character string data. */
-	uint8_t *value;
-	/** Character string length. */
-	size_t length;
-};
-
-extern measured_string_t *measured_string_create_bulk(const uint8_t *, size_t);
-extern measured_string_t *measured_string_copy(measured_string_t *);
-
-extern int measured_strings_receive(measured_string_t **, uint8_t **, size_t);
-extern int measured_strings_reply(const measured_string_t *, size_t);
-
-extern int measured_strings_return(async_exch_t *, measured_string_t **,
-    uint8_t **, size_t);
-extern int measured_strings_send(async_exch_t *, const measured_string_t *,
-    size_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/include/async.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -139,4 +139,5 @@
 extern void async_wait_for(aid_t, sysarg_t *);
 extern int async_wait_timeout(aid_t, sysarg_t *, suseconds_t);
+extern void async_forget(aid_t);
 
 extern fid_t async_new_connection(task_id_t, sysarg_t, ipc_callid_t,
@@ -320,5 +321,5 @@
     sysarg_t *, sysarg_t *);
 
-extern async_sess_t *async_connect_me(exch_mgmt_t, async_exch_t *);
+extern async_sess_t *async_clone_establish(exch_mgmt_t, async_exch_t *);
 extern async_sess_t *async_connect_me_to(exch_mgmt_t, async_exch_t *, sysarg_t,
     sysarg_t, sysarg_t);
Index: uspace/lib/c/include/inet/inet.h
===================================================================
--- uspace/lib/c/include/inet/inet.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/include/inet/inet.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,69 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_INET_H_
+#define LIBC_INET_INET_H_
+
+#include <sys/types.h>
+
+#define INET_TTL_MAX 255
+
+typedef struct {
+	uint32_t ipv4;
+} inet_addr_t;
+
+typedef struct {
+	inet_addr_t src;
+	inet_addr_t dest;
+	uint8_t tos;
+	void *data;
+	size_t size;
+} inet_dgram_t;
+
+typedef struct {
+	int (*recv)(inet_dgram_t *);
+} inet_ev_ops_t;
+
+typedef enum {
+	INET_DF = 1
+} inet_df_t;
+
+extern int inet_init(uint8_t, inet_ev_ops_t *);
+extern int inet_send(inet_dgram_t *, uint8_t, inet_df_t);
+extern int inet_get_srcaddr(inet_addr_t *, uint8_t, inet_addr_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/inetcfg.h
===================================================================
--- uspace/lib/c/include/inet/inetcfg.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/include/inet/inetcfg.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,95 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_INETCFG_H_
+#define LIBC_INET_INETCFG_H_
+
+#include <inet/inet.h>
+#include <sys/types.h>
+
+/** Network address */
+typedef struct {
+	/** Address */
+	uint32_t ipv4;
+	/** Number of valid bits in @c ipv4 */
+	int bits;
+} inet_naddr_t;
+
+/** Address object info */
+typedef struct {
+	/** Network address */
+	inet_naddr_t naddr;
+	/** Link service ID */
+	sysarg_t ilink;
+	/** Address object name */
+	char *name;
+} inet_addr_info_t;
+
+/** IP link info */
+typedef struct {
+	/** Link service name */
+	char *name;
+	/** Default MTU */
+	size_t def_mtu;
+} inet_link_info_t;
+
+/** Static route info */
+typedef struct {
+	/** Destination network address */
+	inet_naddr_t dest;
+	/** Router address */
+	inet_addr_t router;
+	/** Static route name */
+	char *name;
+} inet_sroute_info_t;
+
+extern int inetcfg_init(void);
+extern int inetcfg_addr_create_static(const char *, inet_naddr_t *, sysarg_t, sysarg_t *);
+extern int inetcfg_addr_delete(sysarg_t);
+extern int inetcfg_addr_get(sysarg_t, inet_addr_info_t *);
+extern int inetcfg_addr_get_id(const char *, sysarg_t, sysarg_t *);
+extern int inetcfg_get_addr_list(sysarg_t **, size_t *);
+extern int inetcfg_get_link_list(sysarg_t **, size_t *);
+extern int inetcfg_get_sroute_list(sysarg_t **, size_t *);
+extern int inetcfg_link_get(sysarg_t, inet_link_info_t *);
+extern int inetcfg_sroute_get(sysarg_t, inet_sroute_info_t *);
+extern int inetcfg_sroute_get_id(const char *, sysarg_t *);
+extern int inetcfg_sroute_create(const char *, inet_naddr_t *, inet_addr_t *,
+    sysarg_t *);
+extern int inetcfg_sroute_delete(sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/inetping.h
===================================================================
--- uspace/lib/c/include/inet/inetping.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/include/inet/inetping.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,61 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_INETPING_H_
+#define LIBC_INET_INETPING_H_
+
+#include <inet/inet.h>
+#include <sys/types.h>
+
+typedef struct {
+	inet_addr_t src;
+	inet_addr_t dest;
+	uint16_t seq_no;
+	void *data;
+	size_t size;
+} inetping_sdu_t;
+
+typedef struct inetping_ev_ops {
+	int (*recv)(inetping_sdu_t *);
+} inetping_ev_ops_t;
+
+extern int inetping_init(inetping_ev_ops_t *);
+extern int inetping_send(inetping_sdu_t *);
+extern int inetping_get_srcaddr(inet_addr_t *, inet_addr_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/iplink.h
===================================================================
--- uspace/lib/c/include/inet/iplink.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/include/inet/iplink.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,78 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_IPLINK_H_
+#define LIBC_INET_IPLINK_H_
+
+#include <async.h>
+#include <sys/types.h>
+
+struct iplink_ev_ops;
+
+typedef struct {
+	async_sess_t *sess;
+	struct iplink_ev_ops *ev_ops;
+} iplink_t;
+
+typedef struct {
+	uint32_t ipv4;
+} iplink_addr_t;
+
+/** IP link Service Data Unit */
+typedef struct {
+	/** Local source address */
+	iplink_addr_t lsrc;
+	/** Local destination address */
+	iplink_addr_t ldest;
+	/** Serialized IP packet */
+	void *data;
+	/** Size of @c data in bytes */
+	size_t size;
+} iplink_sdu_t;
+
+typedef struct iplink_ev_ops {
+	int (*recv)(iplink_t *, iplink_sdu_t *);
+} iplink_ev_ops_t;
+
+extern int iplink_open(async_sess_t *, iplink_ev_ops_t *, iplink_t **);
+extern void iplink_close(iplink_t *);
+extern int iplink_send(iplink_t *, iplink_sdu_t *);
+extern int iplink_addr_add(iplink_t *, iplink_addr_t *);
+extern int iplink_addr_remove(iplink_t *, iplink_addr_t *);
+extern int iplink_get_mtu(iplink_t *, size_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/iplink_srv.h
===================================================================
--- uspace/lib/c/include/inet/iplink_srv.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/include/inet/iplink_srv.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,86 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_IPLINK_SRV_H_
+#define LIBC_INET_IPLINK_SRV_H_
+
+#include <async.h>
+#include <fibril_synch.h>
+#include <bool.h>
+#include <sys/types.h>
+
+struct iplink_ops;
+
+typedef struct {
+	fibril_mutex_t lock;
+	bool connected;
+	struct iplink_ops *ops;
+	void *arg;
+	async_sess_t *client_sess;
+} iplink_srv_t;
+
+typedef struct {
+	uint32_t ipv4;
+} iplink_srv_addr_t;
+
+/** IP link Service Data Unit */
+typedef struct {
+	/** Local source address */
+	iplink_srv_addr_t lsrc;
+	/** Local destination address */
+	iplink_srv_addr_t ldest;
+	/** Serialized IP packet */
+	void *data;
+	/** Size of @c data in bytes */
+	size_t size;
+} iplink_srv_sdu_t;
+
+typedef struct iplink_ops {
+	int (*open)(iplink_srv_t *);
+	int (*close)(iplink_srv_t *);
+	int (*send)(iplink_srv_t *, iplink_srv_sdu_t *);
+	int (*get_mtu)(iplink_srv_t *, size_t *);
+	int (*addr_add)(iplink_srv_t *, iplink_srv_addr_t *);
+	int (*addr_remove)(iplink_srv_t *, iplink_srv_addr_t *);
+} iplink_ops_t;
+
+extern void iplink_srv_init(iplink_srv_t *);
+
+extern int iplink_conn(ipc_callid_t, ipc_call_t *, void *);
+extern int iplink_ev_recv(iplink_srv_t *, iplink_srv_sdu_t *);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/c/include/ipc/arp.h
===================================================================
--- uspace/lib/c/include/ipc/arp.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,82 +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
- * ARP module messages.
- * @see arp_interface.h
- */
-
-#ifndef LIBC_ARP_MESSAGES_
-#define LIBC_ARP_MESSAGES_
-
-#include <ipc/net.h>
-
-/** ARP module messages. */
-typedef enum {
-	/** Clean cache message.
-	 * @see arp_clean_cache()
-	 */
-	NET_ARP_CLEAN_CACHE = NET_ARP_FIRST,
-	/** Clear address cache message.
-	 * @see arp_clear_address_msg()
-	 */
-	NET_ARP_CLEAR_ADDRESS,
-	/** Clear device cache message.
-	 * @see arp_clear_device_req()
-	 */
-	NET_ARP_CLEAR_DEVICE,
-	/** New device message.
-	 * @see arp_device_req()
-	 */
-	NET_ARP_DEVICE,
-	/** Address translation message.
-	 * @see arp_translate_req()
-	 */
-	NET_ARP_TRANSLATE
-} arp_messages;
-
-/** @name ARP specific message parameters definitions */
-/*@{*/
-
-/** Return the protocol service message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define ARP_GET_NETIF(call) ((services_t) IPC_GET_ARG2(call))
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/ipc/icmp.h
===================================================================
--- uspace/lib/c/include/ipc/icmp.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,139 +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
- * ICMP module messages.
- * @see icmp_remote.h
- */
-
-#ifndef LIBC_ICMP_MESSAGES_
-#define LIBC_ICMP_MESSAGES_
-
-#include <ipc/net.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <net/icmp_codes.h>
-
-/** ICMP module messages. */
-typedef enum {
-	/** Send echo request. @see icmp_echo() */
-	NET_ICMP_ECHO = NET_ICMP_FIRST,
-	
-	/**
-	 * Send destination unreachable error message.
-	 * @see icmp_destination_unreachable_msg()
-	 */
-	NET_ICMP_DEST_UNREACH,
-	
-	/**
-	 * Send source quench error message.
-	 * @see icmp_source_quench_msg()
-	 */
-	NET_ICMP_SOURCE_QUENCH,
-	
-	/**
-	 * Send time exceeded error message.
-	 * @see icmp_time_exceeded_msg()
-	 */
-	NET_ICMP_TIME_EXCEEDED,
-	
-	/**
-	 * Send parameter problem error message.
-	 * @see icmp_parameter_problem_msg()
-	 */
-	NET_ICMP_PARAMETERPROB
-} icmp_messages_t;
-
-/** @name ICMP specific message parameters definitions */
-/*@{*/
-
-/** Return the ICMP code message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define ICMP_GET_CODE(call)  ((icmp_code_t) IPC_GET_ARG1(call))
-
-/** Return the ICMP link MTU message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define ICMP_GET_MTU(call)  ((icmp_param_t) IPC_GET_ARG3(call))
-
-/** Return the pointer message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define ICMP_GET_POINTER(call)  ((icmp_param_t) IPC_GET_ARG3(call))
-
-/** Return the size message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define ICMP_GET_SIZE(call)  ((size_t) IPC_GET_ARG1(call))
-
-/** Return the timeout message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define ICMP_GET_TIMEOUT(call)  ((suseconds_t) IPC_GET_ARG2(call))
-
-/** Return the time to live message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define ICMP_GET_TTL(call)  ((ip_ttl_t) IPC_GET_ARG3(call))
-
-/** Return the type of service message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define ICMP_GET_TOS(call)  ((ip_tos_t) IPC_GET_ARG4(call))
-
-/** Return the dont fragment message parameter.
- *
- * @param[in] call Message call structure.
- */
-#define ICMP_GET_DONT_FRAGMENT(call)  ((int) IPC_GET_ARG5(call))
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/ipc/il.h
===================================================================
--- uspace/lib/c/include/ipc/il.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,90 +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
- * Internetwork layer modules messages.
- * @see il_remote.h
- * @see ip_interface.h
- */
-
-#ifndef LIBC_IL_MESSAGES_H_
-#define LIBC_IL_MESSAGES_H_
-
-#include <ipc/net.h>
-
-/** Internet layer modules messages. */
-typedef enum {
-	/** Device state changed message.
-	 * @see il_device_state_msg()
-	 */
-	NET_IL_DEVICE_STATE = NET_IL_FIRST,
-	
-	/** Device MTU changed message.
-	 * @see il_mtu_changed_msg()
-	 */
-	NET_IL_MTU_CHANGED,
-	
-	/**
-	 * Device address changed message
-	 * @see il_addr_changed_msg()
-	 */
-	NET_IL_ADDR_CHANGED,
-
-	/** Packet received message.
-	 * @see il_received_msg()
-	 */
-	NET_IL_RECEIVED
-} il_messages;
-
-/** @name Internetwork layer specific message parameters definitions */
-/*@{*/
-
-/** Return the protocol number message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IL_GET_PROTO(call)  ((int) IPC_GET_ARG1(call))
-
-/** Return the registering service message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IL_GET_SERVICE(call)  ((services_t) IPC_GET_ARG2(call))
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/ipc/inet.h
===================================================================
--- uspace/lib/c/include/ipc/inet.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/include/ipc/inet.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,94 @@
+/*
+ * 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 libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_INET_H_
+#define LIBC_IPC_INET_H_
+
+#include <ipc/common.h>
+
+/** Inet ports */
+typedef enum {
+	/** Default port */
+	INET_PORT_DEFAULT = 1,
+	/** Configuration port */
+	INET_PORT_CFG,
+	/** Ping service port */
+	INET_PORT_PING
+} inet_port_t;
+
+/** Requests on Inet default port */
+typedef enum {
+	INET_CALLBACK_CREATE = IPC_FIRST_USER_METHOD,
+	INET_GET_SRCADDR,
+	INET_SEND,
+	INET_SET_PROTO
+} inet_request_t;
+
+/** Events on Inet default port */
+typedef enum {
+	INET_EV_RECV = IPC_FIRST_USER_METHOD
+} inet_event_t;
+
+/** Requests on Inet configuration port */
+typedef enum {
+	INETCFG_ADDR_CREATE_STATIC = IPC_FIRST_USER_METHOD,
+	INETCFG_ADDR_DELETE,
+	INETCFG_ADDR_GET,
+	INETCFG_ADDR_GET_ID,
+	INETCFG_GET_ADDR_LIST,
+	INETCFG_GET_LINK_LIST,
+	INETCFG_GET_SROUTE_LIST,
+	INETCFG_LINK_GET,
+	INETCFG_SROUTE_CREATE,
+	INETCFG_SROUTE_DELETE,
+	INETCFG_SROUTE_GET,
+	INETCFG_SROUTE_GET_ID
+} inetcfg_request_t;
+
+/** Events on Inet ping port */
+typedef enum {
+	INETPING_EV_RECV = IPC_FIRST_USER_METHOD
+} inetping_event_t;
+
+/** Requests on Inet ping port */
+typedef enum {
+	INETPING_SEND = IPC_FIRST_USER_METHOD,
+	INETPING_GET_SRCADDR
+} inetping_request_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: pace/lib/c/include/ipc/ip.h
===================================================================
--- uspace/lib/c/include/ipc/ip.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,141 +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
- * IP module messages.
- * @see ip_interface.h
- */
-
-#ifndef LIBC_IP_MESSAGES_H_
-#define LIBC_IP_MESSAGES_H_
-
-#include <ipc/net.h>
-#include <net/in.h>
-#include <net/ip_codes.h>
-
-/** IP module messages. */
-typedef enum {
-	/** New device message.
-	 * @see ip_device_req()
-	 */
-	NET_IP_DEVICE = NET_IP_FIRST,
-	
-	/** Adds the routing entry.
-	 * @see ip_add_route()
-	 */
-	NET_IP_ADD_ROUTE,
-	
-	/** Gets the actual route information.
-	 * @see ip_get_route()
-	 */
-	NET_IP_GET_ROUTE,
-	
-	/** Processes the received error notification.
-	 * @see ip_received_error_msg()
-	 */
-	NET_IP_RECEIVED_ERROR,
-	
-	/** Sets the default gateway.
-	 * @see ip_set_default_gateway()
-	 */
-	NET_IP_SET_GATEWAY,
-	
-	/** Packet size message.
-	 * @see ip_packet_size_req()
-	 */
-	NET_IP_PACKET_SPACE,
-	
-	/** Packet send message.
-	 * @see ip_send_msg()
-	 */
-	NET_IP_SEND
-} ip_messages;
-
-/** @name IP specific message parameters definitions */
-/*@{*/
-
-/** Return the address message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IP_GET_ADDRESS(call) \
-	({ \
-		in_addr_t addr; \
-		addr.s_addr = IPC_GET_ARG3(call); \
-		addr; \
-	})
-
-/** Return the gateway message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IP_GET_GATEWAY(call) \
-	({ \
-		in_addr_t addr; \
-		addr.s_addr = IPC_GET_ARG2(call); \
-		addr; \
-	})
-
-/** Set the header length in the message answer.
- *
- * @param[out] answer Message answer structure.
- *
- */
-#define IP_SET_HEADERLEN(answer, value)  IPC_SET_ARG2(answer, (sysarg_t) (value))
-
-/** Return the network mask message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IP_GET_NETMASK(call) \
-	({ \
-		in_addr_t addr; \
-		addr.s_addr = IPC_GET_ARG4(call); \
-		addr; \
-	})
-
-/** Return the protocol message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IP_GET_PROTOCOL(call)  ((ip_protocol_t) IPC_GET_ARG1(call))
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/include/ipc/ipc.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -254,7 +254,7 @@
     sysarg_t, sysarg_t, void *, ipc_async_callback_t, bool);
 
+extern int ipc_clone_establish(int);
 extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, task_id_t *,
     sysarg_t *);
-extern int ipc_connect_me(int);
 extern int ipc_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
 extern int ipc_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
Index: uspace/lib/c/include/ipc/iplink.h
===================================================================
--- uspace/lib/c/include/ipc/iplink.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/lib/c/include/ipc/iplink.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,55 @@
+/*
+ * 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 libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_IPLINK_H_
+#define LIBC_IPC_IPLINK_H_
+
+#include <ipc/common.h>
+
+typedef enum {
+	IPLINK_GET_MTU = IPC_FIRST_USER_METHOD,
+	IPLINK_SEND,
+	IPLINK_ADDR_ADD,
+	IPLINK_ADDR_REMOVE
+} iplink_request_t;
+
+typedef enum {
+	IPLINK_EV_RECV = IPC_FIRST_USER_METHOD
+} iplink_event_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: pace/lib/c/include/ipc/net.h
===================================================================
--- uspace/lib/c/include/ipc/net.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,389 +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 libcipc
- *  @{
- */
-
-/** @file
- *  Networking common message definitions.
- */
-
-#ifndef LIBC_NET_MESSAGES_H_
-#define LIBC_NET_MESSAGES_H_
-
-#include <ipc/services.h>
-#include <net/device.h>
-#include <net/packet.h>
-
-/** Return a value indicating whether the value is in the interval.
- *
- * @param[in] item            Value to be checked.
- * @param[in] first_inclusive First value in the interval inclusive.
- * @param[in] last_exclusive  First value after the interval.
- *
- */
-#define IS_IN_INTERVAL(item, first_inclusive, last_exclusive) \
-	(((item) >= (first_inclusive)) && ((item) < (last_exclusive)))
-
-/** @name Networking message counts */
-/*@{*/
-
-#define NET_ARP_COUNT     5   /**< Number of ARP messages. */
-#define NET_ETH_COUNT     0   /**< Number of Ethernet messages. */
-#define NET_ICMP_COUNT    6   /**< Number of ICMP messages. */
-#define NET_IL_COUNT      6   /**< Number of inter-network messages. */
-#define NET_IP_COUNT      4   /**< Number of IP messages. */
-#define NET_NET_COUNT     3   /**< Number of general networking messages. */
-#define NET_NETIF_COUNT   6   /**< Number of network interface driver messages. */
-#define NET_NIL_COUNT     7   /**< Number of network interface layer messages. */
-#define NET_PACKET_COUNT  5   /**< Number of packet management system messages. */
-#define NET_SOCKET_COUNT  14  /**< Number of socket messages. */
-#define NET_TCP_COUNT     0   /**< Number of TCP messages. */
-#define NET_TL_COUNT      1   /**< Number of transport layer messages. */
-#define NET_UDP_COUNT     0   /**< Number of UDP messages. */
-
-/*@}*/
-
-/** @name Networking message intervals
- */
-/*@{*/
-
-
-/** First networking message. */
-#define NET_FIRST  2000
-
-/** First network interface layer message. */
-#define NET_NETIF_FIRST  NET_FIRST
-
-/** Last network interface layer message. */
-#define NET_NETIF_LAST  (NET_NETIF_FIRST + NET_NETIF_COUNT)
-
-/** First general networking message. */
-#define NET_NET_FIRST  (NET_NETIF_LAST + 0)
-
-/** Last general networking message. */
-#define NET_NET_LAST  (NET_NET_FIRST + NET_NET_COUNT)
-
-/** First network interface layer message. */
-#define NET_NIL_FIRST  (NET_NET_LAST + 0)
-
-/** Last network interface layer message. */
-#define NET_NIL_LAST  (NET_NIL_FIRST + NET_NIL_COUNT)
-
-/** First Ethernet message. */
-#define NET_ETH_FIRST  (NET_NIL_LAST + 0)
-
-/** Last Ethernet message. */
-#define NET_ETH_LAST  (NET_ETH_FIRST + NET_ETH_COUNT)
-
-/** First inter-network message. */
-#define NET_IL_FIRST  (NET_ETH_LAST + 0)
-
-/** Last inter-network message. */
-#define NET_IL_LAST  (NET_IL_FIRST + NET_IL_COUNT)
-
-/** First IP message. */
-#define NET_IP_FIRST  (NET_IL_LAST + 0)
-
-/** Last IP message. */
-#define NET_IP_LAST  (NET_IP_FIRST + NET_IP_COUNT)
-
-/** First ARP message. */
-#define NET_ARP_FIRST  (NET_IP_LAST + 0)
-
-/** Last ARP message. */
-#define NET_ARP_LAST  (NET_ARP_FIRST + NET_ARP_COUNT)
-
-/** First ICMP message. */
-#define NET_ICMP_FIRST  (NET_ARP_LAST + 0)
-
-/** Last ICMP message. */
-#define NET_ICMP_LAST  (NET_ICMP_FIRST + NET_ICMP_COUNT)
-
-/** First ICMP message. */
-#define NET_TL_FIRST  (NET_ICMP_LAST + 0)
-
-/** Last ICMP message. */
-#define NET_TL_LAST  (NET_TL_FIRST + NET_TL_COUNT)
-
-/** First UDP message. */
-#define NET_UDP_FIRST  (NET_TL_LAST + 0)
-
-/** Last UDP message. */
-#define NET_UDP_LAST  (NET_UDP_FIRST + NET_UDP_COUNT)
-
-/** First TCP message. */
-#define NET_TCP_FIRST  (NET_UDP_LAST + 0)
-
-/** Last TCP message. */
-#define NET_TCP_LAST  (NET_TCP_FIRST + NET_TCP_COUNT)
-
-/** First socket message. */
-#define NET_SOCKET_FIRST  (NET_TCP_LAST + 0)
-
-/** Last socket message. */
-#define NET_SOCKET_LAST  (NET_SOCKET_FIRST + NET_SOCKET_COUNT)
-
-/** First packet management system message. */
-#define NET_PACKET_FIRST  (NET_SOCKET_LAST + 0)
-
-/** Last packet management system message. */
-#define NET_PACKET_LAST  (NET_PACKET_FIRST + NET_PACKET_COUNT)
-
-/** Last networking message. */
-#define NET_LAST  NET_PACKET_LAST
-
-/** Number of networking messages. */
-#define NET_COUNT  (NET_LAST - NET_FIRST)
-
-/** Check if the IPC call is a generic networking message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_FIRST, NET_LAST)
-
-/** Check if the IPC call is an ARP message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_ARP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_ARP_FIRST, NET_ARP_LAST)
-
-/** Check if the IPC call is an Ethernet message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_ETH_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_ETH_FIRST, NET_ETH_LAST)
-
-/** Check if the IPC call is an ICMP message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_ICMP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_ICMP_FIRST, NET_ICMP_LAST)
-
-/** Check if the IPC call is an inter-network layer message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_IL_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_IL_FIRST, NET_IL_LAST)
-
-/** Check if the IPC call is an IP message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_IP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_IP_FIRST, NET_IP_LAST)
-
-/** Check if the IPC call is a generic networking message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_NET_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_NET_FIRST, NET_NET_LAST)
-
-/** Check if the IPC call is a network interface layer message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_NIL_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_NIL_FIRST, NET_NIL_LAST)
-
-/** Check if the IPC call is a packet manaagement system message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_PACKET_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_PACKET_FIRST, NET_PACKET_LAST)
-
-/** Check if the IPC call is a socket message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_SOCKET_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_SOCKET_FIRST, NET_SOCKET_LAST)
-
-/** Check if the IPC call is a TCP message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_TCP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_TCP_FIRST, NET_TCP_LAST)
-
-/** Check if the IPC call is a transport layer message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_TL_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_TL_FIRST, NET_TL_LAST)
-
-/** Check if the IPC call is a UDP message.
- *
- * @param[in] call IPC call to be checked.
- *
- */
-#define IS_NET_UDP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_UDP_FIRST, NET_UDP_LAST)
-
-/*@}*/
-
-/** @name Networking specific message arguments definitions */
-/*@{*/
-
-/** Return the device identifier message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_DEVICE(call)  ((nic_device_id_t) IPC_GET_ARG1(call))
-
-/** Return the packet identifier message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_PACKET(call)  ((packet_id_t) IPC_GET_ARG2(call))
-
-/** Return the count message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_COUNT(call)  ((size_t) IPC_GET_ARG2(call))
-
-/** Return the device state message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_STATE(call)  ((nic_device_state_t) IPC_GET_ARG2(call))
-
-/** Return the device handle argument
- *
- * @param[in] call Message call structure
- *
- */
-#define IPC_GET_DEVICE_HANDLE(call)  ((service_id_t) IPC_GET_ARG2(call))
-
-/** Return the device driver service message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_SERVICE(call)  ((services_t) IPC_GET_ARG3(call))
-
-/** Return the target service message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_TARGET(call)  ((services_t) IPC_GET_ARG3(call))
-
-/** Return the sender service message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_SENDER(call)  ((services_t) IPC_GET_ARG3(call))
-
-/** Return the maximum transmission unit message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_MTU(call)  ((size_t) IPC_GET_ARG3(call))
-
-/** Return the error service message argument.
- &
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_ERROR(call)  ((services_t) IPC_GET_ARG4(call))
-
-/** Set the device identifier in the message answer.
- *
- * @param[out] answer Message answer structure.
- * @param[in]  value  Value to set.
- *
- */
-#define IPC_SET_DEVICE(answer, value)  IPC_SET_ARG1(answer, (sysarg_t) (value))
-
-/** Set the minimum address length in the message answer.
- *
- * @param[out] answer Message answer structure.
- * @param[in]  value  Value to set.
- *
- */
-#define IPC_SET_ADDR(answer, value)  IPC_SET_ARG1(answer, (sysarg_t) (value))
-
-/** Set the minimum prefix size in the message answer.
- *
- * @param[out] answer Message answer structure.
- * @param[in]  value  Value to set.
- *
- */
-#define IPC_SET_PREFIX(answer, value)  IPC_SET_ARG2(answer, (sysarg_t) (value))
-
-/** Set the maximum content size in the message answer.
- *
- * @param[out] answer Message answer structure.
- * @param[in]  value  Value to set.
- *
- */
-#define IPC_SET_CONTENT(answer, value)  IPC_SET_ARG3(answer, (sysarg_t) (value))
-
-/** Set the minimum suffix size in the message answer.
- *
- * @param[out] answer Message answer structure.
- * @param[in]  value  Value to set.
- *
- */
-#define IPC_SET_SUFFIX(answer, value)  IPC_SET_ARG4(answer, (sysarg_t) (value))
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/ipc/net_net.h
===================================================================
--- uspace/lib/c/include/ipc/net_net.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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
- * Networking subsystem central module messages.
- * @see net_interface.h
- */
-
-#ifndef LIBC_NET_NET_MESSAGES_H_
-#define LIBC_NET_NET_MESSAGES_H_
-
-#include <ipc/net.h>
-
-/** Networking subsystem central module messages. */
-typedef enum {
-	/** Return general configuration
-	 * @see net_get_conf_req()
-	 */
-	NET_NET_GET_CONF = NET_FIRST,
-	/** Return device specific configuration
-	 * @see net_get_device_conf_req()
-	 */
-	NET_NET_GET_DEVICE_CONF,
-	/** Return number of mastered devices */
-	NET_NET_GET_DEVICES_COUNT,
-	/** Return names and device IDs of all devices */
-	NET_NET_GET_DEVICES
-} net_messages;
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/ipc/netif.h
===================================================================
--- uspace/lib/c/include/ipc/netif.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,97 +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
- * Network interface common module messages.
- */
-
-#ifndef LIBC_NETIF_MESSAGES_H_
-#define LIBC_NETIF_MESSAGES_H_
-
-#include <ipc/net.h>
-
-/** Network interface common module messages. */
-typedef enum {
-	/** Probe device message.
-	 * @see netif_probe_req()
-	 */
-	NET_NETIF_PROBE = NET_NETIF_FIRST,
-	
-	/** Send packet message.
-	 * @see netif_send_msg()
-	 */
-	NET_NETIF_SEND,
-	
-	/** Start device message.
-	 * @see netif_start_req()
-	 */
-	NET_NETIF_START,
-	
-	/** Get device usage statistics message.
-	 * @see netif_stats_req()
-	 */
-	NET_NETIF_STATS,
-	
-	/** Stop device message.
-	 * @see netif_stop_req()
-	 */
-	NET_NETIF_STOP,
-	
-	/** Get device address message.
-	 * @see netif_get_addr_req()
-	 */
-	NET_NETIF_GET_ADDR,
-} netif_messages;
-
-/** @name Network interface specific message parameters definitions */
-/*@{*/
-
-/** Return the interrupt number message parameter.
- *
- * @param[in] call Mmessage call structure.
- *
- */
-#define NETIF_GET_IRQ(call) ((int) IPC_GET_ARG2(call))
-
-/** Return the input/output address message parameter.
- *
- * @param[in] call Message call structure.
- *
- */
-#define NETIF_GET_IO(call) ((void *) IPC_GET_ARG3(call))
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/ipc/nil.h
===================================================================
--- uspace/lib/c/include/ipc/nil.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,77 +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
- * Network interface layer module messages.
- */
-
-#ifndef LIBC_NIL_MESSAGES_H_
-#define LIBC_NIL_MESSAGES_H_
-
-#include <ipc/net.h>
-
-/** Network interface layer module messages. */
-typedef enum {
-	/** New device or update MTU message.
-	 * @see nil_device_req()
-	 */
-	NET_NIL_DEVICE = NET_NIL_FIRST,
-	/** Send packet queue message.
-	 * @see nil_send_msg()
-	 */
-	NET_NIL_SEND,
-	/** Packet size message.
-	 * @see nil_packet_size_req()
-	 */
-	NET_NIL_PACKET_SPACE,
-	/** Device local hardware address message.
-	 * @see nil_get_addr()
-	 */
-	NET_NIL_ADDR,
-	/** Device broadcast hardware address message.
-	 * @see nil_get_broadcast_addr()
-	 */
-	NET_NIL_BROADCAST_ADDR
-} nil_messages;
-
-/** @name Network interface layer specific message parameters definitions */
-/*@{*/
-
-/** Return the protocol service message parameter. */
-#define NIL_GET_PROTO(call)  ((services_t) IPC_GET_ARG2(call))
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/ipc/packet.h
===================================================================
--- uspace/lib/c/include/ipc/packet.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,92 +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
- *  Packet server module messages.
- */
-
-#ifndef LIBC_PACKET_MESSAGES_
-#define LIBC_PACKET_MESSAGES_
-
-#include <ipc/net.h>
-
-/** Packet server module messages. */
-typedef enum {
-	/** Create packet message with specified content length.
-	 * @see packet_get_1()
-	 */
-	NET_PACKET_CREATE_1 = NET_PACKET_FIRST,
-	
-	/**
-	 * Create packet message with specified address length, prefix, content
-	 * and suffix.
-	 * @see packet_get_4()
-	 */
-	NET_PACKET_CREATE_4,
-	
-	/** Get packet message.
-	 * @see packet_return() */
-	NET_PACKET_GET,
-	
-	/** Get packet size message.
-	 * @see packet_translate()
-	 */
-	NET_PACKET_GET_SIZE,
-	
-	/** Release packet message.
-	 * @see pq_release()
-	 */
-	NET_PACKET_RELEASE
-} packet_messages;
-
-/** Return the protocol service message parameter. */
-#define ARP_GET_PROTO(call)  ((services_t) IPC_GET_ARG2(call))
-
-/** Return the packet identifier message parameter. */
-#define IPC_GET_ID(call)  ((packet_id_t) IPC_GET_ARG1(call))
-
-/** Return the maximal content length message parameter. */
-#define IPC_GET_CONTENT(call)  ((size_t) IPC_GET_ARG1(call))
-
-/** Return the maximal address length message parameter. */
-#define IPC_GET_ADDR_LEN(call)  ((size_t) IPC_GET_ARG2(call))
-
-/** Return the maximal prefix length message parameter. */
-#define IPC_GET_PREFIX(call)  ((size_t) IPC_GET_ARG3(call))
-
-/** Return the maximal suffix length message parameter. */
-#define IPC_GET_SUFFIX(call)  ((size_t) IPC_GET_ARG4(call))
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/include/ipc/services.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -48,13 +48,11 @@
 	SERVICE_IRC        = FOURCC('i', 'r', 'c', ' '),
 	SERVICE_CLIPBOARD  = FOURCC('c', 'l', 'i', 'p'),
-	SERVICE_NETWORKING = FOURCC('n', 'e', 't', ' '),
-	SERVICE_ETHERNET   = FOURCC('e', 't', 'h', ' '),
-	SERVICE_NILDUMMY   = FOURCC('n', 'i', 'l', 'd'),
-	SERVICE_IP         = FOURCC('i', 'p', 'v', '4'),
-	SERVICE_ARP        = FOURCC('a', 'r', 'p', ' '),
-	SERVICE_ICMP       = FOURCC('i', 'c', 'm', 'p'),
 	SERVICE_UDP        = FOURCC('u', 'd', 'p', ' '),
 	SERVICE_TCP        = FOURCC('t', 'c', 'p', ' ')
 } services_t;
+
+#define SERVICE_NAME_INET     "net/inet"
+#define SERVICE_NAME_INETCFG  "net/inetcfg"
+#define SERVICE_NAME_INETPING "net/inetping"
 
 #endif
Index: uspace/lib/c/include/ipc/socket.h
===================================================================
--- uspace/lib/c/include/ipc/socket.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/include/ipc/socket.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -38,10 +38,8 @@
 #define LIBC_SOCKET_MESSAGES_H_
 
-#include <ipc/net.h>
-
 /** Socket client messages. */
 typedef enum {
 	/** Creates a new socket. @see socket() */
-	NET_SOCKET = NET_SOCKET_FIRST,
+	NET_SOCKET = IPC_FIRST_USER_METHOD,
 	/** Binds the socket. @see bind() */
 	NET_SOCKET_BIND,
Index: pace/lib/c/include/ipc/tl.h
===================================================================
--- uspace/lib/c/include/ipc/tl.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,54 +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
- * Transport layer modules messages.
- * @see tl_interface.h
- */
-
-#ifndef LIBC_TL_MESSAGES_H_
-#define LIBC_TL_MESSAGES_H_
-
-#include <ipc/net.h>
-
-/** Transport layer modules messages. */
-typedef enum {
-	/** Packet received message.
-	 * @see tl_received_msg()
-	 */
-	NET_TL_RECEIVED = NET_TL_FIRST
-} tl_messages;
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/icmp_api.h
===================================================================
--- uspace/lib/c/include/net/icmp_api.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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 libc
- * @{
- */
-
-/** @file
- * ICMP module application interface.
- */
-
-#ifndef LIBC_ICMP_API_H_
-#define LIBC_ICMP_API_H_
-
-#include <net/socket_codes.h>
-#include <net/inet.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <adt/measured_strings.h>
-#include <net/ip_codes.h>
-#include <net/icmp_codes.h>
-#include <net/icmp_common.h>
-#include <async.h>
-
-/** @name ICMP module application interface
- * This interface is used by other application modules.
- */
-/*@{*/
-
-extern int icmp_echo_msg(async_sess_t *, size_t, mseconds_t, ip_ttl_t, ip_tos_t,
-    int, const struct sockaddr *, socklen_t);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/icmp_codes.h
===================================================================
--- uspace/lib/c/include/net/icmp_codes.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,282 +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
- * ICMP types and codes according to the on-line IANA - ICMP Type Numbers
- *
- * http://www.iana.org/assignments/icmp-parameters>
- *
- * cited September 14 2009.
- */
-
-#ifndef LIBC_ICMP_CODES_H_
-#define LIBC_ICMP_CODES_H_
-
-#include <sys/types.h>
-
-/** ICMP type type definition. */
-typedef uint8_t icmp_type_t;
-
-/** ICMP code type definition. */
-typedef uint8_t icmp_code_t;
-
-/** ICMP parameter type definition. */
-typedef uint16_t icmp_param_t;
-
-/** @name ICMP types definitions */
-/*@{*/
-
-/** Echo Reply. */
-#define ICMP_ECHOREPLY		0
-
-/** Destination Unreachable. */
-#define ICMP_DEST_UNREACH	3
-
-/** Source Quench. */
-#define ICMP_SOURCE_QUENCH	4
-
-/** Redirect. */
-#define ICMP_REDIRECT		5
-
-/** Alternate Host Address. */
-#define ICMP_ALTERNATE_ADDR	6
-
-/** Echo Request. */
-#define ICMP_ECHO		8
-
-/** Router Advertisement. */
-#define ICMP_ROUTER_ADV		9
-
-/** Router solicitation. */
-#define ICMP_ROUTER_SOL		10
-
-/** Time Exceeded. */
-#define ICMP_TIME_EXCEEDED	11
-
-/** Parameter Problem. */
-#define ICMP_PARAMETERPROB	12
-
-/** Timestamp Request. */
-#define ICMP_TIMESTAMP		13
-
-/** Timestamp Reply. */
-#define ICMP_TIMESTAMPREPLY	14
-
-/** Information Request. */
-#define ICMP_INFO_REQUEST	15
-
-/** Information Reply. */
-#define ICMP_INFO_REPLY		16
-
-/** Address Mask Request. */
-#define ICMP_ADDRESS		17
-
-/** Address Mask Reply. */
-#define ICMP_ADDRESSREPLY	18
-
-/** Traceroute. */
-#define ICMP_TRACEROUTE		30
-
-/** Datagram Conversion Error. */
-#define ICMP_CONVERSION_ERROR	31
-
-/** Mobile Host Redirect. */
-#define ICMP_REDIRECT_MOBILE	32
-
-/** IPv6 Where-Are-You. */
-#define ICMP_IPV6_WHERE_ARE_YOU	33
-
-/** IPv6 I-Am-Here. */
-#define ICMP_IPV6_I_AM_HERE	34
-
-/** Mobile Registration Request. */
-#define ICMP_MOBILE_REQUEST	35
-
-/** Mobile Registration Reply. */
-#define ICMP_MOBILE_REPLY	36
-
-/** Domain name request. */
-#define ICMP_DN_REQUEST		37
-
-/** Domain name reply. */
-#define ICMP_DN_REPLY		38
-
-/** SKIP. */
-#define ICMP_SKIP		39
-
-/** Photuris. */
-#define ICMP_PHOTURIS		40
-
-/*@}*/
-
-/** @name ICMP_DEST_UNREACH codes definitions
- */
-/*@{*/
-
-/** Network Unreachable. */
-#define ICMP_NET_UNREACH	0
-
-/** Host Unreachable. */
-#define ICMP_HOST_UNREACH	1
-
-/** Protocol Unreachable. */
-#define ICMP_PROT_UNREACH	2
-
-/** Port Unreachable. */
-#define ICMP_PORT_UNREACH	3
-
-/** Fragmentation needed but the Do Not Fragment bit was set. */
-#define ICMP_FRAG_NEEDED	4
-
-/** Source Route failed. */
-#define ICMP_SR_FAILED		5
-
-/** Destination network unknown. */
-#define ICMP_NET_UNKNOWN	6
-
-/** Destination host unknown. */
-#define ICMP_HOST_UNKNOWN	7
-
-/** Source host isolated (obsolete). */
-#define ICMP_HOST_ISOLATED	8
-
-/** Destination network administratively prohibited. */
-#define ICMP_NET_ANO		9
-
-/** Destination host administratively prohibited. */
-#define ICMP_HOST_ANO		10
-
-/** Network unreachable for this type of service. */
-#define ICMP_NET_UNR_TOS	11
-
-/** Host unreachable for this type of service. */
-#define ICMP_HOST_UNR_TOS	12
-
-/** Communication administratively prohibited by filtering. */
-#define ICMP_PKT_FILTERED	13
-
-/** Host precedence violation. */
-#define ICMP_PREC_VIOLATION	14
-
-/** Precedence cutoff in effect. */
-#define ICMP_PREC_CUTOFF	15
-
-/*@}*/
-
-/** @name ICMP_REDIRECT codes definitions */
-/*@{*/
-
-/** Network redirect (or subnet). */
-#define ICMP_REDIR_NET		0
-
-/** Host redirect. */
-#define ICMP_REDIR_HOST		1
-
-/** Network redirect for this type of service. */
-#define ICMP_REDIR_NETTOS	2
-
-/** Host redirect for this type of service. */
-#define ICMP_REDIR_HOSTTOS	3
-
-/*@}*/
-
-/** @name ICMP_ALTERNATE_ADDRESS codes definitions */
-/*@{*/
-
-/** Alternate address for host. */
-#define ICMP_ALTERNATE_HOST	0
-
-/*@}*/
-
-/** @name ICMP_ROUTER_ADV codes definitions */
-/*@{*/
-
-/** Normal router advertisement. */
-#define ICMP_ROUTER_NORMAL	0
-
-/** Does not route common traffic. */
-#define ICMP_ROUTER_NO_NORMAL_TRAFFIC	16
-
-/*@}*/
-
-/** @name ICMP_TIME_EXCEEDED codes definitions */
-/*@{*/
-
-/** Transit TTL exceeded. */
-#define ICMP_EXC_TTL		0
-
-/** Reassembly TTL exceeded. */
-#define ICMP_EXC_FRAGTIME	1
-
-/*@}*/
-
-/** @name ICMP_PARAMETERPROB codes definitions */
-/*@{*/
-
-/** Pointer indicates the error. */
-#define ICMP_PARAM_POINTER	0
-
-/** Missing required option. */
-#define ICMP_PARAM_MISSING	1
-
-/** Bad length. */
-#define ICMP_PARAM_LENGTH	2
-
-/*@}*/
-
-/** @name ICMP_PHOTURIS codes definitions */
-/*@{*/
-
-/** Bad SPI. */
-#define ICMP_PHOTURIS_BAD_SPI			0
-
-/** Authentication failed. */
-#define ICMP_PHOTURIS_AUTHENTICATION		1
-
-/** Decompression failed. */
-#define ICMP_PHOTURIS_DECOMPRESSION		2
-
-/** Decryption failed. */
-#define ICMP_PHOTURIS_DECRYPTION		3
-
-/** Need authentication. */
-#define ICMP_PHOTURIS_NEED_AUTHENTICATION	4
-
-/** Need authorization. */
-#define ICMP_PHOTURIS_NEED_AUTHORIZATION	5
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/icmp_common.h
===================================================================
--- uspace/lib/c/include/net/icmp_common.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,49 +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
- * ICMP module common interface.
- */
-
-#ifndef LIBC_ICMP_COMMON_H_
-#define LIBC_ICMP_COMMON_H_
-
-#include <ipc/services.h>
-#include <sys/time.h>
-#include <async.h>
-
-extern async_sess_t *icmp_connect_module(void);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/net/in.h
===================================================================
--- uspace/lib/c/include/net/in.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/include/net/in.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -45,4 +45,6 @@
 #define INET_ADDRSTRLEN  (4 * 3 + 3 + 1)
 
+#define INADDR_ANY 0
+
 /** Type definition of the INET address.
  * @see in_addr
Index: uspace/lib/c/include/net/modules.h
===================================================================
--- uspace/lib/c/include/net/modules.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/c/include/net/modules.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -46,16 +46,7 @@
 #include <sys/time.h>
 
-/** Connect to module function type definition.
- *
- * @return Session to the service.
- *
- */
-typedef async_sess_t *connect_module_t(services_t);
-
 extern void answer_call(ipc_callid_t, int, ipc_call_t *, size_t);
 extern async_sess_t *bind_service(services_t, sysarg_t, sysarg_t, sysarg_t,
     async_client_conn_t);
-extern async_sess_t *connect_to_service(services_t);
-extern int data_reply(void *, size_t);
 extern void refresh_answer(ipc_call_t *, size_t *);
 
Index: pace/lib/c/include/net/packet.h
===================================================================
--- uspace/lib/c/include/net/packet.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,94 +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
- *  Packet map and queue.
- */
-
-#ifndef LIBC_PACKET_H_
-#define LIBC_PACKET_H_
-
-#include <sys/types.h>
-
-/** Packet identifier type.
- * Value zero is used as an invalid identifier.
- */
-typedef sysarg_t packet_id_t;
-
-/** Type definition of the packet.
- * @see packet
- */
-typedef struct packet packet_t;
-
-/** Type definition of the packet dimension.
- * @see packet_dimension
- */
-typedef struct packet_dimension packet_dimension_t;
-
-/** Packet dimension. */
-struct packet_dimension {
-	/** Reserved packet prefix length. */
-	size_t prefix;
-	/** Maximal packet content length. */
-	size_t content;
-	/** Reserved packet suffix length. */
-	size_t suffix;
-	/** Maximal packet address length. */
-	size_t addr_len;
-};
-
-/** @name Packet management system interface
- */
-/*@{*/
-
-extern packet_t *pm_find(packet_id_t);
-extern int pm_add(packet_t *);
-extern void pm_remove(packet_t *);
-extern int pm_init(void);
-extern void pm_destroy(void);
-
-extern int pq_add(packet_t **, packet_t *, size_t, size_t);
-extern packet_t *pq_find(packet_t *, size_t);
-extern int pq_insert_after(packet_t *, packet_t *);
-extern packet_t *pq_detach(packet_t *);
-extern int pq_set_order(packet_t *, size_t, size_t);
-extern int pq_get_order(packet_t *, size_t *, size_t *);
-extern void pq_destroy(packet_t *, void (*)(packet_t *));
-extern packet_t *pq_next(packet_t *);
-extern packet_t *pq_previous(packet_t *);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/net/packet_header.h
===================================================================
--- uspace/lib/c/include/net/packet_header.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,147 +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
- * Packet header.
- */
-
-#ifndef LIBC_PACKET_HEADER_H_
-#define LIBC_PACKET_HEADER_H_
-
-#include <net/packet.h>
-
-/** Returns the actual packet data length.
- * @param[in] header	The packet header.
- */
-#define PACKET_DATA_LENGTH(header) \
-	((header)->data_end - (header)->data_start)
-
-/** Returns the maximum packet address length.
- * @param[in] header	The packet header.
- */
-#define PACKET_MAX_ADDRESS_LENGTH(header) \
-	((header)->dest_addr - (header)->src_addr)
-
-/** Returns the minimum packet suffix.
- *  @param[in] header	The packet header.
- */
-#define PACKET_MIN_SUFFIX(header) \
-	((header)->length - (header)->data_start - (header)->max_content)
-
-/** Packet integrity check magic value. */
-#define PACKET_MAGIC_VALUE	0x11227788
-
-/** Maximum total length of the packet */
-#define PACKET_MAX_LENGTH  65536
-
-/** Packet header. */
-struct packet {
-	/** Packet identifier. */
-	packet_id_t packet_id;
-
-	/**
-	 * Packet queue sorting value.
-	 * The packet queue is sorted the ascending order.
-	 */
-	size_t order;
-
-	/** Packet metric. */
-	size_t metric;
-	/** Previous packet in the queue. */
-	packet_id_t previous;
-	/** Next packet in the queue. */
-	packet_id_t next;
-
-	/**
-	 * Total length of the packet.
-	 * Contains the header, the addresses and the data of the packet.
-	 * Corresponds to the mapped sharable memory block.
-	 */
-	size_t length;
-
-	/** Offload info provided by the NIC */
-	uint32_t offload_info;
-
-	/** Mask which bits in offload info are valid */
-	uint32_t offload_mask;
-
-	/** Stored source and destination addresses length. */
-	size_t addr_len;
-
-	/**
-	 * Souce address offset in bytes from the beginning of the packet
-	 * header.
-	 */
-	size_t src_addr;
-
-	/**
-	 * Destination address offset in bytes from the beginning of the packet
-	 * header.
-	 */
-	size_t dest_addr;
-
-	/** Reserved data prefix length in bytes. */
-	size_t max_prefix;
-	/** Reserved content length in bytes. */
-	size_t max_content;
-
-	/**
-	 * Actual data start offset in bytes from the beginning of the packet
-	 * header.
-	 */
-	size_t data_start;
-
-	/**
-	 * Actual data end offset in bytes from the beginning of the packet
-	 * header.
-	 */
-	size_t data_end;
-
-	/** Integrity check magic value. */
-	int magic_value;
-};
-
-/** Returns whether the packet is valid.
- * @param[in] packet	The packet to be checked.
- * @return		True if the packet is not NULL and the magic value is
- *			correct.
- * @return		False otherwise.
- */
-static inline int packet_is_valid(const packet_t *packet)
-{
-	return packet && (packet->magic_value == PACKET_MAGIC_VALUE);
-}
-
-#endif
-
-/** @}
- */
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -259,5 +259,5 @@
 	if (data_request == 0) {
 		// FIXME: How to let the other side know that we want to abort?
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		return ENOMEM;
 	}
@@ -308,5 +308,5 @@
 		const int ret = async_data_write_start(exch, data, size);
 		if (ret != EOK) {
-			async_wait_for(opening_request, NULL);
+			async_forget(opening_request);
 			return ret;
 		}
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/fs/libfs.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -320,5 +320,5 @@
 	if (rc != EOK) {
 		async_exchange_end(exch);
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return rc;
 	}
@@ -341,5 +341,5 @@
 	if (reg.plb_ro == (void *) -1) {
 		async_exchange_end(exch);
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return ENOMEM;
 	}
@@ -348,5 +348,5 @@
 	
 	if (rc) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return rc;
 	}
@@ -404,5 +404,5 @@
 	
 	async_exch_t *exch = async_exchange_begin(mountee_sess);
-	async_sess_t *sess = async_connect_me(EXCHANGE_PARALLEL, exch);
+	async_sess_t *sess = async_clone_establish(EXCHANGE_PARALLEL, exch);
 	
 	if (!sess) {
Index: uspace/lib/net/Makefile
===================================================================
--- uspace/lib/net/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/net/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -33,24 +33,5 @@
 
 SOURCES = \
-	generic/generic.c \
-	generic/net_remote.c \
-	generic/net_checksum.c \
-	generic/packet_client.c \
-	generic/packet_remote.c \
-	generic/protocol_map.c \
-	adt/module_map.c \
-	nil/nil_remote.c \
-	nil/nil_skel.c \
-	il/il_remote.c \
-	il/il_skel.c \
-	il/ip_remote.c \
-	il/ip_client.c \
-	il/arp_remote.c \
-	tl/icmp_remote.c \
-	tl/icmp_client.c \
-	tl/socket_core.c \
-	tl/tl_common.c \
-	tl/tl_remote.c \
-	tl/tl_skel.c
+	tl/socket_core.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: pace/lib/net/adt/module_map.c
===================================================================
--- uspace/lib/net/adt/module_map.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,145 +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
- * Character string to module map implementation.
- */
-
-#include <malloc.h>
-#include <task.h>
-#include <unistd.h>
-#include <errno.h>
-#include <net/modules.h>
-#include <adt/generic_char_map.h>
-#include <adt/module_map.h>
-
-GENERIC_CHAR_MAP_IMPLEMENT(modules, module_t)
-
-/** Add module to the module map.
- *
- * @param[out] module         Module structure added.
- * @param[in]  modules        Module map.
- * @param[in]  name           Module name.
- * @param[in]  filename       Full path filename.
- * @param[in]  service        Module service.
- * @param[in]  task_id        Module current task identifier.
- *                            Zero means not running.
- * @param[in]  connect_module Module connecting function.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int add_module(module_t **module, modules_t *modules, const uint8_t *name,
-    const uint8_t *filename, services_t service, task_id_t task_id,
-    connect_module_t connect_module)
-{
-	module_t *tmp_module;
-	int rc;
-	
-	tmp_module = (module_t *) malloc(sizeof(module_t));
-	if (!tmp_module)
-		return ENOMEM;
-	
-	tmp_module->task_id = task_id;
-	tmp_module->sess = NULL;
-	tmp_module->usage = 0;
-	tmp_module->name = name;
-	tmp_module->filename = filename;
-	tmp_module->service = service;
-	tmp_module->connect_module = connect_module;
-	
-	rc = modules_add(modules, tmp_module->name, 0, tmp_module);
-	if (rc != EOK) {
-		free(tmp_module);
-		return rc;
-	}
-	
-	if (module)
-		*module = tmp_module;
-	
-	return EOK;
-}
-
-/** Search and return the specified module.
- *
- * If the module is not running, the module filaname is spawned.
- * If the module is not connected, the connect_function is called.
- *
- * @param[in] modules Module map.
- * @param[in] name    Module name.
- *
- * @return The running module found. It does not have to be
- *         connected.
- * @return NULL if there is no such module.
- *
- */
-module_t *get_running_module(modules_t *modules, uint8_t *name)
-{
-	module_t *module = modules_find(modules, name, 0);
-	if (!module)
-		return NULL;
-	
-	if (!module->task_id) {
-		module->task_id = net_spawn(module->filename);
-		if (!module->task_id)
-			return NULL;
-	}
-	
-	if (!module->sess)
-		module->sess = module->connect_module(module->service);
-	
-	return module;
-}
-
-/** Start the given module.
- *
- * @param[in] fname The module full or relative path filename.
- *
- * @return The new module task identifier on success.
- * @return Zero if there is no such module.
- *
- */
-task_id_t net_spawn(const uint8_t *fname)
-{
-	task_id_t id;
-	int rc;
-	
-	rc = task_spawnl(&id, (const char *) fname, (const char *) fname, NULL);
-	if (rc != EOK)
-		return 0;
-	
-	return id;
-}
-
-/** @}
- */
Index: pace/lib/net/generic/generic.c
===================================================================
--- uspace/lib/net/generic/generic.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,287 +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
- * Generic communication interfaces for networking.
- */
-
-#include <generic.h>
-#include <async.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <adt/measured_strings.h>
-#include <net/packet.h>
-
-/** Notify the module about the device state change.
- *
- * @param[in] sess      Service module session.
- * @param[in] message   Service specific message.
- * @param[in] device_id Device identifier.
- * @param[in] state     New device state.
- * @param[in] target    Target module service.
- *
- * @return EOK on success.
- *
- */
-int generic_device_state_msg_remote(async_sess_t *sess, sysarg_t message,
-    nic_device_id_t device_id, sysarg_t state, services_t target)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	async_msg_3(exch, message, (sysarg_t) device_id, state, target);
-	async_exchange_end(exch);
-	
-	return EOK;
-}
-
-/** Notify a module about the device.
- *
- * @param[in] sess      Service module session.
- * @param[in] message   Service specific message.
- * @param[in] device_id Device identifier.
- * @param[in] service   Device module service.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the specific service
- *         message.
- *
- */
-int generic_device_req_remote(async_sess_t *sess, sysarg_t message,
-    nic_device_id_t device_id, services_t service)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_3_0(exch, message, (sysarg_t) device_id, 0,
-	    (sysarg_t) service);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-/** Returns the address.
- *
- * @param[in] sess      Service module session.
- * @param[in] message   Service specific message.
- * @param[in] device_id Device identifier.
- * @param[out] address  Desired address.
- * @param[out] data     Address data container.
- *
- * @return EOK on success.
- * @return EBADMEM if the address parameter and/or the data
- *         parameter is NULL.
- * @return Other error codes as defined for the specific service
- *         message.
- *
- */
-int generic_get_addr_req(async_sess_t *sess, sysarg_t message,
-    nic_device_id_t device_id, uint8_t *address, size_t max_len)
-{
-	aid_t aid;
-	ipc_call_t result;
-	
-	assert(address != NULL);
-	
-	/* Request the address */
-	async_exch_t *exch = async_exchange_begin(sess);
-	aid = async_send_1(exch, message, (sysarg_t) device_id, &result);
-	
-	sysarg_t ipcrc;
-	int rc = async_data_read_start(exch, address, max_len);
-	async_exchange_end(exch);
-	
-	if (rc != EOK) {
-		async_wait_for(aid, &ipcrc);
-		return rc;
-	}
-	
-	async_wait_for(aid, &ipcrc);
-	if (ipcrc == EOK) {
-		return IPC_GET_ARG1(result);
-	} else {
-		return (int) ipcrc;
-	}
-}
-
-/** Return the device packet dimension for sending.
- *
- * @param[in] sess              Service module session.
- * @param[in] message           Service specific message.
- * @param[in] device_id         Device identifier.
- * @param[out] packet_dimension Packet dimension.
- *
- * @return EOK on success.
- * @return EBADMEM if the packet_dimension parameter is NULL.
- * @return Other error codes as defined for the specific service
- *         message.
- *
- */
-int generic_packet_size_req_remote(async_sess_t *sess, sysarg_t message,
-    nic_device_id_t device_id, packet_dimension_t *packet_dimension)
-{
-	if (!packet_dimension)
-		return EBADMEM;
-	
-	sysarg_t addr_len;
-	sysarg_t prefix;
-	sysarg_t content;
-	sysarg_t suffix;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	sysarg_t result = async_req_1_4(exch, message, (sysarg_t) device_id,
-	    &addr_len, &prefix, &content, &suffix);
-	async_exchange_end(exch);
-	
-	packet_dimension->prefix = (size_t) prefix;
-	packet_dimension->content = (size_t) content;
-	packet_dimension->suffix = (size_t) suffix;
-	packet_dimension->addr_len = (size_t) addr_len;
-	
-	return (int) result;
-}
-
-/** Pass the packet queue to the module.
- *
- * @param[in] sess      Service module session.
- * @param[in] message   Service specific message.
- * @param[in] device_id Device identifier.
- * @param[in] packet_id Received packet or the received packet queue
- *                      identifier.
- * @param[in] target    Target module service.
- * @param[in] error     Error module service.
- *
- * @return EOK on success.
- *
- */
-int generic_received_msg_remote(async_sess_t *sess, sysarg_t message,
-    nic_device_id_t device_id, packet_id_t packet_id, services_t target,
-    services_t error)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	if (error) {
-		async_msg_4(exch, message, (sysarg_t) device_id,
-		    (sysarg_t) packet_id, (sysarg_t) target, (sysarg_t) error);
-	} else {
-		async_msg_3(exch, message, (sysarg_t) device_id,
-		    (sysarg_t) packet_id, (sysarg_t) target);
-	}
-	
-	async_exchange_end(exch);
-	
-	return EOK;
-}
-
-/** Send the packet queue.
- *
- * @param[in] sess      Service module session.
- * @param[in] message   Service specific message.
- * @param[in] device_id Device identifier.
- * @param[in] packet_id Packet or the packet queue identifier.
- * @param[in] sender    Sending module service.
- * @param[in] error     Error module service.
- *
- * @return EOK on success.
- *
- */
-int generic_send_msg_remote(async_sess_t *sess, sysarg_t message,
-    nic_device_id_t device_id, packet_id_t packet_id, services_t sender,
-    services_t error)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	if (error) {
-		async_msg_4(exch, message, (sysarg_t) device_id,
-		    (sysarg_t) packet_id, (sysarg_t) sender, (sysarg_t) error);
-	} else {
-		async_msg_3(exch, message, (sysarg_t) device_id,
-		    (sysarg_t) packet_id, (sysarg_t) sender);
-	}
-	
-	async_exchange_end(exch);
-	
-	return EOK;
-}
-
-/** Translates the given strings.
- *
- * Allocates and returns the needed memory block as the data parameter.
- *
- * @param[in] sess          Service module session.
- * @param[in] message       Service specific message.
- * @param[in] device_id     Device identifier.
- * @param[in] service       Module service.
- * @param[in] configuration Key strings.
- * @param[in] count         Number of configuration keys.
- * @param[out] translation  Translated values.
- * @param[out] data         Translation data container.
- *
- * @return EOK on success.
- * @return EINVAL if the configuration parameter is NULL.
- * @return EINVAL if the count parameter is zero.
- * @return EBADMEM if the translation or the data parameters are
- *         NULL.
- * @return Other error codes as defined for the specific service
- *         message.
- *
- */
-int generic_translate_req(async_sess_t *sess, sysarg_t message,
-    nic_device_id_t device_id, services_t service,
-    measured_string_t *configuration, size_t count,
-    measured_string_t **translation, uint8_t **data)
-{
-	if ((!configuration) || (count == 0))
-		return EINVAL;
-	
-	if ((!translation) || (!data))
-		return EBADMEM;
-	
-	/* Request the translation */
-	async_exch_t *exch = async_exchange_begin(sess);
-	aid_t message_id = async_send_3(exch, message, (sysarg_t) device_id,
-	    (sysarg_t) count, (sysarg_t) service, NULL);
-	measured_strings_send(exch, configuration, count);
-	int rc = measured_strings_return(exch, translation, data, count);
-	async_exchange_end(exch);
-	
-	sysarg_t result;
-	async_wait_for(message_id, &result);
-	
-	/* If not successful */
-	if ((rc == EOK) && (result != EOK)) {
-		/* Clear the data */
-		free(*translation);
-		free(*data);
-	}
-	
-	return (int) result;
-}
-
-/** @}
- */
Index: pace/lib/net/generic/net_checksum.c
===================================================================
--- uspace/lib/net/generic/net_checksum.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,224 +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
- * General CRC and checksum computation implementation.
- */
-
-#include <sys/types.h>
-
-#include <net_checksum.h>
-
-/** Big-endian encoding CRC divider. */
-#define CRC_DIVIDER_BE  0x04c11db7
-
-/** Little-endian encoding CRC divider. */
-#define CRC_DIVIDER_LE  0xedb88320
-
-/** Compacts the computed checksum to the 16 bit number adding the carries.
- *
- * @param[in] sum	Computed checksum.
- * @return		Compacted computed checksum to the 16 bits.
- */
-uint16_t compact_checksum(uint32_t sum)
-{
-	/* Shorten to the 16 bits */
-	while (sum >> 16)
-		sum = (sum & 0xffff) + (sum >> 16);
-
-	return (uint16_t) sum;
-}
-
-/** Computes sum of the 2 byte fields.
- *
- * Padds one zero (0) byte if odd.
- *
- * @param[in] seed	Initial value. Often used as 0 or ~0.
- * @param[in] data	Pointer to the beginning of data to process.
- * @param[in] length	Length of the data in bytes.
- * @return		The computed checksum of the length bytes of the data.
- */
-uint32_t compute_checksum(uint32_t seed, uint8_t *data, size_t length)
-{
-	size_t index;
-
-	/* Sum all the 16 bit fields */
-	for (index = 0; index + 1 < length; index += 2)
-		seed += (data[index] << 8) + data[index + 1];
-
-	/* Last odd byte with zero padding */
-	if (index + 1 == length)
-		seed += data[index] << 8;
-
-	return seed;
-}
-
-/** Computes CRC32 value in the big-endian environment.
- *
- * @param[in] seed	Initial value. Often used as 0 or ~0.
- * @param[in] data	Pointer to the beginning of data to process.
- * @param[in] length	Length of the data in bits.
- * @return		The computed CRC32 of the length bits of the data.
- */
-uint32_t compute_crc32_be(uint32_t seed, uint8_t * data, size_t length)
-{
-	size_t index;
-
-	/* Process full bytes */
-	while (length >= 8) {
-		/* Add the data */
-		seed ^= (*data) << 24;
-		
-		/* For each added bit */
-		for (index = 0; index < 8; ++index) {
-			/* If the first bit is set */
-			if (seed & 0x80000000) {
-				/* Shift and divide the checksum */
-				seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
-			} else {
-				/* Shift otherwise */
-				seed <<= 1;
-			}
-		}
-		
-		/* Move to the next byte */
-		++data;
-		length -= 8;
-	}
-
-	/* Process the odd bits */
-	if (length > 0) {
-		/* Add the data with zero padding */
-		seed ^= ((*data) & (0xff << (8 - length))) << 24;
-		
-		/* For each added bit */
-		for (index = 0; index < length; ++index) {
-			/* If the first bit is set */
-			if (seed & 0x80000000) {
-				/* Shift and divide the checksum */
-				seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
-			} else {
-				/* Shift otherwise */
-				seed <<= 1;
-			}
-		}
-	}
-
-	return seed;
-}
-
-/** Computes CRC32 value in the little-endian environment.
- *
- * @param[in] seed	Initial value. Often used as 0 or ~0.
- * @param[in] data	Pointer to the beginning of data to process.
- * @param[in] length	Length of the data in bits.
- * @return		The computed CRC32 of the length bits of the data.
- */
-uint32_t compute_crc32_le(uint32_t seed, uint8_t * data, size_t length)
-{
-	size_t index;
-
-	/* Process full bytes */
-	while (length >= 8) {
-		/* Add the data */
-		seed ^= (*data);
-		
-		/* For each added bit */
-		for (index = 0; index < 8; ++index) {
-			/* If the last bit is set */
-			if (seed & 1) {
-				/* Shift and divide the checksum */
-				seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
-			} else {
-				/* Shift otherwise */
-				seed >>= 1;
-			}
-		}
-		
-		/* Move to the next byte */
-		++data;
-		length -= 8;
-	}
-
-	/* Process the odd bits */
-	if (length > 0) {
-		/* Add the data with zero padding */
-		seed ^= (*data) >> (8 - length);
-		
-		for (index = 0; index < length; ++index) {
-			/* If the last bit is set */
-			if (seed & 1) {
-				/* Shift and divide the checksum */
-				seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
-			} else {
-				/* Shift otherwise */
-				seed >>= 1;
-			}
-		}
-	}
-
-	return seed;
-}
-
-/** Returns or flips the checksum if zero.
- *
- * @param[in] checksum	The computed checksum.
- * @return		The internet protocol header checksum.
- * @return		0xFFFF if the computed checksum is zero.
- */
-uint16_t flip_checksum(uint16_t checksum)
-{
-	/* Flip, zero is returned as 0xFFFF (not flipped) */
-	checksum = ~checksum;
-	return checksum ? checksum : IP_CHECKSUM_ZERO;
-}
-
-/** Compute the IP header checksum.
- *
- * To compute the checksum of a new packet, the checksum header field must be
- * zero. To check the checksum of a received packet, the checksum may be left
- * set. Zero will be returned in this case if valid.
- *
- * @param[in] data	The header data.
- * @param[in] length	The header length in bytes.
- * @return		The internet protocol header checksum.
- * @return		0xFFFF if the computed checksum is zero.
- */
-uint16_t ip_checksum(uint8_t *data, size_t length)
-{
-	/* Compute, compact and flip the data checksum */
-	return flip_checksum(compact_checksum(compute_checksum(0, data,
-	    length)));
-}
-
-/** @}
- */
Index: pace/lib/net/generic/net_remote.c
===================================================================
--- uspace/lib/net/generic/net_remote.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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 libnet
- * @{
- */
-
-/** @file
- * Networking interface implementation for remote modules.
- * @see net_interface.h
- */
-
-#include <ipc/services.h>
-#include <ipc/net_net.h>
-#include <malloc.h>
-#include <async.h>
-#include <generic.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <net_interface.h>
-#include <adt/measured_strings.h>
-
-/** Connect to the networking module.
- *
- * @return Networking module session on success.
- *
- */
-async_sess_t *net_connect_module(void)
-{
-	return connect_to_service(SERVICE_NETWORKING);
-}
-
-/** Free the received settings.
- *
- * @param[in] settings Received settings.
- * @param[in] data     Received settings data.
- *
- * @see net_get_device_conf_req()
- * @see net_get_conf_req()
- *
- */
-void net_free_settings(measured_string_t *settings, uint8_t *data)
-{
-	if (settings)
-		free(settings);
-	if (data)
-		free(data);
-}
-
-/** Return the global configuration.
- *
- * The configuration names are read and the appropriate settings are set
- * instead. Call net_free_settings() function to release the returned
- * configuration.
- *
- * @param[in]     sess          Networking module session.
- * @param[in,out] configuration Requested configuration. The names are
- *                              read and the appropriate settings are set
- *                              instead.
- *
- * @param[in]     count         Configuration entries count.
- * @param[in,out] data          Configuration and settings data.
- *
- * @return EOK on success.
- * @return EINVAL if the configuration is NULL.
- * @return EINVAL if the count is zero.
- * @return Other error codes as defined for the
- *         generic_translate_req() function.
- *
- */
-int net_get_conf_req(async_sess_t *sess, measured_string_t **configuration,
-    size_t count, uint8_t **data)
-{
-	return generic_translate_req(sess, NET_NET_GET_CONF, 0, 0,
-	    *configuration, count, configuration, data);
-}
-
-/** Return the device specific configuration.
- *
- * Return the global configuration if the device specific is not found.
- * The configuration names are read and the appropriate settings are set
- * instead. Call net_free_settings() function to release the returned
- * configuration.
- *
- * @param[in]     sess          The networking module session.
- * @param[in]     device_id     Device identifier.
- * @param[in,out] configuration Requested device configuration. The names
- *                              are read and the appropriate settings are
- *                              set instead.
- * @param[in]     count         Configuration entries count.
- * @param[in,out] data          Configuration and settings data.
- *
- * @return EOK on success.
- * @return EINVAL if the configuration is NULL.
- * @return EINVAL if the count is zero.
- * @return Other error codes as defined for the
- *         generic_translate_req() function.
- *
- */
-int net_get_device_conf_req(async_sess_t *sess, nic_device_id_t device_id,
-    measured_string_t **configuration, size_t count, uint8_t **data)
-{
-	return generic_translate_req(sess, NET_NET_GET_DEVICE_CONF,
-	    device_id, 0, *configuration, count, configuration, data);
-}
-
-int net_get_devices_req(async_sess_t *sess, measured_string_t **devices,
-    size_t *count, uint8_t **data)
-{
-	if ((!devices) || (!count))
-		return EBADMEM;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	int rc = async_req_0_1(exch, NET_NET_GET_DEVICES_COUNT, count);
-	if (rc != EOK) {
-		async_exchange_end(exch);
-		return rc;
-	}
-	
-	if (*count == 0) {
-		async_exchange_end(exch);
-		*data = NULL;
-		return EOK;
-	}
-	
-	aid_t message_id = async_send_0(exch, NET_NET_GET_DEVICES, NULL);
-	rc = measured_strings_return(exch, devices, data, *count);
-	
-	async_exchange_end(exch);
-	
-	sysarg_t result;
-	async_wait_for(message_id, &result);
-	
-	if ((rc == EOK) && (result != EOK)) {
-		free(*devices);
-		free(*data);
-	}
-	
-	return (int) result;
-}
-
-/** @}
- */
Index: pace/lib/net/generic/packet_client.c
===================================================================
--- uspace/lib/net/generic/packet_client.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,294 +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
- * Packet client implementation.
- */
-
-#include <errno.h>
-#include <mem.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-
-#include <net/packet.h>
-#include <net/packet_header.h>
-
-/** Copies the specified data to the beginning of the actual packet content.
- *
- * Pushes the content end if needed.
- *
- * @param[in] packet	The packet to be filled.
- * @param[in] data	The data to be copied.
- * @param[in] length	The length of the copied data.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		ENOMEM if there is not enough memory left.
- */
-int packet_copy_data(packet_t *packet, const void *data, size_t length)
-{
-	if (!packet_is_valid(packet))
-		return EINVAL;
-
-	if (packet->data_start + length >= packet->length)
-		return ENOMEM;
-
-	memcpy((void *) packet + packet->data_start, data, length);
-	if (packet->data_start + length > packet->data_end) 
-		packet->data_end = packet->data_start + length;
-
-	return EOK;
-}
-
-/** Allocates the specified space right before the actual packet content and
- * returns its pointer.
- *
- * @param[in] packet	The packet to be used.
- * @param[in] length	The space length to be allocated at the beginning of the
- *			packet content.
- * @return		The pointer to the allocated memory.
- * @return		NULL if there is not enough memory left.
- */
-void *packet_prefix(packet_t *packet, size_t length)
-{
-	if ((!packet_is_valid(packet)) ||
-	    (packet->data_start - sizeof(packet_t) -
-	    2 * (packet->dest_addr - packet->src_addr) < length)) {
-		return NULL;
-	}
-
-	packet->data_start -= length;
-	return (void *) packet + packet->data_start;
-}
-
-/** Allocates the specified space right after the actual packet content and
- * returns its pointer.
- *
- * @param[in] packet	The packet to be used.
- * @param[in] length	The space length to be allocated at the end of the
- *			 packet content.
- * @return		The pointer to the allocated memory.
- * @return		NULL if there is not enough memory left.
- */
-void *packet_suffix(packet_t *packet, size_t length)
-{
-	if ((!packet_is_valid(packet)) ||
-	    (packet->data_end + length >= packet->length)) {
-		return NULL;
-	}
-
-	packet->data_end += length;
-	return (void *) packet + packet->data_end - length;
-}
-
-/** Trims the actual packet content by the specified prefix and suffix lengths.
- *
- * @param[in] packet	The packet to be trimmed.
- * @param[in] prefix	The prefix length to be removed from the beginning of
- *			the packet content.
- * @param[in] suffix	The suffix length to be removed from the end of the
- *			packet content.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		ENOMEM if there is not enough memory left.
- */
-int packet_trim(packet_t *packet, size_t prefix, size_t suffix)
-{
-	if (!packet_is_valid(packet))
-		return EINVAL;
-
-	if (prefix + suffix > PACKET_DATA_LENGTH(packet))
-		return ENOMEM;
-
-	packet->data_start += prefix;
-	packet->data_end -= suffix;
-	return EOK;
-}
-
-/** Returns the packet identifier.
- *
- * @param[in] packet	The packet.
- * @return		The packet identifier.
- * @return		Zero if the packet is not valid.
- */
-packet_id_t packet_get_id(const packet_t *packet)
-{
-	return packet_is_valid(packet) ? packet->packet_id : 0;
-}
-
-/** Returns the stored packet addresses and their length.
- *
- * @param[in] packet	The packet.
- * @param[out] src	The source address. May be NULL if not desired.
- * @param[out] dest	The destination address. May be NULL if not desired.
- * @return		The stored addresses length.
- * @return		Zero if the addresses are not present.
- * @return		EINVAL if the packet is not valid.
- */
-int packet_get_addr(const packet_t *packet, uint8_t **src, uint8_t **dest)
-{
-	if (!packet_is_valid(packet))
-		return EINVAL;
-	if (!packet->addr_len)
-		return 0;
-	if (src)
-		*src = (void *) packet + packet->src_addr;
-	if (dest)
-		*dest = (void *) packet + packet->dest_addr;
-
-	return packet->addr_len;
-}
-
-/** Returns the packet content length.
- *
- * @param[in] packet	The packet.
- * @return		The packet content length in bytes.
- * @return		Zero if the packet is not valid.
- */
-size_t packet_get_data_length(const packet_t *packet)
-{
-	if (!packet_is_valid(packet))
-		return 0;
-
-	return PACKET_DATA_LENGTH(packet);
-}
-
-/** Returns the pointer to the beginning of the packet content.
- *
- * @param[in] packet	The packet.
- * @return		The pointer to the beginning of the packet content.
- * @return		NULL if the packet is not valid.
- */
-void *packet_get_data(const packet_t *packet)
-{
-	if (!packet_is_valid(packet))
-		return NULL;
-
-	return (void *) packet + packet->data_start;
-}
-
-/** Sets the packet addresses.
- *
- * @param[in] packet	The packet.
- * @param[in] src	The new source address. May be NULL.
- * @param[in] dest	The new destination address. May be NULL.
- * @param[in] addr_len	The addresses length.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		ENOMEM if there is not enough memory left.
- */
-int
-packet_set_addr(packet_t *packet, const uint8_t *src, const uint8_t *dest,
-    size_t addr_len)
-{
-	size_t padding;
-	size_t allocated;
-
-	if (!packet_is_valid(packet))
-		return EINVAL;
-
-	allocated = PACKET_MAX_ADDRESS_LENGTH(packet);
-	if (allocated < addr_len)
-		return ENOMEM;
-
-	padding = allocated - addr_len;
-	packet->addr_len = addr_len;
-
-	if (src) {
-		memcpy((void *) packet + packet->src_addr, src, addr_len);
-		if (padding)
-			bzero((void *) packet + packet->src_addr + addr_len,
-			    padding);
-	} else {
-		bzero((void *) packet + packet->src_addr, allocated);
-	}
-
-	if (dest) {
-		memcpy((void *) packet + packet->dest_addr, dest, addr_len);
-		if (padding)
-			bzero((void *) packet + packet->dest_addr + addr_len,
-			    padding);
-	} else {
-		bzero((void *) packet + packet->dest_addr, allocated);
-	}
-
-	return EOK;
-}
-
-/** Return the packet copy.
- *
- * Copy the addresses, data, order and metric values.
- * Queue placement is not copied.
- *
- * @param[in] sess   Packet server module session.
- * @param[in] packet Original packet.
- *
- * @return Packet copy.
- * @return NULL on error.
- *
- */
-packet_t *packet_get_copy(async_sess_t *sess, packet_t *packet)
-{
-	if (!packet_is_valid(packet))
-		return NULL;
-	
-	/* Get a new packet */
-	packet_t *copy = packet_get_4_remote(sess, PACKET_DATA_LENGTH(packet),
-	    PACKET_MAX_ADDRESS_LENGTH(packet), packet->max_prefix,
-	    PACKET_MIN_SUFFIX(packet));
-	
-	if (!copy)
-		return NULL;
-	
-	/* Get addresses */
-	uint8_t *src = NULL;
-	uint8_t *dest = NULL;
-	size_t addrlen = packet_get_addr(packet, &src, &dest);
-	
-	/* Copy data */
-	if ((packet_copy_data(copy, packet_get_data(packet),
-	    PACKET_DATA_LENGTH(packet)) == EOK) &&
-	    /* Copy addresses if present */
-	    ((addrlen <= 0) ||
-	    (packet_set_addr(copy, src, dest, addrlen) == EOK))) {
-		copy->order = packet->order;
-		copy->metric = packet->metric;
-		return copy;
-	} else {
-		pq_release_remote(sess, copy->packet_id);
-		return NULL;
-	}
-}
-
-/** @}
- */
Index: pace/lib/net/generic/packet_remote.c
===================================================================
--- uspace/lib/net/generic/packet_remote.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,229 +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
- * Packet client interface implementation for remote modules.
- * @see packet_client.h
- */
-
-#include <async.h>
-#include <errno.h>
-#include <ipc/packet.h>
-#include <sys/mman.h>
-
-#include <packet_client.h>
-#include <packet_remote.h>
-
-#include <net/packet.h>
-#include <net/packet_header.h>
-
-/** Obtain the packet from the packet server as the shared memory block.
- *
- * Create the local packet mapping as well.
- *
- * @param[in]  sess      Packet server module session.
- * @param[out] packet    Packet reference pointer to store the received
- *                       packet reference.
- * @param[in]  packet_id Packet identifier.
- * @param[in]  size      Packet total size in bytes.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the pm_add() function.
- * @return Other error codes as defined for the async_share_in_start()
- *         function.
- *
- */
-static int packet_return(async_sess_t *sess, packet_t **packet,
-    packet_id_t packet_id, size_t size)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	ipc_call_t answer;
-	aid_t message = async_send_1(exch, NET_PACKET_GET, packet_id, &answer);
-	int rc = async_share_in_start_0_0(exch, size, (void *) packet);
-	async_exchange_end(exch);
-	
-	sysarg_t result;
-	async_wait_for(message, &result);
-	
-	if (rc != EOK)
-		return rc;
-	
-	if (packet == (void *) -1)
-		return ENOMEM;
-	
-	rc = pm_add(*packet);
-	if (rc != EOK) {
-		munmap(*packet, size);
-		return rc;
-	}
-	
-	return result;
-}
-
-/** Translate the packet identifier to the packet reference.
- *
- * Try to find mapping first. The packet server is asked to share
- * the packet if the mapping is not present.
- *
- * @param[in]  sess      Packet server module session.
- * @param[out] packet    Packet reference.
- * @param[in]  packet_id Packet identifier.
- *
- * @return EOK on success.
- * @return EINVAL if the packet parameter is NULL.
- * @return Other error codes as defined for the NET_PACKET_GET_SIZE
- *         message.
- * @return Other error codes as defined for the packet_return()
- *         function.
- *
- */
-int packet_translate_remote(async_sess_t *sess, packet_t **packet,
-    packet_id_t packet_id)
-{
-	if (!packet)
-		return EINVAL;
-	
-	*packet = pm_find(packet_id);
-	if (*packet == NULL) {
-		async_exch_t *exch = async_exchange_begin(sess);
-		sysarg_t size;
-		int rc = async_req_1_1(exch, NET_PACKET_GET_SIZE, packet_id,
-		    &size);
-		async_exchange_end(exch);
-		
-		if (rc != EOK)
-			return rc;
-		
-		rc = packet_return(sess, packet, packet_id, size);
-		if (rc != EOK)
-			return rc;
-	}
-	
-	if ((*packet != NULL) && ((*packet)->next)) {
-		packet_t *next;
-		return packet_translate_remote(sess, &next, (*packet)->next);
-	}
-	
-	return EOK;
-}
-
-/** Obtain the packet of given dimensions.
- *
- * Contact the packet server to return the appropriate packet.
- *
- * @param[in] sess        Packet server module session.
- * @param[in] addr_len    Source and destination addresses maximal length
- *                        in bytes.
- * @param[in] max_prefix  Maximal prefix length in bytes.
- * @param[in] max_content Maximal content length in bytes.
- * @param[in] max_suffix  Maximal suffix length in bytes.
- *
- * @return The packet reference.
- * @return NULL on error.
- *
- */
-packet_t *packet_get_4_remote(async_sess_t *sess, size_t max_content,
-    size_t addr_len, size_t max_prefix, size_t max_suffix)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	sysarg_t packet_id;
-	sysarg_t size;
-	int rc = async_req_4_2(exch, NET_PACKET_CREATE_4, max_content, addr_len,
-	    max_prefix, max_suffix, &packet_id, &size);
-	async_exchange_end(exch);
-	
-	if (rc != EOK)
-		return NULL;
-	
-	packet_t *packet = pm_find(packet_id);
-	if (!packet) {
-		rc = packet_return(sess, &packet, packet_id, size);
-		if (rc != EOK)
-			return NULL;
-	}
-	
-	return packet;
-}
-
-/** Obtain the packet of given content size.
- *
- * Contact the packet server to return the appropriate packet.
- *
- * @param[in] sess    Packet server module session.
- * @param[in] content Maximal content length in bytes.
- *
- * @return The packet reference.
- * @return NULL on error.
- *
- */
-packet_t *packet_get_1_remote(async_sess_t *sess, size_t content)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	sysarg_t packet_id;
-	sysarg_t size;
-	int rc = async_req_1_2(exch, NET_PACKET_CREATE_1, content, &packet_id,
-	    &size);
-	async_exchange_end(exch);
-	
-	if (rc != EOK)
-		return NULL;
-	
-	packet_t *packet = pm_find(packet_id);
-	if (!packet) {
-		rc = packet_return(sess, &packet, packet_id, size);
-		if (rc != EOK)
-			return NULL;
-	}
-	
-	return packet;
-}
-
-/** Release the packet queue.
- *
- * All packets in the queue are marked as free for use.
- * The packet queue may be one packet only.
- * The module should not use the packets after this point until they are
- * received or obtained again.
- *
- * @param[in] sess      Packet server module session.
- * @param[in] packet_id Packet identifier.
- *
- */
-void pq_release_remote(async_sess_t *sess, packet_id_t packet_id)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	async_msg_1(exch, NET_PACKET_RELEASE, packet_id);
-	async_exchange_end(exch);
-}
-
-/** @}
- */
Index: pace/lib/net/generic/protocol_map.c
===================================================================
--- uspace/lib/net/generic/protocol_map.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,148 +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
- * @{
- */
-
-#include <protocol_map.h>
-#include <ethernet_lsap.h>
-#include <ethernet_protocols.h>
-#include <net_hardware.h>
-
-#include <ipc/services.h>
-
-/** Maps the internetwork layer service to the network interface layer type.
- *
- * @param[in] nil	Network interface layer service.
- * @param[in] il	Internetwork layer service.
- * @return		Network interface layer type of the internetworking
- *			layer service.
- * @return		Zero if mapping is not found.
- */
-eth_type_t protocol_map(services_t nil, services_t il)
-{
-	switch (nil) {
-	case SERVICE_ETHERNET:
-	case SERVICE_NILDUMMY:
-		switch (il) {
-		case SERVICE_IP:
-			return ETH_P_IP;
-		case SERVICE_ARP:
-			return ETH_P_ARP;
-		default:
-			return 0;
-		}
-	default:
-		return 0;
-	}
-}
-
-/** Maps the network interface layer type to the internetwork layer service.
- *
- * @param[in] nil	Network interface layer service.
- * @param[in] protocol	Network interface layer type.
- * @return		Internetwork layer service of the network interface
- *			layer type.
- * @return		Zero if mapping is not found.
- */
-services_t protocol_unmap(services_t nil, int protocol)
-{
-	switch (nil) {
-	case SERVICE_ETHERNET:
-	case SERVICE_NILDUMMY:
-		switch (protocol) {
-		case ETH_P_IP:
-			return SERVICE_IP;
-		case ETH_P_ARP:
-			return SERVICE_ARP;
-		default:
-			return 0;
-		}
-	default:
-		return 0;
-	}
-}
-
-/** Maps the link service access point identifier to the Ethernet protocol
- * identifier.
- *
- * @param[in] lsap	Link service access point identifier.
- * @return		Ethernet protocol identifier of the link service access
- *			point identifier.
- * @return		ETH_LSAP_NULL if mapping is not found.
- */
-eth_type_t lsap_map(eth_lsap_t lsap)
-{
-	switch (lsap) {
-	case ETH_LSAP_IP:
-		return ETH_P_IP;
-	case ETH_LSAP_ARP:
-		return ETH_P_ARP;
-	default:
-		return ETH_LSAP_NULL;
-	}
-}
-
-/** Maps the Ethernet protocol identifier to the link service access point
- * identifier.
- *
- * @param[in] ethertype	Ethernet protocol identifier.
- * @return		Link service access point identifier.
- * @return		Zero if mapping is not found.
- */
-eth_lsap_t lsap_unmap(eth_type_t ethertype)
-{
-	switch (ethertype) {
-	case ETH_P_IP:
-		return ETH_LSAP_IP;
-	case ETH_P_ARP:
-		return ETH_LSAP_ARP;
-	default:
-		return 0;
-	}
-}
-
-/** Maps the network interface layer services to the hardware types.
- *
- * @param[in] nil	The network interface service.
- * @return		The hardware type of the network interface service.
- * @return		Zero if mapping is not found.
- */
-hw_type_t hardware_map(services_t nil)
-{
-	switch (nil) {
-	case SERVICE_ETHERNET:
-		return HW_ETHER;
-	default:
-		return 0;
-	}
-}
-
-/** @}
- */
Index: pace/lib/net/il/arp_remote.c
===================================================================
--- uspace/lib/net/il/arp_remote.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,188 +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
- * ARP interface implementation for remote modules.
- * @see arp_interface.h
- */
-
-#include <arp_interface.h>
-#include <generic.h>
-#include <ipc/services.h>
-#include <ipc/arp.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <adt/measured_strings.h>
-#include <async.h>
-#include <errno.h>
-
-/** Connect to the ARP module.
- *
- * @return ARP module session on success.
- *
- */
-async_sess_t *arp_connect_module(services_t service)
-{
-	// FIXME: Get rid of the useless argument
-	return connect_to_service(SERVICE_ARP);
-}
-
-/** Cleans the cache.
- *
- * @param[in] sess ARP module session.
- *
- * @return EOK on success.
- *
- */
-int arp_clean_cache_req(async_sess_t *sess)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_0_0(exch, NET_ARP_CLEAN_CACHE);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-/** Clear the given protocol address from the cache.
- *
- * @param[in] sess      ARP module session.
- * @param[in] device_id Device identifier.
- * @param[in] protocol  Requesting protocol service.
- * @param[in] address   Protocol address to be cleared.
- *
- * @return EOK on success.
- * @return ENOENT if the mapping is not found.
- *
- */
-int arp_clear_address_req(async_sess_t *sess, nic_device_id_t device_id,
-    services_t protocol, measured_string_t *address)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	aid_t message_id = async_send_2(exch, NET_ARP_CLEAR_ADDRESS,
-	    (sysarg_t) device_id, protocol, NULL);
-	measured_strings_send(exch, address, 1);
-	async_exchange_end(exch);
-	
-	sysarg_t result;
-	async_wait_for(message_id, &result);
-	
-	return (int) result;
-}
-
-/** Clear the device cache.
- *
- * @param[in] sess      ARP module session.
- * @param[in] device_id Device identifier.
- *
- * @return EOK on success.
- * @return ENOENT if the device is not found.
- *
- */
-int arp_clear_device_req(async_sess_t *sess, nic_device_id_t device_id)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_1_0(exch, NET_ARP_CLEAR_DEVICE,
-	    (sysarg_t) device_id);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-/** Register new device and the requesting protocol service.
- *
- * Connect to the network interface layer service.
- * Determine the device broadcast address, its address lengths and packet size.
- *
- * @param[in] sess      ARP module session.
- * @param[in] device_id New device identifier.
- * @param[in] protocol  Requesting protocol service.
- * @param[in] netif     Underlying device network interface layer service.
- * @param[in] address   Local requesting protocol address of the device.
- *
- * @return EOK on success.
- * @return EEXIST if the device is already used.
- * @return ENOMEM if there is not enough memory left.
- * @return ENOENT if the network interface service is not known.
- * @return EREFUSED if the network interface service is not
- *         responding.
- * @return Other error codes as defined for the
- *         nil_packet_get_size() function.
- * @return Other error codes as defined for the nil_get_addr()
- *         function.
- * @return Other error codes as defined for the
- *         nil_get_broadcast_addr() function.
- *
- */
-int arp_device_req(async_sess_t *sess, nic_device_id_t device_id,
-    services_t protocol, services_t netif, measured_string_t *address)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	aid_t message_id = async_send_3(exch, NET_ARP_DEVICE,
-	    (sysarg_t) device_id, protocol, netif, NULL);
-	measured_strings_send(exch, address, 1);
-	async_exchange_end(exch);
-	
-	sysarg_t result;
-	async_wait_for(message_id, &result);
-
-	return (int) result;
-}
-
-/** Translate the given protocol address to the network interface address.
- *
- * Broadcast the ARP request if the mapping is not found.
- * Allocate and returns the needed memory block as the data parameter.
- *
- * @param[in]  sess        ARP module session.
- * @param[in]  device_id   Device identifier.
- * @param[in]  protocol    Requesting protocol service.
- * @param[in]  address     Local requesting protocol address.
- * @param[out] translation Translation of the local protocol address.
- * @param[out] data        Allocated raw translation data container.
- *
- * @return EOK on success.
- * @return EINVAL if the address parameter is NULL.
- * @return EBADMEM if the translation or the data parameters are
- *         NULL.
- * @return ENOENT if the mapping is not found.
- *
- */
-int arp_translate_req(async_sess_t *sess, nic_device_id_t device_id,
-    services_t protocol, measured_string_t *address,
-    measured_string_t **translation, uint8_t **data)
-{
-	return generic_translate_req(sess, NET_ARP_TRANSLATE, device_id,
-	    protocol, address, 1, translation, data);
-}
-
-/** @}
- */
Index: pace/lib/net/il/il_remote.c
===================================================================
--- uspace/lib/net/il/il_remote.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,123 +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
- * Internetwork layer module interface for the underlying network interface
- * layer.
- */
-
-#include <il_remote.h>
-#include <generic.h>
-#include <packet_client.h>
-#include <ipc/services.h>
-#include <ipc/il.h>
-#include <net/device.h>
-#include <net/packet.h>
-
-/** Notify the internetwork layer modules about the device state change.
- *
- * @param[in] sess      Internetwork layer module session.
- * @param[in] device_id Device identifier.
- * @param[in] state     New device state.
- * @param[in] target    Target internetwork module service to be
- *                      delivered to.
- *
- * @return EOK on success.
- *
- */
-int il_device_state_msg(async_sess_t *sess, nic_device_id_t device_id,
-    nic_device_state_t state, services_t target)
-{
-	return generic_device_state_msg_remote(sess, NET_IL_DEVICE_STATE,
-	    device_id, state, target);
-}
-
-/** Notify the internetwork layer modules about the received packet/s.
- *
- * @param[in] sess      Internetwork layer module session.
- * @param[in] device_id Device identifier.
- * @param[in] packet    Received packet or the received packet queue.
- * @param[in] target    Target internetwork module service to be
- *                      delivered to.
- *
- * @return EOK on success.
- *
- */
-int il_received_msg(async_sess_t *sess, nic_device_id_t device_id,
-    packet_t *packet, services_t target)
-{
-	return generic_received_msg_remote(sess, NET_IL_RECEIVED, device_id,
-	    packet_get_id(packet), target, 0);
-}
-
-/** Notify the internetwork layer modules about the mtu change.
- *
- * @param[in] sess      Internetwork layer module session.
- * @param[in] device_id Device identifier.
- * @param[in] mtu       New MTU value.
- * @param[in] target    Target internetwork module service to be
- *                      delivered to.
- *
- * @return EOK on success.
- *
- */
-int il_mtu_changed_msg(async_sess_t *sess, nic_device_id_t device_id, size_t mtu,
-    services_t target)
-{
-	return generic_device_state_msg_remote(sess, NET_IL_MTU_CHANGED,
-	    device_id, mtu, target);
-}
-
-/** Notify IL layer modules about address change (implemented by ARP)
- *
- */
-int il_addr_changed_msg(async_sess_t *sess, nic_device_id_t device_id,
-    size_t addr_len, const uint8_t *address)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	aid_t message_id = async_send_1(exch, NET_IL_ADDR_CHANGED,
-			(sysarg_t) device_id, NULL);
-	int rc = async_data_write_start(exch, address, addr_len);
-	
-	async_exchange_end(exch);
-	
-	sysarg_t res;
-    async_wait_for(message_id, &res);
-    if (rc != EOK)
-		return rc;
-	
-    return (int) res;
-}
-
-/** @}
- */
Index: pace/lib/net/il/il_skel.c
===================================================================
--- uspace/lib/net/il/il_skel.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,128 +1,0 @@
-/*
- * Copyright (c) 2011 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 libnet
- * @{
- */
-
-/** @file
- * Internetworking layer module skeleton implementation.
- * @see il_skel.h
- */
-
-#include <bool.h>
-#include <errno.h>
-#include <ns.h>
-#include <il_skel.h>
-#include <net_interface.h>
-#include <net/modules.h>
-
-/** Default thread for new connections.
- *
- * @param[in] iid   The initial message identifier.
- * @param[in] icall The initial message call structure.
- *
- */
-static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg)
-{
-	/*
-	 * Accept the connection by answering
-	 * the initial IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		size_t count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = il_module_message(callid, &call, &answer,
-		    &count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, count);
-	}
-}
-
-/** Start the internetworking layer module.
- *
- * Initialize the client connection serving function, initialize
- * the module, register the module service and start the async
- * manager, processing IPC messages in an infinite loop.
- *
- * @param[in] service Service identification.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the pm_init() function.
- * @return Other error codes as defined for the il_initialize()
- *         function.
- *
- */
-int il_module_start(sysarg_t service)
-{
-	async_set_client_connection(il_client_connection);
-	async_sess_t *sess = net_connect_module();
-	if (!sess)
-		return ENOENT;
-	
-	int rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	rc = il_initialize(sess);
-	if (rc != EOK)
-		goto out;
-	
-	rc = service_register(service);
-	if (rc != EOK)
-		goto out;
-	
-	async_manager();
-	
-out:
-	pm_destroy();
-	return rc;
-}
-
-/** @}
- */
Index: pace/lib/net/il/ip_client.c
===================================================================
--- uspace/lib/net/il/ip_client.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,268 +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
- * IP client interface implementation.
- * @see ip_client.h
- */
-
-#include <errno.h>
-#include <sys/types.h>
-
-#include <ip_client.h>
-#include <packet_client.h>
-#include <ip_header.h>
-
-#include <net/packet.h>
-
-/** Returns the IP header length.
- *
- * @param[in] packet	The packet.
- * @return		The IP header length in bytes.
- * @return		Zero if there is no IP header.
- */
-size_t ip_client_header_length(packet_t *packet)
-{
-	ip_header_t *header;
-
-	header = (ip_header_t *) packet_get_data(packet);
-	if (!header || (packet_get_data_length(packet) < sizeof(ip_header_t)))
-		return 0;
-
-	return IP_HEADER_LENGTH(header);
-}
-
-/** Constructs the IPv4 pseudo header.
- *
- * @param[in] protocol	The transport protocol.
- * @param[in] src	The source address.
- * @param[in] srclen	The source address length.
- * @param[in] dest	The destination address.
- * @param[in] destlen	The destination address length.
- * @param[in] data_length The data length to be set.
- * @param[out] header	The constructed IPv4 pseudo header.
- * @param[out] headerlen The length of the IP pseudo header in bytes.
- * @return		EOK on success.
- * @return		EBADMEM if the header and/or the headerlen parameter is
- *			NULL.
- * @return		EINVAL if the source address and/or the destination
- *			address parameter is NULL.
- * @return		EINVAL if the source address length is less than struct
- *			sockaddr length.
- * @return		EINVAL if the source address length differs from the
- *			destination address length.
- * @return		EINVAL if the source address family differs from the
- *			destination family.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		ENOMEM if there is not enough memory left.
- */
-int
-ip_client_get_pseudo_header(ip_protocol_t protocol, struct sockaddr *src,
-    socklen_t srclen, struct sockaddr *dest, socklen_t destlen,
-    size_t data_length, void **header, size_t *headerlen)
-{
-	ipv4_pseudo_header_t *header_in;
-	struct sockaddr_in *address_in;
-
-	if (!header || !headerlen)
-		return EBADMEM;
-
-	if (!src || !dest || srclen <= 0 ||
-	    (((size_t) srclen < sizeof(struct sockaddr))) ||
-	    (srclen != destlen) || (src->sa_family != dest->sa_family)) {
-		return EINVAL;
-	}
-
-	switch (src->sa_family) {
-	case AF_INET:
-		if (srclen != sizeof(struct sockaddr_in))
-			return EINVAL;
-		
-		*headerlen = sizeof(*header_in);
-		header_in = (ipv4_pseudo_header_t *) malloc(*headerlen);
-		if (!header_in)
-			return ENOMEM;
-
-		bzero(header_in, *headerlen);
-		address_in = (struct sockaddr_in *) dest;
-		header_in->destination_address = address_in->sin_addr.s_addr;
-		address_in = (struct sockaddr_in *) src;
-		header_in->source_address = address_in->sin_addr.s_addr;
-		header_in->protocol = protocol;
-		header_in->data_length = htons(data_length);
-		*header = header_in;
-		return EOK;
-
-	// TODO IPv6
-#if 0
-	case AF_INET6:
-		if (addrlen != sizeof(struct sockaddr_in6))
-			return EINVAL;
-
-		address_in6 = (struct sockaddr_in6 *) addr;
-		return EOK;
-#endif
-
-	default:
-		return EAFNOSUPPORT;
-	}
-}
-
-/** Prepares the packet to be transfered via IP.
- *
- * The IP header is prefixed.
- *
- * @param[in,out] packet The packet to be prepared.
- * @param[in] protocol	The transport protocol.
- * @param[in] ttl	The time to live counter. The IPDEFTTL is set if zero.
- * @param[in] tos	The type of service.
- * @param[in] dont_fragment The value indicating whether fragmentation is
- *			disabled.
- * @param[in] ipopt_length The prefixed IP options length in bytes.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left in the packet.
- */
-int
-ip_client_prepare_packet(packet_t *packet, ip_protocol_t protocol, ip_ttl_t ttl,
-    ip_tos_t tos, int dont_fragment, size_t ipopt_length)
-{
-	ip_header_t *header;
-	uint8_t *data;
-	size_t padding;
-
-	/*
-	 * Compute the padding if IP options are set
-	 * multiple of 4 bytes
-	 */
-	padding =  ipopt_length % 4;
-	if (padding) {
-		padding = 4 - padding;
-		ipopt_length += padding;
-	}
-
-	/* Prefix the header */
-	data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding);
-	if (!data)
-		return ENOMEM;
-
-	/* Add the padding */
-	while (padding--)
-		data[sizeof(ip_header_t) + padding] = IPOPT_NOOP;
-
-	/* Set the header */
-	header = (ip_header_t *) data;
-	SET_IP_HEADER_LENGTH(header,
-	    (IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) + ipopt_length)));
-	header->ttl = (ttl ? ttl : IPDEFTTL);
-	header->tos = tos;
-	header->protocol = protocol;
-
-	if (dont_fragment)
-		SET_IP_HEADER_FLAGS(header, IPFLAG_DONT_FRAGMENT);
-
-	return EOK;
-}
-
-/** Processes the received IP packet.
- *
- * Fills set header fields.
- * Returns the prefixed IP header length.
- *
- * @param[in] packet	The received packet.
- * @param[out] protocol	The transport protocol. May be NULL if not desired.
- * @param[out] ttl	The time to live counter. May be NULL if not desired.
- * @param[out] tos	The type of service. May be NULL if not desired.
- * @param[out] dont_fragment The value indicating whether the fragmentation is
- *			disabled. May be NULL if not desired.
- * @param[out] ipopt_length The IP options length in bytes. May be NULL if not
- *			desired.
- * @return		The prefixed IP header length in bytes on success.
- * @return		ENOMEM if the packet is too short to contain the IP
- *			header.
- */
-int
-ip_client_process_packet(packet_t *packet, ip_protocol_t *protocol,
-    ip_ttl_t *ttl, ip_tos_t *tos, int *dont_fragment, size_t *ipopt_length)
-{
-	ip_header_t *header;
-
-	header = (ip_header_t *) packet_get_data(packet);
-	if (!header || (packet_get_data_length(packet) < sizeof(ip_header_t)))
-		return ENOMEM;
-
-	if (protocol)
-		*protocol = header->protocol;
-	if (ttl)
-		*ttl = header->ttl;
-	if (tos)
-		*tos = header->tos;
-	if (dont_fragment)
-		*dont_fragment = GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT;
-	if (ipopt_length) {
-		*ipopt_length = IP_HEADER_LENGTH(header) - sizeof(ip_header_t);
-		return sizeof(ip_header_t);
-	} else {
-		return IP_HEADER_LENGTH(header);
-	}
-}
-
-/** Updates the IPv4 pseudo header data length field.
- *
- * @param[in,out] header The IPv4 pseudo header to be updated.
- * @param[in] headerlen	The length of the IP pseudo header in bytes.
- * @param[in] data_length The data length to be set.
- * @return		EOK on success.
- * @return		EBADMEM if the header parameter is NULL.
- * @return		EINVAL if the headerlen parameter is not IPv4 pseudo
- *			header length.
- */
-int
-ip_client_set_pseudo_header_data_length(void *header, size_t headerlen,
-    size_t data_length)
-{
-	ipv4_pseudo_header_t *header_in;
-
-	if (!header)
-		return EBADMEM;
-
-	if (headerlen == sizeof(ipv4_pseudo_header_t)) {
-		header_in = (ipv4_pseudo_header_t *) header;
-		header_in->data_length = htons(data_length);
-		return EOK;
-	// TODO IPv6
-	} else {
-		return EINVAL;
-	}
-}
-
-/** @}
- */
Index: pace/lib/net/il/ip_remote.c
===================================================================
--- uspace/lib/net/il/ip_remote.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,270 +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
- *
- * IP interface implementation for remote modules.
- *
- * @see ip_interface.h
- * @see il_remote.h
- *
- */
-
-#include <ip_remote.h>
-#include <ip_interface.h>
-#include <packet_client.h>
-#include <generic.h>
-#include <ipc/services.h>
-#include <ipc/il.h>
-#include <ipc/ip.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <net/inet.h>
-
-/** Add a route to the device routing table.
- *
- * The target network is routed using this device.
- *
- * @param[in] sess      IP module sessions.
- * @param[in] device_id Device identifier.
- * @param[in] address   Target network address.
- * @param[in] netmask   Target network mask.
- * @param[in] gateway   Target network gateway. Not used if zero.
- *
- */
-int ip_add_route_req_remote(async_sess_t *sess, nic_device_id_t device_id,
-    in_addr_t address, in_addr_t netmask, in_addr_t gateway)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_4_0(exch, NET_IP_ADD_ROUTE,
-	    (sysarg_t) device_id, (sysarg_t) gateway.s_addr,
-	    (sysarg_t) address.s_addr, (sysarg_t) netmask.s_addr);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-/** Create bidirectional connection with the ip module service and register
- * the message receiver.
- *
- * @param[in] service  IP module service.
- * @param[in] protocol Transport layer protocol.
- * @param[in] me       Rquesting module service.
- * @param[in] receiver Message receiver. Used for remote connection.
- *
- * @return Session to the needed service.
- * @return NULL on failure.
- *
- */
-async_sess_t *ip_bind_service(services_t service, int protocol, services_t me,
-    async_client_conn_t receiver)
-{
-	return bind_service(service, (sysarg_t) protocol, me, service,
-	    receiver);
-}
-
-/** Connect to the IP module.
- *
- * @return The IP module session.
- *
- */
-async_sess_t *ip_connect_module(services_t service)
-{
-	// FIXME: Get rid of the useless argument
-	return connect_to_service(SERVICE_IP);
-}
-
-/** Register the new device.
- *
- * Register itself as the ip packet receiver.
- * If the device uses ARP registers also the new ARP device.
- *
- * @param[in] sess      IP module session.
- * @param[in] device_id New device identifier.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- * @return EINVAL if the device configuration is invalid.
- * @return ENOTSUP if the device uses IPv6.
- * @return ENOTSUP if the device uses DHCP.
- * @return Other error codes as defined for the
- *         net_get_device_conf_req() function.
- * @return Other error codes as defined for the arp_device_req()
- *         function.
- *
- */
-int ip_device_req(async_sess_t *sess, nic_device_id_t device_id,
-    services_t service)
-{
-	return generic_device_req_remote(sess, NET_IP_DEVICE, device_id,
-	    service);
-}
-
-/** Return the device identifier and the IP pseudo header based on the
- * destination address.
- *
- * @param[in] sess        IP module session.
- * @param[in] protocol    Transport protocol.
- * @param[in] destination Destination address.
- * @param[in] addrlen     Destination address length.
- * @param[out] device_id  Device identifier.
- * @param[out] header     Constructed IP pseudo header.
- * @param[out] headerlen  IP pseudo header length.
- *
- */
-int ip_get_route_req_remote(async_sess_t *sess, ip_protocol_t protocol,
-    const struct sockaddr *destination, socklen_t addrlen,
-    nic_device_id_t *device_id, void **header, size_t *headerlen)
-{
-	if ((!destination) || (addrlen == 0))
-		return EINVAL;
-	
-	if ((!device_id) || (!header) || (!headerlen))
-		return EBADMEM;
-	
-	*header = NULL;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	ipc_call_t answer;
-	aid_t message_id = async_send_1(exch, NET_IP_GET_ROUTE,
-	    (sysarg_t) protocol, &answer);
-	
-	if ((async_data_write_start(exch, destination, addrlen) == EOK) &&
-	    (async_data_read_start(exch, headerlen, sizeof(*headerlen)) == EOK) &&
-	    (*headerlen > 0)) {
-		*header = malloc(*headerlen);
-		if (*header) {
-			if (async_data_read_start(exch, *header,
-			    *headerlen) != EOK)
-				free(*header);
-		}
-	}
-	
-	async_exchange_end(exch);
-	
-	sysarg_t result;
-	async_wait_for(message_id, &result);
-	
-	if ((result != EOK) && *header)
-		free(*header);
-	else
-		*device_id = IPC_GET_DEVICE(answer);
-	
-	return (int) result;
-}
-
-/** Return the device packet dimension for sending.
- *
- * @param[in] sess              IP module session.
- * @param[in] device_id         Device identifier.
- * @param[out] packet_dimension Packet dimension.
- *
- * @return EOK on success.
- * @return ENOENT if there is no such device.
- * @return Other error codes as defined for the
- *         generic_packet_size_req_remote() function.
- *
- */
-int ip_packet_size_req_remote(async_sess_t *sess, nic_device_id_t device_id,
-    packet_dimension_t *packet_dimension)
-{
-	return generic_packet_size_req_remote(sess, NET_IP_PACKET_SPACE,
-	    device_id, packet_dimension);
-}
-
-/** Notify the IP module about the received error notification packet.
- *
- * @param[in] sess      IP module session.
- * @param[in] device_id Device identifier.
- * @param[in] packet    Received packet or the received packet queue.
- * @param[in] target    Target internetwork module service to be
- *                      delivered to.
- * @param[in] error     Packet error reporting service. Prefixes the
- *                      received packet.
- *
- * @return EOK on success.
- *
- */
-int ip_received_error_msg_remote(async_sess_t *sess, nic_device_id_t device_id,
-    packet_t *packet, services_t target, services_t error)
-{
-	return generic_received_msg_remote(sess, NET_IP_RECEIVED_ERROR,
-	    device_id, packet_get_id(packet), target, error);
-}
-
-/** Send the packet queue.
- *
- * The packets may get fragmented if needed.
- *
- * @param[in] sess      IP module session.
- * @param[in] device_id Device identifier.
- * @param[in] packet    Packet fragments as a packet queue. All the
- *                      packets have to have the same destination address.
- * @param[in] sender    Sending module service.
- * @param[in] error     Packet error reporting service. Prefixes the
- *                      received packet.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the generic_send_msg()
- *         function.
- *
- */
-int ip_send_msg_remote(async_sess_t *sess, nic_device_id_t device_id,
-    packet_t *packet, services_t sender, services_t error)
-{
-	return generic_send_msg_remote(sess, NET_IP_SEND, device_id,
-	    packet_get_id(packet), sender, error);
-}
-
-/** Set the default gateway.
- *
- * This gateway is used if no other route is found.
- *
- * @param[in] sess      IP module session.
- * @param[in] device_id Device identifier.
- * @param[in] gateway   Default gateway.
- *
- */
-int ip_set_gateway_req_remote(async_sess_t *sess, nic_device_id_t device_id,
-    in_addr_t gateway)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_2_0(exch, NET_IP_SET_GATEWAY,
-	    (sysarg_t) device_id, (sysarg_t) gateway.s_addr);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-/** @}
- */
Index: pace/lib/net/include/adt/module_map.h
===================================================================
--- uspace/lib/net/include/adt/module_map.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,82 +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
- * Character string to module map.
- */
-
-#ifndef LIBNET_MODULES_MAP_H_
-#define LIBNET_MODULES_MAP_H_
-
-#include <task.h>
-#include <async.h>
-#include <net/modules.h>
-#include <adt/generic_char_map.h>
-
-/** Type definition of the module structure.
- * @see module_struct
- */
-typedef struct module_struct module_t;
-
-/** Module map.
- * Sorted by module names.
- * @see generic_char_map.h
- */
-GENERIC_CHAR_MAP_DECLARE(modules, module_t)
-
-/** Module structure. */
-struct module_struct {
-	/** Module task identifier if running. */
-	task_id_t task_id;
-	/** Module service identifier. */
-	services_t service;
-	/** Module session if running and connected. */
-	async_sess_t *sess;
-	/** Usage counter. */
-	int usage;
-	/** Module name. */
-	const uint8_t *name;
-	/** Module full path filename. */
-	const uint8_t *filename;
-	/** Connecting function. */
-	connect_module_t *connect_module;
-};
-
-extern int add_module(module_t **, modules_t *, const uint8_t *,
-    const uint8_t *, services_t, task_id_t, connect_module_t *);
-extern module_t *get_running_module(modules_t *, uint8_t *);
-extern task_id_t net_spawn(const uint8_t *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/arp_interface.h
===================================================================
--- uspace/lib/net/include/arp_interface.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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 libnet
- * @{
- */
-
-#ifndef LIBNET_ARP_INTERFACE_H_
-#define LIBNET_ARP_INTERFACE_H_
-
-#include <adt/measured_strings.h>
-#include <task.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <net/socket.h>
-#include <async.h>
-
-/** @name ARP module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-extern int arp_device_req(async_sess_t *, nic_device_id_t, services_t, services_t,
-    measured_string_t *);
-extern int arp_translate_req(async_sess_t *, nic_device_id_t, services_t,
-    measured_string_t *, measured_string_t **, uint8_t **);
-extern int arp_clear_device_req(async_sess_t *, nic_device_id_t);
-extern int arp_clear_address_req(async_sess_t *, nic_device_id_t, services_t,
-    measured_string_t *);
-extern int arp_clean_cache_req(async_sess_t *);
-extern async_sess_t *arp_connect_module(services_t);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/ethernet_lsap.h
===================================================================
--- uspace/lib/net/include/ethernet_lsap.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,64 +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
- * Link service access point identifiers.
- */
-
-#ifndef LIBNET_ETHERNET_LSAP_H_
-#define LIBNET_ETHERNET_LSAP_H_
-
-#include <sys/types.h>
-
-/** Ethernet LSAP type definition. */
-typedef uint8_t eth_lsap_t;
-
-/** @name Ethernet LSAP values definitions */
-/*@{*/
-
-/** Null LSAP LSAP identifier. */
-#define ETH_LSAP_NULL	0x00
-/** ARPANET Internet Protocol (IP) LSAP identifier. */
-#define ETH_LSAP_IP	0x06
-/** ARPANET Address Resolution Protocol (ARP) LSAP identifier. */
-#define ETH_LSAP_ARP	0x98
-/** SubNetwork Access Protocol (SNAP) LSAP identifier. */
-#define ETH_LSAP_SNAP	0xAA
-/** Global LSAP LSAP identifier. */
-#define ETH_LSAP_GLSAP	0xFF
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/ethernet_protocols.h
===================================================================
--- uspace/lib/net/include/ethernet_protocols.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,66 +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
- * Ethernet protocol numbers according to the on-line IANA - Ethernet numbers
- * http://www.iana.org/assignments/ethernet-numbers
- * cited January 17 2009.
- */
-
-#ifndef LIBNET_ETHERNET_PROTOCOLS_H_
-#define LIBNET_ETHERNET_PROTOCOLS_H_
-
-#include <sys/types.h>
-
-/** Ethernet protocol type definition. */
-typedef uint16_t eth_type_t;
-
-/** @name Ethernet protocols definitions */
-/*@{*/
-
-/** Ethernet minimal protocol number.
- * According to the IEEE 802.3 specification.
- */
-#define ETH_MIN_PROTO		0x0600 /* 1536 */
-
-/** Internet IP (IPv4) ethernet protocol type. */
-#define ETH_P_IP		0x0800
-
-/** ARP ethernet protocol type. */
-#define ETH_P_ARP		0x0806
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/generic.h
===================================================================
--- uspace/lib/net/include/generic.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,64 +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
- * Generic communication interfaces for networking.
- */
-
-#ifndef LIBNET_GENERIC_H_
-#define LIBNET_GENERIC_H_
-
-#include <ipc/services.h>
-#include <net/device.h>
-#include <adt/measured_strings.h>
-#include <net/packet.h>
-#include <async.h>
-
-extern int generic_device_state_msg_remote(async_sess_t *, sysarg_t,
-    nic_device_id_t, sysarg_t, services_t);
-extern int generic_device_req_remote(async_sess_t *, sysarg_t, nic_device_id_t,
-    services_t);
-extern int generic_get_addr_req(async_sess_t *, sysarg_t, nic_device_id_t,
-    uint8_t *address, size_t max_length);
-extern int generic_packet_size_req_remote(async_sess_t *, sysarg_t,
-    nic_device_id_t, packet_dimension_t *);
-extern int generic_received_msg_remote(async_sess_t *, sysarg_t,
-    nic_device_id_t, packet_id_t, services_t, services_t);
-extern int generic_send_msg_remote(async_sess_t *, sysarg_t, nic_device_id_t,
-    packet_id_t, services_t, services_t);
-extern int generic_translate_req(async_sess_t *, sysarg_t, nic_device_id_t,
-    services_t, measured_string_t *, size_t, measured_string_t **, uint8_t **);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/icmp_client.h
===================================================================
--- uspace/lib/net/include/icmp_client.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,50 +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
- * ICMP client interface.
- */
-
-#ifndef LIBNET_ICMP_CLIENT_H_
-#define LIBNET_ICMP_CLIENT_H_
-
-#include <net/icmp_codes.h>
-#include <net/packet.h>
-
-extern int icmp_client_process_packet(packet_t *, icmp_type_t *, icmp_code_t *,
-    icmp_param_t *, icmp_param_t *);
-extern size_t icmp_client_header_length(packet_t *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/icmp_header.h
===================================================================
--- uspace/lib/net/include/icmp_header.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,104 +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
- * ICMP header definition.
- * Based on the RFC 792.
- */
-
-#ifndef LIBNET_ICMP_HEADER_H_
-#define LIBNET_ICMP_HEADER_H_
-
-#include <sys/types.h>
-
-#include <net/in.h>
-#include <net/icmp_codes.h>
-
-/** ICMP header size in bytes. */
-#define ICMP_HEADER_SIZE  sizeof(icmp_header_t)
-
-/** Echo specific data. */
-typedef struct icmp_echo {
-	/** Message idintifier. */
-	icmp_param_t identifier;
-	/** Message sequence number. */
-	icmp_param_t sequence_number;
-} __attribute__((packed)) icmp_echo_t;
-
-/** Internet control message header. */
-typedef struct icmp_header {
-	/** The type of the message. */
-	uint8_t type;
-	
-	/**
-	 * The error code for the datagram reported by the ICMP message.
-	 * The interpretation is dependent on the message type.
-	 */
-	uint8_t code;
-	
-	/**
-	 * The checksum is the 16-bit ones's complement of the one's complement
-	 * sum of the ICMP message starting with the ICMP Type. For computing
-	 * the checksum, the checksum field should be zero. If the checksum does
-	 * not match the contents, the datagram is discarded.
-	 */
-	uint16_t checksum;
-	
-	/** Message specific data. */
-	union {
-		/** Echo specific data. */
-		icmp_echo_t echo;
-		/** Proposed gateway value. */
-		in_addr_t gateway;
-		
-		/** Fragmentation needed specific data. */
-		struct {
-			/** Reserved field. Must be zero. */
-			icmp_param_t reserved;
-			/** Proposed MTU. */
-			icmp_param_t mtu;
-		} frag;
-		
-		/** Parameter problem specific data. */
-		struct {
-			/** Problem pointer. */
-			icmp_param_t pointer;
-			/** Reserved field. Must be zero. */
-			icmp_param_t reserved;
-		} param;
-	} un;
-} __attribute__((packed)) icmp_header_t;
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/icmp_remote.h
===================================================================
--- uspace/lib/net/include/icmp_remote.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,64 +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
- *  @{
- */
-
-#ifndef LIBNET_ICMP_REMOTE_H_
-#define LIBNET_ICMP_REMOTE_H_
-
-#include <net/socket_codes.h>
-#include <sys/types.h>
-#include <net/device.h>
-#include <adt/measured_strings.h>
-#include <net/packet.h>
-#include <net/inet.h>
-#include <net/ip_codes.h>
-#include <net/icmp_codes.h>
-#include <net/icmp_common.h>
-#include <async.h>
-
-/** @name ICMP module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-extern int icmp_destination_unreachable_msg(async_sess_t *, icmp_code_t,
-    icmp_param_t, packet_t *);
-extern int icmp_source_quench_msg(async_sess_t *, packet_t *);
-extern int icmp_time_exceeded_msg(async_sess_t *, icmp_code_t, packet_t *);
-extern int icmp_parameter_problem_msg(async_sess_t *, icmp_code_t, icmp_param_t,
-    packet_t *);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/il_remote.h
===================================================================
--- uspace/lib/net/include/il_remote.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,66 +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
- * Internetwork layer module interface for the underlying network interface
- * layer. This interface is always called by the remote modules.
- */
-
-#ifndef LIBNET_IL_REMOTE_H_
-#define LIBNET_IL_REMOTE_H_
-
-#include <ipc/services.h>
-#include <sys/types.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <async.h>
-
-/** @name Internetwork layer module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-extern int il_device_state_msg(async_sess_t *, nic_device_id_t,
-    nic_device_state_t, services_t);
-extern int il_received_msg(async_sess_t *, nic_device_id_t, packet_t *,
-    services_t);
-extern int il_mtu_changed_msg(async_sess_t *, nic_device_id_t, size_t,
-    services_t);
-extern int il_addr_changed_msg(async_sess_t *, nic_device_id_t, size_t,
-    const uint8_t *);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/il_skel.h
===================================================================
--- uspace/lib/net/include/il_skel.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,81 +1,0 @@
-/*
- * Copyright (c) 2010 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 libnet
- * @{
- */
-
-#ifndef LIBNET_IL_SKEL_H_
-#define LIBNET_IL_SKEL_H_
-
-/** @file
- * Internetwork layer module skeleton.
- * The skeleton has to be part of each internetwork layer module.
- */
-
-#include <ipc/services.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <async.h>
-
-/** Module initialization.
- *
- * This has to be implemented in user code.
- *
- * @param[in] sess Networking module session.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module
- *         initialize function.
- *
- */
-extern int il_initialize(async_sess_t *sess);
-
-/** Process the internetwork layer module message.
- *
- * This has to be implemented in user code.
- *
- * @param[in]  callid Message identifier.
- * @param[in]  call   Message parameters.
- * @param[out] answer Answer.
- * @param[out] count  Number of arguments of the answer.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module.
- *
- */
-extern int il_module_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count);
-
-extern int il_module_start(sysarg_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/ip_client.h
===================================================================
--- uspace/lib/net/include/ip_client.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,61 +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
- * IP client interface.
- */
-
-#ifndef LIBNET_IP_CLIENT_H_
-#define LIBNET_IP_CLIENT_H_
-
-#include <net/socket_codes.h>
-#include <sys/types.h>
-
-#include <net/packet.h>
-#include <net/ip_codes.h>
-#include <ip_interface.h>
-
-extern int ip_client_prepare_packet(packet_t *, ip_protocol_t, ip_ttl_t,
-    ip_tos_t, int, size_t);
-extern int ip_client_process_packet(packet_t *, ip_protocol_t *, ip_ttl_t *,
-    ip_tos_t *, int *, size_t *);
-extern size_t ip_client_header_length(packet_t *);
-extern int ip_client_set_pseudo_header_data_length(void *, size_t, size_t);
-extern int ip_client_get_pseudo_header(ip_protocol_t, struct sockaddr *,
-    socklen_t, struct sockaddr *, socklen_t, size_t, void **, size_t *);
-
-// TODO ipopt manipulation
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/ip_header.h
===================================================================
--- uspace/lib/net/include/ip_header.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,223 +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
- * IP header and options definitions.
- * Based on the RFC 791.
- */
-
-#ifndef LIBNET_IP_HEADER_H_
-#define LIBNET_IP_HEADER_H_
-
-#include <byteorder.h>
-#include <sys/types.h>
-
-/** Returns the fragment offest high bits.
- * @param[in] length The prefixed data total length.
- */
-#define IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length) \
-	((((length) / 8U) & 0x1f00) >> 8)
-
-/** Returns the fragment offest low bits.
- * @param[in] length The prefixed data total length.
- */
-#define IP_COMPUTE_FRAGMENT_OFFSET_LOW(length) \
-	(((length) / 8U) & 0xff)
-
-/** Returns the IP header length.
- * @param[in] length The IP header length in bytes.
- */
-#define IP_COMPUTE_HEADER_LENGTH(length) \
-	((uint8_t) ((length) / 4U))
-
-/** Returns the fragment offest.
- * @param[in] header The IP packet header.
- */
-#define IP_FRAGMENT_OFFSET(header) \
-	(((GET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header) << 8) + \
-	    (header)->fragment_offset_low) * 8U)
-
-/** Returns the IP packet header checksum.
- *  @param[in] header The IP packet header.
- */
-#define IP_HEADER_CHECKSUM(header) \
-	(htons(ip_checksum((uint8_t *) (header), IP_HEADER_LENGTH(header))))
-
-/** Returns the actual IP packet data length.
- * @param[in] header The IP packet header.
- */
-#define IP_HEADER_DATA_LENGTH(header) \
-	(IP_TOTAL_LENGTH(header) - IP_HEADER_LENGTH(header))
-
-/** Returns the actual IP header length in bytes.
- * @param[in] header The IP packet header.
- */
-#define IP_HEADER_LENGTH(header) \
-	(GET_IP_HEADER_LENGTH(header) * 4U)
-
-/** Returns the actual IP packet total length.
- * @param[in] header The IP packet header.
- */
-#define IP_TOTAL_LENGTH(header) \
-	ntohs((header)->total_length)
-
-/** @name IP flags definitions */
-/*@{*/
-
-/** Fragment flag field shift. */
-#define IPFLAG_FRAGMENT_SHIFT	1
-
-/** Fragmented flag field shift. */
-#define IPFLAG_FRAGMENTED_SHIFT	0
-
-/** Don't fragment flag value.
- * Permits the packet fragmentation.
- */
-#define IPFLAG_DONT_FRAGMENT	(0x1 << IPFLAG_FRAGMENT_SHIFT)
-
-/** Last fragment flag value.
- * Indicates the last packet fragment.
- */
-#define IPFLAG_LAST_FRAGMENT	(0x0 << IPFLAG_FRAGMENTED_SHIFT)
-
-/** May fragment flag value.
- * Allows the packet fragmentation.
- */
-#define IPFLAG_MAY_FRAGMENT	(0x0 << IPFLAG_FRAGMENT_SHIFT)
-
-/** More fragments flag value.
- * Indicates that more packet fragments follow.
- */
-#define IPFLAG_MORE_FRAGMENTS	(0x1 << IPFLAG_FRAGMENTED_SHIFT)
-
-/*@}*/
-
-/** Type definition of the internet header.
- * @see ip_header
- */
-typedef struct ip_header ip_header_t;
-
-/** Type definition of the internet option header.
- * @see ip_header
- */
-typedef struct ip_option ip_option_t;
-
-/** Type definition of the internet version 4 pseudo header.
- * @see ipv4_pseudo_header
- */
-typedef struct ipv4_pseudo_header ipv4_pseudo_header_t;
-
-/** Internet header.
- *
- * The variable options should be included after the header itself and
- * indicated by the increased header length value.
- */
-struct ip_header {
-	uint8_t vhl; /* version, header_length */
-
-#define GET_IP_HEADER_VERSION(header) \
-	(((header)->vhl & 0xf0) >> 4)
-#define SET_IP_HEADER_VERSION(header, version) \
-	((header)->vhl = \
-	 ((version & 0x0f) << 4) | ((header)->vhl & 0x0f))
-
-#define GET_IP_HEADER_LENGTH(header) \
-	((header)->vhl & 0x0f)
-#define SET_IP_HEADER_LENGTH(header, length) \
-	((header)->vhl = \
-	 (length & 0x0f) | ((header)->vhl & 0xf0))
-
-	uint8_t tos;
-	uint16_t total_length;
-	uint16_t identification;
-
-	uint8_t ffoh; /* flags, fragment_offset_high */
-
-#define GET_IP_HEADER_FLAGS(header) \
-	(((header)->ffoh & 0xe0) >> 5)
-#define SET_IP_HEADER_FLAGS(header, flags) \
-	((header)->ffoh = \
-	 ((flags & 0x07) << 5) | ((header)->ffoh & 0x1f))
-
-#define GET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header) \
-	((header)->ffoh & 0x1f)
-#define SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, fragment_offset_high) \
-	((header)->ffoh = \
-	 (fragment_offset_high & 0x1f) | ((header)->ffoh & 0xe0))
-
-	uint8_t fragment_offset_low;
-	uint8_t ttl;
-	uint8_t protocol;
-	uint16_t header_checksum;
-	uint32_t source_address;
-	uint32_t destination_address;
-} __attribute__ ((packed));
-
-/** Internet option header.
- *
- * Only type field is always valid.
- * Other fields' validity depends on the option type.
- */
-struct ip_option {
-	uint8_t type;
-	uint8_t length;
-	uint8_t pointer;
-
-	uint8_t of; /* overflow, flags */
-
-#define GET_IP_OPTION_OVERFLOW(option) \
-	(((option)->of & 0xf0) >> 4)
-#define SET_IP_OPTION_OVERFLOW(option, overflow) \
-	((option)->of = \
-	 ((overflow & 0x0f) << 4) | ((option)->of & 0x0f))
-
-#define GET_IP_OPTION_FLAGS(option) \
-	((option)->of & 0x0f)
-#define SET_IP_OPTION_FLAGS(option, flags) \
-	((option)->of = \
-	 (flags & 0x0f) | ((option)->of & 0xf0))
-
-} __attribute__ ((packed));
-
-/** Internet version 4 pseudo header. */
-struct ipv4_pseudo_header {
-	uint32_t source_address;
-	uint32_t destination_address;
-	uint8_t reserved;
-	uint8_t protocol;
-	uint16_t data_length;
-} __attribute__ ((packed));
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/ip_interface.h
===================================================================
--- uspace/lib/net/include/ip_interface.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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 libnet 
- * @{
- */
-
-#ifndef LIBNET_IP_INTERFACE_H_
-#define LIBNET_IP_INTERFACE_H_
-
-#include <net/socket_codes.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <net/in.h>
-#include <net/ip_codes.h>
-#include <ip_remote.h>
-#include <async.h>
-
-#define ip_received_error_msg  ip_received_error_msg_remote
-#define ip_set_gateway_req     ip_set_gateway_req_remote
-#define ip_packet_size_req     ip_packet_size_req_remote
-#define ip_add_route_req       ip_add_route_req_remote
-#define ip_send_msg            ip_send_msg_remote
-#define ip_get_route_req       ip_get_route_req_remote
-
-/** @name IP module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-/** The transport layer notification function type definition.
- *
- * Notify the transport layer modules about the received packet/s.
- *
- * @param[in] device_id Device identifier.
- * @param[in] packet    Received packet or the received packet queue.
- * @param[in] receiver  Receiving module service.
- * @param[in] error     Packet error reporting service. Prefixes the
- *                      received packet.
- *
- * @return EOK on success.
- *
- */
-typedef int (*tl_received_msg_t)(nic_device_id_t device_id, packet_t *packet,
-    services_t receiver, services_t error);
-
-extern async_sess_t *ip_bind_service(services_t, int, services_t, async_client_conn_t);
-extern async_sess_t *ip_connect_module(services_t);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/ip_remote.h
===================================================================
--- uspace/lib/net/include/ip_remote.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,61 +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
- * @{
- */
-
-#ifndef LIBNET_IP_REMOTE_H_
-#define LIBNET_IP_REMOTE_H_
-
-#include <ipc/services.h>
-#include <net/ip_codes.h>
-#include <net/inet.h>
-#include <net/in.h>
-#include <net/packet.h>
-#include <net/device.h>
-#include <net/socket.h>
-#include <async.h>
-
-extern int ip_set_gateway_req_remote(async_sess_t *, nic_device_id_t, in_addr_t);
-extern int ip_packet_size_req_remote(async_sess_t *, nic_device_id_t,
-    packet_dimension_t *);
-extern int ip_received_error_msg_remote(async_sess_t *, nic_device_id_t, packet_t *,
-    services_t, services_t);
-extern int ip_device_req(async_sess_t *, nic_device_id_t, services_t);
-extern int ip_add_route_req_remote(async_sess_t *, nic_device_id_t, in_addr_t,
-    in_addr_t, in_addr_t);
-extern int ip_send_msg_remote(async_sess_t *, nic_device_id_t, packet_t *,
-    services_t, services_t);
-extern int ip_get_route_req_remote(async_sess_t *, ip_protocol_t,
-    const struct sockaddr *, socklen_t, nic_device_id_t *, void **, size_t *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/net_checksum.h
===================================================================
--- uspace/lib/net/include/net_checksum.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,73 +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
- * General CRC and checksum computation.
- */
-
-#ifndef LIBNET_CHECKSUM_H_
-#define LIBNET_CHECKSUM_H_
-
-#include <byteorder.h>
-#include <sys/types.h>
-
-/** IP checksum value for computed zero checksum.
- *
- * Zero is returned as 0xFFFF (not flipped)
- *
- */
-#define IP_CHECKSUM_ZERO  0xffffU
-
-#ifdef __BE__
-
-#define compute_crc32(seed, data, length) \
-	compute_crc32_be(seed, (uint8_t *) data, length)
-
-#endif
-
-#ifdef __LE__
-
-#define compute_crc32(seed, data, length) \
-	compute_crc32_le(seed, (uint8_t *) data, length)
-
-#endif
-
-extern uint32_t compute_crc32_le(uint32_t, uint8_t *, size_t);
-extern uint32_t compute_crc32_be(uint32_t, uint8_t *, size_t);
-extern uint32_t compute_checksum(uint32_t, uint8_t *, size_t);
-extern uint16_t compact_checksum(uint32_t);
-extern uint16_t flip_checksum(uint16_t);
-extern uint16_t ip_checksum(uint8_t *, size_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/net_hardware.h
===================================================================
--- uspace/lib/net/include/net_hardware.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,60 +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
- * Hardware types according to the on-line IANA - Address Resolution Protocol
- * (ARP) Parameters
- * http://www.iana.org/assignments/arp-parameters/arp-parameters.xml,
- * cited January 14 2009.
- */
-
-#ifndef LIBNET_NET_HARDWARE_H_
-#define LIBNET_NET_HARDWARE_H_
-
-#include <sys/types.h>
-
-/** Network interface layer type type definition. */
-typedef uint8_t hw_type_t;
-
-/** @name Network interface layer types definitions */
-/*@{*/
-
-/** Ethernet (10Mb) hardware type. */
-#define HW_ETHER		1
-
-/*@}*/
-
-#endif
-
-/** @}
- */
-
Index: pace/lib/net/include/net_interface.h
===================================================================
--- uspace/lib/net/include/net_interface.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,61 +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
- *  @{
- */
-
-#ifndef LIBNET_NET_INTERFACE_H_
-#define LIBNET_NET_INTERFACE_H_
-
-#include <ipc/services.h>
-#include <net/device.h>
-#include <adt/measured_strings.h>
-#include <async.h>
-#include <devman.h>
-
-/** @name Networking module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-extern int net_get_device_conf_req(async_sess_t *, nic_device_id_t,
-    measured_string_t **, size_t, uint8_t **);
-extern int net_get_conf_req(async_sess_t *, measured_string_t **, size_t,
-    uint8_t **);
-extern void net_free_settings(measured_string_t *, uint8_t *);
-extern int net_get_devices_req(async_sess_t *, measured_string_t **, size_t *,
-    uint8_t **);
-extern async_sess_t *net_connect_module(void);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/nil_remote.h
===================================================================
--- uspace/lib/net/include/nil_remote.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,68 +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 netif
- * @{
- */
-
-#ifndef __NET_NIL_REMOTE_H__
-#define __NET_NIL_REMOTE_H__
-
-#include <ipc/loc.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <devman.h>
-#include <generic.h>
-#include <async.h>
-#include <sys/types.h>
-
-#define nil_bind_service(service, device_id, me, receiver) \
-	bind_service(service, device_id, me, 0, receiver)
-
-#define nil_packet_size_req(sess, device_id, packet_dimension) \
-	generic_packet_size_req_remote(sess, NET_NIL_PACKET_SPACE, \
-	    device_id, packet_dimension)
-
-#define nil_get_addr_req(sess, device_id, address, data) \
-	generic_get_addr_req(sess, NET_NIL_ADDR, device_id, address, data)
-
-#define nil_get_broadcast_addr_req(sess, device_id, address, data) \
-	generic_get_addr_req(sess, NET_NIL_BROADCAST_ADDR, device_id, \
-	    address, data)
-
-#define nil_send_msg(sess, device_id, packet, sender) \
-	generic_send_msg_remote(sess, NET_NIL_SEND, device_id, \
-	    packet_get_id(packet), sender, 0)
-
-extern int nil_device_req(async_sess_t *, nic_device_id_t, devman_handle_t,
-    size_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/nil_skel.h
===================================================================
--- uspace/lib/net/include/nil_skel.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,116 +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
- * Network interface layer modules common skeleton.
- * All network interface layer modules have to implement this interface.
- */
-
-#ifndef LIBNET_NIL_SKEL_H_
-#define LIBNET_NIL_SKEL_H_
-
-#include <ipc/services.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <async.h>
-
-/** Module initialization.
- *
- * This has to be implemented in user code.
- *
- * @param[in] sess Networking module session.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module
- *         initialize function.
- *
- */
-extern int nil_initialize(async_sess_t *sess);
-
-/** Notify the network interface layer about the device state change.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id Device identifier.
- * @param[in] state     New device state.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module
- *         device state function.
- *
- */
-extern int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state);
-
-/** Pass the packet queue to the network interface layer.
- *
- * Process and redistribute the received packet queue to the registered
- * upper layers.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id Source device identifier.
- * @param[in] packet    Received packet or the received packet queue.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module
- *         received function.
- *
- */
-extern int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet);
-
-/** Message processing function.
- *
- * This has to be implemented in user code.
- *
- * @param[in]  callid Message identifier.
- * @param[in]  call   Message parameters.
- * @param[out] answer Message answer parameters.
- * @param[out] count  Message answer arguments.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is not known.
- * @return Other error codes as defined for each specific module
- *         message function.
- *
- * @see IS_NET_NIL_MESSAGE()
- *
- */
-extern int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *count);
-
-extern int nil_module_start(sysarg_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/packet_client.h
===================================================================
--- uspace/lib/net/include/packet_client.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,118 +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
- * Packet client.
- *
- * To function correctly, initialization of the packet map by the pm_init()
- * function has to happen at the first place. The module should not send the
- * packet messages to the packet server but use the functions provided. The
- * packet map should be released by the pm_destroy() function during the module
- * termination. The packets and the packet queues can't be locked at all. The
- * processing modules should process them sequentially - by passing the packets
- * to the next module and stopping using the passed ones.
- *
- * @see packet.h
- */
-
-#ifndef LIBNET_PACKET_CLIENT_H_
-#define LIBNET_PACKET_CLIENT_H_
-
-#include <net/packet.h>
-#include <async.h>
-
-/** @name Packet client interface */
-/*@{*/
-
-/** Allocates the specified type right before the actual packet content and
- * returns its pointer.
- *
- * The wrapper of the packet_prepend() function.
- *
- * @param[in] packet	The packet to be used.
- * @param[in] type	The type to be allocated at the beginning of the packet
- *			content.
- * @return		The typed pointer to the allocated memory.
- * @return		NULL if the packet is not valid.
- * @return		NULL if there is not enough memory left.
- */
-#define PACKET_PREFIX(packet, type) \
-	(type *) packet_prefix((packet), sizeof(type))
-
-/** Allocates the specified type right after the actual packet content and
- * returns its pointer.
- *
- * The wrapper of the packet_append() function.
- *
- * @param[in] packet	The packet to be used.
- * @param[in] type	The type to be allocated at the end of the packet
- *			content.
- * @return		The typed pointer to the allocated memory.
- * @return		NULL if the packet is not valid.
- * @return		NULL if there is not enough memory left.
- */
-#define PACKET_SUFFIX(packet, type) \
-	(type *) packet_suffix((packet), sizeof(type))
-
-/** Trims the actual packet content by the specified prefix and suffix types.
- *
- * The wrapper of the packet_trim() function.
- *
- * @param[in] packet	The packet to be trimmed.
- * @param[in] prefix	The type of the prefix to be removed from the beginning
- *			of the packet content.
- * @param[in] suffix	The type of the suffix to be removed from the end of
- *			the packet content.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		ENOMEM if there is not enough memory left.
- */
-#define PACKET_TRIM(packet, prefix, suffix) \
-	packet_trim((packet), sizeof(prefix), sizeof(suffix))
-
-extern void *packet_prefix(packet_t *, size_t);
-extern void *packet_suffix(packet_t *, size_t);
-extern int packet_trim(packet_t *, size_t, size_t);
-extern int packet_copy_data(packet_t *, const void *, size_t);
-extern packet_id_t packet_get_id(const packet_t *);
-extern size_t packet_get_data_length(const packet_t *);
-extern void *packet_get_data(const packet_t *);
-extern int packet_get_addr(const packet_t *, uint8_t **, uint8_t **);
-extern int packet_set_addr(packet_t *, const uint8_t *, const uint8_t *, size_t);
-extern packet_t *packet_get_copy(async_sess_t *, packet_t *);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/packet_remote.h
===================================================================
--- uspace/lib/net/include/packet_remote.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,49 +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
- * @{
- */
-
-#ifndef LIBNET_PACKET_REMOTE_H_
-#define LIBNET_PACKET_REMOTE_H_
-
-#include <net/packet.h>
-#include <sys/types.h>
-#include <async.h>
-
-extern int packet_translate_remote(async_sess_t *, packet_t **, packet_id_t);
-extern packet_t *packet_get_4_remote(async_sess_t *, size_t, size_t, size_t,
-    size_t);
-extern packet_t *packet_get_1_remote(async_sess_t *, size_t);
-extern void pq_release_remote(async_sess_t *, packet_id_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/protocol_map.h
===================================================================
--- uspace/lib/net/include/protocol_map.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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 libnet
- * @{
- */
-
-/** @file
- * Internetwork layer services - network interface layer service type
- * translation.
- */
-
-#ifndef LIBNET_PROTOCOL_MAP_H_
-#define LIBNET_PROTOCOL_MAP_H_
-
-#include <ethernet_lsap.h>
-#include <ethernet_protocols.h>
-#include <net_hardware.h>
-
-#include <ipc/services.h>
-
-extern eth_type_t protocol_map(services_t, services_t);
-extern services_t protocol_unmap(services_t, int);
-extern eth_type_t lsap_map(eth_lsap_t);
-extern eth_lsap_t lsap_unmap(eth_type_t);
-extern hw_type_t hardware_map(services_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/net/include/socket_core.h
===================================================================
--- uspace/lib/net/include/socket_core.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/net/include/socket_core.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -44,5 +44,4 @@
 #include <net/in.h>
 #include <net/device.h>
-#include <net/packet.h>
 #include <async.h>
 
@@ -80,6 +79,4 @@
 	/** Bound port. */
 	int port;
-	/** Received packets queue. */
-	dyn_fifo_t received;
 	/** Sockets for acceptance queue. */
 	dyn_fifo_t accepted;
@@ -118,5 +115,4 @@
 extern int socket_destroy(async_sess_t *, int, socket_cores_t *,
     socket_ports_t *, void (*)(socket_core_t *));
-extern int socket_reply_packets(packet_t *, size_t *);
 extern socket_core_t *socket_port_find(socket_ports_t *, int, const uint8_t *,
     size_t);
Index: pace/lib/net/include/tl_common.h
===================================================================
--- uspace/lib/net/include/tl_common.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * Copyright (c) 2008 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
- * Transport layer common functions.
- */
-
-#ifndef LIBNET_TL_COMMON_H_
-#define LIBNET_TL_COMMON_H_
-
-#include <ipc/services.h>
-#include <net/socket_codes.h>
-#include <net/packet.h>
-#include <net/device.h>
-#include <net/inet.h>
-#include <async.h>
-
-/** Device packet dimensions.
- * Maps devices to the packet dimensions.
- * @see device.h
- */
-DEVICE_MAP_DECLARE(packet_dimensions, packet_dimension_t);
-
-extern int tl_get_ip_packet_dimension(async_sess_t *, packet_dimensions_t *,
-    nic_device_id_t, packet_dimension_t **);
-extern int tl_get_address_port(const struct sockaddr *, int, uint16_t *);
-extern int tl_update_ip_packet_dimension(packet_dimensions_t *, nic_device_id_t,
-    size_t);
-extern int tl_set_address_port(struct sockaddr *, int, uint16_t);
-extern int tl_prepare_icmp_packet(async_sess_t *, async_sess_t *, packet_t *,
-    services_t);
-extern int tl_socket_read_packet_data(async_sess_t *, packet_t **, size_t,
-    const packet_dimension_t *, const struct sockaddr *, socklen_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/tl_remote.h
===================================================================
--- uspace/lib/net/include/tl_remote.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,61 +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
- * Transport layer module interface for the underlying internetwork layer.
- */
-
-#ifndef LIBNET_TL_REMOTE_H_
-#define LIBNET_TL_REMOTE_H_
-
-#include <ipc/services.h>
-#include <ipc/tl.h>
-#include <generic.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <packet_client.h>
-#include <async.h>
-
-/** @name Transport layer module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-extern int tl_received_msg(async_sess_t *, nic_device_id_t, packet_t *,
-    services_t, services_t);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/tl_skel.h
===================================================================
--- uspace/lib/net/include/tl_skel.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * Copyright (c) 2010 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 libnet
- * @{
- */
-
-#ifndef LIBNET_TL_SKEL_H_
-#define LIBNET_TL_SKEL_H_
-
-/** @file
- * Transport layer module skeleton.
- * The skeleton has to be part of each transport layer module.
- */
-
-#include <fibril_synch.h>
-#include <ipc/services.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <async.h>
-
-/** Module initialization.
- *
- * This has to be implemented in user code.
- *
- * @param[in] sess Networking module session.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module
- *         initialize function.
- *
- */
-extern int tl_initialize(async_sess_t *sess);
-
-/** Per-connection module initialization.
- *
- * This has to be implemented in user code.
- *
- */
-extern void tl_connection(void);
-
-/** Process the transport layer module message.
- *
- * This has to be implemented in user code.
- *
- * @param[in]  callid Message identifier.
- * @param[in]  call   Message parameters.
- * @param[out] answer Answer.
- * @param[out] count  Number of arguments of the answer.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module.
- *
- */
-extern int tl_message(ipc_callid_t, ipc_call_t *,
-    ipc_call_t *, size_t *);
-
-extern int tl_module_start(sysarg_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/nil/nil_remote.c
===================================================================
--- uspace/lib/net/nil/nil_remote.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,57 +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
- * Network interface layer interface implementation for remote modules.
- * @see nil_remote.h
- */
-
-#include <ipc/loc.h>
-#include <nil_remote.h>
-#include <generic.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <packet_client.h>
-#include <ipc/nil.h>
-
-int nil_device_req(async_sess_t *sess, nic_device_id_t device_id,
-    service_id_t sid, size_t mtu)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_3_0(exch, NET_NIL_DEVICE, (sysarg_t) device_id,
-	    (sysarg_t) sid, (sysarg_t) mtu);
-	async_exchange_end(exch);
-	return rc;
-}
-
-/** @}
- */
Index: pace/lib/net/nil/nil_skel.c
===================================================================
--- uspace/lib/net/nil/nil_skel.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,128 +1,0 @@
-/*
- * Copyright (c) 2011 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 libnet
- * @{
- */
-
-/** @file
- * Network interface layer module skeleton implementation.
- * @see nil_skel.h
- */
-
-#include <bool.h>
-#include <errno.h>
-#include <ns.h>
-#include <nil_skel.h>
-#include <net_interface.h>
-#include <net/modules.h>
-
-/** Default thread for new connections.
- *
- * @param[in] iid   The initial message identifier.
- * @param[in] icall The initial message call structure.
- *
- */
-static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg)
-{
-	/*
-	 * Accept the connection by answering
-	 * the initial IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		size_t count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = nil_module_message(callid, &call, &answer,
-		    &count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, count);
-	}
-}
-
-/** Start the network interface layer module.
- *
- * Initialize the client connection serving function, initialize
- * the module, register the module service and start the async
- * manager, processing IPC messages in an infinite loop.
- *
- * @param[in] service Service identification.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the pm_init() function.
- * @return Other error codes as defined for the nil_initialize()
- *         function.
- *
- */
-int nil_module_start(sysarg_t service)
-{
-	async_set_client_connection(nil_client_connection);
-	async_sess_t *sess = net_connect_module();
-	if (!sess)
-		return ENOENT;
-	
-	int rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	rc = nil_initialize(sess);
-	if (rc != EOK)
-		goto out;
-	
-	rc = service_register(service);
-	if (rc != EOK)
-		goto out;
-	
-	async_manager();
-	
-out:
-	pm_destroy();
-	return rc;
-}
-
-/** @}
- */
Index: pace/lib/net/tl/icmp_client.c
===================================================================
--- uspace/lib/net/tl/icmp_client.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,93 +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
- * ICMP client interface implementation.
- * @see icmp_client.h
- */
-
-#include <icmp_client.h>
-#include <icmp_header.h>
-#include <packet_client.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <net/icmp_codes.h>
-#include <net/packet.h>
-
-/** Processes the received packet prefixed with an ICMP header.
- *
- * @param[in] packet	The received packet.
- * @param[out] type	The ICMP header type.
- * @param[out] code	The ICMP header code.
- * @param[out] pointer	The ICMP header pointer.
- * @param[out] mtu	The ICMP header MTU.
- * @return		The ICMP header length.
- * @return		Zero if the packet contains no data.
- */
-int icmp_client_process_packet(packet_t *packet, icmp_type_t *type,
-    icmp_code_t *code, icmp_param_t *pointer, icmp_param_t *mtu)
-{
-	icmp_header_t *header;
-
-	header = (icmp_header_t *) packet_get_data(packet);
-	if (!header ||
-	    (packet_get_data_length(packet) < sizeof(icmp_header_t))) {
-		return 0;
-	}
-
-	if (type)
-		*type = header->type;
-	if (code)
-		*code = header->code;
-	if (pointer)
-		*pointer = header->un.param.pointer;
-	if (mtu)
-		*mtu = header->un.frag.mtu;
-
-	return sizeof(icmp_header_t);
-}
-
-/** Returns the ICMP header length.
- *
- * @param[in] packet	The packet.
- * @return		The ICMP header length in bytes.
- */
-size_t icmp_client_header_length(packet_t *packet)
-{
-	if (packet_get_data_length(packet) < sizeof(icmp_header_t))
-		return 0;
-
-	return sizeof(icmp_header_t);
-}
-
-/** @}
- */
Index: pace/lib/net/tl/icmp_remote.c
===================================================================
--- uspace/lib/net/tl/icmp_remote.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,152 +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
- * ICMP interface implementation for remote modules.
- * @see icmp_remote.h
- */
-
-#include <icmp_remote.h>
-#include <net/modules.h>
-#include <packet_client.h>
-#include <ipc/services.h>
-#include <ipc/icmp.h>
-#include <sys/types.h>
-#include <async.h>
-#include <errno.h>
-
-/** Send the Destination Unreachable error notification packet.
- *
- * Beginning of the packet is sent as the notification packet data.
- * The source and the destination addresses should be set in the original
- * packet.
- *
- * @param[in] sess   ICMP module session.
- * @param[in] code   Error specific code.
- * @param[in] mtu    Error MTU value.
- * @param[in] packet Original packet.
- *
- * @return EOK on success.
- * @return EPERM if the ICMP error notifications are disabled.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int icmp_destination_unreachable_msg(async_sess_t *sess, icmp_code_t code,
-    icmp_param_t mtu, packet_t *packet)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	async_msg_3(exch, NET_ICMP_DEST_UNREACH, (sysarg_t) code,
-	    (sysarg_t) packet_get_id(packet), (sysarg_t) mtu);
-	async_exchange_end(exch);
-	
-	return EOK;
-}
-
-/** Send the Source Quench error notification packet.
- *
- * Beginning of the packet is sent as the notification packet data.
- * The source and the destination addresses should be set in the original
- * packet.
- *
- * @param[in] sess   ICMP module session.
- * @param[in] packet Original packet.
- *
- * @return EOK on success.
- * @return EPERM if the ICMP error notifications are disabled.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int icmp_source_quench_msg(async_sess_t *sess, packet_t *packet)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	async_msg_2(exch, NET_ICMP_SOURCE_QUENCH, 0,
-	    (sysarg_t) packet_get_id(packet));
-	async_exchange_end(exch);
-	
-	return EOK;
-}
-
-/** Send the Time Exceeded error notification packet.
- *
- * Beginning of the packet is sent as the notification packet data.
- * The source and the destination addresses should be set in the original
- * packet.
- *
- * @param[in] sess   ICMP module session.
- * @param[in] code   Error specific code.
- * @param[in] packet Original packet.
- *
- * @return EOK on success.
- * @return EPERM if the ICMP error notifications are disabled.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int icmp_time_exceeded_msg(async_sess_t *sess, icmp_code_t code,
-    packet_t *packet)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	async_msg_2(exch, NET_ICMP_TIME_EXCEEDED, (sysarg_t) code,
-	    (sysarg_t) packet_get_id(packet));
-	async_exchange_end(exch);
-	
-	return EOK;
-}
-
-/** Send the Parameter Problem error notification packet.
- *
- * Beginning of the packet is sent as the notification packet data.
- * The source and the destination addresses should be set in the original
- * packet.
- *
- * @param[in] sess    ICMP module session.
- * @param[in] code    Error specific code.
- * @param[in] pointer Problematic parameter offset.
- * @param[in] packet  Original packet.
- *
- * @return EOK on success.
- * @return EPERM if the ICMP error notifications are disabled.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int icmp_parameter_problem_msg(async_sess_t *sess, icmp_code_t code,
-    icmp_param_t pointer, packet_t *packet)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	async_msg_3(exch, NET_ICMP_PARAMETERPROB, (sysarg_t) code,
-	    (sysarg_t) packet_get_id(packet), (sysarg_t) pointer);
-	async_exchange_end(exch);
-	
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/lib/net/tl/socket_core.c
===================================================================
--- uspace/lib/net/tl/socket_core.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/net/tl/socket_core.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -36,10 +36,7 @@
 
 #include <socket_core.h>
-#include <packet_client.h>
-#include <packet_remote.h>
 #include <net/socket_codes.h>
 #include <net/in.h>
 #include <net/inet.h>
-#include <net/packet.h>
 #include <net/modules.h>
 #include <stdint.h>
@@ -92,10 +89,4 @@
 	}
 	
-	/* Release all received packets */
-	int packet_id;
-	while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0)
-		pq_release_remote(sess, packet_id);
-	
-	dyn_fifo_destroy(&socket->received);
 	dyn_fifo_destroy(&socket->accepted);
 	
@@ -448,20 +439,13 @@
 	socket->key_length = 0;
 	socket->specific_data = specific_data;
-	rc = dyn_fifo_initialize(&socket->received, SOCKET_INITIAL_RECEIVED_SIZE);
+	
+	rc = dyn_fifo_initialize(&socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE);
 	if (rc != EOK) {
 		free(socket);
 		return rc;
 	}
-	
-	rc = dyn_fifo_initialize(&socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE);
-	if (rc != EOK) {
-		dyn_fifo_destroy(&socket->received);
-		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->received);
 		dyn_fifo_destroy(&socket->accepted);
 		free(socket);
@@ -506,87 +490,4 @@
 	socket_destroy_core(sess, socket, local_sockets, global_sockets,
 	    socket_release);
-	
-	return EOK;
-}
-
-/** Replies the packet or the packet queue data to the application via the
- * socket.
- *
- * Uses the current message processing fibril.
- *
- * @param[in] packet	The packet to be transfered.
- * @param[out] length	The total data length.
- * @return		EOK on success.
- * @return		EBADMEM if the length parameter is NULL.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the data_reply()
- *			function.
- */
-int socket_reply_packets(packet_t *packet, size_t *length)
-{
-	packet_t *next_packet;
-	size_t fragments;
-	size_t *lengths;
-	size_t index;
-	int rc;
-
-	if (!length)
-		return EBADMEM;
-
-	next_packet = pq_next(packet);
-	if (!next_packet) {
-		/* Write all if only one fragment */
-		rc = data_reply(packet_get_data(packet),
-		    packet_get_data_length(packet));
-		if (rc != EOK)
-			return rc;
-		/* Store the total length */
-		*length = packet_get_data_length(packet);
-	} else {
-		/* Count the packet fragments */
-		fragments = 1;
-		next_packet = pq_next(packet);
-		while ((next_packet = pq_next(next_packet)))
-			++fragments;
-		
-		/* Compute and store the fragment lengths */
-		lengths = (size_t *) malloc(sizeof(size_t) * fragments +
-		    sizeof(size_t));
-		if (!lengths)
-			return ENOMEM;
-		
-		lengths[0] = packet_get_data_length(packet);
-		lengths[fragments] = lengths[0];
-		next_packet = pq_next(packet);
-		
-		for (index = 1; index < fragments; ++index) {
-			lengths[index] = packet_get_data_length(next_packet);
-			lengths[fragments] += lengths[index];
-			next_packet = pq_next(packet);
-		}
-		
-		/* Write the fragment lengths */
-		rc = data_reply(lengths, sizeof(int) * (fragments + 1));
-		if (rc != EOK) {
-			free(lengths);
-			return rc;
-		}
-		next_packet = packet;
-		
-		/* Write the fragments */
-		for (index = 0; index < fragments; ++index) {
-			rc = data_reply(packet_get_data(next_packet),
-			    lengths[index]);
-			if (rc != EOK) {
-				free(lengths);
-				return rc;
-			}
-			next_packet = pq_next(next_packet);
-		}
-		
-		/* Store the total length */
-		*length = lengths[fragments];
-		free(lengths);
-	}
 	
 	return EOK;
Index: pace/lib/net/tl/tl_common.c
===================================================================
--- uspace/lib/net/tl/tl_common.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,333 +1,0 @@
-/*
- * Copyright (c) 2008 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
- * Transport layer common functions implementation.
- * @see tl_common.h
- */
-
-#include <tl_common.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <icmp_remote.h>
-#include <ip_remote.h>
-#include <ip_interface.h>
-#include <tl_remote.h>
-#include <net/socket_codes.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <async.h>
-#include <ipc/services.h>
-#include <errno.h>
-
-DEVICE_MAP_IMPLEMENT(packet_dimensions, packet_dimension_t);
-
-/** Gets the address port.
- *
- * Supports AF_INET and AF_INET6 address families.
- *
- * @param[in,out] addr	The address to be updated.
- * @param[in] addrlen	The address length.
- * @param[out] port	The set port.
- * @return		EOK on success.
- * @return		EINVAL if the address length does not match the address
- *			family.
- * @return		EAFNOSUPPORT if the address family is not supported.
- */
-int
-tl_get_address_port(const struct sockaddr *addr, int addrlen, uint16_t *port)
-{
-	const struct sockaddr_in *address_in;
-	const struct sockaddr_in6 *address_in6;
-
-	if ((addrlen <= 0) || ((size_t) addrlen < sizeof(struct sockaddr)))
-		return EINVAL;
-
-	switch (addr->sa_family) {
-	case AF_INET:
-		if (addrlen != sizeof(struct sockaddr_in))
-			return EINVAL;
-
-		address_in = (struct sockaddr_in *) addr;
-		*port = ntohs(address_in->sin_port);
-		break;
-	
-	case AF_INET6:
-		if (addrlen != sizeof(struct sockaddr_in6))
-			return EINVAL;
-
-		address_in6 = (struct sockaddr_in6 *) addr;
-		*port = ntohs(address_in6->sin6_port);
-		break;
-	
-	default:
-		return EAFNOSUPPORT;
-	}
-
-	return EOK;
-}
-
-/** Get IP packet dimensions.
- *
- * Try to search a cache and query the IP module if not found.
- * The reply is cached then.
- *
- * @param[in]  sess              IP module session.
- * @param[in]  packet_dimensions Packet dimensions cache.
- * @param[in]  device_id         Device identifier.
- * @param[out] packet_dimension  IP packet dimensions.
- *
- * @return EOK on success.
- * @return EBADMEM if the packet_dimension parameter is NULL.
- * @return ENOMEM if there is not enough memory left.
- * @return EINVAL if the packet_dimensions cache is not valid.
- * @return Other codes as defined for the ip_packet_size_req()
- *         function.
- *
- */
-int tl_get_ip_packet_dimension(async_sess_t *sess,
-    packet_dimensions_t *packet_dimensions, nic_device_id_t device_id,
-    packet_dimension_t **packet_dimension)
-{
-	if (!packet_dimension)
-		return EBADMEM;
-	
-	*packet_dimension = packet_dimensions_find(packet_dimensions,
-	    device_id);
-	if (!*packet_dimension) {
-		/* Ask for and remember them if not found */
-		*packet_dimension = malloc(sizeof(**packet_dimension));
-		if (!*packet_dimension)
-			return ENOMEM;
-		
-		int rc = ip_packet_size_req(sess, device_id, *packet_dimension);
-		if (rc != EOK) {
-			free(*packet_dimension);
-			return rc;
-		}
-		
-		rc = packet_dimensions_add(packet_dimensions, device_id,
-		    *packet_dimension);
-		if (rc < 0) {
-			free(*packet_dimension);
-			return rc;
-		}
-	}
-	
-	return EOK;
-}
-
-/** Updates IP device packet dimensions cache.
- *
- * @param[in,out] packet_dimensions The packet dimensions cache.
- * @param[in] device_id	The device identifier.
- * @param[in] content	The new maximum content size.
- * @return		EOK on success.
- * @return		ENOENT if the packet dimension is not cached.
- */
-int tl_update_ip_packet_dimension(packet_dimensions_t *packet_dimensions,
-    nic_device_id_t device_id, size_t content)
-{
-	packet_dimension_t *packet_dimension;
-
-	packet_dimension = packet_dimensions_find(packet_dimensions, device_id);
-	if (!packet_dimension)
-		return ENOENT;
-
-	packet_dimension->content = content;
-
-	if (device_id != NIC_DEVICE_INVALID_ID) {
-		packet_dimension = packet_dimensions_find(packet_dimensions,
-		    NIC_DEVICE_INVALID_ID);
-
-		if (packet_dimension) {
-			if (packet_dimension->content >= content)
-				packet_dimension->content = content;
-			else
-				packet_dimensions_exclude(packet_dimensions,
-				    NIC_DEVICE_INVALID_ID, free);
-		}
-	}
-
-	return EOK;
-}
-
-/** Sets the address port.
- *
- * Supports AF_INET and AF_INET6 address families.
- *
- * @param[in,out] addr	The address to be updated.
- * @param[in] addrlen	The address length.
- * @param[in] port	The port to be set.
- * @return		EOK on success.
- * @return		EINVAL if the address length does not match the address
- *			family.
- * @return		EAFNOSUPPORT if the address family is not supported.
- */
-int tl_set_address_port(struct sockaddr * addr, int addrlen, uint16_t port)
-{
-	struct sockaddr_in *address_in;
-	struct sockaddr_in6 *address_in6;
-	size_t length;
-
-	if (addrlen < 0)
-		return EINVAL;
-	
-	length = (size_t) addrlen;
-	if (length < sizeof(struct sockaddr))
-		return EINVAL;
-
-	switch (addr->sa_family) {
-	case AF_INET:
-		if (length != sizeof(struct sockaddr_in))
-			return EINVAL;
-		address_in = (struct sockaddr_in *) addr;
-		address_in->sin_port = htons(port);
-		return EOK;
-	
-	case AF_INET6:
-		if (length != sizeof(struct sockaddr_in6))
-				return EINVAL;
-		address_in6 = (struct sockaddr_in6 *) addr;
-		address_in6->sin6_port = htons(port);
-		return EOK;
-	
-	default:
-		return EAFNOSUPPORT;
-	}
-}
-
-/** Prepares the packet for ICMP error notification.
- *
- * Keep the first packet and release all the others.
- * Release all the packets on error.
- *
- * @param[in] packet_sess Packet server module session.
- * @param[in] icmp_sess   ICMP module phone.
- * @param[in] packet      Packet to be send.
- * @param[in] error       Packet error reporting service. Prefixes the
- *                        received packet.
- *
- * @return EOK on success.
- * @return ENOENT if no packet may be sent.
- *
- */
-int tl_prepare_icmp_packet(async_sess_t *packet_sess, async_sess_t *icmp_sess,
-    packet_t *packet, services_t error)
-{
-	/* Detach the first packet and release the others */
-	packet_t *next = pq_detach(packet);
-	if (next)
-		pq_release_remote(packet_sess, packet_get_id(next));
-	
-	uint8_t *src;
-	int length = packet_get_addr(packet, &src, NULL);
-	if ((length > 0) && (!error) && (icmp_sess) &&
-	    /*
-	     * Set both addresses to the source one (avoids the source address
-	     * deletion before setting the destination one)
-	     */
-	    (packet_set_addr(packet, src, src, (size_t) length) == EOK)) {
-		return EOK;
-	} else
-		pq_release_remote(packet_sess, packet_get_id(packet));
-	
-	return ENOENT;
-}
-
-/** Receives data from the socket into a packet.
- *
- * @param[in]  sess      Packet server module session.
- * @param[out] packet    New created packet.
- * @param[in]  prefix    Reserved packet data prefix length.
- * @param[in]  dimension Packet dimension.
- * @param[in]  addr      Destination address.
- * @param[in]  addrlen   Address length.
- *
- * @return Number of bytes received.
- * @return EINVAL if the client does not send data.
- * @return ENOMEM if there is not enough memory left.
- * @return Other error codes as defined for the
- *         async_data_read_finalize() function.
- *
- */
-int tl_socket_read_packet_data(async_sess_t *sess, packet_t **packet,
-    size_t prefix, const packet_dimension_t *dimension,
-    const struct sockaddr *addr, socklen_t addrlen)
-{
-	ipc_callid_t callid;
-	size_t length;
-	void *data;
-	int rc;
-
-	if (!dimension)
-		return EINVAL;
-
-	/* Get the data length */
-	if (!async_data_write_receive(&callid, &length))
-		return EINVAL;
-
-	/* Get a new packet */
-	*packet = packet_get_4_remote(sess, length, dimension->addr_len,
-	    prefix + dimension->prefix, dimension->suffix);
-	if (!packet)
-		return ENOMEM;
-
-	/* Allocate space in the packet */
-	data = packet_suffix(*packet, length);
-	if (!data) {
-		pq_release_remote(sess, packet_get_id(*packet));
-		return ENOMEM;
-	}
-
-	/* Read the data into the packet */
-	rc = async_data_write_finalize(callid, data, length);
-	if (rc != EOK) {
-		pq_release_remote(sess, packet_get_id(*packet));
-		return rc;
-	}
-	
-	/* Set the packet destination address */
-	rc = packet_set_addr(*packet, NULL, (uint8_t *) addr, addrlen);
-	if (rc != EOK) {
-		pq_release_remote(sess, packet_get_id(*packet));
-		return rc;
-	}
-
-	return (int) length;
-}
-
-/** @}
- */
Index: pace/lib/net/tl/tl_remote.c
===================================================================
--- uspace/lib/net/tl/tl_remote.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,66 +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
- * @{
- */
-
-#include <tl_remote.h>
-#include <generic.h>
-#include <packet_client.h>
-#include <ipc/services.h>
-#include <ipc/tl.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <async.h>
-
-/** Notify the remote transport layer modules about the received packet/s.
- *
- * @param[in] sess      Transport layer module session.
- * @param[in] device_id Device identifier.
- * @param[in] packet    Received packet or the received packet queue.
- *                      The packet queue is used to carry a fragmented
- *                      datagram. The first packet contains the headers,
- *                      the others contain only data.
- * @param[in] target    Target transport layer module service to be
- *                      delivered to.
- * @param[in] error     Packet error reporting service. Prefixes the
- *                      received packet.
- *
- * @return EOK on success.
- *
- */
-int tl_received_msg(async_sess_t *sess, nic_device_id_t device_id, packet_t *packet,
-    services_t target, services_t error)
-{
-	return generic_received_msg_remote(sess, NET_TL_RECEIVED, device_id,
-	    packet_get_id(packet), target, error);
-}
-
-/** @}
- */
Index: pace/lib/net/tl/tl_skel.c
===================================================================
--- uspace/lib/net/tl/tl_skel.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,134 +1,0 @@
-/*
- * Copyright (c) 2011 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 libnet
- * @{
- */
-
-/** @file
- * Transport layer module skeleton implementation.
- * @see tl_skel.h
- */
-
-#include <bool.h>
-#include <errno.h>
-#include <ns.h>
-#include <tl_skel.h>
-#include <net_interface.h>
-#include <net/modules.h>
-
-/** 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 tl_client_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg)
-{
-	/*
-	 * Accept the connection by answering
-	 * the initial IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-	
-	/* Per-connection initialization */
-	tl_connection();
-	
-	while (true) {
-		ipc_call_t answer;
-		size_t count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = tl_message(callid, &call, &answer, &count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, count);
-	}
-}
-
-/** Start the trasport layer module.
- *
- * Initialize the client connection serving function, initialize
- * the module, register the module service and start the async
- * manager, processing IPC messages in an infinite loop.
- *
- * @param[in] service Service identification.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the pm_init() function.
- * @return Other error codes as defined for the il_initialize()
- *         function.
- * @return Other error codes as defined for the REGISTER_ME() macro
- *         function.
- *
- */
-int tl_module_start(sysarg_t service)
-{
-	async_set_client_connection(tl_client_connection);
-	async_sess_t *sess = net_connect_module();
-	if (!sess)
-		return ENOENT;
-	
-	int rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	rc = tl_initialize(sess);
-	if (rc != EOK)
-		goto out;
-	
-	rc = service_register(service);
-	if (rc != EOK)
-		goto out;
-	
-	task_retval(0);
-	async_manager();
-	
-out:
-	pm_destroy();
-	return rc;
-}
-
-/** @}
- */
Index: uspace/lib/nic/include/nic.h
===================================================================
--- uspace/lib/nic/include/nic.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/nic/include/nic.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -232,5 +232,4 @@
 extern int nic_report_poll_mode(nic_t *, nic_poll_mode_t, struct timeval *);
 extern void nic_query_address(nic_t *, nic_address_t *);
-extern void nic_received_noneth_frame(nic_t *, void *, size_t);
 extern void nic_received_frame(nic_t *, nic_frame_t *);
 extern void nic_received_frame_list(nic_t *, nic_frame_list_t *);
Index: uspace/lib/nic/src/nic_driver.c
===================================================================
--- uspace/lib/nic/src/nic_driver.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/nic/src/nic_driver.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -624,23 +624,4 @@
 
 /**
- * This function is to be used only in the loopback driver. It's workaround
- * for the situation when the frame does not contain ethernet address.
- * The filtering is therefore not applied here.
- *
- * @param nic_data
- * @param data		Frame data
- * @param size		Frame size in bytes
- */
-void nic_received_noneth_frame(nic_t *nic_data, void *data, size_t size)
-{
-	fibril_rwlock_write_lock(&nic_data->stats_lock);
-	nic_data->stats.receive_packets++;
-	nic_data->stats.receive_bytes += size;
-	fibril_rwlock_write_unlock(&nic_data->stats_lock);
-	
-	nic_ev_received(nic_data->client_session, data, size);
-}
-
-/**
  * Some NICs can receive multiple frames during single interrupt. These can
  * send them in whole list of frames (actually nic_frame_t structures), then
Index: uspace/lib/nic/src/nic_ev.c
===================================================================
--- uspace/lib/nic/src/nic_ev.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/nic/src/nic_ev.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -54,5 +54,5 @@
 
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
@@ -86,5 +86,5 @@
 
 	if (retval != EOK) {
-		async_wait_for(req, NULL);
+		async_forget(req);
 		return retval;
 	}
Index: uspace/lib/usbhid/src/hidiface.c
===================================================================
--- uspace/lib/usbhid/src/hidiface.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/usbhid/src/hidiface.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -120,5 +120,5 @@
 	
 	if (data_request == 0) {
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		free(buffer);
 		return ENOMEM;
@@ -206,5 +206,5 @@
 	
 	if (data_request == 0) {
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		return ENOMEM;
 	}
Index: uspace/lib/usbvirt/src/ipc_hc.c
===================================================================
--- uspace/lib/usbvirt/src/ipc_hc.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/lib/usbvirt/src/ipc_hc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -80,5 +80,5 @@
 	if (rc != EOK) {
 		async_exchange_end(exch);
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		return rc;
 	}
@@ -91,5 +91,5 @@
 	
 	if (data_request == 0) {
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		return ENOMEM;
 	}
@@ -153,5 +153,5 @@
 	if (rc != EOK) {
 		async_exchange_end(exch);
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		return rc;
 	}
@@ -161,5 +161,5 @@
 		if (rc != EOK) {
 			async_exchange_end(exch);
-			async_wait_for(opening_request, NULL);
+			async_forget(opening_request);
 			return rc;
 		}
@@ -226,5 +226,5 @@
 	
 	if (data_request == 0) {
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		return ENOMEM;
 	}
@@ -301,5 +301,5 @@
 	
 	if (rc != EOK) {
-		async_wait_for(opening_request, NULL);
+		async_forget(opening_request);
 		return rc;
 	}
Index: pace/srv/clip/Makefile
===================================================================
--- uspace/srv/clip/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,36 +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 = ../..
-BINARY = clip
-
-SOURCES = \
-	clip.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/clip/clip.c
===================================================================
--- uspace/srv/clip/clip.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,193 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-#include <stdio.h>
-#include <bool.h>
-#include <async.h>
-#include <ns.h>
-#include <ipc/services.h>
-#include <ipc/clipboard.h>
-#include <malloc.h>
-#include <fibril_synch.h>
-#include <errno.h>
-
-#define NAME  "clip"
-
-static char *clip_data = NULL;
-static size_t clip_size = 0;
-static clipboard_tag_t clip_tag = CLIPBOARD_TAG_NONE;
-static FIBRIL_MUTEX_INITIALIZE(clip_mtx);
-
-static void clip_put_data(ipc_callid_t rid, ipc_call_t *request)
-{
-	char *data;
-	int rc;
-	size_t size;
-	
-	switch (IPC_GET_ARG1(*request)) {
-	case CLIPBOARD_TAG_NONE:
-		fibril_mutex_lock(&clip_mtx);
-		
-		if (clip_data)
-			free(clip_data);
-		
-		clip_data = NULL;
-		clip_size = 0;
-		clip_tag = CLIPBOARD_TAG_NONE;
-		
-		fibril_mutex_unlock(&clip_mtx);
-		async_answer_0(rid, EOK);
-		break;
-	case CLIPBOARD_TAG_DATA:
-		rc = async_data_write_accept((void **) &data, false, 0, 0, 0, &size);
-		if (rc != EOK) {
-			async_answer_0(rid, rc);
-			break;
-		}
-		
-		fibril_mutex_lock(&clip_mtx);
-		
-		if (clip_data)
-			free(clip_data);
-		
-		clip_data = data;
-		clip_size = size;
-		clip_tag = CLIPBOARD_TAG_DATA;
-		
-		fibril_mutex_unlock(&clip_mtx);
-		async_answer_0(rid, EOK);
-		break;
-	default:
-		async_answer_0(rid, EINVAL);
-	}
-}
-
-static void clip_get_data(ipc_callid_t rid, ipc_call_t *request)
-{
-	fibril_mutex_lock(&clip_mtx);
-	
-	ipc_callid_t callid;
-	size_t size;
-	
-	/* Check for clipboard data tag compatibility */
-	switch (IPC_GET_ARG1(*request)) {
-	case CLIPBOARD_TAG_DATA:
-		if (!async_data_read_receive(&callid, &size)) {
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			break;
-		}
-		
-		if (clip_tag != CLIPBOARD_TAG_DATA) {
-			/* So far we only understand binary data */
-			async_answer_0(callid, EOVERFLOW);
-			async_answer_0(rid, EOVERFLOW);
-			break;
-		}
-		
-		if (clip_size != size) {
-			/* The client expects different size of data */
-			async_answer_0(callid, EOVERFLOW);
-			async_answer_0(rid, EOVERFLOW);
-			break;
-		}
-		
-		sysarg_t retval = async_data_read_finalize(callid, clip_data, size);
-		if (retval != EOK) {
-			async_answer_0(rid, retval);
-			break;
-		}
-		
-		async_answer_0(rid, EOK);
-	default:
-		/*
-		 * Sorry, we don't know how to get unknown or NONE
-		 * data from the clipbard
-		 */
-		async_answer_0(rid, EINVAL);
-		break;
-	}
-	
-	fibril_mutex_unlock(&clip_mtx);
-}
-
-static void clip_content(ipc_callid_t rid, ipc_call_t *request)
-{
-	fibril_mutex_lock(&clip_mtx);
-	
-	size_t size = clip_size;
-	clipboard_tag_t tag = clip_tag;
-	
-	fibril_mutex_unlock(&clip_mtx);
-	async_answer_2(rid, EOK, (sysarg_t) size, (sysarg_t) tag);
-}
-
-static void clip_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	/* Accept connection */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case CLIPBOARD_PUT_DATA:
-			clip_put_data(callid, &call);
-			break;
-		case CLIPBOARD_GET_DATA:
-			clip_get_data(callid, &call);
-			break;
-		case CLIPBOARD_CONTENT:
-			clip_content(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOENT);
-		}
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	printf("%s: HelenOS clipboard service\n", NAME);
-	
-	async_set_client_connection(clip_connection);
-	
-	if (service_register(SERVICE_CLIPBOARD) != EOK)
-		return -1;
-	
-	printf("%s: Accepting connections\n", NAME);
-	task_retval(0);
-	async_manager();
-	
-	/* Never reached */
-	return 0;
-}
Index: pace/srv/clip/clip.h
===================================================================
--- uspace/srv/clip/clip.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,32 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-#ifndef CLIP_MAIN_H_
-#define CLIP_MAIN_H_
-
-#endif
Index: uspace/srv/clipboard/Makefile
===================================================================
--- uspace/srv/clipboard/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/clipboard/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,36 @@
+#
+# 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 = ../..
+BINARY = clipboard
+
+SOURCES = \
+	clipboard.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/clipboard/clip.h
===================================================================
--- uspace/srv/clipboard/clip.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/clipboard/clip.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+#ifndef CLIP_MAIN_H_
+#define CLIP_MAIN_H_
+
+#endif
Index: uspace/srv/clipboard/clipboard.c
===================================================================
--- uspace/srv/clipboard/clipboard.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/clipboard/clipboard.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+#include <stdio.h>
+#include <bool.h>
+#include <async.h>
+#include <ns.h>
+#include <ipc/services.h>
+#include <ipc/clipboard.h>
+#include <malloc.h>
+#include <fibril_synch.h>
+#include <errno.h>
+
+#define NAME  "clipboard"
+
+static char *clip_data = NULL;
+static size_t clip_size = 0;
+static clipboard_tag_t clip_tag = CLIPBOARD_TAG_NONE;
+static FIBRIL_MUTEX_INITIALIZE(clip_mtx);
+
+static void clip_put_data(ipc_callid_t rid, ipc_call_t *request)
+{
+	char *data;
+	int rc;
+	size_t size;
+	
+	switch (IPC_GET_ARG1(*request)) {
+	case CLIPBOARD_TAG_NONE:
+		fibril_mutex_lock(&clip_mtx);
+		
+		if (clip_data)
+			free(clip_data);
+		
+		clip_data = NULL;
+		clip_size = 0;
+		clip_tag = CLIPBOARD_TAG_NONE;
+		
+		fibril_mutex_unlock(&clip_mtx);
+		async_answer_0(rid, EOK);
+		break;
+	case CLIPBOARD_TAG_DATA:
+		rc = async_data_write_accept((void **) &data, false, 0, 0, 0, &size);
+		if (rc != EOK) {
+			async_answer_0(rid, rc);
+			break;
+		}
+		
+		fibril_mutex_lock(&clip_mtx);
+		
+		if (clip_data)
+			free(clip_data);
+		
+		clip_data = data;
+		clip_size = size;
+		clip_tag = CLIPBOARD_TAG_DATA;
+		
+		fibril_mutex_unlock(&clip_mtx);
+		async_answer_0(rid, EOK);
+		break;
+	default:
+		async_answer_0(rid, EINVAL);
+	}
+}
+
+static void clip_get_data(ipc_callid_t rid, ipc_call_t *request)
+{
+	fibril_mutex_lock(&clip_mtx);
+	
+	ipc_callid_t callid;
+	size_t size;
+	
+	/* Check for clipboard data tag compatibility */
+	switch (IPC_GET_ARG1(*request)) {
+	case CLIPBOARD_TAG_DATA:
+		if (!async_data_read_receive(&callid, &size)) {
+			async_answer_0(callid, EINVAL);
+			async_answer_0(rid, EINVAL);
+			break;
+		}
+		
+		if (clip_tag != CLIPBOARD_TAG_DATA) {
+			/* So far we only understand binary data */
+			async_answer_0(callid, EOVERFLOW);
+			async_answer_0(rid, EOVERFLOW);
+			break;
+		}
+		
+		if (clip_size != size) {
+			/* The client expects different size of data */
+			async_answer_0(callid, EOVERFLOW);
+			async_answer_0(rid, EOVERFLOW);
+			break;
+		}
+		
+		sysarg_t retval = async_data_read_finalize(callid, clip_data, size);
+		if (retval != EOK) {
+			async_answer_0(rid, retval);
+			break;
+		}
+		
+		async_answer_0(rid, EOK);
+	default:
+		/*
+		 * Sorry, we don't know how to get unknown or NONE
+		 * data from the clipbard
+		 */
+		async_answer_0(rid, EINVAL);
+		break;
+	}
+	
+	fibril_mutex_unlock(&clip_mtx);
+}
+
+static void clip_content(ipc_callid_t rid, ipc_call_t *request)
+{
+	fibril_mutex_lock(&clip_mtx);
+	
+	size_t size = clip_size;
+	clipboard_tag_t tag = clip_tag;
+	
+	fibril_mutex_unlock(&clip_mtx);
+	async_answer_2(rid, EOK, (sysarg_t) size, (sysarg_t) tag);
+}
+
+static void clip_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Accept connection */
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case CLIPBOARD_PUT_DATA:
+			clip_put_data(callid, &call);
+			break;
+		case CLIPBOARD_GET_DATA:
+			clip_get_data(callid, &call);
+			break;
+		case CLIPBOARD_CONTENT:
+			clip_content(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOENT);
+		}
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS clipboard service\n", NAME);
+	
+	async_set_client_connection(clip_connection);
+	
+	if (service_register(SERVICE_CLIPBOARD) != EOK)
+		return -1;
+	
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+	
+	/* Never reached */
+	return 0;
+}
Index: uspace/srv/fs/fat/fat_dentry.c
===================================================================
--- uspace/srv/fs/fat/fat_dentry.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/srv/fs/fat/fat_dentry.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -334,5 +334,5 @@
 	while (i < count) {
 		if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
-			if (ascii_check(ch) & IS_D_CHAR(ch))
+			if (ascii_check(ch) && IS_D_CHAR(ch))
 				*dst = toupper(ch);
 			else
Index: uspace/srv/fs/fat/fat_directory.c
===================================================================
--- uspace/srv/fs/fat/fat_directory.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/srv/fs/fat/fat_directory.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -162,4 +162,11 @@
 	int rc;
 
+	void *data;
+	fat_instance_t *instance;
+
+	rc = fs_instance_get(di->nodep->idx->service_id, &data);
+	assert(rc == EOK);
+	instance = (fat_instance_t *) data;
+	
 	do {
 		rc = fat_directory_get(di, &d);
@@ -177,5 +184,5 @@
 				long_entry_count--;
 				if ((FAT_LFN_ORDER(d) == long_entry_count) && 
-					(checksum == FAT_LFN_CHKSUM(d))) {
+				    (checksum == FAT_LFN_CHKSUM(d))) {
 					/* Right order! */
 					fat_lfn_get_entry(d, wname,
@@ -189,5 +196,5 @@
 					long_entry = false;
 				}
-			} else if (FAT_IS_LFN(d)) {
+			} else if (FAT_IS_LFN(d) && instance->lfn_enabled) {
 				/* We found Last long entry! */
 				if (FAT_LFN_COUNT(d) <= FAT_LFN_MAX_COUNT) {
@@ -308,5 +315,5 @@
 		checksum = fat_dentry_chksum(de->name);
 
-		rc = fat_directory_seek(di, start_pos+long_entry_count);
+		rc = fat_directory_seek(di, start_pos + long_entry_count);
 		if (rc != EOK)
 			return rc;
Index: uspace/srv/hid/input/port/chardev.c
===================================================================
--- uspace/srv/hid/input/port/chardev.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/srv/hid/input/port/chardev.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -63,5 +63,5 @@
 /** List of devices to try connecting to. */
 static const char *in_devs[] = {
-	"char/s3c24ser"
+	"char/s3c24xx_uart"
 };
 
Index: uspace/srv/hid/s3c24xx_ts/Makefile
===================================================================
--- uspace/srv/hid/s3c24xx_ts/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/srv/hid/s3c24xx_ts/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -29,6 +29,5 @@
 USPACE_PREFIX = ../../..
 
-# Need to use short name because of FAT 8+3 limit
-BINARY = s3c24ts
+BINARY = s3c24xx_ts
 
 SOURCES = \
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -52,5 +52,5 @@
 #include "s3c24xx_ts.h"
 
-#define NAME       "s3c24ser"
+#define NAME       "s3c24xx_ts"
 #define NAMESPACE  "hid"
 
Index: uspace/srv/loc/loc.c
===================================================================
--- uspace/srv/loc/loc.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/srv/loc/loc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -1296,4 +1296,7 @@
 	categ_dir_add_cat(&cdir, cat);
 
+	cat = category_new("iplink");
+	categ_dir_add_cat(&cdir, cat);
+
 	cat = category_new("keyboard");
 	categ_dir_add_cat(&cdir, cat);
Index: pace/srv/net/cfg/e1k.nic
===================================================================
--- uspace/srv/net/cfg/e1k.nic	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,21 +1,0 @@
-# E1000 configuration
-
-NAME=e1k
-
-HWPATH=devices/\hw\pci0\00:03.0\port0
-NIL=eth
-IL=ip
-
-# 8023_2_LSAP, 8023_2_SNAP
-ETH_MODE=DIX
-ETH_DUMMY=no
-
-IP_CONFIG=static
-IP_ADDR=10.0.2.15
-IP_ROUTING=yes
-IP_NETMASK=255.255.255.240
-IP_BROADCAST=10.0.2.255
-IP_GATEWAY=10.0.2.2
-ARP=arp
-
-MTU=1500
Index: pace/srv/net/cfg/general
===================================================================
--- uspace/srv/net/cfg/general	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,12 +1,0 @@
-# general configuration
-
-IPV=4
-IP_ROUTING=no
-
-MTU=1500
-
-ICMP_ERROR_REPORTING=yes
-ICMP_ECHO_REPLYING=yes
-
-UDP_CHECKSUM_COMPUTING=yes
-UDP_AUTOBINDING=yes
Index: pace/srv/net/cfg/lo.nic
===================================================================
--- uspace/srv/net/cfg/lo.nic	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,13 +1,0 @@
-# loopback configuration
-
-NAME=lo
-
-HWPATH=devices/\virt\lo\port0
-NIL=nildummy
-IL=ip
-
-IP_CONFIG=static
-IP_ADDR=127.0.0.1
-IP_NETMASK=255.0.0.0
-
-MTU=15535
Index: pace/srv/net/cfg/ne2k.nic
===================================================================
--- uspace/srv/net/cfg/ne2k.nic	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,21 +1,0 @@
-# NE2000 configuration
-
-NAME=ne2k
-
-HWPATH=devices/\hw\pci0\00:01.0\ne2k\port0
-NIL=eth
-IL=ip
-
-# 8023_2_LSAP, 8023_2_SNAP
-ETH_MODE=DIX
-ETH_DUMMY=no
-
-IP_CONFIG=static
-IP_ADDR=10.0.2.15
-IP_ROUTING=yes
-IP_NETMASK=255.255.255.240
-IP_BROADCAST=10.0.2.255
-IP_GATEWAY=10.0.2.2
-ARP=arp
-
-MTU=1500
Index: uspace/srv/net/ethip/Makefile
===================================================================
--- uspace/srv/net/ethip/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+BINARY = ethip
+
+SOURCES = \
+	arp.c \
+	atrans.c \
+	ethip.c \
+	ethip_nic.c \
+	pdu.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/ethip/arp.c
===================================================================
--- uspace/srv/net/ethip/arp.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/arp.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,151 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <errno.h>
+#include <io/log.h>
+#include <inet/iplink_srv.h>
+#include <stdlib.h>
+
+#include "arp.h"
+#include "atrans.h"
+#include "ethip.h"
+#include "ethip_nic.h"
+#include "pdu.h"
+#include "std.h"
+
+/** Time to wait for ARP reply in microseconds */
+#define ARP_REQUEST_TIMEOUT (3 * 1000 * 1000)
+
+static int arp_send_packet(ethip_nic_t *nic, arp_eth_packet_t *packet);
+
+void arp_received(ethip_nic_t *nic, eth_frame_t *frame)
+{
+	int rc;
+	arp_eth_packet_t packet;
+	arp_eth_packet_t reply;
+	ethip_link_addr_t *laddr;
+
+	log_msg(LVL_DEBUG, "arp_received()");
+
+	rc = arp_pdu_decode(frame->data, frame->size, &packet);
+	if (rc != EOK)
+		return;
+
+	log_msg(LVL_DEBUG, "ARP PDU decoded, opcode=%d, tpa=%x",
+	    packet.opcode, packet.target_proto_addr.ipv4);
+
+	laddr = ethip_nic_addr_find(nic, &packet.target_proto_addr);
+	if (laddr != NULL) {
+		log_msg(LVL_DEBUG, "Request/reply to my address");
+
+		(void) atrans_add(&packet.sender_proto_addr,
+		    &packet.sender_hw_addr);
+
+		if (packet.opcode == aop_request) {
+        		reply.opcode = aop_reply;
+        		reply.sender_hw_addr = nic->mac_addr;
+			reply.sender_proto_addr = laddr->addr;
+			reply.target_hw_addr = packet.sender_hw_addr;
+			reply.target_proto_addr = packet.sender_proto_addr;
+
+			arp_send_packet(nic, &reply);
+		}
+	}
+}
+
+int arp_translate(ethip_nic_t *nic, iplink_srv_addr_t *src_addr,
+    iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
+{
+	int rc;
+	arp_eth_packet_t packet;
+
+	rc = atrans_lookup(ip_addr, mac_addr);
+	if (rc == EOK)
+		return EOK;
+
+	packet.opcode = aop_request;
+	packet.sender_hw_addr = nic->mac_addr;
+	packet.sender_proto_addr = *src_addr;
+	packet.target_hw_addr.addr = MAC48_BROADCAST;
+	packet.target_proto_addr = *ip_addr;
+
+	rc = arp_send_packet(nic, &packet);
+	if (rc != EOK)
+		return rc;
+
+	(void) atrans_wait_timeout(ARP_REQUEST_TIMEOUT);
+
+	return atrans_lookup(ip_addr, mac_addr);
+}
+
+static int arp_send_packet(ethip_nic_t *nic, arp_eth_packet_t *packet)
+{
+	int rc;
+	void *pdata;
+	size_t psize;
+
+	eth_frame_t frame;
+	void *fdata;
+	size_t fsize;
+
+	log_msg(LVL_DEBUG, "arp_send_packet()");
+
+	rc = arp_pdu_encode(packet, &pdata, &psize);
+	if (rc != EOK)
+		return rc;
+
+	frame.dest.addr = packet->target_hw_addr.addr;
+	frame.src.addr =  packet->sender_hw_addr.addr;
+	frame.etype_len = ETYPE_ARP;
+	frame.data = pdata;
+	frame.size = psize;
+
+	rc = eth_pdu_encode(&frame, &fdata, &fsize);
+	if (rc != EOK) {
+		free(pdata);
+		return rc;
+	}
+
+	rc = ethip_nic_send(nic, fdata, fsize);
+	free(fdata);
+	free(pdata);
+
+	return rc;
+
+}
+
+/** @}
+ */
Index: uspace/srv/net/ethip/arp.h
===================================================================
--- uspace/srv/net/ethip/arp.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/arp.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,50 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ARP_H_
+#define ARP_H_
+
+#include <inet/iplink_srv.h>
+#include "ethip.h"
+
+extern void arp_received(ethip_nic_t *, eth_frame_t *);
+extern int arp_translate(ethip_nic_t *, iplink_srv_addr_t *,
+    iplink_srv_addr_t *, mac48_addr_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/atrans.c
===================================================================
--- uspace/srv/net/ethip/atrans.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/atrans.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,137 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <inet/iplink_srv.h>
+#include <stdlib.h>
+
+#include "atrans.h"
+#include "ethip.h"
+
+/** Address translation list (of ethip_atrans_t) */
+static FIBRIL_MUTEX_INITIALIZE(atrans_list_lock);
+static LIST_INITIALIZE(atrans_list);
+static FIBRIL_CONDVAR_INITIALIZE(atrans_cv);
+
+static ethip_atrans_t *atrans_find(iplink_srv_addr_t *ip_addr)
+{
+	list_foreach(atrans_list, link) {
+		ethip_atrans_t *atrans = list_get_instance(link,
+		    ethip_atrans_t, atrans_list);
+
+		if (atrans->ip_addr.ipv4 == ip_addr->ipv4)
+			return atrans;
+	}
+
+	return NULL;
+}
+
+int atrans_add(iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
+{
+	ethip_atrans_t *atrans;
+	ethip_atrans_t *prev;
+
+	atrans = calloc(1, sizeof(ethip_atrans_t));
+	if (atrans == NULL)
+		return ENOMEM;
+
+	atrans->ip_addr = *ip_addr;
+	atrans->mac_addr = *mac_addr;
+
+	fibril_mutex_lock(&atrans_list_lock);
+	prev = atrans_find(ip_addr);
+	if (prev != NULL) {
+		list_remove(&prev->atrans_list);
+		free(prev);
+	}
+
+	list_append(&atrans->atrans_list, &atrans_list);
+	fibril_mutex_unlock(&atrans_list_lock);
+	fibril_condvar_broadcast(&atrans_cv);
+
+	return EOK;
+}
+
+int atrans_remove(iplink_srv_addr_t *ip_addr)
+{
+	ethip_atrans_t *atrans;
+
+	fibril_mutex_lock(&atrans_list_lock);
+	atrans = atrans_find(ip_addr);
+	if (atrans == NULL) {
+		fibril_mutex_unlock(&atrans_list_lock);
+		return ENOENT;
+	}
+
+	list_remove(&atrans->atrans_list);
+	fibril_mutex_unlock(&atrans_list_lock);
+	free(atrans);
+
+	return EOK;
+}
+
+int atrans_lookup(iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
+{
+	ethip_atrans_t *atrans;
+
+	fibril_mutex_lock(&atrans_list_lock);
+	atrans = atrans_find(ip_addr);
+	if (atrans == NULL) {
+		fibril_mutex_unlock(&atrans_list_lock);
+		return ENOENT;
+	}
+
+	fibril_mutex_unlock(&atrans_list_lock);
+	*mac_addr = atrans->mac_addr;
+	return EOK;
+}
+
+int atrans_wait_timeout(suseconds_t timeout)
+{
+	int rc;
+
+	fibril_mutex_lock(&atrans_list_lock);
+	rc = fibril_condvar_wait_timeout(&atrans_cv, &atrans_list_lock,
+	    timeout);
+	fibril_mutex_unlock(&atrans_list_lock);
+
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/srv/net/ethip/atrans.h
===================================================================
--- uspace/srv/net/ethip/atrans.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/atrans.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,51 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ATRANS_H_
+#define ATRANS_H_
+
+#include <inet/iplink_srv.h>
+#include "ethip.h"
+
+extern int atrans_add(iplink_srv_addr_t *, mac48_addr_t *);
+extern int atrans_remove(iplink_srv_addr_t *);
+extern int atrans_lookup(iplink_srv_addr_t *, mac48_addr_t *);
+extern int atrans_wait_timeout(suseconds_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/ethip.c
===================================================================
--- uspace/srv/net/ethip/ethip.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/ethip.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,288 @@
+/*
+ * 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 ethip
+ * @{
+ */
+/**
+ * @file
+ * @brief IP link provider for Ethernet
+ *
+ * Based on the IETF RFC 894 standard.
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <inet/iplink_srv.h>
+#include <io/log.h>
+#include <loc.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "arp.h"
+#include "ethip.h"
+#include "ethip_nic.h"
+#include "pdu.h"
+#include "std.h"
+
+#define NAME "ethip"
+
+static int ethip_open(iplink_srv_t *srv);
+static int ethip_close(iplink_srv_t *srv);
+static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu);
+static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu);
+static int ethip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr);
+static int ethip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr);
+
+static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static iplink_ops_t ethip_iplink_ops = {
+	.open = ethip_open,
+	.close = ethip_close,
+	.send = ethip_send,
+	.get_mtu = ethip_get_mtu,
+	.addr_add = ethip_addr_add,
+	.addr_remove = ethip_addr_remove
+};
+
+static int ethip_init(void)
+{
+	int rc;
+
+	async_set_client_connection(ethip_client_conn);
+
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering server.");
+		return rc;
+	}
+
+	rc = ethip_nic_discovery_start();
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+int ethip_iplink_init(ethip_nic_t *nic)
+{
+	int rc;
+	service_id_t sid;
+	category_id_t iplink_cat;
+	static unsigned link_num = 0;
+	char *svc_name = NULL;
+
+	log_msg(LVL_DEBUG, "ethip_iplink_init()");
+
+	iplink_srv_init(&nic->iplink);
+	nic->iplink.ops = &ethip_iplink_ops;
+	nic->iplink.arg = nic;
+
+	rc = asprintf(&svc_name, "net/eth%u", ++link_num);
+	if (rc < 0) {
+		log_msg(LVL_ERROR, "Out of memory.");
+		goto error;
+	}
+
+	rc = loc_service_register(svc_name, &sid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service %s.", svc_name);
+		goto error;
+	}
+
+	nic->iplink_sid = sid;
+
+	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
+		goto error;
+	}
+
+	rc = loc_service_add_to_cat(sid, iplink_cat);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed adding %s to category.", svc_name);
+		goto error;
+	}
+
+	return EOK;
+
+error:
+	if (svc_name != NULL)
+		free(svc_name);
+	return rc;
+}
+
+static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ethip_nic_t *nic;
+	service_id_t sid;
+
+	sid = (service_id_t)IPC_GET_ARG1(*icall);
+	log_msg(LVL_DEBUG, "ethip_client_conn(%u)", (unsigned)sid);
+	nic = ethip_nic_find_by_iplink_sid(sid);
+	if (nic == NULL) {
+		log_msg(LVL_WARN, "Uknown service ID.");
+		return;
+	}
+
+	iplink_conn(iid, icall, &nic->iplink);
+}
+
+static int ethip_open(iplink_srv_t *srv)
+{
+	log_msg(LVL_DEBUG, "ethip_open()");
+	return EOK;
+}
+
+static int ethip_close(iplink_srv_t *srv)
+{
+	log_msg(LVL_DEBUG, "ethip_close()");
+	return EOK;
+}
+
+static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+	eth_frame_t frame;
+	void *data;
+	size_t size;
+	mac48_addr_t dest_mac_addr;
+	int rc;
+
+	log_msg(LVL_DEBUG, "ethip_send()");
+
+	rc = arp_translate(nic, &sdu->lsrc, &sdu->ldest, &dest_mac_addr);
+	if (rc != EOK) {
+		log_msg(LVL_WARN, "Failed to look up IP address 0x%" PRIx32,
+		    sdu->ldest.ipv4);
+		return rc;
+	}
+
+	frame.dest      = dest_mac_addr;
+	frame.src       = nic->mac_addr;
+	frame.etype_len = ETYPE_IP;
+	frame.data = sdu->data;
+	frame.size = sdu->size;
+
+	rc = eth_pdu_encode(&frame, &data, &size);
+	if (rc != EOK)
+		return rc;
+
+	rc = ethip_nic_send(nic, data, size);
+	free(data);
+
+	return rc;
+}
+
+int ethip_received(iplink_srv_t *srv, void *data, size_t size)
+{
+	log_msg(LVL_DEBUG, "ethip_received(): srv=%p", srv);
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+	eth_frame_t frame;
+	iplink_srv_sdu_t sdu;
+	int rc;
+
+	log_msg(LVL_DEBUG, "ethip_received()");
+
+	log_msg(LVL_DEBUG, " - eth_pdu_decode");
+	rc = eth_pdu_decode(data, size, &frame);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, " - eth_pdu_decode failed");
+		return rc;
+	}
+
+	switch (frame.etype_len) {
+	case ETYPE_ARP:
+		arp_received(nic, &frame);
+		break;
+	case ETYPE_IP:
+		log_msg(LVL_DEBUG, " - construct SDU");
+		sdu.lsrc.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 1;
+		sdu.ldest.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 4;
+		sdu.data = frame.data;
+		sdu.size = frame.size;
+		log_msg(LVL_DEBUG, " - call iplink_ev_recv");
+		rc = iplink_ev_recv(&nic->iplink, &sdu);
+		break;
+	default:
+		log_msg(LVL_DEBUG, "Unknown ethertype 0x%" PRIx16,
+		    frame.etype_len);
+	}
+
+	free(frame.data);
+	return rc;
+}
+
+static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu)
+{
+	log_msg(LVL_DEBUG, "ethip_get_mtu()");
+	*mtu = 1500;
+	return EOK;
+}
+
+static int ethip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+
+	log_msg(LVL_DEBUG, "ethip_addr_add(0x%" PRIx32 ")", addr->ipv4);
+	return ethip_nic_addr_add(nic, addr);
+}
+
+static int ethip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+
+	log_msg(LVL_DEBUG, "ethip_addr_remove(0x%" PRIx32 ")", addr->ipv4);
+	return ethip_nic_addr_add(nic, addr);
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+
+	printf(NAME ": HelenOS IP over Ethernet service\n");
+
+	if (log_init(NAME, LVL_WARN) != EOK) {
+		printf(NAME ": Failed to initialize logging.\n");
+		return 1;
+	}
+
+	rc = ethip_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/net/ethip/ethip.h
===================================================================
--- uspace/srv/net/ethip/ethip.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/ethip.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,126 @@
+/*
+ * 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 ethip
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ETHIP_H_
+#define ETHIP_H_
+
+#include <adt/list.h>
+#include <async.h>
+#include <inet/iplink_srv.h>
+#include <loc.h>
+#include <sys/types.h>
+
+#define MAC48_BROADCAST 0xffffffffffff
+
+typedef struct {
+	link_t addr_list;
+	iplink_srv_addr_t addr;
+} ethip_link_addr_t;
+
+/** IEEE MAC-48 identifier */
+typedef struct {
+	/** MAC Address (in lowest 48 bits) */
+	uint64_t addr;
+} mac48_addr_t;
+
+typedef struct ethip_nic {
+	link_t nic_list;
+	service_id_t svc_id;
+	char *svc_name;
+	async_sess_t *sess;
+
+	iplink_srv_t iplink;
+	service_id_t iplink_sid;
+
+	/** MAC address */
+	mac48_addr_t mac_addr;
+	/** List of IP addresses configured on this link */
+	list_t addr_list; /* of ethip_link_addr_t */
+} ethip_nic_t;
+
+/** Ethernet frame */
+typedef struct {
+	/** Destination Address */
+	mac48_addr_t dest;
+	/** Source Address */
+	mac48_addr_t src;
+	/** Ethertype or Length */
+	uint16_t etype_len;
+	/** Payload */
+	void *data;
+	/** Payload size */
+	size_t size;
+} eth_frame_t;
+
+/** ARP opcode */
+typedef enum {
+	/** Request */
+	aop_request,
+	/** Reply */
+	aop_reply
+} arp_opcode_t;
+
+/** ARP packet (for 48-bit MAC addresses and IPv4)
+ *
+ * Internal representation
+ */
+typedef struct {
+	/** Opcode */
+	arp_opcode_t opcode;
+	/** Sender hardware address */
+	mac48_addr_t sender_hw_addr;
+	/** Sender protocol address */
+	iplink_srv_addr_t sender_proto_addr;
+	/** Target hardware address */
+	mac48_addr_t target_hw_addr;
+	/** Target protocol address */
+	iplink_srv_addr_t target_proto_addr;
+} arp_eth_packet_t;
+
+/** Address translation table element */
+typedef struct {
+	link_t atrans_list;
+	iplink_srv_addr_t ip_addr;
+	mac48_addr_t mac_addr;
+} ethip_atrans_t;
+
+extern int ethip_iplink_init(ethip_nic_t *);
+extern int ethip_received(iplink_srv_t *, void *, size_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/ethip_nic.c
===================================================================
--- uspace/srv/net/ethip/ethip_nic.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/ethip_nic.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,386 @@
+/*
+ * 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 ethip
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <adt/list.h>
+#include <async.h>
+#include <bool.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <inet/iplink_srv.h>
+#include <io/log.h>
+#include <loc.h>
+#include <device/nic.h>
+#include <stdlib.h>
+
+#include "ethip.h"
+#include "ethip_nic.h"
+#include "pdu.h"
+
+static int ethip_nic_open(service_id_t sid);
+static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static LIST_INITIALIZE(ethip_nic_list);
+static FIBRIL_MUTEX_INITIALIZE(ethip_discovery_lock);
+
+static int ethip_nic_check_new(void)
+{
+	bool already_known;
+	category_id_t iplink_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	int rc;
+
+	fibril_mutex_lock(&ethip_discovery_lock);
+
+	rc = loc_category_get_id("nic", &iplink_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed resolving category 'nic'.");
+		fibril_mutex_unlock(&ethip_discovery_lock);
+		return ENOENT;
+	}
+
+	rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed getting list of IP links.");
+		fibril_mutex_unlock(&ethip_discovery_lock);
+		return EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		already_known = false;
+
+		list_foreach(ethip_nic_list, nic_link) {
+			ethip_nic_t *nic = list_get_instance(nic_link,
+			    ethip_nic_t, nic_list);
+			if (nic->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+
+		if (!already_known) {
+			log_msg(LVL_DEBUG, "Found NIC '%lu'",
+			    (unsigned long) svcs[i]);
+			rc = ethip_nic_open(svcs[i]);
+			if (rc != EOK)
+				log_msg(LVL_ERROR, "Could not open NIC.");
+		}
+	}
+
+	fibril_mutex_unlock(&ethip_discovery_lock);
+	return EOK;
+}
+
+static ethip_nic_t *ethip_nic_new(void)
+{
+	ethip_nic_t *nic = calloc(1, sizeof(ethip_nic_t));
+
+	if (nic == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating NIC structure. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&nic->nic_list);
+	list_initialize(&nic->addr_list);
+
+	return nic;
+}
+
+static ethip_link_addr_t *ethip_nic_addr_new(iplink_srv_addr_t *addr)
+{
+	ethip_link_addr_t *laddr = calloc(1, sizeof(ethip_link_addr_t));
+
+	if (laddr == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating NIC address structure. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&laddr->addr_list);
+	laddr->addr.ipv4 = addr->ipv4;
+	return laddr;
+}
+
+static void ethip_nic_delete(ethip_nic_t *nic)
+{
+	if (nic->svc_name != NULL)
+		free(nic->svc_name);
+	free(nic);
+}
+
+static void ethip_link_addr_delete(ethip_link_addr_t *laddr)
+{
+	free(laddr);
+}
+
+static int ethip_nic_open(service_id_t sid)
+{
+	ethip_nic_t *nic;
+	int rc;
+	bool in_list = false;
+	nic_address_t nic_address;
+
+	log_msg(LVL_DEBUG, "ethip_nic_open()");
+	nic = ethip_nic_new();
+	if (nic == NULL)
+		return ENOMEM;
+
+	rc = loc_service_get_name(sid, &nic->svc_name);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed getting service name.");
+		goto error;
+	}
+
+	nic->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
+	if (nic->sess == NULL) {
+		log_msg(LVL_ERROR, "Failed connecting '%s'", nic->svc_name);
+		goto error;
+	}
+
+	nic->svc_id = sid;
+
+	rc = nic_callback_create(nic->sess, ethip_nic_cb_conn, nic);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed creating callback connection "
+		    "from '%s'", nic->svc_name);
+		goto error;
+	}
+
+	log_msg(LVL_DEBUG, "Opened NIC '%s'", nic->svc_name);
+	list_append(&nic->nic_list, &ethip_nic_list);
+	in_list = true;
+
+	rc = ethip_iplink_init(nic);
+	if (rc != EOK)
+		goto error;
+
+	rc = nic_get_address(nic->sess, &nic_address);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Error getting MAC address of NIC '%s'.",
+		    nic->svc_name);
+		goto error;
+	}
+
+	mac48_decode(nic_address.address, &nic->mac_addr);
+
+	rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Error activating NIC '%s'.",
+		    nic->svc_name);
+		goto error;
+	}
+
+	log_msg(LVL_DEBUG, "Initialized IP link service, MAC = 0x%" PRIx64,
+	    nic->mac_addr.addr);
+
+	return EOK;
+
+error:
+	if (in_list)
+		list_remove(&nic->nic_list);
+	if (nic->sess != NULL)
+		async_hangup(nic->sess);
+	ethip_nic_delete(nic);
+	return rc;
+}
+
+static void ethip_nic_cat_change_cb(void)
+{
+	(void) ethip_nic_check_new();
+}
+
+static void ethip_nic_addr_changed(ethip_nic_t *nic, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	log_msg(LVL_DEBUG, "ethip_nic_addr_changed()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void ethip_nic_received(ethip_nic_t *nic, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	void *data;
+	size_t size;
+
+	log_msg(LVL_DEBUG, "ethip_nic_received() nic=%p", nic);
+
+	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "data_write_accept() failed");
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "Ethernet PDU contents (%zu bytes)",
+	    size);
+
+	log_msg(LVL_DEBUG, "call ethip_received");
+	rc = ethip_received(&nic->iplink, data, size);
+	log_msg(LVL_DEBUG, "free data");
+	free(data);
+
+	log_msg(LVL_DEBUG, "ethip_nic_received() done, rc=%d", rc);
+	async_answer_0(callid, rc);
+}
+
+static void ethip_nic_device_state(ethip_nic_t *nic, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	log_msg(LVL_DEBUG, "ethip_nic_device_state()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)arg;
+
+	log_msg(LVL_DEBUG, "ethnip_nic_cb_conn()");
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case NIC_EV_ADDR_CHANGED:
+			ethip_nic_addr_changed(nic, callid, &call);
+			break;
+		case NIC_EV_RECEIVED:
+			ethip_nic_received(nic, callid, &call);
+			break;
+		case NIC_EV_DEVICE_STATE:
+			ethip_nic_device_state(nic, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+		}
+	}
+}
+
+int ethip_nic_discovery_start(void)
+{
+	int rc;
+
+	rc = loc_register_cat_change_cb(ethip_nic_cat_change_cb);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering callback for NIC "
+		    "discovery (%d).", rc);
+		return rc;
+	}
+
+	return ethip_nic_check_new();
+}
+
+ethip_nic_t *ethip_nic_find_by_iplink_sid(service_id_t iplink_sid)
+{
+	log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid(%u)",
+	    (unsigned) iplink_sid);
+
+	list_foreach(ethip_nic_list, link) {
+		log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - element");
+		ethip_nic_t *nic = list_get_instance(link, ethip_nic_t,
+		    nic_list);
+
+		if (nic->iplink_sid == iplink_sid) {
+			log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - found %p", nic);
+			return nic;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - not found");
+	return NULL;
+}
+
+int ethip_nic_send(ethip_nic_t *nic, void *data, size_t size)
+{
+	int rc;
+	log_msg(LVL_DEBUG, "ethip_nic_send(size=%zu)", size);
+	rc = nic_send_frame(nic->sess, data, size);
+	log_msg(LVL_DEBUG, "nic_send_frame -> %d", rc);
+	return rc;
+}
+
+int ethip_nic_addr_add(ethip_nic_t *nic, iplink_srv_addr_t *addr)
+{
+	ethip_link_addr_t *laddr;
+
+	log_msg(LVL_DEBUG, "ethip_nic_addr_add()");
+	laddr = ethip_nic_addr_new(addr);
+	if (laddr == NULL)
+		return ENOMEM;
+
+	list_append(&laddr->addr_list, &nic->addr_list);
+	return EOK;
+}
+
+int ethip_nic_addr_remove(ethip_nic_t *nic, iplink_srv_addr_t *addr)
+{
+	ethip_link_addr_t *laddr;
+
+	log_msg(LVL_DEBUG, "ethip_nic_addr_remove()");
+
+	laddr = ethip_nic_addr_find(nic, addr);
+	if (laddr == NULL)
+		return ENOENT;
+
+	list_remove(&laddr->addr_list);
+	ethip_link_addr_delete(laddr);
+	return EOK;
+}
+
+ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *nic,
+    iplink_srv_addr_t *addr)
+{
+	log_msg(LVL_DEBUG, "ethip_nic_addr_find()");
+
+	list_foreach(nic->addr_list, link) {
+		ethip_link_addr_t *laddr = list_get_instance(link,
+		    ethip_link_addr_t, addr_list);
+
+		if (addr->ipv4 == laddr->addr.ipv4)
+			return laddr;
+	}
+
+	return NULL;
+}
+
+/** @}
+ */
Index: uspace/srv/net/ethip/ethip_nic.h
===================================================================
--- uspace/srv/net/ethip/ethip_nic.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/ethip_nic.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,54 @@
+/*
+ * 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 ethip
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ETHIP_NIC_H_
+#define ETHIP_NIC_H_
+
+#include <ipc/loc.h>
+#include "ethip.h"
+
+extern int ethip_nic_discovery_start(void);
+extern ethip_nic_t *ethip_nic_find_by_iplink_sid(service_id_t);
+extern int ethip_nic_send(ethip_nic_t *, void *, size_t);
+extern int ethip_nic_addr_add(ethip_nic_t *, iplink_srv_addr_t *);
+extern int ethip_nic_addr_remove(ethip_nic_t *, iplink_srv_addr_t *);
+extern ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *,
+    iplink_srv_addr_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/pdu.c
===================================================================
--- uspace/srv/net/ethip/pdu.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/pdu.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,240 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "ethip.h"
+#include "std.h"
+#include "pdu.h"
+
+#define MAC48_BYTES 6
+
+/** Encode Ethernet PDU. */
+int eth_pdu_encode(eth_frame_t *frame, void **rdata, size_t *rsize)
+{
+	void *data;
+	size_t size;
+	eth_header_t *hdr;
+
+	size = max(sizeof(eth_header_t) + frame->size, ETH_FRAME_MIN_SIZE);
+
+	data = calloc(size, 1);
+	if (data == NULL)
+		return ENOMEM;
+
+	hdr = (eth_header_t *)data;
+	mac48_encode(&frame->src, hdr->src);
+	mac48_encode(&frame->dest, hdr->dest);
+	hdr->etype_len = host2uint16_t_be(frame->etype_len);
+
+	memcpy((uint8_t *)data + sizeof(eth_header_t), frame->data,
+	    frame->size);
+
+	log_msg(LVL_DEBUG, "Encoding Ethernet frame src=%llx dest=%llx etype=%x",
+	    frame->src, frame->dest, frame->etype_len);
+	log_msg(LVL_DEBUG, "Encoded Ethernet frame (%zu bytes)", size);
+
+	*rdata = data;
+	*rsize = size;
+	return EOK;
+}
+
+/** Decode Ethernet PDU. */
+int eth_pdu_decode(void *data, size_t size, eth_frame_t *frame)
+{
+	eth_header_t *hdr;
+
+	log_msg(LVL_DEBUG, "eth_pdu_decode()");
+
+	if (size < sizeof(eth_header_t)) {
+		log_msg(LVL_DEBUG, "PDU too short (%zu)", size);
+		return EINVAL;
+	}
+
+	hdr = (eth_header_t *)data;
+
+	frame->size = size - sizeof(eth_header_t);
+	frame->data = calloc(frame->size, 1);
+	if (frame->data == NULL)
+		return ENOMEM;
+
+	mac48_decode(hdr->src, &frame->src);
+	mac48_decode(hdr->dest, &frame->dest);
+	frame->etype_len = uint16_t_be2host(hdr->etype_len);
+
+	memcpy(frame->data, (uint8_t *)data + sizeof(eth_header_t),
+	    frame->size);
+
+	log_msg(LVL_DEBUG, "Decoding Ethernet frame src=%llx dest=%llx etype=%x",
+	    frame->src, frame->dest, frame->etype_len);
+	log_msg(LVL_DEBUG, "Decoded Ethernet frame payload (%zu bytes)", frame->size);
+
+	return EOK;
+}
+
+void mac48_encode(mac48_addr_t *addr, void *buf)
+{
+	uint64_t val;
+	uint8_t *bbuf = (uint8_t *)buf;
+	int i;
+
+	val = addr->addr;
+	for (i = 0; i < MAC48_BYTES; i++)
+		bbuf[i] = (val >> (8 * (MAC48_BYTES - i - 1))) & 0xff;
+}
+
+void mac48_decode(void *data, mac48_addr_t *addr)
+{
+	uint64_t val;
+	uint8_t *bdata = (uint8_t *)data;
+	int i;
+
+	val = 0;
+	for (i = 0; i < MAC48_BYTES; i++)
+		val |= (uint64_t)bdata[i] << (8 * (MAC48_BYTES - i - 1));
+
+	addr->addr = val;
+}
+
+/** Encode ARP PDU. */
+int arp_pdu_encode(arp_eth_packet_t *packet, void **rdata, size_t *rsize)
+{
+	void *data;
+	size_t size;
+	arp_eth_packet_fmt_t *pfmt;
+	uint16_t fopcode;
+
+	log_msg(LVL_DEBUG, "arp_pdu_encode()");
+
+	size = sizeof(arp_eth_packet_fmt_t);
+
+	data = calloc(size, 1);
+	if (data == NULL)
+		return ENOMEM;
+
+	pfmt = (arp_eth_packet_fmt_t *)data;
+
+	switch (packet->opcode) {
+	case aop_request: fopcode = AOP_REQUEST; break;
+	case aop_reply: fopcode = AOP_REPLY; break;
+	default:
+		assert(false);
+		fopcode = 0;
+	}
+
+	pfmt->hw_addr_space = host2uint16_t_be(AHRD_ETHERNET);
+	pfmt->proto_addr_space = host2uint16_t_be(ETYPE_IP);
+	pfmt->hw_addr_size = ETH_ADDR_SIZE;
+	pfmt->proto_addr_size = IPV4_ADDR_SIZE;
+	pfmt->opcode = host2uint16_t_be(fopcode);
+	mac48_encode(&packet->sender_hw_addr, pfmt->sender_hw_addr);
+	pfmt->sender_proto_addr =
+	    host2uint32_t_be(packet->sender_proto_addr.ipv4);
+	mac48_encode(&packet->target_hw_addr, pfmt->target_hw_addr);
+	pfmt->target_proto_addr =
+	    host2uint32_t_be(packet->target_proto_addr.ipv4);
+
+	*rdata = data;
+	*rsize = size;
+	return EOK;
+}
+
+/** Decode ARP PDU. */
+int arp_pdu_decode(void *data, size_t size, arp_eth_packet_t *packet)
+{
+	arp_eth_packet_fmt_t *pfmt;
+
+	log_msg(LVL_DEBUG, "arp_pdu_decode()");
+
+	if (size < sizeof(arp_eth_packet_fmt_t)) {
+		log_msg(LVL_DEBUG, "ARP PDU too short (%zu)", size);
+		return EINVAL;
+	}
+
+	pfmt = (arp_eth_packet_fmt_t *)data;
+
+	if (uint16_t_be2host(pfmt->hw_addr_space) != AHRD_ETHERNET) {
+		log_msg(LVL_DEBUG, "HW address space != %u (%" PRIu16 ")",
+		    AHRD_ETHERNET, uint16_t_be2host(pfmt->hw_addr_space));
+		return EINVAL;
+	}
+
+	if (uint16_t_be2host(pfmt->proto_addr_space) != 0x0800) {
+		log_msg(LVL_DEBUG, "Proto address space != %u (%" PRIu16 ")",
+		    ETYPE_IP, uint16_t_be2host(pfmt->proto_addr_space));
+		return EINVAL;
+	}
+
+	if (pfmt->hw_addr_size != ETH_ADDR_SIZE) {
+		log_msg(LVL_DEBUG, "HW address size != %zu (%zu)",
+		    (size_t)ETH_ADDR_SIZE, (size_t)pfmt->hw_addr_size);
+		return EINVAL;
+	}
+
+	if (pfmt->proto_addr_size != IPV4_ADDR_SIZE) {
+		log_msg(LVL_DEBUG, "Proto address size != %zu (%zu)",
+		    (size_t)IPV4_ADDR_SIZE, (size_t)pfmt->proto_addr_size);
+		return EINVAL;
+	}
+
+	switch (uint16_t_be2host(pfmt->opcode)) {
+	case AOP_REQUEST: packet->opcode = aop_request; break;
+	case AOP_REPLY: packet->opcode = aop_reply; break;
+	default:
+		log_msg(LVL_DEBUG, "Invalid ARP opcode (%" PRIu16 ")",
+		    uint16_t_be2host(pfmt->opcode));
+		return EINVAL;
+	}
+
+	mac48_decode(pfmt->sender_hw_addr, &packet->sender_hw_addr);
+	packet->sender_proto_addr.ipv4 =
+	    uint32_t_be2host(pfmt->sender_proto_addr);
+	mac48_decode(pfmt->target_hw_addr, &packet->target_hw_addr);
+	packet->target_proto_addr.ipv4 =
+	    uint32_t_be2host(pfmt->target_proto_addr);
+	log_msg(LVL_DEBUG, "packet->tpa = %x\n", pfmt->target_proto_addr);
+
+	return EOK;
+}
+
+
+/** @}
+ */
Index: uspace/srv/net/ethip/pdu.h
===================================================================
--- uspace/srv/net/ethip/pdu.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/pdu.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,53 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ETH_PDU_H_
+#define ETH_PDU_H_
+
+#include "ethip.h"
+
+extern int eth_pdu_encode(eth_frame_t *, void **, size_t *);
+extern int eth_pdu_decode(void *, size_t, eth_frame_t *);
+extern void mac48_encode(mac48_addr_t *, void *);
+extern void mac48_decode(void *, mac48_addr_t *);
+extern int arp_pdu_encode(arp_eth_packet_t *, void **, size_t *);
+extern int arp_pdu_decode(void *, size_t, arp_eth_packet_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/std.h
===================================================================
--- uspace/srv/net/ethip/std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/ethip/std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,97 @@
+/*
+ * 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 ethip
+ * @{
+ */
+/**
+ * @file Ethernet, IP/Ethernet standard definitions
+ *
+ */
+
+#ifndef ETHIP_STD_H_
+#define ETHIP_STD_H_
+
+#include <sys/types.h>
+
+#define ETH_ADDR_SIZE 6
+#define IPV4_ADDR_SIZE 4
+#define ETH_FRAME_MIN_SIZE 60
+
+/** Ethernet frame header */
+typedef struct {
+	/** Destination Address */
+	uint8_t dest[ETH_ADDR_SIZE];
+	/** Source Address */
+	uint8_t src[ETH_ADDR_SIZE];
+	/** Ethertype or Length */
+	uint16_t etype_len;
+} eth_header_t;
+
+/** ARP packet format (for 48-bit MAC addresses and IPv4) */
+typedef struct {
+	/** Hardware address space */
+	uint16_t hw_addr_space;
+	/** Protocol address space */
+	uint16_t proto_addr_space;
+	/** Hardware address size */
+	uint8_t hw_addr_size;
+	/** Protocol address size */
+	uint8_t proto_addr_size;
+	/** Opcode */
+	uint16_t opcode;
+	/** Sender hardware address */
+	uint8_t sender_hw_addr[ETH_ADDR_SIZE];
+	/** Sender protocol address */
+	uint32_t sender_proto_addr;
+	/** Target hardware address */
+	uint8_t target_hw_addr[ETH_ADDR_SIZE];
+	/** Target protocol address */
+	uint32_t target_proto_addr;
+} __attribute__((packed)) arp_eth_packet_fmt_t;
+
+enum arp_opcode_fmt {
+	AOP_REQUEST = 1,
+	AOP_REPLY   = 2
+};
+
+enum arp_hw_addr_space {
+	AHRD_ETHERNET = 1
+};
+
+/** IP Ethertype */
+enum ether_type {
+	ETYPE_ARP = 0x0806,
+	ETYPE_IP  = 0x0800
+};
+
+
+#endif
+
+/** @}
+ */
Index: pace/srv/net/il/arp/Makefile
===================================================================
--- uspace/srv/net/il/arp/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,38 +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 = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = arp
-
-SOURCES = \
-	arp.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,946 +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 arp
- * @{
- */
-
-/** @file
- * ARP module implementation.
- * @see arp.h
- */
-
-#include <async.h>
-#include <malloc.h>
-#include <mem.h>
-#include <fibril_synch.h>
-#include <assert.h>
-#include <stdio.h>
-#include <str.h>
-#include <task.h>
-#include <adt/measured_strings.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/arp.h>
-#include <ipc/il.h>
-#include <ipc/nil.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <nil_remote.h>
-#include <protocol_map.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <il_remote.h>
-#include <il_skel.h>
-#include "arp.h"
-
-/** ARP module name. */
-#define NAME  "arp"
-
-/** Number of microseconds to wait for an ARP reply. */
-#define ARP_TRANS_WAIT  1000000
-
-/** @name ARP operation codes definitions */
-/*@{*/
-
-/** REQUEST operation code. */
-#define ARPOP_REQUEST  1
-
-/** REPLY operation code. */
-#define ARPOP_REPLY  2
-
-/*@}*/
-
-/** Type definition of an ARP protocol header.
- * @see arp_header
- */
-typedef struct arp_header arp_header_t;
-
-/** ARP protocol header. */
-struct arp_header {
-	/**
-	 * Hardware type identifier.
-	 * @see hardware.h
-	 */
-	uint16_t hardware;
-	
-	/** Protocol identifier. */
-	uint16_t protocol;
-	/** Hardware address length in bytes. */
-	uint8_t hardware_length;
-	/** Protocol address length in bytes. */
-	uint8_t protocol_length;
-	
-	/**
-	 * ARP packet type.
-	 * @see arp_oc.h
-	 */
-	uint16_t operation;
-} __attribute__ ((packed));
-
-/** ARP global data. */
-arp_globals_t arp_globals;
-
-DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
-INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
-GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
-
-static void arp_clear_trans(arp_trans_t *trans)
-{
-	if (trans->hw_addr) {
-		free(trans->hw_addr);
-		trans->hw_addr = NULL;
-	}
-	
-	fibril_condvar_broadcast(&trans->cv);
-}
-
-static void arp_clear_addr(arp_addr_t *addresses)
-{
-	int count;
-	
-	for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
-		arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
-		    count);
-		if (trans)
-			arp_clear_trans(trans);
-	}
-}
-
-/** Clear the device specific data.
- *
- * @param[in] device Device specific data.
- */
-static void arp_clear_device(arp_device_t *device)
-{
-	int count;
-	
-	for (count = arp_protos_count(&device->protos) - 1; count >= 0;
-	    count--) {
-		arp_proto_t *proto = arp_protos_get_index(&device->protos,
-		    count);
-		
-		if (proto) {
-			if (proto->addr)
-				free(proto->addr);
-			
-			if (proto->addr_data)
-				free(proto->addr_data);
-			
-			arp_clear_addr(&proto->addresses);
-			arp_addr_destroy(&proto->addresses, free);
-		}
-	}
-	
-	arp_protos_clear(&device->protos, free);
-}
-
-static int arp_clean_cache_req(void)
-{
-	int count;
-	
-	fibril_mutex_lock(&arp_globals.lock);
-	for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
-	    count--) {
-		arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
-		    count);
-		
-		if (device)
-			arp_clear_device(device);
-	}
-	
-	arp_cache_clear(&arp_globals.cache, free);
-	fibril_mutex_unlock(&arp_globals.lock);
-	
-	return EOK;
-}
-
-static int arp_clear_address_req(nic_device_id_t device_id,
-    services_t protocol, measured_string_t *address)
-{
-	fibril_mutex_lock(&arp_globals.lock);
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	
-	arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
-	if (!proto) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	
-	arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
-	    address->length);
-	if (trans)
-		arp_clear_trans(trans);
-	
-	arp_addr_exclude(&proto->addresses, address->value, address->length, free);
-	
-	fibril_mutex_unlock(&arp_globals.lock);
-	return EOK;
-}
-
-static int arp_clear_device_req(nic_device_id_t device_id)
-{
-	fibril_mutex_lock(&arp_globals.lock);
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	
-	arp_clear_device(device);
-	
-	fibril_mutex_unlock(&arp_globals.lock);
-	return EOK;
-}
-
-/** Create new protocol specific data.
- *
- * Allocate and return the needed memory block as the proto parameter.
- *
- * @param[out] proto   Allocated protocol specific data.
- * @param[in]  service Protocol module service.
- * @param[in]  address Actual protocol device address.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int arp_proto_create(arp_proto_t **proto, services_t service,
-    measured_string_t *address)
-{
-	*proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
-	if (!*proto)
-		return ENOMEM;
-	
-	(*proto)->service = service;
-	(*proto)->addr = address;
-	(*proto)->addr_data = address->value;
-	
-	int rc = arp_addr_initialize(&(*proto)->addresses);
-	if (rc != EOK) {
-		free(*proto);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/** Process the received ARP packet.
- *
- * Update the source hardware address if the source entry exists or the packet
- * is targeted to my protocol address.
- *
- * Respond to the ARP request if the packet is the ARP request and is
- * targeted to my address.
- *
- * @param[in]     device_id Source device identifier.
- * @param[in,out] packet    Received packet.
- *
- * @return EOK on success and the packet is no longer needed.
- * @return One on success and the packet has been reused.
- * @return EINVAL if the packet is too small to carry an ARP
- *         packet.
- * @return EINVAL if the received address lengths differs from
- *         the registered values.
- * @return ENOENT if the device is not found in the cache.
- * @return ENOENT if the protocol for the device is not found in
- *         the cache.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int arp_receive_message(nic_device_id_t device_id, packet_t *packet)
-{
-	int rc;
-	
-	size_t length = packet_get_data_length(packet);
-	if (length <= sizeof(arp_header_t))
-		return EINVAL;
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device)
-		return ENOENT;
-	
-	arp_header_t *header = (arp_header_t *) packet_get_data(packet);
-	if ((ntohs(header->hardware) != device->hardware) ||
-	    (length < sizeof(arp_header_t) + header->hardware_length * 2U +
-	    header->protocol_length * 2U)) {
-		return EINVAL;
-	}
-	
-	arp_proto_t *proto = arp_protos_find(&device->protos,
-	    protocol_unmap(device->service, ntohs(header->protocol)));
-	if (!proto)
-		return ENOENT;
-	
-	uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
-	uint8_t *src_proto = src_hw + header->hardware_length;
-	uint8_t *des_hw = src_proto + header->protocol_length;
-	uint8_t *des_proto = des_hw + header->hardware_length;
-	
-	arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
-	    header->protocol_length);
-	
-	if ((trans) && (trans->hw_addr)) {
-		/* Translation exists */
-		if (trans->hw_addr->length != header->hardware_length)
-			return EINVAL;
-		
-		memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
-	}
-	
-	/* Is my protocol address? */
-	if (proto->addr->length != header->protocol_length)
-		return EINVAL;
-	
-	if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
-		if (!trans) {
-			/* Update the translation */
-			trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
-			if (!trans)
-				return ENOMEM;
-			
-			trans->hw_addr = NULL;
-			fibril_condvar_initialize(&trans->cv);
-			rc = arp_addr_add(&proto->addresses, src_proto,
-			    header->protocol_length, trans);
-			if (rc != EOK) {
-				free(trans);
-				return rc;
-			}
-		}
-		
-		if (!trans->hw_addr) {
-			trans->hw_addr = measured_string_create_bulk(src_hw,
-			    header->hardware_length);
-			if (!trans->hw_addr)
-				return ENOMEM;
-			
-			/* Notify the fibrils that wait for the translation. */
-			fibril_condvar_broadcast(&trans->cv);
-		}
-		
-		if (ntohs(header->operation) == ARPOP_REQUEST) {
-			header->operation = htons(ARPOP_REPLY);
-			memcpy(des_proto, src_proto, header->protocol_length);
-			memcpy(src_proto, proto->addr->value,
-			    header->protocol_length);
-			memcpy(src_hw, device->addr,
-			    device->packet_dimension.addr_len);
-			memcpy(des_hw, trans->hw_addr->value,
-			    header->hardware_length);
-			
-			rc = packet_set_addr(packet, src_hw, des_hw,
-			    header->hardware_length);
-			if (rc != EOK)
-				return rc;
-			
-			nil_send_msg(device->sess, device_id, packet,
-			    SERVICE_ARP);
-			return 1;
-		}
-	}
-	
-	return EOK;
-}
-
-/** Update the device content length according to the new MTU value.
- *
- * @param[in] device_id Device identifier.
- * @param[in] mtu       New MTU value.
- *
- * @return ENOENT if device is not found.
- * @return EOK on success.
- *
- */
-static int arp_mtu_changed_message(nic_device_id_t device_id, size_t mtu)
-{
-	fibril_mutex_lock(&arp_globals.lock);
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	
-	device->packet_dimension.content = mtu;
-	
-	fibril_mutex_unlock(&arp_globals.lock);
-	
-	printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
-	
-	return EOK;
-}
-
-static int arp_addr_changed_message(nic_device_id_t device_id)
-{
-	uint8_t addr_buffer[NIC_MAX_ADDRESS_LENGTH];
-	size_t length;
-	ipc_callid_t data_callid;
-	if (!async_data_write_receive(&data_callid, &length)) {
-		async_answer_0(data_callid, EINVAL);
-		return EINVAL;
-	}
-	if (length > NIC_MAX_ADDRESS_LENGTH) {
-		async_answer_0(data_callid, ELIMIT);
-		return ELIMIT;
-	}
-	if (async_data_write_finalize(data_callid, addr_buffer, length) != EOK) {
-		return EINVAL;
-	}
-
-	fibril_mutex_lock(&arp_globals.lock);
-
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-
-	memcpy(device->addr, addr_buffer, length);
-	device->addr_len = length;
-
-	fibril_mutex_unlock(&arp_globals.lock);
-	return EOK;
-}
-
-/** Process IPC messages from the registered device driver modules
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_IL_DEVICE_STATE:
-			/* Do nothing - keep the cache */
-			async_answer_0(iid, (sysarg_t) EOK);
-			break;
-		
-		case NET_IL_RECEIVED:
-			rc = packet_translate_remote(arp_globals.net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc == EOK) {
-				fibril_mutex_lock(&arp_globals.lock);
-				do {
-					packet_t *next = pq_detach(packet);
-					rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
-					if (rc != 1) {
-						pq_release_remote(arp_globals.net_sess,
-						    packet_get_id(packet));
-					}
-					
-					packet = next;
-				} while (packet);
-				fibril_mutex_unlock(&arp_globals.lock);
-			}
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		
-		case NET_IL_MTU_CHANGED:
-			rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
-			    IPC_GET_MTU(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		case NET_IL_ADDR_CHANGED:
-			rc = arp_addr_changed_message(IPC_GET_DEVICE(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-		
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Register the device.
- *
- * Create new device entry in the cache or update the protocol address if the
- * device with the device identifier and the driver service exists.
- *
- * @param[in] device_id Device identifier.
- * @param[in] service   Device driver service.
- * @param[in] protocol  Protocol service.
- * @param[in] address   Actual device protocol address.
- *
- * @return EOK on success.
- * @return EEXIST if another device with the same device identifier
- *         and different driver service exists.
- * @return ENOMEM if there is not enough memory left.
- * @return Other error codes as defined for the
- *         measured_strings_return() function.
- *
- */
-static int arp_device_message(nic_device_id_t device_id, services_t service,
-    services_t protocol, measured_string_t *address)
-{
-	int index;
-	int rc;
-	
-	fibril_mutex_lock(&arp_globals.lock);
-	
-	/* An existing device? */
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (device) {
-		if (device->service != service) {
-			printf("%s: Device %d already exists\n", NAME,
-			    device->device_id);
-			fibril_mutex_unlock(&arp_globals.lock);
-			return EEXIST;
-		}
-		
-		arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
-		if (proto) {
-			free(proto->addr);
-			free(proto->addr_data);
-			proto->addr = address;
-			proto->addr_data = address->value;
-		} else {
-			rc = arp_proto_create(&proto, protocol, address);
-			if (rc != EOK) {
-				fibril_mutex_unlock(&arp_globals.lock);
-				return rc;
-			}
-			
-			index = arp_protos_add(&device->protos, proto->service,
-			    proto);
-			if (index < 0) {
-				fibril_mutex_unlock(&arp_globals.lock);
-				free(proto);
-				return index;
-			}
-			
-			printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
-			    device_id, protocol);
-		}
-	} else {
-		hw_type_t hardware = hardware_map(service);
-		if (!hardware)
-			return ENOENT;
-		
-		/* Create new device */
-		device = (arp_device_t *) malloc(sizeof(arp_device_t));
-		if (!device) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			return ENOMEM;
-		}
-		
-		device->hardware = hardware;
-		device->device_id = device_id;
-		rc = arp_protos_initialize(&device->protos);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device);
-			return rc;
-		}
-		
-		arp_proto_t *proto;
-		rc = arp_proto_create(&proto, protocol, address);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device);
-			return rc;
-		}
-		
-		index = arp_protos_add(&device->protos, proto->service, proto);
-		if (index < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return index;
-		}
-		
-		device->service = service;
-		
-		/* Bind */
-		device->sess = nil_bind_service(device->service,
-		    (sysarg_t) device->device_id, SERVICE_ARP,
-		    arp_receiver);
-		if (device->sess == NULL) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return EREFUSED;
-		}
-		
-		/* Get packet dimensions */
-		rc = nil_packet_size_req(device->sess, device_id,
-		    &device->packet_dimension);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return rc;
-		}
-		
-		/* Get hardware address */
-		int len = nil_get_addr_req(device->sess, device_id, device->addr,
-		    NIC_MAX_ADDRESS_LENGTH);
-		if (len < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return len;
-		}
-		
-		device->addr_len = len;
-		
-		/* Get broadcast address */
-		len = nil_get_broadcast_addr_req(device->sess, device_id,
-		    device->broadcast_addr, NIC_MAX_ADDRESS_LENGTH);
-		if (len < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return len;
-		}
-		
-		device->broadcast_addr_len = len;
-		
-		rc = arp_cache_add(&arp_globals.cache, device->device_id,
-		    device);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return rc;
-		}
-		printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
-		    " proto: %d)\n", NAME, device->device_id, device->hardware,
-		    device->service, protocol);
-	}
-	
-	fibril_mutex_unlock(&arp_globals.lock);
-	return EOK;
-}
-
-int il_initialize(async_sess_t *net_sess)
-{
-	fibril_mutex_initialize(&arp_globals.lock);
-	
-	fibril_mutex_lock(&arp_globals.lock);
-	arp_globals.net_sess = net_sess;
-	int rc = arp_cache_initialize(&arp_globals.cache);
-	fibril_mutex_unlock(&arp_globals.lock);
-	
-	return rc;
-}
-
-static int arp_send_request(nic_device_id_t device_id, services_t protocol,
-    measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
-{
-	/* ARP packet content size = header + (address + translation) * 2 */
-	size_t length = 8 + 2 * (proto->addr->length + device->addr_len);
-	if (length > device->packet_dimension.content)
-		return ELIMIT;
-	
-	packet_t *packet = packet_get_4_remote(arp_globals.net_sess,
-	    device->packet_dimension.addr_len, device->packet_dimension.prefix,
-	    length, device->packet_dimension.suffix);
-	if (!packet)
-		return ENOMEM;
-	
-	arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
-	if (!header) {
-		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
-		return ENOMEM;
-	}
-	
-	header->hardware = htons(device->hardware);
-	header->hardware_length = (uint8_t) device->addr_len;
-	header->protocol = htons(protocol_map(device->service, protocol));
-	header->protocol_length = (uint8_t) proto->addr->length;
-	header->operation = htons(ARPOP_REQUEST);
-	
-	length = sizeof(arp_header_t);
-	memcpy(((uint8_t *) header) + length, device->addr,
-	    device->addr_len);
-	length += device->addr_len;
-	memcpy(((uint8_t *) header) + length, proto->addr->value,
-	    proto->addr->length);
-	length += proto->addr->length;
-	bzero(((uint8_t *) header) + length, device->addr_len);
-	length += device->addr_len;
-	memcpy(((uint8_t *) header) + length, target->value, target->length);
-	
-	int rc = packet_set_addr(packet, device->addr, device->broadcast_addr,
-	    device->addr_len);
-	if (rc != EOK) {
-		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
-		return rc;
-	}
-	
-	nil_send_msg(device->sess, device_id, packet, SERVICE_ARP);
-	return EOK;
-}
-
-/** Return the hardware address for the given protocol address.
- *
- * Send the ARP request packet if the hardware address is not found in the
- * cache.
- *
- * @param[in]  device_id   Device identifier.
- * @param[in]  protocol    Protocol service.
- * @param[in]  target      Target protocol address.
- * @param[out] translation Where the hardware address of the target is stored.
- *
- * @return EOK on success.
- * @return EAGAIN if the caller should try again.
- * @return Other error codes in case of error.
- *
- */
-static int arp_translate_message(nic_device_id_t device_id, services_t protocol,
-    measured_string_t *target, measured_string_t **translation)
-{
-	bool retry = false;
-	int rc;
-
-	assert(fibril_mutex_is_locked(&arp_globals.lock));
-	
-restart:
-	if ((!target) || (!translation))
-		return EBADMEM;
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device)
-		return ENOENT;
-	
-	arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
-	if ((!proto) || (proto->addr->length != target->length))
-		return ENOENT;
-	
-	arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
-	    target->length);
-	if (trans) {
-		if (trans->hw_addr) {
-			/* The translation is in place. */
-			*translation = trans->hw_addr;
-			return EOK;
-		}
-		
-		if (retry) {
-			/*
-			 * We may get here as a result of being signalled for
-			 * some reason while waiting for the translation (e.g.
-			 * translation becoming available, record being removed
-			 * from the table) and then losing the race for
-			 * the arp_globals.lock with someone else who modified
-			 * the table.
-			 *
-			 * Remove the incomplete record so that it is possible
-			 * to make new ARP requests.
-			 */
-			arp_clear_trans(trans);
-			arp_addr_exclude(&proto->addresses, target->value,
-			    target->length, free);
-			return EAGAIN;
-		}
-		
-		/*
-		 * We are a random passer-by who merely joins an already waiting
-		 * fibril in waiting for the translation.
-		 */
-		rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
-		    ARP_TRANS_WAIT);
-		if (rc == ETIMEOUT)
-			return ENOENT;
-		
-		/*
-		 * Need to recheck because we did not hold the lock while
-		 * sleeping on the condition variable.
-		 */
-		retry = true;
-		goto restart;
-	}
-	
-	if (retry)
-		return EAGAIN;
-
-	/*
-	 * We are under the protection of arp_globals.lock, so we can afford to
-	 * first send the ARP request and then insert an incomplete ARP record.
-	 * The incomplete record is used to tell any other potential waiter
-	 * that this fibril has already sent the request and that it is waiting
-	 * for the answer. Lastly, any fibril which sees the incomplete request
-	 * can perform a timed wait on its condition variable to wait for the
-	 * ARP reply to arrive.
-	 */
-
-	rc = arp_send_request(device_id, protocol, target, device, proto);
-	if (rc != EOK)
-		return rc;
-	
-	trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
-	if (!trans)
-		return ENOMEM;
-	
-	trans->hw_addr = NULL;
-	fibril_condvar_initialize(&trans->cv);
-	
-	rc = arp_addr_add(&proto->addresses, target->value, target->length,
-	    trans);
-	if (rc != EOK) {
-		free(trans);
-		return rc;
-	}
-	
-	rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
-	    ARP_TRANS_WAIT);
-	if (rc == ETIMEOUT) {
-		/*
-		 * Remove the incomplete record so that it is possible to make 
-		 * new ARP requests.
-		 */
-		arp_clear_trans(trans);
-		arp_addr_exclude(&proto->addresses, target->value,
-		    target->length, free);
-		return ENOENT;
-	}
-	
-	/*
-	 * We need to recheck that the translation has indeed become available,
-	 * because we dropped the arp_globals.lock while sleeping on the
-	 * condition variable and someone else might have e.g. removed the
-	 * translation before we managed to lock arp_globals.lock again.
-	 */
-
-	retry = true;
-	goto restart;
-}
-
-/** Process the ARP message.
- *
- * @param[in]  callid Message identifier.
- * @param[in]  call   Message parameters.
- * @param[out] answer Answer.
- * @param[out] count  Number of arguments of the answer.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is not known.
- *
- * @see arp_interface.h
- * @see IS_NET_ARP_MESSAGE()
- *
- */
-int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *count)
-{
-	measured_string_t *address;
-	measured_string_t *translation;
-	uint8_t *data;
-	int rc;
-	
-	*count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_ARP_DEVICE:
-		rc = measured_strings_receive(&address, &data, 1);
-		if (rc != EOK)
-			return rc;
-		
-		rc = arp_device_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
-		if (rc != EOK) {
-			free(address);
-			free(data);
-		}
-		
-		return rc;
-	
-	case NET_ARP_TRANSLATE:
-		rc = measured_strings_receive(&address, &data, 1);
-		if (rc != EOK)
-			return rc;
-		
-		fibril_mutex_lock(&arp_globals.lock);
-		rc = arp_translate_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call), address, &translation);
-		free(address);
-		free(data);
-		
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			return rc;
-		}
-		
-		if (!translation) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			return ENOENT;
-		}
-		
-		rc = measured_strings_reply(translation, 1);
-		fibril_mutex_unlock(&arp_globals.lock);
-		return rc;
-	
-	case NET_ARP_CLEAR_DEVICE:
-		return arp_clear_device_req(IPC_GET_DEVICE(*call));
-	
-	case NET_ARP_CLEAR_ADDRESS:
-		rc = measured_strings_receive(&address, &data, 1);
-		if (rc != EOK)
-			return rc;
-		
-		arp_clear_address_req(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call), address);
-		free(address);
-		free(data);
-		return EOK;
-	
-	case NET_ARP_CLEAN_CACHE:
-		return arp_clean_cache_req();
-	}
-	
-	return ENOTSUP;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return il_module_start(SERVICE_ARP);
-}
-
-/** @}
- */
Index: pace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,159 +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 arp
- * @{
- */
-
-/** @file
- * ARP module.
- */
-
-#ifndef NET_ARP_H_
-#define NET_ARP_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <net_hardware.h>
-#include <adt/generic_char_map.h>
-#include <adt/int_map.h>
-#include <adt/measured_strings.h>
-
-/** Type definition of the ARP device specific data.
- * @see arp_device
- */
-typedef struct arp_device arp_device_t;
-
-/** Type definition of the ARP global data.
- * @see arp_globals
- */
-typedef struct arp_globals arp_globals_t;
-
-/** Type definition of the ARP protocol specific data.
- * @see arp_proto
- */
-typedef struct arp_proto arp_proto_t;
-
-/** Type definition of the ARP address translation record.
- * @see arp_trans
- */
-typedef struct arp_trans arp_trans_t;
-
-/** ARP address map.
- *
- * Translates addresses.
- * @see generic_char_map.h
- */
-GENERIC_CHAR_MAP_DECLARE(arp_addr, arp_trans_t);
-
-/** ARP address cache.
- *
- * Maps devices to the ARP device specific data.
- * @see device.h
- */
-DEVICE_MAP_DECLARE(arp_cache, arp_device_t);
-
-/** ARP protocol map.
- *
- * Maps protocol identifiers to the ARP protocol specific data.
- * @see int_map.h
- */
-INT_MAP_DECLARE(arp_protos, arp_proto_t);
-
-/** ARP device specific data. */
-struct arp_device {
-	/** Actual device hardware address. */
-	uint8_t addr[NIC_MAX_ADDRESS_LENGTH];
-	/** Actual device hardware address length. */
-	size_t addr_len;
-	/** Broadcast device hardware address. */
-	uint8_t broadcast_addr[NIC_MAX_ADDRESS_LENGTH];
-	/** Broadcast device hardware address length. */
-	size_t broadcast_addr_len;
-	/** Device identifier. */
-	nic_device_id_t device_id;
-	/** Hardware type. */
-	hw_type_t hardware;
-	/** Packet dimension. */
-	packet_dimension_t packet_dimension;
-	/** Device module session. */
-	async_sess_t *sess;
-	
-	/**
-	 * Protocol map.
-	 * Address map for each protocol.
-	 */
-	arp_protos_t protos;
-	
-	/** Device module service. */
-	services_t service;
-};
-
-/** ARP global data. */
-struct arp_globals {
-	/** ARP address cache. */
-	arp_cache_t cache;
-	
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	
-	/** Safety lock. */
-	fibril_mutex_t lock;
-};
-
-/** ARP protocol specific data. */
-struct arp_proto {
-	/** Actual device protocol address. */
-	measured_string_t *addr;
-	/** Actual device protocol address data. */
-	uint8_t *addr_data;
-	/** Address map. */
-	arp_addr_t addresses;
-	/** Protocol service. */
-	services_t service;
-};
-
-/** ARP address translation record. */
-struct arp_trans {
-	/**
-	 * Hardware address for the translation. NULL denotes an incomplete
-	 * record with possible waiters.
-	 */
-	measured_string_t *hw_addr;
-	/** Condition variable used for waiting for completion of the record. */
-	fibril_condvar_t cv;
-};
-
-#endif
-
-/** @}
- */
-
Index: pace/srv/net/il/ip/Makefile
===================================================================
--- uspace/srv/net/il/ip/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,38 +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 = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = ip
-
-SOURCES = \
-	ip.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,2010 +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 ip
- * @{
- */
-
-/** @file
- * IP module implementation.
- * @see arp.h
- */
-
-#include <async.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <stdio.h>
-#include <str.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/nil.h>
-#include <ipc/il.h>
-#include <ipc/ip.h>
-#include <sys/types.h>
-#include <byteorder.h>
-#include "ip.h"
-
-#include <adt/measured_strings.h>
-#include <adt/module_map.h>
-
-#include <packet_client.h>
-#include <net/socket_codes.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <net/icmp_codes.h>
-
-#include <arp_interface.h>
-#include <net_checksum.h>
-#include <icmp_client.h>
-#include <icmp_remote.h>
-#include <ip_client.h>
-#include <ip_interface.h>
-#include <ip_header.h>
-#include <net_interface.h>
-#include <nil_remote.h>
-#include <tl_remote.h>
-#include <packet_remote.h>
-#include <il_remote.h>
-#include <il_skel.h>
-
-/** IP module name. */
-#define NAME			"ip"
-
-/** IP version 4. */
-#define IPV4			4
-
-/** Default network interface IP version. */
-#define NET_DEFAULT_IPV		IPV4
-
-/** Default network interface IP routing. */
-#define NET_DEFAULT_IP_ROUTING	false
-
-/** Minimum IP packet content. */
-#define IP_MIN_CONTENT		576
-
-/** ARP module name. */
-#define ARP_NAME		"arp"
-
-/** ARP module filename. */
-#define ARP_FILENAME		"/srv/arp"
-
-/** IP packet address length. */
-#define IP_ADDR			sizeof(struct sockaddr_in6)
-
-/** IP packet prefix length. */
-#define IP_PREFIX		sizeof(ip_header_t)
-
-/** IP packet suffix length. */
-#define IP_SUFFIX		0
-
-/** IP packet maximum content length. */
-#define IP_MAX_CONTENT		65535
-
-/** The IP localhost address. */
-#define IPV4_LOCALHOST_ADDRESS	htonl((127 << 24) + 1)
-
-/** IP global data. */
-ip_globals_t ip_globals;
-
-DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t);
-INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
-GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
-
-static void ip_receiver(ipc_callid_t, ipc_call_t *, void *);
-
-/** Release the packet and returns the result.
- *
- * @param[in] packet Packet queue to be released.
- * @param[in] result Result to be returned.
- *
- * @return Result parameter.
- *
- */
-static int ip_release_and_return(packet_t *packet, int result)
-{
-	pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
-	return result;
-}
-
-/** Return the ICMP session.
- *
- * Search the registered protocols.
- *
- * @return Found ICMP session.
- * @return NULL if the ICMP is not registered.
- *
- */
-static async_sess_t *ip_get_icmp_session(void)
-{
-	fibril_rwlock_read_lock(&ip_globals.protos_lock);
-	ip_proto_t *proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
-	async_sess_t *sess = proto ? proto->sess : NULL;
-	fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-	
-	return sess;
-}
-
-/** Prepares the ICMP notification packet.
- *
- * Releases additional packets and keeps only the first one.
- *
- * @param[in] packet	The packet or the packet queue to be reported as faulty.
- * @param[in] header	The first packet IP header. May be NULL.
- * @return		EOK on success.
- * @return		EINVAL if there are no data in the packet.
- * @return		EINVAL if the packet is a fragment.
- * @return		ENOMEM if the packet is too short to contain the IP
- *			header.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		EPERM if the protocol is not allowed to send ICMP
- *			notifications. The ICMP protocol itself.
- * @return		Other error codes as defined for the packet_set_addr().
- */
-static int ip_prepare_icmp(packet_t *packet, ip_header_t *header)
-{
-	packet_t *next;
-	struct sockaddr *dest;
-	struct sockaddr_in dest_in;
-	socklen_t addrlen;
-
-	/* Detach the first packet and release the others */
-	next = pq_detach(packet);
-	if (next)
-		pq_release_remote(ip_globals.net_sess, packet_get_id(next));
-
-	if (!header) {
-		if (packet_get_data_length(packet) <= sizeof(ip_header_t))
-			return ENOMEM;
-
-		/* Get header */
-		header = (ip_header_t *) packet_get_data(packet);
-		if (!header)
-			return EINVAL;
-
-	}
-
-	/* Only for the first fragment */
-	if (IP_FRAGMENT_OFFSET(header))
-		return EINVAL;
-
-	/* Not for the ICMP protocol */
-	if (header->protocol == IPPROTO_ICMP)
-		return EPERM;
-
-	/* Set the destination address */
-	switch (GET_IP_HEADER_VERSION(header)) {
-	case IPVERSION:
-		addrlen = sizeof(dest_in);
-		bzero(&dest_in, addrlen);
-		dest_in.sin_family = AF_INET;
-		memcpy(&dest_in.sin_addr.s_addr, &header->source_address,
-		    sizeof(header->source_address));
-		dest = (struct sockaddr *) &dest_in;
-		break;
-
-	default:
-		return EAFNOSUPPORT;
-	}
-
-	return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
-}
-
-/** Prepare the ICMP notification packet.
- *
- * Release additional packets and keep only the first one.
- * All packets are released on error.
- *
- * @param[in] error  Packet error service.
- * @param[in] packet Packet or the packet queue to be reported as faulty.
- * @param[in] header First packet IP header. May be NULL.
- *
- * @return Found ICMP session.
- * @return NULL if the error parameter is set.
- * @return NULL if the ICMP session is not found.
- * @return NULL if the ip_prepare_icmp() fails.
- *
- */
-static async_sess_t *ip_prepare_icmp_and_get_session(services_t error,
-    packet_t *packet, ip_header_t *header)
-{
-	async_sess_t *sess = ip_get_icmp_session();
-	
-	if ((error) || (!sess) || (ip_prepare_icmp(packet, header))) {
-		pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
-		return NULL;
-	}
-	
-	return sess;
-}
-
-int il_initialize(async_sess_t *net_sess)
-{
-	fibril_rwlock_initialize(&ip_globals.lock);
-	fibril_rwlock_write_lock(&ip_globals.lock);
-	fibril_rwlock_initialize(&ip_globals.protos_lock);
-	fibril_rwlock_initialize(&ip_globals.netifs_lock);
-	
-	ip_globals.net_sess = net_sess;
-	ip_globals.packet_counter = 0;
-	ip_globals.gateway.address.s_addr = 0;
-	ip_globals.gateway.netmask.s_addr = 0;
-	ip_globals.gateway.gateway.s_addr = 0;
-	ip_globals.gateway.netif = NULL;
-	
-	int rc = ip_netifs_initialize(&ip_globals.netifs);
-	if (rc != EOK)
-		goto out;
-	rc = ip_protos_initialize(&ip_globals.protos);
-	if (rc != EOK)
-		goto out;
-	rc = modules_initialize(&ip_globals.modules);
-	if (rc != EOK)
-		goto out;
-	rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME,
-	    (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module);
-
-out:
-	fibril_rwlock_write_unlock(&ip_globals.lock);
-
-	return rc;
-}
-
-/** Initializes a new network interface specific data.
- *
- * Connects to the network interface layer module, reads the netif
- * configuration, starts an ARP module if needed and sets the netif routing
- * table.
- * 
- * The device identifier and the nil service has to be set.
- *
- * @param[in,out] ip_netif Network interface specific data.
- * @return		EOK on success.
- * @return		ENOTSUP if DHCP is configured.
- * @return		ENOTSUP if IPv6 is configured.
- * @return		EINVAL if any of the addresses is invalid.
- * @return		EINVAL if the used ARP module is not known.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			net_get_device_conf_req() function.
- * @return		Other error codes as defined for the bind_service()
- *			function.
- * @return		Other error codes as defined for the specific
- *			arp_device_req() function.
- * @return		Other error codes as defined for the
- *			nil_packet_size_req() function.
- */
-static int ip_netif_initialize(ip_netif_t *ip_netif)
-{
-	measured_string_t names[] = {
-		{
-			(uint8_t *) "IPV",
-			3
-		},
-		{
-			(uint8_t *) "IP_CONFIG",
-			9
-		},
-		{
-			(uint8_t *) "IP_ADDR",
-			7
-		},
-		{
-			(uint8_t *) "IP_NETMASK",
-			10
-		},
-		{
-			(uint8_t *) "IP_GATEWAY",
-			10
-		},
-		{
-			(uint8_t *) "IP_BROADCAST",
-			12
-		},
-		{
-			(uint8_t *) "ARP",
-			3
-		},
-		{
-			(uint8_t *) "IP_ROUTING",
-			10
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	measured_string_t address;
-	ip_route_t *route;
-	in_addr_t gateway;
-	int index;
-	int rc;
-
-	ip_netif->arp = NULL;
-	route = NULL;
-	ip_netif->ipv = NET_DEFAULT_IPV;
-	ip_netif->dhcp = false;
-	ip_netif->routing = NET_DEFAULT_IP_ROUTING;
-	configuration = &names[0];
-	
-	/* Get configuration */
-	rc = net_get_device_conf_req(ip_globals.net_sess, ip_netif->device_id,
-	    &configuration, count, &data);
-	if (rc != EOK)
-		return rc;
-	
-	if (configuration) {
-		if (configuration[0].value)
-			ip_netif->ipv = strtol((char *) configuration[0].value, NULL, 0);
-		
-		ip_netif->dhcp = !str_lcmp((char *) configuration[1].value, "dhcp",
-		    configuration[1].length);
-		
-		if (ip_netif->dhcp) {
-			// TODO dhcp
-			net_free_settings(configuration, data);
-			return ENOTSUP;
-		} else if (ip_netif->ipv == IPV4) {
-			route = (ip_route_t *) malloc(sizeof(ip_route_t));
-			if (!route) {
-				net_free_settings(configuration, data);
-				return ENOMEM;
-			}
-			route->address.s_addr = 0;
-			route->netmask.s_addr = 0;
-			route->gateway.s_addr = 0;
-			route->netif = ip_netif;
-			index = ip_routes_add(&ip_netif->routes, route);
-			if (index < 0) {
-				net_free_settings(configuration, data);
-				free(route);
-				return index;
-			}
-			
-			if ((inet_pton(AF_INET, (char *) configuration[2].value,
-			    (uint8_t *) &route->address.s_addr) != EOK) ||
-			    (inet_pton(AF_INET, (char *) configuration[3].value,
-			    (uint8_t *) &route->netmask.s_addr) != EOK) ||
-			    (inet_pton(AF_INET, (char *) configuration[4].value,
-			    (uint8_t *) &gateway.s_addr) == EINVAL) ||
-			    (inet_pton(AF_INET, (char *) configuration[5].value,
-			    (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
-			    {
-				net_free_settings(configuration, data);
-				return EINVAL;
-			}
-		} else {
-			// TODO ipv6 in separate module
-			net_free_settings(configuration, data);
-			return ENOTSUP;
-		}
-		
-		if (configuration[6].value) {
-			ip_netif->arp = get_running_module(&ip_globals.modules,
-			    configuration[6].value);
-			if (!ip_netif->arp) {
-				printf("Failed to start the arp %s\n",
-				    configuration[6].value);
-				net_free_settings(configuration, data);
-				return EINVAL;
-			}
-		}
-		
-		if (configuration[7].value)
-			ip_netif->routing = (configuration[7].value[0] == 'y');
-		
-		net_free_settings(configuration, data);
-	}
-	
-	/* Bind netif service which also initializes the device */
-	ip_netif->sess = nil_bind_service(ip_netif->service,
-	    (sysarg_t) ip_netif->device_id, SERVICE_IP,
-	    ip_receiver);
-	if (ip_netif->sess == NULL) {
-		printf("Failed to contact the nil service %d\n",
-		    ip_netif->service);
-		return ENOENT;
-	}
-	
-	/* Has to be after the device netif module initialization */
-	if (ip_netif->arp) {
-		if (route) {
-			address.value = (uint8_t *) &route->address.s_addr;
-			address.length = sizeof(in_addr_t);
-			
-			rc = arp_device_req(ip_netif->arp->sess,
-			    ip_netif->device_id, SERVICE_IP, ip_netif->service,
-			    &address);
-			if (rc != EOK)
-				return rc;
-		} else {
-			ip_netif->arp = 0;
-		}
-	}
-	
-	/* Get packet dimensions */
-	rc = nil_packet_size_req(ip_netif->sess, ip_netif->device_id,
-	    &ip_netif->packet_dimension);
-	if (rc != EOK)
-		return rc;
-	
-	if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) {
-		printf("Maximum transmission unit %zu bytes is too small, at "
-		    "least %d bytes are needed\n",
-		    ip_netif->packet_dimension.content, IP_MIN_CONTENT);
-		ip_netif->packet_dimension.content = IP_MIN_CONTENT;
-	}
-	
-	index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
-	if (index < 0)
-		return index;
-	
-	if (gateway.s_addr) {
-		/* The default gateway */
-		ip_globals.gateway.address.s_addr = 0;
-		ip_globals.gateway.netmask.s_addr = 0;
-		ip_globals.gateway.gateway.s_addr = gateway.s_addr;
-		ip_globals.gateway.netif = ip_netif;
-		
-		char defgateway[INET_ADDRSTRLEN];
-		inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr,
-		    defgateway, INET_ADDRSTRLEN);
-		printf("%s: Default gateway (%s)\n", NAME, defgateway);
-	}
-	
-	return EOK;
-}
-
-static int ip_device_req_local(nic_device_id_t device_id, services_t netif)
-{
-	ip_netif_t *ip_netif;
-	ip_route_t *route;
-	int index;
-	int rc;
-
-	ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
-	if (!ip_netif)
-		return ENOMEM;
-
-	rc = ip_routes_initialize(&ip_netif->routes);
-	if (rc != EOK) {
-		free(ip_netif);
-		return rc;
-	}
-	
-	ip_netif->device_id = device_id;
-	ip_netif->service = netif;
-	ip_netif->state = NIC_STATE_STOPPED;
-	
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-
-	rc = ip_netif_initialize(ip_netif);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		ip_routes_destroy(&ip_netif->routes, free);
-		free(ip_netif);
-		return rc;
-	}
-	if (ip_netif->arp)
-		ip_netif->arp->usage++;
-
-	/* Print the settings */
-	printf("%s: Device registered (id: %d, ipv: %d, conf: %s)\n",
-	    NAME, ip_netif->device_id, ip_netif->ipv,
-	    ip_netif->dhcp ? "dhcp" : "static");
-	
-	// TODO ipv6 addresses
-	
-	char address[INET_ADDRSTRLEN];
-	char netmask[INET_ADDRSTRLEN];
-	char gateway[INET_ADDRSTRLEN];
-	
-	for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
-		route = ip_routes_get_index(&ip_netif->routes, index);
-		if (route) {
-			inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
-			    address, INET_ADDRSTRLEN);
-			inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
-			    netmask, INET_ADDRSTRLEN);
-			inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
-			    gateway, INET_ADDRSTRLEN);
-			printf("%s: Route %d (address: %s, netmask: %s, "
-			    "gateway: %s)\n", NAME, index, address, netmask,
-			    gateway);
-		}
-	}
-	
-	inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
-	    INET_ADDRSTRLEN);
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Broadcast (%s)\n", NAME, address);
-
-	return EOK;
-}
-
-/** Searches the network interfaces if there is a suitable route.
- *
- * @param[in] netif	The network interface to be searched for routes. May be
- *			NULL.
- * @param[in] destination The destination address.
- * @return		The found route.
- * @return		NULL if no route was found.
- */
-static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
-    in_addr_t destination)
-{
-	int index;
-	ip_route_t *route;
-	
-	if (!netif)
-		return NULL;
-	
-	/* Start with the first one (the direct route) */
-	for (index = 0; index < ip_routes_count(&netif->routes); index++) {
-		route = ip_routes_get_index(&netif->routes, index);
-		if ((route) &&
-		    ((route->address.s_addr & route->netmask.s_addr) ==
-		    (destination.s_addr & route->netmask.s_addr)))
-			return route;
-	}
-
-	return NULL;
-}
-
-/** Searches all network interfaces if there is a suitable route.
- *
- * @param[in] destination The destination address.
- * @return		The found route.
- * @return		NULL if no route was found.
- */
-static ip_route_t *ip_find_route(in_addr_t destination) {
-	int index;
-	ip_route_t *route;
-	ip_netif_t *netif;
-
-	/* Start with the last netif - the newest one */
-	index = ip_netifs_count(&ip_globals.netifs) - 1;
-	while (index >= 0) {
-		netif = ip_netifs_get_index(&ip_globals.netifs, index);
-		if (netif && (netif->state == NIC_STATE_ACTIVE)) {
-			route = ip_netif_find_route(netif, destination);
-			if (route)
-				return route;
-		}
-		index--;
-	}
-
-	return &ip_globals.gateway;
-}
-
-/** Returns the network interface's IP address.
- *
- * @param[in] netif	The network interface.
- * @return		The IP address.
- * @return		NULL if no IP address was found.
- */
-static in_addr_t *ip_netif_address(ip_netif_t *netif)
-{
-	ip_route_t *route;
-
-	route = ip_routes_get_index(&netif->routes, 0);
-	return route ? &route->address : NULL;
-}
-
-/** Copies the fragment header.
- *
- * Copies only the header itself and relevant IP options.
- *
- * @param[out] last	The created header.
- * @param[in] first	The original header to be copied.
- */
-static void ip_create_last_header(ip_header_t *last, ip_header_t *first)
-{
-	ip_option_t *option;
-	size_t next;
-	size_t length;
-
-	/* Copy first itself */
-	memcpy(last, first, sizeof(ip_header_t));
-	length = sizeof(ip_header_t);
-	next = sizeof(ip_header_t);
-
-	/* Process all IP options */
-	while (next < GET_IP_HEADER_LENGTH(first)) {
-		option = (ip_option_t *) (((uint8_t *) first) + next);
-		/* Skip end or noop */
-		if ((option->type == IPOPT_END) ||
-		    (option->type == IPOPT_NOOP)) {
-			next++;
-		} else {
-			/* Copy if told so or skip */
-			if (IPOPT_COPIED(option->type)) {
-				memcpy(((uint8_t *) last) + length,
-				    ((uint8_t *) first) + next, option->length);
-				length += option->length;
-			}
-			/* Next option */
-			next += option->length;
-		}
-	}
-
-	/* Align 4 byte boundary */
-	if (length % 4) {
-		bzero(((uint8_t *) last) + length, 4 - (length % 4));
-		SET_IP_HEADER_LENGTH(last, (length / 4 + 1));
-	} else {
-		SET_IP_HEADER_LENGTH(last, (length / 4));
-	}
-
-	last->header_checksum = 0;
-}
-
-/** Prepares the outgoing packet or the packet queue.
- *
- * The packet queue is a fragmented packet
- * Updates the first packet's IP header.
- * Prefixes the additional packets with fragment headers.
- *
- * @param[in] source	The source address.
- * @param[in] dest	The destination address.
- * @param[in,out] packet The packet to be sent.
- * @param[in] destination The destination hardware address.
- * @return		EOK on success.
- * @return		EINVAL if the packet is too small to contain the IP
- *			header.
- * @return		EINVAL if the packet is too long than the IP allows.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the packet_set_addr()
- *			function.
- */
-static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
-    packet_t *packet, measured_string_t *destination)
-{
-	size_t length;
-	ip_header_t *header;
-	ip_header_t *last_header;
-	ip_header_t *middle_header;
-	packet_t *next;
-	int rc;
-
-	length = packet_get_data_length(packet);
-	if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))
-		return EINVAL;
-
-	header = (ip_header_t *) packet_get_data(packet);
-	if (destination) {
-		rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
-		    destination->length);
-	} else {
-		rc = packet_set_addr(packet, NULL, NULL, 0);
-	}
-	if (rc != EOK)
-		return rc;
-	
-	SET_IP_HEADER_VERSION(header, IPV4);
-	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, 0);
-	header->fragment_offset_low = 0;
-	header->header_checksum = 0;
-	if (source)
-		header->source_address = source->s_addr;
-	header->destination_address = dest.s_addr;
-
-	fibril_rwlock_write_lock(&ip_globals.lock);
-	ip_globals.packet_counter++;
-	header->identification = htons(ip_globals.packet_counter);
-	fibril_rwlock_write_unlock(&ip_globals.lock);
-
-	if (pq_next(packet)) {
-		last_header = (ip_header_t *) malloc(IP_HEADER_LENGTH(header));
-		if (!last_header)
-			return ENOMEM;
-		ip_create_last_header(last_header, header);
-		next = pq_next(packet);
-		while (pq_next(next)) {
-			middle_header = (ip_header_t *) packet_prefix(next,
-			    IP_HEADER_LENGTH(last_header));
-			if (!middle_header) {
-				free(last_header);
-				return ENOMEM;
-			}
-
-			memcpy(middle_header, last_header,
-			    IP_HEADER_LENGTH(last_header));
-			SET_IP_HEADER_FLAGS(header,
-			    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
-			middle_header->total_length =
-			    htons(packet_get_data_length(next));
-			SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
-			    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
-			middle_header->fragment_offset_low =
-			    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
-			middle_header->header_checksum =
-			    IP_HEADER_CHECKSUM(middle_header);
-			if (destination) {
-				rc = packet_set_addr(next, NULL,
-				    (uint8_t *) destination->value,
-				    destination->length);
-				if (rc != EOK) {
-				    	free(last_header);
-					return rc;
-				}
-			}
-			length += packet_get_data_length(next);
-			next = pq_next(next);
-		}
-
-		middle_header = (ip_header_t *) packet_prefix(next,
-		    IP_HEADER_LENGTH(last_header));
-		if (!middle_header) {
-			free(last_header);
-			return ENOMEM;
-		}
-
-		memcpy(middle_header, last_header,
-		    IP_HEADER_LENGTH(last_header));
-		middle_header->total_length =
-		    htons(packet_get_data_length(next));
-		SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
-		    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
-		middle_header->fragment_offset_low =
-		    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
-		middle_header->header_checksum =
-		    IP_HEADER_CHECKSUM(middle_header);
-		if (destination) {
-			rc = packet_set_addr(next, NULL,
-			    (uint8_t *) destination->value,
-			    destination->length);
-			if (rc != EOK) {
-				free(last_header);
-				return rc;
-			}
-		}
-		length += packet_get_data_length(next);
-		free(last_header);
-		SET_IP_HEADER_FLAGS(header,
-		    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
-	}
-
-	header->total_length = htons(length);
-	/* Unnecessary for all protocols */
-	header->header_checksum = IP_HEADER_CHECKSUM(header);
-
-	return EOK;
-}
-
-/** Fragments the packet from the end.
- *
- * @param[in] packet	The packet to be fragmented.
- * @param[in,out] new_packet The new packet fragment.
- * @param[in,out] header The original packet header.
- * @param[in,out] new_header The new packet fragment header.
- * @param[in] length	The new fragment length.
- * @param[in] src	The source address.
- * @param[in] dest	The destiantion address.
- * @param[in] addrlen	The address length.
- * @return		EOK on success.
- * @return		ENOMEM if the target packet is too small.
- * @return		Other error codes as defined for the packet_set_addr()
- *			function.
- * @return		Other error codes as defined for the pq_insert_after()
- *			function.
- */
-static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
-    ip_header_t *header, ip_header_t *new_header, size_t length,
-    const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
-{
-	void *data;
-	size_t offset;
-	int rc;
-
-	data = packet_suffix(new_packet, length);
-	if (!data)
-		return ENOMEM;
-
-	memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
-	    length);
-	
-	rc = packet_trim(packet, 0, length);
-	if (rc != EOK)
-		return rc;
-	
-	header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
-	new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
-	offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
-	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(new_header,
-	    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset));
-	new_header->fragment_offset_low =
-	    IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
-	new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
-	
-	rc = packet_set_addr(new_packet, (const uint8_t *) src,
-	    (const uint8_t *) dest, addrlen);
-	if (rc != EOK)
-		return rc;
-
-	return pq_insert_after(packet, new_packet);
-}
-
-/** Prefixes a middle fragment header based on the last fragment header to the
- * packet.
- *
- * @param[in] packet	The packet to be prefixed.
- * @param[in] last	The last header to be copied.
- * @return		The prefixed middle header.
- * @return		NULL on error.
- */
-static ip_header_t *ip_create_middle_header(packet_t *packet,
-    ip_header_t *last)
-{
-	ip_header_t *middle;
-
-	middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
-	if (!middle)
-		return NULL;
-	memcpy(middle, last, IP_HEADER_LENGTH(last));
-	SET_IP_HEADER_FLAGS(middle,
-	    (GET_IP_HEADER_FLAGS(middle) | IPFLAG_MORE_FRAGMENTS));
-	return middle;
-}
-
-/** Checks the packet length and fragments it if needed.
- *
- * The new fragments are queued before the original packet.
- *
- * @param[in,out] packet The packet to be checked.
- * @param[in] length	The maximum packet length.
- * @param[in] prefix	The minimum prefix size.
- * @param[in] suffix	The minimum suffix size.
- * @param[in] addr_len	The minimum address length.
- * @return		EOK on success.
- * @return		EINVAL if the packet_get_addr() function fails.
- * @return		EINVAL if the packet does not contain the IP header.
- * @return		EPERM if the packet needs to be fragmented and the
- *			fragmentation is not allowed.
- * @return		ENOMEM if there is not enough memory left.
- * @return		ENOMEM if there is no packet available.
- * @return		ENOMEM if the packet is too small to contain the IP
- *			header.
- * @return		Other error codes as defined for the packet_trim()
- *			function.
- * @return		Other error codes as defined for the
- *			ip_create_middle_header() function.
- * @return		Other error codes as defined for the
- *			ip_fragment_packet_data() function.
- */
-static int
-ip_fragment_packet(packet_t *packet, size_t length, size_t prefix, size_t suffix,
-    socklen_t addr_len)
-{
-	packet_t *new_packet;
-	ip_header_t *header;
-	ip_header_t *middle_header;
-	ip_header_t *last_header;
-	struct sockaddr *src;
-	struct sockaddr *dest;
-	socklen_t addrlen;
-	int result;
-	int rc;
-
-	result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
-	if (result <= 0)
-		return EINVAL;
-
-	addrlen = (socklen_t) result;
-	if (packet_get_data_length(packet) <= sizeof(ip_header_t))
-		return ENOMEM;
-
-	/* Get header */
-	header = (ip_header_t *) packet_get_data(packet);
-	if (!header)
-		return EINVAL;
-
-	/* Fragmentation forbidden? */
-	if(GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT)
-		return EPERM;
-
-	/* Create the last fragment */
-	new_packet = packet_get_4_remote(ip_globals.net_sess, prefix, length,
-	    suffix, ((addrlen > addr_len) ? addrlen : addr_len));
-	if (!new_packet)
-		return ENOMEM;
-
-	/* Allocate as much as originally */
-	last_header = (ip_header_t *) packet_suffix(new_packet,
-	    IP_HEADER_LENGTH(header));
-	if (!last_header)
-		return ip_release_and_return(packet, ENOMEM);
-
-	ip_create_last_header(last_header, header);
-
-	/* Trim the unused space */
-	rc = packet_trim(new_packet, 0,
-	    IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header));
-	if (rc != EOK)
-		return ip_release_and_return(packet, rc);
-
-	/* Greatest multiple of 8 lower than content */
-	// TODO even fragmentation?
-	length = length & ~0x7;
-	
-	rc = ip_fragment_packet_data(packet, new_packet, header, last_header,
-	    ((IP_HEADER_DATA_LENGTH(header) -
-	    ((length - IP_HEADER_LENGTH(header)) & ~0x7)) %
-	    ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)),
-	    src, dest, addrlen);
-	if (rc != EOK)
-		return ip_release_and_return(packet, rc);
-
-	/* Mark the first as fragmented */
-	SET_IP_HEADER_FLAGS(header,
-	    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
-
-	/* Create middle fragments */
-	while (IP_TOTAL_LENGTH(header) > length) {
-		new_packet = packet_get_4_remote(ip_globals.net_sess, prefix,
-		    length, suffix,
-		    ((addrlen >= addr_len) ? addrlen : addr_len));
-		if (!new_packet)
-			return ENOMEM;
-
-		middle_header = ip_create_middle_header(new_packet,
-		    last_header);
-		if (!middle_header)
-			return ip_release_and_return(packet, ENOMEM);
-
-		rc = ip_fragment_packet_data(packet, new_packet, header,
-		    middle_header,
-		    (length - IP_HEADER_LENGTH(middle_header)) & ~0x7,
-		    src, dest, addrlen);
-		if (rc != EOK)
-			return ip_release_and_return(packet, rc);
-	}
-
-	/* Finish the first fragment */
-	header->header_checksum = IP_HEADER_CHECKSUM(header);
-
-	return EOK;
-}
-
-/** Check the packet queue lengths and fragments the packets if needed.
- *
- * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
- * be fragmented and the fragmentation is not allowed.
- *
- * @param[in,out] packet   Packet or the packet queue to be checked.
- * @param[in]     prefix   Minimum prefix size.
- * @param[in]     content  Maximum content size.
- * @param[in]     suffix   Minimum suffix size.
- * @param[in]     addr_len Minimum address length.
- * @param[in]     error    Error module service.
- *
- * @return The packet or the packet queue of the allowed length.
- * @return NULL if there are no packets left.
- *
- */
-static packet_t *ip_split_packet(packet_t *packet, size_t prefix, size_t content,
-    size_t suffix, socklen_t addr_len, services_t error)
-{
-	size_t length;
-	packet_t *next;
-	packet_t *new_packet;
-	int result;
-	async_sess_t *sess;
-	
-	next = packet;
-	/* Check all packets */
-	while (next) {
-		length = packet_get_data_length(next);
-		
-		if (length <= content) {
-			next = pq_next(next);
-			continue;
-		}
-
-		/* Too long */
-		result = ip_fragment_packet(next, content, prefix,
-		    suffix, addr_len);
-		if (result != EOK) {
-			new_packet = pq_detach(next);
-			if (next == packet) {
-				/* The new first packet of the queue */
-				packet = new_packet;
-			}
-			/* Fragmentation needed? */
-			if (result == EPERM) {
-				sess = ip_prepare_icmp_and_get_session(error, next, NULL);
-				if (sess) {
-					/* Fragmentation necessary ICMP */
-					icmp_destination_unreachable_msg(sess,
-					    ICMP_FRAG_NEEDED, content, next);
-				}
-			} else {
-				pq_release_remote(ip_globals.net_sess,
-				    packet_get_id(next));
-			}
-
-			next = new_packet;
-			continue;
-		}
-
-		next = pq_next(next);
-	}
-
-	return packet;
-}
-
-/** Send the packet or the packet queue via the specified route.
- *
- * The ICMP_HOST_UNREACH error notification may be sent if route hardware
- * destination address is found.
- *
- * @param[in,out] packet Packet to be sent.
- * @param[in]     netif  Target network interface.
- * @param[in]     route  Target route.
- * @param[in]     src    Source address.
- * @param[in]     dest   Destination address.
- * @param[in]     error  Error module service.
- *
- * @return EOK on success.
- * @return Other error codes as defined for arp_translate_req().
- * @return Other error codes as defined for ip_prepare_packet().
- *
- */
-static int ip_send_route(packet_t *packet, ip_netif_t *netif,
-    ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
-{
-	measured_string_t destination;
-	measured_string_t *translation;
-	uint8_t *data;
-	async_sess_t *sess;
-	int rc;
-
-	/* Get destination hardware address */
-	if (netif->arp && (route->address.s_addr != dest.s_addr)) {
-		destination.value = route->gateway.s_addr ?
-		    (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr;
-		destination.length = sizeof(dest.s_addr);
-
-		rc = arp_translate_req(netif->arp->sess, netif->device_id,
-		    SERVICE_IP, &destination, &translation, &data);
-		if (rc != EOK) {
-			pq_release_remote(ip_globals.net_sess,
-			    packet_get_id(packet));
-			return rc;
-		}
-
-		if (!translation || !translation->value) {
-			if (translation) {
-				free(translation);
-				free(data);
-			}
-			sess = ip_prepare_icmp_and_get_session(error, packet,
-			    NULL);
-			if (sess) {
-				/* Unreachable ICMP if no routing */
-				icmp_destination_unreachable_msg(sess,
-				    ICMP_HOST_UNREACH, 0, packet);
-			}
-			return EINVAL;
-		}
-
-	} else {
-		translation = NULL;
-	}
-
-	rc = ip_prepare_packet(src, dest, packet, translation);
-	if (rc != EOK) {
-		pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
-	} else {
-		packet = ip_split_packet(packet, netif->packet_dimension.prefix,
-		    netif->packet_dimension.content,
-		    netif->packet_dimension.suffix,
-		    netif->packet_dimension.addr_len, error);
-		if (packet) {
-			nil_send_msg(netif->sess, netif->device_id, packet,
-			    SERVICE_IP);
-		}
-	}
-
-	if (translation) {
-		free(translation);
-		free(data);
-	}
-
-	return rc;
-}
-
-static int ip_send_msg_local(nic_device_id_t device_id, packet_t *packet,
-    services_t sender, services_t error)
-{
-	int addrlen;
-	ip_netif_t *netif;
-	ip_route_t *route;
-	struct sockaddr *addr;
-	struct sockaddr_in *address_in;
-	in_addr_t *dest;
-	in_addr_t *src;
-	async_sess_t *sess;
-	int rc;
-
-	/*
-	 * Addresses in the host byte order
-	 * Should be the next hop address or the target destination address
-	 */
-	addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
-	if (addrlen < 0)
-		return ip_release_and_return(packet, addrlen);
-	if ((size_t) addrlen < sizeof(struct sockaddr))
-		return ip_release_and_return(packet, EINVAL);
-
-	switch (addr->sa_family) {
-	case AF_INET:
-		if (addrlen != sizeof(struct sockaddr_in))
-			return ip_release_and_return(packet, EINVAL);
-		address_in = (struct sockaddr_in *) addr;
-		dest = &address_in->sin_addr;
-		if (!dest->s_addr)
-			dest->s_addr = IPV4_LOCALHOST_ADDRESS;
-		break;
-	case AF_INET6:
-	default:
-		return ip_release_and_return(packet, EAFNOSUPPORT);
-	}
-
-	netif = NULL;
-	route = NULL;
-	fibril_rwlock_read_lock(&ip_globals.netifs_lock);
-
-	/* Device specified? */
-	if (device_id > 0) {
-		netif = ip_netifs_find(&ip_globals.netifs, device_id);
-		route = ip_netif_find_route(netif, *dest);
-		if (netif && !route && (ip_globals.gateway.netif == netif))
-			route = &ip_globals.gateway;
-	}
-
-	if (!route) {
-		route = ip_find_route(*dest);
-		netif = route ? route->netif : NULL;
-	}
-	if (!netif || !route) {
-		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-		sess = ip_prepare_icmp_and_get_session(error, packet, NULL);
-		if (sess) {
-			/* Unreachable ICMP if no routing */
-			icmp_destination_unreachable_msg(sess,
-			    ICMP_NET_UNREACH, 0, packet);
-		}
-		return ENOENT;
-	}
-
-	if (error) {
-		/*
-		 * Do not send for broadcast, anycast packets or network
-		 * broadcast.
-		 */
-		if (!dest->s_addr || !(~dest->s_addr) ||
-		    !(~((dest->s_addr & ~route->netmask.s_addr) |
-		    route->netmask.s_addr)) ||
-		    (!(dest->s_addr & ~route->netmask.s_addr))) {
-			return ip_release_and_return(packet, EINVAL);
-		}
-	}
-	
-	/* If the local host is the destination */
-	if ((route->address.s_addr == dest->s_addr) &&
-	    (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
-		/* Find the loopback device to deliver */
-		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
-		route = ip_find_route(*dest);
-		netif = route ? route->netif : NULL;
-		if (!netif || !route) {
-			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-			sess = ip_prepare_icmp_and_get_session(error, packet,
-			    NULL);
-			if (sess) {
-				/* Unreachable ICMP if no routing */
-				icmp_destination_unreachable_msg(sess,
-				    ICMP_HOST_UNREACH, 0, packet);
-			}
-			return ENOENT;
-		}
-	}
-	
-	src = ip_netif_address(netif);
-	if (!src) {
-		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-		return ip_release_and_return(packet, ENOENT);
-	}
-
-	rc = ip_send_route(packet, netif, route, src, *dest, error);
-	fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-
-	return rc;
-}
-
-/** Updates the device state.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] state	The new state value.
- * @return		EOK on success.
- * @return		ENOENT if device is not found.
- */
-static int ip_device_state_message(nic_device_id_t device_id,
-    nic_device_state_t state)
-{
-	ip_netif_t *netif;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-	/* Find the device */
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-	netif->state = state;
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Device %d changed state to '%s'\n", NAME, device_id,
-	    nic_device_state_to_string(state));
-
-	return EOK;
-}
-
-/** Returns the packet destination address from the IP header.
- *
- * @param[in] header	The packet IP header to be read.
- * @return		The packet destination address.
- */
-static in_addr_t ip_get_destination(ip_header_t *header)
-{
-	in_addr_t destination;
-
-	// TODO search set ipopt route?
-	destination.s_addr = header->destination_address;
-	return destination;
-}
-
-/** Delivers the packet to the local host.
- *
- * The packet is either passed to another module or released on error.
- * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
- * found.
- *
- * @param[in] device_id	The source device identifier.
- * @param[in] packet	The packet to be delivered.
- * @param[in] header	The first packet IP header. May be NULL.
- * @param[in] error	The packet error service.
- * @return		EOK on success.
- * @return		ENOTSUP if the packet is a fragment.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		ENOENT if the target protocol is not found.
- * @return		Other error codes as defined for the packet_set_addr()
- *			function.
- * @return		Other error codes as defined for the packet_trim()
- *			function.
- * @return		Other error codes as defined for the protocol specific
- *			tl_received_msg() function.
- */
-static int ip_deliver_local(nic_device_id_t device_id, packet_t *packet,
-    ip_header_t *header, services_t error)
-{
-	ip_proto_t *proto;
-	async_sess_t *sess;
-	services_t service;
-	tl_received_msg_t received_msg;
-	struct sockaddr *src;
-	struct sockaddr *dest;
-	struct sockaddr_in src_in;
-	struct sockaddr_in dest_in;
-	socklen_t addrlen;
-	int rc;
-
-	if ((GET_IP_HEADER_FLAGS(header) & IPFLAG_MORE_FRAGMENTS) ||
-	    IP_FRAGMENT_OFFSET(header)) {
-		// TODO fragmented
-		return ENOTSUP;
-	}
-	
-	switch (GET_IP_HEADER_VERSION(header)) {
-	case IPVERSION:
-		addrlen = sizeof(src_in);
-		bzero(&src_in, addrlen);
-		src_in.sin_family = AF_INET;
-		memcpy(&dest_in, &src_in, addrlen);
-		memcpy(&src_in.sin_addr.s_addr, &header->source_address,
-		    sizeof(header->source_address));
-		memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
-		    sizeof(header->destination_address));
-		src = (struct sockaddr *) &src_in;
-		dest = (struct sockaddr *) &dest_in;
-		break;
-
-	default:
-		return ip_release_and_return(packet, EAFNOSUPPORT);
-	}
-
-	rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
-	    addrlen);
-	if (rc != EOK)
-		return ip_release_and_return(packet, rc);
-
-	/* Trim padding if present */
-	if (!error &&
-	    (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
-		rc = packet_trim(packet, 0,
-		    packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
-		if (rc != EOK)
-			return ip_release_and_return(packet, rc);
-	}
-
-	fibril_rwlock_read_lock(&ip_globals.protos_lock);
-
-	proto = ip_protos_find(&ip_globals.protos, header->protocol);
-	if (!proto) {
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-		sess = ip_prepare_icmp_and_get_session(error, packet, header);
-		if (sess) {
-			/* Unreachable ICMP */
-			icmp_destination_unreachable_msg(sess,
-			    ICMP_PROT_UNREACH, 0, packet);
-		}
-		return ENOENT;
-	}
-
-	if (proto->received_msg) {
-		service = proto->service;
-		received_msg = proto->received_msg;
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-		rc = received_msg(device_id, packet, service, error);
-	} else {
-		rc = tl_received_msg(proto->sess, device_id, packet,
-		    proto->service, error);
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-	}
-
-	return rc;
-}
-
-/** Processes the received packet.
- *
- * The packet is either passed to another module or released on error.
- *
- * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
- * invalid.
- * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
- * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
- * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
- * another host and the routing is disabled.
- *
- * @param[in] device_id	The source device identifier.
- * @param[in] packet	The received packet to be processed.
- * @return		EOK on success.
- * @return		EINVAL if the TTL is less than two.
- * @return		EINVAL if the checksum is invalid.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		ENOENT if no route was found.
- * @return		ENOENT if the packet is for another host and the routing
- *			is disabled.
- */
-static int ip_process_packet(nic_device_id_t device_id, packet_t *packet)
-{
-	ip_header_t *header;
-	in_addr_t dest;
-	ip_route_t *route;
-	async_sess_t *sess;
-	struct sockaddr *addr;
-	struct sockaddr_in addr_in;
-	socklen_t addrlen;
-	int rc;
-	
-	header = (ip_header_t *) packet_get_data(packet);
-	if (!header)
-		return ip_release_and_return(packet, ENOMEM);
-
-	/* Checksum */
-	if ((header->header_checksum) &&
-	    (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
-		sess = ip_prepare_icmp_and_get_session(0, packet, header);
-		if (sess) {
-			/* Checksum error ICMP */
-			icmp_parameter_problem_msg(sess, ICMP_PARAM_POINTER,
-			    ((size_t) ((void *) &header->header_checksum)) -
-			    ((size_t) ((void *) header)), packet);
-		}
-		return EINVAL;
-	}
-
-	if (header->ttl <= 1) {
-		sess = ip_prepare_icmp_and_get_session(0, packet, header);
-		if (sess) {
-			/* TTL exceeded ICMP */
-			icmp_time_exceeded_msg(sess, ICMP_EXC_TTL, packet);
-		}
-		return EINVAL;
-	}
-	
-	/* Process ipopt and get destination */
-	dest = ip_get_destination(header);
-
-	/* Set the destination address */
-	switch (GET_IP_HEADER_VERSION(header)) {
-	case IPVERSION:
-		addrlen = sizeof(addr_in);
-		bzero(&addr_in, addrlen);
-		addr_in.sin_family = AF_INET;
-		memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
-		addr = (struct sockaddr *) &addr_in;
-		break;
-
-	default:
-		return ip_release_and_return(packet, EAFNOSUPPORT);
-	}
-
-	rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
-	if (rc != EOK)
-		return rc;
-	
-	route = ip_find_route(dest);
-	if (!route) {
-		sess = ip_prepare_icmp_and_get_session(0, packet, header);
-		if (sess) {
-			/* Unreachable ICMP */
-			icmp_destination_unreachable_msg(sess,
-			    ICMP_HOST_UNREACH, 0, packet);
-		}
-		return ENOENT;
-	}
-
-	if (route->address.s_addr == dest.s_addr) {
-		/* Local delivery */
-		return ip_deliver_local(device_id, packet, header, 0);
-	}
-
-	if (route->netif->routing) {
-		header->ttl--;
-		return ip_send_route(packet, route->netif, route, NULL, dest,
-		    0);
-	}
-
-	sess = ip_prepare_icmp_and_get_session(0, packet, header);
-	if (sess) {
-		/* Unreachable ICMP if no routing */
-		icmp_destination_unreachable_msg(sess, ICMP_HOST_UNREACH, 0,
-		    packet);
-	}
-	
-	return ENOENT;
-}
-
-/** Return the device packet dimensions for sending.
- *
- * @param[in]  device_id Device identifier.
- * @param[out] addr_len  Minimum reserved address length.
- * @param[out] prefix    Minimum reserved prefix size.
- * @param[out] content   Maximum content size.
- * @param[out] suffix    Minimum reserved suffix size.
- *
- * @return EOK on success.
- *
- */
-static int ip_packet_size_message(nic_device_id_t device_id, size_t *addr_len,
-    size_t *prefix, size_t *content, size_t *suffix)
-{
-	ip_netif_t *netif;
-	int index;
-
-	if (!addr_len || !prefix || !content || !suffix)
-		return EBADMEM;
-
-	*content = IP_MAX_CONTENT - IP_PREFIX;
-	fibril_rwlock_read_lock(&ip_globals.netifs_lock);
-	if (device_id < 0) {
-		*addr_len = IP_ADDR;
-		*prefix = 0;
-		*suffix = 0;
-
-		for (index = ip_netifs_count(&ip_globals.netifs) - 1;
-		    index >= 0; index--) {
-			netif = ip_netifs_get_index(&ip_globals.netifs, index);
-			if (!netif)
-				continue;
-			
-			if (netif->packet_dimension.addr_len > *addr_len)
-				*addr_len = netif->packet_dimension.addr_len;
-			
-			if (netif->packet_dimension.prefix > *prefix)
-				*prefix = netif->packet_dimension.prefix;
-				
-			if (netif->packet_dimension.suffix > *suffix)
-				*suffix = netif->packet_dimension.suffix;
-		}
-
-		*prefix = *prefix + IP_PREFIX;
-		*suffix = *suffix + IP_SUFFIX;
-	} else {
-		netif = ip_netifs_find(&ip_globals.netifs, device_id);
-		if (!netif) {
-			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-			return ENOENT;
-		}
-
-		*addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ?
-		    netif->packet_dimension.addr_len : IP_ADDR;
-		*prefix = netif->packet_dimension.prefix + IP_PREFIX;
-		*suffix = netif->packet_dimension.suffix + IP_SUFFIX;
-	}
-	fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-
-	return EOK;
-}
-
-/** Updates the device content length according to the new MTU value.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] mtu	The new mtu value.
- * @return		EOK on success.
- * @return		ENOENT if device is not found.
- */
-static int ip_mtu_changed_message(nic_device_id_t device_id, size_t mtu)
-{
-	ip_netif_t *netif;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-	netif->packet_dimension.content = mtu;
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
-
-	return EOK;
-}
-
-/** Process IPC messages from the registered device driver modules
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_IL_DEVICE_STATE:
-			rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
-			    IPC_GET_STATE(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		
-		case NET_IL_RECEIVED:
-			rc = packet_translate_remote(ip_globals.net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc == EOK) {
-				do {
-					packet_t *next = pq_detach(packet);
-					ip_process_packet(IPC_GET_DEVICE(*icall), packet);
-					packet = next;
-				} while (packet);
-			}
-			
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		
-		case NET_IL_MTU_CHANGED:
-			rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
-			    IPC_GET_MTU(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		case NET_IL_ADDR_CHANGED:
-			async_answer_0(iid, (sysarg_t) EOK);
-			break;
-
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Register the transport layer protocol.
- *
- * The traffic of this protocol will be supplied using either the receive
- * function or IPC message.
- *
- * @param[in] protocol     Transport layer module protocol.
- * @param[in] service      Transport layer module service.
- * @param[in] sess         Transport layer module session.
- * @param[in] received_msg Receiving function.
- *
- * @return EOK on success.
- * @return EINVAL if the protocol parameter and/or the service
- *         parameter is zero.
- * @return EINVAL if the phone parameter is not a positive number
- *         and the tl_receive_msg is NULL.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int ip_register(int protocol, services_t service, async_sess_t *sess,
-    tl_received_msg_t received_msg)
-{
-	ip_proto_t *proto;
-	int index;
-
-	if ((!protocol) || (!service) || ((!sess) && (!received_msg)))
-		return EINVAL;
-	
-	proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
-	if (!proto)
-		return ENOMEM;
-
-	proto->protocol = protocol;
-	proto->service = service;
-	proto->sess = sess;
-	proto->received_msg = received_msg;
-
-	fibril_rwlock_write_lock(&ip_globals.protos_lock);
-	index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
-	if (index < 0) {
-		fibril_rwlock_write_unlock(&ip_globals.protos_lock);
-		free(proto);
-		return index;
-	}
-	fibril_rwlock_write_unlock(&ip_globals.protos_lock);
-
-	printf("%s: Protocol registered (protocol: %d)\n",
-	    NAME, proto->protocol);
-
-	return EOK;
-}
-
-static int ip_add_route_req_local(nic_device_id_t device_id, in_addr_t address,
-    in_addr_t netmask, in_addr_t gateway)
-{
-	ip_route_t *route;
-	ip_netif_t *netif;
-	int index;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-
-	route = (ip_route_t *) malloc(sizeof(ip_route_t));
-	if (!route) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOMEM;
-	}
-
-	route->address.s_addr = address.s_addr;
-	route->netmask.s_addr = netmask.s_addr;
-	route->gateway.s_addr = gateway.s_addr;
-	route->netif = netif;
-	index = ip_routes_add(&netif->routes, route);
-	if (index < 0)
-		free(route);
-
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-	
-	return index;
-}
-
-static int ip_set_gateway_req_local(nic_device_id_t device_id,
-    in_addr_t gateway)
-{
-	ip_netif_t *netif;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-
-	ip_globals.gateway.address.s_addr = 0;
-	ip_globals.gateway.netmask.s_addr = 0;
-	ip_globals.gateway.gateway.s_addr = gateway.s_addr;
-	ip_globals.gateway.netif = netif;
-	
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-	
-	return EOK;
-}
-
-/** Notify the IP module about the received error notification packet.
- *
- * @param[in] device_id Device identifier.
- * @param[in] packet    Received packet or the received packet queue.
- * @param[in] target    Target internetwork module service to be
- *                      delivered to.
- * @param[in] error     Packet error reporting service. Prefixes the
- *                      received packet.
- *
- * @return EOK on success.
- *
- */
-static int ip_received_error_msg_local(nic_device_id_t device_id,
-    packet_t *packet, services_t target, services_t error)
-{
-	uint8_t *data;
-	int offset;
-	icmp_type_t type;
-	icmp_code_t code;
-	ip_netif_t *netif;
-	measured_string_t address;
-	ip_route_t *route;
-	ip_header_t *header;
-
-	switch (error) {
-	case SERVICE_ICMP:
-		offset = icmp_client_process_packet(packet, &type, &code, NULL,
-		    NULL);
-		if (offset < 0)
-			return ip_release_and_return(packet, ENOMEM);
-
-		data = packet_get_data(packet);
-		header = (ip_header_t *)(data + offset);
-
-		/* Destination host unreachable? */
-		if ((type != ICMP_DEST_UNREACH) ||
-		    (code != ICMP_HOST_UNREACH)) {
-			/* No, something else */
-			break;
-		}
-
-		fibril_rwlock_read_lock(&ip_globals.netifs_lock);
-
-		netif = ip_netifs_find(&ip_globals.netifs, device_id);
-		if (!netif || !netif->arp) {
-			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-			break;
-		}
-
-		route = ip_routes_get_index(&netif->routes, 0);
-
-		/* From the same network? */
-		if (route && ((route->address.s_addr & route->netmask.s_addr) ==
-		    (header->destination_address & route->netmask.s_addr))) {
-			/* Clear the ARP mapping if any */
-			address.value = (uint8_t *) &header->destination_address;
-			address.length = sizeof(header->destination_address);
-			arp_clear_address_req(netif->arp->sess,
-			    netif->device_id, SERVICE_IP, &address);
-		}
-
-		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-		break;
-
-	default:
-		return ip_release_and_return(packet, ENOTSUP);
-	}
-
-	return ip_deliver_local(device_id, packet, header, error);
-}
-
-static int ip_get_route_req_local(ip_protocol_t protocol,
-    const struct sockaddr *destination, socklen_t addrlen,
-    nic_device_id_t *device_id, void **header, size_t *headerlen)
-{
-	struct sockaddr_in *address_in;
-	in_addr_t *dest;
-	in_addr_t *src;
-	ip_route_t *route;
-	ipv4_pseudo_header_t *header_in;
-
-	if (!destination || (addrlen <= 0))
-		return EINVAL;
-
-	if (!device_id || !header || !headerlen)
-		return EBADMEM;
-
-	if ((size_t) addrlen < sizeof(struct sockaddr))
-		return EINVAL;
-
-	switch (destination->sa_family) {
-	case AF_INET:
-		if (addrlen != sizeof(struct sockaddr_in))
-			return EINVAL;
-		address_in = (struct sockaddr_in *) destination;
-		dest = &address_in->sin_addr;
-		if (!dest->s_addr)
-			dest->s_addr = IPV4_LOCALHOST_ADDRESS;
-		break;
-
-	case AF_INET6:
-	default:
-		return EAFNOSUPPORT;
-	}
-
-	fibril_rwlock_read_lock(&ip_globals.lock);
-	route = ip_find_route(*dest);
-	/* If the local host is the destination */
-	if (route && (route->address.s_addr == dest->s_addr) &&
-	    (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
-		/* Find the loopback device to deliver */
-		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
-		route = ip_find_route(*dest);
-	}
-
-	if (!route || !route->netif) {
-		fibril_rwlock_read_unlock(&ip_globals.lock);
-		return ENOENT;
-	}
-
-	*device_id = route->netif->device_id;
-	src = ip_netif_address(route->netif);
-	fibril_rwlock_read_unlock(&ip_globals.lock);
-
-	*headerlen = sizeof(*header_in);
-	header_in = (ipv4_pseudo_header_t *) malloc(*headerlen);
-	if (!header_in)
-		return ENOMEM;
-
-	bzero(header_in, *headerlen);
-	header_in->destination_address = dest->s_addr;
-	header_in->source_address = src->s_addr;
-	header_in->protocol = protocol;
-	header_in->data_length = 0;
-	*header = header_in;
-
-	return EOK;
-}
-
-/** Processes the IP message.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @param[out] answer	The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer in the
- *			answer parameter.
- * @return		EOK on success.
- * @return		ENOTSUP if the message is not known.
- *
- * @see ip_interface.h
- * @see il_remote.h
- * @see IS_NET_IP_MESSAGE()
- */
-int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *answer_count)
-{
-	packet_t *packet;
-	struct sockaddr *addr;
-	void *header;
-	size_t headerlen;
-	size_t addrlen;
-	size_t prefix;
-	size_t suffix;
-	size_t content;
-	nic_device_id_t device_id;
-	int rc;
-	
-	*answer_count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
-		    callback, NULL);
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_IP_DEVICE:
-		return ip_device_req_local(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call));
-	
-	case NET_IP_RECEIVED_ERROR:
-		rc = packet_translate_remote(ip_globals.net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		return ip_received_error_msg_local(IPC_GET_DEVICE(*call),
-		    packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
-	
-	case NET_IP_ADD_ROUTE:
-		return ip_add_route_req_local(IPC_GET_DEVICE(*call),
-		    IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
-		    IP_GET_GATEWAY(*call));
-
-	case NET_IP_SET_GATEWAY:
-		return ip_set_gateway_req_local(IPC_GET_DEVICE(*call),
-		    IP_GET_GATEWAY(*call));
-
-	case NET_IP_GET_ROUTE:
-		rc = async_data_write_accept((void **) &addr, false, 0, 0, 0,
-		    &addrlen);
-		if (rc != EOK)
-			return rc;
-		
-		rc = ip_get_route_req_local(IP_GET_PROTOCOL(*call), addr,
-		    (socklen_t) addrlen, &device_id, &header, &headerlen);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_DEVICE(*answer, device_id);
-		IP_SET_HEADERLEN(*answer, headerlen);
-		
-		*answer_count = 2;
-		
-		rc = data_reply(&headerlen, sizeof(headerlen));
-		if (rc == EOK)
-			rc = data_reply(header, headerlen);
-			
-		free(header);
-		return rc;
-	
-	case NET_IP_PACKET_SPACE:
-		rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
-		    &prefix, &content, &suffix);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, addrlen);
-		IPC_SET_PREFIX(*answer, prefix);
-		IPC_SET_CONTENT(*answer, content);
-		IPC_SET_SUFFIX(*answer, suffix);
-		*answer_count = 4;
-		return EOK;
-	
-	case NET_IP_SEND:
-		rc = packet_translate_remote(ip_globals.net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return ip_send_msg_local(IPC_GET_DEVICE(*call), packet, 0,
-		    IPC_GET_ERROR(*call));
-	}
-	
-	return ENOTSUP;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return il_module_start(SERVICE_IP);
-}
-
-/** @}
- */
Index: pace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,162 +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 ip
- * @{
- */
-
-/** @file
- * IP module.
- */
-
-#ifndef NET_IP_H_
-#define NET_IP_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <net/inet.h>
-#include <ip_interface.h>
-#include <adt/int_map.h>
-#include <adt/generic_field.h>
-#include <adt/module_map.h>
-
-/** Type definition of the IP global data.
- * @see ip_globals
- */
-typedef struct ip_globals ip_globals_t;
-
-/** Type definition of the IP network interface specific data.
- * @see ip_netif
- */
-typedef struct ip_netif ip_netif_t;
-
-/** Type definition of the IP protocol specific data.
- * @see ip_proto
- */
-typedef struct ip_proto ip_proto_t;
-
-/** Type definition of the IP route specific data.
- *  @see ip_route
- */
-typedef struct ip_route	ip_route_t;
-
-/** IP network interfaces.
- * Maps devices to the IP network interface specific data.
- * @see device.h
- */
-DEVICE_MAP_DECLARE(ip_netifs, ip_netif_t);
-
-/** IP registered protocols.
- * Maps protocols to the IP protocol specific data.
- * @see int_map.h
- */
-INT_MAP_DECLARE(ip_protos, ip_proto_t);
-
-/** IP routing table.
- * @see generic_field.h
- */
-GENERIC_FIELD_DECLARE(ip_routes, ip_route_t);
-
-/** IP network interface specific data. */
-struct ip_netif {
-	/** ARP module. Assigned if using ARP. */
-	module_t *arp;
-	/** Broadcast address. */
-	in_addr_t broadcast;
-	/** Device identifier. */
-	nic_device_id_t device_id;
-	/** Indicates whether using DHCP. */
-	int dhcp;
-	/** IP version. */
-	int ipv;
-	/** Packet dimension. */
-	packet_dimension_t packet_dimension;
-	/** Netif module session. */
-	async_sess_t *sess;
-	/** Routing table. */
-	ip_routes_t routes;
-	/** Indicates whether IP routing is enabled. */
-	int routing;
-	/** Netif module service. */
-	services_t service;
-	/** Device state. */
-	nic_device_state_t state;
-};
-
-/** IP protocol specific data. */
-struct ip_proto {
-	/** Protocol module session. */
-	async_sess_t *sess;
-	/** Protocol number. */
-	int protocol;
-	/** Protocol packet receiving function. */
-	tl_received_msg_t received_msg;
-	/** Protocol module service. */
-	services_t service;
-};
-
-/** IP route specific data. */
-struct ip_route {
-	/** Target address. */
-	in_addr_t address;
-	/** Gateway. */
-	in_addr_t gateway;
-	/** Parent netif. */
-	ip_netif_t *netif;
-	/** Target network mask. */
-	in_addr_t netmask;
-};
-
-/** IP global data. */
-struct ip_globals {
-	/** Default gateway. */
-	ip_route_t gateway;
-	/** Safety lock. */
-	fibril_rwlock_t lock;
-	/** Known support modules. */
-	modules_t modules;
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	/** Registered network interfaces. */
-	ip_netifs_t netifs;
-	/** Netifs safeyt lock. */
-	fibril_rwlock_t netifs_lock;
-	/** Packet counter. */
-	uint16_t packet_counter;
-	/** Registered protocols. */
-	ip_protos_t protos;
-	/** Protocols safety lock. */
-	fibril_rwlock_t protos_lock;
-};
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/inet/Makefile
===================================================================
--- uspace/srv/net/inet/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+BINARY = inet
+
+SOURCES = \
+	addrobj.c \
+	icmp.c \
+	inet.c \
+	inet_link.c \
+	inet_util.c \
+	inetcfg.c \
+	inetping.c \
+	pdu.c \
+	reass.c \
+	sroute.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/inet/addrobj.c
===================================================================
--- uspace/srv/net/inet/addrobj.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/addrobj.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,229 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <bitops.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <ipc/loc.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "addrobj.h"
+#include "inet.h"
+#include "inet_link.h"
+#include "inet_util.h"
+
+static FIBRIL_MUTEX_INITIALIZE(addr_list_lock);
+static LIST_INITIALIZE(addr_list);
+static sysarg_t addr_id = 0;
+
+inet_addrobj_t *inet_addrobj_new(void)
+{
+	inet_addrobj_t *addr = calloc(1, sizeof(inet_addrobj_t));
+
+	if (addr == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating address object. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&addr->addr_list);
+	fibril_mutex_lock(&addr_list_lock);
+	addr->id = ++addr_id;
+	fibril_mutex_unlock(&addr_list_lock);
+
+	return addr;
+}
+
+void inet_addrobj_delete(inet_addrobj_t *addr)
+{
+	if (addr->name != NULL)
+		free(addr->name);
+	free(addr);
+}
+
+void inet_addrobj_add(inet_addrobj_t *addr)
+{
+	fibril_mutex_lock(&addr_list_lock);
+	list_append(&addr->addr_list, &addr_list);
+	fibril_mutex_unlock(&addr_list_lock);
+}
+
+void inet_addrobj_remove(inet_addrobj_t *addr)
+{
+	fibril_mutex_lock(&addr_list_lock);
+	list_remove(&addr->addr_list);
+	fibril_mutex_unlock(&addr_list_lock);
+}
+
+/** Find address object matching address @a addr.
+ *
+ * @param addr	Address
+ * @oaram find	iaf_net to find network (using mask),
+ *		iaf_addr to find local address (exact match)
+ */
+inet_addrobj_t *inet_addrobj_find(inet_addr_t *addr, inet_addrobj_find_t find)
+{
+	uint32_t mask;
+
+	log_msg(LVL_DEBUG, "inet_addrobj_find(%x)", (unsigned)addr->ipv4);
+
+	fibril_mutex_lock(&addr_list_lock);
+
+	list_foreach(addr_list, link) {
+		inet_addrobj_t *naddr = list_get_instance(link,
+		    inet_addrobj_t, addr_list);
+
+		mask = inet_netmask(naddr->naddr.bits);
+		if ((naddr->naddr.ipv4 & mask) == (addr->ipv4 & mask)) {
+			fibril_mutex_unlock(&addr_list_lock);
+			log_msg(LVL_DEBUG, "inet_addrobj_find: found %p",
+			    naddr);
+			return naddr;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "inet_addrobj_find: Not found");
+	fibril_mutex_unlock(&addr_list_lock);
+
+	return NULL;
+}
+
+/** Find address object on a link, with a specific name.
+ *
+ * @param name	Address object name
+ * @param ilink	Inet link
+ * @return	Address object
+ */
+inet_addrobj_t *inet_addrobj_find_by_name(const char *name, inet_link_t *ilink)
+{
+	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name('%s', '%s')",
+	    name, ilink->svc_name);
+
+	fibril_mutex_lock(&addr_list_lock);
+
+	list_foreach(addr_list, link) {
+		inet_addrobj_t *naddr = list_get_instance(link,
+		    inet_addrobj_t, addr_list);
+
+		if (naddr->ilink == ilink && str_cmp(naddr->name, name) == 0) {
+			fibril_mutex_unlock(&addr_list_lock);
+			log_msg(LVL_DEBUG, "inet_addrobj_find_by_name: found %p",
+			    naddr);
+			return naddr;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name: Not found");
+	fibril_mutex_unlock(&addr_list_lock);
+
+	return NULL;
+}
+
+/** Find address object with the given ID.
+ *
+ * @param id	Address object ID
+ * @return	Address object
+ */
+inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t id)
+{
+	log_msg(LVL_DEBUG, "inet_addrobj_get_by_id(%zu)", (size_t)id);
+
+	fibril_mutex_lock(&addr_list_lock);
+
+	list_foreach(addr_list, link) {
+		inet_addrobj_t *naddr = list_get_instance(link,
+		    inet_addrobj_t, addr_list);
+
+		if (naddr->id == id) {
+			fibril_mutex_unlock(&addr_list_lock);
+			return naddr;
+		}
+	}
+
+	fibril_mutex_unlock(&addr_list_lock);
+
+	return NULL;
+}
+
+/** Send datagram from address object */
+int inet_addrobj_send_dgram(inet_addrobj_t *addr, inet_addr_t *ldest,
+    inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
+{
+	inet_addr_t lsrc_addr;
+	inet_addr_t *ldest_addr;
+
+	lsrc_addr.ipv4 = addr->naddr.ipv4;
+	ldest_addr = &dgram->dest;
+
+	return inet_link_send_dgram(addr->ilink, &lsrc_addr, ldest_addr, dgram,
+	    proto, ttl, df);
+}
+
+/** Get IDs of all address objects. */
+int inet_addrobj_get_id_list(sysarg_t **rid_list, size_t *rcount)
+{
+	sysarg_t *id_list;
+	size_t count, i;
+
+	fibril_mutex_lock(&addr_list_lock);
+	count = list_count(&addr_list);
+
+	id_list = calloc(count, sizeof(sysarg_t));
+	if (id_list == NULL) {
+		fibril_mutex_unlock(&addr_list_lock);
+		return ENOMEM;
+	}
+
+	i = 0;
+	list_foreach(addr_list, link) {
+		inet_addrobj_t *addr = list_get_instance(link,
+		    inet_addrobj_t, addr_list);
+
+		id_list[i++] = addr->id;
+	}
+
+	fibril_mutex_unlock(&addr_list_lock);
+
+	*rid_list = id_list;
+	*rcount = count;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/addrobj.h
===================================================================
--- uspace/srv/net/inet/addrobj.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/addrobj.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,65 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_ADDROBJ_H_
+#define INET_ADDROBJ_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+typedef enum {
+	/* Find matching network address (using mask) */
+	iaf_net,
+	/* Find exact local address (not using mask) */
+	iaf_addr
+} inet_addrobj_find_t;
+
+extern inet_addrobj_t *inet_addrobj_new(void);
+extern void inet_addrobj_delete(inet_addrobj_t *);
+extern void inet_addrobj_add(inet_addrobj_t *);
+extern void inet_addrobj_remove(inet_addrobj_t *);
+extern inet_addrobj_t *inet_addrobj_find(inet_addr_t *, inet_addrobj_find_t);
+extern inet_addrobj_t *inet_addrobj_find_by_name(const char *, inet_link_t *);
+extern inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t);
+extern int inet_addrobj_send_dgram(inet_addrobj_t *, inet_addr_t *,
+    inet_dgram_t *, uint8_t, uint8_t, int);
+extern int inet_addrobj_get_id_list(sysarg_t **, size_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/icmp.c
===================================================================
--- uspace/srv/net/inet/icmp.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/icmp.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,183 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <io/log.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "icmp.h"
+#include "icmp_std.h"
+#include "inet.h"
+#include "inetping.h"
+#include "pdu.h"
+
+/* XXX */
+#define INET_TTL_MAX 255
+
+static int icmp_recv_echo_request(inet_dgram_t *);
+static int icmp_recv_echo_reply(inet_dgram_t *);
+
+int icmp_recv(inet_dgram_t *dgram)
+{
+	uint8_t type;
+
+	log_msg(LVL_DEBUG, "icmp_recv()");
+
+	if (dgram->size < 1)
+		return EINVAL;
+
+	type = *(uint8_t *)dgram->data;
+
+	switch (type) {
+	case ICMP_ECHO_REQUEST:
+		return icmp_recv_echo_request(dgram);
+	case ICMP_ECHO_REPLY:
+		return icmp_recv_echo_reply(dgram);
+	default:
+		break;
+	}
+
+	return EINVAL;
+}
+
+static int icmp_recv_echo_request(inet_dgram_t *dgram)
+{
+	icmp_echo_t *request, *reply;
+	uint16_t checksum;
+	size_t size;
+	inet_dgram_t rdgram;
+	int rc;
+
+	log_msg(LVL_DEBUG, "icmp_recv_echo_request()");
+
+	if (dgram->size < sizeof(icmp_echo_t))
+		return EINVAL;
+
+	request = (icmp_echo_t *)dgram->data;
+	size = dgram->size;
+
+	reply = calloc(size, 1);
+	if (reply == NULL)
+		return ENOMEM;
+
+	memcpy(reply, request, size);
+
+	reply->type = ICMP_ECHO_REPLY;
+	reply->code = 0;
+	reply->checksum = 0;
+
+	checksum = inet_checksum_calc(INET_CHECKSUM_INIT, reply, size);
+	reply->checksum = host2uint16_t_be(checksum);
+
+	rdgram.src = dgram->dest;
+	rdgram.dest = dgram->src;
+	rdgram.tos = ICMP_TOS;
+	rdgram.data = reply;
+	rdgram.size = size;
+
+	rc = inet_route_packet(&rdgram, IP_PROTO_ICMP, INET_TTL_MAX, 0);
+
+	free(reply);
+
+	return rc;
+}
+
+static int icmp_recv_echo_reply(inet_dgram_t *dgram)
+{
+	icmp_echo_t *reply;
+	inetping_sdu_t sdu;
+	uint16_t ident;
+
+	log_msg(LVL_DEBUG, "icmp_recv_echo_reply()");
+
+	if (dgram->size < sizeof(icmp_echo_t))
+		return EINVAL;
+
+	reply = (icmp_echo_t *)dgram->data;
+
+	sdu.src = dgram->src;
+	sdu.dest = dgram->dest;
+	sdu.seq_no = uint16_t_be2host(reply->seq_no);
+	sdu.data = reply + sizeof(icmp_echo_t);
+	sdu.size = dgram->size - sizeof(icmp_echo_t);
+	ident = uint16_t_be2host(reply->ident);
+
+	return inetping_recv(ident, &sdu);
+}
+
+int icmp_ping_send(uint16_t ident, inetping_sdu_t *sdu)
+{
+	inet_dgram_t dgram;
+	icmp_echo_t *request;
+	void *rdata;
+	size_t rsize;
+	uint16_t checksum;
+	int rc;
+
+	rsize = sizeof(icmp_echo_t) + sdu->size;
+	rdata = calloc(rsize, 1);
+	if (rdata == NULL)
+		return ENOMEM;
+
+	request = (icmp_echo_t *)rdata;
+
+	request->type = ICMP_ECHO_REQUEST;
+	request->code = 0;
+	request->checksum = 0;
+	request->ident = host2uint16_t_be(ident);
+	request->seq_no = host2uint16_t_be(sdu->seq_no);
+
+	memcpy(rdata + sizeof(icmp_echo_t), sdu->data, sdu->size);
+
+	checksum = inet_checksum_calc(INET_CHECKSUM_INIT, rdata, rsize);
+	request->checksum = host2uint16_t_be(checksum);
+
+	dgram.src = sdu->src;
+	dgram.dest = sdu->dest;
+	dgram.tos = ICMP_TOS;
+	dgram.data = rdata;
+	dgram.size = rsize;
+
+	rc = inet_route_packet(&dgram, IP_PROTO_ICMP, INET_TTL_MAX, 0);
+
+	free(rdata);
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/icmp.h
===================================================================
--- uspace/srv/net/inet/icmp.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/icmp.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,48 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ICMP_H_
+#define ICMP_H_
+
+#include "inet.h"
+
+extern int icmp_recv(inet_dgram_t *);
+extern int icmp_ping_send(uint16_t, inetping_sdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/icmp_std.h
===================================================================
--- uspace/srv/net/inet/icmp_std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/icmp_std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,70 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file ICMP standard definitions
+ *
+ */
+
+#ifndef ICMP_STD_H_
+#define ICMP_STD_H_
+
+#include <sys/types.h>
+
+#define IP_PROTO_ICMP 1
+
+/** Type of service used for ICMP */
+#define ICMP_TOS	0
+
+/** ICMP message type */
+enum icmp_type {
+	ICMP_ECHO_REPLY   = 0,
+	ICMP_ECHO_REQUEST = 8
+};
+
+/** ICMP Echo Request or Reply message header */
+typedef struct {
+	/** ICMP message type */
+	uint8_t type;
+	/** Code (0) */
+	uint8_t code;
+	/** Internet checksum of the ICMP message */
+	uint16_t checksum;
+	/** Indentifier */
+	uint16_t ident;
+	/** Sequence number */
+	uint16_t seq_no;
+} icmp_echo_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet.c
===================================================================
--- uspace/srv/net/inet/inet.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inet.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,450 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief Internet Protocol service
+ */
+
+#include <adt/list.h>
+#include <async.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <ipc/inet.h>
+#include <ipc/services.h>
+#include <loc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "addrobj.h"
+#include "icmp.h"
+#include "icmp_std.h"
+#include "inet.h"
+#include "inetcfg.h"
+#include "inetping.h"
+#include "inet_link.h"
+#include "reass.h"
+#include "sroute.h"
+
+#define NAME "inet"
+
+static void inet_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static FIBRIL_MUTEX_INITIALIZE(client_list_lock);
+static LIST_INITIALIZE(client_list);
+
+static int inet_init(void)
+{
+	service_id_t sid;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_init()");
+
+	async_set_client_connection(inet_client_conn);
+
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering server (%d).", rc);
+		return EEXIST;
+	}
+
+	rc = loc_service_register_with_iface(SERVICE_NAME_INET, &sid,
+	    INET_PORT_DEFAULT);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		return EEXIST;
+	}
+
+	rc = loc_service_register_with_iface(SERVICE_NAME_INETCFG, &sid,
+	    INET_PORT_CFG);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		return EEXIST;
+	}
+
+	rc = loc_service_register_with_iface(SERVICE_NAME_INETPING, &sid,
+	    INET_PORT_PING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		return EEXIST;
+	}
+
+	rc = inet_link_discovery_start();
+	if (rc != EOK)
+		return EEXIST;
+
+	return EOK;
+}
+
+static void inet_callback_create_srv(inet_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	log_msg(LVL_DEBUG, "inet_callback_create_srv()");
+
+	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	client->sess = sess;
+	async_answer_0(callid, EOK);
+}
+
+static int inet_find_dir(inet_addr_t *src, inet_addr_t *dest, uint8_t tos,
+    inet_dir_t *dir)
+{
+	inet_sroute_t *sr;
+
+	/* XXX Handle case where source address is specified */
+	(void) src;
+
+	dir->aobj = inet_addrobj_find(dest, iaf_net);
+	if (dir->aobj != NULL) {
+		dir->ldest = *dest;
+		dir->dtype = dt_direct;
+	} else {
+		/* No direct path, try using a static route */
+		sr = inet_sroute_find(dest);
+		if (sr != NULL) {
+			dir->aobj = inet_addrobj_find(&sr->router, iaf_net);
+			dir->ldest = sr->router;
+			dir->dtype = dt_router;
+		}
+	}
+
+	if (dir->aobj == NULL) {
+		log_msg(LVL_DEBUG, "inet_send: No route to destination.");
+		return ENOENT;
+	}
+
+	return EOK;
+}
+
+int inet_route_packet(inet_dgram_t *dgram, uint8_t proto, uint8_t ttl,
+    int df)
+{
+	inet_dir_t dir;
+	int rc;
+
+	rc = inet_find_dir(&dgram->src, &dgram->dest, dgram->tos, &dir);
+	if (rc != EOK)
+		return rc;
+
+	return inet_addrobj_send_dgram(dir.aobj, &dir.ldest, dgram,
+	    proto, ttl, df);
+}
+
+static int inet_send(inet_client_t *client, inet_dgram_t *dgram,
+    uint8_t proto, uint8_t ttl, int df)
+{
+	return inet_route_packet(dgram, proto, ttl, df);
+}
+
+int inet_get_srcaddr(inet_addr_t *remote, uint8_t tos, inet_addr_t *local)
+{
+	inet_dir_t dir;
+	int rc;
+
+	rc = inet_find_dir(NULL, remote, tos, &dir);
+	if (rc != EOK)
+		return rc;
+
+	/* XXX dt_local? */
+
+	/* Take source address from the address object */
+	local->ipv4 = dir.aobj->naddr.ipv4;
+	return EOK;
+}
+
+static void inet_get_srcaddr_srv(inet_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	inet_addr_t remote;
+	uint8_t tos;
+	inet_addr_t local;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_get_srcaddr_srv()");
+
+	remote.ipv4 = IPC_GET_ARG1(*call);
+	tos = IPC_GET_ARG2(*call);
+	local.ipv4 = 0;
+
+	rc = inet_get_srcaddr(&remote, tos, &local);
+	async_answer_1(callid, rc, local.ipv4);
+}
+
+static void inet_send_srv(inet_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	inet_dgram_t dgram;
+	uint8_t ttl;
+	int df;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_send_srv()");
+
+	dgram.src.ipv4 = IPC_GET_ARG1(*call);
+	dgram.dest.ipv4 = IPC_GET_ARG2(*call);
+	dgram.tos = IPC_GET_ARG3(*call);
+	ttl = IPC_GET_ARG4(*call);
+	df = IPC_GET_ARG5(*call);
+
+	rc = async_data_write_accept(&dgram.data, false, 0, 0, 0, &dgram.size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	rc = inet_send(client, &dgram, client->protocol, ttl, df);
+
+	free(dgram.data);
+	async_answer_0(callid, rc);
+}
+
+static void inet_set_proto_srv(inet_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	sysarg_t proto;
+
+	proto = IPC_GET_ARG1(*call);
+	log_msg(LVL_DEBUG, "inet_set_proto_srv(%lu)", (unsigned long) proto);
+
+	if (proto > UINT8_MAX) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	client->protocol = proto;
+	async_answer_0(callid, EOK);
+}
+
+static void inet_client_init(inet_client_t *client)
+{
+	client->sess = NULL;
+
+	fibril_mutex_lock(&client_list_lock);
+	list_append(&client->client_list, &client_list);
+	fibril_mutex_unlock(&client_list_lock);
+}
+
+static void inet_client_fini(inet_client_t *client)
+{
+	async_hangup(client->sess);
+	client->sess = NULL;
+
+	fibril_mutex_lock(&client_list_lock);
+	list_remove(&client->client_list);
+	fibril_mutex_unlock(&client_list_lock);
+}
+
+static void inet_default_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	inet_client_t client;
+
+	log_msg(LVL_DEBUG, "inet_default_conn()");
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	inet_client_init(&client);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		switch (method) {
+		case INET_CALLBACK_CREATE:
+			inet_callback_create_srv(&client, callid, &call);
+			break;
+		case INET_GET_SRCADDR:
+			inet_get_srcaddr_srv(&client, callid, &call);
+			break;
+		case INET_SEND:
+			inet_send_srv(&client, callid, &call);
+			break;
+		case INET_SET_PROTO:
+			inet_set_proto_srv(&client, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+
+	inet_client_fini(&client);
+}
+
+static void inet_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	sysarg_t port;
+
+	port = IPC_GET_ARG1(*icall);
+
+	switch (port) {
+	case INET_PORT_DEFAULT:
+		inet_default_conn(iid, icall, arg);
+		break;
+	case INET_PORT_CFG:
+		inet_cfg_conn(iid, icall, arg);
+		break;
+	case INET_PORT_PING:
+		inetping_conn(iid, icall, arg);
+		break;
+	default:
+		async_answer_0(iid, ENOTSUP);
+		break;
+	}
+}
+
+static inet_client_t *inet_client_find(uint8_t proto)
+{
+	fibril_mutex_lock(&client_list_lock);
+
+	list_foreach(client_list, link) {
+		inet_client_t *client = list_get_instance(link, inet_client_t,
+		    client_list);
+
+		if (client->protocol == proto) {
+			fibril_mutex_unlock(&client_list_lock);
+			return client;
+		}
+	}
+
+	fibril_mutex_unlock(&client_list_lock);
+	return NULL;
+}
+
+int inet_ev_recv(inet_client_t *client, inet_dgram_t *dgram)
+{
+	async_exch_t *exch = async_exchange_begin(client->sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_3(exch, INET_EV_RECV, dgram->src.ipv4,
+	    dgram->dest.ipv4, dgram->tos, &answer);
+	int 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);
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+int inet_recv_dgram_local(inet_dgram_t *dgram, uint8_t proto)
+{
+	inet_client_t *client;
+
+	log_msg(LVL_DEBUG, "inet_recv_dgram_local()");
+
+	/* ICMP messages are handled internally */
+	if (proto == IP_PROTO_ICMP)
+		return icmp_recv(dgram);
+
+	client = inet_client_find(proto);
+	if (client == NULL) {
+		log_msg(LVL_DEBUG, "No client found for protocol 0x%" PRIx8,
+		    proto);
+		return ENOENT;
+	}
+
+	return inet_ev_recv(client, dgram);
+}
+
+int inet_recv_packet(inet_packet_t *packet)
+{
+	inet_addrobj_t *addr;
+	inet_dgram_t dgram;
+
+	addr = inet_addrobj_find(&packet->dest, iaf_addr);
+	if (addr != NULL) {
+		/* Destined for one of the local addresses */
+
+		/* Check if packet is a complete datagram */
+		if (packet->offs == 0 && !packet->mf) {
+			/* It is complete deliver it immediately */
+			dgram.src = packet->src;
+			dgram.dest = packet->dest;
+			dgram.tos = packet->tos;
+			dgram.data = packet->data;
+			dgram.size = packet->size;
+
+			return inet_recv_dgram_local(&dgram, packet->proto);
+		} else {
+			/* It is a fragment, queue it for reassembly */
+			inet_reass_queue_packet(packet);
+		}
+	}
+
+	return ENOENT;
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+
+	printf(NAME ": HelenOS Internet Protocol service\n");
+
+	if (log_init(NAME, LVL_WARN) != EOK) {
+		printf(NAME ": Failed to initialize logging.\n");
+		return 1;
+	}
+
+	rc = inet_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet.h
===================================================================
--- uspace/srv/net/inet/inet.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inet.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,202 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_H_
+#define INET_H_
+
+#include <adt/list.h>
+#include <bool.h>
+#include <inet/iplink.h>
+#include <ipc/loc.h>
+#include <sys/types.h>
+#include <async.h>
+
+/** Inet Client */
+typedef struct {
+	async_sess_t *sess;
+	uint8_t protocol;
+	link_t client_list;
+} inet_client_t;
+
+/** Inetping Client */
+typedef struct {
+	/** Callback session */
+	async_sess_t *sess;
+	/** Session identifier */
+	uint16_t ident;
+	/** Link to client list */
+	link_t client_list;
+} inetping_client_t;
+
+/** Host address */
+typedef struct {
+	uint32_t ipv4;
+} inet_addr_t;
+
+/** Network address */
+typedef struct {
+	/** Address */
+	uint32_t ipv4;
+	/** Number of valid bits in @c ipv4 */
+	int bits;
+} inet_naddr_t;
+
+/** Address object info */
+typedef struct {
+	/** Network address */
+	inet_naddr_t naddr;
+	/** Link service ID */
+	sysarg_t ilink;
+	/** Address object name */
+	char *name;
+} inet_addr_info_t;
+
+/** IP link info */
+typedef struct {
+	/** Link service name */
+	char *name;
+	/** Default MTU */
+	size_t def_mtu;
+} inet_link_info_t;
+
+/** Static route info */
+typedef struct {
+	/** Destination network address */
+	inet_naddr_t dest;
+	/** Router address */
+	inet_addr_t router;
+	/** Static route name */
+	char *name;
+} inet_sroute_info_t;
+
+typedef struct {
+	/** Source address */
+	inet_addr_t src;
+	/** Destination address */
+	inet_addr_t dest;
+	/** Type of service */
+	uint8_t tos;
+	/** Protocol */
+	uint8_t proto;
+	/** Time to live */
+	uint8_t ttl;
+	/** Identifier */
+	uint16_t ident;
+	/** Do not fragment */
+	bool df;
+	/** More fragments */
+	bool mf;
+	/** Offset of fragment into datagram, in bytes */
+	size_t offs;
+	/** Packet data */
+	void *data;
+	/** Packet data size in bytes */
+	size_t size;
+} inet_packet_t;
+
+typedef struct {
+	inet_addr_t src;
+	inet_addr_t dest;
+	uint8_t tos;
+	void *data;
+	size_t size;
+} inet_dgram_t;
+
+typedef struct {
+	link_t link_list;
+	service_id_t svc_id;
+	char *svc_name;
+	async_sess_t *sess;
+	iplink_t *iplink;
+	size_t def_mtu;
+} inet_link_t;
+
+typedef struct {
+	link_t addr_list;
+	sysarg_t id;
+	inet_naddr_t naddr;
+	inet_link_t *ilink;
+	char *name;
+} inet_addrobj_t;
+
+/** Static route configuration */
+typedef struct {
+	link_t sroute_list;
+	sysarg_t id;
+	/** Destination network */
+	inet_naddr_t dest;
+	/** Router via which to route packets */
+	inet_addr_t router;
+	char *name;
+} inet_sroute_t;
+
+typedef enum {
+	/** Destination is on this network node */
+	dt_local,
+	/** Destination is directly reachable */
+	dt_direct,
+	/** Destination is behind a router */
+	dt_router
+} inet_dir_type_t;
+
+/** Direction (next hop) to a destination */
+typedef struct {
+	/** Route type */
+	inet_dir_type_t dtype;
+	/** Address object (direction) */
+	inet_addrobj_t *aobj;
+	/** Local destination address */
+	inet_addr_t ldest;
+} inet_dir_t;
+
+typedef struct {
+	inet_addr_t src;
+	inet_addr_t dest;
+	uint16_t seq_no;
+	void *data;
+	size_t size;
+} inetping_sdu_t;
+
+extern int inet_ev_recv(inet_client_t *, inet_dgram_t *);
+extern int inet_recv_packet(inet_packet_t *);
+extern int inet_route_packet(inet_dgram_t *, uint8_t, uint8_t, int);
+extern int inet_get_srcaddr(inet_addr_t *, uint8_t, inet_addr_t *);
+extern int inet_recv_dgram_local(inet_dgram_t *, uint8_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_link.c
===================================================================
--- uspace/srv/net/inet/inet_link.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inet_link.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,309 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <inet/iplink.h>
+#include <io/log.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "addrobj.h"
+#include "inet.h"
+#include "inet_link.h"
+#include "pdu.h"
+
+static int inet_link_open(service_id_t sid);
+static int inet_iplink_recv(iplink_t *ilink, iplink_sdu_t *sdu);
+
+static iplink_ev_ops_t inet_iplink_ev_ops = {
+	.recv = inet_iplink_recv
+};
+
+static LIST_INITIALIZE(inet_link_list);
+static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock);
+
+static int inet_iplink_recv(iplink_t *iplink, iplink_sdu_t *sdu)
+{
+	inet_packet_t packet;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_iplink_recv()");
+	rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "failed decoding PDU");
+		return rc;
+	}
+
+	log_msg(LVL_DEBUG, "call inet_recv_packet()");
+	rc = inet_recv_packet(&packet);
+	log_msg(LVL_DEBUG, "call inet_recv_packet -> %d", rc);
+	free(packet.data);
+
+	return rc;
+}
+
+static int inet_link_check_new(void)
+{
+	bool already_known;
+	category_id_t iplink_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	int rc;
+
+	fibril_mutex_lock(&inet_discovery_lock);
+
+	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
+		fibril_mutex_unlock(&inet_discovery_lock);
+		return ENOENT;
+	}
+
+	rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed getting list of IP links.");
+		fibril_mutex_unlock(&inet_discovery_lock);
+		return EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		already_known = false;
+
+		list_foreach(inet_link_list, ilink_link) {
+			inet_link_t *ilink = list_get_instance(ilink_link,
+			    inet_link_t, link_list);
+			if (ilink->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+
+		if (!already_known) {
+			log_msg(LVL_DEBUG, "Found IP link '%lu'",
+			    (unsigned long) svcs[i]);
+			rc = inet_link_open(svcs[i]);
+			if (rc != EOK)
+				log_msg(LVL_ERROR, "Could not open IP link.");
+		}
+	}
+
+	fibril_mutex_unlock(&inet_discovery_lock);
+	return EOK;
+}
+
+static inet_link_t *inet_link_new(void)
+{
+	inet_link_t *ilink = calloc(1, sizeof(inet_link_t));
+
+	if (ilink == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating link structure. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&ilink->link_list);
+
+	return ilink;
+}
+
+static void inet_link_delete(inet_link_t *ilink)
+{
+	if (ilink->svc_name != NULL)
+		free(ilink->svc_name);
+	free(ilink);
+}
+
+static int inet_link_open(service_id_t sid)
+{
+	inet_link_t *ilink;
+	iplink_addr_t iaddr;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_link_open()");
+	ilink = inet_link_new();
+	if (ilink == NULL)
+		return ENOMEM;
+
+	ilink->svc_id = sid;
+	ilink->iplink = NULL;
+
+	rc = loc_service_get_name(sid, &ilink->svc_name);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed getting service name.");
+		goto error;
+	}
+
+	ilink->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
+	if (ilink->sess == NULL) {
+		log_msg(LVL_ERROR, "Failed connecting '%s'", ilink->svc_name);
+		goto error;
+	}
+
+	rc = iplink_open(ilink->sess, &inet_iplink_ev_ops, &ilink->iplink);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed opening IP link '%s'",
+		    ilink->svc_name);
+		goto error;
+	}
+
+	rc = iplink_get_mtu(ilink->iplink, &ilink->def_mtu);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed determinning MTU of link '%s'",
+		    ilink->svc_name);
+		goto error;
+	}
+
+	log_msg(LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
+	list_append(&ilink->link_list, &inet_link_list);
+
+	inet_addrobj_t *addr;
+
+	static int first = 1;
+	/* XXX For testing: set static IP address 192.168.0.4/24 */
+	addr = inet_addrobj_new();
+	if (first) {
+		addr->naddr.ipv4 = (127 << 24) + (0 << 16) + (0 << 8) + 1;
+		first = 0;
+	} else {
+		addr->naddr.ipv4 = (192 << 24) + (168 << 16) + (0 << 8) + 4;
+	}
+	addr->naddr.bits = 24;
+	addr->ilink = ilink;
+	addr->name = str_dup("v4a");
+	inet_addrobj_add(addr);
+
+	iaddr.ipv4 = addr->naddr.ipv4;
+	rc = iplink_addr_add(ilink->iplink, &iaddr);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
+		/* XXX Roll back */
+		return rc;
+	}
+
+	return EOK;
+
+error:
+	if (ilink->iplink != NULL)
+		iplink_close(ilink->iplink);
+	inet_link_delete(ilink);
+	return rc;
+}
+
+static void inet_link_cat_change_cb(void)
+{
+	(void) inet_link_check_new();
+}
+
+int inet_link_discovery_start(void)
+{
+	int rc;
+
+	rc = loc_register_cat_change_cb(inet_link_cat_change_cb);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering callback for IP link "
+		    "discovery (%d).", rc);
+		return rc;
+	}
+
+	return inet_link_check_new();
+}
+
+/** Send datagram over Internet link */
+int inet_link_send_dgram(inet_link_t *ilink, inet_addr_t *lsrc,
+    inet_addr_t *ldest, inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
+{
+	iplink_sdu_t sdu;
+	inet_packet_t packet;
+	int rc;
+	size_t offs, roffs;
+
+	/*
+	 * Fill packet structure. Fragmentation is performed by
+	 * inet_pdu_encode().
+	 */
+	packet.src = dgram->src;
+	packet.dest = dgram->dest;
+	packet.tos = dgram->tos;
+	packet.proto = proto;
+	packet.ttl = ttl;
+	packet.df = df;
+	packet.data = dgram->data;
+	packet.size = dgram->size;
+
+	sdu.lsrc.ipv4 = lsrc->ipv4;
+	sdu.ldest.ipv4 = ldest->ipv4;
+
+	offs = 0;
+	do {
+		/* Encode one fragment */
+		rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data,
+		    &sdu.size, &roffs);
+		if (rc != EOK)
+			return rc;
+
+		/* Send the PDU */
+		rc = iplink_send(ilink->iplink, &sdu);
+		free(sdu.data);
+
+		offs = roffs;
+	} while (offs < packet.size);
+
+	return rc;
+}
+
+inet_link_t *inet_link_get_by_id(sysarg_t link_id)
+{
+	fibril_mutex_lock(&inet_discovery_lock);
+
+	list_foreach(inet_link_list, elem) {
+		inet_link_t *ilink = list_get_instance(elem, inet_link_t,
+		    link_list);
+
+		if (ilink->svc_id == link_id) {
+			fibril_mutex_unlock(&inet_discovery_lock);
+			return ilink;
+		}
+	}
+
+	fibril_mutex_unlock(&inet_discovery_lock);
+	return NULL;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_link.h
===================================================================
--- uspace/srv/net/inet/inet_link.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inet_link.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,51 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_LINK_H_
+#define INET_LINK_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+extern int inet_link_discovery_start(void);
+extern int inet_link_send_dgram(inet_link_t *, inet_addr_t *,
+    inet_addr_t *, inet_dgram_t *, uint8_t, uint8_t, int);
+extern inet_link_t *inet_link_get_by_id(sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_std.h
===================================================================
--- uspace/srv/net/inet/inet_std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inet_std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,98 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file IP header definitions
+ *
+ */
+
+#ifndef INET_STD_H_
+#define INET_STD_H_
+
+#include <sys/types.h>
+
+/** Internet Datagram header (fixed part) */
+typedef struct {
+	/** Version, Internet Header Length */
+	uint8_t ver_ihl;
+	/* Type of Service */
+	uint8_t tos;
+	/** Total Length */
+	uint16_t tot_len;
+	/** Identification */
+	uint16_t id;
+	/** Flags, Fragment Offset */
+	uint16_t flags_foff;
+	/** Time to Live */
+	uint8_t ttl;
+	/** Protocol */
+	uint8_t proto;
+	/** Header Checksum */
+	uint16_t chksum;
+	/** Source Address */
+	uint32_t src_addr;
+	/** Destination Address */
+	uint32_t dest_addr;
+} ip_header_t;
+
+/** Bits in ip_header_t.ver_ihl */
+enum ver_ihl_bits {
+	/** Version, highest bit */
+	VI_VERSION_h = 7,
+	/** Version, lowest bit */
+	VI_VERSION_l = 4,
+	/** Internet Header Length, highest bit */
+	VI_IHL_h     = 3,
+	/** Internet Header Length, lowest bit */
+	VI_IHL_l     = 0
+};
+
+/** Bits in ip_header_t.flags_foff */
+enum flags_foff_bits {
+	/** Reserved, must be zero */
+	FF_FLAG_RSVD = 15,
+	/** Don't Fragment */
+	FF_FLAG_DF = 14,
+	/** More Fragments */
+	FF_FLAG_MF = 13,
+	/** Fragment Offset, highest bit */
+	FF_FRAGOFF_h = 12,
+	/** Fragment Offset, lowest bit */
+	FF_FRAGOFF_l = 0
+};
+
+/** Fragment offset is expressed in units of 8 bytes */
+#define FRAG_OFFS_UNIT 8
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_util.c
===================================================================
--- uspace/srv/net/inet/inet_util.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inet_util.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,54 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <assert.h>
+#include <bitops.h>
+#include <sys/types.h>
+#include "inet_util.h"
+
+uint32_t inet_netmask(int bits)
+{
+	assert(bits >= 0);
+	assert(bits < 32);
+
+	if (bits == 0)
+		return 0;
+	else
+		return BIT_RANGE(uint32_t, 31, 31 - (bits - 1));
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_util.h
===================================================================
--- uspace/srv/net/inet/inet_util.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inet_util.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,47 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_UTIL_H_
+#define INET_UTIL_H_
+
+#include <sys/types.h>
+
+uint32_t inet_netmask(int bits);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inetcfg.c
===================================================================
--- uspace/srv/net/inet/inetcfg.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inetcfg.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,631 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <macros.h>
+#include <io/log.h>
+#include <ipc/inet.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <str.h>
+#include <sys/types.h>
+
+#include "addrobj.h"
+#include "inet.h"
+#include "inet_link.h"
+#include "inetcfg.h"
+#include "sroute.h"
+
+static int inetcfg_addr_create_static(char *name, inet_naddr_t *naddr,
+    sysarg_t link_id, sysarg_t *addr_id)
+{
+	inet_link_t *ilink;
+	inet_addrobj_t *addr;
+	iplink_addr_t iaddr;
+	int rc;
+
+	ilink = inet_link_get_by_id(link_id);
+	if (ilink == NULL) {
+		log_msg(LVL_DEBUG, "Link %lu not found.",
+		    (unsigned long) link_id);
+		return ENOENT;
+	}
+
+	addr = inet_addrobj_new();
+	if (addr == NULL) {
+		*addr_id = 0;
+		return ENOMEM;
+	}
+
+	addr->naddr = *naddr;
+	addr->ilink = ilink;
+	addr->name = str_dup(name);
+	inet_addrobj_add(addr);
+
+	iaddr.ipv4 = addr->naddr.ipv4;
+	rc = iplink_addr_add(ilink->iplink, &iaddr);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
+		inet_addrobj_remove(addr);
+		inet_addrobj_delete(addr);
+		return rc;
+	}
+
+	return EOK;
+}
+
+static int inetcfg_addr_delete(sysarg_t addr_id)
+{
+	inet_addrobj_t *addr;
+
+	addr = inet_addrobj_get_by_id(addr_id);
+	if (addr == NULL)
+		return ENOENT;
+
+	inet_addrobj_remove(addr);
+	inet_addrobj_delete(addr);
+
+	return EOK;
+}
+
+static int inetcfg_addr_get(sysarg_t addr_id, inet_addr_info_t *ainfo)
+{
+	inet_addrobj_t *addr;
+
+	addr = inet_addrobj_get_by_id(addr_id);
+	if (addr == NULL)
+		return ENOENT;
+
+	ainfo->naddr = addr->naddr;
+	ainfo->ilink = addr->ilink->svc_id;
+	ainfo->name = str_dup(addr->name);
+
+	return EOK;
+}
+
+static int inetcfg_addr_get_id(char *name, sysarg_t link_id, sysarg_t *addr_id)
+{
+	inet_link_t *ilink;
+	inet_addrobj_t *addr;
+
+	ilink = inet_link_get_by_id(link_id);
+	if (ilink == NULL) {
+		log_msg(LVL_DEBUG, "Link %zu not found.", (size_t) link_id);
+		return ENOENT;
+	}
+
+	addr = inet_addrobj_find_by_name(name, ilink);
+	if (addr == NULL) {
+		log_msg(LVL_DEBUG, "Address '%s' not found.", name);
+		return ENOENT;
+	}
+
+	*addr_id = addr->id;
+	return EOK;
+}
+
+static int inetcfg_get_addr_list(sysarg_t **addrs, size_t *count)
+{
+	return inet_addrobj_get_id_list(addrs, count);
+}
+
+static int inetcfg_get_link_list(sysarg_t **addrs, size_t *count)
+{
+	return ENOTSUP;
+}
+
+static int inetcfg_get_sroute_list(sysarg_t **sroutes, size_t *count)
+{
+	return inet_sroute_get_id_list(sroutes, count);
+}
+
+static int inetcfg_link_get(sysarg_t link_id, inet_link_info_t *linfo)
+{
+	inet_link_t *ilink;
+
+	ilink = inet_link_get_by_id(link_id);
+	if (ilink == NULL) {
+		return ENOENT;
+	}
+
+	linfo->name = str_dup(ilink->svc_name);
+	linfo->def_mtu = ilink->def_mtu;
+	return EOK;
+}
+
+static int inetcfg_sroute_create(char *name, inet_naddr_t *dest,
+    inet_addr_t *router, sysarg_t *sroute_id)
+{
+	inet_sroute_t *sroute;
+
+	sroute = inet_sroute_new();
+	if (sroute == NULL) {
+		*sroute_id = 0;
+		return ENOMEM;
+	}
+
+	sroute->dest = *dest;
+	sroute->router = *router;
+	sroute->name = str_dup(name);
+	inet_sroute_add(sroute);
+
+	*sroute_id = sroute->id;
+	return EOK;
+}
+
+static int inetcfg_sroute_delete(sysarg_t sroute_id)
+{
+	inet_sroute_t *sroute;
+
+	sroute = inet_sroute_get_by_id(sroute_id);
+	if (sroute == NULL)
+		return ENOENT;
+
+	inet_sroute_remove(sroute);
+	inet_sroute_delete(sroute);
+
+	return EOK;
+}
+
+static int inetcfg_sroute_get(sysarg_t sroute_id, inet_sroute_info_t *srinfo)
+{
+	inet_sroute_t *sroute;
+
+	sroute = inet_sroute_get_by_id(sroute_id);
+	if (sroute == NULL)
+		return ENOENT;
+
+	srinfo->dest = sroute->dest;
+	srinfo->router = sroute->router;
+	srinfo->name = str_dup(sroute->name);
+
+	return EOK;
+}
+
+static int inetcfg_sroute_get_id(char *name, sysarg_t *sroute_id)
+{
+	inet_sroute_t *sroute;
+
+	sroute = inet_sroute_find_by_name(name);
+	if (sroute == NULL) {
+		log_msg(LVL_DEBUG, "Static route '%s' not found.", name);
+		return ENOENT;
+	}
+
+	*sroute_id = sroute->id;
+	return EOK;
+}
+
+static void inetcfg_addr_create_static_srv(ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	char *name;
+	inet_naddr_t naddr;
+	sysarg_t link_id;
+	sysarg_t addr_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_addr_create_static_srv()");
+
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	naddr.ipv4 = IPC_GET_ARG1(*call);
+	naddr.bits = IPC_GET_ARG2(*call);
+	link_id    = IPC_GET_ARG3(*call);
+
+	addr_id = 0;
+	rc = inetcfg_addr_create_static(name, &naddr, link_id, &addr_id);
+	free(name);
+	async_answer_1(callid, rc, addr_id);
+}
+
+static void inetcfg_addr_delete_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	sysarg_t addr_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_addr_delete_srv()");
+
+	addr_id = IPC_GET_ARG1(*call);
+
+	rc = inetcfg_addr_delete(addr_id);
+	async_answer_0(callid, rc);
+}
+
+static void inetcfg_addr_get_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t max_size;
+
+	sysarg_t addr_id;
+	inet_addr_info_t ainfo;
+	int rc;
+
+	addr_id = IPC_GET_ARG1(*call);
+	log_msg(LVL_DEBUG, "inetcfg_addr_get_srv()");
+
+	ainfo.naddr.ipv4 = 0;
+	ainfo.naddr.bits = 0;
+	ainfo.ilink = 0;
+	ainfo.name = NULL;
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_addr_get(addr_id, &ainfo);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sysarg_t retval = async_data_read_finalize(rcallid, ainfo.name,
+	    min(max_size, str_size(ainfo.name)));
+	free(ainfo.name);
+
+	async_answer_3(callid, retval, ainfo.naddr.ipv4, ainfo.naddr.bits,
+	    ainfo.ilink);
+}
+
+static void inetcfg_addr_get_id_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	char *name;
+	sysarg_t link_id;
+	sysarg_t addr_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_addr_get_id_srv()");
+
+	link_id = IPC_GET_ARG1(*call);
+
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	addr_id = 0;
+	rc = inetcfg_addr_get_id(name, link_id, &addr_id);
+	free(name);
+	async_answer_1(callid, rc, addr_id);
+}
+
+static void inetcfg_get_addr_list_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t count;
+	size_t max_size;
+	size_t act_size;
+	size_t size;
+	sysarg_t *id_buf;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_get_addr_list_srv()");
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_get_addr_list(&id_buf, &count);
+	if (rc != EOK) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	act_size = count * sizeof(sysarg_t);
+	size = min(act_size, max_size);
+
+	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
+	free(id_buf);
+
+	async_answer_1(callid, retval, act_size);
+}
+
+
+static void inetcfg_get_link_list_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t max_size;
+	size_t act_size;
+	size_t size;
+	sysarg_t *id_buf;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_get_link_list_srv()");
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_get_link_list(&id_buf, &act_size);
+	if (rc != EOK) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	size = min(act_size, max_size);
+
+	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
+	free(id_buf);
+
+	async_answer_1(callid, retval, act_size);
+}
+
+static void inetcfg_get_sroute_list_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t count;
+	size_t max_size;
+	size_t act_size;
+	size_t size;
+	sysarg_t *id_buf;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_get_sroute_list_srv()");
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_get_sroute_list(&id_buf, &count);
+	if (rc != EOK) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	act_size = count * sizeof(sysarg_t);
+	size = min(act_size, max_size);
+
+	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
+	free(id_buf);
+
+	async_answer_1(callid, retval, act_size);
+}
+
+static void inetcfg_link_get_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t max_size;
+
+	sysarg_t link_id;
+	inet_link_info_t linfo;
+	int rc;
+
+	link_id = IPC_GET_ARG1(*call);
+	log_msg(LVL_DEBUG, "inetcfg_link_get_srv()");
+
+	linfo.name = NULL;
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_link_get(link_id, &linfo);
+	if (rc != EOK) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sysarg_t retval = async_data_read_finalize(rcallid, linfo.name,
+	    min(max_size, str_size(linfo.name)));
+	free(linfo.name);
+
+	async_answer_1(callid, retval, linfo.def_mtu);
+}
+
+static void inetcfg_sroute_create_srv(ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	char *name;
+	inet_naddr_t dest;
+	inet_addr_t router;
+	sysarg_t sroute_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_sroute_create_srv()");
+
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	dest.ipv4   = IPC_GET_ARG1(*call);
+	dest.bits   = IPC_GET_ARG2(*call);
+	router.ipv4 = IPC_GET_ARG3(*call);
+
+	sroute_id = 0;
+	rc = inetcfg_sroute_create(name, &dest, &router, &sroute_id);
+	free(name);
+	async_answer_1(callid, rc, sroute_id);
+}
+
+static void inetcfg_sroute_delete_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	sysarg_t sroute_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_sroute_delete_srv()");
+
+	sroute_id = IPC_GET_ARG1(*call);
+
+	rc = inetcfg_sroute_delete(sroute_id);
+	async_answer_0(callid, rc);
+}
+
+static void inetcfg_sroute_get_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t max_size;
+
+	sysarg_t sroute_id;
+	inet_sroute_info_t srinfo;
+	int rc;
+
+	sroute_id = IPC_GET_ARG1(*call);
+	log_msg(LVL_DEBUG, "inetcfg_sroute_get_srv()");
+
+	srinfo.dest.ipv4 = 0;
+	srinfo.dest.bits = 0;
+	srinfo.router.ipv4 = 0;
+	srinfo.name = NULL;
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_sroute_get(sroute_id, &srinfo);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sysarg_t retval = async_data_read_finalize(rcallid, srinfo.name,
+	    min(max_size, str_size(srinfo.name)));
+	free(srinfo.name);
+
+	async_answer_3(callid, retval, srinfo.dest.ipv4, srinfo.dest.bits,
+	    srinfo.router.ipv4);
+}
+
+static void inetcfg_sroute_get_id_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	char *name;
+	sysarg_t sroute_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_sroute_get_id_srv()");
+
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sroute_id = 0;
+	rc = inetcfg_sroute_get_id(name, &sroute_id);
+	free(name);
+	async_answer_1(callid, rc, sroute_id);
+}
+
+void inet_cfg_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	log_msg(LVL_DEBUG, "inet_cfg_conn()");
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		switch (method) {
+		case INETCFG_ADDR_CREATE_STATIC:
+			inetcfg_addr_create_static_srv(callid, &call);
+			break;
+		case INETCFG_ADDR_DELETE:
+			inetcfg_addr_delete_srv(callid, &call);
+			break;
+		case INETCFG_ADDR_GET:
+			inetcfg_addr_get_srv(callid, &call);
+			break;
+		case INETCFG_ADDR_GET_ID:
+			inetcfg_addr_get_id_srv(callid, &call);
+			break;
+		case INETCFG_GET_ADDR_LIST:
+			inetcfg_get_addr_list_srv(callid, &call);
+			break;
+		case INETCFG_GET_LINK_LIST:
+			inetcfg_get_link_list_srv(callid, &call);
+			break;
+		case INETCFG_GET_SROUTE_LIST:
+			inetcfg_get_sroute_list_srv(callid, &call);
+			break;
+		case INETCFG_LINK_GET:
+			inetcfg_link_get_srv(callid, &call);
+			break;
+		case INETCFG_SROUTE_CREATE:
+			inetcfg_sroute_create_srv(callid, &call);
+			break;
+		case INETCFG_SROUTE_DELETE:
+			inetcfg_sroute_delete_srv(callid, &call);
+			break;
+		case INETCFG_SROUTE_GET:
+			inetcfg_sroute_get_srv(callid, &call);
+			break;
+		case INETCFG_SROUTE_GET_ID:
+			inetcfg_sroute_get_id_srv(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inetcfg.h
===================================================================
--- uspace/srv/net/inet/inetcfg.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inetcfg.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,45 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INETCFG_H_
+#define INETCFG_H_
+
+extern void inet_cfg_conn(ipc_callid_t, ipc_call_t *, void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inetping.c
===================================================================
--- uspace/srv/net/inet/inetping.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inetping.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,230 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <ipc/inet.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "icmp.h"
+#include "icmp_std.h"
+#include "inet.h"
+#include "inetping.h"
+
+static FIBRIL_MUTEX_INITIALIZE(client_list_lock);
+static LIST_INITIALIZE(client_list);
+
+/** Last used session identifier. Protected by @c client_list_lock */
+static uint16_t inetping_ident = 0;
+
+static inetping_client_t *inetping_client_find(uint16_t);
+
+static int inetping_send(inetping_client_t *client, inetping_sdu_t *sdu)
+{
+	return icmp_ping_send(client->ident, sdu);
+}
+
+static int inetping_get_srcaddr(inetping_client_t *client, inet_addr_t *remote,
+    inet_addr_t *local)
+{
+	return inet_get_srcaddr(remote, ICMP_TOS, local);
+}
+
+int inetping_recv(uint16_t ident, inetping_sdu_t *sdu)
+{
+	inetping_client_t *client;
+	async_exch_t *exch;
+	ipc_call_t answer;
+
+	client = inetping_client_find(ident);
+	if (client == NULL) {
+		log_msg(LVL_DEBUG, "Unknown ICMP ident. Dropping.");
+		return ENOENT;
+	}
+
+	exch = async_exchange_begin(client->sess);
+
+	aid_t req = async_send_3(exch, INETPING_EV_RECV, sdu->src.ipv4,
+	    sdu->dest.ipv4, sdu->seq_no, &answer);
+	int rc = async_data_write_start(exch, sdu->data, sdu->size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK) {
+		return retval;
+	}
+
+	return EOK;
+}
+
+static void inetping_send_srv(inetping_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	inetping_sdu_t sdu;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetping_send_srv()");
+
+	rc = async_data_write_accept((void **) &sdu.data, false, 0, 0, 0,
+	    &sdu.size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sdu.src.ipv4 = IPC_GET_ARG1(*call);
+	sdu.dest.ipv4 = IPC_GET_ARG2(*call);
+	sdu.seq_no = IPC_GET_ARG3(*call);
+
+	rc = inetping_send(client, &sdu);
+	free(sdu.data);
+
+	async_answer_0(callid, rc);
+}
+
+static void inetping_get_srcaddr_srv(inetping_client_t *client,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	inet_addr_t remote;
+	inet_addr_t local;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetping_get_srcaddr_srv()");
+
+	remote.ipv4 = IPC_GET_ARG1(*call);
+	local.ipv4 = 0;
+
+	rc = inetping_get_srcaddr(client, &remote, &local);
+	async_answer_1(callid, rc, local.ipv4);
+}
+
+static int inetping_client_init(inetping_client_t *client)
+{
+	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL)
+		return ENOMEM;
+
+	client->sess = sess;
+	link_initialize(&client->client_list);
+
+	fibril_mutex_lock(&client_list_lock);
+	client->ident = ++inetping_ident;
+	list_append(&client->client_list, &client_list);
+	fibril_mutex_unlock(&client_list_lock);
+
+	return EOK;
+}
+
+static void inetping_client_fini(inetping_client_t *client)
+{
+	async_hangup(client->sess);
+	client->sess = NULL;
+
+	fibril_mutex_lock(&client_list_lock);
+	list_remove(&client->client_list);
+	fibril_mutex_unlock(&client_list_lock);
+}
+
+static inetping_client_t *inetping_client_find(uint16_t ident)
+{
+	fibril_mutex_lock(&client_list_lock);
+
+	list_foreach(client_list, link) {
+		inetping_client_t *client = list_get_instance(link,
+		    inetping_client_t, client_list);
+
+		if (client->ident == ident) {
+			fibril_mutex_unlock(&client_list_lock);
+			return client;
+		}
+	}
+
+	fibril_mutex_unlock(&client_list_lock);
+	return NULL;
+}
+
+void inetping_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	inetping_client_t client;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetping_conn()");
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	rc = inetping_client_init(&client);
+	if (rc != EOK)
+		return;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			break;
+		}
+
+		switch (method) {
+		case INETPING_SEND:
+			inetping_send_srv(&client, callid, &call);
+			break;
+		case INETPING_GET_SRCADDR:
+			inetping_get_srcaddr_srv(&client, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+
+	inetping_client_fini(&client);
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inetping.h
===================================================================
--- uspace/srv/net/inet/inetping.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/inetping.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,46 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INETPING_H_
+#define INETPING_H_
+
+extern void inetping_conn(ipc_callid_t, ipc_call_t *, void *);
+extern int inetping_recv(uint16_t, inetping_sdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/pdu.c
===================================================================
--- uspace/srv/net/inet/pdu.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/pdu.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,268 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <align.h>
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "inet.h"
+#include "inet_std.h"
+#include "pdu.h"
+
+static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);
+static uint16_t ip_ident = 0;
+
+/** One's complement addition.
+ *
+ * Result is a + b + carry.
+ */
+static uint16_t inet_ocadd16(uint16_t a, uint16_t b)
+{
+	uint32_t s;
+
+	s = (uint32_t)a + (uint32_t)b;
+	return (s & 0xffff) + (s >> 16);
+}
+
+uint16_t inet_checksum_calc(uint16_t ivalue, void *data, size_t size)
+{
+	uint16_t sum;
+	uint16_t w;
+	size_t words, i;
+	uint8_t *bdata;
+
+	sum = ~ivalue;
+	words = size / 2;
+	bdata = (uint8_t *)data;
+
+	for (i = 0; i < words; i++) {
+		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
+		sum = inet_ocadd16(sum, w);
+	}
+
+	if (size % 2 != 0) {
+		w = ((uint16_t)bdata[2*words] << 8);
+		sum = inet_ocadd16(sum, w);
+	}
+
+	return ~sum;
+}
+
+/** Encode Internet PDU.
+ *
+ * Encode internet packet into PDU (serialized form). Will encode a
+ * fragment of the payload starting at offset @a offs. The resulting
+ * PDU will have at most @a mtu bytes. @a *roffs will be set to the offset
+ * of remaining payload. If some data is remaining, the MF flag will
+ * be set in the header, otherwise the offset will equal @a packet->size.
+ *
+ * @param packet	Packet to encode
+ * @param offs		Offset into packet payload (in bytes)
+ * @param mtu		MTU (Maximum Transmission Unit) in bytes
+ * @param rdata		Place to store pointer to allocated data buffer
+ * @param rsize		Place to store size of allocated data buffer
+ * @param roffs		Place to store offset of remaning data
+ */
+int inet_pdu_encode(inet_packet_t *packet, size_t offs, size_t mtu,
+    void **rdata, size_t *rsize, size_t *roffs)
+{
+	void *data;
+	size_t size;
+	ip_header_t *hdr;
+	size_t hdr_size;
+	size_t data_offs;
+	uint16_t chksum;
+	uint16_t ident;
+	uint16_t flags_foff;
+	uint16_t foff;
+	size_t fragoff_limit;
+	size_t xfer_size;
+	size_t spc_avail;
+	size_t rem_offs;
+
+	/* Upper bound for fragment offset field */
+	fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
+
+	/* Verify that total size of datagram is within reasonable bounds */
+	if (offs + packet->size > FRAG_OFFS_UNIT * fragoff_limit)
+		return ELIMIT;
+
+	hdr_size = sizeof(ip_header_t);
+	data_offs = ROUND_UP(hdr_size, 4);
+
+	assert(offs % FRAG_OFFS_UNIT == 0);
+	assert(offs / FRAG_OFFS_UNIT < fragoff_limit);
+
+	/* Value for the fragment offset field */
+	foff = offs / FRAG_OFFS_UNIT;
+
+	if (hdr_size >= mtu)
+		return EINVAL;
+
+	/* Amount of space in the PDU available for payload */
+	spc_avail = mtu - hdr_size;
+	spc_avail -= (spc_avail % FRAG_OFFS_UNIT);
+
+	/* Amount of data (payload) to transfer */
+	xfer_size = min(packet->size - offs, spc_avail);
+
+	/* Total PDU size */
+	size = hdr_size + xfer_size;
+
+	/* Offset of remaining payload */
+	rem_offs = offs + xfer_size;
+
+	/* Flags */
+	flags_foff =
+	    (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) +
+	    (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) +
+	    (foff << FF_FRAGOFF_l);
+
+	data = calloc(size, 1);
+	if (data == NULL)
+		return ENOMEM;
+
+	/* Allocate identifier */
+	fibril_mutex_lock(&ip_ident_lock);
+	ident = ++ip_ident;
+	fibril_mutex_unlock(&ip_ident_lock);
+
+	/* Encode header fields */
+	hdr = (ip_header_t *)data;
+	hdr->ver_ihl = (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t));
+	hdr->tos = packet->tos;
+	hdr->tot_len = host2uint16_t_be(size);
+	hdr->id = host2uint16_t_be(ident);
+	hdr->flags_foff = host2uint16_t_be(flags_foff);
+	hdr->ttl = packet->ttl;
+	hdr->proto = packet->proto;
+	hdr->chksum = 0;
+	hdr->src_addr = host2uint32_t_be(packet->src.ipv4);
+	hdr->dest_addr = host2uint32_t_be(packet->dest.ipv4);
+
+	/* Compute checksum */
+	chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *)hdr, hdr_size);
+	hdr->chksum = host2uint16_t_be(chksum);
+
+	/* Copy payload */
+	memcpy((uint8_t *)data + data_offs, packet->data + offs, xfer_size);
+
+	*rdata = data;
+	*rsize = size;
+	*roffs = rem_offs;
+
+	return EOK;
+}
+
+int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet)
+{
+	ip_header_t *hdr;
+	size_t tot_len;
+	size_t data_offs;
+	uint8_t version;
+	uint16_t ident;
+	uint16_t flags_foff;
+	uint16_t foff;
+
+	log_msg(LVL_DEBUG, "inet_pdu_decode()");
+
+	if (size < sizeof(ip_header_t)) {
+		log_msg(LVL_DEBUG, "PDU too short (%zu)", size);
+		return EINVAL;
+	}
+
+	hdr = (ip_header_t *)data;
+
+	version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h, VI_VERSION_l,
+	    hdr->ver_ihl);
+	if (version != 4) {
+		log_msg(LVL_DEBUG, "Version (%d) != 4", version);
+		return EINVAL;
+	}
+
+	tot_len = uint16_t_be2host(hdr->tot_len);
+	if (tot_len < sizeof(ip_header_t)) {
+		log_msg(LVL_DEBUG, "Total Length too small (%zu)", tot_len);
+		return EINVAL;
+	}
+
+	if (tot_len > size) {
+		log_msg(LVL_DEBUG, "Total Length = %zu > PDU size = %zu",
+			tot_len, size);
+		return EINVAL;
+	}
+
+	ident = uint16_t_be2host(hdr->id);
+	flags_foff = uint16_t_be2host(hdr->flags_foff);
+	foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,
+	    flags_foff);
+	/* XXX Checksum */
+
+	packet->src.ipv4 = uint32_t_be2host(hdr->src_addr);
+	packet->dest.ipv4 = uint32_t_be2host(hdr->dest_addr);
+	packet->tos = hdr->tos;
+	packet->proto = hdr->proto;
+	packet->ttl = hdr->ttl;
+	packet->ident = ident;
+
+	packet->df = (flags_foff & BIT_V(uint16_t, FF_FLAG_DF)) != 0;
+	packet->mf = (flags_foff & BIT_V(uint16_t, FF_FLAG_MF)) != 0;
+	packet->offs = foff * FRAG_OFFS_UNIT;
+
+	/* XXX IP options */
+	data_offs = sizeof(uint32_t) * BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h,
+	    VI_IHL_l, hdr->ver_ihl);
+
+	packet->size = tot_len - data_offs;
+	packet->data = calloc(packet->size, 1);
+	if (packet->data == NULL) {
+		log_msg(LVL_WARN, "Out of memory.");
+		return ENOMEM;
+	}
+
+	memcpy(packet->data, (uint8_t *)data + data_offs, packet->size);
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/pdu.h
===================================================================
--- uspace/srv/net/inet/pdu.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/pdu.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,54 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_PDU_H_
+#define INET_PDU_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+#define INET_CHECKSUM_INIT 0xffff
+
+extern uint16_t inet_checksum_calc(uint16_t, void *, size_t);
+
+extern int inet_pdu_encode(inet_packet_t *, size_t, size_t, void **,
+    size_t *, size_t *);
+extern int inet_pdu_decode(void *, size_t, inet_packet_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/reass.c
===================================================================
--- uspace/srv/net/inet/reass.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/reass.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,374 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief Datagram reassembly.
+ */
+
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "inet.h"
+#include "inet_std.h"
+#include "reass.h"
+
+/** Datagram being reassembled.
+ *
+ * Uniquely identified by (source address, destination address, protocol,
+ * identification) per RFC 791 sec. 2.3 / Fragmentation.
+ */
+typedef struct {
+	link_t map_link;
+	/** List of fragments, @c reass_frag_t */
+	list_t frags;
+} reass_dgram_t;
+
+/** One datagram fragment */
+typedef struct {
+	link_t dgram_link;
+	inet_packet_t packet;
+} reass_frag_t;
+
+/** Datagram map, list of reass_dgram_t */
+static LIST_INITIALIZE(reass_dgram_map);
+/** Protects access to @c reass_dgram_map */
+static FIBRIL_MUTEX_INITIALIZE(reass_dgram_map_lock);
+
+static reass_dgram_t *reass_dgram_new(void);
+static reass_dgram_t *reass_dgram_get(inet_packet_t *);
+static int reass_dgram_insert_frag(reass_dgram_t *, inet_packet_t *);
+static bool reass_dgram_complete(reass_dgram_t *);
+static void reass_dgram_remove(reass_dgram_t *);
+static int reass_dgram_deliver(reass_dgram_t *);
+static void reass_dgram_destroy(reass_dgram_t *);
+
+/** Queue packet for datagram reassembly.
+ *
+ * @param packet	Packet
+ * @return		EOK on success or ENOMEM.
+ */
+int inet_reass_queue_packet(inet_packet_t *packet)
+{
+	reass_dgram_t *rdg;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_reass_queue_packet()");
+
+	fibril_mutex_lock(&reass_dgram_map_lock);
+
+	/* Get existing or new datagram */
+	rdg = reass_dgram_get(packet);
+	if (rdg == NULL) {
+		/* Only happens when we are out of memory */
+		fibril_mutex_unlock(&reass_dgram_map_lock);
+		log_msg(LVL_DEBUG, "Allocation failed, packet dropped.");
+		return ENOMEM;
+	}
+
+	/* Insert fragment into the datagram */
+	rc = reass_dgram_insert_frag(rdg, packet);
+	if (rc != EOK)
+		return ENOMEM;
+
+	/* Check if datagram is complete */
+	if (reass_dgram_complete(rdg)) {
+		/* Remove it from the map */
+		reass_dgram_remove(rdg);
+		fibril_mutex_unlock(&reass_dgram_map_lock);
+
+		/* Deliver complete datagram */
+		rc = reass_dgram_deliver(rdg);
+		reass_dgram_destroy(rdg);
+		return rc;
+	}
+
+	fibril_mutex_unlock(&reass_dgram_map_lock);
+	return EOK;
+}
+
+/** Get datagram reassembly structure for packet.
+ *
+ * @param packet	Packet
+ * @return		Datagram reassembly structure matching @a packet
+ */
+static reass_dgram_t *reass_dgram_get(inet_packet_t *packet)
+{
+	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
+
+	list_foreach(reass_dgram_map, link) {
+		reass_dgram_t *rdg = list_get_instance(link, reass_dgram_t,
+		    map_link);
+
+		link_t *f1_link = list_first(&rdg->frags);
+		assert(f1_link != NULL);
+
+		reass_frag_t *f1 = list_get_instance(f1_link, reass_frag_t,
+		    dgram_link);
+
+		if (f1->packet.src.ipv4 == packet->src.ipv4 &&
+		    f1->packet.dest.ipv4 == packet->dest.ipv4 &&
+		    f1->packet.proto == packet->proto &&
+		    f1->packet.ident == packet->ident) {
+			/* Match */
+			return rdg;
+		}
+	}
+
+	/* No existing reassembly structure. Create a new one. */
+	return reass_dgram_new();
+}
+
+/** Create new datagram reassembly structure.
+ *
+ * @return New datagram reassembly structure.
+ */
+static reass_dgram_t *reass_dgram_new(void)
+{
+	reass_dgram_t *rdg;
+
+	rdg = calloc(1, sizeof(reass_dgram_t));
+	if (rdg == NULL)
+		return NULL;
+
+	link_initialize(&rdg->map_link);
+	list_initialize(&rdg->frags);
+
+	return rdg;
+}
+
+static reass_frag_t *reass_frag_new(void)
+{
+	reass_frag_t *frag;
+
+	frag = calloc(1, sizeof(reass_frag_t));
+	if (frag == NULL)
+		return NULL;
+
+	link_initialize(&frag->dgram_link);
+
+	return frag;
+}
+
+static int reass_dgram_insert_frag(reass_dgram_t *rdg, inet_packet_t *packet)
+{
+	reass_frag_t *frag;
+	void *data_copy;
+	link_t *link;
+
+	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
+
+	frag = reass_frag_new();
+
+	/* Clone the packet */
+
+	data_copy = malloc(packet->size);
+	if (data_copy == NULL)
+		return ENOMEM;
+
+	frag->packet = *packet;
+	frag->packet.data = data_copy;
+
+	/*
+	 * XXX Make resource-consuming attacks harder, eliminate any duplicate
+	 * data immediately. Possibly eliminate redundant packet headers.
+	 */
+
+	/*
+	 * Insert into the list, which is sorted by offs member ascending.
+	 */
+
+	link = list_first(&rdg->frags);
+	while (link != NULL) {
+		reass_frag_t *qf = list_get_instance(link, reass_frag_t,
+		    dgram_link);
+
+		if (qf->packet.offs >= packet->offs)
+			break;
+
+		link = link->next;
+	}
+
+	if (link != NULL)
+		list_insert_after(&frag->dgram_link, link);
+	else
+		list_append(&frag->dgram_link, &rdg->frags);
+
+	return EOK;
+}
+
+/** Check if datagram is complete.
+ *
+ * @param rdg		Datagram reassembly structure
+ * @return		@c true if complete, @c false if not
+ */
+static bool reass_dgram_complete(reass_dgram_t *rdg)
+{
+	reass_frag_t *frag, *prev;
+	link_t *link;
+
+	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
+	assert(!list_empty(&rdg->frags));
+
+	/* First fragment must be at offset zero */
+	frag = list_get_instance(list_first(&rdg->frags), reass_frag_t,
+	    dgram_link);
+	if (frag->packet.offs != 0)
+		return false;
+
+	prev = frag;
+	while (true) {
+		link = frag->dgram_link.next;
+		if (link == NULL)
+			return false;
+
+		/* Each next fragment must follow immediately or overlap */
+		frag = list_get_instance(link, reass_frag_t, dgram_link);
+		if (frag->packet.offs > prev->packet.offs + prev->packet.size)
+			return false;
+
+		/* No more fragments - datagram is complete */
+		if (!frag->packet.mf)
+			return true;
+
+		prev = frag;
+	}
+
+	return false;
+}
+
+/** Remove datagram from reassembly map.
+ *
+ * @param rdg		Datagram reassembly structure
+ */
+static void reass_dgram_remove(reass_dgram_t *rdg)
+{
+	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
+	list_remove(&rdg->map_link);
+}
+
+/** Deliver complete datagram.
+ *
+ * @param rdg		Datagram reassembly structure.
+ */
+static int reass_dgram_deliver(reass_dgram_t *rdg)
+{
+	size_t dgram_size;
+	size_t fragoff_limit;
+	inet_dgram_t dgram;
+	reass_frag_t *frag;
+	uint8_t proto;
+
+	/*
+	 * Potentially there could be something beyond the first packet
+	 * that has !MF. Make sure we ignore that.
+	 */
+	frag = NULL;
+	list_foreach(rdg->frags, link) {
+		frag = list_get_instance(link, reass_frag_t, dgram_link);
+
+		if (!frag->packet.mf)
+			break;
+	}
+
+	assert(frag != NULL);
+	assert(!frag->packet.mf);
+
+	dgram_size = frag->packet.offs + frag->packet.size;
+
+	/* Upper bound for fragment offset field */
+	fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
+
+	/* Verify that total size of datagram is within reasonable bounds */
+	if (dgram_size > FRAG_OFFS_UNIT * fragoff_limit)
+		return ELIMIT;
+
+	dgram.data = calloc(dgram_size, 1);
+	if (dgram.data == NULL)
+		return ENOMEM;
+
+	dgram.size = dgram_size;
+	dgram.src = frag->packet.src;
+	dgram.dest = frag->packet.dest;
+	dgram.tos = frag->packet.tos;
+	proto = frag->packet.proto;
+
+	/* Pull together data from individual fragments */
+
+	size_t doffs = 0;
+
+	frag = NULL;
+	list_foreach(rdg->frags, link) {
+		frag = list_get_instance(link, reass_frag_t, dgram_link);
+
+		size_t cb, ce;
+
+		cb = max(doffs, frag->packet.offs);
+		ce = min(dgram_size, frag->packet.offs + frag->packet.size);
+
+		if (ce > cb) {
+			memcpy(dgram.data + cb,
+			    frag->packet.data + cb - frag->packet.offs,
+			    ce - cb);
+		}
+
+		if (!frag->packet.mf)
+			break;
+	}
+
+	return inet_recv_dgram_local(&dgram, proto);
+}
+
+/** Destroy datagram reassembly structure.
+ *
+ * @param rdg		Datagram reassembly structure.
+ */
+static void reass_dgram_destroy(reass_dgram_t *rdg)
+{
+	while (!list_empty(&rdg->frags)) {
+		link_t *flink = list_first(&rdg->frags);
+		reass_frag_t *frag = list_get_instance(flink, reass_frag_t,
+		    dgram_link);
+
+		list_remove(&frag->dgram_link);
+		free(frag->packet.data);
+		free(frag);
+	}
+
+	free(rdg);
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/reass.h
===================================================================
--- uspace/srv/net/inet/reass.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/reass.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,48 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_REASS_H_
+#define INET_REASS_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+extern int inet_reass_queue_packet(inet_packet_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/sroute.c
===================================================================
--- uspace/srv/net/inet/sroute.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/sroute.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,219 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <bitops.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <ipc/loc.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "sroute.h"
+#include "inet.h"
+#include "inet_link.h"
+#include "inet_util.h"
+
+static FIBRIL_MUTEX_INITIALIZE(sroute_list_lock);
+static LIST_INITIALIZE(sroute_list);
+static sysarg_t sroute_id = 0;
+
+inet_sroute_t *inet_sroute_new(void)
+{
+	inet_sroute_t *sroute = calloc(1, sizeof(inet_sroute_t));
+
+	if (sroute == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating static route object. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&sroute->sroute_list);
+	fibril_mutex_lock(&sroute_list_lock);
+	sroute->id = ++sroute_id;
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	return sroute;
+}
+
+void inet_sroute_delete(inet_sroute_t *sroute)
+{
+	if (sroute->name != NULL)
+		free(sroute->name);
+	free(sroute);
+}
+
+void inet_sroute_add(inet_sroute_t *sroute)
+{
+	fibril_mutex_lock(&sroute_list_lock);
+	list_append(&sroute->sroute_list, &sroute_list);
+	fibril_mutex_unlock(&sroute_list_lock);
+}
+
+void inet_sroute_remove(inet_sroute_t *sroute)
+{
+	fibril_mutex_lock(&sroute_list_lock);
+	list_remove(&sroute->sroute_list);
+	fibril_mutex_unlock(&sroute_list_lock);
+}
+
+/** Find address object matching address @a addr.
+ *
+ * @param addr	Address
+ */
+inet_sroute_t *inet_sroute_find(inet_addr_t *addr)
+{
+	uint32_t mask;
+	inet_sroute_t *best;
+
+	log_msg(LVL_DEBUG, "inet_sroute_find(%x)", (unsigned)addr->ipv4);
+
+	fibril_mutex_lock(&sroute_list_lock);
+
+	best = NULL;
+
+	list_foreach(sroute_list, link) {
+		inet_sroute_t *sroute = list_get_instance(link,
+		    inet_sroute_t, sroute_list);
+
+		/* Look for the most specific route */
+		if (best != NULL && best->dest.bits >= sroute->dest.bits)
+			continue;
+
+		mask = inet_netmask(sroute->dest.bits);
+		if ((sroute->dest.ipv4 & mask) == (addr->ipv4 & mask)) {
+			fibril_mutex_unlock(&sroute_list_lock);
+			log_msg(LVL_DEBUG, "inet_sroute_find: found %p",
+			    sroute);
+			return sroute;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "inet_sroute_find: Not found");
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	return NULL;
+}
+
+/** Find static route with a specific name.
+ *
+ * @param name	Address object name
+ * @return	Address object
+ */
+inet_sroute_t *inet_sroute_find_by_name(const char *name)
+{
+	log_msg(LVL_DEBUG, "inet_sroute_find_by_name('%s')",
+	    name);
+
+	fibril_mutex_lock(&sroute_list_lock);
+
+	list_foreach(sroute_list, link) {
+		inet_sroute_t *sroute = list_get_instance(link,
+		    inet_sroute_t, sroute_list);
+
+		if (str_cmp(sroute->name, name) == 0) {
+			fibril_mutex_unlock(&sroute_list_lock);
+			log_msg(LVL_DEBUG, "inet_sroute_find_by_name: found %p",
+			    sroute);
+			return sroute;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "inet_sroute_find_by_name: Not found");
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	return NULL;
+}
+
+/** Find static route with the given ID.
+ *
+ * @param id	Address object ID
+ * @return	Address object
+ */
+inet_sroute_t *inet_sroute_get_by_id(sysarg_t id)
+{
+	log_msg(LVL_DEBUG, "inet_sroute_get_by_id(%zu)", (size_t)id);
+
+	fibril_mutex_lock(&sroute_list_lock);
+
+	list_foreach(sroute_list, link) {
+		inet_sroute_t *sroute = list_get_instance(link,
+		    inet_sroute_t, sroute_list);
+
+		if (sroute->id == id) {
+			fibril_mutex_unlock(&sroute_list_lock);
+			return sroute;
+		}
+	}
+
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	return NULL;
+}
+
+/** Get IDs of all static routes. */
+int inet_sroute_get_id_list(sysarg_t **rid_list, size_t *rcount)
+{
+	sysarg_t *id_list;
+	size_t count, i;
+
+	fibril_mutex_lock(&sroute_list_lock);
+	count = list_count(&sroute_list);
+
+	id_list = calloc(count, sizeof(sysarg_t));
+	if (id_list == NULL) {
+		fibril_mutex_unlock(&sroute_list_lock);
+		return ENOMEM;
+	}
+
+	i = 0;
+	list_foreach(sroute_list, link) {
+		inet_sroute_t *sroute = list_get_instance(link,
+		    inet_sroute_t, sroute_list);
+
+		id_list[i++] = sroute->id;
+	}
+
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	*rid_list = id_list;
+	*rcount = count;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/sroute.h
===================================================================
--- uspace/srv/net/inet/sroute.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/inet/sroute.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,58 @@
+/*
+ * 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_SROUTE_H_
+#define INET_SROUTE_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+extern inet_sroute_t *inet_sroute_new(void);
+extern void inet_sroute_delete(inet_sroute_t *);
+extern void inet_sroute_add(inet_sroute_t *);
+extern void inet_sroute_remove(inet_sroute_t *);
+extern inet_sroute_t *inet_sroute_find(inet_addr_t *);
+extern inet_sroute_t *inet_sroute_find_by_name(const char *);
+extern inet_sroute_t *inet_sroute_get_by_id(sysarg_t);
+extern int inet_sroute_send_dgram(inet_sroute_t *, inet_addr_t *,
+    inet_dgram_t *, uint8_t, uint8_t, int);
+extern int inet_sroute_get_id_list(sysarg_t **, size_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/loopip/Makefile
===================================================================
--- uspace/srv/net/loopip/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/loopip/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+BINARY = loopip
+
+SOURCES = \
+	loopip.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/loopip/loopip.c
===================================================================
--- uspace/srv/net/loopip/loopip.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/loopip/loopip.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,227 @@
+/*
+ * 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 loopip
+ * @{
+ */
+/**
+ * @file
+ * @brief Loopback IP link provider
+ */
+
+#include <adt/prodcons.h>
+#include <async.h>
+#include <errno.h>
+#include <inet/iplink_srv.h>
+#include <io/log.h>
+#include <loc.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define NAME "loopip"
+
+static int loopip_open(iplink_srv_t *srv);
+static int loopip_close(iplink_srv_t *srv);
+static int loopip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu);
+static int loopip_get_mtu(iplink_srv_t *srv, size_t *mtu);
+static int loopip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr);
+static int loopip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr);
+
+static void loopip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static iplink_ops_t loopip_iplink_ops = {
+	.open = loopip_open,
+	.close = loopip_close,
+	.send = loopip_send,
+	.get_mtu = loopip_get_mtu,
+	.addr_add = loopip_addr_add,
+	.addr_remove = loopip_addr_remove
+};
+
+static iplink_srv_t loopip_iplink;
+static prodcons_t loopip_rcv_queue;
+
+typedef struct {
+	link_t link;
+	iplink_srv_sdu_t sdu;
+} rqueue_entry_t;
+
+static int loopip_recv_fibril(void *arg)
+{
+	while (true) {
+		log_msg(LVL_DEBUG, "loopip_recv_fibril(): Wait for one item");
+		link_t *link = prodcons_consume(&loopip_rcv_queue);
+		rqueue_entry_t *rqe = list_get_instance(link, rqueue_entry_t, link);
+
+		(void) iplink_ev_recv(&loopip_iplink, &rqe->sdu);
+	}
+
+	return 0;
+}
+
+static int loopip_init(void)
+{
+	int rc;
+	service_id_t sid;
+	category_id_t iplink_cat;
+	const char *svc_name = "net/loopback";
+
+	async_set_client_connection(loopip_client_conn);
+
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering server.");
+		return rc;
+	}
+
+	iplink_srv_init(&loopip_iplink);
+	loopip_iplink.ops = &loopip_iplink_ops;
+	loopip_iplink.arg = NULL;
+
+	prodcons_initialize(&loopip_rcv_queue);
+
+	rc = loc_service_register(svc_name, &sid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service %s.", svc_name);
+		return rc;
+	}
+
+	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
+		return rc;
+	}
+
+	rc = loc_service_add_to_cat(sid, iplink_cat);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed adding %s to category.", svc_name);
+		return rc;
+	}
+
+	fid_t fid = fibril_create(loopip_recv_fibril, NULL);
+	if (fid == 0)
+		return ENOMEM;
+
+	fibril_add_ready(fid);
+
+	return EOK;
+}
+
+static void loopip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	log_msg(LVL_DEBUG, "loopip_client_conn()");
+	iplink_conn(iid, icall, &loopip_iplink);
+}
+
+static int loopip_open(iplink_srv_t *srv)
+{
+	log_msg(LVL_DEBUG, "loopip_open()");
+	return EOK;
+}
+
+static int loopip_close(iplink_srv_t *srv)
+{
+	log_msg(LVL_DEBUG, "loopip_close()");
+	return EOK;
+}
+
+static int loopip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
+{
+	rqueue_entry_t *rqe;
+
+	log_msg(LVL_DEBUG, "loopip_send()");
+
+	rqe = calloc(1, sizeof(rqueue_entry_t));
+	if (rqe == NULL)
+		return ENOMEM;
+	/*
+	 * Clone SDU
+	 */
+	rqe->sdu.lsrc = sdu->ldest;
+	rqe->sdu.ldest = sdu->lsrc;
+	rqe->sdu.data = malloc(sdu->size);
+	if (rqe->sdu.data == NULL) {
+		free(rqe);
+		return ENOMEM;
+	}
+
+	memcpy(rqe->sdu.data, sdu->data, sdu->size);
+	rqe->sdu.size = sdu->size;
+
+	/*
+	 * Insert to receive queue
+	 */
+	prodcons_produce(&loopip_rcv_queue, &rqe->link);
+
+	return EOK;
+}
+
+static int loopip_get_mtu(iplink_srv_t *srv, size_t *mtu)
+{
+	log_msg(LVL_DEBUG, "loopip_get_mtu()");
+	*mtu = 1500;
+	return EOK;
+}
+
+static int loopip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr)
+{
+	log_msg(LVL_DEBUG, "loopip_addr_add(0x%" PRIx32 ")", addr->ipv4);
+	return EOK;
+}
+
+static int loopip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr)
+{
+	log_msg(LVL_DEBUG, "loopip_addr_remove(0x%" PRIx32 ")", addr->ipv4);
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+
+	printf(NAME ": HelenOS loopback IP link provider\n");
+
+	if (log_init(NAME, LVL_WARN) != EOK) {
+		printf(NAME ": Failed to initialize logging.\n");
+		return 1;
+	}
+
+	rc = loopip_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/** @}
+ */
Index: pace/srv/net/net/Makefile
===================================================================
--- uspace/srv/net/net/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,48 +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 = ../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include \
-    -I$(LIBDRV_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = net
-
-SOURCES = \
-	net.c \
-	packet_server.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,777 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * 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 net
- * @{
- */
-
-#include <assert.h>
-#include <async.h>
-#include <ctype.h>
-#include <ddi.h>
-#include <errno.h>
-#include <str_error.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <str.h>
-#include <str_error.h>
-#include <ns.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/net_net.h>
-#include <ipc/il.h>
-#include <ipc/ip.h>
-#include <ipc/nil.h>
-#include <net/packet.h>
-#include <net/device.h>
-#include <adt/char_map.h>
-#include <adt/generic_char_map.h>
-#include <adt/measured_strings.h>
-#include <adt/module_map.h>
-#include <fibril_synch.h>
-#include <loc.h>
-#include <nic.h>
-#include <nil_remote.h>
-#include <net_interface.h>
-#include <ip_interface.h>
-#include <device/nic.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <cfg.h>
-#include "net.h"
-#include "packet_server.h"
-
-#define MAX_PATH_LENGTH  1024
-
-/** Networking module global data. */
-net_globals_t net_globals;
-
-GENERIC_CHAR_MAP_IMPLEMENT(measured_strings, measured_string_t);
-DEVICE_MAP_IMPLEMENT(netifs, netif_t);
-LIST_INITIALIZE(netif_list);
-
-static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
-
-/** Add the configured setting to the configuration map.
- *
- * @param[in] configuration The configuration map.
- * @param[in] name          The setting name.
- * @param[in] value         The setting value.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int add_configuration(measured_strings_t *configuration,
-    const uint8_t *name, const uint8_t *value)
-{
-	int rc;
-	
-	measured_string_t *setting =
-	    measured_string_create_bulk(value, 0);
-	if (!setting)
-		return ENOMEM;
-	
-	/* Add the configuration setting */
-	rc = measured_strings_add(configuration, name, 0, setting);
-	if (rc != EOK) {
-		free(setting);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/** Generate new system-unique device identifier.
- *
- * @return The system-unique devic identifier.
- *
- */
-static nic_device_id_t generate_new_device_id(void)
-{
-	return device_assign_devno();
-}
-
-static int read_configuration_file(const char *directory, const char *filename,
-    measured_strings_t *configuration)
-{
-	printf("%s: Reading configuration file %s/%s\n", NAME, directory, filename);
-	
-	cfg_file_t cfg;
-	int rc = cfg_load_path(directory, filename, &cfg);
-	if (rc != EOK)
-		return rc;
-	
-	if (cfg_anonymous(&cfg) == NULL) {
-		cfg_unload(&cfg);
-		return ENOENT;
-	}
-	
-	cfg_section_foreach(cfg_anonymous(&cfg), link) {
-		const cfg_entry_t *entry = cfg_entry_instance(link);
-		
-		rc = add_configuration(configuration,
-		    (uint8_t *) entry->key, (uint8_t *) entry->value);
-		if (rc != EOK) {
-			cfg_unload(&cfg);
-			return rc;
-		}
-	}
-	
-	cfg_unload(&cfg);
-	return EOK;
-}
-
-/** Read the network interface specific configuration.
- *
- * @param[in]     name  The network interface name.
- * @param[in,out] netif The network interface structure.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the add_configuration() function.
- *
- */
-static int read_netif_configuration(const char *name, netif_t *netif)
-{
-	return read_configuration_file(CONF_DIR, name, &netif->configuration);
-}
-
-/** Read the networking subsystem global configuration.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the add_configuration() function.
- *
- */
-static int read_configuration(void)
-{
-	return read_configuration_file(CONF_DIR, CONF_GENERAL_FILE,
-	    &net_globals.configuration);
-}
-
-/** Return the configured values.
- *
- * The network interface configuration is searched first.
- *
- * @param[in]  netif_conf    The network interface configuration setting.
- * @param[out] configuration The found configured values.
- * @param[in]  count         The desired settings count.
- * @param[out] data          The found configuration settings data.
- *
- * @return EOK.
- *
- */
-static int net_get_conf(measured_strings_t *netif_conf,
-    measured_string_t *configuration, size_t count)
-{
-	if ((!configuration) || (count <= 0))
-			return EINVAL;
-	
-	size_t index;
-	for (index = 0; index < count; index++) {
-		measured_string_t *setting =
-		    measured_strings_find(netif_conf, configuration[index].value, 0);
-		if (!setting)
-			setting = measured_strings_find(&net_globals.configuration,
-			    configuration[index].value, 0);
-		
-		if (setting) {
-			configuration[index].length = setting->length;
-			configuration[index].value = setting->value;
-		} else {
-			configuration[index].length = 0;
-			configuration[index].value = NULL;
-		}
-	}
-	
-	return EOK;
-}
-
-static int net_get_device_conf(nic_device_id_t device_id,
-    measured_string_t *configuration, size_t count)
-{
-	netif_t *netif = netifs_find(&net_globals.netifs, device_id);
-	if (netif)
-		return net_get_conf(&netif->configuration, configuration, count);
-	else
-		return net_get_conf(NULL, configuration, count);
-}
-
-static int net_get_devices(measured_string_t **devices, size_t *dev_count)
-{
-	if (!devices)
-		return EBADMEM;
-	
-	size_t max_count = netifs_count(&net_globals.netifs);
-	*devices = malloc(max_count * sizeof(measured_string_t));
-	if (*devices == NULL)
-		return ENOMEM;
-	
-	size_t count = 0;
-	for (size_t i = 0; i < max_count; i++) {
-		netif_t *item = netifs_get_index(&net_globals.netifs, i);
-		if (item->sess != NULL) {
-			/* 
-			 * Use format "device_id:device_name"
-			 * FIXME: This typecasting looks really ugly
-			 */
-			(*devices)[count].length = asprintf(
-			    (char **) &((*devices)[count].value),
-			    NIC_DEVICE_PRINT_FMT ":%s", item->id,
-			    (const char *) item->name);
-			count++;
-		}
-	}
-	
-	*dev_count = (size_t) count;
-	return EOK;
-}
-
-static int net_get_devices_count()
-{
-	size_t max_count = netifs_count(&net_globals.netifs);
-	
-	size_t count = 0;
-	for (size_t i = 0; i < max_count; i++) {
-		netif_t *item = netifs_get_index(&net_globals.netifs, i);
-		if (item->sess != NULL)
-			count++;
-	}
-	
-	return count;
-}
-
-static void net_free_devices(measured_string_t *devices, size_t count)
-{
-	size_t i;
-	for (i = 0; i < count; ++i)
-		free(devices[i].value);
-	
-	free(devices);
-}
-
-/** Start the network interface according to its configuration.
- *
- * Register the network interface with the subsystem modules.
- * Start the needed subsystem modules.
- *
- * @param[in] netif The network interface specific data.
- *
- * @return EOK on success.
- * @return EINVAL if there are some settings missing.
- * @return ENOENT if the internet protocol module is not known.
- * @return Other error codes as defined for the netif_probe_req() function.
- * @return Other error codes as defined for the nil_device_req() function.
- * @return Other error codes as defined for the needed internet layer
- *         registering function.
- *
- */
-static int init_device(netif_t *netif, service_id_t sid)
-{
-	printf("%s: Initializing device '%s'\n", NAME, netif->name);
-	
-	netif->sid = sid;
-	netif->sess = loc_service_connect(EXCHANGE_SERIALIZE, netif->sid,
-	    IPC_FLAG_BLOCKING);
-	if (netif->sess == NULL) {
-		printf("%s: Unable to connect to device\n", NAME);
-		return EREFUSED;
-	}
-	
-	/* Optional network interface layer */
-	measured_string_t *setting = measured_strings_find(&netif->configuration,
-	    (uint8_t *) CONF_NIL, 0);
-	if (setting) {
-		netif->nil = get_running_module(&net_globals.modules,
-		    setting->value);
-		if (!netif->nil) {
-			printf("%s: Unable to connect to network interface layer '%s'\n",
-			    NAME, setting->value);
-			return EINVAL;
-		}
-	} else
-		netif->nil = NULL;
-	
-	/* Mandatory internet layer */
-	setting = measured_strings_find(&netif->configuration,
-	    (uint8_t *) CONF_IL, 0);
-	netif->il = get_running_module(&net_globals.modules,
-	    setting->value);
-	if (!netif->il) {
-		printf("%s: Unable to connect to internet layer '%s'\n",
-		    NAME, setting->value);
-		return EINVAL;
-	}
-	
-	/* Network interface layer startup */
-	int rc;
-	services_t nil_service;
-	if (netif->nil) {
-		setting = measured_strings_find(&netif->configuration,
-		    (uint8_t *) CONF_MTU, 0);
-		if (!setting)
-			setting = measured_strings_find(&net_globals.configuration,
-			    (uint8_t *) CONF_MTU, 0);
-		
-		int mtu = setting ?
-		    strtol((const char *) setting->value, NULL, 10) : 0;
-		rc = nil_device_req(netif->nil->sess, netif->id,
-		    netif->sid, mtu);
-		if (rc != EOK) {
-			printf("%s: Unable to start network interface layer\n",
-			    NAME);
-			return rc;
-		}
-		
-		nil_service = netif->nil->service;
-	} else
-		nil_service = -1;
-	
-	/* Inter-network layer startup */
-	switch (netif->il->service) {
-	case SERVICE_IP:
-		rc = ip_device_req(netif->il->sess, netif->id, nil_service);
-		if (rc != EOK) {
-			printf("%s: Unable to start internet layer\n", NAME);
-			return rc;
-		}
-		
-		break;
-	default:
-		printf("%s: Unknown service\n", NAME);
-		return ENOENT;
-	}
-	
-	printf("%s: Activating device '%s'\n", NAME, netif->name);
-	list_append(&netif->netif_list, &netif_list);
-	return nic_set_state(netif->sess, NIC_STATE_ACTIVE);
-}
-
-static int net_nic_ready(service_id_t sid)
-{
-	int rc;
-	char *hwpath;
-	
-	rc = loc_service_get_name(sid, &hwpath);
-	if (rc != EOK) {
-		printf("%s: Failed getting name of service '%u'\n",
-		    NAME, (unsigned) sid);
-		return EINVAL;
-	}
-	
-	int index = char_map_find(&net_globals.netif_hwpaths,
-	    (uint8_t *) hwpath, 0);
-	
-	if (index == CHAR_MAP_NULL) {
-		printf("%s: Service '%s' not found in map.\n", NAME, hwpath);
-		free(hwpath);
-		return ENOENT;
-	}
-	
-	free(hwpath);
-	
-	netif_t *netif = netifs_get_index(&net_globals.netifs, index);
-	if (netif == NULL)
-		return ENOENT;
-	
-	rc = init_device(netif, sid);
-	if (rc != EOK)
-		return rc;
-	
-	/* Increment module usage */
-	if (netif->nil)
-		netif->nil->usage++;
-	
-	netif->il->usage++;
-	
-	return EOK;
-}
-
-/** Process the networking message.
- *
- * @param[in]  callid       The message identifier.
- * @param[in]  call         The message parameters.
- * @param[out] answer       The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer
- *                          in the answer parameter.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is not known.
- *
- * @see net_interface.h
- * @see IS_NET_NET_MESSAGE()
- *
- */
-static int net_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	measured_string_t *strings;
-	uint8_t *data;
-	int rc;
-	size_t count;
-	
-	*answer_count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_NET_GET_DEVICE_CONF:
-		rc = measured_strings_receive(&strings, &data,
-		    IPC_GET_COUNT(*call));
-		if (rc != EOK)
-			return rc;
-		
-		net_get_device_conf(IPC_GET_DEVICE(*call), strings,
-		    IPC_GET_COUNT(*call));
-		
-		rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
-		free(strings);
-		free(data);
-		return rc;
-	case NET_NET_GET_CONF:
-		rc = measured_strings_receive(&strings, &data,
-		    IPC_GET_COUNT(*call));
-		if (rc != EOK)
-			return rc;
-		
-		net_get_conf(NULL, strings, IPC_GET_COUNT(*call));
-		
-		rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
-		free(strings);
-		free(data);
-		return rc;
-	case NET_NET_GET_DEVICES_COUNT:
-		count = (size_t) net_get_devices_count();
-		IPC_SET_ARG1(*answer, count);
-		*answer_count = 1;
-		return EOK;
-	case NET_NET_GET_DEVICES:
-		rc = net_get_devices(&strings, &count);
-		if (rc != EOK)
-			return rc;
-		
-		rc = measured_strings_reply(strings, count);
-		net_free_devices(strings, count);
-		return rc;
-	default:
-		return ENOTSUP;
-	}
-}
-
-/** 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 net_client_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		/* Clear the answer structure */
-		ipc_call_t answer;
-		size_t count;
-		refresh_answer(&answer, &count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res;
-		if (IS_NET_PACKET_MESSAGE(call))
-			res = packet_server_message(callid, &call, &answer, &count);
-		else
-			res = net_message(callid, &call, &answer, &count);
-		
-		/* End if told to either by the message or the processing result */
-		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, count);
-	}
-}
-
-static int nic_check_new(void)
-{
-	category_id_t nic_cat;
-	service_id_t *svcs;
-	size_t count, i;
-	bool already_known;
-	int rc;
-
-	fibril_mutex_lock(&discovery_lock);
-
-	rc = loc_category_get_id(DEVICE_CATEGORY_NIC, &nic_cat, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		printf("%s: Failed resolving category '%s'.\n", NAME,
-		    DEVICE_CATEGORY_NIC);
-		return ENOENT;
-	}
-
-	rc = loc_category_get_svcs(nic_cat, &svcs, &count);
-	if (rc != EOK) {
-		printf("%s: Failed getting list of NIC devices.\n", NAME);
-		return EIO;
-	}
-
-	for (i = 0; i < count; i++) {
-		already_known = false;
-
-		list_foreach(netif_list, link) {
-			netif_t *netif = list_get_instance(link, netif_t, netif_list);
-			if (netif->sid == svcs[i]) {
-				already_known = true;
-				break;
-			}
-		}
-
-		if (!already_known) {
-			rc = net_nic_ready(svcs[i]);
-			if (rc != EOK) {
-				printf("%s: Failed adding NIC device #%u.\n",
-				    NAME, (unsigned) svcs[i]);
-			}
-		}
-	}
-
-	free(svcs);
-	fibril_mutex_unlock(&discovery_lock);
-	return EOK;
-}
-
-static void cat_change_cb(void)
-{
-	(void) nic_check_new();
-}
-
-static int net_start_nic_discovery(void)
-{
-	int rc;
-
-	rc = loc_register_cat_change_cb(cat_change_cb);
-	if (rc != EOK) {
-		printf("%s: Failed registering callback for device discovery (%d).\n",
-		    NAME, rc);
-		return rc;
-	}
-
-	return nic_check_new();
-}
-
-int main(int argc, char *argv[])
-{
-	netifs_initialize(&net_globals.netifs);
-	char_map_initialize(&net_globals.netif_hwpaths);
-	modules_initialize(&net_globals.modules);
-	measured_strings_initialize(&net_globals.configuration);
-	async_set_client_connection(net_client_connection);
-	
-	int rc = pm_init();
-	if (rc != EOK) {
-		printf("%s: Unable to initialize packet management\n", NAME);
-		return rc;
-	}
-	
-	rc = packet_server_init();
-	if (rc != EOK) {
-		printf("%s: Unable to initialize packet server\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	rc = read_configuration();
-	if (rc != EOK) {
-		printf("%s: Error reading configuration\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	DIR *config_dir = opendir(CONF_DIR);
-	if (config_dir != NULL) {
-		struct dirent *dir_entry;
-		while ((dir_entry = readdir(config_dir))) {
-			/* Ignore files without the CONF_EXT extension */
-			if ((str_size(dir_entry->d_name) < str_size(CONF_EXT)) ||
-			    (str_cmp(dir_entry->d_name + str_size(dir_entry->d_name) -
-			    str_size(CONF_EXT), CONF_EXT) != 0))
-				continue;
-			
-			
-			netif_t *netif = (netif_t *) malloc(sizeof(netif_t));
-			if (!netif)
-				continue;
-			
-			netif->sid = -1;
-			netif->sess = NULL;
-			
-			netif->id = generate_new_device_id();
-			if (!netif->id) {
-				free(netif);
-				continue;
-			}
-			
-			rc = measured_strings_initialize(&netif->configuration);
-			if (rc != EOK) {
-				free(netif);
-				continue;
-			}
-			
-			rc = read_netif_configuration(dir_entry->d_name, netif);
-			if (rc != EOK) {
-				printf("%s: Error reading configuration %s\n", NAME,
-				    dir_entry->d_name);
-				free(netif);
-				continue;
-			}
-			
-			measured_string_t *name = measured_strings_find(&netif->configuration,
-			    (uint8_t *) CONF_NAME, 0);
-			if (!name) {
-				printf("%s: Network interface name is missing in %s\n",
-				    NAME, dir_entry->d_name);
-				measured_strings_destroy(&netif->configuration, free);
-				free(netif);
-				continue;
-			}
-			
-			netif->name = name->value;
-			
-			/* Mandatory hardware path */
-			measured_string_t *hwpath = measured_strings_find(
-			    &netif->configuration, (const uint8_t *) CONF_HWPATH, 0);
-			if (!hwpath) {
-				printf("%s: Hardware path is missing in %s\n",
-				    NAME, dir_entry->d_name);
-				measured_strings_destroy(&netif->configuration, free);
-				free(netif);
-				continue;
-			}
-			
-			int index = netifs_add(&net_globals.netifs, netif->id, netif);
-			if (index < 0) {
-				measured_strings_destroy(&netif->configuration, free);
-				free(netif);
-				continue;
-			}
-			
-			/*
-			 * Add to the hardware paths map and init network interfaces
-			 * and needed modules.
-			 */
-			rc = char_map_add(&net_globals.netif_hwpaths, hwpath->value, 0, index);
-			if (rc != EOK) {
-				measured_strings_destroy(&netif->configuration, free);
-				netifs_exclude_index(&net_globals.netifs, index, free);
-				continue;
-			}
-		}
-		
-		closedir(config_dir);
-	}
-	
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) ETHERNET_NAME,
-	    (uint8_t *) ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service);
-	if (rc != EOK) {
-		printf("%s: Error adding module '%s'\n", NAME, ETHERNET_NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) NILDUMMY_NAME,
-	    (uint8_t *) NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service);
-	if (rc != EOK) {
-		printf("%s: Error adding module '%s'\n", NAME, NILDUMMY_NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	task_id_t task_id = net_spawn((uint8_t *) IP_FILENAME);
-	if (!task_id) {
-		printf("%s: Error spawning IP module\n", NAME);
-		pm_destroy();
-		return EINVAL;
-	}
-	
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) IP_NAME,
-	    (uint8_t *) IP_FILENAME, SERVICE_IP, task_id, ip_connect_module);
-	if (rc != EOK) {
-		printf("%s: Error adding module '%s'\n", NAME, IP_NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	if (!net_spawn((uint8_t *) "/srv/icmp")) {
-		printf("%s: Error spawning ICMP module\n", NAME);
-		pm_destroy();
-		return EINVAL;
-	}
-	
-	if (!net_spawn((uint8_t *) "/srv/udp")) {
-		printf("%s: Error spawning UDP module\n", NAME);
-		pm_destroy();
-		return EINVAL;
-	}
-	
-	if (!net_spawn((uint8_t *) "/srv/tcp")) {
-		printf("%s: Error spawning TCP module\n", NAME);
-		pm_destroy();
-		return EINVAL;
-	}
-	
-	rc = service_register(SERVICE_NETWORKING);
-	if (rc != EOK) {
-		printf("%s: Error registering service\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	rc = net_start_nic_discovery();
-	if (rc != EOK) {
-		printf("%s: Error starting NIC discovery\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	task_retval(0);
-	async_manager();
-	return 0;
-}
-
-/** @}
- */
Index: pace/srv/net/net/net.h
===================================================================
--- uspace/srv/net/net/net.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,132 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * 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
- * @{
- */
-
-#ifndef NET_NET_H_
-#define NET_NET_H_
-
-#include <ipc/loc.h>
-#include <net/device.h>
-#include <adt/char_map.h>
-#include <adt/generic_char_map.h>
-#include <adt/measured_strings.h>
-#include <adt/module_map.h>
-#include <net/packet.h>
-
-#define NAME  "net"
-
-#define ETHERNET_FILENAME  "/srv/eth"
-#define ETHERNET_NAME      "eth"
-
-#define IP_FILENAME  "/srv/ip"
-#define IP_NAME      "ip"
-
-#define NILDUMMY_FILENAME  "/srv/nildummy"
-#define NILDUMMY_NAME      "nildummy"
-
-/** @}
- */
-
-/** @name Configuration setting names definitions
- * @{
- */
-
-#define CONF_IL     "IL"     /**< Internet protocol module name configuration label. */
-#define CONF_IO     "IO"     /**< Device input/output address configuration label. */
-#define CONF_IRQ    "IRQ"    /**< Interrupt number configuration label. */
-#define CONF_MTU    "MTU"    /**< Maximum transmission unit configuration label. */
-#define CONF_NAME   "NAME"   /**< Network interface name configuration label. */
-#define CONF_HWPATH "HWPATH" /**< Network interface hardware pathname label. */
-#define CONF_NIL    "NIL"    /**< Network interface layer module name configuration label. */
-
-/** @}
- */
-
-#define CONF_DIR           "/cfg/net"  /**< Configuration directory. */
-#define CONF_GENERAL_FILE  "general"   /**< General configuration file. */
-#define CONF_EXT           ".nic"      /**< Extension for NIC's configuration files. */
-
-/** Configuration settings.
- *
- * Maps setting names to the values.
- * @see generic_char_map.h
- *
- */
-GENERIC_CHAR_MAP_DECLARE(measured_strings, measured_string_t);
-
-/** Present network interface device.
- *
- */
-typedef struct {
-	/** System-unique network interface name. */
-	uint8_t *name;
-	/** System-unique network interface identifier. */
-	nic_device_id_t id;
-	/** Configuration. */
-	measured_strings_t configuration;
-	
-	/** Serving network interface driver module index. */
-	service_id_t sid;    /**< Service ID */
-	async_sess_t *sess;  /**< Driver session. */
-	
-	module_t *nil;  /**< Serving link layer module index. */
-	module_t *il;   /**< Serving internet layer module index. */
-	
-	link_t netif_list;
-} netif_t;
-
-/** Present network interfaces.
- *
- * Maps devices to the networking device specific data.
- * @see device.h
- *
- */
-DEVICE_MAP_DECLARE(netifs, netif_t);
-
-/** Networking module global data.
- *
- */
-typedef struct {
-	measured_strings_t configuration;  /**< Global configuration. */
-	modules_t modules;                 /**< Available modules. */
-	
-	/** Network interface structure indices by hardware path. */
-	char_map_t netif_hwpaths;
-	
-	/** Present network interfaces. */
-	netifs_t netifs;
-} net_globals_t;
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/net/packet_server.c
===================================================================
--- uspace/srv/net/net/packet_server.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,402 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * 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 libpacket
- *  @{
- */
-
-/** @file
- * Packet server implementation.
- */
-
-#include <align.h>
-#include <assert.h>
-#include <async.h>
-#include <errno.h>
-#include <str_error.h>
-#include <stdio.h>
-#include <fibril_synch.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <ipc/packet.h>
-#include <ipc/net.h>
-#include <net/packet.h>
-#include <net/packet_header.h>
-
-#include "packet_server.h"
-
-#define PACKET_SERVER_PROFILE 1
-
-/** Number of queues cacheing the unused packets */
-#define FREE_QUEUES_COUNT	7
-/** Maximum number of packets in each queue */
-#define FREE_QUEUE_MAX_LENGTH	16
-
-/** The default address length reserved for new packets. */
-#define DEFAULT_ADDR_LEN	32
-
-/** The default prefix reserved for new packets. */
-#define DEFAULT_PREFIX		64
-
-/** The default suffix reserved for new packets. */
-#define DEFAULT_SUFFIX		64
-
-/** The queue with unused packets */
-typedef struct packet_queue {
-	packet_t *first;	/**< First packet in the queue */
-	size_t packet_size; /**< Maximal size of the packets in this queue */
-	int count;			/**< Length of the queue */
-} packet_queue_t;
-
-/** Packet server global data. */
-static struct {
-	/** Safety lock. */
-	fibril_mutex_t lock;
-	/** Free packet queues. */
-	packet_queue_t free_queues[FREE_QUEUES_COUNT];
-	
-	/** Total packets allocated. */
-	packet_id_t next_id;
-} ps_globals = {
-	.lock = FIBRIL_MUTEX_INITIALIZER(ps_globals.lock),
-	.free_queues = {
-		{ NULL, PAGE_SIZE, 0},
-		{ NULL, PAGE_SIZE * 2, 0},
-		{ NULL, PAGE_SIZE * 4, 0},
-		{ NULL, PAGE_SIZE * 8, 0},
-		{ NULL, PAGE_SIZE * 16, 0},
-		{ NULL, PAGE_SIZE * 32, 0},
-		{ NULL, PAGE_SIZE * 64, 0},
-	},
-	.next_id = 1
-};
-
-/** Clears and initializes the packet according to the given dimensions.
- *
- * @param[in] packet	The packet to be initialized.
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- */
-static void packet_init(packet_t *packet,
-	size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix)
-{
-	/* Clear the packet content */
-	bzero(((void *) packet) + sizeof(packet_t),
-	    packet->length - sizeof(packet_t));
-	
-	/* Clear the packet header */
-	packet->order = 0;
-	packet->metric = 0;
-	packet->previous = 0;
-	packet->next = 0;
-	packet->offload_info = 0;
-	packet->offload_mask = 0;
-	packet->addr_len = 0;
-	packet->src_addr = sizeof(packet_t);
-	packet->dest_addr = packet->src_addr + addr_len;
-	packet->max_prefix = max_prefix;
-	packet->max_content = max_content;
-	packet->data_start = packet->dest_addr + addr_len + packet->max_prefix;
-	packet->data_end = packet->data_start;
-}
-
-/**
- * Releases the memory allocated for the packet
- *
- * @param[in] packet Pointer to the memory where the packet was allocated
- */
-static void packet_dealloc(packet_t *packet)
-{
-	pm_remove(packet);
-	munmap(packet, packet->length);
-}
-
-/** Creates a new packet of dimensions at least as given.
- *
- * @param[in] length	The total length of the packet, including the header,
- *			the addresses and the data of the packet.
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- * @return		The packet of dimensions at least as given.
- * @return		NULL if there is not enough memory left.
- */
-static packet_t *packet_alloc(size_t length, size_t addr_len,
-	size_t max_prefix, size_t max_content, size_t max_suffix)
-{
-	packet_t *packet;
-	int rc;
-
-	/* Global lock is locked */
-	assert(fibril_mutex_is_locked(&ps_globals.lock));
-	/* The length is some multiple of PAGE_SIZE */
-	assert(!(length & (PAGE_SIZE - 1)));
-
-	packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
-		MAP_SHARED | MAP_ANONYMOUS, 0, 0);
-	if (packet == MAP_FAILED)
-		return NULL;
-	
-	/* Using 32bit packet_id the id could overflow */
-	packet_id_t pid;
-	do {
-		pid = ps_globals.next_id;
-		ps_globals.next_id++;
-	} while (!pid || pm_find(pid));
-	packet->packet_id = pid;
-
-	packet->length = length;
-	packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
-	packet->magic_value = PACKET_MAGIC_VALUE;
-	rc = pm_add(packet);
-	if (rc != EOK) {
-		packet_dealloc(packet);
-		return NULL;
-	}
-	
-	return packet;
-}
-
-/** Return the packet of dimensions at least as given.
- *
- * Try to reuse free packets first.
- * Create a new packet aligned to the memory page size if none available.
- * Lock the global data during its processing.
- *
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- * @return		The packet of dimensions at least as given.
- * @return		NULL if there is not enough memory left.
- */
-static packet_t *packet_get_local(size_t addr_len,
-	size_t max_prefix, size_t max_content, size_t max_suffix)
-{
-	size_t length = ALIGN_UP(sizeof(packet_t) + 2 * addr_len
-		+ max_prefix + max_content + max_suffix, PAGE_SIZE);
-	
-	if (length > PACKET_MAX_LENGTH)
-		return NULL;
-
-	fibril_mutex_lock(&ps_globals.lock);
-	
-	packet_t *packet;
-	unsigned int index;
-	
-	for (index = 0; index < FREE_QUEUES_COUNT; index++) {
-		if ((length > ps_globals.free_queues[index].packet_size) &&
-			(index < FREE_QUEUES_COUNT - 1))
-			continue;
-		
-		packet = ps_globals.free_queues[index].first;
-		while (packet_is_valid(packet) && (packet->length < length))
-			packet = pm_find(packet->next);
-		
-		if (packet_is_valid(packet)) {
-			ps_globals.free_queues[index].count--;
-			if (packet == ps_globals.free_queues[index].first) {
-				ps_globals.free_queues[index].first = pq_detach(packet);
-			} else {
-				pq_detach(packet);
-			}
-			
-			packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
-			fibril_mutex_unlock(&ps_globals.lock);
-			
-			return packet;
-		}
-	}
-	
-	packet = packet_alloc(length, addr_len,
-		max_prefix, max_content, max_suffix);
-	
-	fibril_mutex_unlock(&ps_globals.lock);
-	
-	return packet;
-}
-
-/** Release the packet and returns it to the appropriate free packet queue.
- *
- * @param[in] packet	The packet to be released.
- *
- */
-static void packet_release(packet_t *packet)
-{
-	int index;
-	int result;
-
-	assert(fibril_mutex_is_locked(&ps_globals.lock));
-
-	for (index = 0; (index < FREE_QUEUES_COUNT - 1) &&
-	    (packet->length > ps_globals.free_queues[index].packet_size); index++) {
-		;
-	}
-	
-	ps_globals.free_queues[index].count++;
-	result = pq_add(&ps_globals.free_queues[index].first, packet,
-		packet->length,	packet->length);
-	assert(result == EOK);
-}
-
-/** Releases the packet queue.
- *
- * @param[in] packet_id	The first packet identifier.
- * @return		EOK on success.
- * @return		ENOENT if there is no such packet.
- */
-static int packet_release_wrapper(packet_id_t packet_id)
-{
-	packet_t *packet;
-
-	packet = pm_find(packet_id);
-	if (!packet_is_valid(packet))
-		return ENOENT;
-
-	fibril_mutex_lock(&ps_globals.lock);
-	pq_destroy(packet, packet_release);
-	fibril_mutex_unlock(&ps_globals.lock);
-
-	return EOK;
-}
-
-/** Shares the packet memory block.
- * @param[in] packet	The packet to be shared.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		EINVAL if the calling module does not accept the memory.
- * @return		ENOMEM if the desired and actual sizes differ.
- * @return		Other error codes as defined for the
- *			async_share_in_finalize() function.
- */
-static int packet_reply(packet_t *packet)
-{
-	if (!packet_is_valid(packet))
-		return EINVAL;
-	
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_share_in_receive(&callid, &size)) {
-		async_answer_0(callid, EINVAL);
-		return EINVAL;
-	}
-	
-	if (size != packet->length) {
-		async_answer_0(callid, ENOMEM);
-		return ENOMEM;
-	}
-	
-	return async_share_in_finalize(callid, packet,
-	    PROTO_READ | PROTO_WRITE);
-}
-
-/** Processes the packet server message.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @param[out] answer	The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer in the
- *			answer parameter.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- * @return		ENOENT if there is no such packet as in the packet
- *			message parameter.
- * @return		ENOTSUP if the message is not known.
- * @return		Other error codes as defined for the
- *			packet_release_wrapper() function.
- */
-int packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *answer_count)
-{
-	packet_t *packet;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_PACKET_CREATE_1:
-		packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX,
-			IPC_GET_CONTENT(*call), DEFAULT_SUFFIX);
-		if (!packet)
-			return ENOMEM;
-		*answer_count = 2;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
-		IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
-		return EOK;
-	
-	case NET_PACKET_CREATE_4:
-		packet = packet_get_local(
-			((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(*call)) ?
-		    IPC_GET_ADDR_LEN(*call) : DEFAULT_ADDR_LEN),
-		    DEFAULT_PREFIX + IPC_GET_PREFIX(*call),
-		    IPC_GET_CONTENT(*call),
-		    DEFAULT_SUFFIX + IPC_GET_SUFFIX(*call));
-		if (!packet)
-			return ENOMEM;
-		*answer_count = 2;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
-		IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
-		return EOK;
-	
-	case NET_PACKET_GET:
-		packet = pm_find(IPC_GET_ID(*call));
-		if (!packet_is_valid(packet))
-			return ENOENT;
-		
-		return packet_reply(packet);
-	
-	case NET_PACKET_GET_SIZE:
-		packet = pm_find(IPC_GET_ID(*call));
-		if (!packet_is_valid(packet))
-			return ENOENT;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->length);
-		*answer_count = 1;
-		return EOK;
-	
-	case NET_PACKET_RELEASE:
-		return packet_release_wrapper(IPC_GET_ID(*call));
-	}
-	
-	return ENOTSUP;
-}
-
-int packet_server_init()
-{
-	return EOK;
-}
-
-/** @}
- */
Index: pace/srv/net/net/packet_server.h
===================================================================
--- uspace/srv/net/net/packet_server.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,57 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * 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 libpacket
- * @{
- */
-
-/** @file
- * Packet server.
- * The hosting module has to be compiled with both the packet.c and the
- * packet_server.c source files. To function correctly, initialization of the
- * packet map by the pm_init() function has to happen at the first place. Then
- * the packet messages have to be processed by the packet_server_message()
- * function. The packet map should be released by the pm_destroy() function
- * during the module termination.
- * @see IS_NET_PACKET_MESSAGE()
- */
-
-#ifndef NET_PACKET_SERVER_H_
-#define NET_PACKET_SERVER_H_
-
-#include <ipc/common.h>
-
-extern int packet_server_init(void);
-extern int packet_server_message(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    size_t *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/nil/eth/Makefile
===================================================================
--- uspace/srv/net/nil/eth/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,46 +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 = ../../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = eth
-
-SOURCES = \
-	eth.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,997 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * 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 eth
- *  @{
- */
-
-/** @file
- *  Ethernet module implementation.
- *  @see eth.h
- */
-
-#include <assert.h>
-#include <async.h>
-#include <malloc.h>
-#include <mem.h>
-#include <stdio.h>
-#include <byteorder.h>
-#include <str.h>
-#include <errno.h>
-#include <ipc/nil.h>
-#include <ipc/net.h>
-#include <ipc/services.h>
-#include <loc.h>
-#include <net/modules.h>
-#include <net_checksum.h>
-#include <ethernet_lsap.h>
-#include <ethernet_protocols.h>
-#include <protocol_map.h>
-#include <net/device.h>
-#include <net_interface.h>
-#include <il_remote.h>
-#include <adt/measured_strings.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <device/nic.h>
-#include <nil_skel.h>
-#include "eth.h"
-
-/** The module name. */
-#define NAME  "eth"
-
-/** Reserved packet prefix length. */
-#define ETH_PREFIX \
-	(sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + \
-	    sizeof(eth_header_snap_t))
-
-/** Reserved packet suffix length. */
-#define ETH_SUFFIX  (sizeof(eth_fcs_t))
-
-/** Maximum packet content length. */
-#define ETH_MAX_CONTENT  1500u
-
-/** Minimum packet content length. */
-#define ETH_MIN_CONTENT  46u
-
-/** Maximum tagged packet content length. */
-#define ETH_MAX_TAGGED_CONTENT(flags) \
-	(ETH_MAX_CONTENT - \
-	    ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
-	    sizeof(eth_header_lsap_t) : 0) - \
-	    (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
-
-/** Minimum tagged packet content length. */
-#define ETH_MIN_TAGGED_CONTENT(flags) \
-	(ETH_MIN_CONTENT - \
-	    ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
-	    sizeof(eth_header_lsap_t) : 0) - \
-	    (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
-
-/** Dummy flag shift value. */
-#define ETH_DUMMY_SHIFT  0
-
-/** Mode flag shift value. */
-#define ETH_MODE_SHIFT  1
-
-/** Dummy device flag.
- * Preamble and FCS are mandatory part of the packets.
- */
-#define ETH_DUMMY  (1 << ETH_DUMMY_SHIFT)
-
-/** Returns the dummy flag.
- * @see ETH_DUMMY
- */
-#define IS_DUMMY(flags)  ((flags) & ETH_DUMMY)
-
-/** Device mode flags.
- * @see ETH_DIX
- * @see ETH_8023_2_LSAP
- * @see ETH_8023_2_SNAP
- */
-#define ETH_MODE_MASK  (3 << ETH_MODE_SHIFT)
-
-/** DIX Ethernet mode flag. */
-#define ETH_DIX  (1 << ETH_MODE_SHIFT)
-
-/** Return whether the DIX Ethernet mode flag is set.
- *
- * @param[in] flags Ethernet flags.
- * @see ETH_DIX
- *
- */
-#define IS_DIX(flags)  (((flags) & ETH_MODE_MASK) == ETH_DIX)
-
-/** 802.3 + 802.2 + LSAP mode flag. */
-#define ETH_8023_2_LSAP  (2 << ETH_MODE_SHIFT)
-
-/** Return whether the 802.3 + 802.2 + LSAP mode flag is set.
- *
- * @param[in] flags Ethernet flags.
- * @see ETH_8023_2_LSAP
- *
- */
-#define IS_8023_2_LSAP(flags)  (((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP)
-
-/** 802.3 + 802.2 + LSAP + SNAP mode flag. */
-#define ETH_8023_2_SNAP  (3 << ETH_MODE_SHIFT)
-
-/** Return whether the 802.3 + 802.2 + LSAP + SNAP mode flag is set.
- *
- * @param[in] flags Ethernet flags.
- * @see ETH_8023_2_SNAP
- *
- */
-#define IS_8023_2_SNAP(flags)  (((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP)
-
-/** Type definition of the ethernet address type.
- * @see eth_addr_type
- */
-typedef enum eth_addr_type eth_addr_type_t;
-
-/** Ethernet address type. */
-enum eth_addr_type {
-	/** Local address. */
-	ETH_LOCAL_ADDR,
-	/** Broadcast address. */
-	ETH_BROADCAST_ADDR
-};
-
-/** Ethernet module global data. */
-eth_globals_t eth_globals;
-
-DEVICE_MAP_IMPLEMENT(eth_devices, eth_device_t);
-INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
-
-static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg);
-
-static int eth_device_state(eth_device_t *device, sysarg_t state)
-{
-	int index;
-	eth_proto_t *proto;
-
-	fibril_rwlock_read_lock(&eth_globals.protos_lock);
-	for (index = eth_protos_count(&eth_globals.protos) - 1; index >= 0;
-	    index--) {
-		proto = eth_protos_get_index(&eth_globals.protos, index);
-		if ((proto) && (proto->sess)) {
-			il_device_state_msg(proto->sess, device->device_id,
-			    state, proto->service);
-		}
-	}
-	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-	
-	return EOK;
-}
-
-int nil_initialize(async_sess_t *sess)
-{
-	int rc;
-
-	fibril_rwlock_initialize(&eth_globals.devices_lock);
-	fibril_rwlock_initialize(&eth_globals.protos_lock);
-	
-	fibril_rwlock_write_lock(&eth_globals.devices_lock);
-	fibril_rwlock_write_lock(&eth_globals.protos_lock);
-	
-	eth_globals.net_sess = sess;
-	memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
-			ETH_ADDR);
-
-	rc = eth_devices_initialize(&eth_globals.devices);
-	if (rc != EOK) {
-		free(eth_globals.broadcast_addr);
-		goto out;
-	}
-
-	rc = eth_protos_initialize(&eth_globals.protos);
-	if (rc != EOK) {
-		free(eth_globals.broadcast_addr);
-		eth_devices_destroy(&eth_globals.devices, free);
-	}
-	
-out:
-	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-	
-	return rc;
-}
-
-/** Register new device or updates the MTU of an existing one.
- *
- * Determine the device local hardware address.
- *
- * @param[in] device_id New device identifier.
- * @param[in] sid       NIC service ID.
- * @param[in] mtu       Device maximum transmission unit.
- *
- * @return EOK on success.
- * @return EEXIST if the device with the different service exists.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int eth_device_message(nic_device_id_t device_id, service_id_t sid,
-    size_t mtu)
-{
-	eth_device_t *device;
-	int index;
-	measured_string_t names[2] = {
-		{
-			(uint8_t *) "ETH_MODE",
-			8
-		},
-		{
-			(uint8_t *) "ETH_DUMMY",
-			9
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	eth_proto_t *proto;
-	int rc;
-
-	fibril_rwlock_write_lock(&eth_globals.devices_lock);
-	/* An existing device? */
-	device = eth_devices_find(&eth_globals.devices, device_id);
-	if (device) {
-		if (device->sid != sid) {
-			printf("Device %d already exists\n", device->device_id);
-			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-			return EEXIST;
-		}
-		
-		/* Update mtu */
-		if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
-			device->mtu = mtu;
-		else
-			device->mtu = ETH_MAX_TAGGED_CONTENT(device->flags);
-		
-		printf("Device %d already exists:\tMTU\t= %zu\n",
-		    device->device_id, device->mtu);
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		
-		/* Notify all upper layer modules */
-		fibril_rwlock_read_lock(&eth_globals.protos_lock);
-		for (index = 0; index < eth_protos_count(&eth_globals.protos);
-		    index++) {
-			proto = eth_protos_get_index(&eth_globals.protos,
-			    index);
-			if (proto->sess) {
-				il_mtu_changed_msg(proto->sess,
-				    device->device_id, device->mtu,
-				    proto->service);
-			}
-		}
-
-		fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-		return EOK;
-	}
-	
-	/* Create a new device */
-	device = (eth_device_t *) malloc(sizeof(eth_device_t));
-	if (!device)
-		return ENOMEM;
-
-	device->device_id = device_id;
-	device->sid = sid;
-	device->flags = 0;
-	if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
-		device->mtu = mtu;
-	else
-		device->mtu = ETH_MAX_TAGGED_CONTENT(device->flags);
-
-	configuration = &names[0];
-	rc = net_get_device_conf_req(eth_globals.net_sess, device->device_id,
-	    &configuration, count, &data);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device);
-		return rc;
-	}
-
-	if (configuration) {
-		if (!str_lcmp((char *) configuration[0].value, "DIX",
-		    configuration[0].length)) {
-			device->flags |= ETH_DIX;
-		} else if(!str_lcmp((char *) configuration[0].value, "8023_2_LSAP",
-		    configuration[0].length)) {
-			device->flags |= ETH_8023_2_LSAP;
-		} else {
-			device->flags |= ETH_8023_2_SNAP;
-		}
-		
-		if (configuration[1].value &&
-		    (configuration[1].value[0] == 'y')) {
-			device->flags |= ETH_DUMMY;
-		}
-		net_free_settings(configuration, data);
-	} else {
-		device->flags |= ETH_8023_2_SNAP;
-	}
-	
-	/* Bind the device driver */
-	device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
-	    IPC_FLAG_BLOCKING);
-	if (device->sess == NULL) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device);
-		return ENOENT;
-	}
-	
-	rc = nic_callback_create(device->sess, eth_nic_cb_connection, device);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		async_hangup(device->sess);
-		free(device);
-		return EIO;
-	}
-	
-	/* Get hardware address */
-	rc = nic_get_address(device->sess, &device->addr);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device);
-		return rc;
-	}
-	
-	/* Add to the cache */
-	index = eth_devices_add(&eth_globals.devices, device->device_id,
-	    device);
-	if (index < 0) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device);
-		return index;
-	}
-	
-	printf("%s: Device registered (id: %d, sid: %zu: mtu: %zu, "
-	    "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
-	    device->device_id, device->sid, device->mtu,
-	    ARGSMAC(device->addr.address), device->flags);
-
-	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-	return EOK;
-}
-
-/** Processes the received packet and chooses the target registered module.
- *
- * @param[in] flags	The device flags.
- * @param[in] packet	The packet.
- * @return		The target registered module.
- * @return		NULL if the packet is not long enough.
- * @return		NULL if the packet is too long.
- * @return		NULL if the raw ethernet protocol is used.
- * @return		NULL if the dummy device FCS checksum is invalid.
- * @return		NULL if the packet address length is not big enough.
- */
-static eth_proto_t *eth_process_packet(int flags, packet_t *packet)
-{
-	eth_header_snap_t *header;
-	size_t length;
-	eth_type_t type;
-	size_t prefix;
-	size_t suffix;
-	eth_fcs_t *fcs;
-	uint8_t *data;
-	int rc;
-
-	length = packet_get_data_length(packet);
-	
-	if (IS_DUMMY(flags))
-		packet_trim(packet, sizeof(eth_preamble_t), 0);
-	if (length < sizeof(eth_header_t) + ETH_MIN_CONTENT +
-	    (IS_DUMMY(flags) ? ETH_SUFFIX : 0))
-		return NULL;
-	
-	data = packet_get_data(packet);
-	header = (eth_header_snap_t *) data;
-	type = ntohs(header->header.ethertype);
-	
-	if (type >= ETH_MIN_PROTO) {
-		/* DIX Ethernet */
-		prefix = sizeof(eth_header_t);
-		suffix = 0;
-		fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
-		length -= sizeof(eth_fcs_t);
-	} else if (type <= ETH_MAX_CONTENT) {
-		/* Translate "LSAP" values */
-		if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
-		    (header->lsap.ssap == ETH_LSAP_GLSAP)) {
-			/* Raw packet -- discard */
-			return NULL;
-		} else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
-		    (header->lsap.ssap == ETH_LSAP_SNAP)) {
-			/*
-			 * IEEE 802.3 + 802.2 + LSAP + SNAP
-			 * organization code not supported
-			 */
-			type = ntohs(header->snap.ethertype);
-			prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
-			    sizeof(eth_header_snap_t);
-		} else {
-			/* IEEE 802.3 + 802.2 LSAP */
-			type = lsap_map(header->lsap.dsap);
-			prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
-		}
-
-		suffix = (type < ETH_MIN_CONTENT) ? ETH_MIN_CONTENT - type : 0U;
-		fcs = (eth_fcs_t *) data + prefix + type + suffix;
-		suffix += length - prefix - type;
-		length = prefix + type + suffix;
-	} else {
-		/* Invalid length/type, should not occur */
-		return NULL;
-	}
-	
-	if (IS_DUMMY(flags)) {
-		if (~compute_crc32(~0U, data, length * 8) != ntohl(*fcs))
-			return NULL;
-		suffix += sizeof(eth_fcs_t);
-	}
-	
-	rc = packet_set_addr(packet, header->header.source_address,
-	    header->header.destination_address, ETH_ADDR);
-	if (rc != EOK)
-		return NULL;
-
-	rc = packet_trim(packet, prefix, suffix);
-	if (rc != EOK)
-		return NULL;
-	
-	return eth_protos_find(&eth_globals.protos, type);
-}
-
-int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
-{
-	eth_proto_t *proto;
-	packet_t *next;
-	eth_device_t *device;
-	int flags;
-
-	fibril_rwlock_read_lock(&eth_globals.devices_lock);
-	device = eth_devices_find(&eth_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-		return ENOENT;
-	}
-
-	flags = device->flags;
-	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	fibril_rwlock_read_lock(&eth_globals.protos_lock);
-	
-	do {
-		next = pq_detach(packet);
-		proto = eth_process_packet(flags, packet);
-		if (proto) {
-			il_received_msg(proto->sess, device_id, packet,
-			    proto->service);
-		} else {
-			/* Drop invalid/unknown */
-			pq_release_remote(eth_globals.net_sess,
-			    packet_get_id(packet));
-		}
-		packet = next;
-	} while (packet);
-
-	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-	return EOK;
-}
-
-/** Returns the device packet dimensions for sending.
- *
- * @param[in] device_id	The device identifier.
- * @param[out] addr_len	The minimum reserved address length.
- * @param[out] prefix	The minimum reserved prefix size.
- * @param[out] content	The maximum content size.
- * @param[out] suffix	The minimum reserved suffix size.
- * @return		EOK on success.
- * @return		EBADMEM if either one of the parameters is NULL.
- * @return		ENOENT if there is no such device.
- */
-static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len,
-    size_t *prefix, size_t *content, size_t *suffix)
-{
-	eth_device_t *device;
-
-	if (!addr_len || !prefix || !content || !suffix)
-		return EBADMEM;
-	
-	fibril_rwlock_read_lock(&eth_globals.devices_lock);
-	device = eth_devices_find(&eth_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-		return ENOENT;
-	}
-
-	*content = device->mtu;
-	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	
-	*addr_len = ETH_ADDR;
-	*prefix = ETH_PREFIX;
-	*suffix = ETH_MIN_CONTENT + ETH_SUFFIX;
-
-	return EOK;
-}
-
-/** Send the device hardware address.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] type	Type of the desired address.
- * @return		EOK on success.
- * @return		EBADMEM if the address parameter is NULL.
- * @return		ENOENT if there no such device.
- */
-static int eth_addr_message(nic_device_id_t device_id, eth_addr_type_t type)
-{
-	eth_device_t *device = NULL;
-	uint8_t *address;
-	size_t max_len;
-	ipc_callid_t callid;
-	
-	if (type == ETH_BROADCAST_ADDR)
-		address = eth_globals.broadcast_addr;
-	else {
-		fibril_rwlock_read_lock(&eth_globals.devices_lock);
-		device = eth_devices_find(&eth_globals.devices, device_id);
-		if (!device) {
-			fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-			return ENOENT;
-		}
-		
-		address = (uint8_t *) &device->addr.address;
-	}
-	
-	int rc = EOK;
-	if (!async_data_read_receive(&callid, &max_len)) {
-		rc = EREFUSED;
-		goto end;
-	}
-	
-	if (max_len < ETH_ADDR) {
-		async_data_read_finalize(callid, NULL, 0);
-		rc = ELIMIT;
-		goto end;
-	}
-	
-	rc = async_data_read_finalize(callid, address, ETH_ADDR);
-	if (rc != EOK)
-		goto end;
-	
-end:
-	
-	if (type == ETH_LOCAL_ADDR)
-		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	
-	return rc;
-}
-
-/** Register receiving module service.
- *
- * Pass received packets for this service.
- *
- * @param[in] service Module service.
- * @param[in] sess    Service session.
- *
- * @return EOK on success.
- * @return ENOENT if the service is not known.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int eth_register_message(services_t service, async_sess_t *sess)
-{
-	eth_proto_t *proto;
-	int protocol;
-	int index;
-
-	protocol = protocol_map(SERVICE_ETHERNET, service);
-	if (!protocol)
-		return ENOENT;
-
-	fibril_rwlock_write_lock(&eth_globals.protos_lock);
-	proto = eth_protos_find(&eth_globals.protos, protocol);
-	if (proto) {
-		proto->sess = sess;
-		fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-		return EOK;
-	} else {
-		proto = (eth_proto_t *) malloc(sizeof(eth_proto_t));
-		if (!proto) {
-			fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-			return ENOMEM;
-		}
-
-		proto->service = service;
-		proto->protocol = protocol;
-		proto->sess = sess;
-
-		index = eth_protos_add(&eth_globals.protos, protocol, proto);
-		if (index < 0) {
-			fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-			free(proto);
-			return index;
-		}
-	}
-	
-	printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
-	    NAME, proto->protocol, proto->service);
-	
-	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-	return EOK;
-}
-
-/** Prepares the packet for sending.
- *
- * @param[in] flags	The device flags.
- * @param[in] packet	The packet.
- * @param[in] src_addr	The source hardware address.
- * @param[in] ethertype	The ethernet protocol type.
- * @param[in] mtu	The device maximum transmission unit.
- * @return		EOK on success.
- * @return		EINVAL if the packet addresses length is not long
- *			enough.
- * @return		EINVAL if the packet is bigger than the device MTU.
- * @return		ENOMEM if there is not enough memory in the packet.
- */
-static int
-eth_prepare_packet(int flags, packet_t *packet, uint8_t *src_addr, int ethertype,
-    size_t mtu)
-{
-	eth_header_snap_t *header;
-	eth_header_lsap_t *header_lsap;
-	eth_header_t *header_dix;
-	eth_fcs_t *fcs;
-	uint8_t *src;
-	uint8_t *dest;
-	size_t length;
-	int i;
-	void *padding;
-	eth_preamble_t *preamble;
-
-	i = packet_get_addr(packet, &src, &dest);
-	if (i < 0)
-		return i;
-	
-	if (i != ETH_ADDR)
-		return EINVAL;
-	
-	for (i = 0; i < ETH_ADDR; i++) {
-		if (src[i]) {
-			src_addr = src;
-			break;
-		}
-	}
-
-	length = packet_get_data_length(packet);
-	if (length > mtu)
-		return EINVAL;
-	
-	if (length < ETH_MIN_TAGGED_CONTENT(flags)) {
-		padding = packet_suffix(packet,
-		    ETH_MIN_TAGGED_CONTENT(flags) - length);
-		if (!padding)
-			return ENOMEM;
-
-		bzero(padding, ETH_MIN_TAGGED_CONTENT(flags) - length);
-	}
-	
-	if (IS_DIX(flags)) {
-		header_dix = PACKET_PREFIX(packet, eth_header_t);
-		if (!header_dix)
-			return ENOMEM;
-		
-		header_dix->ethertype = (uint16_t) ethertype;
-		memcpy(header_dix->source_address, src_addr, ETH_ADDR);
-		memcpy(header_dix->destination_address, dest, ETH_ADDR);
-		src = &header_dix->destination_address[0];
-	} else if (IS_8023_2_LSAP(flags)) {
-		header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
-		if (!header_lsap)
-			return ENOMEM;
-		
-		header_lsap->header.ethertype = htons(length +
-		    sizeof(eth_header_lsap_t));
-		header_lsap->lsap.dsap = lsap_unmap(ntohs(ethertype));
-		header_lsap->lsap.ssap = header_lsap->lsap.dsap;
-		header_lsap->lsap.ctrl = IEEE_8023_2_UI;
-		memcpy(header_lsap->header.source_address, src_addr, ETH_ADDR);
-		memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
-		src = &header_lsap->header.destination_address[0];
-	} else if (IS_8023_2_SNAP(flags)) {
-		header = PACKET_PREFIX(packet, eth_header_snap_t);
-		if (!header)
-			return ENOMEM;
-		
-		header->header.ethertype = htons(length +
-		    sizeof(eth_header_lsap_t) + sizeof(eth_header_snap_t));
-		header->lsap.dsap = (uint16_t) ETH_LSAP_SNAP;
-		header->lsap.ssap = header->lsap.dsap;
-		header->lsap.ctrl = IEEE_8023_2_UI;
-		
-		for (i = 0; i < 3; i++)
-			header->snap.protocol[i] = 0;
-		
-		header->snap.ethertype = (uint16_t) ethertype;
-		memcpy(header->header.source_address, src_addr, ETH_ADDR);
-		memcpy(header->header.destination_address, dest, ETH_ADDR);
-		src = &header->header.destination_address[0];
-	}
-	
-	if (IS_DUMMY(flags)) {
-		preamble = PACKET_PREFIX(packet, eth_preamble_t);
-		if (!preamble)
-			return ENOMEM;
-		
-		for (i = 0; i < 7; i++)
-			preamble->preamble[i] = ETH_PREAMBLE;
-		
-		preamble->sfd = ETH_SFD;
-		
-		fcs = PACKET_SUFFIX(packet, eth_fcs_t);
-		if (!fcs)
-			return ENOMEM;
-
-		*fcs = htonl(~compute_crc32(~0U, src, length * 8));
-	}
-	
-	return EOK;
-}
-
-/** Sends the packet queue.
- *
- * Sends only packet successfully processed by the eth_prepare_packet()
- * function.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The packet queue.
- * @param[in] sender	The sending module service.
- * @return		EOK on success.
- * @return		ENOENT if there no such device.
- * @return		EINVAL if the service parameter is not known.
- */
-static int eth_send_message(nic_device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	eth_device_t *device;
-	packet_t *next;
-	packet_t *tmp;
-	int ethertype;
-	int rc;
-
-	ethertype = htons(protocol_map(SERVICE_ETHERNET, sender));
-	if (!ethertype) {
-		pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-	
-	fibril_rwlock_read_lock(&eth_globals.devices_lock);
-	device = eth_devices_find(&eth_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-		return ENOENT;
-	}
-	
-	/* Process packet queue */
-	next = packet;
-	do {
-		rc = eth_prepare_packet(device->flags, next,
-		    (uint8_t *) &device->addr.address, ethertype, device->mtu);
-		if (rc != EOK) {
-			/* Release invalid packet */
-			tmp = pq_detach(next);
-			if (next == packet)
-				packet = tmp;
-			pq_release_remote(eth_globals.net_sess,
-			    packet_get_id(next));
-			next = tmp;
-		} else {
-			nic_send_frame(device->sess, packet_get_data(next),
-			    packet_get_data_length(next));
-			next = pq_next(next);
-		}
-	} while (next);
-	
-	pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
-	
-	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	return EOK;
-}
-
-static int eth_received(eth_device_t *device)
-{
-	void *data;
-	size_t size;
-	int rc;
-	
-	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
-	if (rc != EOK) {
-		printf("%s: data_write_accept() failed\n", NAME);
-		return rc;
-	}
-	
-	packet_t *packet = packet_get_1_remote(eth_globals.net_sess, size);
-	if (packet == NULL)
-		return ENOMEM;
-	
-	void *pdata = packet_suffix(packet, size);
-	memcpy(pdata, data, size);
-	free(data);
-	
-	return nil_received_msg_local(device->device_id, packet);
-}
-
-static int eth_addr_changed(eth_device_t *device)
-{
-	nic_address_t address;
-	size_t length;
-	ipc_callid_t data_callid;
-	if (!async_data_write_receive(&data_callid, &length)) {
-		async_answer_0(data_callid, EINVAL);
-		return EINVAL;
-	}
-	if (length > sizeof (nic_address_t)) {
-		async_answer_0(data_callid, ELIMIT);
-		return ELIMIT;
-	}
-	if (async_data_write_finalize(data_callid, &address, length) != EOK) {
-		return EINVAL;
-	}
-
-	fibril_rwlock_write_lock(&eth_globals.devices_lock);
-
-	printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
-		device->device_id, ARGSMAC(device->addr.address),
-		ARGSMAC(address.address));
-	memcpy(&device->addr, &address, sizeof (nic_address_t));
-	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-
-	/* Notify all upper layer modules */
-	fibril_rwlock_read_lock(&eth_globals.protos_lock);
-	int index;
-	for (index = 0; index < eth_protos_count(&eth_globals.protos); index++) {
-		eth_proto_t *proto = eth_protos_get_index(&eth_globals.protos, index);
-		if (proto->sess != NULL) {
-			il_addr_changed_msg(proto->sess, device->device_id,
-					ETH_ADDR, address.address);
-		}
-	}
-
-	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-	return EOK;
-}
-
-int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	packet_t *packet;
-	size_t addrlen;
-	size_t prefix;
-	size_t suffix;
-	size_t content;
-	int rc;
-	
-	*answer_count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return eth_register_message(NIL_GET_PROTO(*call), callback);
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_NIL_DEVICE:
-		return eth_device_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
-	case NET_NIL_SEND:
-		rc = packet_translate_remote(eth_globals.net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return eth_send_message(IPC_GET_DEVICE(*call), packet,
-		    IPC_GET_SERVICE(*call));
-	case NET_NIL_PACKET_SPACE:
-		rc = eth_packet_space_message(IPC_GET_DEVICE(*call), &addrlen,
-		    &prefix, &content, &suffix);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, addrlen);
-		IPC_SET_PREFIX(*answer, prefix);
-		IPC_SET_CONTENT(*answer, content);
-		IPC_SET_SUFFIX(*answer, suffix);
-		*answer_count = 4;
-		
-		return EOK;
-	case NET_NIL_ADDR:
-		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, ETH_ADDR);
-		*answer_count = 1;
-		
-		return EOK;
-	case NET_NIL_BROADCAST_ADDR:
-		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, ETH_ADDR);
-		*answer_count = 1;
-		
-		return EOK;
-	}
-	
-	return ENOTSUP;
-}
-
-static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	eth_device_t *device = (eth_device_t *)arg;
-	int rc;
-	
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NIC_EV_DEVICE_STATE:
-			rc = eth_device_state(device, IPC_GET_ARG1(call));
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_RECEIVED:
-			rc = eth_received(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_ADDR_CHANGED:
-			rc = eth_addr_changed(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-		}
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return nil_module_start(SERVICE_ETHERNET);
-}
-
-/** @}
- */
Index: pace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,277 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * 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 eth
- *  @{
- */
-
-/** @file
- * Ethernet module.
- */
-
-#ifndef NET_ETH_H_
-#define NET_ETH_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/loc.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <adt/measured_strings.h>
-
-/** Ethernet address length. */
-#define ETH_ADDR  6
-
-/** Ethernet header preamble value. */
-#define ETH_PREAMBLE  0x55
-
-/** Ethernet header start of frame value. */
-#define ETH_SFD  0xD5
-
-/** IEEE 802.2 unordered information control field. */
-#define IEEE_8023_2_UI  0x03
-
-/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
- * @see eth_header_snap
- */
-typedef struct eth_header_snap eth_header_snap_t;
-
-/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
- * @see eth_header_lsap
- */
-typedef struct eth_header_lsap eth_header_lsap_t;
-
-/** Type definition of the Ethernet header LSAP extension.
- * @see eth_ieee_lsap
- */
-typedef struct eth_ieee_lsap eth_ieee_lsap_t;
-
-/** Type definition of the Ethernet header SNAP extension.
- * @see eth_snap
- */
-typedef struct eth_snap eth_snap_t;
-
-/** Type definition of the Ethernet header preamble.
- * @see preamble
- */
-typedef struct eth_preamble eth_preamble_t;
-
-/** Type definition of the Ethernet header.
- * @see eth_header
- */
-typedef struct eth_header eth_header_t;
-
-/** Ethernet header Link Service Access Point extension. */
-struct eth_ieee_lsap {
-	/**
-	 * Destination Service Access Point identifier.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t dsap;
-	
-	/**
-	 * Source Service Access Point identifier.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t ssap;
-	
-	/**
-	 * Control parameter.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t ctrl;
-} __attribute__ ((packed));
-
-/** Ethernet header SNAP extension. */
-struct eth_snap {
-	/** Protocol identifier or organization code. */
-	uint8_t protocol[3];
-	
-	/**
-	 * Ethernet protocol identifier in the network byte order (big endian).
-	 * @see ethernet_protocols.h
-	 */
-	uint16_t ethertype;
-} __attribute__ ((packed));
-
-/** Ethernet header preamble.
- *
- * Used for dummy devices.
- */
-struct eth_preamble {
-	/**
-	 * Controlling preamble used for the frame transmission synchronization.
-	 * All should be set to ETH_PREAMBLE.
-	 */
-	uint8_t preamble[7];
-	
-	/**
-	 * Start of Frame Delimiter used for the frame transmission
-	 * synchronization.
-	 * Should be set to ETH_SFD.
-	 */
-	uint8_t sfd;
-} __attribute__ ((packed));
-
-/** Ethernet header. */
-struct eth_header {
-	/** Destination host Ethernet address (MAC address). */
-	uint8_t destination_address[ETH_ADDR];
-	/** Source host Ethernet address (MAC address). */
-	uint8_t source_address[ETH_ADDR];
-	
-	/**
-	 * Ethernet protocol identifier in the network byte order (big endian).
-	 * @see ethernet_protocols.h
-	 */
-	uint16_t ethertype;
-} __attribute__ ((packed));
-
-/** Ethernet header IEEE 802.3 + 802.2 extension. */
-struct eth_header_lsap {
-	/** Ethernet header. */
-	eth_header_t header;
-	
-	/**
-	 * LSAP extension.
-	 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
-	 * used.
-	 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
-	 * without any extensions is being used and the frame content starts
-	 * rigth after the two fields.
-	 */
-	eth_ieee_lsap_t lsap;
-} __attribute__ ((packed));
-
-/** Ethernet header IEEE 802.3 + 802.2 + SNAP extensions. */
-struct eth_header_snap {
-	/** Ethernet header. */
-	eth_header_t header;
-	
-	/**
-	 * LSAP extension.
-	 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
-	 * used.
-	 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
-	 * without any extensions is being used and the frame content starts
-	 * rigth after the two fields.
-	 */
-	eth_ieee_lsap_t lsap;
-	
-	/** SNAP extension. */
-	eth_snap_t snap;
-} __attribute__ ((packed));
-
-/** Ethernet Frame Check Sequence. */
-typedef uint32_t eth_fcs_t;
-
-/** Type definition of the Ethernet global data.
- * @see eth_globals
- */
-typedef struct eth_globals eth_globals_t;
-
-/** Type definition of the Ethernet device specific data.
- * @see eth_device
- */
-typedef struct eth_device eth_device_t;
-
-/** Type definition of the Ethernet protocol specific data.
- * @see eth_proto
- */
-typedef struct eth_proto eth_proto_t;
-
-/** Ethernet device map.
- * Maps devices to the Ethernet device specific data.
- * @see device.h
- */
-DEVICE_MAP_DECLARE(eth_devices, eth_device_t);
-
-/** Ethernet protocol map.
- * Maps protocol identifiers to the Ethernet protocol specific data.
- * @see int_map.h
- */
-INT_MAP_DECLARE(eth_protos, eth_proto_t);
-
-/** Ethernet device specific data. */
-struct eth_device {
-	/** Device identifier. */
-	nic_device_id_t device_id;
-	/** Device handle */
-	service_id_t sid;
-	/** Driver session. */
-	async_sess_t *sess;
-	/** Maximal transmission unit. */
-	size_t mtu;
-	
-	/**
-	 * Various device flags.
-	 * @see ETH_DUMMY
-	 * @see ETH_MODE_MASK
-	 */
-	int flags;
-	
-	/** Actual device hardware address. */
-	nic_address_t addr;
-};
-
-/** Ethernet protocol specific data. */
-struct eth_proto {
-	/** Protocol service. */
-	services_t service;
-	/** Protocol identifier. */
-	int protocol;
-	/** Protocol module session. */
-	async_sess_t *sess;
-};
-
-/** Ethernet global data. */
-struct eth_globals {
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	/** Safety lock for devices. */
-	fibril_rwlock_t devices_lock;
-	/** All known Ethernet devices. */
-	eth_devices_t devices;
-	/** Safety lock for protocols. */
-	fibril_rwlock_t protos_lock;
-	
-	/**
-	 * Protocol map.
-	 * Service map for each protocol.
-	 */
-	eth_protos_t protos;
-	
-	/** Broadcast device hardware address. */
-	uint8_t broadcast_addr[ETH_ADDR];
-};
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/nil/nildummy/Makefile
===================================================================
--- uspace/srv/net/nil/nildummy/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,46 +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 = ../../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = nildummy
-
-SOURCES = \
-	nildummy.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,506 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * 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 nildummy
- * @{
- */
-
-/** @file
- * Dummy network interface layer module implementation.
- * @see nildummy.h
- */
-
-#include <assert.h>
-#include <async.h>
-#include <malloc.h>
-#include <mem.h>
-#include <stdio.h>
-#include <str.h>
-#include <ipc/nil.h>
-#include <ipc/net.h>
-#include <ipc/services.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <il_remote.h>
-#include <adt/measured_strings.h>
-#include <net/packet.h>
-#include <packet_remote.h>
-#include <packet_client.h>
-#include <device/nic.h>
-#include <loc.h>
-#include <nil_skel.h>
-#include "nildummy.h"
-
-/** The module name. */
-#define NAME  "nildummy"
-
-/** Default maximum transmission unit. */
-#define NET_DEFAULT_MTU  1500
-
-/** Network interface layer module global data. */
-nildummy_globals_t nildummy_globals;
-
-DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
-
-static void nildummy_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg);
-
-static int nildummy_device_state(nildummy_device_t *device, sysarg_t state)
-{
-	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-	if (nildummy_globals.proto.sess)
-		il_device_state_msg(nildummy_globals.proto.sess,
-		    device->device_id, state, nildummy_globals.proto.service);
-	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
-	
-	return EOK;
-}
-
-static int nildummy_addr_changed(nildummy_device_t *device)
-{
-	return ENOTSUP;
-}
-
-int nil_initialize(async_sess_t *sess)
-{
-	fibril_rwlock_initialize(&nildummy_globals.devices_lock);
-	fibril_rwlock_initialize(&nildummy_globals.protos_lock);
-	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
-	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
-	
-	nildummy_globals.net_sess = sess;
-	nildummy_globals.proto.sess = NULL;
-	int rc = nildummy_devices_initialize(&nildummy_globals.devices);
-	
-	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
-	fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-	
-	return rc;
-}
-
-/** Register new device or updates the MTU of an existing one.
- *
- * Determine the device local hardware address.
- *
- * @param[in] device_id New device identifier.
- * @param[in] service   Device driver service.
- * @param[in] mtu       Device maximum transmission unit.
- *
- * @return EOK on success.
- * @return EEXIST if the device with the different service exists.
- * @return ENOMEM if there is not enough memory left.
- * @return Other error codes as defined for the
- *         netif_bind_service() function.
- * @return Other error codes as defined for the
- *         netif_get_addr_req() function.
- *
- */
-static int nildummy_device_message(nic_device_id_t device_id,
-    service_id_t sid, size_t mtu)
-{
-	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
-	
-	/* An existing device? */
-	nildummy_device_t *device =
-	    nildummy_devices_find(&nildummy_globals.devices, device_id);
-	if (device) {
-		if (device->sid != sid) {
-			printf("Device %d exists, handles do not match\n",
-			    device->device_id);
-			fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-			return EEXIST;
-		}
-		
-		/* Update MTU */
-		if (mtu > 0)
-			device->mtu = mtu;
-		else
-			device->mtu = NET_DEFAULT_MTU;
-		
-		printf("Device %d already exists (mtu: %zu)\n", device->device_id,
-		    device->mtu);
-		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		
-		/* Notify the upper layer module */
-		fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-		if (nildummy_globals.proto.sess) {
-			il_mtu_changed_msg(nildummy_globals.proto.sess,
-			    device->device_id, device->mtu,
-			    nildummy_globals.proto.service);
-		}
-		fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
-		
-		return EOK;
-	}
-	
-	/* Create a new device */
-	device = (nildummy_device_t *) malloc(sizeof(nildummy_device_t));
-	if (!device)
-		return ENOMEM;
-	
-	device->device_id = device_id;
-	device->sid = sid;
-	if (mtu > 0)
-		device->mtu = mtu;
-	else
-		device->mtu = NET_DEFAULT_MTU;
-	
-	/* Bind the device driver */
-	device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
-	    IPC_FLAG_BLOCKING);
-	if (device->sess == NULL) {
-		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		free(device);
-		return ENOENT;
-	}
-	
-	int rc = nic_callback_create(device->sess, nildummy_nic_cb_conn,
-	    device);
-	if (rc != EOK) {
-		async_hangup(device->sess);
-		
-		return ENOENT;
-	}
-	
-	/* Get hardware address */
-	rc = nic_get_address(device->sess, &device->addr);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		free(device);
-		return rc;
-	}
-	
-	device->addr_len = ETH_ADDR;
-	
-	/* Add to the cache */
-	int index = nildummy_devices_add(&nildummy_globals.devices,
-	    device->device_id, device);
-	if (index < 0) {
-		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		free(device);
-		return index;
-	}
-	
-	printf("%s: Device registered (id: %d, mtu: %zu)\n", NAME,
-	    device->device_id, device->mtu);
-	fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-	return EOK;
-}
-
-/** Return the device hardware address.
- *
- * @param[in]  device_id Device identifier.
- * @param[out] address   Device hardware address.
- *
- * @return EOK on success.
- * @return EBADMEM if the address parameter is NULL.
- * @return ENOENT if there no such device.
- *
- */
-static int nildummy_addr_message(nic_device_id_t device_id, size_t *addrlen)
-{
-	if (!addrlen)
-		return EBADMEM;
-	
-	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	
-	nildummy_device_t *device =
-	    nildummy_devices_find(&nildummy_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return ENOENT;
-	}
-	
-	ipc_callid_t callid;
-	size_t max_len;
-	if (!async_data_read_receive(&callid, &max_len)) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return EREFUSED;
-	}
-	
-	if (max_len < device->addr_len) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		async_data_read_finalize(callid, NULL, 0);
-		return ELIMIT;
-	}
-	
-	int rc = async_data_read_finalize(callid,
-	    (uint8_t *) &device->addr.address, device->addr_len);
-	if (rc != EOK) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return rc;
-	}
-	
-	*addrlen = device->addr_len;
-	
-	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-	return EOK;
-}
-
-/** Return the device packet dimensions for sending.
- *
- * @param[in]  device_id Device identifier.
- * @param[out] addr_len  Minimum reserved address length.
- * @param[out] prefix    Minimum reserved prefix size.
- * @param[out] content   Maximum content size.
- * @param[out] suffix    Minimum reserved suffix size.
- *
- * @return EOK on success.
- * @return EBADMEM if either one of the parameters is NULL.
- * @return ENOENT if there is no such device.
- *
- */
-static int nildummy_packet_space_message(nic_device_id_t device_id,
-    size_t *addr_len, size_t *prefix, size_t *content, size_t *suffix)
-{
-	if ((!addr_len) || (!prefix) || (!content) || (!suffix))
-		return EBADMEM;
-	
-	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	
-	nildummy_device_t *device =
-	    nildummy_devices_find(&nildummy_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return ENOENT;
-	}
-	
-	*content = device->mtu;
-	
-	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-	
-	*addr_len = 0;
-	*prefix = 0;
-	*suffix = 0;
-	return EOK;
-}
-
-int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
-{
-	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-	
-	if (nildummy_globals.proto.sess) {
-		do {
-			packet_t *next = pq_detach(packet);
-			il_received_msg(nildummy_globals.proto.sess, device_id,
-			    packet, nildummy_globals.proto.service);
-			packet = next;
-		} while (packet);
-	}
-	
-	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
-	
-	return EOK;
-}
-
-/** Register receiving module service.
- *
- * Pass received packets for this service.
- *
- * @param[in] service Module service.
- * @param[in] sess    Service session.
- *
- * @return EOK on success.
- * @return ENOENT if the service is not known.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int nildummy_register_message(services_t service, async_sess_t *sess)
-{
-	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
-	nildummy_globals.proto.service = service;
-	nildummy_globals.proto.sess = sess;
-	
-	printf("%s: Protocol registered (service: %#x)\n",
-	    NAME, nildummy_globals.proto.service);
-	
-	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
-	return EOK;
-}
-
-/** Send the packet queue.
- *
- * @param[in] device_id Device identifier.
- * @param[in] packet    Packet queue.
- * @param[in] sender    Sending module service.
- *
- * @return EOK on success.
- * @return ENOENT if there no such device.
- * @return EINVAL if the service parameter is not known.
- *
- */
-static int nildummy_send_message(nic_device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	
-	nildummy_device_t *device =
-	    nildummy_devices_find(&nildummy_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return ENOENT;
-	}
-	
-	packet_t *p = packet;
-	do {
-		nic_send_frame(device->sess, packet_get_data(p),
-		    packet_get_data_length(p));
-		p = pq_next(p);
-	} while (p != NULL);
-	
-	pq_release_remote(nildummy_globals.net_sess, packet_get_id(packet));
-	
-	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-	
-	return EOK;
-}
-
-static int nildummy_received(nildummy_device_t *device)
-{
-	void *data;
-	size_t size;
-	int rc;
-
-	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
-	if (rc != EOK)
-		return rc;
-
-	packet_t *packet = packet_get_1_remote(nildummy_globals.net_sess, size);
-	if (packet == NULL)
-		return ENOMEM;
-
-	void *pdata = packet_suffix(packet, size);
-	memcpy(pdata, data, size);
-	free(pdata);
-
-	return nil_received_msg_local(device->device_id, packet);
-}
-
-int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	packet_t *packet;
-	size_t addrlen;
-	size_t prefix;
-	size_t suffix;
-	size_t content;
-	int rc;
-	
-	*answer_count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return nildummy_register_message(NIL_GET_PROTO(*call), callback);
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_NIL_DEVICE:
-		return nildummy_device_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
-	
-	case NET_NIL_SEND:
-		rc = packet_translate_remote(nildummy_globals.net_sess,
-		    &packet, IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		return nildummy_send_message(IPC_GET_DEVICE(*call), packet,
-		    IPC_GET_SERVICE(*call));
-	
-	case NET_NIL_PACKET_SPACE:
-		rc = nildummy_packet_space_message(IPC_GET_DEVICE(*call),
-		    &addrlen, &prefix, &content, &suffix);
-		if (rc != EOK)
-			return rc;
-		IPC_SET_ADDR(*answer, addrlen);
-		IPC_SET_PREFIX(*answer, prefix);
-		IPC_SET_CONTENT(*answer, content);
-		IPC_SET_SUFFIX(*answer, suffix);
-		*answer_count = 4;
-		return EOK;
-	
-	case NET_NIL_ADDR:
-	case NET_NIL_BROADCAST_ADDR:
-		rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &addrlen);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, addrlen);
-		*answer_count = 1;
-		return rc;
-	}
-	
-	return ENOTSUP;
-}
-
-static void nildummy_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	nildummy_device_t *device = (nildummy_device_t *)arg;
-	int rc;
-	
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NIC_EV_DEVICE_STATE:
-			rc = nildummy_device_state(device, IPC_GET_ARG1(call));
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_RECEIVED:
-			rc = nildummy_received(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_ADDR_CHANGED:
-			rc = nildummy_addr_changed(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-		}
-	}
-}
-
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return nil_module_start(SERVICE_NILDUMMY);
-}
-
-/** @}
- */
Index: pace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,124 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * 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 nildummy
- * @{
- */
-
-/** @file
- * Dummy network interface layer module.
- */
-
-#ifndef NET_NILDUMMY_H_
-#define NET_NILDUMMY_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/loc.h>
-#include <ipc/services.h>
-#include <net/device.h>
-
-/** Type definition of the dummy nil global data.
- *
- * @see nildummy_globals
- *
- */
-typedef struct nildummy_globals nildummy_globals_t;
-
-/** Type definition of the dummy nil device specific data.
- *
- * @see nildummy_device
- *
- */
-typedef struct nildummy_device nildummy_device_t;
-
-/** Type definition of the dummy nil protocol specific data.
- *
- * @see nildummy_proto
- *
- */
-typedef struct nildummy_proto nildummy_proto_t;
-
-/** Dummy nil device map.
- *
- * Map devices to the dummy nil device specific data.
- * @see device.h
- *
- */
-DEVICE_MAP_DECLARE(nildummy_devices, nildummy_device_t);
-
-/** Dummy nil device specific data. */
-struct nildummy_device {
-	/** Device identifier. */
-	nic_device_id_t device_id;
-	/** Device service ID. */
-	service_id_t sid;
-	/** Driver session. */
-	async_sess_t *sess;
-	
-	/** Maximal transmission unit. */
-	size_t mtu;
-	
-	/** Actual device hardware address. */
-	nic_address_t addr;
-	/** Actual device hardware address length. */
-	size_t addr_len;
-};
-
-/** Dummy nil protocol specific data. */
-struct nildummy_proto {
-	/** Protocol service. */
-	services_t service;
-	
-	/** Protocol module session. */
-	async_sess_t *sess;
-};
-
-/** Dummy nil global data. */
-struct nildummy_globals {
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	
-	/** Lock for devices. */
-	fibril_rwlock_t devices_lock;
-	
-	/** All known Ethernet devices. */
-	nildummy_devices_t devices;
-	
-	/** Safety lock for protocols. */
-	fibril_rwlock_t protos_lock;
-	
-	/** Default protocol. */
-	nildummy_proto_t proto;
-};
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/tcp/Makefile
===================================================================
--- uspace/srv/net/tcp/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,48 @@
+#
+# 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 = $(LIBNET_PREFIX)/libnet.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+BINARY = tcp
+
+SOURCES = \
+	conn.c \
+	iqueue.c \
+	ncsim.c \
+	pdu.c \
+	rqueue.c \
+	segment.c \
+	seq_no.c \
+	sock.c \
+	tcp.c \
+	test.c \
+	tqueue.c \
+	ucall.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/tcp/conn.c
===================================================================
--- uspace/srv/net/tcp/conn.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/conn.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,1278 @@
+/*
+ * 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 TCP connection processing and state machine
+ */
+
+#include <adt/list.h>
+#include <bool.h>
+#include <errno.h>
+#include <io/log.h>
+#include <macros.h>
+#include <stdlib.h>
+#include "conn.h"
+#include "iqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+#include "tqueue.h"
+#include "ucall.h"
+
+#define RCV_BUF_SIZE 4096/*2*/
+#define SND_BUF_SIZE 4096
+
+#define MAX_SEGMENT_LIFETIME	(15*1000*1000) //(2*60*1000*1000)
+#define TIME_WAIT_TIMEOUT	(2*MAX_SEGMENT_LIFETIME)
+
+LIST_INITIALIZE(conn_list);
+FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
+
+static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
+static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
+static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
+
+/** Create new connection structure.
+ *
+ * @param lsock		Local socket (will be deeply copied)
+ * @param fsock		Foreign socket (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 *conn = NULL;
+	bool tqueue_inited = false;
+
+	/* Allocate connection structure */
+	conn = calloc(1, sizeof(tcp_conn_t));
+	if (conn == NULL)
+		goto error;
+
+	conn->tw_timer = fibril_timer_create();
+	if (conn->tw_timer == NULL)
+		goto error;
+
+	fibril_mutex_initialize(&conn->lock);
+
+	/* One for the user, one for not being in closed state */
+	atomic_set(&conn->refcnt, 2);
+
+	/* Allocate receive buffer */
+	fibril_condvar_initialize(&conn->rcv_buf_cv);
+	conn->rcv_buf_size = RCV_BUF_SIZE;
+	conn->rcv_buf_used = 0;
+	conn->rcv_buf_fin = false;
+
+	conn->rcv_buf = calloc(1, conn->rcv_buf_size);
+	if (conn->rcv_buf == NULL)
+		goto error;
+
+	/** Allocate send buffer */
+	fibril_condvar_initialize(&conn->snd_buf_cv);
+	conn->snd_buf_size = SND_BUF_SIZE;
+	conn->snd_buf_used = 0;
+	conn->snd_buf_fin = false;
+	conn->snd_buf = calloc(1, conn->snd_buf_size);
+	if (conn->snd_buf == NULL)
+		goto error;
+
+	/* Set up receive window. */
+	conn->rcv_wnd = conn->rcv_buf_size;
+
+	/* Initialize incoming segment queue */
+	tcp_iqueue_init(&conn->incoming, conn);
+
+	/* Initialize retransmission queue */
+	if (tcp_tqueue_init(&conn->retransmit, conn) != EOK)
+		goto error;
+
+	tqueue_inited = true;
+
+	/* Connection state change signalling */
+	fibril_condvar_initialize(&conn->cstate_cv);
+
+	conn->cstate_cb = NULL;
+
+	conn->cstate = st_listen;
+	conn->reset = false;
+	conn->deleted = false;
+	conn->ap = ap_passive;
+	conn->fin_is_acked = false;
+	conn->ident.local = *lsock;
+	if (fsock != NULL)
+		conn->ident.foreign = *fsock;
+
+	return conn;
+
+error:
+	if (tqueue_inited)
+		tcp_tqueue_fini(&conn->retransmit);
+	if (conn != NULL && conn->rcv_buf != NULL)
+		free(conn->rcv_buf);
+	if (conn != NULL && conn->snd_buf != NULL)
+		free(conn->snd_buf);
+	if (conn != NULL && conn->tw_timer != NULL)
+		fibril_timer_destroy(conn->tw_timer);
+	if (conn != NULL)
+		free(conn);
+
+	return NULL;
+}
+
+/** Destroy connection structure.
+ *
+ * Connection structure should be destroyed when the folowing condtitions
+ * are met:
+ * (1) user has deleted the connection
+ * (2) the connection has entered closed state
+ * (3) nobody is holding references to the connection
+ *
+ * This happens when @a conn->refcnt is zero as we count (1) and (2)
+ * as special references.
+ *
+ * @param conn		Connection
+ */
+static void tcp_conn_free(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
+	tcp_tqueue_fini(&conn->retransmit);
+
+	if (conn->rcv_buf != NULL)
+		free(conn->rcv_buf);
+	if (conn->snd_buf != NULL)
+		free(conn->snd_buf);
+	if (conn->tw_timer != NULL)
+		fibril_timer_destroy(conn->tw_timer);
+	free(conn);
+}
+
+/** Add reference to connection.
+ *
+ * Increase connection reference count by one.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_addref(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
+	atomic_inc(&conn->refcnt);
+}
+
+/** Remove reference from connection.
+ *
+ * Decrease connection reference count by one.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_delref(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
+
+	if (atomic_predec(&conn->refcnt) == 0)
+		tcp_conn_free(conn);
+}
+
+/** Delete connection.
+ *
+ * The caller promises not make no further references to @a conn.
+ * TCP will free @a conn eventually.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_delete(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
+
+	assert(conn->deleted == false);
+	tcp_conn_delref(conn);
+}
+
+/** Enlist connection.
+ *
+ * Add connection to the connection map.
+ */
+void tcp_conn_add(tcp_conn_t *conn)
+{
+	tcp_conn_addref(conn);
+	fibril_mutex_lock(&conn_list_lock);
+	list_append(&conn->link, &conn_list);
+	fibril_mutex_unlock(&conn_list_lock);
+}
+
+/** Delist connection.
+ *
+ * Remove connection from the connection map.
+ */
+void tcp_conn_remove(tcp_conn_t *conn)
+{
+	fibril_mutex_lock(&conn_list_lock);
+	list_remove(&conn->link);
+	fibril_mutex_unlock(&conn_list_lock);
+	tcp_conn_delref(conn);
+}
+
+static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
+{
+	tcp_cstate_t old_state;
+
+	log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
+
+	old_state = conn->cstate;
+	conn->cstate = nstate;
+	fibril_condvar_broadcast(&conn->cstate_cv);
+
+	/* Run user callback function */
+	if (conn->cstate_cb != NULL) {
+		log_msg(LVL_DEBUG, "tcp_conn_state_set() - run user CB");
+		conn->cstate_cb(conn, conn->cstate_cb_arg);
+	} else {
+		log_msg(LVL_DEBUG, "tcp_conn_state_set() - no user CB");
+	}
+
+	assert(old_state != st_closed);
+	if (nstate == st_closed) {
+		/* Drop one reference for now being in closed state */
+		tcp_conn_delref(conn);
+	}
+}
+
+/** Synchronize connection.
+ *
+ * This is the first step of an active connection attempt,
+ * sends out SYN and sets up ISS and SND.xxx.
+ */
+void tcp_conn_sync(tcp_conn_t *conn)
+{
+	/* XXX select ISS */
+	conn->iss = 1;
+	conn->snd_nxt = conn->iss;
+	conn->snd_una = conn->iss;
+	conn->ap = ap_active;
+
+	tcp_tqueue_ctrl_seg(conn, CTL_SYN);
+	tcp_conn_state_set(conn, st_syn_sent);
+}
+
+/** FIN has been sent.
+ *
+ * This function should be called when FIN is sent over the connection,
+ * as a result the connection state is changed appropriately.
+ */
+void tcp_conn_fin_sent(tcp_conn_t *conn)
+{
+	switch (conn->cstate) {
+	case st_syn_received:
+	case st_established:
+		log_msg(LVL_DEBUG, "%s: FIN sent -> Fin-Wait-1", conn->name);
+		tcp_conn_state_set(conn, st_fin_wait_1);
+		break;
+	case st_close_wait:
+		log_msg(LVL_DEBUG, "%s: FIN sent -> Last-Ack", conn->name);
+		tcp_conn_state_set(conn, st_last_ack);
+		break;
+	default:
+		log_msg(LVL_ERROR, "%s: Connection state %d", conn->name,
+		    conn->cstate);
+		assert(false);
+	}
+
+	conn->fin_is_acked = false;
+}
+
+/** Match socket with pattern. */
+static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
+{
+	log_msg(LVL_DEBUG, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
+	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
+
+	if (patt->addr.ipv4 != TCP_IPV4_ANY &&
+	    patt->addr.ipv4 != sock->addr.ipv4)
+		return false;
+
+	if (patt->port != TCP_PORT_ANY &&
+	    patt->port != sock->port)
+		return false;
+
+	log_msg(LVL_DEBUG, " -> match");
+
+	return true;
+}
+
+/** Match socket pair with pattern. */
+static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
+{
+	log_msg(LVL_DEBUG, "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.
+ * The connection reference count is bumped by one.
+ *
+ * @param sp	Socket pair
+ * @return	Connection structure or NULL if not found.
+ */
+tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_find_ref(%p)", sp);
+
+	fibril_mutex_lock(&conn_list_lock);
+
+	list_foreach(conn_list, link) {
+		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
+		tcp_sockpair_t *csp = &conn->ident;
+		log_msg(LVL_DEBUG, "compare with conn (f:(%x,%u), l:(%x,%u))",
+		    csp->foreign.addr.ipv4, csp->foreign.port,
+		    csp->local.addr.ipv4, csp->local.port);
+		if (tcp_sockpair_match(sp, csp)) {
+			tcp_conn_addref(conn);
+			fibril_mutex_unlock(&conn_list_lock);
+			return conn;
+		}
+	}
+
+	fibril_mutex_unlock(&conn_list_lock);
+	return NULL;
+}
+
+/** Reset connection.
+ *
+ * @param conn	Connection
+ */
+static void tcp_conn_reset(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
+	tcp_conn_state_set(conn, st_closed);
+	conn->reset = true;
+
+	tcp_conn_tw_timer_clear(conn);
+	tcp_tqueue_clear(&conn->retransmit);
+
+	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+	fibril_condvar_broadcast(&conn->snd_buf_cv);
+}
+
+/** Signal to the user that connection has been reset.
+ *
+ * Send an out-of-band signal to the user.
+ */
+static void tcp_reset_signal(tcp_conn_t *conn)
+{
+	/* TODO */
+	log_msg(LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
+}
+
+/** Determine if SYN has been received.
+ *
+ * @param conn	Connection
+ * @return	@c true if SYN has been received, @c false otherwise.
+ */
+bool tcp_conn_got_syn(tcp_conn_t *conn)
+{
+	switch (conn->cstate) {
+	case st_listen:
+	case st_syn_sent:
+		return false;
+	case st_syn_received:
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		return true;
+	case st_closed:
+		log_msg(LVL_WARN, "state=%d", (int) conn->cstate);
+		assert(false);
+	}
+
+	assert(false);
+}
+
+/** Segment arrived in Listen state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_listen(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_sa_listen(%p, %p)", conn, seg);
+
+	if ((seg->ctrl & CTL_RST) != 0) {
+		log_msg(LVL_DEBUG, "Ignoring incoming RST.");
+		return;
+	}
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		log_msg(LVL_DEBUG, "Incoming ACK, send acceptable RST.");
+		tcp_reply_rst(&conn->ident, seg);
+		return;
+	}
+
+	if ((seg->ctrl & CTL_SYN) == 0) {
+		log_msg(LVL_DEBUG, "SYN not present. Ignoring segment.");
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "Got SYN, sending SYN, ACK.");
+
+	conn->rcv_nxt = seg->seq + 1;
+	conn->irs = seg->seq;
+
+
+	log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
+
+	if (seg->len > 1)
+		log_msg(LVL_WARN, "SYN combined with data, ignoring data.");
+
+	/* XXX select ISS */
+	conn->iss = 1;
+	conn->snd_nxt = conn->iss;
+	conn->snd_una = conn->iss;
+
+	/*
+	 * Surprisingly the spec does not deal with initial window setting.
+	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
+	 * will always be accepted as new window setting.
+	 */
+	conn->snd_wnd = seg->wnd;
+	conn->snd_wl1 = seg->seq;
+	conn->snd_wl2 = seg->seq;
+
+	tcp_conn_state_set(conn, st_syn_received);
+
+	tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
+
+	tcp_segment_delete(seg);
+}
+
+/** Segment arrived in Syn-Sent state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_syn_sent(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_sa_syn_sent(%p, %p)", conn, seg);
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		log_msg(LVL_DEBUG, "snd_una=%u, seg.ack=%u, snd_nxt=%u",
+		    conn->snd_una, seg->ack, conn->snd_nxt);
+		if (!seq_no_ack_acceptable(conn, seg->ack)) {
+			if ((seg->ctrl & CTL_RST) == 0) {
+				log_msg(LVL_WARN, "ACK not acceptable, send RST");
+				tcp_reply_rst(&conn->ident, seg);
+			} else {
+				log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
+			}
+			return;
+		}
+	}
+
+	if ((seg->ctrl & CTL_RST) != 0) {
+		/* If we get here, we have either an acceptable ACK or no ACK */
+		if ((seg->ctrl & CTL_ACK) != 0) {
+			log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
+			    conn->name);
+			/* Reset connection */
+			tcp_conn_reset(conn);
+			return;
+		} else {
+			log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
+			    conn->name);
+			return;
+		}
+	}
+
+	/* XXX precedence */
+
+	if ((seg->ctrl & CTL_SYN) == 0) {
+		log_msg(LVL_DEBUG, "No SYN bit, ignoring segment.");
+		return;
+	}
+
+	conn->rcv_nxt = seg->seq + 1;
+	conn->irs = seg->seq;
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		conn->snd_una = seg->ack;
+
+		/*
+		 * Prune acked segments from retransmission queue and
+		 * possibly transmit more data.
+		 */
+		tcp_tqueue_ack_received(conn);
+	}
+
+	log_msg(LVL_DEBUG, "Sent SYN, got SYN.");
+
+	/*
+	 * Surprisingly the spec does not deal with initial window setting.
+	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
+	 * will always be accepted as new window setting.
+	 */
+	log_msg(LVL_DEBUG, "SND.WND := %" PRIu32 ", SND.WL1 := %" PRIu32 ", "
+	    "SND.WL2 = %" PRIu32, seg->wnd, seg->seq, seg->seq);
+	conn->snd_wnd = seg->wnd;
+	conn->snd_wl1 = seg->seq;
+	conn->snd_wl2 = seg->seq;
+
+	if (seq_no_syn_acked(conn)) {
+		log_msg(LVL_DEBUG, "%s: syn acked -> Established", conn->name);
+		tcp_conn_state_set(conn, st_established);
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK /* XXX */);
+	} else {
+		log_msg(LVL_DEBUG, "%s: syn not acked -> Syn-Received",
+		    conn->name);
+		tcp_conn_state_set(conn, st_syn_received);
+		tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
+	}
+
+	tcp_segment_delete(seg);
+}
+
+/** Segment arrived in state where segments are processed in sequence order.
+ *
+ * Queue segment in incoming segments queue for processing.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_queue(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	tcp_segment_t *pseg;
+
+	log_msg(LVL_DEBUG, "tcp_conn_sa_seq(%p, %p)", conn, seg);
+
+	/* Discard unacceptable segments ("old duplicates") */
+	if (!seq_no_segment_acceptable(conn, seg)) {
+		log_msg(LVL_DEBUG, "Replying ACK to unacceptable segment.");
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+		tcp_segment_delete(seg);
+		return;
+	}
+
+	/* Queue for processing */
+	tcp_iqueue_insert_seg(&conn->incoming, seg);
+
+	/*
+	 * Process all segments from incoming queue that are ready.
+	 * Unacceptable segments are discarded by tcp_iqueue_get_ready_seg().
+	 *
+	 * XXX Need to return ACK for unacceptable segments
+	 */
+	while (tcp_iqueue_get_ready_seg(&conn->incoming, &pseg) == EOK)
+		tcp_conn_seg_process(conn, pseg);
+}
+
+/** Process segment RST field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if ((seg->ctrl & CTL_RST) == 0)
+		return cp_continue;
+
+	switch (conn->cstate) {
+	case st_syn_received:
+		/* XXX In case of passive open, revert to Listen state */
+		if (conn->ap == ap_passive) {
+			tcp_conn_state_set(conn, st_listen);
+			/* XXX Revert conn->ident */
+			tcp_conn_tw_timer_clear(conn);
+			tcp_tqueue_clear(&conn->retransmit);
+		} else {
+			tcp_conn_reset(conn);
+		}
+		break;
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+		/* General "connection reset" signal */
+		tcp_reset_signal(conn);
+		tcp_conn_reset(conn);
+		break;
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		tcp_conn_reset(conn);
+		break;
+	case st_listen:
+	case st_syn_sent:
+	case st_closed:
+		assert(false);
+	}
+
+	return cp_done;
+}
+
+/** Process segment security and precedence fields.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_sp(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment SYN field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_syn(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if ((seg->ctrl & CTL_SYN) == 0)
+		return cp_continue;
+
+	/*
+	 * Assert SYN is in receive window, otherwise this step should not
+	 * be reached.
+	 */
+	assert(seq_no_in_rcv_wnd(conn, seg->seq));
+
+	log_msg(LVL_WARN, "SYN is in receive window, should send reset. XXX");
+
+	/*
+	 * TODO
+	 *
+	 * Send a reset, resond "reset" to all outstanding RECEIVEs and SEND,
+	 * flush segment queues. Send unsolicited "connection reset" signal
+	 * to user, connection -> closed state, delete TCB, return.
+	 */
+	return cp_done;
+}
+
+/** Process segment ACK field in Syn-Received state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_sr(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (!seq_no_ack_acceptable(conn, seg->ack)) {
+		/* ACK is not acceptable, send RST. */
+		log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST.");
+		tcp_reply_rst(&conn->ident, seg);
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	log_msg(LVL_DEBUG, "%s: SYN ACKed -> Established", conn->name);
+
+	tcp_conn_state_set(conn, st_established);
+
+	/* XXX Not mentioned in spec?! */
+	conn->snd_una = seg->ack;
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Established state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_seg_proc_ack_est(%p, %p)", conn, seg);
+
+	log_msg(LVL_DEBUG, "SEG.ACK=%u, SND.UNA=%u, SND.NXT=%u",
+	    (unsigned)seg->ack, (unsigned)conn->snd_una,
+	    (unsigned)conn->snd_nxt);
+
+	if (!seq_no_ack_acceptable(conn, seg->ack)) {
+		log_msg(LVL_DEBUG, "ACK not acceptable.");
+		if (!seq_no_ack_duplicate(conn, seg->ack)) {
+			log_msg(LVL_WARN, "Not acceptable, not duplicate. "
+			    "Send ACK and drop.");
+			/* Not acceptable, not duplicate. Send ACK and drop. */
+			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+			tcp_segment_delete(seg);
+			return cp_done;
+		} else {
+			log_msg(LVL_DEBUG, "Ignoring duplicate ACK.");
+		}
+	} else {
+		/* Update SND.UNA */
+		conn->snd_una = seg->ack;
+	}
+
+	if (seq_no_new_wnd_update(conn, seg)) {
+		conn->snd_wnd = seg->wnd;
+		conn->snd_wl1 = seg->seq;
+		conn->snd_wl2 = seg->ack;
+
+		log_msg(LVL_DEBUG, "Updating send window, SND.WND=%" PRIu32
+		    ", SND.WL1=%" PRIu32 ", SND.WL2=%" PRIu32,
+		    conn->snd_wnd, conn->snd_wl1, conn->snd_wl2);
+	}
+
+	/*
+	 * Prune acked segments from retransmission queue and
+	 * possibly transmit more data.
+	 */
+	tcp_tqueue_ack_received(conn);
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Fin-Wait-1 state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_fw1(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	if (conn->fin_is_acked) {
+		log_msg(LVL_DEBUG, "%s: FIN acked -> Fin-Wait-2", conn->name);
+		tcp_conn_state_set(conn, st_fin_wait_2);
+	}
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Fin-Wait-2 state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_fw2(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment ACK field in Close-Wait state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_cw(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* The same processing as in Established state */
+	return tcp_conn_seg_proc_ack_est(conn, seg);
+}
+
+/** Process segment ACK field in Closing state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_cls(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment ACK field in Last-Ack state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_la(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	if (conn->fin_is_acked) {
+		log_msg(LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
+		tcp_conn_remove(conn);
+		tcp_conn_state_set(conn, st_closed);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Time-Wait state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_tw(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* Nothing to do */
+	return cp_continue;
+}
+
+/** Process segment ACK field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_ack(%p, %p)",
+	    conn->name, conn, seg);
+
+	if ((seg->ctrl & CTL_ACK) == 0) {
+		log_msg(LVL_WARN, "Segment has no ACK. Dropping.");
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	switch (conn->cstate) {
+	case st_syn_received:
+		return tcp_conn_seg_proc_ack_sr(conn, seg);
+	case st_established:
+		return tcp_conn_seg_proc_ack_est(conn, seg);
+	case st_fin_wait_1:
+		return tcp_conn_seg_proc_ack_fw1(conn, seg);
+	case st_fin_wait_2:
+		return tcp_conn_seg_proc_ack_fw2(conn, seg);
+	case st_close_wait:
+		return tcp_conn_seg_proc_ack_cw(conn, seg);
+	case st_closing:
+		return tcp_conn_seg_proc_ack_cls(conn, seg);
+	case st_last_ack:
+		return tcp_conn_seg_proc_ack_la(conn, seg);
+	case st_time_wait:
+		return tcp_conn_seg_proc_ack_tw(conn, seg);
+	case st_listen:
+	case st_syn_sent:
+	case st_closed:
+		assert(false);
+	}
+
+	assert(false);
+}
+
+/** Process segment URG field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_urg(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	return cp_continue;
+}
+
+/** Process segment text.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_text(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	size_t text_size;
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_text(%p, %p)",
+	    conn->name, conn, seg);
+
+	switch (conn->cstate) {
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+		/* OK */
+		break;
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		/* Invalid since FIN has been received. Ignore text. */
+		return cp_continue;
+	case st_listen:
+	case st_syn_sent:
+	case st_syn_received:
+	case st_closed:
+		assert(false);
+	}
+
+	/*
+	 * Process segment text
+	 */
+	assert(seq_no_segment_ready(conn, seg));
+
+	/* Trim anything outside our receive window */
+	tcp_conn_trim_seg_to_wnd(conn, seg);
+
+	/* Determine how many bytes to copy */
+	text_size = tcp_segment_text_size(seg);
+	xfer_size = min(text_size, conn->rcv_buf_size - conn->rcv_buf_used);
+
+	/* Copy data to receive buffer */
+	tcp_segment_text_copy(seg, conn->rcv_buf + conn->rcv_buf_used,
+	    xfer_size);
+	conn->rcv_buf_used += xfer_size;
+
+	/* Signal to the receive function that new data has arrived */
+	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+
+	log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
+
+	/* Advance RCV.NXT */
+	conn->rcv_nxt += xfer_size;
+
+	/* Update receive window. XXX Not an efficient strategy. */
+	conn->rcv_wnd -= xfer_size;
+
+	/* Send ACK */
+	if (xfer_size > 0)
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+	if (xfer_size < seg->len) {
+		/* Trim part of segment which we just received */
+		tcp_conn_trim_seg_to_wnd(conn, seg);
+	} else {
+		log_msg(LVL_DEBUG, "%s: Nothing left in segment, dropping "
+		    "(xfer_size=%zu, SEG.LEN=%zu, seg->ctrl=%u)",
+		    conn->name, xfer_size, seg->len, (unsigned)seg->ctrl);
+		/* Nothing left in segment */
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process segment FIN field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_fin(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_fin(%p, %p)",
+	    conn->name, conn, seg);
+	log_msg(LVL_DEBUG, " seg->len=%zu, seg->ctl=%u", (size_t) seg->len,
+	    (unsigned) seg->ctrl);
+
+	/* Only process FIN if no text is left in segment. */
+	if (tcp_segment_text_size(seg) == 0 && (seg->ctrl & CTL_FIN) != 0) {
+		log_msg(LVL_DEBUG, " - FIN found in segment.");
+
+		/* Send ACK */
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+		conn->rcv_nxt++;
+		conn->rcv_wnd--;
+
+		/* Change connection state */
+		switch (conn->cstate) {
+		case st_listen:
+		case st_syn_sent:
+		case st_closed:
+			/* Connection not synchronized */
+			assert(false);
+		case st_syn_received:
+		case st_established:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Close-Wait",
+			    conn->name);
+			tcp_conn_state_set(conn, st_close_wait);
+			break;
+		case st_fin_wait_1:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Closing",
+			    conn->name);
+			tcp_conn_state_set(conn, st_closing);
+			break;
+		case st_fin_wait_2:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Time-Wait",
+			    conn->name);
+			tcp_conn_state_set(conn, st_time_wait);
+			/* Start the Time-Wait timer */
+			tcp_conn_tw_timer_set(conn);
+			break;
+		case st_close_wait:
+		case st_closing:
+		case st_last_ack:
+			/* Do nothing */
+			break;
+		case st_time_wait:
+			/* Restart the Time-Wait timer */
+			tcp_conn_tw_timer_set(conn);
+			break;
+		}
+
+		/* Add FIN to the receive buffer */
+		conn->rcv_buf_fin = true;
+		fibril_condvar_broadcast(&conn->rcv_buf_cv);
+
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process incoming segment.
+ *
+ * We are in connection state where segments are processed in order
+ * of sequence number. This processes one segment taken from the
+ * connection incoming segments queue.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_seg_process(%p, %p)", conn, seg);
+	tcp_segment_dump(seg);
+
+	/* Check whether segment is acceptable */
+	/* XXX Permit valid ACKs, URGs and RSTs */
+/*	if (!seq_no_segment_acceptable(conn, seg)) {
+		log_msg(LVL_WARN, "Segment not acceptable, dropping.");
+		if ((seg->ctrl & CTL_RST) == 0) {
+			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+		}
+		return;
+	}
+*/
+
+	if (tcp_conn_seg_proc_rst(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_sp(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_syn(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_ack(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_urg(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_text(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_fin(conn, seg) == cp_done)
+		return;
+
+	/*
+	 * If anything is left from the segment, insert it back into the
+	 * incoming segments queue.
+	 */
+	if (seg->len > 0) {
+		log_msg(LVL_DEBUG, "Re-insert segment %p. seg->len=%zu",
+		    seg, (size_t) seg->len);
+		tcp_iqueue_insert_seg(&conn->incoming, seg);
+	} else {
+		tcp_segment_delete(seg);
+	}
+}
+
+/** Segment arrived on a connection.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%c: tcp_conn_segment_arrived(%p)",
+	    conn->name, seg);
+
+	switch (conn->cstate) {
+	case st_listen:
+		tcp_conn_sa_listen(conn, seg); break;
+	case st_syn_sent:
+		tcp_conn_sa_syn_sent(conn, seg); break;
+	case st_syn_received:
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		/* Process segments in order of sequence number */
+		tcp_conn_sa_queue(conn, seg); break;
+	case st_closed:
+		log_msg(LVL_DEBUG, "state=%d", (int) conn->cstate);
+		assert(false);
+	}
+}
+
+/** Time-Wait timeout handler.
+ *
+ * @param arg	Connection
+ */
+static void tw_timeout_func(void *arg)
+{
+	tcp_conn_t *conn = (tcp_conn_t *) arg;
+
+	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_DEBUG, "Connection already closed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
+	tcp_conn_remove(conn);
+	tcp_conn_state_set(conn, st_closed);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/** Start or restart the Time-Wait timeout.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_tw_timer_set(tcp_conn_t *conn)
+{
+	tcp_conn_addref(conn);
+	fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
+	    (void *)conn);
+}
+
+/** Clear the Time-Wait timeout.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
+{
+	if (fibril_timer_clear(conn->tw_timer) == fts_active)
+		tcp_conn_delref(conn);
+}
+
+/** Trim segment to the receive window.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+void tcp_conn_trim_seg_to_wnd(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	uint32_t left, right;
+
+	seq_no_seg_trim_calc(conn, seg, &left, &right);
+	tcp_segment_trim(seg, left, right);
+}
+
+/** Handle unexpected segment received on a socket pair.
+ *
+ * We reply with an RST unless the received segment has RST.
+ *
+ * @param sp		Socket pair which received the segment
+ * @param seg		Unexpected segment
+ */
+void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, 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;
+}
+
+/** Send RST in response to an incoming segment.
+ *
+ * @param sp		Socket pair which received the segment
+ * @param seg		Incoming segment
+ */
+void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_segment_t *rseg;
+
+	log_msg(LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
+
+	rseg = tcp_segment_make_rst(seg);
+	tcp_transmit_segment(sp, rseg);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/conn.h
===================================================================
--- uspace/srv/net/tcp/conn.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/conn.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,61 @@
+/*
+ * 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 TCP connection processing and state machine
+ */
+
+#ifndef CONN_H
+#define CONN_H
+
+#include <bool.h>
+#include "tcp_type.h"
+
+extern tcp_conn_t *tcp_conn_new(tcp_sock_t *, tcp_sock_t *);
+extern void tcp_conn_delete(tcp_conn_t *);
+extern void tcp_conn_add(tcp_conn_t *);
+extern void tcp_conn_remove(tcp_conn_t *);
+extern void tcp_conn_sync(tcp_conn_t *);
+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 void tcp_conn_addref(tcp_conn_t *);
+extern void tcp_conn_delref(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_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 *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/iqueue.c
===================================================================
--- uspace/srv/net/tcp/iqueue.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/iqueue.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,156 @@
+/*
+ * 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 Connection incoming segments queue
+ *
+ * Segments are sorted in order of their sequence number.
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include "iqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** Initialize incoming segments queue.
+ *
+ * @param iqueue	Incoming queue
+ * @param conn		Connection the queue is associated with
+ */
+void tcp_iqueue_init(tcp_iqueue_t *iqueue, tcp_conn_t *conn)
+{
+	list_initialize(&iqueue->list);
+	iqueue->conn = conn;
+}
+
+/** Insert segment into incoming queue.
+ *
+ * @param iqueue	Incoming queue
+ * @param seg		Segment
+ */
+void tcp_iqueue_insert_seg(tcp_iqueue_t *iqueue, tcp_segment_t *seg)
+{
+	tcp_iqueue_entry_t *iqe;
+	tcp_iqueue_entry_t *qe;
+	link_t *link;
+	log_msg(LVL_DEBUG, "tcp_iqueue_insert_seg()");
+
+	iqe = calloc(1, sizeof(tcp_iqueue_entry_t));
+	if (iqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating IQE.");
+		return;
+	}
+
+	iqe->seg = seg;
+
+	/* Sort by sequence number */
+
+	link = list_first(&iqueue->list);
+	while (link != NULL) {
+		qe = list_get_instance(link,
+		    tcp_iqueue_entry_t, link);
+
+		if (seq_no_seg_cmp(iqueue->conn, iqe->seg, qe->seg) >= 0)
+			break;
+	}
+
+	if (link != NULL)
+		list_insert_before(&iqe->link, &qe->link);
+	else
+		list_append(&iqe->link, &iqueue->list);
+}
+
+/** Get next ready segment from incoming queue.
+ *
+ * Return the segment with the earliest sequence number if it is ready.
+ * A segment is ready if its SEG.SEQ is earlier or equal to RCV.NXT.
+ *
+ * @param iqueue	Incoming queue
+ * @param seg		Place to store pointer to segment
+ * @return		EOK on success, ENOENT if no segment is ready
+ */
+int tcp_iqueue_get_ready_seg(tcp_iqueue_t *iqueue, tcp_segment_t **seg)
+{
+	tcp_iqueue_entry_t *iqe;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "tcp_get_ready_seg()");
+
+	link = list_first(&iqueue->list);
+	if (link == NULL) {
+		log_msg(LVL_DEBUG, "iqueue is empty");
+		return ENOENT;
+	}
+
+	iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
+
+	while (!seq_no_segment_acceptable(iqueue->conn, iqe->seg)) {
+		log_msg(LVL_DEBUG, "Skipping unacceptable segment (RCV.NXT=%"
+		    PRIu32 ", RCV.NXT+RCV.WND=%" PRIu32 ", SEG.SEQ=%" PRIu32
+		    ", SEG.LEN=%" PRIu32 ")", iqueue->conn->rcv_nxt,
+		    iqueue->conn->rcv_nxt + iqueue->conn->rcv_wnd,
+		    iqe->seg->seq, iqe->seg->len);
+
+		list_remove(&iqe->link);
+		tcp_segment_delete(iqe->seg);
+
+         	link = list_first(&iqueue->list);
+		if (link == NULL) {
+			log_msg(LVL_DEBUG, "iqueue is empty");
+			return ENOENT;
+		}
+
+		iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
+	}
+
+	/* Do not return segments that are not ready for processing */
+	if (!seq_no_segment_ready(iqueue->conn, iqe->seg)) {
+		log_msg(LVL_DEBUG, "Next segment not ready: SEG.SEQ=%u, "
+		    "RCV.NXT=%u, SEG.LEN=%u", iqe->seg->seq,
+		    iqueue->conn->rcv_nxt, iqe->seg->len);
+		return ENOENT;
+	}
+
+	log_msg(LVL_DEBUG, "Returning ready segment %p", iqe->seg);
+	list_remove(&iqe->link);
+	*seg = iqe->seg;
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/iqueue.h
===================================================================
--- uspace/srv/net/tcp/iqueue.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/iqueue.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,47 @@
+/*
+ * 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 Connection incoming segments queue
+ */
+
+#ifndef IQUEUE_H
+#define IQUEUE_H
+
+#include "tcp_type.h"
+
+extern void tcp_iqueue_init(tcp_iqueue_t *, tcp_conn_t *);
+extern void tcp_iqueue_insert_seg(tcp_iqueue_t *, tcp_segment_t *);
+extern int tcp_iqueue_get_ready_seg(tcp_iqueue_t *, tcp_segment_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/ncsim.c
===================================================================
--- uspace/srv/net/tcp/ncsim.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/ncsim.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,172 @@
+/*
+ * 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 Network condition simulator
+ *
+ * Simulate network conditions for testing the reliability implementation:
+ *    - variable latency
+ *    - frame drop
+ */
+
+#include <adt/list.h>
+#include <async.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include <thread.h>
+#include "conn.h"
+#include "ncsim.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "tcp_type.h"
+
+static list_t sim_queue;
+static fibril_mutex_t sim_queue_lock;
+static fibril_condvar_t sim_queue_cv;
+
+/** Initialize segment receive queue. */
+void tcp_ncsim_init(void)
+{
+	list_initialize(&sim_queue);
+	fibril_mutex_initialize(&sim_queue_lock);
+	fibril_condvar_initialize(&sim_queue_cv);
+}
+
+/** Bounce segment through simulator into receive queue.
+ *
+ * @param sp	Socket pair, oriented for transmission
+ * @param seg	Segment
+ */
+void tcp_ncsim_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_squeue_entry_t *sqe;
+	tcp_squeue_entry_t *old_qe;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_bounce_seg()");
+	tcp_rqueue_bounce_seg(sp, seg);
+	return;
+
+	if (0 /*random() % 4 == 3*/) {
+		/* Drop segment */
+		log_msg(LVL_ERROR, "NCSim dropping segment");
+		tcp_segment_delete(seg);
+		return;
+	}
+
+	sqe = calloc(1, sizeof(tcp_squeue_entry_t));
+	if (sqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating SQE.");
+		return;
+	}
+
+	sqe->delay = random() % (1000 * 1000);
+	sqe->sp = *sp;
+	sqe->seg = seg;
+
+	fibril_mutex_lock(&sim_queue_lock);
+
+	link = list_first(&sim_queue);
+	while (link != NULL && sqe->delay > 0) {
+		old_qe = list_get_instance(link, tcp_squeue_entry_t, link);
+		if (sqe->delay < old_qe->delay)
+			break;
+
+		sqe->delay -= old_qe->delay;
+
+		link = link->next;
+		if (link == &sim_queue.head)
+			link = NULL;
+	}
+
+	if (link != NULL)
+		list_insert_after(&sqe->link, link);
+	else
+		list_append(&sqe->link, &sim_queue);
+
+	fibril_condvar_broadcast(&sim_queue_cv);
+	fibril_mutex_unlock(&sim_queue_lock);
+}
+
+/** Network condition simulator handler thread. */
+static void tcp_ncsim_thread(void *arg)
+{
+	link_t *link;
+	tcp_squeue_entry_t *sqe;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_thread()");
+
+
+	while (true) {
+		fibril_mutex_lock(&sim_queue_lock);
+
+		while (list_empty(&sim_queue))
+			fibril_condvar_wait(&sim_queue_cv, &sim_queue_lock);
+
+		do {
+			link = list_first(&sim_queue);
+			sqe = list_get_instance(link, tcp_squeue_entry_t, link);
+
+			log_msg(LVL_DEBUG, "NCSim - Sleep");
+			rc = fibril_condvar_wait_timeout(&sim_queue_cv,
+			    &sim_queue_lock, sqe->delay);
+		} while (rc != ETIMEOUT);
+
+		list_remove(link);
+		fibril_mutex_unlock(&sim_queue_lock);
+
+		log_msg(LVL_DEBUG, "NCSim - End Sleep");
+		tcp_rqueue_bounce_seg(&sqe->sp, sqe->seg);
+		free(sqe);
+	}
+}
+
+/** Start simulator handler thread. */
+void tcp_ncsim_thread_start(void)
+{
+	thread_id_t tid;
+        int rc;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_thread_start()");
+
+	rc = thread_create(tcp_ncsim_thread, NULL, "ncsim", &tid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed creating ncsim thread.");
+		return;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/ncsim.h
===================================================================
--- uspace/srv/net/tcp/ncsim.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/ncsim.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,48 @@
+/*
+ * 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 Network condition simulator
+ */
+
+#ifndef NCSIM_H
+#define NCSIM_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_thread_start(void);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/pdu.c
===================================================================
--- uspace/srv/net/tcp/pdu.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/pdu.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,314 @@
+/*
+ * 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 TCP header encoding and decoding
+ */
+
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "pdu.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "std.h"
+#include "tcp_type.h"
+
+#define TCP_CHECKSUM_INIT 0xffff
+
+/** One's complement addition.
+ *
+ * Result is a + b + carry.
+ */
+static uint16_t tcp_ocadd16(uint16_t a, uint16_t b)
+{
+	uint32_t s;
+
+	s = (uint32_t)a + (uint32_t)b;
+	return (s & 0xffff) + (s >> 16);
+}
+
+static uint16_t tcp_checksum_calc(uint16_t ivalue, void *data, size_t size)
+{
+	uint16_t sum;
+	uint16_t w;
+	size_t words, i;
+	uint8_t *bdata;
+
+	sum = ~ivalue;
+	words = size / 2;
+	bdata = (uint8_t *)data;
+
+	for (i = 0; i < words; i++) {
+		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
+		sum = tcp_ocadd16(sum, w);
+	}
+
+	if (size % 2 != 0) {
+		w = ((uint16_t)bdata[2*words] << 8);
+		sum = tcp_ocadd16(sum, w);
+	}
+
+	return ~sum;
+}
+
+static void tcp_header_decode_flags(uint16_t doff_flags, tcp_control_t *rctl)
+{
+	tcp_control_t ctl;
+
+	ctl = 0;
+
+	if ((doff_flags & BIT_V(uint16_t, DF_URG)) != 0)
+		ctl |= 0 /* XXX */;
+	if ((doff_flags & BIT_V(uint16_t, DF_ACK)) != 0)
+		ctl |= CTL_ACK;
+	if ((doff_flags & BIT_V(uint16_t, DF_PSH)) != 0)
+		ctl |= 0 /* XXX */;
+	if ((doff_flags & BIT_V(uint16_t, DF_RST)) != 0)
+		ctl |= CTL_RST;
+	if ((doff_flags & BIT_V(uint16_t, DF_SYN)) != 0)
+		ctl |= CTL_SYN;
+	if ((doff_flags & BIT_V(uint16_t, DF_FIN)) != 0)
+		ctl |= CTL_FIN;
+
+	*rctl = ctl;
+}
+
+static void tcp_header_encode_flags(tcp_control_t ctl, uint16_t doff_flags0,
+    uint16_t *rdoff_flags)
+{
+	uint16_t doff_flags;
+
+	doff_flags = doff_flags0;
+
+	if ((ctl & CTL_ACK) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_ACK);
+	if ((ctl & CTL_RST) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_RST);
+	if ((ctl & CTL_SYN) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_SYN);
+	if ((ctl & CTL_FIN) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_FIN);
+
+	*rdoff_flags = doff_flags;
+}
+
+static void tcp_header_setup(tcp_sockpair_t *sp, 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->seq = host2uint32_t_be(seg->seq);
+	hdr->ack = host2uint32_t_be(seg->ack);
+
+	doff = (sizeof(tcp_header_t) / sizeof(uint32_t)) << DF_DATA_OFFSET_l;
+	tcp_header_encode_flags(seg->ctrl, doff, &doff_flags);
+
+	hdr->doff_flags = host2uint16_t_be(doff_flags);
+	hdr->window = host2uint16_t_be(seg->wnd);
+	hdr->checksum = 0;
+	hdr->urg_ptr = host2uint16_t_be(seg->up);
+}
+
+static void tcp_phdr_setup(tcp_pdu_t *pdu, tcp_phdr_t *phdr)
+{
+	phdr->src_addr = host2uint32_t_be(pdu->src_addr.ipv4);
+	phdr->dest_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
+	phdr->zero = 0;
+	phdr->protocol = 6; /* XXX Magic number */
+	phdr->tcp_length = host2uint16_t_be(pdu->header_size + pdu->text_size);
+}
+
+static void tcp_header_decode(tcp_header_t *hdr, tcp_segment_t *seg)
+{
+	tcp_header_decode_flags(uint16_t_be2host(hdr->doff_flags), &seg->ctrl);
+	seg->seq = uint32_t_be2host(hdr->seq);
+	seg->ack = uint32_t_be2host(hdr->ack);
+	seg->wnd = uint16_t_be2host(hdr->window);
+	seg->up = uint16_t_be2host(hdr->urg_ptr);
+}
+
+static int tcp_header_encode(tcp_sockpair_t *sp, tcp_segment_t *seg,
+    void **header, size_t *size)
+{
+	tcp_header_t *hdr;
+
+	hdr = calloc(1, sizeof(tcp_header_t));
+	if (hdr == NULL)
+		return ENOMEM;
+
+	tcp_header_setup(sp, seg, hdr);
+	*header = hdr;
+	*size = sizeof(tcp_header_t);
+
+	return EOK;
+}
+
+static tcp_pdu_t *tcp_pdu_new(void)
+{
+	return calloc(1, sizeof(tcp_pdu_t));
+}
+
+/** Create PDU with the specified header and text data.
+ *
+ * Note that you still need to set addresses in the returned PDU.
+ *
+ * @param hdr		Header data
+ * @param hdr_size      Header size in bytes
+ * @param text		Text data
+ * @param text_size	Text size in bytes
+ * @return		New PDU
+ */
+tcp_pdu_t *tcp_pdu_create(void *hdr, size_t hdr_size, void *text,
+    size_t text_size)
+{
+	tcp_pdu_t *pdu;
+
+	pdu = tcp_pdu_new();
+	if (pdu == NULL)
+		return NULL;
+
+	pdu->header = malloc(hdr_size);
+	pdu->text = malloc(text_size);
+	if (pdu->header == NULL || pdu->text == NULL)
+		goto error;
+
+	memcpy(pdu->header, hdr, hdr_size);
+	memcpy(pdu->text, text, text_size);
+
+	pdu->header_size = hdr_size;
+	pdu->text_size = text_size;
+
+	return pdu;
+
+error:
+	if (pdu->header != NULL)
+		free(pdu->header);
+	if (pdu->text != NULL)
+		free(pdu->text);
+
+	return NULL;
+}
+
+void tcp_pdu_delete(tcp_pdu_t *pdu)
+{
+	free(pdu->header);
+	free(pdu->text);
+	free(pdu);
+}
+
+static uint16_t tcp_pdu_checksum_calc(tcp_pdu_t *pdu)
+{
+	uint16_t cs_phdr;
+	uint16_t cs_headers;
+	uint16_t cs_all;
+	tcp_phdr_t phdr;
+
+	tcp_phdr_setup(pdu, &phdr);
+	cs_phdr = tcp_checksum_calc(TCP_CHECKSUM_INIT, (void *)&phdr,
+	    sizeof(tcp_phdr_t));
+	cs_headers = tcp_checksum_calc(cs_phdr, pdu->header, pdu->header_size);
+	cs_all = tcp_checksum_calc(cs_headers, pdu->text, pdu->text_size);
+
+	return cs_all;
+}
+
+static void tcp_pdu_set_checksum(tcp_pdu_t *pdu, uint16_t checksum)
+{
+	tcp_header_t *hdr;
+
+	hdr = (tcp_header_t *)pdu->header;
+	hdr->checksum = host2uint16_t_be(checksum);
+}
+
+/** Decode incoming PDU */
+int tcp_pdu_decode(tcp_pdu_t *pdu, tcp_sockpair_t *sp, tcp_segment_t **seg)
+{
+	tcp_segment_t *nseg;
+	tcp_header_t *hdr;
+
+	nseg = tcp_segment_make_data(0, pdu->text, pdu->text_size);
+	if (nseg == NULL)
+		return ENOMEM;
+
+	tcp_header_decode(pdu->header, nseg);
+	nseg->len += seq_no_control_len(nseg->ctrl);
+
+	hdr = (tcp_header_t *)pdu->header;
+
+	sp->local.port = uint16_t_be2host(hdr->dest_port);
+	sp->local.addr = pdu->dest_addr;
+	sp->foreign.port = uint16_t_be2host(hdr->src_port);
+	sp->foreign.addr = pdu->src_addr;
+
+	*seg = nseg;
+	return EOK;
+}
+
+/** Encode outgoing PDU */
+int tcp_pdu_encode(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_pdu_t **pdu)
+{
+	tcp_pdu_t *npdu;
+	size_t text_size;
+	uint16_t checksum;
+
+	npdu = tcp_pdu_new();
+	if (npdu == NULL)
+		return ENOMEM;
+
+	npdu->src_addr = sp->local.addr;
+	npdu->dest_addr = sp->foreign.addr;
+	tcp_header_encode(sp, seg, &npdu->header, &npdu->header_size);
+
+	text_size = tcp_segment_text_size(seg);
+	npdu->text = calloc(1, text_size);
+	if (npdu->text == NULL)
+		return ENOMEM;
+
+	npdu->text_size = text_size;
+	memcpy(npdu->text, seg->data, text_size);
+
+	/* Checksum calculation */
+	checksum = tcp_pdu_checksum_calc(npdu);
+	tcp_pdu_set_checksum(npdu, checksum);
+
+	*pdu = npdu;
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/pdu.h
===================================================================
--- uspace/srv/net/tcp/pdu.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/pdu.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,50 @@
+/*
+ * 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 TCP PDU (encoded Protocol Data Unit) handling
+ */
+
+#ifndef PDU_H
+#define PDU_H
+
+#include <sys/types.h>
+#include "std.h"
+#include "tcp_type.h"
+
+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 **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/rqueue.c
===================================================================
--- uspace/srv/net/tcp/rqueue.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/rqueue.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,163 @@
+/*
+ * 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 Global segment receive queue
+ */
+
+#include <adt/prodcons.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include <thread.h>
+#include "conn.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "tcp_type.h"
+#include "ucall.h"
+
+/** Transcode bounced segments.
+ *
+ * If defined, segments bounced via the internal debugging loopback will
+ * be encoded to a PDU and the decoded. Otherwise they will be bounced back
+ * directly without passing the encoder-decoder.
+ */
+#define BOUNCE_TRANSCODE
+
+static prodcons_t rqueue;
+
+/** Initialize segment receive queue. */
+void tcp_rqueue_init(void)
+{
+	prodcons_initialize(&rqueue);
+}
+
+/** Bounce segment directy into receive queue without constructing the PDU.
+ *
+ * This is for testing purposes only.
+ *
+ * @param sp	Socket pair, oriented for transmission
+ * @param seg	Segment
+ */
+void tcp_rqueue_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_sockpair_t rident;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_bounce_seg()");
+
+#ifdef BOUNCE_TRANSCODE
+	tcp_pdu_t *pdu;
+	tcp_segment_t *dseg;
+
+	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	tcp_pdu_delete(pdu);
+
+	/** Insert decoded segment into rqueue */
+	tcp_rqueue_insert_seg(&rident, dseg);
+	tcp_segment_delete(seg);
+#else
+	/* Reverse the identification */
+	tcp_sockpair_flipped(sp, &rident);
+
+	/* Insert segment back into rqueue */
+	tcp_rqueue_insert_seg(&rident, seg);
+#endif
+}
+
+/** Insert segment into receive queue.
+ *
+ * @param sp	Socket pair, oriented for reception
+ * @param seg	Segment
+ */
+void tcp_rqueue_insert_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_rqueue_entry_t *rqe;
+	log_msg(LVL_DEBUG, "tcp_rqueue_insert_seg()");
+
+	tcp_segment_dump(seg);
+
+	rqe = calloc(1, sizeof(tcp_rqueue_entry_t));
+	if (rqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating RQE.");
+		return;
+	}
+
+	rqe->sp = *sp;
+	rqe->seg = seg;
+
+	prodcons_produce(&rqueue, &rqe->link);
+}
+
+/** Receive queue handler thread. */
+static void tcp_rqueue_thread(void *arg)
+{
+	link_t *link;
+	tcp_rqueue_entry_t *rqe;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_thread()");
+
+	while (true) {
+		link = prodcons_consume(&rqueue);
+		rqe = list_get_instance(link, tcp_rqueue_entry_t, link);
+
+		tcp_as_segment_arrived(&rqe->sp, rqe->seg);
+	}
+}
+
+/** Start receive queue handler thread. */
+void tcp_rqueue_thread_start(void)
+{
+	thread_id_t tid;
+        int rc;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_thread_start()");
+
+	rc = thread_create(tcp_rqueue_thread, NULL, "rqueue", &tid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed creating rqueue thread.");
+		return;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/rqueue.h
===================================================================
--- uspace/srv/net/tcp/rqueue.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/rqueue.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,50 @@
+/*
+ * 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 Global segment receive queue
+ */
+
+#ifndef RQUEUE_H
+#define RQUEUE_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_handler(void *);
+extern void tcp_rqueue_thread_start(void);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/segment.c
===================================================================
--- uspace/srv/net/tcp/segment.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/segment.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,261 @@
+/*
+ * 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 Segment processing
+ */
+
+#include <io/log.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** Alocate new segment structure. */
+tcp_segment_t *tcp_segment_new(void)
+{
+	return calloc(1, sizeof(tcp_segment_t));
+}
+
+/** Delete segment. */
+void tcp_segment_delete(tcp_segment_t *seg)
+{
+	free(seg);
+}
+
+/** Create duplicate of segment.
+ *
+ * @param seg	Segment
+ * @return 	Duplicate segment
+ */
+tcp_segment_t *tcp_segment_dup(tcp_segment_t *seg)
+{
+	tcp_segment_t *scopy;
+	size_t tsize;
+
+	scopy = tcp_segment_new();
+	if (scopy == NULL)
+		return NULL;
+
+	scopy->ctrl = seg->ctrl;
+	scopy->seq = seg->seq;
+	scopy->ack = seg->ack;
+	scopy->len = seg->len;
+	scopy->wnd = seg->wnd;
+	scopy->up = seg->up;
+
+	tsize = tcp_segment_text_size(seg);
+	scopy->data = calloc(tsize, 1);
+	if (scopy->data == NULL) {
+		free(scopy);
+		return NULL;
+	}
+
+	memcpy(scopy->data, seg->data, tsize);
+	scopy->dfptr = scopy->data;
+
+	return scopy;
+}
+
+/** Create a control-only segment.
+ *
+  * @return	Segment
+ */
+tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t ctrl)
+{
+	tcp_segment_t *seg;
+
+	seg = tcp_segment_new();
+	if (seg == NULL)
+		return NULL;
+
+	seg->ctrl = ctrl;
+	seg->len = seq_no_control_len(ctrl);
+
+	return seg;
+}
+
+/** Create an RST segment.
+ *
+ * @param seg	Segment we are replying to
+ * @return	RST segment
+ */
+tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *seg)
+{
+	tcp_segment_t *rseg;
+
+	rseg = tcp_segment_new();
+	if (rseg == NULL)
+		return NULL;
+
+	if ((seg->ctrl & CTL_ACK) == 0) {
+		rseg->ctrl = CTL_RST | CTL_ACK;
+		rseg->seq = 0;
+		rseg->ack = seg->seq + seg->len;
+	} else {
+		rseg->ctrl = CTL_RST;
+		rseg->seq = seg->ack;
+	}
+
+	return rseg;
+}
+
+/** Create a control segment.
+ *
+  * @return	Segment
+ */
+tcp_segment_t *tcp_segment_make_data(tcp_control_t ctrl, void *data,
+    size_t size)
+{
+	tcp_segment_t *seg;
+
+	seg = tcp_segment_new();
+	if (seg == NULL)
+		return NULL;
+
+	seg->ctrl = ctrl;
+	seg->len = seq_no_control_len(ctrl) + size;
+
+	seg->dfptr = seg->data = malloc(size);
+	if (seg->dfptr == NULL) {
+		free(seg);
+		return NULL;
+	}
+
+	memcpy(seg->data, data, size);
+
+	return seg;
+}
+
+
+/** Trim segment from left and right by the specified amount.
+ *
+ * Trim any text or control to remove the specified amount of sequence
+ * numbers from the left (lower sequence numbers) and right side
+ * (higher sequence numbers) of the segment.
+ *
+ * @param seg		Segment, will be modified in place
+ * @param left		Amount of sequence numbers to trim from the left
+ * @param right		Amount of sequence numbers to trim from the right
+ */
+void tcp_segment_trim(tcp_segment_t *seg, uint32_t left, uint32_t right)
+{
+	uint32_t t_size;
+
+	assert(left + right <= seg->len);
+
+	/* Special case, entire segment trimmed from left */
+	if (left == seg->len) {
+		seg->seq = seg->seq + seg->len;
+		seg->len = 0;
+		return;
+	}
+
+	/* Special case, entire segment trimmed from right */
+	if (right == seg->len) {
+		seg->len = 0;
+		return;
+	}
+
+	/* General case */
+
+	t_size = tcp_segment_text_size(seg);
+
+	if (left > 0 && (seg->ctrl & CTL_SYN) != 0) {
+		/* Trim SYN */
+		seg->ctrl &= ~CTL_SYN;
+		seg->seq++;
+		seg->len--;
+		left--;
+	}
+
+	if (right > 0 && (seg->ctrl & CTL_FIN) != 0) {
+		/* Trim FIN */
+		seg->ctrl &= ~CTL_FIN;
+		seg->len--;
+		right--;
+	}
+
+	if (left > 0 || right > 0) {
+		/* Trim segment text */
+		assert(left + right <= t_size);
+
+		seg->data += left;
+		seg->len -= left + right;
+	}
+}
+
+/** Copy out text data from segment.
+ *
+ * Data is copied from the beginning of the segment text up to @a size bytes.
+ * @a size must not be greater than the size of the segment text, but
+ * it can be less.
+ *
+ * @param seg	Segment
+ * @param buf	Destination buffer
+ * @param size	Size of destination buffer
+ */
+void tcp_segment_text_copy(tcp_segment_t *seg, void *buf, size_t size)
+{
+	assert(size <= tcp_segment_text_size(seg));
+	memcpy(buf, seg->data, size);
+}
+
+/** Return number of bytes in segment text.
+ *
+ * @param seg	Segment
+ * @return	Number of bytes in segment text
+ */
+size_t tcp_segment_text_size(tcp_segment_t *seg)
+{
+	return seg->len - seq_no_control_len(seg->ctrl);
+}
+
+/** Dump segment contents to log.
+ *
+ * @param seg	Segment
+ */
+void tcp_segment_dump(tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "Segment dump:");
+	log_msg(LVL_DEBUG, " - ctrl = %u", (unsigned)seg->ctrl);
+	log_msg(LVL_DEBUG, " - seq = % " PRIu32, seg->seq);
+	log_msg(LVL_DEBUG, " - ack = % " PRIu32, seg->ack);
+	log_msg(LVL_DEBUG, " - len = % " PRIu32, seg->len);
+	log_msg(LVL_DEBUG, " - wnd = % " PRIu32, seg->wnd);
+	log_msg(LVL_DEBUG, " - up = % " PRIu32, seg->up);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/segment.h
===================================================================
--- uspace/srv/net/tcp/segment.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/segment.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,57 @@
+/*
+ * 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 Segment processing
+ */
+
+#ifndef SEGMENT_H
+#define SEGMENT_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+extern tcp_segment_t *tcp_segment_new(void);
+extern void tcp_segment_delete(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_dup(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t);
+extern tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_make_data(tcp_control_t, void *, size_t);
+extern void tcp_segment_trim(tcp_segment_t *, uint32_t, uint32_t);
+extern void tcp_segment_text_copy(tcp_segment_t *, void *, size_t);
+extern size_t tcp_segment_text_size(tcp_segment_t *);
+extern void tcp_segment_dump(tcp_segment_t *);
+
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/seq_no.c
===================================================================
--- uspace/srv/net/tcp/seq_no.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/seq_no.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,243 @@
+/*
+ * 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 Sequence number computations
+ */
+
+#include <assert.h>
+#include <bool.h>
+#include <sys/types.h>
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** a <= b < c modulo sequence space */
+static bool seq_no_le_lt(uint32_t a, uint32_t b, uint32_t c)
+{
+	if (a <= c) {
+		return (a <= b) && (b < c);
+	} else {
+		return (b < c) || (a <= b);
+	}
+}
+
+/** a < b <= c modulo sequence space */
+static bool seq_no_lt_le(uint32_t a, uint32_t b, uint32_t c)
+{
+	if (a <= c) {
+		return (a < b) && (b <= c);
+	} else {
+		return (b <= c) || (a < b);
+	}
+}
+
+/** Determine wheter ack is acceptable (new acknowledgement) */
+bool seq_no_ack_acceptable(tcp_conn_t *conn, uint32_t seg_ack)
+{
+	/* SND.UNA < SEG.ACK <= SND.NXT */
+	return seq_no_lt_le(conn->snd_una, seg_ack, conn->snd_nxt);
+}
+
+/** Determine wheter ack is duplicate.
+ *
+ * ACK is duplicate if it refers to a sequence number that has
+ * aleady been acked (SEG.ACK <= SND.UNA).
+ */
+bool seq_no_ack_duplicate(tcp_conn_t *conn, uint32_t seg_ack)
+{
+	uint32_t diff;
+
+	/*
+	 * There does not seem to be a three-point comparison
+	 * equivalent of SEG.ACK < SND.UNA. Thus we do it
+	 * on a best-effort basis, based on the difference.
+	 * [-2^31, 0) means less-than, 0 means equal, [0, 2^31)
+	 * means greater-than. Less-than or equal means duplicate.
+	 */
+	diff = seg_ack - conn->snd_una;
+	return diff == 0 || (diff & (0x1 << 31)) != 0;
+}
+
+/** Determine if sequence number is in receive window. */
+bool seq_no_in_rcv_wnd(tcp_conn_t *conn, uint32_t sn)
+{
+	return seq_no_le_lt(conn->rcv_nxt, sn, conn->rcv_nxt + conn->rcv_wnd);
+}
+
+/** Determine segment has new window update.
+ *
+ * Window update is new if either SND.WL1 < SEG.SEQ or
+ * (SND.WL1 = SEG.SEQ and SND.WL2 <= SEG.ACK).
+ */
+bool seq_no_new_wnd_update(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	bool n_seq, n_ack;
+
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	/*
+	 * We make use of the fact that the peer should not ACK anything
+	 * beyond our send window (we surely haven't sent that yet)
+	 * as we should have filtered those acks out.
+	 * We use SND.UNA+SND.WND as the third point of comparison.
+	 */
+
+	n_seq = seq_no_lt_le(conn->snd_wl1, seg->seq,
+	    conn->snd_una + conn->snd_wnd);
+
+	n_ack = conn->snd_wl1 == seg->seq &&
+	    seq_no_le_lt(conn->snd_wl2, seg->ack,
+	    conn->snd_una + conn->snd_wnd + 1);
+
+	return n_seq || n_ack;
+}
+
+/** Determine if segment is ready for processing.
+ *
+ * Assuming segment is acceptable, a segment is ready if it intersects
+ * RCV.NXT, that is we can process it immediately.
+ */
+bool seq_no_segment_ready(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	return seq_no_le_lt(seg->seq, conn->rcv_nxt, seg->seq + seg->len + 1);
+}
+
+/** Determine whether segment is fully acked */
+bool seq_no_segment_acked(tcp_conn_t *conn, tcp_segment_t *seg, uint32_t ack)
+{
+	assert(seg->len > 0);
+	return seq_no_lt_le(seg->seq, seg->seq + seg->len, ack);
+}
+
+/** Determine whether initial SYN is acked */
+bool seq_no_syn_acked(tcp_conn_t *conn)
+{
+	return seq_no_lt_le(conn->iss, conn->snd_una, conn->snd_nxt);
+}
+
+/** Determine whether segment overlaps the receive window */
+bool seq_no_segment_acceptable(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	bool b_in, e_in;
+
+	b_in = seq_no_le_lt(conn->rcv_nxt, seg->seq, conn->rcv_nxt
+	    + conn->rcv_wnd);
+
+	e_in = seq_no_le_lt(conn->rcv_nxt, seg->seq + seg->len - 1,
+	    conn->rcv_nxt + conn->rcv_wnd);
+
+	if (seg->len == 0 && conn->rcv_wnd == 0) {
+		return seg->seq == conn->rcv_nxt;
+	} else if (seg->len == 0 && conn->rcv_wnd != 0) {
+		return b_in;
+	} else if (seg->len > 0 && conn->rcv_wnd == 0) {
+		return false;
+	} else {
+		return b_in || e_in;
+	}
+}
+
+/** Determine size that control bits occupy in sequence space. */
+uint32_t seq_no_control_len(tcp_control_t ctrl)
+{
+	uint32_t len = 0;
+
+	if ((ctrl & CTL_SYN) != 0)
+		++len;
+
+	if ((ctrl & CTL_FIN) != 0)
+		++len;
+
+	return len;
+}
+
+/** Calculate the amount of trim needed to fit segment in receive window. */
+void seq_no_seg_trim_calc(tcp_conn_t *conn, tcp_segment_t *seg,
+    uint32_t *left, uint32_t *right)
+{
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	/*
+	 * If RCV.NXT is between SEG.SEQ and RCV.NXT+RCV.WND, then
+	 * left trim amount is positive
+	 */
+	if (seq_no_lt_le(seg->seq, conn->rcv_nxt,
+	    conn->rcv_nxt + conn->rcv_wnd)) {
+		*left = conn->rcv_nxt - seg->seq;
+	} else {
+		*left = 0;
+	}
+
+	/*
+	 * If SEG.SEQ+SEG.LEN is between SEG.SEQ and RCV.NXT+RCV.WND,
+	 * then right trim is zero.
+	 */
+	if (seq_no_lt_le(seg->seq - 1, seg->seq + seg->len,
+	    conn->rcv_nxt + conn->rcv_wnd)) {
+		*right = 0;
+	} else {
+		*right = (seg->seq + seg->len) -
+		    (conn->rcv_nxt + conn->rcv_wnd);
+	}
+}
+
+/** Segment order comparison.
+ *
+ * Compare sequence order of two acceptable segments.
+ *
+ * @param conn		Connection
+ * @param sa		Segment A
+ * @param sb		Segment B
+ *
+ * @return		-1, 0, 1, resp. if A < B, A == B, A > B in terms
+ *			of sequence order of the beginning of the segment.
+ */
+int seq_no_seg_cmp(tcp_conn_t *conn, tcp_segment_t *sa, tcp_segment_t *sb)
+{
+	assert(seq_no_segment_acceptable(conn, sa));
+	assert(seq_no_segment_acceptable(conn, sb));
+
+	if (seq_no_lt_le(sa->seq, sb->seq, conn->rcv_nxt + conn->rcv_wnd))
+		return -1;
+
+	if (seq_no_lt_le(sb->seq, sa->seq, conn->rcv_nxt + conn->rcv_wnd))
+		return +1;
+
+	assert(sa->seq == sb->seq);
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/seq_no.h
===================================================================
--- uspace/srv/net/tcp/seq_no.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/seq_no.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,58 @@
+/*
+ * 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 Sequence number computations
+ */
+
+#ifndef SEQ_NO_H
+#define SEQ_NO_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+extern bool seq_no_ack_acceptable(tcp_conn_t *, uint32_t);
+extern bool seq_no_ack_duplicate(tcp_conn_t *, uint32_t);
+extern bool seq_no_in_rcv_wnd(tcp_conn_t *, uint32_t);
+extern bool seq_no_new_wnd_update(tcp_conn_t *, tcp_segment_t *);
+extern bool seq_no_segment_acked(tcp_conn_t *, tcp_segment_t *, uint32_t);
+extern bool seq_no_syn_acked(tcp_conn_t *);
+extern bool seq_no_segment_ready(tcp_conn_t *, tcp_segment_t *);
+extern bool seq_no_segment_acceptable(tcp_conn_t *, tcp_segment_t *);
+extern void seq_no_seg_trim_calc(tcp_conn_t *, tcp_segment_t *, uint32_t *,
+    uint32_t *);
+extern int seq_no_seg_cmp(tcp_conn_t *, tcp_segment_t *, tcp_segment_t *);
+
+extern uint32_t seq_no_control_len(tcp_control_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/sock.c
===================================================================
--- uspace/srv/net/tcp/sock.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/sock.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,848 @@
+/*
+ * 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/modules.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 FRAGMENT_SIZE 1024
+
+#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);
+
+int tcp_sock_init(void)
+{
+	int rc;
+
+	socket_ports_initialize(&gsock);
+
+	async_set_client_connection(tcp_sock_connection);
+
+	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(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,
+	    FRAGMENT_SIZE, 0, 0, 1);
+	async_exchange_end(exch);
+}
+
+static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
+{
+	log_msg(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,
+	    FRAGMENT_SIZE, 0, 0, 0);
+	async_exchange_end(exch);
+}
+
+static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	tcp_sockdata_t *sock;
+	socket_core_t *sock_core;
+	int sock_id;
+	int rc;
+	ipc_call_t answer;
+
+	log_msg(LVL_DEBUG, "tcp_sock_socket()");
+	sock = calloc(sizeof(tcp_sockdata_t), 1);
+	if (sock == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_initialize(&sock->lock);
+	sock->client = client;
+	sock->laddr.ipv4 = TCP_IPV4_ANY;
+	sock->lconn = NULL;
+	sock->backlog = 0;
+	list_initialize(&sock->ready);
+
+	sock_id = SOCKET_GET_SOCKET_ID(call);
+	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sock_core = socket_cores_find(&client->sockets, sock_id);
+	assert(sock_core != NULL);
+	sock->sock_core = sock_core;
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_SOCKET_ID(answer, sock_id);
+
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
+	answer_call(callid, EOK, &answer, 3);
+}
+
+static void tcp_sock_bind(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int rc;
+	struct sockaddr *addr;
+	size_t addr_len;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+
+	log_msg(LVL_DEBUG, "tcp_sock_bind()");
+	log_msg(LVL_DEBUG, " - async_data_write_accept");
+	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_bind");
+	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
+	    addr, addr_len, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
+	    last_used_port);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_cores_find");
+	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
+	if (sock_core != NULL) {
+		socket = (tcp_sockdata_t *)sock_core->specific_data;
+		/* XXX Anything to do? */
+		(void) socket;
+	}
+
+	log_msg(LVL_DEBUG, " - success");
+	async_answer_0(callid, EOK);
+}
+
+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;
+
+	log_msg(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;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+
+	/*
+	 * Prepare @c backlog listening connections.
+	 */
+	fibril_mutex_lock(&socket->lock);
+
+	socket->backlog = backlog;
+	socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
+	if (socket->lconn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - open connections");
+
+	lsocket.addr.ipv4 = TCP_IPV4_ANY;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = TCP_IPV4_ANY;
+	fsocket.port = TCP_PORT_ANY;
+
+	for (i = 0; i < backlog; i++) {
+
+		lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
+		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)
+{
+	int rc;
+	struct sockaddr_in *addr;
+	int socket_id;
+	size_t addr_len;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	tcp_error_t trc;
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+
+	log_msg(LVL_DEBUG, "tcp_sock_connect()");
+
+	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
+	if (rc != EOK || addr_len != sizeof(struct sockaddr_in)) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	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;
+	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;
+	}
+
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
+		/* Determine local IP address */
+		inet_addr_t loc_addr, rem_addr;
+
+		rem_addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+		rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			log_msg(LVL_DEBUG, "tcp_sock_connect: Failed to "
+			    "determine local address.");
+			return;
+		}
+
+		socket->laddr.ipv4 = loc_addr.ipv4;
+		log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
+	}
+
+	lsocket.addr.ipv4 = socket->laddr.ipv4;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+	fsocket.port = uint16_t_be2host(addr->sin_port);
+
+	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);
+	}
+
+	async_answer_0(callid, rc);
+
+	/* Push one fragment notification to client's queue */
+	tcp_sock_notify_data(sock_core);
+	log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");
+}
+
+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;
+	socket_core_t *asock_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(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;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	log_msg(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 */
+
+	lsocket.addr.ipv4 = TCP_IPV4_ANY;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = TCP_IPV4_ANY;
+	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 */
+
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
+	asocket = calloc(sizeof(tcp_sockdata_t), 1);
+	if (asocket == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_initialize(&asocket->lock);
+	asocket->client = client;
+	asocket->conn = conn;
+	log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
+
+	rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
+
+	asock_core = socket_cores_find(&client->sockets, asock_id);
+	assert(asock_core != NULL);
+
+	refresh_answer(&answer, NULL);
+
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_SOCKET_ID(answer, asock_id);
+	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
+
+	answer_call(callid, asock_core->socket_id, &answer, 3);
+
+	/* Push one fragment notification to client's queue */
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
+	tcp_sock_notify_data(asock_core);
+	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;
+	uint8_t buffer[FRAGMENT_SIZE];
+	tcp_error_t trc;
+	int rc;
+
+	log_msg(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);
+		return;
+	}
+
+	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);
+			return;
+		}
+
+		if (length > FRAGMENT_SIZE)
+			length = FRAGMENT_SIZE;
+
+		rc = async_data_write_finalize(wcallid, buffer, length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			return;
+		}
+
+		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);
+			return;
+		}
+	}
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	answer_call(callid, EOK, &answer, 2);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(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)
+{
+	int socket_id;
+	int flags;
+	size_t addr_length, length;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	ipc_call_t answer;
+	ipc_callid_t rcallid;
+	uint8_t buffer[FRAGMENT_SIZE];
+	size_t data_len;
+	xflags_t xflags;
+	tcp_error_t trc;
+	struct sockaddr_in addr;
+	tcp_sock_t *rsock;
+	int rc;
+
+	log_msg(LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	flags = SOCKET_GET_FLAGS(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) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOTCONN);
+		return;
+	}
+
+	(void)flags;
+
+	trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len,
+	    &xflags);
+	log_msg(LVL_DEBUG, "**** tcp_uc_receive done");
+
+	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(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
+		/* Fill addr */
+		rsock = &socket->conn->ident.foreign;
+		addr.sin_family = AF_INET;
+		addr.sin_addr.s_addr = host2uint32_t_be(rsock->addr.ipv4);
+		addr.sin_port = host2uint16_t_be(rsock->port);
+
+		log_msg(LVL_DEBUG, "addr read receive");
+		if (!async_data_read_receive(&rcallid, &addr_length)) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+
+		if (addr_length > sizeof(addr))
+			addr_length = sizeof(addr);
+
+		log_msg(LVL_DEBUG, "addr read finalize");
+		rc = async_data_read_finalize(rcallid, &addr, addr_length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "data read receive");
+	if (!async_data_read_receive(&rcallid, &length)) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (length > data_len)
+		length = data_len;
+
+	log_msg(LVL_DEBUG, "data read finalize");
+	rc = async_data_read_finalize(rcallid, buffer, length);
+
+	if (length < data_len && rc == EOK)
+		rc = EOVERFLOW;
+
+	SOCKET_SET_READ_DATA_LENGTH(answer, length);
+	answer_call(callid, EOK, &answer, 1);
+
+	/* Push one fragment notification to client's queue */
+	tcp_sock_notify_data(sock_core);
+	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 rc;
+	uint8_t buffer[FRAGMENT_SIZE];
+	size_t data_len;
+	xflags_t xflags;
+
+	log_msg(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) {
+		trc = tcp_uc_close(socket->conn);
+		if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EBADF);
+			return;
+		}
+
+		/* Drain incoming data. This should really be done in the background. */
+		do {
+			trc = tcp_uc_receive(socket->conn, buffer,
+			    FRAGMENT_SIZE, &data_len, &xflags);
+		} while (trc == TCP_EOK);
+
+		tcp_uc_delete(socket->conn);
+	}
+
+	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(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(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(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(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 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(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(LVL_DEBUG, "tcp_sock_connection: Clean up");
+	async_hangup(client.sess);
+	socket_cores_release(NULL, &client.sockets, &gsock, tcp_free_sock_data);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/sock.h
===================================================================
--- uspace/srv/net/tcp/sock.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/sock.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,45 @@
+/*
+ * 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/std.h
===================================================================
--- uspace/srv/net/tcp/std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,101 @@
+/*
+ * 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 TCP header definitions
+ *
+ * Based on IETF RFC 793
+ */
+
+#ifndef STD_H
+#define STD_H
+
+#include <sys/types.h>
+
+/** TCP Header (fixed part) */
+typedef struct {
+	/** Source port */
+	uint16_t src_port;
+	/** Destination port */
+	uint16_t dest_port;
+	/** Sequence number */
+	uint32_t seq;
+	/** Acknowledgement number */
+	uint32_t ack;
+	/** Data Offset, Reserved, Flags */
+	uint16_t doff_flags;
+	/** Window */
+	uint16_t window;
+	/* Checksum */
+	uint16_t checksum;
+	/** Urgent pointer */
+	uint16_t urg_ptr;
+} tcp_header_t;
+
+/** Bits in tcp_header_t.doff_flags */
+enum doff_flags_bits {
+	DF_DATA_OFFSET_h	= 15,
+	DF_DATA_OFFSET_l	= 12,
+	DF_URG			= 5,
+	DF_ACK			= 4,
+	DF_PSH			= 3,
+	DF_RST			= 2,
+	DF_SYN			= 1,
+	DF_FIN			= 0
+};
+
+/** TCP pseudo header */
+typedef struct {
+	/** Source address */
+	uint32_t src_addr;
+	/** Destination address */
+	uint32_t dest_addr;
+	/** Zero */
+	uint8_t zero;
+	/** Protocol */
+	uint8_t protocol;
+	/** TCP length */
+	uint16_t tcp_length;
+} tcp_phdr_t;
+
+/** Option kind */
+enum opt_kind {
+	/** End of option list */
+	OPT_END_LIST		= 0,
+	/** No-operation */
+	OPT_NOP			= 1,
+	/** Maximum segment size */
+	OPT_MAX_SEG_SIZE	= 2
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/tcp.c
===================================================================
--- uspace/srv/net/tcp/tcp.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/tcp.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,230 @@
+/*
+ * 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 TCP (Transmission Control Protocol) network module
+ */
+
+#include <async.h>
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <inet/inet.h>
+#include <io/log.h>
+#include <stdio.h>
+#include <task.h>
+
+#include "ncsim.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "sock.h"
+#include "std.h"
+#include "tcp.h"
+#include "test.h"
+
+#define NAME       "tcp"
+
+#define IP_PROTO_TCP 6
+
+static int tcp_inet_ev_recv(inet_dgram_t *dgram);
+static void tcp_received_pdu(tcp_pdu_t *pdu);
+
+static inet_ev_ops_t tcp_inet_ev_ops = {
+	.recv = tcp_inet_ev_recv
+};
+
+/** Received datagram callback */
+static int tcp_inet_ev_recv(inet_dgram_t *dgram)
+{
+	uint8_t *pdu_raw;
+	size_t pdu_raw_size;
+
+	log_msg(LVL_DEBUG, "tcp_inet_ev_recv()");
+
+	pdu_raw = dgram->data;
+	pdu_raw_size = dgram->size;
+
+	/* Split into header and payload. */
+
+	log_msg(LVL_DEBUG, "tcp_inet_ev_recv() - split header/payload");
+
+	tcp_pdu_t *pdu;
+	size_t hdr_size;
+	tcp_header_t *hdr;
+	uint32_t data_offset;
+
+	if (pdu_raw_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
+		    pdu_raw_size, sizeof(tcp_header_t));
+		return EINVAL;
+	}
+
+	hdr = (tcp_header_t *)pdu_raw;
+	data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
+	    uint16_t_be2host(hdr->doff_flags));
+
+	hdr_size = sizeof(uint32_t) * data_offset;
+
+	if (pdu_raw_size < hdr_size) {
+		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
+		    pdu_raw_size, hdr_size);
+		return EINVAL;
+	}
+
+	if (hdr_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
+		    hdr_size, sizeof(tcp_header_t));		return EINVAL;
+	}
+
+	log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
+	    pdu_raw_size, hdr_size);
+	pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
+	    pdu_raw_size - hdr_size);
+	if (pdu == NULL) {
+		log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
+		return ENOMEM;
+	}
+
+	pdu->src_addr.ipv4 = dgram->src.ipv4;
+	pdu->dest_addr.ipv4 = dgram->dest.ipv4;
+	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
+	    pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
+
+	tcp_received_pdu(pdu);
+	tcp_pdu_delete(pdu);
+
+	return EOK;
+}
+
+/** Transmit PDU over network layer. */
+void tcp_transmit_pdu(tcp_pdu_t *pdu)
+{
+	int rc;
+	uint8_t *pdu_raw;
+	size_t pdu_raw_size;
+	inet_dgram_t dgram;
+
+	pdu_raw_size = pdu->header_size + pdu->text_size;
+	pdu_raw = malloc(pdu_raw_size);
+	if (pdu_raw == NULL) {
+		log_msg(LVL_ERROR, "Failed to transmit PDU. Out of memory.");
+		return;
+	}
+
+	memcpy(pdu_raw, pdu->header, pdu->header_size);
+	memcpy(pdu_raw + pdu->header_size, pdu->text,
+	    pdu->text_size);
+
+	dgram.src.ipv4 = pdu->src_addr.ipv4;
+	dgram.dest.ipv4 = pdu->dest_addr.ipv4;
+	dgram.tos = 0;
+	dgram.data = pdu_raw;
+	dgram.size = pdu_raw_size;
+
+	rc = inet_send(&dgram, INET_TTL_MAX, 0);
+	if (rc != EOK)
+		log_msg(LVL_ERROR, "Failed to transmit PDU.");
+}
+
+/** Process received PDU. */
+static void tcp_received_pdu(tcp_pdu_t *pdu)
+{
+	tcp_segment_t *dseg;
+	tcp_sockpair_t rident;
+
+	log_msg(LVL_DEBUG, "tcp_received_pdu()");
+
+	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
+		return;
+	}
+
+	/* Insert decoded segment into rqueue */
+	tcp_rqueue_insert_seg(&rident, dseg);
+}
+
+static int tcp_init(void)
+{
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_init()");
+
+	tcp_rqueue_init();
+	tcp_rqueue_thread_start();
+
+	tcp_ncsim_init();
+	tcp_ncsim_thread_start();
+
+	if (0) tcp_test();
+
+	rc = inet_init(IP_PROTO_TCP, &tcp_inet_ev_ops);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		return ENOENT;
+	}
+
+	rc = tcp_sock_init();
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed initializing socket service.");
+		return ENOENT;
+	}
+
+	return EOK;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+
+	printf(NAME ": TCP (Transmission Control Protocol) network module\n");
+
+	rc = log_init(NAME, LVL_WARN);
+	if (rc != EOK) {
+		printf(NAME ": Failed to initialize log.\n");
+		return 1;
+	}
+
+	rc = tcp_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/tcp.h
===================================================================
--- uspace/srv/net/tcp/tcp.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/tcp.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,46 @@
+/*
+ * 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 TCP (Transmission Control Protocol) network module
+ */
+
+#ifndef TCP_H
+#define TCP_H
+
+#include <async.h>
+#include "tcp_type.h"
+
+extern void tcp_transmit_pdu(tcp_pdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tcp/tcp_type.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/tcp_type.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,363 @@
+/*
+ * 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 TCP type definitions
+ */
+
+#ifndef TCP_TYPE_H
+#define TCP_TYPE_H
+
+#include <adt/list.h>
+#include <async.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <socket_core.h>
+#include <sys/types.h>
+
+struct tcp_conn;
+
+typedef enum {
+	/** Listen */
+	st_listen,
+	/** Syn-sent */
+	st_syn_sent,
+	/** Syn-received */
+	st_syn_received,
+	/** Established */
+	st_established,
+	/** Fin-wait-1 */
+	st_fin_wait_1,
+	/** Fin-wait-2 */
+	st_fin_wait_2,
+	/** Close-wait */
+	st_close_wait,
+	/** Closing */
+	st_closing,
+	/** Last-ack */
+	st_last_ack,
+	/** Time-wait */
+	st_time_wait,
+	/** Closed */
+	st_closed
+} tcp_cstate_t;
+
+/** Error codes returned by TCP user calls (per the spec). */
+typedef enum {
+	/* OK */
+	TCP_EOK,
+	/* Connection aborted due to user timeout */
+	TCP_EABORTED,
+	/* Connection already exists */
+	TCP_EEXISTS,
+	/* Connection closing */
+	TCP_ECLOSING,
+	/* Connection does not exist */
+	TCP_ENOTEXIST,
+	/* Connection illegal for this process */
+	TCP_EILLEGAL,
+	/* Connection not open */
+	TCP_ENOTOPEN,
+	/* Connection reset */
+	TCP_ERESET,
+	/* Foreign socket unspecified */
+	TCP_EUNSPEC,
+	/* Insufficient resources */
+	TCP_ENORES,
+	/* Precedence not allowed */
+	TCP_EINVPREC,
+	/* Security/compartment not allowed */
+	TCP_EINVCOMP
+} tcp_error_t;
+
+typedef enum {
+	XF_PUSH		= 0x1,
+	XF_URGENT	= 0x2
+} xflags_t;
+
+typedef enum {
+	CTL_SYN		= 0x1,
+	CTL_FIN		= 0x2,
+	CTL_RST		= 0x4,
+	CTL_ACK		= 0x8
+} tcp_control_t;
+
+typedef struct {
+	uint32_t ipv4;
+} netaddr_t;
+
+typedef struct {
+	netaddr_t addr;
+	uint16_t port;
+} tcp_sock_t;
+
+enum netaddr {
+	TCP_IPV4_ANY = 0
+};
+
+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 {
+	struct tcp_conn *conn;
+	list_t list;
+} tcp_iqueue_t;
+
+/** Retransmission queue */
+typedef struct {
+	struct tcp_conn *conn;
+	list_t list;
+
+	/** Retransmission timer */
+	fibril_timer_t *timer;
+} tcp_tqueue_t;
+
+typedef enum {
+	ap_active,
+	ap_passive
+} acpass_t;
+
+typedef enum {
+	tcp_open_nonblock = 1
+} tcp_open_flags_t;
+
+typedef struct tcp_conn tcp_conn_t;
+
+/** Connection state change callback function */
+typedef void (*tcp_cstate_cb_t)(tcp_conn_t *, void *);
+
+/** Connection */
+struct tcp_conn {
+	char *name;
+	link_t link;
+
+	/** Connection state change callback function */
+	tcp_cstate_cb_t cstate_cb;
+	/** Argument to @c cstate_cb */
+	void *cstate_cb_arg;
+
+	/** Connection identification (local and foreign socket) */
+	tcp_sockpair_t ident;
+
+	/** Active or passive connection */
+	acpass_t ap;
+
+	/** Protects access to connection structure */
+	fibril_mutex_t lock;
+	/** Reference count */
+	atomic_t refcnt;
+
+	/** Connection state */
+	tcp_cstate_t cstate;
+	/** True if connection was reset */
+	bool reset;
+	/** True if connection was deleted by user */
+	bool deleted;
+	/** Signalled when @c cstate changes */
+	fibril_condvar_t cstate_cv;
+
+	/** Set when FIN is removed from the retransmission queue */
+	bool fin_is_acked;
+
+	/** Queue of incoming segments */
+	tcp_iqueue_t incoming;
+
+	/** Retransmission queue */
+	tcp_tqueue_t retransmit;
+
+	/** Time-Wait timeout timer */
+	fibril_timer_t *tw_timer;
+
+	/** Receive buffer */
+	uint8_t *rcv_buf;
+	/** Receive buffer size */
+	size_t rcv_buf_size;
+	/** Receive buffer number of bytes used */
+	size_t rcv_buf_used;
+	/** Receive buffer contains FIN */
+	bool rcv_buf_fin;
+	/** Receive buffer CV. Broadcast when new data is inserted */
+	fibril_condvar_t rcv_buf_cv;
+
+	/** Send buffer */
+	uint8_t *snd_buf;
+	/** Send buffer size */
+	size_t snd_buf_size;
+	/** Send buffer number of bytes used */
+	size_t snd_buf_used;
+	/** Send buffer contains FIN */
+	bool snd_buf_fin;
+	/** Send buffer CV. Broadcast when space is made available in buffer */
+	fibril_condvar_t snd_buf_cv;
+
+	/** Send unacknowledged */
+	uint32_t snd_una;
+	/** Send next */
+	uint32_t snd_nxt;
+	/** Send window */
+	uint32_t snd_wnd;
+	/** Send urgent pointer */
+	uint32_t snd_up;
+	/** Segment sequence number used for last window update */
+	uint32_t snd_wl1;
+	/** Segment acknowledgement number used for last window update */
+	uint32_t snd_wl2;
+	/** Initial send sequence number */
+	uint32_t iss;
+
+	/** Receive next */
+	uint32_t rcv_nxt;
+	/** Receive window */
+	uint32_t rcv_wnd;
+	/** Receive urgent pointer */
+	uint32_t rcv_up;
+	/** Initial receive sequence number */
+	uint32_t irs;
+};
+
+/** Data returned by Status user call */
+typedef struct {
+	/** Connection state */
+	tcp_cstate_t cstate;
+} tcp_conn_status_t;
+
+typedef struct {
+	/** SYN, FIN */
+	tcp_control_t ctrl;
+
+	/** Segment sequence number */
+	uint32_t seq;
+	/** Segment acknowledgement number */
+	uint32_t ack;
+	/** Segment length in sequence space */
+	uint32_t len;
+	/** Segment window */
+	uint32_t wnd;
+	/** Segment urgent pointer */
+	uint32_t up;
+
+	/** Segment data, may be moved when trimming segment */
+	void *data;
+	/** Segment data, original pointer used to free data */
+	void *dfptr;
+} tcp_segment_t;
+
+
+typedef struct {
+	link_t link;
+	tcp_sockpair_t sp;
+	tcp_segment_t *seg;
+} tcp_rqueue_entry_t;
+
+/** NCSim queue entry */
+typedef struct {
+	link_t link;
+	suseconds_t delay;
+	tcp_sockpair_t sp;
+	tcp_segment_t *seg;
+} tcp_squeue_entry_t;
+
+typedef struct {
+	link_t link;
+	tcp_segment_t *seg;
+} tcp_iqueue_entry_t;
+
+/** Retransmission queue entry */
+typedef struct {
+	link_t link;
+	tcp_conn_t *conn;
+	tcp_segment_t *seg;
+} tcp_tqueue_entry_t;
+
+typedef enum {
+	cp_continue,
+	cp_done
+} cproc_t;
+
+/** Encoded PDU */
+typedef struct {
+	/** Source address */
+	netaddr_t src_addr;
+	/** Destination address */
+	netaddr_t dest_addr;
+
+	/** Encoded header */
+	void *header;
+	/** Encoded header size */
+	size_t header_size;
+	/** Text */
+	void *text;
+	/** Text size */
+	size_t text_size;
+} tcp_pdu_t;
+
+typedef struct {
+	async_sess_t *sess;
+	socket_cores_t sockets;
+} tcp_client_t;
+
+typedef struct tcp_sockdata {
+	/** Lock */
+	fibril_mutex_t lock;
+	/** Socket core */
+	socket_core_t *sock_core;
+	/** Client */
+	tcp_client_t *client;
+	/** Connection */
+	tcp_conn_t *conn;
+	/** Local address */
+	netaddr_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;
+} tcp_sockdata_t;
+
+typedef struct tcp_sock_lconn {
+	tcp_conn_t *conn;
+	tcp_sockdata_t *socket;
+	int index;
+	link_t ready_list;
+} tcp_sock_lconn_t;
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/test.c
===================================================================
--- uspace/srv/net/tcp/test.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/test.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,145 @@
+/*
+ * 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 Internal TCP test
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include <thread.h>
+#include <str.h>
+#include "tcp_type.h"
+#include "ucall.h"
+
+#include "test.h"
+
+#define RCV_BUF_SIZE 64
+
+static void test_srv(void *arg)
+{
+	tcp_conn_t *conn;
+	tcp_sock_t lsock;
+	tcp_sock_t fsock;
+	char rcv_buf[RCV_BUF_SIZE + 1];
+	size_t rcvd;
+	xflags_t xflags;
+
+	printf("test_srv()\n");
+	lsock.port = 80;
+	lsock.addr.ipv4 = 0x7f000001;
+	fsock.port = 1024;
+	fsock.addr.ipv4 = 0x7f000001;
+	printf("S: User open...\n");
+	tcp_uc_open(&lsock, &fsock, ap_passive, 0, &conn);
+	conn->name = (char *) "S";
+
+	while (true) {
+		printf("S: User receive...\n");
+		tcp_uc_receive(conn, rcv_buf, RCV_BUF_SIZE, &rcvd, &xflags);
+		if (rcvd == 0) {
+			printf("S: End of data reached.\n");
+			break;
+		}
+		rcv_buf[rcvd] = '\0';
+		printf("S: User received %zu bytes '%s'.\n", rcvd, rcv_buf);
+
+		async_usleep(1000*1000*2);
+	}
+
+	async_usleep(/*10**/1000*1000);
+
+	printf("S: User close...\n");
+	tcp_uc_close(conn);
+
+	printf("test_srv() terminating\n");
+}
+
+static void test_cli(void *arg)
+{
+	tcp_conn_t *conn;
+	tcp_sock_t lsock;
+	tcp_sock_t fsock;
+	const char *msg = "Hello World!";
+
+	printf("test_cli()\n");
+
+	lsock.port = 1024;
+	lsock.addr.ipv4 = 0x7f000001;
+	fsock.port = 80;
+	fsock.addr.ipv4 = 0x7f000001;
+
+	async_usleep(1000*1000*3);
+	printf("C: User open...\n");
+	tcp_uc_open(&lsock, &fsock, ap_active, 0, &conn);
+	conn->name = (char *) "C";
+
+	async_usleep(1000*1000*10);
+	printf("C: User send...\n");
+	tcp_uc_send(conn, (void *)msg, str_size(msg), 0);
+
+	async_usleep(1000*1000*20/**20*2*/);
+	printf("C: User close...\n");
+	tcp_uc_close(conn);
+}
+
+void tcp_test(void)
+{
+	thread_id_t srv_tid;
+	thread_id_t cli_tid;
+	int rc;
+
+	printf("tcp_test()\n");
+
+	async_usleep(1000*1000);
+
+	if (0) {
+		rc = thread_create(test_srv, NULL, "test_srv", &srv_tid);
+		if (rc != EOK) {
+			printf("Failed to create server thread.\n");
+			return;
+		}
+	}
+
+	if (0) {
+		rc = thread_create(test_cli, NULL, "test_cli", &cli_tid);
+		if (rc != EOK) {
+			printf("Failed to create client thread.\n");
+			return;
+		}
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/test.h
===================================================================
--- uspace/srv/net/tcp/test.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/test.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,43 @@
+/*
+ * 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 Internal TCP test
+ */
+
+#ifndef TEST_H
+#define TEST_H
+
+extern void tcp_test(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/tqueue.c
===================================================================
--- uspace/srv/net/tcp/tqueue.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/tqueue.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,381 @@
+/*
+ * 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 TCP transmission queue
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <byteorder.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "conn.h"
+#include "ncsim.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tqueue.h"
+#include "tcp.h"
+#include "tcp_type.h"
+
+#define RETRANSMIT_TIMEOUT	(2*1000*1000)
+
+static void retransmit_timeout_func(void *arg);
+static void tcp_tqueue_timer_set(tcp_conn_t *conn);
+static void tcp_tqueue_timer_clear(tcp_conn_t *conn);
+
+int tcp_tqueue_init(tcp_tqueue_t *tqueue, tcp_conn_t *conn)
+{
+	tqueue->conn = conn;
+	tqueue->timer = fibril_timer_create();
+	if (tqueue->timer == NULL)
+		return ENOMEM;
+
+	list_initialize(&tqueue->list);
+
+	return EOK;
+}
+
+void tcp_tqueue_clear(tcp_tqueue_t *tqueue)
+{
+	tcp_tqueue_timer_clear(tqueue->conn);
+}
+
+void tcp_tqueue_fini(tcp_tqueue_t *tqueue)
+{
+	if (tqueue->timer != NULL) {
+		fibril_timer_destroy(tqueue->timer);
+		tqueue->timer = NULL;
+	}
+}
+
+void tcp_tqueue_ctrl_seg(tcp_conn_t *conn, tcp_control_t ctrl)
+{
+	tcp_segment_t *seg;
+
+	log_msg(LVL_DEBUG, "tcp_tqueue_ctrl_seg(%p, %u)", conn, ctrl);
+
+	seg = tcp_segment_make_ctrl(ctrl);
+	tcp_tqueue_seg(conn, seg);
+}
+
+void tcp_tqueue_seg(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	tcp_segment_t *rt_seg;
+	tcp_tqueue_entry_t *tqe;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_seg(%p, %p)", conn->name, conn,
+	    seg);
+
+	/*
+	 * Add segment to retransmission queue
+	 */
+
+	if (seg->len > 0) {
+		rt_seg = tcp_segment_dup(seg);
+		if (rt_seg == NULL) {
+			log_msg(LVL_ERROR, "Memory allocation failed.");
+			/* XXX Handle properly */
+			return;
+		}
+
+		tqe = calloc(1, sizeof(tcp_tqueue_entry_t));
+		if (tqe == NULL) {
+			log_msg(LVL_ERROR, "Memory allocation failed.");
+			/* XXX Handle properly */
+			return;
+		}
+
+		tqe->conn = conn;
+		tqe->seg = rt_seg;
+		rt_seg->seq = conn->snd_nxt;
+
+		list_append(&tqe->link, &conn->retransmit.list);
+
+		/* Set retransmission timer */
+		tcp_tqueue_timer_set(conn);
+	}
+
+	tcp_prepare_transmit_segment(conn, seg);
+}
+
+void tcp_prepare_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/*
+	 * Always send ACK once we have received SYN, except for RST segments.
+	 * (Spec says we should always send ACK once connection has been
+	 * established.)
+	 */
+	if (tcp_conn_got_syn(conn) && (seg->ctrl & CTL_RST) == 0)
+		seg->ctrl |= CTL_ACK;
+
+	seg->seq = conn->snd_nxt;
+	conn->snd_nxt += seg->len;
+
+	tcp_conn_transmit_segment(conn, seg);
+}
+
+/** Transmit data from the send buffer.
+ *
+ * @param conn	Connection
+ */
+void tcp_tqueue_new_data(tcp_conn_t *conn)
+{
+	size_t avail_wnd;
+	size_t xfer_seqlen;
+	size_t snd_buf_seqlen;
+	size_t data_size;
+	tcp_control_t ctrl;
+	bool send_fin;
+
+	tcp_segment_t *seg;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_new_data()", conn->name);
+
+	/* Number of free sequence numbers in send window */
+	avail_wnd = (conn->snd_una + conn->snd_wnd) - conn->snd_nxt;
+	snd_buf_seqlen = conn->snd_buf_used + (conn->snd_buf_fin ? 1 : 0);
+
+	xfer_seqlen = min(snd_buf_seqlen, avail_wnd);
+	log_msg(LVL_DEBUG, "%s: snd_buf_seqlen = %zu, SND.WND = %zu, "
+	    "xfer_seqlen = %zu", conn->name, snd_buf_seqlen, conn->snd_wnd,
+	    xfer_seqlen);
+
+	if (xfer_seqlen == 0)
+		return;
+
+	/* XXX Do not always send immediately */
+
+	send_fin = conn->snd_buf_fin && xfer_seqlen == snd_buf_seqlen;
+	data_size = xfer_seqlen - (send_fin ? 1 : 0);
+
+	if (send_fin) {
+		log_msg(LVL_DEBUG, "%s: Sending out FIN.", conn->name);
+		/* We are sending out FIN */
+		ctrl = CTL_FIN;
+	} else {
+		ctrl = 0;
+	}
+
+	seg = tcp_segment_make_data(ctrl, conn->snd_buf, data_size);
+	if (seg == NULL) {
+		log_msg(LVL_ERROR, "Memory allocation failure.");
+		return;
+	}
+
+	/* Remove data from send buffer */
+	memmove(conn->snd_buf, conn->snd_buf + data_size,
+	    conn->snd_buf_used - data_size);
+	conn->snd_buf_used -= data_size;
+
+	if (send_fin)
+		conn->snd_buf_fin = false;
+
+	fibril_condvar_broadcast(&conn->snd_buf_cv);
+
+	if (send_fin)
+		tcp_conn_fin_sent(conn);
+
+	tcp_tqueue_seg(conn, seg);
+}
+
+/** Remove ACKed segments from retransmission queue and possibly transmit
+ * more data.
+ *
+ * This should be called when SND.UNA is updated due to incoming ACK.
+ */
+void tcp_tqueue_ack_received(tcp_conn_t *conn)
+{
+	link_t *cur, *next;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_ack_received(%p)", conn->name,
+	    conn);
+
+	cur = conn->retransmit.list.head.next;
+
+	while (cur != &conn->retransmit.list.head) {
+		next = cur->next;
+
+		tcp_tqueue_entry_t *tqe = list_get_instance(cur,
+		    tcp_tqueue_entry_t, link);
+
+		if (seq_no_segment_acked(conn, tqe->seg, conn->snd_una)) {
+			/* Remove acknowledged segment */
+			list_remove(cur);
+
+			if ((tqe->seg->ctrl & CTL_FIN) != 0) {
+				log_msg(LVL_DEBUG, "Fin has been acked");
+				log_msg(LVL_DEBUG, "SND.UNA=%" PRIu32
+				    " SEG.SEQ=%" PRIu32 " SEG.LEN=%" PRIu32,
+				    conn->snd_una, tqe->seg->seq, tqe->seg->len);
+				/* Our FIN has been acked */
+				conn->fin_is_acked = true;
+			}
+
+			tcp_segment_delete(tqe->seg);
+			free(tqe);
+
+			/* Reset retransmission timer */
+			tcp_tqueue_timer_set(conn);
+		}
+
+		cur = next;
+	}
+
+	/* Clear retransmission timer if the queue is empty. */
+	if (list_empty(&conn->retransmit.list))
+		tcp_tqueue_timer_clear(conn);
+
+	/* Possibly transmit more data */
+	tcp_tqueue_new_data(conn);
+}
+
+void tcp_conn_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_transmit_segment(%p, %p)",
+	    conn->name, conn, seg);
+
+	seg->wnd = conn->rcv_wnd;
+
+	if ((seg->ctrl & CTL_ACK) != 0)
+		seg->ack = conn->rcv_nxt;
+	else
+		seg->ack = 0;
+
+	tcp_transmit_segment(&conn->ident, seg);
+}
+
+void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_transmit_segment(f:(%x,%u),l:(%x,%u), %p)",
+	    sp->foreign.addr.ipv4, sp->foreign.port,
+	    sp->local.addr.ipv4, sp->local.port, seg);
+
+	log_msg(LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
+	    seg->seq, seg->wnd);
+
+	tcp_segment_dump(seg);
+/*
+	tcp_pdu_prepare(conn, seg, &data, &len);
+	tcp_pdu_transmit(data, len);
+*/
+//	tcp_rqueue_bounce_seg(sp, seg);
+//	tcp_ncsim_bounce_seg(sp, seg);
+
+	tcp_pdu_t *pdu;
+
+	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	tcp_transmit_pdu(pdu);
+	tcp_pdu_delete(pdu);
+}
+
+static void retransmit_timeout_func(void *arg)
+{
+	tcp_conn_t *conn = (tcp_conn_t *) arg;
+	tcp_tqueue_entry_t *tqe;
+	tcp_segment_t *rt_seg;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_DEBUG, "Connection already closed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	link = list_first(&conn->retransmit.list);
+	if (link == NULL) {
+		log_msg(LVL_DEBUG, "Nothing to retransmit");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	tqe = list_get_instance(link, tcp_tqueue_entry_t, link);
+
+	rt_seg = tcp_segment_dup(tqe->seg);
+	if (rt_seg == NULL) {
+		log_msg(LVL_ERROR, "Memory allocation failed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		/* XXX Handle properly */
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "### %s: retransmitting segment", conn->name);
+	tcp_conn_transmit_segment(tqe->conn, rt_seg);
+
+	/* Reset retransmission timer */
+	tcp_tqueue_timer_set(tqe->conn);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/** Set or re-set retransmission timer */
+static void tcp_tqueue_timer_set(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
+
+	/* Clear first to make sure we update refcnt correctly */
+	tcp_tqueue_timer_clear(conn);
+
+	tcp_conn_addref(conn);
+	fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
+	    retransmit_timeout_func, (void *) conn);
+}
+
+/** Clear retransmission timer */
+static void tcp_tqueue_timer_clear(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
+
+	if (fibril_timer_clear(conn->retransmit.timer) == fts_active)
+		tcp_conn_delref(conn);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/tqueue.h
===================================================================
--- uspace/srv/net/tcp/tqueue.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/tqueue.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,57 @@
+/*
+ * 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 TCP transmission queue
+ */
+
+#ifndef TQUEUE_H
+#define TQUEUE_H
+
+#include "std.h"
+#include "tcp_type.h"
+
+extern int tcp_tqueue_init(tcp_tqueue_t *, tcp_conn_t *);
+extern void tcp_tqueue_clear(tcp_tqueue_t *);
+extern void tcp_tqueue_fini(tcp_tqueue_t *);
+extern void tcp_tqueue_ctrl_seg(tcp_conn_t *, tcp_control_t);
+extern void tcp_tqueue_seg(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_tqueue_new_data(tcp_conn_t *);
+extern void tcp_tqueue_ack_received(tcp_conn_t *);
+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_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 *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/ucall.c
===================================================================
--- uspace/srv/net/tcp/ucall.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/ucall.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,346 @@
+/*
+ * 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 TCP entry points (close to those defined in the RFC)
+ */
+
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include "conn.h"
+#include "tcp_type.h"
+#include "tqueue.h"
+#include "ucall.h"
+
+/*
+ * User calls
+ */
+
+/** OPEN user call
+ *
+ * @param lsock		Local socket
+ * @param fsock		Foreign socket
+ * @param acpass	Active/passive
+ * @param oflags	Open flags
+ * @param conn		Connection
+ *
+ * Unlike in the spec we allow specifying the local address. This means
+ * the implementation does not need to magically guess it, especially
+ * considering there can be more than one local address.
+ *
+ * XXX We should be able to call active open on an existing listening
+ * connection.
+ * XXX We should be able to get connection structure immediately, before
+ * establishment.
+ */
+tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
+    tcp_open_flags_t oflags, tcp_conn_t **conn)
+{
+	tcp_conn_t *nconn;
+
+	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
+	    lsock, fsock, acpass == ap_active ? "active" : "passive",
+	    oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
+
+	nconn = tcp_conn_new(lsock, fsock);
+	tcp_conn_add(nconn);
+
+	if (acpass == ap_active) {
+		/* Synchronize (initiate) connection */
+		tcp_conn_sync(nconn);
+	}
+
+	if (oflags == tcp_open_nonblock) {
+		*conn = nconn;
+		return TCP_EOK;
+	}
+
+	/* Wait for connection to be established or reset */
+	log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
+	fibril_mutex_lock(&nconn->lock);
+	while (nconn->cstate == st_listen ||
+	    nconn->cstate == st_syn_sent ||
+	    nconn->cstate == st_syn_received) {
+		fibril_condvar_wait(&nconn->cstate_cv, &nconn->lock);
+	}
+
+	if (nconn->cstate != st_established) {
+		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
+		assert(nconn->cstate == st_closed);
+		fibril_mutex_unlock(&nconn->lock);
+		return TCP_ERESET;
+	}
+
+	fibril_mutex_unlock(&nconn->lock);
+	log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
+
+	*conn = nconn;
+	log_msg(LVL_DEBUG, "tcp_uc_open -> %p", nconn);
+	return TCP_EOK;
+}
+
+/** SEND user call */
+tcp_error_t tcp_uc_send(tcp_conn_t *conn, void *data, size_t size,
+    xflags_t flags)
+{
+	size_t buf_free;
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	if (conn->cstate == st_listen) {
+		/* Change connection to active */
+		tcp_conn_sync(conn);
+	}
+
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ECLOSING;
+	}
+
+	while (size > 0) {
+		buf_free = conn->snd_buf_size - conn->snd_buf_used;
+		while (buf_free == 0 && !conn->reset) {
+			log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.",
+			    conn->name);
+			fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock);
+			buf_free = conn->snd_buf_size - conn->snd_buf_used;
+		}
+
+		if (conn->reset) {
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ERESET;
+		}
+
+		xfer_size = min(size, buf_free);
+
+		/* Copy data to buffer */
+		memcpy(conn->snd_buf + conn->snd_buf_used, data, xfer_size);
+		data += xfer_size;
+		conn->snd_buf_used += xfer_size;
+		size -= xfer_size;
+
+		tcp_tqueue_new_data(conn);
+	}
+
+	tcp_tqueue_new_data(conn);
+	fibril_mutex_unlock(&conn->lock);
+
+	return TCP_EOK;
+}
+
+/** RECEIVE user call */
+tcp_error_t tcp_uc_receive(tcp_conn_t *conn, void *buf, size_t size,
+    size_t *rcvd, xflags_t *xflags)
+{
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	/* Wait for data to become available */
+	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
+		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
+		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
+	}
+
+	if (conn->rcv_buf_used == 0) {
+		*rcvd = 0;
+		*xflags = 0;
+
+		if (conn->rcv_buf_fin) {
+			/* End of data, peer closed connection */
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ECLOSING;
+		} else {
+			/* Connection was reset */
+			assert(conn->reset);
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ERESET;
+		}
+	}
+
+	/* Copy data from receive buffer to user buffer */
+	xfer_size = min(size, conn->rcv_buf_used);
+	memcpy(buf, conn->rcv_buf, xfer_size);
+	*rcvd = xfer_size;
+
+	/* Remove data from receive buffer */
+	memmove(conn->rcv_buf, conn->rcv_buf + xfer_size, conn->rcv_buf_used -
+	    xfer_size);
+	conn->rcv_buf_used -= xfer_size;
+	conn->rcv_wnd += xfer_size;
+
+	/* TODO */
+	*xflags = 0;
+
+	/* Send new size of receive window */
+	tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_receive() - returning %zu bytes",
+	    conn->name, xfer_size);
+
+	fibril_mutex_unlock(&conn->lock);
+
+	return TCP_EOK;
+}
+
+/** CLOSE user call */
+tcp_error_t tcp_uc_close(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ECLOSING;
+	}
+
+	conn->snd_buf_fin = true;
+	tcp_tqueue_new_data(conn);
+
+	fibril_mutex_unlock(&conn->lock);
+	return TCP_EOK;
+}
+
+/** ABORT user call */
+void tcp_uc_abort(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_abort()");
+}
+
+/** STATUS user call */
+void tcp_uc_status(tcp_conn_t *conn, tcp_conn_status_t *cstatus)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_status()");
+	cstatus->cstate = conn->cstate;
+}
+
+/** Delete connection user call.
+ *
+ * (Not in spec.) Inform TCP that the user is done with this connection
+ * and will not make any further calls/references to it. TCP can deallocate
+ * the connection from now on.
+ */
+void tcp_uc_delete(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_delete()");
+	tcp_conn_delete(conn);
+}
+
+void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
+	    conn, cb, arg);
+
+	conn->cstate_cb = cb;
+	conn->cstate_cb_arg = arg;
+}
+
+/*
+ * Arriving segments
+ */
+
+/** Segment arrived */
+void tcp_as_segment_arrived(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_conn_t *conn;
+
+	log_msg(LVL_DEBUG, "tcp_as_segment_arrived(f:(%x,%u), l:(%x,%u))",
+	    sp->foreign.addr.ipv4, sp->foreign.port,
+	    sp->local.addr.ipv4, sp->local.port);
+
+	conn = tcp_conn_find_ref(sp);
+	if (conn == NULL) {
+		log_msg(LVL_WARN, "No connection found.");
+		tcp_unexpected_segment(sp, seg);
+		return;
+	}
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_WARN, "Connection is closed.");
+		tcp_unexpected_segment(sp, seg);
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
+	if (conn->ident.foreign.port == TCP_PORT_ANY)
+		conn->ident.foreign.port = sp->foreign.port;
+	if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
+
+	tcp_conn_segment_arrived(conn, seg);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/*
+ * Timeouts
+ */
+
+/** User timeout */
+void tcp_to_user(void)
+{
+	log_msg(LVL_DEBUG, "tcp_to_user()");
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/ucall.h
===================================================================
--- uspace/srv/net/tcp/ucall.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/tcp/ucall.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,67 @@
+/*
+ * 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 TCP user calls (close to those defined in the RFC)
+ */
+
+#ifndef UCALL_H
+#define UCALL_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+/*
+ * User calls
+ */
+extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_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);
+extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
+extern tcp_error_t tcp_uc_close(tcp_conn_t *);
+extern void tcp_uc_abort(tcp_conn_t *);
+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 *);
+
+/*
+ * Arriving segments
+ */
+extern void tcp_as_segment_arrived(tcp_sockpair_t *, tcp_segment_t *);
+
+/*
+ * Timeouts
+ */
+extern void tcp_to_user(void);
+
+#endif
+
+/** @}
+ */
Index: pace/srv/net/tl/icmp/Makefile
===================================================================
--- uspace/srv/net/tl/icmp/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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 = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = icmp
-STATIC_ONLY = y
-
-SOURCES = \
-	icmp.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,809 +1,0 @@
-/*
- * Copyright (c) 2008 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 icmp
- * @{
- */
-
-/** @file
- * ICMP module implementation.
- */
-
-#include <async.h>
-#include <atomic.h>
-#include <fibril.h>
-#include <fibril_synch.h>
-#include <stdint.h>
-#include <str.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/tl.h>
-#include <ipc/icmp.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <adt/hash_table.h>
-
-#include <net/socket_codes.h>
-#include <net/ip_protocols.h>
-#include <net/inet.h>
-#include <net/modules.h>
-#include <net/icmp_api.h>
-#include <net/icmp_codes.h>
-#include <net/icmp_common.h>
-
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <net_checksum.h>
-#include <icmp_client.h>
-#include <icmp_remote.h>
-#include <il_remote.h>
-#include <ip_client.h>
-#include <ip_interface.h>
-#include <net_interface.h>
-#include <tl_remote.h>
-#include <tl_skel.h>
-#include <icmp_header.h>
-
-/** ICMP module name */
-#define NAME  "icmp"
-
-/** Number of replies hash table keys */
-#define REPLY_KEYS  2
-
-/** Number of replies hash table buckets */
-#define REPLY_BUCKETS  1024
-
-/**
- * Original datagram length in bytes transfered to the error
- * notification message.
- */
-#define ICMP_KEEP_LENGTH  8
-
-/** Compute the ICMP datagram checksum.
- *
- * @param[in,out] header ICMP datagram header.
- * @param[in]     length Total datagram length.
- *
- * @return Computed checksum.
- *
- */
-#define ICMP_CHECKSUM(header, length) \
-	htons(ip_checksum((uint8_t *) (header), (length)))
-
-/** An echo request datagrams pattern. */
-#define ICMP_ECHO_TEXT  "ICMP hello from HelenOS."
-
-/** ICMP reply data. */
-typedef struct {
-	/** Hash table link */
-	link_t link;
-	
-	/** Reply identification and sequence */
-	icmp_param_t id;
-	icmp_param_t sequence;
-	
-	/** Reply signaling */
-	fibril_condvar_t condvar;
-	
-	/** Reply result */
-	int result;
-} icmp_reply_t;
-
-/** Global data */
-static async_sess_t *net_sess = NULL;
-static async_sess_t *ip_sess = NULL;
-static bool error_reporting = true;
-static bool echo_replying = true;
-static packet_dimension_t icmp_dimension;
-
-/** ICMP client identification counter */
-static atomic_t icmp_client;
-
-/** ICMP identifier and sequence number (client-specific) */
-static fibril_local icmp_param_t icmp_id;
-static fibril_local icmp_param_t icmp_seq;
-
-/** Reply hash table */
-static fibril_mutex_t reply_lock;
-static hash_table_t replies;
-
-static hash_index_t replies_hash(unsigned long key[])
-{
-	/*
-	 * ICMP identifier and sequence numbers
-	 * are 16-bit values.
-	 */
-	hash_index_t index = ((key[0] & 0xffff) << 16) | (key[1] & 0xffff);
-	return (index % REPLY_BUCKETS);
-}
-
-static int replies_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	icmp_reply_t *reply =
-	    hash_table_get_instance(item, icmp_reply_t, link);
-	
-	if (keys == 1)
-		return (reply->id == key[0]);
-	else
-		return ((reply->id == key[0]) && (reply->sequence == key[1]));
-}
-
-static void replies_remove_callback(link_t *item)
-{
-}
-
-static hash_table_operations_t reply_ops = {
-	.hash = replies_hash,
-	.compare = replies_compare,
-	.remove_callback = replies_remove_callback
-};
-
-/** Release the packet and return the result.
- *
- * @param[in] packet Packet queue to be released.
- *
- */
-static void icmp_release(packet_t *packet)
-{
-	pq_release_remote(net_sess, packet_get_id(packet));
-}
-
-/** Send the ICMP message.
- *
- * Set the message type and code and compute the checksum.
- * Error messages are sent only if allowed in the configuration.
- * Release the packet on errors.
- *
- * @param[in] type          Message type.
- * @param[in] code          Message code.
- * @param[in] packet        Message packet to be sent.
- * @param[in] header        ICMP header.
- * @param[in] error         Error service to be announced. Should be
- *                          SERVICE_ICMP or zero.
- * @param[in] ttl           Time to live.
- * @param[in] tos           Type of service.
- * @param[in] dont_fragment Disable fragmentation.
- *
- * @return EOK on success.
- * @return EPERM if the error message is not allowed.
- *
- */
-static int icmp_send_packet(icmp_type_t type, icmp_code_t code,
-    packet_t *packet, icmp_header_t *header, services_t error, ip_ttl_t ttl,
-    ip_tos_t tos, bool dont_fragment)
-{
-	/* Do not send an error if disabled */
-	if ((error) && (!error_reporting)) {
-		icmp_release(packet);
-		return EPERM;
-	}
-	
-	header->type = type;
-	header->code = code;
-	
-	/*
-	 * The checksum needs to be calculated
-	 * with a virtual checksum field set to
-	 * zero.
-	 */
-	header->checksum = 0;
-	header->checksum = ICMP_CHECKSUM(header,
-	    packet_get_data_length(packet));
-	
-	int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
-	    dont_fragment, 0);
-	if (rc != EOK) {
-		icmp_release(packet);
-		return rc;
-	}
-	
-	return ip_send_msg(ip_sess, -1, packet, SERVICE_ICMP, error);
-}
-
-/** Prepare the ICMP error packet.
- *
- * Truncate the original packet if longer than ICMP_KEEP_LENGTH bytes.
- * Prefix and return the ICMP header.
- *
- * @param[in,out] packet Original packet.
- *
- * @return The prefixed ICMP header.
- * @return NULL on errors.
- *
- */
-static icmp_header_t *icmp_prepare_packet(packet_t *packet)
-{
-	size_t total_length = packet_get_data_length(packet);
-	if (total_length <= 0)
-		return NULL;
-	
-	size_t header_length = ip_client_header_length(packet);
-	if (header_length <= 0)
-		return NULL;
-	
-	/* Truncate if longer than 64 bits (without the IP header) */
-	if ((total_length > header_length + ICMP_KEEP_LENGTH) &&
-	    (packet_trim(packet, 0,
-	    total_length - header_length - ICMP_KEEP_LENGTH) != EOK))
-		return NULL;
-	
-	icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
-	if (!header)
-		return NULL;
-	
-	bzero(header, sizeof(*header));
-	return header;
-}
-
-/** Request an echo message.
- *
- * Send a packet with specified parameters to the target host
- * and wait for the reply upto the given timeout.
- * Block the caller until the reply or the timeout occurs.
- *
- * @param[in] id            Message identifier.
- * @param[in] sequence      Message sequence parameter.
- * @param[in] size          Message data length in bytes.
- * @param[in] timeout       Timeout in miliseconds.
- * @param[in] ttl           Time to live.
- * @param[in] tos           Type of service.
- * @param[in] dont_fragment Disable fragmentation.
- * @param[in] addr          Target host address.
- * @param[in] addrlen       Torget host address length.
- *
- * @return ICMP_ECHO on success.
- * @return ETIMEOUT if the reply has not arrived before the
- *         timeout.
- * @return ICMP type of the received error notification.
- * @return EINVAL if the addrlen parameter is less or equal to
- *         zero.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size,
-    mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment,
-    const struct sockaddr *addr, socklen_t addrlen)
-{
-	if (addrlen <= 0)
-		return EINVAL;
-	
-	size_t length = (size_t) addrlen;
-	
-	packet_t *packet = packet_get_4_remote(net_sess, size,
-	    icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
-	    icmp_dimension.suffix);
-	if (!packet)
-		return ENOMEM;
-	
-	/* Prepare the requesting packet, set the destination address. */
-	int rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
-	if (rc != EOK) {
-		icmp_release(packet);
-		return rc;
-	}
-	
-	/* Allocate space in the packet */
-	uint8_t *data = (uint8_t *) packet_suffix(packet, size);
-	if (!data) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	/* Fill the data */
-	length = 0;
-	while (size > length + sizeof(ICMP_ECHO_TEXT)) {
-		memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT));
-		length += sizeof(ICMP_ECHO_TEXT);
-	}
-	memcpy(data + length, ICMP_ECHO_TEXT, size - length);
-	
-	/* Prefix the header */
-	icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	bzero(header, sizeof(icmp_header_t));
-	header->un.echo.identifier = id;
-	header->un.echo.sequence_number = sequence;
-	
-	/* Prepare the reply structure */
-	icmp_reply_t *reply = malloc(sizeof(icmp_reply_t));
-	if (!reply) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	reply->id = id;
-	reply->sequence = sequence;
-	fibril_condvar_initialize(&reply->condvar);
-	
-	/* Add the reply to the replies hash table */
-	fibril_mutex_lock(&reply_lock);
-	
-	unsigned long key[REPLY_KEYS] = {id, sequence};
-	hash_table_insert(&replies, key, &reply->link);
-	
-	/* Send the request */
-	icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
-	    dont_fragment);
-	
-	/* Wait for the reply. Timeout in microseconds. */
-	rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock,
-	    timeout * 1000);
-	if (rc == EOK)
-		rc = reply->result;
-	
-	/* Remove the reply from the replies hash table */
-	hash_table_remove(&replies, key, REPLY_KEYS);
-	
-	fibril_mutex_unlock(&reply_lock);
-	
-	free(reply);
-	
-	return rc;
-}
-
-static int icmp_destination_unreachable(icmp_code_t code, icmp_param_t mtu,
-    packet_t *packet)
-{
-	icmp_header_t *header = icmp_prepare_packet(packet);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	if (mtu)
-		header->un.frag.mtu = mtu;
-	
-	return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header,
-	    SERVICE_ICMP, 0, 0, false);
-}
-
-static int icmp_source_quench(packet_t *packet)
-{
-	icmp_header_t *header = icmp_prepare_packet(packet);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header,
-	    SERVICE_ICMP, 0, 0, false);
-}
-
-static int icmp_time_exceeded(icmp_code_t code, packet_t *packet)
-{
-	icmp_header_t *header = icmp_prepare_packet(packet);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
-	    SERVICE_ICMP, 0, 0, false);
-}
-
-static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer,
-    packet_t *packet)
-{
-	icmp_header_t *header = icmp_prepare_packet(packet);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	header->un.param.pointer = pointer;
-	return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header,
-	    SERVICE_ICMP, 0, 0, false);
-}
-
-/** Try to set the pending reply result as the received message type.
- *
- * If the reply data is not present, the reply timed out and the other fibril
- * is already awake. The packet is released.
- *
- * @param[in] packet The received reply message.
- * @param[in] header The ICMP message header.
- * @param[in] type   The received reply message type.
- * @param[in] code   The received reply message code.
- *
- */
-static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
-    icmp_type_t type, icmp_code_t code)
-{
-	unsigned long key[REPLY_KEYS] =
-	    {header->un.echo.identifier, header->un.echo.sequence_number};
-	
-	/* The packet is no longer needed */
-	icmp_release(packet);
-	
-	/* Find the pending reply */
-	fibril_mutex_lock(&reply_lock);
-	
-	link_t *link = hash_table_find(&replies, key);
-	if (link != NULL) {
-		icmp_reply_t *reply =
-		   hash_table_get_instance(link, icmp_reply_t, link);
-		
-		reply->result = type;
-		fibril_condvar_signal(&reply->condvar);
-	}
-	
-	fibril_mutex_unlock(&reply_lock);
-}
-
-/** Process the received ICMP packet.
- *
- * Notify the destination socket application.
- *
- * @param[in,out] packet Received packet.
- * @param[in]     error  Packet error reporting service to prefix
- *                       the received packet.
- *
- * @return EOK on success.
- * @return EINVAL if the packet is not valid.
- * @return EINVAL if the stored packet address is not the an_addr_t.
- * @return EINVAL if the packet does not contain any data.
- * @return NO_DATA if the packet content is shorter than the user
- *         datagram header.
- * @return ENOMEM if there is not enough memory left.
- * @return EADDRNOTAVAIL if the destination socket does not exist.
- * @return Other error codes as defined for the
- *         ip_client_process_packet() function.
- *
- */
-static int icmp_process_packet(packet_t *packet, services_t error)
-{
-	icmp_type_t type;
-	icmp_code_t code;
-	int rc;
-	
-	switch (error) {
-	case SERVICE_NONE:
-		break;
-	case SERVICE_ICMP:
-		/* Process error */
-		rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
-		if (rc < 0)
-			return rc;
-		
-		/* Remove the error header */
-		rc = packet_trim(packet, (size_t) rc, 0);
-		if (rc != EOK)
-			return rc;
-		
-		break;
-	default:
-		return ENOTSUP;
-	}
-	
-	/* Get rid of the IP header */
-	size_t length = ip_client_header_length(packet);
-	rc = packet_trim(packet, length, 0);
-	if (rc != EOK)
-		return rc;
-	
-	length = packet_get_data_length(packet);
-	if (length <= 0)
-		return EINVAL;
-	
-	if (length < ICMP_HEADER_SIZE)
-		return EINVAL;
-	
-	void *data = packet_get_data(packet);
-	if (!data)
-		return EINVAL;
-	
-	/* Get ICMP header */
-	icmp_header_t *header = (icmp_header_t *) data;
-	
-	if (header->checksum) {
-		while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
-			/*
-			 * Set the original message type on error notification.
-			 * Type swap observed in Qemu.
-			 */
-			if (error) {
-				switch (header->type) {
-				case ICMP_ECHOREPLY:
-					header->type = ICMP_ECHO;
-					continue;
-				}
-			}
-			
-			return EINVAL;
-		}
-	}
-	
-	switch (header->type) {
-	case ICMP_ECHOREPLY:
-		if (error)
-			icmp_process_echo_reply(packet, header, type, code);
-		else
-			icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
-		
-		return EOK;
-	
-	case ICMP_ECHO:
-		if (error) {
-			icmp_process_echo_reply(packet, header, type, code);
-			return EOK;
-		}
-		
-		/* Do not send a reply if disabled */
-		if (echo_replying) {
-			uint8_t *src;
-			int addrlen = packet_get_addr(packet, &src, NULL);
-			
-			/*
-			 * Set both addresses to the source one (avoid the
-			 * source address deletion before setting the
-			 * destination one).
-			 */
-			if ((addrlen > 0) && (packet_set_addr(packet, src, src,
-			    (size_t) addrlen) == EOK)) {
-				/* Send the reply */
-				icmp_send_packet(ICMP_ECHOREPLY, 0, packet,
-				    header, 0, 0, 0, 0);
-				return EOK;
-			}
-			
-			return EINVAL;
-		}
-		
-		return EPERM;
-	
-	case ICMP_DEST_UNREACH:
-	case ICMP_SOURCE_QUENCH:
-	case ICMP_REDIRECT:
-	case ICMP_ALTERNATE_ADDR:
-	case ICMP_ROUTER_ADV:
-	case ICMP_ROUTER_SOL:
-	case ICMP_TIME_EXCEEDED:
-	case ICMP_PARAMETERPROB:
-	case ICMP_CONVERSION_ERROR:
-	case ICMP_REDIRECT_MOBILE:
-	case ICMP_SKIP:
-	case ICMP_PHOTURIS:
-		ip_received_error_msg(ip_sess, -1, packet,
-		    SERVICE_IP, SERVICE_ICMP);
-		return EOK;
-	
-	default:
-		return ENOTSUP;
-	}
-}
-
-/** Process IPC messages from the IP module
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		if (!IPC_GET_IMETHOD(*icall))
-			break;
-		
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc == EOK) {
-				rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
-				if (rc != EOK)
-					icmp_release(packet);
-			}
-			
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Initialize the ICMP module.
- *
- * @param[in] sess Network module session.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int tl_initialize(async_sess_t *sess)
-{
-	measured_string_t names[] = {
-		{
-			(uint8_t *) "ICMP_ERROR_REPORTING",
-			20
-		},
-		{
-			(uint8_t *) "ICMP_ECHO_REPLYING",
-			18
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	
-	if (!hash_table_create(&replies, REPLY_BUCKETS, REPLY_KEYS, &reply_ops))
-		return ENOMEM;
-	
-	fibril_mutex_initialize(&reply_lock);
-	atomic_set(&icmp_client, 0);
-	
-	net_sess = sess;
-	ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
-	    icmp_receiver);
-	if (ip_sess == NULL)
-		return ENOENT;
-	
-	int rc = ip_packet_size_req(ip_sess, -1, &icmp_dimension);
-	if (rc != EOK)
-		return rc;
-	
-	icmp_dimension.prefix += ICMP_HEADER_SIZE;
-	icmp_dimension.content -= ICMP_HEADER_SIZE;
-	
-	/* Get configuration */
-	configuration = &names[0];
-	rc = net_get_conf_req(net_sess, &configuration, count, &data);
-	if (rc != EOK)
-		return rc;
-	
-	if (configuration) {
-		if (configuration[0].value)
-			error_reporting = (configuration[0].value[0] == 'y');
-		
-		if (configuration[1].value)
-			echo_replying = (configuration[1].value[0] == 'y');
-		
-		net_free_settings(configuration, data);
-	}
-	
-	return EOK;
-}
-
-/** Per-connection initialization
- *
- * Initialize client-specific global variables.
- *
- */
-void tl_connection(void)
-{
-	icmp_id = (icmp_param_t) atomic_postinc(&icmp_client);
-	icmp_seq = 1;
-}
-
-/** Process the ICMP message.
- *
- * @param[in]  callid Message identifier.
- * @param[in]  call   Message parameters.
- * @param[out] answer Answer.
- * @param[out] count  Number of arguments of the answer.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is not known.
- * @return Other error codes as defined for the packet_translate()
- *         function.
- * @return Other error codes as defined for the
- *         icmp_destination_unreachable() function.
- * @return Other error codes as defined for the
- *         icmp_source_quench() function.
- * @return Other error codes as defined for the
- *         icmp_time_exceeded() function.
- * @return Other error codes as defined for the
- *         icmp_parameter_problem() function.
- *
- * @see icmp_remote.h
- * @see IS_NET_ICMP_MESSAGE()
- *
- */
-int tl_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *count)
-{
-	struct sockaddr *addr;
-	size_t size;
-	packet_t *packet;
-	int rc;
-	
-	*count = 0;
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_ICMP_ECHO:
-		rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &size);
-		if (rc != EOK)
-			return rc;
-		
-		rc = icmp_echo(icmp_id, icmp_seq, ICMP_GET_SIZE(*call),
-		    ICMP_GET_TIMEOUT(*call), ICMP_GET_TTL(*call),
-		    ICMP_GET_TOS(*call), ICMP_GET_DONT_FRAGMENT(*call),
-		    addr, (socklen_t) size);
-		
-		free(addr);
-		icmp_seq++;
-		return rc;
-	
-	case NET_ICMP_DEST_UNREACH:
-		rc = packet_translate_remote(net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return icmp_destination_unreachable(ICMP_GET_CODE(*call),
-		    ICMP_GET_MTU(*call), packet);
-	
-	case NET_ICMP_SOURCE_QUENCH:
-		rc = packet_translate_remote(net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return icmp_source_quench(packet);
-	
-	case NET_ICMP_TIME_EXCEEDED:
-		rc = packet_translate_remote(net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return icmp_time_exceeded(ICMP_GET_CODE(*call), packet);
-	
-	case NET_ICMP_PARAMETERPROB:
-		rc = packet_translate_remote(net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return icmp_parameter_problem(ICMP_GET_CODE(*call),
-		    ICMP_GET_POINTER(*call), packet);
-	}
-	
-	return ENOTSUP;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return tl_module_start(SERVICE_ICMP);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/Makefile
===================================================================
--- uspace/srv/net/tl/tcp/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,48 +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 = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = tcp
-
-SOURCES = \
-	conn.c \
-	iqueue.c \
-	ncsim.c \
-	pdu.c \
-	rqueue.c \
-	segment.c \
-	seq_no.c \
-	sock.c \
-	tcp.c \
-	test.c \
-	tqueue.c \
-	ucall.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/tl/tcp/conn.c
===================================================================
--- uspace/srv/net/tl/tcp/conn.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,1282 +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 TCP connection processing and state machine
- */
-
-#include <adt/list.h>
-#include <bool.h>
-#include <errno.h>
-#include <io/log.h>
-#include <macros.h>
-#include <stdlib.h>
-#include "conn.h"
-#include "iqueue.h"
-#include "segment.h"
-#include "seq_no.h"
-#include "tcp_type.h"
-#include "tqueue.h"
-#include "ucall.h"
-
-#define RCV_BUF_SIZE 4096/*2*/
-#define SND_BUF_SIZE 4096
-
-#define MAX_SEGMENT_LIFETIME	(15*1000*1000) //(2*60*1000*1000)
-#define TIME_WAIT_TIMEOUT	(2*MAX_SEGMENT_LIFETIME)
-
-LIST_INITIALIZE(conn_list);
-FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
-
-static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
-static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
-static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
-
-/** Create new connection structure.
- *
- * @param lsock		Local socket (will be deeply copied)
- * @param fsock		Foreign socket (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 *conn = NULL;
-	bool tqueue_inited = false;
-
-	/* Allocate connection structure */
-	conn = calloc(1, sizeof(tcp_conn_t));
-	if (conn == NULL)
-		goto error;
-
-	conn->tw_timer = fibril_timer_create();
-	if (conn->tw_timer == NULL)
-		goto error;
-
-	fibril_mutex_initialize(&conn->lock);
-
-	/* One for the user, one for not being in closed state */
-	atomic_set(&conn->refcnt, 2);
-
-	/* Allocate receive buffer */
-	fibril_condvar_initialize(&conn->rcv_buf_cv);
-	conn->rcv_buf_size = RCV_BUF_SIZE;
-	conn->rcv_buf_used = 0;
-	conn->rcv_buf_fin = false;
-
-	conn->rcv_buf = calloc(1, conn->rcv_buf_size);
-	if (conn->rcv_buf == NULL)
-		goto error;
-
-	/** Allocate send buffer */
-	fibril_condvar_initialize(&conn->snd_buf_cv);
-	conn->snd_buf_size = SND_BUF_SIZE;
-	conn->snd_buf_used = 0;
-	conn->snd_buf_fin = false;
-	conn->snd_buf = calloc(1, conn->snd_buf_size);
-	if (conn->snd_buf == NULL)
-		goto error;
-
-	/* Set up receive window. */
-	conn->rcv_wnd = conn->rcv_buf_size;
-
-	/* Initialize incoming segment queue */
-	tcp_iqueue_init(&conn->incoming, conn);
-
-	/* Initialize retransmission queue */
-	if (tcp_tqueue_init(&conn->retransmit, conn) != EOK)
-		goto error;
-
-	tqueue_inited = true;
-
-	/* Connection state change signalling */
-	fibril_condvar_initialize(&conn->cstate_cv);
-
-	conn->cstate_cb = NULL;
-
-	conn->cstate = st_listen;
-	conn->reset = false;
-	conn->deleted = false;
-	conn->ap = ap_passive;
-	conn->fin_is_acked = false;
-	conn->ident.local = *lsock;
-	if (fsock != NULL)
-		conn->ident.foreign = *fsock;
-
-	return conn;
-
-error:
-	if (tqueue_inited)
-		tcp_tqueue_fini(&conn->retransmit);
-	if (conn != NULL && conn->rcv_buf != NULL)
-		free(conn->rcv_buf);
-	if (conn != NULL && conn->snd_buf != NULL)
-		free(conn->snd_buf);
-	if (conn != NULL && conn->tw_timer != NULL)
-		fibril_timer_destroy(conn->tw_timer);
-	if (conn != NULL)
-		free(conn);
-
-	return NULL;
-}
-
-/** Destroy connection structure.
- *
- * Connection structure should be destroyed when the folowing condtitions
- * are met:
- * (1) user has deleted the connection
- * (2) the connection has entered closed state
- * (3) nobody is holding references to the connection
- *
- * This happens when @a conn->refcnt is zero as we count (1) and (2)
- * as special references.
- *
- * @param conn		Connection
- */
-static void tcp_conn_free(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
-	tcp_tqueue_fini(&conn->retransmit);
-
-	if (conn->rcv_buf != NULL)
-		free(conn->rcv_buf);
-	if (conn->snd_buf != NULL)
-		free(conn->snd_buf);
-	if (conn->tw_timer != NULL)
-		fibril_timer_destroy(conn->tw_timer);
-	free(conn);
-}
-
-/** Add reference to connection.
- *
- * Increase connection reference count by one.
- *
- * @param conn		Connection
- */
-void tcp_conn_addref(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
-	atomic_inc(&conn->refcnt);
-}
-
-/** Remove reference from connection.
- *
- * Decrease connection reference count by one.
- *
- * @param conn		Connection
- */
-void tcp_conn_delref(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
-
-	if (atomic_predec(&conn->refcnt) == 0)
-		tcp_conn_free(conn);
-}
-
-/** Delete connection.
- *
- * The caller promises not make no further references to @a conn.
- * TCP will free @a conn eventually.
- *
- * @param conn		Connection
- */
-void tcp_conn_delete(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
-
-	assert(conn->deleted == false);
-	tcp_conn_delref(conn);
-}
-
-/** Enlist connection.
- *
- * Add connection to the connection map.
- */
-void tcp_conn_add(tcp_conn_t *conn)
-{
-	tcp_conn_addref(conn);
-	fibril_mutex_lock(&conn_list_lock);
-	list_append(&conn->link, &conn_list);
-	fibril_mutex_unlock(&conn_list_lock);
-}
-
-/** Delist connection.
- *
- * Remove connection from the connection map.
- */
-void tcp_conn_remove(tcp_conn_t *conn)
-{
-	fibril_mutex_lock(&conn_list_lock);
-	list_remove(&conn->link);
-	fibril_mutex_unlock(&conn_list_lock);
-	tcp_conn_delref(conn);
-}
-
-static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
-{
-	tcp_cstate_t old_state;
-
-	log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
-
-	old_state = conn->cstate;
-	conn->cstate = nstate;
-	fibril_condvar_broadcast(&conn->cstate_cv);
-
-	/* Run user callback function */
-	if (conn->cstate_cb != NULL) {
-		log_msg(LVL_DEBUG, "tcp_conn_state_set() - run user CB");
-		conn->cstate_cb(conn, conn->cstate_cb_arg);
-	} else {
-		log_msg(LVL_DEBUG, "tcp_conn_state_set() - no user CB");
-	}
-
-	assert(old_state != st_closed);
-	if (nstate == st_closed) {
-		/* Drop one reference for now being in closed state */
-		tcp_conn_delref(conn);
-	}
-}
-
-/** Synchronize connection.
- *
- * This is the first step of an active connection attempt,
- * sends out SYN and sets up ISS and SND.xxx.
- */
-void tcp_conn_sync(tcp_conn_t *conn)
-{
-	/* XXX select ISS */
-	conn->iss = 1;
-	conn->snd_nxt = conn->iss;
-	conn->snd_una = conn->iss;
-	conn->ap = ap_active;
-
-	tcp_tqueue_ctrl_seg(conn, CTL_SYN);
-	tcp_conn_state_set(conn, st_syn_sent);
-}
-
-/** FIN has been sent.
- *
- * This function should be called when FIN is sent over the connection,
- * as a result the connection state is changed appropriately.
- */
-void tcp_conn_fin_sent(tcp_conn_t *conn)
-{
-	switch (conn->cstate) {
-	case st_syn_received:
-	case st_established:
-		log_msg(LVL_DEBUG, "%s: FIN sent -> Fin-Wait-1", conn->name);
-		tcp_conn_state_set(conn, st_fin_wait_1);
-		break;
-	case st_close_wait:
-		log_msg(LVL_DEBUG, "%s: FIN sent -> Last-Ack", conn->name);
-		tcp_conn_state_set(conn, st_last_ack);
-		break;
-	default:
-		log_msg(LVL_ERROR, "%s: Connection state %d", conn->name,
-		    conn->cstate);
-		assert(false);
-	}
-
-	conn->fin_is_acked = false;
-}
-
-/** Compare two sockets.
- *
- * Two sockets are equal if the address is equal and the port number
- * is equal.
- */
-static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
-{
-	log_msg(LVL_DEBUG, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
-	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
-
-	if (patt->addr.ipv4 != TCP_IPV4_ANY &&
-	    patt->addr.ipv4 != sock->addr.ipv4)
-		return false;
-
-	if (patt->port != TCP_PORT_ANY &&
-	    patt->port != sock->port)
-		return false;
-
-	log_msg(LVL_DEBUG, " -> match");
-
-	return true;
-}
-
-/** Match socket with pattern. */
-static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
-{
-	log_msg(LVL_DEBUG, "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.
- * The connection reference count is bumped by one.
- *
- * @param sp	Socket pair
- * @return	Connection structure or NULL if not found.
- */
-tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp);
-
-	fibril_mutex_lock(&conn_list_lock);
-
-	list_foreach(conn_list, link) {
-		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
-		tcp_sockpair_t *csp = &conn->ident;
-		log_msg(LVL_DEBUG, "compare with conn (f:(%x,%u), l:(%x,%u))",
-		    csp->foreign.addr.ipv4, csp->foreign.port,
-		    csp->local.addr.ipv4, csp->local.port);
-		if (tcp_sockpair_match(sp, csp)) {
-			tcp_conn_addref(conn);
-			fibril_mutex_unlock(&conn_list_lock);
-			return conn;
-		}
-	}
-
-	fibril_mutex_unlock(&conn_list_lock);
-	return NULL;
-}
-
-/** Reset connection.
- *
- * @param conn	Connection
- */
-static void tcp_conn_reset(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
-	tcp_conn_state_set(conn, st_closed);
-	conn->reset = true;
-
-	tcp_conn_tw_timer_clear(conn);
-	tcp_tqueue_clear(&conn->retransmit);
-
-	fibril_condvar_broadcast(&conn->rcv_buf_cv);
-	fibril_condvar_broadcast(&conn->snd_buf_cv);
-}
-
-/** Signal to the user that connection has been reset.
- *
- * Send an out-of-band signal to the user.
- */
-static void tcp_reset_signal(tcp_conn_t *conn)
-{
-	/* TODO */
-	log_msg(LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
-}
-
-/** Determine if SYN has been received.
- *
- * @param conn	Connection
- * @return	@c true if SYN has been received, @c false otherwise.
- */
-bool tcp_conn_got_syn(tcp_conn_t *conn)
-{
-	switch (conn->cstate) {
-	case st_listen:
-	case st_syn_sent:
-		return false;
-	case st_syn_received:
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		return true;
-	case st_closed:
-		log_msg(LVL_WARN, "state=%d", (int) conn->cstate);
-		assert(false);
-	}
-
-	assert(false);
-}
-
-/** Segment arrived in Listen state.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_listen(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_sa_listen(%p, %p)", conn, seg);
-
-	if ((seg->ctrl & CTL_RST) != 0) {
-		log_msg(LVL_DEBUG, "Ignoring incoming RST.");
-		return;
-	}
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		log_msg(LVL_DEBUG, "Incoming ACK, send acceptable RST.");
-		tcp_reply_rst(&conn->ident, seg);
-		return;
-	}
-
-	if ((seg->ctrl & CTL_SYN) == 0) {
-		log_msg(LVL_DEBUG, "SYN not present. Ignoring segment.");
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "Got SYN, sending SYN, ACK.");
-
-	conn->rcv_nxt = seg->seq + 1;
-	conn->irs = seg->seq;
-
-
-	log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
-
-	if (seg->len > 1)
-		log_msg(LVL_WARN, "SYN combined with data, ignoring data.");
-
-	/* XXX select ISS */
-	conn->iss = 1;
-	conn->snd_nxt = conn->iss;
-	conn->snd_una = conn->iss;
-
-	/*
-	 * Surprisingly the spec does not deal with initial window setting.
-	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
-	 * will always be accepted as new window setting.
-	 */
-	conn->snd_wnd = seg->wnd;
-	conn->snd_wl1 = seg->seq;
-	conn->snd_wl2 = seg->seq;
-
-	tcp_conn_state_set(conn, st_syn_received);
-
-	tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
-
-	tcp_segment_delete(seg);
-}
-
-/** Segment arrived in Syn-Sent state.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_syn_sent(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_sa_syn_sent(%p, %p)", conn, seg);
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		log_msg(LVL_DEBUG, "snd_una=%u, seg.ack=%u, snd_nxt=%u",
-		    conn->snd_una, seg->ack, conn->snd_nxt);
-		if (!seq_no_ack_acceptable(conn, seg->ack)) {
-			if ((seg->ctrl & CTL_RST) == 0) {
-				log_msg(LVL_WARN, "ACK not acceptable, send RST");
-				tcp_reply_rst(&conn->ident, seg);
-			} else {
-				log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
-			}
-			return;
-		}
-	}
-
-	if ((seg->ctrl & CTL_RST) != 0) {
-		/* If we get here, we have either an acceptable ACK or no ACK */
-		if ((seg->ctrl & CTL_ACK) != 0) {
-			log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
-			    conn->name);
-			/* Reset connection */
-			tcp_conn_reset(conn);
-			return;
-		} else {
-			log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
-			    conn->name);
-			return;
-		}
-	}
-
-	/* XXX precedence */
-
-	if ((seg->ctrl & CTL_SYN) == 0) {
-		log_msg(LVL_DEBUG, "No SYN bit, ignoring segment.");
-		return;
-	}
-
-	conn->rcv_nxt = seg->seq + 1;
-	conn->irs = seg->seq;
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		conn->snd_una = seg->ack;
-
-		/*
-		 * Prune acked segments from retransmission queue and
-		 * possibly transmit more data.
-		 */
-		tcp_tqueue_ack_received(conn);
-	}
-
-	log_msg(LVL_DEBUG, "Sent SYN, got SYN.");
-
-	/*
-	 * Surprisingly the spec does not deal with initial window setting.
-	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
-	 * will always be accepted as new window setting.
-	 */
-	log_msg(LVL_DEBUG, "SND.WND := %" PRIu32 ", SND.WL1 := %" PRIu32 ", "
-	    "SND.WL2 = %" PRIu32, seg->wnd, seg->seq, seg->seq);
-	conn->snd_wnd = seg->wnd;
-	conn->snd_wl1 = seg->seq;
-	conn->snd_wl2 = seg->seq;
-
-	if (seq_no_syn_acked(conn)) {
-		log_msg(LVL_DEBUG, "%s: syn acked -> Established", conn->name);
-		tcp_conn_state_set(conn, st_established);
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK /* XXX */);
-	} else {
-		log_msg(LVL_DEBUG, "%s: syn not acked -> Syn-Received",
-		    conn->name);
-		tcp_conn_state_set(conn, st_syn_received);
-		tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
-	}
-
-	tcp_segment_delete(seg);
-}
-
-/** Segment arrived in state where segments are processed in sequence order.
- *
- * Queue segment in incoming segments queue for processing.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_queue(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	tcp_segment_t *pseg;
-
-	log_msg(LVL_DEBUG, "tcp_conn_sa_seq(%p, %p)", conn, seg);
-
-	/* Discard unacceptable segments ("old duplicates") */
-	if (!seq_no_segment_acceptable(conn, seg)) {
-		log_msg(LVL_DEBUG, "Replying ACK to unacceptable segment.");
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-		tcp_segment_delete(seg);
-		return;
-	}
-
-	/* Queue for processing */
-	tcp_iqueue_insert_seg(&conn->incoming, seg);
-
-	/*
-	 * Process all segments from incoming queue that are ready.
-	 * Unacceptable segments are discarded by tcp_iqueue_get_ready_seg().
-	 *
-	 * XXX Need to return ACK for unacceptable segments
-	 */
-	while (tcp_iqueue_get_ready_seg(&conn->incoming, &pseg) == EOK)
-		tcp_conn_seg_process(conn, pseg);
-}
-
-/** Process segment RST field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if ((seg->ctrl & CTL_RST) == 0)
-		return cp_continue;
-
-	switch (conn->cstate) {
-	case st_syn_received:
-		/* XXX In case of passive open, revert to Listen state */
-		if (conn->ap == ap_passive) {
-			tcp_conn_state_set(conn, st_listen);
-			/* XXX Revert conn->ident */
-			tcp_conn_tw_timer_clear(conn);
-			tcp_tqueue_clear(&conn->retransmit);
-		} else {
-			tcp_conn_reset(conn);
-		}
-		break;
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-		/* General "connection reset" signal */
-		tcp_reset_signal(conn);
-		tcp_conn_reset(conn);
-		break;
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		tcp_conn_reset(conn);
-		break;
-	case st_listen:
-	case st_syn_sent:
-	case st_closed:
-		assert(false);
-	}
-
-	return cp_done;
-}
-
-/** Process segment security and precedence fields.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_sp(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment SYN field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_syn(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if ((seg->ctrl & CTL_SYN) == 0)
-		return cp_continue;
-
-	/*
-	 * Assert SYN is in receive window, otherwise this step should not
-	 * be reached.
-	 */
-	assert(seq_no_in_rcv_wnd(conn, seg->seq));
-
-	log_msg(LVL_WARN, "SYN is in receive window, should send reset. XXX");
-
-	/*
-	 * TODO
-	 *
-	 * Send a reset, resond "reset" to all outstanding RECEIVEs and SEND,
-	 * flush segment queues. Send unsolicited "connection reset" signal
-	 * to user, connection -> closed state, delete TCB, return.
-	 */
-	return cp_done;
-}
-
-/** Process segment ACK field in Syn-Received state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_sr(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (!seq_no_ack_acceptable(conn, seg->ack)) {
-		/* ACK is not acceptable, send RST. */
-		log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST.");
-		tcp_reply_rst(&conn->ident, seg);
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	log_msg(LVL_DEBUG, "%s: SYN ACKed -> Established", conn->name);
-
-	tcp_conn_state_set(conn, st_established);
-
-	/* XXX Not mentioned in spec?! */
-	conn->snd_una = seg->ack;
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Established state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_seg_proc_ack_est(%p, %p)", conn, seg);
-
-	log_msg(LVL_DEBUG, "SEG.ACK=%u, SND.UNA=%u, SND.NXT=%u",
-	    (unsigned)seg->ack, (unsigned)conn->snd_una,
-	    (unsigned)conn->snd_nxt);
-
-	if (!seq_no_ack_acceptable(conn, seg->ack)) {
-		log_msg(LVL_DEBUG, "ACK not acceptable.");
-		if (!seq_no_ack_duplicate(conn, seg->ack)) {
-			log_msg(LVL_WARN, "Not acceptable, not duplicate. "
-			    "Send ACK and drop.");
-			/* Not acceptable, not duplicate. Send ACK and drop. */
-			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-			tcp_segment_delete(seg);
-			return cp_done;
-		} else {
-			log_msg(LVL_DEBUG, "Ignoring duplicate ACK.");
-		}
-	} else {
-		/* Update SND.UNA */
-		conn->snd_una = seg->ack;
-	}
-
-	if (seq_no_new_wnd_update(conn, seg)) {
-		conn->snd_wnd = seg->wnd;
-		conn->snd_wl1 = seg->seq;
-		conn->snd_wl2 = seg->ack;
-
-		log_msg(LVL_DEBUG, "Updating send window, SND.WND=%" PRIu32
-		    ", SND.WL1=%" PRIu32 ", SND.WL2=%" PRIu32,
-		    conn->snd_wnd, conn->snd_wl1, conn->snd_wl2);
-	}
-
-	/*
-	 * Prune acked segments from retransmission queue and
-	 * possibly transmit more data.
-	 */
-	tcp_tqueue_ack_received(conn);
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Fin-Wait-1 state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_fw1(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	if (conn->fin_is_acked) {
-		log_msg(LVL_DEBUG, "%s: FIN acked -> Fin-Wait-2", conn->name);
-		tcp_conn_state_set(conn, st_fin_wait_2);
-	}
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Fin-Wait-2 state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_fw2(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment ACK field in Close-Wait state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_cw(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* The same processing as in Established state */
-	return tcp_conn_seg_proc_ack_est(conn, seg);
-}
-
-/** Process segment ACK field in Closing state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_cls(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment ACK field in Last-Ack state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_la(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	if (conn->fin_is_acked) {
-		log_msg(LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
-		tcp_conn_remove(conn);
-		tcp_conn_state_set(conn, st_closed);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Time-Wait state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_tw(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* Nothing to do */
-	return cp_continue;
-}
-
-/** Process segment ACK field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_ack(%p, %p)",
-	    conn->name, conn, seg);
-
-	if ((seg->ctrl & CTL_ACK) == 0) {
-		log_msg(LVL_WARN, "Segment has no ACK. Dropping.");
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	switch (conn->cstate) {
-	case st_syn_received:
-		return tcp_conn_seg_proc_ack_sr(conn, seg);
-	case st_established:
-		return tcp_conn_seg_proc_ack_est(conn, seg);
-	case st_fin_wait_1:
-		return tcp_conn_seg_proc_ack_fw1(conn, seg);
-	case st_fin_wait_2:
-		return tcp_conn_seg_proc_ack_fw2(conn, seg);
-	case st_close_wait:
-		return tcp_conn_seg_proc_ack_cw(conn, seg);
-	case st_closing:
-		return tcp_conn_seg_proc_ack_cls(conn, seg);
-	case st_last_ack:
-		return tcp_conn_seg_proc_ack_la(conn, seg);
-	case st_time_wait:
-		return tcp_conn_seg_proc_ack_tw(conn, seg);
-	case st_listen:
-	case st_syn_sent:
-	case st_closed:
-		assert(false);
-	}
-
-	assert(false);
-}
-
-/** Process segment URG field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_urg(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	return cp_continue;
-}
-
-/** Process segment text.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_text(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	size_t text_size;
-	size_t xfer_size;
-
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_text(%p, %p)",
-	    conn->name, conn, seg);
-
-	switch (conn->cstate) {
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-		/* OK */
-		break;
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		/* Invalid since FIN has been received. Ignore text. */
-		return cp_continue;
-	case st_listen:
-	case st_syn_sent:
-	case st_syn_received:
-	case st_closed:
-		assert(false);
-	}
-
-	/*
-	 * Process segment text
-	 */
-	assert(seq_no_segment_ready(conn, seg));
-
-	/* Trim anything outside our receive window */
-	tcp_conn_trim_seg_to_wnd(conn, seg);
-
-	/* Determine how many bytes to copy */
-	text_size = tcp_segment_text_size(seg);
-	xfer_size = min(text_size, conn->rcv_buf_size - conn->rcv_buf_used);
-
-	/* Copy data to receive buffer */
-	tcp_segment_text_copy(seg, conn->rcv_buf + conn->rcv_buf_used,
-	    xfer_size);
-	conn->rcv_buf_used += xfer_size;
-
-	/* Signal to the receive function that new data has arrived */
-	fibril_condvar_broadcast(&conn->rcv_buf_cv);
-
-	log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
-
-	/* Advance RCV.NXT */
-	conn->rcv_nxt += xfer_size;
-
-	/* Update receive window. XXX Not an efficient strategy. */
-	conn->rcv_wnd -= xfer_size;
-
-	/* Send ACK */
-	if (xfer_size > 0)
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-
-	if (xfer_size < seg->len) {
-		/* Trim part of segment which we just received */
-		tcp_conn_trim_seg_to_wnd(conn, seg);
-	} else {
-		log_msg(LVL_DEBUG, "%s: Nothing left in segment, dropping "
-		    "(xfer_size=%zu, SEG.LEN=%zu, seg->ctrl=%u)",
-		    conn->name, xfer_size, seg->len, (unsigned)seg->ctrl);
-		/* Nothing left in segment */
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process segment FIN field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_fin(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_fin(%p, %p)",
-	    conn->name, conn, seg);
-	log_msg(LVL_DEBUG, " seg->len=%zu, seg->ctl=%u", (size_t) seg->len,
-	    (unsigned) seg->ctrl);
-
-	/* Only process FIN if no text is left in segment. */
-	if (tcp_segment_text_size(seg) == 0 && (seg->ctrl & CTL_FIN) != 0) {
-		log_msg(LVL_DEBUG, " - FIN found in segment.");
-
-		/* Send ACK */
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-
-		conn->rcv_nxt++;
-		conn->rcv_wnd--;
-
-		/* Change connection state */
-		switch (conn->cstate) {
-		case st_listen:
-		case st_syn_sent:
-		case st_closed:
-			/* Connection not synchronized */
-			assert(false);
-		case st_syn_received:
-		case st_established:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Close-Wait",
-			    conn->name);
-			tcp_conn_state_set(conn, st_close_wait);
-			break;
-		case st_fin_wait_1:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Closing",
-			    conn->name);
-			tcp_conn_state_set(conn, st_closing);
-			break;
-		case st_fin_wait_2:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Time-Wait",
-			    conn->name);
-			tcp_conn_state_set(conn, st_time_wait);
-			/* Start the Time-Wait timer */
-			tcp_conn_tw_timer_set(conn);
-			break;
-		case st_close_wait:
-		case st_closing:
-		case st_last_ack:
-			/* Do nothing */
-			break;
-		case st_time_wait:
-			/* Restart the Time-Wait timer */
-			tcp_conn_tw_timer_set(conn);
-			break;
-		}
-
-		/* Add FIN to the receive buffer */
-		conn->rcv_buf_fin = true;
-		fibril_condvar_broadcast(&conn->rcv_buf_cv);
-
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process incoming segment.
- *
- * We are in connection state where segments are processed in order
- * of sequence number. This processes one segment taken from the
- * connection incoming segments queue.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_seg_process(%p, %p)", conn, seg);
-	tcp_segment_dump(seg);
-
-	/* Check whether segment is acceptable */
-	/* XXX Permit valid ACKs, URGs and RSTs */
-/*	if (!seq_no_segment_acceptable(conn, seg)) {
-		log_msg(LVL_WARN, "Segment not acceptable, dropping.");
-		if ((seg->ctrl & CTL_RST) == 0) {
-			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-		}
-		return;
-	}
-*/
-
-	if (tcp_conn_seg_proc_rst(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_sp(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_syn(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_ack(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_urg(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_text(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_fin(conn, seg) == cp_done)
-		return;
-
-	/*
-	 * If anything is left from the segment, insert it back into the
-	 * incoming segments queue.
-	 */
-	if (seg->len > 0) {
-		log_msg(LVL_DEBUG, "Re-insert segment %p. seg->len=%zu",
-		    seg, (size_t) seg->len);
-		tcp_iqueue_insert_seg(&conn->incoming, seg);
-	} else {
-		tcp_segment_delete(seg);
-	}
-}
-
-/** Segment arrived on a connection.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%c: tcp_conn_segment_arrived(%p)",
-	    conn->name, seg);
-
-	switch (conn->cstate) {
-	case st_listen:
-		tcp_conn_sa_listen(conn, seg); break;
-	case st_syn_sent:
-		tcp_conn_sa_syn_sent(conn, seg); break;
-	case st_syn_received:
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		/* Process segments in order of sequence number */
-		tcp_conn_sa_queue(conn, seg); break;
-	case st_closed:
-		log_msg(LVL_DEBUG, "state=%d", (int) conn->cstate);
-		assert(false);
-	}
-}
-
-/** Time-Wait timeout handler.
- *
- * @param arg	Connection
- */
-static void tw_timeout_func(void *arg)
-{
-	tcp_conn_t *conn = (tcp_conn_t *) arg;
-
-	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LVL_DEBUG, "Connection already closed.");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
-	tcp_conn_remove(conn);
-	tcp_conn_state_set(conn, st_closed);
-
-	fibril_mutex_unlock(&conn->lock);
-	tcp_conn_delref(conn);
-}
-
-/** Start or restart the Time-Wait timeout.
- *
- * @param conn		Connection
- */
-void tcp_conn_tw_timer_set(tcp_conn_t *conn)
-{
-	tcp_conn_addref(conn);
-	fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
-	    (void *)conn);
-}
-
-/** Clear the Time-Wait timeout.
- *
- * @param conn		Connection
- */
-void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
-{
-	if (fibril_timer_clear(conn->tw_timer) == fts_active)
-		tcp_conn_delref(conn);
-}
-
-/** Trim segment to the receive window.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-void tcp_conn_trim_seg_to_wnd(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	uint32_t left, right;
-
-	seq_no_seg_trim_calc(conn, seg, &left, &right);
-	tcp_segment_trim(seg, left, right);
-}
-
-/** Handle unexpected segment received on a socket pair.
- *
- * We reply with an RST unless the received segment has RST.
- *
- * @param sp		Socket pair which received the segment
- * @param seg		Unexpected segment
- */
-void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, 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;
-}
-
-/** Send RST in response to an incoming segment.
- *
- * @param sp		Socket pair which received the segment
- * @param seg		Incoming segment
- */
-void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_segment_t *rseg;
-
-	log_msg(LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
-
-	rseg = tcp_segment_make_rst(seg);
-	tcp_transmit_segment(sp, rseg);
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/conn.h
===================================================================
--- uspace/srv/net/tl/tcp/conn.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,61 +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 TCP connection processing and state machine
- */
-
-#ifndef CONN_H
-#define CONN_H
-
-#include <bool.h>
-#include "tcp_type.h"
-
-extern tcp_conn_t *tcp_conn_new(tcp_sock_t *, tcp_sock_t *);
-extern void tcp_conn_delete(tcp_conn_t *);
-extern void tcp_conn_add(tcp_conn_t *);
-extern void tcp_conn_remove(tcp_conn_t *);
-extern void tcp_conn_sync(tcp_conn_t *);
-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 void tcp_conn_addref(tcp_conn_t *);
-extern void tcp_conn_delref(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_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 *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/iqueue.c
===================================================================
--- uspace/srv/net/tl/tcp/iqueue.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,156 +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 Connection incoming segments queue
- *
- * Segments are sorted in order of their sequence number.
- */
-
-#include <adt/list.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdlib.h>
-#include "iqueue.h"
-#include "segment.h"
-#include "seq_no.h"
-#include "tcp_type.h"
-
-/** Initialize incoming segments queue.
- *
- * @param iqueue	Incoming queue
- * @param conn		Connection the queue is associated with
- */
-void tcp_iqueue_init(tcp_iqueue_t *iqueue, tcp_conn_t *conn)
-{
-	list_initialize(&iqueue->list);
-	iqueue->conn = conn;
-}
-
-/** Insert segment into incoming queue.
- *
- * @param iqueue	Incoming queue
- * @param seg		Segment
- */
-void tcp_iqueue_insert_seg(tcp_iqueue_t *iqueue, tcp_segment_t *seg)
-{
-	tcp_iqueue_entry_t *iqe;
-	tcp_iqueue_entry_t *qe;
-	link_t *link;
-	log_msg(LVL_DEBUG, "tcp_iqueue_insert_seg()");
-
-	iqe = calloc(1, sizeof(tcp_iqueue_entry_t));
-	if (iqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating IQE.");
-		return;
-	}
-
-	iqe->seg = seg;
-
-	/* Sort by sequence number */
-
-	link = list_first(&iqueue->list);
-	while (link != NULL) {
-		qe = list_get_instance(link,
-		    tcp_iqueue_entry_t, link);
-
-		if (seq_no_seg_cmp(iqueue->conn, iqe->seg, qe->seg) >= 0)
-			break;
-	}
-
-	if (link != NULL)
-		list_insert_before(&iqe->link, &qe->link);
-	else
-		list_append(&iqe->link, &iqueue->list);
-}
-
-/** Get next ready segment from incoming queue.
- *
- * Return the segment with the earliest sequence number if it is ready.
- * A segment is ready if its SEG.SEQ is earlier or equal to RCV.NXT.
- *
- * @param iqueue	Incoming queue
- * @param seg		Place to store pointer to segment
- * @return		EOK on success, ENOENT if no segment is ready
- */
-int tcp_iqueue_get_ready_seg(tcp_iqueue_t *iqueue, tcp_segment_t **seg)
-{
-	tcp_iqueue_entry_t *iqe;
-	link_t *link;
-
-	log_msg(LVL_DEBUG, "tcp_get_ready_seg()");
-
-	link = list_first(&iqueue->list);
-	if (link == NULL) {
-		log_msg(LVL_DEBUG, "iqueue is empty");
-		return ENOENT;
-	}
-
-	iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
-
-	while (!seq_no_segment_acceptable(iqueue->conn, iqe->seg)) {
-		log_msg(LVL_DEBUG, "Skipping unacceptable segment (RCV.NXT=%"
-		    PRIu32 ", RCV.NXT+RCV.WND=%" PRIu32 ", SEG.SEQ=%" PRIu32
-		    ", SEG.LEN=%" PRIu32 ")", iqueue->conn->rcv_nxt,
-		    iqueue->conn->rcv_nxt + iqueue->conn->rcv_wnd,
-		    iqe->seg->seq, iqe->seg->len);
-
-		list_remove(&iqe->link);
-		tcp_segment_delete(iqe->seg);
-
-         	link = list_first(&iqueue->list);
-		if (link == NULL) {
-			log_msg(LVL_DEBUG, "iqueue is empty");
-			return ENOENT;
-		}
-
-		iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
-	}
-
-	/* Do not return segments that are not ready for processing */
-	if (!seq_no_segment_ready(iqueue->conn, iqe->seg)) {
-		log_msg(LVL_DEBUG, "Next segment not ready: SEG.SEQ=%u, "
-		    "RCV.NXT=%u, SEG.LEN=%u", iqe->seg->seq,
-		    iqueue->conn->rcv_nxt, iqe->seg->len);
-		return ENOENT;
-	}
-
-	log_msg(LVL_DEBUG, "Returning ready segment %p", iqe->seg);
-	list_remove(&iqe->link);
-	*seg = iqe->seg;
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/iqueue.h
===================================================================
--- uspace/srv/net/tl/tcp/iqueue.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,47 +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 Connection incoming segments queue
- */
-
-#ifndef IQUEUE_H
-#define IQUEUE_H
-
-#include "tcp_type.h"
-
-extern void tcp_iqueue_init(tcp_iqueue_t *, tcp_conn_t *);
-extern void tcp_iqueue_insert_seg(tcp_iqueue_t *, tcp_segment_t *);
-extern int tcp_iqueue_get_ready_seg(tcp_iqueue_t *, tcp_segment_t **);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/ncsim.c
===================================================================
--- uspace/srv/net/tl/tcp/ncsim.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,172 +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 Network condition simulator
- *
- * Simulate network conditions for testing the reliability implementation:
- *    - variable latency
- *    - frame drop
- */
-
-#include <adt/list.h>
-#include <async.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdlib.h>
-#include <thread.h>
-#include "conn.h"
-#include "ncsim.h"
-#include "rqueue.h"
-#include "segment.h"
-#include "tcp_type.h"
-
-static list_t sim_queue;
-static fibril_mutex_t sim_queue_lock;
-static fibril_condvar_t sim_queue_cv;
-
-/** Initialize segment receive queue. */
-void tcp_ncsim_init(void)
-{
-	list_initialize(&sim_queue);
-	fibril_mutex_initialize(&sim_queue_lock);
-	fibril_condvar_initialize(&sim_queue_cv);
-}
-
-/** Bounce segment through simulator into receive queue.
- *
- * @param sp	Socket pair, oriented for transmission
- * @param seg	Segment
- */
-void tcp_ncsim_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_squeue_entry_t *sqe;
-	tcp_squeue_entry_t *old_qe;
-	link_t *link;
-
-	log_msg(LVL_DEBUG, "tcp_ncsim_bounce_seg()");
-	tcp_rqueue_bounce_seg(sp, seg);
-	return;
-
-	if (0 /*random() % 4 == 3*/) {
-		/* Drop segment */
-		log_msg(LVL_ERROR, "NCSim dropping segment");
-		tcp_segment_delete(seg);
-		return;
-	}
-
-	sqe = calloc(1, sizeof(tcp_squeue_entry_t));
-	if (sqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating SQE.");
-		return;
-	}
-
-	sqe->delay = random() % (1000 * 1000);
-	sqe->sp = *sp;
-	sqe->seg = seg;
-
-	fibril_mutex_lock(&sim_queue_lock);
-
-	link = list_first(&sim_queue);
-	while (link != NULL && sqe->delay > 0) {
-		old_qe = list_get_instance(link, tcp_squeue_entry_t, link);
-		if (sqe->delay < old_qe->delay)
-			break;
-
-		sqe->delay -= old_qe->delay;
-
-		link = link->next;
-		if (link == &sim_queue.head)
-			link = NULL;
-	}
-
-	if (link != NULL)
-		list_insert_after(&sqe->link, link);
-	else
-		list_append(&sqe->link, &sim_queue);
-
-	fibril_condvar_broadcast(&sim_queue_cv);
-	fibril_mutex_unlock(&sim_queue_lock);
-}
-
-/** Network condition simulator handler thread. */
-static void tcp_ncsim_thread(void *arg)
-{
-	link_t *link;
-	tcp_squeue_entry_t *sqe;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_ncsim_thread()");
-
-
-	while (true) {
-		fibril_mutex_lock(&sim_queue_lock);
-
-		while (list_empty(&sim_queue))
-			fibril_condvar_wait(&sim_queue_cv, &sim_queue_lock);
-
-		do {
-			link = list_first(&sim_queue);
-			sqe = list_get_instance(link, tcp_squeue_entry_t, link);
-
-			log_msg(LVL_DEBUG, "NCSim - Sleep");
-			rc = fibril_condvar_wait_timeout(&sim_queue_cv,
-			    &sim_queue_lock, sqe->delay);
-		} while (rc != ETIMEOUT);
-
-		list_remove(link);
-		fibril_mutex_unlock(&sim_queue_lock);
-
-		log_msg(LVL_DEBUG, "NCSim - End Sleep");
-		tcp_rqueue_bounce_seg(&sqe->sp, sqe->seg);
-		free(sqe);
-	}
-}
-
-/** Start simulator handler thread. */
-void tcp_ncsim_thread_start(void)
-{
-	thread_id_t tid;
-        int rc;
-
-	log_msg(LVL_DEBUG, "tcp_ncsim_thread_start()");
-
-	rc = thread_create(tcp_ncsim_thread, NULL, "ncsim", &tid);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed creating ncsim thread.");
-		return;
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/ncsim.h
===================================================================
--- uspace/srv/net/tl/tcp/ncsim.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,48 +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 Network condition simulator
- */
-
-#ifndef NCSIM_H
-#define NCSIM_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_thread_start(void);
-
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/pdu.c
===================================================================
--- uspace/srv/net/tl/tcp/pdu.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,314 +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 TCP header encoding and decoding
- */
-
-#include <bitops.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <mem.h>
-#include <stdlib.h>
-#include "pdu.h"
-#include "segment.h"
-#include "seq_no.h"
-#include "std.h"
-#include "tcp_type.h"
-
-#define TCP_CHECKSUM_INIT 0xffff
-
-/** One's complement addition.
- *
- * Result is a + b + carry.
- */
-static uint16_t tcp_ocadd16(uint16_t a, uint16_t b)
-{
-	uint32_t s;
-
-	s = (uint32_t)a + (uint32_t)b;
-	return (s & 0xffff) + (s >> 16);
-}
-
-static uint16_t tcp_checksum_calc(uint16_t ivalue, void *data, size_t size)
-{
-	uint16_t sum;
-	uint16_t w;
-	size_t words, i;
-	uint8_t *bdata;
-
-	sum = ~ivalue;
-	words = size / 2;
-	bdata = (uint8_t *)data;
-
-	for (i = 0; i < words; i++) {
-		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
-		sum = tcp_ocadd16(sum, w);
-	}
-
-	if (size % 2 != 0) {
-		w = ((uint16_t)bdata[2*words] << 8);
-		sum = tcp_ocadd16(sum, w);
-	}
-
-	return ~sum;
-}
-
-static void tcp_header_decode_flags(uint16_t doff_flags, tcp_control_t *rctl)
-{
-	tcp_control_t ctl;
-
-	ctl = 0;
-
-	if ((doff_flags & BIT_V(uint16_t, DF_URG)) != 0)
-		ctl |= 0 /* XXX */;
-	if ((doff_flags & BIT_V(uint16_t, DF_ACK)) != 0)
-		ctl |= CTL_ACK;
-	if ((doff_flags & BIT_V(uint16_t, DF_PSH)) != 0)
-		ctl |= 0 /* XXX */;
-	if ((doff_flags & BIT_V(uint16_t, DF_RST)) != 0)
-		ctl |= CTL_RST;
-	if ((doff_flags & BIT_V(uint16_t, DF_SYN)) != 0)
-		ctl |= CTL_SYN;
-	if ((doff_flags & BIT_V(uint16_t, DF_FIN)) != 0)
-		ctl |= CTL_FIN;
-
-	*rctl = ctl;
-}
-
-static void tcp_header_encode_flags(tcp_control_t ctl, uint16_t doff_flags0,
-    uint16_t *rdoff_flags)
-{
-	uint16_t doff_flags;
-
-	doff_flags = doff_flags0;
-
-	if ((ctl & CTL_ACK) != 0)
-		doff_flags |= BIT_V(uint16_t, DF_ACK);
-	if ((ctl & CTL_RST) != 0)
-		doff_flags |= BIT_V(uint16_t, DF_RST);
-	if ((ctl & CTL_SYN) != 0)
-		doff_flags |= BIT_V(uint16_t, DF_SYN);
-	if ((ctl & CTL_FIN) != 0)
-		doff_flags |= BIT_V(uint16_t, DF_FIN);
-
-	*rdoff_flags = doff_flags;
-}
-
-static void tcp_header_setup(tcp_sockpair_t *sp, 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->seq = host2uint32_t_be(seg->seq);
-	hdr->ack = host2uint32_t_be(seg->ack);
-
-	doff = (sizeof(tcp_header_t) / sizeof(uint32_t)) << DF_DATA_OFFSET_l;
-	tcp_header_encode_flags(seg->ctrl, doff, &doff_flags);
-
-	hdr->doff_flags = host2uint16_t_be(doff_flags);
-	hdr->window = host2uint16_t_be(seg->wnd);
-	hdr->checksum = 0;
-	hdr->urg_ptr = host2uint16_t_be(seg->up);
-}
-
-static void tcp_phdr_setup(tcp_pdu_t *pdu, tcp_phdr_t *phdr)
-{
-	phdr->src_addr = host2uint32_t_be(pdu->src_addr.ipv4);
-	phdr->dest_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
-	phdr->zero = 0;
-	phdr->protocol = 6; /* XXX Magic number */
-	phdr->tcp_length = host2uint16_t_be(pdu->header_size + pdu->text_size);
-}
-
-static void tcp_header_decode(tcp_header_t *hdr, tcp_segment_t *seg)
-{
-	tcp_header_decode_flags(uint16_t_be2host(hdr->doff_flags), &seg->ctrl);
-	seg->seq = uint32_t_be2host(hdr->seq);
-	seg->ack = uint32_t_be2host(hdr->ack);
-	seg->wnd = uint16_t_be2host(hdr->window);
-	seg->up = uint16_t_be2host(hdr->urg_ptr);
-}
-
-static int tcp_header_encode(tcp_sockpair_t *sp, tcp_segment_t *seg,
-    void **header, size_t *size)
-{
-	tcp_header_t *hdr;
-
-	hdr = calloc(1, sizeof(tcp_header_t));
-	if (hdr == NULL)
-		return ENOMEM;
-
-	tcp_header_setup(sp, seg, hdr);
-	*header = hdr;
-	*size = sizeof(tcp_header_t);
-
-	return EOK;
-}
-
-static tcp_pdu_t *tcp_pdu_new(void)
-{
-	return calloc(1, sizeof(tcp_pdu_t));
-}
-
-/** Create PDU with the specified header and text data.
- *
- * Note that you still need to set addresses in the returned PDU.
- *
- * @param hdr		Header data
- * @param hdr_size      Header size in bytes
- * @param text		Text data
- * @param text_size	Text size in bytes
- * @return		New PDU
- */
-tcp_pdu_t *tcp_pdu_create(void *hdr, size_t hdr_size, void *text,
-    size_t text_size)
-{
-	tcp_pdu_t *pdu;
-
-	pdu = tcp_pdu_new();
-	if (pdu == NULL)
-		return NULL;
-
-	pdu->header = malloc(hdr_size);
-	pdu->text = malloc(text_size);
-	if (pdu->header == NULL || pdu->text == NULL)
-		goto error;
-
-	memcpy(pdu->header, hdr, hdr_size);
-	memcpy(pdu->text, text, text_size);
-
-	pdu->header_size = hdr_size;
-	pdu->text_size = text_size;
-
-	return pdu;
-
-error:
-	if (pdu->header != NULL)
-		free(pdu->header);
-	if (pdu->text != NULL)
-		free(pdu->text);
-
-	return NULL;
-}
-
-void tcp_pdu_delete(tcp_pdu_t *pdu)
-{
-	free(pdu->header);
-	free(pdu->text);
-	free(pdu);
-}
-
-static uint16_t tcp_pdu_checksum_calc(tcp_pdu_t *pdu)
-{
-	uint16_t cs_phdr;
-	uint16_t cs_headers;
-	uint16_t cs_all;
-	tcp_phdr_t phdr;
-
-	tcp_phdr_setup(pdu, &phdr);
-	cs_phdr = tcp_checksum_calc(TCP_CHECKSUM_INIT, (void *)&phdr,
-	    sizeof(tcp_phdr_t));
-	cs_headers = tcp_checksum_calc(cs_phdr, pdu->header, pdu->header_size);
-	cs_all = tcp_checksum_calc(cs_headers, pdu->text, pdu->text_size);
-
-	return cs_all;
-}
-
-static void tcp_pdu_set_checksum(tcp_pdu_t *pdu, uint16_t checksum)
-{
-	tcp_header_t *hdr;
-
-	hdr = (tcp_header_t *)pdu->header;
-	hdr->checksum = host2uint16_t_be(checksum);
-}
-
-/** Encode outgoing PDU */
-int tcp_pdu_decode(tcp_pdu_t *pdu, tcp_sockpair_t *sp, tcp_segment_t **seg)
-{
-	tcp_segment_t *nseg;
-	tcp_header_t *hdr;
-
-	nseg = tcp_segment_make_data(0, pdu->text, pdu->text_size);
-	if (nseg == NULL)
-		return ENOMEM;
-
-	tcp_header_decode(pdu->header, nseg);
-	nseg->len += seq_no_control_len(nseg->ctrl);
-
-	hdr = (tcp_header_t *)pdu->header;
-
-	sp->local.port = uint16_t_be2host(hdr->dest_port);
-	sp->local.addr = pdu->dest_addr;
-	sp->foreign.port = uint16_t_be2host(hdr->src_port);
-	sp->foreign.addr = pdu->src_addr;
-
-	*seg = nseg;
-	return EOK;
-}
-
-/** Decode incoming PDU */
-int tcp_pdu_encode(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_pdu_t **pdu)
-{
-	tcp_pdu_t *npdu;
-	size_t text_size;
-	uint16_t checksum;
-
-	npdu = tcp_pdu_new();
-	if (npdu == NULL)
-		return ENOMEM;
-
-	npdu->src_addr = sp->local.addr;
-	npdu->dest_addr = sp->foreign.addr;
-	tcp_header_encode(sp, seg, &npdu->header, &npdu->header_size);
-
-	text_size = tcp_segment_text_size(seg);
-	npdu->text = calloc(1, text_size);
-	if (npdu->text == NULL)
-		return ENOMEM;
-
-	npdu->text_size = text_size;
-	memcpy(npdu->text, seg->data, text_size);
-
-	/* Checksum calculation */
-	checksum = tcp_pdu_checksum_calc(npdu);
-	tcp_pdu_set_checksum(npdu, checksum);
-
-	*pdu = npdu;
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/pdu.h
===================================================================
--- uspace/srv/net/tl/tcp/pdu.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,50 +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 TCP PDU (encoded Protocol Data Unit) handling
- */
-
-#ifndef PDU_H
-#define PDU_H
-
-#include <sys/types.h>
-#include "std.h"
-#include "tcp_type.h"
-
-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 **);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/rqueue.c
===================================================================
--- uspace/srv/net/tl/tcp/rqueue.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,163 +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 Global segment receive queue
- */
-
-#include <adt/prodcons.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdlib.h>
-#include <thread.h>
-#include "conn.h"
-#include "pdu.h"
-#include "rqueue.h"
-#include "segment.h"
-#include "tcp_type.h"
-#include "ucall.h"
-
-/** Transcode bounced segments.
- *
- * If defined, segments bounced via the internal debugging loopback will
- * be encoded to a PDU and the decoded. Otherwise they will be bounced back
- * directly without passing the encoder-decoder.
- */
-#define BOUNCE_TRANSCODE
-
-static prodcons_t rqueue;
-
-/** Initialize segment receive queue. */
-void tcp_rqueue_init(void)
-{
-	prodcons_initialize(&rqueue);
-}
-
-/** Bounce segment directy into receive queue without constructing the PDU.
- *
- * This is for testing purposes only.
- *
- * @param sp	Socket pair, oriented for transmission
- * @param seg	Segment
- */
-void tcp_rqueue_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_sockpair_t rident;
-
-	log_msg(LVL_DEBUG, "tcp_rqueue_bounce_seg()");
-
-#ifdef BOUNCE_TRANSCODE
-	tcp_pdu_t *pdu;
-	tcp_segment_t *dseg;
-
-	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
-		return;
-	}
-
-	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
-		return;
-	}
-
-	tcp_pdu_delete(pdu);
-
-	/** Insert decoded segment into rqueue */
-	tcp_rqueue_insert_seg(&rident, dseg);
-	tcp_segment_delete(seg);
-#else
-	/* Reverse the identification */
-	tcp_sockpair_flipped(sp, &rident);
-
-	/* Insert segment back into rqueue */
-	tcp_rqueue_insert_seg(&rident, seg);
-#endif
-}
-
-/** Insert segment into receive queue.
- *
- * @param sp	Socket pair, oriented for reception
- * @param seg	Segment
- */
-void tcp_rqueue_insert_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_rqueue_entry_t *rqe;
-	log_msg(LVL_DEBUG, "tcp_rqueue_insert_seg()");
-
-	tcp_segment_dump(seg);
-
-	rqe = calloc(1, sizeof(tcp_rqueue_entry_t));
-	if (rqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating RQE.");
-		return;
-	}
-
-	rqe->sp = *sp;
-	rqe->seg = seg;
-
-	prodcons_produce(&rqueue, &rqe->link);
-}
-
-/** Receive queue handler thread. */
-static void tcp_rqueue_thread(void *arg)
-{
-	link_t *link;
-	tcp_rqueue_entry_t *rqe;
-
-	log_msg(LVL_DEBUG, "tcp_rqueue_thread()");
-
-	while (true) {
-		link = prodcons_consume(&rqueue);
-		rqe = list_get_instance(link, tcp_rqueue_entry_t, link);
-
-		tcp_as_segment_arrived(&rqe->sp, rqe->seg);
-	}
-}
-
-/** Start receive queue handler thread. */
-void tcp_rqueue_thread_start(void)
-{
-	thread_id_t tid;
-        int rc;
-
-	log_msg(LVL_DEBUG, "tcp_rqueue_thread_start()");
-
-	rc = thread_create(tcp_rqueue_thread, NULL, "rqueue", &tid);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed creating rqueue thread.");
-		return;
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/rqueue.h
===================================================================
--- uspace/srv/net/tl/tcp/rqueue.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,50 +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 Global segment receive queue
- */
-
-#ifndef RQUEUE_H
-#define RQUEUE_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_handler(void *);
-extern void tcp_rqueue_thread_start(void);
-
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/segment.c
===================================================================
--- uspace/srv/net/tl/tcp/segment.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,261 +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 Segment processing
- */
-
-#include <io/log.h>
-#include <mem.h>
-#include <stdlib.h>
-#include "segment.h"
-#include "seq_no.h"
-#include "tcp_type.h"
-
-/** Alocate new segment structure. */
-tcp_segment_t *tcp_segment_new(void)
-{
-	return calloc(1, sizeof(tcp_segment_t));
-}
-
-/** Delete segment. */
-void tcp_segment_delete(tcp_segment_t *seg)
-{
-	free(seg);
-}
-
-/** Create duplicate of segment.
- *
- * @param seg	Segment
- * @return 	Duplicate segment
- */
-tcp_segment_t *tcp_segment_dup(tcp_segment_t *seg)
-{
-	tcp_segment_t *scopy;
-	size_t tsize;
-
-	scopy = tcp_segment_new();
-	if (scopy == NULL)
-		return NULL;
-
-	scopy->ctrl = seg->ctrl;
-	scopy->seq = seg->seq;
-	scopy->ack = seg->ack;
-	scopy->len = seg->len;
-	scopy->wnd = seg->wnd;
-	scopy->up = seg->up;
-
-	tsize = tcp_segment_text_size(seg);
-	scopy->data = calloc(tsize, 1);
-	if (scopy->data == NULL) {
-		free(scopy);
-		return NULL;
-	}
-
-	memcpy(scopy->data, seg->data, tsize);
-	scopy->dfptr = scopy->data;
-
-	return scopy;
-}
-
-/** Create a control-only segment.
- *
-  * @return	Segment
- */
-tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t ctrl)
-{
-	tcp_segment_t *seg;
-
-	seg = tcp_segment_new();
-	if (seg == NULL)
-		return NULL;
-
-	seg->ctrl = ctrl;
-	seg->len = seq_no_control_len(ctrl);
-
-	return seg;
-}
-
-/** Create an RST segment.
- *
- * @param seg	Segment we are replying to
- * @return	RST segment
- */
-tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *seg)
-{
-	tcp_segment_t *rseg;
-
-	rseg = tcp_segment_new();
-	if (rseg == NULL)
-		return NULL;
-
-	if ((seg->ctrl & CTL_ACK) == 0) {
-		rseg->ctrl = CTL_RST | CTL_ACK;
-		rseg->seq = 0;
-		rseg->ack = seg->seq + seg->len;
-	} else {
-		rseg->ctrl = CTL_RST;
-		rseg->seq = seg->ack;
-	}
-
-	return rseg;
-}
-
-/** Create a control segment.
- *
-  * @return	Segment
- */
-tcp_segment_t *tcp_segment_make_data(tcp_control_t ctrl, void *data,
-    size_t size)
-{
-	tcp_segment_t *seg;
-
-	seg = tcp_segment_new();
-	if (seg == NULL)
-		return NULL;
-
-	seg->ctrl = ctrl;
-	seg->len = seq_no_control_len(ctrl) + size;
-
-	seg->dfptr = seg->data = malloc(size);
-	if (seg->dfptr == NULL) {
-		free(seg);
-		return NULL;
-	}
-
-	memcpy(seg->data, data, size);
-
-	return seg;
-}
-
-
-/** Trim segment from left and right by the specified amount.
- *
- * Trim any text or control to remove the specified amount of sequence
- * numbers from the left (lower sequence numbers) and right side
- * (higher sequence numbers) of the segment.
- *
- * @param seg		Segment, will be modified in place
- * @param left		Amount of sequence numbers to trim from the left
- * @param right		Amount of sequence numbers to trim from the right
- */
-void tcp_segment_trim(tcp_segment_t *seg, uint32_t left, uint32_t right)
-{
-	uint32_t t_size;
-
-	assert(left + right <= seg->len);
-
-	/* Special case, entire segment trimmed from left */
-	if (left == seg->len) {
-		seg->seq = seg->seq + seg->len;
-		seg->len = 0;
-		return;
-	}
-
-	/* Special case, entire segment trimmed from right */
-	if (right == seg->len) {
-		seg->len = 0;
-		return;
-	}
-
-	/* General case */
-
-	t_size = tcp_segment_text_size(seg);
-
-	if (left > 0 && (seg->ctrl & CTL_SYN) != 0) {
-		/* Trim SYN */
-		seg->ctrl &= ~CTL_SYN;
-		seg->seq++;
-		seg->len--;
-		left--;
-	}
-
-	if (right > 0 && (seg->ctrl & CTL_FIN) != 0) {
-		/* Trim FIN */
-		seg->ctrl &= ~CTL_FIN;
-		seg->len--;
-		right--;
-	}
-
-	if (left > 0 || right > 0) {
-		/* Trim segment text */
-		assert(left + right <= t_size);
-
-		seg->data += left;
-		seg->len -= left + right;
-	}
-}
-
-/** Copy out text data from segment.
- *
- * Data is copied from the beginning of the segment text up to @a size bytes.
- * @a size must not be greater than the size of the segment text, but
- * it can be less.
- *
- * @param seg	Segment
- * @param buf	Destination buffer
- * @param size	Size of destination buffer
- */
-void tcp_segment_text_copy(tcp_segment_t *seg, void *buf, size_t size)
-{
-	assert(size <= tcp_segment_text_size(seg));
-	memcpy(buf, seg->data, size);
-}
-
-/** Return number of bytes in segment text.
- *
- * @param seg	Segment
- * @return	Number of bytes in segment text
- */
-size_t tcp_segment_text_size(tcp_segment_t *seg)
-{
-	return seg->len - seq_no_control_len(seg->ctrl);
-}
-
-/** Dump segment contents to log.
- *
- * @param seg	Segment
- */
-void tcp_segment_dump(tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "Segment dump:");
-	log_msg(LVL_DEBUG, " - ctrl = %u", (unsigned)seg->ctrl);
-	log_msg(LVL_DEBUG, " - seq = % " PRIu32, seg->seq);
-	log_msg(LVL_DEBUG, " - ack = % " PRIu32, seg->ack);
-	log_msg(LVL_DEBUG, " - len = % " PRIu32, seg->len);
-	log_msg(LVL_DEBUG, " - wnd = % " PRIu32, seg->wnd);
-	log_msg(LVL_DEBUG, " - up = % " PRIu32, seg->up);
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/segment.h
===================================================================
--- uspace/srv/net/tl/tcp/segment.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,57 +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 Segment processing
- */
-
-#ifndef SEGMENT_H
-#define SEGMENT_H
-
-#include <sys/types.h>
-#include "tcp_type.h"
-
-extern tcp_segment_t *tcp_segment_new(void);
-extern void tcp_segment_delete(tcp_segment_t *);
-extern tcp_segment_t *tcp_segment_dup(tcp_segment_t *);
-extern tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t);
-extern tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *);
-extern tcp_segment_t *tcp_segment_make_data(tcp_control_t, void *, size_t);
-extern void tcp_segment_trim(tcp_segment_t *, uint32_t, uint32_t);
-extern void tcp_segment_text_copy(tcp_segment_t *, void *, size_t);
-extern size_t tcp_segment_text_size(tcp_segment_t *);
-extern void tcp_segment_dump(tcp_segment_t *);
-
-
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/seq_no.c
===================================================================
--- uspace/srv/net/tl/tcp/seq_no.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,243 +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 Sequence number computations
- */
-
-#include <assert.h>
-#include <bool.h>
-#include <sys/types.h>
-#include "seq_no.h"
-#include "tcp_type.h"
-
-/** a <= b < c modulo sequence space */
-static bool seq_no_le_lt(uint32_t a, uint32_t b, uint32_t c)
-{
-	if (a <= c) {
-		return (a <= b) && (b < c);
-	} else {
-		return (b < c) || (a <= b);
-	}
-}
-
-/** a < b <= c modulo sequence space */
-static bool seq_no_lt_le(uint32_t a, uint32_t b, uint32_t c)
-{
-	if (a <= c) {
-		return (a < b) && (b <= c);
-	} else {
-		return (b <= c) || (a < b);
-	}
-}
-
-/** Determine wheter ack is acceptable (new acknowledgement) */
-bool seq_no_ack_acceptable(tcp_conn_t *conn, uint32_t seg_ack)
-{
-	/* SND.UNA < SEG.ACK <= SND.NXT */
-	return seq_no_lt_le(conn->snd_una, seg_ack, conn->snd_nxt);
-}
-
-/** Determine wheter ack is duplicate.
- *
- * ACK is duplicate if it refers to a sequence number that has
- * aleady been acked (SEG.ACK <= SND.UNA).
- */
-bool seq_no_ack_duplicate(tcp_conn_t *conn, uint32_t seg_ack)
-{
-	uint32_t diff;
-
-	/*
-	 * There does not seem to be a three-point comparison
-	 * equivalent of SEG.ACK < SND.UNA. Thus we do it
-	 * on a best-effort basis, based on the difference.
-	 * [-2^31, 0) means less-than, 0 means equal, [0, 2^31)
-	 * means greater-than. Less-than or equal means duplicate.
-	 */
-	diff = seg_ack - conn->snd_una;
-	return diff == 0 || (diff & (0x1 << 31)) != 0;
-}
-
-/** Determine if sequence number is in receive window. */
-bool seq_no_in_rcv_wnd(tcp_conn_t *conn, uint32_t sn)
-{
-	return seq_no_le_lt(conn->rcv_nxt, sn, conn->rcv_nxt + conn->rcv_wnd);
-}
-
-/** Determine segment has new window update.
- *
- * Window update is new if either SND.WL1 < SEG.SEQ or
- * (SND.WL1 = SEG.SEQ and SND.WL2 <= SEG.ACK).
- */
-bool seq_no_new_wnd_update(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	bool n_seq, n_ack;
-
-	assert(seq_no_segment_acceptable(conn, seg));
-
-	/*
-	 * We make use of the fact that the peer should not ACK anything
-	 * beyond our send window (we surely haven't sent that yet)
-	 * as we should have filtered those acks out.
-	 * We use SND.UNA+SND.WND as the third point of comparison.
-	 */
-
-	n_seq = seq_no_lt_le(conn->snd_wl1, seg->seq,
-	    conn->snd_una + conn->snd_wnd);
-
-	n_ack = conn->snd_wl1 == seg->seq &&
-	    seq_no_le_lt(conn->snd_wl2, seg->ack,
-	    conn->snd_una + conn->snd_wnd + 1);
-
-	return n_seq || n_ack;
-}
-
-/** Determine if segment is ready for processing.
- *
- * Assuming segment is acceptable, a segment is ready if it intersects
- * RCV.NXT, that is we can process it immediately.
- */
-bool seq_no_segment_ready(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	assert(seq_no_segment_acceptable(conn, seg));
-
-	return seq_no_le_lt(seg->seq, conn->rcv_nxt, seg->seq + seg->len + 1);
-}
-
-/** Determine whether segment is fully acked */
-bool seq_no_segment_acked(tcp_conn_t *conn, tcp_segment_t *seg, uint32_t ack)
-{
-	assert(seg->len > 0);
-	return seq_no_lt_le(seg->seq, seg->seq + seg->len, ack);
-}
-
-/** Determine whether initial SYN is acked */
-bool seq_no_syn_acked(tcp_conn_t *conn)
-{
-	return seq_no_lt_le(conn->iss, conn->snd_una, conn->snd_nxt);
-}
-
-/** Determine whether segment overlaps the receive window */
-bool seq_no_segment_acceptable(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	bool b_in, e_in;
-
-	b_in = seq_no_le_lt(conn->rcv_nxt, seg->seq, conn->rcv_nxt
-	    + conn->rcv_wnd);
-
-	e_in = seq_no_le_lt(conn->rcv_nxt, seg->seq + seg->len - 1,
-	    conn->rcv_nxt + conn->rcv_wnd);
-
-	if (seg->len == 0 && conn->rcv_wnd == 0) {
-		return seg->seq == conn->rcv_nxt;
-	} else if (seg->len == 0 && conn->rcv_wnd != 0) {
-		return b_in;
-	} else if (seg->len > 0 && conn->rcv_wnd == 0) {
-		return false;
-	} else {
-		return b_in || e_in;
-	}
-}
-
-/** Determine size that control bits occupy in sequence space. */
-uint32_t seq_no_control_len(tcp_control_t ctrl)
-{
-	uint32_t len = 0;
-
-	if ((ctrl & CTL_SYN) != 0)
-		++len;
-
-	if ((ctrl & CTL_FIN) != 0)
-		++len;
-
-	return len;
-}
-
-/** Calculate the amount of trim needed to fit segment in receive window. */
-void seq_no_seg_trim_calc(tcp_conn_t *conn, tcp_segment_t *seg,
-    uint32_t *left, uint32_t *right)
-{
-	assert(seq_no_segment_acceptable(conn, seg));
-
-	/*
-	 * If RCV.NXT is between SEG.SEQ and RCV.NXT+RCV.WND, then
-	 * left trim amount is positive
-	 */
-	if (seq_no_lt_le(seg->seq, conn->rcv_nxt,
-	    conn->rcv_nxt + conn->rcv_wnd)) {
-		*left = conn->rcv_nxt - seg->seq;
-	} else {
-		*left = 0;
-	}
-
-	/*
-	 * If SEG.SEQ+SEG.LEN is between SEG.SEQ and RCV.NXT+RCV.WND,
-	 * then right trim is zero.
-	 */
-	if (seq_no_lt_le(seg->seq - 1, seg->seq + seg->len,
-	    conn->rcv_nxt + conn->rcv_wnd)) {
-		*right = 0;
-	} else {
-		*right = (seg->seq + seg->len) -
-		    (conn->rcv_nxt + conn->rcv_wnd);
-	}
-}
-
-/** Segment order comparison.
- *
- * Compare sequence order of two acceptable segments.
- *
- * @param conn		Connection
- * @param sa		Segment A
- * @param sb		Segment B
- *
- * @return		-1, 0, 1, resp. if A < B, A == B, A > B in terms
- *			of sequence order of the beginning of the segment.
- */
-int seq_no_seg_cmp(tcp_conn_t *conn, tcp_segment_t *sa, tcp_segment_t *sb)
-{
-	assert(seq_no_segment_acceptable(conn, sa));
-	assert(seq_no_segment_acceptable(conn, sb));
-
-	if (seq_no_lt_le(sa->seq, sb->seq, conn->rcv_nxt + conn->rcv_wnd))
-		return -1;
-
-	if (seq_no_lt_le(sb->seq, sa->seq, conn->rcv_nxt + conn->rcv_wnd))
-		return +1;
-
-	assert(sa->seq == sb->seq);
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/seq_no.h
===================================================================
--- uspace/srv/net/tl/tcp/seq_no.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,58 +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 Sequence number computations
- */
-
-#ifndef SEQ_NO_H
-#define SEQ_NO_H
-
-#include <sys/types.h>
-#include "tcp_type.h"
-
-extern bool seq_no_ack_acceptable(tcp_conn_t *, uint32_t);
-extern bool seq_no_ack_duplicate(tcp_conn_t *, uint32_t);
-extern bool seq_no_in_rcv_wnd(tcp_conn_t *, uint32_t);
-extern bool seq_no_new_wnd_update(tcp_conn_t *, tcp_segment_t *);
-extern bool seq_no_segment_acked(tcp_conn_t *, tcp_segment_t *, uint32_t);
-extern bool seq_no_syn_acked(tcp_conn_t *);
-extern bool seq_no_segment_ready(tcp_conn_t *, tcp_segment_t *);
-extern bool seq_no_segment_acceptable(tcp_conn_t *, tcp_segment_t *);
-extern void seq_no_seg_trim_calc(tcp_conn_t *, tcp_segment_t *, uint32_t *,
-    uint32_t *);
-extern int seq_no_seg_cmp(tcp_conn_t *, tcp_segment_t *, tcp_segment_t *);
-
-extern uint32_t seq_no_control_len(tcp_control_t);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/sock.c
===================================================================
--- uspace/srv/net/tl/tcp/sock.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,832 +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 <io/log.h>
-#include <ip_client.h>
-#include <ipc/socket.h>
-#include <net/modules.h>
-#include <net/socket.h>
-
-#include "sock.h"
-#include "std.h"
-#include "tcp.h"
-#include "tcp_type.h"
-#include "ucall.h"
-
-#define FRAGMENT_SIZE 1024
-
-#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_cstate_cb(tcp_conn_t *conn, void *arg);
-
-void tcp_sock_init(void)
-{
-	socket_ports_initialize(&gsock);
-}
-
-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;
-}
-
-static void tcp_sock_notify_data(socket_core_t *sock_core)
-{
-	log_msg(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,
-	    FRAGMENT_SIZE, 0, 0, 1);
-	async_exchange_end(exch);
-}
-
-static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
-{
-	log_msg(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,
-	    FRAGMENT_SIZE, 0, 0, 0);
-	async_exchange_end(exch);
-}
-
-static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	tcp_sockdata_t *sock;
-	socket_core_t *sock_core;
-	int sock_id;
-	int rc;
-	ipc_call_t answer;
-
-	log_msg(LVL_DEBUG, "tcp_sock_socket()");
-	sock = calloc(sizeof(tcp_sockdata_t), 1);
-	if (sock == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&sock->lock);
-	sock->client = client;
-	sock->laddr.ipv4 = TCP_IPV4_ANY;
-	sock->lconn = NULL;
-	sock->backlog = 0;
-	list_initialize(&sock->ready);
-
-	sock_id = SOCKET_GET_SOCKET_ID(call);
-	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sock_core = socket_cores_find(&client->sockets, sock_id);
-	assert(sock_core != NULL);
-	sock->sock_core = sock_core;
-
-	refresh_answer(&answer, NULL);
-	SOCKET_SET_SOCKET_ID(answer, sock_id);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
-	answer_call(callid, EOK, &answer, 3);
-}
-
-static void tcp_sock_bind(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int rc;
-	struct sockaddr *addr;
-	size_t addr_len;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-
-	log_msg(LVL_DEBUG, "tcp_sock_bind()");
-	log_msg(LVL_DEBUG, " - async_data_write_accept");
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - call socket_bind");
-	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
-	    addr, addr_len, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-	    last_used_port);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - call socket_cores_find");
-	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
-	if (sock_core != NULL) {
-		socket = (tcp_sockdata_t *)sock_core->specific_data;
-		/* XXX Anything to do? */
-		(void) socket;
-	}
-
-	log_msg(LVL_DEBUG, " - success");
-	async_answer_0(callid, EOK);
-}
-
-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;
-
-	log_msg(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;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-
-	/*
-	 * Prepare @c backlog listening connections.
-	 */
-	fibril_mutex_lock(&socket->lock);
-
-	socket->backlog = backlog;
-	socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
-	if (socket->lconn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - open connections");
-
-	lsocket.addr.ipv4 = TCP_IPV4_ANY;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = TCP_IPV4_ANY;
-	fsocket.port = TCP_PORT_ANY;
-
-	for (i = 0; i < backlog; i++) {
-
-		lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
-		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)
-{
-	int rc;
-	struct sockaddr_in *addr;
-	int socket_id;
-	size_t addr_len;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	nic_device_id_t dev_id;
-	tcp_phdr_t *phdr;
-	size_t phdr_len;
-
-	log_msg(LVL_DEBUG, "tcp_sock_connect()");
-
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
-	if (rc != EOK || addr_len != sizeof(struct sockaddr_in)) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	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;
-	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;
-	}
-
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
-		/* Find route to determine local IP address. */
-		rc = ip_get_route_req(ip_sess, IPPROTO_TCP,
-		    (struct sockaddr *)addr, sizeof(*addr), &dev_id,
-		    (void **)&phdr, &phdr_len);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			log_msg(LVL_DEBUG, "tcp_transmit_connect: Failed to find route.");
-			return;
-		}
-
-		socket->laddr.ipv4 = uint32_t_be2host(phdr->src_addr);
-		log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
-		free(phdr);
-	}
-
-	lsocket.addr.ipv4 = socket->laddr.ipv4;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
-	fsocket.port = uint16_t_be2host(addr->sin_port);
-
-	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);
-	}
-
-	async_answer_0(callid, rc);
-
-	/* Push one fragment notification to client's queue */
-	tcp_sock_notify_data(sock_core);
-	log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");
-}
-
-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;
-	socket_core_t *asock_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(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;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	log_msg(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 */
-
-	lsocket.addr.ipv4 = TCP_IPV4_ANY;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = TCP_IPV4_ANY;
-	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 */
-
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
-	asocket = calloc(sizeof(tcp_sockdata_t), 1);
-	if (asocket == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&asocket->lock);
-	asocket->client = client;
-	asocket->conn = conn;
-	log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
-
-	rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
-
-	asock_core = socket_cores_find(&client->sockets, asock_id);
-	assert(asock_core != NULL);
-
-	refresh_answer(&answer, NULL);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	SOCKET_SET_SOCKET_ID(answer, asock_id);
-	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
-
-	answer_call(callid, asock_core->socket_id, &answer, 3);
-
-	/* Push one fragment notification to client's queue */
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
-	tcp_sock_notify_data(asock_core);
-	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;
-	uint8_t buffer[FRAGMENT_SIZE];
-	tcp_error_t trc;
-	int rc;
-
-	log_msg(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);
-		return;
-	}
-
-	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);
-			return;
-		}
-
-		if (length > FRAGMENT_SIZE)
-			length = FRAGMENT_SIZE;
-
-		rc = async_data_write_finalize(wcallid, buffer, length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			return;
-		}
-
-		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);
-			return;
-		}
-	}
-
-	refresh_answer(&answer, NULL);
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	answer_call(callid, EOK, &answer, 2);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(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)
-{
-	int socket_id;
-	int flags;
-	size_t addr_length, length;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t rcallid;
-	uint8_t buffer[FRAGMENT_SIZE];
-	size_t data_len;
-	xflags_t xflags;
-	tcp_error_t trc;
-	struct sockaddr_in addr;
-	tcp_sock_t *rsock;
-	int rc;
-
-	log_msg(LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	flags = SOCKET_GET_FLAGS(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) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-
-	(void)flags;
-
-	trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len,
-	    &xflags);
-	log_msg(LVL_DEBUG, "**** tcp_uc_receive done");
-
-	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(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
-		/* Fill addr */
-		rsock = &socket->conn->ident.foreign;
-		addr.sin_family = AF_INET;
-		addr.sin_addr.s_addr = host2uint32_t_be(rsock->addr.ipv4);
-		addr.sin_port = host2uint16_t_be(rsock->port);
-
-		log_msg(LVL_DEBUG, "addr read receive");
-		if (!async_data_read_receive(&rcallid, &addr_length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-
-		if (addr_length > sizeof(addr))
-			addr_length = sizeof(addr);
-
-		log_msg(LVL_DEBUG, "addr read finalize");
-		rc = async_data_read_finalize(rcallid, &addr, addr_length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "data read receive");
-	if (!async_data_read_receive(&rcallid, &length)) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (length > data_len)
-		length = data_len;
-
-	log_msg(LVL_DEBUG, "data read finalize");
-	rc = async_data_read_finalize(rcallid, buffer, length);
-
-	if (length < data_len && rc == EOK)
-		rc = EOVERFLOW;
-
-	SOCKET_SET_READ_DATA_LENGTH(answer, length);
-	answer_call(callid, EOK, &answer, 1);
-
-	/* Push one fragment notification to client's queue */
-	tcp_sock_notify_data(sock_core);
-	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 rc;
-	uint8_t buffer[FRAGMENT_SIZE];
-	size_t data_len;
-	xflags_t xflags;
-
-	log_msg(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) {
-		trc = tcp_uc_close(socket->conn);
-		if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EBADF);
-			return;
-		}
-
-		/* Drain incoming data. This should really be done in the background. */
-		do {
-			trc = tcp_uc_receive(socket->conn, buffer,
-			    FRAGMENT_SIZE, &data_len, &xflags);
-		} while (trc == TCP_EOK);
-
-		tcp_uc_delete(socket->conn);
-	}
-
-	rc = socket_destroy(net_sess, 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(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(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(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(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);
-}
-
-int tcp_sock_connection(async_sess_t *sess, ipc_callid_t iid, ipc_call_t icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	tcp_client_t client;
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	client.sess = sess;
-	socket_cores_initialize(&client.sockets);
-
-	while (true) {
-		callid = async_get_call(&call);
-		if (!IPC_GET_IMETHOD(call))
-			break;
-
-		log_msg(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;
-		}
-	}
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/sock.h
===================================================================
--- uspace/srv/net/tl/tcp/sock.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,46 +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 void tcp_sock_init(void);
-extern int tcp_sock_connection(async_sess_t *, ipc_callid_t, ipc_call_t);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/std.h
===================================================================
--- uspace/srv/net/tl/tcp/std.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,101 +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 TCP header definitions
- *
- * Based on IETF RFC 793
- */
-
-#ifndef STD_H
-#define STD_H
-
-#include <sys/types.h>
-
-/** TCP Header (fixed part) */
-typedef struct {
-	/** Source port */
-	uint16_t src_port;
-	/** Destination port */
-	uint16_t dest_port;
-	/** Sequence number */
-	uint32_t seq;
-	/** Acknowledgement number */
-	uint32_t ack;
-	/** Data Offset, Reserved, Flags */
-	uint16_t doff_flags;
-	/** Window */
-	uint16_t window;
-	/* Checksum */
-	uint16_t checksum;
-	/** Urgent pointer */
-	uint16_t urg_ptr;
-} tcp_header_t;
-
-/** Bits in tcp_header_t.doff_flags */
-enum doff_flags_bits {
-	DF_DATA_OFFSET_h	= 15,
-	DF_DATA_OFFSET_l	= 12,
-	DF_URG			= 5,
-	DF_ACK			= 4,
-	DF_PSH			= 3,
-	DF_RST			= 2,
-	DF_SYN			= 1,
-	DF_FIN			= 0
-};
-
-/** TCP pseudo header */
-typedef struct {
-	/** Source address */
-	uint32_t src_addr;
-	/** Destination address */
-	uint32_t dest_addr;
-	/** Zero */
-	uint8_t zero;
-	/** Protocol */
-	uint8_t protocol;
-	/** TCP length */
-	uint16_t tcp_length;
-} tcp_phdr_t;
-
-/** Option kind */
-enum opt_kind {
-	/** End of option list */
-	OPT_END_LIST		= 0,
-	/** No-operation */
-	OPT_NOP			= 1,
-	/** Maximum segment size */
-	OPT_MAX_SEG_SIZE	= 2
-};
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,446 +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 TCP (Transmission Control Protocol) network module
- */
-
-#include <async.h>
-#include <bitops.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdio.h>
-#include <task.h>
-
-#include <icmp_remote.h>
-#include <ip_client.h>
-#include <ip_interface.h>
-#include <ipc/services.h>
-#include <ipc/tl.h>
-#include <tl_common.h>
-#include <tl_skel.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-
-#include "ncsim.h"
-#include "pdu.h"
-#include "rqueue.h"
-#include "sock.h"
-#include "std.h"
-#include "tcp.h"
-#include "test.h"
-
-#define NAME       "tcp"
-
-async_sess_t *net_sess;
-static async_sess_t *icmp_sess;
-async_sess_t *ip_sess;
-packet_dimensions_t pkt_dims;
-
-static void tcp_received_pdu(tcp_pdu_t *pdu);
-
-/* Pull up packets into a single memory block. */
-static int pq_pullup(packet_t *packet, void **data, size_t *dsize)
-{
-	packet_t *npacket;
-	size_t tot_len;
-	int length;
-
-	npacket = packet;
-	tot_len = 0;
-	do {
-		length = packet_get_data_length(packet);
-		if (length <= 0)
-			return EINVAL;
-
-		tot_len += length;
-	} while ((npacket = pq_next(npacket)) != NULL);
-
-	uint8_t *buf;
-	uint8_t *dp;
-
-	buf = calloc(tot_len, 1);
-	if (buf == NULL) {
-		free(buf);
-		return ENOMEM;
-	}
-
-	npacket = packet;
-	dp = buf;
-	do {
-		length = packet_get_data_length(packet);
-		if (length <= 0) {
-			free(buf);
-			return EINVAL;
-		}
-
-		memcpy(dp, packet_get_data(packet), length);
-		dp += length;
-	} while ((npacket = pq_next(npacket)) != NULL);
-
-	*data = buf;
-	*dsize = tot_len;
-	return EOK;
-}
-
-/** Process packet received from network layer. */
-static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet,
-    services_t error)
-{
-	int rc;
-	size_t offset;
-	int length;
-	struct sockaddr_in *src_addr;
-	struct sockaddr_in *dest_addr;
-	size_t addr_len;
-
-	log_msg(LVL_DEBUG, "tcp_received_msg()");
-
-	switch (error) {
-	case SERVICE_NONE:
-		break;
-	case SERVICE_ICMP:
-	default:
-		log_msg(LVL_WARN, "Unsupported service number %u",
-		    (unsigned)error);
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return ENOTSUP;
-	}
-
-	/* Process and trim off IP header */
-	log_msg(LVL_DEBUG, "tcp_received_msg() - IP header");
-
-	rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
-	if (rc < 0) {
-		log_msg(LVL_WARN, "ip_client_process_packet() failed");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return rc;
-	}
-
-	offset = (size_t)rc;
-	length = packet_get_data_length(packet);
-
-	if (length < 0 || (size_t)length < offset) {
-		log_msg(LVL_WARN, "length=%d, dropping.", length);
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	addr_len = packet_get_addr(packet, (uint8_t **)&src_addr,
-	    (uint8_t **)&dest_addr);
-	if (addr_len <= 0) {
-		log_msg(LVL_WARN, "Failed to get packet address.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	if (addr_len != sizeof(struct sockaddr_in)) {
-		log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)",
-		    addr_len, sizeof(struct sockaddr_in));
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	rc = packet_trim(packet, offset, 0);
-	if (rc != EOK) {
-		log_msg(LVL_WARN, "Failed to trim packet.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return rc;
-	}
-
-	/* Pull up packets into a single memory block, pdu_raw. */
-	log_msg(LVL_DEBUG, "tcp_received_msg() - pull up");
-	uint8_t *pdu_raw;
-	size_t pdu_raw_size = 0;
-
-	pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size);
-
-	/* Split into header and payload. */
-
-	log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload");
-
-	tcp_pdu_t *pdu;
-	size_t hdr_size;
-	tcp_header_t *hdr;
-	uint32_t data_offset;
-
-	if (pdu_raw_size < sizeof(tcp_header_t)) {
-		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
-		    pdu_raw_size, sizeof(tcp_header_t));
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	hdr = (tcp_header_t *)pdu_raw;
-	data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
-	    uint16_t_be2host(hdr->doff_flags));
-
-	hdr_size = sizeof(uint32_t) * data_offset;
-
-	if (pdu_raw_size < hdr_size) {
-		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
-		    pdu_raw_size, hdr_size);
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	if (hdr_size < sizeof(tcp_header_t)) {
-		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
-		    hdr_size, sizeof(tcp_header_t));
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
-	    pdu_raw_size, hdr_size);
-	pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
-	    pdu_raw_size - hdr_size);
-	if (pdu == NULL) {
-		log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
-		return ENOMEM;
-	}
-
-	free(pdu_raw);
-
-	pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr);
-	pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr);
-	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
-	    pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
-
-	tcp_received_pdu(pdu);
-	tcp_pdu_delete(pdu);
-
-	return EOK;
-}
-
-/** Receive packets from network layer. */
-static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_receiver()");
-
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_TL_RECEIVED:
-			log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED");
-			rc = packet_translate_remote(net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc != EOK) {
-				log_msg(LVL_DEBUG, "Error %d translating packet.", rc);
-				async_answer_0(iid, (sysarg_t)rc);
-				break;
-			}
-			rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
-			    IPC_GET_ERROR(*icall));
-			async_answer_0(iid, (sysarg_t)rc);
-			break;
-		default:
-			log_msg(LVL_DEBUG, "method = %u",
-			    (unsigned)IPC_GET_IMETHOD(*icall));
-			async_answer_0(iid, ENOTSUP);
-			break;
-		}
-
-		iid = async_get_call(icall);
-	}
-}
-
-/** Transmit PDU over network layer. */
-void tcp_transmit_pdu(tcp_pdu_t *pdu)
-{
-	struct sockaddr_in dest;
-	nic_device_id_t dev_id;
-	void *phdr;
-	size_t phdr_len;
-	packet_dimension_t *pkt_dim;
-	int rc;
-	packet_t *packet;
-	void *pkt_data;
-	size_t pdu_size;
-
-	dest.sin_family = AF_INET;
-	dest.sin_port = 0; /* not needed */
-	dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
-
-	/* Find route. Obtained pseudo-header is not used. */
-	rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest,
-	    sizeof(dest), &dev_id, &phdr, &phdr_len);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route.");
-		return;
-	}
-
-	rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension.");
-		return;
-	}
-
-	pdu_size = pdu->header_size + pdu->text_size;
-
-	packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len,
-	    pkt_dim->prefix, pkt_dim->suffix);
-	if (!packet) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet.");
-		return;
-	}
-
-	pkt_data = packet_suffix(packet, pdu_size);
-	if (!pkt_data) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return;
-	}
-
-	rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return;
-	}
-
-	rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest));
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return;
-	}
-
-	/* Copy PDU data to packet */
-	memcpy(pkt_data, pdu->header, pdu->header_size);
-	memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text,
-	    pdu->text_size);
-
-	/* Transmit packet. XXX Transfers packet ownership to IP? */
-	ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0);
-}
-
-/** Process received PDU. */
-static void tcp_received_pdu(tcp_pdu_t *pdu)
-{
-	tcp_segment_t *dseg;
-	tcp_sockpair_t rident;
-
-	log_msg(LVL_DEBUG, "tcp_received_pdu()");
-
-	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
-		return;
-	}
-
-	/* Insert decoded segment into rqueue */
-	tcp_rqueue_insert_seg(&rident, dseg);
-}
-
-/* Called from libnet */
-void tl_connection(void)
-{
-	log_msg(LVL_DEBUG, "tl_connection()");
-}
-
-/* Called from libnet */
-int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *answer_count)
-{
-	async_sess_t *callback;
-
-	log_msg(LVL_DEBUG, "tl_message()");
-
-	*answer_count = 0;
-	callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return tcp_sock_connection(callback, callid, *call);
-
-	return ENOTSUP;
-}
-
-/* Called from libnet */
-int tl_initialize(async_sess_t *sess)
-{
-	int rc;
-
-	net_sess = sess;
-	icmp_sess = icmp_connect_module();
-
-	log_msg(LVL_DEBUG, "tl_initialize()");
-
-	tcp_sock_init();
-
-	ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP,
-	    tcp_receiver);
-	if (ip_sess == NULL)
-		return ENOENT;
-
-	rc = packet_dimensions_initialize(&pkt_dims);
-	if (rc != EOK)
-		return rc;
-
-	return EOK;
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	printf(NAME ": TCP (Transmission Control Protocol) network module\n");
-
-	rc = log_init(NAME, LVL_ERROR);
-	if (rc != EOK) {
-		printf(NAME ": Failed to initialize log.\n");
-		return 1;
-	}
-
-//	printf(NAME ": Accepting connections\n");
-//	task_retval(0);
-
-	tcp_rqueue_init();
-	tcp_rqueue_thread_start();
-
-	tcp_ncsim_init();
-	tcp_ncsim_thread_start();
-
-	if (0) tcp_test();
-/*
-	async_manager();
-*/
-	tl_module_start(SERVICE_TCP);
-
-	/* Not reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,49 +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 TCP (Transmission Control Protocol) network module
- */
-
-#ifndef TCP_H
-#define TCP_H
-
-#include <async.h>
-#include <packet_remote.h>
-#include "tcp_type.h"
-
-extern async_sess_t *net_sess;
-extern async_sess_t *ip_sess;
-extern void tcp_transmit_pdu(tcp_pdu_t *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_type.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,363 +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 TCP type definitions
- */
-
-#ifndef TCP_TYPE_H
-#define TCP_TYPE_H
-
-#include <adt/list.h>
-#include <async.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <socket_core.h>
-#include <sys/types.h>
-
-struct tcp_conn;
-
-typedef enum {
-	/** Listen */
-	st_listen,
-	/** Syn-sent */
-	st_syn_sent,
-	/** Syn-received */
-	st_syn_received,
-	/** Established */
-	st_established,
-	/** Fin-wait-1 */
-	st_fin_wait_1,
-	/** Fin-wait-2 */
-	st_fin_wait_2,
-	/** Close-wait */
-	st_close_wait,
-	/** Closing */
-	st_closing,
-	/** Last-ack */
-	st_last_ack,
-	/** Time-wait */
-	st_time_wait,
-	/** Closed */
-	st_closed
-} tcp_cstate_t;
-
-/** Error codes returned by TCP user calls (per the spec). */
-typedef enum {
-	/* OK */
-	TCP_EOK,
-	/* Connection aborted due to user timeout */
-	TCP_EABORTED,
-	/* Connection already exists */
-	TCP_EEXISTS,
-	/* Connection closing */
-	TCP_ECLOSING,
-	/* Connection does not exist */
-	TCP_ENOTEXIST,
-	/* Connection illegal for this process */
-	TCP_EILLEGAL,
-	/* Connection not open */
-	TCP_ENOTOPEN,
-	/* Connection reset */
-	TCP_ERESET,
-	/* Foreign socket unspecified */
-	TCP_EUNSPEC,
-	/* Insufficient resources */
-	TCP_ENORES,
-	/* Precedence not allowed */
-	TCP_EINVPREC,
-	/* Security/compartment not allowed */
-	TCP_EINVCOMP
-} tcp_error_t;
-
-typedef enum {
-	XF_PUSH		= 0x1,
-	XF_URGENT	= 0x2
-} xflags_t;
-
-typedef enum {
-	CTL_SYN		= 0x1,
-	CTL_FIN		= 0x2,
-	CTL_RST		= 0x4,
-	CTL_ACK		= 0x8
-} tcp_control_t;
-
-typedef struct {
-	uint32_t ipv4;
-} netaddr_t;
-
-typedef struct {
-	netaddr_t addr;
-	uint16_t port;
-} tcp_sock_t;
-
-enum netaddr {
-	TCP_IPV4_ANY = 0
-};
-
-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 {
-	struct tcp_conn *conn;
-	list_t list;
-} tcp_iqueue_t;
-
-/** Retransmission queue */
-typedef struct {
-	struct tcp_conn *conn;
-	list_t list;
-
-	/** Retransmission timer */
-	fibril_timer_t *timer;
-} tcp_tqueue_t;
-
-typedef enum {
-	ap_active,
-	ap_passive
-} acpass_t;
-
-typedef enum {
-	tcp_open_nonblock = 1
-} tcp_open_flags_t;
-
-typedef struct tcp_conn tcp_conn_t;
-
-/** Connection state change callback function */
-typedef void (*tcp_cstate_cb_t)(tcp_conn_t *, void *);
-
-/** Connection */
-struct tcp_conn {
-	char *name;
-	link_t link;
-
-	/** Connection state change callback function */
-	tcp_cstate_cb_t cstate_cb;
-	/** Argument to @c cstate_cb */
-	void *cstate_cb_arg;
-
-	/** Connection identification (local and foreign socket) */
-	tcp_sockpair_t ident;
-
-	/** Active or passive connection */
-	acpass_t ap;
-
-	/** Protects access to connection structure */
-	fibril_mutex_t lock;
-	/** Reference count */
-	atomic_t refcnt;
-
-	/** Connection state */
-	tcp_cstate_t cstate;
-	/** True if connection was reset */
-	bool reset;
-	/** True if connection was deleted by user */
-	bool deleted;
-	/** Signalled when @c cstate changes */
-	fibril_condvar_t cstate_cv;
-
-	/** Set when FIN is removed from the retransmission queue */
-	bool fin_is_acked;
-
-	/** Queue of incoming segments */
-	tcp_iqueue_t incoming;
-
-	/** Retransmission queue */
-	tcp_tqueue_t retransmit;
-
-	/** Time-Wait timeout timer */
-	fibril_timer_t *tw_timer;
-
-	/** Receive buffer */
-	uint8_t *rcv_buf;
-	/** Receive buffer size */
-	size_t rcv_buf_size;
-	/** Receive buffer number of bytes used */
-	size_t rcv_buf_used;
-	/** Receive buffer contains FIN */
-	bool rcv_buf_fin;
-	/** Receive buffer CV. Broadcast when new data is inserted */
-	fibril_condvar_t rcv_buf_cv;
-
-	/** Send buffer */
-	uint8_t *snd_buf;
-	/** Send buffer size */
-	size_t snd_buf_size;
-	/** Send buffer number of bytes used */
-	size_t snd_buf_used;
-	/** Send buffer contains FIN */
-	bool snd_buf_fin;
-	/** Send buffer CV. Broadcast when space is made available in buffer */
-	fibril_condvar_t snd_buf_cv;
-
-	/** Send unacknowledged */
-	uint32_t snd_una;
-	/** Send next */
-	uint32_t snd_nxt;
-	/** Send window */
-	uint32_t snd_wnd;
-	/** Send urgent pointer */
-	uint32_t snd_up;
-	/** Segment sequence number used for last window update */
-	uint32_t snd_wl1;
-	/** Segment acknowledgement number used for last window update */
-	uint32_t snd_wl2;
-	/** Initial send sequence number */
-	uint32_t iss;
-
-	/** Receive next */
-	uint32_t rcv_nxt;
-	/** Receive window */
-	uint32_t rcv_wnd;
-	/** Receive urgent pointer */
-	uint32_t rcv_up;
-	/** Initial receive sequence number */
-	uint32_t irs;
-};
-
-/** Data returned by Status user call */
-typedef struct {
-	/** Connection state */
-	tcp_cstate_t cstate;
-} tcp_conn_status_t;
-
-typedef struct {
-	/** SYN, FIN */
-	tcp_control_t ctrl;
-
-	/** Segment sequence number */
-	uint32_t seq;
-	/** Segment acknowledgement number */
-	uint32_t ack;
-	/** Segment length in sequence space */
-	uint32_t len;
-	/** Segment window */
-	uint32_t wnd;
-	/** Segment urgent pointer */
-	uint32_t up;
-
-	/** Segment data, may be moved when trimming segment */
-	void *data;
-	/** Segment data, original pointer used to free data */
-	void *dfptr;
-} tcp_segment_t;
-
-
-typedef struct {
-	link_t link;
-	tcp_sockpair_t sp;
-	tcp_segment_t *seg;
-} tcp_rqueue_entry_t;
-
-/** NCSim queue entry */
-typedef struct {
-	link_t link;
-	suseconds_t delay;
-	tcp_sockpair_t sp;
-	tcp_segment_t *seg;
-} tcp_squeue_entry_t;
-
-typedef struct {
-	link_t link;
-	tcp_segment_t *seg;
-} tcp_iqueue_entry_t;
-
-/** Retransmission queue entry */
-typedef struct {
-	link_t link;
-	tcp_conn_t *conn;
-	tcp_segment_t *seg;
-} tcp_tqueue_entry_t;
-
-typedef enum {
-	cp_continue,
-	cp_done
-} cproc_t;
-
-/** Encoded PDU */
-typedef struct {
-	/** Source address */
-	netaddr_t src_addr;
-	/** Destination address */
-	netaddr_t dest_addr;
-
-	/** Encoded header */
-	void *header;
-	/** Encoded header size */
-	size_t header_size;
-	/** Text */
-	void *text;
-	/** Text size */
-	size_t text_size;
-} tcp_pdu_t;
-
-typedef struct {
-	async_sess_t *sess;
-	socket_cores_t sockets;
-} tcp_client_t;
-
-typedef struct tcp_sockdata {
-	/** Lock */
-	fibril_mutex_t lock;
-	/** Socket core */
-	socket_core_t *sock_core;
-	/** Client */
-	tcp_client_t *client;
-	/** Connection */
-	tcp_conn_t *conn;
-	/** Local address */
-	netaddr_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;
-} tcp_sockdata_t;
-
-typedef struct tcp_sock_lconn {
-	tcp_conn_t *conn;
-	tcp_sockdata_t *socket;
-	int index;
-	link_t ready_list;
-} tcp_sock_lconn_t;
-
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/test.c
===================================================================
--- uspace/srv/net/tl/tcp/test.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,145 +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 Internal TCP test
- */
-
-#include <async.h>
-#include <errno.h>
-#include <stdio.h>
-#include <thread.h>
-#include <str.h>
-#include "tcp_type.h"
-#include "ucall.h"
-
-#include "test.h"
-
-#define RCV_BUF_SIZE 64
-
-static void test_srv(void *arg)
-{
-	tcp_conn_t *conn;
-	tcp_sock_t lsock;
-	tcp_sock_t fsock;
-	char rcv_buf[RCV_BUF_SIZE + 1];
-	size_t rcvd;
-	xflags_t xflags;
-
-	printf("test_srv()\n");
-	lsock.port = 80;
-	lsock.addr.ipv4 = 0x7f000001;
-	fsock.port = 1024;
-	fsock.addr.ipv4 = 0x7f000001;
-	printf("S: User open...\n");
-	tcp_uc_open(&lsock, &fsock, ap_passive, 0, &conn);
-	conn->name = (char *) "S";
-
-	while (true) {
-		printf("S: User receive...\n");
-		tcp_uc_receive(conn, rcv_buf, RCV_BUF_SIZE, &rcvd, &xflags);
-		if (rcvd == 0) {
-			printf("S: End of data reached.\n");
-			break;
-		}
-		rcv_buf[rcvd] = '\0';
-		printf("S: User received %zu bytes '%s'.\n", rcvd, rcv_buf);
-
-		async_usleep(1000*1000*2);
-	}
-
-	async_usleep(/*10**/1000*1000);
-
-	printf("S: User close...\n");
-	tcp_uc_close(conn);
-
-	printf("test_srv() terminating\n");
-}
-
-static void test_cli(void *arg)
-{
-	tcp_conn_t *conn;
-	tcp_sock_t lsock;
-	tcp_sock_t fsock;
-	const char *msg = "Hello World!";
-
-	printf("test_cli()\n");
-
-	lsock.port = 1024;
-	lsock.addr.ipv4 = 0x7f000001;
-	fsock.port = 80;
-	fsock.addr.ipv4 = 0x7f000001;
-
-	async_usleep(1000*1000*3);
-	printf("C: User open...\n");
-	tcp_uc_open(&lsock, &fsock, ap_active, 0, &conn);
-	conn->name = (char *) "C";
-
-	async_usleep(1000*1000*10);
-	printf("C: User send...\n");
-	tcp_uc_send(conn, (void *)msg, str_size(msg), 0);
-
-	async_usleep(1000*1000*20/**20*2*/);
-	printf("C: User close...\n");
-	tcp_uc_close(conn);
-}
-
-void tcp_test(void)
-{
-	thread_id_t srv_tid;
-	thread_id_t cli_tid;
-	int rc;
-
-	printf("tcp_test()\n");
-
-	async_usleep(1000*1000);
-
-	if (0) {
-		rc = thread_create(test_srv, NULL, "test_srv", &srv_tid);
-		if (rc != EOK) {
-			printf("Failed to create server thread.\n");
-			return;
-		}
-	}
-
-	if (0) {
-		rc = thread_create(test_cli, NULL, "test_cli", &cli_tid);
-		if (rc != EOK) {
-			printf("Failed to create client thread.\n");
-			return;
-		}
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/test.h
===================================================================
--- uspace/srv/net/tl/tcp/test.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,43 +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 Internal TCP test
- */
-
-#ifndef TEST_H
-#define TEST_H
-
-extern void tcp_test(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/tqueue.c
===================================================================
--- uspace/srv/net/tl/tcp/tqueue.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,381 +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 TCP transmission queue
- */
-
-#include <adt/list.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <byteorder.h>
-#include <io/log.h>
-#include <macros.h>
-#include <mem.h>
-#include <stdlib.h>
-#include "conn.h"
-#include "ncsim.h"
-#include "pdu.h"
-#include "rqueue.h"
-#include "segment.h"
-#include "seq_no.h"
-#include "tqueue.h"
-#include "tcp.h"
-#include "tcp_type.h"
-
-#define RETRANSMIT_TIMEOUT	(2*1000*1000)
-
-static void retransmit_timeout_func(void *arg);
-static void tcp_tqueue_timer_set(tcp_conn_t *conn);
-static void tcp_tqueue_timer_clear(tcp_conn_t *conn);
-
-int tcp_tqueue_init(tcp_tqueue_t *tqueue, tcp_conn_t *conn)
-{
-	tqueue->conn = conn;
-	tqueue->timer = fibril_timer_create();
-	if (tqueue->timer == NULL)
-		return ENOMEM;
-
-	list_initialize(&tqueue->list);
-
-	return EOK;
-}
-
-void tcp_tqueue_clear(tcp_tqueue_t *tqueue)
-{
-	tcp_tqueue_timer_clear(tqueue->conn);
-}
-
-void tcp_tqueue_fini(tcp_tqueue_t *tqueue)
-{
-	if (tqueue->timer != NULL) {
-		fibril_timer_destroy(tqueue->timer);
-		tqueue->timer = NULL;
-	}
-}
-
-void tcp_tqueue_ctrl_seg(tcp_conn_t *conn, tcp_control_t ctrl)
-{
-	tcp_segment_t *seg;
-
-	log_msg(LVL_DEBUG, "tcp_tqueue_ctrl_seg(%p, %u)", conn, ctrl);
-
-	seg = tcp_segment_make_ctrl(ctrl);
-	tcp_tqueue_seg(conn, seg);
-}
-
-void tcp_tqueue_seg(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	tcp_segment_t *rt_seg;
-	tcp_tqueue_entry_t *tqe;
-
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_seg(%p, %p)", conn->name, conn,
-	    seg);
-
-	/*
-	 * Add segment to retransmission queue
-	 */
-
-	if (seg->len > 0) {
-		rt_seg = tcp_segment_dup(seg);
-		if (rt_seg == NULL) {
-			log_msg(LVL_ERROR, "Memory allocation failed.");
-			/* XXX Handle properly */
-			return;
-		}
-
-		tqe = calloc(1, sizeof(tcp_tqueue_entry_t));
-		if (tqe == NULL) {
-			log_msg(LVL_ERROR, "Memory allocation failed.");
-			/* XXX Handle properly */
-			return;
-		}
-
-		tqe->conn = conn;
-		tqe->seg = rt_seg;
-		rt_seg->seq = conn->snd_nxt;
-
-		list_append(&tqe->link, &conn->retransmit.list);
-
-		/* Set retransmission timer */
-		tcp_tqueue_timer_set(conn);
-	}
-
-	tcp_prepare_transmit_segment(conn, seg);
-}
-
-void tcp_prepare_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/*
-	 * Always send ACK once we have received SYN, except for RST segments.
-	 * (Spec says we should always send ACK once connection has been
-	 * established.)
-	 */
-	if (tcp_conn_got_syn(conn) && (seg->ctrl & CTL_RST) == 0)
-		seg->ctrl |= CTL_ACK;
-
-	seg->seq = conn->snd_nxt;
-	conn->snd_nxt += seg->len;
-
-	tcp_conn_transmit_segment(conn, seg);
-}
-
-/** Transmit data from the send buffer.
- *
- * @param conn	Connection
- */
-void tcp_tqueue_new_data(tcp_conn_t *conn)
-{
-	size_t avail_wnd;
-	size_t xfer_seqlen;
-	size_t snd_buf_seqlen;
-	size_t data_size;
-	tcp_control_t ctrl;
-	bool send_fin;
-
-	tcp_segment_t *seg;
-
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_new_data()", conn->name);
-
-	/* Number of free sequence numbers in send window */
-	avail_wnd = (conn->snd_una + conn->snd_wnd) - conn->snd_nxt;
-	snd_buf_seqlen = conn->snd_buf_used + (conn->snd_buf_fin ? 1 : 0);
-
-	xfer_seqlen = min(snd_buf_seqlen, avail_wnd);
-	log_msg(LVL_DEBUG, "%s: snd_buf_seqlen = %zu, SND.WND = %zu, "
-	    "xfer_seqlen = %zu", conn->name, snd_buf_seqlen, conn->snd_wnd,
-	    xfer_seqlen);
-
-	if (xfer_seqlen == 0)
-		return;
-
-	/* XXX Do not always send immediately */
-
-	send_fin = conn->snd_buf_fin && xfer_seqlen == snd_buf_seqlen;
-	data_size = xfer_seqlen - (send_fin ? 1 : 0);
-
-	if (send_fin) {
-		log_msg(LVL_DEBUG, "%s: Sending out FIN.", conn->name);
-		/* We are sending out FIN */
-		ctrl = CTL_FIN;
-	} else {
-		ctrl = 0;
-	}
-
-	seg = tcp_segment_make_data(ctrl, conn->snd_buf, data_size);
-	if (seg == NULL) {
-		log_msg(LVL_ERROR, "Memory allocation failure.");
-		return;
-	}
-
-	/* Remove data from send buffer */
-	memmove(conn->snd_buf, conn->snd_buf + data_size,
-	    conn->snd_buf_used - data_size);
-	conn->snd_buf_used -= data_size;
-
-	if (send_fin)
-		conn->snd_buf_fin = false;
-
-	fibril_condvar_broadcast(&conn->snd_buf_cv);
-
-	if (send_fin)
-		tcp_conn_fin_sent(conn);
-
-	tcp_tqueue_seg(conn, seg);
-}
-
-/** Remove ACKed segments from retransmission queue and possibly transmit
- * more data.
- *
- * This should be called when SND.UNA is updated due to incoming ACK.
- */
-void tcp_tqueue_ack_received(tcp_conn_t *conn)
-{
-	link_t *cur, *next;
-
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_ack_received(%p)", conn->name,
-	    conn);
-
-	cur = conn->retransmit.list.head.next;
-
-	while (cur != &conn->retransmit.list.head) {
-		next = cur->next;
-
-		tcp_tqueue_entry_t *tqe = list_get_instance(cur,
-		    tcp_tqueue_entry_t, link);
-
-		if (seq_no_segment_acked(conn, tqe->seg, conn->snd_una)) {
-			/* Remove acknowledged segment */
-			list_remove(cur);
-
-			if ((tqe->seg->ctrl & CTL_FIN) != 0) {
-				log_msg(LVL_DEBUG, "Fin has been acked");
-				log_msg(LVL_DEBUG, "SND.UNA=%" PRIu32
-				    " SEG.SEQ=%" PRIu32 " SEG.LEN=%" PRIu32,
-				    conn->snd_una, tqe->seg->seq, tqe->seg->len);
-				/* Our FIN has been acked */
-				conn->fin_is_acked = true;
-			}
-
-			tcp_segment_delete(tqe->seg);
-			free(tqe);
-
-			/* Reset retransmission timer */
-			tcp_tqueue_timer_set(conn);
-		}
-
-		cur = next;
-	}
-
-	/* Clear retransmission timer if the queue is empty. */
-	if (list_empty(&conn->retransmit.list))
-		tcp_tqueue_timer_clear(conn);
-
-	/* Possibly transmit more data */
-	tcp_tqueue_new_data(conn);
-}
-
-void tcp_conn_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_transmit_segment(%p, %p)",
-	    conn->name, conn, seg);
-
-	seg->wnd = conn->rcv_wnd;
-
-	if ((seg->ctrl & CTL_ACK) != 0)
-		seg->ack = conn->rcv_nxt;
-	else
-		seg->ack = 0;
-
-	tcp_transmit_segment(&conn->ident, seg);
-}
-
-void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_transmit_segment(f:(%x,%u),l:(%x,%u), %p)",
-	    sp->foreign.addr.ipv4, sp->foreign.port,
-	    sp->local.addr.ipv4, sp->local.port, seg);
-
-	log_msg(LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
-	    seg->seq, seg->wnd);
-
-	tcp_segment_dump(seg);
-/*
-	tcp_pdu_prepare(conn, seg, &data, &len);
-	tcp_pdu_transmit(data, len);
-*/
-//	tcp_rqueue_bounce_seg(sp, seg);
-//	tcp_ncsim_bounce_seg(sp, seg);
-
-	tcp_pdu_t *pdu;
-
-	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
-		return;
-	}
-
-	tcp_transmit_pdu(pdu);
-	tcp_pdu_delete(pdu);
-}
-
-static void retransmit_timeout_func(void *arg)
-{
-	tcp_conn_t *conn = (tcp_conn_t *) arg;
-	tcp_tqueue_entry_t *tqe;
-	tcp_segment_t *rt_seg;
-	link_t *link;
-
-	log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LVL_DEBUG, "Connection already closed.");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	link = list_first(&conn->retransmit.list);
-	if (link == NULL) {
-		log_msg(LVL_DEBUG, "Nothing to retransmit");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	tqe = list_get_instance(link, tcp_tqueue_entry_t, link);
-
-	rt_seg = tcp_segment_dup(tqe->seg);
-	if (rt_seg == NULL) {
-		log_msg(LVL_ERROR, "Memory allocation failed.");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		/* XXX Handle properly */
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "### %s: retransmitting segment", conn->name);
-	tcp_conn_transmit_segment(tqe->conn, rt_seg);
-
-	/* Reset retransmission timer */
-	tcp_tqueue_timer_set(tqe->conn);
-
-	fibril_mutex_unlock(&conn->lock);
-	tcp_conn_delref(conn);
-}
-
-/** Set or re-set retransmission timer */
-static void tcp_tqueue_timer_set(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
-
-	/* Clear first to make sure we update refcnt correctly */
-	tcp_tqueue_timer_clear(conn);
-
-	tcp_conn_addref(conn);
-	fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
-	    retransmit_timeout_func, (void *) conn);
-}
-
-/** Clear retransmission timer */
-static void tcp_tqueue_timer_clear(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
-
-	if (fibril_timer_clear(conn->retransmit.timer) == fts_active)
-		tcp_conn_delref(conn);
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/tqueue.h
===================================================================
--- uspace/srv/net/tl/tcp/tqueue.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,57 +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 TCP transmission queue
- */
-
-#ifndef TQUEUE_H
-#define TQUEUE_H
-
-#include "std.h"
-#include "tcp_type.h"
-
-extern int tcp_tqueue_init(tcp_tqueue_t *, tcp_conn_t *);
-extern void tcp_tqueue_clear(tcp_tqueue_t *);
-extern void tcp_tqueue_fini(tcp_tqueue_t *);
-extern void tcp_tqueue_ctrl_seg(tcp_conn_t *, tcp_control_t);
-extern void tcp_tqueue_seg(tcp_conn_t *, tcp_segment_t *);
-extern void tcp_tqueue_new_data(tcp_conn_t *);
-extern void tcp_tqueue_ack_received(tcp_conn_t *);
-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_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 *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/ucall.c
===================================================================
--- uspace/srv/net/tl/tcp/ucall.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,346 +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 TCP entry points (close to those defined in the RFC)
- */
-
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <macros.h>
-#include <mem.h>
-#include "conn.h"
-#include "tcp_type.h"
-#include "tqueue.h"
-#include "ucall.h"
-
-/*
- * User calls
- */
-
-/** OPEN user call
- *
- * @param lsock		Local socket
- * @param fsock		Foreign socket
- * @param acpass	Active/passive
- * @param oflags	Open flags
- * @param conn		Connection
- *
- * Unlike in the spec we allow specifying the local address. This means
- * the implementation does not need to magically guess it, especially
- * considering there can be more than one local address.
- *
- * XXX We should be able to call active open on an existing listening
- * connection.
- * XXX We should be able to get connection structure immediately, before
- * establishment.
- */
-tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
-    tcp_open_flags_t oflags, tcp_conn_t **conn)
-{
-	tcp_conn_t *nconn;
-
-	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
-	    lsock, fsock, acpass == ap_active ? "active" : "passive",
-	    oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
-
-	nconn = tcp_conn_new(lsock, fsock);
-	tcp_conn_add(nconn);
-
-	if (acpass == ap_active) {
-		/* Synchronize (initiate) connection */
-		tcp_conn_sync(nconn);
-	}
-
-	if (oflags == tcp_open_nonblock) {
-		*conn = nconn;
-		return TCP_EOK;
-	}
-
-	/* Wait for connection to be established or reset */
-	log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
-	fibril_mutex_lock(&nconn->lock);
-	while (nconn->cstate == st_listen ||
-	    nconn->cstate == st_syn_sent ||
-	    nconn->cstate == st_syn_received) {
-		fibril_condvar_wait(&nconn->cstate_cv, &nconn->lock);
-	}
-
-	if (nconn->cstate != st_established) {
-		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
-		assert(nconn->cstate == st_closed);
-		fibril_mutex_unlock(&nconn->lock);
-		return TCP_ERESET;
-	}
-
-	fibril_mutex_unlock(&nconn->lock);
-	log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
-
-	*conn = nconn;
-	log_msg(LVL_DEBUG, "tcp_uc_open -> %p", nconn);
-	return TCP_EOK;
-}
-
-/** SEND user call */
-tcp_error_t tcp_uc_send(tcp_conn_t *conn, void *data, size_t size,
-    xflags_t flags)
-{
-	size_t buf_free;
-	size_t xfer_size;
-
-	log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ENOTEXIST;
-	}
-
-	if (conn->cstate == st_listen) {
-		/* Change connection to active */
-		tcp_conn_sync(conn);
-	}
-
-
-	if (conn->snd_buf_fin) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ECLOSING;
-	}
-
-	while (size > 0) {
-		buf_free = conn->snd_buf_size - conn->snd_buf_used;
-		while (buf_free == 0 && !conn->reset) {
-			log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.",
-			    conn->name);
-			fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock);
-			buf_free = conn->snd_buf_size - conn->snd_buf_used;
-		}
-
-		if (conn->reset) {
-			fibril_mutex_unlock(&conn->lock);
-			return TCP_ERESET;
-		}
-
-		xfer_size = min(size, buf_free);
-
-		/* Copy data to buffer */
-		memcpy(conn->snd_buf + conn->snd_buf_used, data, xfer_size);
-		data += xfer_size;
-		conn->snd_buf_used += xfer_size;
-		size -= xfer_size;
-
-		tcp_tqueue_new_data(conn);
-	}
-
-	tcp_tqueue_new_data(conn);
-	fibril_mutex_unlock(&conn->lock);
-
-	return TCP_EOK;
-}
-
-/** RECEIVE user call */
-tcp_error_t tcp_uc_receive(tcp_conn_t *conn, void *buf, size_t size,
-    size_t *rcvd, xflags_t *xflags)
-{
-	size_t xfer_size;
-
-	log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ENOTEXIST;
-	}
-
-	/* Wait for data to become available */
-	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
-		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
-		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
-	}
-
-	if (conn->rcv_buf_used == 0) {
-		*rcvd = 0;
-		*xflags = 0;
-
-		if (conn->rcv_buf_fin) {
-			/* End of data, peer closed connection */
-			fibril_mutex_unlock(&conn->lock);
-			return TCP_ECLOSING;
-		} else {
-			/* Connection was reset */
-			assert(conn->reset);
-			fibril_mutex_unlock(&conn->lock);
-			return TCP_ERESET;
-		}
-	}
-
-	/* Copy data from receive buffer to user buffer */
-	xfer_size = min(size, conn->rcv_buf_used);
-	memcpy(buf, conn->rcv_buf, xfer_size);
-	*rcvd = xfer_size;
-
-	/* Remove data from receive buffer */
-	memmove(conn->rcv_buf, conn->rcv_buf + xfer_size, conn->rcv_buf_used -
-	    xfer_size);
-	conn->rcv_buf_used -= xfer_size;
-	conn->rcv_wnd += xfer_size;
-
-	/* TODO */
-	*xflags = 0;
-
-	/* Send new size of receive window */
-	tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-
-	log_msg(LVL_DEBUG, "%s: tcp_uc_receive() - returning %zu bytes",
-	    conn->name, xfer_size);
-
-	fibril_mutex_unlock(&conn->lock);
-
-	return TCP_EOK;
-}
-
-/** CLOSE user call */
-tcp_error_t tcp_uc_close(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ENOTEXIST;
-	}
-
-	if (conn->snd_buf_fin) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ECLOSING;
-	}
-
-	conn->snd_buf_fin = true;
-	tcp_tqueue_new_data(conn);
-
-	fibril_mutex_unlock(&conn->lock);
-	return TCP_EOK;
-}
-
-/** ABORT user call */
-void tcp_uc_abort(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "tcp_uc_abort()");
-}
-
-/** STATUS user call */
-void tcp_uc_status(tcp_conn_t *conn, tcp_conn_status_t *cstatus)
-{
-	log_msg(LVL_DEBUG, "tcp_uc_status()");
-	cstatus->cstate = conn->cstate;
-}
-
-/** Delete connection user call.
- *
- * (Not in spec.) Inform TCP that the user is done with this connection
- * and will not make any further calls/references to it. TCP can deallocate
- * the connection from now on.
- */
-void tcp_uc_delete(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "tcp_uc_delete()");
-	tcp_conn_delete(conn);
-}
-
-void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
-{
-	log_msg(LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
-	    conn, cb, arg);
-
-	conn->cstate_cb = cb;
-	conn->cstate_cb_arg = arg;
-}
-
-/*
- * Arriving segments
- */
-
-/** Segment arrived */
-void tcp_as_segment_arrived(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_conn_t *conn;
-
-	log_msg(LVL_DEBUG, "tcp_as_segment_arrived(f:(%x,%u), l:(%x,%u))",
-	    sp->foreign.addr.ipv4, sp->foreign.port,
-	    sp->local.addr.ipv4, sp->local.port);
-
-	conn = tcp_conn_find_ref(sp);
-	if (conn == NULL) {
-		log_msg(LVL_WARN, "No connection found.");
-		tcp_unexpected_segment(sp, seg);
-		return;
-	}
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LVL_WARN, "Connection is closed.");
-		tcp_unexpected_segment(sp, seg);
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
-		conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
-	if (conn->ident.foreign.port == TCP_PORT_ANY)
-		conn->ident.foreign.port = sp->foreign.port;
-	if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
-		conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
-
-	tcp_conn_segment_arrived(conn, seg);
-
-	fibril_mutex_unlock(&conn->lock);
-	tcp_conn_delref(conn);
-}
-
-/*
- * Timeouts
- */
-
-/** User timeout */
-void tcp_to_user(void)
-{
-	log_msg(LVL_DEBUG, "tcp_to_user()");
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/ucall.h
===================================================================
--- uspace/srv/net/tl/tcp/ucall.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,67 +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 TCP user calls (close to those defined in the RFC)
- */
-
-#ifndef UCALL_H
-#define UCALL_H
-
-#include <sys/types.h>
-#include "tcp_type.h"
-
-/*
- * User calls
- */
-extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_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);
-extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
-extern tcp_error_t tcp_uc_close(tcp_conn_t *);
-extern void tcp_uc_abort(tcp_conn_t *);
-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 *);
-
-/*
- * Arriving segments
- */
-extern void tcp_as_segment_arrived(tcp_sockpair_t *, tcp_segment_t *);
-
-/*
- * Timeouts
- */
-extern void tcp_to_user(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/udp/Makefile
===================================================================
--- uspace/srv/net/tl/udp/Makefile	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,38 +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 = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = udp
-
-SOURCES = \
-	udp.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,934 +1,0 @@
-/*
- * Copyright (c) 2008 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 udp
- * @{
- */
-
-/** @file
- * UDP module implementation.
- * @see udp.h
- */
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/tl.h>
-#include <ipc/socket.h>
-#include <adt/dynamic_fifo.h>
-#include <errno.h>
-
-#include <net/socket_codes.h>
-#include <net/ip_protocols.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/modules.h>
-
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <net_checksum.h>
-#include <ip_client.h>
-#include <ip_interface.h>
-#include <icmp_client.h>
-#include <icmp_remote.h>
-#include <net_interface.h>
-#include <socket_core.h>
-#include <tl_common.h>
-#include <tl_remote.h>
-#include <tl_skel.h>
-
-#include "udp.h"
-#include "udp_header.h"
-
-/** UDP module name. */
-#define NAME  "udp"
-
-/** Default UDP checksum computing. */
-#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING	true
-
-/** Default UDP autobind when sending via unbound sockets. */
-#define NET_DEFAULT_UDP_AUTOBINDING	true
-
-/** Maximum UDP fragment size. */
-#define MAX_UDP_FRAGMENT_SIZE		65535
-
-/** Free ports pool start. */
-#define UDP_FREE_PORTS_START		1025
-
-/** Free ports pool end. */
-#define UDP_FREE_PORTS_END		65535
-
-/** UDP global data.  */
-udp_globals_t udp_globals;
-
-/** Releases the packet and returns the result.
- *
- * @param[in] packet	The packet queue to be released.
- * @param[in] result	The result to be returned.
- * @return		The result parameter.
- */
-static int udp_release_and_return(packet_t *packet, int result)
-{
-	pq_release_remote(udp_globals.net_sess, packet_get_id(packet));
-	return result;
-}
-
-/** Processes the received UDP packet queue.
- *
- * Notifies the destination socket application.
- * Releases the packet on error or sends an ICMP error notification.
- *
- * @param[in] device_id	The receiving device identifier.
- * @param[in,out] packet The received packet queue.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		EINVAL if the stored packet address is not the
- *			an_addr_t.
- * @return		EINVAL if the packet does not contain any data.
- * @return 		NO_DATA if the packet content is shorter than the user
- *			datagram header.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EADDRNOTAVAIL if the destination socket does not exist.
- * @return		Other error codes as defined for the
- *			ip_client_process_packet() function.
- */
-static int udp_process_packet(nic_device_id_t device_id, packet_t *packet,
-    services_t error)
-{
-	size_t length;
-	size_t offset;
-	int result;
-	udp_header_t *header;
-	socket_core_t *socket;
-	packet_t *next_packet;
-	size_t total_length;
-	uint32_t checksum;
-	int fragments;
-	packet_t *tmp_packet;
-	icmp_type_t type;
-	icmp_code_t code;
-	void *ip_header;
-	struct sockaddr *src;
-	struct sockaddr *dest;
-	packet_dimension_t *packet_dimension;
-	int rc;
-
-	switch (error) {
-	case SERVICE_NONE:
-		break;
-	case SERVICE_ICMP:
-		/* Ignore error */
-		// length = icmp_client_header_length(packet);
-
-		/* Process error */
-		result = icmp_client_process_packet(packet, &type,
-		    &code, NULL, NULL);
-		if (result < 0)
-			return udp_release_and_return(packet, result);
-		length = (size_t) result;
-		rc = packet_trim(packet, length, 0);
-		if (rc != EOK)
-			return udp_release_and_return(packet, rc);
-		break;
-	default:
-		return udp_release_and_return(packet, ENOTSUP);
-	}
-
-	/* TODO process received ipopts? */
-	result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
-	if (result < 0)
-		return udp_release_and_return(packet, result);
-	offset = (size_t) result;
-
-	length = packet_get_data_length(packet);
-	if (length <= 0)
-		return udp_release_and_return(packet, EINVAL);
-	if (length < UDP_HEADER_SIZE + offset)
-		return udp_release_and_return(packet, NO_DATA);
-
-	/* Trim all but UDP header */
-	rc = packet_trim(packet, offset, 0);
-	if (rc != EOK)
-		return udp_release_and_return(packet, rc);
-
-	/* Get UDP header */
-	header = (udp_header_t *) packet_get_data(packet);
-	if (!header)
-		return udp_release_and_return(packet, NO_DATA);
-
-	/* Find the destination socket */
-	socket = socket_port_find(&udp_globals.sockets,
-	    ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
-	if (!socket) {
-		if (tl_prepare_icmp_packet(udp_globals.net_sess,
-		    udp_globals.icmp_sess, packet, error) == EOK) {
-			icmp_destination_unreachable_msg(udp_globals.icmp_sess,
-			    ICMP_PORT_UNREACH, 0, packet);
-		}
-		return EADDRNOTAVAIL;
-	}
-
-	/* Count the received packet fragments */
-	next_packet = packet;
-	fragments = 0;
-	total_length = ntohs(header->total_length);
-
-	/* Compute header checksum if set */
-	if (header->checksum && !error) {
-		result = packet_get_addr(packet, (uint8_t **) &src,
-		    (uint8_t **) &dest);
-		if (result <= 0)
-			return udp_release_and_return(packet, result);
-		
-		rc = ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest,
-		    result, total_length, &ip_header, &length);
-		if (rc != EOK) {
-			return udp_release_and_return(packet, rc);
-		} else {
-			checksum = compute_checksum(0, ip_header, length);
-			/*
-			 * The udp header checksum will be added with the first
-			 * fragment later.
-			 */
-			free(ip_header);
-		}
-	} else {
-		header->checksum = 0;
-		checksum = 0;
-	}
-
-	do {
-		fragments++;
-		length = packet_get_data_length(next_packet);
-		if (length <= 0)
-			return udp_release_and_return(packet, NO_DATA);
-
-		if (total_length < length) {
-			rc = packet_trim(next_packet, 0, length - total_length);
-			if (rc != EOK)
-				return udp_release_and_return(packet, rc);
-
-			/* Add partial checksum if set */
-			if (header->checksum) {
-				checksum = compute_checksum(checksum,
-				    packet_get_data(packet),
-				    packet_get_data_length(packet));
-			}
-
-			/* Relese the rest of the packet fragments */
-			tmp_packet = pq_next(next_packet);
-			while (tmp_packet) {
-				next_packet = pq_detach(tmp_packet);
-				pq_release_remote(udp_globals.net_sess,
-				    packet_get_id(tmp_packet));
-				tmp_packet = next_packet;
-			}
-
-			/* Exit the loop */
-			break;
-		}
-		total_length -= length;
-
-		/* Add partial checksum if set */
-		if (header->checksum) {
-			checksum = compute_checksum(checksum,
-			    packet_get_data(packet),
-			    packet_get_data_length(packet));
-		}
-
-	} while ((next_packet = pq_next(next_packet)) && (total_length > 0));
-
-	/* Verify checksum */
-	if (header->checksum) {
-		if (flip_checksum(compact_checksum(checksum)) !=
-		    IP_CHECKSUM_ZERO) {
-			if (tl_prepare_icmp_packet(udp_globals.net_sess,
-			    udp_globals.icmp_sess, packet, error) == EOK) {
-				/* Checksum error ICMP */
-				icmp_parameter_problem_msg(
-				    udp_globals.icmp_sess, ICMP_PARAM_POINTER,
-				    ((size_t) ((void *) &header->checksum)) -
-				    ((size_t) ((void *) header)), packet);
-			}
-			return EINVAL;
-		}
-	}
-
-	/* Queue the received packet */
-	rc = dyn_fifo_push(&socket->received, packet_get_id(packet),
-	    SOCKET_MAX_RECEIVED_SIZE);
-	if (rc != EOK)
-		return udp_release_and_return(packet, rc);
-		
-	rc = tl_get_ip_packet_dimension(udp_globals.ip_sess,
-	    &udp_globals.dimensions, device_id, &packet_dimension);
-	if (rc != EOK)
-		return udp_release_and_return(packet, rc);
-
-	/* Notify the destination socket */
-	fibril_rwlock_write_unlock(&udp_globals.lock);
-	
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
-	    packet_dimension->content, 0, 0, (sysarg_t) fragments);
-	async_exchange_end(exch);
-
-	return EOK;
-}
-
-/** Processes the received UDP packet queue.
- *
- * Is used as an entry point from the underlying IP module.
- * Locks the global lock and calls udp_process_packet() function.
- *
- * @param[in] device_id	The receiving device identifier.
- * @param[in,out] packet The received packet queue.
- * @param receiver	The target service. Ignored parameter.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- * @return		Other error codes as defined for the
- *			udp_process_packet() function.
- */
-static int udp_received_msg(nic_device_id_t device_id, packet_t *packet,
-    services_t receiver, services_t error)
-{
-	int result;
-
-	fibril_rwlock_write_lock(&udp_globals.lock);
-	result = udp_process_packet(device_id, packet, error);
-	if (result != EOK)
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-
-	return result;
-}
-
-/** Process IPC messages from the IP module
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(udp_globals.net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc == EOK)
-				rc = udp_received_msg(IPC_GET_DEVICE(*icall), packet,
-				    SERVICE_UDP, IPC_GET_ERROR(*icall));
-			
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Initialize the UDP module.
- *
- * @param[in] sess Network module session.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int tl_initialize(async_sess_t *sess)
-{
-	measured_string_t names[] = {
-		{
-			(uint8_t *) "UDP_CHECKSUM_COMPUTING",
-			22
-		},
-		{
-			(uint8_t *) "UDP_AUTOBINDING",
-			15
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	
-	fibril_rwlock_initialize(&udp_globals.lock);
-	fibril_rwlock_write_lock(&udp_globals.lock);
-	
-	udp_globals.net_sess = sess;
-	udp_globals.icmp_sess = icmp_connect_module();
-	
-	udp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
-	     SERVICE_UDP, udp_receiver);
-	if (udp_globals.ip_sess == NULL) {
-	    fibril_rwlock_write_unlock(&udp_globals.lock);
-	    return ENOENT;
-	}
-	
-	/* Read default packet dimensions */
-	int rc = ip_packet_size_req(udp_globals.ip_sess, -1,
-	    &udp_globals.packet_dimension);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	rc = socket_ports_initialize(&udp_globals.sockets);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	rc = packet_dimensions_initialize(&udp_globals.dimensions);
-	if (rc != EOK) {
-		socket_ports_destroy(&udp_globals.sockets, free);
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
-	udp_globals.packet_dimension.content -= sizeof(udp_header_t);
-	udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
-
-	udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
-	udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
-
-	/* Get configuration */
-	configuration = &names[0];
-	rc = net_get_conf_req(udp_globals.net_sess, &configuration, count,
-	    &data);
-	if (rc != EOK) {
-		socket_ports_destroy(&udp_globals.sockets, free);
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	if (configuration) {
-		if (configuration[0].value)
-			udp_globals.checksum_computing =
-			    (configuration[0].value[0] == 'y');
-		
-		if (configuration[1].value)
-			udp_globals.autobinding =
-			    (configuration[1].value[0] == 'y');
-
-		net_free_settings(configuration, data);
-	}
-
-	fibril_rwlock_write_unlock(&udp_globals.lock);
-	return EOK;
-}
-
-/** Sends data from the socket to the remote address.
- *
- * Binds the socket to a free port if not already connected/bound.
- * Handles the NET_SOCKET_SENDTO message.
- * Supports AF_INET and AF_INET6 address families.
- *
- * @param[in,out] local_sockets The application local sockets.
- * @param[in] socket_id	Socket identifier.
- * @param[in] addr	The destination address.
- * @param[in] addrlen	The address length.
- * @param[in] fragments	The number of data fragments.
- * @param[out] data_fragment_size The data fragment size in bytes.
- * @param[in] flags	Various send flags.
- * @return		EOK on success.
- * @return		EAFNOTSUPPORT if the address family is not supported.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EINVAL if the address is invalid.
- * @return		ENOTCONN if the sending socket is not and cannot be
- *			bound.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			socket_read_packet_data() function.
- * @return		Other error codes as defined for the
- *			ip_client_prepare_packet() function.
- * @return		Other error codes as defined for the ip_send_msg()
- *			function.
- */
-static int udp_sendto_message(socket_cores_t *local_sockets, int socket_id,
-    const struct sockaddr *addr, socklen_t addrlen, int fragments,
-    size_t *data_fragment_size, int flags)
-{
-	socket_core_t *socket;
-	packet_t *packet;
-	packet_t *next_packet;
-	udp_header_t *header;
-	int index;
-	size_t total_length;
-	int result;
-	uint16_t dest_port;
-	uint32_t checksum;
-	void *ip_header;
-	size_t headerlen;
-	nic_device_id_t device_id;
-	packet_dimension_t *packet_dimension;
-	size_t size;
-	int rc;
-
-	/* In case of error, do not update the data fragment size. */
-	*data_fragment_size = 0;
-	
-	rc = tl_get_address_port(addr, addrlen, &dest_port);
-	if (rc != EOK)
-		return rc;
-
-	socket = socket_cores_find(local_sockets, socket_id);
-	if (!socket)
-		return ENOTSOCK;
-
-	if ((socket->port <= 0) && udp_globals.autobinding) {
-		/* Bind the socket to a random free port if not bound */
-		rc = socket_bind_free_port(&udp_globals.sockets, socket,
-		    UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
-		    udp_globals.last_used_port);
-		if (rc != EOK)
-			return rc;
-		/* Set the next port as the search starting port number */
-		udp_globals.last_used_port = socket->port;
-	}
-
-	if (udp_globals.checksum_computing) {
-		rc = ip_get_route_req(udp_globals.ip_sess, IPPROTO_UDP, addr,
-		    addrlen, &device_id, &ip_header, &headerlen);
-		if (rc != EOK)
-			return rc;
-		/* Get the device packet dimension */
-//		rc = tl_get_ip_packet_dimension(udp_globals.ip_sess,
-//		    &udp_globals.dimensions, device_id, &packet_dimension);
-//		if (rc != EOK)
-//			return rc;
-	}
-//	} else {
-		/* Do not ask all the time */
-		rc = ip_packet_size_req(udp_globals.ip_sess, -1,
-		    &udp_globals.packet_dimension);
-		if (rc != EOK)
-			return rc;
-		packet_dimension = &udp_globals.packet_dimension;
-//	}
-
-	/*
-	 * Update the data fragment size based on what the lower layers can
-	 * handle without fragmentation, but not more than the maximum allowed
-	 * for UDP.
-	 */
-	size = MAX_UDP_FRAGMENT_SIZE;
-	if (packet_dimension->content < size)
-	    size = packet_dimension->content;
-	*data_fragment_size = size;
-
-	/* Read the first packet fragment */
-	result = tl_socket_read_packet_data(udp_globals.net_sess, &packet,
-	    UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
-	if (result < 0)
-		return result;
-
-	total_length = (size_t) result;
-	if (udp_globals.checksum_computing)
-		checksum = compute_checksum(0, packet_get_data(packet),
-		    packet_get_data_length(packet));
-	else
-		checksum = 0;
-
-	/* Prefix the UDP header */
-	header = PACKET_PREFIX(packet, udp_header_t);
-	if (!header)
-		return udp_release_and_return(packet, ENOMEM);
-
-	bzero(header, sizeof(*header));
-
-	/* Read the rest of the packet fragments */
-	for (index = 1; index < fragments; index++) {
-		result = tl_socket_read_packet_data(udp_globals.net_sess,
-		    &next_packet, 0, packet_dimension, addr, addrlen);
-		if (result < 0)
-			return udp_release_and_return(packet, result);
-
-		rc = pq_add(&packet, next_packet, index, 0);
-		if (rc != EOK)
-			return udp_release_and_return(packet, rc);
-
-		total_length += (size_t) result;
-		if (udp_globals.checksum_computing) {
-			checksum = compute_checksum(checksum,
-			    packet_get_data(next_packet),
-			    packet_get_data_length(next_packet));
-		}
-	}
-
-	/* Set the UDP header */
-	header->source_port = htons((socket->port > 0) ? socket->port : 0);
-	header->destination_port = htons(dest_port);
-	header->total_length = htons(total_length + sizeof(*header));
-	header->checksum = 0;
-
-	if (udp_globals.checksum_computing) {
-		/* Update the pseudo header */
-		rc = ip_client_set_pseudo_header_data_length(ip_header,
-		    headerlen, total_length + UDP_HEADER_SIZE);
-		if (rc != EOK) {
-			free(ip_header);
-			return udp_release_and_return(packet, rc);
-		}
-
-		/* Finish the checksum computation */
-		checksum = compute_checksum(checksum, ip_header, headerlen);
-		checksum = compute_checksum(checksum, (uint8_t *) header,
-		    sizeof(*header));
-		header->checksum =
-		    htons(flip_checksum(compact_checksum(checksum)));
-		free(ip_header);
-	} else
-		device_id = NIC_DEVICE_INVALID_ID;
-
-	/* Prepare the first packet fragment */
-	rc = ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0);
-	if (rc != EOK)
-		return udp_release_and_return(packet, rc);
-
-	/* Release the UDP global lock on success. */
-	fibril_rwlock_write_unlock(&udp_globals.lock);
-
-	/* Send the packet */
-	ip_send_msg(udp_globals.ip_sess, device_id, packet, SERVICE_UDP, 0);
-
-	return EOK;
-}
-
-/** Receives data to the socket.
- *
- * Handles the NET_SOCKET_RECVFROM message.
- * Replies the source address as well.
- *
- * @param[in] local_sockets The application local sockets.
- * @param[in] socket_id	Socket identifier.
- * @param[in] flags	Various receive flags.
- * @param[out] addrlen	The source address length.
- * @return		The number of bytes received.
- * @return		ENOTSOCK if the socket is not found.
- * @return		NO_DATA if there are no received packets or data.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EINVAL if the received address is not an IP address.
- * @return		Other error codes as defined for the packet_translate()
- *			function.
- * @return		Other error codes as defined for the data_reply()
- *			function.
- */
-static int udp_recvfrom_message(socket_cores_t *local_sockets, int socket_id,
-    int flags, size_t *addrlen)
-{
-	socket_core_t *socket;
-	int packet_id;
-	packet_t *packet;
-	udp_header_t *header;
-	struct sockaddr *addr;
-	size_t length;
-	uint8_t *data;
-	int result;
-	int rc;
-
-	/* Find the socket */
-	socket = socket_cores_find(local_sockets, socket_id);
-	if (!socket)
-		return ENOTSOCK;
-
-	/* Get the next received packet */
-	packet_id = dyn_fifo_value(&socket->received);
-	if (packet_id < 0)
-		return NO_DATA;
-	
-	rc = packet_translate_remote(udp_globals.net_sess, &packet, packet_id);
-	if (rc != EOK) {
-		(void) dyn_fifo_pop(&socket->received);
-		return rc;
-	}
-
-	/* Get UDP header */
-	data = packet_get_data(packet);
-	if (!data) {
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, NO_DATA);
-	}
-	header = (udp_header_t *) data;
-
-	/* Set the source address port */
-	result = packet_get_addr(packet, (uint8_t **) &addr, NULL);
-	rc = tl_set_address_port(addr, result, ntohs(header->source_port));
-	if (rc != EOK) {
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, rc);
-	}
-	*addrlen = (size_t) result;
-
-	/* Send the source address */
-	rc = data_reply(addr, *addrlen);
-	switch (rc) {
-	case EOK:
-		break;
-	case EOVERFLOW:
-		return rc;
-	default:
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, rc);
-	}
-
-	/* Trim the header */
-	rc = packet_trim(packet, UDP_HEADER_SIZE, 0);
-	if (rc != EOK) {
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, rc);
-	}
-
-	/* Reply the packets */
-	rc = socket_reply_packets(packet, &length);
-	switch (rc) {
-	case EOK:
-		break;
-	case EOVERFLOW:
-		return rc;
-	default:
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, rc);
-	}
-
-	(void) dyn_fifo_pop(&socket->received);
-
-	/* Release the packet and return the total length */
-	return udp_release_and_return(packet, (int) length);
-}
-
-/** Process the socket client messages.
- *
- * Run until the client module disconnects.
- *
- * @see socket.h
- *
- * @param[in] sess   Callback session.
- * @param[in] callid Message identifier.
- * @param[in] call   Message parameters.
- *
- * @return EOK on success.
- *
- */
-static int udp_process_client_messages(async_sess_t *sess, ipc_callid_t callid,
-    ipc_call_t call)
-{
-	int res;
-	socket_cores_t local_sockets;
-	struct sockaddr *addr;
-	int socket_id;
-	size_t addrlen;
-	size_t size;
-	ipc_call_t answer;
-	size_t answer_count;
-	packet_dimension_t *packet_dimension;
-
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_TO_ME call.
-	 */
-	res = EOK;
-	answer_count = 0;
-
-	/*
-	 * The client connection is only in one fibril and therefore no
-	 * additional locks are needed.
-	 */
-
-	socket_cores_initialize(&local_sockets);
-
-	while (true) {
-
-		/* Answer the call */
-		answer_call(callid, res, &answer, answer_count);
-
-		/* Refresh data */
-		refresh_answer(&answer, &answer_count);
-
-		/* Get the next call */
-		callid = async_get_call(&call);
-
-		/* Process the call */
-		if (!IPC_GET_IMETHOD(call)) {
-			res = EHANGUP;
-			break;
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NET_SOCKET:
-			socket_id = SOCKET_GET_SOCKET_ID(call);
-			res = socket_create(&local_sockets, sess, NULL,
-			    &socket_id);
-			SOCKET_SET_SOCKET_ID(answer, socket_id);
-
-			if (res != EOK)
-				break;
-			
-			size = MAX_UDP_FRAGMENT_SIZE;
-			if (tl_get_ip_packet_dimension(udp_globals.ip_sess,
-			    &udp_globals.dimensions, NIC_DEVICE_INVALID_ID,
-			    &packet_dimension) == EOK) {
-				if (packet_dimension->content < size)
-					size = packet_dimension->content;
-			}
-			SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
-			SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
-			answer_count = 3;
-			break;
-
-		case NET_SOCKET_BIND:
-			res = async_data_write_accept((void **) &addr, false,
-			    0, 0, 0, &addrlen);
-			if (res != EOK)
-				break;
-			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = socket_bind(&local_sockets, &udp_globals.sockets,
-			    SOCKET_GET_SOCKET_ID(call), addr, addrlen,
-			    UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
-			    udp_globals.last_used_port);
-			fibril_rwlock_write_unlock(&udp_globals.lock);
-			free(addr);
-			break;
-
-		case NET_SOCKET_SENDTO:
-			res = async_data_write_accept((void **) &addr, false,
-			    0, 0, 0, &addrlen);
-			if (res != EOK)
-				break;
-
-			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = udp_sendto_message(&local_sockets,
-			    SOCKET_GET_SOCKET_ID(call), addr, addrlen,
-			    SOCKET_GET_DATA_FRAGMENTS(call), &size,
-			    SOCKET_GET_FLAGS(call));
-			SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
-
-			if (res != EOK)
-				fibril_rwlock_write_unlock(&udp_globals.lock);
-			else
-				answer_count = 2;
-			
-			free(addr);
-			break;
-
-		case NET_SOCKET_RECVFROM:
-			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = udp_recvfrom_message(&local_sockets,
-			     SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
-			     &addrlen);
-			fibril_rwlock_write_unlock(&udp_globals.lock);
-
-			if (res <= 0)
-				break;
-
-			SOCKET_SET_READ_DATA_LENGTH(answer, res);
-			SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
-			answer_count = 3;
-			res = EOK;
-			break;
-			
-		case NET_SOCKET_CLOSE:
-			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = socket_destroy(udp_globals.net_sess,
-			    SOCKET_GET_SOCKET_ID(call), &local_sockets,
-			    &udp_globals.sockets, NULL);
-			fibril_rwlock_write_unlock(&udp_globals.lock);
-			break;
-
-		case NET_SOCKET_GETSOCKOPT:
-		case NET_SOCKET_SETSOCKOPT:
-		default:
-			res = ENOTSUP;
-			break;
-		}
-	}
-
-	/* Release the application session */
-	async_hangup(sess);
-
-	/* Release all local sockets */
-	socket_cores_release(udp_globals.net_sess, &local_sockets,
-	    &udp_globals.sockets, NULL);
-
-	return res;
-}
-
-/** Per-connection initialization
- *
- */
-void tl_connection(void)
-{
-}
-
-/** Processes the UDP message.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @param[out] answer	The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer in the
- *			answer parameter.
- * @return		EOK on success.
- * @return		ENOTSUP if the message is not known.
- *
- * @see udp_interface.h
- * @see IS_NET_UDP_MESSAGE()
- */
-int tl_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	*answer_count = 0;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return udp_process_client_messages(callback, callid, *call);
-	
-	return ENOTSUP;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return tl_module_start(SERVICE_UDP);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/udp/udp.h
===================================================================
--- uspace/srv/net/tl/udp/udp.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(revision )
@@ -1,77 +1,0 @@
-/*
- * Copyright (c) 2008 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 udp
- * @{
- */
-
-/** @file
- * UDP module.
- */
-
-#ifndef NET_UDP_H_
-#define NET_UDP_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <socket_core.h>
-#include <tl_common.h>
-
-/** Type definition of the UDP global data.
- * @see udp_globals
- */
-typedef struct udp_globals udp_globals_t;
-
-/** UDP global data. */
-struct udp_globals {
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	/** IP module session. */
-	async_sess_t *ip_sess;
-	/** ICMP module session. */
-	async_sess_t *icmp_sess;
-	/** Packet dimension. */
-	packet_dimension_t packet_dimension;
-	/** Indicates whether UDP checksum computing is enabled. */
-	int checksum_computing;
-	/** Indicates whether UDP autobnding on send is enabled. */
-	int autobinding;
-	/** Last used free port. */
-	int last_used_port;
-	/** Active sockets. */
-	socket_ports_t sockets;
-	/** Device packet dimensions. */
-	packet_dimensions_t dimensions;
-	/** Safety lock. */
-	fibril_rwlock_t lock;
-};
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/udp/udp_header.h
===================================================================
--- uspace/srv/net/tl/udp/udp_header.h	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ 	(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 udp
- * @{
- */
-
-/** @file
- * UDP header definition.
- * Based on the RFC 768.
- */
-
-#ifndef NET_UDP_HEADER_H_
-#define NET_UDP_HEADER_H_
-
-#include <sys/types.h>
-
-/** UDP header size in bytes. */
-#define UDP_HEADER_SIZE		sizeof(udp_header_t)
-
-/** Type definition of the user datagram header.
- * @see udp_header
- */
-typedef struct udp_header udp_header_t;
-
-/** User datagram header. */
-struct udp_header {
-	uint16_t source_port;
-	uint16_t destination_port;
-	uint16_t total_length;
-	uint16_t checksum;
-} __attribute__ ((packed));
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/udp/Makefile
===================================================================
--- uspace/srv/net/udp/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/Makefile	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+BINARY = udp
+
+SOURCES = \
+	assoc.c \
+	msg.c \
+	sock.c \
+	pdu.c \
+	ucall.c \
+	udp.c \
+	udp_inet.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/udp/assoc.c
===================================================================
--- uspace/srv/net/udp/assoc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/assoc.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,411 @@
+/*
+ * 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 associations
+ */
+
+#include <adt/list.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <stdlib.h>
+
+#include "assoc.h"
+#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 *);
+
+/** Create new association structure.
+ *
+ * @param lsock		Local socket (will be deeply copied)
+ * @param fsock		Foreign socket (will be deeply copied)
+ * @return		New association or NULL
+ */
+udp_assoc_t *udp_assoc_new(udp_sock_t *lsock, udp_sock_t *fsock)
+{
+	udp_assoc_t *assoc = NULL;
+
+	/* Allocate association structure */
+	assoc = calloc(1, sizeof(udp_assoc_t));
+	if (assoc == NULL)
+		goto error;
+
+	fibril_mutex_initialize(&assoc->lock);
+
+	/* One for the user */
+	atomic_set(&assoc->refcnt, 1);
+
+	/* Initialize receive queue */
+	list_initialize(&assoc->rcv_queue);
+	fibril_condvar_initialize(&assoc->rcv_queue_cv);
+
+	if (lsock != NULL)
+		assoc->ident.local = *lsock;
+	if (fsock != NULL)
+		assoc->ident.foreign = *fsock;
+
+	return assoc;
+error:
+	return NULL;
+}
+
+/** Destroy association structure.
+ *
+ * Association structure should be destroyed when the folowing conditions
+ * are met:
+ * (1) user has deleted the association
+ * (2) nobody is holding references to the association
+ *
+ * This happens when @a assoc->refcnt is zero as we count (1)
+ * as an extra reference.
+ *
+ * @param assoc		Association
+ */
+static void udp_assoc_free(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "%s: udp_assoc_free(%p)", assoc->name, assoc);
+
+	while (!list_empty(&assoc->rcv_queue)) {
+		link_t *link = list_first(&assoc->rcv_queue);
+		udp_rcv_queue_entry_t *rqe = list_get_instance(link,
+		    udp_rcv_queue_entry_t, link);
+		list_remove(link);
+
+		udp_msg_delete(rqe->msg);
+		free(rqe);
+	}
+
+	free(assoc);
+}
+
+/** Add reference to association.
+ *
+ * Increase association reference count by one.
+ *
+ * @param assoc		Association
+ */
+void udp_assoc_addref(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "%s: upd_assoc_addref(%p)", assoc->name, assoc);
+	atomic_inc(&assoc->refcnt);
+}
+
+/** Remove reference from association.
+ *
+ * Decrease association reference count by one.
+ *
+ * @param assoc		Association
+ */
+void udp_assoc_delref(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "%s: udp_assoc_delref(%p)", assoc->name, assoc);
+
+	if (atomic_predec(&assoc->refcnt) == 0)
+		udp_assoc_free(assoc);
+}
+
+/** Delete association.
+ *
+ * The caller promises not make no further references to @a assoc.
+ * UDP will free @a assoc eventually.
+ *
+ * @param assoc		Association
+ */
+void udp_assoc_delete(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "%s: udp_assoc_delete(%p)", assoc->name, assoc);
+
+	assert(assoc->deleted == false);
+	udp_assoc_delref(assoc);
+	assoc->deleted = true;
+}
+
+/** Enlist association.
+ *
+ * Add association to the association map.
+ */
+void udp_assoc_add(udp_assoc_t *assoc)
+{
+	udp_assoc_addref(assoc);
+	fibril_mutex_lock(&assoc_list_lock);
+	list_append(&assoc->link, &assoc_list);
+	fibril_mutex_unlock(&assoc_list_lock);
+}
+
+/** Delist association.
+ *
+ * Remove association from the association map.
+ */
+void udp_assoc_remove(udp_assoc_t *assoc)
+{
+	fibril_mutex_lock(&assoc_list_lock);
+	list_remove(&assoc->link);
+	fibril_mutex_unlock(&assoc_list_lock);
+	udp_assoc_delref(assoc);
+}
+
+/** 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(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 fsock		Foreign socket (deeply copied)
+ */
+void udp_assoc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
+{
+	log_msg(LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock);
+	fibril_mutex_lock(&assoc->lock);
+	assoc->ident.local = *lsock;
+	fibril_mutex_unlock(&assoc->lock);
+}
+
+/** Send message to association.
+ *
+ * @param assoc		Association
+ * @param fsock		Foreign socket or NULL not to override @a assoc
+ * @param msg		Message
+ *
+ * @return		EOK on success
+ *			EINVAL if foreign socket 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)
+{
+	udp_pdu_t *pdu;
+	udp_sockpair_t sp;
+	int rc;
+
+	log_msg(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 (sp.foreign.addr.ipv4 == 0 || sp.foreign.port == 0)
+		return EINVAL;
+
+	rc = udp_pdu_encode(&sp, msg, &pdu);
+	if (rc != EOK)
+		return ENOMEM;
+
+	rc = udp_transmit_pdu(pdu);
+	if (rc != EOK)
+		return EIO;
+
+	udp_pdu_delete(pdu);
+
+	return EOK;
+}
+
+/** Get a received message.
+ *
+ * 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)
+{
+	link_t *link;
+	udp_rcv_queue_entry_t *rqe;
+
+	log_msg(LVL_DEBUG, "udp_assoc_recv()");
+
+	fibril_mutex_lock(&assoc->lock);
+	while (list_empty(&assoc->rcv_queue)) {
+		log_msg(LVL_DEBUG, "udp_assoc_recv() - waiting");
+		fibril_condvar_wait(&assoc->rcv_queue_cv, &assoc->lock);
+	}
+
+	log_msg(LVL_DEBUG, "udp_assoc_recv() - got a message");
+	link = list_first(&assoc->rcv_queue);
+	rqe = list_get_instance(link, udp_rcv_queue_entry_t, link);
+	list_remove(link);
+	fibril_mutex_unlock(&assoc->lock);
+
+	*msg = rqe->msg;
+	*fsock = rqe->sp.foreign;
+	free(rqe);
+
+	return EOK;
+}
+
+/** Message received.
+ *
+ * Find the association to which the message belongs and queue it.
+ */
+void udp_assoc_received(udp_sockpair_t *rsp, udp_msg_t *msg)
+{
+	udp_assoc_t *assoc;
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg);
+
+	assoc = udp_assoc_find_ref(rsp);
+	if (assoc == NULL) {
+		log_msg(LVL_DEBUG, "No association found. Message dropped.");
+		/* XXX Generate ICMP error. */
+		/* XXX Might propagate error directly by error return. */
+		return;
+	}
+
+	rc = udp_assoc_queue_msg(assoc, rsp, msg);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "Out of memory. Message dropped.");
+		/* XXX Generate ICMP error? */
+	}
+}
+
+static int udp_assoc_queue_msg(udp_assoc_t *assoc, udp_sockpair_t *sp,
+    udp_msg_t *msg)
+{
+	udp_rcv_queue_entry_t *rqe;
+
+	log_msg(LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)",
+	    assoc, sp, msg);
+
+	rqe = calloc(1, sizeof(udp_rcv_queue_entry_t));
+	if (rqe == NULL)
+		return ENOMEM;
+
+	link_initialize(&rqe->link);
+	rqe->sp = *sp;
+	rqe->msg = msg;
+
+	fibril_mutex_lock(&assoc->lock);
+	list_append(&rqe->link, &assoc->rcv_queue);
+	fibril_mutex_unlock(&assoc->lock);
+
+	fibril_condvar_broadcast(&assoc->rcv_queue_cv);
+
+	return EOK;
+}
+
+/** Match socket with pattern. */
+static bool udp_socket_match(udp_sock_t *sock, udp_sock_t *patt)
+{
+	log_msg(LVL_DEBUG, "udp_socket_match(sock=(%x,%u), pat=(%x,%u))",
+	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
+
+	if (patt->addr.ipv4 != UDP_IPV4_ANY &&
+	    patt->addr.ipv4 != sock->addr.ipv4)
+		return false;
+
+	if (patt->port != UDP_PORT_ANY &&
+	    patt->port != sock->port)
+		return false;
+
+	log_msg(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(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(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.
+ * The association reference count is bumped by one.
+ *
+ * @param sp	Socket pair
+ * @return	Association structure or NULL if not found.
+ */
+static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *sp)
+{
+	log_msg(LVL_DEBUG, "udp_assoc_find_ref(%p)", sp);
+
+	fibril_mutex_lock(&assoc_list_lock);
+
+	list_foreach(assoc_list, link) {
+		udp_assoc_t *assoc = list_get_instance(link, udp_assoc_t, link);
+		udp_sockpair_t *asp = &assoc->ident;
+		log_msg(LVL_DEBUG, "compare with assoc (f:(%x,%u), l:(%x,%u))",
+		    asp->foreign.addr.ipv4, asp->foreign.port,
+		    asp->local.addr.ipv4, asp->local.port);
+
+		/* Skip unbound associations */
+		if (asp->local.port == UDP_PORT_ANY)
+			continue;
+
+		if (udp_sockpair_match(sp, asp)) {
+			log_msg(LVL_DEBUG, "Returning assoc %p", assoc);
+			udp_assoc_addref(assoc);
+			fibril_mutex_unlock(&assoc_list_lock);
+			return assoc;
+		}
+	}
+
+	fibril_mutex_unlock(&assoc_list_lock);
+	return NULL;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/assoc.h
===================================================================
--- uspace/srv/net/udp/assoc.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/assoc.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,57 @@
+/*
+ * 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 associations
+ */
+
+#ifndef ASSOC_H
+#define ASSOC_H
+
+#include <sys/types.h>
+#include "udp_type.h"
+
+extern udp_assoc_t *udp_assoc_new(udp_sock_t *, udp_sock_t *);
+extern void udp_assoc_delete(udp_assoc_t *);
+extern void 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_foreign(udp_assoc_t *, udp_sock_t *);
+extern void udp_assoc_set_local(udp_assoc_t *, udp_sock_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 *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/msg.c
===================================================================
--- uspace/srv/net/udp/msg.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/msg.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,57 @@
+/*
+ * 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 message
+ */
+
+#include <io/log.h>
+#include <stdlib.h>
+
+#include "msg.h"
+#include "udp_type.h"
+
+/** Alocate new segment structure. */
+udp_msg_t *udp_msg_new(void)
+{
+	return calloc(1, sizeof(udp_msg_t));
+}
+
+/** Delete segment. */
+void udp_msg_delete(udp_msg_t *msg)
+{
+	free(msg);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/msg.h
===================================================================
--- uspace/srv/net/udp/msg.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/msg.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,46 @@
+/*
+ * 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 message
+ */
+
+#ifndef MSG_H
+#define MSG_H
+
+#include "udp_type.h"
+
+extern udp_msg_t *udp_msg_new(void);
+extern void udp_msg_delete(udp_msg_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/pdu.c
===================================================================
--- uspace/srv/net/udp/pdu.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/pdu.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,210 @@
+/*
+ * 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 PDU encoding and decoding
+ */
+
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "msg.h"
+#include "pdu.h"
+#include "std.h"
+#include "udp_type.h"
+
+#define UDP_CHECKSUM_INIT 0xffff
+
+/** One's complement addition.
+ *
+ * Result is a + b + carry.
+ */
+static uint16_t udp_ocadd16(uint16_t a, uint16_t b)
+{
+	uint32_t s;
+
+	s = (uint32_t)a + (uint32_t)b;
+	return (s & 0xffff) + (s >> 16);
+}
+
+static uint16_t udp_checksum_calc(uint16_t ivalue, void *data, size_t size)
+{
+	uint16_t sum;
+	uint16_t w;
+	size_t words, i;
+	uint8_t *bdata;
+
+	sum = ~ivalue;
+	words = size / 2;
+	bdata = (uint8_t *)data;
+
+	for (i = 0; i < words; i++) {
+		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
+		sum = udp_ocadd16(sum, w);
+	}
+
+	if (size % 2 != 0) {
+		w = ((uint16_t)bdata[2*words] << 8);
+		sum = udp_ocadd16(sum, w);
+	}
+
+	return ~sum;
+}
+
+static void udp_phdr_setup(udp_pdu_t *pdu, udp_phdr_t *phdr)
+{
+	phdr->src_addr = host2uint32_t_be(pdu->src.ipv4);
+	phdr->dest_addr = host2uint32_t_be(pdu->dest.ipv4);
+	phdr->zero = 0;
+	phdr->protocol = IP_PROTO_UDP;
+	phdr->udp_length = host2uint16_t_be(pdu->data_size);
+}
+
+udp_pdu_t *udp_pdu_new(void)
+{
+	return calloc(1, sizeof(udp_pdu_t));
+}
+
+void udp_pdu_delete(udp_pdu_t *pdu)
+{
+	free(pdu->data);
+	free(pdu);
+}
+
+static uint16_t udp_pdu_checksum_calc(udp_pdu_t *pdu)
+{
+	uint16_t cs_phdr;
+	uint16_t cs_all;
+	udp_phdr_t phdr;
+
+	udp_phdr_setup(pdu, &phdr);
+	cs_phdr = udp_checksum_calc(UDP_CHECKSUM_INIT, (void *)&phdr,
+	    sizeof(udp_phdr_t));
+	cs_all = udp_checksum_calc(cs_phdr, pdu->data, pdu->data_size);
+
+	return cs_all;
+}
+
+static void udp_pdu_set_checksum(udp_pdu_t *pdu, uint16_t checksum)
+{
+	udp_header_t *hdr;
+
+	hdr = (udp_header_t *)pdu->data;
+	hdr->checksum = host2uint16_t_be(checksum);
+}
+
+/** Decode incoming PDU */
+int udp_pdu_decode(udp_pdu_t *pdu, udp_sockpair_t *sp, udp_msg_t **msg)
+{
+	udp_msg_t *nmsg;
+	udp_header_t *hdr;
+	void *text;
+	size_t text_size;
+	uint16_t length;
+	uint16_t checksum;
+
+	if (pdu->data_size < sizeof(udp_header_t))
+		return EINVAL;
+
+	text = pdu->data + sizeof(udp_header_t);
+	text_size = pdu->data_size - sizeof(udp_header_t);
+
+	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;
+
+	length = uint16_t_be2host(hdr->length);
+	checksum = uint16_t_be2host(hdr->checksum);
+	(void) checksum;
+
+	if (length < sizeof(udp_header_t) ||
+	    length > sizeof(udp_header_t) + text_size)
+		return EINVAL;
+
+	nmsg = udp_msg_new();
+	if (nmsg == NULL)
+		return ENOMEM;
+
+	nmsg->data = text;
+	nmsg->data_size = length - sizeof(udp_header_t);
+
+	*msg = nmsg;
+	return EOK;
+}
+
+/** Encode outgoing PDU */
+int udp_pdu_encode(udp_sockpair_t *sp, udp_msg_t *msg, udp_pdu_t **pdu)
+{
+	udp_pdu_t *npdu;
+	udp_header_t *hdr;
+	uint16_t checksum;
+
+	npdu = udp_pdu_new();
+	if (npdu == NULL)
+		return ENOMEM;
+
+	npdu->src = sp->local.addr;
+	npdu->dest = sp->foreign.addr;
+
+	npdu->data_size = sizeof(udp_header_t) + msg->data_size;
+	npdu->data = calloc(1, npdu->data_size);
+	if (npdu->data == NULL) {
+		udp_pdu_delete(npdu);
+		return ENOMEM;
+	}
+
+	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->length = host2uint16_t_be(npdu->data_size);
+	hdr->checksum = 0;
+
+	memcpy((uint8_t *)npdu->data + sizeof(udp_header_t), msg->data,
+	    msg->data_size);
+
+	/* Checksum calculation */
+	checksum = udp_pdu_checksum_calc(npdu);
+	udp_pdu_set_checksum(npdu, checksum);
+
+	*pdu = npdu;
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/pdu.h
===================================================================
--- uspace/srv/net/udp/pdu.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/pdu.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,50 @@
+/*
+ * 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 PDU (encoded Protocol Data Unit) handling
+ */
+
+#ifndef PDU_H
+#define PDU_H
+
+#include <sys/types.h>
+#include "std.h"
+#include "udp_type.h"
+
+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 **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/sock.c
===================================================================
--- uspace/srv/net/udp/sock.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/sock.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2008 Lukas Mejdrech
+ * 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
+ */
+
+#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/modules.h>
+#include <net/socket.h>
+#include <ns.h>
+
+#include "sock.h"
+#include "std.h"
+#include "udp_type.h"
+#include "ucall.h"
+
+#define FRAGMENT_SIZE 1024
+
+/** 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);
+
+int udp_sock_init(void)
+{
+	int rc;
+
+	socket_ports_initialize(&gsock);
+
+	async_set_client_connection(udp_sock_connection);
+
+	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;
+	assert(socket->assoc != NULL);
+	udp_uc_destroy(socket->assoc);
+}
+
+static void udp_sock_notify_data(socket_core_t *sock_core)
+{
+	log_msg(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,
+	    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(LVL_DEBUG, "udp_sock_socket()");
+	sock = calloc(sizeof(udp_sockdata_t), 1);
+	if (sock == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_initialize(&sock->lock);
+	sock->client = client;
+
+	rc = udp_uc_create(&sock->assoc);
+	if (rc != EOK) {
+		udp_uc_destroy(sock->assoc);
+		free(sock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sock_id = SOCKET_GET_SOCKET_ID(call);
+	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sock_core = socket_cores_find(&client->sockets, sock_id);
+	assert(sock_core != NULL);
+	sock->sock_core = sock_core;
+
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_SOCKET_ID(answer, sock_id);
+
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_HEADER_SIZE(answer, sizeof(udp_header_t));
+	answer_call(callid, EOK, &answer, 3);
+}
+
+static void udp_sock_bind(udp_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;
+	udp_sockdata_t *socket;
+	udp_sock_t fsock;
+	udp_error_t urc;
+
+	log_msg(LVL_DEBUG, "udp_sock_bind()");
+	log_msg(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;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_bind");
+	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
+	    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
+	    last_used_port);
+	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(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 = (udp_sockdata_t *)sock_core->specific_data;
+
+	fsock.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+	fsock.port = sock_core->port;
+	urc = udp_uc_set_local(socket->assoc, &fsock);
+
+	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);
+	}
+
+	udp_sock_notify_data(sock_core);
+
+	log_msg(LVL_DEBUG, " - success");
+	async_answer_0(callid, rc);
+out:
+	if (addr != NULL)
+		free(addr);
+}
+
+static void udp_sock_listen(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(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(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(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)
+{
+	int socket_id;
+	int fragments;
+	int index;
+	struct sockaddr_in *addr;
+	size_t addr_size;
+	socket_core_t *sock_core;
+	udp_sockdata_t *socket;
+	udp_sock_t fsock, *fsockp;
+	ipc_call_t answer;
+	ipc_callid_t wcallid;
+	size_t length;
+	uint8_t buffer[FRAGMENT_SIZE];
+	udp_error_t urc;
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_sock_send()");
+
+	addr = NULL;
+
+	if (IPC_GET_IMETHOD(call) == NET_SOCKET_SENDTO) {
+		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;
+		}
+
+		fsock.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+		fsock.port = uint16_t_be2host(addr->sin_port);
+		fsockp = &fsock;
+	} else {
+		fsockp = NULL;
+	}
+
+	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;
+	}
+
+	if (sock_core->port == 0) {
+		/* Implicitly bind socket to port */
+		rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
+		    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
+		    last_used_port);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			goto out;
+		}
+
+		udp_sock_notify_data(sock_core);
+	}
+
+	socket = (udp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->assoc->ident.local.addr.ipv4 == UDP_IPV4_ANY) {
+		/* Determine local IP address */
+		inet_addr_t loc_addr, rem_addr;
+
+		rem_addr.ipv4 = fsockp ? fsock.addr.ipv4 :
+		    socket->assoc->ident.foreign.addr.ipv4;
+
+		rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			log_msg(LVL_DEBUG, "udp_sock_sendto: Failed to "
+			    "determine local address.");
+			return;
+		}
+
+		socket->assoc->ident.local.addr.ipv4 = loc_addr.ipv4;
+		log_msg(LVL_DEBUG, "Local IP address is %x",
+		    socket->assoc->ident.local.addr.ipv4);
+	}
+
+
+	assert(socket->assoc != NULL);
+
+	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 > FRAGMENT_SIZE)
+			length = 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;
+		}
+
+		urc = udp_uc_send(socket->assoc, fsockp, buffer, length, 0);
+
+		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);
+		}
+
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			goto out;
+		}
+	}
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	answer_call(callid, EOK, &answer, 2);
+	fibril_mutex_unlock(&socket->lock);
+out:
+	if (addr != NULL)
+		free(addr);
+}
+
+static void udp_sock_recvfrom(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int flags;
+	size_t addr_length, length;
+	socket_core_t *sock_core;
+	udp_sockdata_t *socket;
+	ipc_call_t answer;
+	ipc_callid_t rcallid;
+	uint8_t buffer[FRAGMENT_SIZE];
+	size_t data_len;
+	xflags_t xflags;
+	udp_error_t urc;
+	struct sockaddr_in addr;
+	udp_sock_t rsock;
+	int rc;
+
+	log_msg(LVL_DEBUG, "%p: udp_sock_recv[from]()", client);
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	flags = SOCKET_GET_FLAGS(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	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;
+	}
+
+	(void)flags;
+
+	urc = udp_uc_receive(socket->assoc, buffer, FRAGMENT_SIZE, &data_len,
+	    &xflags, &rsock);
+	log_msg(LVL_DEBUG, "**** udp_uc_receive done, data_len=%zu", data_len);
+
+	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(LVL_DEBUG, "**** udp_uc_receive -> %d", rc);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
+		/* Fill addr */
+		addr.sin_family = AF_INET;
+		addr.sin_addr.s_addr = host2uint32_t_be(rsock.addr.ipv4);
+		addr.sin_port = host2uint16_t_be(rsock.port);
+
+		log_msg(LVL_DEBUG, "addr read receive");
+		if (!async_data_read_receive(&rcallid, &addr_length)) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+
+		if (addr_length > sizeof(addr))
+			addr_length = sizeof(addr);
+
+		log_msg(LVL_DEBUG, "addr read finalize");
+		rc = async_data_read_finalize(rcallid, &addr, addr_length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "data read receive");
+	if (!async_data_read_receive(&rcallid, &length)) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (length > data_len)
+		length = data_len;
+
+	log_msg(LVL_DEBUG, "data read finalize");
+	rc = async_data_read_finalize(rcallid, buffer, length);
+
+	if (length < data_len && rc == EOK)
+		rc = EOVERFLOW;
+
+	log_msg(LVL_DEBUG, "read_data_length <- %zu", length);
+	SOCKET_SET_READ_DATA_LENGTH(answer, length);
+	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(addr));
+	answer_call(callid, EOK, &answer, 3);
+
+	/* Push one fragment notification to client's queue */
+	udp_sock_notify_data(sock_core);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void udp_sock_close(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	socket_core_t *sock_core;
+	udp_sockdata_t *socket;
+	int rc;
+
+	log_msg(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 = (udp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
+	    udp_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 udp_sock_getsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(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(LVL_DEBUG, "udp_sock_setsockopt()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+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);
+
+	client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	socket_cores_initialize(&client.sockets);
+
+	while (true) {
+		log_msg(LVL_DEBUG, "udp_sock_connection: wait");
+		callid = async_get_call(&call);
+		if (!IPC_GET_IMETHOD(call))
+			break;
+
+		log_msg(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(LVL_DEBUG, "udp_sock_connection: Clean up");
+	async_hangup(client.sess);
+	socket_cores_release(NULL, &client.sockets, &gsock, udp_free_sock_data);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/sock.h
===================================================================
--- uspace/srv/net/udp/sock.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/sock.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,45 @@
+/*
+ * 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: uspace/srv/net/udp/std.h
===================================================================
--- uspace/srv/net/udp/std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/std.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,73 @@
+/*
+ * 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 standard definitions
+ *
+ * Based on IETF RFC 768
+ */
+
+#ifndef STD_H
+#define STD_H
+
+#include <sys/types.h>
+
+#define IP_PROTO_UDP 17
+
+/** UDP Header */
+typedef struct {
+	/** Source port */
+	uint16_t src_port;
+	/** Destination port */
+	uint16_t dest_port;
+	/** Length (header + data) */
+	uint16_t length;
+	/* Checksum */
+	uint16_t checksum;
+} udp_header_t;
+
+/** UDP pseudo header */
+typedef struct {
+	/** Source address */
+	uint32_t src_addr;
+	/** Destination address */
+	uint32_t dest_addr;
+	/** Zero */
+	uint8_t zero;
+	/** Protocol */
+	uint8_t protocol;
+	/** TCP length */
+	uint16_t udp_length;
+} udp_phdr_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/ucall.c
===================================================================
--- uspace/srv/net/udp/ucall.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/ucall.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,133 @@
+/*
+ * 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(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;
+}
+
+udp_error_t udp_uc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
+{
+	log_msg(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(LVL_DEBUG, "udp_uc_set_local(%p, %p)", assoc, lsock);
+
+	udp_assoc_set_local(assoc, lsock);
+	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(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(LVL_DEBUG, "%s: udp_uc_receive()", assoc->name);
+	rc = udp_assoc_recv(assoc, &msg, fsock);
+	switch (rc) {
+	}
+
+	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(LVL_DEBUG, "udp_uc_status()");
+//	cstatus->cstate = conn->cstate;
+}
+
+void udp_uc_destroy(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "udp_uc_destroy()");
+	udp_assoc_remove(assoc);
+	udp_assoc_delete(assoc);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/ucall.h
===================================================================
--- uspace/srv/net/udp/ucall.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/ucall.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,54 @@
+/*
+ * 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 <sys/types.h>
+#include "udp_type.h"
+
+extern udp_error_t udp_uc_create(udp_assoc_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_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 *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/udp.c
===================================================================
--- uspace/srv/net/udp/udp.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/udp.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,95 @@
+/*
+ * 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 Datagram Protocol) service
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdio.h>
+#include <task.h>
+
+#include "udp_inet.h"
+#include "sock.h"
+
+#define NAME       "udp"
+
+static int udp_init(void)
+{
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_init()");
+
+	rc = udp_inet_init();
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		return ENOENT;
+	}
+
+	rc = udp_sock_init();
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed initializing socket service.");
+		return ENOENT;
+	}
+
+	return EOK;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+
+	printf(NAME ": UDP (User Datagram Protocol) service\n");
+
+	rc = log_init(NAME, LVL_WARN);
+	if (rc != EOK) {
+		printf(NAME ": Failed to initialize log.\n");
+		return 1;
+	}
+
+	rc = udp_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/udp_inet.c
===================================================================
--- uspace/srv/net/udp/udp_inet.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/udp_inet.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,139 @@
+/*
+ * 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
+ */
+
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <inet/inet.h>
+#include <io/log.h>
+#include <stdio.h>
+#include <task.h>
+
+#include "assoc.h"
+#include "pdu.h"
+#include "std.h"
+#include "udp_inet.h"
+#include "udp_type.h"
+
+static int udp_inet_ev_recv(inet_dgram_t *dgram);
+static void udp_received_pdu(udp_pdu_t *pdu);
+
+static inet_ev_ops_t udp_inet_ev_ops = {
+	.recv = udp_inet_ev_recv
+};
+
+/** Received datagram callback */
+static int udp_inet_ev_recv(inet_dgram_t *dgram)
+{
+	udp_pdu_t *pdu;
+
+	log_msg(LVL_DEBUG, "udp_inet_ev_recv()");
+
+	pdu = udp_pdu_new();
+	pdu->data = dgram->data;
+	pdu->data_size = dgram->size;
+
+	pdu->src.ipv4 = dgram->src.ipv4;
+	pdu->dest.ipv4 = dgram->dest.ipv4;
+	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
+	    pdu->src.ipv4, pdu->dest.ipv4);
+
+	udp_received_pdu(pdu);
+	udp_pdu_delete(pdu);
+
+	return EOK;
+}
+
+/** Transmit PDU over network layer. */
+int udp_transmit_pdu(udp_pdu_t *pdu)
+{
+	int rc;
+	inet_dgram_t dgram;
+
+	log_msg(LVL_DEBUG, "udp_transmit_pdu()");
+
+	dgram.src.ipv4 = pdu->src.ipv4;
+	dgram.dest.ipv4 = pdu->dest.ipv4;
+	dgram.tos = 0;
+	dgram.data = pdu->data;
+	dgram.size = pdu->data_size;
+
+	rc = inet_send(&dgram, INET_TTL_MAX, 0);
+	if (rc != EOK)
+		log_msg(LVL_ERROR, "Failed to transmit PDU.");
+
+	return rc;
+}
+
+/** Process received PDU. */
+static void udp_received_pdu(udp_pdu_t *pdu)
+{
+	udp_msg_t *dmsg;
+	udp_sockpair_t rident;
+
+	log_msg(LVL_DEBUG, "udp_received_pdu()");
+
+	if (udp_pdu_decode(pdu, &rident, &dmsg) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
+		return;
+	}
+
+	/*
+	 * Insert decoded message into appropriate receive queue.
+	 * This transfers ownership of dmsg to the callee, we do not
+	 * free it.
+	 */
+	udp_assoc_received(&rident, dmsg);
+}
+
+int udp_inet_init(void)
+{
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_inet_init()");
+
+	rc = inet_init(IP_PROTO_UDP, &udp_inet_ev_ops);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		return ENOENT;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/udp_inet.h
===================================================================
--- uspace/srv/net/udp/udp_inet.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/udp_inet.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,46 @@
+/*
+ * 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 udp
+ * @{
+ */
+/** @file
+ */
+
+#ifndef UDP_INET_H
+#define UDP_INET_H
+
+#include "udp_type.h"
+
+extern int udp_inet_init(void);
+extern int udp_transmit_pdu(udp_pdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/udp_type.h
===================================================================
--- uspace/srv/net/udp/udp_type.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
+++ uspace/srv/net/udp/udp_type.h	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -0,0 +1,157 @@
+/*
+ * 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 type definitions
+ */
+
+#ifndef UDP_TYPE_H
+#define UDP_TYPE_H
+
+#include <fibril_synch.h>
+#include <socket_core.h>
+#include <sys/types.h>
+
+typedef enum {
+	UDP_EOK,
+	/* Insufficient resources */
+	UDP_ENORES,
+	/* Foreign socket unspecified */
+	UDP_EUNSPEC,
+	/* No route to destination */
+	UDP_ENOROUTE
+} udp_error_t;
+
+typedef enum {
+	XF_DUMMY	= 0x1
+} xflags_t;
+
+typedef struct {
+	uint32_t ipv4;
+} netaddr_t;
+
+enum netaddr {
+	UDP_IPV4_ANY = 0
+};
+
+enum tcp_port {
+	UDP_PORT_ANY = 0
+};
+
+typedef struct {
+	netaddr_t addr;
+	uint16_t port;
+} udp_sock_t;
+
+typedef struct {
+	udp_sock_t local;
+	udp_sock_t foreign;
+} udp_sockpair_t;
+
+/** Unencoded UDP message (datagram) */
+typedef struct {
+	/** Message data */
+	void *data;
+	/** Message data size */
+	size_t data_size;
+} udp_msg_t;
+
+/** Encoded PDU */
+typedef struct {
+	/** Source address */
+	netaddr_t src;
+	/** Destination address */
+	netaddr_t dest;
+
+	/** Encoded PDU data including header */
+	void *data;
+	/** Encoded PDU data size */
+	size_t data_size;
+} udp_pdu_t;
+
+typedef struct {
+	async_sess_t *sess;
+	socket_cores_t sockets;
+} udp_client_t;
+
+/** UDP association
+ *
+ * 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.
+ */
+typedef struct {
+	char *name;
+	link_t link;
+
+	/** Association identification (local and foreign socket) */
+	udp_sockpair_t ident;
+
+	/** True if association was deleted by user */
+	bool deleted;
+
+	/** Protects access to association structure */
+	fibril_mutex_t lock;
+	/** Reference count */
+	atomic_t refcnt;
+
+	/** Receive queue */
+	list_t rcv_queue;
+	/** Receive queue CV. Broadcast when new datagram is inserted */
+	fibril_condvar_t rcv_queue_cv;
+} udp_assoc_t;
+
+typedef struct {
+} udp_assoc_status_t;
+
+typedef struct udp_sockdata {
+	/** Lock */
+	fibril_mutex_t lock;
+	/** Socket core */
+	socket_core_t *sock_core;
+	/** Client */
+	udp_client_t *client;
+	/** Connection */
+	udp_assoc_t *assoc;
+} udp_sockdata_t;
+
+typedef struct {
+	/** Link to receive queue */
+	link_t link;
+	/** Socket pair */
+	udp_sockpair_t sp;
+	/** Message */
+	udp_msg_t *msg;
+} udp_rcv_queue_entry_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 3293a941ed36f5cd042093b66eabe6807080c177)
+++ uspace/srv/vfs/vfs_ops.c	(revision 7719958acb56b8b553bd6f0bfe042be335827596)
@@ -137,5 +137,5 @@
 			
 			if (rc != EOK) {
-				async_wait_for(msg, NULL);
+				async_forget(msg);
 				fibril_rwlock_write_unlock(&namespace_rwlock);
 				async_answer_0(rid, rc);
@@ -204,5 +204,5 @@
 	if (rc != EOK) {
 		vfs_exchange_release(exch);
-		async_wait_for(msg, NULL);
+		async_forget(msg);
 		
 		/* Mount failed, drop reference to mp_node. */
@@ -219,5 +219,5 @@
 	if (rc != EOK) {
 		vfs_exchange_release(exch);
-		async_wait_for(msg, NULL);
+		async_forget(msg);
 		
 		/* Mount failed, drop reference to mp_node. */
